Index: lib/compiler/implementation/compile_time_constants.dart |
diff --git a/lib/compiler/implementation/compile_time_constants.dart b/lib/compiler/implementation/compile_time_constants.dart |
index c21e47d72051bfeb6451f9a281f533594e4b0ca0..81627ab520206b6d6d0dfb4ddf0ed165a18c3151 100644 |
--- a/lib/compiler/implementation/compile_time_constants.dart |
+++ b/lib/compiler/implementation/compile_time_constants.dart |
@@ -17,8 +17,8 @@ class ConstantHandler extends CompilerTask { |
*/ |
final Map<VariableElement, Constant> initialVariableValues; |
- /** Set of all registered compiled constants. */ |
- final Set<Constant> compiledConstants; |
+ /** Map from compile-time constants to their JS name. */ |
+ final Map<Constant, String> compiledConstants; |
/** The set of variable elements that are in the process of being computed. */ |
final Set<VariableElement> pendingVariables; |
@@ -29,14 +29,18 @@ class ConstantHandler extends CompilerTask { |
ConstantHandler(Compiler compiler, this.constantSystem) |
: initialVariableValues = new Map<VariableElement, Dynamic>(), |
- compiledConstants = new Set<Constant>(), |
+ compiledConstants = new Map<Constant, String>(), |
pendingVariables = new Set<VariableElement>(), |
lazyStatics = new Set<VariableElement>(), |
super(compiler); |
String get name => 'ConstantHandler'; |
void registerCompileTimeConstant(Constant constant) { |
- compiledConstants.add(constant); |
+ Function ifAbsentThunk = (() { |
+ return constant.isFunction() |
+ ? null : compiler.namer.getFreshGlobalName("CTC"); |
+ }); |
+ compiledConstants.putIfAbsent(constant, ifAbsentThunk); |
} |
/** |
@@ -208,17 +212,91 @@ class ConstantHandler extends CompilerTask { |
} |
} |
- compiledConstants.forEach(addConstant); |
+ compiledConstants.forEach((Constant key, ignored) => addConstant(key)); |
return result; |
} |
- Constant getInitialValueFor(VariableElement element) { |
- Constant initialValue = initialVariableValues[element]; |
- if (initialValue === null) { |
+ String getNameForConstant(Constant constant) { |
+ return compiledConstants[constant]; |
+ } |
+ |
+ /** This function writes the constant in non-canonicalized form. */ |
+ CodeBuffer writeJsCode(CodeBuffer buffer, Constant value) { |
+ value._writeJsCode(buffer, this); |
+ return buffer; |
+ } |
+ |
+ CodeBuffer writeConstant(CodeBuffer buffer, Constant value) { |
+ value._writeCanonicalizedJsCode(buffer, this); |
+ return buffer; |
+ } |
+ |
+ CodeBuffer writeJsCodeForVariable(CodeBuffer buffer, |
+ VariableElement element) { |
+ if (!initialVariableValues.containsKey(element)) { |
compiler.internalError("No initial value for given element", |
element: element); |
} |
- return initialValue; |
+ Constant constant = initialVariableValues[element]; |
+ writeConstant(buffer, constant); |
+ return buffer; |
+ } |
+ |
+ /** |
+ * Write the contents of the quoted string to a [CodeBuffer] in |
+ * a form that is valid as JavaScript string literal content. |
+ * The string is assumed quoted by single quote characters. |
+ */ |
+ static void writeEscapedString(DartString string, |
+ CodeBuffer buffer, |
+ void cancel(String reason)) { |
+ Iterator<int> iterator = string.iterator(); |
+ while (iterator.hasNext()) { |
+ int code = iterator.next(); |
+ if (code === $SQ) { |
+ buffer.add(@"\'"); |
+ } else if (code === $LF) { |
+ buffer.add(@'\n'); |
+ } else if (code === $CR) { |
+ buffer.add(@'\r'); |
+ } else if (code === $LS) { |
+ // This Unicode line terminator and $PS are invalid in JS string |
+ // literals. |
+ buffer.add(@'\u2028'); |
+ } else if (code === $PS) { |
+ buffer.add(@'\u2029'); |
+ } else if (code === $BACKSLASH) { |
+ buffer.add(@'\\'); |
+ } else { |
+ if (code > 0xffff) { |
+ cancel('Unhandled non-BMP character: U+${code.toRadixString(16)}'); |
+ } |
+ // TODO(lrn): Consider whether all codes above 0x7f really need to |
+ // be escaped. We build a Dart string here, so it should be a literal |
+ // stage that converts it to, e.g., UTF-8 for a JS interpreter. |
+ if (code < 0x20) { |
+ buffer.add(@'\x'); |
+ if (code < 0x10) buffer.add('0'); |
+ buffer.add(code.toRadixString(16)); |
+ } else if (code >= 0x80) { |
+ if (code < 0x100) { |
+ buffer.add(@'\x'); |
+ } else { |
+ buffer.add(@'\u'); |
+ if (code < 0x1000) { |
+ buffer.add('0'); |
+ } |
+ } |
+ buffer.add(code.toRadixString(16)); |
+ } else { |
+ buffer.addCharCode(code); |
+ } |
+ } |
+ } |
+ } |
+ |
+ String getJsConstructor(ClassElement element) { |
+ return compiler.namer.isolatePropertiesAccess(element); |
} |
} |
@@ -303,7 +381,7 @@ class CompileTimeConstantEvaluator extends AbstractVisitor { |
List<Constant> values = <Constant>[]; |
Constant protoValue = null; |
for (StringConstant key in keys) { |
- if (key.value == MapConstant.PROTO_PROPERTY) { |
+ if (key.value == const LiteralDartString(MapConstant.PROTO_PROPERTY)) { |
protoValue = map[key]; |
} else { |
values.add(map[key]); |