Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(42)

Side by Side Diff: src/liveedit-debugger.js

Issue 2883020: Describe LiveEdit changes and support preview mode (Closed)
Patch Set: tests Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/debug-debugger.js ('k') | test/mjsunit/debug-liveedit-3.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « src/debug-debugger.js ('k') | test/mjsunit/debug-liveedit-3.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698