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 "use strict"; | 23 (function(global, utils) { |
| 24 "use strict"; |
24 | 25 |
25 Debug.LiveEdit = new function() { | 26 // ------------------------------------------------------------------- |
| 27 // Imports |
| 28 |
| 29 var FindScriptSourcePosition = global.Debug.findScriptSourcePosition; |
| 30 var GetScriptBreakPoints; |
| 31 var GlobalArray = global.Array; |
| 32 var MathFloor = global.Math.floor; |
| 33 var SyntaxError = global.SyntaxError; |
| 34 |
| 35 utils.Import(function(from) { |
| 36 GetScriptBreakPoints = from.GetScriptBreakPoints; |
| 37 }); |
| 38 |
| 39 // ------------------------------------------------------------------- |
26 | 40 |
27 // Forward declaration for minifier. | 41 // Forward declaration for minifier. |
28 var FunctionStatus; | 42 var FunctionStatus; |
29 | 43 |
30 // Applies the change to the script. | 44 // Applies the change to the script. |
31 // The change is in form of list of chunks encoded in a single array as | 45 // The change is in form of list of chunks encoded in a single array as |
32 // a series of triplets (pos1_start, pos1_end, pos2_end) | 46 // a series of triplets (pos1_start, pos1_end, pos2_end) |
33 function ApplyPatchMultiChunk(script, diff_array, new_source, preview_only, | 47 function ApplyPatchMultiChunk(script, diff_array, new_source, preview_only, |
34 change_log) { | 48 change_log) { |
35 | 49 |
(...skipping 29 matching lines...) Expand all Loading... |
65 failure.details = details; | 79 failure.details = details; |
66 } | 80 } |
67 throw failure; | 81 throw failure; |
68 } | 82 } |
69 var root_new_node = BuildCodeInfoTree(new_compile_info); | 83 var root_new_node = BuildCodeInfoTree(new_compile_info); |
70 | 84 |
71 // Link recompiled script data with other data. | 85 // Link recompiled script data with other data. |
72 FindCorrespondingFunctions(root_old_node, root_new_node); | 86 FindCorrespondingFunctions(root_old_node, root_new_node); |
73 | 87 |
74 // Prepare to-do lists. | 88 // Prepare to-do lists. |
75 var replace_code_list = new Array(); | 89 var replace_code_list = new GlobalArray(); |
76 var link_to_old_script_list = new Array(); | 90 var link_to_old_script_list = new GlobalArray(); |
77 var link_to_original_script_list = new Array(); | 91 var link_to_original_script_list = new GlobalArray(); |
78 var update_positions_list = new Array(); | 92 var update_positions_list = new GlobalArray(); |
79 | 93 |
80 function HarvestTodo(old_node) { | 94 function HarvestTodo(old_node) { |
81 function CollectDamaged(node) { | 95 function CollectDamaged(node) { |
82 link_to_old_script_list.push(node); | 96 link_to_old_script_list.push(node); |
83 for (var i = 0; i < node.children.length; i++) { | 97 for (var i = 0; i < node.children.length; i++) { |
84 CollectDamaged(node.children[i]); | 98 CollectDamaged(node.children[i]); |
85 } | 99 } |
86 } | 100 } |
87 | 101 |
88 // Recursively collects all newly compiled functions that are going into | 102 // Recursively collects all newly compiled functions that are going into |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 updated: false | 135 updated: false |
122 }; | 136 }; |
123 | 137 |
124 if (preview_only) { | 138 if (preview_only) { |
125 return preview_description; | 139 return preview_description; |
126 } | 140 } |
127 | 141 |
128 HarvestTodo(root_old_node); | 142 HarvestTodo(root_old_node); |
129 | 143 |
130 // Collect shared infos for functions whose code need to be patched. | 144 // Collect shared infos for functions whose code need to be patched. |
131 var replaced_function_infos = new Array(); | 145 var replaced_function_infos = new GlobalArray(); |
132 for (var i = 0; i < replace_code_list.length; i++) { | 146 for (var i = 0; i < replace_code_list.length; i++) { |
133 var live_shared_function_infos = | 147 var live_shared_function_infos = |
134 replace_code_list[i].live_shared_function_infos; | 148 replace_code_list[i].live_shared_function_infos; |
135 | 149 |
136 if (live_shared_function_infos) { | 150 if (live_shared_function_infos) { |
137 for (var j = 0; j < live_shared_function_infos.length; j++) { | 151 for (var j = 0; j < live_shared_function_infos.length; j++) { |
138 replaced_function_infos.push(live_shared_function_infos[j]); | 152 replaced_function_infos.push(live_shared_function_infos[j]); |
139 } | 153 } |
140 } | 154 } |
141 } | 155 } |
(...skipping 21 matching lines...) Expand all Loading... |
163 %LiveEditReplaceScript(script, new_source, null); | 177 %LiveEditReplaceScript(script, new_source, null); |
164 old_script = UNDEFINED; | 178 old_script = UNDEFINED; |
165 } else { | 179 } else { |
166 var old_script_name = CreateNameForOldScript(script); | 180 var old_script_name = CreateNameForOldScript(script); |
167 | 181 |
168 // Update the script text and create a new script representing an old | 182 // Update the script text and create a new script representing an old |
169 // version of the script. | 183 // version of the script. |
170 old_script = %LiveEditReplaceScript(script, new_source, | 184 old_script = %LiveEditReplaceScript(script, new_source, |
171 old_script_name); | 185 old_script_name); |
172 | 186 |
173 var link_to_old_script_report = new Array(); | 187 var link_to_old_script_report = new GlobalArray(); |
174 change_log.push( { linked_to_old_script: link_to_old_script_report } ); | 188 change_log.push( { linked_to_old_script: link_to_old_script_report } ); |
175 | 189 |
176 // We need to link to old script all former nested functions. | 190 // We need to link to old script all former nested functions. |
177 for (var i = 0; i < link_to_old_script_list.length; i++) { | 191 for (var i = 0; i < link_to_old_script_list.length; i++) { |
178 LinkToOldScript(link_to_old_script_list[i], old_script, | 192 LinkToOldScript(link_to_old_script_list[i], old_script, |
179 link_to_old_script_report); | 193 link_to_old_script_report); |
180 } | 194 } |
181 | 195 |
182 preview_description.created_script_name = old_script_name; | 196 preview_description.created_script_name = old_script_name; |
183 } | 197 } |
184 | 198 |
185 // Link to an actual script all the functions that we are going to use. | 199 // Link to an actual script all the functions that we are going to use. |
186 for (var i = 0; i < link_to_original_script_list.length; i++) { | 200 for (var i = 0; i < link_to_original_script_list.length; i++) { |
187 %LiveEditFunctionSetScript( | 201 %LiveEditFunctionSetScript( |
188 link_to_original_script_list[i].info.shared_function_info, script); | 202 link_to_original_script_list[i].info.shared_function_info, script); |
189 } | 203 } |
190 | 204 |
191 for (var i = 0; i < replace_code_list.length; i++) { | 205 for (var i = 0; i < replace_code_list.length; i++) { |
192 PatchFunctionCode(replace_code_list[i], change_log); | 206 PatchFunctionCode(replace_code_list[i], change_log); |
193 } | 207 } |
194 | 208 |
195 var position_patch_report = new Array(); | 209 var position_patch_report = new GlobalArray(); |
196 change_log.push( {position_patched: position_patch_report} ); | 210 change_log.push( {position_patched: position_patch_report} ); |
197 | 211 |
198 for (var i = 0; i < update_positions_list.length; i++) { | 212 for (var i = 0; i < update_positions_list.length; i++) { |
199 // TODO(LiveEdit): take into account whether it's source_changed or | 213 // TODO(LiveEdit): take into account whether it's source_changed or |
200 // unchanged and whether positions changed at all. | 214 // unchanged and whether positions changed at all. |
201 PatchPositions(update_positions_list[i], diff_array, | 215 PatchPositions(update_positions_list[i], diff_array, |
202 position_patch_report); | 216 position_patch_report); |
203 | 217 |
204 if (update_positions_list[i].live_shared_function_infos) { | 218 if (update_positions_list[i].live_shared_function_infos) { |
205 update_positions_list[i].live_shared_function_infos. | 219 update_positions_list[i].live_shared_function_infos. |
206 forEach(function (info) { | 220 forEach(function (info) { |
207 %LiveEditFunctionSourceUpdated(info.raw_array); | 221 %LiveEditFunctionSourceUpdated(info.raw_array); |
208 }); | 222 }); |
209 } | 223 } |
210 } | 224 } |
211 | 225 |
212 break_points_restorer(pos_translator, old_script); | 226 break_points_restorer(pos_translator, old_script); |
213 | 227 |
214 preview_description.updated = true; | 228 preview_description.updated = true; |
215 return preview_description; | 229 return preview_description; |
216 } | 230 } |
217 // Function is public. | |
218 this.ApplyPatchMultiChunk = ApplyPatchMultiChunk; | |
219 | |
220 | 231 |
221 // Fully compiles source string as a script. Returns Array of | 232 // Fully compiles source string as a script. Returns Array of |
222 // FunctionCompileInfo -- a descriptions of all functions of the script. | 233 // FunctionCompileInfo -- a descriptions of all functions of the script. |
223 // Elements of array are ordered by start positions of functions (from top | 234 // Elements of array are ordered by start positions of functions (from top |
224 // to bottom) in the source. Fields outer_index and next_sibling_index help | 235 // to bottom) in the source. Fields outer_index and next_sibling_index help |
225 // to navigate the nesting structure of functions. | 236 // to navigate the nesting structure of functions. |
226 // | 237 // |
227 // All functions get compiled linked to script provided as parameter script. | 238 // All functions get compiled linked to script provided as parameter script. |
228 // TODO(LiveEdit): consider not using actual scripts as script, because | 239 // TODO(LiveEdit): consider not using actual scripts as script, because |
229 // we have to manually erase all links right after compile. | 240 // we have to manually erase all links right after compile. |
230 function GatherCompileInfo(source, script) { | 241 function GatherCompileInfo(source, script) { |
231 // Get function info, elements are partially sorted (it is a tree of | 242 // Get function info, elements are partially sorted (it is a tree of |
232 // nested functions serialized as parent followed by serialized children. | 243 // nested functions serialized as parent followed by serialized children. |
233 var raw_compile_info = %LiveEditGatherCompileInfo(script, source); | 244 var raw_compile_info = %LiveEditGatherCompileInfo(script, source); |
234 | 245 |
235 // Sort function infos by start position field. | 246 // Sort function infos by start position field. |
236 var compile_info = new Array(); | 247 var compile_info = new GlobalArray(); |
237 var old_index_map = new Array(); | 248 var old_index_map = new GlobalArray(); |
238 for (var i = 0; i < raw_compile_info.length; i++) { | 249 for (var i = 0; i < raw_compile_info.length; i++) { |
239 var info = new FunctionCompileInfo(raw_compile_info[i]); | 250 var info = new FunctionCompileInfo(raw_compile_info[i]); |
240 // Remove all links to the actual script. Breakpoints system and | 251 // Remove all links to the actual script. Breakpoints system and |
241 // LiveEdit itself believe that any function in heap that points to a | 252 // LiveEdit itself believe that any function in heap that points to a |
242 // particular script is a regular function. | 253 // particular script is a regular function. |
243 // For some functions we will restore this link later. | 254 // For some functions we will restore this link later. |
244 %LiveEditFunctionSetScript(info.shared_function_info, UNDEFINED); | 255 %LiveEditFunctionSetScript(info.shared_function_info, UNDEFINED); |
245 compile_info.push(info); | 256 compile_info.push(info); |
246 old_index_map.push(i); | 257 old_index_map.push(i); |
247 } | 258 } |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
360 var break_points_update_report = []; | 371 var break_points_update_report = []; |
361 change_log.push( { break_points_update: break_points_update_report } ); | 372 change_log.push( { break_points_update: break_points_update_report } ); |
362 | 373 |
363 var break_point_old_positions = []; | 374 var break_point_old_positions = []; |
364 for (var i = 0; i < script_break_points.length; i++) { | 375 for (var i = 0; i < script_break_points.length; i++) { |
365 var break_point = script_break_points[i]; | 376 var break_point = script_break_points[i]; |
366 | 377 |
367 break_point.clear(); | 378 break_point.clear(); |
368 | 379 |
369 // TODO(LiveEdit): be careful with resource offset here. | 380 // TODO(LiveEdit): be careful with resource offset here. |
370 var break_point_position = Debug.findScriptSourcePosition(original_script, | 381 var break_point_position = FindScriptSourcePosition(original_script, |
371 break_point.line(), break_point.column()); | 382 break_point.line(), break_point.column()); |
372 | 383 |
373 var old_position_description = { | 384 var old_position_description = { |
374 position: break_point_position, | 385 position: break_point_position, |
375 line: break_point.line(), | 386 line: break_point.line(), |
376 column: break_point.column() | 387 column: break_point.column() |
377 }; | 388 }; |
378 break_point_old_positions.push(old_position_description); | 389 break_point_old_positions.push(old_position_description); |
379 } | 390 } |
380 | 391 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
436 } | 447 } |
437 | 448 |
438 function DiffChunk(pos1, pos2, len1, len2) { | 449 function DiffChunk(pos1, pos2, len1, len2) { |
439 this.pos1 = pos1; | 450 this.pos1 = pos1; |
440 this.pos2 = pos2; | 451 this.pos2 = pos2; |
441 this.len1 = len1; | 452 this.len1 = len1; |
442 this.len2 = len2; | 453 this.len2 = len2; |
443 } | 454 } |
444 | 455 |
445 function PosTranslator(diff_array) { | 456 function PosTranslator(diff_array) { |
446 var chunks = new Array(); | 457 var chunks = new GlobalArray(); |
447 var current_diff = 0; | 458 var current_diff = 0; |
448 for (var i = 0; i < diff_array.length; i += 3) { | 459 for (var i = 0; i < diff_array.length; i += 3) { |
449 var pos1_begin = diff_array[i]; | 460 var pos1_begin = diff_array[i]; |
450 var pos2_begin = pos1_begin + current_diff; | 461 var pos2_begin = pos1_begin + current_diff; |
451 var pos1_end = diff_array[i + 1]; | 462 var pos1_end = diff_array[i + 1]; |
452 var pos2_end = diff_array[i + 2]; | 463 var pos2_end = diff_array[i + 2]; |
453 chunks.push(new DiffChunk(pos1_begin, pos2_begin, pos1_end - pos1_begin, | 464 chunks.push(new DiffChunk(pos1_begin, pos2_begin, pos1_end - pos1_begin, |
454 pos2_end - pos2_begin)); | 465 pos2_end - pos2_begin)); |
455 current_diff = pos2_end - pos1_end; | 466 current_diff = pos2_end - pos1_end; |
456 } | 467 } |
457 this.chunks = chunks; | 468 this.chunks = chunks; |
458 } | 469 } |
459 PosTranslator.prototype.GetChunks = function() { | 470 PosTranslator.prototype.GetChunks = function() { |
460 return this.chunks; | 471 return this.chunks; |
461 }; | 472 }; |
462 | 473 |
463 PosTranslator.prototype.Translate = function(pos, inside_chunk_handler) { | 474 PosTranslator.prototype.Translate = function(pos, inside_chunk_handler) { |
464 var array = this.chunks; | 475 var array = this.chunks; |
465 if (array.length == 0 || pos < array[0].pos1) { | 476 if (array.length == 0 || pos < array[0].pos1) { |
466 return pos; | 477 return pos; |
467 } | 478 } |
468 var chunk_index1 = 0; | 479 var chunk_index1 = 0; |
469 var chunk_index2 = array.length - 1; | 480 var chunk_index2 = array.length - 1; |
470 | 481 |
471 while (chunk_index1 < chunk_index2) { | 482 while (chunk_index1 < chunk_index2) { |
472 var middle_index = Math.floor((chunk_index1 + chunk_index2) / 2); | 483 var middle_index = MathFloor((chunk_index1 + chunk_index2) / 2); |
473 if (pos < array[middle_index + 1].pos1) { | 484 if (pos < array[middle_index + 1].pos1) { |
474 chunk_index2 = middle_index; | 485 chunk_index2 = middle_index; |
475 } else { | 486 } else { |
476 chunk_index1 = middle_index + 1; | 487 chunk_index1 = middle_index + 1; |
477 } | 488 } |
478 } | 489 } |
479 var chunk = array[chunk_index1]; | 490 var chunk = array[chunk_index1]; |
480 if (pos >= chunk.pos1 + chunk.len1) { | 491 if (pos >= chunk.pos1 + chunk.len1) { |
481 return pos + chunk.pos2 + chunk.len2 - chunk.pos1 - chunk.len1; | 492 return pos + chunk.pos2 + chunk.len2 - chunk.pos1 - chunk.len1; |
482 } | 493 } |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
543 // From array of function infos that is implicitly a tree creates | 554 // From array of function infos that is implicitly a tree creates |
544 // an actual tree of functions in script. | 555 // an actual tree of functions in script. |
545 function BuildCodeInfoTree(code_info_array) { | 556 function BuildCodeInfoTree(code_info_array) { |
546 // Throughtout all function we iterate over input array. | 557 // Throughtout all function we iterate over input array. |
547 var index = 0; | 558 var index = 0; |
548 | 559 |
549 // Recursive function that builds a branch of tree. | 560 // Recursive function that builds a branch of tree. |
550 function BuildNode() { | 561 function BuildNode() { |
551 var my_index = index; | 562 var my_index = index; |
552 index++; | 563 index++; |
553 var child_array = new Array(); | 564 var child_array = new GlobalArray(); |
554 while (index < code_info_array.length && | 565 while (index < code_info_array.length && |
555 code_info_array[index].outer_index == my_index) { | 566 code_info_array[index].outer_index == my_index) { |
556 child_array.push(BuildNode()); | 567 child_array.push(BuildNode()); |
557 } | 568 } |
558 var node = new CodeInfoTreeNode(code_info_array[my_index], child_array, | 569 var node = new CodeInfoTreeNode(code_info_array[my_index], child_array, |
559 my_index); | 570 my_index); |
560 for (var i = 0; i < child_array.length; i++) { | 571 for (var i = 0; i < child_array.length; i++) { |
561 child_array[i].parent = node; | 572 child_array[i].parent = node; |
562 } | 573 } |
563 return node; | 574 return node; |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 // inside function body may in fact be something like "} function B() {" that | 686 // inside function body may in fact be something like "} function B() {" that |
676 // splits a function into 2 functions. | 687 // splits a function into 2 functions. |
677 function FindCorrespondingFunctions(old_code_tree, new_code_tree) { | 688 function FindCorrespondingFunctions(old_code_tree, new_code_tree) { |
678 | 689 |
679 // A recursive function that tries to find a correspondence for all | 690 // A recursive function that tries to find a correspondence for all |
680 // child functions and for their inner functions. | 691 // child functions and for their inner functions. |
681 function ProcessNode(old_node, new_node) { | 692 function ProcessNode(old_node, new_node) { |
682 var scope_change_description = | 693 var scope_change_description = |
683 IsFunctionContextLocalsChanged(old_node.info, new_node.info); | 694 IsFunctionContextLocalsChanged(old_node.info, new_node.info); |
684 if (scope_change_description) { | 695 if (scope_change_description) { |
685 old_node.status = FunctionStatus.CHANGED; | 696 old_node.status = FunctionStatus.CHANGED; |
686 } | 697 } |
687 | 698 |
688 var old_children = old_node.children; | 699 var old_children = old_node.children; |
689 var new_children = new_node.children; | 700 var new_children = new_node.children; |
690 | 701 |
691 var unmatched_new_nodes_list = []; | 702 var unmatched_new_nodes_list = []; |
692 var textually_unmatched_new_nodes_list = []; | 703 var textually_unmatched_new_nodes_list = []; |
693 | 704 |
694 var old_index = 0; | 705 var old_index = 0; |
695 var new_index = 0; | 706 var new_index = 0; |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
776 old_code_tree.corresponding_node = new_code_tree; | 787 old_code_tree.corresponding_node = new_code_tree; |
777 old_code_tree.textual_corresponding_node = new_code_tree; | 788 old_code_tree.textual_corresponding_node = new_code_tree; |
778 | 789 |
779 Assert(old_code_tree.status != FunctionStatus.DAMAGED, | 790 Assert(old_code_tree.status != FunctionStatus.DAMAGED, |
780 "Script became damaged"); | 791 "Script became damaged"); |
781 } | 792 } |
782 | 793 |
783 function FindLiveSharedInfos(old_code_tree, script) { | 794 function FindLiveSharedInfos(old_code_tree, script) { |
784 var shared_raw_list = %LiveEditFindSharedFunctionInfosForScript(script); | 795 var shared_raw_list = %LiveEditFindSharedFunctionInfosForScript(script); |
785 | 796 |
786 var shared_infos = new Array(); | 797 var shared_infos = new GlobalArray(); |
787 | 798 |
788 for (var i = 0; i < shared_raw_list.length; i++) { | 799 for (var i = 0; i < shared_raw_list.length; i++) { |
789 shared_infos.push(new SharedInfoWrapper(shared_raw_list[i])); | 800 shared_infos.push(new SharedInfoWrapper(shared_raw_list[i])); |
790 } | 801 } |
791 | 802 |
792 // Finds all SharedFunctionInfos that corresponds to compile info | 803 // Finds all SharedFunctionInfos that corresponds to compile info |
793 // in old version of the script. | 804 // in old version of the script. |
794 function FindFunctionInfos(compile_info) { | 805 function FindFunctionInfos(compile_info) { |
795 var wrappers = []; | 806 var wrappers = []; |
796 | 807 |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
893 return; | 904 return; |
894 } | 905 } |
895 | 906 |
896 // Minifier forward declaration. | 907 // Minifier forward declaration. |
897 var FunctionPatchabilityStatus; | 908 var FunctionPatchabilityStatus; |
898 | 909 |
899 // For array of wrapped shared function infos checks that none of them | 910 // For array of wrapped shared function infos checks that none of them |
900 // have activations on stack (of any thread). Throws a Failure exception | 911 // have activations on stack (of any thread). Throws a Failure exception |
901 // if this proves to be false. | 912 // if this proves to be false. |
902 function CheckStackActivations(shared_wrapper_list, change_log) { | 913 function CheckStackActivations(shared_wrapper_list, change_log) { |
903 var shared_list = new Array(); | 914 var shared_list = new GlobalArray(); |
904 for (var i = 0; i < shared_wrapper_list.length; i++) { | 915 for (var i = 0; i < shared_wrapper_list.length; i++) { |
905 shared_list[i] = shared_wrapper_list[i].info; | 916 shared_list[i] = shared_wrapper_list[i].info; |
906 } | 917 } |
907 var result = %LiveEditCheckAndDropActivations(shared_list, true); | 918 var result = %LiveEditCheckAndDropActivations(shared_list, true); |
908 if (result[shared_list.length]) { | 919 if (result[shared_list.length]) { |
909 // Extra array element may contain error message. | 920 // Extra array element may contain error message. |
910 throw new Failure(result[shared_list.length]); | 921 throw new Failure(result[shared_list.length]); |
911 } | 922 } |
912 | 923 |
913 var problems = new Array(); | 924 var problems = new GlobalArray(); |
914 var dropped = new Array(); | 925 var dropped = new GlobalArray(); |
915 for (var i = 0; i < shared_list.length; i++) { | 926 for (var i = 0; i < shared_list.length; i++) { |
916 var shared = shared_wrapper_list[i]; | 927 var shared = shared_wrapper_list[i]; |
917 if (result[i] == FunctionPatchabilityStatus.REPLACED_ON_ACTIVE_STACK) { | 928 if (result[i] == FunctionPatchabilityStatus.REPLACED_ON_ACTIVE_STACK) { |
918 dropped.push({ name: shared.function_name } ); | 929 dropped.push({ name: shared.function_name } ); |
919 } else if (result[i] != FunctionPatchabilityStatus.AVAILABLE_FOR_PATCH) { | 930 } else if (result[i] != FunctionPatchabilityStatus.AVAILABLE_FOR_PATCH) { |
920 var description = { | 931 var description = { |
921 name: shared.function_name, | 932 name: shared.function_name, |
922 start_pos: shared.start_position, | 933 start_pos: shared.start_position, |
923 end_pos: shared.end_position, | 934 end_pos: shared.end_position, |
924 replace_problem: | 935 replace_problem: |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
957 } | 968 } |
958 } | 969 } |
959 }; | 970 }; |
960 | 971 |
961 | 972 |
962 // A logical failure in liveedit process. This means that change_log | 973 // A logical failure in liveedit process. This means that change_log |
963 // is valid and consistent description of what happened. | 974 // is valid and consistent description of what happened. |
964 function Failure(message) { | 975 function Failure(message) { |
965 this.message = message; | 976 this.message = message; |
966 } | 977 } |
967 // Function (constructor) is public. | |
968 this.Failure = Failure; | |
969 | 978 |
970 Failure.prototype.toString = function() { | 979 Failure.prototype.toString = function() { |
971 return "LiveEdit Failure: " + this.message; | 980 return "LiveEdit Failure: " + this.message; |
972 }; | 981 }; |
973 | 982 |
974 function CopyErrorPositionToDetails(e, details) { | 983 function CopyErrorPositionToDetails(e, details) { |
975 function createPositionStruct(script, position) { | 984 function createPositionStruct(script, position) { |
976 if (position == -1) return; | 985 if (position == -1) return; |
977 var location = script.locationFromPosition(position, true); | 986 var location = script.locationFromPosition(position, true); |
978 if (location == null) return; | 987 if (location == null) return; |
(...skipping 14 matching lines...) Expand all Loading... |
993 start: createPositionStruct(script, e.startPosition), | 1002 start: createPositionStruct(script, e.startPosition), |
994 end: createPositionStruct(script, e.endPosition) | 1003 end: createPositionStruct(script, e.endPosition) |
995 }; | 1004 }; |
996 details.position = position_struct; | 1005 details.position = position_struct; |
997 } | 1006 } |
998 | 1007 |
999 // A testing entry. | 1008 // A testing entry. |
1000 function GetPcFromSourcePos(func, source_pos) { | 1009 function GetPcFromSourcePos(func, source_pos) { |
1001 return %GetFunctionCodePositionFromSource(func, source_pos); | 1010 return %GetFunctionCodePositionFromSource(func, source_pos); |
1002 } | 1011 } |
1003 // Function is public. | |
1004 this.GetPcFromSourcePos = GetPcFromSourcePos; | |
1005 | 1012 |
1006 // LiveEdit main entry point: changes a script text to a new string. | 1013 // LiveEdit main entry point: changes a script text to a new string. |
1007 function SetScriptSource(script, new_source, preview_only, change_log) { | 1014 function SetScriptSource(script, new_source, preview_only, change_log) { |
1008 var old_source = script.source; | 1015 var old_source = script.source; |
1009 var diff = CompareStrings(old_source, new_source); | 1016 var diff = CompareStrings(old_source, new_source); |
1010 return ApplyPatchMultiChunk(script, diff, new_source, preview_only, | 1017 return ApplyPatchMultiChunk(script, diff, new_source, preview_only, |
1011 change_log); | 1018 change_log); |
1012 } | 1019 } |
1013 // Function is public. | |
1014 this.SetScriptSource = SetScriptSource; | |
1015 | 1020 |
1016 function CompareStrings(s1, s2) { | 1021 function CompareStrings(s1, s2) { |
1017 return %LiveEditCompareStrings(s1, s2); | 1022 return %LiveEditCompareStrings(s1, s2); |
1018 } | 1023 } |
1019 | 1024 |
1020 // Applies the change to the script. | 1025 // Applies the change to the script. |
1021 // The change is always a substring (change_pos, change_pos + change_len) | 1026 // The change is always a substring (change_pos, change_pos + change_len) |
1022 // being replaced with a completely different string new_str. | 1027 // being replaced with a completely different string new_str. |
1023 // This API is a legacy and is obsolete. | 1028 // This API is a legacy and is obsolete. |
1024 // | 1029 // |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1091 function DescribePositions(node) { | 1096 function DescribePositions(node) { |
1092 return { | 1097 return { |
1093 start_position: node.info.start_position, | 1098 start_position: node.info.start_position, |
1094 end_position: node.info.end_position | 1099 end_position: node.info.end_position |
1095 }; | 1100 }; |
1096 } | 1101 } |
1097 | 1102 |
1098 return ProcessOldNode(old_code_tree); | 1103 return ProcessOldNode(old_code_tree); |
1099 } | 1104 } |
1100 | 1105 |
1101 // Functions are public for tests. | 1106 // ------------------------------------------------------------------- |
1102 this.TestApi = { | 1107 // Exports |
| 1108 |
| 1109 var LiveEdit = {}; |
| 1110 LiveEdit.SetScriptSource = SetScriptSource; |
| 1111 LiveEdit.ApplyPatchMultiChunk = ApplyPatchMultiChunk; |
| 1112 LiveEdit.Failure = Failure; |
| 1113 LiveEdit.GetPcFromSourcePos = GetPcFromSourcePos; |
| 1114 |
| 1115 LiveEdit.TestApi = { |
1103 PosTranslator: PosTranslator, | 1116 PosTranslator: PosTranslator, |
1104 CompareStrings: CompareStrings, | 1117 CompareStrings: CompareStrings, |
1105 ApplySingleChunkPatch: ApplySingleChunkPatch | 1118 ApplySingleChunkPatch: ApplySingleChunkPatch |
1106 }; | 1119 }; |
1107 }; | 1120 |
| 1121 global.Debug.LiveEdit = LiveEdit; |
| 1122 |
| 1123 }) |
OLD | NEW |