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 | 4 |
5 /// This library defines runtime operations on objects used by the code | 5 /// This library defines runtime operations on objects used by the code |
6 /// generator. | 6 /// generator. |
7 part of dart._runtime; | 7 part of dart._runtime; |
8 | 8 |
9 _canonicalFieldName(obj, name, args, displayName) => JS('', '''(() => { | 9 _canonicalFieldName(obj, name, args, displayName) => JS('', '''(() => { |
10 $name = $canonicalMember($obj, $name); | 10 $name = $canonicalMember($obj, $name); |
(...skipping 21 matching lines...) Expand all Loading... | |
32 dput(obj, field, value) => JS('', '''(() => { | 32 dput(obj, field, value) => JS('', '''(() => { |
33 $field = $_canonicalFieldName($obj, $field, [$value], $field); | 33 $field = $_canonicalFieldName($obj, $field, [$value], $field); |
34 // TODO(vsm): Implement NSM and type checks. | 34 // TODO(vsm): Implement NSM and type checks. |
35 // See: https://github.com/dart-lang/dev_compiler/issues/170 | 35 // See: https://github.com/dart-lang/dev_compiler/issues/170 |
36 $obj[$field] = $value; | 36 $obj[$field] = $value; |
37 return $value; | 37 return $value; |
38 })()'''); | 38 })()'''); |
39 | 39 |
40 /// Check that a function of a given type can be applied to | 40 /// Check that a function of a given type can be applied to |
41 /// actuals. | 41 /// actuals. |
42 checkApply(type, actuals) => JS('', '''(() => { | 42 _checkApply(type, actuals) => JS('', '''(() => { |
43 if ($actuals.length < $type.args.length) return false; | 43 if ($actuals.length < $type.args.length) return false; |
44 let index = 0; | 44 let index = 0; |
45 for(let i = 0; i < $type.args.length; ++i) { | 45 for(let i = 0; i < $type.args.length; ++i) { |
46 if (!$instanceOfOrNull($actuals[i], $type.args[i])) return false; | 46 if (!$instanceOfOrNull($actuals[i], $type.args[i])) return false; |
47 ++index; | 47 ++index; |
48 } | 48 } |
49 if ($actuals.length == $type.args.length) return true; | 49 if ($actuals.length == $type.args.length) return true; |
50 let extras = $actuals.length - $type.args.length; | 50 let extras = $actuals.length - $type.args.length; |
51 if ($type.optionals.length > 0) { | 51 if ($type.optionals.length > 0) { |
52 if (extras > $type.optionals.length) return false; | 52 if (extras > $type.optionals.length) return false; |
(...skipping 27 matching lines...) Expand all Loading... | |
80 | 80 |
81 throwNoSuchMethod(obj, name, pArgs, nArgs, extras) => JS('', '''(() => { | 81 throwNoSuchMethod(obj, name, pArgs, nArgs, extras) => JS('', '''(() => { |
82 $throw_(new $NoSuchMethodError($obj, $_dartSymbol($name), $pArgs, $nArgs, $ext ras)); | 82 $throw_(new $NoSuchMethodError($obj, $_dartSymbol($name), $pArgs, $nArgs, $ext ras)); |
83 })()'''); | 83 })()'''); |
84 | 84 |
85 throwNoSuchMethodFunc(obj, name, pArgs, opt_func) => JS('', '''(() => { | 85 throwNoSuchMethodFunc(obj, name, pArgs, opt_func) => JS('', '''(() => { |
86 if ($obj === void 0) $obj = $opt_func; | 86 if ($obj === void 0) $obj = $opt_func; |
87 $throwNoSuchMethod($obj, $name, $pArgs); | 87 $throwNoSuchMethod($obj, $name, $pArgs); |
88 })()'''); | 88 })()'''); |
89 | 89 |
90 checkAndCall(f, ftype, obj, args, name) => JS('', '''(() => { | 90 _checkAndCall(f, ftype, obj, typeArgs, args, name) => JS('', '''(() => { |
91 let originalFunction = $f; | 91 let originalFunction = $f; |
92 if (!($f instanceof Function)) { | 92 if (!($f instanceof Function)) { |
93 // We're not a function (and hence not a method either) | 93 // We're not a function (and hence not a method either) |
94 // Grab the `call` method if it's not a function. | 94 // Grab the `call` method if it's not a function. |
95 if ($f != null) { | 95 if ($f != null) { |
96 $ftype = $getMethodType($f, 'call'); | 96 $ftype = $getMethodType($f, 'call'); |
97 $f = $f.call; | 97 $f = $f.call; |
98 } | 98 } |
99 if (!($f instanceof Function)) { | 99 if (!($f instanceof Function)) { |
100 $throwNoSuchMethodFunc($obj, $name, $args, originalFunction); | 100 $throwNoSuchMethodFunc($obj, $name, $args, originalFunction); |
101 } | 101 } |
102 } | 102 } |
103 // If f is a function, but not a method (no method type) | 103 // If f is a function, but not a method (no method type) |
104 // then it should have been a function valued field, so | 104 // then it should have been a function valued field, so |
105 // get the type from the function. | 105 // get the type from the function. |
106 if ($ftype === void 0) { | 106 if ($ftype === void 0) { |
107 $ftype = $read($f); | 107 $ftype = $read($f); |
108 } | 108 } |
109 | 109 |
110 if (!$ftype) { | 110 if (!$ftype) { |
111 // TODO(leafp): Allow JS objects to go through? | 111 // TODO(leafp): Allow JS objects to go through? |
112 // This includes the DOM. | 112 if ($typeArgs != null) { |
113 // TODO(jmesserly): is there a sensible way to handle these? | |
114 $throwStrongModeError('call to JS object `' + $obj + | |
115 '` with type arguments <' + $typeArgs + '> is not supported.'); | |
116 } | |
113 return $f.apply($obj, $args); | 117 return $f.apply($obj, $args); |
114 } | 118 } |
115 | 119 |
116 if ($checkApply($ftype, $args)) { | 120 // Apply type arguments |
121 let formalCount = $ftype[$_typeFormalCount]; | |
122 if (formalCount != null) { | |
123 if ($typeArgs == null) { | |
124 $typeArgs = Array(formalCount).fill($dynamicR); | |
Jennifer Messerly
2016/04/28 23:28:54
This should be instantiating to bounds.
Related to
| |
125 } else if ($typeArgs.length != formalCount) { | |
126 // TODO(jmesserly): is this the right error? | |
127 $throwStrongModeError( | |
128 'incorrect number of arguments to generic function ' + | |
129 $typeName($ftype) + ', got <' + $typeArgs + '> expected ' + | |
130 formalCount + '.'); | |
131 } | |
132 // Instantiate the function. | |
133 $ftype = $ftype(...$typeArgs); | |
134 } else if ($typeArgs != null) { | |
135 $throwStrongModeError( | |
136 'got type arguments to non-generic function ' + $typeName($ftype) + | |
137 ', got <' + $typeArgs + '> expected none.'); | |
138 } | |
139 | |
140 if ($_checkApply($ftype, $args)) { | |
141 if ($typeArgs != null) { | |
142 return $f.apply($obj, $typeArgs).apply($obj, $args); | |
143 } | |
117 return $f.apply($obj, $args); | 144 return $f.apply($obj, $args); |
118 } | 145 } |
119 | 146 |
120 // TODO(leafp): throw a type error (rather than NSM) | 147 // TODO(leafp): throw a type error (rather than NSM) |
121 // if the arity matches but the types are wrong. | 148 // if the arity matches but the types are wrong. |
149 // TODO(jmesserly): nSM should include type args? | |
122 $throwNoSuchMethodFunc($obj, $name, $args, originalFunction); | 150 $throwNoSuchMethodFunc($obj, $name, $args, originalFunction); |
123 })()'''); | 151 })()'''); |
124 | 152 |
125 dcall(f, @rest args) => JS('', '''(() => { | 153 dcall(f, @rest args) => |
126 let ftype = $read($f); | 154 _checkAndCall(f, read(f), JS('', 'void 0'), null, args, 'call'); |
127 return $checkAndCall($f, ftype, void 0, $args, 'call'); | |
128 })()'''); | |
129 | 155 |
130 /// Shared code for dsend, dindex, and dsetindex. */ | |
131 callMethod(obj, name, args, displayName) => JS('', '''(() => { | |
132 let symbol = $_canonicalFieldName($obj, $name, $args, $displayName); | |
133 let f = $obj != null ? $obj[symbol] : null; | |
134 let ftype = $getMethodType($obj, $name); | |
135 return $checkAndCall(f, ftype, $obj, $args, $displayName); | |
136 })()'''); | |
137 | 156 |
138 dsend(obj, method, @rest args) => JS('', '''(() => { | 157 dgcall(f, typeArgs, @rest args) => |
139 return $callMethod($obj, $method, $args, $method); | 158 _checkAndCall(f, read(f), JS('', 'void 0'), typeArgs, args, 'call'); |
140 })()'''); | |
141 | 159 |
142 dindex(obj, index) => JS('', '''(() => { | |
143 return $callMethod($obj, 'get', [$index], '[]'); | |
144 })()'''); | |
145 | 160 |
146 dsetindex(obj, index, value) => JS('', '''(() => { | 161 /// Shared code for dsend, dindex, and dsetindex. |
147 $callMethod($obj, 'set', [$index, $value], '[]='); | 162 _callMethod(obj, name, typeArgs, args, displayName) { |
148 return $value; | 163 var symbol = _canonicalFieldName(obj, name, args, displayName); |
149 })()'''); | 164 var f = obj != null ? JS('', '#[#]', obj, symbol) : null; |
165 var ftype = getMethodType(obj, symbol); | |
166 return _checkAndCall(f, ftype, obj, typeArgs, args, displayName); | |
167 } | |
168 | |
169 dsend(obj, method, @rest args) => _callMethod(obj, method, null, args, method); | |
170 | |
171 dgsend(obj, typeArgs, method, @rest args) => | |
172 _callMethod(obj, method, typeArgs, args, method); | |
173 | |
174 dindex(obj, index) => _callMethod(obj, 'get', null, JS('', '[#]', index), '[]'); | |
175 | |
176 dsetindex(obj, index, value) => | |
177 _callMethod(obj, 'set', null, JS('', '[#, #]', index, value), '[]='); | |
150 | 178 |
151 _ignoreTypeFailure(actual, type) => JS('', '''(() => { | 179 _ignoreTypeFailure(actual, type) => JS('', '''(() => { |
152 // TODO(vsm): Remove this hack ... | 180 // TODO(vsm): Remove this hack ... |
153 // This is primarily due to the lack of generic methods, | 181 // This is primarily due to the lack of generic methods, |
154 // but we need to triage all the types. | 182 // but we need to triage all the types. |
155 if ($isSubtype($type, $Iterable) && $isSubtype($actual, $Iterable) || | 183 if ($isSubtype($type, $Iterable) && $isSubtype($actual, $Iterable) || |
156 $isSubtype($type, $Future) && $isSubtype($actual, $Future) || | 184 $isSubtype($type, $Future) && $isSubtype($actual, $Future) || |
157 $isSubtype($type, $Map) && $isSubtype($actual, $Map) || | 185 $isSubtype($type, $Map) && $isSubtype($actual, $Map) || |
158 $isSubtype($type, $Function) && $isSubtype($actual, $Function) || | 186 $isSubtype($type, $Function) && $isSubtype($actual, $Function) || |
159 $isSubtype($type, $Stream) && $isSubtype($actual, $Stream) || | 187 $isSubtype($type, $Stream) && $isSubtype($actual, $Stream) || |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
427 constructor(dartIterator) { | 455 constructor(dartIterator) { |
428 this.dartIterator = dartIterator; | 456 this.dartIterator = dartIterator; |
429 } | 457 } |
430 next() { | 458 next() { |
431 let i = this.dartIterator; | 459 let i = this.dartIterator; |
432 let done = !i.moveNext(); | 460 let done = !i.moveNext(); |
433 return { done: done, value: done ? void 0 : i.current }; | 461 return { done: done, value: done ? void 0 : i.current }; |
434 } | 462 } |
435 } | 463 } |
436 '''); | 464 '''); |
OLD | NEW |