Commit 69d166fc authored by Alexey Kozyatinskiy's avatar Alexey Kozyatinskiy Committed by Commit Bot

[debug] migrate all liveedit tests to use LiveEdit::PatchScript

After this CL all liveedit tests call the same LiveEdit::PatchScript
method. This method will be updated later.
As well some new liveedit cctests added, unfortunately part of them
do not work with current implementation.

R=dgozman@chromium.org,yangguo@chromium.org

Bug: v8:7862
Cq-Include-Trybots: luci.chromium.try:linux_chromium_headless_rel;luci.chromium.try:linux_chromium_rel_ng;master.tryserver.blink:linux_trusty_blink_rel
Change-Id: I3521af12b0f95b39d13aaafb1d1cf60f3f642a97
Reviewed-on: https://chromium-review.googlesource.com/1108382
Commit-Queue: Aleksey Kozyatinskiy <kozyatinskiy@chromium.org>
Reviewed-by: 's avatarYang Guo <yangguo@chromium.org>
Reviewed-by: 's avatarDmitry Gozman <dgozman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53936}
parent 1cda2a6c
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include "src/debug/debug-evaluate.h" #include "src/debug/debug-evaluate.h"
#include "src/debug/debug-type-profile.h" #include "src/debug/debug-type-profile.h"
#include "src/debug/debug.h" #include "src/debug/debug.h"
#include "src/debug/liveedit.h"
#include "src/deoptimizer.h" #include "src/deoptimizer.h"
#include "src/detachable-vector.h" #include "src/detachable-vector.h"
#include "src/execution.h" #include "src/execution.h"
...@@ -9404,11 +9405,12 @@ v8::debug::Location debug::Script::GetSourceLocation(int offset) const { ...@@ -9404,11 +9405,12 @@ v8::debug::Location debug::Script::GetSourceLocation(int offset) const {
} }
bool debug::Script::SetScriptSource(v8::Local<v8::String> newSource, bool debug::Script::SetScriptSource(v8::Local<v8::String> newSource,
bool preview, bool* stack_changed) const { bool preview,
debug::LiveEditResult* result) const {
i::Handle<i::Script> script = Utils::OpenHandle(this); i::Handle<i::Script> script = Utils::OpenHandle(this);
i::Isolate* isolate = script->GetIsolate(); i::Isolate* isolate = script->GetIsolate();
return isolate->debug()->SetScriptSource( return isolate->debug()->SetScriptSource(
script, Utils::OpenHandle(*newSource), preview, stack_changed); script, Utils::OpenHandle(*newSource), preview, result);
} }
bool debug::Script::SetBreakpoint(v8::Local<v8::String> condition, bool debug::Script::SetBreakpoint(v8::Local<v8::String> condition,
......
...@@ -86,6 +86,25 @@ void BreakRightNow(Isolate* isolate); ...@@ -86,6 +86,25 @@ void BreakRightNow(Isolate* isolate);
bool AllFramesOnStackAreBlackboxed(Isolate* isolate); bool AllFramesOnStackAreBlackboxed(Isolate* isolate);
struct LiveEditResult {
enum Status {
OK,
COMPILE_ERROR,
BLOCKED_BY_RUNNING_GENERATOR,
BLOCKED_BY_FUNCTION_ABOVE_BREAK_FRAME,
BLOCKED_BY_FUNCTION_BELOW_NON_DROPPABLE_FRAME,
BLOCKED_BY_ACTIVE_FUNCTION,
BLOCKED_BY_NEW_TARGET_IN_RESTART_FRAME,
FRAME_RESTART_IS_NOT_SUPPORTED
};
Status status = OK;
bool stack_changed = false;
// Fields below are available only for COMPILE_ERROR.
v8::Local<v8::String> message;
int line_number = -1;
int column_number = -1;
};
/** /**
* Native wrapper around v8::internal::Script object. * Native wrapper around v8::internal::Script object.
*/ */
...@@ -114,7 +133,7 @@ class V8_EXPORT_PRIVATE Script { ...@@ -114,7 +133,7 @@ class V8_EXPORT_PRIVATE Script {
int GetSourceOffset(const debug::Location& location) const; int GetSourceOffset(const debug::Location& location) const;
v8::debug::Location GetSourceLocation(int offset) const; v8::debug::Location GetSourceLocation(int offset) const;
bool SetScriptSource(v8::Local<v8::String> newSource, bool preview, bool SetScriptSource(v8::Local<v8::String> newSource, bool preview,
bool* stack_changed) const; LiveEditResult* result) const;
bool SetBreakpoint(v8::Local<v8::String> condition, debug::Location* location, bool SetBreakpoint(v8::Local<v8::String> condition, debug::Location* location,
BreakpointId* id) const; BreakpointId* id) const;
}; };
......
...@@ -601,7 +601,7 @@ bool Debug::IsMutedAtCurrentLocation(JavaScriptFrame* frame) { ...@@ -601,7 +601,7 @@ bool Debug::IsMutedAtCurrentLocation(JavaScriptFrame* frame) {
MaybeHandle<Object> Debug::CallFunction(const char* name, int argc, MaybeHandle<Object> Debug::CallFunction(const char* name, int argc,
Handle<Object> args[], Handle<Object> args[],
bool catch_exceptions) { MaybeHandle<Object>* maybe_exception) {
AllowJavascriptExecutionDebugOnly allow_script(isolate_); AllowJavascriptExecutionDebugOnly allow_script(isolate_);
PostponeInterruptsScope no_interrupts(isolate_); PostponeInterruptsScope no_interrupts(isolate_);
AssertDebugContext(); AssertDebugContext();
...@@ -610,17 +610,11 @@ MaybeHandle<Object> Debug::CallFunction(const char* name, int argc, ...@@ -610,17 +610,11 @@ MaybeHandle<Object> Debug::CallFunction(const char* name, int argc,
Handle<JSFunction> fun = Handle<JSFunction>::cast( Handle<JSFunction> fun = Handle<JSFunction>::cast(
JSReceiver::GetProperty(isolate_, holder, name).ToHandleChecked()); JSReceiver::GetProperty(isolate_, holder, name).ToHandleChecked());
Handle<Object> undefined = isolate_->factory()->undefined_value(); Handle<Object> undefined = isolate_->factory()->undefined_value();
if (catch_exceptions) { return Execution::TryCall(isolate_, fun, undefined, argc, args,
MaybeHandle<Object> maybe_exception; Execution::MessageHandling::kReport,
return Execution::TryCall(isolate_, fun, undefined, argc, args, maybe_exception);
Execution::MessageHandling::kReport,
&maybe_exception);
} else {
return Execution::Call(isolate_, fun, undefined, argc, args);
}
} }
// Check whether a single break point object is triggered. // Check whether a single break point object is triggered.
bool Debug::CheckBreakPoint(Handle<BreakPoint> break_point, bool Debug::CheckBreakPoint(Handle<BreakPoint> break_point,
bool is_break_at_entry) { bool is_break_at_entry) {
...@@ -1907,22 +1901,52 @@ bool Debug::CanBreakAtEntry(Handle<SharedFunctionInfo> shared) { ...@@ -1907,22 +1901,52 @@ bool Debug::CanBreakAtEntry(Handle<SharedFunctionInfo> shared) {
} }
bool Debug::SetScriptSource(Handle<Script> script, Handle<String> source, bool Debug::SetScriptSource(Handle<Script> script, Handle<String> source,
bool preview, bool* stack_changed) { bool preview, debug::LiveEditResult* output) {
SaveContext save(isolate_); SaveContext save(isolate_);
StackFrame::Id frame_id = break_frame_id();
DebugScope debug_scope(this); DebugScope debug_scope(this);
if (debug_scope.failed()) return false; if (debug_scope.failed()) return false;
isolate_->set_context(*debug_context()); isolate_->set_context(*debug_context());
if (frame_id != StackFrame::NO_ID) {
thread_local_.break_frame_id_ = frame_id;
}
set_live_edit_enabled(true); set_live_edit_enabled(true);
Handle<Object> script_wrapper = Script::GetWrapper(script); Handle<Object> script_wrapper = Script::GetWrapper(script);
Handle<Object> argv[] = {script_wrapper, source, Handle<Object> argv[] = {script_wrapper, source,
isolate_->factory()->ToBoolean(preview), isolate_->factory()->ToBoolean(preview),
isolate_->factory()->NewJSArray(0)}; isolate_->factory()->NewJSArray(0)};
Handle<Object> result; Handle<Object> result;
if (!CallFunction("SetScriptSource", arraysize(argv), argv, false) MaybeHandle<Object> maybe_exception;
if (!CallFunction("SetScriptSource", arraysize(argv), argv, &maybe_exception)
.ToHandle(&result)) { .ToHandle(&result)) {
isolate_->OptionalRescheduleException(false); Handle<Object> pending_exception = maybe_exception.ToHandleChecked();
set_live_edit_enabled(false); set_live_edit_enabled(false);
if (pending_exception->IsJSObject()) {
Handle<JSObject> exception = Handle<JSObject>::cast(pending_exception);
Handle<String> message = Handle<String>::cast(
JSReceiver::GetProperty(isolate_, exception, "message")
.ToHandleChecked());
Handle<String> blocked_message =
isolate_->factory()->NewStringFromAsciiChecked(
"Blocked by functions on stack");
if (blocked_message->Equals(*message)) {
output->status = debug::LiveEditResult::
BLOCKED_BY_FUNCTION_BELOW_NON_DROPPABLE_FRAME;
} else {
Handle<JSObject> details = Handle<JSObject>::cast(
JSReceiver::GetProperty(isolate_, exception, "details")
.ToHandleChecked());
Handle<String> error = Handle<String>::cast(
JSReceiver::GetProperty(isolate_, details, "syntaxErrorMessage")
.ToHandleChecked());
output->status = debug::LiveEditResult::COMPILE_ERROR;
output->line_number = kNoSourcePosition;
output->column_number = kNoSourcePosition;
output->message = Utils::ToLocal(error);
}
}
return false; return false;
} }
set_live_edit_enabled(false); set_live_edit_enabled(false);
...@@ -1930,7 +1954,8 @@ bool Debug::SetScriptSource(Handle<Script> script, Handle<String> source, ...@@ -1930,7 +1954,8 @@ bool Debug::SetScriptSource(Handle<Script> script, Handle<String> source,
JSReceiver::GetProperty(isolate_, Handle<JSObject>::cast(result), JSReceiver::GetProperty(isolate_, Handle<JSObject>::cast(result),
"stack_modified") "stack_modified")
.ToHandleChecked(); .ToHandleChecked();
*stack_changed = stack_changed_value->IsTrue(isolate_); output->stack_changed = stack_changed_value->IsTrue(isolate_);
output->status = debug::LiveEditResult::OK;
return true; return true;
} }
......
...@@ -313,7 +313,7 @@ class Debug { ...@@ -313,7 +313,7 @@ class Debug {
// change. stack_changed is true if after editing script on pause stack is // change. stack_changed is true if after editing script on pause stack is
// changed and client should request stack trace again. // changed and client should request stack trace again.
bool SetScriptSource(Handle<Script> script, Handle<String> source, bool SetScriptSource(Handle<Script> script, Handle<String> source,
bool preview, bool* stack_changed); bool preview, debug::LiveEditResult* result);
// Threading support. // Threading support.
char* ArchiveDebug(char* to); char* ArchiveDebug(char* to);
...@@ -467,7 +467,7 @@ class Debug { ...@@ -467,7 +467,7 @@ class Debug {
bool CheckBreakPoint(Handle<BreakPoint> break_point, bool is_break_at_entry); bool CheckBreakPoint(Handle<BreakPoint> break_point, bool is_break_at_entry);
MaybeHandle<Object> CallFunction(const char* name, int argc, MaybeHandle<Object> CallFunction(const char* name, int argc,
Handle<Object> args[], Handle<Object> args[],
bool catch_exceptions = true); MaybeHandle<Object>* maybe_exception);
inline void AssertDebugContext() { inline void AssertDebugContext() {
DCHECK(in_debug_scope()); DCHECK(in_debug_scope());
......
...@@ -1597,5 +1597,10 @@ int LiveEdit::TranslatePosition(const std::vector<SourceChangeRange>& changes, ...@@ -1597,5 +1597,10 @@ int LiveEdit::TranslatePosition(const std::vector<SourceChangeRange>& changes,
return position + (it->new_end_position - it->end_position); return position + (it->new_end_position - it->end_position);
} }
void LiveEdit::PatchScript(Handle<Script> script, Handle<String> new_source,
debug::LiveEditResult* result) {
script->GetIsolate()->debug()->SetScriptSource(script, new_source, false,
result);
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -29,6 +29,9 @@ ...@@ -29,6 +29,9 @@
#include "src/ast/ast-traversal-visitor.h" #include "src/ast/ast-traversal-visitor.h"
namespace v8 { namespace v8 {
namespace debug {
struct LiveEditResult;
}
namespace internal { namespace internal {
class JavaScriptFrame; class JavaScriptFrame;
...@@ -140,6 +143,8 @@ class LiveEdit : AllStatic { ...@@ -140,6 +143,8 @@ class LiveEdit : AllStatic {
std::vector<SourceChangeRange>* changes); std::vector<SourceChangeRange>* changes);
static int TranslatePosition(const std::vector<SourceChangeRange>& changed, static int TranslatePosition(const std::vector<SourceChangeRange>& changed,
int position); int position);
static void PatchScript(Handle<Script> script, Handle<String> source,
debug::LiveEditResult* result);
// A copy of this is in liveedit.js. // A copy of this is in liveedit.js.
enum FunctionPatchabilityStatus { enum FunctionPatchabilityStatus {
......
...@@ -294,62 +294,6 @@ Response buildScopes(v8::debug::ScopeIterator* iterator, ...@@ -294,62 +294,6 @@ Response buildScopes(v8::debug::ScopeIterator* iterator,
return Response::OK(); return Response::OK();
} }
bool liveEditExceptionToDetails(
V8InspectorImpl* inspector, v8::Local<v8::Context> context,
v8::Local<v8::Value> exceptionValue,
Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) {
if (!exceptionValue->IsObject()) return false;
v8::Isolate* isolate = context->GetIsolate();
v8::Local<v8::Object> exception = exceptionValue.As<v8::Object>();
v8::Local<v8::Value> detailsValue;
if (!exception->Get(context, toV8String(isolate, "details"))
.ToLocal(&detailsValue) ||
!detailsValue->IsObject()) {
return false;
}
v8::Local<v8::Object> details = detailsValue.As<v8::Object>();
v8::Local<v8::Value> message;
if (!details->Get(context, toV8String(isolate, "syntaxErrorMessage"))
.ToLocal(&message) ||
!message->IsString()) {
return false;
}
v8::Local<v8::Value> positionValue;
if (!details->Get(context, toV8String(isolate, "position"))
.ToLocal(&positionValue) ||
!positionValue->IsObject()) {
return false;
}
v8::Local<v8::Value> startPositionValue;
if (!positionValue.As<v8::Object>()
->Get(context, toV8String(isolate, "start"))
.ToLocal(&startPositionValue) ||
!startPositionValue->IsObject()) {
return false;
}
v8::Local<v8::Object> startPosition = startPositionValue.As<v8::Object>();
v8::Local<v8::Value> lineValue;
if (!startPosition->Get(context, toV8String(isolate, "line"))
.ToLocal(&lineValue) ||
!lineValue->IsInt32()) {
return false;
}
v8::Local<v8::Value> columnValue;
if (!startPosition->Get(context, toV8String(isolate, "column"))
.ToLocal(&columnValue) ||
!columnValue->IsInt32()) {
return false;
}
*exceptionDetails =
protocol::Runtime::ExceptionDetails::create()
.setExceptionId(inspector->nextExceptionId())
.setText(toProtocolString(message.As<v8::String>()))
.setLineNumber(lineValue->Int32Value(context).FromJust() - 1)
.setColumnNumber(columnValue->Int32Value(context).FromJust() - 1)
.build();
return true;
}
protocol::DictionaryValue* getOrCreateObject(protocol::DictionaryValue* object, protocol::DictionaryValue* getOrCreateObject(protocol::DictionaryValue* object,
const String16& key) { const String16& key) {
protocol::DictionaryValue* value = object->getObject(key); protocol::DictionaryValue* value = object->getObject(key);
...@@ -927,23 +871,22 @@ Response V8DebuggerAgentImpl::setScriptSource( ...@@ -927,23 +871,22 @@ Response V8DebuggerAgentImpl::setScriptSource(
v8::HandleScope handleScope(m_isolate); v8::HandleScope handleScope(m_isolate);
v8::Local<v8::Context> context = inspected->context(); v8::Local<v8::Context> context = inspected->context();
v8::Context::Scope contextScope(context); v8::Context::Scope contextScope(context);
v8::TryCatch tryCatch(m_isolate);
v8::debug::LiveEditResult result;
bool stackChangedValue = false; it->second->setSource(newContent, dryRun.fromMaybe(false), &result);
it->second->setSource(newContent, dryRun.fromMaybe(false), if (result.status != v8::debug::LiveEditResult::OK) {
&stackChangedValue); *optOutCompileError =
if (tryCatch.HasCaught()) { protocol::Runtime::ExceptionDetails::create()
if (liveEditExceptionToDetails(m_inspector, context, tryCatch.Exception(), .setExceptionId(m_inspector->nextExceptionId())
optOutCompileError)) { .setText(toProtocolString(result.message))
return Response::OK(); .setLineNumber(result.line_number != -1 ? result.line_number - 1
} : 0)
v8::Local<v8::Message> message = tryCatch.Message(); .setColumnNumber(result.column_number != -1 ? result.column_number
if (!message.IsEmpty()) : 0)
return Response::Error(toProtocolStringWithTypeCheck(message->Get())); .build();
else return Response::OK();
return Response::InternalError();
} else { } else {
*stackChanged = stackChangedValue; *stackChanged = result.stack_changed;
} }
std::unique_ptr<Array<CallFrame>> callFrames; std::unique_ptr<Array<CallFrame>> callFrames;
Response response = currentCallFrames(&callFrames); Response response = currentCallFrames(&callFrames);
......
...@@ -166,12 +166,12 @@ class ActualScript : public V8DebuggerScript { ...@@ -166,12 +166,12 @@ class ActualScript : public V8DebuggerScript {
} }
void setSource(const String16& newSource, bool preview, void setSource(const String16& newSource, bool preview,
bool* stackChanged) override { v8::debug::LiveEditResult* result) override {
DCHECK(!isModule()); DCHECK(!isModule());
v8::HandleScope scope(m_isolate); v8::EscapableHandleScope scope(m_isolate);
v8::Local<v8::String> v8Source = toV8String(m_isolate, newSource); v8::Local<v8::String> v8Source = toV8String(m_isolate, newSource);
if (!m_script.Get(m_isolate)->SetScriptSource(v8Source, preview, if (!m_script.Get(m_isolate)->SetScriptSource(v8Source, preview, result)) {
stackChanged)) { result->message = scope.Escape(result->message);
return; return;
} }
if (preview) return; if (preview) return;
...@@ -290,7 +290,9 @@ class WasmVirtualScript : public V8DebuggerScript { ...@@ -290,7 +290,9 @@ class WasmVirtualScript : public V8DebuggerScript {
bool isLiveEdit() const override { return false; } bool isLiveEdit() const override { return false; }
bool isModule() const override { return false; } bool isModule() const override { return false; }
void setSourceMappingURL(const String16&) override {} void setSourceMappingURL(const String16&) override {}
void setSource(const String16&, bool, bool*) override { UNREACHABLE(); } void setSource(const String16&, bool, v8::debug::LiveEditResult*) override {
UNREACHABLE();
}
bool isSourceLoadedLazily() const override { return true; } bool isSourceLoadedLazily() const override { return true; }
const String16& source() const override { const String16& source() const override {
return m_wasmTranslation->GetSource(m_id, m_functionIndex); return m_wasmTranslation->GetSource(m_id, m_functionIndex);
......
...@@ -73,7 +73,7 @@ class V8DebuggerScript { ...@@ -73,7 +73,7 @@ class V8DebuggerScript {
void setSourceURL(const String16&); void setSourceURL(const String16&);
virtual void setSourceMappingURL(const String16&) = 0; virtual void setSourceMappingURL(const String16&) = 0;
virtual void setSource(const String16& source, bool preview, virtual void setSource(const String16& source, bool preview,
bool* stackChanged) = 0; v8::debug::LiveEditResult* result) = 0;
virtual bool getPossibleBreakpoints( virtual bool getPossibleBreakpoints(
const v8::debug::Location& start, const v8::debug::Location& end, const v8::debug::Location& start, const v8::debug::Location& end,
......
...@@ -898,5 +898,43 @@ RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionFinished) { ...@@ -898,5 +898,43 @@ RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionFinished) {
return isolate->heap()->undefined_value(); return isolate->heap()->undefined_value();
} }
RUNTIME_FUNCTION(Runtime_LiveEditPatchScript) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSFunction, script_function, 0);
CONVERT_ARG_HANDLE_CHECKED(String, new_source, 1);
Handle<Script> script(Script::cast(script_function->shared()->script()),
isolate);
v8::debug::LiveEditResult result;
LiveEdit::PatchScript(script, new_source, &result);
switch (result.status) {
case v8::debug::LiveEditResult::COMPILE_ERROR:
return isolate->Throw(*isolate->factory()->NewStringFromAsciiChecked(
"LiveEdit failed: COMPILE_ERROR"));
case v8::debug::LiveEditResult::BLOCKED_BY_RUNNING_GENERATOR:
return isolate->Throw(*isolate->factory()->NewStringFromAsciiChecked(
"LiveEdit failed: BLOCKED_BY_RUNNING_GENERATOR"));
case v8::debug::LiveEditResult::BLOCKED_BY_FUNCTION_ABOVE_BREAK_FRAME:
return isolate->Throw(*isolate->factory()->NewStringFromAsciiChecked(
"LiveEdit failed: BLOCKED_BY_FUNCTION_ABOVE_BREAK_FRAME"));
case v8::debug::LiveEditResult::
BLOCKED_BY_FUNCTION_BELOW_NON_DROPPABLE_FRAME:
return isolate->Throw(*isolate->factory()->NewStringFromAsciiChecked(
"LiveEdit failed: BLOCKED_BY_FUNCTION_BELOW_NON_DROPPABLE_FRAME"));
case v8::debug::LiveEditResult::BLOCKED_BY_ACTIVE_FUNCTION:
return isolate->Throw(*isolate->factory()->NewStringFromAsciiChecked(
"LiveEdit failed: BLOCKED_BY_ACTIVE_FUNCTION"));
case v8::debug::LiveEditResult::BLOCKED_BY_NEW_TARGET_IN_RESTART_FRAME:
return isolate->Throw(*isolate->factory()->NewStringFromAsciiChecked(
"LiveEdit failed: BLOCKED_BY_NEW_TARGET_IN_RESTART_FRAME"));
case v8::debug::LiveEditResult::FRAME_RESTART_IS_NOT_SUPPORTED:
return isolate->Throw(*isolate->factory()->NewStringFromAsciiChecked(
"LiveEdit failed: FRAME_RESTART_IS_NOT_SUPPORTED"));
case v8::debug::LiveEditResult::OK:
return isolate->heap()->undefined_value();
}
return isolate->heap()->undefined_value();
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -155,7 +155,8 @@ namespace internal { ...@@ -155,7 +155,8 @@ namespace internal {
F(ScriptLocationFromLine, 4, 1) \ F(ScriptLocationFromLine, 4, 1) \
F(ScriptPositionInfo2, 3, 1) \ F(ScriptPositionInfo2, 3, 1) \
F(ScriptPositionInfo, 3, 1) \ F(ScriptPositionInfo, 3, 1) \
F(SetGeneratorScopeVariableValue, 4, 1) F(SetGeneratorScopeVariableValue, 4, 1) \
F(LiveEditPatchScript, 2, 1)
#define FOR_EACH_INTRINSIC_FORIN(F) \ #define FOR_EACH_INTRINSIC_FORIN(F) \
F(ForInEnumerate, 1, 1) \ F(ForInEnumerate, 1, 1) \
......
This diff is collapsed.
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax
Debug = debug.Debug Debug = debug.Debug
...@@ -34,13 +35,11 @@ eval("var something1 = 25; " ...@@ -34,13 +35,11 @@ eval("var something1 = 25; "
assertEquals("Cat", ChooseAnimal()); assertEquals("Cat", ChooseAnimal());
var script = Debug.findScript(ChooseAnimal);
var orig_animal = "Cat"; var orig_animal = "Cat";
var patch_pos = script.source.indexOf(orig_animal);
var new_animal_patch = "Cap' + 'y' + 'bara"; var new_animal_patch = "Cap' + 'y' + 'bara";
var new_source =
Debug.scriptSource(ChooseAnimal).replace(orig_animal, new_animal_patch);
var change_log = new Array(); %LiveEditPatchScript(ChooseAnimal, new_source);
Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos, orig_animal.length, new_animal_patch, change_log);
assertEquals("Capybara", ChooseAnimal()); assertEquals("Capybara", ChooseAnimal());
...@@ -25,8 +25,7 @@ ...@@ -25,8 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --noalways-opt // Flags: --noalways-opt --allow-natives-syntax
Debug = debug.Debug Debug = debug.Debug
...@@ -43,19 +42,12 @@ var old_closure = ChooseAnimal(19); ...@@ -43,19 +42,12 @@ var old_closure = ChooseAnimal(19);
assertEquals("Cat", old_closure()); assertEquals("Cat", old_closure());
var script = Debug.findScript(ChooseAnimal);
var orig_animal = "'Cat'";
var patch_pos = script.source.indexOf(orig_animal);
var new_animal_patch = "'Capybara' + p";
// We patch innermost function "Chooser". // We patch innermost function "Chooser".
// However, this does not actually patch existing "Chooser" instances, // However, this does not actually patch existing "Chooser" instances,
// because old value of parameter "p" was not saved. // because old value of parameter "p" was not saved.
// Instead it patches ChooseAnimal. // Instead it patches ChooseAnimal.
var change_log = new Array(); %LiveEditPatchScript(
Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos, orig_animal.length, new_animal_patch, change_log); ChooseAnimal, Debug.scriptSource(ChooseAnimal).replace("'Cat'", "'Capybara' + p"));
print("Change log: " + JSON.stringify(change_log) + "\n");
var new_closure = ChooseAnimal(19); var new_closure = ChooseAnimal(19);
// New instance of closure is patched. // New instance of closure is patched.
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
// hasen't been changed. However actually function became one level more nested // hasen't been changed. However actually function became one level more nested
// and must be recompiled because it uses variable from outer scope. // and must be recompiled because it uses variable from outer scope.
// Flags: --allow-natives-syntax
Debug = debug.Debug Debug = debug.Debug
...@@ -49,15 +50,11 @@ eval( ...@@ -49,15 +50,11 @@ eval(
var z6 = Factory(6); var z6 = Factory(6);
assertEquals(8, z6()); assertEquals(8, z6());
var script = Debug.findScript(Factory); var new_source = Debug.scriptSource(Factory).replace(
function_z_text,
'function Intermediate() {\nreturn (\n' + function_z_text + ')\n;\n}\n');
var new_source = script.source.replace(function_z_text, "function Intermediate() {\nreturn (\n" + function_z_text + ")\n;\n}\n"); %LiveEditPatchScript(Factory, new_source);
print("new source: " + new_source);
var change_log = new Array();
var result = Debug.LiveEdit.SetScriptSource(script, new_source, false, change_log);
print("Result: " + JSON.stringify(result) + "\n");
print("Change log: " + JSON.stringify(change_log) + "\n");
assertEquals(8, z6()); assertEquals(8, z6());
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
// hasen't been changed. However actually function became one level more nested // hasen't been changed. However actually function became one level more nested
// and must be recompiled because it uses variable from outer scope. // and must be recompiled because it uses variable from outer scope.
// Flags: --allow-natives-syntax
Debug = debug.Debug Debug = debug.Debug
...@@ -53,14 +54,10 @@ var res = TestFunction(); ...@@ -53,14 +54,10 @@ var res = TestFunction();
print(res); print(res);
assertEquals('a,c', res); assertEquals('a,c', res);
var script = Debug.findScript(TestFunction); var new_source = Debug.scriptSource(TestFunction).replace('2013', 'b');
var new_source = script.source.replace("2013", "b");
print("new source: " + new_source); print("new source: " + new_source);
var change_log = new Array();
var result = Debug.LiveEdit.SetScriptSource(script, new_source, false, change_log);
print("Result: " + JSON.stringify(result) + "\n"); %LiveEditPatchScript(TestFunction, new_source);
print("Change log: " + JSON.stringify(change_log) + "\n");
var res = TestFunction(); var res = TestFunction();
print(res); print(res);
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax
Debug = debug.Debug Debug = debug.Debug
...@@ -33,35 +34,26 @@ unique_id = 1; ...@@ -33,35 +34,26 @@ unique_id = 1;
function TestBase(name) { function TestBase(name) {
print("TestBase constructor: " + name); print("TestBase constructor: " + name);
this.ChooseAnimal = eval( const original_source = '/* ' + unique_id + '*/\n' +
"/* " + unique_id + "*/\n" + '(function ChooseAnimal(callback) {\n ' +
"(function ChooseAnimal(callback) {\n " + ' callback();\n' +
" callback();\n" + ' return \'Cat\';\n' +
" return 'Cat';\n" + '})\n';
"})\n" const updated_source = original_source.replace('\'Cat\'', '\'Capybara\'');
);
this.ChooseAnimal = eval(original_source);
// Prevents eval script caching. // Prevents eval script caching.
unique_id++; unique_id++;
var script = Debug.findScript(this.ChooseAnimal); const func = this.ChooseAnimal;
var orig_animal = "'Cat'";
var patch_pos = script.source.indexOf(orig_animal);
var new_animal_patch = "'Capybara'";
var got_exception = false; var got_exception = false;
var successfully_changed = false; var successfully_changed = false;
// Should be called from Debug context. // Should be called from Debug context.
this.ScriptChanger = function() { this.ScriptChanger = () => {
assertEquals(false, successfully_changed, "applying patch second time"); assertEquals(false, successfully_changed, "applying patch second time");
// Runs in debugger context. %LiveEditPatchScript(func, updated_source);
var change_log = new Array();
try {
Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos, orig_animal.length, new_animal_patch, change_log);
} finally {
print("Change log: " + JSON.stringify(change_log) + "\n");
}
successfully_changed = true; successfully_changed = true;
}; };
} }
...@@ -74,7 +66,7 @@ function WrapInCatcher(f, holder) { ...@@ -74,7 +66,7 @@ function WrapInCatcher(f, holder) {
try { try {
f(); f();
} catch (e) { } catch (e) {
if (e instanceof Debug.LiveEdit.Failure) { if (e.startsWith('LiveEdit failed')) {
holder[0] = e; holder[0] = e;
} else { } else {
throw e; throw e;
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax
Debug = debug.Debug Debug = debug.Debug
...@@ -34,23 +35,16 @@ eval("var something1 = 25; \n" ...@@ -34,23 +35,16 @@ eval("var something1 = 25; \n"
assertEquals("Cat", ChooseAnimal()); assertEquals("Cat", ChooseAnimal());
var script = Debug.findScript(ChooseAnimal); var new_source =
Debug.scriptSource(ChooseAnimal).replace('Cat', 'Cap\' + ) + \'bara');
print('new source: ' + new_source);
var orig_animal = "Cat";
var patch_pos = script.source.indexOf(orig_animal);
var new_animal_patch = "Cap' + ) + 'bara";
var change_log = new Array();
var caught_exception = null; var caught_exception = null;
try { try {
Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos, %LiveEditPatchScript(ChooseAnimal, new_source);
orig_animal.length, new_animal_patch, change_log);
} catch (e) { } catch (e) {
caught_exception = e; caught_exception = e;
} }
assertNotNull(caught_exception); assertNotNull(caught_exception);
assertEquals("Unexpected token )", assertEquals('LiveEdit failed: COMPILE_ERROR', caught_exception);
caught_exception.details.syntaxErrorMessage);
assertEquals(2, caught_exception.details.position.start.line);
...@@ -92,8 +92,7 @@ function TestCase(test_scenario, expected_output) { ...@@ -92,8 +92,7 @@ function TestCase(test_scenario, expected_output) {
} }
script_text_generator.change(change_var); script_text_generator.change(change_var);
try { try {
Debug.LiveEdit.SetScriptSource(script, script_text_generator.get(), %LiveEditPatchScript(test_fun, script_text_generator.get())
false, []);
} catch (e) { } catch (e) {
print("LiveEdit exception: " + e); print("LiveEdit exception: " + e);
throw e; throw e;
......
...@@ -2,9 +2,9 @@ ...@@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// Flags: --allow-natives-syntax
Debug = debug.Debug Debug = debug.Debug
function BestEditor() { function BestEditor() {
throw 'Emacs'; throw 'Emacs';
} }
...@@ -37,11 +37,8 @@ function listener(event, exec_state, event_data, data) { ...@@ -37,11 +37,8 @@ function listener(event, exec_state, event_data, data) {
}; };
function Replace(fun, original, patch) { function Replace(fun, original, patch) {
var script = Debug.findScript(fun);
if (fun.toString().indexOf(original) < 0) return; if (fun.toString().indexOf(original) < 0) return;
var patch_pos = script.source.indexOf(original); %LiveEditPatchScript(fun, Debug.scriptSource(fun).replace(original, patch));
var change_log = [];
Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos, original.length, patch, change_log);
} }
Debug.setListener(listener); Debug.setListener(listener);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file // found in the LICENSE file
// Flags: --allow-natives-syntax --enable-inspector // Flags: --allow-natives-syntax
Debug = debug.Debug Debug = debug.Debug
...@@ -17,14 +17,10 @@ assertEquals("Cat", foo()); ...@@ -17,14 +17,10 @@ assertEquals("Cat", foo());
foo(); foo();
var script = Debug.findScript(ChooseAnimal); var new_source =
Debug.scriptSource(ChooseAnimal).replace('Cat', "Cap' + 'y' + 'bara");
print('new source: ' + new_source);
var orig_animal = "Cat"; %LiveEditPatchScript(ChooseAnimal, new_source);
var patch_pos = script.source.indexOf(orig_animal);
var new_animal_patch = "Cap' + 'y' + 'bara";
var change_log = new Array();
Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos, orig_animal.length, new_animal_patch, change_log);
assertEquals("Capybara", foo()); assertEquals("Capybara", foo());
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax
Debug = debug.Debug Debug = debug.Debug
...@@ -46,14 +47,9 @@ function Test(old_expression, new_expression) { ...@@ -46,14 +47,9 @@ function Test(old_expression, new_expression) {
assertEquals("Cat", ChooseAnimalArray[i]()); assertEquals("Cat", ChooseAnimalArray[i]());
} }
var script = Debug.findScript(ChooseAnimalArray[0]); var new_source =
Debug.scriptSource(ChooseAnimalArray[0]).replace(old_expression, new_expression);
var patch_pos = script.source.indexOf(old_expression); %LiveEditPatchScript(ChooseAnimalArray[0], new_source);
var new_animal_patch = new_expression;
var change_log = new Array();
Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos,
old_expression.length, new_expression, change_log);
for (var i = 0; i < ChooseAnimalArray.length; i++) { for (var i = 0; i < ChooseAnimalArray.length; i++) {
assertEquals("Capybara", ChooseAnimalArray[i]()); assertEquals("Capybara", ChooseAnimalArray[i]());
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax
Debug = debug.Debug Debug = debug.Debug
...@@ -47,9 +48,7 @@ eval("var something1 = 25; \n" ...@@ -47,9 +48,7 @@ eval("var something1 = 25; \n"
assertEquals("Cat", ChooseAnimal()); assertEquals("Cat", ChooseAnimal());
assertEquals(25, something1); assertEquals(25, something1);
var script = Debug.findScript(ChooseAnimal); var new_source = Debug.scriptSource(ChooseAnimal).replace("Cat", "Cap' + 'yb' + 'ara");
var new_source = script.source.replace("Cat", "Cap' + 'yb' + 'ara");
var new_source = new_source.replace("25", "26"); var new_source = new_source.replace("25", "26");
var new_source = new_source.replace("Help", "Hello"); var new_source = new_source.replace("Help", "Hello");
var new_source = new_source.replace("17", "18"); var new_source = new_source.replace("17", "18");
...@@ -62,10 +61,7 @@ var new_source = new_source.replace("17", "18"); ...@@ -62,10 +61,7 @@ var new_source = new_source.replace("17", "18");
var new_source = new_source.replace("// Array", "Array"); var new_source = new_source.replace("// Array", "Array");
print("new source: " + new_source); print("new source: " + new_source);
var change_log = new Array(); %LiveEditPatchScript(ChooseAnimal, new_source);
var result = Debug.LiveEdit.SetScriptSource(script, new_source, false, change_log);
print("Result: " + JSON.stringify(result) + "\n");
print("Change log: " + JSON.stringify(change_log) + "\n");
assertEquals("Capybara", ChooseAnimal()); assertEquals("Capybara", ChooseAnimal());
// Global variable do not get changed (without restarting script). // Global variable do not get changed (without restarting script).
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
// change they are 114 characters away from each other. New instance of Code is // change they are 114 characters away from each other. New instance of Code is
// required when those numbers cross the border value of 64 (in any direction). // required when those numbers cross the border value of 64 (in any direction).
// Flags: --allow-natives-syntax
Debug = debug.Debug Debug = debug.Debug
eval( eval(
...@@ -46,19 +47,13 @@ eval( ...@@ -46,19 +47,13 @@ eval(
"}" "}"
); );
var script = Debug.findScript(BeingReplaced);
var orig_body = "{}";
var patch_pos = script.source.indexOf(orig_body);
// Line long enough to change rinfo encoding.
var new_body_patch = "{return 'Capybara';" +
" " +
"}";
var change_log = new Array();
function Changer() { function Changer() {
Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos, orig_body.length, new_body_patch, change_log); // Line long enough to change rinfo encoding.
print("Change log: " + JSON.stringify(change_log) + "\n"); var new_source =
Debug.scriptSource(BeingReplaced).replace("{}", "{return 'Capybara';" +
" " +
"}");
%LiveEditPatchScript(BeingReplaced, new_source);
} }
function NoOp() { function NoOp() {
......
...@@ -2,25 +2,23 @@ ...@@ -2,25 +2,23 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// Flags: --allow-natives-syntax
Debug = debug.Debug Debug = debug.Debug
var counter = 0; var counter = 0;
var exception = null; var exception = null;
function f() { function f() {
if (++counter > 5) return; if (++counter > 5) return;
debugger; debugger;
return counter; return counter;
} };
function listener(event, exec_state, event_data, data) { function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return; if (event != Debug.DebugEvent.Break) return;
try { try {
var script = Debug.findScript(f);
var original = 'debugger;'; var original = 'debugger;';
var patch = 'debugger;\n'; var patch = 'debugger;\n';
var position = script.source.indexOf(original); %LiveEditPatchScript(f, Debug.scriptSource(f).replace(original, patch));
Debug.LiveEdit.TestApi.ApplySingleChunkPatch(
script, position, original.length, patch, []);
} catch (e) { } catch (e) {
exception = e; exception = e;
} }
......
...@@ -25,22 +25,20 @@ ...@@ -25,22 +25,20 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax
Debug = debug.Debug; Debug = debug.Debug;
Debug.setListener(listener); Debug.setListener(listener);
SlimFunction = eval( SlimFunction = eval(
"(function() {\n " + '(function f() {\n ' +
" return 'Cat';\n" + ' return \'Cat\';\n' +
"})\n" '})\n');
);
var script = Debug.findScript(SlimFunction); var script = Debug.findScript(SlimFunction);
Debug.setScriptBreakPointById(script.id, 1, 0); Debug.setScriptBreakPointById(script.id, 1, 0);
var orig_animal = "'Cat'"; var orig_animal = "'Cat'";
var patch_pos = script.source.indexOf(orig_animal);
var new_animal_patch = "'Capybara'"; var new_animal_patch = "'Capybara'";
debugger_handler = (function() { debugger_handler = (function() {
...@@ -50,14 +48,8 @@ debugger_handler = (function() { ...@@ -50,14 +48,8 @@ debugger_handler = (function() {
return; return;
} }
already_called = true; already_called = true;
%LiveEditPatchScript(
var change_log = new Array(); SlimFunction, script.source.replace(orig_animal, new_animal_patch));
try {
Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos,
orig_animal.length, new_animal_patch, change_log);
} finally {
print("Change log: " + JSON.stringify(change_log) + "\n");
}
}; };
})(); })();
......
...@@ -2,9 +2,9 @@ ...@@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// Flags: --allow-natives-syntax
Debug = debug.Debug Debug = debug.Debug
function BestEditor() { function BestEditor() {
return 'Emacs'; return 'Emacs';
} }
...@@ -39,11 +39,8 @@ function listener(event, exec_state, event_data, data) { ...@@ -39,11 +39,8 @@ function listener(event, exec_state, event_data, data) {
}; };
function Replace(fun, original, patch) { function Replace(fun, original, patch) {
var script = Debug.findScript(fun);
if (fun.toString().indexOf(original) < 0) return; if (fun.toString().indexOf(original) < 0) return;
var patch_pos = script.source.indexOf(original); %LiveEditPatchScript(fun, Debug.scriptSource(fun).replace(original, patch));
var change_log = [];
Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos, original.length, patch, change_log);
} }
Debug.setListener(listener); Debug.setListener(listener);
...@@ -56,7 +53,7 @@ Debug.setListener(null); ...@@ -56,7 +53,7 @@ Debug.setListener(null);
assertNull(exception); assertNull(exception);
assertEquals(["Emacs", "Eclipse", "Vim"], results); assertEquals(["Emacs", "Eclipse", "Vim"], results);
print(JSON.stringify(log, 1)); // TODO(kozyatinskiy): uncomment lines with new liveedit implementation.
assertEquals([ assertEquals([
"debugger;", "debugger;",
"results.push(BestEditor());", "results.push(BestEditor());",
...@@ -65,12 +62,12 @@ assertEquals([ ...@@ -65,12 +62,12 @@ assertEquals([
"results.push(BestEditor());", "results.push(BestEditor());",
"results.push(BestEditor());", "results.push(BestEditor());",
" return 'Emacs';", " return 'Emacs';",
" return 'Eclipse';", // " return 'Eclipse';",
" return 'Eclipse';", " return 'Eclipse';",
"results.push(BestEditor());", "results.push(BestEditor());",
"results.push(BestEditor());", "results.push(BestEditor());",
" return 'Eclipse';", " return 'Eclipse';",
" return 'Vim';", // " return 'Vim';",
" return 'Vim';", " return 'Vim';",
"results.push(BestEditor());", "results.push(BestEditor());",
"Debug.setListener(null);" "Debug.setListener(null);"
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// Test that live-editing a frame that uses new.target fails. // Test that live-editing a frame that uses new.target fails.
// Flags: --allow-natives-syntax
Debug = debug.Debug Debug = debug.Debug
var calls = 0; var calls = 0;
...@@ -43,16 +43,11 @@ function ExecuteInDebugContext(f) { ...@@ -43,16 +43,11 @@ function ExecuteInDebugContext(f) {
function Replace(fun, original, patch) { function Replace(fun, original, patch) {
ExecuteInDebugContext(function() { ExecuteInDebugContext(function() {
var change_log = [];
try { try {
var script = Debug.findScript(fun); %LiveEditPatchScript(fun, Debug.scriptSource(fun).replace(original, patch));
var patch_pos = script.source.indexOf(original);
Debug.LiveEdit.TestApi.ApplySingleChunkPatch(
script, patch_pos, original.length, patch, change_log);
} catch (e) { } catch (e) {
assertEquals("BLOCKED_NO_NEW_TARGET_ON_RESTART", // TODO(kozyatinskiy): message should be BLOCKED_BY_NEW_TARGET_IN_RESTART_FRAME.
change_log[0].functions_on_stack[0].replace_problem); assertEquals(e, 'LiveEdit failed: BLOCKED_BY_FUNCTION_BELOW_NON_DROPPABLE_FRAME');
assertInstanceof(e, Debug.LiveEdit.Failure);
exceptions++; exceptions++;
} }
}); });
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// Flags: --allow-natives-syntax
// Test that live-editing a frame to introduce new.target fails. // Test that live-editing a frame to introduce new.target fails.
Debug = debug.Debug Debug = debug.Debug
...@@ -40,16 +40,11 @@ function ExecuteInDebugContext(f) { ...@@ -40,16 +40,11 @@ function ExecuteInDebugContext(f) {
function Replace(fun, original, patch) { function Replace(fun, original, patch) {
ExecuteInDebugContext(function() { ExecuteInDebugContext(function() {
var change_log = [];
try { try {
var script = Debug.findScript(fun); %LiveEditPatchScript(fun, Debug.scriptSource(fun).replace(original, patch));
var patch_pos = script.source.indexOf(original);
Debug.LiveEdit.TestApi.ApplySingleChunkPatch(
script, patch_pos, original.length, patch, change_log);
} catch (e) { } catch (e) {
assertEquals("BLOCKED_NO_NEW_TARGET_ON_RESTART", // TODO(kozyatinskiy): message should be BLOCKED_BY_NEW_TARGET_IN_RESTART_FRAME.
change_log[0].functions_on_stack[0].replace_problem); assertEquals(e, 'LiveEdit failed: BLOCKED_BY_FUNCTION_BELOW_NON_DROPPABLE_FRAME');
assertInstanceof(e, Debug.LiveEdit.Failure);
exceptions++; exceptions++;
} }
}); });
......
...@@ -2,10 +2,10 @@ ...@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// Test that live-editing a frame above one that uses new.target succeeds. // Test that live-editing a frame above one that uses new.target succeeds.
// Flags: --allow-natives-syntax
Debug = debug.Debug Debug = debug.Debug;
var wrapper_calls = 0; var wrapper_calls = 0;
var construct_calls = 0; var construct_calls = 0;
var exceptions = 0; var exceptions = 0;
...@@ -47,10 +47,7 @@ function Replace(fun, original, patch) { ...@@ -47,10 +47,7 @@ function Replace(fun, original, patch) {
ExecuteInDebugContext(function() { ExecuteInDebugContext(function() {
var change_log = []; var change_log = [];
try { try {
var script = Debug.findScript(fun); %LiveEditPatchScript(fun, Debug.scriptSource(fun).replace(original, patch));
var patch_pos = script.source.indexOf(original);
Debug.LiveEdit.TestApi.ApplySingleChunkPatch(
script, patch_pos, original.length, patch, change_log);
} catch (e) { } catch (e) {
exceptions++; exceptions++;
} }
......
...@@ -2,9 +2,8 @@ ...@@ -2,9 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// Flags: --allow-natives-syntax
var Debug = debug.Debug; var Debug = debug.Debug;
var LiveEdit = Debug.LiveEdit;
unique_id = 0; unique_id = 0;
...@@ -62,15 +61,8 @@ function ExecuteInDebugContext(f) { ...@@ -62,15 +61,8 @@ function ExecuteInDebugContext(f) {
function patch(fun, from, to) { function patch(fun, from, to) {
function debug() { function debug() {
var log = new Array();
var script = Debug.findScript(fun); var script = Debug.findScript(fun);
var pos = script.source.indexOf(from); %LiveEditPatchScript(fun, script.source.replace(from, to));
try {
LiveEdit.TestApi.ApplySingleChunkPatch(script, pos, from.length, to,
log);
} finally {
print("Change log: " + JSON.stringify(log) + "\n");
}
} }
ExecuteInDebugContext(debug); ExecuteInDebugContext(debug);
} }
...@@ -84,8 +76,9 @@ function patch(fun, from, to) { ...@@ -84,8 +76,9 @@ function patch(fun, from, to) {
function attempt_gen_patch() { function attempt_gen_patch() {
assertFalse(gen_patch_attempted); assertFalse(gen_patch_attempted);
gen_patch_attempted = true; gen_patch_attempted = true;
assertThrows(function() { patch(generator, "'Cat'", "'Capybara'") }, assertThrowsEquals(function() {
LiveEdit.Failure); patch(generator, '\'Cat\'', '\'Capybara\'')
}, 'LiveEdit failed: BLOCKED_BY_FUNCTION_BELOW_NON_DROPPABLE_FRAME');
}; };
var iter = generator(attempt_gen_patch); var iter = generator(attempt_gen_patch);
assertIteratorResult(undefined, false, iter.next()); assertIteratorResult(undefined, false, iter.next());
...@@ -104,8 +97,10 @@ function patch(fun, from, to) { ...@@ -104,8 +97,10 @@ function patch(fun, from, to) {
// Patching will fail however when a live iterator is suspended. // Patching will fail however when a live iterator is suspended.
iter = generator(function(){}); iter = generator(function(){});
assertIteratorResult(undefined, false, iter.next()); assertIteratorResult(undefined, false, iter.next());
assertThrows(function() { patch(generator, "'Capybara'", "'Tapir'") }, // TODO(kozyatinskiy): message should be BLOCKED_BY_RUNNING_GENERATOR.
LiveEdit.Failure); assertThrowsEquals(function() {
patch(generator, '\'Capybara\'', '\'Tapir\'')
}, 'LiveEdit failed: BLOCKED_BY_FUNCTION_BELOW_NON_DROPPABLE_FRAME');
assertIteratorResult("Capybara", true, iter.next()); assertIteratorResult("Capybara", true, iter.next());
// Try to patch functions with activations inside and outside generator // Try to patch functions with activations inside and outside generator
...@@ -123,8 +118,9 @@ function patch(fun, from, to) { ...@@ -123,8 +118,9 @@ function patch(fun, from, to) {
} }
fun_patch_attempted = true; fun_patch_attempted = true;
// Patching outside a generator activation must fail. // Patching outside a generator activation must fail.
assertThrows(function() { patch(fun_outside, "'Cat'", "'Cobra'") }, assertThrowsEquals(function() {
LiveEdit.Failure); patch(fun_outside, '\'Cat\'', '\'Cobra\'')
}, 'LiveEdit failed: BLOCKED_BY_FUNCTION_BELOW_NON_DROPPABLE_FRAME');
// Patching inside a generator activation may succeed. // Patching inside a generator activation may succeed.
patch(fun_inside, "'Cat'", "'Koala'"); patch(fun_inside, "'Cat'", "'Koala'");
} }
......
...@@ -2,8 +2,9 @@ ...@@ -2,8 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// Flags: --allow-natives-syntax
var Debug = debug.Debug; var Debug = debug.Debug;
var LiveEdit = Debug.LiveEdit;
unique_id = 0; unique_id = 0;
...@@ -69,16 +70,8 @@ function ExecuteInDebugContext(f) { ...@@ -69,16 +70,8 @@ function ExecuteInDebugContext(f) {
function patch(fun, from, to) { function patch(fun, from, to) {
function debug() { function debug() {
var log = new Array();
var script = Debug.findScript(fun); var script = Debug.findScript(fun);
var pos = script.source.indexOf(from); %LiveEditPatchScript(fun, script.source.replace(from, to));
print(`pos ${pos}`);
try {
LiveEdit.TestApi.ApplySingleChunkPatch(script, pos, from.length, to,
log);
} finally {
print("Change log: " + JSON.stringify(log) + "\n");
}
} }
ExecuteInDebugContext(debug); ExecuteInDebugContext(debug);
} }
...@@ -92,8 +85,9 @@ function patch(fun, from, to) { ...@@ -92,8 +85,9 @@ function patch(fun, from, to) {
function attempt_patch() { function attempt_patch() {
assertFalse(patch_attempted); assertFalse(patch_attempted);
patch_attempted = true; patch_attempted = true;
assertThrows(function() { patch(asyncfn, "'Cat'", "'Capybara'") }, assertThrowsEquals(function() {
LiveEdit.Failure); patch(asyncfn, '\'Cat\'', '\'Capybara\'')
}, 'LiveEdit failed: BLOCKED_BY_FUNCTION_BELOW_NON_DROPPABLE_FRAME');
}; };
var promise = asyncfn(attempt_patch); var promise = asyncfn(attempt_patch);
// Patch should not succeed because there is a live async function activation // Patch should not succeed because there is a live async function activation
...@@ -112,15 +106,17 @@ function patch(fun, from, to) { ...@@ -112,15 +106,17 @@ function patch(fun, from, to) {
// Patching will fail however when an async function is suspended. // Patching will fail however when an async function is suspended.
var resolve; var resolve;
promise = asyncfn(function(){return new Promise(function(r){resolve = r})}); promise = asyncfn(function(){return new Promise(function(r){resolve = r})});
assertThrows(function() { patch(asyncfn, "'Capybara'", "'Tapir'") }, // TODO(kozyatinskiy): message should be BLOCKED_BY_RUNNING_GENERATOR.
LiveEdit.Failure); assertThrowsEquals(function() {
patch(asyncfn, '\'Capybara\'', '\'Tapir\'')
}, 'LiveEdit failed: BLOCKED_BY_FUNCTION_BELOW_NON_DROPPABLE_FRAME');
resolve(); resolve();
assertPromiseValue("Capybara", promise); assertPromiseValue("Capybara", promise);
// Try to patch functions with activations inside and outside async // Try to patch functions with activations inside and outside async
// function activations. We should succeed in the former case, but not in the // function activations. We should succeed in the former case, but not in the
// latter. // latter.
var fun_outside = MakeFunction(); var fun_outside = eval('((callback) => { callback(); return \'Cat\';})');
var fun_inside = MakeFunction(); var fun_inside = MakeFunction();
var fun_patch_attempted = false; var fun_patch_attempted = false;
var fun_patch_restarted = false; var fun_patch_restarted = false;
...@@ -132,15 +128,18 @@ function patch(fun, from, to) { ...@@ -132,15 +128,18 @@ function patch(fun, from, to) {
} }
fun_patch_attempted = true; fun_patch_attempted = true;
// Patching outside an async function activation must fail. // Patching outside an async function activation must fail.
assertThrows(function() { patch(fun_outside, "'Cat'", "'Cobra'") }, assertThrowsEquals(function() {
LiveEdit.Failure); patch(fun_outside, '\'Cat\'', '\'Cobra\'')
}, 'LiveEdit failed: BLOCKED_BY_FUNCTION_BELOW_NON_DROPPABLE_FRAME');
// Patching inside an async function activation may succeed. // Patching inside an async function activation may succeed.
patch(fun_inside, "'Cat'", "'Koala'"); patch(fun_inside, "'Cat'", "'Koala'");
} }
promise = asyncfn(function() { return fun_inside(attempt_fun_patches) }); result = fun_outside(() => asyncfn(function() {
return fun_inside(attempt_fun_patches);
}));
assertEquals('Cat', assertEquals('Cat',
fun_outside(function () { fun_outside(function () {
assertPromiseValue('Capybara', promise); assertEquals(result, 'Cat');
assertTrue(fun_patch_restarted); assertTrue(fun_patch_restarted);
assertTrue(fun_inside.toString().includes("'Koala'")); assertTrue(fun_inside.toString().includes("'Koala'"));
})); }));
......
...@@ -311,11 +311,6 @@ class DebugWrapper { ...@@ -311,11 +311,6 @@ class DebugWrapper {
return scopes; return scopes;
} }
get LiveEdit() {
const debugContext = %GetDebugContext();
return debugContext.Debug.LiveEdit;
}
// --- Internal methods. ----------------------------------------------------- // --- Internal methods. -----------------------------------------------------
getNextMessageId() { getNextMessageId() {
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// Flags: --no-always-opt
let {session, contextGroup, Protocol} = let {session, contextGroup, Protocol} =
InspectorTest.start('Tests Debugger.setScriptSource'); InspectorTest.start('Tests Debugger.setScriptSource');
......
...@@ -11,9 +11,13 @@ Running test: testIncorrectScriptId ...@@ -11,9 +11,13 @@ Running test: testIncorrectScriptId
Running test: testSourceWithSyntaxError Running test: testSourceWithSyntaxError
{ {
error : {
code : -32000
message : Uncaught [object Object]
}
id : <messageId> id : <messageId>
result : {
exceptionDetails : {
columnNumber : 0
exceptionId : <exceptionId>
lineNumber : 0
text : Invalid or unexpected token
}
}
} }
...@@ -10,9 +10,9 @@ TestExpression(2,4) === 8 ...@@ -10,9 +10,9 @@ TestExpression(2,4) === 8
Update current script source 'a * b' -> 'a # b'.. Update current script source 'a * b' -> 'a # b'..
{ {
exceptionDetails : { exceptionDetails : {
columnNumber : 13 columnNumber : 0
exceptionId : <exceptionId> exceptionId : <exceptionId>
lineNumber : 1 lineNumber : 0
text : Invalid or unexpected token text : Invalid or unexpected token
} }
} }
......
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