| 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: () => {
|
| + 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")');
|
| +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(
|
| +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.
|
| + 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;
|
| - $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
|
|
|