| Index: lib/src/codegen/js_codegen.dart
|
| diff --git a/lib/src/codegen/js_codegen.dart b/lib/src/codegen/js_codegen.dart
|
| index a4e3c60ce577433dc4d86e18af80e6ae9988bb8c..6ac84ed451de2d5dd97a1ab51668701a16716b50 100644
|
| --- a/lib/src/codegen/js_codegen.dart
|
| +++ b/lib/src/codegen/js_codegen.dart
|
| @@ -2,6 +2,8 @@
|
| // for details. All rights reserved. Use of this source code is governed by a
|
| // BSD-style license that can be found in the LICENSE file.
|
|
|
| +library js_codegen;
|
| +
|
| import 'dart:collection' show HashSet, HashMap, SplayTreeSet;
|
|
|
| import 'package:analyzer/analyzer.dart' hide ConstantEvaluator;
|
| @@ -41,6 +43,8 @@ import 'module_builder.dart';
|
| import 'nullability_inferrer.dart';
|
| import 'side_effect_analysis.dart';
|
|
|
| +part 'js_typeref_codegen.dart';
|
| +
|
| // Various dynamic helpers we call.
|
| // If renaming these, make sure to check other places like the
|
| // _runtime.js file and comments.
|
| @@ -53,7 +57,8 @@ const DSETINDEX = 'dsetindex';
|
| const DCALL = 'dcall';
|
| const DSEND = 'dsend';
|
|
|
| -class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| +class JSCodegenVisitor extends GeneralizingAstVisitor
|
| + with ClosureAnnotator, JsTypeRefCodegen {
|
| final AbstractCompiler compiler;
|
| final CodegenOptions options;
|
| final LibraryElement currentLibrary;
|
| @@ -348,12 +353,13 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| var type = element.type;
|
| var name = element.name;
|
|
|
| - var fnType = annotateTypeDef(
|
| + var fnType = annotate(
|
| js.statement('const # = dart.typedef(#, () => #);', [
|
| name,
|
| js.string(name, "'"),
|
| _emitTypeName(type, lowerTypedef: true)
|
| ]),
|
| + node,
|
| node.element);
|
|
|
| return _finishClassDef(type, fnType);
|
| @@ -423,8 +429,12 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| }
|
| }
|
|
|
| - var classExpr = new JS.ClassExpression(new JS.Identifier(type.name),
|
| - _classHeritage(classElem), _emitClassMethods(node, ctors, fields));
|
| + var classExpr = new JS.ClassExpression(
|
| + new JS.Identifier(type.name),
|
| + _classHeritage(classElem),
|
| + _emitClassMethods(node, ctors, fields),
|
| + _emitTypeArgs(classElem).toList(),
|
| + _emitFieldDeclarations(classElem, fields, staticFields).toList());
|
|
|
| String jsPeerName;
|
| var jsPeer = findAnnotation(classElem, isJsPeerInterface);
|
| @@ -457,6 +467,39 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| return result;
|
| }
|
|
|
| + Iterable<JS.Identifier> _emitTypeArgs(TypeParameterizedElement e) sync* {
|
| + if (!options.closure) return;
|
| + for (var typeParam in e.typeParameters) {
|
| + yield new JS.Identifier(typeParam.name);
|
| + }
|
| + }
|
| +
|
| + /// Emit field declarations for TypeScript & Closure's ES6_TYPED
|
| + /// (e.g. `class Foo { i: string; }`)
|
| + Iterable<JS.VariableDeclarationList> _emitFieldDeclarations(
|
| + ClassElement classElem,
|
| + List<FieldDeclaration> fields,
|
| + List<FieldDeclaration> staticFields) sync* {
|
| + if (!options.closure) return;
|
| +
|
| + makeInitialization(VariableDeclaration decl) =>
|
| + new JS.VariableInitialization(
|
| + new JS.Identifier(
|
| + // TODO(ochafik): use a refactored _emitMemberName instead.
|
| + decl.name.name,
|
| + type: emitTypeRef(decl.element.type)),
|
| + null);
|
| +
|
| + for (var field in fields) {
|
| + yield new JS.VariableDeclarationList(
|
| + null, field.fields.variables.map(makeInitialization).toList());
|
| + }
|
| + for (var field in staticFields) {
|
| + yield new JS.VariableDeclarationList(
|
| + 'static', field.fields.variables.map(makeInitialization).toList());
|
| + }
|
| + }
|
| +
|
| @override
|
| JS.Statement visitEnumDeclaration(EnumDeclaration node) {
|
| var element = node.element;
|
| @@ -689,8 +732,8 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| var superVar = new JS.TemporaryId(cls.name.name + r'$super');
|
| return _statement([
|
| js.statement('const # = #;', [superVar, cls.heritage]),
|
| - new JS.ClassDeclaration(
|
| - new JS.ClassExpression(cls.name, superVar, cls.methods))
|
| + new JS.ClassDeclaration(new JS.ClassExpression(
|
| + cls.name, superVar, cls.methods, cls.typeArgs, cls.fields))
|
| ]);
|
| }
|
| return new JS.ClassDeclaration(cls);
|
| @@ -935,8 +978,9 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| ];
|
| }
|
| var name = _constructorName(node.element.unnamedConstructor);
|
| - return annotateDefaultConstructor(
|
| + return annotate(
|
| new JS.Method(name, js.call('function() { #; }', body) as JS.Fun),
|
| + node,
|
| node.element);
|
| }
|
|
|
| @@ -945,6 +989,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| if (_externalOrNative(node)) return null;
|
|
|
| var name = _constructorName(node.element);
|
| + var returnType = emitTypeRef(node.element.enclosingElement.type);
|
|
|
| // Wacky factory redirecting constructors: factory Foo.q(x, y) = Bar.baz;
|
| var redirect = node.redirectedConstructor;
|
| @@ -956,11 +1001,13 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| var params =
|
| _emitFormalParameterList(node.parameters, allowDestructuring: false);
|
|
|
| - var fun = js.call('function(#) { return $newKeyword #(#); }',
|
| - [params, _visit(redirect), params]) as JS.Fun;
|
| + var fun = new JS.Fun(
|
| + params,
|
| + js.statement(
|
| + '{ return $newKeyword #(#); }', [_visit(redirect), params]),
|
| + returnType: returnType);
|
| return annotate(
|
| - new JS.Method(name, fun, isStatic: true)..sourceInformation = node,
|
| - node.element);
|
| + new JS.Method(name, fun, isStatic: true), node, node.element);
|
| }
|
|
|
| // Factory constructors are essentially static methods.
|
| @@ -970,10 +1017,10 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| if (init != null) body.add(init);
|
| body.add(_visit(node.body));
|
| var fun = new JS.Fun(
|
| - _visit(node.parameters) as List<JS.Parameter>, new JS.Block(body));
|
| + _visit(node.parameters) as List<JS.Parameter>, new JS.Block(body),
|
| + returnType: returnType);
|
| return annotate(
|
| - new JS.Method(name, fun, isStatic: true)..sourceInformation = node,
|
| - node.element);
|
| + new JS.Method(name, fun, isStatic: true), node, node.element);
|
| }
|
|
|
| // Code generation for Object's constructor.
|
| @@ -1009,9 +1056,11 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| // this allows use of `super` for instance methods/properties.
|
| // It also avoids V8 restrictions on `super` in default constructors.
|
| return annotate(
|
| - new JS.Method(name,
|
| - new JS.Fun(_visit(node.parameters) as List<JS.Parameter>, body))
|
| - ..sourceInformation = node,
|
| + new JS.Method(
|
| + name,
|
| + new JS.Fun(_visit(node.parameters) as List<JS.Parameter>, body,
|
| + returnType: returnType)),
|
| + node,
|
| node.element);
|
| }
|
|
|
| @@ -1108,7 +1157,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
|
|
| var name = _constructorName(superCtor);
|
| var args = node != null ? _visit(node.argumentList) : [];
|
| - return js.statement('super.#(#);', [name, args])..sourceInformation = node;
|
| + return annotate(js.statement('super.#(#);', [name, args]), node);
|
| }
|
|
|
| bool _shouldCallUnnamedSuperCtor(ClassElement e) {
|
| @@ -1160,7 +1209,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| for (var p in ctor.parameters.parameters) {
|
| var element = p.element;
|
| if (element is FieldFormalParameterElement) {
|
| - fields[element.field] = _visit(p);
|
| + fields[element.field] = _emitFormalParameter(p, allowType: false);
|
| }
|
| }
|
|
|
| @@ -1216,12 +1265,13 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| var parameters = _parametersOf(node);
|
| if (parameters == null) return null;
|
|
|
| + var destructure = _canDestructureParams(parameters);
|
| var body = <JS.Statement>[];
|
| for (var param in parameters.parameters) {
|
| - var jsParam = _visit(param.identifier);
|
| + var jsParam = _emitSimpleIdentifier(param.identifier, allowType: false);
|
|
|
| if (param.kind == ParameterKind.NAMED) {
|
| - if (!_isDestructurableNamedParam(param)) {
|
| + if (!destructure) {
|
| // Parameters will be passed using their real names, not the (possibly
|
| // renamed) local variable.
|
| var paramName = js.string(param.identifier.name, "'");
|
| @@ -1276,7 +1326,9 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| var params = _visit(node.parameters) as List<JS.Parameter>;
|
| if (params == null) params = <JS.Parameter>[];
|
|
|
| - JS.Fun fn = _emitFunctionBody(params, node.body);
|
| + var typeArgs = _emitTypeArgs(node.element).toList();
|
| + var returnType = emitTypeRef(node.element.returnType);
|
| + JS.Fun fn = _emitFunctionBody(params, node.body, typeArgs, returnType);
|
| if (node.operatorKeyword != null &&
|
| node.name.name == '[]=' &&
|
| params.isNotEmpty) {
|
| @@ -1292,8 +1344,9 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| body = new JS.Call(new JS.ArrowFun([], fn.body), []).toStatement();
|
| }
|
| // Rewrite the function to include the return.
|
| - fn = new JS.Fun(fn.params, new JS.Block([body, returnValue]))
|
| - ..sourceInformation = fn.sourceInformation;
|
| + fn = new JS.Fun(fn.params, new JS.Block([body, returnValue]),
|
| + typeArgs: fn.typeArgs,
|
| + returnType: fn.returnType)..sourceInformation = fn.sourceInformation;
|
| }
|
|
|
| return annotate(
|
| @@ -1301,6 +1354,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| isGetter: node.isGetter,
|
| isSetter: node.isSetter,
|
| isStatic: node.isStatic),
|
| + node,
|
| node.element);
|
| }
|
|
|
| @@ -1308,7 +1362,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| /// the SDK), or `null` if there's none. This is used to control the name
|
| /// under which functions are compiled and exported.
|
| String _getJSExportName(Element e) {
|
| - if (!currentLibrary.source.isInSystemLibrary) {
|
| + if (!e.source.isInSystemLibrary) {
|
| return null;
|
| }
|
| var jsName = findAnnotation(e, isJSExportNameAnnotation);
|
| @@ -1340,7 +1394,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| }
|
|
|
| var id = new JS.Identifier(name);
|
| - body.add(annotate(new JS.FunctionDeclaration(id, fn), node.element));
|
| + body.add(annotate(new JS.FunctionDeclaration(id, fn), node, node.element));
|
| if (!_isDartRuntime) {
|
| body.add(_emitFunctionTagged(id, node.element.type, topLevel: true)
|
| .toStatement());
|
| @@ -1381,7 +1435,8 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| if (call.target is JS.ArrowFun && call.arguments.isEmpty) {
|
| JS.ArrowFun innerFun = call.target;
|
| if (innerFun.params.isEmpty) {
|
| - return new JS.Fun(fn.params, innerFun.body);
|
| + return new JS.Fun(fn.params, innerFun.body,
|
| + typeArgs: fn.typeArgs, returnType: fn.returnType);
|
| }
|
| }
|
| }
|
| @@ -1394,6 +1449,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| return annotate(
|
| new JS.Method(_propertyName(name), _visit(node.functionExpression),
|
| isGetter: node.isGetter, isSetter: node.isSetter),
|
| + node,
|
| node.element);
|
| }
|
|
|
| @@ -1446,8 +1502,10 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
|
|
| var parent = node.parent;
|
| var inStmt = parent.parent is FunctionDeclarationStatement;
|
| + var typeArgs = _emitTypeArgs(node.element).toList();
|
| + var returnType = emitTypeRef(node.element.returnType);
|
| if (parent is FunctionDeclaration) {
|
| - return _emitFunctionBody(params, node.body);
|
| + return _emitFunctionBody(params, node.body, typeArgs, returnType);
|
| } else {
|
| // Chrome Canary does not accept default values with destructuring in
|
| // arrow functions yet (e.g. `({a} = {}) => 1`) but happily accepts them
|
| @@ -1456,18 +1514,23 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| // TODO(ochafik): Simplify this code when Chrome Canary catches up.
|
| var canUseArrowFun = !node.parameters.parameters.any(_isNamedParam);
|
|
|
| - String code = canUseArrowFun ? '(#) => #' : 'function(#) { return # }';
|
| JS.Node jsBody;
|
| var body = node.body;
|
| if (body.isGenerator || body.isAsynchronous) {
|
| - jsBody = _emitGeneratorFunctionBody(params, body);
|
| + jsBody = _emitGeneratorFunctionBody(params, body, returnType);
|
| } else if (body is ExpressionFunctionBody) {
|
| jsBody = _visit(body.expression);
|
| } else {
|
| - code = canUseArrowFun ? '(#) => { #; }' : 'function(#) { #; }';
|
| jsBody = _visit(body);
|
| }
|
| - var clos = js.call(code, [params, jsBody]);
|
| + if (jsBody is JS.Expression && !canUseArrowFun) {
|
| + jsBody = js.statement("{ return #; }", [jsBody]);
|
| + }
|
| + var clos = canUseArrowFun
|
| + ? new JS.ArrowFun(params, jsBody,
|
| + typeArgs: typeArgs, returnType: returnType)
|
| + : new JS.Fun(params, jsBody,
|
| + typeArgs: typeArgs, returnType: returnType);
|
| if (!inStmt) {
|
| var type = getStaticType(node);
|
| return _emitFunctionTagged(clos, type,
|
| @@ -1477,20 +1540,23 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| }
|
| }
|
|
|
| - JS.Fun _emitFunctionBody(List<JS.Parameter> params, FunctionBody body) {
|
| + JS.Fun _emitFunctionBody(List<JS.Parameter> params, FunctionBody body,
|
| + List<JS.Identifier> typeArgs, JS.TypeRef returnType) {
|
| // sync*, async, async*
|
| if (body.isAsynchronous || body.isGenerator) {
|
| return new JS.Fun(
|
| params,
|
| - js.statement(
|
| - '{ return #; }', [_emitGeneratorFunctionBody(params, body)]));
|
| + js.statement('{ return #; }',
|
| + [_emitGeneratorFunctionBody(params, body, returnType)]),
|
| + returnType: returnType);
|
| }
|
| // normal function (sync)
|
| - return new JS.Fun(params, _visit(body));
|
| + return new JS.Fun(params, _visit(body),
|
| + typeArgs: typeArgs, returnType: returnType);
|
| }
|
|
|
| JS.Expression _emitGeneratorFunctionBody(
|
| - List<JS.Parameter> params, FunctionBody body) {
|
| + List<JS.Parameter> params, FunctionBody body, JS.TypeRef returnType) {
|
| var kind = body.isSynchronous ? 'sync' : 'async';
|
| if (body.isGenerator) kind += 'Star';
|
|
|
| @@ -1534,7 +1600,8 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| _asyncStarController = null;
|
| jsParams = params;
|
| }
|
| - JS.Expression gen = new JS.Fun(jsParams, _visit(body), isGenerator: true);
|
| + JS.Expression gen = new JS.Fun(jsParams, _visit(body),
|
| + isGenerator: true, returnType: returnType);
|
| if (JS.This.foundIn(gen)) {
|
| gen = js.call('#.bind(this)', gen);
|
| }
|
| @@ -1564,7 +1631,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| } else {
|
| declareFn = new JS.FunctionDeclaration(name, fn);
|
| }
|
| - declareFn = annotate(declareFn, node.functionDeclaration.element);
|
| + declareFn = annotate(declareFn, node, node.functionDeclaration.element);
|
|
|
| return new JS.Block([
|
| declareFn,
|
| @@ -1572,10 +1639,14 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| ]);
|
| }
|
|
|
| + @override
|
| + JS.Expression visitSimpleIdentifier(SimpleIdentifier node) =>
|
| + _emitSimpleIdentifier(node);
|
| +
|
| /// Writes a simple identifier. This can handle implicit `this` as well as
|
| /// going through the qualified library name if necessary.
|
| - @override
|
| - JS.Expression visitSimpleIdentifier(SimpleIdentifier node) {
|
| + JS.Expression _emitSimpleIdentifier(SimpleIdentifier node,
|
| + {bool allowType: false}) {
|
| var accessor = node.staticElement;
|
| if (accessor == null) {
|
| return js.commentExpression(
|
| @@ -1644,7 +1715,10 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| }
|
| }
|
|
|
| - return new JS.Identifier(name);
|
| + return annotate(
|
| + new JS.Identifier(name,
|
| + type: allowType ? emitTypeRef(node.bestType) : null),
|
| + node);
|
| }
|
|
|
| JS.TemporaryId _getTemp(Element key, String name) =>
|
| @@ -2044,12 +2118,10 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| bool _isNamedParam(FormalParameter param) =>
|
| param.kind == ParameterKind.NAMED;
|
|
|
| - /// We cannot destructure named params that clash with JS reserved names:
|
| - /// see discussion in https://github.com/dart-lang/dev_compiler/issues/392.
|
| - bool _isDestructurableNamedParam(FormalParameter param) =>
|
| - _isNamedParam(param) &&
|
| - !invalidVariableName(param.identifier.name) &&
|
| - options.destructureNamedParams;
|
| + bool _canDestructureParams(FormalParameterList params) =>
|
| + canDestructureNamedParams(
|
| + params.parameters.where(_isNamedParam).map((p) => p.identifier.name),
|
| + options);
|
|
|
| @override
|
| List<JS.Parameter> visitFormalParameterList(FormalParameterList node) =>
|
| @@ -2060,8 +2132,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| var result = <JS.Parameter>[];
|
|
|
| var namedVars = <JS.DestructuredVariable>[];
|
| - var destructure = allowDestructuring &&
|
| - node.parameters.where(_isNamedParam).every(_isDestructurableNamedParam);
|
| + var destructure = allowDestructuring && _canDestructureParams(node);
|
| var hasNamedArgsConflictingWithObjectProperties = false;
|
| var needsOpts = false;
|
|
|
| @@ -2072,7 +2143,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| hasNamedArgsConflictingWithObjectProperties = true;
|
| }
|
| namedVars.add(new JS.DestructuredVariable(
|
| - name: _visit(param.identifier),
|
| + name: _emitSimpleIdentifier(param.identifier),
|
| defaultValue: _defaultParamValue(param)));
|
| } else {
|
| needsOpts = true;
|
| @@ -2093,6 +2164,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| : js.call('{}');
|
| result.add(new JS.DestructuredVariable(
|
| structure: new JS.ObjectBindingPattern(namedVars),
|
| + type: emitNamedParamsArgType(node.parameterElements),
|
| defaultValue: defaultOpts));
|
| }
|
| return result;
|
| @@ -2224,7 +2296,8 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| return _emitTopLevelField(node);
|
| }
|
|
|
| - var name = new JS.Identifier(node.name.name);
|
| + var name =
|
| + new JS.Identifier(node.name.name, type: emitTypeRef(node.element.type));
|
| return new JS.VariableInitialization(name, _visitInitializer(node));
|
| }
|
|
|
| @@ -2260,12 +2333,13 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
|
|
| var fieldName = field.name.name;
|
| if (eagerInit && !JS.invalidStaticFieldName(fieldName)) {
|
| - return annotateVariable(
|
| + return annotate(
|
| js.statement('#.# = #;', [
|
| classElem.name,
|
| _emitMemberName(fieldName, isStatic: true),
|
| jsInit
|
| ]),
|
| + field,
|
| field.element);
|
| }
|
|
|
| @@ -2313,15 +2387,22 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
|
|
| if (isPublic(fieldName)) _addExport(fieldName, exportName);
|
| var declKeyword = field.isConst || field.isFinal ? 'const' : 'let';
|
| - return annotateVariable(
|
| - js.statement(
|
| - '$declKeyword # = #;', [new JS.Identifier(fieldName), jsInit]),
|
| - field.element);
|
| + return js.statement('#;', [
|
| + annotate(
|
| + new JS.VariableDeclarationList(declKeyword, [
|
| + new JS.VariableInitialization(
|
| + new JS.Identifier(fieldName,
|
| + type: emitTypeRef(field.element.type)),
|
| + jsInit)
|
| + ]),
|
| + field,
|
| + field.element)
|
| + ]);
|
| }
|
|
|
| if (eagerInit && !JS.invalidStaticFieldName(fieldName)) {
|
| - return annotateVariable(
|
| - js.statement('# = #;', [_visit(field.name), jsInit]), field.element);
|
| + return annotate(js.statement('# = #;', [_visit(field.name), jsInit]),
|
| + field, field.element);
|
| }
|
|
|
| return _emitLazyFields(currentLibrary, [field]);
|
| @@ -2347,6 +2428,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| js.call('function() { return #; }', _visit(node.initializer))
|
| as JS.Fun,
|
| isGetter: true),
|
| + node,
|
| _findAccessor(element, getter: true)));
|
|
|
| // TODO(jmesserly): currently uses a dummy setter to indicate writable.
|
| @@ -2354,6 +2436,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| methods.add(annotate(
|
| new JS.Method(access, js.call('function(_) {}') as JS.Fun,
|
| isSetter: true),
|
| + node,
|
| _findAccessor(element, getter: false)));
|
| }
|
| }
|
| @@ -2742,8 +2825,10 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| _visit(node.expression);
|
|
|
| @override
|
| - visitFormalParameter(FormalParameter node) {
|
| - var id = visitSimpleIdentifier(node.identifier);
|
| + visitFormalParameter(FormalParameter node) => _emitFormalParameter(node);
|
| +
|
| + _emitFormalParameter(FormalParameter node, {bool allowType: true}) {
|
| + var id = _emitSimpleIdentifier(node.identifier, allowType: allowType);
|
|
|
| var isRestArg = findAnnotation(node.element, isJsRestAnnotation) != null;
|
| return isRestArg ? new JS.RestParameter(id) : id;
|
| @@ -3303,7 +3388,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| _visit(AstNode node) {
|
| if (node == null) return null;
|
| var result = node.accept(this);
|
| - if (result is JS.Node) result.sourceInformation = node;
|
| + if (result is JS.Node) result = annotate(result, node);
|
| return result;
|
| }
|
|
|
| @@ -3446,34 +3531,14 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
|
| DartType getStaticType(Expression e) =>
|
| e.staticType ?? DynamicTypeImpl.instance;
|
|
|
| - @override
|
| - String getQualifiedName(TypeDefiningElement type) {
|
| - JS.TemporaryId id = _imports[type.library];
|
| - return id == null ? type.name : '${id.name}.${type.name}';
|
| + JS.Node annotate(JS.Node node, AstNode original, [Element element]) {
|
| + if (options.closure && element != null) {
|
| + node = node.withClosureAnnotation(
|
| + closureAnnotationFor(node, original, element, _namedArgTemp.name));
|
| + }
|
| + return node..sourceInformation = original;
|
| }
|
|
|
| - JS.Node annotate(JS.Node method, ExecutableElement e) =>
|
| - options.closure && e != null
|
| - ? method.withClosureAnnotation(
|
| - closureAnnotationFor(e, _namedArgTemp.name))
|
| - : method;
|
| -
|
| - JS.Node annotateDefaultConstructor(JS.Node method, ClassElement e) =>
|
| - options.closure && e != null
|
| - ? method
|
| - .withClosureAnnotation(closureAnnotationForDefaultConstructor(e))
|
| - : method;
|
| -
|
| - JS.Node annotateVariable(JS.Node node, VariableElement e) =>
|
| - options.closure && e != null
|
| - ? node.withClosureAnnotation(closureAnnotationForVariable(e))
|
| - : node;
|
| -
|
| - JS.Node annotateTypeDef(JS.Node node, FunctionTypeAliasElement e) =>
|
| - options.closure && e != null
|
| - ? node.withClosureAnnotation(closureAnnotationForTypeDef(e))
|
| - : node;
|
| -
|
| /// Returns true if this is any kind of object represented by `Number` in JS.
|
| ///
|
| /// In practice, this is 4 types: num, int, double, and JSNumber.
|
|
|