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