OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 // Patch file for the dart:async library. | 5 // Patch file for the dart:async library. |
6 | 6 |
7 import 'dart:_isolate_helper' show TimerImpl; | 7 import 'dart:_isolate_helper' show TimerImpl; |
8 import 'dart:_foreign_helper' show JS, DART_CLOSURE_TO_JS; | |
8 | 9 |
9 typedef void _TimerCallback0(); | 10 typedef void _TimerCallback0(); |
10 typedef void _TimerCallback1(Timer timer); | 11 typedef void _TimerCallback1(Timer timer); |
11 | 12 |
12 patch class Timer { | 13 patch class Timer { |
13 patch factory Timer(var duration, var callback) { | 14 patch factory Timer(var duration, var callback) { |
14 // TODO(floitsch): remove these checks when we remove the deprecated | 15 // TODO(floitsch): remove these checks when we remove the deprecated |
15 // millisecond argument and the 1-argument callback. Also remove the | 16 // millisecond argument and the 1-argument callback. Also remove the |
16 // int-test below. | 17 // int-test below. |
17 if (callback is! _TimerCallback0 && callback is! _TimerCallback1) { | 18 if (callback is! _TimerCallback0 && callback is! _TimerCallback1) { |
(...skipping 14 matching lines...) Expand all Loading... | |
32 */ | 33 */ |
33 patch factory Timer.repeating(var duration, void callback(Timer timer)) { | 34 patch factory Timer.repeating(var duration, void callback(Timer timer)) { |
34 // TODO(floitsch): remove this check when we remove the deprecated | 35 // TODO(floitsch): remove this check when we remove the deprecated |
35 // millisecond argument. | 36 // millisecond argument. |
36 int milliseconds = duration is int ? duration : duration.inMilliseconds; | 37 int milliseconds = duration is int ? duration : duration.inMilliseconds; |
37 if (milliseconds < 0) milliseconds = 0; | 38 if (milliseconds < 0) milliseconds = 0; |
38 return new TimerImpl.repeating(milliseconds, callback); | 39 return new TimerImpl.repeating(milliseconds, callback); |
39 } | 40 } |
40 } | 41 } |
41 | 42 |
42 final Set<String> _loadedLibraries = new Set<String>(); | |
43 | |
44 patch class DeferredLibrary { | 43 patch class DeferredLibrary { |
45 patch Future<bool> load() { | 44 patch Future<bool> load() { |
46 // TODO(ahe): Implement this. | 45 return _load(libraryName, uri); |
47 Future future = | |
48 new Future<bool>.immediate(!_loadedLibraries.contains(libraryName)); | |
49 _loadedLibraries.add(libraryName); | |
50 return future; | |
51 } | 46 } |
52 } | 47 } |
48 | |
49 // TODO(ahe): This should not only apply to this isolate. | |
50 final _loadedLibraries = <String, Completer<bool>>{}; | |
51 | |
52 Future<bool> _load(String libraryName, String uri) { | |
53 // TODO(ahe): Validate libraryName. Kasper points out that you want | |
54 // to be able to experiment with the effect of toggling @DeferLoad, | |
55 // so perhaps we should silently ignore "bad" library names. | |
56 Completer completer = new Completer<bool>(); | |
57 Future<bool> future = _loadedLibraries[libraryName]; | |
58 if (future != null) { | |
59 future.then((_) { completer.complete(false); }); | |
60 return completer.future; | |
61 } | |
62 _loadedLibraries[libraryName] = completer.future; | |
63 | |
64 if (uri == null) { | |
65 uri = _currentScriptUri; | |
66 int index = JS('int', '#.lastIndexOf("/")', uri); | |
ngeoffray
2013/02/19 10:04:57
It says it's a URI, but did you check it worked on
ahe
2013/02/19 11:10:36
Yes. It is a URL.
| |
67 uri = JS('String', '#.substring(0, # + 1) + #', uri, index, "part.js"); | |
ngeoffray
2013/02/19 10:04:57
Why don't you use Dart String methods for substrin
ahe
2013/02/19 11:10:36
I was trying to avoid bringing unnecessary "junk"
| |
68 } | |
69 | |
70 if (_hasDocument) { | |
71 // Inject a script tag. | |
72 var script = JS('', 'document.createElement("script")'); | |
73 JS('', '#.type = "text/javascript"', script); | |
74 JS('', '#.async = "async"', script); | |
75 JS('', '#.src = #', script, uri); | |
76 var onLoad = JS('', '#.bind(null, #)', | |
77 DART_CLOSURE_TO_JS(_onDeferredLibraryLoad), completer); | |
78 JS('', '#.addEventListener("load", #, false)', script, onLoad); | |
79 JS('', 'document.body.appendChild(#)', script); | |
80 } else if (JS('String', 'typeof load') == 'function') { | |
81 new Timer(0, (_) { | |
82 JS('void', 'load(#)', uri); | |
83 completer.complete(true); | |
84 }); | |
85 } else { | |
86 throw new UnsupportedError('load not supported'); | |
87 } | |
88 return completer.future; | |
89 } | |
90 | |
91 /// Used to implement deferred loading. Used as callback on "load" | |
92 /// event above in [load]. | |
93 _onDeferredLibraryLoad(Completer<bool> completer, event) { | |
94 completer.complete(true); | |
95 } | |
96 | |
97 bool get _hasDocument => JS('String', 'typeof document') == 'object'; | |
98 | |
99 /// Returns the URI of the current script (as a string). | |
100 // TODO(ahe): Share with IsolateNatives.computeThisScript. | |
101 String get _currentScriptUri() { | |
102 // TODO(ahe): The following works in Firefox during loading of the | |
103 // script, and is being considered for the standard. | |
104 // if (_hasDocument) { | |
105 // var currentScript = JS('', 'document.currentScript'); | |
106 // if (JS('String', 'typeof #', currentScript) == 'object') { | |
107 // return JS('String', '#.src', currentScript); | |
108 // } | |
109 // } | |
110 | |
111 var stack = JS('String|Null', 'new Error().stack'); | |
112 if (stack == null) { | |
113 // According to Internet Explorer documentation, the stack | |
114 // property is not set until the exception is thrown. | |
115 stack = JS('String', | |
116 'function() {try{throw new Error()}catch(e){return e.stack}}'); | |
117 } | |
118 var pattern, matches; | |
119 | |
120 // This pattern matches V8, Chrome, and Internet Explorer stack | |
121 // traces that look like this: | |
122 // Error | |
123 // at methodName (URI:LINE:COLUMN) | |
124 pattern = JS('', r'new RegExp("^ *at (.*):[0-9]*:[0-9]*$", "m")'); | |
125 | |
126 matches = JS('', '#.match(#)', stack, pattern); | |
127 if (matches != null) return matches[1]; | |
128 | |
129 // This pattern matches Firefox stack traces that look like this: | |
130 // methodName@URI:LINE | |
131 pattern = JS('', r'new RegExp("^[^@]*@(.*):[0-9]*$", "m")'); | |
132 | |
133 matches = JS('', '#.match(#)', stack, pattern); | |
134 if (matches != null) return matches[1]; | |
135 | |
136 throw new UnsupportedError('Cannot extract URI from "$stack"'); | |
137 } | |
OLD | NEW |