Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 library dart2js_incremental.library_updater; | 5 library dart2js_incremental.library_updater; |
| 6 | 6 |
| 7 import 'dart:async' show | 7 import 'dart:async' show |
| 8 Future; | 8 Future; |
| 9 | 9 |
| 10 import 'dart:convert' show | 10 import 'dart:convert' show |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 25 PartialElement, | 25 PartialElement, |
| 26 PartialFunctionElement, | 26 PartialFunctionElement, |
| 27 Token; | 27 Token; |
| 28 | 28 |
| 29 import 'package:compiler/implementation/source_file.dart' show | 29 import 'package:compiler/implementation/source_file.dart' show |
| 30 StringSourceFile; | 30 StringSourceFile; |
| 31 | 31 |
| 32 import 'package:compiler/implementation/tree/tree.dart' show | 32 import 'package:compiler/implementation/tree/tree.dart' show |
| 33 FunctionExpression; | 33 FunctionExpression; |
| 34 | 34 |
| 35 import 'package:compiler/implementation/js/js.dart' show | |
| 36 js; | |
| 37 | |
| 38 import 'package:compiler/implementation/js/js.dart' as jsAst; | |
| 39 | |
| 40 import 'package:compiler/implementation/js_emitter/js_emitter.dart' show | |
| 41 ClassBuilder; | |
| 42 | |
| 43 import 'package:compiler/js_lib/shared/embedded_names.dart' as embeddedNames; | |
| 44 | |
| 35 import 'diff.dart' show | 45 import 'diff.dart' show |
| 36 Difference, | 46 Difference, |
| 37 computeDifference; | 47 computeDifference; |
| 38 | 48 |
| 39 typedef void Logger(message); | 49 typedef void Logger(message); |
| 40 | 50 |
| 41 // TODO(ahe): Generalize this class. For now only works for Compiler.mainApp, | 51 // TODO(ahe): Generalize this class. For now only works for Compiler.mainApp, |
| 42 // and only if that library has exactly one compilation unit. | 52 // and only if that library has exactly one compilation unit. |
| 43 class LibraryUpdater { | 53 class LibraryUpdater { |
| 44 final Compiler compiler; | 54 final Compiler compiler; |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 168 token = token.next; | 178 token = token.next; |
| 169 } | 179 } |
| 170 print('Simple modification of ${after} detected'); | 180 print('Simple modification of ${after} detected'); |
| 171 updates.add(new FunctionUpdate(compiler, before, after)); | 181 updates.add(new FunctionUpdate(compiler, before, after)); |
| 172 return true; | 182 return true; |
| 173 } | 183 } |
| 174 | 184 |
| 175 List<Element> applyUpdates() { | 185 List<Element> applyUpdates() { |
| 176 return updates.map((Update update) => update.apply()).toList(); | 186 return updates.map((Update update) => update.apply()).toList(); |
| 177 } | 187 } |
| 188 | |
| 189 String computeUpdateJs() { | |
| 190 List<Element> updatedElements = applyUpdates(); | |
| 191 compiler.progress.reset(); | |
| 192 for (Element element in updatedElements) { | |
| 193 compiler.enqueuer.resolution.addToWorkList(element); | |
| 194 } | |
| 195 compiler.processQueue(compiler.enqueuer.resolution, null); | |
| 196 | |
| 197 compiler.phase = Compiler.PHASE_DONE_RESOLVING; | |
| 198 | |
| 199 for (Element element in updatedElements) { | |
| 200 compiler.enqueuer.codegen.addToWorkList(element); | |
| 201 } | |
| 202 compiler.processQueue(compiler.enqueuer.codegen, null); | |
| 203 | |
| 204 jsAst.Block updates = new jsAst.Block.empty(); | |
| 205 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { | |
| 206 updates.statements.add(computeMemberUpdateJs(element)); | |
|
sra1
2014/10/07 18:03:06
Construct ASTs functionally.
Don't modify construc
ahe
2014/10/08 12:09:45
I'm doing something like that.
| |
| 207 } | |
| 208 | |
| 209 if (updates.statements.length == 1) { | |
| 210 return prettyPrintJs(updates.statements.single); | |
| 211 } else { | |
| 212 return prettyPrintJs(updates); | |
| 213 } | |
| 214 } | |
| 215 | |
| 216 jsAst.Node computeMemberUpdateJs(Element element) { | |
| 217 ClassBuilder builder = new ClassBuilder(element, compiler.backend.namer); | |
| 218 | |
| 219 compiler.backend.emitter.oldEmitter.containerBuilder.addMember( | |
| 220 element, builder); | |
| 221 jsAst.Property property = builder.properties.single; | |
| 222 jsAst.Node name = property.name; | |
| 223 jsAst.Node function = property.value; | |
| 224 jsAst.Node globalObject = compiler.backend.namer.globalObjectFor(element); | |
| 225 jsAst.Expression globalFunctionsAccess = | |
| 226 compiler.backend.emitter.generateEmbeddedGlobalAccess( | |
| 227 embeddedNames.GLOBAL_FUNCTIONS); | |
| 228 jsAst.Node updateGlobalFunction = | |
| 229 js.statement( | |
| 230 '#.# = #.# = f', [globalFunctionsAccess, name, globalObject, name]); | |
| 231 // Create a scope by creating a new function. The updated function literal | |
| 232 // is passed as an argument to this function which ensures that temporary | |
| 233 // names in updateScope don't shadow global names. | |
|
floitsch
2014/10/07 15:56:58
The only temporary variable updateScope has is the
ahe
2014/10/07 16:32:40
Yes, but I know I want to add at least one more st
floitsch
2014/10/07 17:48:38
Maybe you could write it with conditions:
if (#) #
sra1
2014/10/07 18:03:06
You can conditionally generate code with templates
ahe
2014/10/08 12:09:45
I think I'll avoid templates with conditionals in
| |
| 234 jsAst.Fun updateScope = new jsAst.Fun( | |
| 235 [new jsAst.Parameter('f')], new jsAst.Block.empty()); | |
|
floitsch
2014/10/07 15:56:58
does the following work?
jsAst.Fun = js('function
ahe
2014/10/07 16:32:40
Yes. But doesn't scale to multiple statements. I
floitsch
2014/10/07 17:48:38
I think you don't even need a block:
js('function
sra1
2014/10/07 18:03:06
It does work, with a minor tweak.
Blocks (and ite
ahe
2014/10/08 12:09:45
That's pretty nifty, but I feel that this is more
| |
| 236 updateScope.body.statements.add(updateGlobalFunction); | |
|
sra1
2014/10/07 18:03:06
Ditto: Construct ASTs functionally.
ahe
2014/10/08 12:09:45
I don't know what you mean by that.
| |
| 237 return js.statement('(#)(#)', [updateScope, function]); | |
| 238 } | |
| 239 | |
| 240 String prettyPrintJs(jsAst.Node node) { | |
| 241 return jsAst.prettyPrint(node, compiler).getText(); | |
| 242 } | |
| 178 } | 243 } |
| 179 | 244 |
| 180 /// Represents an update (aka patch) of [before] to [after]. We use the word | 245 /// Represents an update (aka patch) of [before] to [after]. We use the word |
| 181 /// "update" to avoid confusion with the compiler feature of "patch" methods. | 246 /// "update" to avoid confusion with the compiler feature of "patch" methods. |
| 182 abstract class Update { | 247 abstract class Update { |
| 183 final Compiler compiler; | 248 final Compiler compiler; |
| 184 | 249 |
| 185 PartialElement get before; | 250 PartialElement get before; |
| 186 | 251 |
| 187 PartialElement get after; | 252 PartialElement get after; |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 214 before.getOrSet = after.getOrSet; | 279 before.getOrSet = after.getOrSet; |
| 215 } | 280 } |
| 216 | 281 |
| 217 /// Reset various caches and remove this element from the compiler's internal | 282 /// Reset various caches and remove this element from the compiler's internal |
| 218 /// state. | 283 /// state. |
| 219 void reuseElement() { | 284 void reuseElement() { |
| 220 compiler.forgetElement(before); | 285 compiler.forgetElement(before); |
| 221 before.reuseElement(); | 286 before.reuseElement(); |
| 222 } | 287 } |
| 223 } | 288 } |
| OLD | NEW |