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

Side by Side 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, 1 month 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 unified diff | Download patch
« no previous file with comments | « no previous file | tests/html/html.status » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library dart2js.js_emitter.program_builder; 5 library dart2js.js_emitter.program_builder;
6 6
7 import '../js_emitter.dart' show 7 import '../js_emitter.dart' show
8 ClassStubGenerator, 8 ClassStubGenerator,
9 CodeEmitterTask, 9 CodeEmitterTask,
10 computeMixinClass, 10 computeMixinClass,
(...skipping 12 matching lines...) Expand all
23 Names, 23 Names,
24 Selectors; 24 Selectors;
25 import '../../compiler.dart' show 25 import '../../compiler.dart' show
26 Compiler; 26 Compiler;
27 import '../../constants/values.dart' show 27 import '../../constants/values.dart' show
28 ConstantValue, 28 ConstantValue,
29 InterceptorConstantValue; 29 InterceptorConstantValue;
30 import '../../core_types.dart' show 30 import '../../core_types.dart' show
31 CoreClasses; 31 CoreClasses;
32 import '../../dart_types.dart' show 32 import '../../dart_types.dart' show
33 DartType; 33 DartType,
34 FunctionType,
35 TypedefType;
34 import '../../elements/elements.dart' show 36 import '../../elements/elements.dart' show
35 ClassElement, 37 ClassElement,
36 Element, 38 Element,
37 Elements, 39 Elements,
38 FieldElement, 40 FieldElement,
39 FunctionElement, 41 FunctionElement,
40 FunctionSignature, 42 FunctionSignature,
43 GetterElement,
41 LibraryElement, 44 LibraryElement,
42 MethodElement, 45 MethodElement,
43 Name, 46 Name,
44 ParameterElement, 47 ParameterElement,
45 TypedefElement, 48 TypedefElement,
46 VariableElement; 49 VariableElement;
47 import '../../js/js.dart' as js; 50 import '../../js/js.dart' as js;
48 import '../../js_backend/backend_helpers.dart' show 51 import '../../js_backend/backend_helpers.dart' show
49 BackendHelpers; 52 BackendHelpers;
50 import '../../js_backend/js_backend.dart' show 53 import '../../js_backend/js_backend.dart' show
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 if (stubNames.add(stubName.key)) { 403 if (stubNames.add(stubName.key)) {
401 interceptorClass.callStubs.add(_buildStubMethod( 404 interceptorClass.callStubs.add(_buildStubMethod(
402 stubName, 405 stubName,
403 js.js('function(obj, v) { return obj.# = v }', 406 js.js('function(obj, v) { return obj.# = v }',
404 [member.name]), 407 [member.name]),
405 element: member)); 408 element: member));
406 } 409 }
407 } 410 }
408 } 411 }
409 412
413 // Generating stubs for direct calls and stubs for call-through
414 // of getters that happen to be functions.
415 bool isFunctionLike = false;
416 FunctionType functionType = null;
417
410 if (member.isFunction) { 418 if (member.isFunction) {
419 FunctionElement fn = member;
420 functionType = fn.type;
421 } else if (member.isGetter) {
422 if (_compiler.trustTypeAnnotations) {
423 GetterElement getter = member;
424 DartType returnType = getter.type.returnType;
425 if (returnType.isFunctionType) {
426 functionType = returnType;
427 } else if (returnType.treatAsDynamic ||
428 _compiler.types.isSubtype(returnType,
429 backend.coreTypes.functionType)) {
430 if (returnType.isTypedef) {
431 TypedefType typedef = returnType;
432 // TODO(jacobr): can we just use typdef.unaliased instead?
433 functionType = typedef.element.functionSignature.type;
434 } else {
435 // Other misc function type such as coreTypes.Function.
436 // Allow any number of arguments.
437 isFunctionLike = true;
438 }
439 }
440 } else {
441 isFunctionLike = true;
442 }
443 } // TODO(jacobr): handle field elements.
444
445 if (isFunctionLike || functionType != null) {
446 int minArgs;
447 int maxArgs;
448 if (functionType != null) {
449 minArgs = functionType.parameterTypes.length;
450 maxArgs = minArgs + functionType.optionalParameterTypes.length;
451 } else {
452 minArgs = 0;
453 maxArgs = 32767;
454 }
411 var selectors = 455 var selectors =
412 _compiler.codegenWorld.invocationsByName(member.name); 456 _compiler.codegenWorld.invocationsByName(member.name);
413 FunctionElement fn = member;
414 // Named arguments are not yet supported. In the future we 457 // Named arguments are not yet supported. In the future we
415 // may want to map named arguments to an object literal containing 458 // may want to map named arguments to an object literal containing
416 // all named arguments. 459 // all named arguments.
417 if (selectors != null && !selectors.isEmpty) { 460 if (selectors != null && !selectors.isEmpty) {
418 for (var selector in selectors.keys) { 461 for (var selector in selectors.keys) {
419 // Check whether the arity matches this member. 462 // Check whether the arity matches this member.
420 var argumentCount = selector.argumentCount; 463 var argumentCount = selector.argumentCount;
421 if (argumentCount > fn.parameters.length) break; 464 // JS interop does not support named arguments.
422 if (argumentCount < fn.parameters.length && 465 if (selector.namedArgumentCount > 0) break;
423 !fn.parameters[argumentCount].isOptional) break; 466 if (argumentCount < minArgs) break;
467 if (argumentCount > maxArgs) break;
424 var stubName = namer.invocationName(selector); 468 var stubName = namer.invocationName(selector);
425 if (!stubNames.add(stubName.key)) break; 469 if (!stubNames.add(stubName.key)) break;
426 var candidateParameterNames =
427 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLOMOPQRSTUVWXYZ';
428 var parameters = new List<String>.generate(argumentCount, 470 var parameters = new List<String>.generate(argumentCount,
429 (i) => candidateParameterNames[i]); 471 (i) => 'p$i');
430 472
473 // We intentionally generate the same stub method for direct
474 // calls and call-throughs of getters so that calling a
475 // getter that returns a function behaves the same as calling
476 // a method. This is helpful as many typed JavaScript APIs
477 // specify member functions with getters that return
478 // functions. The behavior of this solution matches JavaScript
479 // behavior implicitly binding this only when JavaScript
480 // would.
431 interceptorClass.callStubs.add(_buildStubMethod( 481 interceptorClass.callStubs.add(_buildStubMethod(
432 stubName, 482 stubName,
433 js.js('function(receiver, #) { return receiver.#(#) }', 483 js.js('function(receiver, #) { return receiver.#(#) }',
434 [parameters, member.name, parameters]), 484 [parameters, member.name, parameters]),
435 element: member)); 485 element: member));
436 } 486 }
437 } 487 }
438 } 488 }
439 }); 489 });
440 } 490 }
(...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after
964 Constant constant = new Constant(name, holder, constantValue); 1014 Constant constant = new Constant(name, holder, constantValue);
965 _constants[constantValue] = constant; 1015 _constants[constantValue] = constant;
966 } 1016 }
967 } 1017 }
968 1018
969 Holder _registerStaticStateHolder() { 1019 Holder _registerStaticStateHolder() {
970 return _registry.registerHolder( 1020 return _registry.registerHolder(
971 namer.staticStateHolder, isStaticStateHolder: true); 1021 namer.staticStateHolder, isStaticStateHolder: true);
972 } 1022 }
973 } 1023 }
OLDNEW
« 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