diff --git a/pkg/compiler/lib/src/js_backend/js_backend.dart b/pkg/compiler/lib/src/js_backend/js_backend.dart index 91995261c1f..1667ec7ce6b 100644 --- a/pkg/compiler/lib/src/js_backend/js_backend.dart +++ b/pkg/compiler/lib/src/js_backend/js_backend.dart @@ -7,7 +7,8 @@ library js_backend; import 'dart:async' show EventSink, Future; import 'dart:collection' show Queue, LinkedHashMap, LinkedHashSet; -import 'package:_internal/compiler/js_lib/shared/embedded_names.dart' as embeddedNames; +import 'package:_internal/compiler/js_lib/shared/embedded_names.dart' + as embeddedNames; import '../closure.dart'; import '../constants/expressions.dart'; diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart index c4ab7b4361e..a4a158fcc53 100644 --- a/pkg/compiler/lib/src/js_backend/namer.dart +++ b/pkg/compiler/lib/src/js_backend/namer.dart @@ -892,25 +892,25 @@ class Namer implements ClosureNamer { String globalObjectForConstant(ConstantValue constant) => 'C'; - String operatorIsPrefix() => r'$is'; + String get operatorIsPrefix => r'$is'; - String operatorAsPrefix() => r'$as'; + String get operatorAsPrefix => r'$as'; - String operatorSignature() => r'$signature'; + String get operatorSignature => r'$signature'; - String typedefTag() => r'typedef'; + String get typedefTag => r'typedef'; - String functionTypeTag() => r'func'; + String get functionTypeTag => r'func'; - String functionTypeVoidReturnTag() => r'void'; + String get functionTypeVoidReturnTag => r'void'; - String functionTypeReturnTypeTag() => r'ret'; + String get functionTypeReturnTypeTag => r'ret'; - String functionTypeRequiredParametersTag() => r'args'; + String get functionTypeRequiredParametersTag => r'args'; - String functionTypeOptionalParametersTag() => r'opt'; + String get functionTypeOptionalParametersTag => r'opt'; - String functionTypeNamedParametersTag() => r'named'; + String get functionTypeNamedParametersTag => r'named'; Map functionTypeNameMap = new Map(); @@ -928,14 +928,14 @@ class Namer implements ClosureNamer { String operatorIsType(DartType type) { if (type.isFunctionType) { // TODO(erikcorry): Reduce from $isx to ix when we are minifying. - return '${operatorIsPrefix()}_${getFunctionTypeName(type)}'; + return '${operatorIsPrefix}_${getFunctionTypeName(type)}'; } return operatorIs(type.element); } String operatorIs(Element element) { // TODO(erikcorry): Reduce from $isx to ix when we are minifying. - return '${operatorIsPrefix()}${getRuntimeTypeName(element)}'; + return '${operatorIsPrefix}${getRuntimeTypeName(element)}'; } /* @@ -954,7 +954,7 @@ class Namer implements ClosureNamer { // TODO(ahe): Creating a string here is unfortunate. It is slow (due to // string concatenation in the implementation), and may prevent // segmentation of '$'. - return '${operatorAsPrefix()}${getNameForRti(element)}'; + return '${operatorAsPrefix}${getNameForRti(element)}'; } String safeName(String name) => _safeName(name, jsReserved); diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart index cb4e509d5d9..f32d77fe9d7 100644 --- a/pkg/compiler/lib/src/js_backend/runtime_types.dart +++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart @@ -676,18 +676,18 @@ class TypeRepresentationGenerator extends DartTypeVisitor { } jsAst.LiteralString name = js.string(namer.getFunctionTypeName(type)); - addProperty(namer.functionTypeTag(), name); + addProperty(namer.functionTypeTag, name); if (type.returnType.isVoid) { - addProperty(namer.functionTypeVoidReturnTag(), js('true')); + addProperty(namer.functionTypeVoidReturnTag, js('true')); } else if (!type.returnType.treatAsDynamic) { - addProperty(namer.functionTypeReturnTypeTag(), visit(type.returnType)); + addProperty(namer.functionTypeReturnTypeTag, visit(type.returnType)); } if (!type.parameterTypes.isEmpty) { - addProperty(namer.functionTypeRequiredParametersTag(), + addProperty(namer.functionTypeRequiredParametersTag, visitList(type.parameterTypes)); } if (!type.optionalParameterTypes.isEmpty) { - addProperty(namer.functionTypeOptionalParametersTag(), + addProperty(namer.functionTypeOptionalParametersTag, visitList(type.optionalParameterTypes)); } if (!type.namedParameterTypes.isEmpty) { @@ -699,7 +699,7 @@ class TypeRepresentationGenerator extends DartTypeVisitor { jsAst.Expression name = js.string(names[index]); namedArguments.add(new jsAst.Property(name, visit(types[index]))); } - addProperty(namer.functionTypeNamedParametersTag(), + addProperty(namer.functionTypeNamedParametersTag, new jsAst.ObjectInitializer(namedArguments)); } return new jsAst.ObjectInitializer(properties); @@ -726,7 +726,7 @@ class TypeRepresentationGenerator extends DartTypeVisitor { type.treatAsRaw ? name : visitList(type.typeArguments, head: name); // Add it to the function-type object. - jsAst.LiteralString tag = js.string(namer.typedefTag()); + jsAst.LiteralString tag = js.string(namer.typedefTag); initializer.properties.add(new jsAst.Property(tag, encodedTypedef)); return initializer; } else { diff --git a/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart index 143b0d40ca9..7ce762989fc 100644 --- a/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart +++ b/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart @@ -379,6 +379,7 @@ class OldEmitter implements Emitter { generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES); jsAst.Expression metadataAccess = generateEmbeddedGlobalAccess(embeddedNames.METADATA); + String signaturePropertyName = namer.operatorSignature; return js(''' function(collectedClasses, isolateProperties, existingIsolateProperties) { @@ -426,7 +427,7 @@ class OldEmitter implements Emitter { supr = split[0]; var functionSignature = split[1]; if (functionSignature) - desc.\$signature = (function(s) { + desc.$signaturePropertyName = (function(s) { return function(){ return #metadata[s]; }; })(functionSignature); } diff --git a/pkg/compiler/lib/src/js_emitter/old_emitter/type_test_emitter.dart b/pkg/compiler/lib/src/js_emitter/old_emitter/type_test_emitter.dart index e01100546b4..aed7c6877e9 100644 --- a/pkg/compiler/lib/src/js_emitter/old_emitter/type_test_emitter.dart +++ b/pkg/compiler/lib/src/js_emitter/old_emitter/type_test_emitter.dart @@ -64,7 +64,7 @@ class TypeTestEmitter extends CodeEmitterHelper { } RuntimeTypes rti = backend.rti; jsAst.Expression encoding = rti.getSignatureEncoding(type, thisAccess); - String operatorSignature = namer.operatorSignature(); + String operatorSignature = namer.operatorSignature; if (!type.containsTypeVariables) { builder.functionType = '${emitter.metadataEmitter.reifyType(type)}'; } else { diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart index 48f9271912d..865e32c550a 100644 --- a/pkg/compiler/lib/src/ssa/builder.dart +++ b/pkg/compiler/lib/src/ssa/builder.dart @@ -3834,41 +3834,57 @@ class SsaBuilder extends ResolvedVisitor { } else if (name == 'JS_CREATE_ISOLATE') { handleForeignCreateIsolate(node); } else if (name == 'JS_OPERATOR_IS_PREFIX') { - stack.add(addConstantString(backend.namer.operatorIsPrefix())); + // TODO(floitsch): this should be a JS_NAME. + stack.add(addConstantString(backend.namer.operatorIsPrefix)); } else if (name == 'JS_OBJECT_CLASS_NAME') { + // TODO(floitsch): this should be a JS_NAME. String name = backend.namer.getRuntimeTypeName(compiler.objectClass); stack.add(addConstantString(name)); } else if (name == 'JS_NULL_CLASS_NAME') { + // TODO(floitsch): this should be a JS_NAME. String name = backend.namer.getRuntimeTypeName(compiler.nullClass); stack.add(addConstantString(name)); } else if (name == 'JS_FUNCTION_CLASS_NAME') { + // TODO(floitsch): this should be a JS_NAME. String name = backend.namer.getRuntimeTypeName(compiler.functionClass); stack.add(addConstantString(name)); } else if (name == 'JS_OPERATOR_AS_PREFIX') { - stack.add(addConstantString(backend.namer.operatorAsPrefix())); + // TODO(floitsch): this should be a JS_NAME. + stack.add(addConstantString(backend.namer.operatorAsPrefix)); } else if (name == 'JS_SIGNATURE_NAME') { - stack.add(addConstantString(backend.namer.operatorSignature())); + // TODO(floitsch): this should be a JS_NAME. + stack.add(addConstantString(backend.namer.operatorSignature)); + } else if (name == 'JS_TYPEDEF_TAG') { + // TODO(floitsch): this should be a JS_NAME. + stack.add(addConstantString(backend.namer.typedefTag)); } else if (name == 'JS_FUNCTION_TYPE_TAG') { - stack.add(addConstantString(backend.namer.functionTypeTag())); + // TODO(floitsch): this should be a JS_NAME. + stack.add(addConstantString(backend.namer.functionTypeTag)); } else if (name == 'JS_FUNCTION_TYPE_VOID_RETURN_TAG') { - stack.add(addConstantString(backend.namer.functionTypeVoidReturnTag())); + // TODO(floitsch): this should be a JS_NAME. + stack.add(addConstantString(backend.namer.functionTypeVoidReturnTag)); } else if (name == 'JS_FUNCTION_TYPE_RETURN_TYPE_TAG') { - stack.add(addConstantString(backend.namer.functionTypeReturnTypeTag())); + // TODO(floitsch): this should be a JS_NAME. + stack.add(addConstantString(backend.namer.functionTypeReturnTypeTag)); } else if (name == 'JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG') { + // TODO(floitsch): this should be a JS_NAME. stack.add(addConstantString( - backend.namer.functionTypeRequiredParametersTag())); + backend.namer.functionTypeRequiredParametersTag)); } else if (name == 'JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG') { + // TODO(floitsch): this should be a JS_NAME. stack.add(addConstantString( - backend.namer.functionTypeOptionalParametersTag())); + backend.namer.functionTypeOptionalParametersTag)); } else if (name == 'JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG') { + // TODO(floitsch): this should be a JS_NAME. stack.add(addConstantString( - backend.namer.functionTypeNamedParametersTag())); + backend.namer.functionTypeNamedParametersTag)); } else if (name == 'JS_DART_OBJECT_CONSTRUCTOR') { handleForeignDartObjectJsConstructorFunction(node); } else if (name == 'JS_IS_INDEXABLE_FIELD_NAME') { + // TODO(floitsch): this should be a JS_NAME. Element element = backend.findHelper('JavaScriptIndexingBehavior'); stack.add(addConstantString(backend.namer.operatorIs(element))); } else if (name == 'JS_CURRENT_ISOLATE') { diff --git a/sdk/lib/_internal/compiler/js_lib/foreign_helper.dart b/sdk/lib/_internal/compiler/js_lib/foreign_helper.dart index c1511548af8..156ab630333 100644 --- a/sdk/lib/_internal/compiler/js_lib/foreign_helper.dart +++ b/sdk/lib/_internal/compiler/js_lib/foreign_helper.dart @@ -208,6 +208,9 @@ JS_CURRENT_ISOLATE() {} /// Returns the name used for generated function types on classes and methods. String JS_SIGNATURE_NAME() {} +/// Returns the name used to tag typedefs. +String JS_TYPEDEF_TAG() {} + /// Returns the name used to tag function type representations in JavaScript. String JS_FUNCTION_TYPE_TAG() {} diff --git a/sdk/lib/_internal/compiler/js_lib/js_helper.dart b/sdk/lib/_internal/compiler/js_lib/js_helper.dart index 2de11198c0b..3ce3a10191f 100644 --- a/sdk/lib/_internal/compiler/js_lib/js_helper.dart +++ b/sdk/lib/_internal/compiler/js_lib/js_helper.dart @@ -2031,7 +2031,7 @@ abstract class Closure implements Function { throw 'Error in reflectionInfo.'; } - JS('', '#.\$signature = #', prototype, signatureFunction); + JS('', '#[#] = #', prototype, JS_SIGNATURE_NAME(), signatureFunction); JS('', '#[#] = #', prototype, callName, trampoline); for (int i = 1; i < functions.length; i++) { diff --git a/sdk/lib/_internal/compiler/js_lib/js_mirrors.dart b/sdk/lib/_internal/compiler/js_lib/js_mirrors.dart index 1c0433d09d6..d634385d99f 100644 --- a/sdk/lib/_internal/compiler/js_lib/js_mirrors.dart +++ b/sdk/lib/_internal/compiler/js_lib/js_mirrors.dart @@ -23,7 +23,15 @@ import 'dart:_foreign_helper' show JS_CURRENT_ISOLATE, JS_CURRENT_ISOLATE_CONTEXT, JS_EMBEDDED_GLOBAL, - JS_GET_NAME; + JS_GET_NAME, + JS_TYPEDEF_TAG, + JS_FUNCTION_TYPE_TAG, + JS_FUNCTION_TYPE_RETURN_TYPE_TAG, + JS_FUNCTION_TYPE_VOID_RETURN_TAG, + JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG, + JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG, + JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG; + import 'dart:_internal' as _symbol_dev; @@ -2602,19 +2610,44 @@ class JsFunctionTypeMirror extends BrokenClassMirror JsFunctionTypeMirror(this._typeData, this.owner); - bool get _hasReturnType => JS('bool', '"ret" in #', _typeData); - get _returnType => JS('', '#.ret', _typeData); + bool get _hasReturnType { + return JS('bool', '# in #', JS_FUNCTION_TYPE_RETURN_TYPE_TAG(), _typeData); + } + get _returnType { + return JS('', '#[#]', _typeData, JS_FUNCTION_TYPE_RETURN_TYPE_TAG()); + } - bool get _isVoid => JS('bool', '!!#.void', _typeData); + bool get _isVoid { + return JS('bool', '!!#[#]', _typeData, JS_FUNCTION_TYPE_VOID_RETURN_TAG()); + } - bool get _hasArguments => JS('bool', '"args" in #', _typeData); - List get _arguments => JS('JSExtendableArray', '#.args', _typeData); + bool get _hasArguments { + return JS('bool', '# in #', + JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG(), _typeData); + } + List get _arguments { + return JS('JSExtendableArray', '#[#]', + _typeData, JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG()); + } - bool get _hasOptionalArguments => JS('bool', '"opt" in #', _typeData); - List get _optionalArguments => JS('JSExtendableArray', '#.opt', _typeData); + bool get _hasOptionalArguments { + return JS('bool', '# in #', + JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG(), _typeData); + } + List get _optionalArguments { + return JS('JSExtendableArray', '#[#]', + _typeData, JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG()); + } + + bool get _hasNamedArguments { + return JS('bool', '# in #', + JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG(), _typeData); + } + get _namedArguments { + return JS('=Object', '#[#]', + _typeData, JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG()); + } - bool get _hasNamedArguments => JS('bool', '"named" in #', _typeData); - get _namedArguments => JS('=Object', '#.named', _typeData); bool get isOriginalDeclaration => true; bool get isAbstract => false; @@ -2799,10 +2832,13 @@ TypeMirror typeMirrorFromRuntimeTypeRepresentation( return reflectClassByMangledName( getMangledTypeName(createRuntimeType(representation))); } - if (type != null && JS('', '#.typedef', type) != null) { + String typedefPropertyName = JS_TYPEDEF_TAG(); + String functionTagPropertyName = JS_FUNCTION_TYPE_TAG(); + if (type != null && JS('', '#[#]', type, typedefPropertyName) != null) { return typeMirrorFromRuntimeTypeRepresentation( - owner, JS('', '#.typedef', type)); - } else if (type != null && JS('', '#.func', type) != null) { + owner, JS('', '#[#]', type, typedefPropertyName)); + } else if (type != null && + JS('', '#[#]', type, functionTagPropertyName) != null) { return new JsFunctionTypeMirror(type, owner); } return reflectClass(Function); diff --git a/tests/compiler/dart2js/deferred_emit_type_checks_test.dart b/tests/compiler/dart2js/deferred_emit_type_checks_test.dart index 6ece06e02d5..d397ababc0f 100644 --- a/tests/compiler/dart2js/deferred_emit_type_checks_test.dart +++ b/tests/compiler/dart2js/deferred_emit_type_checks_test.dart @@ -52,8 +52,10 @@ void main() { asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) { String mainOutput = outputs['main.js'].mem[0]; String deferredOutput = outputs['out_1.part.js'].mem[0]; - RegExp re = new RegExp(r"\n _ = .\.A;\n _.\$isA = TRUE;"); - print(deferredOutput); + String isPrefix = compiler.backend.namer.operatorIsPrefix; + String escapedIsPrefix = isPrefix.replaceAll(r'$', r'\$'); + RegExp re = new RegExp(r"\n _ = .\.A;\n _." + "${escapedIsPrefix}A = TRUE;"); Expect.isTrue(re.hasMatch(deferredOutput)); Expect.isFalse(re.hasMatch(mainOutput)); })); diff --git a/tests/compiler/dart2js/type_representation_test.dart b/tests/compiler/dart2js/type_representation_test.dart index 7bd7f3ccb44..4f634203897 100644 --- a/tests/compiler/dart2js/type_representation_test.dart +++ b/tests/compiler/dart2js/type_representation_test.dart @@ -78,12 +78,13 @@ void testTypeRepresentations() { } JavaScriptBackend backend = env.compiler.backend; - String func = backend.namer.functionTypeTag(); - String retvoid = backend.namer.functionTypeVoidReturnTag(); - String ret = backend.namer.functionTypeReturnTypeTag(); - String args = backend.namer.functionTypeRequiredParametersTag(); - String opt = backend.namer.functionTypeOptionalParametersTag(); - String named = backend.namer.functionTypeNamedParametersTag(); + String func = backend.namer.functionTypeTag; + String retvoid = backend.namer.functionTypeVoidReturnTag; + String ret = backend.namer.functionTypeReturnTypeTag; + String args = backend.namer.functionTypeRequiredParametersTag; + String opt = backend.namer.functionTypeOptionalParametersTag; + String named = backend.namer.functionTypeNamedParametersTag; + String typedefTag = backend.namer.typedefTag; ClassElement List_ = env.getElement('List'); TypeVariableType List_E = List_.typeVariables[0]; @@ -142,52 +143,55 @@ void testTypeRepresentations() { // List expect(instantiate(List_, [Typedef_]), '[$List_rep, {$func: "void_", $retvoid: true}]', - '[$List_rep, {$func: "void_", $retvoid: true, typedef: $Typedef_rep}]'); + '[$List_rep, {$func: "void_", $retvoid: true,' + ' $typedefTag: $Typedef_rep}]'); expect(instantiate(List_, [Typedef2_]), '[$List_rep, {$func: "int_", $ret: $int_rep}]', - '[$List_rep, {$func: "int_", $ret: $int_rep, typedef: $Typedef2_rep}]'); + '[$List_rep, {$func: "int_", $ret: $int_rep,' + ' $typedefTag: $Typedef2_rep}]'); expect(instantiate(List_, [Typedef3_]), '[$List_rep, {$func: "List_", $ret: [$List_rep, $int_rep]}]', '[$List_rep, {$func: "List_", $ret: [$List_rep, $int_rep],' - ' typedef: $Typedef3_rep}]'); + ' $typedefTag: $Typedef3_rep}]'); expect(instantiate(List_, [Typedef4_]), '[$List_rep, {$func: "args0"}]', - '[$List_rep, {$func: "args0", typedef: $Typedef4_rep}]'); + '[$List_rep, {$func: "args0", $typedefTag: $Typedef4_rep}]'); expect(instantiate(List_, [Typedef5_]), '[$List_rep, {$func: "dynamic__int_String",' ' $args: [$int_rep, $String_rep]}]', '[$List_rep, {$func: "dynamic__int_String",' - ' $args: [$int_rep, $String_rep], typedef: $Typedef5_rep}]'); + ' $args: [$int_rep, $String_rep], $typedefTag: $Typedef5_rep}]'); expect(instantiate(List_, [Typedef6_]), '[$List_rep, {$func: "dynamic__int__String",' ' $args: [$int_rep], $opt: [$String_rep]}]', '[$List_rep, {$func: "dynamic__int__String",' - ' $args: [$int_rep], $opt: [$String_rep], typedef: $Typedef6_rep}]'); + ' $args: [$int_rep], $opt: [$String_rep],' + ' $typedefTag: $Typedef6_rep}]'); expect(instantiate(List_, [Typedef7_]), '[$List_rep, {$func: "dynamic__int_String__List_dynamic", $args: ' '[$int_rep, $String_rep], $opt: [[$List_rep, $int_rep], null]}]', '[$List_rep, {$func: "dynamic__int_String__List_dynamic", $args: ' '[$int_rep, $String_rep], $opt: [[$List_rep, $int_rep], null], ' - 'typedef: $Typedef7_rep}]'); + '$typedefTag: $Typedef7_rep}]'); expect(instantiate(List_, [Typedef8_]), '[$List_rep, {$func: "dynamic__int__String0", $args: [$int_rep],' ' $named: {b: $String_rep}}]', '[$List_rep, {$func: "dynamic__int__String0", $args: [$int_rep],' - ' $named: {b: $String_rep}, typedef: $Typedef8_rep}]'); + ' $named: {b: $String_rep}, $typedefTag: $Typedef8_rep}]'); expect(instantiate(List_, [Typedef9_]), '[$List_rep, {$func: "dynamic__int_String__List_dynamic0", ' '$args: [$int_rep, $String_rep], $named: ' '{c: [$List_rep, $int_rep], d: null}}]', '[$List_rep, {$func: "dynamic__int_String__List_dynamic0", ' '$args: [$int_rep, $String_rep], $named: {c: [$List_rep, $int_rep],' - ' d: null}, typedef: $Typedef9_rep}]'); + ' d: null}, $typedefTag: $Typedef9_rep}]'); expect(instantiate(List_, [Typedef10_]), '[$List_rep, {$func: "dynamic__void__int__dynamic", ' '$args: [{$func: "void__int__dynamic", $retvoid: true, ' '$args: [$int_rep], $opt: [null]}]}]', '[$List_rep, {$func: "dynamic__void__int__dynamic", ' '$args: [{$func: "void__int__dynamic", $retvoid: true, ' - '$args: [$int_rep], $opt: [null]}], typedef: $Typedef10_rep}]'); + '$args: [$int_rep], $opt: [null]}], $typedefTag: $Typedef10_rep}]'); // Map expect(Map_.computeType(env.compiler), @@ -250,5 +254,3 @@ void testTypeRepresentations() { ' $retvoid: true, $args: [$int_rep], $opt: [null]}]}'); })); } - -