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
This commit is contained in:
Eric Seidel 2015-02-12 13:42:11 -08:00
parent aa99c2f67b
commit c7d2352897
32 changed files with 2659 additions and 7 deletions

399
engine/bindings2/BUILD.gn Normal file
View File

@ -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")
}

View File

@ -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

View File

@ -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",
]

View File

@ -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

View File

@ -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;

View File

@ -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_

View File

@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#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<const uint8_t*>(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<DartState> dart_state,
RefPtr<DartValue> 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

View File

@ -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_

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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_

View File

@ -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> 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<DartEventListener*>(peer))
return listener;
RefPtr<DartEventListener> 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<DartEventListener> 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<DartEventListener*>(peer);
listener->closure_ = nullptr;
listener->deref(); // Balances ref in DartEventListener::DartEventListener
}
} // namespace blink

View File

@ -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<DartEventListener> 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<DartState> data_state_;
Dart_WeakPersistentHandle closure_;
};
template <>
struct DartConverter<EventListener*> {
static PassRefPtr<EventListener> FromDart(Dart_Handle handle) {
return DartEventListener::FromDart(handle);
}
static PassRefPtr<EventListener> FromArguments(Dart_NativeArguments args,
int index,
Dart_Handle& exception) {
return FromDart(Dart_GetNativeArgument(args, index));
}
static PassRefPtr<EventListener> 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_

View File

@ -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>(float number) {
return formatPotentiallyNonFiniteNumber(number);
}
template <>
String ExceptionMessages::formatNumber<double>(double number) {
return formatPotentiallyNonFiniteNumber(number);
}
} // namespace blink

View File

@ -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 <typename NumType>
static String formatNumber(NumType number) {
return formatFiniteNumber(number);
}
static String incorrectPropertyType(const String& property,
const String& detail);
template <typename NumberType>
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 <typename NumberType>
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 <typename NumberType>
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 <typename NumType>
static String formatFiniteNumber(NumType number) {
if (number > 1e20 || number < -1e20)
return String::format("%e", 1.0 * number);
return String::number(number);
}
template <typename NumType>
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>(float number);
template <>
String ExceptionMessages::formatNumber<double>(double number);
} // namespace blink
#endif // SKY_ENGINE_BINDINGS2_EXCEPTIONMESSAGES_H_

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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_

View File

@ -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 <stdio.h>
#include <string.h>
#include <vector>
#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<const uint8_t*>(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<int64_t>(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<CloserCallbackPeer*>(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<int64_t>(MOJO_HANDLE_INVALID);
Dart_Handle result = Dart_IntegerToInt64(mojo_handle, &raw_handle);
if (Dart_IsError(result)) {
SetInvalidArgumentReturn(arguments);
return;
}
if (raw_handle == static_cast<int64_t>(MOJO_HANDLE_INVALID)) {
SetInvalidArgumentReturn(arguments);
return;
}
CloserCallbackPeer* callback_peer = new CloserCallbackPeer();
callback_peer->handle = static_cast<MojoHandle>(raw_handle);
Dart_NewWeakPersistentHandle(mojo_handle_instance,
reinterpret_cast<void*>(callback_peer),
sizeof(CloserCallbackPeer),
MojoHandleCloserCallback);
Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(MOJO_RESULT_OK));
}
void MojoHandle_Close(Dart_NativeArguments arguments) {
int64_t handle;
CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, InvalidArgument);
MojoResult res = MojoClose(static_cast<MojoHandle>(handle));
Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(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<MojoHandle>(handle)),
static_cast<MojoHandleSignals>(signals),
static_cast<MojoDeadline>(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::Handle> mojo_handles(handles_len);
std::vector<MojoHandleSignals> 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<MojoHandleSignals>(mojo_signal);
}
std::vector<MojoHandleSignalsState> states(handles_len);
mojo::WaitManyResult wmr = mojo::WaitMany(
mojo_handles, mojo_signals, static_cast<MojoDeadline>(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<MojoCreateSharedBufferOptionsFlags>(flags);
MojoHandle out = MOJO_HANDLE_INVALID;;
MojoResult res = MojoCreateSharedBuffer(
&options, static_cast<int32_t>(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<MojoDuplicateBufferHandleOptionsFlags>(flags);
MojoHandle out = MOJO_HANDLE_INVALID;;
MojoResult res = MojoDuplicateBufferHandle(
static_cast<MojoHandle>(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<MojoHandle>(handle),
offset,
num_bytes,
&out,
static_cast<MojoMapBufferFlags>(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<int64_t>(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<MojoCreateDataPipeOptionsFlags>(flags);
options.element_num_bytes = static_cast<uint32_t>(element_bytes);
options.capacity_num_bytes = static_cast<uint32_t>(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<uint32_t>(num_bytes);
MojoResult res = MojoWriteData(
static_cast<MojoHandle>(handle),
data,
&length,
static_cast<MojoWriteDataFlags>(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<uint32_t>(buffer_bytes);
MojoResult res = MojoBeginWriteData(
static_cast<MojoHandle>(handle),
&buffer,
&size,
static_cast<MojoWriteDataFlags>(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<MojoHandle>(handle),
static_cast<uint32_t>(num_bytes_written));
Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(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<uint32_t>(num_bytes);
MojoResult res = MojoReadData(
static_cast<MojoHandle>(handle),
data,
&len,
static_cast<MojoReadDataFlags>(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<uint32_t>(buffer_bytes);
MojoResult res = MojoBeginReadData(
static_cast<MojoHandle>(handle),
const_cast<const void**>(&buffer),
&size,
static_cast<MojoWriteDataFlags>(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<MojoHandle>(handle),
static_cast<uint32_t>(num_bytes_read));
Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(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<MojoCreateMessagePipeOptionsFlags>(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<MojoHandle[]> 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<MojoHandle>(mojo_handle);
}
}
MojoResult res = MojoWriteMessage(
static_cast<MojoHandle>(handle),
const_cast<const void*>(bytes),
static_cast<uint32_t>(num_bytes),
mojo_handles.get(),
static_cast<uint32_t>(handles_len),
static_cast<MojoWriteMessageFlags>(flags));
// Release the data.
if (!Dart_IsNull(typed_data)) {
Dart_TypedDataReleaseData(typed_data);
}
Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(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<uint32_t>(num_bytes);
// Grab the handles if there are any.
scoped_ptr<MojoHandle[]> 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<uint32_t>(handles_len);
MojoResult res = MojoReadMessage(
static_cast<MojoHandle>(handle),
bytes,
&blen,
mojo_handles.get(),
&hlen,
static_cast<MojoReadMessageFlags>(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<const void*>(&cd);
MojoResult res = MojoWriteMessage(
control_handle, bytes, sizeof(cd), nullptr, 0, 0);
Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(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<void*>(&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<int64_t>(MOJO_RESULT_OK));
}
void MojoHandleWatcher_GetControlHandle(Dart_NativeArguments arguments) {
Dart_SetIntegerReturnValue(arguments, mojo_control_handle);
}
} // namespace blink

View File

@ -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_

View File

@ -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 <typename T>
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_

View File

@ -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

View File

@ -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<ScheduledAction> 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_

View File

@ -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 %}

View File

@ -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();

View File

@ -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 <inttypes.h>
#include <stdint.h>
#include <stddef.h>
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

View File

@ -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';

View File

@ -9,6 +9,7 @@
#include <string.h>
#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

View File

@ -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_;

View File

@ -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_