Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Unified Diff: pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart

Issue 2623053004: Fix noSuchMethod handling of methods that are also extension methods. Fix noSuchMethod handling of … (Closed)
Patch Set: Fix noSuchMethod handling of methods that are also extension methods. Fix noSuchMethod handling of … Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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
« no previous file with comments | « pkg/dev_compiler/test/codegen/single_test.html ('k') | pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698