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