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

Unified Diff: lib/src/compiler/code_generator.dart

Issue 2069903002: Partial fix for call methods #542 (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: fix Created 4 years, 6 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 | « lib/runtime/dart_sdk.js ('k') | test/browser/language_tests.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/src/compiler/code_generator.dart
diff --git a/lib/src/compiler/code_generator.dart b/lib/src/compiler/code_generator.dart
index d0bdf2043190b9a91a642c7f84ea0751b1be688b..2c5a906696277ea986bef981bb02007e828914a1 100644
--- a/lib/src/compiler/code_generator.dart
+++ b/lib/src/compiler/code_generator.dart
@@ -701,6 +701,7 @@ class CodeGenerator extends GeneralizingAstVisitor
var fields = <FieldDeclaration>[];
var staticFields = <FieldDeclaration>[];
var methods = <MethodDeclaration>[];
+ bool isCallable = false;
for (var member in node.members) {
if (member is ConstructorDeclaration) {
ctors.add(member);
@@ -708,6 +709,11 @@ class CodeGenerator extends GeneralizingAstVisitor
(member.isStatic ? staticFields : fields).add(member);
} else if (member is MethodDeclaration) {
methods.add(member);
+ if (member.name.name == 'call' &&
+ !member.isGetter &&
+ !member.isSetter) {
vsm 2016/06/15 15:23:25 Per spec / VM, 'call' could be a getter or field.
Jennifer Messerly 2016/06/15 16:50:32 Oh crazy... it felt like some of the tests seem to
+ isCallable = true;
+ }
}
}
@@ -738,7 +744,7 @@ class CodeGenerator extends GeneralizingAstVisitor
_emitSuperHelperSymbols(_superHelperSymbols, body);
// Emit the class, e.g. `core.Object = class Object { ... }`
- _defineClass(classElem, className, classExpr, body);
+ _defineClass(classElem, className, classExpr, isCallable, body);
// Emit things that come after the ES6 `class ... { ... }`.
var jsPeerName = _getJSPeerName(classElem);
@@ -746,7 +752,7 @@ class CodeGenerator extends GeneralizingAstVisitor
_emitClassTypeTests(classElem, className, body);
- _defineNamedConstructors(ctors, body, className);
+ _defineNamedConstructors(ctors, body, className, isCallable);
_emitVirtualFieldSymbols(virtualFieldSymbols, body);
_emitClassSignature(methods, classElem, ctors, extensions, className, body);
_defineExtensionMembers(extensions, className, body);
@@ -764,6 +770,23 @@ class CodeGenerator extends GeneralizingAstVisitor
return _statement(body);
}
+ /// Emits code to support a class with a "call" method and an unnamed
+ /// constructor.
+ ///
+ /// This ensures instances created by the unnamed constructor are functions.
+ /// Named constructors are handled elsewhere, see [_defineNamedConstructors].
+ JS.Expression _emitCallableClass(JS.ClassExpression classExpr) {
+ var newClassExpr = js.call(r'''function (...args) {
+ let call = this.call.bind(this);
+ call.__proto__ = this.__proto__;
+ call.new.apply(call, args);
+ return call;
+ }''');
+ // Name the constructor function the same as the class.
+ return js.call('dart.callableClass(#, #)',
+ [new JS.NamedFunction(classExpr.name, newClassExpr), classExpr]);
+ }
+
void _emitClassTypeTests(ClassElement classElem, JS.Expression className,
List<JS.Statement> body) {
if (classElem == objectClass) {
@@ -979,11 +1002,19 @@ class CodeGenerator extends GeneralizingAstVisitor
}
void _defineClass(ClassElement classElem, JS.Expression className,
- JS.ClassExpression classExpr, List<JS.Statement> body) {
+ JS.ClassExpression classExpr, bool isCallable, List<JS.Statement> body) {
+ bool isCallableUnnamed = isCallable && classElem.unnamedConstructor != null;
+
if (classElem.typeParameters.isNotEmpty) {
- body.add(new JS.ClassDeclaration(classExpr));
+ if (isCallableUnnamed) {
+ body.add(js.statement(
+ 'const # = #;', [classExpr.name, _emitCallableClass(classExpr)]));
+ } else {
+ body.add(new JS.ClassDeclaration(classExpr));
+ }
} else {
- body.add(js.statement('# = #;', [className, classExpr]));
+ var expr = isCallableUnnamed ? _emitCallableClass(classExpr) : classExpr;
+ body.add(js.statement('# = #;', [className, expr]));
}
}
@@ -1401,11 +1432,15 @@ class CodeGenerator extends GeneralizingAstVisitor
}
void _defineNamedConstructors(List<ConstructorDeclaration> ctors,
- List<JS.Statement> body, JS.Expression className) {
+ List<JS.Statement> body, JS.Expression className, bool isCallable) {
+ var runtimeHelper = isCallable
+ ? 'defineNamedConstructorCallable'
+ : 'defineNamedConstructor';
+
for (ConstructorDeclaration member in ctors) {
if (member.name != null && member.factoryKeyword == null) {
- body.add(js.statement('dart.defineNamedConstructor(#, #);',
- [className, _constructorName(member.element)]));
+ body.add(js.statement('dart.#(#, #);',
+ [runtimeHelper, className, _constructorName(member.element)]));
}
}
}
« no previous file with comments | « lib/runtime/dart_sdk.js ('k') | test/browser/language_tests.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698