diff --git a/lib/runtime/dart/_interceptors.js b/lib/runtime/dart/_interceptors.js index b17828a4..658cf797 100644 --- a/lib/runtime/dart/_interceptors.js +++ b/lib/runtime/dart/_interceptors.js @@ -448,6 +448,7 @@ dart.library('dart/_interceptors', null, /* Imports */[ statics: () => ({markFixedList: [core.List, [core.List]]}), names: ['markFixedList'] }); + JSArray[dart.metadata] = () => [dart.const(new _js_helper.JsPeerInterface({name: 'Array'}))]; return JSArray; }); let JSArray = JSArray$(); @@ -925,6 +926,7 @@ dart.library('dart/_interceptors', null, /* Imports */[ }), names: ['_bitCount', '_shru', '_shrs', '_ors', '_spread'] }); + JSInt[dart.metadata] = () => [dart.const(new _js_helper.JsPeerInterface({name: 'Number'}))]; dart.registerExtension(dart.global.Number, JSInt); class JSDouble extends JSNumber { JSDouble() { @@ -1436,6 +1438,7 @@ dart.library('dart/_interceptors', null, /* Imports */[ }), names: ['_isWhitespace', '_skipLeadingWhitespace', '_skipTrailingWhitespace'] }); + JSString[dart.metadata] = () => [dart.const(new _js_helper.JsPeerInterface({name: 'String'}))]; dart.registerExtension(dart.global.String, JSString); let _string = Symbol('_string'); class _CodeUnits extends _internal.UnmodifiableListBase$(core.int) { @@ -1481,6 +1484,7 @@ dart.library('dart/_interceptors', null, /* Imports */[ dart.setSignature(JSBool, { constructors: () => ({JSBool: [JSBool, []]}) }); + JSBool[dart.metadata] = () => [dart.const(new _js_helper.JsPeerInterface({name: 'Boolean'}))]; dart.registerExtension(dart.global.Boolean, JSBool); class JSIndexable extends core.Object {} class JSMutableIndexable extends JSIndexable {} diff --git a/lib/runtime/dart/_native_typed_data.js b/lib/runtime/dart/_native_typed_data.js index 3eec1f9d..5892f584 100644 --- a/lib/runtime/dart/_native_typed_data.js +++ b/lib/runtime/dart/_native_typed_data.js @@ -3,11 +3,11 @@ dart.library('dart/_native_typed_data', null, /* Imports */[ 'dart/typed_data', 'dart/collection', 'dart/_internal', - 'dart/_js_helper', 'dart/math' ], /* Lazy imports */[ + 'dart/_js_helper', 'dart/_interceptors' -], function(exports, core, typed_data, collection, _internal, _js_helper, math, _interceptors) { +], function(exports, core, typed_data, collection, _internal, math, _js_helper, _interceptors) { 'use strict'; class NativeByteBuffer extends core.Object { NativeByteBuffer() { @@ -145,6 +145,7 @@ dart.library('dart/_native_typed_data', null, /* Imports */[ asByteData: [typed_data.ByteData, [], [core.int, core.int]] }) }); + NativeByteBuffer[dart.metadata] = () => [dart.const(new _js_helper.Native("ArrayBuffer"))]; let _storage = Symbol('_storage'); let _invalidIndex = Symbol('_invalidIndex'); let _checkIndex = Symbol('_checkIndex'); @@ -510,6 +511,7 @@ dart.library('dart/_native_typed_data', null, /* Imports */[ [_checkSublistArguments]: [core.int, [core.int, core.int, core.int]] }) }); + NativeTypedData[dart.metadata] = () => [dart.const(new _js_helper.Native("ArrayBufferView"))]; function _checkLength(length) { if (!(typeof length == 'number')) throw new core.ArgumentError(`Invalid length ${length}`); @@ -701,6 +703,7 @@ dart.library('dart/_native_typed_data', null, /* Imports */[ }), names: ['_create1', '_create2', '_create3'] }); + NativeByteData[dart.metadata] = () => [dart.const(new _js_helper.Native("DataView"))]; let _setRangeFast = Symbol('_setRangeFast'); class NativeTypedArray extends NativeTypedData { NativeTypedArray() { @@ -832,6 +835,7 @@ dart.library('dart/_native_typed_data', null, /* Imports */[ names: ['_create1', '_create2', '_create3'] }); dart.defineExtensionMembers(NativeFloat32List, ['sublist']); + NativeFloat32List[dart.metadata] = () => [dart.const(new _js_helper.Native("Float32Array"))]; class NativeFloat64List extends NativeTypedArrayOfDouble { static new(length) { return NativeFloat64List._create1(_checkLength(length)); @@ -879,6 +883,7 @@ dart.library('dart/_native_typed_data', null, /* Imports */[ names: ['_create1', '_create2', '_create3'] }); dart.defineExtensionMembers(NativeFloat64List, ['sublist']); + NativeFloat64List[dart.metadata] = () => [dart.const(new _js_helper.Native("Float64Array"))]; class NativeInt16List extends NativeTypedArrayOfInt { static new(length) { return NativeInt16List._create1(_checkLength(length)); @@ -933,6 +938,7 @@ dart.library('dart/_native_typed_data', null, /* Imports */[ names: ['_create1', '_create2', '_create3'] }); dart.defineExtensionMembers(NativeInt16List, ['get', 'sublist']); + NativeInt16List[dart.metadata] = () => [dart.const(new _js_helper.Native("Int16Array"))]; class NativeInt32List extends NativeTypedArrayOfInt { static new(length) { return NativeInt32List._create1(_checkLength(length)); @@ -987,6 +993,7 @@ dart.library('dart/_native_typed_data', null, /* Imports */[ names: ['_create1', '_create2', '_create3'] }); dart.defineExtensionMembers(NativeInt32List, ['get', 'sublist']); + NativeInt32List[dart.metadata] = () => [dart.const(new _js_helper.Native("Int32Array"))]; class NativeInt8List extends NativeTypedArrayOfInt { static new(length) { return NativeInt8List._create1(_checkLength(length)); @@ -1041,6 +1048,7 @@ dart.library('dart/_native_typed_data', null, /* Imports */[ names: ['_create1', '_create2', '_create3'] }); dart.defineExtensionMembers(NativeInt8List, ['get', 'sublist']); + NativeInt8List[dart.metadata] = () => [dart.const(new _js_helper.Native("Int8Array"))]; class NativeUint16List extends NativeTypedArrayOfInt { static new(length) { return NativeUint16List._create1(_checkLength(length)); @@ -1095,6 +1103,7 @@ dart.library('dart/_native_typed_data', null, /* Imports */[ names: ['_create1', '_create2', '_create3'] }); dart.defineExtensionMembers(NativeUint16List, ['get', 'sublist']); + NativeUint16List[dart.metadata] = () => [dart.const(new _js_helper.Native("Uint16Array"))]; class NativeUint32List extends NativeTypedArrayOfInt { static new(length) { return NativeUint32List._create1(_checkLength(length)); @@ -1149,6 +1158,7 @@ dart.library('dart/_native_typed_data', null, /* Imports */[ names: ['_create1', '_create2', '_create3'] }); dart.defineExtensionMembers(NativeUint32List, ['get', 'sublist']); + NativeUint32List[dart.metadata] = () => [dart.const(new _js_helper.Native("Uint32Array"))]; class NativeUint8ClampedList extends NativeTypedArrayOfInt { static new(length) { return NativeUint8ClampedList._create1(_checkLength(length)); @@ -1206,6 +1216,7 @@ dart.library('dart/_native_typed_data', null, /* Imports */[ names: ['_create1', '_create2', '_create3'] }); dart.defineExtensionMembers(NativeUint8ClampedList, ['get', 'sublist', 'length']); + NativeUint8ClampedList[dart.metadata] = () => [dart.const(new _js_helper.Native("Uint8ClampedArray,CanvasPixelArray"))]; class NativeUint8List extends NativeTypedArrayOfInt { static new(length) { return NativeUint8List._create1(_checkLength(length)); @@ -1263,6 +1274,7 @@ dart.library('dart/_native_typed_data', null, /* Imports */[ names: ['_create1', '_create2', '_create3'] }); dart.defineExtensionMembers(NativeUint8List, ['get', 'sublist', 'length']); + NativeUint8List[dart.metadata] = () => [dart.const(new _js_helper.Native("Uint8Array,!nonleaf"))]; class NativeFloat32x4 extends core.Object { static _truncate(x) { NativeFloat32x4._list.set(0, dart.as(x, core.num)); diff --git a/lib/runtime/dart/async.js b/lib/runtime/dart/async.js index b643ab70..7c4bcfe4 100644 --- a/lib/runtime/dart/async.js +++ b/lib/runtime/dart/async.js @@ -1791,6 +1791,7 @@ dart.library('dart/async', null, /* Imports */[ constructors: () => ({DeferredLibrary: [DeferredLibrary, [core.String], {uri: core.String}]}), methods: () => ({load: [Future$(core.Null), []]}) }); + DeferredLibrary[dart.metadata] = () => [dart.const(new core.Deprecated("Dart sdk v. 1.8"))]; let _s = Symbol('_s'); class DeferredLoadException extends core.Object { DeferredLoadException(s) { diff --git a/lib/runtime/dart_runtime.js b/lib/runtime/dart_runtime.js index ac24ada7..edf20639 100644 --- a/lib/runtime/dart_runtime.js +++ b/lib/runtime/dart_runtime.js @@ -876,6 +876,7 @@ var dart, dartx; /** The Symbol for storing type arguments on a specialized generic type. */ dart.mixins = Symbol('mixins'); dart.implements = Symbol('implements'); + dart.metadata = Symbol('metadata'); /** * Returns a new type that mixes members from base and all mixins. diff --git a/lib/src/codegen/js_codegen.dart b/lib/src/codegen/js_codegen.dart index 28ba34dc..62a5a011 100644 --- a/lib/src/codegen/js_codegen.dart +++ b/lib/src/codegen/js_codegen.dart @@ -363,8 +363,8 @@ class JSCodegenVisitor extends GeneralizingAstVisitor { jsPeerName = getConstantField(jsPeer, 'name', types.stringType); } - var body = _finishClassMembers( - classElem, classExpr, ctors, fields, methods, jsPeerName); + var body = _finishClassMembers(classElem, classExpr, ctors, fields, methods, + node.metadata, jsPeerName); var result = _finishClassDef(type, body); @@ -541,13 +541,23 @@ class JSCodegenVisitor extends GeneralizingAstVisitor { [_emitMemberName('iterator', type: t)])); } + JS.Expression _instantiateAnnotation(Annotation node) { + var element = node.element; + if (element is ConstructorElement) { + return _emitInstanceCreationExpression(element, element.returnType, + node.constructorName, node.arguments, true); + } else { + return _visit(node.name); + } + } + /// 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, List ctors, List fields, List methods, - String jsPeerName) { + List metadata, String jsPeerName) { var name = classElem.name; var body = []; @@ -627,6 +637,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor { } } } + var tCtors = []; for (ConstructorDeclaration node in ctors) { var memberName = _constructorName(node.element); @@ -637,6 +648,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor { new JS.Property(memberName, new JS.ArrayInitializer(parts)); tCtors.add(property); } + build(name, elements) { var o = new JS.ObjectInitializer(elements, multiline: elements.length > 1); @@ -675,6 +687,14 @@ class JSCodegenVisitor extends GeneralizingAstVisitor { ])); } + // Metadata + if (metadata.isNotEmpty) { + body.add(js.statement('#[dart.metadata] = () => #;', [ + name, + new JS.ArrayInitializer(metadata.map(_instantiateAnnotation).toList()) + ])); + } + return _statement(body); } @@ -1743,11 +1763,10 @@ class JSCodegenVisitor extends GeneralizingAstVisitor { _properties.clear(); } - @override - visitConstructorName(ConstructorName node) { - var typeName = _visit(node.type); - var element = node.staticElement; - if (node.name != null || element.isFactory) { + JS.Expression _emitConstructorName( + ConstructorElement element, DartType type, SimpleIdentifier name) { + var typeName = _emitTypeName(type); + if (name != null || element.isFactory) { var namedCtor = _constructorName(element); return new JS.PropertyAccess(typeName, namedCtor); } @@ -1755,30 +1774,45 @@ class JSCodegenVisitor extends GeneralizingAstVisitor { } @override - visitInstanceCreationExpression(InstanceCreationExpression node) { + visitConstructorName(ConstructorName node) { + return _emitConstructorName(node.staticElement, node.type.type, node.name); + } + + JS.Expression _emitInstanceCreationExpression(ConstructorElement element, + DartType type, SimpleIdentifier name, ArgumentList argumentList, + bool isConst) { emitNew() { JS.Expression ctor; bool isFactory = false; - var element = node.staticElement; + // var element = node.staticElement; if (element == null) { // TODO(jmesserly): this only happens if we had a static error. // Should we generate a throw instead? - ctor = _visit(node.constructorName.type); - var ctorName = node.constructorName.name; - if (ctorName != null) { - ctor = new JS.PropertyAccess(ctor, _propertyName(ctorName.name)); + ctor = _emitTypeName(type); + if (name != null) { + ctor = new JS.PropertyAccess(ctor, _propertyName(name.name)); } } else { - ctor = _visit(node.constructorName); + ctor = _emitConstructorName(element, type, name); isFactory = element.isFactory; } - var args = _visit(node.argumentList); + var args = _visit(argumentList); return isFactory ? new JS.Call(ctor, args) : new JS.New(ctor, args); } - if (node.isConst) return _emitConst(node, emitNew); + if (isConst) return _emitConst(emitNew); return emitNew(); } + @override + visitInstanceCreationExpression(InstanceCreationExpression node) { + var element = node.staticElement; + var constructor = node.constructorName; + var name = constructor.name; + var type = constructor.type.type; + return _emitInstanceCreationExpression( + element, type, name, node.argumentList, node.isConst); + } + /// True if this type is built-in to JS, and we use the values unwrapped. /// For these types we generate a calling convention via static /// "extension methods". This allows types to be extended without adding @@ -1876,6 +1910,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor { var op = node.operator; var left = node.leftOperand; var right = node.rightOperand; + var leftType = getStaticType(left); var rightType = getStaticType(right); @@ -1945,7 +1980,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor { return id; } - JS.Expression _emitConst(Expression node, JS.Expression expr()) { + JS.Expression _emitConst(JS.Expression expr()) { // TODO(jmesserly): emit the constants at top level if possible. // This wasn't quite working, so disabled for now. return js.call('dart.const(#)', expr()); @@ -2436,7 +2471,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor { var name = js.string(node.components.join('.'), "'"); return new JS.New(_emitTypeName(types.symbolType), [name]); } - return _emitConst(node, emitSymbol); + return _emitConst(emitSymbol); } @override @@ -2450,7 +2485,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor { } return list; } - if (node.constKeyword != null) return _emitConst(node, emitList); + if (node.constKeyword != null) return _emitConst(emitList); return emitList(); } @@ -2482,7 +2517,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor { // TODO(jmesserly): add generic types args. return js.call('dart.map(#)', [mapArguments]); } - if (node.constKeyword != null) return _emitConst(node, emitMap); + if (node.constKeyword != null) return _emitConst(emitMap); return emitMap(); }