Index: pkg/dev_compiler/lib/src/compiler/code_generator.dart |
diff --git a/pkg/dev_compiler/lib/src/compiler/code_generator.dart b/pkg/dev_compiler/lib/src/compiler/code_generator.dart |
index acde51b79004f0ff7831f11b6a09782300014c06..06cf6bce33d9e09975c247feee0ebaa602aa46ec 100644 |
--- a/pkg/dev_compiler/lib/src/compiler/code_generator.dart |
+++ b/pkg/dev_compiler/lib/src/compiler/code_generator.dart |
@@ -175,10 +175,9 @@ class CodeGenerator extends Object |
bool _superAllowed = true; |
- List<JS.TemporaryId> _superHelperSymbols = <JS.TemporaryId>[]; |
- List<JS.Method> _superHelpers = <JS.Method>[]; |
+ final _superHelpers = new Map<String, JS.Method>(); |
- List<TypeParameterType> _typeParamInConst = null; |
+ List<TypeParameterType> _typeParamInConst; |
/// Whether we are currently generating code for the body of a `JS()` call. |
bool _isInForeignJS = false; |
@@ -395,13 +394,20 @@ class CodeGenerator extends Object |
libraryPrefix.addAll(libraryJSName.split('.')); |
} |
+ var original = e; |
+ var variableElement = e; |
+ if (original is PropertyAccessorElement) { |
+ variableElement = original.variable; |
+ if (original.isSynthetic) e = variableElement; |
+ } |
+ |
String elementJSName; |
if (findAnnotation(e, isPublicJSAnnotation) != null) { |
elementJSName = getAnnotationName(e, isPublicJSAnnotation) ?? ''; |
} |
- if (e is TopLevelVariableElement) { |
- elementJSName = _jsInteropStaticMemberName(e); |
+ if (variableElement is TopLevelVariableElement) { |
+ elementJSName = _jsInteropStaticMemberName(original); |
} |
if (elementJSName == null) return null; |
@@ -426,34 +432,31 @@ class CodeGenerator extends Object |
return access; |
} |
- String _jsInteropStaticMemberName(Element e, {String name}) { |
- if (e == null || |
- e.library == null || |
+ String _jsInteropStaticMemberName(Element e) { |
+ if (e?.library == null || |
findAnnotation(e.library, isPublicJSAnnotation) == null) { |
return null; |
} |
- if (e is PropertyInducingElement) { |
- // Assume properties have consistent JS names for getters and setters. |
- return _jsInteropStaticMemberName(e.getter, name: e.name) ?? |
- _jsInteropStaticMemberName(e.setter, name: e.name); |
- } |
if (e is ExecutableElement && e.isExternal) { |
- return getAnnotationName(e, isPublicJSAnnotation) ?? name ?? e.name; |
+ return getAnnotationName(e, isPublicJSAnnotation) ?? |
+ (e is PropertyAccessorElement ? e.variable : e).name; |
+ } |
+ if (e is PropertyInducingElement && e.getter.isExternal) { |
+ return getAnnotationName(e, isPublicJSAnnotation) ?? e.name; |
} |
return null; |
} |
- JS.Expression _emitJSInteropStaticMemberName(Element e) { |
+ String _emitJSInteropStaticMemberName(Element e) { |
var name = _jsInteropStaticMemberName(e); |
- if (name == null) return null; |
// We do not support statics names with JS annotations containing dots. |
// See https://github.com/dart-lang/sdk/issues/27926 |
- if (name.contains('.')) { |
- throw new UnimplementedError( |
+ if (name != null && name.contains('.')) { |
+ throw new UnsupportedError( |
'We do not support JS annotations containing dots on static members. ' |
'See https://github.com/dart-lang/sdk/issues/27926'); |
} |
- return js.string(name); |
+ return name; |
} |
/// Flattens blocks in [items] to a single list. |
@@ -904,7 +907,7 @@ class CodeGenerator extends Object |
var body = <JS.Statement>[]; |
_initExtensionSymbols(classElem, methods, fields, body); |
- _emitSuperHelperSymbols(_superHelperSymbols, body); |
+ _emitSuperHelperSymbols(body); |
// Emit the class, e.g. `core.Object = class Object { ... }` |
_defineClass(classElem, className, classExpr, body); |
@@ -1136,12 +1139,11 @@ class CodeGenerator extends Object |
} |
} |
- void _emitSuperHelperSymbols( |
- List<JS.TemporaryId> superHelperSymbols, List<JS.Statement> body) { |
- for (var id in superHelperSymbols) { |
+ void _emitSuperHelperSymbols(List<JS.Statement> body) { |
+ for (var id in _superHelpers.values.map((m) => m.name as JS.TemporaryId)) { |
body.add(js.statement('const # = Symbol(#)', [id, js.string(id.name)])); |
} |
- superHelperSymbols.clear(); |
+ _superHelpers.clear(); |
} |
void _emitVirtualFieldSymbols( |
@@ -1431,8 +1433,7 @@ class CodeGenerator extends Object |
} |
// Add all of the super helper methods |
- jsMethods.addAll(_superHelpers); |
- _superHelpers.clear(); |
+ jsMethods.addAll(_superHelpers.values); |
return jsMethods.where((m) => m != null).toList(growable: false); |
} |
@@ -2767,7 +2768,7 @@ class CodeGenerator extends Object |
// library member |
if (element.enclosingElement is CompilationUnitElement) { |
- return _emitTopLevelName(element); |
+ return _emitTopLevelName(accessor); |
} |
var name = element.name; |
@@ -2778,7 +2779,7 @@ class CodeGenerator extends Object |
bool isStatic = element.isStatic; |
var type = element.enclosingElement.type; |
var member = _emitMemberName(name, |
- isStatic: isStatic, type: type, element: element); |
+ isStatic: isStatic, type: type, element: accessor); |
if (isStatic) { |
var dynType = _emitStaticAccess(type); |
@@ -2795,7 +2796,7 @@ class CodeGenerator extends Object |
var safeName = _emitMemberName(name, |
isStatic: isStatic, |
type: type, |
- element: element, |
+ element: accessor, |
alwaysSymbolizeNative: true); |
return _callHelper('bind(this, #)', safeName); |
} |
@@ -3183,72 +3184,56 @@ class CodeGenerator extends Object |
return new JS.MetaLet(vars, [_emitSet(lhs, inc)]); |
} |
- JS.Expression _emitSet(Expression lhs, Expression rhs) { |
- if (lhs is IndexExpression) { |
- var target = _getTarget(lhs); |
+ JS.Expression _emitSet(Expression left, Expression right) { |
+ if (left is IndexExpression) { |
+ var target = _getTarget(left); |
if (_useNativeJsIndexer(target.staticType)) { |
- return js |
- .call('#[#] = #', [_visit(target), _visit(lhs.index), _visit(rhs)]); |
+ return js.call( |
+ '#[#] = #', [_visit(target), _visit(left.index), _visit(right)]); |
} |
- return _emitSend(target, '[]=', [lhs.index, rhs]); |
+ return _emitSend(target, '[]=', [left.index, right]); |
} |
- if (lhs is SimpleIdentifier) { |
- return _emitSetSimpleIdentifier(lhs, rhs); |
+ if (left is SimpleIdentifier) { |
+ return _emitSetSimpleIdentifier(left, right); |
} |
Expression target = null; |
SimpleIdentifier id; |
- if (lhs is PropertyAccess) { |
- if (lhs.operator.lexeme == '?.') { |
- return _emitNullSafeSet(lhs, rhs); |
+ if (left is PropertyAccess) { |
+ if (left.operator.lexeme == '?.') { |
+ return _emitNullSafeSet(left, right); |
} |
- target = _getTarget(lhs); |
- id = lhs.propertyName; |
- } else if (lhs is PrefixedIdentifier) { |
- if (isLibraryPrefix(lhs.prefix)) { |
- return _emitSet(lhs.identifier, rhs); |
+ target = _getTarget(left); |
+ id = left.propertyName; |
+ } else if (left is PrefixedIdentifier) { |
+ if (isLibraryPrefix(left.prefix)) { |
+ return _emitSet(left.identifier, right); |
} |
- target = lhs.prefix; |
- id = lhs.identifier; |
+ target = left.prefix; |
+ id = left.identifier; |
} else { |
assert(false); |
} |
- assert(target != null); |
- |
- if (target is SuperExpression) { |
- return _emitSetSuper(lhs, target, id, rhs); |
- } |
- |
- if (target != null && isDynamicInvoke(target)) { |
+ if (isDynamicInvoke(target)) { |
return _callHelper('#(#, #, #)', [ |
_emitDynamicOperationName('dput'), |
_visit(target), |
_emitMemberName(id.name), |
- _visit(rhs) |
+ _visit(right) |
]); |
} |
var accessor = id.staticElement; |
- var element = |
- accessor is PropertyAccessorElement ? accessor.variable : accessor; |
- |
- if (element is ClassMemberElement && element is! ConstructorElement) { |
- bool isStatic = element.isStatic; |
- if (isStatic) { |
- if (element is FieldElement) { |
- return _emitSetStaticProperty(lhs, element, rhs); |
- } |
- return _badAssignment('Unknown static: $element', lhs, rhs); |
- } |
- if (element is FieldElement) { |
- return _emitWriteInstanceProperty( |
- lhs, _visit(target), element, _visit(rhs)); |
+ if (accessor is PropertyAccessorElement) { |
+ var field = accessor.variable; |
+ if (field is FieldElement) { |
+ return _emitSetField(left, right, field, _visit(target)); |
} |
} |
- return _badAssignment('Unhandled assignment', lhs, rhs); |
+ return _badAssignment('Unhandled assignment', left, right); |
} |
JS.Expression _badAssignment(String problem, Expression lhs, Expression rhs) { |
@@ -3263,9 +3248,9 @@ class CodeGenerator extends Object |
/// identifier assignment targets (local, top level library member, implicit |
/// `this` or class, etc.) |
JS.Expression _emitSetSimpleIdentifier( |
- SimpleIdentifier node, Expression rhs) { |
+ SimpleIdentifier node, Expression right) { |
JS.Expression unimplemented() { |
- return _badAssignment("Unimplemented: unknown name '$node'", node, rhs); |
+ return _badAssignment("Unimplemented: unknown name '$node'", node, right); |
} |
var accessor = resolutionMap.staticElementForIdentifier(node); |
@@ -3281,31 +3266,18 @@ class CodeGenerator extends Object |
} |
if (element is LocalVariableElement || element is ParameterElement) { |
- return _emitSetLocal(node, element, rhs); |
+ return _emitSetLocal(node, element, right); |
} |
if (element.enclosingElement is CompilationUnitElement) { |
// Top level library member. |
- return _emitSetTopLevel(node, element, rhs); |
+ return _emitSetTopLevel(node, accessor, right); |
} |
// Unqualified class member. This could mean implicit `this`, or implicit |
// static from the same class. |
- if (element is ClassMemberElement) { |
- bool isStatic = element.isStatic; |
- if (isStatic) { |
- if (element is FieldElement) { |
- return _emitSetStaticProperty(node, element, rhs); |
- } |
- return unimplemented(); |
- } |
- |
- // For instance members, we add implicit-this. |
- if (element is FieldElement) { |
- return _emitWriteInstanceProperty( |
- node, new JS.This(), element, _visit(rhs)); |
- } |
- return unimplemented(); |
+ if (element is FieldElement) { |
+ return _emitSetField(node, right, element, new JS.This()); |
} |
// We should not get here. |
@@ -3331,42 +3303,23 @@ class CodeGenerator extends Object |
/// Emits assignment to library scope element [element]. |
JS.Expression _emitSetTopLevel( |
- Expression lhs, Element element, Expression rhs) { |
+ Expression lhs, PropertyAccessorElement element, Expression rhs) { |
return _visit<JS.Expression>(rhs) |
.toAssignExpression(annotate(_emitTopLevelName(element), lhs)); |
} |
/// Emits assignment to a static field element or property. |
- JS.Expression _emitSetStaticProperty( |
- Expression lhs, Element element, Expression rhs) { |
- // For static methods, we add the raw type name, without generics or |
- // library prefix. We don't need those because static calls can't use |
- // the generic type. |
- ClassElement classElement = element.enclosingElement; |
- var type = classElement.type; |
- var dynType = _emitStaticAccess(type); |
- var member = _emitMemberName(element.name, |
- isStatic: true, type: type, element: element); |
- return _visit<JS.Expression>(rhs).toAssignExpression( |
- annotate(new JS.PropertyAccess(dynType, member), lhs)); |
- } |
- |
- /// Emits an assignment to the [element] property of instance referenced by |
- /// [jsTarget]. |
- JS.Expression _emitWriteInstanceProperty(Expression lhs, |
- JS.Expression jsTarget, Element element, JS.Expression value) { |
- String memberName = element.name; |
- var type = (element.enclosingElement as ClassElement).type; |
- var name = _emitMemberName(memberName, type: type, element: element); |
- return value.toAssignExpression( |
- annotate(new JS.PropertyAccess(jsTarget, name), lhs)); |
- } |
- |
- JS.Expression _emitSetSuper(Expression lhs, SuperExpression target, |
- SimpleIdentifier id, Expression rhs) { |
- // TODO(sra): Determine whether and access helper is required for the |
- // setter. For now fall back on the r-value path. |
- return _visit<JS.Expression>(rhs).toAssignExpression(_visit(lhs)); |
+ JS.Expression _emitSetField(Expression left, Expression right, |
+ FieldElement field, JS.Expression jsTarget) { |
+ var type = field.enclosingElement.type; |
+ var isStatic = field.isStatic; |
+ var member = _emitMemberName(field.name, |
+ isStatic: isStatic, type: type, element: field.setter); |
+ jsTarget = isStatic |
+ ? new JS.PropertyAccess(_emitStaticAccess(type), member) |
+ : _emitTargetAccess(jsTarget, member, field.setter); |
+ return _visit<JS.Expression>(right) |
+ .toAssignExpression(annotate(jsTarget, left)); |
} |
JS.Expression _emitNullSafeSet(PropertyAccess node, Expression right) { |
@@ -3451,75 +3404,78 @@ class CodeGenerator extends Object |
return _emitMethodCall(target, node); |
} |
- JS.Expression _emitMethodCall(Expression target, MethodInvocation node) { |
- var args = _emitArgumentList(node.argumentList); |
- var typeArgs = _emitInvokeTypeArguments(node); |
- |
- if (target is SuperExpression && !_superAllowed) { |
- return _emitSuperHelperCall(typeArgs, args, target, node); |
- } |
- |
- return _emitMethodCallInternal(target, node, args, typeArgs); |
- } |
- |
- JS.Expression _emitSuperHelperCall(List<JS.Expression> typeArgs, |
- List<JS.Expression> args, SuperExpression target, MethodInvocation node) { |
- var fakeTypeArgs = |
- typeArgs?.map((_) => new JS.TemporaryId('a'))?.toList(growable: false); |
- var fakeArgs = |
- args.map((_) => new JS.TemporaryId('a')).toList(growable: false); |
- var combinedFakeArgs = <JS.TemporaryId>[]; |
- if (fakeTypeArgs != null) { |
- combinedFakeArgs.addAll(fakeTypeArgs); |
- } |
- combinedFakeArgs.addAll(fakeArgs); |
- |
- var forwardedCall = |
- _emitMethodCallInternal(target, node, fakeArgs, fakeTypeArgs); |
- var superForwarder = _getSuperHelperFor( |
- node.methodName.name, forwardedCall, combinedFakeArgs); |
- |
- var combinedRealArgs = <JS.Expression>[]; |
- if (typeArgs != null) { |
- combinedRealArgs.addAll(typeArgs); |
- } |
- combinedRealArgs.addAll(args); |
- |
- return js.call('this.#(#)', [superForwarder, combinedRealArgs]); |
- } |
- |
- JS.Expression _getSuperHelperFor(String name, JS.Expression forwardedCall, |
- List<JS.Expression> helperArgs) { |
- var helperMethod = |
- new JS.Fun(helperArgs, new JS.Block([new JS.Return(forwardedCall)])); |
- var helperMethodName = new JS.TemporaryId('super\$$name'); |
- _superHelperSymbols.add(helperMethodName); |
- _superHelpers.add(new JS.Method(helperMethodName, helperMethod)); |
- return helperMethodName; |
- } |
- |
- JS.Expression _emitTarget(Expression target, Element element, bool isStatic) { |
+ JS.Expression _emitTarget(Expression target, Element member, bool isStatic) { |
if (isStatic) { |
- if (element is ConstructorElement) { |
- return _emitConstructorAccess(element.enclosingElement.type); |
+ if (member is ConstructorElement) { |
+ return _emitConstructorAccess(member.enclosingElement.type); |
} |
- if (element is ExecutableElement) { |
- return _emitStaticAccess( |
- (element.enclosingElement as ClassElement).type); |
+ if (member is PropertyAccessorElement) { |
+ var field = member.variable; |
+ if (field is FieldElement) { |
+ return _emitStaticAccess(field.enclosingElement.type); |
+ } |
} |
- if (element is FieldElement) { |
- return _emitStaticAccess(element.enclosingElement.type); |
+ if (member is MethodElement) { |
+ return _emitStaticAccess(member.enclosingElement.type); |
} |
} |
return _visit(target); |
} |
- /// Emits a (possibly generic) instance, or static method call. |
- JS.Expression _emitMethodCallInternal( |
- Expression target, |
- MethodInvocation node, |
- List<JS.Expression> args, |
- List<JS.Expression> typeArgs) { |
+ /// Emits the [JS.PropertyAccess] for accessors or method calls to |
+ /// [jsTarget].[jsName], replacing `super` if it is not allowed in scope. |
+ JS.Expression _emitTargetAccess( |
+ JS.Expression jsTarget, JS.Expression jsName, Element member) { |
+ if (!_superAllowed && jsTarget is JS.Super) { |
+ return _getSuperHelper(member, jsName) |
+ ..sourceInformation = jsTarget.sourceInformation; |
+ } |
+ return new JS.PropertyAccess(jsTarget, jsName); |
+ } |
+ |
+ JS.Expression _getSuperHelper(Element member, JS.Expression jsName) { |
+ var jsMethod = _superHelpers.putIfAbsent(member.name, () { |
+ if (member is PropertyAccessorElement) { |
+ var field = member.variable as FieldElement; |
+ var name = field.name; |
+ var isSetter = member.isSetter; |
+ var fn = js.call( |
+ isSetter |
+ ? 'function(x) { super[#] = x; }' |
+ : 'function() { return super[#]; }', |
+ [jsName]); |
+ return new JS.Method(new JS.TemporaryId(name), fn, |
+ isGetter: !isSetter, isSetter: isSetter); |
+ } else { |
+ var method = member as MethodElement; |
+ var name = method.name; |
+ // For generic methods, we can simply pass along the type arguments, |
+ // and let the resulting closure accept the actual arguments. |
+ List<JS.Identifier> params; |
+ if (method.typeParameters.isNotEmpty) { |
+ params = _emitTypeFormals(method.typeParameters); |
+ } else { |
+ params = []; |
+ for (var param in method.parameters) { |
+ if (param.parameterKind == ParameterKind.NAMED) { |
+ params.add(namedArgumentTemp); |
+ break; |
+ } |
+ params.add(new JS.Identifier(param.name)); |
+ } |
+ } |
+ var fn = js.call( |
+ 'function(#) { return super[#](#); }', [params, jsName, params]); |
+ return new JS.Method(new JS.TemporaryId(name), fn); |
+ } |
+ }); |
+ return new JS.PropertyAccess(new JS.This(), jsMethod.name); |
+ } |
+ |
+ JS.Expression _emitMethodCall(Expression target, MethodInvocation node) { |
+ var args = _emitArgumentList(node.argumentList); |
+ var typeArgs = _emitInvokeTypeArguments(node); |
+ |
var type = getStaticType(target); |
var element = node.methodName.staticElement; |
bool isStatic = element is ExecutableElement && element.isStatic; |
@@ -3546,8 +3502,7 @@ class CodeGenerator extends Object |
assert(typeArgs == null); // Object methods don't take type args. |
return _callHelper('#(#, #)', [name, jsTarget, args]); |
} |
- |
- jsTarget = new JS.PropertyAccess(jsTarget, memberName); |
+ jsTarget = _emitTargetAccess(jsTarget, memberName, element); |
if (typeArgs != null) jsTarget = new JS.Call(jsTarget, typeArgs); |
return new JS.Call(jsTarget, args); |
@@ -3994,12 +3949,9 @@ class CodeGenerator extends Object |
} |
} |
- JS.Expression objExpr; |
- if (target is ClassElement) { |
- objExpr = _emitTopLevelName(target); |
- } else { |
- objExpr = emitLibraryName(target); |
- } |
+ var objExpr = target is ClassElement |
+ ? _emitTopLevelName(target) |
+ : emitLibraryName(target); |
return _callHelperStatement('defineLazy(#, { # });', [objExpr, methods]); |
} |
@@ -4718,7 +4670,7 @@ class CodeGenerator extends Object |
JS.This visitThisExpression(ThisExpression node) => new JS.This(); |
@override |
- JS.Super visitSuperExpression(SuperExpression node) => new JS.Super(); |
+ JS.Expression visitSuperExpression(SuperExpression node) => new JS.Super(); |
@override |
visitPrefixedIdentifier(PrefixedIdentifier node) { |
@@ -4819,35 +4771,6 @@ class CodeGenerator extends Object |
(_extensionTypes.hasNativeSubtype(type) && target is! SuperExpression); |
} |
- /// Shared code for [PrefixedIdentifier] and [PropertyAccess]. |
- JS.Expression _emitAccess( |
- Expression target, SimpleIdentifier memberId, DartType resultType) { |
- Element member = memberId.staticElement; |
- if (member is PropertyAccessorElement) { |
- member = (member as PropertyAccessorElement).variable; |
- } |
- String memberName = memberId.name; |
- var typeArgs = _getTypeArgs(member, resultType); |
- |
- if (target is SuperExpression && !_superAllowed) { |
- return _emitSuperHelperAccess(target, member, memberName, typeArgs); |
- } |
- return _emitAccessInternal(target, member, memberName, typeArgs); |
- } |
- |
- JS.Expression _emitSuperHelperAccess(SuperExpression target, Element member, |
- String memberName, List<JS.Expression> typeArgs) { |
- var fakeTypeArgs = |
- typeArgs?.map((_) => new JS.TemporaryId('a'))?.toList(growable: false); |
- |
- var forwardedAccess = |
- _emitAccessInternal(target, member, memberName, fakeTypeArgs); |
- var superForwarder = _getSuperHelperFor( |
- memberName, forwardedAccess, fakeTypeArgs ?? const []); |
- |
- return js.call('this.#(#)', [superForwarder, typeArgs ?? const []]); |
- } |
- |
List<JS.Expression> _getTypeArgs(Element member, DartType instantiated) { |
DartType type; |
if (member is ExecutableElement) { |
@@ -4861,40 +4784,46 @@ class CodeGenerator extends Object |
return _emitFunctionTypeArguments(type, instantiated); |
} |
- JS.LiteralString _emitDynamicOperationName(String name) => |
- js.string(options.replCompile ? '${name}Repl' : name); |
+ /// Shared code for [PrefixedIdentifier] and [PropertyAccess]. |
+ JS.Expression _emitAccess( |
+ Expression target, SimpleIdentifier memberId, DartType resultType) { |
+ var accessor = memberId.staticElement; |
+ // If `member` is a getter/setter, get the corresponding |
+ var field = |
+ accessor is PropertyAccessorElement ? accessor.variable : accessor; |
+ String memberName = memberId.name; |
+ var typeArgs = _getTypeArgs(accessor, resultType); |
- JS.Expression _emitAccessInternal(Expression target, Element member, |
- String memberName, List<JS.Expression> typeArgs) { |
- bool isStatic = member is ClassMemberElement && member.isStatic; |
+ bool isStatic = field is ClassMemberElement && field.isStatic; |
var name = _emitMemberName(memberName, |
- type: getStaticType(target), isStatic: isStatic, element: member); |
+ type: getStaticType(target), isStatic: isStatic, element: accessor); |
if (isDynamicInvoke(target)) { |
return _callHelper('#(#, #)', |
[_emitDynamicOperationName('dload'), _visit(target), name]); |
} |
- var jsTarget = _emitTarget(target, member, isStatic); |
- bool isSuper = jsTarget is JS.Super; |
+ var jsTarget = _emitTarget(target, accessor, isStatic); |
+ |
+ var isSuper = jsTarget is JS.Super; |
if (isSuper && |
- !member.isSynthetic && |
- member is FieldElementImpl && |
- !virtualFields.isVirtual(member)) { |
+ accessor.isSynthetic && |
+ field is FieldElementImpl && |
+ !virtualFields.isVirtual(field)) { |
// If super.x is a sealed field, then x is an instance property since |
// subclasses cannot override x. |
- jsTarget = new JS.This(); |
+ jsTarget = annotate(new JS.This(), target); |
} |
JS.Expression result; |
- if (member != null && member is MethodElement && !isStatic) { |
+ if (accessor is MethodElement && !isStatic) { |
// Tear-off methods: explicitly bind it. |
// To be safe always use the symbolized name when binding on a native |
- // class as bind assumes the name will match the name class sigatures |
+ // class as bind assumes the name will match the name class signatures |
// which is symbolized for native classes. |
var safeName = _emitMemberName(memberName, |
type: getStaticType(target), |
isStatic: isStatic, |
- element: member, |
+ element: accessor, |
alwaysSymbolizeNative: true); |
if (isSuper) { |
result = |
@@ -4908,7 +4837,7 @@ class CodeGenerator extends Object |
} else if (_isObjectMemberCall(target, memberName)) { |
result = _callHelper('#(#)', [memberName, jsTarget]); |
} else { |
- result = js.call('#.#', [jsTarget, name]); |
+ result = _emitTargetAccess(jsTarget, name, accessor); |
} |
if (typeArgs == null) { |
return result; |
@@ -4916,6 +4845,9 @@ class CodeGenerator extends Object |
return _callHelper('gbind(#, #)', [result, typeArgs]); |
} |
+ JS.LiteralString _emitDynamicOperationName(String name) => |
+ js.string(options.replCompile ? '${name}Repl' : name); |
+ |
/// Emits a generic send, like an operator method. |
/// |
/// **Please note** this function does not support method invocation syntax |
@@ -5487,7 +5419,7 @@ class CodeGenerator extends Object |
Element element}) { |
// Static members skip the rename steps and may require JS interop renames. |
if (isStatic) { |
- return _emitJSInteropStaticMemberName(element) ?? _propertyName(name); |
+ return _propertyName(_emitJSInteropStaticMemberName(element) ?? name); |
} |
if (name.startsWith('_')) { |