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

Unified Diff: pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart

Issue 1431523002: Fix behavior when typed JS interop getters are called as functions. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: PTAL Created 5 years, 2 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
« no previous file with comments | « no previous file | tests/html/html.status » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index 5f5543926f33ac58d5bc4687c708fa304cfcba9e..9471cac584dc5366edb071db14adff70c8a67242 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -30,7 +30,9 @@ import '../../constants/values.dart' show
import '../../core_types.dart' show
CoreClasses;
import '../../dart_types.dart' show
- DartType;
+ DartType,
+ FunctionType,
+ TypedefType;
import '../../elements/elements.dart' show
ClassElement,
Element,
@@ -38,6 +40,7 @@ import '../../elements/elements.dart' show
FieldElement,
FunctionElement,
FunctionSignature,
+ GetterElement,
LibraryElement,
MethodElement,
Name,
@@ -407,10 +410,50 @@ class ProgramBuilder {
}
}
+ // Generating stubs for direct calls and stubs for call-through
+ // of getters that happen to be functions.
+ bool isFunctionLike = false;
+ FunctionType functionType = null;
+
if (member.isFunction) {
+ FunctionElement fn = member;
+ functionType = fn.type;
+ } else if (member.isGetter) {
+ if (_compiler.trustTypeAnnotations) {
+ GetterElement getter = member;
+ DartType returnType = getter.type.returnType;
+ if (returnType.isFunctionType) {
+ functionType = returnType;
+ } else if (returnType.treatAsDynamic ||
+ _compiler.types.isSubtype(returnType,
+ backend.coreTypes.functionType)) {
+ if (returnType.isTypedef) {
+ TypedefType typedef = returnType;
+ // TODO(jacobr): can we just use typdef.unaliased instead?
+ functionType = typedef.element.functionSignature.type;
+ } else {
+ // Other misc function type such as coreTypes.Function.
+ // Allow any number of arguments.
+ isFunctionLike = true;
+ }
+ }
+ } else {
+ isFunctionLike = true;
+ }
+ } // TODO(jacobr): handle field elements.
+
+ if (isFunctionLike || functionType != null) {
+ int minArgs;
+ int maxArgs;
+ if (functionType != null) {
+ minArgs = functionType.parameterTypes.length;
+ maxArgs = minArgs + functionType.optionalParameterTypes.length;
+ } else {
+ minArgs = 0;
+ maxArgs = 32767;
+ }
var selectors =
_compiler.codegenWorld.invocationsByName(member.name);
- FunctionElement fn = member;
// Named arguments are not yet supported. In the future we
// may want to map named arguments to an object literal containing
// all named arguments.
@@ -418,16 +461,23 @@ class ProgramBuilder {
for (var selector in selectors.keys) {
// Check whether the arity matches this member.
var argumentCount = selector.argumentCount;
- if (argumentCount > fn.parameters.length) break;
- if (argumentCount < fn.parameters.length &&
- !fn.parameters[argumentCount].isOptional) break;
+ // JS interop does not support named arguments.
+ if (selector.namedArgumentCount > 0) break;
+ if (argumentCount < minArgs) break;
+ if (argumentCount > maxArgs) break;
var stubName = namer.invocationName(selector);
if (!stubNames.add(stubName.key)) break;
- var candidateParameterNames =
- 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLOMOPQRSTUVWXYZ';
var parameters = new List<String>.generate(argumentCount,
- (i) => candidateParameterNames[i]);
-
+ (i) => 'p$i');
+
+ // We intentionally generate the same stub method for direct
+ // calls and call-throughs of getters so that calling a
+ // getter that returns a function behaves the same as calling
+ // a method. This is helpful as many typed JavaScript APIs
+ // specify member functions with getters that return
+ // functions. The behavior of this solution matches JavaScript
+ // behavior implicitly binding this only when JavaScript
+ // would.
interceptorClass.callStubs.add(_buildStubMethod(
stubName,
js.js('function(receiver, #) { return receiver.#(#) }',
« no previous file with comments | « no previous file | tests/html/html.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698