mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 04:27:17 +00:00
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
This commit is contained in:
parent
34a556e5a9
commit
0df0c89ae6
|
@ -15,6 +15,7 @@ import 'package:_internal/compiler/js_lib/shared/embedded_names.dart' show
|
||||||
DEFERRED_LIBRARY_URIS,
|
DEFERRED_LIBRARY_URIS,
|
||||||
DEFERRED_LIBRARY_HASHES,
|
DEFERRED_LIBRARY_HASHES,
|
||||||
INITIALIZE_LOADED_HUNK,
|
INITIALIZE_LOADED_HUNK,
|
||||||
|
IS_HUNK_INITIALIZED,
|
||||||
IS_HUNK_LOADED;
|
IS_HUNK_LOADED;
|
||||||
|
|
||||||
import '../js_emitter.dart' show NativeGenerator;
|
import '../js_emitter.dart' show NativeGenerator;
|
||||||
|
|
|
@ -161,6 +161,7 @@ class OldEmitter implements Emitter {
|
||||||
String get lazyInitializerName
|
String get lazyInitializerName
|
||||||
=> '${namer.isolateName}.${lazyInitializerProperty}';
|
=> '${namer.isolateName}.${lazyInitializerProperty}';
|
||||||
String get initName => 'init';
|
String get initName => 'init';
|
||||||
|
|
||||||
String get makeConstListProperty
|
String get makeConstListProperty
|
||||||
=> namer.getMappedInstanceName('makeConstantList');
|
=> namer.getMappedInstanceName('makeConstantList');
|
||||||
|
|
||||||
|
@ -1831,23 +1832,34 @@ function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) {
|
||||||
/// Emits support-code for deferred loading into [buffer].
|
/// Emits support-code for deferred loading into [buffer].
|
||||||
void emitDeferredBoilerPlate(CodeBuffer buffer,
|
void emitDeferredBoilerPlate(CodeBuffer buffer,
|
||||||
Map<OutputUnit, String> deferredLoadHashes) {
|
Map<OutputUnit, String> deferredLoadHashes) {
|
||||||
// Function for checking if a hunk is loaded given its hash.
|
jsAst.Statement functions = js.statement('''
|
||||||
buffer.write(jsAst.prettyPrint(
|
{
|
||||||
js('# = function(hunkHash) {'
|
// Function for checking if a hunk is loaded given its hash.
|
||||||
' return !!$deferredInitializers[hunkHash];'
|
#isHunkLoaded = function(hunkHash) {
|
||||||
'}', generateEmbeddedGlobalAccess(embeddedNames.IS_HUNK_LOADED)),
|
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));
|
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
|
// 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,
|
// 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
|
// and a corresponding mapping to a list of hashes used by
|
||||||
|
|
|
@ -15,6 +15,7 @@ import 'dart:_js_embedded_names' show
|
||||||
DEFERRED_LIBRARY_HASHES,
|
DEFERRED_LIBRARY_HASHES,
|
||||||
INITIALIZE_LOADED_HUNK,
|
INITIALIZE_LOADED_HUNK,
|
||||||
IS_HUNK_LOADED,
|
IS_HUNK_LOADED,
|
||||||
|
IS_HUNK_INITIALIZED,
|
||||||
NATIVE_SUPERCLASS_TAG_NAME;
|
NATIVE_SUPERCLASS_TAG_NAME;
|
||||||
|
|
||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
|
@ -3313,15 +3314,18 @@ Future<Null> loadDeferredLibrary(String loadId) {
|
||||||
// The indices into `uris` and `hashes` that we want to load.
|
// The indices into `uris` and `hashes` that we want to load.
|
||||||
List<int> indices = new List.generate(uris.length, (i) => i);
|
List<int> indices = new List.generate(uris.length, (i) => i);
|
||||||
var isHunkLoaded = JS_EMBEDDED_GLOBAL('', IS_HUNK_LOADED);
|
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.
|
// Filter away indices for hunks that have already been loaded.
|
||||||
List<int> indicesToLoad = indices
|
List<int> indicesToLoad = indices
|
||||||
.where((int i) => !JS('bool','#(#)', isHunkLoaded, hashes[i]))
|
.where((int i) => !JS('bool','#(#)', isHunkLoaded, hashes[i]))
|
||||||
.toList();
|
.toList();
|
||||||
// Load the needed hunks.
|
List<int> indicesToInitialize = indices
|
||||||
|
.where((int i) => !JS('bool','#(#)', isHunkInitialized, hashes[i]))
|
||||||
|
.toList(); // Load the needed hunks.
|
||||||
return Future.wait(indicesToLoad
|
return Future.wait(indicesToLoad
|
||||||
.map((int i) => _loadHunk(uris[i]))).then((_) {
|
.map((int i) => _loadHunk(uris[i]))).then((_) {
|
||||||
// Now all hunks have been loaded, we run the needed initializers.
|
// 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);
|
var initializer = JS_EMBEDDED_GLOBAL('', INITIALIZE_LOADED_HUNK);
|
||||||
JS('void', '#(#)', initializer, hashes[i]);
|
JS('void', '#(#)', initializer, hashes[i]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,8 @@ const DEFERRED_LIBRARY_URIS = 'deferredLibraryUris';
|
||||||
const DEFERRED_LIBRARY_HASHES = 'deferredLibraryHashes';
|
const DEFERRED_LIBRARY_HASHES = 'deferredLibraryHashes';
|
||||||
const INITIALIZE_LOADED_HUNK = 'initializeLoadedHunk';
|
const INITIALIZE_LOADED_HUNK = 'initializeLoadedHunk';
|
||||||
const IS_HUNK_LOADED = 'isHunkLoaded';
|
const IS_HUNK_LOADED = 'isHunkLoaded';
|
||||||
|
const IS_HUNK_INITIALIZED = 'isHunkInitialized';
|
||||||
|
const DEFERRED_INITIALIZED = 'deferredInitialized';
|
||||||
const CLASS_ID_EXTRACTOR = 'classIdExtractor';
|
const CLASS_ID_EXTRACTOR = 'classIdExtractor';
|
||||||
const CLASS_FIELDS_EXTRACTOR = 'classFieldsExtractor';
|
const CLASS_FIELDS_EXTRACTOR = 'classFieldsExtractor';
|
||||||
const INSTANCE_FROM_CLASS_ID = "instanceFromClassId";
|
const INSTANCE_FROM_CLASS_ID = "instanceFromClassId";
|
||||||
|
|
28
tests/html/deferred_multi_app.dart
Normal file
28
tests/html/deferred_multi_app.dart
Normal file
|
@ -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, '*');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
23
tests/html/deferred_multi_app_htmltest.html
Normal file
23
tests/html/deferred_multi_app_htmltest.html
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<!--
|
||||||
|
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.
|
||||||
|
|
||||||
|
Test that two instances of a script does not interfere when loading the same
|
||||||
|
deferred library.
|
||||||
|
|
||||||
|
START_HTML_DART_TEST
|
||||||
|
{
|
||||||
|
"scripts": ["deferred_multi_app.dart"],
|
||||||
|
"expectedMessages": ["one", "two"]
|
||||||
|
}
|
||||||
|
END_HTML_DART_TEST
|
||||||
|
-->
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<div id="state">1</div>
|
||||||
|
<script>window.parent.dispatchEvent(new Event('detect_errors'));</script>
|
||||||
|
<script src="deferred_multi_app.dart" type="application/dart"></script>
|
||||||
|
<script src="deferred_multi_app.dart" type="application/dart"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
11
tests/html/deferred_multi_app_lib.dart
Normal file
11
tests/html/deferred_multi_app_lib.dart
Normal file
|
@ -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";
|
||||||
|
}
|
|
@ -105,6 +105,9 @@ xhr_test: Pass, Fail # Issue 11884
|
||||||
[$runtime == drt || $runtime == dartium || $runtime == chrome || $runtime == chromeOnAndroid || $runtime == ContentShellOnAndroid ]
|
[$runtime == drt || $runtime == dartium || $runtime == chrome || $runtime == chromeOnAndroid || $runtime == ContentShellOnAndroid ]
|
||||||
webgl_1_test: Pass, Fail # Issue 8219
|
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]
|
[ $compiler == none && ($runtime == drt || $runtime == dartium) && $system == windows]
|
||||||
websql_test: Skip # Issue 4941: stderr contains a backtrace.
|
websql_test: Skip # Issue 4941: stderr contains a backtrace.
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue