OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 part of dart._runtime; | 4 part of dart._runtime; |
5 | 5 |
6 /// This library defines a set of general javascript utilities for us | 6 /// This library defines a set of general javascript utilities for us |
7 /// by the Dart runtime. | 7 /// by the Dart runtime. |
8 // TODO(ochafik): Rewrite some of these in Dart when possible. | 8 // TODO(ochafik): Rewrite some of these in Dart when possible. |
9 | 9 |
10 defineProperty(obj, name, desc) => | 10 defineProperty(obj, name, desc) => |
11 JS('', 'Object.defineProperty(#, #, #)', obj, name, desc); | 11 JS('', 'Object.defineProperty(#, #, #)', obj, name, desc); |
12 | 12 |
13 defineValue(obj, name, value) { | 13 defineValue(obj, name, value) { |
14 defineProperty(obj, name, | 14 defineProperty(obj, name, |
15 JS('', '{ value: #, configurable: true, writable: true }', value)); | 15 JS('', '{ value: #, configurable: true, writable: true }', value)); |
16 return value; | 16 return value; |
17 } | 17 } |
18 | 18 |
| 19 void defineGetter(obj, name, getter) { |
| 20 defineProperty(obj, name, JS('', '{get: #}', getter)); |
| 21 } |
| 22 |
| 23 void defineMemoizedGetter(obj, name, compute) { |
| 24 defineProperty( |
| 25 obj, |
| 26 name, |
| 27 JS('', '{get: () => #, configurable: true}', |
| 28 defineValue(obj, name, JS('', '#()', compute)))); |
| 29 } |
| 30 |
19 getOwnPropertyDescriptor(obj, name) => | 31 getOwnPropertyDescriptor(obj, name) => |
20 JS('', 'Object.getOwnPropertyDescriptor(#, #)', obj, name); | 32 JS('', 'Object.getOwnPropertyDescriptor(#, #)', obj, name); |
21 | 33 |
22 Iterable getOwnPropertyNames(obj) => | 34 Iterable getOwnPropertyNames(obj) => |
23 JS('', 'Object.getOwnPropertyNames(#)', obj); | 35 JS('', 'Object.getOwnPropertyNames(#)', obj); |
24 | 36 |
25 Iterable getOwnPropertySymbols(obj) => | 37 Iterable getOwnPropertySymbols(obj) => |
26 JS('', 'Object.getOwnPropertySymbols(#)', obj); | 38 JS('', 'Object.getOwnPropertySymbols(#)', obj); |
27 | 39 |
28 final hasOwnProperty = JS('', 'Object.prototype.hasOwnProperty'); | 40 final hasOwnProperty = JS('', 'Object.prototype.hasOwnProperty'); |
29 | 41 |
30 /// This error indicates a strong mode specific failure, other than a type | 42 /// This error indicates a strong mode specific failure, other than a type |
31 /// assertion failure (TypeError) or CastError. | 43 /// assertion failure (TypeError) or CastError. |
32 void throwStrongModeError(String message) { | 44 void throwStrongModeError(String message) { |
33 if (JS('bool', 'dart.__trapRuntimeErrors')) JS('', 'debugger'); | 45 if (JS('bool', 'dart.__trapRuntimeErrors')) JS('', 'debugger'); |
34 throw new StrongModeErrorImplementation(message); | 46 throw new StrongModeErrorImplementation(message); |
35 } | 47 } |
36 | 48 |
37 /// This error indicates a bug in the runtime or the compiler. | 49 /// This error indicates a bug in the runtime or the compiler. |
38 void throwInternalError(String message) { | 50 void throwInternalError(String message) { |
39 if (JS('bool', 'dart.__trapRuntimeErrors')) JS('', 'debugger'); | 51 if (JS('bool', 'dart.__trapRuntimeErrors')) JS('', 'debugger'); |
40 JS('', 'throw Error(#)', message); | 52 JS('', 'throw Error(#)', message); |
41 } | 53 } |
42 | 54 |
43 getOwnNamesAndSymbols(obj) { | 55 Iterable getOwnNamesAndSymbols(obj) { |
44 var names = getOwnPropertyNames(obj); | 56 var names = getOwnPropertyNames(obj); |
45 var symbols = getOwnPropertySymbols(obj); | 57 var symbols = getOwnPropertySymbols(obj); |
46 return JS('', '#.concat(#)', names, symbols); | 58 return JS('', '#.concat(#)', names, symbols); |
47 } | 59 } |
48 | 60 |
49 safeGetOwnProperty(obj, name) { | 61 safeGetOwnProperty(obj, name) { |
50 var desc = getOwnPropertyDescriptor(obj, name); | 62 var desc = getOwnPropertyDescriptor(obj, name); |
51 if (desc != null) return JS('', '#.value', desc); | 63 if (desc != null) return JS('', '#.value', desc); |
52 } | 64 } |
53 | 65 |
(...skipping 22 matching lines...) Expand all Loading... |
76 init = circularInitError; | 88 init = circularInitError; |
77 lazySetter(f()); | 89 lazySetter(f()); |
78 return value; | 90 return value; |
79 } | 91 } |
80 $desc.get = lazyGetter; | 92 $desc.get = lazyGetter; |
81 $desc.configurable = true; | 93 $desc.configurable = true; |
82 if ($desc.set) $desc.set = lazySetter; | 94 if ($desc.set) $desc.set = lazySetter; |
83 return $defineProperty($to, $name, $desc); | 95 return $defineProperty($to, $name, $desc); |
84 })()'''); | 96 })()'''); |
85 | 97 |
86 void defineLazy(to, from) => JS( | 98 copyTheseProperties(to, from, names) { |
87 '', | 99 for (var i = 0; i < JS('int', '#.length', names); ++i) { |
88 '''(() => { | 100 copyProperty(to, from, JS('', '#[#]', names, i)); |
89 for (let name of $getOwnNamesAndSymbols($from)) { | |
90 $defineLazyProperty($to, name, $getOwnPropertyDescriptor($from, name)); | |
91 } | 101 } |
92 })()'''); | 102 return to; |
93 | |
94 defineMemoizedGetter(obj, name, getter) { | |
95 return defineLazyProperty(obj, name, JS('', '{get: #}', getter)); | |
96 } | 103 } |
97 | 104 |
98 copyTheseProperties(to, from, names) => JS( | |
99 '', | |
100 '''(() => { | |
101 for (let i = 0; i < $names.length; ++i) { | |
102 $copyProperty($to, $from, $names[i]); | |
103 } | |
104 return $to; | |
105 })()'''); | |
106 | |
107 copyProperty(to, from, name) { | 105 copyProperty(to, from, name) { |
108 var desc = getOwnPropertyDescriptor(from, name); | 106 var desc = getOwnPropertyDescriptor(from, name); |
109 if (JS('bool', '# == Symbol.iterator', name)) { | 107 if (JS('bool', '# == Symbol.iterator', name)) { |
110 // On native types, Symbol.iterator may already be present. | 108 // On native types, Symbol.iterator may already be present. |
111 // TODO(jmesserly): investigate if we still need this. | 109 // TODO(jmesserly): investigate if we still need this. |
112 // If so, we need to find a better solution. | 110 // If so, we need to find a better solution. |
113 // See https://github.com/dart-lang/sdk/issues/28324 | 111 // See https://github.com/dart-lang/sdk/issues/28324 |
114 var existing = getOwnPropertyDescriptor(to, name); | 112 var existing = getOwnPropertyDescriptor(to, name); |
115 if (existing != null) { | 113 if (existing != null) { |
116 if (JS('bool', '#.writable', existing)) { | 114 if (JS('bool', '#.writable', existing)) { |
117 JS('', '#[#] = #.value', to, name, desc); | 115 JS('', '#[#] = #.value', to, name, desc); |
118 } | 116 } |
119 return; | 117 return; |
120 } | 118 } |
121 } | 119 } |
122 defineProperty(to, name, desc); | 120 defineProperty(to, name, desc); |
123 } | 121 } |
124 | 122 |
125 @JSExportName('export') | 123 @JSExportName('export') |
126 exportProperty(to, from, name) => copyProperty(to, from, name); | 124 exportProperty(to, from, name) => copyProperty(to, from, name); |
127 | 125 |
128 /// Copy properties from source to destination object. | 126 /// Copy properties from source to destination object. |
129 /// This operation is commonly called `mixin` in JS. | 127 /// This operation is commonly called `mixin` in JS. |
130 copyProperties(to, from) { | 128 copyProperties(to, from) { |
131 return copyTheseProperties(to, from, getOwnNamesAndSymbols(from)); | 129 return copyTheseProperties(to, from, getOwnNamesAndSymbols(from)); |
132 } | 130 } |
OLD | NEW |