OLD | NEW |
---|---|
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
44 // LiveEdit namespace is declared inside a single function constructor. | 44 // LiveEdit namespace is declared inside a single function constructor. |
45 Debug.LiveEdit = new function() { | 45 Debug.LiveEdit = new function() { |
46 | 46 |
47 // Forward declaration for minifier. | 47 // Forward declaration for minifier. |
48 var FunctionStatus; | 48 var FunctionStatus; |
49 | 49 |
50 | 50 |
51 // Applies the change to the script. | 51 // Applies the change to the script. |
52 // The change is in form of list of chunks encoded in a single array as | 52 // The change is in form of list of chunks encoded in a single array as |
53 // a series of triplets (pos1_start, pos1_end, pos2_end) | 53 // a series of triplets (pos1_start, pos1_end, pos2_end) |
54 function ApplyPatchMultiChunk(script, diff_array, new_source, change_log) { | 54 function ApplyPatchMultiChunk(script, diff_array, new_source, preview_only, ch ange_log) { |
mnaganov (inactive)
2010/07/02 16:23:36
nit: >80 chars
Peter Rybin
2013/06/26 19:39:57
Done.
| |
55 | 55 |
56 var old_source = script.source; | 56 var old_source = script.source; |
57 | 57 |
58 // Gather compile information about old version of script. | 58 // Gather compile information about old version of script. |
59 var old_compile_info = GatherCompileInfo(old_source, script); | 59 var old_compile_info = GatherCompileInfo(old_source, script); |
60 | 60 |
61 // Build tree structures for old and new versions of the script. | 61 // Build tree structures for old and new versions of the script. |
62 var root_old_node = BuildCodeInfoTree(old_compile_info); | 62 var root_old_node = BuildCodeInfoTree(old_compile_info); |
63 | 63 |
64 var pos_translator = new PosTranslator(diff_array); | 64 var pos_translator = new PosTranslator(diff_array); |
(...skipping 24 matching lines...) Expand all Loading... | |
89 | 89 |
90 function HarvestTodo(old_node) { | 90 function HarvestTodo(old_node) { |
91 function CollectDamaged(node) { | 91 function CollectDamaged(node) { |
92 link_to_old_script_list.push(node); | 92 link_to_old_script_list.push(node); |
93 for (var i = 0; i < node.children.length; i++) { | 93 for (var i = 0; i < node.children.length; i++) { |
94 CollectDamaged(node.children[i]); | 94 CollectDamaged(node.children[i]); |
95 } | 95 } |
96 } | 96 } |
97 | 97 |
98 // Recursively collects all newly compiled functions that are going into | 98 // Recursively collects all newly compiled functions that are going into |
99 // business and should be have link to the actual script updated. | 99 // business and should have link to the actual script updated. |
100 function CollectNew(node_list) { | 100 function CollectNew(node_list) { |
101 for (var i = 0; i < node_list.length; i++) { | 101 for (var i = 0; i < node_list.length; i++) { |
102 link_to_original_script_list.push(node_list[i]); | 102 link_to_original_script_list.push(node_list[i]); |
103 CollectNew(node_list[i].children); | 103 CollectNew(node_list[i].children); |
104 } | 104 } |
105 } | 105 } |
106 | 106 |
107 if (old_node.status == FunctionStatus.DAMAGED) { | 107 if (old_node.status == FunctionStatus.DAMAGED) { |
108 CollectDamaged(old_node); | 108 CollectDamaged(old_node); |
109 return; | 109 return; |
110 } | 110 } |
111 if (old_node.status == FunctionStatus.UNCHANGED) { | 111 if (old_node.status == FunctionStatus.UNCHANGED) { |
112 update_positions_list.push(old_node); | 112 update_positions_list.push(old_node); |
113 } else if (old_node.status == FunctionStatus.SOURCE_CHANGED) { | 113 } else if (old_node.status == FunctionStatus.SOURCE_CHANGED) { |
114 update_positions_list.push(old_node); | 114 update_positions_list.push(old_node); |
115 } else if (old_node.status == FunctionStatus.CHANGED) { | 115 } else if (old_node.status == FunctionStatus.CHANGED) { |
116 replace_code_list.push(old_node); | 116 replace_code_list.push(old_node); |
117 CollectNew(old_node.unmatched_new_nodes); | 117 CollectNew(old_node.unmatched_new_nodes); |
118 } | 118 } |
119 for (var i = 0; i < old_node.children.length; i++) { | 119 for (var i = 0; i < old_node.children.length; i++) { |
120 HarvestTodo(old_node.children[i]); | 120 HarvestTodo(old_node.children[i]); |
121 } | 121 } |
122 } | 122 } |
123 | 123 |
124 var preview_description = { | |
125 change_tree: DescribeChangeTree(root_old_node), | |
126 textual_diff: { | |
127 old_len: old_source.length, | |
128 new_len: new_source.length, | |
129 chunks: diff_array | |
130 }, | |
131 updated: false | |
132 }; | |
133 | |
134 if (preview_only) { | |
135 return preview_description; | |
136 } | |
137 | |
124 HarvestTodo(root_old_node); | 138 HarvestTodo(root_old_node); |
125 | 139 |
126 // Collect shared infos for functions whose code need to be patched. | 140 // Collect shared infos for functions whose code need to be patched. |
127 var replaced_function_infos = new Array(); | 141 var replaced_function_infos = new Array(); |
128 for (var i = 0; i < replace_code_list.length; i++) { | 142 for (var i = 0; i < replace_code_list.length; i++) { |
129 var info_wrapper = replace_code_list[i].live_shared_info_wrapper; | 143 var info_wrapper = replace_code_list[i].live_shared_info_wrapper; |
130 if (info_wrapper) { | 144 if (info_wrapper) { |
131 replaced_function_infos.push(info_wrapper); | 145 replaced_function_infos.push(info_wrapper); |
132 } | 146 } |
133 } | 147 } |
134 | 148 |
135 // Check that function being patched is not currently on stack. | |
136 CheckStackActivations(replaced_function_infos, change_log); | |
137 | |
138 | |
139 // We haven't changed anything before this line yet. | 149 // We haven't changed anything before this line yet. |
140 // Committing all changes. | 150 // Committing all changes. |
141 | 151 |
152 // Check that function being patched is not currently on stack or drop them. | |
153 var dropped_functions_number = | |
154 CheckStackActivations(replaced_function_infos, change_log); | |
155 | |
156 preview_description.stack_modified = dropped_functions_number != 0; | |
157 | |
142 // Start with breakpoints. Convert their line/column positions and | 158 // Start with breakpoints. Convert their line/column positions and |
143 // temporary remove. | 159 // temporary remove. |
144 var break_points_restorer = TemporaryRemoveBreakPoints(script, change_log); | 160 var break_points_restorer = TemporaryRemoveBreakPoints(script, change_log); |
145 | 161 |
146 var old_script; | 162 var old_script; |
147 | 163 |
148 // Create an old script only if there are function that should be linked | 164 // Create an old script only if there are function that should be linked |
149 // to old version. | 165 // to old version. |
150 if (link_to_old_script_list.length == 0) { | 166 if (link_to_old_script_list.length == 0) { |
151 %LiveEditReplaceScript(script, new_source, null); | 167 %LiveEditReplaceScript(script, new_source, null); |
152 old_script = void 0; | 168 old_script = void 0; |
153 } else { | 169 } else { |
154 var old_script_name = CreateNameForOldScript(script); | 170 var old_script_name = CreateNameForOldScript(script); |
155 | 171 |
156 // Update the script text and create a new script representing an old | 172 // Update the script text and create a new script representing an old |
157 // version of the script. | 173 // version of the script. |
158 old_script = %LiveEditReplaceScript(script, new_source, | 174 old_script = %LiveEditReplaceScript(script, new_source, |
159 old_script_name); | 175 old_script_name); |
160 | 176 |
161 var link_to_old_script_report = new Array(); | 177 var link_to_old_script_report = new Array(); |
162 change_log.push( { linked_to_old_script: link_to_old_script_report } ); | 178 change_log.push( { linked_to_old_script: link_to_old_script_report } ); |
163 | 179 |
164 // We need to link to old script all former nested functions. | 180 // We need to link to old script all former nested functions. |
165 for (var i = 0; i < link_to_old_script_list.length; i++) { | 181 for (var i = 0; i < link_to_old_script_list.length; i++) { |
166 LinkToOldScript(link_to_old_script_list[i], old_script, | 182 LinkToOldScript(link_to_old_script_list[i], old_script, |
167 link_to_old_script_report); | 183 link_to_old_script_report); |
168 } | 184 } |
185 | |
186 preview_description.created_script_name = old_script_name; | |
169 } | 187 } |
170 | 188 |
171 // Link to an actual script all the functions that we are going to use. | 189 // Link to an actual script all the functions that we are going to use. |
172 for (var i = 0; i < link_to_original_script_list.length; i++) { | 190 for (var i = 0; i < link_to_original_script_list.length; i++) { |
173 %LiveEditFunctionSetScript( | 191 %LiveEditFunctionSetScript( |
174 link_to_original_script_list[i].info.shared_function_info, script); | 192 link_to_original_script_list[i].info.shared_function_info, script); |
175 } | 193 } |
176 | 194 |
177 for (var i = 0; i < replace_code_list.length; i++) { | 195 for (var i = 0; i < replace_code_list.length; i++) { |
178 PatchFunctionCode(replace_code_list[i], change_log); | 196 PatchFunctionCode(replace_code_list[i], change_log); |
179 } | 197 } |
180 | 198 |
181 var position_patch_report = new Array(); | 199 var position_patch_report = new Array(); |
182 change_log.push( {position_patched: position_patch_report} ); | 200 change_log.push( {position_patched: position_patch_report} ); |
183 | 201 |
184 for (var i = 0; i < update_positions_list.length; i++) { | 202 for (var i = 0; i < update_positions_list.length; i++) { |
185 // TODO(LiveEdit): take into account wether it's source_changed or | 203 // TODO(LiveEdit): take into account wether it's source_changed or |
186 // unchanged and whether positions changed at all. | 204 // unchanged and whether positions changed at all. |
187 PatchPositions(update_positions_list[i], diff_array, | 205 PatchPositions(update_positions_list[i], diff_array, |
188 position_patch_report); | 206 position_patch_report); |
189 } | 207 } |
190 | 208 |
191 break_points_restorer(pos_translator, old_script); | 209 break_points_restorer(pos_translator, old_script); |
210 | |
211 preview_description.updated = true; | |
212 return preview_description; | |
192 } | 213 } |
193 // Function is public. | 214 // Function is public. |
194 this.ApplyPatchMultiChunk = ApplyPatchMultiChunk; | 215 this.ApplyPatchMultiChunk = ApplyPatchMultiChunk; |
195 | 216 |
196 | 217 |
197 // Fully compiles source string as a script. Returns Array of | 218 // Fully compiles source string as a script. Returns Array of |
198 // FunctionCompileInfo -- a descriptions of all functions of the script. | 219 // FunctionCompileInfo -- a descriptions of all functions of the script. |
199 // Elements of array are ordered by start positions of functions (from top | 220 // Elements of array are ordered by start positions of functions (from top |
200 // to bottom) in the source. Fields outer_index and next_sibling_index help | 221 // to bottom) in the source. Fields outer_index and next_sibling_index help |
201 // to navigate the nesting structure of functions. | 222 // to navigate the nesting structure of functions. |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
487 this.parent = void 0; | 508 this.parent = void 0; |
488 | 509 |
489 this.status = FunctionStatus.UNCHANGED; | 510 this.status = FunctionStatus.UNCHANGED; |
490 // Status explanation is used for debugging purposes and will be shown | 511 // Status explanation is used for debugging purposes and will be shown |
491 // in user UI if some explanations are needed. | 512 // in user UI if some explanations are needed. |
492 this.status_explanation = void 0; | 513 this.status_explanation = void 0; |
493 this.new_start_pos = void 0; | 514 this.new_start_pos = void 0; |
494 this.new_end_pos = void 0; | 515 this.new_end_pos = void 0; |
495 this.corresponding_node = void 0; | 516 this.corresponding_node = void 0; |
496 this.unmatched_new_nodes = void 0; | 517 this.unmatched_new_nodes = void 0; |
518 | |
519 // 'Textual' correspondence/matching is weaker than 'pure' | |
520 // correspondence/matching. We need 'textual' level for visual presentation | |
521 // in UI, we use 'pure' level for actual code manipulation. | |
522 // Sometimes only function body is changed (functions in old and new script | |
523 // textually correspond), but we cannot patch the code, so we see them | |
524 // as an old function deleted and new function created. | |
525 this.textual_corresponding_node = void 0; | |
526 this.textually_unmatched_new_nodes = void 0; | |
527 | |
497 this.live_shared_info_wrapper = void 0; | 528 this.live_shared_info_wrapper = void 0; |
498 } | 529 } |
499 | 530 |
500 // From array of function infos that is implicitly a tree creates | 531 // From array of function infos that is implicitly a tree creates |
501 // an actual tree of functions in script. | 532 // an actual tree of functions in script. |
502 function BuildCodeInfoTree(code_info_array) { | 533 function BuildCodeInfoTree(code_info_array) { |
503 // Throughtout all function we iterate over input array. | 534 // Throughtout all function we iterate over input array. |
504 var index = 0; | 535 var index = 0; |
505 | 536 |
506 // Recursive function that builds a branch of tree. | 537 // Recursive function that builds a branch of tree. |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
633 // splits a function into 2 functions. | 664 // splits a function into 2 functions. |
634 function FindCorrespondingFunctions(old_code_tree, new_code_tree) { | 665 function FindCorrespondingFunctions(old_code_tree, new_code_tree) { |
635 | 666 |
636 // A recursive function that tries to find a correspondence for all | 667 // A recursive function that tries to find a correspondence for all |
637 // child functions and for their inner functions. | 668 // child functions and for their inner functions. |
638 function ProcessChildren(old_node, new_node) { | 669 function ProcessChildren(old_node, new_node) { |
639 var old_children = old_node.children; | 670 var old_children = old_node.children; |
640 var new_children = new_node.children; | 671 var new_children = new_node.children; |
641 | 672 |
642 var unmatched_new_nodes_list = []; | 673 var unmatched_new_nodes_list = []; |
674 var textually_unmatched_new_nodes_list = []; | |
643 | 675 |
644 var old_index = 0; | 676 var old_index = 0; |
645 var new_index = 0; | 677 var new_index = 0; |
646 while (old_index < old_children.length) { | 678 while (old_index < old_children.length) { |
647 if (old_children[old_index].status == FunctionStatus.DAMAGED) { | 679 if (old_children[old_index].status == FunctionStatus.DAMAGED) { |
648 old_index++; | 680 old_index++; |
649 } else if (new_index < new_children.length) { | 681 } else if (new_index < new_children.length) { |
650 if (new_children[new_index].info.start_position < | 682 if (new_children[new_index].info.start_position < |
651 old_children[old_index].new_start_pos) { | 683 old_children[old_index].new_start_pos) { |
652 unmatched_new_nodes_list.push(new_children[new_index]); | 684 unmatched_new_nodes_list.push(new_children[new_index]); |
685 textually_unmatched_new_nodes_list.push(new_children[new_index]); | |
653 new_index++; | 686 new_index++; |
654 } else if (new_children[new_index].info.start_position == | 687 } else if (new_children[new_index].info.start_position == |
655 old_children[old_index].new_start_pos) { | 688 old_children[old_index].new_start_pos) { |
656 if (new_children[new_index].info.end_position == | 689 if (new_children[new_index].info.end_position == |
657 old_children[old_index].new_end_pos) { | 690 old_children[old_index].new_end_pos) { |
658 old_children[old_index].corresponding_node = | 691 old_children[old_index].corresponding_node = |
659 new_children[new_index]; | 692 new_children[new_index]; |
693 old_children[old_index].textual_corresponding_node = | |
694 new_children[new_index]; | |
660 if (old_children[old_index].status != FunctionStatus.UNCHANGED) { | 695 if (old_children[old_index].status != FunctionStatus.UNCHANGED) { |
661 ProcessChildren(old_children[old_index], | 696 ProcessChildren(old_children[old_index], |
662 new_children[new_index]); | 697 new_children[new_index]); |
663 if (old_children[old_index].status == FunctionStatus.DAMAGED) { | 698 if (old_children[old_index].status == FunctionStatus.DAMAGED) { |
664 unmatched_new_nodes_list.push( | 699 unmatched_new_nodes_list.push( |
665 old_children[old_index].corresponding_node); | 700 old_children[old_index].corresponding_node); |
666 old_children[old_index].corresponding_node = void 0; | 701 old_children[old_index].corresponding_node = void 0; |
667 old_node.status = FunctionStatus.CHANGED; | 702 old_node.status = FunctionStatus.CHANGED; |
668 } | 703 } |
669 } | 704 } |
670 } else { | 705 } else { |
671 old_children[old_index].status = FunctionStatus.DAMAGED; | 706 old_children[old_index].status = FunctionStatus.DAMAGED; |
672 old_children[old_index].status_explanation = | 707 old_children[old_index].status_explanation = |
673 "No corresponding function in new script found"; | 708 "No corresponding function in new script found"; |
674 old_node.status = FunctionStatus.CHANGED; | 709 old_node.status = FunctionStatus.CHANGED; |
675 unmatched_new_nodes_list.push(new_children[new_index]); | 710 unmatched_new_nodes_list.push(new_children[new_index]); |
711 textually_unmatched_new_nodes_list.push(new_children[new_index]); | |
676 } | 712 } |
677 new_index++; | 713 new_index++; |
678 old_index++; | 714 old_index++; |
679 } else { | 715 } else { |
680 old_children[old_index].status = FunctionStatus.DAMAGED; | 716 old_children[old_index].status = FunctionStatus.DAMAGED; |
681 old_children[old_index].status_explanation = | 717 old_children[old_index].status_explanation = |
682 "No corresponding function in new script found"; | 718 "No corresponding function in new script found"; |
683 old_node.status = FunctionStatus.CHANGED; | 719 old_node.status = FunctionStatus.CHANGED; |
684 old_index++; | 720 old_index++; |
685 } | 721 } |
686 } else { | 722 } else { |
687 old_children[old_index].status = FunctionStatus.DAMAGED; | 723 old_children[old_index].status = FunctionStatus.DAMAGED; |
688 old_children[old_index].status_explanation = | 724 old_children[old_index].status_explanation = |
689 "No corresponding function in new script found"; | 725 "No corresponding function in new script found"; |
690 old_node.status = FunctionStatus.CHANGED; | 726 old_node.status = FunctionStatus.CHANGED; |
691 old_index++; | 727 old_index++; |
692 } | 728 } |
693 } | 729 } |
694 | 730 |
695 while (new_index < new_children.length) { | 731 while (new_index < new_children.length) { |
696 unmatched_new_nodes_list.push(new_children[new_index]); | 732 unmatched_new_nodes_list.push(new_children[new_index]); |
733 textually_unmatched_new_nodes_list.push(new_children[new_index]); | |
697 new_index++; | 734 new_index++; |
698 } | 735 } |
699 | 736 |
700 if (old_node.status == FunctionStatus.CHANGED) { | 737 if (old_node.status == FunctionStatus.CHANGED) { |
701 if (!CompareFunctionExpectations(old_node.info, new_node.info)) { | 738 var why_wrong_expectations = |
739 WhyFunctionExpectationsDiffer(old_node.info, new_node.info); | |
740 if (why_wrong_expectations) { | |
702 old_node.status = FunctionStatus.DAMAGED; | 741 old_node.status = FunctionStatus.DAMAGED; |
703 old_node.status_explanation = "Changed code expectations"; | 742 old_node.status_explanation = why_wrong_expectations; |
704 } | 743 } |
705 } | 744 } |
706 old_node.unmatched_new_nodes = unmatched_new_nodes_list; | 745 old_node.unmatched_new_nodes = unmatched_new_nodes_list; |
746 old_node.textually_unmatched_new_nodes = | |
747 textually_unmatched_new_nodes_list; | |
707 } | 748 } |
708 | 749 |
709 ProcessChildren(old_code_tree, new_code_tree); | 750 ProcessChildren(old_code_tree, new_code_tree); |
710 | 751 |
711 old_code_tree.corresponding_node = new_code_tree; | 752 old_code_tree.corresponding_node = new_code_tree; |
753 old_code_tree.textual_corresponding_node = new_code_tree; | |
754 | |
712 Assert(old_code_tree.status != FunctionStatus.DAMAGED, | 755 Assert(old_code_tree.status != FunctionStatus.DAMAGED, |
713 "Script became damaged"); | 756 "Script became damaged"); |
714 } | 757 } |
715 | 758 |
716 function FindLiveSharedInfos(old_code_tree, script) { | 759 function FindLiveSharedInfos(old_code_tree, script) { |
717 var shared_raw_list = %LiveEditFindSharedFunctionInfosForScript(script); | 760 var shared_raw_list = %LiveEditFindSharedFunctionInfosForScript(script); |
718 | 761 |
719 var shared_infos = new Array(); | 762 var shared_infos = new Array(); |
720 | 763 |
721 for (var i = 0; i < shared_raw_list.length; i++) { | 764 for (var i = 0; i < shared_raw_list.length; i++) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
785 report_array.push( { name: old_info_node.info.function_name } ); | 828 report_array.push( { name: old_info_node.info.function_name } ); |
786 } | 829 } |
787 | 830 |
788 // Adds a suffix to script name to mark that it is old version. | 831 // Adds a suffix to script name to mark that it is old version. |
789 function CreateNameForOldScript(script) { | 832 function CreateNameForOldScript(script) { |
790 // TODO(635): try better than this; support several changes. | 833 // TODO(635): try better than this; support several changes. |
791 return script.name + " (old)"; | 834 return script.name + " (old)"; |
792 } | 835 } |
793 | 836 |
794 // Compares a function interface old and new version, whether it | 837 // Compares a function interface old and new version, whether it |
795 // changed or not. | 838 // changed or not. Returns explanation if they differ. |
796 function CompareFunctionExpectations(function_info1, function_info2) { | 839 function WhyFunctionExpectationsDiffer(function_info1, function_info2) { |
797 // Check that function has the same number of parameters (there may exist | 840 // Check that function has the same number of parameters (there may exist |
798 // an adapter, that won't survive function parameter number change). | 841 // an adapter, that won't survive function parameter number change). |
799 if (function_info1.param_num != function_info2.param_num) { | 842 if (function_info1.param_num != function_info2.param_num) { |
800 return false; | 843 return "Changed parameter number: " + function_info1.param_num + |
844 " and " + function_info2.param_num; | |
801 } | 845 } |
802 var scope_info1 = function_info1.scope_info; | 846 var scope_info1 = function_info1.scope_info; |
803 var scope_info2 = function_info2.scope_info; | 847 var scope_info2 = function_info2.scope_info; |
804 | 848 |
805 if (!scope_info1) { | 849 var scope_info1_text; |
806 return !scope_info2; | 850 var scope_info2_text; |
851 | |
852 if (scope_info1) { | |
853 scope_info1_text = scope_info1.toString(); | |
854 } else { | |
855 scope_info1_text = ""; | |
807 } | 856 } |
808 | 857 if (scope_info2) { |
809 if (scope_info1.length != scope_info2.length) { | 858 scope_info2_text = scope_info2.toString(); |
810 return false; | 859 } else { |
860 scope_info2_text = ""; | |
811 } | 861 } |
812 | 862 |
813 // Check that outer scope structure is not changed. Otherwise the function | 863 if (scope_info1_text != scope_info2_text) { |
814 // will not properly work with existing scopes. | 864 return "Incompatible variable maps: [" + scope_info1_text + |
815 return scope_info1.toString() == scope_info2.toString(); | 865 "] and [" + scope_info2_text + "]"; |
866 } | |
867 return; | |
mnaganov (inactive)
2010/07/02 16:23:36
I would expect a comment here.
Peter Rybin
2013/06/26 19:39:57
Done.
| |
816 } | 868 } |
817 | 869 |
818 // Minifier forward declaration. | 870 // Minifier forward declaration. |
819 var FunctionPatchabilityStatus; | 871 var FunctionPatchabilityStatus; |
820 | 872 |
821 // For array of wrapped shared function infos checks that none of them | 873 // For array of wrapped shared function infos checks that none of them |
822 // have activations on stack (of any thread). Throws a Failure exception | 874 // have activations on stack (of any thread). Throws a Failure exception |
823 // if this proves to be false. | 875 // if this proves to be false. |
824 function CheckStackActivations(shared_wrapper_list, change_log) { | 876 function CheckStackActivations(shared_wrapper_list, change_log) { |
825 var shared_list = new Array(); | 877 var shared_list = new Array(); |
(...skipping 23 matching lines...) Expand all Loading... | |
849 problems.push(description); | 901 problems.push(description); |
850 } | 902 } |
851 } | 903 } |
852 if (dropped.length > 0) { | 904 if (dropped.length > 0) { |
853 change_log.push({ dropped_from_stack: dropped }); | 905 change_log.push({ dropped_from_stack: dropped }); |
854 } | 906 } |
855 if (problems.length > 0) { | 907 if (problems.length > 0) { |
856 change_log.push( { functions_on_stack: problems } ); | 908 change_log.push( { functions_on_stack: problems } ); |
857 throw new Failure("Blocked by functions on stack"); | 909 throw new Failure("Blocked by functions on stack"); |
858 } | 910 } |
911 | |
912 return dropped.length; | |
859 } | 913 } |
860 | 914 |
861 // A copy of the FunctionPatchabilityStatus enum from liveedit.h | 915 // A copy of the FunctionPatchabilityStatus enum from liveedit.h |
862 var FunctionPatchabilityStatus = { | 916 var FunctionPatchabilityStatus = { |
863 AVAILABLE_FOR_PATCH: 1, | 917 AVAILABLE_FOR_PATCH: 1, |
864 BLOCKED_ON_ACTIVE_STACK: 2, | 918 BLOCKED_ON_ACTIVE_STACK: 2, |
865 BLOCKED_ON_OTHER_STACK: 3, | 919 BLOCKED_ON_OTHER_STACK: 3, |
866 BLOCKED_UNDER_NATIVE_CODE: 4, | 920 BLOCKED_UNDER_NATIVE_CODE: 4, |
867 REPLACED_ON_ACTIVE_STACK: 5 | 921 REPLACED_ON_ACTIVE_STACK: 5 |
868 } | 922 } |
(...skipping 21 matching lines...) Expand all Loading... | |
890 } | 944 } |
891 | 945 |
892 // A testing entry. | 946 // A testing entry. |
893 function GetPcFromSourcePos(func, source_pos) { | 947 function GetPcFromSourcePos(func, source_pos) { |
894 return %GetFunctionCodePositionFromSource(func, source_pos); | 948 return %GetFunctionCodePositionFromSource(func, source_pos); |
895 } | 949 } |
896 // Function is public. | 950 // Function is public. |
897 this.GetPcFromSourcePos = GetPcFromSourcePos; | 951 this.GetPcFromSourcePos = GetPcFromSourcePos; |
898 | 952 |
899 // LiveEdit main entry point: changes a script text to a new string. | 953 // LiveEdit main entry point: changes a script text to a new string. |
900 function SetScriptSource(script, new_source, change_log) { | 954 function SetScriptSource(script, new_source, preview_only, change_log) { |
901 var old_source = script.source; | 955 var old_source = script.source; |
902 var diff = CompareStringsLinewise(old_source, new_source); | 956 var diff = CompareStringsLinewise(old_source, new_source); |
903 if (diff.length == 0) { | 957 return ApplyPatchMultiChunk(script, diff, new_source, preview_only, |
904 change_log.push( { empty_diff: true } ); | 958 change_log); |
905 return; | |
906 } | |
907 ApplyPatchMultiChunk(script, diff, new_source, change_log); | |
908 } | 959 } |
909 // Function is public. | 960 // Function is public. |
910 this.SetScriptSource = SetScriptSource; | 961 this.SetScriptSource = SetScriptSource; |
911 | 962 |
912 function CompareStringsLinewise(s1, s2) { | 963 function CompareStringsLinewise(s1, s2) { |
913 return %LiveEditCompareStringsLinewise(s1, s2); | 964 return %LiveEditCompareStringsLinewise(s1, s2); |
914 } | 965 } |
915 | 966 |
916 // Applies the change to the script. | 967 // Applies the change to the script. |
917 // The change is always a substring (change_pos, change_pos + change_len) | 968 // The change is always a substring (change_pos, change_pos + change_len) |
918 // being replaced with a completely different string new_str. | 969 // being replaced with a completely different string new_str. |
919 // This API is a legacy and is obsolete. | 970 // This API is a legacy and is obsolete. |
920 // | 971 // |
921 // @param {Script} script that is being changed | 972 // @param {Script} script that is being changed |
922 // @param {Array} change_log a list that collects engineer-readable | 973 // @param {Array} change_log a list that collects engineer-readable |
923 // description of what happened. | 974 // description of what happened. |
924 function ApplySingleChunkPatch(script, change_pos, change_len, new_str, | 975 function ApplySingleChunkPatch(script, change_pos, change_len, new_str, |
925 change_log) { | 976 change_log) { |
926 var old_source = script.source; | 977 var old_source = script.source; |
927 | 978 |
928 // Prepare new source string. | 979 // Prepare new source string. |
929 var new_source = old_source.substring(0, change_pos) + | 980 var new_source = old_source.substring(0, change_pos) + |
930 new_str + old_source.substring(change_pos + change_len); | 981 new_str + old_source.substring(change_pos + change_len); |
931 | 982 |
932 return ApplyPatchMultiChunk(script, | 983 return ApplyPatchMultiChunk(script, |
933 [ change_pos, change_pos + change_len, change_pos + new_str.length], | 984 [ change_pos, change_pos + change_len, change_pos + new_str.length], |
934 new_source, change_log); | 985 new_source, false, change_log); |
986 } | |
987 | |
988 // Creates JSON description for a change tree. | |
989 function DescribeChangeTree(old_code_tree) { | |
990 | |
991 function ProcessOldNode(node) { | |
992 var child_infos = []; | |
993 for (var i = 0; i < node.children.length; i++) { | |
994 var child = node.children[i]; | |
995 if (child.status != FunctionStatus.UNCHANGED) { | |
996 child_infos.push(ProcessOldNode(child)); | |
997 } | |
998 } | |
999 var new_child_infos = []; | |
1000 if (node.textually_unmatched_new_nodes) { | |
1001 for (var i = 0; i < node.textually_unmatched_new_nodes.length; i++) { | |
1002 var child = node.textually_unmatched_new_nodes[i]; | |
1003 new_child_infos.push(ProcessNewNode(child)); | |
1004 } | |
1005 } | |
1006 var res = { | |
1007 name: node.info.function_name, | |
1008 positions: DescribePositions(node), | |
1009 status: node.status, | |
1010 children: child_infos, | |
1011 new_children: new_child_infos | |
1012 }; | |
1013 if (node.status_explanation) { | |
1014 res.status_explanation = node.status_explanation; | |
1015 } | |
1016 if (node.textual_corresponding_node) { | |
1017 res.new_positions = DescribePositions(node.textual_corresponding_node); | |
1018 } | |
1019 return res; | |
1020 } | |
1021 | |
1022 function ProcessNewNode(node) { | |
1023 var child_infos = []; | |
1024 // Do not list ancestors. | |
1025 if (false) { | |
1026 for (var i = 0; i < node.children.length; i++) { | |
1027 child_infos.push(ProcessNewNode(node.children[i])); | |
1028 } | |
1029 } | |
1030 var res = { | |
1031 name: node.info.function_name, | |
1032 positions: DescribePositions(node), | |
1033 children: child_infos, | |
1034 }; | |
1035 return res; | |
1036 } | |
1037 | |
1038 function DescribePositions(node) { | |
1039 return { | |
1040 start_position: node.info.start_position, | |
1041 end_position: node.info.end_position | |
1042 }; | |
1043 } | |
1044 | |
1045 return ProcessOldNode(old_code_tree); | |
935 } | 1046 } |
936 | 1047 |
937 | 1048 |
938 // Functions are public for tests. | 1049 // Functions are public for tests. |
939 this.TestApi = { | 1050 this.TestApi = { |
940 PosTranslator: PosTranslator, | 1051 PosTranslator: PosTranslator, |
941 CompareStringsLinewise: CompareStringsLinewise, | 1052 CompareStringsLinewise: CompareStringsLinewise, |
942 ApplySingleChunkPatch: ApplySingleChunkPatch | 1053 ApplySingleChunkPatch: ApplySingleChunkPatch |
943 } | 1054 } |
944 } | 1055 } |
OLD | NEW |