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

Unified Diff: src/liveedit-debugger.js

Issue 2883020: Describe LiveEdit changes and support preview mode (Closed)
Patch Set: follow codereview Created 10 years, 6 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-3.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 34d5c0da89a1a038b6c306b8dd89cd845cb13e5f..c8c6f082c03297d28ca895c8b70cd73345db1197 100644
--- a/src/liveedit-debugger.js
+++ b/src/liveedit-debugger.js
@@ -51,7 +51,8 @@ Debug.LiveEdit = new function() {
// 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) {
+ function ApplyPatchMultiChunk(script, diff_array, new_source, preview_only,
+ change_log) {
var old_source = script.source;
@@ -96,7 +97,7 @@ Debug.LiveEdit = new function() {
}
// Recursively collects all newly compiled functions that are going into
- // business and should be have link to the actual script updated.
+ // business and should have link to the actual script updated.
function CollectNew(node_list) {
for (var i = 0; i < node_list.length; i++) {
link_to_original_script_list.push(node_list[i]);
@@ -121,6 +122,20 @@ Debug.LiveEdit = new function() {
}
}
+ var preview_description = {
+ change_tree: DescribeChangeTree(root_old_node),
+ textual_diff: {
+ old_len: old_source.length,
+ new_len: new_source.length,
+ chunks: diff_array
+ },
+ updated: false
+ };
+
+ if (preview_only) {
+ return preview_description;
+ }
+
HarvestTodo(root_old_node);
// Collect shared infos for functions whose code need to be patched.
@@ -132,13 +147,15 @@ Debug.LiveEdit = new function() {
}
}
- // Check that function being patched is not currently on stack.
- CheckStackActivations(replaced_function_infos, change_log);
-
-
// We haven't changed anything before this line yet.
// Committing all changes.
+ // Check that function being patched is not currently on stack or drop them.
+ var dropped_functions_number =
+ CheckStackActivations(replaced_function_infos, change_log);
+
+ preview_description.stack_modified = dropped_functions_number != 0;
+
// Start with breakpoints. Convert their line/column positions and
// temporary remove.
var break_points_restorer = TemporaryRemoveBreakPoints(script, change_log);
@@ -166,6 +183,8 @@ Debug.LiveEdit = new function() {
LinkToOldScript(link_to_old_script_list[i], old_script,
link_to_old_script_report);
}
+
+ preview_description.created_script_name = old_script_name;
}
// Link to an actual script all the functions that we are going to use.
@@ -189,6 +208,9 @@ Debug.LiveEdit = new function() {
}
break_points_restorer(pos_translator, old_script);
+
+ preview_description.updated = true;
+ return preview_description;
}
// Function is public.
this.ApplyPatchMultiChunk = ApplyPatchMultiChunk;
@@ -494,6 +516,16 @@ Debug.LiveEdit = new function() {
this.new_end_pos = void 0;
this.corresponding_node = void 0;
this.unmatched_new_nodes = void 0;
+
+ // 'Textual' correspondence/matching is weaker than 'pure'
+ // correspondence/matching. We need 'textual' level for visual presentation
+ // in UI, we use 'pure' level for actual code manipulation.
+ // Sometimes only function body is changed (functions in old and new script
+ // textually correspond), but we cannot patch the code, so we see them
+ // as an old function deleted and new function created.
+ this.textual_corresponding_node = void 0;
+ this.textually_unmatched_new_nodes = void 0;
+
this.live_shared_info_wrapper = void 0;
}
@@ -640,6 +672,7 @@ Debug.LiveEdit = new function() {
var new_children = new_node.children;
var unmatched_new_nodes_list = [];
+ var textually_unmatched_new_nodes_list = [];
var old_index = 0;
var new_index = 0;
@@ -650,6 +683,7 @@ Debug.LiveEdit = new function() {
if (new_children[new_index].info.start_position <
old_children[old_index].new_start_pos) {
unmatched_new_nodes_list.push(new_children[new_index]);
+ textually_unmatched_new_nodes_list.push(new_children[new_index]);
new_index++;
} else if (new_children[new_index].info.start_position ==
old_children[old_index].new_start_pos) {
@@ -657,6 +691,8 @@ Debug.LiveEdit = new function() {
old_children[old_index].new_end_pos) {
old_children[old_index].corresponding_node =
new_children[new_index];
+ old_children[old_index].textual_corresponding_node =
+ new_children[new_index];
if (old_children[old_index].status != FunctionStatus.UNCHANGED) {
ProcessChildren(old_children[old_index],
new_children[new_index]);
@@ -673,6 +709,7 @@ Debug.LiveEdit = new function() {
"No corresponding function in new script found";
old_node.status = FunctionStatus.CHANGED;
unmatched_new_nodes_list.push(new_children[new_index]);
+ textually_unmatched_new_nodes_list.push(new_children[new_index]);
}
new_index++;
old_index++;
@@ -694,21 +731,28 @@ Debug.LiveEdit = new function() {
while (new_index < new_children.length) {
unmatched_new_nodes_list.push(new_children[new_index]);
+ textually_unmatched_new_nodes_list.push(new_children[new_index]);
new_index++;
}
if (old_node.status == FunctionStatus.CHANGED) {
- if (!CompareFunctionExpectations(old_node.info, new_node.info)) {
+ var why_wrong_expectations =
+ WhyFunctionExpectationsDiffer(old_node.info, new_node.info);
+ if (why_wrong_expectations) {
old_node.status = FunctionStatus.DAMAGED;
- old_node.status_explanation = "Changed code expectations";
+ old_node.status_explanation = why_wrong_expectations;
}
}
old_node.unmatched_new_nodes = unmatched_new_nodes_list;
+ old_node.textually_unmatched_new_nodes =
+ textually_unmatched_new_nodes_list;
}
ProcessChildren(old_code_tree, new_code_tree);
old_code_tree.corresponding_node = new_code_tree;
+ old_code_tree.textual_corresponding_node = new_code_tree;
+
Assert(old_code_tree.status != FunctionStatus.DAMAGED,
"Script became damaged");
}
@@ -792,27 +836,37 @@ Debug.LiveEdit = new function() {
}
// Compares a function interface old and new version, whether it
- // changed or not.
- function CompareFunctionExpectations(function_info1, function_info2) {
+ // changed or not. Returns explanation if they differ.
+ function WhyFunctionExpectationsDiffer(function_info1, function_info2) {
// Check that function has the same number of parameters (there may exist
// an adapter, that won't survive function parameter number change).
if (function_info1.param_num != function_info2.param_num) {
- return false;
+ return "Changed parameter number: " + function_info1.param_num +
+ " and " + function_info2.param_num;
}
var scope_info1 = function_info1.scope_info;
var scope_info2 = function_info2.scope_info;
-
- if (!scope_info1) {
- return !scope_info2;
+
+ var scope_info1_text;
+ var scope_info2_text;
+
+ if (scope_info1) {
+ scope_info1_text = scope_info1.toString();
+ } else {
+ scope_info1_text = "";
}
-
- if (scope_info1.length != scope_info2.length) {
- return false;
+ if (scope_info2) {
+ scope_info2_text = scope_info2.toString();
+ } else {
+ scope_info2_text = "";
}
-
- // Check that outer scope structure is not changed. Otherwise the function
- // will not properly work with existing scopes.
- return scope_info1.toString() == scope_info2.toString();
+
+ if (scope_info1_text != scope_info2_text) {
+ return "Incompatible variable maps: [" + scope_info1_text +
+ "] and [" + scope_info2_text + "]";
+ }
+ // No differences. Return undefined.
+ return;
}
// Minifier forward declaration.
@@ -856,6 +910,8 @@ Debug.LiveEdit = new function() {
change_log.push( { functions_on_stack: problems } );
throw new Failure("Blocked by functions on stack");
}
+
+ return dropped.length;
}
// A copy of the FunctionPatchabilityStatus enum from liveedit.h
@@ -897,14 +953,11 @@ Debug.LiveEdit = new function() {
this.GetPcFromSourcePos = GetPcFromSourcePos;
// LiveEdit main entry point: changes a script text to a new string.
- function SetScriptSource(script, new_source, change_log) {
+ function SetScriptSource(script, new_source, preview_only, change_log) {
var old_source = script.source;
var diff = CompareStringsLinewise(old_source, new_source);
- if (diff.length == 0) {
- change_log.push( { empty_diff: true } );
- return;
- }
- ApplyPatchMultiChunk(script, diff, new_source, change_log);
+ return ApplyPatchMultiChunk(script, diff, new_source, preview_only,
+ change_log);
}
// Function is public.
this.SetScriptSource = SetScriptSource;
@@ -931,7 +984,67 @@ Debug.LiveEdit = new function() {
return ApplyPatchMultiChunk(script,
[ change_pos, change_pos + change_len, change_pos + new_str.length],
- new_source, change_log);
+ new_source, false, change_log);
+ }
+
+ // Creates JSON description for a change tree.
+ function DescribeChangeTree(old_code_tree) {
+
+ function ProcessOldNode(node) {
+ var child_infos = [];
+ for (var i = 0; i < node.children.length; i++) {
+ var child = node.children[i];
+ if (child.status != FunctionStatus.UNCHANGED) {
+ child_infos.push(ProcessOldNode(child));
+ }
+ }
+ var new_child_infos = [];
+ if (node.textually_unmatched_new_nodes) {
+ for (var i = 0; i < node.textually_unmatched_new_nodes.length; i++) {
+ var child = node.textually_unmatched_new_nodes[i];
+ new_child_infos.push(ProcessNewNode(child));
+ }
+ }
+ var res = {
+ name: node.info.function_name,
+ positions: DescribePositions(node),
+ status: node.status,
+ children: child_infos,
+ new_children: new_child_infos
+ };
+ if (node.status_explanation) {
+ res.status_explanation = node.status_explanation;
+ }
+ if (node.textual_corresponding_node) {
+ res.new_positions = DescribePositions(node.textual_corresponding_node);
+ }
+ return res;
+ }
+
+ function ProcessNewNode(node) {
+ var child_infos = [];
+ // Do not list ancestors.
+ if (false) {
+ for (var i = 0; i < node.children.length; i++) {
+ child_infos.push(ProcessNewNode(node.children[i]));
+ }
+ }
+ var res = {
+ name: node.info.function_name,
+ positions: DescribePositions(node),
+ children: child_infos,
+ };
+ return res;
+ }
+
+ function DescribePositions(node) {
+ return {
+ start_position: node.info.start_position,
+ end_position: node.info.end_position
+ };
+ }
+
+ return ProcessOldNode(old_code_tree);
}
« 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