| Index: lib/src/codegen/js_codegen.dart
|
| diff --git a/lib/src/codegen/js_codegen.dart b/lib/src/codegen/js_codegen.dart
|
| index cd4b5c9b812a71288b821e696a00ae6110152b5a..ba422122e11c403b259e2e3602844037b0c0e55f 100644
|
| --- a/lib/src/codegen/js_codegen.dart
|
| +++ b/lib/src/codegen/js_codegen.dart
|
| @@ -377,11 +377,8 @@ class JSCodegenVisitor extends GeneralizingAstVisitor
|
| }
|
| }
|
|
|
| - var classExpr = new JS.ClassExpression(
|
| - new JS.Identifier(element.name), _classHeritage(element), body);
|
| -
|
| - return _finishClassDef(
|
| - element.type, _emitClassHeritageWorkaround(classExpr));
|
| + var cls = _emitClassDeclaration(element, body);
|
| + return _finishClassDef(element.type, cls);
|
| }
|
|
|
| JS.Statement _emitJsType(String dartClassName, DartObject jsName) {
|
| @@ -421,11 +418,11 @@ class JSCodegenVisitor extends GeneralizingAstVisitor
|
| }
|
| }
|
|
|
| - var classExpr = new JS.ClassExpression(new JS.Identifier(type.name),
|
| - _classHeritage(classElem), _emitClassMethods(node, ctors, fields),
|
| - typeParams: _emitTypeFormals(classElem.typeParameters),
|
| - fields:
|
| - _emitFieldDeclarations(classElem, fields, staticFields).toList());
|
| + var allFields = new List.from(fields)..addAll(staticFields);
|
| +
|
| + var classDecl = _emitClassDeclaration(
|
| + classElem, _emitClassMethods(node, ctors, fields),
|
| + fields: allFields);
|
|
|
| String jsPeerName;
|
| var jsPeer = findAnnotation(classElem, isJsPeerInterface);
|
| @@ -442,7 +439,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor
|
| }
|
| }
|
|
|
| - var body = _finishClassMembers(classElem, classExpr, ctors, fields,
|
| + var body = _finishClassMembers(classElem, classDecl, ctors, fields,
|
| staticFields, methods, node.metadata, jsPeerName);
|
|
|
| var result = _finishClassDef(type, body);
|
| @@ -467,36 +464,24 @@ class JSCodegenVisitor extends GeneralizingAstVisitor
|
| }
|
|
|
| List<JS.Identifier> _emitTypeFormals(List<TypeParameterElement> typeFormals) {
|
| - if (!options.closure) return null;
|
| return typeFormals
|
| .map((t) => new JS.Identifier(t.name))
|
| .toList(growable: false);
|
| }
|
|
|
| - /// Emit field declarations for TypeScript & Closure's ES6_TYPED
|
| + /// Emits a field declaration 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());
|
| - }
|
| + JS.VariableDeclarationList _emitTypeScriptField(FieldDeclaration field) {
|
| + return new JS.VariableDeclarationList(
|
| + field.isStatic ? 'static' : null,
|
| + field.fields.variables
|
| + .map((decl) => new JS.VariableInitialization(
|
| + new JS.Identifier(
|
| + // TODO(ochafik): use a refactored _emitMemberName instead.
|
| + decl.name.name,
|
| + type: emitTypeRef(decl.element.type)),
|
| + null))
|
| + .toList(growable: false));
|
| }
|
|
|
| @override
|
| @@ -527,7 +512,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor
|
|
|
| // Create enum class
|
| var classExpr = new JS.ClassExpression(
|
| - id, _classHeritage(element), [constructor, toStringF]);
|
| + id, _emitClassHeritage(element), [constructor, toStringF]);
|
| var result = <JS.Statement>[js.statement('#', classExpr)];
|
|
|
| // Create static fields for each enum value
|
| @@ -608,7 +593,33 @@ class JSCodegenVisitor extends GeneralizingAstVisitor
|
| return false;
|
| }
|
|
|
| - JS.Expression _classHeritage(ClassElement element) {
|
| + JS.Statement _emitClassDeclaration(
|
| + ClassElement element, List<JS.Method> methods,
|
| + {List<FieldDeclaration> fields}) {
|
| + String name = element.name;
|
| + var heritage = _emitClassHeritage(element);
|
| + var typeParams = _emitTypeFormals(element.typeParameters);
|
| + var jsFields = fields?.map(_emitTypeScriptField)?.toList();
|
| +
|
| + // Workaround for Closure: super classes must be qualified paths.
|
| + // TODO(jmesserly): is there a bug filed? we need to get out of the business
|
| + // of working around bugs in other transpilers...
|
| + JS.Statement workaroundSuper = null;
|
| + if (options.closure && heritage is JS.Call) {
|
| + var superVar = new JS.TemporaryId('$name\$super');
|
| + workaroundSuper = js.statement('const # = #;', [superVar, heritage]);
|
| + heritage = superVar;
|
| + }
|
| + var decl = new JS.ClassDeclaration(new JS.ClassExpression(
|
| + new JS.Identifier(name), heritage, methods,
|
| + typeParams: typeParams, fields: jsFields));
|
| + if (workaroundSuper != null) {
|
| + return new JS.Block([workaroundSuper, decl]);
|
| + }
|
| + return decl;
|
| + }
|
| +
|
| + JS.Expression _emitClassHeritage(ClassElement element) {
|
| var type = element.type;
|
| if (type.isObject) return null;
|
|
|
| @@ -758,34 +769,12 @@ class JSCodegenVisitor extends GeneralizingAstVisitor
|
| }
|
| }
|
|
|
| - _isQualifiedPath(JS.Expression node) =>
|
| - node is JS.Identifier ||
|
| - node is JS.PropertyAccess &&
|
| - _isQualifiedPath(node.receiver) &&
|
| - node.selector is JS.LiteralString;
|
| -
|
| - /// Workaround for Closure: super classes must be qualified paths.
|
| - JS.Statement _emitClassHeritageWorkaround(JS.ClassExpression cls) {
|
| - if (options.closure &&
|
| - cls.heritage != null &&
|
| - !_isQualifiedPath(cls.heritage)) {
|
| - 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,
|
| - typeParams: cls.typeParams, fields: cls.fields))
|
| - ]);
|
| - }
|
| - return new JS.ClassDeclaration(cls);
|
| - }
|
| -
|
| /// Emit class members that need to come after the class declaration, such
|
| /// as static fields. See [_emitClassMethods] for things that are emitted
|
| /// inside the ES6 `class { ... }` node.
|
| JS.Statement _finishClassMembers(
|
| ClassElement classElem,
|
| - JS.ClassExpression cls,
|
| + JS.Statement classDecl,
|
| List<ConstructorDeclaration> ctors,
|
| List<FieldDeclaration> fields,
|
| List<FieldDeclaration> staticFields,
|
| @@ -818,7 +807,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor
|
| }
|
| }
|
|
|
| - body.add(_emitClassHeritageWorkaround(cls));
|
| + body.add(classDecl);
|
|
|
| // TODO(jmesserly): we should really just extend native Array.
|
| if (jsPeerName != null && classElem.typeParameters.isNotEmpty) {
|
| @@ -3499,7 +3488,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor
|
|
|
| // TODO(jmesserly): this will need to be a generic method, if we ever want to
|
| // self-host strong mode.
|
| - List /*<T>*/ _visitList /*<T>*/ (Iterable<AstNode> nodes) {
|
| + List/*<T>*/ _visitList/*<T>*/(Iterable<AstNode> nodes) {
|
| if (nodes == null) return null;
|
| var result = /*<T>*/ [];
|
| for (var node in nodes) result.add(_visit(node));
|
| @@ -3820,6 +3809,7 @@ class JSGenerator extends CodeGenerator {
|
| ? Uri.parse('http://${flags.host}:${flags.port}/')
|
| : null;
|
| return writeJsLibrary(module, out, compiler.inputBaseDir, serverUri,
|
| + emitTypes: options.closure,
|
| emitSourceMaps: options.emitSourceMaps,
|
| fileSystem: compiler.fileSystem);
|
| }
|
|
|