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

Unified Diff: src/liveedit-debugger.js

Issue 1697016: LiveEdit: clean JS sources a bit (Closed)
Patch Set: tab Created 10 years, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/debug-debugger.js ('k') | test/mjsunit/debug-liveedit-1.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/liveedit-debugger.js
diff --git a/src/liveedit-debugger.js b/src/liveedit-debugger.js
index 59c6ca174c3098bf886b1fbaee9d2570f739386c..34d5c0da89a1a038b6c306b8dd89cd845cb13e5f 100644
--- a/src/liveedit-debugger.js
+++ b/src/liveedit-debugger.js
@@ -44,222 +44,41 @@
// LiveEdit namespace is declared inside a single function constructor.
Debug.LiveEdit = new function() {
- // Applies the change to the script.
- // The change is always a substring (change_pos, change_pos + change_len)
- // being replaced with a completely different string new_str.
- // This API is a legacy and is obsolete.
- //
- // @param {Script} script that is being changed
- // @param {Array} change_log a list that collects engineer-readable
- // description of what happened.
- function ApplyPatch(script, change_pos, change_len, new_str,
- change_log) {
- var old_source = script.source;
-
- // Prepare new source string.
- var new_source = old_source.substring(0, change_pos) +
- new_str + old_source.substring(change_pos + change_len);
-
- return ApplyPatchMultiChunk(script,
- [ change_pos, change_pos + change_len, change_pos + new_str.length],
- new_source, change_log);
- }
- // Function is public.
- this.ApplyPatch = ApplyPatch;
-
// Forward declaration for minifier.
var FunctionStatus;
+
// Applies the change to the script.
// The change is in form of list of chunks encoded in a single array as
// a series of triplets (pos1_start, pos1_end, pos2_end)
function ApplyPatchMultiChunk(script, diff_array, new_source, change_log) {
- // Fully compiles source string as a script. Returns Array of
- // FunctionCompileInfo -- a descriptions of all functions of the script.
- // Elements of array are ordered by start positions of functions (from top
- // to bottom) in the source. Fields outer_index and next_sibling_index help
- // to navigate the nesting structure of functions.
- //
- // The script is used for compilation, because it produces code that
- // needs to be linked with some particular script (for nested functions).
- function GatherCompileInfo(source) {
- // Get function info, elements are partially sorted (it is a tree of
- // nested functions serialized as parent followed by serialized children.
- var raw_compile_info = %LiveEditGatherCompileInfo(script, source);
-
- // Sort function infos by start position field.
- var compile_info = new Array();
- var old_index_map = new Array();
- for (var i = 0; i < raw_compile_info.length; i++) {
- var info = new FunctionCompileInfo(raw_compile_info[i]);
- // Remove all links to the actual script. Breakpoints system and
- // LiveEdit itself believe that any function in heap that points to a
- // particular script is a regular function.
- // For some functions we will restore this link later.
- %LiveEditFunctionSetScript(info.shared_function_info, void 0);
- compile_info.push(info);
- old_index_map.push(i);
- }
-
- for (var i = 0; i < compile_info.length; i++) {
- var k = i;
- for (var j = i + 1; j < compile_info.length; j++) {
- if (compile_info[k].start_position > compile_info[j].start_position) {
- k = j;
- }
- }
- if (k != i) {
- var temp_info = compile_info[k];
- var temp_index = old_index_map[k];
- compile_info[k] = compile_info[i];
- old_index_map[k] = old_index_map[i];
- compile_info[i] = temp_info;
- old_index_map[i] = temp_index;
- }
- }
-
- // After sorting update outer_inder field using old_index_map. Also
- // set next_sibling_index field.
- var current_index = 0;
-
- // The recursive function, that goes over all children of a particular
- // node (i.e. function info).
- function ResetIndexes(new_parent_index, old_parent_index) {
- var previous_sibling = -1;
- while (current_index < compile_info.length &&
- compile_info[current_index].outer_index == old_parent_index) {
- var saved_index = current_index;
- compile_info[saved_index].outer_index = new_parent_index;
- if (previous_sibling != -1) {
- compile_info[previous_sibling].next_sibling_index = saved_index;
- }
- previous_sibling = saved_index;
- current_index++;
- ResetIndexes(saved_index, old_index_map[saved_index]);
- }
- if (previous_sibling != -1) {
- compile_info[previous_sibling].next_sibling_index = -1;
- }
- }
-
- ResetIndexes(-1, -1);
- Assert(current_index == compile_info.length);
-
- return compile_info;
- }
-
- // Variable forward declarations. Preprocessor "Minifier" needs them.
- var old_compile_info;
- var shared_infos;
- // Finds SharedFunctionInfo that corresponds compile info with index
- // in old version of the script.
- // TODO(LiveEdit): Redesign this part. Find live SharedFunctionInfo
- // about the time that FindCorrespondingFunctions is being run.
- function FindFunctionInfo(index) {
- var old_info = old_compile_info[index];
- for (var i = 0; i < shared_infos.length; i++) {
- var info = shared_infos[i];
- if (info.start_position == old_info.start_position &&
- info.end_position == old_info.end_position) {
- return info;
- }
- }
- }
-
- // Replaces function's Code.
- function PatchCode(old_node) {
- var new_info = old_node.corresponding_node.info;
- var shared_info = FindFunctionInfo(old_node.array_index);
- if (shared_info) {
- %LiveEditReplaceFunctionCode(new_info.raw_array, shared_info.raw_array);
-
- // The function got a new code. However, this new code brings all new
- // instances of SharedFunctionInfo for nested functions. However,
- // we want the original instances to be used wherever possible.
- // (This is because old instances and new instances will be both
- // linked to a script and breakpoints subsystem does not really
- // expects this; neither does LiveEdit subsystem on next call).
- for (var i = 0; i < old_node.children.length; i++) {
- if (old_node.children[i].corresponding_node) {
- var corresponding_child = old_node.children[i].corresponding_node;
- var child_shared_info =
- FindFunctionInfo(old_node.children[i].array_index);
- if (child_shared_info) {
- %LiveEditReplaceRefToNestedFunction(shared_info.info,
- corresponding_child.info.shared_function_info,
- child_shared_info.info);
- }
- }
- }
-
- change_log.push( {function_patched: new_info.function_name} );
- } else {
- change_log.push( {function_patched: new_info.function_name,
- function_info_not_found: true} );
- }
- }
-
-
- var position_patch_report;
- function PatchPositions(old_info, shared_info) {
- if (!shared_info) {
- // TODO(LiveEdit): function is not compiled yet or is already collected.
- position_patch_report.push(
- { name: old_info.function_name, info_not_found: true } );
- return;
- }
- %LiveEditPatchFunctionPositions(
- shared_info.raw_array, diff_array);
- position_patch_report.push( { name: old_info.function_name } );
- }
-
- var link_to_old_script_report;
- var old_script;
- // Makes a function associated with another instance of a script (the
- // one representing its old version). This way the function still
- // may access its own text.
- function LinkToOldScript(shared_info, old_info_node) {
- if (shared_info) {
- %LiveEditFunctionSetScript(shared_info.info, old_script);
- link_to_old_script_report.push( { name: shared_info.function_name } );
- } else {
- link_to_old_script_report.push(
- { name: old_info_node.info.function_name, not_found: true } );
- }
- }
-
-
var old_source = script.source;
-
- // Find all SharedFunctionInfo's that are compiled from this script.
- var shared_raw_list = %LiveEditFindSharedFunctionInfosForScript(script);
-
- var shared_infos = new Array();
-
- for (var i = 0; i < shared_raw_list.length; i++) {
- shared_infos.push(new SharedInfoWrapper(shared_raw_list[i]));
- }
-
+
// Gather compile information about old version of script.
- var old_compile_info = GatherCompileInfo(old_source);
+ var old_compile_info = GatherCompileInfo(old_source, script);
+ // Build tree structures for old and new versions of the script.
+ var root_old_node = BuildCodeInfoTree(old_compile_info);
+
+ var pos_translator = new PosTranslator(diff_array);
+
+ // Analyze changes.
+ MarkChangedFunctions(root_old_node, pos_translator.GetChunks());
+
+ // Find all SharedFunctionInfo's that were compiled from this script.
+ FindLiveSharedInfos(root_old_node, script);
+
// Gather compile information about new version of script.
var new_compile_info;
try {
- new_compile_info = GatherCompileInfo(new_source);
+ new_compile_info = GatherCompileInfo(new_source, script);
} catch (e) {
throw new Failure("Failed to compile new version of script: " + e);
}
-
- var pos_translator = new PosTranslator(diff_array);
-
- // Build tree structures for old and new versions of the script.
- var root_old_node = BuildCodeInfoTree(old_compile_info);
var root_new_node = BuildCodeInfoTree(new_compile_info);
- // Analyze changes.
- MarkChangedFunctions(root_old_node, pos_translator.GetChunks());
+ // Link recompiled script data with other data.
FindCorrespondingFunctions(root_old_node, root_new_node);
// Prepare to-do lists.
@@ -307,9 +126,9 @@ Debug.LiveEdit = new function() {
// Collect shared infos for functions whose code need to be patched.
var replaced_function_infos = new Array();
for (var i = 0; i < replace_code_list.length; i++) {
- var info = FindFunctionInfo(replace_code_list[i].array_index);
- if (info) {
- replaced_function_infos.push(info);
+ var info_wrapper = replace_code_list[i].live_shared_info_wrapper;
+ if (info_wrapper) {
+ replaced_function_infos.push(info_wrapper);
}
}
@@ -344,9 +163,8 @@ Debug.LiveEdit = new function() {
// We need to link to old script all former nested functions.
for (var i = 0; i < link_to_old_script_list.length; i++) {
- LinkToOldScript(
- FindFunctionInfo(link_to_old_script_list[i].array_index),
- link_to_old_script_list[i]);
+ LinkToOldScript(link_to_old_script_list[i], old_script,
+ link_to_old_script_report);
}
}
@@ -357,7 +175,7 @@ Debug.LiveEdit = new function() {
}
for (var i = 0; i < replace_code_list.length; i++) {
- PatchCode(replace_code_list[i]);
+ PatchFunctionCode(replace_code_list[i], change_log);
}
var position_patch_report = new Array();
@@ -366,8 +184,8 @@ Debug.LiveEdit = new function() {
for (var i = 0; i < update_positions_list.length; i++) {
// TODO(LiveEdit): take into account wether it's source_changed or
// unchanged and whether positions changed at all.
- PatchPositions(update_positions_list[i].info,
- FindFunctionInfo(update_positions_list[i].array_index));
+ PatchPositions(update_positions_list[i], diff_array,
+ position_patch_report);
}
break_points_restorer(pos_translator, old_script);
@@ -375,6 +193,132 @@ Debug.LiveEdit = new function() {
// Function is public.
this.ApplyPatchMultiChunk = ApplyPatchMultiChunk;
+
+ // Fully compiles source string as a script. Returns Array of
+ // FunctionCompileInfo -- a descriptions of all functions of the script.
+ // Elements of array are ordered by start positions of functions (from top
+ // to bottom) in the source. Fields outer_index and next_sibling_index help
+ // to navigate the nesting structure of functions.
+ //
+ // All functions get compiled linked to script provided as parameter script.
+ // TODO(LiveEdit): consider not using actual scripts as script, because
+ // we have to manually erase all links right after compile.
+ function GatherCompileInfo(source, script) {
+ // Get function info, elements are partially sorted (it is a tree of
+ // nested functions serialized as parent followed by serialized children.
+ var raw_compile_info = %LiveEditGatherCompileInfo(script, source);
+
+ // Sort function infos by start position field.
+ var compile_info = new Array();
+ var old_index_map = new Array();
+ for (var i = 0; i < raw_compile_info.length; i++) {
+ var info = new FunctionCompileInfo(raw_compile_info[i]);
+ // Remove all links to the actual script. Breakpoints system and
+ // LiveEdit itself believe that any function in heap that points to a
+ // particular script is a regular function.
+ // For some functions we will restore this link later.
+ %LiveEditFunctionSetScript(info.shared_function_info, void 0);
+ compile_info.push(info);
+ old_index_map.push(i);
+ }
+
+ for (var i = 0; i < compile_info.length; i++) {
+ var k = i;
+ for (var j = i + 1; j < compile_info.length; j++) {
+ if (compile_info[k].start_position > compile_info[j].start_position) {
+ k = j;
+ }
+ }
+ if (k != i) {
+ var temp_info = compile_info[k];
+ var temp_index = old_index_map[k];
+ compile_info[k] = compile_info[i];
+ old_index_map[k] = old_index_map[i];
+ compile_info[i] = temp_info;
+ old_index_map[i] = temp_index;
+ }
+ }
+
+ // After sorting update outer_inder field using old_index_map. Also
+ // set next_sibling_index field.
+ var current_index = 0;
+
+ // The recursive function, that goes over all children of a particular
+ // node (i.e. function info).
+ function ResetIndexes(new_parent_index, old_parent_index) {
+ var previous_sibling = -1;
+ while (current_index < compile_info.length &&
+ compile_info[current_index].outer_index == old_parent_index) {
+ var saved_index = current_index;
+ compile_info[saved_index].outer_index = new_parent_index;
+ if (previous_sibling != -1) {
+ compile_info[previous_sibling].next_sibling_index = saved_index;
+ }
+ previous_sibling = saved_index;
+ current_index++;
+ ResetIndexes(saved_index, old_index_map[saved_index]);
+ }
+ if (previous_sibling != -1) {
+ compile_info[previous_sibling].next_sibling_index = -1;
+ }
+ }
+
+ ResetIndexes(-1, -1);
+ Assert(current_index == compile_info.length);
+
+ return compile_info;
+ }
+
+
+ // Replaces function's Code.
+ function PatchFunctionCode(old_node, change_log) {
+ var new_info = old_node.corresponding_node.info;
+ var shared_info_wrapper = old_node.live_shared_info_wrapper;
+ if (shared_info_wrapper) {
+ %LiveEditReplaceFunctionCode(new_info.raw_array,
+ shared_info_wrapper.raw_array);
+
+ // The function got a new code. However, this new code brings all new
+ // instances of SharedFunctionInfo for nested functions. However,
+ // we want the original instances to be used wherever possible.
+ // (This is because old instances and new instances will be both
+ // linked to a script and breakpoints subsystem does not really
+ // expects this; neither does LiveEdit subsystem on next call).
+ for (var i = 0; i < old_node.children.length; i++) {
+ if (old_node.children[i].corresponding_node) {
+ var corresponding_child = old_node.children[i].corresponding_node;
+ var child_shared_info_wrapper =
+ old_node.children[i].live_shared_info_wrapper;
+ if (child_shared_info_wrapper) {
+ %LiveEditReplaceRefToNestedFunction(shared_info_wrapper.info,
+ corresponding_child.info.shared_function_info,
+ child_shared_info_wrapper.info);
+ }
+ }
+ }
+
+ change_log.push( {function_patched: new_info.function_name} );
+ } else {
+ change_log.push( {function_patched: new_info.function_name,
+ function_info_not_found: true} );
+ }
+ }
+
+
+ // Makes a function associated with another instance of a script (the
+ // one representing its old version). This way the function still
+ // may access its own text.
+ function LinkToOldScript(old_info_node, old_script, report_array) {
+ var shared_info = old_info_node.live_shared_info_wrapper;
+ if (shared_info) {
+ %LiveEditFunctionSetScript(shared_info.info, old_script);
+ report_array.push( { name: shared_info.function_name } );
+ } else {
+ report_array.push(
+ { name: old_info_node.info.function_name, not_found: true } );
+ }
+ }
+
// Returns function that restores breakpoints.
function TemporaryRemoveBreakPoints(original_script, change_log) {
@@ -550,6 +494,7 @@ Debug.LiveEdit = new function() {
this.new_end_pos = void 0;
this.corresponding_node = void 0;
this.unmatched_new_nodes = void 0;
+ this.live_shared_info_wrapper = void 0;
}
// From array of function infos that is implicitly a tree creates
@@ -767,6 +712,40 @@ Debug.LiveEdit = new function() {
Assert(old_code_tree.status != FunctionStatus.DAMAGED,
"Script became damaged");
}
+
+ function FindLiveSharedInfos(old_code_tree, script) {
+ var shared_raw_list = %LiveEditFindSharedFunctionInfosForScript(script);
+
+ var shared_infos = new Array();
+
+ for (var i = 0; i < shared_raw_list.length; i++) {
+ shared_infos.push(new SharedInfoWrapper(shared_raw_list[i]));
+ }
+
+ // Finds SharedFunctionInfo that corresponds compile info with index
+ // in old version of the script.
+ function FindFunctionInfo(compile_info) {
+ for (var i = 0; i < shared_infos.length; i++) {
+ var wrapper = shared_infos[i];
+ if (wrapper.start_position == compile_info.start_position &&
+ wrapper.end_position == compile_info.end_position) {
+ return wrapper;
+ }
+ }
+ }
+
+ function TraverseTree(node) {
+ var info_wrapper = FindFunctionInfo(node.info);
+ if (info_wrapper) {
+ node.live_shared_info_wrapper = info_wrapper;
+ }
+ for (var i = 0; i < node.children.length; i++) {
+ TraverseTree(node.children[i]);
+ }
+ }
+
+ TraverseTree(old_code_tree);
+ }
// An object describing function compilation details. Its index fields
@@ -791,7 +770,21 @@ Debug.LiveEdit = new function() {
this.info = raw_array[3];
this.raw_array = raw_array;
}
-
+
+ // Changes positions (including all statments) in function.
+ function PatchPositions(old_info_node, diff_array, report_array) {
+ var shared_info_wrapper = old_info_node.live_shared_info_wrapper;
+ if (!shared_info_wrapper) {
+ // TODO(LiveEdit): function is not compiled yet or is already collected.
+ report_array.push(
+ { name: old_info_node.info.function_name, info_not_found: true } );
+ return;
+ }
+ %LiveEditPatchFunctionPositions(shared_info_wrapper.raw_array,
+ diff_array);
+ report_array.push( { name: old_info_node.info.function_name } );
+ }
+
// Adds a suffix to script name to mark that it is old version.
function CreateNameForOldScript(script) {
// TODO(635): try better than this; support several changes.
@@ -919,10 +912,33 @@ Debug.LiveEdit = new function() {
function CompareStringsLinewise(s1, s2) {
return %LiveEditCompareStringsLinewise(s1, s2);
}
+
+ // Applies the change to the script.
+ // The change is always a substring (change_pos, change_pos + change_len)
+ // being replaced with a completely different string new_str.
+ // This API is a legacy and is obsolete.
+ //
+ // @param {Script} script that is being changed
+ // @param {Array} change_log a list that collects engineer-readable
+ // description of what happened.
+ function ApplySingleChunkPatch(script, change_pos, change_len, new_str,
+ change_log) {
+ var old_source = script.source;
+
+ // Prepare new source string.
+ var new_source = old_source.substring(0, change_pos) +
+ new_str + old_source.substring(change_pos + change_len);
+
+ return ApplyPatchMultiChunk(script,
+ [ change_pos, change_pos + change_len, change_pos + new_str.length],
+ new_source, change_log);
+ }
+
// Functions are public for tests.
this.TestApi = {
PosTranslator: PosTranslator,
- CompareStringsLinewise: CompareStringsLinewise
+ CompareStringsLinewise: CompareStringsLinewise,
+ ApplySingleChunkPatch: ApplySingleChunkPatch
}
}
« no previous file with comments | « src/debug-debugger.js ('k') | test/mjsunit/debug-liveedit-1.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698