| Index: sdk/lib/_internal/lib/async_patch.dart
|
| diff --git a/sdk/lib/_internal/lib/async_patch.dart b/sdk/lib/_internal/lib/async_patch.dart
|
| index 053e856712e68786fb5cb93344e60daca09c38a0..c26f29f9291e8c5926101078eefd5077c82b9295 100644
|
| --- a/sdk/lib/_internal/lib/async_patch.dart
|
| +++ b/sdk/lib/_internal/lib/async_patch.dart
|
| @@ -4,9 +4,15 @@
|
|
|
| // Patch file for the dart:async library.
|
|
|
| -import 'dart:_js_helper' show Primitives;
|
| -import 'dart:_isolate_helper' show IsolateNatives, TimerImpl;
|
| -import 'dart:_foreign_helper' show JS, DART_CLOSURE_TO_JS;
|
| +import 'dart:_js_helper' show Primitives, convertDartClosureToJS;
|
| +import 'dart:_isolate_helper' show
|
| + IsolateNatives,
|
| + TimerImpl,
|
| + leaveJsAsync,
|
| + enterJsAsync,
|
| + isWorker;
|
| +
|
| +import 'dart:_foreign_helper' show JS;
|
|
|
| patch Timer _createTimer(Duration duration, void callback()) {
|
| int milliseconds = duration.inMilliseconds;
|
| @@ -41,7 +47,7 @@ patch class DeferredLibrary {
|
| libraryName, index));
|
| }
|
| Iterable<Future<bool>> allLoads =
|
| - hunkNames.map((libraryName) => _load(libraryName, uri));
|
| + hunkNames.map((hunkName) => _load(hunkName, uri));
|
| return Future.wait(allLoads).then((results) {
|
| return results.any((x) => x);
|
| });
|
| @@ -60,57 +66,88 @@ Future<bool> _load(String hunkName, String uri) {
|
| return future.then((_) => false);
|
| }
|
|
|
| - if (Primitives.isJsshell) {
|
| - // TODO(ahe): Move this code to a JavaScript command helper script that is
|
| - // not included in generated output.
|
| - return _loadedLibraries[hunkName] = new Future<bool>(() {
|
| - if (uri == null) uri = '$hunkName';
|
| - // Create a new function to avoid getting access to current function
|
| - // context.
|
| - JS('void', '(new Function(#))()', 'loadRelativeToScript("$uri")');
|
| - return true;
|
| - });
|
| - } else if (Primitives.isD8) {
|
| + if (uri == null) {
|
| + uri = IsolateNatives.thisScript;
|
| + }
|
| + int index = uri.lastIndexOf('/');
|
| + uri = '${uri.substring(0, index + 1)}$hunkName';
|
| +
|
| + if (Primitives.isJsshell || Primitives.isD8) {
|
| // TODO(ahe): Move this code to a JavaScript command helper script that is
|
| // not included in generated output.
|
| return _loadedLibraries[hunkName] = new Future<bool>(() {
|
| - if (uri == null) {
|
| - uri = IsolateNatives.computeThisScriptD8();
|
| - int index = uri.lastIndexOf('/');
|
| - uri = '${uri.substring(0, index + 1)}$hunkName';
|
| + try {
|
| + // Create a new function to avoid getting access to current function
|
| + // context.
|
| + JS('void', '(new Function(#))()', 'load("$uri")');
|
| + } catch (error, stackTrace) {
|
| + throw new DeferredLoadException("Loading $uri failed.");
|
| }
|
| - // Create a new function to avoid getting access to current function
|
| - // context.
|
| - JS('void', '(new Function(#))()', 'load("$uri")');
|
| return true;
|
| });
|
| - }
|
| + } else if (isWorker()) {
|
| + // We are in a web worker. Load the code with an XMLHttpRequest.
|
| + return _loadedLibraries[hunkName] = new Future<bool>(() {
|
| + Completer completer = new Completer<bool>();
|
| + enterJsAsync();
|
| + Future<bool> leavingFuture = completer.future.whenComplete(() {
|
| + leaveJsAsync();
|
| + });
|
|
|
| - return _loadedLibraries[hunkName] = new Future<bool>(() {
|
| - Completer completer = new Completer<bool>();
|
| - if (uri == null) {
|
| - uri = IsolateNatives.thisScript;
|
| int index = uri.lastIndexOf('/');
|
| uri = '${uri.substring(0, index + 1)}$hunkName';
|
| - }
|
| + var xhr = JS('dynamic', 'new XMLHttpRequest()');
|
| + JS('void', '#.open("GET", #)', xhr, uri);
|
| + JS('void', '#.addEventListener("load", #, false)',
|
| + xhr, convertDartClosureToJS((event) {
|
| + if (JS('int', '#.status', xhr) != 200) {
|
| + completer.completeError(
|
| + new DeferredLoadException("Loading $uri failed."));
|
| + return;
|
| + }
|
| + String code = JS('String', '#.responseText', xhr);
|
| + try {
|
| + // Create a new function to avoid getting access to current function
|
| + // context.
|
| + JS('void', '(new Function(#))()', code);
|
| + } catch (error, stackTrace) {
|
| + completer.completeError(
|
| + new DeferredLoadException("Evaluating $uri failed."));
|
| + return;
|
| + }
|
| + completer.complete(true);
|
| + }, 1));
|
|
|
| + var fail = convertDartClosureToJS((event) {
|
| + new DeferredLoadException("Loading $uri failed.");
|
| + }, 1);
|
| + JS('void', '#.addEventListener("error", #, false)', xhr, fail);
|
| + JS('void', '#.addEventListener("abort", #, false)', xhr, fail);
|
| +
|
| + JS('void', '#.send()', xhr);
|
| + return leavingFuture;
|
| + });
|
| + }
|
| + // We are in a dom-context.
|
| + return _loadedLibraries[hunkName] = new Future<bool>(() {
|
| + Completer completer = new Completer<bool>();
|
| // Inject a script tag.
|
| var script = JS('', 'document.createElement("script")');
|
| JS('', '#.type = "text/javascript"', script);
|
| JS('', '#.src = #', script, uri);
|
| - var onLoad = JS('', '#.bind(null, #)',
|
| - DART_CLOSURE_TO_JS(_onDeferredLibraryLoad), completer);
|
| - JS('', '#.addEventListener("load", #, false)', script, onLoad);
|
| + JS('', '#.addEventListener("load", #, false)',
|
| + script, convertDartClosureToJS((event) {
|
| + completer.complete(true);
|
| + }, 1));
|
| + JS('', '#.addEventListener("error", #, false)',
|
| + script, convertDartClosureToJS((event) {
|
| + completer.completeError(
|
| + new DeferredLoadException("Loading $uri failed."));
|
| + }, 1));
|
| JS('', 'document.body.appendChild(#)', script);
|
|
|
| return completer.future;
|
| });
|
| }
|
|
|
| -/// Used to implement deferred loading. Used as callback on "load"
|
| -/// event above in [load].
|
| -_onDeferredLibraryLoad(Completer<bool> completer, event) {
|
| - completer.complete(true);
|
| -}
|
| -
|
| bool get _hasDocument => JS('String', 'typeof document') == 'object';
|
|
|