OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // LiveEdit feature implementation. The script should be executed after | 5 // LiveEdit feature implementation. The script should be executed after |
6 // debug.js. | 6 // debug.js. |
7 | 7 |
8 // A LiveEdit namespace. It contains functions that modifies JavaScript code | 8 // A LiveEdit namespace. It contains functions that modifies JavaScript code |
9 // according to changes of script source (if possible). | 9 // according to changes of script source (if possible). |
10 // | 10 // |
11 // When new script source is put in, the difference is calculated textually, | 11 // When new script source is put in, the difference is calculated textually, |
12 // in form of list of delete/add/change chunks. The functions that include | 12 // in form of list of delete/add/change chunks. The functions that include |
13 // change chunk(s) get recompiled, or their enclosing functions are | 13 // change chunk(s) get recompiled, or their enclosing functions are |
14 // recompiled instead. | 14 // recompiled instead. |
15 // If the function may not be recompiled (e.g. it was completely erased in new | 15 // If the function may not be recompiled (e.g. it was completely erased in new |
16 // version of the script) it remains unchanged, but the code that could | 16 // version of the script) it remains unchanged, but the code that could |
17 // create a new instance of this function goes away. An old version of script | 17 // create a new instance of this function goes away. An old version of script |
18 // is created to back up this obsolete function. | 18 // is created to back up this obsolete function. |
19 // All unchanged functions have their positions updated accordingly. | 19 // All unchanged functions have their positions updated accordingly. |
20 // | 20 // |
21 // LiveEdit namespace is declared inside a single function constructor. | 21 // LiveEdit namespace is declared inside a single function constructor. |
22 | 22 |
23 (function(global, utils) { | 23 (function(global, utils) { |
24 "use strict"; | 24 "use strict"; |
25 | 25 |
26 // ------------------------------------------------------------------- | 26 // ------------------------------------------------------------------- |
27 // Imports | 27 // Imports |
28 | 28 |
29 var FindScriptSourcePosition = global.Debug.findScriptSourcePosition; | 29 var FindScriptSourcePosition = global.Debug.findScriptSourcePosition; |
30 var GetScriptBreakPoints; | |
31 var GlobalArray = global.Array; | 30 var GlobalArray = global.Array; |
32 var MathFloor = global.Math.floor; | 31 var MathFloor = global.Math.floor; |
33 var SyntaxError = global.SyntaxError; | 32 var SyntaxError = global.SyntaxError; |
34 | 33 |
35 utils.Import(function(from) { | |
36 GetScriptBreakPoints = from.GetScriptBreakPoints; | |
37 }); | |
38 | |
39 // ------------------------------------------------------------------- | 34 // ------------------------------------------------------------------- |
40 | 35 |
41 // Forward declaration for minifier. | 36 // Forward declaration for minifier. |
42 var FunctionStatus; | 37 var FunctionStatus; |
43 | 38 |
44 // Applies the change to the script. | 39 // Applies the change to the script. |
45 // The change is in form of list of chunks encoded in a single array as | 40 // The change is in form of list of chunks encoded in a single array as |
46 // a series of triplets (pos1_start, pos1_end, pos2_end) | 41 // a series of triplets (pos1_start, pos1_end, pos2_end) |
47 function ApplyPatchMultiChunk(script, diff_array, new_source, preview_only, | 42 function ApplyPatchMultiChunk(script, diff_array, new_source, preview_only, |
48 change_log) { | 43 change_log) { |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 // Check that function being patched is not currently on stack or drop them. | 158 // Check that function being patched is not currently on stack or drop them. |
164 var dropped_functions_number = | 159 var dropped_functions_number = |
165 CheckStackActivations(replaced_function_old_infos, | 160 CheckStackActivations(replaced_function_old_infos, |
166 replaced_function_new_infos, | 161 replaced_function_new_infos, |
167 change_log); | 162 change_log); |
168 | 163 |
169 // Our current implementation requires client to manually issue "step in" | 164 // Our current implementation requires client to manually issue "step in" |
170 // command for correct stack state if the stack was modified. | 165 // command for correct stack state if the stack was modified. |
171 preview_description.stack_modified = dropped_functions_number != 0; | 166 preview_description.stack_modified = dropped_functions_number != 0; |
172 | 167 |
173 // Start with breakpoints. Convert their line/column positions and | |
174 // temporary remove. | |
175 var break_points_restorer = TemporaryRemoveBreakPoints(script, change_log); | |
176 | |
177 var old_script; | 168 var old_script; |
178 | 169 |
179 // Create an old script only if there are function that should be linked | 170 // Create an old script only if there are function that should be linked |
180 // to old version. | 171 // to old version. |
181 if (link_to_old_script_list.length == 0) { | 172 if (link_to_old_script_list.length == 0) { |
182 %LiveEditReplaceScript(script, new_source, null); | 173 %LiveEditReplaceScript(script, new_source, null); |
183 old_script = UNDEFINED; | 174 old_script = UNDEFINED; |
184 } else { | 175 } else { |
185 var old_script_name = CreateNameForOldScript(script); | 176 var old_script_name = CreateNameForOldScript(script); |
186 | 177 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 position_patch_report); | 212 position_patch_report); |
222 | 213 |
223 if (update_positions_list[i].live_shared_function_infos) { | 214 if (update_positions_list[i].live_shared_function_infos) { |
224 update_positions_list[i].live_shared_function_infos. | 215 update_positions_list[i].live_shared_function_infos. |
225 forEach(function (info) { | 216 forEach(function (info) { |
226 %LiveEditFunctionSourceUpdated(info.raw_array); | 217 %LiveEditFunctionSourceUpdated(info.raw_array); |
227 }); | 218 }); |
228 } | 219 } |
229 } | 220 } |
230 | 221 |
231 break_points_restorer(pos_translator, old_script); | |
232 | |
233 preview_description.updated = true; | 222 preview_description.updated = true; |
234 return preview_description; | 223 return preview_description; |
235 } | 224 } |
236 | 225 |
237 // Fully compiles source string as a script. Returns Array of | 226 // Fully compiles source string as a script. Returns Array of |
238 // FunctionCompileInfo -- a descriptions of all functions of the script. | 227 // FunctionCompileInfo -- a descriptions of all functions of the script. |
239 // Elements of array are ordered by start positions of functions (from top | 228 // Elements of array are ordered by start positions of functions (from top |
240 // to bottom) in the source. Fields outer_index and next_sibling_index help | 229 // to bottom) in the source. Fields outer_index and next_sibling_index help |
241 // to navigate the nesting structure of functions. | 230 // to navigate the nesting structure of functions. |
242 // | 231 // |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 %LiveEditFunctionSetScript(info.info, old_script); | 350 %LiveEditFunctionSetScript(info.info, old_script); |
362 }); | 351 }); |
363 | 352 |
364 report_array.push( { name: old_info_node.info.function_name } ); | 353 report_array.push( { name: old_info_node.info.function_name } ); |
365 } else { | 354 } else { |
366 report_array.push( | 355 report_array.push( |
367 { name: old_info_node.info.function_name, not_found: true } ); | 356 { name: old_info_node.info.function_name, not_found: true } ); |
368 } | 357 } |
369 } | 358 } |
370 | 359 |
371 | |
372 // Returns function that restores breakpoints. | |
373 function TemporaryRemoveBreakPoints(original_script, change_log) { | |
374 var script_break_points = GetScriptBreakPoints(original_script); | |
375 | |
376 var break_points_update_report = []; | |
377 change_log.push( { break_points_update: break_points_update_report } ); | |
378 | |
379 var break_point_old_positions = []; | |
380 for (var i = 0; i < script_break_points.length; i++) { | |
381 var break_point = script_break_points[i]; | |
382 | |
383 break_point.clear(); | |
384 | |
385 // TODO(LiveEdit): be careful with resource offset here. | |
386 var break_point_position = FindScriptSourcePosition(original_script, | |
387 break_point.line(), break_point.column()); | |
388 | |
389 var old_position_description = { | |
390 position: break_point_position, | |
391 line: break_point.line(), | |
392 column: break_point.column() | |
393 }; | |
394 break_point_old_positions.push(old_position_description); | |
395 } | |
396 | |
397 | |
398 // Restores breakpoints and creates their copies in the "old" copy of | |
399 // the script. | |
400 return function (pos_translator, old_script_copy_opt) { | |
401 // Update breakpoints (change positions and restore them in old version | |
402 // of script. | |
403 for (var i = 0; i < script_break_points.length; i++) { | |
404 var break_point = script_break_points[i]; | |
405 if (old_script_copy_opt) { | |
406 var clone = break_point.cloneForOtherScript(old_script_copy_opt); | |
407 clone.set(old_script_copy_opt); | |
408 | |
409 break_points_update_report.push( { | |
410 type: "copied_to_old", | |
411 id: break_point.number(), | |
412 new_id: clone.number(), | |
413 positions: break_point_old_positions[i] | |
414 } ); | |
415 } | |
416 | |
417 var updated_position = pos_translator.Translate( | |
418 break_point_old_positions[i].position, | |
419 PosTranslator.ShiftWithTopInsideChunkHandler); | |
420 | |
421 var new_location = | |
422 original_script.locationFromPosition(updated_position, false); | |
423 | |
424 break_point.update_positions(new_location.line, new_location.column); | |
425 | |
426 var new_position_description = { | |
427 position: updated_position, | |
428 line: new_location.line, | |
429 column: new_location.column | |
430 }; | |
431 | |
432 break_point.set(original_script); | |
433 | |
434 break_points_update_report.push( { type: "position_changed", | |
435 id: break_point.number(), | |
436 old_positions: break_point_old_positions[i], | |
437 new_positions: new_position_description | |
438 } ); | |
439 } | |
440 }; | |
441 } | |
442 | |
443 | |
444 function Assert(condition, message) { | 360 function Assert(condition, message) { |
445 if (!condition) { | 361 if (!condition) { |
446 if (message) { | 362 if (message) { |
447 throw "Assert " + message; | 363 throw "Assert " + message; |
448 } else { | 364 } else { |
449 throw "Assert"; | 365 throw "Assert"; |
450 } | 366 } |
451 } | 367 } |
452 } | 368 } |
453 | 369 |
(...skipping 661 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1115 | 1031 |
1116 LiveEdit.TestApi = { | 1032 LiveEdit.TestApi = { |
1117 PosTranslator: PosTranslator, | 1033 PosTranslator: PosTranslator, |
1118 CompareStrings: CompareStrings, | 1034 CompareStrings: CompareStrings, |
1119 ApplySingleChunkPatch: ApplySingleChunkPatch | 1035 ApplySingleChunkPatch: ApplySingleChunkPatch |
1120 }; | 1036 }; |
1121 | 1037 |
1122 global.Debug.LiveEdit = LiveEdit; | 1038 global.Debug.LiveEdit = LiveEdit; |
1123 | 1039 |
1124 }) | 1040 }) |
OLD | NEW |