From c7d23528970c0bc39aee9c3ba3eb8684f5d265ea Mon Sep 17 00:00:00 2001 From: Eric Seidel Date: Thu, 12 Feb 2015 13:42:11 -0800 Subject: [PATCH] Add the c++ code part of bindings2/ This is all the bindings-level dart code we had to write to enable Dart in Sky. We wrote this over the last 2 weeks in: https://github.com/eseidel/skydart R=abarth@chromium.org, jamesr@chromium.org BUG=454613 Review URL: https://codereview.chromium.org/918333002 --- engine/bindings2/BUILD.gn | 399 +++++++++ engine/bindings2/IDLExtendedAttributes.txt | 81 ++ engine/bindings2/bindings.gni | 50 ++ engine/bindings2/builtin.cc | 60 ++ engine/bindings2/builtin.dart | 53 ++ engine/bindings2/builtin.h | 34 + engine/bindings2/builtin_natives.cc | 184 ++++ engine/bindings2/builtin_natives.h | 28 + engine/bindings2/builtin_sky.cc | 37 + engine/bindings2/builtin_sky.h | 34 + engine/bindings2/dart_callback.cc | 39 + engine/bindings2/dart_callback.h | 30 + engine/bindings2/dart_event_listener.cc | 69 ++ engine/bindings2/dart_event_listener.h | 64 ++ engine/bindings2/exception_messages.cc | 166 ++++ engine/bindings2/exception_messages.h | 155 ++++ engine/bindings2/exception_state.cc | 48 ++ engine/bindings2/exception_state.h | 68 ++ .../bindings2/exception_state_placeholder.cc | 19 + .../bindings2/exception_state_placeholder.h | 39 + engine/bindings2/mojo_natives.cc | 804 ++++++++++++++++++ engine/bindings2/mojo_natives.h | 20 + engine/bindings2/nullable.h | 54 ++ engine/bindings2/scheduled_action.cc | 30 + engine/bindings2/scheduled_action.h | 37 + .../scripts/templates/attributes_cpp.template | 6 +- .../scripts/templates/methods_cpp.template | 8 +- engine/bindings2/snapshot.cc.tmpl | 18 + engine/bindings2/snapshot.dart | 16 + engine/tonic/dart_builtin.cc | 7 + engine/tonic/dart_builtin.h | 3 + engine/tonic/dart_converter.h | 6 + 32 files changed, 2659 insertions(+), 7 deletions(-) create mode 100644 engine/bindings2/BUILD.gn create mode 100644 engine/bindings2/IDLExtendedAttributes.txt create mode 100644 engine/bindings2/bindings.gni create mode 100644 engine/bindings2/builtin.cc create mode 100644 engine/bindings2/builtin.dart create mode 100644 engine/bindings2/builtin.h create mode 100644 engine/bindings2/builtin_natives.cc create mode 100644 engine/bindings2/builtin_natives.h create mode 100644 engine/bindings2/builtin_sky.cc create mode 100644 engine/bindings2/builtin_sky.h create mode 100644 engine/bindings2/dart_callback.cc create mode 100644 engine/bindings2/dart_callback.h create mode 100644 engine/bindings2/dart_event_listener.cc create mode 100644 engine/bindings2/dart_event_listener.h create mode 100644 engine/bindings2/exception_messages.cc create mode 100644 engine/bindings2/exception_messages.h create mode 100644 engine/bindings2/exception_state.cc create mode 100644 engine/bindings2/exception_state.h create mode 100644 engine/bindings2/exception_state_placeholder.cc create mode 100644 engine/bindings2/exception_state_placeholder.h create mode 100644 engine/bindings2/mojo_natives.cc create mode 100644 engine/bindings2/mojo_natives.h create mode 100644 engine/bindings2/nullable.h create mode 100644 engine/bindings2/scheduled_action.cc create mode 100644 engine/bindings2/scheduled_action.h create mode 100644 engine/bindings2/snapshot.cc.tmpl create mode 100644 engine/bindings2/snapshot.dart diff --git a/engine/bindings2/BUILD.gn b/engine/bindings2/BUILD.gn new file mode 100644 index 00000000000..b1467e8d6fb --- /dev/null +++ b/engine/bindings2/BUILD.gn @@ -0,0 +1,399 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//sky/engine/bindings2/bindings.gni") +import("//sky/engine/core/core.gni") + +source_set("bindings2") { + sources = [ + "builtin.cc", + "builtin.h", + "builtin_natives.cc", + "builtin_natives.h", + "builtin_sky.cc", + "builtin_sky.h", + "dart_callback.cc", + "dart_callback.h", + "dart_event_listener.cc", + "dart_event_listener.h", + "exception_messages.cc", + "exception_messages.h", + "exception_state.cc", + "exception_state.h", + "exception_state_placeholder.cc", + "exception_state_placeholder.h", + "mojo_natives.cc", + "mojo_natives.h", + "nullable.h", + "scheduled_action.cc", + "scheduled_action.h", + ] + deps = [ + "//base", + "//dart/runtime/bin:libdart_withcore", + "//mojo/public/c/system", + "//mojo/public/cpp/system", + "//sky/engine/platform:platform", + "//sky/engine/tonic", + "//sky/engine/wtf", + ":generated_bindings", + ":snapshot_cc", + ] + include_dirs = [ + "..", + "$root_build_dir", + ] +} + +action("generate_snapshot_bin") { + deps = [ + "//dart/runtime/bin:gen_snapshot($host_toolchain)", + ":generate_sky_core_dart", + ] + inputs = [ + "//dart/runtime/tools/create_snapshot_bin.py", + "//sky/engine/bindings2/builtin.dart", + "//mojo/public/dart/bindings.dart", + "//mojo/public/dart/core.dart", + "//mojo/public/dart/src/application.dart", + "//mojo/public/dart/src/buffer.dart", + "//mojo/public/dart/src/codec.dart", + "//mojo/public/dart/src/data_pipe.dart", + "//mojo/public/dart/src/drain_data.dart", + "//mojo/public/dart/src/event_stream.dart", + "//mojo/public/dart/src/handle.dart", + "//mojo/public/dart/src/handle_watcher.dart", + "//mojo/public/dart/src/message.dart", + "//mojo/public/dart/src/message_pipe.dart", + "//mojo/public/dart/src/proxy.dart", + "//mojo/public/dart/src/service_provider.dart", + "//mojo/public/dart/src/struct.dart", + "//mojo/public/dart/src/stub.dart", + "//mojo/public/dart/src/timer_queue.dart", + "//mojo/public/dart/src/types.dart", + "snapshot.dart", + ] + output = "$target_gen_dir/snapshot_gen.bin" + outputs = [ + output, + ] + + builtin_path = rebase_path("//sky/engine/bindings2/builtin.dart") + sky_core_path = rebase_path("$bindings_output_dir/sky_core.dart") + mojo_bindings_path = rebase_path("//mojo/public/dart/bindings.dart") + mojo_core_path = rebase_path("//mojo/public/dart/core.dart") + + gen_snapshot_dir = + get_label_info("//dart/runtime/bin:gen_snapshot($host_toolchain)", + "root_out_dir") + script = "//dart/runtime/tools/create_snapshot_bin.py" + + args = [ + "--executable", + rebase_path("$gen_snapshot_dir/gen_snapshot"), + "--package_root", + rebase_path("$root_gen_dir"), + "--script", + rebase_path("snapshot.dart"), + "--output_bin", + rebase_path(output, root_build_dir), + "--target_os", + os, + "--url_mapping=dart:sky,$sky_core_path", + "--url_mapping=dart:mojo_bindings,$mojo_bindings_path", + "--url_mapping=dart:mojo_core,$mojo_core_path", + "--url_mapping=dart:sky_builtin,$builtin_path", + ] +} + +action("generate_snapshot_file") { + deps = [ + ":generate_snapshot_bin", + ] + inputs = [ + "//dart/runtime/tools/create_snapshot_file.py", + "snapshot.cc.tmpl", + "$target_gen_dir/snapshot_gen.bin", + ] + output = "$target_gen_dir/snapshot.cc" + outputs = [ + output, + ] + + script = "//dart/runtime/tools/create_snapshot_file.py" + args = [ + "--input_bin", + rebase_path("$target_gen_dir/snapshot_gen.bin"), + "--input_cc", + rebase_path("snapshot.cc.tmpl"), + "--output", + rebase_path(output), + ] +} + +source_set("snapshot_cc") { + sources = [ + "$target_gen_dir/snapshot.cc", + ] + + deps = [ + ":generate_snapshot_file", + ] +} + +action("compute_interfaces_info_individual") { + sources = core_idl_files + core_dependency_idl_files + script = "$bindings_scripts_dir/compute_interfaces_info_individual.py" + output_file = "$bindings_output_dir/InterfacesInfoIndividual.pickle" + + # TODO(eseidel): This is no longer needed, could pass these as args. + file_list = "$target_gen_dir/${target_name}_file_list.txt" + write_file(file_list, rebase_path(sources, root_build_dir)) + + # TODO(eseidel): Use depfile instead of this manual list. + inputs = [ "$bindings_scripts_dir/utilities.py" ] + sources + + outputs = [ + file_list, + output_file, + ] + + args = [ + # TODO(eseidel): Remove component-dir, it is meaningless in sky. + "--component-dir", + "ignored", + "--idl-files-list", + rebase_path(file_list, root_build_dir), + "--interfaces-info-file", + rebase_path(output_file, root_build_dir), + + # TODO(eseidel): only-if-changed is always true, remove + "--write-file-only-if-changed=1", + ] +} + +interfaces_info_individual_path = + "$bindings_output_dir/InterfacesInfoIndividual.pickle" + +interfaces_info_overall_path = + "$bindings_output_dir/InterfacesInfoOverall.pickle" + +action("compute_interfaces_info_overall") { + script = "$bindings_scripts_dir/compute_interfaces_info_overall.py" + + inputs = [ + interfaces_info_individual_path, + ] + outputs = [ + interfaces_info_overall_path, + ] + + args = [ + # TODO(eseidel): only-if-changed is always true, remove + "--write-file-only-if-changed=1", + "--", + ] + args += rebase_path(inputs, root_build_dir) + args += rebase_path(outputs, root_build_dir) + + deps = [ + ":compute_interfaces_info_individual", + ] +} + +# This separate pre-caching step is required to use lex/parse table +# caching in PLY, since PLY itself does not check if the cache is +# valid, and thus may end up using a stale cache if this step hasn"t +# been run to update it. +# +# This action"s dependencies *is* the cache validation. +# +# GYP version: scripts.gyp:cached_lex_yacc_tables +action("cached_lex_yacc_tables") { + script = "scripts/blink_idl_parser.py" + + inputs = idl_lexer_parser_files + outputs = [ + "$bindings_output_dir/lextab.py", + "$bindings_output_dir/parsetab.pickle", + ] + + args = [ rebase_path(bindings_output_dir, root_build_dir) ] +} + +# Runs the idl_compiler script over a list of sources. +# +# Parameters: +# sources = list of IDL files to compile +# output_dir = string containing the directory to put the output files. +template("idl_compiler") { + output_dir = invoker.output_dir + + action_foreach(target_name) { + # TODO(brettw) GYP adds a "-S before the script name to skip "import site" to + # speed up startup. Figure out if we need this and do something similar (not + # really expressible in GN now). + script = "$bindings_scripts_dir/compiler.py" + + inputs = idl_lexer_parser_files + idl_compiler_files + inputs += [ + "scripts/templates/attributes_cpp.template", + "scripts/templates/callback_interface_cpp.template", + "scripts/templates/callback_interface_dart.template", + "scripts/templates/callback_interface_h.template", + "scripts/templates/interface_base_cpp.template", + "scripts/templates/interface_cpp.template", + "scripts/templates/interface_dart.template", + "scripts/templates/interface_h.template", + "scripts/templates/methods_cpp.template", + ] + inputs += [ + "$bindings_output_dir/lextab.py", + "$bindings_output_dir/parsetab.pickle", + + # "$bindings_output_dir/cached_jinja_templates.stamp", + "//sky/engine/bindings2/IDLExtendedAttributes.txt", + + # If the dependency structure or public interface info (e.g., + # [ImplementedAs]) changes, we rebuild all files, since we"re not + # computing dependencies file-by-file in the build. + # This data is generally stable. + interfaces_info_overall_path, + ] + + # Further, if any dependency (partial interface or implemented + # interface) changes, rebuild everything, since every IDL potentially + # depends on them, because we"re not computing dependencies + # file-by-file. + # FIXME: This is too conservative, and causes excess rebuilds: + # compute this file-by-file. http://crbug.com/341748 + # This should theoretically just be the IDL files passed in. + inputs += core_dependency_idl_files + + sources = invoker.sources + outputs = [ + "$output_dir/Dart{{source_name_part}}.cpp", + "$output_dir/Dart{{source_name_part}}.h", + "$output_dir/{{source_name_part}}.dart", + ] + + args = [ + "--output-dir", + rebase_path(output_dir, root_build_dir), + "--interfaces-info", + rebase_path(interfaces_info_overall_path, root_build_dir), + "--write-file-only-if-changed=1", # Always true for Ninja. + "{{source}}", + ] + + deps = [ + ":compute_interfaces_info_overall", + ":cached_lex_yacc_tables", + + # ":cached_jinja_templates", + ] + } +} + +idl_compiler("compile_idls") { + sources = core_idl_files + output_dir = bindings_output_dir +} + +action("generate_dart_globals") { + sources = core_idl_files + script = "$bindings_scripts_dir/compiler.py" + + file_list = "$target_gen_dir/${target_name}_file_list.txt" + write_file(file_list, rebase_path(sources, root_build_dir)) + + inputs = sources + idl_compiler_files + inputs += [ + "scripts/templates/global_cpp.template", + "scripts/templates/global_h.template", + ] + + outputs = [ + file_list, + "$bindings_output_dir/DartGlobal.h", + "$bindings_output_dir/DartGlobal.cpp", + ] + + args = [ + "--output-directory", + rebase_path(bindings_output_dir, root_build_dir), + "--generate-globals", + rebase_path(bindings_output_dir, root_build_dir), + rebase_path(file_list, root_build_dir), + ] + + deps = [ + ":compile_idls", + ] +} + +action("generate_sky_core_dart") { + sources = core_idl_files + script = "$bindings_scripts_dir/compiler.py" + + file_list = "$target_gen_dir/${target_name}_file_list.txt" + write_file(file_list, rebase_path(sources, root_build_dir)) + + inputs = + sources + idl_compiler_files + [ "scripts/templates/dart_blink.template" ] + + outputs = [ + file_list, + "$bindings_output_dir/sky_core.dart", + ] + + args = [ + "--output-directory", + rebase_path(bindings_output_dir, root_build_dir), + "--generate-dart-blink", + rebase_path(bindings_output_dir, root_build_dir), + rebase_path(file_list, root_build_dir), + ] + + deps = [ + ":compile_idls", + ] +} + +source_set("generated_bindings") { + deps = [ + "//base", + "//dart/runtime/bin:libdart_withcore", + "//gpu/command_buffer/client:gles2_c_lib", + "//mojo/application", + "//mojo/common", + "//mojo/edk/js", + "//mojo/public/c/system", + "//mojo/public/cpp/bindings", + "//mojo/public/cpp/system", + "//mojo/public/cpp/utility", + "//mojo/public/interfaces/application", + "//mojo/services/keyboard/public/interfaces", + "//mojo/services/navigation/public/interfaces", + "//mojo/services/view_manager/public/cpp", + "//skia", + "//sky/engine/wtf", + "//third_party/angle:translator", + "//third_party/iccjpeg", + "//third_party/libpng", + "//third_party/ots", + "//third_party/qcms", + "//third_party/zlib", + "//url", + ":generate_dart_globals", + ] + + include_dirs = [ + "..", + "$root_build_dir", + ] + + sources = get_target_outputs(":compile_idls") + sources += get_target_outputs(":generate_dart_globals") +} diff --git a/engine/bindings2/IDLExtendedAttributes.txt b/engine/bindings2/IDLExtendedAttributes.txt new file mode 100644 index 00000000000..48d59728265 --- /dev/null +++ b/engine/bindings2/IDLExtendedAttributes.txt @@ -0,0 +1,81 @@ +# +# This file describes all Blink IDL extended attributes and allowed values. +# If any IDL file uses an extended attribute or values not listed below, the +# build will fail. +# If you would like to add a new extended attribute or value, please: +# (1) add the extended attribute or value to this file +# (2) add an explanation to the Blink IDL extended attributes document: +# http://www.chromium.org/blink/webidl/blink-idl-extended-attributes +# (3) add appropriate test cases to run-bindings-tests +# +# The syntax of this file is as follows: +# - One extended attribute per one line: Name and (optionally) Values. +# - "Attr" means that the Attr does not take a value, i.e. [Attr]. +# - "Attr=X" means that Attr takes a required value, which must be X; +# i.e. [Attr=X]. +# - "Attr=X|Y|Z" means that Attr takes a required value, and the valid +# values are X, Y, and Z, and combinations thereof; +# e.g. [Attr=X], [Attr=Y], [Attr=X|Z]. +# The separator must be | or &, so [Attr=X&Z] is also valid; the +# separator makes a difference for Conditional, but otherwise is simply +# a style convention. +# - "Attr=|X|Y|Z" means that Attr takes an optional value, whose valid +# values (if present) are X, Y, and Z, and combinations thereof; e.g. +# [Attr], [Attr=X], [Attr=Y], [Attr=X|Z], [Attr=X|Y|Z], [Attr=X&Z]. +# Note that including an empty value in the list, as in [Attr=X||Y], +# is NOT valid: the value is optional, but empty values are not allowed. +# - "Attr=*" means that Attr takes a required value, which can be +# arbitrary, and combinations thereof, e.g. [Attr=IndexedDB], +# [Attr=DeleteFunction], [Attr=X|Y]. +# - "Attr=|*" means that Attr takes an optional value, which can be +# arbitrary, e.g. [Attr], [Attr=X]. +# - "Attr=X|*" means that Attr takes an required value, which can be +# arbitrary, but that "X" is standard, e.g. [Attr=X], [Attr=Foo]. +# + +ActiveDOMObject +CachedAttribute=* +CallWith=ExecutionContext|ScriptState|ScriptArguments|ActiveWindow|FirstWindow|ThisValue +Constructor +# FIXME: remove [ConstructorCallWith=Document], as can instead use +# [ConstructorCallWith=ExecutionContext] + toDocument(executionContext) +ConstructorCallWith=ExecutionContext|Document +Custom=|Getter|Setter|VisitDOMWrapper|Wrap|PropertyGetter|PropertyEnumerator|PropertyQuery +CustomConstructor +CustomElementCallbacks +Default=Undefined +DependentLifetime +DoNotCheckConstants +EnforceRange +EventConstructor +Exposed=* +Global=|* +Immutable +ImplementedAs=* +InitializedByEventConstructor +Iterable +LegacyTreatAsPartialInterface +NamedConstructor=* +NoImplHeader +NoInterfaceObject +NotEnumerable +NotScriptWrappable +OverrideBuiltins +PartialInterfaceImplementedAs=* +PutForwards=* +RaisesException=|Getter|Setter|Constructor +Reflect=|* +ReflectEmpty=* +ReflectInvalid=* +ReflectMissing=* +ReflectOnly=* +Replaceable +SetWrapperReferenceFrom=* +SetWrapperReferenceTo=* +SetterCallWith=ExecutionContext|ScriptArguments|ActiveWindow|FirstWindow +SpecialWrapFor=* +TreatNullAs=NullString|EmptyString +TreatReturnedNullStringAs=Null|Undefined +TreatUndefinedAs=NullString +TypeChecking=Interface|Unrestricted +URL diff --git a/engine/bindings2/bindings.gni b/engine/bindings2/bindings.gni new file mode 100644 index 00000000000..92726b759a8 --- /dev/null +++ b/engine/bindings2/bindings.gni @@ -0,0 +1,50 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +bindings_scripts_dir = "//sky/engine/bindings2/scripts" +bindings_output_dir = "$root_gen_dir/sky/bindings" + +idl_lexer_parser_files = [ + # PLY (Python Lex-Yacc) + "//third_party/ply/lex.py", + "//third_party/ply/yacc.py", + + # Web IDL lexer/parser (base parser) + "//tools/idl_parser/idl_lexer.py", + "//tools/idl_parser/idl_node.py", + "//tools/idl_parser/idl_parser.py", + + # Blink IDL lexer/parser/constructor + "scripts/blink_idl_lexer.py", + "scripts/blink_idl_parser.py", +] + +idl_compiler_files = [ + "scripts/compiler.py", + + # Blink IDL front end (ex-lexer/parser) + "scripts/idl_definitions.py", + "scripts/idl_reader.py", + "scripts/idl_types.py", + "scripts/idl_validator.py", + "scripts/interface_dependency_resolver.py", + + # Dart Code gen goes here. + "scripts/dart_attributes.py", + "scripts/dart_callback_interface.py", + "scripts/dart_compiler.py", + "scripts/dart_interface.py", + "scripts/dart_methods.py", + "scripts/dart_types.py", + "scripts/dart_utilities.py", + "scripts/code_generator_dart.py", + + # The dart files depend on the v8 files. :( + "scripts/v8_attributes.py", + "scripts/v8_globals.py", + "scripts/v8_interface.py", + "scripts/v8_methods.py", + "scripts/v8_types.py", + "scripts/v8_utilities.py", +] diff --git a/engine/bindings2/builtin.cc b/engine/bindings2/builtin.cc new file mode 100644 index 00000000000..5938de54aa7 --- /dev/null +++ b/engine/bindings2/builtin.cc @@ -0,0 +1,60 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "sky/engine/config.h" +#include "sky/engine/bindings2/builtin.h" + +#include "base/logging.h" +#include "dart/runtime/include/dart_api.h" +#include "gen/sky/bindings/DartGlobal.h" +#include "sky/engine/bindings2/builtin_natives.h" +#include "sky/engine/bindings2/builtin_sky.h" +#include "sky/engine/bindings2/mojo_natives.h" + +namespace blink { +namespace { + +struct LibraryDescriptor { + const char* url; + bool has_natives; + Dart_NativeEntrySymbol native_symbol; + Dart_NativeEntryResolver native_resolver; +}; + +const LibraryDescriptor kBuiltinLibraries[] = { + /* { url_, has_natives_, native_symbol_, native_resolver_ } */ + {"dart:sky_builtin", true, BuiltinNatives::NativeSymbol, BuiltinNatives::NativeLookup}, + {"dart:sky", true, skySnapshotSymbolizer, skySnapshotResolver}, + {"dart:mojo_bindings", false, nullptr, nullptr}, + {"dart:mojo_core", true, MojoNativeSymbol, MojoNativeLookup}, +}; + +} // namespace + +void Builtin::SetNativeResolver(BuiltinLibraryId id) { + static_assert(arraysize(kBuiltinLibraries) == kInvalidLibrary, + "Unexpected number of builtin libraries"); + DCHECK_GE(id, kBuiltinLibrary); + DCHECK_LT(id, kInvalidLibrary); + if (kBuiltinLibraries[id].has_natives) { + Dart_Handle library = DartBuiltin::LookupLibrary(kBuiltinLibraries[id].url); + // Setup the native resolver for built in library functions. + DART_CHECK_VALID( + Dart_SetNativeResolver(library, + kBuiltinLibraries[id].native_resolver, + kBuiltinLibraries[id].native_symbol)); + } +} + +Dart_Handle Builtin::LoadAndCheckLibrary(BuiltinLibraryId id) { + static_assert(arraysize(kBuiltinLibraries) == kInvalidLibrary, + "Unexpected number of builtin libraries"); + DCHECK_GE(id, kBuiltinLibrary); + DCHECK_LT(id, kInvalidLibrary); + Dart_Handle library = DartBuiltin::LookupLibrary(kBuiltinLibraries[id].url); + DART_CHECK_VALID(library); + return library; +} + +} // namespace blink diff --git a/engine/bindings2/builtin.dart b/engine/bindings2/builtin.dart new file mode 100644 index 00000000000..8dc83511346 --- /dev/null +++ b/engine/bindings2/builtin.dart @@ -0,0 +1,53 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +library sky_builtin; + +import "dart:async"; + +// Corelib 'print' implementation. +void _print(arg) { + _Logger._printString(arg.toString()); +} + +class _Logger { + static void _printString(String s) native "Logger_PrintString"; +} + +class _Timer implements Timer { + _Timer(int milliseconds, + void callback(Timer timer), + bool repeating) { + _id = _create(milliseconds, () { + if (!repeating) + _id = 0; + callback(this); + }, repeating); + } + + void cancel() { + _cancel(_id); + _id = 0; + } + + bool get isActive => _id != 0; + + static int _create(int milliseconds, + void callback(), + bool repeating) native "Timer_create"; + static void _cancel(int id) native "Timer_cancel"; + + int _id; +} + +void _scheduleMicrotask(void callback()) native "ScheduleMicrotask"; +Timer _createTimer(int milliseconds, + void callback(Timer timer), + bool repeating) { + return new _Timer(milliseconds, callback, repeating); +} + +_getPrintClosure() => _print; +_getScheduleMicrotaskClosure() => _scheduleMicrotask; +_getCreateTimerClosure() => _createTimer; diff --git a/engine/bindings2/builtin.h b/engine/bindings2/builtin.h new file mode 100644 index 00000000000..0a1b616fc46 --- /dev/null +++ b/engine/bindings2/builtin.h @@ -0,0 +1,34 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SKY_ENGINE_BINDINGS2_BUILTIN_H_ +#define SKY_ENGINE_BINDINGS2_BUILTIN_H_ + +#include "base/macros.h" +#include "dart/runtime/include/dart_api.h" + +namespace blink { + +class Builtin { + public: + // Note: Changes to this enum should be accompanied with changes to + // the builtin_libraries_ array in builtin.cc. + enum BuiltinLibraryId { + kBuiltinLibrary, + kSkyLibrary, + kMojoBindingsLibrary, + kMojoCoreLibrary, + kInvalidLibrary, + }; + + static void SetNativeResolver(BuiltinLibraryId id); + static Dart_Handle LoadAndCheckLibrary(BuiltinLibraryId id); + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(Builtin); +}; + +} // namespace blink + +#endif // SKY_ENGINE_BINDINGS2_BUILTIN_H_ diff --git a/engine/bindings2/builtin_natives.cc b/engine/bindings2/builtin_natives.cc new file mode 100644 index 00000000000..2e890063f0d --- /dev/null +++ b/engine/bindings2/builtin_natives.cc @@ -0,0 +1,184 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "sky/engine/config.h" +#include "sky/engine/bindings2/builtin_natives.h" + +#include +#include +#include + +#include "base/bind.h" +#include "base/logging.h" +#include "base/macros.h" +#include "dart/runtime/include/dart_api.h" +#include "sky/engine/bindings2/builtin.h" +#include "sky/engine/core/dom/Microtask.h" +#include "sky/engine/core/script/dom_dart_state.h" +#include "sky/engine/tonic/dart_api_scope.h" +#include "sky/engine/tonic/dart_error.h" +#include "sky/engine/tonic/dart_isolate_scope.h" +#include "sky/engine/tonic/dart_state.h" +#include "sky/engine/tonic/dart_value.h" +#include "sky/engine/wtf/text/WTFString.h" + +namespace blink { + +#define REGISTER_FUNCTION(name, count) \ + { "" #name, name, count }, +#define DECLARE_FUNCTION(name, count) \ + extern void name(Dart_NativeArguments args); + +// Lists the native functions implementing basic functionality in +// the Mojo embedder dart, such as printing, and file I/O. +#define BUILTIN_NATIVE_LIST(V) \ + V(Logger_PrintString, 1) \ + V(ScheduleMicrotask, 1) \ + V(Timer_create, 3) \ + V(Timer_cancel, 1) + +BUILTIN_NATIVE_LIST(DECLARE_FUNCTION); + +static struct NativeEntries { + const char* name; + Dart_NativeFunction function; + int argument_count; +} BuiltinEntries[] = {BUILTIN_NATIVE_LIST(REGISTER_FUNCTION)}; + +Dart_NativeFunction BuiltinNatives::NativeLookup(Dart_Handle name, + int argument_count, + bool* auto_setup_scope) { + const char* function_name = nullptr; + Dart_Handle result = Dart_StringToCString(name, &function_name); + DART_CHECK_VALID(result); + DCHECK(function_name != nullptr); + DCHECK(auto_setup_scope != nullptr); + *auto_setup_scope = true; + size_t num_entries = arraysize(BuiltinEntries); + for (size_t i = 0; i < num_entries; i++) { + const struct NativeEntries& entry = BuiltinEntries[i]; + if (!strcmp(function_name, entry.name) && + (entry.argument_count == argument_count)) { + return entry.function; + } + } + return nullptr; +} + +const uint8_t* BuiltinNatives::NativeSymbol(Dart_NativeFunction native_function) { + size_t num_entries = arraysize(BuiltinEntries); + for (size_t i = 0; i < num_entries; i++) { + const struct NativeEntries& entry = BuiltinEntries[i]; + if (entry.function == native_function) { + return reinterpret_cast(entry.name); + } + } + return nullptr; +} + +static Dart_Handle GetClosure(Dart_Handle builtin_library, const char* name) { + Dart_Handle getter_name = ToDart(name); + Dart_Handle closure = Dart_Invoke(builtin_library, getter_name, 0, nullptr); + DART_CHECK_VALID(closure); + return closure; +} + +static void InitDartInternal(Dart_Handle builtin_library) { + Dart_Handle print = GetClosure(builtin_library, "_getPrintClosure"); + Dart_Handle timer = GetClosure(builtin_library, "_getCreateTimerClosure"); + + Dart_Handle internal_library = DartBuiltin::LookupLibrary("dart:_internal") + + DART_CHECK_VALID(Dart_SetField( + internal_library, ToDart("_printClosure"), print)); + + Dart_Handle vm_hooks_name = ToDart("VMLibraryHooks"); + Dart_Handle vm_hooks = Dart_GetClass(internal_library, vm_hooks_name); + DART_CHECK_VALID(vm_hooks); + Dart_Handle timer_name = ToDart("timerFactory"); + DART_CHECK_VALID(Dart_SetField(vm_hooks, timer_name, timer)); +} + +static void InitAsync(Dart_Handle builtin_library) { + Dart_Handle schedule_microtask = + GetClosure(builtin_library, "_getScheduleMicrotaskClosure"); + Dart_Handle internal_library = DartBuiltin::LookupLibrary("dart:async") + Dart_Handle set_schedule_microtask = ToDart("_setScheduleImmediateClosure"); + DART_CHECK_VALID(Dart_Invoke(async_library, set_schedule_microtask, 1, + &schedule_microtask)); +} + +void BuiltinNatives::Init() { + Dart_Handle builtin = Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary); + DART_CHECK_VALID(builtin); + InitDartInternal(builtin); + InitAsync(builtin); +} + +// Implementation of native functions which are used for some +// test/debug functionality in standalone dart mode. +void Logger_PrintString(Dart_NativeArguments args) { + intptr_t length = 0; + uint8_t* chars = nullptr; + Dart_Handle str = Dart_GetNativeArgument(args, 0); + Dart_Handle result = Dart_StringToUTF8(str, &chars, &length); + if (Dart_IsError(result)) { + Dart_PropagateError(result); + } else { + + String message(chars, length); + // TODO(dart): Hook up to developer console (if/when that's a thing). +#if OS(ANDROID) + LOG(INFO) << "CONSOLE: " << message.utf8().data(); +#else + printf("CONSOLE: %s\n", message.utf8().data()); + fflush(stdout); +#endif + } +} + +static void ExecuteMicrotask(base::WeakPtr dart_state, + RefPtr callback) { + if (!dart_state) + return; + DartIsolateScope scope(dart_state->isolate()); + DartApiScope api_scope; + LogIfError(Dart_InvokeClosure(callback->dart_value(), 0, nullptr)); +} + +void ScheduleMicrotask(Dart_NativeArguments args) { + Dart_Handle closure = Dart_GetNativeArgument(args, 0); + if (LogIfError(closure) || !Dart_IsClosure(closure)) + return; + DartState* dart_state = DartState::Current(); + Microtask::enqueueMicrotask(base::Bind(&ExecuteMicrotask, + dart_state->GetWeakPtr(), DartValue::Create(dart_state, closure))); +} + +void Timer_create(Dart_NativeArguments args) { + int64_t milliseconds = 0; + DART_CHECK_VALID(Dart_GetNativeIntegerArgument(args, 0, &milliseconds)); + Dart_Handle closure = Dart_GetNativeArgument(args, 1); + DART_CHECK_VALID(closure); + CHECK(Dart_IsClosure(closure)); + bool repeating = false; + DART_CHECK_VALID(Dart_GetNativeBooleanArgument(args, 2, &repeating)); + + DOMDartState* state = DOMDartState::Current(); + int timer_id = DOMTimer::install(state->document(), + ScheduledAction::Create(state, closure), + milliseconds, + !repeating); + Dart_SetIntegerReturnValue(args, timer_id); +} + +void Timer_cancel(Dart_NativeArguments args) { + int64_t timer_id = 0; + DART_CHECK_VALID(Dart_GetNativeIntegerArgument(args, 0, &timer_id)); + + DOMDartState* state = DOMDartState::Current(); + DOMTimer::removeByID(state->document(), timer_id); +} + +} // namespace blink diff --git a/engine/bindings2/builtin_natives.h b/engine/bindings2/builtin_natives.h new file mode 100644 index 00000000000..84b371738a4 --- /dev/null +++ b/engine/bindings2/builtin_natives.h @@ -0,0 +1,28 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SKY_ENGINE_BINDINGS2_BUILTIN_NATIVES_H_ +#define SKY_ENGINE_BINDINGS2_BUILTIN_NATIVES_H_ + +#include "base/macros.h" +#include "dart/runtime/include/dart_api.h" + +namespace blink { + +class BuiltinNatives { + public: + static Dart_NativeFunction NativeLookup(Dart_Handle name, + int argument_count, + bool* auto_setup_scope); + static const uint8_t* NativeSymbol(Dart_NativeFunction native_function); + + static void Init(); + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(BuiltinNatives); +}; + +} // namespace blink + +#endif // SKY_ENGINE_BINDINGS2_BUILTIN_NATIVES_H_ diff --git a/engine/bindings2/builtin_sky.cc b/engine/bindings2/builtin_sky.cc new file mode 100644 index 00000000000..570833d53aa --- /dev/null +++ b/engine/bindings2/builtin_sky.cc @@ -0,0 +1,37 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "sky/engine/config.h" +#include "sky/engine/bindings2/builtin_sky.h" + +#include "sky/engine/bindings2/builtin.h" +#include "sky/engine/core/frame/LocalDOMWindow.h" +#include "sky/engine/core/script/dom_dart_state.h" +#include "sky/engine/tonic/dart_error.h" + +namespace blink { + +BuiltinSky::BuiltinSky(DOMDartState* dart_state) { + Builtin::SetNativeResolver(Builtin::kSkyLibrary); + library_.Set(dart_state, Builtin::LoadAndCheckLibrary(Builtin::kSkyLibrary)); +} + +BuiltinSky::~BuiltinSky() { +} + +void BuiltinSky::InstallWindow(DOMDartState* dart_state) { + CHECK(!LogIfError(Dart_SetField(library_.value(), + ToDart("window"), + ToDart(dart_state->CurrentWindow())))); + // TODO(abarth): Retain the document wrapper. +} + +Dart_Handle BuiltinSky::GetClassByName(const char* class_name) { + Dart_Handle name_handle = ToDart(class_name); + Dart_Handle class_handle = Dart_GetType(library_.value(), name_handle, 0, nullptr); + DCHECK(!Dart_IsError(class_handle)) << class_name; + return class_handle; +} + +} // namespace blink diff --git a/engine/bindings2/builtin_sky.h b/engine/bindings2/builtin_sky.h new file mode 100644 index 00000000000..04bf57258fb --- /dev/null +++ b/engine/bindings2/builtin_sky.h @@ -0,0 +1,34 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SKY_ENGINE_BINDINGS2_BUILTIN_SKY_H_ +#define SKY_ENGINE_BINDINGS2_BUILTIN_SKY_H_ + +#include "base/macros.h" +#include "dart/runtime/include/dart_api.h" +#include "sky/engine/tonic/dart_class_provider.h" +#include "sky/engine/tonic/dart_persistent_value.h" + +namespace blink { +class DOMDartState; + +class BuiltinSky : public DartClassProvider { + public: + explicit BuiltinSky(DOMDartState* dart_state); + ~BuiltinSky(); + + void InstallWindow(DOMDartState* dart_state); + + // DartClassProvider: + Dart_Handle GetClassByName(const char* class_name) override; + + private: + DartPersistentValue library_; + + DISALLOW_COPY_AND_ASSIGN(BuiltinSky); +}; + +} // namespace blink + +#endif // SKY_ENGINE_BINDINGS2_BUILTIN_SKY_H_ diff --git a/engine/bindings2/dart_callback.cc b/engine/bindings2/dart_callback.cc new file mode 100644 index 00000000000..847e1a8ad2b --- /dev/null +++ b/engine/bindings2/dart_callback.cc @@ -0,0 +1,39 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "sky/engine/config.h" +#include "sky/engine/bindings2/dart_callback.h" + +#include "sky/engine/tonic/dart_error.h" +#include "sky/engine/tonic/dart_state.h" + +namespace blink { + +DartCallback::DartCallback(DartState* dart_state, + Dart_Handle callback, + Dart_Handle& exception) + : callback_(dart_state, callback) { + if (!Dart_IsClosure(callback)) { + exception = ToDart("Callback must be a function"); + callback_.Clear(); + } +} + +DartCallback::~DartCallback() { +} + +bool DartCallback::IsIsolateAlive() const { + return !!callback_.dart_state(); +} + +Dart_Isolate DartCallback::GetIsolate() const { + return callback_.dart_state()->isolate(); +} + +bool DartCallback::handleEvent(int argc, Dart_Handle* argv) { + LogIfError(Dart_InvokeClosure(callback_.value(), argc, argv)); + return true; +} + +} // namespace blink diff --git a/engine/bindings2/dart_callback.h b/engine/bindings2/dart_callback.h new file mode 100644 index 00000000000..78c54a636c1 --- /dev/null +++ b/engine/bindings2/dart_callback.h @@ -0,0 +1,30 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SKY_ENGINE_BINDINGS2_DART_CALLBACK_H_ +#define SKY_ENGINE_BINDINGS2_DART_CALLBACK_H_ + +#include "dart/runtime/include/dart_api.h" +#include "sky/engine/tonic/dart_persistent_value.h" + +namespace blink { + +class DartCallback { + public: + DartCallback(DartState* dart_state, + Dart_Handle callback, + Dart_Handle& exception); + ~DartCallback(); + + bool handleEvent(int argc, Dart_Handle* argv); + + bool IsIsolateAlive() const; + Dart_Isolate GetIsolate() const; + + private: + DartPersistentValue callback_; +}; +} + +#endif // SKY_ENGINE_BINDINGS2_DART_CALLBACK_H_ diff --git a/engine/bindings2/dart_event_listener.cc b/engine/bindings2/dart_event_listener.cc new file mode 100644 index 00000000000..70e1b2aa1c7 --- /dev/null +++ b/engine/bindings2/dart_event_listener.cc @@ -0,0 +1,69 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "sky/engine/config.h" +#include "sky/engine/bindings2/dart_event_listener.h" + +#include "sky/engine/core/events/Event.h" +#include "sky/engine/tonic/dart_api_scope.h" +#include "sky/engine/tonic/dart_error.h" +#include "sky/engine/tonic/dart_gc_visitor.h" +#include "sky/engine/tonic/dart_isolate_scope.h" + +namespace blink { + +PassRefPtr DartEventListener::FromDart(Dart_Handle handle) { + if (!Dart_IsClosure(handle)) + return nullptr; + void* peer = nullptr; + CHECK(!Dart_IsError(Dart_GetPeer(handle, &peer))); + if (DartEventListener* listener = static_cast(peer)) + return listener; + RefPtr listener = adoptRef(new DartEventListener(handle)); + listener->data_state_ = DartState::Current()->GetWeakPtr(); + DCHECK(Dart_IsClosure(handle)); + listener->ref(); // Balanced in Finalize + listener->closure_ = Dart_NewPrologueWeakPersistentHandle( + handle, listener.get(), sizeof(*listener), &DartEventListener::Finalize); + CHECK(!Dart_IsError(Dart_SetPeer(handle, listener.get()))); + return listener.release(); +} + +DartEventListener::DartEventListener(Dart_Handle handle) : closure_(nullptr) { +} + +DartEventListener::~DartEventListener() { +} + +void DartEventListener::handleEvent(ExecutionContext* context, Event* event) { + if (!closure_ || !data_state_) + return; + + DartIsolateScope scope(data_state_->isolate()); + DartApiScope api_scope; + + // Notice that we protect ourselves as well as the closure object in the VM. + RefPtr protect(this); + Dart_Handle closure_handle = Dart_HandleFromWeakPersistent(closure_); + Dart_Handle event_handle = ToDart(event); + DCHECK(event_handle); + + Dart_Handle params[] = {event_handle}; + LogIfError(Dart_InvokeClosure(closure_handle, arraysize(params), params)); +} + +void DartEventListener::AcceptDartGCVisitor(DartGCVisitor& visitor) const { + CHECK(!Dart_IsError(Dart_AppendValueToWeakReferenceSet( + visitor.current_set(), closure_))); +} + +void DartEventListener::Finalize(void* isolate_callback_data, + Dart_WeakPersistentHandle handle, + void* peer) { + DartEventListener* listener = static_cast(peer); + listener->closure_ = nullptr; + listener->deref(); // Balances ref in DartEventListener::DartEventListener +} + +} // namespace blink diff --git a/engine/bindings2/dart_event_listener.h b/engine/bindings2/dart_event_listener.h new file mode 100644 index 00000000000..2b3d6fdf867 --- /dev/null +++ b/engine/bindings2/dart_event_listener.h @@ -0,0 +1,64 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SKY_ENGINE_BINDINGS2_DART_EVENT_LISTENER_H_ +#define SKY_ENGINE_BINDINGS2_DART_EVENT_LISTENER_H_ + +#include "dart/runtime/include/dart_api.h" +#include "sky/engine/core/events/EventListener.h" +#include "sky/engine/wtf/PassRefPtr.h" +#include "sky/engine/tonic/dart_converter.h" + +namespace blink { + +class DartEventListener : public EventListener { + public: + static PassRefPtr FromDart(Dart_Handle handle); + + ~DartEventListener() override; + + bool operator==(const EventListener& other) override { + return this == &other; + } + void handleEvent(ExecutionContext*, Event*) override; + + void AcceptDartGCVisitor(DartGCVisitor& visitor) const override; + + private: + explicit DartEventListener(Dart_Handle handle); + + static void Finalize(void* isolate_callback_data, + Dart_WeakPersistentHandle handle, + void* peer); + + base::WeakPtr data_state_; + Dart_WeakPersistentHandle closure_; +}; + +template <> +struct DartConverter { + static PassRefPtr FromDart(Dart_Handle handle) { + return DartEventListener::FromDart(handle); + } + + static PassRefPtr FromArguments(Dart_NativeArguments args, + int index, + Dart_Handle& exception) { + return FromDart(Dart_GetNativeArgument(args, index)); + } + + static PassRefPtr FromArgumentsWithNullCheck( + Dart_NativeArguments args, + int index, + Dart_Handle& exception) { + Dart_Handle handle = Dart_GetNativeArgument(args, index); + if (Dart_IsNull(handle)) + return nullptr; + return FromDart(handle); + } +}; + +} // namespace blink + +#endif // SKY_ENGINE_BINDINGS2_DART_EVENT_LISTENER_H_ diff --git a/engine/bindings2/exception_messages.cc b/engine/bindings2/exception_messages.cc new file mode 100644 index 00000000000..451a8fe73a3 --- /dev/null +++ b/engine/bindings2/exception_messages.cc @@ -0,0 +1,166 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "sky/engine/config.h" +#include "sky/engine/bindings2/exception_messages.h" + +#include "sky/engine/platform/Decimal.h" +#include "sky/engine/wtf/MathExtras.h" + +namespace blink { + +String ExceptionMessages::failedToConstruct(const char* type, + const String& detail) { + return "Failed to construct '" + String(type) + + (!detail.isEmpty() ? String("': " + detail) : String("'")); +} + +String ExceptionMessages::failedToEnumerate(const char* type, + const String& detail) { + return "Failed to enumerate the properties of '" + String(type) + + (!detail.isEmpty() ? String("': " + detail) : String("'")); +} + +String ExceptionMessages::failedToExecute(const char* method, + const char* type, + const String& detail) { + return "Failed to execute '" + String(method) + "' on '" + String(type) + + (!detail.isEmpty() ? String("': " + detail) : String("'")); +} + +String ExceptionMessages::failedToGet(const char* property, + const char* type, + const String& detail) { + return "Failed to read the '" + String(property) + "' property from '" + + String(type) + "': " + detail; +} + +String ExceptionMessages::failedToSet(const char* property, + const char* type, + const String& detail) { + return "Failed to set the '" + String(property) + "' property on '" + + String(type) + "': " + detail; +} + +String ExceptionMessages::failedToDelete(const char* property, + const char* type, + const String& detail) { + return "Failed to delete the '" + String(property) + "' property from '" + + String(type) + "': " + detail; +} + +String ExceptionMessages::failedToGetIndexed(const char* type, + const String& detail) { + return "Failed to read an indexed property from '" + String(type) + "': " + + detail; +} + +String ExceptionMessages::failedToSetIndexed(const char* type, + const String& detail) { + return "Failed to set an indexed property on '" + String(type) + "': " + + detail; +} + +String ExceptionMessages::failedToDeleteIndexed(const char* type, + const String& detail) { + return "Failed to delete an indexed property from '" + String(type) + "': " + + detail; +} + +String ExceptionMessages::constructorNotCallableAsFunction(const char* type) { + return failedToConstruct(type, + "Please use the 'new' operator, this DOM object " + "constructor cannot be called as a function."); +} + +String ExceptionMessages::incorrectPropertyType(const String& property, + const String& detail) { + return "The '" + property + "' property " + detail; +} + +String ExceptionMessages::invalidArity(const char* expected, + unsigned provided) { + return "Valid arities are: " + String(expected) + ", but " + + String::number(provided) + " arguments provided."; +} + +String ExceptionMessages::argumentNullOrIncorrectType( + int argumentIndex, + const String& expectedType) { + return "The " + ordinalNumber(argumentIndex) + + " argument provided is either null, or an invalid " + expectedType + + " object."; +} + +String ExceptionMessages::notAnArrayTypeArgumentOrValue(int argumentIndex) { + String kind; + if (argumentIndex) // method argument + kind = ordinalNumber(argumentIndex) + " argument"; + else // value, e.g. attribute setter + kind = "value provided"; + return "The " + kind + + " is neither an array, nor does it have indexed properties."; +} + +String ExceptionMessages::notASequenceTypeProperty(const String& propertyName) { + return "'" + propertyName + + "' property is neither an array, nor does it have indexed properties."; +} + +String ExceptionMessages::notEnoughArguments(unsigned expected, + unsigned provided) { + return String::number(expected) + " argument" + (expected > 1 ? "s" : "") + + " required, but only " + String::number(provided) + " present."; +} + +String ExceptionMessages::notAFiniteNumber(double value, const char* name) { + ASSERT(!std::isfinite(value)); + return String::format("The %s is %s.", name, + std::isinf(value) ? "infinite" : "not a number"); +} + +String ExceptionMessages::notAFiniteNumber(const Decimal& value, + const char* name) { + ASSERT(!value.isFinite()); + return String::format("The %s is %s.", name, + value.isInfinity() ? "infinite" : "not a number"); +} + +String ExceptionMessages::ordinalNumber(int number) { + String suffix("th"); + switch (number % 10) { + case 1: + if (number % 100 != 11) + suffix = "st"; + break; + case 2: + if (number % 100 != 12) + suffix = "nd"; + break; + case 3: + if (number % 100 != 13) + suffix = "rd"; + break; + } + return String::number(number) + suffix; +} + +String ExceptionMessages::readOnly(const char* detail) { + DEFINE_STATIC_LOCAL(String, readOnly, ("This object is read-only.")); + return detail + ? String::format("This object is read-only, because %s.", detail) + : readOnly; +} + +template <> +String ExceptionMessages::formatNumber(float number) { + return formatPotentiallyNonFiniteNumber(number); +} + +template <> +String ExceptionMessages::formatNumber(double number) { + return formatPotentiallyNonFiniteNumber(number); +} + +} // namespace blink diff --git a/engine/bindings2/exception_messages.h b/engine/bindings2/exception_messages.h new file mode 100644 index 00000000000..1a40c794c76 --- /dev/null +++ b/engine/bindings2/exception_messages.h @@ -0,0 +1,155 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SKY_ENGINE_BINDINGS2_EXCEPTIONMESSAGES_H_ +#define SKY_ENGINE_BINDINGS2_EXCEPTIONMESSAGES_H_ + +#include "sky/engine/wtf/MathExtras.h" +#include "sky/engine/wtf/text/StringBuilder.h" +#include "sky/engine/wtf/text/WTFString.h" + +namespace blink { + +class Decimal; + +class ExceptionMessages { + public: + enum BoundType { + InclusiveBound, + ExclusiveBound, + }; + + static String argumentNullOrIncorrectType(int argumentIndex, + const String& expectedType); + static String constructorNotCallableAsFunction(const char* type); + + static String failedToConstruct(const char* type, const String& detail); + static String failedToEnumerate(const char* type, const String& detail); + static String failedToExecute(const char* method, + const char* type, + const String& detail); + static String failedToGet(const char* property, + const char* type, + const String& detail); + static String failedToSet(const char* property, + const char* type, + const String& detail); + static String failedToDelete(const char* property, + const char* type, + const String& detail); + static String failedToGetIndexed(const char* type, const String& detail); + static String failedToSetIndexed(const char* type, const String& detail); + static String failedToDeleteIndexed(const char* type, const String& detail); + + template + static String formatNumber(NumType number) { + return formatFiniteNumber(number); + } + + static String incorrectPropertyType(const String& property, + const String& detail); + + template + static String indexExceedsMaximumBound(const char* name, + NumberType given, + NumberType bound) { + bool eq = given == bound; + StringBuilder result; + result.appendLiteral("The "); + result.append(name); + result.appendLiteral(" provided ("); + result.append(formatNumber(given)); + result.appendLiteral(") is greater than "); + result.append(eq ? "or equal to " : ""); + result.appendLiteral("the maximum bound ("); + result.append(formatNumber(bound)); + result.appendLiteral(")."); + return result.toString(); + } + + template + static String indexExceedsMinimumBound(const char* name, + NumberType given, + NumberType bound) { + bool eq = given == bound; + StringBuilder result; + result.appendLiteral("The "); + result.append(name); + result.appendLiteral(" provided ("); + result.append(formatNumber(given)); + result.appendLiteral(") is less than "); + result.append(eq ? "or equal to " : ""); + result.appendLiteral("the minimum bound ("); + result.append(formatNumber(bound)); + result.appendLiteral(")."); + return result.toString(); + } + + template + static String indexOutsideRange(const char* name, + NumberType given, + NumberType lowerBound, + BoundType lowerType, + NumberType upperBound, + BoundType upperType) { + StringBuilder result; + result.appendLiteral("The "); + result.append(name); + result.appendLiteral(" provided ("); + result.append(formatNumber(given)); + result.appendLiteral(") is outside the range "); + result.append(lowerType == ExclusiveBound ? '(' : '['); + result.append(formatNumber(lowerBound)); + result.appendLiteral(", "); + result.append(formatNumber(upperBound)); + result.append(upperType == ExclusiveBound ? ')' : ']'); + result.append('.'); + return result.toString(); + } + + static String invalidArity(const char* expected, unsigned provided); + + // If > 0, the argument index that failed type check (1-indexed.) + // If == 0, a (non-argument) value (e.g., a setter) failed the same check. + static String notAnArrayTypeArgumentOrValue(int argumentIndex); + static String notASequenceTypeProperty(const String& propertyName); + static String notAFiniteNumber(double value, + const char* name = "value provided"); + static String notAFiniteNumber(const Decimal& value, + const char* name = "value provided"); + + static String notEnoughArguments(unsigned expected, unsigned provided); + + static String readOnly(const char* detail = 0); + + private: + template + static String formatFiniteNumber(NumType number) { + if (number > 1e20 || number < -1e20) + return String::format("%e", 1.0 * number); + return String::number(number); + } + + template + static String formatPotentiallyNonFiniteNumber(NumType number) { + if (std::isnan(number)) + return "NaN"; + if (std::isinf(number)) + return number > 0 ? "Infinity" : "-Infinity"; + if (number > 1e20 || number < -1e20) + return String::format("%e", number); + return String::number(number); + } + + static String ordinalNumber(int number); +}; + +template <> +String ExceptionMessages::formatNumber(float number); +template <> +String ExceptionMessages::formatNumber(double number); + +} // namespace blink + +#endif // SKY_ENGINE_BINDINGS2_EXCEPTIONMESSAGES_H_ diff --git a/engine/bindings2/exception_state.cc b/engine/bindings2/exception_state.cc new file mode 100644 index 00000000000..3c71fcda242 --- /dev/null +++ b/engine/bindings2/exception_state.cc @@ -0,0 +1,48 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "sky/engine/config.h" +#include "sky/engine/bindings2/exception_state.h" + +namespace blink { + +ExceptionState::ExceptionState() : code_(0), had_exception_(false) { +} + +ExceptionState::ExceptionState(Context context, + const char* propertyName, + const char* interfaceName) { +} + +ExceptionState::ExceptionState(Context context, const char* interfaceName) { +} + +ExceptionState::~ExceptionState() { +} + +void ExceptionState::ThrowDOMException(const ExceptionCode&, + const String& message) { +} + +void ExceptionState::ThrowTypeError(const String& message) { +} + +void ExceptionState::ThrowRangeError(const String& message) { +} + +bool ExceptionState::ThrowIfNeeded() { + return had_exception_; +} + +void ExceptionState::ClearException() { +} + +Dart_Handle ExceptionState::GetDartException(Dart_NativeArguments args, + bool auto_scope) { + // TODO(abarth): Still don't understand autoscope. + DCHECK(auto_scope); + return exception_.Release(); +} + +} // namespace blink diff --git a/engine/bindings2/exception_state.h b/engine/bindings2/exception_state.h new file mode 100644 index 00000000000..e73b88a6fe5 --- /dev/null +++ b/engine/bindings2/exception_state.h @@ -0,0 +1,68 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SKY_ENGINE_BINDINGS2_EXCEPTION_STATE_H_ +#define SKY_ENGINE_BINDINGS2_EXCEPTION_STATE_H_ + +#include "sky/engine/tonic/dart_persistent_value.h" +#include "sky/engine/wtf/Noncopyable.h" +#include "sky/engine/wtf/text/WTFString.h" + +namespace blink { + +typedef int ExceptionCode; + +class ExceptionState { + WTF_MAKE_NONCOPYABLE(ExceptionState); + + public: + enum Context { + ConstructionContext, + ExecutionContext, + DeletionContext, + GetterContext, + SetterContext, + EnumerationContext, + QueryContext, + IndexedGetterContext, + IndexedSetterContext, + IndexedDeletionContext, + UnknownContext, // FIXME: Remove this once we've flipped over to the new + // API. + }; + + ExceptionState(); + ExceptionState(Context context, const char* interfaceName); + ExceptionState(Context context, + const char* propertyName, + const char* interfaceName); + ~ExceptionState(); + + void ThrowDOMException(const ExceptionCode& code, const String& message); + void ThrowTypeError(const String& message); + void ThrowRangeError(const String& message); + + bool ThrowIfNeeded(); + void ClearException(); + + ExceptionCode code() const { return code_; } + const String& message() const { return message_; } + bool had_exception() const { return had_exception_ || code_; } + + Dart_Handle GetDartException(Dart_NativeArguments args, bool auto_scope); + + private: + ExceptionCode code_; + String message_; + bool had_exception_; + DartPersistentValue exception_; +}; + +class NonThrowableExceptionState final : public ExceptionState {}; + +class TrackExceptionState final : public ExceptionState {}; + +} // namespace blink + +#endif // SKY_ENGINE_BINDINGS2_EXCEPTION_STATE_H_ diff --git a/engine/bindings2/exception_state_placeholder.cc b/engine/bindings2/exception_state_placeholder.cc new file mode 100644 index 00000000000..cc75213df26 --- /dev/null +++ b/engine/bindings2/exception_state_placeholder.cc @@ -0,0 +1,19 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "sky/engine/config.h" +#include "sky/engine/bindings2/exception_state_placeholder.h" + +namespace blink { + +#if ENABLE(ASSERT) + +NoExceptionStateAssertionChecker::NoExceptionStateAssertionChecker( + const char* file, + int line) { +} + +#endif + +} // namespace blink diff --git a/engine/bindings2/exception_state_placeholder.h b/engine/bindings2/exception_state_placeholder.h new file mode 100644 index 00000000000..7983f832a18 --- /dev/null +++ b/engine/bindings2/exception_state_placeholder.h @@ -0,0 +1,39 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SKY_ENGINE_BINDINGS2_EXCEPTION_STATE_PLACEHOLDER_H_ +#define SKY_ENGINE_BINDINGS2_EXCEPTION_STATE_PLACEHOLDER_H_ + +#include "sky/engine/bindings2/exception_state.h" +#include "sky/engine/wtf/Assertions.h" + +namespace blink { + +class IgnorableExceptionState final : public ExceptionState { + public: + ExceptionState& ReturnThis() { return *this; } +}; + +#define IGNORE_EXCEPTION (::blink::IgnorableExceptionState().ReturnThis()) + +#if ENABLE(ASSERT) + +class NoExceptionStateAssertionChecker final : public ExceptionState { + public: + NoExceptionStateAssertionChecker(const char* file, int line); + ExceptionState& ReturnThis() { return *this; } +}; + +#define ASSERT_NO_EXCEPTION \ + (::blink::NoExceptionStateAssertionChecker(__FILE__, __LINE__).ReturnThis()) + +#else + +#define ASSERT_NO_EXCEPTION (::blink::IgnorableExceptionState().ReturnThis()) + +#endif + +} // namespace blink + +#endif // SKY_ENGINE_BINDINGS2_EXCEPTION_STATE_PLACEHOLDER_H_ diff --git a/engine/bindings2/mojo_natives.cc b/engine/bindings2/mojo_natives.cc new file mode 100644 index 00000000000..6a853f21010 --- /dev/null +++ b/engine/bindings2/mojo_natives.cc @@ -0,0 +1,804 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include +#include + +#include "base/logging.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "builtin.h" +#include "dart/runtime/include/dart_api.h" +#include "mojo/public/c/system/core.h" +#include "mojo/public/cpp/system/core.h" + +namespace blink { + +#define REGISTER_FUNCTION(name, count) \ + { "" #name, name, count }, +#define DECLARE_FUNCTION(name, count) \ + extern void name(Dart_NativeArguments args); + +#define MOJO_NATIVE_LIST(V) \ + V(MojoSharedBuffer_Create, 2) \ + V(MojoSharedBuffer_Duplicate, 2) \ + V(MojoSharedBuffer_Map, 5) \ + V(MojoSharedBuffer_Unmap, 1) \ + V(MojoDataPipe_Create, 3) \ + V(MojoDataPipe_WriteData, 4) \ + V(MojoDataPipe_BeginWriteData, 3) \ + V(MojoDataPipe_EndWriteData, 2) \ + V(MojoDataPipe_ReadData, 4) \ + V(MojoDataPipe_BeginReadData, 3) \ + V(MojoDataPipe_EndReadData, 2) \ + V(MojoMessagePipe_Create, 1) \ + V(MojoMessagePipe_Write, 5) \ + V(MojoMessagePipe_Read, 5) \ + V(MojoHandle_Close, 1) \ + V(MojoHandle_Wait, 3) \ + V(MojoHandle_Register, 1) \ + V(MojoHandle_WaitMany, 3) \ + V(MojoHandleWatcher_SendControlData, 4) \ + V(MojoHandleWatcher_RecvControlData, 1) \ + V(MojoHandleWatcher_SetControlHandle, 1) \ + V(MojoHandleWatcher_GetControlHandle, 0) + +MOJO_NATIVE_LIST(DECLARE_FUNCTION); + +static struct NativeEntries { + const char* name; + Dart_NativeFunction function; + int argument_count; +} MojoEntries[] = {MOJO_NATIVE_LIST(REGISTER_FUNCTION)}; + +Dart_NativeFunction MojoNativeLookup(Dart_Handle name, + int argument_count, + bool* auto_setup_scope) { + const char* function_name = nullptr; + Dart_Handle result = Dart_StringToCString(name, &function_name); + DART_CHECK_VALID(result); + DCHECK(function_name != nullptr); + DCHECK(auto_setup_scope != nullptr); + *auto_setup_scope = true; + size_t num_entries = arraysize(MojoEntries); + for (size_t i = 0; i < num_entries; ++i) { + const struct NativeEntries& entry = MojoEntries[i]; + if (!strcmp(function_name, entry.name) && + (entry.argument_count == argument_count)) { + return entry.function; + } + } + return nullptr; +} + +const uint8_t* MojoNativeSymbol(Dart_NativeFunction nf) { + size_t num_entries = arraysize(MojoEntries); + for (size_t i = 0; i < num_entries; ++i) { + const struct NativeEntries& entry = MojoEntries[i]; + if (entry.function == nf) { + return reinterpret_cast(entry.name); + } + } + return nullptr; +} + +static void SetNullReturn(Dart_NativeArguments arguments) { + Dart_SetReturnValue(arguments, Dart_Null()); +} + +static void SetInvalidArgumentReturn(Dart_NativeArguments arguments) { + Dart_SetIntegerReturnValue( + arguments, static_cast(MOJO_RESULT_INVALID_ARGUMENT)); +} + +static Dart_Handle MojoLib() { + return DartBuiltins::LookupLibrary("dart:mojo_core"); +} + +static Dart_Handle SignalsStateToDart(Dart_Handle klass, + const MojoHandleSignalsState& state) { + Dart_Handle arg1 = Dart_NewInteger(state.satisfied_signals); + Dart_Handle arg2 = Dart_NewInteger(state.satisfiable_signals); + Dart_Handle args[] = {arg1, arg2}; + return Dart_New(klass, Dart_Null(), 2, args); +} + +#define CHECK_INTEGER_ARGUMENT(args, num, result, failure) \ + { \ + Dart_Handle __status; \ + __status = Dart_GetNativeIntegerArgument(args, num, result); \ + if (Dart_IsError(__status)) { \ + Set##failure##Return(arguments); \ + return; \ + } \ + } \ + +struct CloserCallbackPeer { + MojoHandle handle; +}; + +static void MojoHandleCloserCallback(void* isolate_data, + Dart_WeakPersistentHandle handle, + void* peer) { + CloserCallbackPeer* callback_peer = + reinterpret_cast(peer); + if (callback_peer->handle != MOJO_HANDLE_INVALID) { + MojoClose(callback_peer->handle); + } + delete callback_peer; +} + +// Setup a weak persistent handle for a Dart MojoHandle that calls MojoClose +// on the handle when the MojoHandle is GC'd or the VM is going down. +void MojoHandle_Register(Dart_NativeArguments arguments) { + // An instance of Dart class MojoHandle. + Dart_Handle mojo_handle_instance = Dart_GetNativeArgument(arguments, 0); + if (!Dart_IsInstance(mojo_handle_instance)) { + SetInvalidArgumentReturn(arguments); + return; + } + // TODO(zra): Here, we could check that mojo_handle_instance is really a + // MojoHandle instance, but with the Dart API it's not too easy to get a Type + // object from the class name outside of the root library. For now, we'll rely + // on the existence of the right fields to be sufficient. + + Dart_Handle raw_mojo_handle_instance = Dart_GetField( + mojo_handle_instance, ToDart("_handle")); + if (Dart_IsError(raw_mojo_handle_instance)) { + SetInvalidArgumentReturn(arguments); + return; + } + + Dart_Handle mojo_handle = Dart_GetField( + raw_mojo_handle_instance, ToDart("h")); + if (Dart_IsError(mojo_handle)) { + SetInvalidArgumentReturn(arguments); + return; + } + + int64_t raw_handle = static_cast(MOJO_HANDLE_INVALID); + Dart_Handle result = Dart_IntegerToInt64(mojo_handle, &raw_handle); + if (Dart_IsError(result)) { + SetInvalidArgumentReturn(arguments); + return; + } + + if (raw_handle == static_cast(MOJO_HANDLE_INVALID)) { + SetInvalidArgumentReturn(arguments); + return; + } + + CloserCallbackPeer* callback_peer = new CloserCallbackPeer(); + callback_peer->handle = static_cast(raw_handle); + Dart_NewWeakPersistentHandle(mojo_handle_instance, + reinterpret_cast(callback_peer), + sizeof(CloserCallbackPeer), + MojoHandleCloserCallback); + Dart_SetIntegerReturnValue(arguments, static_cast(MOJO_RESULT_OK)); +} + +void MojoHandle_Close(Dart_NativeArguments arguments) { + int64_t handle; + CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, InvalidArgument); + + MojoResult res = MojoClose(static_cast(handle)); + + Dart_SetIntegerReturnValue(arguments, static_cast(res)); +} + +void MojoHandle_Wait(Dart_NativeArguments arguments) { + int64_t handle = 0; + int64_t signals = 0; + int64_t deadline = 0; + CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, InvalidArgument); + CHECK_INTEGER_ARGUMENT(arguments, 1, &signals, InvalidArgument); + CHECK_INTEGER_ARGUMENT(arguments, 2, &deadline, InvalidArgument); + + MojoHandleSignalsState state; + MojoResult r = mojo::Wait(mojo::Handle(static_cast(handle)), + static_cast(signals), + static_cast(deadline), &state); + + Dart_Handle klass = Dart_GetClass( + MojoLib(), ToDart("MojoHandleSignalsState")); + DART_CHECK_VALID(klass); + + // The return value is structured as a list of length 2: + // [0] MojoResult + // [1] MojoHandleSignalsState. (may be null) + Dart_Handle list = Dart_NewList(2); + Dart_ListSetAt(list, 0, Dart_NewInteger(r)); + if (mojo::WaitManyResult(r).AreSignalsStatesValid()) { + Dart_ListSetAt(list, 1, SignalsStateToDart(klass, state)); + } else { + Dart_ListSetAt(list, 1, Dart_Null()); + } + Dart_SetReturnValue(arguments, list); +} + +void MojoHandle_WaitMany(Dart_NativeArguments arguments) { + int64_t deadline = 0; + Dart_Handle handles = Dart_GetNativeArgument(arguments, 0); + Dart_Handle signals = Dart_GetNativeArgument(arguments, 1); + CHECK_INTEGER_ARGUMENT(arguments, 2, &deadline, InvalidArgument); + + if (!Dart_IsList(handles) || !Dart_IsList(signals)) { + SetInvalidArgumentReturn(arguments); + return; + } + + intptr_t handles_len = 0; + intptr_t signals_len = 0; + Dart_ListLength(handles, &handles_len); + Dart_ListLength(signals, &signals_len); + if (handles_len != signals_len) { + SetInvalidArgumentReturn(arguments); + return; + } + + std::vector mojo_handles(handles_len); + std::vector mojo_signals(handles_len); + + for (int i = 0; i < handles_len; i++) { + Dart_Handle dart_handle = Dart_ListGetAt(handles, i); + Dart_Handle dart_signal = Dart_ListGetAt(signals, i); + if (!Dart_IsInteger(dart_handle) || !Dart_IsInteger(dart_signal)) { + SetInvalidArgumentReturn(arguments); + return; + } + int64_t mojo_handle = 0; + int64_t mojo_signal = 0; + Dart_IntegerToInt64(dart_handle, &mojo_handle); + Dart_IntegerToInt64(dart_signal, &mojo_signal); + mojo_handles[i] = mojo::Handle(mojo_handle); + mojo_signals[i] = static_cast(mojo_signal); + } + + std::vector states(handles_len); + mojo::WaitManyResult wmr = mojo::WaitMany( + mojo_handles, mojo_signals, static_cast(deadline), &states); + + Dart_Handle klass = Dart_GetClass( + MojoLib(), ToDart("MojoHandleSignalsState")); + DART_CHECK_VALID(klass); + + // The return value is structured as a list of length 3: + // [0] MojoResult + // [1] index of handle that caused a return (may be null) + // [2] list of MojoHandleSignalsState. (may be null) + Dart_Handle list = Dart_NewList(3); + Dart_ListSetAt(list, 0, Dart_NewInteger(wmr.result)); + if (wmr.IsIndexValid()) + Dart_ListSetAt(list, 1, Dart_NewInteger(wmr.index)); + else + Dart_ListSetAt(list, 1, Dart_Null()); + if (wmr.AreSignalsStatesValid()) { + Dart_Handle stateList = Dart_NewList(handles_len); + for (int i = 0; i < handles_len; i++) { + Dart_ListSetAt(stateList, i, SignalsStateToDart(klass, states[i])); + } + Dart_ListSetAt(list, 2, stateList); + } else { + Dart_ListSetAt(list, 2, Dart_Null()); + } + Dart_SetReturnValue(arguments, list); +} + +void MojoSharedBuffer_Create(Dart_NativeArguments arguments) { + int64_t num_bytes = 0; + int64_t flags = 0; + CHECK_INTEGER_ARGUMENT(arguments, 0, &num_bytes, Null); + CHECK_INTEGER_ARGUMENT(arguments, 1, &flags, Null); + + MojoCreateSharedBufferOptions options; + options.struct_size = sizeof(MojoCreateSharedBufferOptions); + options.flags = static_cast(flags); + + MojoHandle out = MOJO_HANDLE_INVALID;; + MojoResult res = MojoCreateSharedBuffer( + &options, static_cast(num_bytes), &out); + + Dart_Handle list = Dart_NewList(2); + Dart_ListSetAt(list, 0, Dart_NewInteger(res)); + Dart_ListSetAt(list, 1, Dart_NewInteger(out)); + Dart_SetReturnValue(arguments, list); +} + +void MojoSharedBuffer_Duplicate(Dart_NativeArguments arguments) { + int64_t handle = 0; + int64_t flags = 0; + CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, Null); + CHECK_INTEGER_ARGUMENT(arguments, 1, &flags, Null); + + MojoDuplicateBufferHandleOptions options; + options.struct_size = sizeof(MojoDuplicateBufferHandleOptions); + options.flags = static_cast(flags); + + MojoHandle out = MOJO_HANDLE_INVALID;; + MojoResult res = MojoDuplicateBufferHandle( + static_cast(handle), &options, &out); + + Dart_Handle list = Dart_NewList(2); + Dart_ListSetAt(list, 0, Dart_NewInteger(res)); + Dart_ListSetAt(list, 1, Dart_NewInteger(out)); + Dart_SetReturnValue(arguments, list); +} + +static void MojoBufferUnmapCallback(void* isolate_data, + Dart_WeakPersistentHandle handle, + void* peer) { + MojoUnmapBuffer(peer); +} + +void MojoSharedBuffer_Map(Dart_NativeArguments arguments) { + int64_t handle = 0; + int64_t offset = 0; + int64_t num_bytes = 0; + int64_t flags = 0; + Dart_Handle mojo_buffer = Dart_GetNativeArgument(arguments, 0); + CHECK_INTEGER_ARGUMENT(arguments, 1, &handle, Null); + CHECK_INTEGER_ARGUMENT(arguments, 2, &offset, Null); + CHECK_INTEGER_ARGUMENT(arguments, 3, &num_bytes, Null); + CHECK_INTEGER_ARGUMENT(arguments, 4, &flags, Null); + + void* out; + MojoResult res = MojoMapBuffer(static_cast(handle), + offset, + num_bytes, + &out, + static_cast(flags)); + + Dart_Handle list = Dart_NewList(2); + Dart_Handle typed_data; + if (res == MOJO_RESULT_OK) { + typed_data = Dart_NewExternalTypedData( + Dart_TypedData_kByteData, out, num_bytes); + Dart_NewWeakPersistentHandle( + mojo_buffer, out, num_bytes, MojoBufferUnmapCallback); + } else { + typed_data = Dart_Null(); + } + Dart_ListSetAt(list, 0, Dart_NewInteger(res)); + Dart_ListSetAt(list, 1, typed_data); + Dart_SetReturnValue(arguments, list); +} + +void MojoSharedBuffer_Unmap(Dart_NativeArguments arguments) { + Dart_Handle typed_data = Dart_GetNativeArgument(arguments, 0); + if (Dart_GetTypeOfExternalTypedData(typed_data) == Dart_TypedData_kInvalid) { + SetInvalidArgumentReturn(arguments); + return; + } + + Dart_TypedData_Type typ; + void *data; + intptr_t len; + Dart_TypedDataAcquireData(typed_data, &typ, &data, &len); + MojoResult res = MojoUnmapBuffer(data); + Dart_TypedDataReleaseData(typed_data); + + Dart_SetIntegerReturnValue(arguments, static_cast(res)); +} + +void MojoDataPipe_Create(Dart_NativeArguments arguments) { + int64_t element_bytes = 0; + int64_t capacity_bytes = 0; + int64_t flags = 0; + CHECK_INTEGER_ARGUMENT(arguments, 0, &element_bytes, Null); + CHECK_INTEGER_ARGUMENT(arguments, 1, &capacity_bytes, Null); + CHECK_INTEGER_ARGUMENT(arguments, 2, &flags, Null); + + MojoCreateDataPipeOptions options; + options.struct_size = sizeof(MojoCreateDataPipeOptions); + options.flags = static_cast(flags); + options.element_num_bytes = static_cast(element_bytes); + options.capacity_num_bytes = static_cast(capacity_bytes); + + MojoHandle producer = MOJO_HANDLE_INVALID; + MojoHandle consumer = MOJO_HANDLE_INVALID; + MojoResult res = MojoCreateDataPipe(&options, &producer, &consumer); + + Dart_Handle list = Dart_NewList(3); + Dart_ListSetAt(list, 0, Dart_NewInteger(res)); + Dart_ListSetAt(list, 1, Dart_NewInteger(producer)); + Dart_ListSetAt(list, 2, Dart_NewInteger(consumer)); + Dart_SetReturnValue(arguments, list); +} + +void MojoDataPipe_WriteData(Dart_NativeArguments arguments) { + int64_t handle = 0; + CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, Null); + + Dart_Handle typed_data = Dart_GetNativeArgument(arguments, 1); + if (!Dart_IsTypedData(typed_data)) { + SetNullReturn(arguments); + return; + } + + int64_t num_bytes = 0; + CHECK_INTEGER_ARGUMENT(arguments, 2, &num_bytes, Null); + if (num_bytes <= 0) { + SetNullReturn(arguments); + return; + } + + int64_t flags = 0; + CHECK_INTEGER_ARGUMENT(arguments, 3, &flags, Null); + + Dart_TypedData_Type type; + void* data; + intptr_t data_length; + Dart_TypedDataAcquireData(typed_data, &type, &data, &data_length); + uint32_t length = static_cast(num_bytes); + MojoResult res = MojoWriteData( + static_cast(handle), + data, + &length, + static_cast(flags)); + Dart_TypedDataReleaseData(typed_data); + + Dart_Handle list = Dart_NewList(2); + Dart_ListSetAt(list, 0, Dart_NewInteger(res)); + Dart_ListSetAt(list, 1, Dart_NewInteger(length)); + Dart_SetReturnValue(arguments, list); +} + +void MojoDataPipe_BeginWriteData(Dart_NativeArguments arguments) { + int64_t handle = 0; + int64_t buffer_bytes = 0; + int64_t flags = 0; + CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, Null); + CHECK_INTEGER_ARGUMENT(arguments, 1, &buffer_bytes, Null); + CHECK_INTEGER_ARGUMENT(arguments, 2, &flags, Null); + + void* buffer; + uint32_t size = static_cast(buffer_bytes); + MojoResult res = MojoBeginWriteData( + static_cast(handle), + &buffer, + &size, + static_cast(flags)); + + Dart_Handle list = Dart_NewList(2); + Dart_Handle typed_data; + if (res == MOJO_RESULT_OK) { + typed_data = Dart_NewExternalTypedData( + Dart_TypedData_kByteData, buffer, size); + } else { + typed_data = Dart_Null(); + } + Dart_ListSetAt(list, 0, Dart_NewInteger(res)); + Dart_ListSetAt(list, 1, typed_data); + Dart_SetReturnValue(arguments, list); +} + +void MojoDataPipe_EndWriteData(Dart_NativeArguments arguments) { + int64_t handle = 0; + int64_t num_bytes_written = 0; + CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, InvalidArgument); + CHECK_INTEGER_ARGUMENT(arguments, 1, &num_bytes_written, InvalidArgument); + + MojoResult res = MojoEndWriteData( + static_cast(handle), + static_cast(num_bytes_written)); + + Dart_SetIntegerReturnValue(arguments, static_cast(res)); +} + +void MojoDataPipe_ReadData(Dart_NativeArguments arguments) { + int64_t handle = 0; + CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, Null); + + Dart_Handle typed_data = Dart_GetNativeArgument(arguments, 1); + if (!Dart_IsTypedData(typed_data) && !Dart_IsNull(typed_data)) { + SetNullReturn(arguments); + return; + } + // When querying the amount of data available to read from the pipe, + // null is passed in for typed_data. + + int64_t num_bytes = 0; + CHECK_INTEGER_ARGUMENT(arguments, 2, &num_bytes, Null); + + int64_t flags = 0; + CHECK_INTEGER_ARGUMENT(arguments, 3, &flags, Null); + + Dart_TypedData_Type typ; + void* data = nullptr; + intptr_t bdlen = 0; + if (!Dart_IsNull(typed_data)) { + Dart_TypedDataAcquireData(typed_data, &typ, &data, &bdlen); + } + uint32_t len = static_cast(num_bytes); + MojoResult res = MojoReadData( + static_cast(handle), + data, + &len, + static_cast(flags)); + if (!Dart_IsNull(typed_data)) { + Dart_TypedDataReleaseData(typed_data); + } + + Dart_Handle list = Dart_NewList(2); + Dart_ListSetAt(list, 0, Dart_NewInteger(res)); + Dart_ListSetAt(list, 1, Dart_NewInteger(len)); + Dart_SetReturnValue(arguments, list); +} + +void MojoDataPipe_BeginReadData(Dart_NativeArguments arguments) { + int64_t handle = 0; + int64_t buffer_bytes = 0; + int64_t flags = 0; + CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, Null); + CHECK_INTEGER_ARGUMENT(arguments, 1, &buffer_bytes, Null); + CHECK_INTEGER_ARGUMENT(arguments, 2, &flags, Null); + + void* buffer; + uint32_t size = static_cast(buffer_bytes); + MojoResult res = MojoBeginReadData( + static_cast(handle), + const_cast(&buffer), + &size, + static_cast(flags)); + + Dart_Handle list = Dart_NewList(2); + Dart_Handle typed_data; + if (res == MOJO_RESULT_OK) { + typed_data = Dart_NewExternalTypedData( + Dart_TypedData_kByteData, buffer, size); + } else { + typed_data = Dart_Null(); + } + Dart_ListSetAt(list, 0, Dart_NewInteger(res)); + Dart_ListSetAt(list, 1, typed_data); + Dart_SetReturnValue(arguments, list); +} + +void MojoDataPipe_EndReadData(Dart_NativeArguments arguments) { + int64_t handle = 0; + int64_t num_bytes_read = 0; + CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, InvalidArgument); + CHECK_INTEGER_ARGUMENT(arguments, 1, &num_bytes_read, InvalidArgument); + + MojoResult res = MojoEndReadData( + static_cast(handle), + static_cast(num_bytes_read)); + + Dart_SetIntegerReturnValue(arguments, static_cast(res)); +} + +void MojoMessagePipe_Create(Dart_NativeArguments arguments) { + int64_t flags = 0; + CHECK_INTEGER_ARGUMENT(arguments, 0, &flags, Null); + + MojoCreateMessagePipeOptions options; + options.struct_size = sizeof(MojoCreateMessagePipeOptions); + options.flags = static_cast(flags); + + MojoHandle end1 = MOJO_HANDLE_INVALID; + MojoHandle end2 = MOJO_HANDLE_INVALID; + MojoResult res = MojoCreateMessagePipe(&options, &end1, &end2); + + Dart_Handle list = Dart_NewList(3); + Dart_ListSetAt(list, 0, Dart_NewInteger(res)); + Dart_ListSetAt(list, 1, Dart_NewInteger(end1)); + Dart_ListSetAt(list, 2, Dart_NewInteger(end2)); + Dart_SetReturnValue(arguments, list); +} + +void MojoMessagePipe_Write(Dart_NativeArguments arguments) { + int64_t handle = 0; + CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, InvalidArgument); + + Dart_Handle typed_data = Dart_GetNativeArgument(arguments, 1); + if (!Dart_IsTypedData(typed_data) && !Dart_IsNull(typed_data)) { + SetInvalidArgumentReturn(arguments); + return; + } + + int64_t num_bytes = 0; + CHECK_INTEGER_ARGUMENT(arguments, 2, &num_bytes, InvalidArgument); + if ((Dart_IsNull(typed_data) && (num_bytes != 0)) || + (!Dart_IsNull(typed_data) && (num_bytes <= 0))) { + SetInvalidArgumentReturn(arguments); + return; + } + + Dart_Handle handles = Dart_GetNativeArgument(arguments, 3); + if (!Dart_IsList(handles) && !Dart_IsNull(handles)) { + SetInvalidArgumentReturn(arguments); + return; + } + + int64_t flags = 0; + CHECK_INTEGER_ARGUMENT(arguments, 4, &flags, InvalidArgument); + + // Grab the data if there is any. + Dart_TypedData_Type typ; + void* bytes = nullptr; + intptr_t bdlen = 0; + if (!Dart_IsNull(typed_data)) { + Dart_TypedDataAcquireData(typed_data, &typ, &bytes, &bdlen); + } + + // Grab the handles if there are any. + scoped_ptr mojo_handles; + intptr_t handles_len = 0; + if (!Dart_IsNull(handles)) { + Dart_ListLength(handles, &handles_len); + if (handles_len > 0) { + mojo_handles.reset(new MojoHandle[handles_len]); + } + for (int i = 0; i < handles_len; i++) { + Dart_Handle dart_handle = Dart_ListGetAt(handles, i); + if (!Dart_IsInteger(dart_handle)) { + SetInvalidArgumentReturn(arguments); + return; + } + int64_t mojo_handle = 0; + Dart_IntegerToInt64(dart_handle, &mojo_handle); + mojo_handles[i] = static_cast(mojo_handle); + } + } + + MojoResult res = MojoWriteMessage( + static_cast(handle), + const_cast(bytes), + static_cast(num_bytes), + mojo_handles.get(), + static_cast(handles_len), + static_cast(flags)); + + // Release the data. + if (!Dart_IsNull(typed_data)) { + Dart_TypedDataReleaseData(typed_data); + } + + Dart_SetIntegerReturnValue(arguments, static_cast(res)); +} + +void MojoMessagePipe_Read(Dart_NativeArguments arguments) { + int64_t handle = 0; + CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, Null); + + Dart_Handle typed_data = Dart_GetNativeArgument(arguments, 1); + if (!Dart_IsTypedData(typed_data) && !Dart_IsNull(typed_data)) { + SetNullReturn(arguments); + return; + } + // When querying the amount of data available to read from the pipe, + // null is passed in for typed_data. + + int64_t num_bytes = 0; + CHECK_INTEGER_ARGUMENT(arguments, 2, &num_bytes, Null); + if ((Dart_IsNull(typed_data) && (num_bytes != 0)) || + (!Dart_IsNull(typed_data) && (num_bytes <= 0))) { + SetNullReturn(arguments); + return; + } + + Dart_Handle handles = Dart_GetNativeArgument(arguments, 3); + if (!Dart_IsList(handles) && !Dart_IsNull(handles)) { + SetNullReturn(arguments); + return; + } + + int64_t flags = 0; + CHECK_INTEGER_ARGUMENT(arguments, 4, &flags, Null); + + // Grab the data if there is any. + Dart_TypedData_Type typ; + void* bytes = nullptr; + intptr_t byte_data_len = 0; + if (!Dart_IsNull(typed_data)) { + Dart_TypedDataAcquireData(typed_data, &typ, &bytes, &byte_data_len); + } + uint32_t blen = static_cast(num_bytes); + + // Grab the handles if there are any. + scoped_ptr mojo_handles; + intptr_t handles_len = 0; + if (!Dart_IsNull(handles)) { + Dart_ListLength(handles, &handles_len); + mojo_handles.reset(new MojoHandle[handles_len]); + } + uint32_t hlen = static_cast(handles_len); + + MojoResult res = MojoReadMessage( + static_cast(handle), + bytes, + &blen, + mojo_handles.get(), + &hlen, + static_cast(flags)); + + // Release the data. + if (!Dart_IsNull(typed_data)) { + Dart_TypedDataReleaseData(typed_data); + } + + if (!Dart_IsNull(handles)) { + for (int i = 0; i < handles_len; i++) { + Dart_ListSetAt(handles, i, Dart_NewInteger(mojo_handles[i])); + } + } + + Dart_Handle list = Dart_NewList(3); + Dart_ListSetAt(list, 0, Dart_NewInteger(res)); + Dart_ListSetAt(list, 1, Dart_NewInteger(blen)); + Dart_ListSetAt(list, 2, Dart_NewInteger(hlen)); + Dart_SetReturnValue(arguments, list); +} + +struct ControlData { + int64_t handle; + Dart_Port port; + int64_t data; +}; + +void MojoHandleWatcher_SendControlData(Dart_NativeArguments arguments) { + int64_t control_handle = 0; + int64_t client_handle = 0; + CHECK_INTEGER_ARGUMENT(arguments, 0, &control_handle, InvalidArgument); + CHECK_INTEGER_ARGUMENT(arguments, 1, &client_handle, InvalidArgument); + + Dart_Handle send_port_handle = Dart_GetNativeArgument(arguments, 2); + Dart_Port send_port_id = 0; + if (!Dart_IsNull(send_port_handle)) { + Dart_Handle result = Dart_SendPortGetId(send_port_handle, &send_port_id); + if (Dart_IsError(result)) { + SetInvalidArgumentReturn(arguments); + return; + } + } + + int64_t data = 0; + CHECK_INTEGER_ARGUMENT(arguments, 3, &data, InvalidArgument); + + ControlData cd; + cd.handle = client_handle; + cd.port = send_port_id; + cd.data = data; + const void* bytes = reinterpret_cast(&cd); + MojoResult res = MojoWriteMessage( + control_handle, bytes, sizeof(cd), nullptr, 0, 0); + Dart_SetIntegerReturnValue(arguments, static_cast(res)); +} + +void MojoHandleWatcher_RecvControlData(Dart_NativeArguments arguments) { + int64_t control_handle = 0; + CHECK_INTEGER_ARGUMENT(arguments, 0, &control_handle, Null); + + ControlData cd; + void* bytes = reinterpret_cast(&cd); + uint32_t num_bytes = sizeof(cd); + uint32_t num_handles = 0; + MojoResult res = MojoReadMessage( + control_handle, bytes, &num_bytes, nullptr, &num_handles, 0); + if (res != MOJO_RESULT_OK) { + SetNullReturn(arguments); + return; + } + + Dart_Handle list = Dart_NewList(3); + Dart_ListSetAt(list, 0, Dart_NewInteger(cd.handle)); + Dart_ListSetAt(list, 1, Dart_NewSendPort(cd.port)); + Dart_ListSetAt(list, 2, Dart_NewInteger(cd.data)); + Dart_SetReturnValue(arguments, list); +} + +static int64_t mojo_control_handle = MOJO_HANDLE_INVALID; +void MojoHandleWatcher_SetControlHandle(Dart_NativeArguments arguments) { + int64_t control_handle; + CHECK_INTEGER_ARGUMENT(arguments, 0, &control_handle, InvalidArgument); + mojo_control_handle = control_handle; + Dart_SetIntegerReturnValue(arguments, static_cast(MOJO_RESULT_OK)); +} + +void MojoHandleWatcher_GetControlHandle(Dart_NativeArguments arguments) { + Dart_SetIntegerReturnValue(arguments, mojo_control_handle); +} + +} // namespace blink diff --git a/engine/bindings2/mojo_natives.h b/engine/bindings2/mojo_natives.h new file mode 100644 index 00000000000..79e0c8dde82 --- /dev/null +++ b/engine/bindings2/mojo_natives.h @@ -0,0 +1,20 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SKY_ENGINE_BINDINGS2_MOJO_NATIVES_H_ +#define SKY_ENGINE_BINDINGS2_MOJO_NATIVES_H_ + +#include "dart/runtime/include/dart_api.h" + +namespace blink { + +Dart_NativeFunction MojoNativeLookup(Dart_Handle name, + int argument_count, + bool* auto_setup_scope); + +const uint8_t* MojoNativeSymbol(Dart_NativeFunction nf); + +} // namespace blink + +#endif // SKY_ENGINE_BINDINGS2_MOJO_NATIVES_H_ diff --git a/engine/bindings2/nullable.h b/engine/bindings2/nullable.h new file mode 100644 index 00000000000..4bca0bae3f5 --- /dev/null +++ b/engine/bindings2/nullable.h @@ -0,0 +1,54 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SKY_ENGINE_BINDINGS2_NULLABLE_H_ +#define SKY_ENGINE_BINDINGS2_NULLABLE_H_ + +#include "base/logging.h" + +namespace blink { + +template +class Nullable { + public: + Nullable() : value_(), is_null_(true) {} + Nullable(const T& value) : value_(value), is_null_(false) {} + Nullable(const Nullable& other) + : value_(other.value_), is_null_(other.is_null_) {} + + Nullable& operator=(const Nullable& other) = default; + + void set(const T& value) { + value_ = value; + is_null_ = false; + } + + const T& get() const { + DCHECK(!is_null_); + return value_; + } + T& get() { + DCHECK(!is_null_); + return value_; + } + + bool is_null() const { return is_null_; } + + // See comment in RefPtr.h about what UnspecifiedBoolType is. + typedef const T* UnspecifiedBoolType; + operator UnspecifiedBoolType() const { return is_null_ ? 0 : &value_; } + + bool operator==(const Nullable& other) const { + return (is_null_ && other.is_null_) || + (!is_null_ && !other.is_null_ && value_ == other.value_); + } + + private: + T value_; + bool is_null_; +}; + +} // namespace blink + +#endif // SKY_ENGINE_BINDINGS2_NULLABLE_H_ diff --git a/engine/bindings2/scheduled_action.cc b/engine/bindings2/scheduled_action.cc new file mode 100644 index 00000000000..4a9f0496412 --- /dev/null +++ b/engine/bindings2/scheduled_action.cc @@ -0,0 +1,30 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "sky/engine/config.h" +#include "sky/engine/bindings2/scheduled_action.h" + +#include "sky/engine/tonic/dart_api_scope.h" +#include "sky/engine/tonic/dart_error.h" +#include "sky/engine/tonic/dart_isolate_scope.h" + +namespace blink { + +ScheduledAction::ScheduledAction(DartState* dart_state, Dart_Handle closure) + : closure_(dart_state, closure) { + DCHECK(Dart_IsClosure(closure)); +} + +ScheduledAction::~ScheduledAction() { +} + +void ScheduledAction::Execute(ExecutionContext*) { + if (!closure_.dart_state()) + return; + DartIsolateScope scope(closure_.dart_state()->isolate()); + DartApiScope api_scope; + LogIfError(Dart_InvokeClosure(closure_.value(), 0, nullptr)); +} + +} // namespace blink diff --git a/engine/bindings2/scheduled_action.h b/engine/bindings2/scheduled_action.h new file mode 100644 index 00000000000..5a01be2c8b6 --- /dev/null +++ b/engine/bindings2/scheduled_action.h @@ -0,0 +1,37 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SKY_ENGINE_BINDINGS2_SCHEDULED_ACTION_H_ +#define SKY_ENGINE_BINDINGS2_SCHEDULED_ACTION_H_ + +#include "dart/runtime/include/dart_api.h" +#include "sky/engine/tonic/dart_persistent_value.h" +#include "sky/engine/tonic/dart_state.h" +#include "sky/engine/wtf/RefPtr.h" +#include "sky/engine/wtf/PassOwnPtr.h" + +namespace blink { + +class ExecutionContext; + +class ScheduledAction { + public: + static PassOwnPtr Create(DartState* dart_state, + Dart_Handle closure) { + return adoptPtr(new ScheduledAction(dart_state, closure)); + } + + ~ScheduledAction(); + + void Execute(ExecutionContext*); + + private: + ScheduledAction(DartState* dart_state, Dart_Handle closure); + + DartPersistentValue closure_; +}; + +} // namespace blink + +#endif // SKY_ENGINE_BINDINGS2_SCHEDULED_ACTION_H_ diff --git a/engine/bindings2/scripts/templates/attributes_cpp.template b/engine/bindings2/scripts/templates/attributes_cpp.template index 5d6c7aa347b..cc0184087c4 100644 --- a/engine/bindings2/scripts/templates/attributes_cpp.template +++ b/engine/bindings2/scripts/templates/attributes_cpp.template @@ -8,7 +8,7 @@ static void {{static_attribute_name(attribute, 'Getter')}}(Dart_NativeArguments {% if attribute.is_call_with_execution_context %} ExecutionContext* context = DOMDartState::CurrentDocument(); if (!context) { - exception = Dart_NewStringFromCString("Failed to retrieve a context"); + exception = ToDart("Failed to retrieve a context"); goto fail; } {% endif %} @@ -95,7 +95,7 @@ static void {{static_attribute_name(attribute, 'Setter')}}(Dart_NativeArguments ExecutionContext* context = DOMDartState::CurrentDocument(); if (!context) { - exception = Dart_NewStringFromCString("Failed to retrieve a context"); + exception = ToDart("Failed to retrieve a context"); goto fail; } @@ -104,7 +104,7 @@ static void {{static_attribute_name(attribute, 'Setter')}}(Dart_NativeArguments {% if attribute.is_call_with_script_state %} ScriptState* state = DartUtilities::currentScriptState(); if (!state) { - exception = Dart_NewStringFromCString("Failed to retrieve a script state"); + exception = ToDart("Failed to retrieve a script state"); goto fail; } {% endif %} diff --git a/engine/bindings2/scripts/templates/methods_cpp.template b/engine/bindings2/scripts/templates/methods_cpp.template index 4946eb906ba..aac59cd3b93 100644 --- a/engine/bindings2/scripts/templates/methods_cpp.template +++ b/engine/bindings2/scripts/templates/methods_cpp.template @@ -94,14 +94,14 @@ static void {{static_method_name(method.name, overload_index)}}(Dart_NativeArgum {% if method.is_call_with_script_state %} ScriptState* state = DartUtilities::currentScriptState(); if (!state) { - exception = Dart_NewStringFromCString("Failed to retrieve a script state"); + exception = ToDart("Failed to retrieve a script state"); goto fail; } {% endif %} {% if method.is_call_with_execution_context %} ExecutionContext* context = DOMDartState::CurrentDocument(); if (!context) { - exception = Dart_NewStringFromCString("Failed to retrieve a context"); + exception = ToDart("Failed to retrieve a context"); goto fail; } {% endif %} @@ -318,14 +318,14 @@ static void {{static_method_name(constructor.name, overload_index)}}(Dart_Native {% if is_constructor_call_with_execution_context %} ExecutionContext* context = DOMDartState::CurrentDocument(); if (!context) { - exception = Dart_NewStringFromCString("Failed to retrieve a context"); + exception = ToDart("Failed to retrieve a context"); goto fail; } {% endif %} {% if is_constructor_call_with_document or (constructor == named_constructor) %} LocalDOMWindow* domWindow = DOMDartState::CurrentWindow(); if (!domWindow) { - exception = Dart_NewStringFromCString("Failed to fetch domWindow"); + exception = ToDart("Failed to fetch domWindow"); goto fail; } Document& document = *domWindow->document(); diff --git a/engine/bindings2/snapshot.cc.tmpl b/engine/bindings2/snapshot.cc.tmpl new file mode 100644 index 00000000000..f0da857d9e0 --- /dev/null +++ b/engine/bindings2/snapshot.cc.tmpl @@ -0,0 +1,18 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include +#include + +namespace blink { + +// The string on the next line will be filled in with the contents of the +// generated snapshot binary file. +// This string forms the content of a snapshot which is loaded in by dart. +static const uint8_t snapshot_buffer_[] = { % s}; + +const uint8_t* kDartSnapshotBuffer = snapshot_buffer_; + +} // namespace blink diff --git a/engine/bindings2/snapshot.dart b/engine/bindings2/snapshot.dart new file mode 100644 index 00000000000..de3d83adc0b --- /dev/null +++ b/engine/bindings2/snapshot.dart @@ -0,0 +1,16 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; +import 'dart:collection'; +import 'dart:convert'; +import 'dart:core'; +import 'dart:isolate'; +import 'dart:math'; +import 'dart:mirrors'; +import 'dart:mojo_bindings'; +import 'dart:mojo_core'; +import 'dart:sky'; +import 'dart:sky_builtin'; +import 'dart:typed_data'; diff --git a/engine/tonic/dart_builtin.cc b/engine/tonic/dart_builtin.cc index 9a8f5356ab7..aa12de497f3 100644 --- a/engine/tonic/dart_builtin.cc +++ b/engine/tonic/dart_builtin.cc @@ -9,6 +9,7 @@ #include #include "base/logging.h" +#include "sky/engine/tonic/dart_converter.h" namespace blink { @@ -47,4 +48,10 @@ const uint8_t* DartBuiltin::Symbolizer(Dart_NativeFunction native_function) cons return nullptr; } +Dart_Handle DartBuiltin::LookupLibrary(const char* name) { + Dart_Handle library = Dart_LookupLibrary(ToDart(name)); + DCHECK(!Dart_IsError(library)); + return library; +} + } // namespace blink diff --git a/engine/tonic/dart_builtin.h b/engine/tonic/dart_builtin.h index ce0106f80f1..e612e7bbed7 100644 --- a/engine/tonic/dart_builtin.h +++ b/engine/tonic/dart_builtin.h @@ -27,6 +27,9 @@ class DartBuiltin { const uint8_t* Symbolizer(Dart_NativeFunction native_function) const; + // Helper around Dart_LookupLibrary. + static Dart_Handle LookupLibrary(const char* name); + private: const Natives* natives_; size_t count_; diff --git a/engine/tonic/dart_converter.h b/engine/tonic/dart_converter.h index 37b80d63542..381af62d658 100644 --- a/engine/tonic/dart_converter.h +++ b/engine/tonic/dart_converter.h @@ -320,6 +320,12 @@ inline std::string StdStringFromDart(Dart_Handle handle) { return std::string(utf8.data(), utf8.length()); } + +// Alias Dart_NewStringFromCString for less typing. +inline Dart_Handle ToDart(const char* val) { + return Dart_NewStringFromCString(val); +} + } // namespace blink #endif // SKY_ENGINE_TONIC_DART_CONVERTER_H_