Apply all blink changes between @202695 and tip of trunk
BUG=
Review URL: https://codereview.chromium.org/1663753002 .
git-svn-id: https://src.chromium.org/blink/branches/dart/2454_1@202765 bbb929c8-8fbe-4397-9dbb-9b2b20218538
diff --git a/LayoutTests/dart/custom/lifecycle-exception-expected.txt b/LayoutTests/dart/custom/lifecycle-exception-expected.txt
index edb61e2..abda6f0 100644
--- a/LayoutTests/dart/custom/lifecycle-exception-expected.txt
+++ b/LayoutTests/dart/custom/lifecycle-exception-expected.txt
@@ -1,16 +1,40 @@
-CONSOLE MESSAGE: before attached throw
-CONSOLE ERROR: line 12: Exception: attached error
+CONSOLE MESSAGE: line 1: before attached throw
+CONSOLE ERROR: line 1: Uncaught Unhandled exception:
+attached error
+#0 Error.attached (lifecycle-exception.dart:38:19)
CONSOLE MESSAGE: before attached throw
CONSOLE MESSAGE: Caught direct throw
-CONSOLE ERROR: line 44: Exception: Class 'Error' has no instance method 'attributeChanged' with matching arguments.
+CONSOLE ERROR: line 1: Uncaught Unhandled exception:
+Class 'Error' has no instance method 'attributeChanged' with matching arguments.
NoSuchMethodError: incorrect number of arguments passed to method named 'attributeChanged'
Receiver: Instance of 'Error'
Tried calling: attributeChanged("foo", null, "bar")
Found: attributeChanged()
-CONSOLE MESSAGE: before detached throw
-CONSOLE ERROR: line 18: Exception: detached error
-CONSOLE ERROR: line 29: Exception: Error2 cannot be created
+#0 Object._noSuchMethod (dart:core-patch/object_patch.dart:42)
+#1 Object.noSuchMethod (dart:core-patch/object_patch.dart:45)
+#2 JSObject.noSuchMethod.throwError (dart:js:xxxx)
+#3 JSObject.noSuchMethod (dart:js:xxxx)
+#4 HtmlDocument.registerElement.<anonymous closure> (dart:html:xxxx)
+#5 JsObject._callMethod (dart:js:xxxx)
+#6 JsNative.callMethod (dart:js:xxxx)
+#7 Blink_JsNative_DomException.callMethod (dart:_blink:xxxx)
+#8 BlinkElement.setAttribute_Callback_2_ (dart:_blink:xxxx)
+#9 Element.setAttribute (dart:html:xxxx)
+#10 main (lifecycle-exception.dart:44:13)
+CONSOLE MESSAGE: line 1: before detached throw
+CONSOLE ERROR: line 1: Uncaught Unhandled exception:
+detached error
+#0 Error.detached (lifecycle-exception.dart:45:13)
+CONSOLE ERROR: line 1: Uncaught Unhandled exception:
+Error2 cannot be created
+#0 HtmlDocument.registerElement.<anonymous closure> (dart:html:xxxx)
+#1 JsObject._callMethod (dart:js:xxxx)
+#2 JsNative.callMethod (dart:js:xxxx)
+#3 Blink_JsNative_DomException.callMethod (dart:_blink:xxxx)
+#4 BlinkDocument.createElement_Callback_1_ (dart:_blink:xxxx)
+#5 Document.createElement (dart:html:xxxx)
+#6 main (lifecycle-exception.dart:53:28)
CONSOLE MESSAGE: false
CONSOLE MESSAGE: true
diff --git a/LayoutTests/dart/dom/Console-expected.txt b/LayoutTests/dart/dom/Console-expected.txt
index 1639efd..a74ef58 100644
--- a/LayoutTests/dart/dom/Console-expected.txt
+++ b/LayoutTests/dart/dom/Console-expected.txt
@@ -1,5 +1,5 @@
-CONSOLE MESSAGE: Test message.
-CONSOLE MESSAGE: 42
-CONSOLE MESSAGE: TestObject instance
-CONSOLE MESSAGE: true
+CONSOLE MESSAGE: line: 1 Test message.
+CONSOLE MESSAGE: line: 1 42
+CONSOLE MESSAGE: line: 1 TestObject instance
+CONSOLE MESSAGE: line: 1 true
PASS
diff --git a/LayoutTests/dart/dom/DOMMap.dart b/LayoutTests/dart/dom/DOMMap.dart
index 98416c6..a37f712 100644
--- a/LayoutTests/dart/dom/DOMMap.dart
+++ b/LayoutTests/dart/dom/DOMMap.dart
@@ -7,12 +7,14 @@
main() {
useHtmlConfiguration(true);
test('ElementsIdentity', () {
+ // Except with Dartium/JS-interop we don't get identity, we'll have
+ // to settle for equality.
DivElement div = new Element.tag('div');
div.id = 'test';
document.body.nodes.add(div);
Element element = document.query('#test');
- Expect.identical(div, element);
+ Expect.equals(div, element);
});
test('TwoIsolates', () {
// Test that we can access the same DOM nodes from different isolates.
diff --git a/LayoutTests/dart/exception-expected.txt b/LayoutTests/dart/exception-expected.txt
index 771c35e..91091c0 100644
--- a/LayoutTests/dart/exception-expected.txt
+++ b/LayoutTests/dart/exception-expected.txt
@@ -1,2 +1,4 @@
-CONSOLE ERROR: line 17: Exception: Thrown from event listener
+CONSOLE ERROR: line 1: Uncaught Unhandled exception:
+Thrown from event listener
+#0 main.<anonymous closure> (exception.html:19:17)
PASS
diff --git a/LayoutTests/dart/inspector/debugger-expected.txt b/LayoutTests/dart/inspector/debugger-expected.txt
index 7147799..d4f34e8 100644
--- a/LayoutTests/dart/inspector/debugger-expected.txt
+++ b/LayoutTests/dart/inspector/debugger-expected.txt
@@ -5,6 +5,9 @@
Call stack:
0) handleMessage2 (debugger.dart:14)
1) handleMessage (debugger.dart:9)
+ 2) Function._apply@915557746 (dart:core-patch/function_patch.dart:7)
+ 3) Function.apply (dart:core-patch/function_patch.dart:28)
+ 4) _CreateDartFunctionForInteropIgnoreThis@342649749.call (dart:js:xxxx)
Script execution resumed.
Script execution paused.
Call stack:
diff --git a/LayoutTests/dart/inspector/scope-variables-expected.txt b/LayoutTests/dart/inspector/scope-variables-expected.txt
index adf0689..e7820e3 100644
--- a/LayoutTests/dart/inspector/scope-variables-expected.txt
+++ b/LayoutTests/dart/inspector/scope-variables-expected.txt
@@ -6,6 +6,9 @@
Call stack:
0) handleMessage2 (scope-variables.dart:24)
1) handleMessage (scope-variables.dart:12)
+ 2) Function._apply@915557746 (dart:core-patch/function_patch.dart:7)
+ 3) Function.apply (dart:core-patch/function_patch.dart:28)
+ 4) _CreateDartFunctionForInteropIgnoreThis@342649749.call (dart:js:xxxx)
Dump scope sections:
Local
@@ -14,7 +17,7 @@
a2: null
b: false
d: 1.618
- event: Instance of 'MessageEvent'
+ event: [object MessageEvent]
i: 42
l: [1, 2, 3]
scope_variables_testLibrary
@@ -29,6 +32,7 @@
dart:_blink: dart.dom._blink(VM_PRIVATE_MANGLING)
dart:_builtin: builtin
dart:_internal: dart._internal(VM_PRIVATE_MANGLING)
+ dart:_vmservice: dart._vmservice(VM_PRIVATE_MANGLING)
dart:async: dart.async
dart:collection: dart.collection
dart:convert: dart.convert
diff --git a/LayoutTests/dart/inspector/scope-variables.dart b/LayoutTests/dart/inspector/scope-variables.dart
index 8ea6dfd..888b9aa 100644
--- a/LayoutTests/dart/inspector/scope-variables.dart
+++ b/LayoutTests/dart/inspector/scope-variables.dart
@@ -40,7 +40,7 @@
var globalArrayVariable = [3, 1, 4, 1, 5, 9];
-String get throwingGetter {
+core.String get throwingGetter {
throw 'only the best reviews';
}
diff --git a/LayoutTests/dart/microtask-queue-expected.txt b/LayoutTests/dart/microtask-queue-expected.txt
index 4857b3c..3b9b506 100644
--- a/LayoutTests/dart/microtask-queue-expected.txt
+++ b/LayoutTests/dart/microtask-queue-expected.txt
@@ -1,6 +1,6 @@
CONSOLE MESSAGE: sending something to the console
CONSOLE MESSAGE: done with main
-CONSOLE MESSAGE: mutation occurred
+CONSOLE MESSAGE: line 1: mutation occurred
layer at (0,0) size 800x600
RenderView at (0,0) size 800x600
layer at (0,0) size 800x600
diff --git a/LayoutTests/dart/multi-wrapper-frame-test.html b/LayoutTests/dart/multi-wrapper-frame-test.html
index 9f246aa..a6a83ea 100644
--- a/LayoutTests/dart/multi-wrapper-frame-test.html
+++ b/LayoutTests/dart/multi-wrapper-frame-test.html
@@ -23,7 +23,7 @@
retainWrappers.add(print(iframe.contentWindow.location));
var jsIframe = new JsObject.fromBrowserObject(iframe);
retainWrappers.add(print(jsIframe['contentDocument']));
- var childNode = jsIframe['contentDocument'].callMethod('getElementById', ['child-div']);
+ var childNode = jsIframe['contentDocument'].getElementById('child-div');
retainWrappers.add(print(childNode));
if (iframes == 3) {
diff --git a/LayoutTests/dart/multiscript-js-interop-expected.txt b/LayoutTests/dart/multiscript-js-interop-expected.txt
new file mode 100644
index 0000000..c061d64
--- /dev/null
+++ b/LayoutTests/dart/multiscript-js-interop-expected.txt
@@ -0,0 +1,5 @@
+CONSOLE MESSAGE: line 1: Running script 0
+CONSOLE MESSAGE: line 1: Running script 1
+CONSOLE MESSAGE: line 1: Running script 2
+CONSOLE MESSAGE: line 1: Running script 3
+PASS
diff --git a/LayoutTests/dart/multiscript-js-interop.dart b/LayoutTests/dart/multiscript-js-interop.dart
new file mode 100644
index 0000000..a795bff
--- /dev/null
+++ b/LayoutTests/dart/multiscript-js-interop.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Dart test for testing isolation across multiple script tags.
+library multiscript_js_interop;
+import 'package:js/js.dart';
+
+typedef int GetValue();
+
+@JS('window')
+class State {
+ // Static stored in Dart so there is a unique value in each Dart DOM isolate.
+ static int sDart = 0;
+
+ @JS('sJs')
+ external static List<UpdateValue> get sJs;
+ @JS('sJs')
+ external static set sJs(List<UpdateValue> v);
+
+ static int getValue() { return sDart; }
+
+ static update() {
+ sDart++;
+ // We set this JS value from Dart to verify that JS Interop can pass Arrays
+ // between Dart and JS correctly.
+ if (sJs == null) {
+ sJs = <UpdateValue>[];
+ }
+ sJs.add(allowInterop(getValue));
+ }
+
+ @JS('registerCallback')
+ external static registerCallback(int index, Function callback);
+}
diff --git a/LayoutTests/dart/multiscript-js-interop.html b/LayoutTests/dart/multiscript-js-interop.html
new file mode 100644
index 0000000..80a7f1b
--- /dev/null
+++ b/LayoutTests/dart/multiscript-js-interop.html
@@ -0,0 +1,124 @@
+<html>
+<head>
+<script type="application/javascript" src="../../../../dart/pkg/unittest/lib/test_controller.js"></script>
+<script type="application/javascript">
+var sJs;
+var callbacks = [];
+var numCallbacks = 0;
+// Trivial method to run all 4 callbacks in order once they are all
+// registered.
+function registerCallback(index, callback) {
+ callbacks[index] = callback;
+ numCallbacks++;
+ if (numCallbacks == 4) {
+ for (var i = 0; i < numCallbacks; i++) {
+ callbacks[i]();
+ }
+ }
+}
+</script>
+</head>
+<body>
+
+<script type="application/dart">
+import 'dart:async';
+import 'package:js/js.dart';
+import 'package:unittest/unittest.dart';
+import 'multiscript-js-interop.dart';
+
+main() {
+ State.registerCallback(0, allowInterop(() {
+ // FIXME: Rewrite this test to use html-imports.
+ print("Running script 0");
+ State.update();
+ expect(State.sJs.length, equals(1));
+ expect(State.sDart, equals(1));
+ }));
+}
+</script>
+
+<script type="application/dart">
+import 'package:js/js.dart';
+import 'dart:math';
+import 'package:unittest/unittest.dart';
+import 'multiscript-js-interop.dart';
+
+@JS()
+external Function get doubleValue;
+@JS()
+external Function set doubleValue(Function v);
+
+main() {
+ State.registerCallback(1, allowInterop(() {
+ print("Running script 1");
+ State.update();
+ expect(State.sJs.length, equals(2));
+ expect(State.sDart, equals(1));
+ doubleValue = allowInterop((x) => x*2);
+ expect(doubleValue(21), equals(42));
+ expect(doubleValue("Foo"), equals("FooFoo"));
+ // Point is not a primitive type so passing it to a different isolate is
+ // not allowed.
+ expect(doubleValue(new Point(2, 4)),
+ equals(new Point(4, 8)));
+ }));
+}
+</script>
+
+<script type="application/dart">
+import 'package:js/js.dart';
+import 'package:unittest/unittest.dart';
+import 'multiscript-js-interop.dart';
+
+main() {
+ State.registerCallback(2, allowInterop(() {
+ print("Running script 2");
+ State.update();
+ expect(State.sJs.length, equals(3));
+ expect(State.sDart, equals(1));
+ }));
+}
+</script>
+
+<script type="application/dart">
+import 'dart:math';
+import 'package:js/js.dart';
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+import 'multiscript-js-interop.dart';
+
+// This function is set by a different isolate.
+@JS()
+external Function get doubleValue;
+
+main() {
+ State.registerCallback(3, allowInterop(() {
+ print("Running script 3");
+ useHtmlConfiguration(true);
+ test('Multiple script tags', () {
+ State.update();
+ expect(State.sJs.length, equals(4));
+ expect(State.sDart, equals(1));
+
+ // doubleValue is from a different Dart isolate but arguments are primitive
+ // types so it is safe to call.
+ expect(doubleValue(21), equals(42));
+ expect(doubleValue("Foo"), equals("FooFoo"));
+ // Point is not a primitive type so passing it to a different isolate
+ // using js interop results in a JsObject rather than a Point. A
+ // NoSuchMethodError is thrown in the other Dart isolate but once the
+ // error gets to this isolate it shows up as just an Unhandled Exception.
+ expect(() {
+ try {
+ doubleValue(new Point(2, 4));
+ } catch (e) {
+ throw new Exception(e.toString());
+ }
+ },
+ throwsException);
+ });
+ }));
+}
+</script>
+</body>
+</html>
diff --git a/LayoutTests/dart/resources/multi-wrapper-frame-child.html b/LayoutTests/dart/resources/multi-wrapper-frame-child.html
index 9e663cb..fddbd1e 100644
--- a/LayoutTests/dart/resources/multi-wrapper-frame-child.html
+++ b/LayoutTests/dart/resources/multi-wrapper-frame-child.html
@@ -26,9 +26,9 @@
childLocation = window.location;
parentWindow = context['parent'];
- parentDocument = context['parent']['document'];
- parentHistory = context['parent']['history'];
- parentLocation = context['parent']['location'];
+ parentDocument = parentWindow.document;
+ parentHistory = parentWindow.history;
+ parentLocation = parentWindow.location;
}
</script>
diff --git a/Source/bindings/core/dart/DartApplicationLoader.cpp b/Source/bindings/core/dart/DartApplicationLoader.cpp
index cd186bb..7f7d3ad 100644
--- a/Source/bindings/core/dart/DartApplicationLoader.cpp
+++ b/Source/bindings/core/dart/DartApplicationLoader.cpp
@@ -30,7 +30,9 @@
#include "config.h"
#include "bindings/core/dart/DartApplicationLoader.h"
+#include "bindings/core/dart/DartController.h"
#include "bindings/core/dart/DartDOMWrapper.h"
+#include "bindings/core/dart/DartJsInterop.h"
#include "bindings/core/dart/DartScriptDebugServer.h"
#include "bindings/core/dart/DartService.h"
#include "bindings/core/dart/DartUtilities.h"
@@ -60,9 +62,6 @@
namespace blink {
-// FIXME(vsm): Define this in a central place.
-static const unsigned dartTypeID = 0xDAADDAAD;
-
PassRefPtr<DartScriptInfo> DartScriptInfo::create(PassRefPtr<Element> scriptElement)
{
RefPtr<DartScriptInfo> scriptInfo = adoptRef(new DartScriptInfo(scriptElement));
@@ -156,23 +155,9 @@
, m_originDocument(document)
, m_loadCallback(nullptr)
, m_domEnabled(domEnabled)
- , m_cacheable(false)
, m_state(Uninitialized)
- , m_snapshotMode(SnapshotOff)
{
ASSERT(m_originDocument);
-
- DEFINE_STATIC_LOCAL(String, setting, (getenv("DART_SNAPSHOT_MODE")));
- if (!setting.isNull()) {
- if (setting == "all")
- m_snapshotMode = SnapshotAll;
- else if (setting == "off")
- m_snapshotMode = SnapshotOff;
- else if (setting == "single")
- m_snapshotMode = SnapshotSingle;
- else
- DartUtilities::reportProblem(m_originDocument, String("Invalid DART_SNAPSHOT_MODE: ") + setting);
- }
}
void DartApplicationLoader::addRequest(PassRefPtr<DartScriptInfo> scriptInfo)
@@ -223,18 +208,6 @@
m_state = Fetching;
- // Check for cached snapshot.
- ScriptResource* scriptResource = sourceCode.resource();
- if (scriptResource && m_snapshotMode != SnapshotOff && scriptResource->cacheHandler()) {
- // This is cacheable if there is a resource we can cache the snapshot on.
- m_cacheable = true;
- CachedMetadata* cachedMetadata = scriptResource->cacheHandler()->cachedMetadata(dartTypeID);
- if (cachedMetadata) {
- loadScriptFromSnapshot(sourceCode.url(), reinterpret_cast<const uint8_t*>(cachedMetadata->data()), cachedMetadata->size());
- return;
- }
- }
-
// Set up root library for main DOM isolate.
{
DartIsolateScope isolateScope(m_isolate);
@@ -337,19 +310,18 @@
RELEASE_ASSERT(m_state == Ready);
}
- {
+ if (m_state != Ready) {
V8Scope v8scope(DartDOMData::current());
Dart_Handle result = Dart_FinalizeLoading(completeFutures);
-
+ if (Dart_IsError(result)) {
+ reportDartError(result);
+ return;
+ }
if (completeFutures && m_domEnabled) {
// Call this after Dart_FinalizeLoading so that everything is ready.
DartScriptDebugServer::shared().deferredReady();
}
- if (Dart_IsError(result)) {
- reportDartError(result);
- return;
- }
}
// Invoke the entry point on the main script URL if it has not yet been
// invoked.
@@ -378,76 +350,147 @@
DART_RECORD_TIMER(" DartApplicationLoader::loadScriptFromSnapshot took");
}
+void DartApplicationLoader::initializePlaceholderInteropClasses()
+{
+ // Generate a stub patch for JsObjectImpl for non-DOM isolates to avoid
+ // warnings about missing classes.
+ DartApiScope apiScope;
+
+ Dart_Handle exception = 0;
+ Vector<InteropPatchFile> patches;
+ InteropPatchFile patch;
+ patch.libraryUri = "dart:js";
+ patch.patchFileUri = "DartJsNonDomIsolateInteropPatch.dart";
+ patch.source =
+ "class JsObjectImpl extends JsObject { JsObjectImpl.internal() : super.internal(); }\n"
+ "class JsFunctionImpl extends JsFunction { JsFunctionImpl.internal() : super.internal(); }\n"
+ "class JsArrayImpl<E> extends JsArray<E> { JsArrayImpl.internal() : super.internal(); }\n"
+ "patch class JSObject { factory JSObject.create(JsObject jsObject) { return new JSObject.internal()..blink_jsObject = jsObject; } }\n"
+ "patch class JSFunction { factory JSFunction.create(JsObject jsObject) { return new JSFunction.internal()..blink_jsObject = jsObject; } }\n"
+ "patch class JSArray { factory JSArray.create(JsObject jsObject) { return new JSArray.internal()..blink_jsObject = jsObject; } }\n"
+ "_registerAllJsInterfaces() {}\n";
+ patches.append(patch);
+ InteropPatchFile htmlPatch;
+ htmlPatch.libraryUri = "dart:html";
+ htmlPatch.patchFileUri = "DartHtmlNonDomIsolateInteropPatch.dart";
+ htmlPatch.source =
+ "patch class Window { factory Window._internalWrap() => new Window.internal_(); }\n"
+ "patch class Document { factory Document._internalWrap() => new Document.internal_(); }\n"
+ "patch class HtmlDocument { factory HtmlDocument._internalWrap() => new HtmlDocument.internal_(); }\n"
+ "patch class Node { factory Node._internalWrap() => new Node.internal_(); }\n"
+ "patch class ConsoleBase { factory ConsoleBase._internalWrap() => new ConsoleBase.internal_(); }\n"
+ "patch class Console { factory Console._internalWrap() => new Console.internal_(); }\n";
+ patches.append(htmlPatch);
+
+ JsInterop::initializeJsInterop(DartDOMData::current(), patches, exception);
+ ASSERT(!exception);
+}
+
void DartApplicationLoader::callEntryPoint()
{
RELEASE_ASSERT(m_state == Ready);
- if (m_cacheable) {
- // Snapshot single-script applications.
- ResourceFetcher* loader = m_originDocument->fetcher();
- FetchRequest request(m_originDocument->completeURL(m_scriptUrlString), FetchInitiatorTypeNames::document);
- ResourcePtr<ScriptResource> scriptResource = ScriptResource::fetch(request, loader);
-
- // Check if already snapshotted.
- if (scriptResource
- && scriptResource->cacheHandler()
- && !scriptResource->cacheHandler()->cachedMetadata(dartTypeID)) {
- uint8_t* buffer;
- intptr_t size;
- Dart_Handle result = Dart_CreateScriptSnapshot(&buffer, &size);
- if (Dart_IsError(result)) {
- reportDartError(result);
- // FIXME: exiting early might be not the best option if error is due to snapshot
- // creation proper (and not due to compilation), even though it's unlikely.
- // Consider other options like Dart_CompileAll.
- return;
- }
-
- Vector<uint8_t>* snapshot = DartDOMData::current()->applicationSnapshot();
- ASSERT(snapshot->isEmpty());
- snapshot->append(buffer, size);
-
- // Write the snapshot.
- scriptResource->cacheHandler()->setCachedMetadata(dartTypeID, reinterpret_cast<const char*>(buffer), size);
- }
- }
-
- m_state = Running;
+ Timeline timeline(m_originDocument->frame(), String("callEntryPoint@") + m_scriptUrlString);
if (m_domEnabled) {
- DartScriptDebugServer::shared().isolateLoaded();
- }
+ Vector<InteropPatchFile> patches;
+ uint8_t* buffer;
+ intptr_t size = 0;
+ uint8_t* script_snapshot = NULL;
+ // Unfortunately we need to execute JsInterop::buildInteropPatchFiles before calling
+ // Dart_FinalizeLoading but buildInteropPatchFiles requires Dart_FinalizeLoading
+ // to be called so we create a copy of the current isolate and execute the method
+ // in that isolate before applying the patch file to the application isolate.
- if (m_domEnabled) {
- V8Scope v8scope(DartDOMData::current());
- Dart_Handle mainLibrary = topLevelLibrary();
-
- logObservatoryInformation();
-
- // Trampoline to invoke main.
- // FIXME: Use the page library instead. To do this, we need to import each script tag's library into the page
- // with a unique prefix to ensure a secondary script doesn't define a main.
- String trampolineUrl = m_scriptUrlString + "$trampoline";
- Dart_Handle trampoline = Dart_LoadLibrary(DartUtilities::safeStringToDartString(trampolineUrl), Dart_NewStringFromCString(""), 0, 0);
- Dart_LibraryImportLibrary(trampoline, mainLibrary, Dart_Null());
-
- Dart_Handle result = Dart_FinalizeLoading(false);
+ // Write out the script snapshot.
+ Dart_Handle result = Dart_CreateScriptSnapshot(&buffer, &size);
if (Dart_IsError(result)) {
+ // Dart_CreateScriptSnapshot shouldn't return error unless the
+ // script will have compile time errors but to be paranoid we
+ // report the error anyway even though it is likely a duplicate.
+ // Devtools dedupe duplicate errors adding a number 2 next to the
+ // error so the user experience hit is small.
+ // This will avoid user confusion if we hit an edge case and
+ // start getting silent failures.
DartUtilities::reportProblem(m_originDocument, result, m_scriptUrlString);
+ // Fall back to the placeholder JsInterop classes as we were
+ // unable to create the isolat e
+ initializePlaceholderInteropClasses();
+ } else {
+ script_snapshot = reinterpret_cast<uint8_t*>(malloc(size));
+ memmove(script_snapshot, buffer, size);
+
+ Dart_Isolate applicationIsolate = Dart_CurrentIsolate();
+ Dart_ExitIsolate();
+
+ char* err = 0;
+ Dart_Isolate ALLOW_UNUSED isolate = DartController::createIsolate("js_interop_codegen_isolate", NULL, NULL, NULL, NULL, false, &err);
+ {
+ ASSERT(!err);
+ ASSERT(Dart_CurrentIsolate() == isolate);
+ DartApiScope apiScope;
+ result = Dart_LoadScriptFromSnapshot(script_snapshot, size);
+ ASSERT(!Dart_IsError(result));
+ Dart_FinalizeLoading(false);
+ Dart_Handle exception = 0;
+ JsInterop::buildInteropPatchFiles(DartDOMData::current(), &patches, exception);
+ if (exception) {
+ DartUtilities::reportProblem(m_originDocument, exception, m_scriptUrlString);
+ }
+ }
+ // TODO(jacobr): do we need to cleanup the dartDOMData for the isolate?
+ Dart_ShutdownIsolate();
+ free(script_snapshot);
+
+ Dart_EnterIsolate(applicationIsolate);
}
- // FIXME: Settle on proper behavior here. We have not determined exactly when
- // or how often we'll call the entry point.
- Dart_Handle entryPoint = Dart_NewStringFromCString("main");
- Dart_Handle main = Dart_LookupFunction(trampoline, entryPoint);
- if (!Dart_IsNull(main)) {
- // FIXME: Avoid relooking up main.
- Dart_Handle result = Dart_Invoke(trampoline, entryPoint, 0, 0);
- if (Dart_IsError(result)) {
- DartUtilities::reportProblem(m_originDocument, result, m_scriptUrlString);
+ {
+ Dart_Handle mainLibrary = topLevelLibrary();
+
+ // Trampoline to invoke main.
+ // FIXME: Use the page library instead. To do this, we need to import each script tag's library into the page
+ // with a unique prefix to ensure a secondary script doesn't define a main.
+ String trampolineUrl = m_scriptUrlString + "$trampoline";
+ Dart_Handle trampoline = Dart_LoadLibrary(DartUtilities::safeStringToDartString(trampolineUrl), Dart_NewStringFromCString(""), 0, 0);
+ Dart_LibraryImportLibrary(trampoline, mainLibrary, Dart_Null());
+
+ DartDOMData* domData = DartDOMData::current();
+ DartApiScope apiScope;
+ V8Scope v8scope(domData);
+
+ Dart_Handle exception = 0;
+ if (patches.size() > 0) {
+ JsInterop::initializeJsInterop(domData, patches, exception);
+ }
+ if (exception) {
+ DartUtilities::reportProblem(m_originDocument, exception, m_scriptUrlString);
+ }
+
+ m_state = Running;
+
+ logObservatoryInformation();
+ {
+ Timeline timeline(m_originDocument->frame(), String("notifyDebugServer@") + m_scriptUrlString);
+ DartScriptDebugServer::shared().registerIsolate(Dart_CurrentIsolate(), m_originDocument->page());
+ DartScriptDebugServer::shared().isolateLoaded();
+ }
+
+ // FIXME: Settle on proper behavior here. We have not determined exactly when
+ // or how often we'll call the entry point.
+ Dart_Handle entryPoint = Dart_NewStringFromCString("main");
+ Dart_Handle main = Dart_LookupFunction(trampoline, entryPoint);
+ if (!Dart_IsNull(main)) {
+ // FIXME: Avoid relooking up main.
+ Dart_Handle result = Dart_Invoke(trampoline, entryPoint, 0, 0);
+ if (Dart_IsError(result)) {
+ DartUtilities::reportProblem(m_originDocument, result, m_scriptUrlString);
+ }
}
}
-
+ } else {
+ initializePlaceholderInteropClasses();
+ m_state = Running;
}
}
@@ -536,9 +579,6 @@
if (m_state == Error)
return;
- if (url != m_scriptUrlString && m_snapshotMode != SnapshotAll)
- m_cacheable = false;
-
RELEASE_ASSERT(m_state == Fetching || m_state == Loading || m_state == DeferredLoading);
findDependences(url, source, lineNumber);
RELEASE_ASSERT(m_state == Error || m_state == Loading || m_state == DeferredLoading);
diff --git a/Source/bindings/core/dart/DartApplicationLoader.h b/Source/bindings/core/dart/DartApplicationLoader.h
index 63c783c..5476b82 100644
--- a/Source/bindings/core/dart/DartApplicationLoader.h
+++ b/Source/bindings/core/dart/DartApplicationLoader.h
@@ -131,6 +131,9 @@
bool uninitialized() const { return m_state == Uninitialized; }
const KURL& scriptUrl() { return m_scriptUrl; }
+
+ static void initializePlaceholderInteropClasses();
+
private:
enum State {
// The application failed to load.
@@ -208,7 +211,6 @@
RefPtr<DartErrorEventDispatcher> m_errorEventDispatcher;
RefPtr<Callback> m_loadCallback;
bool m_domEnabled;
- bool m_cacheable;
ScriptList m_htmlImportedScripts;
UrlSet m_pendingLibraries;
@@ -219,7 +221,6 @@
String m_packageRoot;
State m_state;
- SnapshotMode m_snapshotMode;
friend class DartService;
friend class ScriptLoadedCallback;
diff --git a/Source/bindings/core/dart/DartController.cpp b/Source/bindings/core/dart/DartController.cpp
index a422acf..ed1f28f 100644
--- a/Source/bindings/core/dart/DartController.cpp
+++ b/Source/bindings/core/dart/DartController.cpp
@@ -74,12 +74,15 @@
namespace dart {
namespace bin {
extern unsigned int observatory_assets_archive_len; // NOLINT
-extern const char* observatory_assets_archive; // NOLINT
+extern const uint8_t* observatory_assets_archive; // NOLINT
} // namespace bin
} // namespace dart
namespace blink {
+static bool s_checkedMode = false;
+static bool s_vmHasBeenInitialized = false;
+
static void copyValue(Dart_Handle source, const char* fieldName,
Dart_Handle targetLibrary, const char* targetClass, const char* targetField)
{
@@ -115,7 +118,7 @@
}
Dart_Isolate DartController::createIsolate(const char* scriptURL, const char* entryPoint, const char* packageRoot, Dart_IsolateFlags* flags,
- Document* document, bool isDOMEnabled, bool isDebuggerEnabled, char** errorMessage)
+ Document* document, bool isDOMEnabled, char** errorMessage)
{
DART_START_TIMER();
const uint8_t* snapshot = DartUtilities::isolateSnapshot();
@@ -192,12 +195,6 @@
if (isDOMEnabled) {
Dart_SetMessageNotifyCallback(&messageNotifyCallback);
-
- if (isDebuggerEnabled) {
- DART_RECORD_TIMER(" createIsolate before debug setup");
- DartScriptDebugServer::shared().registerIsolate(isolate, document->page());
- DART_RECORD_TIMER(" createIsolate after debug setup");
- }
}
DART_RECORD_TIMER(" createIsolate done %.3f ms");
@@ -211,7 +208,7 @@
// FIXME: proper error reporting.
char* errorMessage = 0;
- Dart_Isolate newIsolate = createIsolate(scriptURL.utf8().data(), entryPoint.utf8().data(), packageRoot, 0, document, true, true, &errorMessage);
+ Dart_Isolate newIsolate = createIsolate(scriptURL.utf8().data(), entryPoint.utf8().data(), packageRoot, 0, document, true, &errorMessage);
ASSERT(newIsolate);
m_isolates.append(newIsolate);
DART_RECORD_TIMER(" createDOMEnabledIsolate took");
@@ -227,9 +224,13 @@
{
DartApiScope apiScope;
+ V8Scope v8scope(DartDOMData::current());
+
Dart_Handle dummyUrl = DartUtilities::stringToDartString(*new String("dummy"));
Dart_Handle dummySource = DartUtilities::stringToDartString(
*new String("library dummy; main() {}"));
+
+ DartApplicationLoader::initializePlaceholderInteropClasses();
Dart_Handle loadResult = Dart_LoadScript(dummyUrl, dummySource, 0, 0);
if (Dart_IsError(loadResult)) {
DartUtilities::reportProblem(m_frame->document(), loadResult);
@@ -242,7 +243,6 @@
return;
}
- V8Scope v8scope(DartDOMData::current());
Dart_Handle sendPort = Dart_NewSendPort(replyTo);
if (Dart_IsError(sendPort)) {
DartUtilities::reportProblem(m_frame->document(), sendPort);
@@ -317,13 +317,20 @@
void DartController::clearWindowShell()
{
DART_START_TIMER();
- initVMIfNeeded();
- DART_RECORD_TIMER("clearWindowShell::initVM took");
m_loaders.clear();
m_usedNames.clear();
m_isolateNames.clear();
m_mainLoader.clear();
+ DART_RECORD_TIMER("clearWindowShell::initVM took");
+ if (!s_vmHasBeenInitialized) {
+ // No point in doing anything if the vm hasn't even been initialized.
+ // just to be paranoid we clear all our data anyway.
+ m_isolates.clear();
+ m_scriptStates.clear();
+ return;
+ }
+
// Due to synchronous dispatch, we may be in an isolate corresponding to another frame.
// If so, exit here but re-enter before returning.
Dart_Isolate currentIsolate = Dart_CurrentIsolate();
@@ -485,7 +492,7 @@
ASSERT(context->isDocument());
Document* document = static_cast<Document*>(context);
- Dart_Isolate isolate = createIsolate(scriptURL, entryPoint, packageRoot, flags, document, false, true, errorMsg);
+ Dart_Isolate isolate = createIsolate(scriptURL, entryPoint, packageRoot, flags, document, false, errorMsg);
if (!isolate) {
// This triggers an exception in the caller.
@@ -517,11 +524,10 @@
return p;
}
-static void setDartFlags(const char* str)
+static void setDartFlags(const char* str, bool checked)
{
if (!str) {
- Dart_SetVMFlags(0, 0);
- return;
+ str = "";
}
size_t length = strlen(str);
@@ -538,6 +544,15 @@
p = skipBlackSpace(p);
p = skipWhiteSpace(p);
}
+ // Make room for
+ // --ignore_patch_signature_mismatch and
+ // --i_like_slow_isolate_spawn flags.
+ argc += 2;
+
+ if (checked) {
+ argc++;
+ }
+
// Allocate argument array.
const char** argv = new const char*[argc];
@@ -552,6 +567,13 @@
p = skipWhiteSpace(p);
}
+ // We need to force this flag to be on so that Typed JS Interop works.
+ argv[argc++] = "--ignore_patch_signature_mismatch";
+ argv[argc++] = "--i_like_slow_isolate_spawn";
+ if (checked) {
+ argv[argc++] = "--checked";
+ }
+
// Set the flags.
Dart_SetVMFlags(argc, argv);
@@ -640,28 +662,42 @@
static Dart_Handle GetVMServiceAssetsArchiveCallback()
{
- return MakeUint8Array(reinterpret_cast<const uint8_t*>(&dart::bin::observatory_assets_archive[0]), dart::bin::observatory_assets_archive_len);
+ uint8_t* decompressed = 0;
+ unsigned decompressedLen = 0;
+ DartService::DecompressAssets(reinterpret_cast<const uint8_t*>(&dart::bin::observatory_assets_archive[0]), dart::bin::observatory_assets_archive_len, &decompressed, &decompressedLen);
+ return MakeUint8Array(decompressed, decompressedLen);
}
-void DartController::initVMIfNeeded()
+void DartController::initVMIfNeeded(bool checked, Document* document)
{
- static bool hasBeenInitialized = false;
- if (hasBeenInitialized)
- return;
+ if (s_vmHasBeenInitialized) {
+ if (checked != s_checkedMode) {
+ // We are in trouble... the requested checked mode doesn't match the mode we are already in.
+ // We could be smart about restarting the VM but that could be risky as the existing Dart
+ // binding code and nobody else is exercising that VM functionality.
+ const char* message = checked ? "Unable to run script in checked mode as DartVM is already running. Please open the page in a new tab or restart your browser." :
+ "Unable to run script in unchecked mode as DartVM is already running. Please open the page in a new tab or restart your browser.";
+ document->domWindow()->alert(message);
+ DartUtilities::reportProblem(document, message);
+ }
+ return;
+ }
+
+ s_checkedMode = checked;
+ s_vmHasBeenInitialized = true;
char flagsProp[DartUtilities::PROP_VALUE_MAX_LEN];
int propLen = DartUtilities::getProp(
"DART_FLAGS", flagsProp, DartUtilities::PROP_VALUE_MAX_LEN);
if (propLen > 0) {
- setDartFlags(flagsProp);
+ setDartFlags(flagsProp, checked);
} else {
- setDartFlags(0);
+ setDartFlags(0, checked);
}
DartService::Bootstrap();
// FIXME(antonm): implement proper unhandled exception callback.
Dart_Initialize(DartUtilities::vmIsolateSnapshot(), 0, &createPureIsolateCallback, 0, 0, 0, openFileCallback, readFileCallback, writeFileCallback, closeFileCallback, generateEntropy, GetVMServiceAssetsArchiveCallback);
- hasBeenInitialized = true;
}
static bool checkForExpiration()
@@ -791,10 +827,10 @@
}
DART_START_TIMER();
- initVMIfNeeded();
- DART_RECORD_TIMER("evaluate::initVM took");
RefPtr<Element> element(loader->element());
-
+ bool checked = element->hasAttribute("checked") || document->documentElement()->hasAttribute("checked");
+ initVMIfNeeded(checked, document);
+ DART_RECORD_TIMER("evaluate::initVM took");
RefPtr<DartScriptInfo> scriptInfo = DartScriptInfo::create(element);
if (!scriptInfo) {
DartUtilities::reportProblem(document, "Dart script must be in HTML or SVG document.");
diff --git a/Source/bindings/core/dart/DartController.h b/Source/bindings/core/dart/DartController.h
index e541f7e..1afdf3c 100644
--- a/Source/bindings/core/dart/DartController.h
+++ b/Source/bindings/core/dart/DartController.h
@@ -89,14 +89,15 @@
void spawnDomUri(const String& uri);
void spawnHelperDomIsolate(const String& libraryUrl, const String& entryPoint, DartDOMData* parentDOMData, Dart_Port replyTo);
+ static Dart_Isolate createIsolate(const char* scriptURL, const char* entryPoint, const char* packageRoot, Dart_IsolateFlags*,
+ Document*, bool isDOMEnabled, char** errorMessage);
+
private:
const char* ExpirationMessage = "This version of Dartium has expired.\n\n"
"Please download the latest version at https://www.dartlang.org/tools/dartium";
- static void initVMIfNeeded();
+ static void initVMIfNeeded(bool checked, Document*);
- static Dart_Isolate createIsolate(const char* scriptURL, const char* entryPoint, const char* packageRoot, Dart_IsolateFlags*,
- Document*, bool isDOMEnabled, bool isDebuggerEnabled, char** errorMessage);
void shutdownIsolate(Dart_Isolate);
Dart_Isolate createDOMEnabledIsolate(const String& scriptURL, const String& entryPoint, const char* packageRoot, Document*);
diff --git a/Source/bindings/core/dart/DartDOMData.cpp b/Source/bindings/core/dart/DartDOMData.cpp
index e9ab3cb..72b33f5 100644
--- a/Source/bindings/core/dart/DartDOMData.cpp
+++ b/Source/bindings/core/dart/DartDOMData.cpp
@@ -57,9 +57,6 @@
, m_functionType(0)
, m_currentException(0)
, m_rootScriptState(0)
- , m_weakReferenceSetForRootMap(0)
- , m_documentWeakReferenceSet(0)
- , m_weakReferenceSetBuilder(0)
{
}
diff --git a/Source/bindings/core/dart/DartDOMData.h b/Source/bindings/core/dart/DartDOMData.h
index 04a03d5..3b1be8d 100644
--- a/Source/bindings/core/dart/DartDOMData.h
+++ b/Source/bindings/core/dart/DartDOMData.h
@@ -71,7 +71,6 @@
typedef HashSet<DartIsolateDestructionObserver*> DartIsolateDestructionObservers;
typedef Dart_PersistentHandle ClassTable[NumWebkitClassIds];
typedef Dart_PersistentHandle LibraryTable[NumDartLibraryIds];
-typedef HashMap<Node*, Dart_WeakReferenceSet> WeakReferenceSetForRootMap;
class DartDOMData {
public:
@@ -96,6 +95,8 @@
void setApplicationLoader(PassRefPtr<DartApplicationLoader>);
PassRefPtr<DartApplicationLoader> applicationLoader();
+ bool hasApplicationLoader() { return m_applicationLoader; }
+
Vector<uint8_t>* applicationSnapshot() { return &m_applicationSnapshot; }
void setReachableWeakHandle(Dart_WeakPersistentHandle reachableWeakHandle)
@@ -193,33 +194,6 @@
m_currentException = exception;
}
- WeakReferenceSetForRootMap* weakReferenceSetForRootMap() const
- {
- return m_weakReferenceSetForRootMap;
- }
- void setWeakReferenceSetForRootMap(WeakReferenceSetForRootMap* map)
- {
- m_weakReferenceSetForRootMap = map;
- }
-
- Dart_WeakReferenceSet documentWeakReferenceSet() const
- {
- return m_documentWeakReferenceSet;
- }
- void setDocumentWeakReferenceSet(Dart_WeakReferenceSet set)
- {
- m_documentWeakReferenceSet = set;
- }
-
- Dart_WeakReferenceSetBuilder weakReferenceSetBuilder() const
- {
- return m_weakReferenceSetBuilder;
- }
- void setWeakReferenceSetBuilder(Dart_WeakReferenceSetBuilder setBuilder)
- {
- m_weakReferenceSetBuilder = setBuilder;
- }
-
private:
Dart_PersistentHandle getLibrary(int libraryId, const char* name);
@@ -244,10 +218,6 @@
Dart_PersistentHandle m_functionType;
Dart_PersistentHandle m_currentException;
DartScriptState* m_rootScriptState;
-
- WeakReferenceSetForRootMap* m_weakReferenceSetForRootMap;
- Dart_WeakReferenceSet m_documentWeakReferenceSet;
- Dart_WeakReferenceSetBuilder m_weakReferenceSetBuilder;
};
}
diff --git a/Source/bindings/core/dart/DartDOMWrapper.h b/Source/bindings/core/dart/DartDOMWrapper.h
index e43f2b5..8c97b74 100644
--- a/Source/bindings/core/dart/DartDOMWrapper.h
+++ b/Source/bindings/core/dart/DartDOMWrapper.h
@@ -322,7 +322,7 @@
// is kept alive.
intptr_t externalAllocationSize = sizeof(*domObject);
- Dart_WeakPersistentHandle wrapper = Dart_NewPrologueWeakPersistentHandle(
+ Dart_WeakPersistentHandle wrapper = Dart_NewWeakPersistentHandle(
newInstance, blinkHandle, externalAllocationSize, &wrapperWeakCallback<BindingsClass>);
Traits::MapTraits::domMap(domData)->set(domObject, wrapper);
}
diff --git a/Source/bindings/core/dart/DartEventListener.cpp b/Source/bindings/core/dart/DartEventListener.cpp
index a1ed651..338c2f4 100644
--- a/Source/bindings/core/dart/DartEventListener.cpp
+++ b/Source/bindings/core/dart/DartEventListener.cpp
@@ -66,7 +66,7 @@
DartEventListener* listenerObj = listener.get();
intptr_t peerSize = sizeof(*listenerObj);
listener->m_isolate = Dart_CurrentIsolate();
- listener->m_listener = Dart_NewPrologueWeakPersistentHandle(closure, listenerObj, peerSize, &weakCallback);
+ listener->m_listener = Dart_NewWeakPersistentHandle(closure, listenerObj, peerSize, &weakCallback);
result = Dart_SetPeer(closure, listenerObj);
ASSERT(!Dart_IsError(result));
listener->ref();
diff --git a/Source/bindings/core/dart/DartHandleProxy.cpp b/Source/bindings/core/dart/DartHandleProxy.cpp
index e8c8756..89ba858 100644
--- a/Source/bindings/core/dart/DartHandleProxy.cpp
+++ b/Source/bindings/core/dart/DartHandleProxy.cpp
@@ -1201,14 +1201,14 @@
Dart_Handle dartValue;
if (propertyValue->IsFunction()) {
- dartValue = JsInterop::toDart(propertyValue);
+ dartValue = JsInterop::toDart(propertyValue, true);
// We need to wrap the JsFunction object we get back
// from the vanila JsInterop library so that users can
// call it like a normal Dart function instead of
// having to use the apply method.
dartValue = Dart_Invoke(domData->jsLibrary(), Dart_NewStringFromCString("_wrapAsDebuggerVarArgsFunction"), 1, &dartValue);
} else {
- dartValue = JsInterop::toDart(propertyValue);
+ dartValue = JsInterop::toDart(propertyValue, true);
}
locals.append(V8Converter::stringToDart(propertyName));
locals.append(dartValue);
diff --git a/Source/bindings/core/dart/DartInjectedScript.cpp b/Source/bindings/core/dart/DartInjectedScript.cpp
index 1114532..a445655 100644
--- a/Source/bindings/core/dart/DartInjectedScript.cpp
+++ b/Source/bindings/core/dart/DartInjectedScript.cpp
@@ -40,6 +40,7 @@
#include "bindings/core/dart/DartUtilities.h"
#include "bindings/core/dart/V8Converter.h"
#include "bindings/core/v8/ScriptFunctionCall.h"
+#include "bindings/core/v8/V8InjectedScriptHost.h"
#include "core/inspector/InjectedScriptHost.h"
#include "core/inspector/JSONParser.h"
#include "platform/JSONValues.h"
@@ -269,21 +270,25 @@
Dart_DeletePersistentHandle(m_consoleApi);
}
+// Copied from V8injectedScriptManager.
+v8::Local<v8::Object> createInjectedScriptHostV8Wrapper(PassRefPtrWillBeRawPtr<InjectedScriptHost> host, InjectedScriptManager* injectedScriptManager, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
+{
+ return V8DOMWrapper::createWrapper(creationContext, &V8InjectedScriptHost::wrapperTypeInfo,
+ host->toScriptWrappableBase(), isolate);
+}
+
Dart_Handle DartInjectedScript::consoleApi()
{
-/* TODO(terry): Need to re-enable when we figure out how to do:
- *
- * Dart_Handle host = DartInjectedScriptHost::toDart(m_host);
- */
-#if 0
if (!m_consoleApi) {
- Dart_Handle host = DartInjectedScriptHost::toDart(m_host);
+ V8Scope v8scope(DartDOMData::current());
+ v8::Local<v8::Object> scriptHostWrapper = createInjectedScriptHostV8Wrapper(m_host, m_injectedScriptManager, m_scriptState->v8ScriptState()->context()->Global(), v8::Isolate::GetCurrent());
+
+ Dart_Handle host = JsInterop::toDart(scriptHostWrapper, false);
Dart_SetPeer(host, this);
Dart_Handle consoleApi = DartUtilities::invokeUtilsMethod("consoleApi", 1, &host);
ASSERT(!Dart_IsError(consoleApi));
m_consoleApi = Dart_NewPersistentHandle(consoleApi);
}
-#endif
return m_consoleApi;
}
@@ -1200,6 +1205,8 @@
Node* DartInjectedScript::nodeForObjectId(const String& objectId)
{
DartIsolateScope scope(m_scriptState->isolate());
+ DartDOMData* domData = DartDOMData::current();
+ V8Scope v8scope(domData);
DartApiScope apiScope;
DartDebuggerObject* object = lookupObject(objectId);
diff --git a/Source/bindings/core/dart/DartJsInterop.cpp b/Source/bindings/core/dart/DartJsInterop.cpp
index 76ba5dd..4afe555 100644
--- a/Source/bindings/core/dart/DartJsInterop.cpp
+++ b/Source/bindings/core/dart/DartJsInterop.cpp
@@ -147,6 +147,7 @@
"})();";
static v8::Local<v8::FunctionTemplate> dartFunctionTemplate();
+static v8::Local<v8::FunctionTemplate> dartFunctionTemplateNoWrap();
static v8::Local<v8::FunctionTemplate> dartObjectTemplate();
static v8::Local<v8::FunctionTemplate> dartListTemplate();
@@ -190,18 +191,43 @@
// there are 2 arguments, the first argument is "this" and the second
// argument is an array of arguments.
if (args.Length() > 1) {
- dartFunctionArgs.append(JsInterop::toDart(args[0]));
+ dartFunctionArgs.append(JsInterop::toDart(args[0], true));
}
v8::Local<v8::Array> argsList = args[args.Length()-1].As<v8::Array>();
uint32_t argsListLength = argsList->Length();
for (uint32_t i = 0; i < argsListLength; i++) {
- dartFunctionArgs.append(JsInterop::toDart(argsList->Get(i)));
+ dartFunctionArgs.append(JsInterop::toDart(argsList->Get(i), true));
}
setJsReturnValue(domData, args, Dart_InvokeClosure(handle, dartFunctionArgs.size(), dartFunctionArgs.data()));
}
+static void functionInvocationCallbackNoWrap(const v8::FunctionCallbackInfo<v8::Value>& args)
+{
+ DartScopes scopes(args.Holder());
+ Dart_Handle handle = scopes.handle;
+ DartDOMData* domData = DartDOMData::current();
+ ASSERT(domData);
+ ASSERT(DartUtilities::isFunction(domData, handle));
+
+ Vector<Dart_Handle> dartFunctionArgs;
+ ASSERT(args.Length() == 1 || args.Length() == 2);
+ // If there is 1 argument, we assume it is a v8:Array or arguments, if
+ // there are 2 arguments, the first argument is "this" and the second
+ // argument is an array of arguments.
+ if (args.Length() > 1) {
+ dartFunctionArgs.append(JsInterop::toDart(args[0], false));
+ }
+
+ v8::Local<v8::Array> argsList = args[args.Length()-1].As<v8::Array>();
+ uint32_t argsListLength = argsList->Length();
+ for (uint32_t i = 0; i < argsListLength; i++) {
+ dartFunctionArgs.append(JsInterop::toDart(argsList->Get(i), false));
+ }
+
+ setJsReturnValue(domData, args, Dart_InvokeClosure(handle, dartFunctionArgs.size(), dartFunctionArgs.data()));
+}
static v8::Local<v8::ObjectTemplate> setupInstanceTemplate(v8::Local<v8::FunctionTemplate> proxyTemplate)
{
v8::Local<v8::ObjectTemplate> instanceTemplate = proxyTemplate->InstanceTemplate();
@@ -209,6 +235,7 @@
return instanceTemplate;
}
+
static v8::Local<v8::FunctionTemplate> dartFunctionTemplate()
{
DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, proxyTemplate, ());
@@ -226,16 +253,17 @@
return proxyTemplateLocal;
}
-static v8::Local<v8::FunctionTemplate> dartObjectTemplate()
+static v8::Local<v8::FunctionTemplate> dartFunctionTemplateNoWrap()
{
DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, proxyTemplate, ());
v8::Local<v8::FunctionTemplate> proxyTemplateLocal;
v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
if (proxyTemplate.IsEmpty()) {
- proxyTemplate.Reset(v8Isolate, v8::FunctionTemplate::New(v8Isolate));
+ proxyTemplate.Reset(v8::Isolate::GetCurrent(), v8::FunctionTemplate::New(v8Isolate));
proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, proxyTemplate);
- proxyTemplateLocal->SetClassName(v8::String::NewFromUtf8(v8Isolate, "DartObject"));
- setupInstanceTemplate(proxyTemplateLocal);
+ v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(proxyTemplateLocal);
+
+ instanceTemplate->SetCallAsFunctionHandler(&functionInvocationCallbackNoWrap);
} else {
proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, proxyTemplate);
}
@@ -291,7 +319,7 @@
void setReturnValue(v8::Local<v8::Value> ret)
{
ASSERT(!tryCatch.HasCaught());
- Dart_SetReturnValue(args, JsInterop::toDart(ret));
+ Dart_SetReturnValue(args, JsInterop::toDart(ret, false));
ASSERT(!tryCatch.HasCaught());
}
@@ -312,17 +340,19 @@
v8::Handle<v8::Value> value = V8Converter::toV8IfPrimitive(domData, handle, exception);
if (!value.IsEmpty() || exception)
return value;
- // TODO(terry): START of uncommented block by Jacob, I've re-enabled for clamped arrays...
- value = V8Converter::toV8IfBrowserNative(domData, handle, exception);
- if (!value.IsEmpty() || exception)
- return value;
- // TODO(terry): END of uncommented block by Jacob.
- if (DartDOMWrapper::subtypeOf(handle, JsObject::dartClassId)) {
- JsObject* object = DartDOMWrapper::unwrapDartWrapper<JsObject>(domData, handle, exception);
+
+ Dart_Handle jso = invokeTopLevelJsInteropMethod(domData, "unwrap_jso", 1, &handle);
+ ASSERT(!Dart_IsError(jso));
+ if (DartDOMWrapper::subtypeOf(jso, JsObject::dartClassId)) {
+ JsObject* object = DartDOMWrapper::unwrapDartWrapper<JsObject>(domData, jso, exception);
if (exception)
return v8::Local<v8::Value>();
return object->localV8Object();
}
+ // TODO(terry): START of uncommented block by Jacob, I've re-enabled for clamped arrays...
+ value = V8Converter::toV8IfBrowserNative(domData, handle, exception);
+ if (!value.IsEmpty() || exception)
+ return value;
if (DartUtilities::isFunction(domData, handle)) {
v8::Local<v8::Object> functionProxy = dartFunctionTemplate()->InstanceTemplate()->NewInstance();
@@ -395,7 +425,7 @@
return v8::Local<v8::Object>::New(v8::Isolate::GetCurrent(), v8Object);
}
-Dart_Handle JsInterop::toDart(v8::Local<v8::Value> v8Handle)
+Dart_Handle JsInterop::toDart(v8::Local<v8::Value> v8Handle, bool sometimesUseHtml)
{
Dart_Handle handle = V8Converter::toDartIfPrimitive(v8Handle);
if (handle)
@@ -426,27 +456,117 @@
}
}
- return JsObject::toDart(object);
+ return JsObject::toDart(object, sometimesUseHtml);
}
-Dart_Handle JsObject::toDart(v8::Local<v8::Object> object)
+Dart_Handle JsObject::toDart(v8::Local<v8::Object> object, bool sometimesUseHtml)
{
- // FIXME: perform caching so that === can be used.
+ Dart_Handle wrapper;
+ v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
+ DartDOMData* domData = DartDOMData::current();
+ DartJsInteropData* interopData = domData->jsInteropData();
+ v8::Local<v8::String> existingDartWrapperKey = interopData->existingDartWrapperHiddenField(v8Isolate);
+
+ // TODO(alanknight): This will fail for multiple isolates referencing the same JS object.
+ // We probably need to use a different property name for different isolates.
+ v8::Local<v8::Value> hiddenValue = object->GetHiddenValue(existingDartWrapperKey);
+
+ if (*hiddenValue && hiddenValue->IsObject()) {
+ DartPersistentValue* scriptValue = DartHandleProxy::readPointerFromProxy(hiddenValue.As<v8::Object>());
+ ASSERT(scriptValue->isIsolateAlive());
+ // If the isolate does not match we fall back to using the existing JS
+ // wrapper for the Dart object so that simple cases that would work in
+ // Dart2Js work. We could alternately throw an exception here.
+ if (scriptValue->isolate() == Dart_CurrentIsolate()) {
+ Dart_Handle wrapper = scriptValue->value();
+ if (sometimesUseHtml) {
+ wrapper = invokeTopLevelJsInteropMethod(domData, "_maybeWrap", 1, &wrapper);
+ }
+ return wrapper;
+ }
+ }
+
+ Dart_Handle ret = 0;
if (object->IsFunction()) {
RefPtr<JsFunction> jsFunction = JsFunction::create(object.As<v8::Function>());
- return JsFunction::toDart(jsFunction);
+ wrapper = JsFunction::toDart(jsFunction);
+ } else if (object->IsArray()
+ // Check for Dart List objects from different Dart isolates.
+ // In dart2js the List from a different isolate would just be a regular
+ // JS Array so it can be treated as a JS Array.
+ || dartListTemplate()->HasInstance(object)) {
+ RefPtr<JsArray> jsArray = JsArray::create(object);
+ wrapper = JsArray::toDart(jsArray);
+ } else {
+ RefPtr<JsObject> jsObject = JsObject::create(object);
+ wrapper = JsObject::toDart(jsObject);
+ if (sometimesUseHtml) {
+ ret = invokeTopLevelJsInteropMethod(DartDOMData::current(), "_maybeWrap", 1, &wrapper);
+ }
}
- if (object->IsArray()) {
- RefPtr<JsArray> jsArray = JsArray::create(object.As<v8::Array>());
- return JsArray::toDart(jsArray);
- }
+ v8::Local<v8::Object> proxy;
- RefPtr<JsObject> jsObject = JsObject::create(object);
- return JsObject::toDart(jsObject);
+ // Prevent creation of cross frame dart:html objects for classes other than Window.
+ // Verify that the object is from the same context using the same check
+ // we used to use in V8Converter.
+ if (!object->CreationContext()->Global()->StrictEquals(DartUtilities::currentV8Context()->Global())) {
+ // Short circuit creating dart:html wrappers for cross frame objects
+ // other than window.
+ // TODO(jacobr): handle cross frame Window objects differently to more
+ // exactly match existing dart:html semantics.
+ if (!object->CreationContext()->Global()->StrictEquals(object)) {
+ Dart_SetField(wrapper, Dart_NewStringFromCString("_dartHtmlWrapper"), wrapper);
+ }
+ }
+ ASSERT(Dart_IsInstance(wrapper));
+ // Simulate the behavior of the Dart dev compiler where new List() is
+ // equivalent to a JavaScript array. We accomplish this by creating a
+ // JavaScript object that fakes that it is a JavaScript array but is
+ // actually backed by a Dart list. This is not a breaking change as
+ // existing Dart-JS interop passed arrays as opaque Dart handles.
+ // The jsify method can still be called if you wish to create a copy
+ // of a json like Dart data structure.
+ proxy = dartObjectTemplate()->InstanceTemplate()->NewInstance();
+ DartHandleProxy::writePointerToProxy(proxy, wrapper);
+ object->SetHiddenValue(existingDartWrapperKey, proxy);
+ return ret != 0 ? ret : wrapper;
}
-static void maybeCreateJsObjectImplClass(DartDOMData* domData)
+void JsInterop::buildInteropPatchFiles(DartDOMData* domData, Vector<InteropPatchFile>* patches, Dart_Handle& exception)
+{
+ // Build patch files implementing all external methods specified with new
+ // style JS interop and JsObjectImpl, JsFunctionImpl, and JsArrayImpl
+ // classes that implement all Dart types annoted with @Js.
+ // The sole purpose of these classes is to ensure that checked mode
+ // allows casting a JsObject to all types implemented by a JsObject.
+ Dart_Handle externals = invokeTopLevelJsInteropMethod(domData, "_generateInteropPatchFiles", 0, 0);
+ if (Dart_IsError(externals)) {
+ exception = externals;
+ return;
+ }
+ ASSERT(Dart_IsList(externals));
+ intptr_t externalsLength = 0;
+ Dart_ListLength(externals, &externalsLength);
+ ASSERT(externalsLength % 3 == 0);
+
+ for (intptr_t i = 0; i < externalsLength; i += 3) {
+ InteropPatchFile patch;
+
+ Dart_Handle libraryUri = Dart_ListGetAt(externals, i);
+ Dart_Handle patchFileUri = Dart_ListGetAt(externals, i + 1);
+ Dart_Handle source = Dart_ListGetAt(externals, i + 2);
+ ASSERT(Dart_IsString(libraryUri));
+ ASSERT(Dart_IsString(patchFileUri));
+ ASSERT(Dart_IsString(source));
+ patch.libraryUri = DartUtilities::toString(libraryUri);
+ patch.patchFileUri = DartUtilities::toString(patchFileUri);
+ patch.source = DartUtilities::toString(source);
+ patches->append(patch);
+ }
+}
+
+void JsInterop::initializeJsInterop(DartDOMData* domData, const Vector<InteropPatchFile>& patches, Dart_Handle& exception)
{
DartJsInteropData* interopData = domData->jsInteropData();
// Skip if the JSObjectImpl class has already been defined.
@@ -458,36 +578,54 @@
// all Dart types that have been passed to the dart:js registerJsInterfaces
// method. The sole purpose of these classes is to ensure that checked mode
// allows casting a JsObject to all types implemented by a JsObject.
- Dart_Handle source = invokeTopLevelJsInteropMethod(domData, "_generateJsObjectImplPart", 0, 0);
- ASSERT(Dart_IsString(source));
- Dart_Handle ret = Dart_LibraryLoadPatch(domData->jsLibrary(), Dart_NewStringFromCString("JsInteropImpl.dart"), source);
- ALLOW_UNUSED_LOCAL(ret);
- ASSERT(!Dart_IsError(ret));
+ Dart_Handle ret;
+ for (size_t i = 0; i < patches.size(); ++i) {
+ const InteropPatchFile& patch = patches[i];
+ Dart_Handle library = Dart_LookupLibrary(DartUtilities::safeStringToDartString(patch.libraryUri));
+ ASSERT(Dart_IsLibrary(library));
+ Dart_Handle patchFileUri = DartUtilities::safeStringToDartString(patch.patchFileUri);
+ Dart_Handle source = DartUtilities::safeStringToDartString(patch.source);
+ ret = Dart_LibraryLoadPatch(library, patchFileUri, source);
+ if (Dart_IsError(ret)) {
+ exception = ret;
+ return;
+ }
+ }
ret = Dart_FinalizeLoading(false);
- ASSERT(!Dart_IsError(ret));
+ if (Dart_IsError(ret)) {
+ exception = ret;
+ return;
+ }
interopData->setJsObjectImplDefined();
- // Start of polyfill work to make Dart List proxies behave like JavaScript
- // Arrays by monkey patching JavaScript Array and the List JavaScript
- // proxies as needed.
- v8::Context::Scope scope(DartUtilities::currentV8Context());
+ if (domData->isDOMEnabled()) {
+ // Start of polyfill work to make Dart List proxies behave like JavaScript
+ // Arrays by monkey patching JavaScript Array and the List JavaScript
+ // proxies as needed.
+ v8::Context::Scope scope(DartUtilities::currentV8Context());
- v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
+ v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
- v8::Local<v8::Function> dartArrayConstructor = dartListTemplate()->GetFunction();
+ v8::Local<v8::Function> dartArrayConstructor = dartListTemplate()->GetFunction();
- DartUtilities::currentV8Context()->Global()->Set(v8::String::NewFromUtf8(v8Isolate, "$DartList"),
- dartArrayConstructor);
- V8ScriptRunner::compileAndRunInternalScript(v8::String::NewFromUtf8(v8Isolate, dartArrayPolyfill), v8Isolate);
+ DartUtilities::currentV8Context()->Global()->Set(v8::String::NewFromUtf8(v8Isolate, "$DartList"),
+ dartArrayConstructor);
+ V8ScriptRunner::compileAndRunInternalScript(v8::String::NewFromUtf8(v8Isolate, dartArrayPolyfill), v8Isolate);
+
+ ret = Dart_Invoke(domData->jsLibrary(), Dart_NewStringFromCString("_registerAllJsInterfaces"), 0, 0);
+ if (Dart_IsError(ret)) {
+ exception = ret;
+ return;
+ }
+ }
}
Dart_Handle JsObject::toDart(PassRefPtr<JsObject> jsObject)
{
DartDOMData* domData = DartDOMData::current();
// We need to ensure JsObjectImpl exists before creating the wrapper.
- maybeCreateJsObjectImplClass(domData);
return DartDOMWrapper::createWrapper<JsObject>(domData, jsObject.get(), JsObject::dartClassId);
}
@@ -500,7 +638,6 @@
{
DartDOMData* domData = DartDOMData::current();
// We need to ensure JsObjectImpl exists before creating the wrapper.
- maybeCreateJsObjectImplClass(domData);
return DartDOMWrapper::createWrapper<JsFunction>(domData, jsFunction.get(), JsFunction::dartClassId);
}
@@ -520,22 +657,16 @@
{
DartDOMData* domData = DartDOMData::current();
// We need to ensure JsArrayImpl exists before creating the wrapper.
- maybeCreateJsObjectImplClass(domData);
return DartDOMWrapper::createWrapper<JsArray>(domData, jsArray.get(), JsArray::dartClassId);
}
-JsArray::JsArray(v8::Local<v8::Array> v8Handle) : JsObject(v8Handle) { }
+JsArray::JsArray(v8::Local<v8::Object> v8Handle) : JsObject(v8Handle) { }
-PassRefPtr<JsArray> JsArray::create(v8::Local<v8::Array> v8Handle)
+PassRefPtr<JsArray> JsArray::create(v8::Local<v8::Object> v8Handle)
{
return adoptRef(new JsArray(v8Handle));
}
-v8::Local<v8::Array> JsArray::localV8Array()
-{
- return localV8Object().As<v8::Array>();
-}
-
namespace JsInteropInternal {
typedef HashMap<Dart_Handle, v8::Handle<v8::Value> > DartHandleToV8Map;
@@ -605,7 +736,7 @@
// a JSObject. FIXME: evaluate if this is the right solution.
// Alternately, we could throw an exception.
if (ret->IsObject()) {
- scopes.setReturnValue(JsObject::toDart(ret.As<v8::Object>()));
+ scopes.setReturnValue(JsObject::toDart(ret.As<v8::Object>(), false));
} else {
// This will throw an exception in Dart checked mode.
scopes.setReturnValue(ret);
@@ -872,7 +1003,7 @@
static void newJsArrayCallback(Dart_NativeArguments args)
{
JsInteropScopes scopes(args);
- scopes.setReturnValue(JsObject::toDart(v8::Array::New(v8::Isolate::GetCurrent())));
+ scopes.setReturnValue(JsObject::toDart(v8::Array::New(v8::Isolate::GetCurrent()), false));
return;
}
@@ -916,10 +1047,10 @@
{
JsInteropScopes scopes(args);
JsArray* receiver = DartDOMWrapper::receiver<JsArray>(args);
- uint32_t length = receiver->localV8Array()->Length();
+ v8::Local<v8::Value> length = receiver->localV8Object()->Get(v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), "length"));
if (scopes.handleJsException(&exception))
goto fail;
- scopes.setReturnValueInteger(length);
+ scopes.setReturnValue(length);
return;
}
@@ -945,7 +1076,7 @@
ASSERT(ret->IsObject());
if (scopes.handleJsException(&exception))
goto fail;
- scopes.setReturnValue(JsObject::toDart(ret.As<v8::Object>()));
+ scopes.setReturnValue(JsObject::toDart(ret.As<v8::Object>(), false));
return;
}
@@ -973,18 +1104,9 @@
// Use the global v8 object if no Dart thisArg was passed in.
thisArg = DartUtilities::currentV8Context()->Global();
} else {
- Dart_Handle jso = Dart_GetField(thisArgDart, Dart_NewStringFromCString("blink_jsObject"));
- if (!Dart_IsError(jso) && DartDOMWrapper::subtypeOf(jso, JsObject::dartClassId)) {
- // Use the blink JS Interop object.
- JsObject* object = DartDOMWrapper::unwrapDartWrapper<JsObject>(domData, jso, exception);
- if (exception)
- thisArg = v8::Local<v8::Value>();
- thisArg = object->localV8Object();
- } else {
- thisArg = JsInterop::fromDart(domData, thisArgDart, exception);
- if (exception)
- goto fail;
- }
+ thisArg = JsInterop::fromDart(domData, thisArgDart, exception);
+ if (exception)
+ goto fail;
if (!thisArg->IsObject()) {
exception = Dart_NewStringFromCString("thisArg is not an object");
goto fail;
@@ -1082,13 +1204,12 @@
{
v8::Local<v8::Context> v8Context = DartUtilities::currentV8Context();
v8::Context::Scope scope(v8Context);
- Dart_SetReturnValue(args, JsObject::toDart(v8Context->Global()));
+ Dart_SetReturnValue(args, JsObject::toDart(v8Context->Global(), false));
}
static void finalizeJsInterfacesCallback(Dart_NativeArguments args)
{
- DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateData(args));
- maybeCreateJsObjectImplClass(domData);
+ // Obsolete.
}
static void interfacesFinalizedCallback(Dart_NativeArguments args)
@@ -1197,7 +1318,7 @@
// a JSObject. FIXME: evaluate if this is the right solution.
// Alternately, we could throw an exception.
if (ret->IsObject()) {
- scopes.setReturnValue(JsObject::toDart(ret.As<v8::Object>()));
+ scopes.setReturnValue(JsObject::toDart(ret.As<v8::Object>(), false));
} else {
// This will throw an exception in Dart checked mode.
scopes.setReturnValue(ret);
@@ -1233,6 +1354,31 @@
ASSERT_NOT_REACHED();
}
+
+static void withThisCallbackNoWrap(Dart_NativeArguments args)
+{
+ Dart_Handle exception = 0;
+ {
+ JsInteropScopes scopes(args);
+ Dart_Handle function = Dart_GetNativeArgument(args, 0);
+ DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateData(args));
+ ASSERT(DartUtilities::isFunction(domData, function));
+
+ v8::Local<v8::Object> proxy = dartFunctionTemplateNoWrap()->InstanceTemplate()->NewInstance();
+ DartHandleProxy::writePointerToProxy(proxy, function);
+
+ v8::Local<v8::Function> ret = v8::Local<v8::Function>::Cast(domData->jsInteropData()->captureThisFunction()->Call(proxy, 0, 0));
+
+ if (scopes.handleJsException(&exception))
+ goto fail;
+ scopes.setReturnValue(ret);
+ return;
+ }
+fail:
+ Dart_ThrowException(exception);
+ ASSERT_NOT_REACHED();
+}
+
}
static DartNativeEntry nativeEntries[] = {
@@ -1242,6 +1388,7 @@
{ JsInteropInternal::interfacesFinalizedCallback, 0, "Js_interfacesFinalized_Callback" },
{ JsInteropInternal::jsifyCallback, 1, "JsObject_jsify" },
{ JsInteropInternal::withThisCallback, 1, "JsFunction_withThis" },
+ { JsInteropInternal::withThisCallbackNoWrap, 1, "JsFunction_withThisNoWrap" },
{ JsInterop::jsInteropGetterCallback, 2, "JsObject_[]" },
{ JsInteropInternal::setterCallback, 3, "JsObject_[]=" },
{ JsInteropInternal::hashCodeCallback, 1, "JsObject_hashCode" },
@@ -1424,7 +1571,7 @@
if (info.Length() == 0) {
e = Dart_Null();
} else {
- e = JsInterop::toDart(info[0]);
+ e = JsInterop::toDart(info[0], false);
}
Dart_Handle args[2] = { handle, e };
Dart_Handle ret = Dart_Invoke(domData->jsLibrary(), Dart_NewStringFromCString(methodName), 2, args);
@@ -1442,7 +1589,7 @@
int length = info.Length();
Dart_Handle argsList = Dart_NewList(length);
for (int i = 0; i < length; ++i) {
- Dart_ListSetAt(argsList, i, JsInterop::toDart(info[i]));
+ Dart_ListSetAt(argsList, i, JsInterop::toDart(info[i], false));
}
// Note: this is also just info.Holder().
Dart_Handle args[2] = { handle, argsList };
@@ -1485,7 +1632,7 @@
DartScopes scopes(info.Holder());
Dart_Handle handle = scopes.handle;
DartDOMData* domData = DartDOMData::current();
- Dart_Handle args[2] = { handle, JsInterop::toDart(value) };
+ Dart_Handle args[2] = { handle, JsInterop::toDart(value, true) };
Dart_Handle ret = Dart_Invoke(domData->jsLibrary(), Dart_NewStringFromCString("_setListLength"), 2, args);
setJsReturnValue(domData, info, ret);
}
@@ -1618,6 +1765,36 @@
return proxyTemplateLocal;
}
+void dartObjectToStringCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ if (handleNonDartProxyThis(info, "toString")) {
+ return;
+ }
+ DartScopes scopes(info.Holder());
+ DartDOMData* domData = DartDOMData::current();
+ Dart_Handle handle = scopes.handle;
+ setJsReturnValue(domData, info, Dart_ToString(handle));
+}
+
+static v8::Local<v8::FunctionTemplate> dartObjectTemplate()
+{
+ DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, proxyTemplate, ());
+ v8::Local<v8::FunctionTemplate> proxyTemplateLocal;
+ v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
+ if (proxyTemplate.IsEmpty()) {
+ proxyTemplate.Reset(v8Isolate, v8::FunctionTemplate::New(v8Isolate));
+ proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, proxyTemplate);
+ v8::Local<v8::ObjectTemplate> protoTemplate = proxyTemplateLocal->PrototypeTemplate();
+ protoTemplate->Set(v8::String::NewFromUtf8(v8Isolate, "toString"), v8::FunctionTemplate::New(v8Isolate, dartObjectToStringCallback));
+
+ proxyTemplateLocal->SetClassName(v8::String::NewFromUtf8(v8Isolate, "DartObject"));
+ setupInstanceTemplate(proxyTemplateLocal);
+ } else {
+ proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, proxyTemplate);
+ }
+ return proxyTemplateLocal;
+}
+
void JsInterop::jsInteropGetterCallback(Dart_NativeArguments args)
{
JsInteropInternal::getterCallback(args);
diff --git a/Source/bindings/core/dart/DartJsInterop.h b/Source/bindings/core/dart/DartJsInterop.h
index 5c01692..cdabd16 100644
--- a/Source/bindings/core/dart/DartJsInterop.h
+++ b/Source/bindings/core/dart/DartJsInterop.h
@@ -33,6 +33,7 @@
#include "bindings/core/dart/DartDOMData.h"
#include "wtf/RefCounted.h"
+#include "wtf/Vector.h"
#include <dart_api.h>
#include <dart_mirrors_api.h>
@@ -45,13 +46,19 @@
class Element;
+struct InteropPatchFile {
+ String libraryUri;
+ String patchFileUri;
+ String source;
+};
+
class JsInterop {
public:
static Dart_NativeFunction resolver(Dart_Handle nameHandle, int argumentCount, bool* autoSetupScope);
static const uint8_t* symbolizer(Dart_NativeFunction);
static v8::Local<v8::Value> fromDart(DartDOMData*, Dart_Handle, Dart_Handle& exception);
- static Dart_Handle toDart(v8::Local<v8::Value>);
+ static Dart_Handle toDart(v8::Local<v8::Value>, bool sometimesUseHtml);
// Return a Blink Element instance (convert to a V8Object which is really a
// Javascript object) as a Dart JsObject that points to the Javascript object.
@@ -62,6 +69,9 @@
static void jsInteropContextCallback(Dart_NativeArguments args);
static void jsInteropGetterCallback(Dart_NativeArguments args);
static void jsInteropCallMethodCallback(Dart_NativeArguments args);
+
+ static void buildInteropPatchFiles(DartDOMData*, Vector<InteropPatchFile>* patches, Dart_Handle& exception);
+ static void initializeJsInterop(DartDOMData*, const Vector<InteropPatchFile>& patches, Dart_Handle& exception);
};
class JsObject : public RefCounted<JsObject> {
@@ -69,7 +79,7 @@
private:
JsObject(v8::Local<v8::Object> v8Handle);
public:
- static Dart_Handle toDart(v8::Local<v8::Object>);
+ static Dart_Handle toDart(v8::Local<v8::Object>, bool sometimesUseHtml);
static Dart_Handle toDart(PassRefPtr<JsObject>);
~JsObject();
@@ -115,14 +125,12 @@
class JsArray : public JsObject {
WTF_MAKE_NONCOPYABLE(JsArray);
private:
- JsArray(v8::Local<v8::Array> v8Handle);
+ JsArray(v8::Local<v8::Object> v8Handle);
public:
static Dart_Handle toDart(PassRefPtr<JsArray> jsObject);
- static PassRefPtr<JsArray> create(v8::Local<v8::Array> v8Handle);
-
- v8::Local<v8::Array> localV8Array();
+ static PassRefPtr<JsArray> create(v8::Local<v8::Object> v8Handle);
static const int dartClassId;
static const bool isNode = false;
diff --git a/Source/bindings/core/dart/DartJsInteropData.cpp b/Source/bindings/core/dart/DartJsInteropData.cpp
index ddad845..00776e6 100644
--- a/Source/bindings/core/dart/DartJsInteropData.cpp
+++ b/Source/bindings/core/dart/DartJsInteropData.cpp
@@ -30,7 +30,9 @@
#include "config.h"
#include "bindings/core/dart/DartJsInteropData.h"
+#include "bindings/core/dart/V8Converter.h"
+#include <dart_api.h>
#include <string.h>
namespace blink {
@@ -73,4 +75,13 @@
return cacheFunction(&m_instanceofFunction, "(function (type) { return this instanceof type; })");
}
+v8::Local<v8::String> DartJsInteropData::existingDartWrapperHiddenField(v8::Isolate* v8Isolate) {
+ if (m_existingDartWrapperHiddenField.IsEmpty()) {
+ // We are abusing Dart_DebugName() as it is supposed to give a unique
+ // per isolate name.
+ m_existingDartWrapperHiddenField.Reset(v8Isolate, v8::String::Concat(v8::String::NewFromUtf8(v8Isolate, "$existing_dart_wrapper_"), V8Converter::stringToV8(Dart_DebugName())));
+ }
+ return v8::Local<v8::String>::New(v8Isolate, m_existingDartWrapperHiddenField);
+}
+
}
diff --git a/Source/bindings/core/dart/DartJsInteropData.h b/Source/bindings/core/dart/DartJsInteropData.h
index 9eb72ba..8a493f6 100644
--- a/Source/bindings/core/dart/DartJsInteropData.h
+++ b/Source/bindings/core/dart/DartJsInteropData.h
@@ -44,6 +44,7 @@
v8::Local<v8::Function> captureThisFunction();
v8::Local<v8::Function> wrapDartFunction();
v8::Local<v8::Function> instanceofFunction();
+ v8::Local<v8::String> existingDartWrapperHiddenField(v8::Isolate*);
bool jsObjectImplDefined() { return m_jsObjectImplDefined; }
void setJsObjectImplDefined() { m_jsObjectImplDefined = true; }
@@ -55,6 +56,8 @@
v8::Persistent<v8::Function> m_wrapDartFunction;
v8::Persistent<v8::Function> m_instanceofFunction;
+ v8::Persistent<v8::String> m_existingDartWrapperHiddenField;
+
bool m_jsObjectImplDefined;
// FIXME: add maps of Dart to V8 and V8 to Dart objects.
diff --git a/Source/bindings/core/dart/DartNativeUtilities.cpp b/Source/bindings/core/dart/DartNativeUtilities.cpp
index f26c4d2..d09b710 100644
--- a/Source/bindings/core/dart/DartNativeUtilities.cpp
+++ b/Source/bindings/core/dart/DartNativeUtilities.cpp
@@ -133,37 +133,37 @@
// element just created and call the custom Dart class created constructor.
void customConstructorCreate(Dart_NativeArguments args)
{
- Dart_Handle exception = 0;
- {
- DartDOMData* domData = DartDOMData::current();
+ Dart_Handle dartElementType = Dart_GetNativeArgument(args, 0);
+ ASSERT(Dart_IsType(dartElementType));
- Dart_Handle dartElementType = Dart_GetNativeArgument(args, 0);
- ASSERT(Dart_IsType(dartElementType));
+ Dart_Handle blinkJsObject = Dart_GetNativeArgument(args, 1);
- Dart_Handle blinkJsObject = Dart_GetNativeArgument(args, 1);
+ Dart_Handle newObject = Dart_Allocate(dartElementType);
+ ASSERT(!Dart_IsError(newObject));
- Dart_Handle newObject = Dart_Allocate(dartElementType);
- ASSERT(!Dart_IsError(newObject));
-
- Dart_Handle jsObject = Dart_SetField(newObject, Dart_NewStringFromCString("blink_jsObject"), blinkJsObject);
- if (Dart_IsError(jsObject)) {
- DartUtilities::reportProblem(domData->scriptExecutionContext(), jsObject);
- goto fail;
- }
-
- newObject = Dart_InvokeConstructor(newObject, Dart_NewStringFromCString("created"), 0, 0);
- if (Dart_IsError(newObject)) {
- DartUtilities::reportProblem(domData->scriptExecutionContext(), newObject);
- goto fail;
- }
-
- Dart_SetReturnValue(args, newObject);
+ Dart_Handle jsObject = Dart_SetField(newObject, Dart_NewStringFromCString("blink_jsObject"), blinkJsObject);
+ if (Dart_IsError(jsObject)) {
+ Dart_PropagateError(jsObject);
return;
}
-fail:
- Dart_ThrowException(exception);
- ASSERT_NOT_REACHED();
+ // Setup the DartHtmlWrapper that we're allocating.
+ DartDOMData* domData = DartDOMData::current();
+ Dart_Handle htmlWrapperArgs[2] = { blinkJsObject, newObject };
+ Dart_Handle ret = Dart_Invoke(domData->jsLibrary(), Dart_NewStringFromCString("setDartHtmlWrapperFor"), 2, htmlWrapperArgs);
+ if (Dart_IsError(ret)) {
+ Dart_PropagateError(ret);
+ return;
+ }
+
+ newObject = Dart_InvokeConstructor(newObject, Dart_NewStringFromCString("created"), 0, 0);
+ if (Dart_IsError(newObject)) {
+ Dart_PropagateError(newObject);
+ return;
+ }
+
+ Dart_SetReturnValue(args, newObject);
+ return;
}
void initializeCustomElement(Dart_NativeArguments args)
diff --git a/Source/bindings/core/dart/DartScriptDebugServer.cpp b/Source/bindings/core/dart/DartScriptDebugServer.cpp
index 47f4d27..a0d168b 100644
--- a/Source/bindings/core/dart/DartScriptDebugServer.cpp
+++ b/Source/bindings/core/dart/DartScriptDebugServer.cpp
@@ -208,6 +208,10 @@
DartIsolateScope scope(isolate);
DartApiScope apiScope;
Dart_Handle exception = 0;
+ if (!DartDOMData::current()->hasApplicationLoader()) {
+ // TODO(jacobr): why are we still hitting this case?
+ break;
+ }
if (!DartDOMData::current()->applicationLoader()->running()) {
// Skip until the loader is actually running. We'll set the breakpoint at that point.
break;
@@ -314,11 +318,15 @@
break;
}
}
- Dart_Handle exception = 0;
- lastLineNumber = DartUtilities::toInteger(Dart_ListGetAt(info, lastLineStart + 1), exception);
- ASSERT(!exception);
- lastColumnNumber = DartUtilities::toInteger(Dart_ListGetAt(info, infoLength - 1), exception);
- ASSERT(!exception);
+ // we shouldn't crash even if a script has zero valid Dart tokens.
+ // TODO(jacobr): I don't know why this occurs.
+ if (lastLineStart + 1 < infoLength && infoLength > 0) {
+ Dart_Handle exception = 0;
+ lastLineNumber = DartUtilities::toInteger(Dart_ListGetAt(info, lastLineStart + 1), exception);
+ ASSERT(!exception);
+ lastColumnNumber = DartUtilities::toInteger(Dart_ListGetAt(info, infoLength - 1), exception);
+ ASSERT(!exception);
+ }
script.startLine = 0;
script.startColumn = 0;
@@ -605,10 +613,14 @@
void DartScriptDebugServer::registerIsolate(Dart_Isolate isolate, Page* page)
{
- threadSafeIsolateTracker().add(isolate);
-
DartIsolateScope scope(isolate);
DartApiScope apiScope;
+ // Check whether this is an isolate we really want to debug.
+ if (DartDOMData::current() == NULL || !DartDOMData::current()->hasApplicationLoader()) {
+ return;
+ }
+
+ threadSafeIsolateTracker().add(isolate);
DartPageDebug* pageDebug = lookupPageDebug(page);
pageDebug->registerIsolate(isolate);
diff --git a/Source/bindings/core/dart/DartService.cpp b/Source/bindings/core/dart/DartService.cpp
index f95bb09..b18ccbc 100644
--- a/Source/bindings/core/dart/DartService.cpp
+++ b/Source/bindings/core/dart/DartService.cpp
@@ -35,4 +35,11 @@
return dart::bin::VmServiceServer::GetServerPort();
}
+
+void DartService::DecompressAssets(const uint8_t* input, unsigned inputLen, uint8_t** output, unsigned* outputLength)
+{
+ dart::bin::VmServiceServer::DecompressAssets(input, inputLen, output, outputLength);
+}
+
+
}
diff --git a/Source/bindings/core/dart/DartService.h b/Source/bindings/core/dart/DartService.h
index 71d1571..884518c 100644
--- a/Source/bindings/core/dart/DartService.h
+++ b/Source/bindings/core/dart/DartService.h
@@ -15,6 +15,7 @@
static Dart_Isolate CreateIsolate();
static const char* GetServerIP();
static intptr_t GetServerPort();
+ static void DecompressAssets(const uint8_t* input, unsigned inputLen, uint8_t** output, unsigned* outputLength);
};
}
diff --git a/Source/bindings/core/dart/DartUtilities.cpp b/Source/bindings/core/dart/DartUtilities.cpp
index 3c9d86e..2e091a1 100644
--- a/Source/bindings/core/dart/DartUtilities.cpp
+++ b/Source/bindings/core/dart/DartUtilities.cpp
@@ -36,6 +36,7 @@
#include "bindings/core/dart/DartController.h"
#include "bindings/core/dart/DartDOMData.h"
+#include "bindings/core/dart/DartJsInterop.h"
#include "bindings/core/dart/DartScriptDebugServer.h"
#include "bindings/core/dart/DartScriptState.h"
#include "bindings/core/dart/V8Converter.h"
@@ -43,6 +44,7 @@
#include "bindings/core/v8/ScriptController.h"
#include "bindings/core/v8/SerializedScriptValueFactory.h"
#include "bindings/core/v8/V8Binding.h"
+#include "bindings/core/v8/V8Node.h"
#include "bindings/core/v8/V8PerIsolateData.h"
#include "core/dom/DOMArrayBuffer.h"
#include "core/dom/DOMDataView.h"
@@ -565,12 +567,26 @@
bool DartUtilities::isNode(Dart_Handle handle)
{
Dart_Handle dartType = DartUtilities::getDartHtmlType("Node");
- return objectIsType(handle, dartType);
+ if (!objectIsType(handle, dartType)) {
+ return false;
+ }
+ // Some dart:html Node instances may not really be Node objects.
+ Dart_Handle exception = 0;
+ v8::Handle<v8::Value> v8Node = JsInterop::fromDart(DartDOMData::current(), handle, exception);
+ if (exception) {
+ return false;
+ }
+ return V8Node::hasInstance(v8Node, v8::Isolate::GetCurrent());
}
-Node* DartUtilities::dartNodeToNativeNode(void* value)
+Node* DartUtilities::dartNodeToNativeNode(Dart_Handle handle)
{
- return static_cast<Node*>(value);
+ Dart_Handle exception = 0;
+ v8::Handle<v8::Value> v8Node = JsInterop::fromDart(DartDOMData::current(), handle, exception);
+ ASSERT(!exception);
+ ASSERT(V8Node::hasInstance(v8Node, v8::Isolate::GetCurrent()));
+ Node* node = V8Node::toImpl(v8Node.As<v8::Object>());
+ return node;
}
bool DartUtilities::isMessagePort(Dart_Handle handle)
diff --git a/Source/bindings/core/dart/DartUtilities.h b/Source/bindings/core/dart/DartUtilities.h
index 66f6171..7e90cbb 100644
--- a/Source/bindings/core/dart/DartUtilities.h
+++ b/Source/bindings/core/dart/DartUtilities.h
@@ -796,7 +796,7 @@
static Dart_Handle getDartHtmlType(const char* typeName);
static bool isNode(Dart_Handle);
- static Node* dartNodeToNativeNode(void*);
+ static Node* dartNodeToNativeNode(Dart_Handle);
static bool isMessagePort(Dart_Handle);
static MessagePort* dartMessagePortToNativeMessagePort(void*);
diff --git a/Source/bindings/core/dart/V8Converter.cpp b/Source/bindings/core/dart/V8Converter.cpp
index 31d0874..2200818 100644
--- a/Source/bindings/core/dart/V8Converter.cpp
+++ b/Source/bindings/core/dart/V8Converter.cpp
@@ -142,7 +142,7 @@
return arrayBufferToV8(data, exception);
}
if (Dart_IsTypedData(value))
- return arrayBufferToV8(value, exception);
+ return arrayBufferViewToV8(value, exception);
// TODO(terry): Using JS Interop only arrays are converted.
/*
if (DartDOMWrapper::subtypeOf(value, DartBlob::dartClassId))
diff --git a/Tools/Scripts/webkitpy/layout_tests/controllers/single_test_runner.py b/Tools/Scripts/webkitpy/layout_tests/controllers/single_test_runner.py
index ca1ca97..196ce56 100644
--- a/Tools/Scripts/webkitpy/layout_tests/controllers/single_test_runner.py
+++ b/Tools/Scripts/webkitpy/layout_tests/controllers/single_test_runner.py
@@ -325,6 +325,10 @@
_observatory_cleaner = re.compile(r"^Observatory.*\n", re.MULTILINE)
_console_observatory_cleaner = re.compile(r"^CONSOLE INFO: Observatory.*\n", re.MULTILINE)
+ _line_number_cleaner = re.compile(r"\(dart:(\w+):\d+\)", re.MULTILINE)
+
+ def _line_number_substitution(self, match):
+ return "(dart:" + match.group(1) + ":xxxx)"
def _get_normalized_output_text(self, output):
"""Returns the normalized text output, i.e. the output in which
@@ -336,6 +340,7 @@
normalized_lines = output.replace("\r\r\n", "\r\n").replace("\r\n", "\n")
normalized_lines = re.sub(self._observatory_cleaner, r"", normalized_lines)
normalized_lines = re.sub(self._console_observatory_cleaner, r"", normalized_lines)
+ normalized_lines = re.sub(self._line_number_cleaner, self._line_number_substitution, normalized_lines)
return normalized_lines
# FIXME: This function also creates the image diff. Maybe that work should