From 0df0c89ae62d95d5d979c2fa57ee0e264da1aaa4 Mon Sep 17 00:00:00 2001 From: "sigurdm@google.com" Date: Wed, 7 Jan 2015 14:05:51 +0000 Subject: [PATCH] Fix deferred loading with multiple apps on same page. Even though two apps don't have to load a file twice, they still both have to initialize it. Still missing this support for the new emitter. BUG= R=floitsch@google.com Review URL: https://codereview.chromium.org//837903002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@42660 260f80e4-7a28-3924-810f-c04153c831b5 --- .../js_emitter/new_emitter/model_emitter.dart | 1 + .../src/js_emitter/old_emitter/emitter.dart | 44 ++++++++++++------- .../_internal/compiler/js_lib/js_helper.dart | 8 +++- .../js_lib/shared/embedded_names.dart | 2 + tests/html/deferred_multi_app.dart | 28 ++++++++++++ tests/html/deferred_multi_app_htmltest.html | 23 ++++++++++ tests/html/deferred_multi_app_lib.dart | 11 +++++ tests/html/html.status | 3 ++ 8 files changed, 102 insertions(+), 18 deletions(-) create mode 100644 tests/html/deferred_multi_app.dart create mode 100644 tests/html/deferred_multi_app_htmltest.html create mode 100644 tests/html/deferred_multi_app_lib.dart diff --git a/pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart index e5ede42529c..668a0e3d53c 100644 --- a/pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart +++ b/pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart @@ -15,6 +15,7 @@ import 'package:_internal/compiler/js_lib/shared/embedded_names.dart' show DEFERRED_LIBRARY_URIS, DEFERRED_LIBRARY_HASHES, INITIALIZE_LOADED_HUNK, + IS_HUNK_INITIALIZED, IS_HUNK_LOADED; import '../js_emitter.dart' show NativeGenerator; diff --git a/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart index a69fc80565b..f250926fe68 100644 --- a/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart +++ b/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart @@ -161,6 +161,7 @@ class OldEmitter implements Emitter { String get lazyInitializerName => '${namer.isolateName}.${lazyInitializerProperty}'; String get initName => 'init'; + String get makeConstListProperty => namer.getMappedInstanceName('makeConstantList'); @@ -1831,23 +1832,34 @@ function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) { /// Emits support-code for deferred loading into [buffer]. void emitDeferredBoilerPlate(CodeBuffer buffer, Map deferredLoadHashes) { - // Function for checking if a hunk is loaded given its hash. - buffer.write(jsAst.prettyPrint( - js('# = function(hunkHash) {' - ' return !!$deferredInitializers[hunkHash];' - '}', generateEmbeddedGlobalAccess(embeddedNames.IS_HUNK_LOADED)), + jsAst.Statement functions = js.statement(''' + { + // Function for checking if a hunk is loaded given its hash. + #isHunkLoaded = function(hunkHash) { + return !!$deferredInitializers[hunkHash]; + }; + #deferredInitialized = new Object(null); + // Function for checking if a hunk is initialized given its hash. + #isHunkInitialized = function(hunkHash) { + return #deferredInitialized[hunkHash]; + }; + // Function for initializing a loaded hunk, given its hash. + #initializeLoadedHunk = function(hunkHash) { + $deferredInitializers[hunkHash]( + $globalsHolder, ${namer.currentIsolate}); + #deferredInitialized[hunkHash] = true; + }; + } + ''', {"isHunkLoaded": generateEmbeddedGlobalAccess( + embeddedNames.IS_HUNK_LOADED), + "isHunkInitialized": generateEmbeddedGlobalAccess( + embeddedNames.IS_HUNK_INITIALIZED), + "initializeLoadedHunk": generateEmbeddedGlobalAccess( + embeddedNames.INITIALIZE_LOADED_HUNK), + "deferredInitialized": generateEmbeddedGlobalAccess( + embeddedNames.DEFERRED_INITIALIZED)}); + buffer.write(jsAst.prettyPrint(functions, compiler, monitor: compiler.dumpInfoTask)); - buffer.write('$N'); - // Function for initializing a loaded hunk, given its hash. - buffer.write(jsAst.prettyPrint( - js('# = function(hunkHash) {' - ' $deferredInitializers[hunkHash](' - '$globalsHolder, ${namer.currentIsolate})' - '}', - generateEmbeddedGlobalAccess( - embeddedNames.INITIALIZE_LOADED_HUNK)), - compiler, monitor: compiler.dumpInfoTask)); - buffer.write('$N'); // Write a javascript mapping from Deferred import load ids (derrived // from the import prefix.) to a list of lists of uris of hunks to load, // and a corresponding mapping to a list of hashes used by diff --git a/sdk/lib/_internal/compiler/js_lib/js_helper.dart b/sdk/lib/_internal/compiler/js_lib/js_helper.dart index d2f38367b38..63a13931be7 100644 --- a/sdk/lib/_internal/compiler/js_lib/js_helper.dart +++ b/sdk/lib/_internal/compiler/js_lib/js_helper.dart @@ -15,6 +15,7 @@ import 'dart:_js_embedded_names' show DEFERRED_LIBRARY_HASHES, INITIALIZE_LOADED_HUNK, IS_HUNK_LOADED, + IS_HUNK_INITIALIZED, NATIVE_SUPERCLASS_TAG_NAME; import 'dart:collection'; @@ -3313,15 +3314,18 @@ Future loadDeferredLibrary(String loadId) { // The indices into `uris` and `hashes` that we want to load. List indices = new List.generate(uris.length, (i) => i); var isHunkLoaded = JS_EMBEDDED_GLOBAL('', IS_HUNK_LOADED); + var isHunkInitialized = JS_EMBEDDED_GLOBAL('', IS_HUNK_INITIALIZED); // Filter away indices for hunks that have already been loaded. List indicesToLoad = indices .where((int i) => !JS('bool','#(#)', isHunkLoaded, hashes[i])) .toList(); - // Load the needed hunks. + List indicesToInitialize = indices + .where((int i) => !JS('bool','#(#)', isHunkInitialized, hashes[i])) + .toList(); // Load the needed hunks. return Future.wait(indicesToLoad .map((int i) => _loadHunk(uris[i]))).then((_) { // Now all hunks have been loaded, we run the needed initializers. - for (int i in indicesToLoad) { + for (int i in indicesToInitialize) { var initializer = JS_EMBEDDED_GLOBAL('', INITIALIZE_LOADED_HUNK); JS('void', '#(#)', initializer, hashes[i]); } diff --git a/sdk/lib/_internal/compiler/js_lib/shared/embedded_names.dart b/sdk/lib/_internal/compiler/js_lib/shared/embedded_names.dart index 344cd7d24ee..14bfd8c50da 100644 --- a/sdk/lib/_internal/compiler/js_lib/shared/embedded_names.dart +++ b/sdk/lib/_internal/compiler/js_lib/shared/embedded_names.dart @@ -32,6 +32,8 @@ const DEFERRED_LIBRARY_URIS = 'deferredLibraryUris'; const DEFERRED_LIBRARY_HASHES = 'deferredLibraryHashes'; const INITIALIZE_LOADED_HUNK = 'initializeLoadedHunk'; const IS_HUNK_LOADED = 'isHunkLoaded'; +const IS_HUNK_INITIALIZED = 'isHunkInitialized'; +const DEFERRED_INITIALIZED = 'deferredInitialized'; const CLASS_ID_EXTRACTOR = 'classIdExtractor'; const CLASS_FIELDS_EXTRACTOR = 'classFieldsExtractor'; const INSTANCE_FROM_CLASS_ID = "instanceFromClassId"; diff --git a/tests/html/deferred_multi_app.dart b/tests/html/deferred_multi_app.dart new file mode 100644 index 00000000000..a029142edab --- /dev/null +++ b/tests/html/deferred_multi_app.dart @@ -0,0 +1,28 @@ +// 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. + +import "deferred_multi_app_lib.dart" deferred as lib; +import "dart:async"; +import "dart:html"; +import "package:expect/expect.dart"; + +main() { + Element state = querySelector("#state"); + if (state.text == "1") { + lib.loadLibrary().then((_) { + var a = lib.one(); + Expect.equals("one", a); + window.postMessage(a, '*'); + }); + state.text = "2"; + } else { + new Timer(new Duration(milliseconds: 100), () { + lib.loadLibrary().then((_) { + var a = lib.two(); + Expect.equals("two", a); + window.postMessage(a, '*'); + }); + }); + } +} \ No newline at end of file diff --git a/tests/html/deferred_multi_app_htmltest.html b/tests/html/deferred_multi_app_htmltest.html new file mode 100644 index 00000000000..f5db7854603 --- /dev/null +++ b/tests/html/deferred_multi_app_htmltest.html @@ -0,0 +1,23 @@ + + + +
1
+ + + + + diff --git a/tests/html/deferred_multi_app_lib.dart b/tests/html/deferred_multi_app_lib.dart new file mode 100644 index 00000000000..6ec352d4a43 --- /dev/null +++ b/tests/html/deferred_multi_app_lib.dart @@ -0,0 +1,11 @@ +// 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. + +one() { + return "one"; +} + +two() { + return "two"; +} \ No newline at end of file diff --git a/tests/html/html.status b/tests/html/html.status index 785c5de52af..39703eb334c 100644 --- a/tests/html/html.status +++ b/tests/html/html.status @@ -105,6 +105,9 @@ xhr_test: Pass, Fail # Issue 11884 [$runtime == drt || $runtime == dartium || $runtime == chrome || $runtime == chromeOnAndroid || $runtime == ContentShellOnAndroid ] webgl_1_test: Pass, Fail # Issue 8219 +[ ($compiler == none || $compiler == dart2dart) ] +deferred_multi_app_htmltest: Fail # Issue 16603 + [ $compiler == none && ($runtime == drt || $runtime == dartium) && $system == windows] websql_test: Skip # Issue 4941: stderr contains a backtrace.