| 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 |