| Index: Source/bindings/core/dart/DartApplicationLoader.cpp
|
| diff --git a/Source/bindings/core/dart/DartApplicationLoader.cpp b/Source/bindings/core/dart/DartApplicationLoader.cpp
|
| index cd186bb03a927ab051203e4db5ee334a1e35d963..7f7d3ad5608b16095b3e7765df991fe3555b1f21 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 @@ DartApplicationLoader::DartApplicationLoader(
|
| , 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 @@ void DartApplicationLoader::processRequests(Dart_Isolate isolate, const ScriptSo
|
|
|
| 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 @@ void DartApplicationLoader::load(PassRefPtr<DartErrorEventDispatcher> errorEvent
|
| 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 @@ void DartApplicationLoader::loadScriptFromSnapshot(const String& url, const uint
|
| 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;
|
| - }
|
| + Timeline timeline(m_originDocument->frame(), String("callEntryPoint@") + m_scriptUrlString);
|
| +
|
| + if (m_domEnabled) {
|
| + 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.
|
| +
|
| + // 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();
|
|
|
| - Vector<uint8_t>* snapshot = DartDOMData::current()->applicationSnapshot();
|
| - ASSERT(snapshot->isEmpty());
|
| - snapshot->append(buffer, size);
|
| + 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);
|
|
|
| - // Write the snapshot.
|
| - scriptResource->cacheHandler()->setCachedMetadata(dartTypeID, reinterpret_cast<const char*>(buffer), size);
|
| + Dart_EnterIsolate(applicationIsolate);
|
| }
|
| - }
|
|
|
| - m_state = Running;
|
| + {
|
| + Dart_Handle mainLibrary = topLevelLibrary();
|
|
|
| - if (m_domEnabled) {
|
| - DartScriptDebugServer::shared().isolateLoaded();
|
| - }
|
| + // 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());
|
|
|
| - if (m_domEnabled) {
|
| - V8Scope v8scope(DartDOMData::current());
|
| - Dart_Handle mainLibrary = topLevelLibrary();
|
| + DartDOMData* domData = DartDOMData::current();
|
| + DartApiScope apiScope;
|
| + V8Scope v8scope(domData);
|
|
|
| - logObservatoryInformation();
|
| + Dart_Handle exception = 0;
|
| + if (patches.size() > 0) {
|
| + JsInterop::initializeJsInterop(domData, patches, exception);
|
| + }
|
| + if (exception) {
|
| + DartUtilities::reportProblem(m_originDocument, exception, m_scriptUrlString);
|
| + }
|
|
|
| - // 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());
|
| + m_state = Running;
|
|
|
| - Dart_Handle result = Dart_FinalizeLoading(false);
|
| - if (Dart_IsError(result)) {
|
| - DartUtilities::reportProblem(m_originDocument, result, m_scriptUrlString);
|
| - }
|
| + 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);
|
| + // 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 @@ void DartApplicationLoader::process(const String& url, const String& source, int
|
| 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);
|
|
|