| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of js_backend; | 5 part of js_backend; |
| 6 | 6 |
| 7 class ConstantEmitter { | 7 class ConstantEmitter { |
| 8 ConstantReferenceEmitter _referenceEmitter; | 8 ConstantReferenceEmitter _referenceEmitter; |
| 9 ConstantInitializerEmitter _initializerEmitter; | 9 ConstantLiteralEmitter _literalEmitter; |
| 10 | 10 |
| 11 ConstantEmitter(Compiler compiler, Namer namer) { | 11 ConstantEmitter(Compiler compiler, Namer namer) { |
| 12 _referenceEmitter = new ConstantReferenceEmitter(compiler, namer); | 12 _literalEmitter = new ConstantLiteralEmitter(compiler, namer, this); |
| 13 _initializerEmitter = new ConstantInitializerEmitter( | 13 _referenceEmitter = new ConstantReferenceEmitter(compiler, namer, this); |
| 14 compiler, namer, _referenceEmitter); | |
| 15 } | 14 } |
| 16 | 15 |
| 17 /** | 16 /** |
| 18 * Constructs an expression that is a reference to the constant. Uses a | 17 * Constructs an expression that is a reference to the constant. Uses a |
| 19 * canonical name unless the constant can be emitted multiple times (as for | 18 * canonical name unless the constant can be emitted multiple times (as for |
| 20 * numbers and strings). | 19 * numbers and strings). |
| 21 */ | 20 */ |
| 22 jsAst.Expression reference(Constant constant) { | 21 jsAst.Expression reference(Constant constant) { |
| 23 return _referenceEmitter.generate(constant); | 22 return _referenceEmitter.generate(constant); |
| 24 } | 23 } |
| 25 | 24 |
| 26 /** | 25 /** |
| 26 * Constructs a literal expression that evaluates to the constant. Uses a |
| 27 * canonical name unless the constant can be emitted multiple times (as for |
| 28 * numbers and strings). |
| 29 */ |
| 30 jsAst.Expression literal(Constant constant) { |
| 31 return _literalEmitter.generate(constant); |
| 32 } |
| 33 |
| 34 /** |
| 27 * Constructs an expression like [reference], but the expression is valid | 35 * Constructs an expression like [reference], but the expression is valid |
| 28 * during isolate initialization. | 36 * during isolate initialization. |
| 29 */ | 37 */ |
| 30 jsAst.Expression referenceInInitializationContext(Constant constant) { | 38 jsAst.Expression referenceInInitializationContext(Constant constant) { |
| 31 return _referenceEmitter.generateInInitializationContext(constant); | 39 return _referenceEmitter.generate(constant); |
| 32 } | 40 } |
| 33 | 41 |
| 34 /** | 42 /** |
| 35 * Constructs an expression used to initialize a canonicalized constant. | 43 * Constructs an expression used to initialize a canonicalized constant. |
| 36 */ | 44 */ |
| 37 jsAst.Expression initializationExpression(Constant constant) { | 45 jsAst.Expression initializationExpression(Constant constant) { |
| 38 return _initializerEmitter.generate(constant); | 46 return _literalEmitter.generate(constant); |
| 39 } | 47 } |
| 40 } | 48 } |
| 41 | 49 |
| 42 /** | 50 /** |
| 43 * Visitor for generating JavaScript expressions to refer to [Constant]s. | 51 * Visitor for generating JavaScript expressions to refer to [Constant]s. |
| 44 * Do not use directly, use methods from [ConstantEmitter]. | 52 * Do not use directly, use methods from [ConstantEmitter]. |
| 45 */ | 53 */ |
| 46 class ConstantReferenceEmitter implements ConstantVisitor<jsAst.Expression> { | 54 class ConstantReferenceEmitter implements ConstantVisitor<jsAst.Expression> { |
| 47 final Compiler compiler; | 55 final Compiler compiler; |
| 48 final Namer namer; | 56 final Namer namer; |
| 49 | 57 |
| 50 ConstantReferenceEmitter(this.compiler, this.namer); | 58 final ConstantEmitter constantEmitter; |
| 59 |
| 60 ConstantReferenceEmitter(this.compiler, this.namer, this.constantEmitter); |
| 51 | 61 |
| 52 jsAst.Expression generate(Constant constant) { | 62 jsAst.Expression generate(Constant constant) { |
| 53 return _visit(constant); | 63 return _visit(constant); |
| 54 } | 64 } |
| 55 | 65 |
| 56 jsAst.Expression generateInInitializationContext(Constant constant) { | |
| 57 return _visit(constant); | |
| 58 } | |
| 59 | |
| 60 jsAst.Expression _visit(Constant constant) { | 66 jsAst.Expression _visit(Constant constant) { |
| 61 return constant.accept(this); | 67 return constant.accept(this); |
| 62 } | 68 } |
| 63 | 69 |
| 70 jsAst.Expression emitCanonicalVersion(Constant constant) { |
| 71 String name = namer.constantName(constant); |
| 72 return new jsAst.PropertyAccess.field( |
| 73 new jsAst.VariableUse(namer.globalObjectForConstant(constant)), name); |
| 74 } |
| 75 |
| 76 jsAst.Expression literal(Constant constant) { |
| 77 return constantEmitter.literal(constant); |
| 78 } |
| 79 |
| 64 jsAst.Expression visitFunction(FunctionConstant constant) { | 80 jsAst.Expression visitFunction(FunctionConstant constant) { |
| 65 return new jsAst.VariableUse( | 81 return new jsAst.VariableUse( |
| 66 namer.isolateStaticClosureAccess(constant.element)); | 82 namer.isolateStaticClosureAccess(constant.element)); |
| 67 } | 83 } |
| 68 | 84 |
| 69 jsAst.Expression visitNull(NullConstant constant) { | 85 jsAst.Expression visitNull(NullConstant constant) { |
| 70 return new jsAst.LiteralNull(); | 86 return literal(constant); |
| 71 } | 87 } |
| 72 | 88 |
| 73 jsAst.Expression visitInt(IntConstant constant) { | 89 jsAst.Expression visitInt(IntConstant constant) { |
| 74 return new jsAst.LiteralNumber('${constant.value}'); | 90 return literal(constant); |
| 75 } | 91 } |
| 76 | 92 |
| 77 jsAst.Expression visitDouble(DoubleConstant constant) { | 93 jsAst.Expression visitDouble(DoubleConstant constant) { |
| 78 double value = constant.value; | 94 return literal(constant); |
| 79 if (value.isNaN) { | |
| 80 return js("0/0"); | |
| 81 } else if (value == double.INFINITY) { | |
| 82 return js("1/0"); | |
| 83 } else if (value == -double.INFINITY) { | |
| 84 return js("-1/0"); | |
| 85 } else { | |
| 86 return new jsAst.LiteralNumber("$value"); | |
| 87 } | |
| 88 } | 95 } |
| 89 | 96 |
| 90 jsAst.Expression visitTrue(TrueConstant constant) { | 97 jsAst.Expression visitTrue(TrueConstant constant) { |
| 91 if (compiler.enableMinification) { | 98 return literal(constant); |
| 92 // Use !0 for true. | |
| 93 return js("!0"); | |
| 94 } else { | |
| 95 return js('true'); | |
| 96 } | |
| 97 } | 99 } |
| 98 | 100 |
| 99 jsAst.Expression visitFalse(FalseConstant constant) { | 101 jsAst.Expression visitFalse(FalseConstant constant) { |
| 100 if (compiler.enableMinification) { | 102 return literal(constant); |
| 101 // Use !1 for false. | |
| 102 return js("!1"); | |
| 103 } else { | |
| 104 return js('false'); | |
| 105 } | |
| 106 } | 103 } |
| 107 | 104 |
| 108 /** | 105 /** |
| 109 * Write the contents of the quoted string to a [CodeBuffer] in | 106 * Write the contents of the quoted string to a [CodeBuffer] in |
| 110 * a form that is valid as JavaScript string literal content. | 107 * a form that is valid as JavaScript string literal content. |
| 111 * The string is assumed quoted by double quote characters. | 108 * The string is assumed quoted by double quote characters. |
| 112 */ | 109 */ |
| 113 jsAst.Expression visitString(StringConstant constant) { | 110 jsAst.Expression visitString(StringConstant constant) { |
| 114 // TODO(sra): If the string is long *and repeated* (and not on a hot path) | 111 // TODO(sra): If the string is long *and repeated* (and not on a hot path) |
| 115 // then it should be assigned to a name. We don't have reference counts (or | 112 // then it should be assigned to a name. We don't have reference counts (or |
| 116 // profile information) here, so this is the wrong place. | 113 // profile information) here, so this is the wrong place. |
| 117 StringBuffer sb = new StringBuffer(); | 114 return literal(constant); |
| 118 writeJsonEscapedCharsOn(constant.value.slowToString(), sb); | |
| 119 return new jsAst.LiteralString('"$sb"'); | |
| 120 } | |
| 121 | |
| 122 jsAst.Expression emitCanonicalVersion(Constant constant) { | |
| 123 String name = namer.constantName(constant); | |
| 124 return new jsAst.PropertyAccess.field( | |
| 125 new jsAst.VariableUse(namer.globalObjectForConstant(constant)), name); | |
| 126 } | 115 } |
| 127 | 116 |
| 128 jsAst.Expression visitList(ListConstant constant) { | 117 jsAst.Expression visitList(ListConstant constant) { |
| 129 return emitCanonicalVersion(constant); | 118 return emitCanonicalVersion(constant); |
| 130 } | 119 } |
| 131 | 120 |
| 132 jsAst.Expression visitMap(MapConstant constant) { | 121 jsAst.Expression visitMap(MapConstant constant) { |
| 133 return emitCanonicalVersion(constant); | 122 return emitCanonicalVersion(constant); |
| 134 } | 123 } |
| 135 | 124 |
| 136 jsAst.Expression visitType(TypeConstant constant) { | 125 jsAst.Expression visitType(TypeConstant constant) { |
| 137 return emitCanonicalVersion(constant); | 126 return emitCanonicalVersion(constant); |
| 138 } | 127 } |
| 139 | 128 |
| 140 jsAst.Expression visitConstructed(ConstructedConstant constant) { | 129 jsAst.Expression visitConstructed(ConstructedConstant constant) { |
| 141 return emitCanonicalVersion(constant); | 130 return emitCanonicalVersion(constant); |
| 142 } | 131 } |
| 143 | 132 |
| 144 jsAst.Expression visitInterceptor(InterceptorConstant constant) { | 133 jsAst.Expression visitInterceptor(InterceptorConstant constant) { |
| 145 return emitCanonicalVersion(constant); | 134 return emitCanonicalVersion(constant); |
| 146 } | 135 } |
| 147 | 136 |
| 148 jsAst.Expression visitDummy(DummyConstant constant) { | 137 jsAst.Expression visitDummy(DummyConstant constant) { |
| 149 return new jsAst.LiteralNumber('0'); | 138 return literal(constant); |
| 139 } |
| 140 |
| 141 jsAst.Expression visitDeferred(DeferredConstant constant) { |
| 142 return emitCanonicalVersion(constant); |
| 150 } | 143 } |
| 151 } | 144 } |
| 152 | 145 |
| 153 /** | 146 /** |
| 154 * Visitor for generating JavaScript expressions to initialize [Constant]s. | 147 * Visitor for generating JavaScript expressions that litterally represent |
| 155 * Do not use directly; use methods from [ConstantEmitter]. | 148 * [Constant]s. These can be used for inlining constants or in initializers. |
| 149 * Do not use directly, use methods from [ConstantEmitter]. |
| 156 */ | 150 */ |
| 157 class ConstantInitializerEmitter implements ConstantVisitor<jsAst.Expression> { | 151 class ConstantLiteralEmitter implements ConstantVisitor<jsAst.Expression> { |
| 158 final Compiler compiler; | |
| 159 final Namer namer; | |
| 160 final ConstantReferenceEmitter referenceEmitter; | |
| 161 | 152 |
| 162 // Matches blank lines, comment lines and trailing comments that can't be part | 153 // Matches blank lines, comment lines and trailing comments that can't be part |
| 163 // of a string. | 154 // of a string. |
| 164 static final RegExp COMMENT_RE = | 155 static final RegExp COMMENT_RE = |
| 165 new RegExp(r'''^ *(//.*)?\n| *//[^''"\n]*$''' , multiLine: true); | 156 new RegExp(r'''^ *(//.*)?\n| *//[^''"\n]*$''' , multiLine: true); |
| 166 | 157 |
| 167 ConstantInitializerEmitter(this.compiler, this.namer, this.referenceEmitter); | 158 final Compiler compiler; |
| 159 final Namer namer; |
| 160 final ConstantEmitter constantEmitter; |
| 161 |
| 162 ConstantLiteralEmitter(this.compiler, this.namer, this.constantEmitter); |
| 168 | 163 |
| 169 jsAst.Expression generate(Constant constant) { | 164 jsAst.Expression generate(Constant constant) { |
| 170 return _visit(constant); | 165 return _visit(constant); |
| 171 } | 166 } |
| 172 | 167 |
| 173 jsAst.Expression _visit(Constant constant) { | 168 jsAst.Expression _visit(Constant constant) { |
| 174 return constant.accept(this); | 169 return constant.accept(this); |
| 175 } | 170 } |
| 176 | 171 |
| 177 jsAst.Expression _reference(Constant constant) { | |
| 178 return referenceEmitter.generateInInitializationContext(constant); | |
| 179 } | |
| 180 | |
| 181 jsAst.Expression visitFunction(FunctionConstant constant) { | 172 jsAst.Expression visitFunction(FunctionConstant constant) { |
| 182 compiler.internalError(NO_LOCATION_SPANNABLE, | 173 return new jsAst.VariableUse( |
| 183 "The function constant does not need specific JS code."); | 174 namer.isolateStaticClosureAccess(constant.element)); |
| 184 return null; | |
| 185 } | 175 } |
| 186 | 176 |
| 187 jsAst.Expression visitNull(NullConstant constant) { | 177 jsAst.Expression visitNull(NullConstant constant) { |
| 188 return _reference(constant); | 178 return new jsAst.LiteralNull(); |
| 189 } | 179 } |
| 190 | 180 |
| 191 jsAst.Expression visitInt(IntConstant constant) { | 181 jsAst.Expression visitInt(IntConstant constant) { |
| 192 return _reference(constant); | 182 return new jsAst.LiteralNumber('${constant.value}'); |
| 193 } | 183 } |
| 194 | 184 |
| 195 jsAst.Expression visitDouble(DoubleConstant constant) { | 185 jsAst.Expression visitDouble(DoubleConstant constant) { |
| 196 return _reference(constant); | 186 double value = constant.value; |
| 187 if (value.isNaN) { |
| 188 return js("0/0"); |
| 189 } else if (value == double.INFINITY) { |
| 190 return js("1/0"); |
| 191 } else if (value == -double.INFINITY) { |
| 192 return js("-1/0"); |
| 193 } else { |
| 194 return new jsAst.LiteralNumber("$value"); |
| 195 } |
| 197 } | 196 } |
| 198 | 197 |
| 199 jsAst.Expression visitTrue(TrueConstant constant) { | 198 jsAst.Expression visitTrue(TrueConstant constant) { |
| 200 return _reference(constant); | 199 if (compiler.enableMinification) { |
| 200 // Use !0 for true. |
| 201 return js("!0"); |
| 202 } else { |
| 203 return js('true'); |
| 204 } |
| 201 } | 205 } |
| 202 | 206 |
| 203 jsAst.Expression visitFalse(FalseConstant constant) { | 207 jsAst.Expression visitFalse(FalseConstant constant) { |
| 204 return _reference(constant); | 208 if (compiler.enableMinification) { |
| 209 // Use !1 for false. |
| 210 return js("!1"); |
| 211 } else { |
| 212 return js('false'); |
| 213 } |
| 205 } | 214 } |
| 206 | 215 |
| 216 /** |
| 217 * Write the contents of the quoted string to a [CodeBuffer] in |
| 218 * a form that is valid as JavaScript string literal content. |
| 219 * The string is assumed quoted by double quote characters. |
| 220 */ |
| 207 jsAst.Expression visitString(StringConstant constant) { | 221 jsAst.Expression visitString(StringConstant constant) { |
| 208 // TODO(sra): Some larger strings are worth sharing. | 222 StringBuffer sb = new StringBuffer(); |
| 209 return _reference(constant); | 223 writeJsonEscapedCharsOn(constant.value.slowToString(), sb); |
| 224 return new jsAst.LiteralString('"$sb"'); |
| 210 } | 225 } |
| 211 | 226 |
| 212 jsAst.Expression visitList(ListConstant constant) { | 227 jsAst.Expression visitList(ListConstant constant) { |
| 213 jsAst.Expression value = new jsAst.Call( | 228 jsAst.Expression value = new jsAst.Call( |
| 214 new jsAst.PropertyAccess.field( | 229 new jsAst.PropertyAccess.field( |
| 215 new jsAst.VariableUse(namer.isolateName), | 230 new jsAst.VariableUse(namer.isolateName), |
| 216 'makeConstantList'), | 231 'makeConstantList'), |
| 217 [new jsAst.ArrayInitializer.from(_array(constant.entries))]); | 232 [new jsAst.ArrayInitializer.from(_array(constant.entries))]); |
| 218 return maybeAddTypeArguments(constant.type, value); | 233 return maybeAddTypeArguments(constant.type, value); |
| 219 } | 234 } |
| 220 | 235 |
| 221 String getJsConstructor(ClassElement element) { | 236 String getJsConstructor(ClassElement element) { |
| 222 return namer.isolateAccess(element); | 237 return namer.isolateAccess(element); |
| 223 } | 238 } |
| 224 | 239 |
| 225 jsAst.Expression visitMap(MapConstant constant) { | 240 jsAst.Expression visitMap(MapConstant constant) { |
| 226 jsAst.Expression jsMap() { | 241 jsAst.Expression jsMap() { |
| 227 List<jsAst.Property> properties = <jsAst.Property>[]; | 242 List<jsAst.Property> properties = <jsAst.Property>[]; |
| 228 for (int i = 0; i < constant.keys.entries.length; i++) { | 243 for (int i = 0; i < constant.keys.entries.length; i++) { |
| 229 StringConstant key = constant.keys.entries[i]; | 244 StringConstant key = constant.keys.entries[i]; |
| 230 if (key.value == MapConstant.PROTO_PROPERTY) continue; | 245 if (key.value == MapConstant.PROTO_PROPERTY) continue; |
| 231 | 246 |
| 232 // Keys in literal maps must be emitted in place. | 247 // Keys in literal maps must be emitted in place. |
| 233 jsAst.Literal keyExpression = _visit(key); | 248 jsAst.Literal keyExpression = _visit(key); |
| 234 jsAst.Expression valueExpression = | 249 jsAst.Expression valueExpression = |
| 235 _reference(constant.values[i]); | 250 constantEmitter.reference(constant.values[i]); |
| 236 properties.add(new jsAst.Property(keyExpression, valueExpression)); | 251 properties.add(new jsAst.Property(keyExpression, valueExpression)); |
| 237 } | 252 } |
| 238 return new jsAst.ObjectInitializer(properties); | 253 return new jsAst.ObjectInitializer(properties); |
| 239 } | 254 } |
| 240 | 255 |
| 241 jsAst.Expression jsGeneralMap() { | 256 jsAst.Expression jsGeneralMap() { |
| 242 List<jsAst.Expression> data = <jsAst.Expression>[]; | 257 List<jsAst.Expression> data = <jsAst.Expression>[]; |
| 243 for (int i = 0; i < constant.keys.entries.length; i++) { | 258 for (int i = 0; i < constant.keys.entries.length; i++) { |
| 244 jsAst.Expression keyExpression = | 259 jsAst.Expression keyExpression = |
| 245 _reference(constant.keys.entries[i]); | 260 constantEmitter.reference(constant.keys.entries[i]); |
| 246 jsAst.Expression valueExpression = | 261 jsAst.Expression valueExpression = |
| 247 _reference(constant.values[i]); | 262 constantEmitter.reference(constant.values[i]); |
| 248 data.add(keyExpression); | 263 data.add(keyExpression); |
| 249 data.add(valueExpression); | 264 data.add(valueExpression); |
| 250 } | 265 } |
| 251 return new jsAst.ArrayInitializer.from(data); | 266 return new jsAst.ArrayInitializer.from(data); |
| 252 } | 267 } |
| 253 | 268 |
| 254 ClassElement classElement = constant.type.element; | 269 ClassElement classElement = constant.type.element; |
| 255 String className = classElement.name; | 270 String className = classElement.name; |
| 256 | 271 |
| 257 List<jsAst.Expression> arguments = <jsAst.Expression>[]; | 272 List<jsAst.Expression> arguments = <jsAst.Expression>[]; |
| 258 | 273 |
| 259 // The arguments of the JavaScript constructor for any given Dart class | 274 // The arguments of the JavaScript constructor for any given Dart class |
| 260 // are in the same order as the members of the class element. | 275 // are in the same order as the members of the class element. |
| 261 int emittedArgumentCount = 0; | 276 int emittedArgumentCount = 0; |
| 262 classElement.implementation.forEachInstanceField( | 277 classElement.implementation.forEachInstanceField( |
| 263 (ClassElement enclosing, Element field) { | 278 (ClassElement enclosing, Element field) { |
| 264 if (field.name == MapConstant.LENGTH_NAME) { | 279 if (field.name == MapConstant.LENGTH_NAME) { |
| 265 arguments.add( | 280 arguments.add( |
| 266 new jsAst.LiteralNumber('${constant.keys.entries.length}')); | 281 new jsAst.LiteralNumber('${constant.keys.entries.length}')); |
| 267 } else if (field.name == MapConstant.JS_OBJECT_NAME) { | 282 } else if (field.name == MapConstant.JS_OBJECT_NAME) { |
| 268 arguments.add(jsMap()); | 283 arguments.add(jsMap()); |
| 269 } else if (field.name == MapConstant.KEYS_NAME) { | 284 } else if (field.name == MapConstant.KEYS_NAME) { |
| 270 arguments.add(_reference(constant.keys)); | 285 arguments.add(constantEmitter.reference(constant.keys)); |
| 271 } else if (field.name == MapConstant.PROTO_VALUE) { | 286 } else if (field.name == MapConstant.PROTO_VALUE) { |
| 272 assert(constant.protoValue != null); | 287 assert(constant.protoValue != null); |
| 273 arguments.add(_reference(constant.protoValue)); | 288 arguments.add(constantEmitter.reference(constant.protoValue)); |
| 274 } else if (field.name == MapConstant.JS_DATA_NAME) { | 289 } else if (field.name == MapConstant.JS_DATA_NAME) { |
| 275 arguments.add(jsGeneralMap()); | 290 arguments.add(jsGeneralMap()); |
| 276 } else { | 291 } else { |
| 277 compiler.internalError(field, | 292 compiler.internalError(field, |
| 278 "Compiler has unexpected field ${field.name} for " | 293 "Compiler has unexpected field ${field.name} for " |
| 279 "${className}."); | 294 "${className}."); |
| 280 } | 295 } |
| 281 emittedArgumentCount++; | 296 emittedArgumentCount++; |
| 282 }, | 297 }, |
| 283 includeSuperAndInjectedMembers: true); | 298 includeSuperAndInjectedMembers: true); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 312 } | 327 } |
| 313 | 328 |
| 314 jsAst.Expression visitInterceptor(InterceptorConstant constant) { | 329 jsAst.Expression visitInterceptor(InterceptorConstant constant) { |
| 315 return new jsAst.PropertyAccess.field( | 330 return new jsAst.PropertyAccess.field( |
| 316 new jsAst.VariableUse( | 331 new jsAst.VariableUse( |
| 317 getJsConstructor(constant.dispatchedType.element)), | 332 getJsConstructor(constant.dispatchedType.element)), |
| 318 'prototype'); | 333 'prototype'); |
| 319 } | 334 } |
| 320 | 335 |
| 321 jsAst.Expression visitDummy(DummyConstant constant) { | 336 jsAst.Expression visitDummy(DummyConstant constant) { |
| 322 return _reference(constant); | 337 return new jsAst.LiteralNumber('0'); |
| 323 } | 338 } |
| 324 | 339 |
| 325 jsAst.Expression visitConstructed(ConstructedConstant constant) { | 340 jsAst.Expression visitConstructed(ConstructedConstant constant) { |
| 326 Element element = constant.type.element; | 341 Element element = constant.type.element; |
| 327 if (element.isForeign(compiler) | 342 if (element.isForeign(compiler) |
| 328 && element.name == 'JS_CONST') { | 343 && element.name == 'JS_CONST') { |
| 329 StringConstant str = constant.fields[0]; | 344 StringConstant str = constant.fields[0]; |
| 330 String value = str.value.slowToString(); | 345 String value = str.value.slowToString(); |
| 331 return new jsAst.LiteralExpression(stripComments(value)); | 346 return new jsAst.LiteralExpression(stripComments(value)); |
| 332 } | 347 } |
| 333 jsAst.New instantiation = new jsAst.New( | 348 jsAst.New instantiation = new jsAst.New( |
| 334 new jsAst.VariableUse(getJsConstructor(constant.type.element)), | 349 new jsAst.VariableUse(getJsConstructor(constant.type.element)), |
| 335 _array(constant.fields)); | 350 _array(constant.fields)); |
| 336 return maybeAddTypeArguments(constant.type, instantiation); | 351 return maybeAddTypeArguments(constant.type, instantiation); |
| 337 } | 352 } |
| 338 | 353 |
| 339 String stripComments(String rawJavaScript) { | 354 String stripComments(String rawJavaScript) { |
| 340 return rawJavaScript.replaceAll(COMMENT_RE, ''); | 355 return rawJavaScript.replaceAll(COMMENT_RE, ''); |
| 341 } | 356 } |
| 342 | 357 |
| 343 List<jsAst.Expression> _array(List<Constant> values) { | 358 List<jsAst.Expression> _array(List<Constant> values) { |
| 344 List<jsAst.Expression> valueList = <jsAst.Expression>[]; | 359 List<jsAst.Expression> valueList = <jsAst.Expression>[]; |
| 345 for (int i = 0; i < values.length; i++) { | 360 for (int i = 0; i < values.length; i++) { |
| 346 valueList.add(_reference(values[i])); | 361 valueList.add(constantEmitter.reference(values[i])); |
| 347 } | 362 } |
| 348 return valueList; | 363 return valueList; |
| 349 } | 364 } |
| 350 | 365 |
| 351 jsAst.Expression maybeAddTypeArguments(InterfaceType type, | 366 jsAst.Expression maybeAddTypeArguments(InterfaceType type, |
| 352 jsAst.Expression value) { | 367 jsAst.Expression value) { |
| 353 if (type is InterfaceType && | 368 if (type is InterfaceType && |
| 354 !type.treatAsRaw && | 369 !type.treatAsRaw && |
| 355 backend.classNeedsRti(type.element)) { | 370 backend.classNeedsRti(type.element)) { |
| 356 InterfaceType interface = type; | 371 InterfaceType interface = type; |
| 357 RuntimeTypes rti = backend.rti; | 372 RuntimeTypes rti = backend.rti; |
| 358 Iterable<String> arguments = interface.typeArguments | 373 Iterable<String> arguments = interface.typeArguments |
| 359 .toList(growable: false) | 374 .toList(growable: false) |
| 360 .map((DartType type) => | 375 .map((DartType type) => |
| 361 rti.getTypeRepresentationWithHashes(type, (_){})); | 376 rti.getTypeRepresentationWithHashes(type, (_){})); |
| 362 jsAst.Expression argumentList = | 377 jsAst.Expression argumentList = |
| 363 new jsAst.LiteralString('[${arguments.join(', ')}]'); | 378 new jsAst.LiteralString('[${arguments.join(', ')}]'); |
| 364 return new jsAst.Call(getHelperProperty(backend.getSetRuntimeTypeInfo()), | 379 return new jsAst.Call(getHelperProperty(backend.getSetRuntimeTypeInfo()), |
| 365 [value, argumentList]); | 380 [value, argumentList]); |
| 366 } | 381 } |
| 367 return value; | 382 return value; |
| 368 } | 383 } |
| 384 |
| 385 jsAst.Expression visitDeferred(DeferredConstant constant) { |
| 386 return constantEmitter.reference(constant.referenced); |
| 387 } |
| 369 } | 388 } |
| OLD | NEW |