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

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

Issue 3797009: Remove trailing spaces from js files. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 10 years, 2 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 | Annotate | Revision Log
« no previous file with comments | « src/debug-debugger.js ('k') | src/messages.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 28 matching lines...) Expand all
39 // version of the script) it remains unchanged, but the code that could 39 // version of the script) it remains unchanged, but the code that could
40 // create a new instance of this function goes away. An old version of script 40 // create a new instance of this function goes away. An old version of script
41 // is created to back up this obsolete function. 41 // is created to back up this obsolete function.
42 // All unchanged functions have their positions updated accordingly. 42 // All unchanged functions have their positions updated accordingly.
43 // 43 //
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
Lasse Reichstein 2010/10/15 13:00:41 One line spacing here should be sufficient.
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, preview_only, 54 function ApplyPatchMultiChunk(script, diff_array, new_source, preview_only,
55 change_log) { 55 change_log) {
56 56
57 var old_source = script.source; 57 var old_source = script.source;
58 58
59 // Gather compile information about old version of script. 59 // Gather compile information about old version of script.
60 var old_compile_info = GatherCompileInfo(old_source, script); 60 var old_compile_info = GatherCompileInfo(old_source, script);
61 61
62 // Build tree structures for old and new versions of the script. 62 // Build tree structures for old and new versions of the script.
63 var root_old_node = BuildCodeInfoTree(old_compile_info); 63 var root_old_node = BuildCodeInfoTree(old_compile_info);
64 64
65 var pos_translator = new PosTranslator(diff_array); 65 var pos_translator = new PosTranslator(diff_array);
66 66
67 // Analyze changes. 67 // Analyze changes.
68 MarkChangedFunctions(root_old_node, pos_translator.GetChunks()); 68 MarkChangedFunctions(root_old_node, pos_translator.GetChunks());
69 69
70 // Find all SharedFunctionInfo's that were compiled from this script. 70 // Find all SharedFunctionInfo's that were compiled from this script.
71 FindLiveSharedInfos(root_old_node, script); 71 FindLiveSharedInfos(root_old_node, script);
72 72
73 // Gather compile information about new version of script. 73 // Gather compile information about new version of script.
74 var new_compile_info; 74 var new_compile_info;
75 try { 75 try {
76 new_compile_info = GatherCompileInfo(new_source, script); 76 new_compile_info = GatherCompileInfo(new_source, script);
77 } catch (e) { 77 } catch (e) {
78 throw new Failure("Failed to compile new version of script: " + e); 78 throw new Failure("Failed to compile new version of script: " + e);
79 } 79 }
80 var root_new_node = BuildCodeInfoTree(new_compile_info); 80 var root_new_node = BuildCodeInfoTree(new_compile_info);
81 81
82 // Link recompiled script data with other data. 82 // Link recompiled script data with other data.
83 FindCorrespondingFunctions(root_old_node, root_new_node); 83 FindCorrespondingFunctions(root_old_node, root_new_node);
84 84
85 // Prepare to-do lists. 85 // Prepare to-do lists.
86 var replace_code_list = new Array(); 86 var replace_code_list = new Array();
87 var link_to_old_script_list = new Array(); 87 var link_to_old_script_list = new Array();
88 var link_to_original_script_list = new Array(); 88 var link_to_original_script_list = new Array();
89 var update_positions_list = new Array(); 89 var update_positions_list = new Array();
90 90
91 function HarvestTodo(old_node) { 91 function HarvestTodo(old_node) {
92 function CollectDamaged(node) { 92 function CollectDamaged(node) {
93 link_to_old_script_list.push(node); 93 link_to_old_script_list.push(node);
94 for (var i = 0; i < node.children.length; i++) { 94 for (var i = 0; i < node.children.length; i++) {
95 CollectDamaged(node.children[i]); 95 CollectDamaged(node.children[i]);
96 } 96 }
97 } 97 }
98 98
99 // Recursively collects all newly compiled functions that are going into 99 // Recursively collects all newly compiled functions that are going into
100 // business and should have link to the actual script updated. 100 // business and should have link to the actual script updated.
101 function CollectNew(node_list) { 101 function CollectNew(node_list) {
102 for (var i = 0; i < node_list.length; i++) { 102 for (var i = 0; i < node_list.length; i++) {
103 link_to_original_script_list.push(node_list[i]); 103 link_to_original_script_list.push(node_list[i]);
104 CollectNew(node_list[i].children); 104 CollectNew(node_list[i].children);
105 } 105 }
106 } 106 }
107 107
108 if (old_node.status == FunctionStatus.DAMAGED) { 108 if (old_node.status == FunctionStatus.DAMAGED) {
109 CollectDamaged(old_node); 109 CollectDamaged(old_node);
110 return; 110 return;
111 } 111 }
112 if (old_node.status == FunctionStatus.UNCHANGED) { 112 if (old_node.status == FunctionStatus.UNCHANGED) {
113 update_positions_list.push(old_node); 113 update_positions_list.push(old_node);
114 } else if (old_node.status == FunctionStatus.SOURCE_CHANGED) { 114 } else if (old_node.status == FunctionStatus.SOURCE_CHANGED) {
115 update_positions_list.push(old_node); 115 update_positions_list.push(old_node);
116 } else if (old_node.status == FunctionStatus.CHANGED) { 116 } else if (old_node.status == FunctionStatus.CHANGED) {
117 replace_code_list.push(old_node); 117 replace_code_list.push(old_node);
118 CollectNew(old_node.unmatched_new_nodes); 118 CollectNew(old_node.unmatched_new_nodes);
119 } 119 }
120 for (var i = 0; i < old_node.children.length; i++) { 120 for (var i = 0; i < old_node.children.length; i++) {
121 HarvestTodo(old_node.children[i]); 121 HarvestTodo(old_node.children[i]);
122 } 122 }
123 } 123 }
124 124
125 var preview_description = { 125 var preview_description = {
126 change_tree: DescribeChangeTree(root_old_node), 126 change_tree: DescribeChangeTree(root_old_node),
127 textual_diff: { 127 textual_diff: {
128 old_len: old_source.length, 128 old_len: old_source.length,
129 new_len: new_source.length, 129 new_len: new_source.length,
130 chunks: diff_array 130 chunks: diff_array
131 }, 131 },
132 updated: false 132 updated: false
133 }; 133 };
134 134
135 if (preview_only) { 135 if (preview_only) {
136 return preview_description; 136 return preview_description;
137 } 137 }
138 138
139 HarvestTodo(root_old_node); 139 HarvestTodo(root_old_node);
140 140
141 // Collect shared infos for functions whose code need to be patched. 141 // Collect shared infos for functions whose code need to be patched.
142 var replaced_function_infos = new Array(); 142 var replaced_function_infos = new Array();
143 for (var i = 0; i < replace_code_list.length; i++) { 143 for (var i = 0; i < replace_code_list.length; i++) {
144 var info_wrapper = replace_code_list[i].live_shared_info_wrapper; 144 var info_wrapper = replace_code_list[i].live_shared_info_wrapper;
145 if (info_wrapper) { 145 if (info_wrapper) {
146 replaced_function_infos.push(info_wrapper); 146 replaced_function_infos.push(info_wrapper);
147 } 147 }
148 } 148 }
149 149
150 // We haven't changed anything before this line yet. 150 // We haven't changed anything before this line yet.
151 // Committing all changes. 151 // Committing all changes.
152 152
153 // Check that function being patched is not currently on stack or drop them. 153 // Check that function being patched is not currently on stack or drop them.
154 var dropped_functions_number = 154 var dropped_functions_number =
155 CheckStackActivations(replaced_function_infos, change_log); 155 CheckStackActivations(replaced_function_infos, change_log);
156 156
157 preview_description.stack_modified = dropped_functions_number != 0; 157 preview_description.stack_modified = dropped_functions_number != 0;
158 158
159 // Start with breakpoints. Convert their line/column positions and 159 // Start with breakpoints. Convert their line/column positions and
160 // temporary remove. 160 // temporary remove.
161 var break_points_restorer = TemporaryRemoveBreakPoints(script, change_log); 161 var break_points_restorer = TemporaryRemoveBreakPoints(script, change_log);
162 162
163 var old_script; 163 var old_script;
164 164
165 // Create an old script only if there are function that should be linked 165 // Create an old script only if there are function that should be linked
166 // to old version. 166 // to old version.
167 if (link_to_old_script_list.length == 0) { 167 if (link_to_old_script_list.length == 0) {
168 %LiveEditReplaceScript(script, new_source, null); 168 %LiveEditReplaceScript(script, new_source, null);
169 old_script = void 0; 169 old_script = void 0;
170 } else { 170 } else {
171 var old_script_name = CreateNameForOldScript(script); 171 var old_script_name = CreateNameForOldScript(script);
172 172
173 // Update the script text and create a new script representing an old 173 // Update the script text and create a new script representing an old
174 // version of the script. 174 // version of the script.
175 old_script = %LiveEditReplaceScript(script, new_source, 175 old_script = %LiveEditReplaceScript(script, new_source,
176 old_script_name); 176 old_script_name);
177 177
178 var link_to_old_script_report = new Array(); 178 var link_to_old_script_report = new Array();
179 change_log.push( { linked_to_old_script: link_to_old_script_report } ); 179 change_log.push( { linked_to_old_script: link_to_old_script_report } );
180 180
181 // We need to link to old script all former nested functions. 181 // We need to link to old script all former nested functions.
182 for (var i = 0; i < link_to_old_script_list.length; i++) { 182 for (var i = 0; i < link_to_old_script_list.length; i++) {
183 LinkToOldScript(link_to_old_script_list[i], old_script, 183 LinkToOldScript(link_to_old_script_list[i], old_script,
184 link_to_old_script_report); 184 link_to_old_script_report);
185 } 185 }
186 186
187 preview_description.created_script_name = old_script_name; 187 preview_description.created_script_name = old_script_name;
188 } 188 }
189 189
190 // Link to an actual script all the functions that we are going to use. 190 // Link to an actual script all the functions that we are going to use.
191 for (var i = 0; i < link_to_original_script_list.length; i++) { 191 for (var i = 0; i < link_to_original_script_list.length; i++) {
192 %LiveEditFunctionSetScript( 192 %LiveEditFunctionSetScript(
193 link_to_original_script_list[i].info.shared_function_info, script); 193 link_to_original_script_list[i].info.shared_function_info, script);
194 } 194 }
195 195
196 for (var i = 0; i < replace_code_list.length; i++) { 196 for (var i = 0; i < replace_code_list.length; i++) {
197 PatchFunctionCode(replace_code_list[i], change_log); 197 PatchFunctionCode(replace_code_list[i], change_log);
198 } 198 }
199 199
200 var position_patch_report = new Array(); 200 var position_patch_report = new Array();
201 change_log.push( {position_patched: position_patch_report} ); 201 change_log.push( {position_patched: position_patch_report} );
202 202
203 for (var i = 0; i < update_positions_list.length; i++) { 203 for (var i = 0; i < update_positions_list.length; i++) {
204 // TODO(LiveEdit): take into account wether it's source_changed or 204 // TODO(LiveEdit): take into account wether it's source_changed or
205 // unchanged and whether positions changed at all. 205 // unchanged and whether positions changed at all.
206 PatchPositions(update_positions_list[i], diff_array, 206 PatchPositions(update_positions_list[i], diff_array,
207 position_patch_report); 207 position_patch_report);
208 } 208 }
209 209
210 break_points_restorer(pos_translator, old_script); 210 break_points_restorer(pos_translator, old_script);
211 211
212 preview_description.updated = true; 212 preview_description.updated = true;
213 return preview_description; 213 return preview_description;
214 } 214 }
215 // Function is public. 215 // Function is public.
216 this.ApplyPatchMultiChunk = ApplyPatchMultiChunk; 216 this.ApplyPatchMultiChunk = ApplyPatchMultiChunk;
217 217
218 218
219 // Fully compiles source string as a script. Returns Array of 219 // Fully compiles source string as a script. Returns Array of
220 // FunctionCompileInfo -- a descriptions of all functions of the script. 220 // FunctionCompileInfo -- a descriptions of all functions of the script.
221 // Elements of array are ordered by start positions of functions (from top 221 // Elements of array are ordered by start positions of functions (from top
222 // to bottom) in the source. Fields outer_index and next_sibling_index help 222 // to bottom) in the source. Fields outer_index and next_sibling_index help
223 // to navigate the nesting structure of functions. 223 // to navigate the nesting structure of functions.
224 // 224 //
225 // All functions get compiled linked to script provided as parameter script. 225 // All functions get compiled linked to script provided as parameter script.
226 // TODO(LiveEdit): consider not using actual scripts as script, because 226 // TODO(LiveEdit): consider not using actual scripts as script, because
227 // we have to manually erase all links right after compile. 227 // we have to manually erase all links right after compile.
228 function GatherCompileInfo(source, script) { 228 function GatherCompileInfo(source, script) {
229 // Get function info, elements are partially sorted (it is a tree of 229 // Get function info, elements are partially sorted (it is a tree of
230 // nested functions serialized as parent followed by serialized children. 230 // nested functions serialized as parent followed by serialized children.
231 var raw_compile_info = %LiveEditGatherCompileInfo(script, source); 231 var raw_compile_info = %LiveEditGatherCompileInfo(script, source);
232 232
233 // Sort function infos by start position field. 233 // Sort function infos by start position field.
234 var compile_info = new Array(); 234 var compile_info = new Array();
235 var old_index_map = new Array(); 235 var old_index_map = new Array();
236 for (var i = 0; i < raw_compile_info.length; i++) { 236 for (var i = 0; i < raw_compile_info.length; i++) {
237 var info = new FunctionCompileInfo(raw_compile_info[i]); 237 var info = new FunctionCompileInfo(raw_compile_info[i]);
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
284 compile_info[previous_sibling].next_sibling_index = -1; 284 compile_info[previous_sibling].next_sibling_index = -1;
285 } 285 }
286 } 286 }
287 287
288 ResetIndexes(-1, -1); 288 ResetIndexes(-1, -1);
289 Assert(current_index == compile_info.length); 289 Assert(current_index == compile_info.length);
290 290
291 return compile_info; 291 return compile_info;
292 } 292 }
293 293
294 294
295 // Replaces function's Code. 295 // Replaces function's Code.
296 function PatchFunctionCode(old_node, change_log) { 296 function PatchFunctionCode(old_node, change_log) {
297 var new_info = old_node.corresponding_node.info; 297 var new_info = old_node.corresponding_node.info;
298 var shared_info_wrapper = old_node.live_shared_info_wrapper; 298 var shared_info_wrapper = old_node.live_shared_info_wrapper;
299 if (shared_info_wrapper) { 299 if (shared_info_wrapper) {
300 %LiveEditReplaceFunctionCode(new_info.raw_array, 300 %LiveEditReplaceFunctionCode(new_info.raw_array,
301 shared_info_wrapper.raw_array); 301 shared_info_wrapper.raw_array);
302 302
303 // The function got a new code. However, this new code brings all new 303 // The function got a new code. However, this new code brings all new
304 // instances of SharedFunctionInfo for nested functions. However, 304 // instances of SharedFunctionInfo for nested functions. However,
305 // we want the original instances to be used wherever possible. 305 // we want the original instances to be used wherever possible.
306 // (This is because old instances and new instances will be both 306 // (This is because old instances and new instances will be both
307 // linked to a script and breakpoints subsystem does not really 307 // linked to a script and breakpoints subsystem does not really
308 // expects this; neither does LiveEdit subsystem on next call). 308 // expects this; neither does LiveEdit subsystem on next call).
309 for (var i = 0; i < old_node.children.length; i++) { 309 for (var i = 0; i < old_node.children.length; i++) {
310 if (old_node.children[i].corresponding_node) { 310 if (old_node.children[i].corresponding_node) {
311 var corresponding_child = old_node.children[i].corresponding_node; 311 var corresponding_child = old_node.children[i].corresponding_node;
312 var child_shared_info_wrapper = 312 var child_shared_info_wrapper =
313 old_node.children[i].live_shared_info_wrapper; 313 old_node.children[i].live_shared_info_wrapper;
314 if (child_shared_info_wrapper) { 314 if (child_shared_info_wrapper) {
315 %LiveEditReplaceRefToNestedFunction(shared_info_wrapper.info, 315 %LiveEditReplaceRefToNestedFunction(shared_info_wrapper.info,
316 corresponding_child.info.shared_function_info, 316 corresponding_child.info.shared_function_info,
317 child_shared_info_wrapper.info); 317 child_shared_info_wrapper.info);
318 } 318 }
319 } 319 }
320 } 320 }
321 321
322 change_log.push( {function_patched: new_info.function_name} ); 322 change_log.push( {function_patched: new_info.function_name} );
323 } else { 323 } else {
324 change_log.push( {function_patched: new_info.function_name, 324 change_log.push( {function_patched: new_info.function_name,
325 function_info_not_found: true} ); 325 function_info_not_found: true} );
326 } 326 }
327 } 327 }
328 328
329 329
330 // Makes a function associated with another instance of a script (the 330 // Makes a function associated with another instance of a script (the
331 // one representing its old version). This way the function still 331 // one representing its old version). This way the function still
332 // may access its own text. 332 // may access its own text.
333 function LinkToOldScript(old_info_node, old_script, report_array) { 333 function LinkToOldScript(old_info_node, old_script, report_array) {
334 var shared_info = old_info_node.live_shared_info_wrapper; 334 var shared_info = old_info_node.live_shared_info_wrapper;
335 if (shared_info) { 335 if (shared_info) {
336 %LiveEditFunctionSetScript(shared_info.info, old_script); 336 %LiveEditFunctionSetScript(shared_info.info, old_script);
337 report_array.push( { name: shared_info.function_name } ); 337 report_array.push( { name: shared_info.function_name } );
338 } else { 338 } else {
339 report_array.push( 339 report_array.push(
340 { name: old_info_node.info.function_name, not_found: true } ); 340 { name: old_info_node.info.function_name, not_found: true } );
341 } 341 }
342 } 342 }
343 343
344 344
345 // Returns function that restores breakpoints. 345 // Returns function that restores breakpoints.
346 function TemporaryRemoveBreakPoints(original_script, change_log) { 346 function TemporaryRemoveBreakPoints(original_script, change_log) {
347 var script_break_points = GetScriptBreakPoints(original_script); 347 var script_break_points = GetScriptBreakPoints(original_script);
348 348
349 var break_points_update_report = []; 349 var break_points_update_report = [];
350 change_log.push( { break_points_update: break_points_update_report } ); 350 change_log.push( { break_points_update: break_points_update_report } );
351 351
352 var break_point_old_positions = []; 352 var break_point_old_positions = [];
353 for (var i = 0; i < script_break_points.length; i++) { 353 for (var i = 0; i < script_break_points.length; i++) {
354 var break_point = script_break_points[i]; 354 var break_point = script_break_points[i];
355 355
356 break_point.clear(); 356 break_point.clear();
357 357
358 // TODO(LiveEdit): be careful with resource offset here. 358 // TODO(LiveEdit): be careful with resource offset here.
359 var break_point_position = Debug.findScriptSourcePosition(original_script, 359 var break_point_position = Debug.findScriptSourcePosition(original_script,
360 break_point.line(), break_point.column()); 360 break_point.line(), break_point.column());
361 361
362 var old_position_description = { 362 var old_position_description = {
363 position: break_point_position, 363 position: break_point_position,
364 line: break_point.line(), 364 line: break_point.line(),
365 column: break_point.column() 365 column: break_point.column()
366 } 366 }
367 break_point_old_positions.push(old_position_description); 367 break_point_old_positions.push(old_position_description);
368 } 368 }
369 369
370 370
371 // Restores breakpoints and creates their copies in the "old" copy of 371 // Restores breakpoints and creates their copies in the "old" copy of
372 // the script. 372 // the script.
373 return function (pos_translator, old_script_copy_opt) { 373 return function (pos_translator, old_script_copy_opt) {
374 // Update breakpoints (change positions and restore them in old version 374 // Update breakpoints (change positions and restore them in old version
375 // of script. 375 // of script.
376 for (var i = 0; i < script_break_points.length; i++) { 376 for (var i = 0; i < script_break_points.length; i++) {
377 var break_point = script_break_points[i]; 377 var break_point = script_break_points[i];
378 if (old_script_copy_opt) { 378 if (old_script_copy_opt) {
379 var clone = break_point.cloneForOtherScript(old_script_copy_opt); 379 var clone = break_point.cloneForOtherScript(old_script_copy_opt);
380 clone.set(old_script_copy_opt); 380 clone.set(old_script_copy_opt);
381 381
382 break_points_update_report.push( { 382 break_points_update_report.push( {
383 type: "copied_to_old", 383 type: "copied_to_old",
384 id: break_point.number(), 384 id: break_point.number(),
385 new_id: clone.number(), 385 new_id: clone.number(),
386 positions: break_point_old_positions[i] 386 positions: break_point_old_positions[i]
387 } ); 387 } );
388 } 388 }
389 389
390 var updated_position = pos_translator.Translate( 390 var updated_position = pos_translator.Translate(
391 break_point_old_positions[i].position, 391 break_point_old_positions[i].position,
392 PosTranslator.ShiftWithTopInsideChunkHandler); 392 PosTranslator.ShiftWithTopInsideChunkHandler);
393 393
394 var new_location = 394 var new_location =
395 original_script.locationFromPosition(updated_position, false); 395 original_script.locationFromPosition(updated_position, false);
396 396
397 break_point.update_positions(new_location.line, new_location.column); 397 break_point.update_positions(new_location.line, new_location.column);
398 398
399 var new_position_description = { 399 var new_position_description = {
400 position: updated_position, 400 position: updated_position,
401 line: new_location.line, 401 line: new_location.line,
402 column: new_location.column 402 column: new_location.column
403 } 403 }
404 404
405 break_point.set(original_script); 405 break_point.set(original_script);
406 406
407 break_points_update_report.push( { type: "position_changed", 407 break_points_update_report.push( { type: "position_changed",
408 id: break_point.number(), 408 id: break_point.number(),
409 old_positions: break_point_old_positions[i], 409 old_positions: break_point_old_positions[i],
410 new_positions: new_position_description 410 new_positions: new_position_description
411 } ); 411 } );
412 } 412 }
413 } 413 }
414 } 414 }
415 415
416 416
417 function Assert(condition, message) { 417 function Assert(condition, message) {
418 if (!condition) { 418 if (!condition) {
419 if (message) { 419 if (message) {
420 throw "Assert " + message; 420 throw "Assert " + message;
421 } else { 421 } else {
422 throw "Assert"; 422 throw "Assert";
423 } 423 }
424 } 424 }
425 } 425 }
426 426
427 function DiffChunk(pos1, pos2, len1, len2) { 427 function DiffChunk(pos1, pos2, len1, len2) {
428 this.pos1 = pos1; 428 this.pos1 = pos1;
429 this.pos2 = pos2; 429 this.pos2 = pos2;
430 this.len1 = len1; 430 this.len1 = len1;
431 this.len2 = len2; 431 this.len2 = len2;
432 } 432 }
433 433
434 function PosTranslator(diff_array) { 434 function PosTranslator(diff_array) {
435 var chunks = new Array(); 435 var chunks = new Array();
436 var current_diff = 0; 436 var current_diff = 0;
437 for (var i = 0; i < diff_array.length; i += 3) { 437 for (var i = 0; i < diff_array.length; i += 3) {
438 var pos1_begin = diff_array[i]; 438 var pos1_begin = diff_array[i];
439 var pos2_begin = pos1_begin + current_diff; 439 var pos2_begin = pos1_begin + current_diff;
440 var pos1_end = diff_array[i + 1]; 440 var pos1_end = diff_array[i + 1];
441 var pos2_end = diff_array[i + 2]; 441 var pos2_end = diff_array[i + 2];
442 chunks.push(new DiffChunk(pos1_begin, pos2_begin, pos1_end - pos1_begin, 442 chunks.push(new DiffChunk(pos1_begin, pos2_begin, pos1_end - pos1_begin,
443 pos2_end - pos2_begin)); 443 pos2_end - pos2_begin));
444 current_diff = pos2_end - pos1_end; 444 current_diff = pos2_end - pos1_end;
445 } 445 }
446 this.chunks = chunks; 446 this.chunks = chunks;
447 } 447 }
448 PosTranslator.prototype.GetChunks = function() { 448 PosTranslator.prototype.GetChunks = function() {
449 return this.chunks; 449 return this.chunks;
450 } 450 }
451 451
452 PosTranslator.prototype.Translate = function(pos, inside_chunk_handler) { 452 PosTranslator.prototype.Translate = function(pos, inside_chunk_handler) {
453 var array = this.chunks; 453 var array = this.chunks;
454 if (array.length == 0 || pos < array[0].pos1) { 454 if (array.length == 0 || pos < array[0].pos1) {
455 return pos; 455 return pos;
456 } 456 }
457 var chunk_index1 = 0; 457 var chunk_index1 = 0;
458 var chunk_index2 = array.length - 1; 458 var chunk_index2 = array.length - 1;
459 459
460 while (chunk_index1 < chunk_index2) { 460 while (chunk_index1 < chunk_index2) {
461 var middle_index = Math.floor((chunk_index1 + chunk_index2) / 2); 461 var middle_index = Math.floor((chunk_index1 + chunk_index2) / 2);
462 if (pos < array[middle_index + 1].pos1) { 462 if (pos < array[middle_index + 1].pos1) {
463 chunk_index2 = middle_index; 463 chunk_index2 = middle_index;
464 } else { 464 } else {
465 chunk_index1 = middle_index + 1; 465 chunk_index1 = middle_index + 1;
466 } 466 }
467 } 467 }
468 var chunk = array[chunk_index1]; 468 var chunk = array[chunk_index1];
469 if (pos >= chunk.pos1 + chunk.len1) { 469 if (pos >= chunk.pos1 + chunk.len1) {
470 return pos + chunk.pos2 + chunk.len2 - chunk.pos1 - chunk.len1; 470 return pos + chunk.pos2 + chunk.len2 - chunk.pos1 - chunk.len1;
471 } 471 }
472 472
473 if (!inside_chunk_handler) { 473 if (!inside_chunk_handler) {
474 inside_chunk_handler = PosTranslator.DefaultInsideChunkHandler; 474 inside_chunk_handler = PosTranslator.DefaultInsideChunkHandler;
475 } 475 }
476 return inside_chunk_handler(pos, chunk); 476 return inside_chunk_handler(pos, chunk);
477 } 477 }
478 478
479 PosTranslator.DefaultInsideChunkHandler = function(pos, diff_chunk) { 479 PosTranslator.DefaultInsideChunkHandler = function(pos, diff_chunk) {
480 Assert(false, "Cannot translate position in changed area"); 480 Assert(false, "Cannot translate position in changed area");
481 } 481 }
482 482
483 PosTranslator.ShiftWithTopInsideChunkHandler = 483 PosTranslator.ShiftWithTopInsideChunkHandler =
484 function(pos, diff_chunk) { 484 function(pos, diff_chunk) {
485 // We carelessly do not check whether we stay inside the chunk after 485 // We carelessly do not check whether we stay inside the chunk after
486 // translation. 486 // translation.
487 return pos - diff_chunk.pos1 + diff_chunk.pos2; 487 return pos - diff_chunk.pos1 + diff_chunk.pos2;
488 } 488 }
489 489
490 var FunctionStatus = { 490 var FunctionStatus = {
491 // No change to function or its inner functions; however its positions 491 // No change to function or its inner functions; however its positions
492 // in script may have been shifted. 492 // in script may have been shifted.
493 UNCHANGED: "unchanged", 493 UNCHANGED: "unchanged",
494 // The code of a function remains unchanged, but something happened inside 494 // The code of a function remains unchanged, but something happened inside
495 // some inner functions. 495 // some inner functions.
496 SOURCE_CHANGED: "source changed", 496 SOURCE_CHANGED: "source changed",
497 // The code of a function is changed or some nested function cannot be 497 // The code of a function is changed or some nested function cannot be
498 // properly patched so this function must be recompiled. 498 // properly patched so this function must be recompiled.
499 CHANGED: "changed", 499 CHANGED: "changed",
500 // Function is changed but cannot be patched. 500 // Function is changed but cannot be patched.
501 DAMAGED: "damaged" 501 DAMAGED: "damaged"
502 } 502 }
503 503
504 function CodeInfoTreeNode(code_info, children, array_index) { 504 function CodeInfoTreeNode(code_info, children, array_index) {
505 this.info = code_info; 505 this.info = code_info;
506 this.children = children; 506 this.children = children;
507 // an index in array of compile_info 507 // an index in array of compile_info
508 this.array_index = array_index; 508 this.array_index = array_index;
509 this.parent = void 0; 509 this.parent = void 0;
510 510
511 this.status = FunctionStatus.UNCHANGED; 511 this.status = FunctionStatus.UNCHANGED;
512 // Status explanation is used for debugging purposes and will be shown 512 // Status explanation is used for debugging purposes and will be shown
513 // in user UI if some explanations are needed. 513 // in user UI if some explanations are needed.
514 this.status_explanation = void 0; 514 this.status_explanation = void 0;
515 this.new_start_pos = void 0; 515 this.new_start_pos = void 0;
516 this.new_end_pos = void 0; 516 this.new_end_pos = void 0;
517 this.corresponding_node = void 0; 517 this.corresponding_node = void 0;
518 this.unmatched_new_nodes = void 0; 518 this.unmatched_new_nodes = void 0;
519 519
520 // 'Textual' correspondence/matching is weaker than 'pure' 520 // 'Textual' correspondence/matching is weaker than 'pure'
521 // correspondence/matching. We need 'textual' level for visual presentation 521 // correspondence/matching. We need 'textual' level for visual presentation
522 // in UI, we use 'pure' level for actual code manipulation. 522 // in UI, we use 'pure' level for actual code manipulation.
523 // Sometimes only function body is changed (functions in old and new script 523 // Sometimes only function body is changed (functions in old and new script
524 // textually correspond), but we cannot patch the code, so we see them 524 // textually correspond), but we cannot patch the code, so we see them
525 // as an old function deleted and new function created. 525 // as an old function deleted and new function created.
526 this.textual_corresponding_node = void 0; 526 this.textual_corresponding_node = void 0;
527 this.textually_unmatched_new_nodes = void 0; 527 this.textually_unmatched_new_nodes = void 0;
528 528
529 this.live_shared_info_wrapper = void 0; 529 this.live_shared_info_wrapper = void 0;
530 } 530 }
531 531
532 // From array of function infos that is implicitly a tree creates 532 // From array of function infos that is implicitly a tree creates
533 // an actual tree of functions in script. 533 // an actual tree of functions in script.
534 function BuildCodeInfoTree(code_info_array) { 534 function BuildCodeInfoTree(code_info_array) {
535 // Throughtout all function we iterate over input array. 535 // Throughtout all function we iterate over input array.
536 var index = 0; 536 var index = 0;
537 537
538 // Recursive function that builds a branch of tree. 538 // Recursive function that builds a branch of tree.
539 function BuildNode() { 539 function BuildNode() {
540 var my_index = index; 540 var my_index = index;
541 index++; 541 index++;
542 var child_array = new Array(); 542 var child_array = new Array();
543 while (index < code_info_array.length && 543 while (index < code_info_array.length &&
544 code_info_array[index].outer_index == my_index) { 544 code_info_array[index].outer_index == my_index) {
545 child_array.push(BuildNode()); 545 child_array.push(BuildNode());
546 } 546 }
547 var node = new CodeInfoTreeNode(code_info_array[my_index], child_array, 547 var node = new CodeInfoTreeNode(code_info_array[my_index], child_array,
548 my_index); 548 my_index);
549 for (var i = 0; i < child_array.length; i++) { 549 for (var i = 0; i < child_array.length; i++) {
550 child_array[i].parent = node; 550 child_array[i].parent = node;
551 } 551 }
552 return node; 552 return node;
553 } 553 }
554 554
555 var root = BuildNode(); 555 var root = BuildNode();
556 Assert(index == code_info_array.length); 556 Assert(index == code_info_array.length);
557 return root; 557 return root;
558 } 558 }
559 559
560 // Applies a list of the textual diff chunks onto the tree of functions. 560 // Applies a list of the textual diff chunks onto the tree of functions.
561 // Determines status of each function (from unchanged to damaged). However 561 // Determines status of each function (from unchanged to damaged). However
562 // children of unchanged functions are ignored. 562 // children of unchanged functions are ignored.
563 function MarkChangedFunctions(code_info_tree, chunks) { 563 function MarkChangedFunctions(code_info_tree, chunks) {
564 564
565 // A convenient interator over diff chunks that also translates 565 // A convenient interator over diff chunks that also translates
566 // positions from old to new in a current non-changed part of script. 566 // positions from old to new in a current non-changed part of script.
567 var chunk_it = new function() { 567 var chunk_it = new function() {
568 var chunk_index = 0; 568 var chunk_index = 0;
569 var pos_diff = 0; 569 var pos_diff = 0;
570 this.current = function() { return chunks[chunk_index]; } 570 this.current = function() { return chunks[chunk_index]; }
571 this.next = function() { 571 this.next = function() {
572 var chunk = chunks[chunk_index]; 572 var chunk = chunks[chunk_index];
573 pos_diff = chunk.pos2 + chunk.len2 - (chunk.pos1 + chunk.len1); 573 pos_diff = chunk.pos2 + chunk.len2 - (chunk.pos1 + chunk.len1);
574 chunk_index++; 574 chunk_index++;
575 } 575 }
576 this.done = function() { return chunk_index >= chunks.length; } 576 this.done = function() { return chunk_index >= chunks.length; }
577 this.TranslatePos = function(pos) { return pos + pos_diff; } 577 this.TranslatePos = function(pos) { return pos + pos_diff; }
578 }; 578 };
579 579
580 // A recursive function that processes internals of a function and all its 580 // A recursive function that processes internals of a function and all its
581 // inner functions. Iterator chunk_it initially points to a chunk that is 581 // inner functions. Iterator chunk_it initially points to a chunk that is
582 // below function start. 582 // below function start.
583 function ProcessInternals(info_node) { 583 function ProcessInternals(info_node) {
584 info_node.new_start_pos = chunk_it.TranslatePos( 584 info_node.new_start_pos = chunk_it.TranslatePos(
585 info_node.info.start_position); 585 info_node.info.start_position);
586 var child_index = 0; 586 var child_index = 0;
587 var code_changed = false; 587 var code_changed = false;
588 var source_changed = false; 588 var source_changed = false;
589 // Simultaneously iterates over child functions and over chunks. 589 // Simultaneously iterates over child functions and over chunks.
590 while (!chunk_it.done() && 590 while (!chunk_it.done() &&
591 chunk_it.current().pos1 < info_node.info.end_position) { 591 chunk_it.current().pos1 < info_node.info.end_position) {
592 if (child_index < info_node.children.length) { 592 if (child_index < info_node.children.length) {
593 var child = info_node.children[child_index]; 593 var child = info_node.children[child_index];
594 594
595 if (child.info.end_position <= chunk_it.current().pos1) { 595 if (child.info.end_position <= chunk_it.current().pos1) {
596 ProcessUnchangedChild(child); 596 ProcessUnchangedChild(child);
597 child_index++; 597 child_index++;
598 continue; 598 continue;
599 } else if (child.info.start_position >= 599 } else if (child.info.start_position >=
600 chunk_it.current().pos1 + chunk_it.current().len1) { 600 chunk_it.current().pos1 + chunk_it.current().len1) {
601 code_changed = true; 601 code_changed = true;
602 chunk_it.next(); 602 chunk_it.next();
603 continue; 603 continue;
604 } else if (child.info.start_position <= chunk_it.current().pos1 && 604 } else if (child.info.start_position <= chunk_it.current().pos1 &&
605 child.info.end_position >= chunk_it.current().pos1 + 605 child.info.end_position >= chunk_it.current().pos1 +
606 chunk_it.current().len1) { 606 chunk_it.current().len1) {
607 ProcessInternals(child); 607 ProcessInternals(child);
608 source_changed = source_changed || 608 source_changed = source_changed ||
609 ( child.status != FunctionStatus.UNCHANGED ); 609 ( child.status != FunctionStatus.UNCHANGED );
610 code_changed = code_changed || 610 code_changed = code_changed ||
611 ( child.status == FunctionStatus.DAMAGED ); 611 ( child.status == FunctionStatus.DAMAGED );
612 child_index++; 612 child_index++;
613 continue; 613 continue;
614 } else { 614 } else {
615 code_changed = true; 615 code_changed = true;
616 child.status = FunctionStatus.DAMAGED; 616 child.status = FunctionStatus.DAMAGED;
617 child.status_explanation = 617 child.status_explanation =
618 "Text diff overlaps with function boundary"; 618 "Text diff overlaps with function boundary";
619 child_index++; 619 child_index++;
620 continue; 620 continue;
621 } 621 }
622 } else { 622 } else {
623 if (chunk_it.current().pos1 + chunk_it.current().len1 <= 623 if (chunk_it.current().pos1 + chunk_it.current().len1 <=
624 info_node.info.end_position) { 624 info_node.info.end_position) {
625 info_node.status = FunctionStatus.CHANGED; 625 info_node.status = FunctionStatus.CHANGED;
626 chunk_it.next(); 626 chunk_it.next();
627 continue; 627 continue;
628 } else { 628 } else {
629 info_node.status = FunctionStatus.DAMAGED; 629 info_node.status = FunctionStatus.DAMAGED;
630 info_node.status_explanation = 630 info_node.status_explanation =
631 "Text diff overlaps with function boundary"; 631 "Text diff overlaps with function boundary";
632 return; 632 return;
633 } 633 }
634 } 634 }
635 Assert("Unreachable", false); 635 Assert("Unreachable", false);
636 } 636 }
637 while (child_index < info_node.children.length) { 637 while (child_index < info_node.children.length) {
638 var child = info_node.children[child_index]; 638 var child = info_node.children[child_index];
639 ProcessUnchangedChild(child); 639 ProcessUnchangedChild(child);
640 child_index++; 640 child_index++;
641 } 641 }
642 if (code_changed) { 642 if (code_changed) {
643 info_node.status = FunctionStatus.CHANGED; 643 info_node.status = FunctionStatus.CHANGED;
644 } else if (source_changed) { 644 } else if (source_changed) {
645 info_node.status = FunctionStatus.SOURCE_CHANGED; 645 info_node.status = FunctionStatus.SOURCE_CHANGED;
646 } 646 }
647 info_node.new_end_pos = 647 info_node.new_end_pos =
648 chunk_it.TranslatePos(info_node.info.end_position); 648 chunk_it.TranslatePos(info_node.info.end_position);
649 } 649 }
650 650
651 function ProcessUnchangedChild(node) { 651 function ProcessUnchangedChild(node) {
652 node.new_start_pos = chunk_it.TranslatePos(node.info.start_position); 652 node.new_start_pos = chunk_it.TranslatePos(node.info.start_position);
653 node.new_end_pos = chunk_it.TranslatePos(node.info.end_position); 653 node.new_end_pos = chunk_it.TranslatePos(node.info.end_position);
654 } 654 }
655 655
656 ProcessInternals(code_info_tree); 656 ProcessInternals(code_info_tree);
657 } 657 }
658 658
659 // For ecah old function (if it is not damaged) tries to find a corresponding 659 // For ecah old function (if it is not damaged) tries to find a corresponding
660 // function in new script. Typically it should succeed (non-damaged functions 660 // function in new script. Typically it should succeed (non-damaged functions
661 // by definition may only have changes inside their bodies). However there are 661 // by definition may only have changes inside their bodies). However there are
662 // reasons for corresponence not to be found; function with unmodified text 662 // reasons for corresponence not to be found; function with unmodified text
663 // in new script may become enclosed into other function; the innocent change 663 // in new script may become enclosed into other function; the innocent change
664 // inside function body may in fact be something like "} function B() {" that 664 // inside function body may in fact be something like "} function B() {" that
665 // splits a function into 2 functions. 665 // splits a function into 2 functions.
666 function FindCorrespondingFunctions(old_code_tree, new_code_tree) { 666 function FindCorrespondingFunctions(old_code_tree, new_code_tree) {
667 667
668 // A recursive function that tries to find a correspondence for all 668 // A recursive function that tries to find a correspondence for all
669 // child functions and for their inner functions. 669 // child functions and for their inner functions.
670 function ProcessChildren(old_node, new_node) { 670 function ProcessChildren(old_node, new_node) {
671 var old_children = old_node.children; 671 var old_children = old_node.children;
672 var new_children = new_node.children; 672 var new_children = new_node.children;
673 673
674 var unmatched_new_nodes_list = []; 674 var unmatched_new_nodes_list = [];
675 var textually_unmatched_new_nodes_list = []; 675 var textually_unmatched_new_nodes_list = [];
676 676
677 var old_index = 0; 677 var old_index = 0;
678 var new_index = 0; 678 var new_index = 0;
679 while (old_index < old_children.length) { 679 while (old_index < old_children.length) {
680 if (old_children[old_index].status == FunctionStatus.DAMAGED) { 680 if (old_children[old_index].status == FunctionStatus.DAMAGED) {
681 old_index++; 681 old_index++;
682 } else if (new_index < new_children.length) { 682 } else if (new_index < new_children.length) {
683 if (new_children[new_index].info.start_position < 683 if (new_children[new_index].info.start_position <
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
721 old_index++; 721 old_index++;
722 } 722 }
723 } else { 723 } else {
724 old_children[old_index].status = FunctionStatus.DAMAGED; 724 old_children[old_index].status = FunctionStatus.DAMAGED;
725 old_children[old_index].status_explanation = 725 old_children[old_index].status_explanation =
726 "No corresponding function in new script found"; 726 "No corresponding function in new script found";
727 old_node.status = FunctionStatus.CHANGED; 727 old_node.status = FunctionStatus.CHANGED;
728 old_index++; 728 old_index++;
729 } 729 }
730 } 730 }
731 731
732 while (new_index < new_children.length) { 732 while (new_index < new_children.length) {
733 unmatched_new_nodes_list.push(new_children[new_index]); 733 unmatched_new_nodes_list.push(new_children[new_index]);
734 textually_unmatched_new_nodes_list.push(new_children[new_index]); 734 textually_unmatched_new_nodes_list.push(new_children[new_index]);
735 new_index++; 735 new_index++;
736 } 736 }
737 737
738 if (old_node.status == FunctionStatus.CHANGED) { 738 if (old_node.status == FunctionStatus.CHANGED) {
739 var why_wrong_expectations = 739 var why_wrong_expectations =
740 WhyFunctionExpectationsDiffer(old_node.info, new_node.info); 740 WhyFunctionExpectationsDiffer(old_node.info, new_node.info);
741 if (why_wrong_expectations) { 741 if (why_wrong_expectations) {
742 old_node.status = FunctionStatus.DAMAGED; 742 old_node.status = FunctionStatus.DAMAGED;
743 old_node.status_explanation = why_wrong_expectations; 743 old_node.status_explanation = why_wrong_expectations;
744 } 744 }
745 } 745 }
746 old_node.unmatched_new_nodes = unmatched_new_nodes_list; 746 old_node.unmatched_new_nodes = unmatched_new_nodes_list;
747 old_node.textually_unmatched_new_nodes = 747 old_node.textually_unmatched_new_nodes =
748 textually_unmatched_new_nodes_list; 748 textually_unmatched_new_nodes_list;
749 } 749 }
750 750
751 ProcessChildren(old_code_tree, new_code_tree); 751 ProcessChildren(old_code_tree, new_code_tree);
752 752
753 old_code_tree.corresponding_node = new_code_tree; 753 old_code_tree.corresponding_node = new_code_tree;
754 old_code_tree.textual_corresponding_node = new_code_tree; 754 old_code_tree.textual_corresponding_node = new_code_tree;
755 755
756 Assert(old_code_tree.status != FunctionStatus.DAMAGED, 756 Assert(old_code_tree.status != FunctionStatus.DAMAGED,
757 "Script became damaged"); 757 "Script became damaged");
758 } 758 }
759 759
760 function FindLiveSharedInfos(old_code_tree, script) { 760 function FindLiveSharedInfos(old_code_tree, script) {
761 var shared_raw_list = %LiveEditFindSharedFunctionInfosForScript(script); 761 var shared_raw_list = %LiveEditFindSharedFunctionInfosForScript(script);
762 762
763 var shared_infos = new Array(); 763 var shared_infos = new Array();
764 764
765 for (var i = 0; i < shared_raw_list.length; i++) { 765 for (var i = 0; i < shared_raw_list.length; i++) {
766 shared_infos.push(new SharedInfoWrapper(shared_raw_list[i])); 766 shared_infos.push(new SharedInfoWrapper(shared_raw_list[i]));
767 } 767 }
768 768
769 // Finds SharedFunctionInfo that corresponds compile info with index 769 // Finds SharedFunctionInfo that corresponds compile info with index
770 // in old version of the script. 770 // in old version of the script.
771 function FindFunctionInfo(compile_info) { 771 function FindFunctionInfo(compile_info) {
772 for (var i = 0; i < shared_infos.length; i++) { 772 for (var i = 0; i < shared_infos.length; i++) {
773 var wrapper = shared_infos[i]; 773 var wrapper = shared_infos[i];
774 if (wrapper.start_position == compile_info.start_position && 774 if (wrapper.start_position == compile_info.start_position &&
775 wrapper.end_position == compile_info.end_position) { 775 wrapper.end_position == compile_info.end_position) {
776 return wrapper; 776 return wrapper;
777 } 777 }
778 } 778 }
779 } 779 }
780 780
781 function TraverseTree(node) { 781 function TraverseTree(node) {
782 var info_wrapper = FindFunctionInfo(node.info); 782 var info_wrapper = FindFunctionInfo(node.info);
783 if (info_wrapper) { 783 if (info_wrapper) {
784 node.live_shared_info_wrapper = info_wrapper; 784 node.live_shared_info_wrapper = info_wrapper;
785 } 785 }
786 for (var i = 0; i < node.children.length; i++) { 786 for (var i = 0; i < node.children.length; i++) {
787 TraverseTree(node.children[i]); 787 TraverseTree(node.children[i]);
788 } 788 }
789 } 789 }
790 790
791 TraverseTree(old_code_tree); 791 TraverseTree(old_code_tree);
792 } 792 }
793 793
794 794
795 // An object describing function compilation details. Its index fields 795 // An object describing function compilation details. Its index fields
796 // apply to indexes inside array that stores these objects. 796 // apply to indexes inside array that stores these objects.
797 function FunctionCompileInfo(raw_array) { 797 function FunctionCompileInfo(raw_array) {
798 this.function_name = raw_array[0]; 798 this.function_name = raw_array[0];
799 this.start_position = raw_array[1]; 799 this.start_position = raw_array[1];
800 this.end_position = raw_array[2]; 800 this.end_position = raw_array[2];
801 this.param_num = raw_array[3]; 801 this.param_num = raw_array[3];
802 this.code = raw_array[4]; 802 this.code = raw_array[4];
803 this.code_scope_info = raw_array[5]; 803 this.code_scope_info = raw_array[5];
804 this.scope_info = raw_array[6]; 804 this.scope_info = raw_array[6];
805 this.outer_index = raw_array[7]; 805 this.outer_index = raw_array[7];
806 this.shared_function_info = raw_array[8]; 806 this.shared_function_info = raw_array[8];
807 this.next_sibling_index = null; 807 this.next_sibling_index = null;
808 this.raw_array = raw_array; 808 this.raw_array = raw_array;
809 } 809 }
810 810
811 function SharedInfoWrapper(raw_array) { 811 function SharedInfoWrapper(raw_array) {
812 this.function_name = raw_array[0]; 812 this.function_name = raw_array[0];
813 this.start_position = raw_array[1]; 813 this.start_position = raw_array[1];
814 this.end_position = raw_array[2]; 814 this.end_position = raw_array[2];
815 this.info = raw_array[3]; 815 this.info = raw_array[3];
816 this.raw_array = raw_array; 816 this.raw_array = raw_array;
817 } 817 }
818 818
819 // Changes positions (including all statments) in function. 819 // Changes positions (including all statments) in function.
820 function PatchPositions(old_info_node, diff_array, report_array) { 820 function PatchPositions(old_info_node, diff_array, report_array) {
821 var shared_info_wrapper = old_info_node.live_shared_info_wrapper; 821 var shared_info_wrapper = old_info_node.live_shared_info_wrapper;
822 if (!shared_info_wrapper) { 822 if (!shared_info_wrapper) {
823 // TODO(LiveEdit): function is not compiled yet or is already collected. 823 // TODO(LiveEdit): function is not compiled yet or is already collected.
824 report_array.push( 824 report_array.push(
825 { name: old_info_node.info.function_name, info_not_found: true } ); 825 { name: old_info_node.info.function_name, info_not_found: true } );
826 return; 826 return;
827 } 827 }
828 %LiveEditPatchFunctionPositions(shared_info_wrapper.raw_array, 828 %LiveEditPatchFunctionPositions(shared_info_wrapper.raw_array,
829 diff_array); 829 diff_array);
830 report_array.push( { name: old_info_node.info.function_name } ); 830 report_array.push( { name: old_info_node.info.function_name } );
831 } 831 }
832 832
833 // Adds a suffix to script name to mark that it is old version. 833 // Adds a suffix to script name to mark that it is old version.
834 function CreateNameForOldScript(script) { 834 function CreateNameForOldScript(script) {
835 // TODO(635): try better than this; support several changes. 835 // TODO(635): try better than this; support several changes.
836 return script.name + " (old)"; 836 return script.name + " (old)";
837 } 837 }
838 838
839 // Compares a function interface old and new version, whether it 839 // Compares a function interface old and new version, whether it
840 // changed or not. Returns explanation if they differ. 840 // changed or not. Returns explanation if they differ.
841 function WhyFunctionExpectationsDiffer(function_info1, function_info2) { 841 function WhyFunctionExpectationsDiffer(function_info1, function_info2) {
842 // Check that function has the same number of parameters (there may exist 842 // Check that function has the same number of parameters (there may exist
843 // an adapter, that won't survive function parameter number change). 843 // an adapter, that won't survive function parameter number change).
844 if (function_info1.param_num != function_info2.param_num) { 844 if (function_info1.param_num != function_info2.param_num) {
845 return "Changed parameter number: " + function_info1.param_num + 845 return "Changed parameter number: " + function_info1.param_num +
846 " and " + function_info2.param_num; 846 " and " + function_info2.param_num;
847 } 847 }
848 var scope_info1 = function_info1.scope_info; 848 var scope_info1 = function_info1.scope_info;
849 var scope_info2 = function_info2.scope_info; 849 var scope_info2 = function_info2.scope_info;
850 850
851 var scope_info1_text; 851 var scope_info1_text;
852 var scope_info2_text; 852 var scope_info2_text;
853 853
854 if (scope_info1) { 854 if (scope_info1) {
855 scope_info1_text = scope_info1.toString(); 855 scope_info1_text = scope_info1.toString();
856 } else { 856 } else {
857 scope_info1_text = ""; 857 scope_info1_text = "";
858 } 858 }
859 if (scope_info2) { 859 if (scope_info2) {
860 scope_info2_text = scope_info2.toString(); 860 scope_info2_text = scope_info2.toString();
861 } else { 861 } else {
862 scope_info2_text = ""; 862 scope_info2_text = "";
863 } 863 }
864 864
865 if (scope_info1_text != scope_info2_text) { 865 if (scope_info1_text != scope_info2_text) {
866 return "Incompatible variable maps: [" + scope_info1_text + 866 return "Incompatible variable maps: [" + scope_info1_text +
867 "] and [" + scope_info2_text + "]"; 867 "] and [" + scope_info2_text + "]";
868 } 868 }
869 // No differences. Return undefined. 869 // No differences. Return undefined.
870 return; 870 return;
871 } 871 }
872 872
873 // Minifier forward declaration. 873 // Minifier forward declaration.
874 var FunctionPatchabilityStatus; 874 var FunctionPatchabilityStatus;
875 875
876 // For array of wrapped shared function infos checks that none of them 876 // For array of wrapped shared function infos checks that none of them
877 // have activations on stack (of any thread). Throws a Failure exception 877 // have activations on stack (of any thread). Throws a Failure exception
878 // if this proves to be false. 878 // if this proves to be false.
879 function CheckStackActivations(shared_wrapper_list, change_log) { 879 function CheckStackActivations(shared_wrapper_list, change_log) {
880 var shared_list = new Array(); 880 var shared_list = new Array();
881 for (var i = 0; i < shared_wrapper_list.length; i++) { 881 for (var i = 0; i < shared_wrapper_list.length; i++) {
882 shared_list[i] = shared_wrapper_list[i].info; 882 shared_list[i] = shared_wrapper_list[i].info;
883 } 883 }
884 var result = %LiveEditCheckAndDropActivations(shared_list, true); 884 var result = %LiveEditCheckAndDropActivations(shared_list, true);
885 if (result[shared_list.length]) { 885 if (result[shared_list.length]) {
886 // Extra array element may contain error message. 886 // Extra array element may contain error message.
887 throw new Failure(result[shared_list.length]); 887 throw new Failure(result[shared_list.length]);
888 } 888 }
889 889
890 var problems = new Array(); 890 var problems = new Array();
891 var dropped = new Array(); 891 var dropped = new Array();
892 for (var i = 0; i < shared_list.length; i++) { 892 for (var i = 0; i < shared_list.length; i++) {
893 var shared = shared_wrapper_list[i]; 893 var shared = shared_wrapper_list[i];
894 if (result[i] == FunctionPatchabilityStatus.REPLACED_ON_ACTIVE_STACK) { 894 if (result[i] == FunctionPatchabilityStatus.REPLACED_ON_ACTIVE_STACK) {
895 dropped.push({ name: shared.function_name } ); 895 dropped.push({ name: shared.function_name } );
896 } else if (result[i] != FunctionPatchabilityStatus.AVAILABLE_FOR_PATCH) { 896 } else if (result[i] != FunctionPatchabilityStatus.AVAILABLE_FOR_PATCH) {
897 var description = { 897 var description = {
898 name: shared.function_name, 898 name: shared.function_name,
899 start_pos: shared.start_position, 899 start_pos: shared.start_position,
900 end_pos: shared.end_position, 900 end_pos: shared.end_position,
901 replace_problem: 901 replace_problem:
902 FunctionPatchabilityStatus.SymbolName(result[i]) 902 FunctionPatchabilityStatus.SymbolName(result[i])
903 }; 903 };
904 problems.push(description); 904 problems.push(description);
905 } 905 }
906 } 906 }
907 if (dropped.length > 0) { 907 if (dropped.length > 0) {
908 change_log.push({ dropped_from_stack: dropped }); 908 change_log.push({ dropped_from_stack: dropped });
909 } 909 }
910 if (problems.length > 0) { 910 if (problems.length > 0) {
911 change_log.push( { functions_on_stack: problems } ); 911 change_log.push( { functions_on_stack: problems } );
912 throw new Failure("Blocked by functions on stack"); 912 throw new Failure("Blocked by functions on stack");
913 } 913 }
914 914
915 return dropped.length; 915 return dropped.length;
916 } 916 }
917 917
918 // A copy of the FunctionPatchabilityStatus enum from liveedit.h 918 // A copy of the FunctionPatchabilityStatus enum from liveedit.h
919 var FunctionPatchabilityStatus = { 919 var FunctionPatchabilityStatus = {
920 AVAILABLE_FOR_PATCH: 1, 920 AVAILABLE_FOR_PATCH: 1,
921 BLOCKED_ON_ACTIVE_STACK: 2, 921 BLOCKED_ON_ACTIVE_STACK: 2,
922 BLOCKED_ON_OTHER_STACK: 3, 922 BLOCKED_ON_OTHER_STACK: 3,
923 BLOCKED_UNDER_NATIVE_CODE: 4, 923 BLOCKED_UNDER_NATIVE_CODE: 4,
924 REPLACED_ON_ACTIVE_STACK: 5 924 REPLACED_ON_ACTIVE_STACK: 5
925 } 925 }
926 926
927 FunctionPatchabilityStatus.SymbolName = function(code) { 927 FunctionPatchabilityStatus.SymbolName = function(code) {
928 var enum = FunctionPatchabilityStatus; 928 var enum = FunctionPatchabilityStatus;
929 for (name in enum) { 929 for (name in enum) {
930 if (enum[name] == code) { 930 if (enum[name] == code) {
931 return name; 931 return name;
932 } 932 }
933 } 933 }
934 } 934 }
935 935
936 936
937 // A logical failure in liveedit process. This means that change_log 937 // A logical failure in liveedit process. This means that change_log
938 // is valid and consistent description of what happened. 938 // is valid and consistent description of what happened.
939 function Failure(message) { 939 function Failure(message) {
940 this.message = message; 940 this.message = message;
941 } 941 }
942 // Function (constructor) is public. 942 // Function (constructor) is public.
943 this.Failure = Failure; 943 this.Failure = Failure;
944 944
945 Failure.prototype.toString = function() { 945 Failure.prototype.toString = function() {
946 return "LiveEdit Failure: " + this.message; 946 return "LiveEdit Failure: " + this.message;
947 } 947 }
948 948
949 // A testing entry. 949 // A testing entry.
950 function GetPcFromSourcePos(func, source_pos) { 950 function GetPcFromSourcePos(func, source_pos) {
951 return %GetFunctionCodePositionFromSource(func, source_pos); 951 return %GetFunctionCodePositionFromSource(func, source_pos);
952 } 952 }
953 // Function is public. 953 // Function is public.
954 this.GetPcFromSourcePos = GetPcFromSourcePos; 954 this.GetPcFromSourcePos = GetPcFromSourcePos;
955 955
956 // LiveEdit main entry point: changes a script text to a new string. 956 // LiveEdit main entry point: changes a script text to a new string.
957 function SetScriptSource(script, new_source, preview_only, change_log) { 957 function SetScriptSource(script, new_source, preview_only, change_log) {
958 var old_source = script.source; 958 var old_source = script.source;
959 var diff = CompareStringsLinewise(old_source, new_source); 959 var diff = CompareStringsLinewise(old_source, new_source);
960 return ApplyPatchMultiChunk(script, diff, new_source, preview_only, 960 return ApplyPatchMultiChunk(script, diff, new_source, preview_only,
961 change_log); 961 change_log);
962 } 962 }
963 // Function is public. 963 // Function is public.
964 this.SetScriptSource = SetScriptSource; 964 this.SetScriptSource = SetScriptSource;
965 965
966 function CompareStringsLinewise(s1, s2) { 966 function CompareStringsLinewise(s1, s2) {
967 return %LiveEditCompareStringsLinewise(s1, s2); 967 return %LiveEditCompareStringsLinewise(s1, s2);
968 } 968 }
969 969
970 // Applies the change to the script. 970 // Applies the change to the script.
971 // The change is always a substring (change_pos, change_pos + change_len) 971 // The change is always a substring (change_pos, change_pos + change_len)
972 // being replaced with a completely different string new_str. 972 // being replaced with a completely different string new_str.
973 // This API is a legacy and is obsolete. 973 // This API is a legacy and is obsolete.
974 // 974 //
975 // @param {Script} script that is being changed 975 // @param {Script} script that is being changed
976 // @param {Array} change_log a list that collects engineer-readable 976 // @param {Array} change_log a list that collects engineer-readable
977 // description of what happened. 977 // description of what happened.
978 function ApplySingleChunkPatch(script, change_pos, change_len, new_str, 978 function ApplySingleChunkPatch(script, change_pos, change_len, new_str,
979 change_log) { 979 change_log) {
980 var old_source = script.source; 980 var old_source = script.source;
981 981
982 // Prepare new source string. 982 // Prepare new source string.
983 var new_source = old_source.substring(0, change_pos) + 983 var new_source = old_source.substring(0, change_pos) +
984 new_str + old_source.substring(change_pos + change_len); 984 new_str + old_source.substring(change_pos + change_len);
985 985
986 return ApplyPatchMultiChunk(script, 986 return ApplyPatchMultiChunk(script,
987 [ change_pos, change_pos + change_len, change_pos + new_str.length], 987 [ change_pos, change_pos + change_len, change_pos + new_str.length],
988 new_source, false, change_log); 988 new_source, false, change_log);
989 } 989 }
990 990
991 // Creates JSON description for a change tree. 991 // Creates JSON description for a change tree.
992 function DescribeChangeTree(old_code_tree) { 992 function DescribeChangeTree(old_code_tree) {
993 993
994 function ProcessOldNode(node) { 994 function ProcessOldNode(node) {
995 var child_infos = []; 995 var child_infos = [];
996 for (var i = 0; i < node.children.length; i++) { 996 for (var i = 0; i < node.children.length; i++) {
997 var child = node.children[i]; 997 var child = node.children[i];
998 if (child.status != FunctionStatus.UNCHANGED) { 998 if (child.status != FunctionStatus.UNCHANGED) {
999 child_infos.push(ProcessOldNode(child)); 999 child_infos.push(ProcessOldNode(child));
1000 } 1000 }
1001 } 1001 }
1002 var new_child_infos = []; 1002 var new_child_infos = [];
1003 if (node.textually_unmatched_new_nodes) { 1003 if (node.textually_unmatched_new_nodes) {
1004 for (var i = 0; i < node.textually_unmatched_new_nodes.length; i++) { 1004 for (var i = 0; i < node.textually_unmatched_new_nodes.length; i++) {
1005 var child = node.textually_unmatched_new_nodes[i]; 1005 var child = node.textually_unmatched_new_nodes[i];
1006 new_child_infos.push(ProcessNewNode(child)); 1006 new_child_infos.push(ProcessNewNode(child));
1007 } 1007 }
1008 } 1008 }
1009 var res = { 1009 var res = {
1010 name: node.info.function_name, 1010 name: node.info.function_name,
1011 positions: DescribePositions(node), 1011 positions: DescribePositions(node),
1012 status: node.status, 1012 status: node.status,
1013 children: child_infos, 1013 children: child_infos,
1014 new_children: new_child_infos 1014 new_children: new_child_infos
1015 }; 1015 };
1016 if (node.status_explanation) { 1016 if (node.status_explanation) {
1017 res.status_explanation = node.status_explanation; 1017 res.status_explanation = node.status_explanation;
1018 } 1018 }
1019 if (node.textual_corresponding_node) { 1019 if (node.textual_corresponding_node) {
1020 res.new_positions = DescribePositions(node.textual_corresponding_node); 1020 res.new_positions = DescribePositions(node.textual_corresponding_node);
1021 } 1021 }
1022 return res; 1022 return res;
1023 } 1023 }
1024 1024
1025 function ProcessNewNode(node) { 1025 function ProcessNewNode(node) {
1026 var child_infos = []; 1026 var child_infos = [];
1027 // Do not list ancestors. 1027 // Do not list ancestors.
1028 if (false) { 1028 if (false) {
1029 for (var i = 0; i < node.children.length; i++) { 1029 for (var i = 0; i < node.children.length; i++) {
1030 child_infos.push(ProcessNewNode(node.children[i])); 1030 child_infos.push(ProcessNewNode(node.children[i]));
1031 } 1031 }
1032 } 1032 }
1033 var res = { 1033 var res = {
1034 name: node.info.function_name, 1034 name: node.info.function_name,
1035 positions: DescribePositions(node), 1035 positions: DescribePositions(node),
1036 children: child_infos, 1036 children: child_infos,
1037 }; 1037 };
1038 return res; 1038 return res;
1039 } 1039 }
1040 1040
1041 function DescribePositions(node) { 1041 function DescribePositions(node) {
1042 return { 1042 return {
1043 start_position: node.info.start_position, 1043 start_position: node.info.start_position,
1044 end_position: node.info.end_position 1044 end_position: node.info.end_position
1045 }; 1045 };
1046 } 1046 }
1047 1047
1048 return ProcessOldNode(old_code_tree); 1048 return ProcessOldNode(old_code_tree);
1049 } 1049 }
1050 1050
1051 1051
1052 // Functions are public for tests. 1052 // Functions are public for tests.
1053 this.TestApi = { 1053 this.TestApi = {
1054 PosTranslator: PosTranslator, 1054 PosTranslator: PosTranslator,
1055 CompareStringsLinewise: CompareStringsLinewise, 1055 CompareStringsLinewise: CompareStringsLinewise,
1056 ApplySingleChunkPatch: ApplySingleChunkPatch 1056 ApplySingleChunkPatch: ApplySingleChunkPatch
1057 } 1057 }
1058 } 1058 }
OLDNEW
« no previous file with comments | « src/debug-debugger.js ('k') | src/messages.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698