OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 library _js_helper; | 5 library _js_helper; |
6 | 6 |
7 import 'dart:_async_await_error_codes' as async_error_codes; | 7 import 'dart:_async_await_error_codes' as async_error_codes; |
8 | 8 |
9 import 'dart:_js_embedded_names' show | 9 import 'dart:_js_embedded_names' show |
10 DEFERRED_LIBRARY_URIS, | 10 DEFERRED_LIBRARY_URIS, |
(...skipping 2266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2277 // BoundClosure.prototype, respectively in pseudo JavaScript code. The | 2277 // BoundClosure.prototype, respectively in pseudo JavaScript code. The |
2278 // simplest way to access the JavaScript construction function of a Dart | 2278 // simplest way to access the JavaScript construction function of a Dart |
2279 // class is to create an instance and access its constructor property. | 2279 // class is to create an instance and access its constructor property. |
2280 // Creating an instance ensures that any lazy class initialization has taken | 2280 // Creating an instance ensures that any lazy class initialization has taken |
2281 // place. The newly created instance could in theory be used directly as the | 2281 // place. The newly created instance could in theory be used directly as the |
2282 // prototype, but it might include additional fields that we don't need. So | 2282 // prototype, but it might include additional fields that we don't need. So |
2283 // we only use the new instance to access the constructor property and use | 2283 // we only use the new instance to access the constructor property and use |
2284 // Object.create to create the desired prototype. | 2284 // Object.create to create the desired prototype. |
2285 // | 2285 // |
2286 // TODO(sra): Perhaps cache the prototype to avoid the allocation. | 2286 // TODO(sra): Perhaps cache the prototype to avoid the allocation. |
2287 var prototype = isStatic | 2287 TearOffClosure dummyObject = isStatic |
2288 ? JS('StaticClosure', 'Object.create(#.constructor.prototype)', | 2288 ? new StaticClosure() |
2289 new StaticClosure()) | 2289 : new BoundClosure(null, null, null, null); |
2290 : JS('BoundClosure', 'Object.create(#.constructor.prototype)', | 2290 |
2291 new BoundClosure(null, null, null, null)); | 2291 var prototype = JS( |
| 2292 'TearOffClosure', |
| 2293 'Object.create(#.constructor.prototype)', |
| 2294 dummyObject); |
2292 | 2295 |
2293 JS('', '#.\$initialize = #', prototype, JS('', '#.constructor', prototype)); | 2296 JS('', '#.\$initialize = #', prototype, JS('', '#.constructor', prototype)); |
2294 var constructor = isStatic | 2297 var constructor = isStatic |
2295 ? JS('', 'function(){this.\$initialize()}') | 2298 ? JS('', 'function(){this.\$initialize()}') |
2296 : isCsp | 2299 : isCsp |
2297 ? JS('', 'function(a,b,c,d) {this.\$initialize(a,b,c,d)}') | 2300 ? JS('', 'function(a,b,c,d) {this.\$initialize(a,b,c,d)}') |
2298 : JS('', | 2301 : JS('', |
2299 'new Function("a,b,c,d", "this.\$initialize(a,b,c,d);" + #)', | 2302 'new Function("a,b,c,d", "this.\$initialize(a,b,c,d);" + #)', |
2300 functionCounter++); | 2303 functionCounter++); |
2301 | 2304 |
2302 // It is necessary to set the constructor property, otherwise it will be | 2305 // It is necessary to set the constructor property, otherwise it will be |
2303 // "Object". | 2306 // "Object". |
2304 JS('', '#.constructor = #', prototype, constructor); | 2307 // We want the constructor.name property to have the name of the |
| 2308 // StaticClosure or BoundClosure class. |
| 2309 // Most browsers (except IE10) don't allow to change the name of a function |
| 2310 // as such we can't just set the property. However, we can work around this |
| 2311 // by creating an empty object with the name property set to the correct |
| 2312 // value and then setting the prototype to the original constructor. |
| 2313 // This works for all browsers except IE10 which doesn't have a way to |
| 2314 // change the prototype. There we simply set the name. |
| 2315 if (JS('bool', 'typeof Object.setPrototypeOf != "undefined"')) { |
| 2316 String tearOffClassName = JS('String', '#.constructor.name', dummyObject); |
| 2317 JS('', '#.constructor = {name: #}', prototype, tearOffClassName); |
| 2318 JS('', 'Object.setPrototypeOf(#.constructor, #)', prototype, constructor); |
| 2319 } else { |
| 2320 // IE10. |
| 2321 JS('', '#.constructor = #', prototype, constructor); |
| 2322 JS('', '#.constructor.name = #', prototype, propertyName); |
| 2323 } |
2305 | 2324 |
2306 JS('', '#.prototype = #', constructor, prototype); | 2325 JS('', '#.prototype = #', constructor, prototype); |
2307 | 2326 |
2308 // Create a closure and "monkey" patch it with call stubs. | 2327 // Create a closure and "monkey" patch it with call stubs. |
2309 var trampoline = function; | 2328 var trampoline = function; |
2310 var isIntercepted = false; | 2329 var isIntercepted = false; |
2311 if (!isStatic) { | 2330 if (!isStatic) { |
2312 if (JS('bool', '#.length == 1', jsArguments)) { | 2331 if (JS('bool', '#.length == 1', jsArguments)) { |
2313 // Intercepted call. | 2332 // Intercepted call. |
2314 isIntercepted = true; | 2333 isIntercepted = true; |
(...skipping 1814 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4129 // This is a function that will return a helper function that does the | 4148 // This is a function that will return a helper function that does the |
4130 // iteration of the sync*. | 4149 // iteration of the sync*. |
4131 // | 4150 // |
4132 // Each invocation should give a body with fresh state. | 4151 // Each invocation should give a body with fresh state. |
4133 final dynamic /* js function */ _outerHelper; | 4152 final dynamic /* js function */ _outerHelper; |
4134 | 4153 |
4135 SyncStarIterable(this._outerHelper); | 4154 SyncStarIterable(this._outerHelper); |
4136 | 4155 |
4137 Iterator get iterator => new SyncStarIterator(JS('', '#()', _outerHelper)); | 4156 Iterator get iterator => new SyncStarIterator(JS('', '#()', _outerHelper)); |
4138 } | 4157 } |
OLD | NEW |