Commit 80453231 authored by peter.rybin@gmail.com's avatar peter.rybin@gmail.com

LiveEdit: breakpoints updates and fixes for related problems

Review URL: http://codereview.chromium.org/1800007

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4533 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent ff0775c3
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "compiler.h" #include "compiler.h"
#include "debug.h" #include "debug.h"
#include "liveedit.h"
#include "oprofile-agent.h" #include "oprofile-agent.h"
#include "prettyprinter.h" #include "prettyprinter.h"
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
...@@ -204,7 +203,6 @@ Handle<Code> CodeGenerator::MakeCodeEpilogue(MacroAssembler* masm, ...@@ -204,7 +203,6 @@ Handle<Code> CodeGenerator::MakeCodeEpilogue(MacroAssembler* masm,
// all the pieces into a Code object. This function is only to be called by // all the pieces into a Code object. This function is only to be called by
// the compiler.cc code. // the compiler.cc code.
Handle<Code> CodeGenerator::MakeCode(CompilationInfo* info) { Handle<Code> CodeGenerator::MakeCode(CompilationInfo* info) {
LiveEditFunctionTracker live_edit_tracker(info->function());
Handle<Script> script = info->script(); Handle<Script> script = info->script();
if (!script->IsUndefined() && !script->source()->IsUndefined()) { if (!script->IsUndefined() && !script->source()->IsUndefined()) {
int len = String::cast(script->source())->length(); int len = String::cast(script->source())->length();
...@@ -216,7 +214,6 @@ Handle<Code> CodeGenerator::MakeCode(CompilationInfo* info) { ...@@ -216,7 +214,6 @@ Handle<Code> CodeGenerator::MakeCode(CompilationInfo* info) {
MacroAssembler masm(NULL, kInitialBufferSize); MacroAssembler masm(NULL, kInitialBufferSize);
CodeGenerator cgen(&masm); CodeGenerator cgen(&masm);
CodeGeneratorScope scope(&cgen); CodeGeneratorScope scope(&cgen);
live_edit_tracker.RecordFunctionScope(info->function()->scope());
cgen.Generate(info); cgen.Generate(info);
if (cgen.HasStackOverflow()) { if (cgen.HasStackOverflow()) {
ASSERT(!Top::has_pending_exception()); ASSERT(!Top::has_pending_exception());
...@@ -225,9 +222,7 @@ Handle<Code> CodeGenerator::MakeCode(CompilationInfo* info) { ...@@ -225,9 +222,7 @@ Handle<Code> CodeGenerator::MakeCode(CompilationInfo* info) {
InLoopFlag in_loop = (cgen.loop_nesting() != 0) ? IN_LOOP : NOT_IN_LOOP; InLoopFlag in_loop = (cgen.loop_nesting() != 0) ? IN_LOOP : NOT_IN_LOOP;
Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, in_loop); Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, in_loop);
Handle<Code> result = MakeCodeEpilogue(cgen.masm(), flags, info); return MakeCodeEpilogue(cgen.masm(), flags, info);
live_edit_tracker.RecordFunctionCode(result);
return result;
} }
......
...@@ -192,6 +192,8 @@ static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global, ...@@ -192,6 +192,8 @@ static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global,
FunctionLiteral* lit = FunctionLiteral* lit =
MakeAST(is_global, script, extension, pre_data, is_json); MakeAST(is_global, script, extension, pre_data, is_json);
LiveEditFunctionTracker live_edit_tracker(lit);
// Check for parse errors. // Check for parse errors.
if (lit == NULL) { if (lit == NULL) {
ASSERT(Top::has_pending_exception()); ASSERT(Top::has_pending_exception());
...@@ -253,6 +255,8 @@ static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global, ...@@ -253,6 +255,8 @@ static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global,
Debugger::OnAfterCompile(script, Debugger::NO_AFTER_COMPILE_FLAGS); Debugger::OnAfterCompile(script, Debugger::NO_AFTER_COMPILE_FLAGS);
#endif #endif
live_edit_tracker.RecordFunctionInfo(result, lit);
return result; return result;
} }
...@@ -448,6 +452,7 @@ bool Compiler::CompileLazy(CompilationInfo* info) { ...@@ -448,6 +452,7 @@ bool Compiler::CompileLazy(CompilationInfo* info) {
Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal, Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
Handle<Script> script, Handle<Script> script,
AstVisitor* caller) { AstVisitor* caller) {
LiveEditFunctionTracker live_edit_tracker(literal);
#ifdef DEBUG #ifdef DEBUG
// We should not try to compile the same function literal more than // We should not try to compile the same function literal more than
// once. // once.
...@@ -552,6 +557,7 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal, ...@@ -552,6 +557,7 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
// the resulting function. // the resulting function.
SetExpectedNofPropertiesFromEstimate(result, SetExpectedNofPropertiesFromEstimate(result,
literal->expected_property_count()); literal->expected_property_count());
live_edit_tracker.RecordFunctionInfo(result, literal);
return result; return result;
} }
......
...@@ -124,12 +124,6 @@ BreakPoint.prototype.source_position = function() { ...@@ -124,12 +124,6 @@ BreakPoint.prototype.source_position = function() {
}; };
BreakPoint.prototype.updateSourcePosition = function(new_position, script) {
this.source_position_ = new_position;
// TODO(635): also update line and column.
};
BreakPoint.prototype.hit_count = function() { BreakPoint.prototype.hit_count = function() {
return this.hit_count_; return this.hit_count_;
}; };
...@@ -245,6 +239,21 @@ function ScriptBreakPoint(type, script_id_or_name, opt_line, opt_column, ...@@ -245,6 +239,21 @@ function ScriptBreakPoint(type, script_id_or_name, opt_line, opt_column,
} }
//Creates a clone of script breakpoint that is linked to another script.
ScriptBreakPoint.prototype.cloneForOtherScript = function (other_script) {
var copy = new ScriptBreakPoint(Debug.ScriptBreakPointType.ScriptId,
other_script.id, this.line_, this.column_, this.groupId_);
copy.number_ = next_break_point_number++;
script_break_points.push(copy);
copy.hit_count_ = this.hit_count_;
copy.active_ = this.active_;
copy.condition_ = this.condition_;
copy.ignoreCount_ = this.ignoreCount_;
return copy;
}
ScriptBreakPoint.prototype.number = function() { ScriptBreakPoint.prototype.number = function() {
return this.number_; return this.number_;
}; };
...@@ -280,6 +289,13 @@ ScriptBreakPoint.prototype.column = function() { ...@@ -280,6 +289,13 @@ ScriptBreakPoint.prototype.column = function() {
}; };
ScriptBreakPoint.prototype.update_positions = function(line, column) {
this.line_ = line;
this.column_ = column;
}
ScriptBreakPoint.prototype.hit_count = function() { ScriptBreakPoint.prototype.hit_count = function() {
return this.hit_count_; return this.hit_count_;
}; };
...@@ -406,6 +422,17 @@ function UpdateScriptBreakPoints(script) { ...@@ -406,6 +422,17 @@ function UpdateScriptBreakPoints(script) {
} }
function GetScriptBreakPoints(script) {
var result = [];
for (var i = 0; i < script_break_points.length; i++) {
if (script_break_points[i].matchesScript(script)) {
result.push(script_break_points[i]);
}
}
return result;
}
Debug.setListener = function(listener, opt_data) { Debug.setListener = function(listener, opt_data) {
if (!IS_FUNCTION(listener) && !IS_UNDEFINED(listener) && !IS_NULL(listener)) { if (!IS_FUNCTION(listener) && !IS_UNDEFINED(listener) && !IS_NULL(listener)) {
throw new Error('Parameters have wrong types.'); throw new Error('Parameters have wrong types.');
......
...@@ -450,7 +450,6 @@ Handle<Code> FullCodeGenerator::MakeCode(CompilationInfo* info) { ...@@ -450,7 +450,6 @@ Handle<Code> FullCodeGenerator::MakeCode(CompilationInfo* info) {
CodeGenerator::MakeCodePrologue(info); CodeGenerator::MakeCodePrologue(info);
const int kInitialBufferSize = 4 * KB; const int kInitialBufferSize = 4 * KB;
MacroAssembler masm(NULL, kInitialBufferSize); MacroAssembler masm(NULL, kInitialBufferSize);
LiveEditFunctionTracker live_edit_tracker(info->function());
FullCodeGenerator cgen(&masm); FullCodeGenerator cgen(&masm);
cgen.Generate(info, PRIMARY); cgen.Generate(info, PRIMARY);
...@@ -459,9 +458,7 @@ Handle<Code> FullCodeGenerator::MakeCode(CompilationInfo* info) { ...@@ -459,9 +458,7 @@ Handle<Code> FullCodeGenerator::MakeCode(CompilationInfo* info) {
return Handle<Code>::null(); return Handle<Code>::null();
} }
Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, NOT_IN_LOOP); Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, NOT_IN_LOOP);
Handle<Code> result = CodeGenerator::MakeCodeEpilogue(&masm, flags, info); return CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
live_edit_tracker.RecordFunctionCode(result);
return result;
} }
......
This diff is collapsed.
This diff is collapsed.
...@@ -67,8 +67,9 @@ class LiveEditFunctionTracker { ...@@ -67,8 +67,9 @@ class LiveEditFunctionTracker {
public: public:
explicit LiveEditFunctionTracker(FunctionLiteral* fun); explicit LiveEditFunctionTracker(FunctionLiteral* fun);
~LiveEditFunctionTracker(); ~LiveEditFunctionTracker();
void RecordFunctionCode(Handle<Code> code); void RecordFunctionInfo(Handle<SharedFunctionInfo> info,
void RecordFunctionScope(Scope* scope); FunctionLiteral* lit);
void RecordRootFunctionInfo(Handle<Code> code);
static bool IsActive(); static bool IsActive();
}; };
...@@ -85,14 +86,26 @@ class LiveEdit : AllStatic { ...@@ -85,14 +86,26 @@ class LiveEdit : AllStatic {
static void ReplaceFunctionCode(Handle<JSArray> new_compile_info_array, static void ReplaceFunctionCode(Handle<JSArray> new_compile_info_array,
Handle<JSArray> shared_info_array); Handle<JSArray> shared_info_array);
static void RelinkFunctionToScript(Handle<JSArray> shared_info_array, // Updates script field in FunctionSharedInfo.
Handle<Script> script_handle); static void SetFunctionScript(Handle<JSValue> function_wrapper,
Handle<Object> script_handle);
// Returns an array of pairs (new source position, breakpoint_object/array) static void PatchFunctionPositions(
// so that JS side could update positions in breakpoint objects.
static Handle<JSArray> PatchFunctionPositions(
Handle<JSArray> shared_info_array, Handle<JSArray> position_change_array); Handle<JSArray> shared_info_array, Handle<JSArray> position_change_array);
// For a script updates its source field. If old_script_name is provided
// (i.e. is a String), also creates a copy of the script with its original
// source and sends notification to debugger.
static Object* ChangeScriptSource(Handle<Script> original_script,
Handle<String> new_source,
Handle<Object> old_script_name);
// In a code of a parent function replaces original function as embedded
// object with a substitution one.
static void ReplaceRefToNestedFunction(Handle<JSValue> parent_function_shared,
Handle<JSValue> orig_function_shared,
Handle<JSValue> subst_function_shared);
// Checks listed functions on stack and return array with corresponding // Checks listed functions on stack and return array with corresponding
// FunctionPatchabilityStatus statuses; extra array element may // FunctionPatchabilityStatus statuses; extra array element may
// contain general error message. Modifies the current stack and // contain general error message. Modifies the current stack and
......
...@@ -9674,38 +9674,30 @@ static Object* Runtime_LiveEditGatherCompileInfo(Arguments args) { ...@@ -9674,38 +9674,30 @@ static Object* Runtime_LiveEditGatherCompileInfo(Arguments args) {
return result; return result;
} }
// Changes the source of the script to a new_source and creates a new // Changes the source of the script to a new_source.
// script representing the old version of the script source. // If old_script_name is provided (i.e. is a String), also creates a copy of
// the script with its original source and sends notification to debugger.
static Object* Runtime_LiveEditReplaceScript(Arguments args) { static Object* Runtime_LiveEditReplaceScript(Arguments args) {
ASSERT(args.length() == 3); ASSERT(args.length() == 3);
HandleScope scope; HandleScope scope;
CONVERT_CHECKED(JSValue, original_script_value, args[0]); CONVERT_CHECKED(JSValue, original_script_value, args[0]);
CONVERT_ARG_CHECKED(String, new_source, 1); CONVERT_ARG_CHECKED(String, new_source, 1);
CONVERT_ARG_CHECKED(String, old_script_name, 2); Handle<Object> old_script_name(args[2]);
Handle<Script> original_script =
Handle<Script>(Script::cast(original_script_value->value()));
Handle<String> original_source(String::cast(original_script->source())); CONVERT_CHECKED(Script, original_script_pointer,
original_script_value->value());
Handle<Script> original_script(original_script_pointer);
original_script->set_source(*new_source); Object* old_script = LiveEdit::ChangeScriptSource(original_script,
Handle<Script> old_script = Factory::NewScript(original_source); new_source,
old_script->set_name(*old_script_name); old_script_name);
old_script->set_line_offset(original_script->line_offset());
old_script->set_column_offset(original_script->column_offset());
old_script->set_data(original_script->data());
old_script->set_type(original_script->type());
old_script->set_context_data(original_script->context_data());
old_script->set_compilation_type(original_script->compilation_type());
old_script->set_eval_from_shared(original_script->eval_from_shared());
old_script->set_eval_from_instructions_offset(
original_script->eval_from_instructions_offset());
// Drop line ends so that they will be recalculated. if (old_script->IsScript()) {
original_script->set_line_ends(Heap::undefined_value()); Handle<Script> script_handle(Script::cast(old_script));
return *(GetScriptWrapper(script_handle));
Debugger::OnAfterCompile(old_script, Debugger::SEND_WHEN_DEBUGGING); } else {
return Heap::null_value();
return *(GetScriptWrapper(old_script)); }
} }
// Replaces code of SharedFunctionInfo with a new one. // Replaces code of SharedFunctionInfo with a new one.
...@@ -9721,35 +9713,60 @@ static Object* Runtime_LiveEditReplaceFunctionCode(Arguments args) { ...@@ -9721,35 +9713,60 @@ static Object* Runtime_LiveEditReplaceFunctionCode(Arguments args) {
} }
// Connects SharedFunctionInfo to another script. // Connects SharedFunctionInfo to another script.
static Object* Runtime_LiveEditRelinkFunctionToScript(Arguments args) { static Object* Runtime_LiveEditFunctionSetScript(Arguments args) {
ASSERT(args.length() == 2); ASSERT(args.length() == 2);
HandleScope scope; HandleScope scope;
CONVERT_ARG_CHECKED(JSArray, shared_info_array, 0); Handle<Object> function_object(args[0]);
CONVERT_ARG_CHECKED(JSValue, script_value, 1); Handle<Object> script_object(args[1]);
Handle<Script> script = Handle<Script>(Script::cast(script_value->value()));
LiveEdit::RelinkFunctionToScript(shared_info_array, script); if (function_object->IsJSValue()) {
Handle<JSValue> function_wrapper = Handle<JSValue>::cast(function_object);
if (script_object->IsJSValue()) {
CONVERT_CHECKED(Script, script, JSValue::cast(*script_object)->value());
script_object = Handle<Object>(script);
}
LiveEdit::SetFunctionScript(function_wrapper, script_object);
} else {
// Just ignore this. We may not have a SharedFunctionInfo for some functions
// and we check it in this function.
}
return Heap::undefined_value(); return Heap::undefined_value();
} }
// In a code of a parent function replaces original function as embedded object
// with a substitution one.
static Object* Runtime_LiveEditReplaceRefToNestedFunction(Arguments args) {
ASSERT(args.length() == 3);
HandleScope scope;
CONVERT_ARG_CHECKED(JSValue, parent_wrapper, 0);
CONVERT_ARG_CHECKED(JSValue, orig_wrapper, 1);
CONVERT_ARG_CHECKED(JSValue, subst_wrapper, 2);
LiveEdit::ReplaceRefToNestedFunction(parent_wrapper, orig_wrapper,
subst_wrapper);
return Heap::undefined_value();
}
// Updates positions of a shared function info (first parameter) according // Updates positions of a shared function info (first parameter) according
// to script source change. Text change is described in second parameter as // to script source change. Text change is described in second parameter as
// array of groups of 3 numbers: // array of groups of 3 numbers:
// (change_begin, change_end, change_end_new_position). // (change_begin, change_end, change_end_new_position).
// Each group describes a change in text; groups are sorted by change_begin. // Each group describes a change in text; groups are sorted by change_begin.
// Returns an array of pairs (new source position, breakpoint_object/array)
// so that JS side could update positions in breakpoint objects.
static Object* Runtime_LiveEditPatchFunctionPositions(Arguments args) { static Object* Runtime_LiveEditPatchFunctionPositions(Arguments args) {
ASSERT(args.length() == 2); ASSERT(args.length() == 2);
HandleScope scope; HandleScope scope;
CONVERT_ARG_CHECKED(JSArray, shared_array, 0); CONVERT_ARG_CHECKED(JSArray, shared_array, 0);
CONVERT_ARG_CHECKED(JSArray, position_change_array, 1); CONVERT_ARG_CHECKED(JSArray, position_change_array, 1);
Handle<Object> result = LiveEdit::PatchFunctionPositions(shared_array, position_change_array);
LiveEdit::PatchFunctionPositions(shared_array, position_change_array);
return *result; return Heap::undefined_value();
} }
......
...@@ -337,7 +337,8 @@ namespace internal { ...@@ -337,7 +337,8 @@ namespace internal {
F(LiveEditGatherCompileInfo, 2, 1) \ F(LiveEditGatherCompileInfo, 2, 1) \
F(LiveEditReplaceScript, 3, 1) \ F(LiveEditReplaceScript, 3, 1) \
F(LiveEditReplaceFunctionCode, 2, 1) \ F(LiveEditReplaceFunctionCode, 2, 1) \
F(LiveEditRelinkFunctionToScript, 2, 1) \ F(LiveEditFunctionSetScript, 2, 1) \
F(LiveEditReplaceRefToNestedFunction, 3, 1) \
F(LiveEditPatchFunctionPositions, 2, 1) \ F(LiveEditPatchFunctionPositions, 2, 1) \
F(LiveEditCheckAndDropActivations, 2, 1) \ F(LiveEditCheckAndDropActivations, 2, 1) \
F(LiveEditCompareStringsLinewise, 2, 1) \ F(LiveEditCompareStringsLinewise, 2, 1) \
......
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --expose-debug-as debug
// Get the Debug object exposed from the debug context global object.
// In this test case we edit a script so that techincally function text
// hasen't been changed. However actually function became one level more nested
// and must be recompiled because it uses variable from outer scope.
Debug = debug.Debug
var function_z_text =
" function Z() {\n"
+ " return 2 + p;\n"
+ " }\n";
eval(
"function Factory(p) {\n"
+ "return (\n"
+ function_z_text
+ ");\n"
+ "}\n"
);
var z6 = Factory(6);
assertEquals(8, z6());
var script = Debug.findScript(Factory);
var new_source = script.source.replace(function_z_text, "function Intermediate() {\nreturn (\n" + function_z_text + ")\n;\n}\n");
print("new source: " + new_source);
var change_log = new Array();
Debug.LiveEdit.SetScriptSource(script, new_source, change_log);
print("Change log: " + JSON.stringify(change_log) + "\n");
assertEquals(8, z6());
var z100 = Factory(100)();
assertEquals(102, z100());
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --expose-debug-as debug
// Get the Debug object exposed from the debug context global object.
Debug = debug.Debug
var function_z_text =
" function Z() {\n"
+ " return 'Z';\n" // Breakpoint line ( #6 )
+ " }\n";
eval(
"function F25() {\n"
+ " return 25;\n" // Breakpoint line ( #1 )
+ "}\n"
+ "function F26 () {\n"
+ " var x = 20;\n"
+ function_z_text // function takes exactly 3 lines
// // Breakpoint line ( #6 )
//
+ " var y = 6;\n"
+ " return x + y;\n"
+ "}\n"
+ "function Nested() {\n"
+ " var a = 30;\n"
+ " return function F27() {\n"
+ " var b = 3;\n" // Breakpoint line ( #14 )
+ " return a - b;\n"
+ " }\n"
+ "}\n"
);
assertEquals(25, F25());
assertEquals(26, F26());
var script = Debug.findScript(F25);
Debug.setScriptBreakPoint(Debug.ScriptBreakPointType.ScriptId, script.id, 1, 1, "true || false || false");
Debug.setScriptBreakPoint(Debug.ScriptBreakPointType.ScriptId, script.id, 6, 1, "true || false || false");
Debug.setScriptBreakPoint(Debug.ScriptBreakPointType.ScriptId, script.id, 14, 1, "true || false || false");
assertEquals(3, Debug.scriptBreakPoints().length);
var new_source = script.source.replace(function_z_text, "");
print("new source: " + new_source);
var change_log = new Array();
Debug.LiveEdit.SetScriptSource(script, new_source, change_log);
print("Change log: " + JSON.stringify(change_log) + "\n");
var breaks = Debug.scriptBreakPoints();
// One breakpoint gets duplicated in a old version of script.
assertTrue(breaks.length > 3 + 1);
var breakpoints_in_script = 0;
var break_position_map = {};
for (var i = 0; i < breaks.length; i++) {
if (breaks[i].script_id() == script.id) {
break_position_map[breaks[i].line()] = true;
breakpoints_in_script++;
}
}
assertEquals(3, breakpoints_in_script);
// Check 2 breakpoints. The one in deleted function should have been moved somewhere.
assertTrue(break_position_map[1]);
assertTrue(break_position_map[11]);
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
Debug = debug.Debug Debug = debug.Debug
function CheckCompareOneWay(s1, s2) { function CheckCompareOneWay(s1, s2) {
var diff_array = Debug.LiveEdit.CompareStringsLinewise(s1, s2); var diff_array = Debug.LiveEdit.TestApi.CompareStringsLinewise(s1, s2);
var pos1 = 0; var pos1 = 0;
var pos2 = 0; var pos2 = 0;
......
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --expose-debug-as debug
// Get the Debug object exposed from the debug context global object.
Debug = debug.Debug
function Return2010() {
return 2010;
}
// Diff it trivial: zero chunks
var NoChunkTranslator = new Debug.LiveEdit.TestApi.PosTranslator([]);
assertEquals(0, NoChunkTranslator.Translate(0));
assertEquals(10, NoChunkTranslator.Translate(10));
// Diff has one chunk
var SingleChunkTranslator = new Debug.LiveEdit.TestApi.PosTranslator([20, 30, 25]);
assertEquals(0, SingleChunkTranslator.Translate(0));
assertEquals(5, SingleChunkTranslator.Translate(5));
assertEquals(10, SingleChunkTranslator.Translate(10));
assertEquals(19, SingleChunkTranslator.Translate(19));
assertEquals(2010, SingleChunkTranslator.Translate(20, Return2010));
assertEquals(25, SingleChunkTranslator.Translate(30));
assertEquals(26, SingleChunkTranslator.Translate(31));
assertEquals(2010, SingleChunkTranslator.Translate(26, Return2010));
try {
SingleChunkTranslator.Translate(21);
assertTrue(false);
} catch (ignore) {
}
try {
SingleChunkTranslator.Translate(24);
assertTrue(false);
} catch (ignore) {
}
// Diff has several chunk (3). See the table below.
/*
chunks: (new <- old)
10 10
15 20
35 40
50 40
70 60
70 70
*/
var MultiChunkTranslator = new Debug.LiveEdit.TestApi.PosTranslator([10, 20, 15, 40, 40, 50, 60, 70, 70 ]);
assertEquals(5, MultiChunkTranslator.Translate(5));
assertEquals(9, MultiChunkTranslator.Translate(9));
assertEquals(2010, MultiChunkTranslator.Translate(10, Return2010));
assertEquals(15, MultiChunkTranslator.Translate(20));
assertEquals(20, MultiChunkTranslator.Translate(25));
assertEquals(34, MultiChunkTranslator.Translate(39));
assertEquals(50, MultiChunkTranslator.Translate(40, Return2010));
assertEquals(55, MultiChunkTranslator.Translate(45));
assertEquals(69, MultiChunkTranslator.Translate(59));
assertEquals(2010, MultiChunkTranslator.Translate(60, Return2010));
assertEquals(70, MultiChunkTranslator.Translate(70));
assertEquals(75, MultiChunkTranslator.Translate(75));
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment