Chromium Code Reviews| Index: pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart |
| diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart |
| index 629db3861208593319cb1cd1953a06c4d2f4e64d..026eb9a1f38b127fa040afded605e91dc01eb982 100644 |
| --- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart |
| +++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart |
| @@ -53,6 +53,27 @@ mixin(base, @rest mixins) => JS( |
| $copyProperties(s, m[$_methodSig]); |
| } |
| return s; |
| + }, |
| + fields: () => { |
|
Jacob
2017/01/21 01:11:30
hole in propagating metadata
|
| + let s = {}; |
| + for (let m of $mixins) { |
| + $copyProperties(s, m[$_fieldSig]); |
| + } |
| + return s; |
| + }, |
| + getters: () => { |
| + let s = {}; |
| + for (let m of $mixins) { |
| + $copyProperties(s, m[$_getterSig]); |
| + } |
| + return s; |
| + }, |
| + setters: () => { |
| + let s = {}; |
| + for (let m of $mixins) { |
| + $copyProperties(s, m[$_setterSig]); |
| + } |
| + return s; |
| } |
| }); |
| @@ -64,12 +85,14 @@ mixin(base, @rest mixins) => JS( |
| /// The Symbol for storing type arguments on a specialized generic type. |
| final _mixins = JS('', 'Symbol("mixins")'); |
| -getMixins(clazz) => JS('', 'Object.hasOwnProperty.call(#, #) ? #[#] : null', clazz, _mixins, clazz, _mixins); |
| +getMixins(clazz) => JS('', 'Object.hasOwnProperty.call(#, #) ? #[#] : null', |
| + clazz, _mixins, clazz, _mixins); |
| @JSExportName('implements') |
| final _implements = JS('', 'Symbol("implements")'); |
| -getImplements(clazz) => JS('', 'Object.hasOwnProperty.call(#, #) ? #[#] : null', clazz, _implements, clazz, _implements); |
| +getImplements(clazz) => JS('', 'Object.hasOwnProperty.call(#, #) ? #[#] : null', |
| + clazz, _implements, clazz, _implements); |
| /// The Symbol for storing type arguments on a specialized generic type. |
| final _typeArguments = JS('', 'Symbol("typeArguments")'); |
| @@ -151,12 +174,12 @@ getGenericArgs(type) => JS('', '$safeGetOwnProperty($type, $_typeArguments)'); |
| final _constructorSig = JS('', 'Symbol("sigCtor")'); |
| final _methodSig = JS('', 'Symbol("sigMethod")'); |
| final _fieldSig = JS('', 'Symbol("sigField")'); |
| -final _getterSig= JS('', 'Symbol("sigGetter")'); |
| -final _setterSig= JS('', 'Symbol("sigSetter")'); |
| +final _getterSig = JS('', 'Symbol("sigGetter")'); |
| +final _setterSig = JS('', 'Symbol("sigSetter")'); |
| final _staticSig = JS('', 'Symbol("sigStaticMethod")'); |
| final _staticFieldSig = JS('', 'Symbol("sigStaticField")'); |
| -final _staticGetterSig= JS('', 'Symbol("sigStaticGetter")'); |
| -final _staticSetterSig= JS('', 'Symbol("sigStaticSetter")'); |
| +final _staticGetterSig = JS('', 'Symbol("sigStaticGetter")'); |
|
Jacob
2017/01/21 01:11:30
Ran the formatter. Sorry about the formatter relat
|
| +final _staticSetterSig = JS('', 'Symbol("sigStaticSetter")'); |
| final _genericTypeCtor = JS('', 'Symbol("genericType")'); |
| // TODO(vsm): Collapse this as well - just provide a dart map to mirrors code. |
| @@ -174,15 +197,14 @@ getStaticSetterSig(value) => JS('', '#[#]', value, _staticSetterSig); |
| getGenericTypeCtor(value) => JS('', '#[#]', value, _genericTypeCtor); |
| /// Get the type of a method from an object using the stored signature |
| -getMethodType(obj, name) => JS( |
| +getType(obj) => JS( |
| '', |
| '''(() => { |
| - let type = $obj == null ? $Object : $obj.__proto__.constructor; |
| - return $getMethodTypeFromType(type, $name); |
| + return $obj == null ? $Object : $obj.__proto__.constructor; |
| })()'''); |
| /// Get the type of a method from a type using the stored signature |
| -getMethodTypeFromType(type, name) => JS( |
|
Jacob
2017/01/21 01:11:30
removed the getMethodType call that used an object
|
| +getMethodType(type, name) => JS( |
| '', |
| '''(() => { |
| let sigObj = $type[$_methodSig]; |
| @@ -190,6 +212,22 @@ getMethodTypeFromType(type, name) => JS( |
| return sigObj[$name]; |
| })()'''); |
| +getFieldType(type, name) => JS( |
| + '', |
| + '''(() => { |
| + let sigObj = $type[$_fieldSig]; |
| + if (sigObj === void 0) return void 0; |
| + return sigObj[$name]; |
| +})()'''); |
| + |
| +getSetterType(type, name) => JS( |
| + '', |
| + '''(() => { |
| + let sigObj = $type[$_setterSig]; |
| + if (sigObj === void 0) return void 0; |
| + return sigObj[$name]; |
| +})()'''); |
| + |
| /// Get the type of a constructor from a class using the stored signature |
| /// If name is undefined, returns the type of the default constructor |
| /// Returns undefined if the constructor is not found. |
| @@ -219,7 +257,7 @@ bind(obj, name, f) => JS( |
| $f = $f.bind($obj); |
| // TODO(jmesserly): track the function's signature on the function, instead |
| // of having to go back to the class? |
| - let sig = $getMethodType($obj, $name); |
| + let sig = $getMethodType($getType($obj), $name); |
| $assert_(sig); |
| $tag($f, sig); |
| return $f; |
| @@ -242,7 +280,9 @@ _setInstanceSignature(f, sigF, kind) => JS( |
| '''(() => { |
| $defineMemoizedGetter($f, $kind, () => { |
| let sigObj = $sigF(); |
| - sigObj.__proto__ = $f.__proto__[$kind]; |
| + let proto = $f.__proto__; |
| + // We need to set the root proto to null not undefined. |
|
Jacob
2017/01/21 01:11:30
This bug resulted in our type metadata looking lik
|
| + sigObj.__proto__ = ($kind in proto) ? proto[$kind] : null; |
| return sigObj; |
| }); |
| })()'''); |
| @@ -330,7 +370,18 @@ setSignature(f, signature) => JS( |
| $_setStaticTypes($f, names); |
| })()'''); |
| -hasMethod(obj, name) => JS('', '$getMethodType($obj, $name) !== void 0'); |
| +_hasSigEntry(type, sigF, name) => JS( |
| + '', |
| + '''(() => { |
| + let sigObj = $type[$sigF]; |
| + if (sigObj === void 0) return false; |
| + return $name in sigObj; |
| +})()'''); |
| + |
| +hasMethod(type, name) => _hasSigEntry(type, _methodSig, name); |
| +hasGetter(type, name) => _hasSigEntry(type, _getterSig, name); |
| +hasSetter(type, name) => _hasSigEntry(type, _setterSig, name); |
| +hasField(type, name) => _hasSigEntry(type, _fieldSig, name); |
| /// Given a class and an initializer method name, creates a constructor |
| /// function with the same name. |
| @@ -431,9 +482,15 @@ registerExtension(jsType, dartExtType) => JS( |
| // Mark the JS type's instances so we can easily check for extensions. |
| jsProto[$_extensionType] = $dartExtType; |
| $_installProperties(jsProto, extProto); |
| - let originalSigFn = $getOwnPropertyDescriptor($dartExtType, $_methodSig).get; |
|
Jacob
2017/01/21 01:11:30
We were forgetting to call updateSig on anything b
|
| - $assert_(originalSigFn); |
| - $defineMemoizedGetter($jsType, $_methodSig, originalSigFn); |
| + function updateSig(sigF) { |
| + let originalSigFn = $getOwnPropertyDescriptor($dartExtType, sigF).get; |
| + $assert_(originalSigFn); |
| + $defineMemoizedGetter($jsType, sigF, originalSigFn); |
| + } |
| + updateSig($_methodSig); |
| + updateSig($_fieldSig); |
| + updateSig($_getterSig); |
| + updateSig($_setterSig); |
| })()'''); |
| /// |
| @@ -469,14 +526,24 @@ defineExtensionMembers(type, methodNames) => JS( |
| // annotations) any time we copy a method as part of our metaprogramming. |
| // It might be more friendly to JS metaprogramming if we include this info |
| // on the function. |
| - let originalSigFn = $getOwnPropertyDescriptor($type, $_methodSig).get; |
| - $defineMemoizedGetter(type, $_methodSig, function() { |
| - let sig = originalSigFn(); |
| - for (let name of $methodNames) { |
| - sig[$getExtensionSymbol(name)] = sig[name]; |
| - } |
| - return sig; |
| - }); |
| + |
| + function upgradeSig(sigF) { |
| + let originalSigFn = $getOwnPropertyDescriptor($type, sigF).get; |
| + $defineMemoizedGetter(type, sigF, function() { |
| + let sig = originalSigFn(); |
| + let propertyNames = Object.getOwnPropertyNames(sig); |
| + for (let name of methodNames) { |
| + if (name in sig) { |
| + sig[$getExtensionSymbol(name)] = sig[name]; |
| + } |
| + } |
| + return sig; |
| + }); |
| + }; |
| + upgradeSig($_methodSig); |
| + upgradeSig($_fieldSig); |
| + upgradeSig($_getterSig); |
| + upgradeSig($_setterSig); |
| })()'''); |
| /// Sets the type of `obj` to be `type` |
| @@ -499,7 +566,9 @@ setBaseClass(derived, base) { |
| /// Like [setBaseClass] but for generic extension types, e.g. `JSArray<E>` |
| setExtensionBaseClass(derived, base) { |
| // Mark the generic type as an extension type and link the prototype objects |
| - return JS('', '''(() => { |
| + return JS( |
| + '', |
| + '''(() => { |
| if ($base) { |
| $derived.prototype[$_extensionType] = $derived; |
| $derived.prototype.__proto__ = $base.prototype |