dart2js: Refactoring, documentation, and a few bugfixes in Namer class.

See long doc comment in namer.dart.

BUG=
R=floitsch@google.com

Committed: https://code.google.com/p/dart/source/detail?r=43588

Reverted: https://code.google.com/p/dart/source/detail?r=43590
(to avoid rebase conflicts for people pushing to trunk)

Committed: https://code.google.com/p/dart/source/detail?r=43724

Reverted: https://code.google.com/p/dart/source/detail?r=43739
(red bots)

Review URL: https://codereview.chromium.org//891673003

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@44092 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
asgerf@google.com 2015-02-27 14:20:49 +00:00
parent 0f41a29315
commit 96b77b5be9
32 changed files with 1031 additions and 403 deletions

View file

@ -2223,6 +2223,9 @@ bool invariant(Spannable spannable, var condition, {var message: null}) {
/// Returns `true` when [s] is private if used as an identifier.
bool isPrivateName(String s) => !s.isEmpty && s.codeUnitAt(0) == $_;
/// Returns `true` when [s] is public if used as an identifier.
bool isPublicName(String s) => !isPrivateName(s);
/// A sink that drains into /dev/null.
class NullSink implements EventSink<String> {
final String name;

View file

@ -547,7 +547,7 @@ class JavaScriptBackend extends Backend {
String registerOneShotInterceptor(Selector selector) {
Set<ClassElement> classes = getInterceptedClassesOn(selector.name);
String name = namer.getOneShotInterceptorName(selector, classes);
String name = namer.nameForGetOneShotInterceptor(selector, classes);
if (!oneShotInterceptors.containsKey(name)) {
registerSpecializedGetInterceptor(classes);
oneShotInterceptors[name] = selector;
@ -746,7 +746,7 @@ class JavaScriptBackend extends Backend {
}
void registerSpecializedGetInterceptor(Set<ClassElement> classes) {
String name = namer.getInterceptorName(getInterceptorMethod, classes);
String name = namer.nameForGetInterceptor(classes);
if (classes.contains(jsInterceptorClass)) {
// We can't use a specialized [getInterceptorMethod], so we make
// sure we emit the one with all checks.

View file

@ -270,7 +270,6 @@ class CodeGenerator extends tree_ir.Visitor<dynamic, js.Expression> {
if (node.target is ConstructorBodyElement) {
// A constructor body cannot be overriden or intercepted, so we can
// use the short form for this invocation.
// TODO(asgerf): prevent name clash between constructor bodies.
return js.js('#.#(#)',
[visitExpression(node.receiver),
glue.instanceMethodName(node.target),

View file

@ -108,9 +108,7 @@ class Glue {
String getInterceptorName(Set<ClassElement> interceptedClasses) {
return _backend.namer.getInterceptorName(
getInterceptorMethod,
interceptedClasses);
return _backend.namer.nameForGetInterceptor(interceptedClasses);
}
js.Expression getInterceptorLibrary() {

View file

@ -250,7 +250,7 @@ class ConstantEmitter
@override
jsAst.Expression visitType(TypeConstantValue constant, [_]) {
DartType type = constant.representedType;
String name = namer.getRuntimeTypeName(type.element);
String name = namer.runtimeTypeName(type.element);
jsAst.Expression typeName = new jsAst.LiteralString("'$name'");
return new jsAst.Call(getHelperProperty(backend.getCreateRuntimeType()),
[typeName]);

View file

@ -26,14 +26,18 @@ class MinifyNamer extends Namer {
_FieldNamingRegistry fieldRegistry;
// You can pass an invalid identifier to this and unlike its non-minifying
// counterpart it will never return the proposedName as the new fresh name.
/// You can pass an invalid identifier to this and unlike its non-minifying
/// counterpart it will never return the proposedName as the new fresh name.
///
/// [sanitizeForNatives] and [sanitizeForAnnotations] are ignored because the
/// minified names will always avoid clashing with annotated names or natives.
String getFreshName(String proposedName,
Set<String> usedNames,
Map<String, String> suggestedNames,
{bool ensureSafe: true}) {
var freshName;
var suggestion = suggestedNames[proposedName];
{bool sanitizeForNatives: false,
bool sanitizeForAnnotations: false}) {
String freshName;
String suggestion = suggestedNames[proposedName];
if (suggestion != null && !usedNames.contains(suggestion)) {
freshName = suggestion;
} else {
@ -44,18 +48,20 @@ class MinifyNamer extends Namer {
return freshName;
}
String getClosureVariableName(String name, int id) {
String getClosureVariableName(String _, int id) {
if (id < ALPHABET_CHARACTERS) {
return new String.fromCharCodes([_letterNumber(id)]);
}
return "${getMappedInstanceName('closure')}_$id";
// Fall back to a slightly longer name.
String basename = _disambiguateMember(null, 'closure');
return '${basename}_$id';
}
// From issue 7554. These should not be used on objects (as instance
// variables) because they clash with names from the DOM. However, it is
// OK to use them as fields, as we only access fields directly if we know
// the receiver type.
static const _reservedNativeProperties = const <String>[
static const List<String> _reservedNativeProperties = const <String>[
'Q', 'a', 'b', 'c', 'd', 'e', 'f', 'r', 'x', 'y', 'z',
// 2-letter:
'ch', 'cx', 'cy', 'db', 'dx', 'dy', 'fr', 'fx', 'fy', 'go', 'id', 'k1',
@ -80,9 +86,11 @@ class MinifyNamer extends Namer {
'Text', 'time', 'type', 'view', 'warn', 'wrap', 'ZERO'];
void reserveBackendNames() {
for (var name in _reservedNativeProperties) {
for (String name in _reservedNativeProperties) {
if (name.length < 2) {
instanceNameMap[name] = name;
// Ensure the 1-letter names are disambiguated to the same name.
String disambiguatedName = name;
reservePublicMemberName(name, disambiguatedName);
}
usedInstanceNames.add(name);
// Getter and setter names are autogenerated by prepending 'g' and 's' to
@ -166,12 +174,12 @@ class MinifyNamer extends Namer {
// in a predictable order determined by the proposed name. This is in order
// to make the renamer stable: small changes in the input should nornally
// result in relatively small changes in the output.
for (var n = 1; n <= 3; n++) {
for (int n = 1; n <= 3; n++) {
int h = hash;
while (h > 10) {
var codes = <int>[_letterNumber(h)];
List<int> codes = <int>[_letterNumber(h)];
int h2 = h ~/ ALPHABET_CHARACTERS;
for (var i = 1; i < n; i++) {
for (int i = 1; i < n; i++) {
codes.add(_alphaNumericNumber(h2));
h2 ~/= ALPHANUMERIC_CHARACTERS;
}
@ -213,9 +221,9 @@ class MinifyNamer extends Namer {
/// If we can't find a hash based name in the three-letter space, then base
/// the name on a letter and a counter.
String _badName(int hash, Set<String> usedNames) {
var startLetter = new String.fromCharCodes([_letterNumber(hash)]);
var name;
var i = 0;
String startLetter = new String.fromCharCodes([_letterNumber(hash)]);
String name;
int i = 0;
do {
name = "$startLetter${i++}";
} while (usedNames.contains(name));
@ -291,8 +299,7 @@ class _FieldNamingRegistry {
nameStore.add(MinifyNamer._reservedNativeProperties[count]);
} else {
nameStore.add(namer.getFreshName("field$count",
namer.usedInstanceNames, namer.suggestedInstanceNames,
ensureSafe: true));
namer.usedInstanceNames, namer.suggestedInstanceNames));
}
}
@ -422,7 +429,7 @@ class _MixinFieldNamingScope extends _FieldNamingScope {
: super.inherit(container, superScope, registry);
String _nextName() {
var proposed = super._nextName();
String proposed = super._nextName();
return proposed + r'$';
}
}

File diff suppressed because it is too large Load diff

View file

@ -33,7 +33,7 @@ class RuntimeTypes {
JavaScriptBackend get backend => compiler.backend;
String get getFunctionThatReturnsNullName
=> backend.namer.getMappedInstanceName('functionThatReturnsNull');
=> backend.namer.internalGlobal('functionThatReturnsNull');
RuntimeTypes(Compiler compiler)
: this.compiler = compiler,
@ -401,7 +401,7 @@ class RuntimeTypes {
String getTypeRepresentationForTypeConstant(DartType type) {
JavaScriptBackend backend = compiler.backend;
Namer namer = backend.namer;
if (type.isDynamic) return namer.getRuntimeTypeName(null);
if (type.isDynamic) return namer.runtimeTypeName(null);
String name = namer.uniqueNameForTypeConstantElement(type.element);
if (!type.element.isClass) return name;
InterfaceType interface = type;
@ -541,7 +541,7 @@ class RuntimeTypes {
getTypeEncoding(type, alwaysGenerateFunction: true);
if (contextClass != null) {
JavaScriptBackend backend = compiler.backend;
String contextName = backend.namer.getNameOfClass(contextClass);
String contextName = backend.namer.className(contextClass);
return js('function () { return #(#, #, #); }',
[ backend.emitter.staticFunctionAccess(backend.getComputeSignature()),
encoding, this_, js.string(contextName) ]);

View file

@ -62,7 +62,7 @@ class ClassStubGenerator {
jsAst.Expression receiver =
js(isInterceptorClass ? receiverArgumentName : 'this');
if (member.isGetter) {
String getterName = namer.getterName(member);
String getterName = namer.getterForElement(member);
if (isInterceptedMethod) {
return js('this.#(#)', [getterName, receiver]);
}

View file

@ -291,8 +291,7 @@ class InterceptorStubGenerator {
Selector selector = backend.oneShotInterceptors[name];
Set<ClassElement> classes =
backend.getInterceptedClassesOn(selector.name);
String getInterceptorName =
namer.getInterceptorName(backend.getInterceptorMethod, classes);
String getInterceptorName = namer.nameForGetInterceptor(classes);
List<String> parameterNames = <String>[];
parameterNames.add('receiver');

View file

@ -66,7 +66,7 @@ class Emitter implements emitterTask.Emitter {
}
js.PropertyAccess _globalPropertyAccess(Element element) {
String name = namer.getNameX(element);
String name = namer.globalPropertyName(element);
js.PropertyAccess pa = new js.PropertyAccess.field(
new js.VariableUse(namer.globalObjectFor(element)),
name);
@ -76,7 +76,7 @@ class Emitter implements emitterTask.Emitter {
@override
js.Expression isolateLazyInitializerAccess(FieldElement element) {
return js.js('#.#', [namer.globalObjectFor(element),
namer.getLazyInitializerName(element)]);
namer.lazyInitializerName(element)]);
}
@override

View file

@ -103,7 +103,7 @@ class ModelEmitter {
js.Expression generateStaticClosureAccess(FunctionElement element) {
return js.js('#.#()',
[namer.globalObjectFor(element), namer.getStaticClosureName(element)]);
[namer.globalObjectFor(element), namer.staticClosureName(element)]);
}
js.Expression generateConstantReference(ConstantValue value) {
@ -320,7 +320,7 @@ class ModelEmitter {
compiler.stringClass, compiler.boolClass, compiler.nullClass,
compiler.listClass];
nativeClassesNeedingUnmangledName.forEach((element) {
names.add(new js.Property(js.string(namer.getNameOfClass(element)),
names.add(new js.Property(js.string(namer.className(element)),
js.string(element.name)));
});

View file

@ -22,7 +22,7 @@ class ClassEmitter extends CodeEmitterHelper {
ClassElement superclass = classElement.superclass;
String superName = "";
if (superclass != null) {
superName = namer.getNameOfClass(superclass);
superName = namer.className(superclass);
}
if (cls.isMixinApplication) {
@ -44,6 +44,14 @@ class ClassEmitter extends CodeEmitterHelper {
emitRuntimeTypeInformation(cls, builder);
emitNativeInfo(cls, builder);
if (classElement == backend.closureClass) {
// We add a special getter here to allow for tearing off a closure from
// itself.
jsAst.Fun function = js('function() { return this; }');
String name = namer.getterForPublicMember(Compiler.CALL_OPERATOR_NAME);
builder.addProperty(name, function);
}
emitClassBuilderWithReflectionData(cls, builder, enclosingBuilder);
}
/**
@ -63,7 +71,7 @@ class ClassEmitter extends CodeEmitterHelper {
jsAst.Expression constructorAst =
_stubGenerator.generateClassConstructor(classElement, fieldNames);
String constructorName = namer.getNameOfClass(classElement);
String constructorName = namer.className(classElement);
OutputUnit outputUnit =
compiler.deferredLoadTask.outputUnitForElement(classElement);
emitter.emitPrecompiledConstructor(
@ -134,14 +142,14 @@ class ClassEmitter extends CodeEmitterHelper {
if (field.needsInterceptedGetter) {
emitter.interceptorEmitter.interceptorInvocationNames.add(
namer.getterName(fieldElement));
namer.getterForElement(fieldElement));
}
// TODO(16168): The setter creator only looks at the getter-name.
// Even though the setter could avoid the interceptor convention we
// currently still need to add the additional argument.
if (field.needsInterceptedGetter || field.needsInterceptedSetter) {
emitter.interceptorEmitter.interceptorInvocationNames.add(
namer.setterName(fieldElement));
namer.setterForElement(fieldElement));
}
int code = field.getterFlags + (field.setterFlags << 2);
@ -483,7 +491,7 @@ class ClassEmitter extends CodeEmitterHelper {
ClassBuilder builder) {
jsAst.Expression code = backend.generatedCode[member];
assert(code != null);
String setterName = namer.setterNameFromAccessorName(accessorName);
String setterName = namer.deriveSetterName(accessorName);
compiler.dumpInfoTask.registerElementAst(member,
builder.addProperty(setterName, code));
generateReflectionDataForFieldGetterOrSetter(
@ -495,9 +503,9 @@ class ClassEmitter extends CodeEmitterHelper {
jsAst.Expression function =
_stubGenerator.generateGetter(member, fieldName);
String getterName = namer.getterNameFromAccessorName(accessorName);
String getterName = namer.deriveGetterName(accessorName);
ClassElement cls = member.enclosingClass;
String className = namer.getNameOfClass(cls);
String className = namer.className(cls);
OutputUnit outputUnit =
compiler.deferredLoadTask.outputUnitForElement(member);
emitter.cspPrecompiledFunctionFor(outputUnit).add(
@ -514,9 +522,9 @@ class ClassEmitter extends CodeEmitterHelper {
jsAst.Expression function =
_stubGenerator.generateSetter(member, fieldName);
String setterName = namer.setterNameFromAccessorName(accessorName);
String setterName = namer.deriveSetterName(accessorName);
ClassElement cls = member.enclosingClass;
String className = namer.getNameOfClass(cls);
String className = namer.className(cls);
OutputUnit outputUnit =
compiler.deferredLoadTask.outputUnitForElement(member);
emitter.cspPrecompiledFunctionFor(outputUnit).add(

View file

@ -194,8 +194,7 @@ class OldEmitter implements Emitter {
=> '${namer.isolateName}.${lazyInitializerProperty}';
String get initName => 'init';
String get makeConstListProperty
=> namer.getMappedInstanceName('makeConstantList');
String get makeConstListProperty => namer.internalGlobal('makeConstantList');
/// The name of the property that contains all field names.
///
@ -205,8 +204,9 @@ class OldEmitter implements Emitter {
/// For deferred loading we communicate the initializers via this global var.
final String deferredInitializers = r"$dart_deferred_initializers";
/// All the global state can be passed around with this variable.
String get globalsHolder => namer.getMappedGlobalName("globalsHolder");
/// Contains the global state that is needed to initialize and load a
/// deferred library.
String get globalsHolder => namer.internalGlobal("globalsHolder");
@override
jsAst.Expression generateEmbeddedGlobalAccess(String global) {
@ -219,7 +219,7 @@ class OldEmitter implements Emitter {
}
jsAst.PropertyAccess globalPropertyAccess(Element element) {
String name = namer.getNameX(element);
String name = namer.globalPropertyName(element);
jsAst.PropertyAccess pa = new jsAst.PropertyAccess.field(
new jsAst.VariableUse(namer.globalObjectFor(element)),
name);
@ -229,13 +229,13 @@ class OldEmitter implements Emitter {
@override
jsAst.Expression isolateLazyInitializerAccess(FieldElement element) {
return jsAst.js('#.#', [namer.globalObjectFor(element),
namer.getLazyInitializerName(element)]);
namer.lazyInitializerName(element)]);
}
@override
jsAst.Expression isolateStaticClosureAccess(FunctionElement element) {
return jsAst.js('#.#()',
[namer.globalObjectFor(element), namer.getStaticClosureName(element)]);
[namer.globalObjectFor(element), namer.staticClosureName(element)]);
}
@override
@ -772,7 +772,7 @@ class OldEmitter implements Emitter {
void emitInitialization(Element element, jsAst.Expression initialValue) {
jsAst.Expression init =
js('$isolateProperties.# = #',
[namer.getNameOfGlobalField(element), initialValue]);
[namer.globalPropertyName(element), initialValue]);
output.addBuffer(jsAst.prettyPrint(init, compiler,
monitor: compiler.dumpInfoTask));
output.add('$N');
@ -841,8 +841,8 @@ class OldEmitter implements Emitter {
[js(lazyInitializerName),
js(isolateProperties),
js.string(element.name),
js.string(namer.getNameX(element)),
js.string(namer.getLazyInitializerName(element)),
js.string(namer.globalPropertyName(element)),
js.string(namer.lazyInitializerName(element)),
code]);
}
@ -1223,9 +1223,9 @@ class OldEmitter implements Emitter {
// typedefs are only emitted with reflection, which requires lots of
// classes.
assert(compiler.objectClass != null);
builder.superName = namer.getNameOfClass(compiler.objectClass);
builder.superName = namer.className(compiler.objectClass);
jsAst.Node declaration = builder.toObjectInitializer();
String mangledName = namer.getNameX(typedef);
String mangledName = namer.globalPropertyName(typedef);
String reflectionName = getReflectionName(typedef, mangledName);
getElementDescriptor(library)
..addProperty(mangledName, declaration)

View file

@ -260,7 +260,7 @@ class NsmEmitter extends CodeEmitterHelper {
}
shortNames.splice.apply(shortNames, calculatedShortNames);
}
}''', {'objectClass': js.string(namer.getNameOfClass(objectClass)),
}''', {'objectClass': js.string(namer.className(objectClass)),
'diffEncoding': js.string('$diffEncoding')}));
} else {
// No useDiffEncoding version.
@ -269,7 +269,7 @@ class NsmEmitter extends CodeEmitterHelper {
statements.add(js.statement(
'var objectClassObject = processedClasses.collected[#objectClass],'
' shortNames = #diffEncoding.split(",")',
{'objectClass': js.string(namer.getNameOfClass(objectClass)),
{'objectClass': js.string(namer.className(objectClass)),
'diffEncoding': js.string('$diffEncoding')}));
if (!minify) {
statements.add(js.statement('var longNames = #longs.split(",")',

View file

@ -59,7 +59,7 @@ class ParameterStubGenerator {
// If the method is intercepted, we need to also pass the actual receiver.
int extraArgumentCount = isInterceptedMethod ? 1 : 0;
// Use '$receiver' to avoid clashes with other parameter names. Using
// '$receiver' works because [:namer.safeName:] used for getting parameter
// '$receiver' works because namer.safeVariableName used for getting parameter
// names never returns a name beginning with a single '$'.
String receiverArgumentName = r'$receiver';
@ -84,7 +84,7 @@ class ParameterStubGenerator {
int parameterIndex = 0;
parameters.orderedForEachParameter((ParameterElement element) {
String jsName = backend.namer.safeName(element.name);
String jsName = backend.namer.safeVariableName(element.name);
assert(jsName != receiverArgumentName);
if (count < optionalParameterStart) {
parametersBuffer[count] = new jsAst.Parameter(jsName);
@ -126,7 +126,7 @@ class ParameterStubGenerator {
} else if (member.isInstanceMember) {
if (needsSuperGetter(member)) {
ClassElement superClass = member.enclosingClass;
String methodName = namer.getNameOfInstanceMember(member);
String methodName = namer.instanceMethodName(member);
// When redirecting, we must ensure that we don't end up in a subclass.
// We thus can't just invoke `this.foo$1.call(filledInArguments)`.
// Instead we need to call the statically resolved target.
@ -140,7 +140,7 @@ class ParameterStubGenerator {
} else {
body = js.statement(
'return this.#(#);',
[namer.getNameOfInstanceMember(member), argumentsBuffer]);
[namer.instanceMethodName(member), argumentsBuffer]);
}
} else {
body = js.statement('return #(#)',

View file

@ -216,7 +216,7 @@ class ProgramBuilder {
// a static field.
_registry.registerHolder(namer.globalObjectForConstant(initialValue));
js.Expression code = _task.emitter.constantReference(initialValue);
String name = namer.getNameOfGlobalField(element);
String name = namer.globalPropertyName(element);
bool isFinal = false;
bool isLazy = false;
@ -252,7 +252,7 @@ class ProgramBuilder {
// before code generation.
if (code == null) return null;
String name = namer.getNameOfGlobalField(element);
String name = namer.globalPropertyName(element);
bool isFinal = element.isFinal;
bool isLazy = true;
// TODO(floitsch): we shouldn't update the registry in the middle of
@ -308,7 +308,7 @@ class ProgramBuilder {
assert(_compiler.hasIncrementalSupport);
List<Field> instanceFields = _buildFields(element, false);
String name = namer.getNameOfClass(element);
String name = namer.className(element);
return new Class(
element, name, null, [], instanceFields, [], [], [], [], [], null,
@ -369,8 +369,7 @@ class ProgramBuilder {
if (element == backend.closureClass) {
// We add a special getter here to allow for tearing off a closure from
// itself.
String name = namer.getterNameFromAccessorName(
namer.getMappedInstanceName(Compiler.CALL_OPERATOR_NAME));
String name = namer.getterForPublicMember(Compiler.CALL_OPERATOR_NAME);
js.Fun function = js.js('function() { return this; }');
callStubs.add(_buildStubMethod(name, function));
}
@ -398,7 +397,7 @@ class ProgramBuilder {
isChecks.add(_buildStubMethod(name, code));
});
String name = namer.getNameOfClass(element);
String name = namer.className(element);
String holderName = namer.globalObjectFor(element);
// TODO(floitsch): we shouldn't update the registry in the middle of
// building a class.
@ -485,7 +484,7 @@ class ProgramBuilder {
}
DartMethod _buildMethod(FunctionElement element) {
String name = namer.getNameOfInstanceMember(element);
String name = namer.methodPropertyName(element);
js.Expression code = backend.generatedCode[element];
// TODO(kasperl): Figure out under which conditions code is null.
@ -501,7 +500,7 @@ class ProgramBuilder {
bool canBeApplied = _methodCanBeApplied(element);
String aliasName = backend.isAliasedSuperMember(element)
? namer.getNameOfAliasedSuperMember(element)
? namer.aliasedSuperMemberPropertyName(element)
: null;
if (isNotApplyTarget) {
@ -516,7 +515,7 @@ class ProgramBuilder {
(canBeReflected && !element.isOperator);
assert(canTearOff ||
!universe.methodsNeedingSuperGetter.contains(element));
tearOffName = namer.getterName(element);
tearOffName = namer.getterForElement(element);
}
}
@ -692,7 +691,7 @@ class ProgramBuilder {
}
StaticDartMethod _buildStaticMethod(FunctionElement element) {
String name = namer.getNameOfMember(element);
String name = namer.methodPropertyName(element);
String holder = namer.globalObjectFor(element);
js.Expression code = backend.generatedCode[element];
@ -705,7 +704,7 @@ class ProgramBuilder {
universe.staticFunctionsNeedingGetter.contains(element));
String tearOffName =
needsTearOff ? namer.getStaticClosureName(element) : null;
needsTearOff ? namer.staticClosureName(element) : null;
String callName = null;

View file

@ -284,7 +284,7 @@ class RuntimeTypeGenerator {
StubMethod _generateTypeVariableReader(ClassElement cls,
TypeVariableElement element) {
String name = namer.readTypeVariableName(element);
String name = namer.nameForReadTypeVariable(element);
int index = RuntimeTypes.getTypeVariableIndex(element);
jsAst.Expression computeTypeVariable;

View file

@ -3943,15 +3943,15 @@ class SsaBuilder extends ResolvedVisitor {
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);
String name = backend.namer.runtimeTypeName(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);
String name = backend.namer.runtimeTypeName(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);
String name = backend.namer.runtimeTypeName(compiler.functionClass);
stack.add(addConstantString(name));
} else if (name == 'JS_OPERATOR_AS_PREFIX') {
// TODO(floitsch): this should be a JS_NAME.
@ -4148,7 +4148,7 @@ class SsaBuilder extends ResolvedVisitor {
// TODO(ahe): Creating a string here is unfortunate. It is slow (due to
// string concatenation in the implementation), and may prevent
// segmentation of '$'.
String substitutionNameString = backend.namer.getNameForRti(cls);
String substitutionNameString = backend.namer.runtimeTypeName(cls);
HInstruction substitutionName = graph.addConstantString(
new ast.LiteralDartString(substitutionNameString), compiler);
pushInvokeStatic(null,

View file

@ -1473,8 +1473,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
void visitInterceptor(HInterceptor node) {
registry.registerSpecializedGetInterceptor(node.interceptedClasses);
String name = backend.namer.getInterceptorName(
backend.getInterceptorMethod, node.interceptedClasses);
String name = backend.namer.nameForGetInterceptor(node.interceptedClasses);
var isolate = new js.VariableUse(
backend.namer.globalObjectFor(backend.interceptorsLibrary));
use(node.receiver);
@ -1520,7 +1519,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
void visitInvokeConstructorBody(HInvokeConstructorBody node) {
use(node.inputs[0]);
js.Expression object = pop();
String methodName = backend.namer.getNameOfInstanceMember(node.element);
String methodName = backend.namer.instanceMethodName(node.element);
List<js.Expression> arguments = visitArguments(node.inputs);
push(js.propertyCall(object, methodName, arguments), node);
registry.registerStaticUse(node.element);
@ -1660,7 +1659,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
methodName = backend.namer.invocationName(selector);
} else {
assert(invariant(node, compiler.hasIncrementalSupport));
methodName = backend.namer.getNameOfInstanceMember(superMethod);
methodName = backend.namer.instanceMethodName(superMethod);
}
push(js.js('#.#.call(#)',
[backend.emitter.prototypeAccess(superClass,
@ -1671,7 +1670,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
use(node.receiver);
push(
js.js('#.#(#)', [
pop(), backend.namer.getNameOfAliasedSuperMember(superMethod),
pop(), backend.namer.aliasedSuperMemberPropertyName(superMethod),
visitArguments(node.inputs, start: 1)]), // Skip receiver argument.
node);
}
@ -2632,7 +2631,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
} else {
backend.emitter.registerReadTypeVariable(element);
push(js.js('#.#()',
[pop(), backend.namer.readTypeVariableName(element)]));
[pop(), backend.namer.nameForReadTypeVariable(element)]));
}
} else {
push(js.js('#(#)', [

View file

@ -289,7 +289,8 @@ class HInstructionStringifier implements HVisitor<String> {
String value = temporaryId(node.inputs[0]);
if (node.interceptedClasses != null) {
JavaScriptBackend backend = compiler.backend;
String cls = backend.namer.getInterceptorSuffix(node.interceptedClasses);
String cls =
backend.namer.suffixForGetInterceptor(node.interceptedClasses);
return "Intercept ($cls): $value";
}
return "Intercept: $value";

View file

@ -85,8 +85,7 @@ void main() {
compiler.listClass
];
JavaScriptBackend backend = compiler.backend;
Iterable<String> nativeNames =
nativeClasses.map(backend.namer.getNameOfClass);
Iterable<String> nativeNames = nativeClasses.map(backend.namer.className);
expectedNames.addAll(nativeNames);
Set recordedNames = new Set()

View file

@ -0,0 +1,47 @@
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// 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 custom_elements_method_clash;
import 'dart:async';
import 'dart:html';
import 'package:unittest/html_individual_config.dart';
import 'package:unittest/unittest.dart';
import 'utils.dart';
class CustomElement extends HtmlElement {
factory CustomElement() => new Element.tag('x-custom');
CustomElement.created() : super.created() {
}
// Try to clash with native 'appendChild' method.
void appendChild() {
throw 'Gotcha!';
}
}
main() {
useHtmlIndividualConfiguration();
setUp(() => customElementsReady);
group('test', () {
test('test', () {
document.registerElement('x-custom', CustomElement);
CustomElement custom = new CustomElement();
document.body.children.add(custom);
// Will call appendChild in JS.
custom.children.add(new DivElement()..text = 'Hello world!');
try {
custom.appendChild(); // Make sure method is not tree shaken.
fail('appendChild did not throw');
} catch(e) {
expect(e, equals('Gotcha!'));
}
});
});
}

View file

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> custom_element_method_clash_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running custom_element_method_clash_test </h1>
<script type="text/javascript"
src="/root_dart/tools/testing/dart/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -0,0 +1,39 @@
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// 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 custom_elements_name_clash;
import 'dart:async';
import 'dart:html';
import 'package:unittest/html_individual_config.dart';
import 'package:unittest/unittest.dart';
import 'utils.dart';
class CustomElement extends HtmlElement {
factory CustomElement() => new Element.tag('x-custom');
CustomElement.created() : super.created() {
}
// Try to clash with native 'appendChild' method.
var appendChild = 123;
}
main() {
useHtmlIndividualConfiguration();
setUp(() => customElementsReady);
group('test', () {
test('test', () {
document.registerElement('x-custom', CustomElement);
CustomElement custom = new CustomElement();
document.body.children.add(custom);
// Will call appendChild in JS.
custom.children.add(new DivElement()..text = 'Hello world!');
});
});
}

View file

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> custom_element_name_clash_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running custom_element_name_clash_test </h1>
<script type="text/javascript"
src="/root_dart/tools/testing/dart/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -0,0 +1,14 @@
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// 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 lib;
var global = 0;
class A {
A() {
global += 10;
try {} catch(e) {} // no inline
}
}

View file

@ -0,0 +1,18 @@
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// 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.
import 'package:expect/expect.dart';
import 'constructor_name_clash_lib.dart' as lib;
class A extends lib.A {
A() {
lib.global += 100;
try {} catch(e) {} // no inline
}
}
main() {
new A();
Expect.equals(110, lib.global);
}

View file

@ -0,0 +1,47 @@
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// 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.
import "package:expect/expect.dart";
class A {
}
class $B extends A {
}
class C implements $B {
// Try to clash with dart2js's isCLASS field.
var isB = false;
var $isB = false;
var is$B = false;
var is$$B = false;
var $is$B = false;
var isA = false;
var $isA = false;
var is$A = false;
var is$$A = false;
var $is$A = false;
}
int inscrutable(int x) => x == 0 ? 0 : x | inscrutable(x & (x - 1));
main() {
var things = [new A(), new $B(), new C()];
var a = things[inscrutable(0)];
Expect.isTrue(a is A);
Expect.isFalse(a is $B);
Expect.isFalse(a is C);
var b = things[inscrutable(1)];
Expect.isTrue(b is A);
Expect.isTrue(b is $B);
Expect.isFalse(b is C);
var c = things[inscrutable(2)];
Expect.isTrue(c is A);
Expect.isTrue(c is $B);
Expect.isTrue(c is C);
}

View file

@ -0,0 +1,36 @@
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// 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.
import 'package:expect/expect.dart';
class Foo {
m({a, b, c}) {
try {} catch(e) {} // no inline
return 'Foo $a $b $c';
}
}
class Bar {
m(z, {a$b, c}) {
try {} catch(e) {} // no inline
var ab = a$b;
return 'Bar $z $ab $c';
}
}
inscrutable(xs, i) => i == 0 ? xs[0] : inscrutable(xs.sublist(1), i-1);
main() {
var list = [new Foo(), new Bar()];
var foo = inscrutable(list, 0);
var bar = inscrutable(list, 1);
Expect.equals(r'Foo a b c', foo.m(a: 'a', b: 'b', c: 'c'));
Expect.equals(r'Bar z a$b c', bar.m('z', a$b: r'a$b', c: 'c'));
Expect.throws(() => foo.m('z', a$b: r'a$b', c: 'c'),
(e) => e is NoSuchMethodError);
Expect.throws(() => bar.m(a: 'a', b: 'b', c: 'c'),
(e) => e is NoSuchMethodError);
}

View file

@ -0,0 +1,14 @@
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// 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 a$_b;
class B {
var _c$ = 10; // With library prefix: _a$_b$_c$
getValueA() {
try {} catch(e) {} // no inline
return this._c$;
}
}

View file

@ -0,0 +1,22 @@
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// 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 a;
import 'private_clash_lib.dart' as lib;
import 'package:expect/expect.dart';
class A extends lib.B {
var _b$_c$ = 100; // With library prefix: _a$_b$_c$
getValueB() {
try {} catch(e) {} // no inline
return this._b$_c$;
}
}
main() {
A a = new A();
Expect.equals(110, a.getValueA() + a.getValueB());
}