Commit e4046706 authored by Alexey Kozyatinskiy's avatar Alexey Kozyatinskiy Committed by Commit Bot

[debug] removed most debugger js

Removed most of mirrors.js and debug.js.
Further steps:
- migrate liveedit.js to native,
- remove debugger context.

R=yangguo@chromium.org
TBR=leszeks@chromium.org

Bug: v8:5530
Cq-Include-Trybots: luci.chromium.try:linux_chromium_headless_rel;master.tryserver.blink:linux_trusty_blink_rel
Change-Id: I291ef20ef3c63a424d32e3e0c9d0962a6ca382d1
Reviewed-on: https://chromium-review.googlesource.com/1081176
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@{#53480}
parent 5cb11a17
......@@ -649,8 +649,6 @@ action("js2c") {
"src/js/prologue.js",
"src/js/array.js",
"src/js/typedarray.js",
"src/debug/mirrors.js",
"src/debug/debug.js",
"src/debug/liveedit.js",
]
......@@ -2259,7 +2257,6 @@ v8_source_set("v8_base") {
"src/runtime/runtime-dataview.cc",
"src/runtime/runtime-date.cc",
"src/runtime/runtime-debug.cc",
"src/runtime/runtime-error.cc",
"src/runtime/runtime-forin.cc",
"src/runtime/runtime-function.cc",
"src/runtime/runtime-futex.cc",
......
......@@ -55,10 +55,6 @@ Reduction JSIntrinsicLowering::Reduce(Node* node) {
return ReduceIsInstanceType(node, JS_TYPED_ARRAY_TYPE);
case Runtime::kInlineIsJSProxy:
return ReduceIsInstanceType(node, JS_PROXY_TYPE);
case Runtime::kInlineIsJSMap:
return ReduceIsInstanceType(node, JS_MAP_TYPE);
case Runtime::kInlineIsJSSet:
return ReduceIsInstanceType(node, JS_SET_TYPE);
case Runtime::kInlineIsJSWeakMap:
return ReduceIsInstanceType(node, JS_WEAK_MAP_TYPE);
case Runtime::kInlineIsJSWeakSet:
......
......@@ -158,7 +158,6 @@ bool Linkage::NeedsFrameStateInput(Runtime::FunctionId function) {
case Runtime::kAbort:
case Runtime::kAllocateInTargetSpace:
case Runtime::kCreateIterResultObject:
case Runtime::kGeneratorGetContinuation:
case Runtime::kIncBlockCounter:
case Runtime::kIsFunction:
case Runtime::kNewClosure:
......@@ -185,8 +184,6 @@ bool Linkage::NeedsFrameStateInput(Runtime::FunctionId function) {
case Runtime::kInlineGeneratorGetResumeMode:
case Runtime::kInlineCreateJSGeneratorObject:
case Runtime::kInlineIsArray:
case Runtime::kInlineIsJSMap:
case Runtime::kInlineIsJSSet:
case Runtime::kInlineIsJSWeakMap:
case Runtime::kInlineIsJSWeakSet:
case Runtime::kInlineIsJSReceiver:
......
......@@ -332,10 +332,8 @@ bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) {
V(IsArray) \
V(IsDate) \
V(IsFunction) \
V(IsJSMap) \
V(IsJSProxy) \
V(IsJSReceiver) \
V(IsJSSet) \
V(IsJSWeakMap) \
V(IsJSWeakSet) \
V(IsRegExp) \
......
......@@ -181,32 +181,5 @@ bool FrameInspector::ParameterIsShadowedByContextLocal(
return ScopeInfo::ContextSlotIndex(info, parameter_name, &mode, &init_flag,
&maybe_assigned_flag) != -1;
}
SaveContext* DebugFrameHelper::FindSavedContextForFrame(Isolate* isolate,
StandardFrame* frame) {
SaveContext* save = isolate->save_context();
while (save != nullptr && !save->IsBelowFrame(frame)) {
save = save->prev();
}
DCHECK(save != nullptr);
return save;
}
int DebugFrameHelper::FindIndexedNonNativeFrame(StackTraceFrameIterator* it,
int index) {
int count = -1;
for (; !it->done(); it->Advance()) {
std::vector<FrameSummary> frames;
it->frame()->Summarize(&frames);
for (size_t i = frames.size(); i != 0; i--) {
// Omit functions from native and extension scripts.
if (!frames[i - 1].is_subject_to_debugging()) continue;
if (++count == index) return static_cast<int>(i) - 1;
}
}
return -1;
}
} // namespace internal
} // namespace v8
......@@ -71,27 +71,6 @@ class FrameInspector {
DISALLOW_COPY_AND_ASSIGN(FrameInspector);
};
class DebugFrameHelper : public AllStatic {
public:
static SaveContext* FindSavedContextForFrame(Isolate* isolate,
StandardFrame* frame);
// Advances the iterator to the frame that matches the index and returns the
// inlined frame index, or -1 if not found. Skips native JS functions.
static int FindIndexedNonNativeFrame(StackTraceFrameIterator* it, int index);
// Helper functions for wrapping and unwrapping stack frame ids.
static Smi* WrapFrameId(StackFrame::Id id) {
DCHECK(IsAligned(OffsetFrom(id), static_cast<intptr_t>(4)));
return Smi::FromInt(id >> 2);
}
static StackFrame::Id UnwrapFrameId(int wrapped) {
return static_cast<StackFrame::Id>(wrapped << 2);
}
};
} // namespace internal
} // namespace v8
......
......@@ -147,10 +147,9 @@ class DebugDelegate {
// |inspector_break_points_hit| contains id of breakpoints installed with
// debug::Script::SetBreakpoint API.
virtual void BreakProgramRequested(
v8::Local<v8::Context> paused_context, v8::Local<v8::Object> exec_state,
v8::Local<v8::Context> paused_context,
const std::vector<debug::BreakpointId>& inspector_break_points_hit) {}
virtual void ExceptionThrown(v8::Local<v8::Context> paused_context,
v8::Local<v8::Object> exec_state,
v8::Local<v8::Value> exception,
v8::Local<v8::Value> promise, bool is_uncaught) {
}
......
......@@ -1704,44 +1704,6 @@ Handle<FixedArray> Debug::GetLoadedScripts() {
return FixedArray::ShrinkOrEmpty(results, length);
}
MaybeHandle<Object> Debug::MakeExecutionState() {
// Create the execution state object.
Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()) };
return CallFunction("MakeExecutionState", arraysize(argv), argv);
}
MaybeHandle<Object> Debug::MakeExceptionEvent(Handle<Object> exception,
bool uncaught,
Handle<Object> promise) {
// Create the new exception event object.
Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()),
exception,
isolate_->factory()->ToBoolean(uncaught),
promise };
return CallFunction("MakeExceptionEvent", arraysize(argv), argv);
}
MaybeHandle<Object> Debug::MakeCompileEvent(Handle<Script> script,
v8::DebugEvent type) {
// Create the compile event object.
Handle<Object> script_wrapper = Script::GetWrapper(script);
Handle<Object> argv[] = { script_wrapper,
isolate_->factory()->NewNumberFromInt(type) };
return CallFunction("MakeCompileEvent", arraysize(argv), argv);
}
MaybeHandle<Object> Debug::MakeAsyncTaskEvent(
v8::debug::DebugAsyncActionType type, int id) {
// Create the async task event object.
Handle<Object> argv[] = {Handle<Smi>(Smi::FromInt(type), isolate_),
Handle<Smi>(Smi::FromInt(id), isolate_)};
return CallFunction("MakeAsyncTaskEvent", arraysize(argv), argv);
}
void Debug::OnThrow(Handle<Object> exception) {
if (in_debug_scope() || ignore_events()) return;
// Temporarily clear any scheduled_exception to allow evaluating
......@@ -1782,7 +1744,7 @@ void Debug::OnAsyncFunctionStateChanged(Handle<JSPromise> promise,
namespace {
v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) {
Handle<Context> context = isolate->debug()->debugger_entry()->GetContext();
Handle<Context> context = handle(isolate->context());
// Isolate::context() may have been nullptr when "script collected" event
// occurred.
if (context.is_null()) return v8::Local<v8::Context>();
......@@ -1813,9 +1775,7 @@ bool Debug::IsFrameBlackboxed(JavaScriptFrame* frame) {
}
void Debug::OnException(Handle<Object> exception, Handle<Object> promise) {
// We cannot generate debug events when JS execution is disallowed.
// TODO(5530): Reenable debug events within DisallowJSScopes once relevant
// code (MakeExceptionEvent and ProcessDebugEvent) have been moved to C++.
// TODO(kozyatinskiy): regress-662674.js test fails on arm without this.
if (!AllowJavascriptExecution::IsAllowed(isolate_)) return;
Isolate::CatchType catch_type = isolate_->PredictExceptionCatcher();
......@@ -1860,14 +1820,8 @@ void Debug::OnException(Handle<Object> exception, Handle<Object> promise) {
PostponeInterruptsScope postpone(isolate_);
DisableBreak no_recursive_break(this);
// Create the execution state.
Handle<Object> exec_state;
// Bail out and don't call debugger if exception.
if (!MakeExecutionState().ToHandle(&exec_state)) return;
debug_delegate_->ExceptionThrown(
GetDebugEventContext(isolate_),
v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)),
v8::Utils::ToLocal(exception), v8::Utils::ToLocal(promise), uncaught);
}
......@@ -1887,11 +1841,6 @@ void Debug::OnDebugBreak(Handle<FixedArray> break_points_hit) {
PostponeInterruptsScope no_interrupts(isolate_);
DisableBreak no_recursive_break(this);
// Create the execution state.
Handle<Object> exec_state;
// Bail out and don't call debugger if exception.
if (!MakeExecutionState().ToHandle(&exec_state)) return;
std::vector<int> inspector_break_points_hit;
int inspector_break_points_count = 0;
// This array contains breakpoints installed using JS debug API.
......@@ -1903,21 +1852,9 @@ void Debug::OnDebugBreak(Handle<FixedArray> break_points_hit) {
debug_delegate_->BreakProgramRequested(
GetDebugEventContext(isolate_),
v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)),
inspector_break_points_hit);
}
void Debug::OnCompileError(Handle<Script> script) {
ProcessCompileEvent(v8::CompileError, script);
}
// Handle debugger actions when a new script is compiled.
void Debug::OnAfterCompile(Handle<Script> script) {
ProcessCompileEvent(v8::AfterCompile, script);
}
void Debug::RunPromiseHook(PromiseHookType hook_type, Handle<JSPromise> promise,
Handle<Object> parent) {
if (hook_type == PromiseHookType::kResolve) return;
......@@ -2036,7 +1973,11 @@ bool Debug::CanBreakAtEntry(Handle<SharedFunctionInfo> shared) {
bool Debug::SetScriptSource(Handle<Script> script, Handle<String> source,
bool preview, bool* stack_changed) {
SaveContext save(isolate_);
DebugScope debug_scope(this);
if (debug_scope.failed()) return false;
isolate_->set_context(*debug_context());
set_live_edit_enabled(true);
Handle<Object> script_wrapper = Script::GetWrapper(script);
Handle<Object> argv[] = {script_wrapper, source,
......@@ -2058,7 +1999,15 @@ bool Debug::SetScriptSource(Handle<Script> script, Handle<String> source,
return true;
}
void Debug::ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script) {
void Debug::OnCompileError(Handle<Script> script) {
ProcessCompileEvent(true, script);
}
void Debug::OnAfterCompile(Handle<Script> script) {
ProcessCompileEvent(false, script);
}
void Debug::ProcessCompileEvent(bool has_compile_error, Handle<Script> script) {
// Attach the correct debug id to the script. The debug id is used by the
// inspector to filter scripts by native context.
script->set_context_data(isolate_->native_context()->debug_context_id());
......@@ -2075,8 +2024,7 @@ void Debug::ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script) {
DisableBreak no_recursive_break(this);
AllowJavascriptExecution allow_script(isolate_);
debug_delegate_->ScriptCompiled(ToApiHandle<debug::Script>(script),
live_edit_enabled(),
event != v8::AfterCompile);
live_edit_enabled(), has_compile_error);
}
......@@ -2149,26 +2097,6 @@ void Debug::UpdateHookOnFunctionCall() {
thread_local_.break_on_next_function_call_;
}
MaybeHandle<Object> Debug::Call(Handle<Object> fun, Handle<Object> data) {
AllowJavascriptExecutionDebugOnly allow_script(isolate_);
DebugScope debug_scope(this);
if (debug_scope.failed()) return isolate_->factory()->undefined_value();
// Create the execution state.
Handle<Object> exec_state;
if (!MakeExecutionState().ToHandle(&exec_state)) {
return isolate_->factory()->undefined_value();
}
Handle<Object> argv[] = { exec_state, data };
return Execution::Call(
isolate_,
fun,
Handle<Object>(debug_context()->global_proxy(), isolate_),
arraysize(argv),
argv);
}
void Debug::HandleDebugBreak(IgnoreBreakMode ignore_break_mode) {
// Initialize LiveEdit.
LiveEdit::InitializeThreadLocal(this);
......@@ -2254,7 +2182,6 @@ void Debug::PrintBreakLocation() {
DebugScope::DebugScope(Debug* debug)
: debug_(debug),
prev_(debug->debugger_entry()),
save_(debug_->isolate_),
no_termination_exceptons_(debug_->isolate_,
StackGuard::TERMINATE_EXECUTION) {
// Link recursive debugger entry.
......@@ -2277,7 +2204,6 @@ DebugScope::DebugScope(Debug* debug)
// Make sure that debugger is loaded and enter the debugger context.
// The previous context is kept in save_.
failed_ = !debug_->is_loaded();
if (!failed_) isolate()->set_context(*debug->debug_context());
}
......@@ -2461,116 +2387,5 @@ bool Debug::PerformSideEffectCheckForObject(Handle<Object> object) {
isolate_->TerminateExecution();
return false;
}
void LegacyDebugDelegate::AsyncEventOccurred(
v8::debug::DebugAsyncActionType type, int id, bool is_blackboxed) {
DebugScope debug_scope(isolate_->debug());
if (debug_scope.failed()) return;
HandleScope scope(isolate_);
Handle<Object> event_data;
if (isolate_->debug()->MakeAsyncTaskEvent(type, id).ToHandle(&event_data)) {
ProcessDebugEvent(v8::AsyncTaskEvent, Handle<JSObject>::cast(event_data));
}
}
void LegacyDebugDelegate::ScriptCompiled(v8::Local<v8::debug::Script> script,
bool is_live_edited,
bool is_compile_error) {
Handle<Object> event_data;
v8::DebugEvent event = is_compile_error ? v8::CompileError : v8::AfterCompile;
if (isolate_->debug()
->MakeCompileEvent(v8::Utils::OpenHandle(*script), event)
.ToHandle(&event_data)) {
ProcessDebugEvent(event, Handle<JSObject>::cast(event_data));
}
}
void LegacyDebugDelegate::BreakProgramRequested(
v8::Local<v8::Context> paused_context, v8::Local<v8::Object> exec_state,
const std::vector<debug::BreakpointId>&) {
ProcessDebugEvent(v8::Break, isolate_->factory()->NewJSObjectWithNullProto(),
Handle<JSObject>::cast(v8::Utils::OpenHandle(*exec_state)));
}
void LegacyDebugDelegate::ExceptionThrown(v8::Local<v8::Context> paused_context,
v8::Local<v8::Object> exec_state,
v8::Local<v8::Value> exception,
v8::Local<v8::Value> promise,
bool is_uncaught) {
Handle<Object> event_data;
if (isolate_->debug()
->MakeExceptionEvent(v8::Utils::OpenHandle(*exception), is_uncaught,
v8::Utils::OpenHandle(*promise))
.ToHandle(&event_data)) {
ProcessDebugEvent(
v8::Exception, Handle<JSObject>::cast(event_data),
Handle<JSObject>::cast(v8::Utils::OpenHandle(*exec_state)));
}
}
void LegacyDebugDelegate::ProcessDebugEvent(v8::DebugEvent event,
Handle<JSObject> event_data) {
Handle<Object> exec_state;
if (isolate_->debug()->MakeExecutionState().ToHandle(&exec_state)) {
ProcessDebugEvent(event, event_data, Handle<JSObject>::cast(exec_state));
}
}
NativeDebugDelegate::NativeDebugDelegate(Isolate* isolate,
v8::Debug::EventCallback callback,
Handle<Object> data)
: LegacyDebugDelegate(isolate), callback_(callback) {
data_ = isolate->global_handles()->Create(*data);
}
NativeDebugDelegate::~NativeDebugDelegate() {
GlobalHandles::Destroy(data_.location());
}
NativeDebugDelegate::EventDetails::EventDetails(DebugEvent event,
Handle<JSObject> exec_state,
Handle<JSObject> event_data,
Handle<Object> callback_data)
: event_(event),
exec_state_(exec_state),
event_data_(event_data),
callback_data_(callback_data) {}
DebugEvent NativeDebugDelegate::EventDetails::GetEvent() const {
return event_;
}
v8::Local<v8::Object> NativeDebugDelegate::EventDetails::GetExecutionState()
const {
return v8::Utils::ToLocal(exec_state_);
}
v8::Local<v8::Object> NativeDebugDelegate::EventDetails::GetEventData() const {
return v8::Utils::ToLocal(event_data_);
}
v8::Local<v8::Context> NativeDebugDelegate::EventDetails::GetEventContext()
const {
return GetDebugEventContext(exec_state_->GetIsolate());
}
v8::Local<v8::Value> NativeDebugDelegate::EventDetails::GetCallbackData()
const {
return v8::Utils::ToLocal(callback_data_);
}
v8::Isolate* NativeDebugDelegate::EventDetails::GetIsolate() const {
return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
}
void NativeDebugDelegate::ProcessDebugEvent(v8::DebugEvent event,
Handle<JSObject> event_data,
Handle<JSObject> exec_state) {
EventDetails event_details(event, exec_state, event_data, data_);
Isolate* isolate = isolate_;
callback_(event_details);
CHECK(!isolate->has_scheduled_exception());
}
} // namespace internal
} // namespace v8
......@@ -31,7 +31,6 @@ namespace internal {
// Forward declarations.
class DebugScope;
// Step actions. NOTE: These values are in macros.py as well.
enum StepAction : int8_t {
StepNone = -1, // Stepping not prepared.
......@@ -228,8 +227,6 @@ class Debug {
void OnAsyncFunctionStateChanged(Handle<JSPromise> promise,
debug::DebugAsyncActionType);
V8_WARN_UNUSED_RESULT MaybeHandle<Object> Call(Handle<Object> fun,
Handle<Object> data);
Handle<Context> GetDebugContext();
void HandleDebugBreak(IgnoreBreakMode ignore_break_mode);
......@@ -267,7 +264,6 @@ class Debug {
void PrepareStepInSuspendedGenerator();
void PrepareStepOnThrow();
void ClearStepping();
void ClearStepOut();
void SetBreakOnNextFunctionCall();
void ClearBreakOnNextFunctionCall();
......@@ -334,10 +330,6 @@ class Debug {
void FreeThreadResources() { }
void Iterate(RootVisitor* v);
bool CheckExecutionState(int id) {
return CheckExecutionState() && break_id() == id;
}
bool CheckExecutionState() {
return is_active() && !debug_context().is_null() && break_id() != 0;
}
......@@ -455,17 +447,7 @@ class Debug {
void OnException(Handle<Object> exception, Handle<Object> promise);
// Constructors for debug event objects.
V8_WARN_UNUSED_RESULT MaybeHandle<Object> MakeExecutionState();
V8_WARN_UNUSED_RESULT MaybeHandle<Object> MakeExceptionEvent(
Handle<Object> exception, bool uncaught, Handle<Object> promise);
V8_WARN_UNUSED_RESULT MaybeHandle<Object> MakeCompileEvent(
Handle<Script> script, v8::DebugEvent type);
V8_WARN_UNUSED_RESULT MaybeHandle<Object> MakeAsyncTaskEvent(
v8::debug::DebugAsyncActionType type, int id);
void ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script);
void ProcessDebugEvent(v8::DebugEvent event, Handle<JSObject> event_data);
void ProcessCompileEvent(bool has_compile_error, Handle<Script> script);
// Find the closest source position for a break point for a given position.
int FindBreakablePosition(Handle<DebugInfo> debug_info, int source_position);
......@@ -496,7 +478,6 @@ class Debug {
bool catch_exceptions = true);
inline void AssertDebugContext() {
DCHECK(isolate_->context() == *debug_context());
DCHECK(in_debug_scope());
}
......@@ -615,7 +596,6 @@ class Debug {
friend class LiveEdit;
friend class SuppressDebug;
friend class NoSideEffectScope;
friend class LegacyDebugDelegate;
friend Handle<FixedArray> GetDebuggedFunctions(); // In test-debug.cc
friend void CheckDebuggerUnloaded(); // In test-debug.cc
......@@ -623,70 +603,6 @@ class Debug {
DISALLOW_COPY_AND_ASSIGN(Debug);
};
class LegacyDebugDelegate : public v8::debug::DebugDelegate {
public:
explicit LegacyDebugDelegate(Isolate* isolate) : isolate_(isolate) {}
void AsyncEventOccurred(v8::debug::DebugAsyncActionType type, int id,
bool is_blackboxed) override;
void ScriptCompiled(v8::Local<v8::debug::Script> script, bool is_live_edited,
bool has_compile_error) override;
void BreakProgramRequested(v8::Local<v8::Context> paused_context,
v8::Local<v8::Object> exec_state,
const std::vector<debug::BreakpointId>&) override;
void ExceptionThrown(v8::Local<v8::Context> paused_context,
v8::Local<v8::Object> exec_state,
v8::Local<v8::Value> exception,
v8::Local<v8::Value> promise, bool is_uncaught) override;
bool IsFunctionBlackboxed(v8::Local<v8::debug::Script> script,
const v8::debug::Location& start,
const v8::debug::Location& end) override {
return false;
}
protected:
Isolate* isolate_;
private:
void ProcessDebugEvent(v8::DebugEvent event, Handle<JSObject> event_data);
virtual void ProcessDebugEvent(v8::DebugEvent event,
Handle<JSObject> event_data,
Handle<JSObject> exec_state) = 0;
};
class NativeDebugDelegate : public LegacyDebugDelegate {
public:
NativeDebugDelegate(Isolate* isolate, v8::Debug::EventCallback callback,
Handle<Object> data);
virtual ~NativeDebugDelegate();
private:
// Details of the debug event delivered to the debug event listener.
class EventDetails : public v8::Debug::EventDetails {
public:
EventDetails(DebugEvent event, Handle<JSObject> exec_state,
Handle<JSObject> event_data, Handle<Object> callback_data);
virtual DebugEvent GetEvent() const;
virtual v8::Local<v8::Object> GetExecutionState() const;
virtual v8::Local<v8::Object> GetEventData() const;
virtual v8::Local<v8::Context> GetEventContext() const;
virtual v8::Local<v8::Value> GetCallbackData() const;
virtual v8::Isolate* GetIsolate() const;
private:
DebugEvent event_; // Debug event causing the break.
Handle<JSObject> exec_state_; // Current execution state.
Handle<JSObject> event_data_; // Data associated with the event.
Handle<Object> callback_data_; // User data passed with the callback
// when it was registered.
};
void ProcessDebugEvent(v8::DebugEvent event, Handle<JSObject> event_data,
Handle<JSObject> exec_state) override;
v8::Debug::EventCallback callback_;
Handle<Object> data_;
};
// This scope is used to load and enter the debug context and create a new
// break state. Leaving the scope will restore the previous state.
// On failure to load, FailedToEnter returns true.
......@@ -698,9 +614,6 @@ class DebugScope BASE_EMBEDDED {
// Check whether loading was successful.
inline bool failed() { return failed_; }
// Get the active context from before entering the debugger.
inline Handle<Context> GetContext() { return save_.context(); }
private:
Isolate* isolate() { return debug_->isolate_; }
......@@ -709,7 +622,6 @@ class DebugScope BASE_EMBEDDED {
StackFrame::Id break_frame_id_; // Previous break frame id.
int break_id_; // Previous break id.
bool failed_; // Did the debug context fail to load?
SaveContext save_; // Saves previous context.
PostponeInterruptsScope no_termination_exceptons_;
};
......
// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
(function (global, utils) {
"use strict";
// ----------------------------------------------------------------------------
// Imports
var FrameMirror = global.FrameMirror;
var GlobalArray = global.Array;
var GlobalRegExp = global.RegExp;
var IsNaN = global.isNaN;
var MakeMirror = global.MakeMirror;
var MathMin = global.Math.min;
var Mirror = global.Mirror;
var ValueMirror = global.ValueMirror;
//----------------------------------------------------------------------------
var Debug = {};
// Debug events which can occur in the V8 JavaScript engine. These originate
// from the API include file debug.h.
Debug.DebugEvent = { Break: 1,
Exception: 2,
AfterCompile: 3,
CompileError: 4,
AsyncTaskEvent: 5 };
// Types of exceptions that can be broken upon.
Debug.ExceptionBreak = { Caught : 0,
Uncaught: 1 };
// The different types of steps.
Debug.StepAction = { StepOut: 0,
StepNext: 1,
StepIn: 2 };
// The different types of scripts matching enum ScriptType in objects.h.
Debug.ScriptType = { Native: 0,
Extension: 1,
Normal: 2,
Wasm: 3};
// The different types of script compilations matching enum
// Script::CompilationType in objects.h.
Debug.ScriptCompilationType = { Host: 0,
Eval: 1,
JSON: 2 };
function ScriptTypeFlag(type) {
return (1 << type);
}
// Globals.
var debugger_flags = {
breakOnCaughtException: {
getValue: function() { return Debug.isBreakOnException(); },
setValue: function(value) {
if (value) {
Debug.setBreakOnException();
} else {
Debug.clearBreakOnException();
}
}
},
breakOnUncaughtException: {
getValue: function() { return Debug.isBreakOnUncaughtException(); },
setValue: function(value) {
if (value) {
Debug.setBreakOnUncaughtException();
} else {
Debug.clearBreakOnUncaughtException();
}
}
},
};
// Returns a Script object. If the parameter is a function the return value
// is the script in which the function is defined. If the parameter is a string
// the return value is the script for which the script name has that string
// value. If it is a regexp and there is a unique script whose name matches
// we return that, otherwise undefined.
Debug.findScript = function(func_or_script_name) {
if (IS_FUNCTION(func_or_script_name)) {
return %FunctionGetScript(func_or_script_name);
} else if (%IsRegExp(func_or_script_name)) {
var scripts = this.scripts();
var last_result = null;
var result_count = 0;
for (var i in scripts) {
var script = scripts[i];
if (func_or_script_name.test(script.name)) {
last_result = script;
result_count++;
}
}
// Return the unique script matching the regexp. If there are more
// than one we don't return a value since there is no good way to
// decide which one to return. Returning a "random" one, say the
// first, would introduce nondeterminism (or something close to it)
// because the order is the heap iteration order.
if (result_count == 1) {
return last_result;
} else {
return UNDEFINED;
}
} else {
return %GetScript(func_or_script_name);
}
};
// Returns the script source. If the parameter is a function the return value
// is the script source for the script in which the function is defined. If the
// parameter is a string the return value is the script for which the script
// name has that string value.
Debug.scriptSource = function(func_or_script_name) {
return this.findScript(func_or_script_name).source;
};
Debug.source = function(f) {
if (!IS_FUNCTION(f)) throw %make_type_error(kDebuggerType);
return %FunctionGetSourceCode(f);
};
Debug.sourcePosition = function(f) {
if (!IS_FUNCTION(f)) throw %make_type_error(kDebuggerType);
return %FunctionGetScriptSourcePosition(f);
};
Debug.findFunctionSourceLocation = function(func, opt_line, opt_column) {
var script = %FunctionGetScript(func);
var script_offset = %FunctionGetScriptSourcePosition(func);
return %ScriptLocationFromLine(script, opt_line, opt_column, script_offset);
};
// Returns the character position in a script based on a line number and an
// optional position within that line.
Debug.findScriptSourcePosition = function(script, opt_line, opt_column) {
var location = %ScriptLocationFromLine(script, opt_line, opt_column, 0);
return location ? location.position : null;
};
Debug.clearStepping = function() {
%ClearStepping();
};
Debug.setBreakOnException = function() {
return %ChangeBreakOnException(Debug.ExceptionBreak.Caught, true);
};
Debug.clearBreakOnException = function() {
return %ChangeBreakOnException(Debug.ExceptionBreak.Caught, false);
};
Debug.isBreakOnException = function() {
return !!%IsBreakOnException(Debug.ExceptionBreak.Caught);
};
Debug.setBreakOnUncaughtException = function() {
return %ChangeBreakOnException(Debug.ExceptionBreak.Uncaught, true);
};
Debug.clearBreakOnUncaughtException = function() {
return %ChangeBreakOnException(Debug.ExceptionBreak.Uncaught, false);
};
Debug.isBreakOnUncaughtException = function() {
return !!%IsBreakOnException(Debug.ExceptionBreak.Uncaught);
};
// Get all the scripts currently loaded. Locating all the scripts is based on
// scanning the heap.
Debug.scripts = function() {
// Collect all scripts in the heap.
return %DebugGetLoadedScripts();
};
// Get a specific script currently loaded. This is based on scanning the heap.
// TODO(clemensh): Create a runtime function for this.
function scriptById(scriptId) {
var scripts = Debug.scripts();
for (var script of scripts) {
if (script.id == scriptId) return script;
}
return UNDEFINED;
};
Debug.debuggerFlags = function() {
return debugger_flags;
};
Debug.MakeMirror = MakeMirror;
function MakeExecutionState(break_id) {
return new ExecutionState(break_id);
}
function ExecutionState(break_id) {
this.break_id = break_id;
this.selected_frame = 0;
}
ExecutionState.prototype.prepareStep = function(action) {
if (action === Debug.StepAction.StepIn ||
action === Debug.StepAction.StepOut ||
action === Debug.StepAction.StepNext) {
return %PrepareStep(this.break_id, action);
}
throw %make_type_error(kDebuggerType);
};
ExecutionState.prototype.evaluateGlobal = function(source) {
return MakeMirror(%DebugEvaluateGlobal(this.break_id, source));
};
ExecutionState.prototype.frameCount = function() {
return %GetFrameCount(this.break_id);
};
ExecutionState.prototype.frame = function(opt_index) {
// If no index supplied return the selected frame.
if (opt_index == null) opt_index = this.selected_frame;
if (opt_index < 0 || opt_index >= this.frameCount()) {
throw %make_type_error(kDebuggerFrame);
}
return new FrameMirror(this.break_id, opt_index);
};
ExecutionState.prototype.setSelectedFrame = function(index) {
var i = TO_NUMBER(index);
if (i < 0 || i >= this.frameCount()) {
throw %make_type_error(kDebuggerFrame);
}
this.selected_frame = i;
};
ExecutionState.prototype.selectedFrame = function() {
return this.selected_frame;
};
function MakeExceptionEvent(break_id, exception, uncaught, promise) {
return new ExceptionEvent(break_id, exception, uncaught, promise);
}
function ExceptionEvent(break_id, exception, uncaught, promise) {
this.exec_state_ = new ExecutionState(break_id);
this.exception_ = exception;
this.uncaught_ = uncaught;
this.promise_ = promise;
}
ExceptionEvent.prototype.eventType = function() {
return Debug.DebugEvent.Exception;
};
ExceptionEvent.prototype.exception = function() {
return this.exception_;
};
ExceptionEvent.prototype.uncaught = function() {
return this.uncaught_;
};
ExceptionEvent.prototype.promise = function() {
return this.promise_;
};
ExceptionEvent.prototype.func = function() {
return this.exec_state_.frame(0).func();
};
ExceptionEvent.prototype.sourceLine = function() {
return this.exec_state_.frame(0).sourceLine();
};
ExceptionEvent.prototype.sourceColumn = function() {
return this.exec_state_.frame(0).sourceColumn();
};
ExceptionEvent.prototype.sourceLineText = function() {
return this.exec_state_.frame(0).sourceLineText();
};
function MakeCompileEvent(script, type) {
return new CompileEvent(script, type);
}
function CompileEvent(script, type) {
this.script_ = MakeMirror(script);
this.type_ = type;
}
CompileEvent.prototype.eventType = function() {
return this.type_;
};
CompileEvent.prototype.script = function() {
return this.script_;
};
function MakeScriptObject_(script, include_source) {
var o = { id: script.id(),
name: script.name(),
lineOffset: script.lineOffset(),
columnOffset: script.columnOffset(),
lineCount: script.lineCount(),
};
if (!IS_UNDEFINED(script.data())) {
o.data = script.data();
}
if (include_source) {
o.source = script.source();
}
return o;
}
function MakeAsyncTaskEvent(type, id) {
return new AsyncTaskEvent(type, id);
}
function AsyncTaskEvent(type, id) {
this.type_ = type;
this.id_ = id;
}
AsyncTaskEvent.prototype.type = function() {
return this.type_;
}
AsyncTaskEvent.prototype.id = function() {
return this.id_;
}
// -------------------------------------------------------------------
// Exports
utils.InstallConstants(global, [
"Debug", Debug,
"CompileEvent", CompileEvent,
]);
// Functions needed by the debugger runtime.
utils.InstallConstants(utils, [
"MakeExecutionState", MakeExecutionState,
"MakeExceptionEvent", MakeExceptionEvent,
"MakeCompileEvent", MakeCompileEvent,
"MakeAsyncTaskEvent", MakeAsyncTaskEvent,
]);
})
......@@ -179,34 +179,4 @@ typedef int BreakpointId;
} // namespace debug
} // namespace v8
// TODO(yangguo): this is legacy left over from removing v8-debug.h, and still
// used in cctests. Let's get rid of these soon.
namespace v8 {
enum DebugEvent {
Break = 1,
Exception = 2,
AfterCompile = 3,
CompileError = 4,
AsyncTaskEvent = 5,
};
class Debug {
public:
class EventDetails {
public:
virtual DebugEvent GetEvent() const = 0;
virtual Local<Object> GetExecutionState() const = 0;
virtual Local<Object> GetEventData() const = 0;
virtual Local<Context> GetEventContext() const = 0;
virtual Local<Value> GetCallbackData() const = 0;
virtual Isolate* GetIsolate() const = 0;
virtual ~EventDetails() {}
};
typedef void (*EventCallback)(const EventDetails& event_details);
};
} // namespace v8
#endif // V8_DEBUG_INTERFACE_TYPES_H_
......@@ -26,7 +26,6 @@
// -------------------------------------------------------------------
// Imports
var FindScriptSourcePosition = global.Debug.findScriptSourcePosition;
var GlobalArray = global.Array;
var MathFloor = global.Math.floor;
var MathMax = global.Math.max;
......@@ -34,6 +33,11 @@
// -------------------------------------------------------------------
function FindScriptSourcePosition(script, opt_line, opt_column) {
var location = %ScriptLocationFromLine(script, opt_line, opt_column, 0);
return location ? location.position : null;
};
// Forward declaration for minifier.
var FunctionStatus;
......@@ -1052,7 +1056,8 @@
utils.InstallConstants(utils, [
"SetScriptSource", LiveEdit.SetScriptSource,
]);
utils.InstallConstants(global, [
"Debug", {},
]);
global.Debug.LiveEdit = LiveEdit;
})
// Copyright 2006-2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
(function(global, utils) {
"use strict";
// ----------------------------------------------------------------------------
// Imports
var GlobalArray = global.Array;
var IsNaN = global.isNaN;
var JSONStringify = global.JSON.stringify;
var MapEntries = global.Map.prototype.entries;
var MapIteratorNext = (new global.Map).entries().next;
var SetIteratorNext = (new global.Set).values().next;
var SetValues = global.Set.prototype.values;
// ----------------------------------------------------------------------------
// Mirror hierarchy:
// - Mirror
// - ValueMirror
// - UndefinedMirror
// - NullMirror
// - BooleanMirror
// - NumberMirror
// - StringMirror
// - SymbolMirror
// - ObjectMirror
// - FunctionMirror
// - UnresolvedFunctionMirror
// - ArrayMirror
// - DateMirror
// - RegExpMirror
// - ErrorMirror
// - PromiseMirror
// - MapMirror
// - SetMirror
// - IteratorMirror
// - GeneratorMirror
// - PropertyMirror
// - InternalPropertyMirror
// - FrameMirror
// - ScriptMirror
// - ScopeMirror
macro IS_BOOLEAN(arg)
(typeof(arg) === 'boolean')
endmacro
macro IS_DATE(arg)
(%IsDate(arg))
endmacro
macro IS_ERROR(arg)
(%IsJSError(arg))
endmacro
macro IS_GENERATOR(arg)
(%IsJSGeneratorObject(arg))
endmacro
macro IS_MAP(arg)
(%_IsJSMap(arg))
endmacro
macro IS_MAP_ITERATOR(arg)
(%IsJSMapIterator(arg))
endmacro
macro IS_SCRIPT(arg)
(%IsScriptWrapper(arg))
endmacro
macro IS_SET(arg)
(%_IsJSSet(arg))
endmacro
macro IS_SET_ITERATOR(arg)
(%IsJSSetIterator(arg))
endmacro
// Must match PropertyFilter in property-details.h
define PROPERTY_FILTER_NONE = 0;
// Type names of the different mirrors.
var MirrorType = {
UNDEFINED_TYPE : 'undefined',
NULL_TYPE : 'null',
BOOLEAN_TYPE : 'boolean',
NUMBER_TYPE : 'number',
STRING_TYPE : 'string',
SYMBOL_TYPE : 'symbol',
OBJECT_TYPE : 'object',
FUNCTION_TYPE : 'function',
REGEXP_TYPE : 'regexp',
ERROR_TYPE : 'error',
PROPERTY_TYPE : 'property',
INTERNAL_PROPERTY_TYPE : 'internalProperty',
FRAME_TYPE : 'frame',
SCRIPT_TYPE : 'script',
CONTEXT_TYPE : 'context',
SCOPE_TYPE : 'scope',
PROMISE_TYPE : 'promise',
MAP_TYPE : 'map',
SET_TYPE : 'set',
ITERATOR_TYPE : 'iterator',
GENERATOR_TYPE : 'generator',
}
/**
* Returns the mirror for a specified value or object.
*
* @param {value or Object} value the value or object to retrieve the mirror for
* @returns {Mirror} the mirror reflects the passed value or object
*/
function MakeMirror(value) {
var mirror;
if (IS_UNDEFINED(value)) {
mirror = new UndefinedMirror();
} else if (IS_NULL(value)) {
mirror = new NullMirror();
} else if (IS_BOOLEAN(value)) {
mirror = new BooleanMirror(value);
} else if (IS_NUMBER(value)) {
mirror = new NumberMirror(value);
} else if (IS_STRING(value)) {
mirror = new StringMirror(value);
} else if (IS_SYMBOL(value)) {
mirror = new SymbolMirror(value);
} else if (IS_ARRAY(value)) {
mirror = new ArrayMirror(value);
} else if (IS_DATE(value)) {
mirror = new DateMirror(value);
} else if (IS_FUNCTION(value)) {
mirror = new FunctionMirror(value);
} else if (%IsRegExp(value)) {
mirror = new RegExpMirror(value);
} else if (IS_ERROR(value)) {
mirror = new ErrorMirror(value);
} else if (IS_SCRIPT(value)) {
mirror = new ScriptMirror(value);
} else if (IS_MAP(value) || IS_WEAKMAP(value)) {
mirror = new MapMirror(value);
} else if (IS_SET(value) || IS_WEAKSET(value)) {
mirror = new SetMirror(value);
} else if (IS_MAP_ITERATOR(value) || IS_SET_ITERATOR(value)) {
mirror = new IteratorMirror(value);
} else if (%is_promise(value)) {
mirror = new PromiseMirror(value);
} else if (IS_GENERATOR(value)) {
mirror = new GeneratorMirror(value);
} else {
mirror = new ObjectMirror(value, MirrorType.OBJECT_TYPE);
}
return mirror;
}
/**
* Returns the mirror for the undefined value.
*
* @returns {Mirror} the mirror reflects the undefined value
*/
function GetUndefinedMirror() {
return MakeMirror(UNDEFINED);
}
/**
* Inherit the prototype methods from one constructor into another.
*
* The Function.prototype.inherits from lang.js rewritten as a standalone
* function (not on Function.prototype). NOTE: If this file is to be loaded
* during bootstrapping this function needs to be revritten using some native
* functions as prototype setup using normal JavaScript does not work as
* expected during bootstrapping (see mirror.js in r114903).
*
* @param {function} ctor Constructor function which needs to inherit the
* prototype
* @param {function} superCtor Constructor function to inherit prototype from
*/
function inherits(ctor, superCtor) {
var tempCtor = function(){};
tempCtor.prototype = superCtor.prototype;
ctor.super_ = superCtor.prototype;
ctor.prototype = new tempCtor();
ctor.prototype.constructor = ctor;
}
// Maximum length when sending strings through the JSON protocol.
var kMaxProtocolStringLength = 80;
// A copy of the PropertyKind enum from property-details.h
var PropertyType = {};
PropertyType.Data = 0;
PropertyType.Accessor = 1;
// Different attributes for a property.
var PropertyAttribute = {};
PropertyAttribute.None = NONE;
PropertyAttribute.ReadOnly = READ_ONLY;
PropertyAttribute.DontEnum = DONT_ENUM;
PropertyAttribute.DontDelete = DONT_DELETE;
// A copy of the scope types from runtime-debug.cc.
// NOTE: these constants should be backward-compatible, so
// add new ones to the end of this list.
var ScopeType = { Global: 0,
Local: 1,
With: 2,
Closure: 3,
Catch: 4,
Block: 5,
Script: 6,
Eval: 7,
Module: 8,
};
/**
* Base class for all mirror objects.
* @param {string} type The type of the mirror
* @constructor
*/
function Mirror(type) {
this.type_ = type;
}
Mirror.prototype.type = function() {
return this.type_;
};
/**
* Check whether the mirror reflects a value.
* @returns {boolean} True if the mirror reflects a value.
*/
Mirror.prototype.isValue = function() {
return this instanceof ValueMirror;
};
/**
* Check whether the mirror reflects the undefined value.
* @returns {boolean} True if the mirror reflects the undefined value.
*/
Mirror.prototype.isUndefined = function() {
return this instanceof UndefinedMirror;
};
/**
* Check whether the mirror reflects the null value.
* @returns {boolean} True if the mirror reflects the null value
*/
Mirror.prototype.isNull = function() {
return this instanceof NullMirror;
};
/**
* Check whether the mirror reflects a boolean value.
* @returns {boolean} True if the mirror reflects a boolean value
*/
Mirror.prototype.isBoolean = function() {
return this instanceof BooleanMirror;
};
/**
* Check whether the mirror reflects a number value.
* @returns {boolean} True if the mirror reflects a number value
*/
Mirror.prototype.isNumber = function() {
return this instanceof NumberMirror;
};
/**
* Check whether the mirror reflects a string value.
* @returns {boolean} True if the mirror reflects a string value
*/
Mirror.prototype.isString = function() {
return this instanceof StringMirror;
};
/**
* Check whether the mirror reflects a symbol.
* @returns {boolean} True if the mirror reflects a symbol
*/
Mirror.prototype.isSymbol = function() {
return this instanceof SymbolMirror;
};
/**
* Check whether the mirror reflects an object.
* @returns {boolean} True if the mirror reflects an object
*/
Mirror.prototype.isObject = function() {
return this instanceof ObjectMirror;
};
/**
* Check whether the mirror reflects a function.
* @returns {boolean} True if the mirror reflects a function
*/
Mirror.prototype.isFunction = function() {
return this instanceof FunctionMirror;
};
/**
* Check whether the mirror reflects an unresolved function.
* @returns {boolean} True if the mirror reflects an unresolved function
*/
Mirror.prototype.isUnresolvedFunction = function() {
return this instanceof UnresolvedFunctionMirror;
};
/**
* Check whether the mirror reflects an array.
* @returns {boolean} True if the mirror reflects an array
*/
Mirror.prototype.isArray = function() {
return this instanceof ArrayMirror;
};
/**
* Check whether the mirror reflects a date.
* @returns {boolean} True if the mirror reflects a date
*/
Mirror.prototype.isDate = function() {
return this instanceof DateMirror;
};
/**
* Check whether the mirror reflects a regular expression.
* @returns {boolean} True if the mirror reflects a regular expression
*/
Mirror.prototype.isRegExp = function() {
return this instanceof RegExpMirror;
};
/**
* Check whether the mirror reflects an error.
* @returns {boolean} True if the mirror reflects an error
*/
Mirror.prototype.isError = function() {
return this instanceof ErrorMirror;
};
/**
* Check whether the mirror reflects a promise.
* @returns {boolean} True if the mirror reflects a promise
*/
Mirror.prototype.isPromise = function() {
return this instanceof PromiseMirror;
};
/**
* Check whether the mirror reflects a generator object.
* @returns {boolean} True if the mirror reflects a generator object
*/
Mirror.prototype.isGenerator = function() {
return this instanceof GeneratorMirror;
};
/**
* Check whether the mirror reflects a property.
* @returns {boolean} True if the mirror reflects a property
*/
Mirror.prototype.isProperty = function() {
return this instanceof PropertyMirror;
};
/**
* Check whether the mirror reflects an internal property.
* @returns {boolean} True if the mirror reflects an internal property
*/
Mirror.prototype.isInternalProperty = function() {
return this instanceof InternalPropertyMirror;
};
/**
* Check whether the mirror reflects a stack frame.
* @returns {boolean} True if the mirror reflects a stack frame
*/
Mirror.prototype.isFrame = function() {
return this instanceof FrameMirror;
};
/**
* Check whether the mirror reflects a script.
* @returns {boolean} True if the mirror reflects a script
*/
Mirror.prototype.isScript = function() {
return this instanceof ScriptMirror;
};
/**
* Check whether the mirror reflects a context.
* @returns {boolean} True if the mirror reflects a context
*/
Mirror.prototype.isContext = function() {
return this instanceof ContextMirror;
};
/**
* Check whether the mirror reflects a scope.
* @returns {boolean} True if the mirror reflects a scope
*/
Mirror.prototype.isScope = function() {
return this instanceof ScopeMirror;
};
/**
* Check whether the mirror reflects a map.
* @returns {boolean} True if the mirror reflects a map
*/
Mirror.prototype.isMap = function() {
return this instanceof MapMirror;
};
/**
* Check whether the mirror reflects a set.
* @returns {boolean} True if the mirror reflects a set
*/
Mirror.prototype.isSet = function() {
return this instanceof SetMirror;
};
/**
* Check whether the mirror reflects an iterator.
* @returns {boolean} True if the mirror reflects an iterator
*/
Mirror.prototype.isIterator = function() {
return this instanceof IteratorMirror;
};
Mirror.prototype.toText = function() {
// Simpel to text which is used when on specialization in subclass.
return "#<" + this.constructor.name + ">";
};
/**
* Base class for all value mirror objects.
* @param {string} type The type of the mirror
* @param {value} value The value reflected by this mirror
* @constructor
* @extends Mirror
*/
function ValueMirror(type, value) {
%_Call(Mirror, this, type);
this.value_ = value;
}
inherits(ValueMirror, Mirror);
/**
* Check whether this is a primitive value.
* @return {boolean} True if the mirror reflects a primitive value
*/
ValueMirror.prototype.isPrimitive = function() {
var type = this.type();
return type === 'undefined' ||
type === 'null' ||
type === 'boolean' ||
type === 'number' ||
type === 'string' ||
type === 'symbol';
};
/**
* Get the actual value reflected by this mirror.
* @return {value} The value reflected by this mirror
*/
ValueMirror.prototype.value = function() {
return this.value_;
};
/**
* Mirror object for Undefined.
* @constructor
* @extends ValueMirror
*/
function UndefinedMirror() {
%_Call(ValueMirror, this, MirrorType.UNDEFINED_TYPE, UNDEFINED);
}
inherits(UndefinedMirror, ValueMirror);
UndefinedMirror.prototype.toText = function() {
return 'undefined';
};
/**
* Mirror object for null.
* @constructor
* @extends ValueMirror
*/
function NullMirror() {
%_Call(ValueMirror, this, MirrorType.NULL_TYPE, null);
}
inherits(NullMirror, ValueMirror);
NullMirror.prototype.toText = function() {
return 'null';
};
/**
* Mirror object for boolean values.
* @param {boolean} value The boolean value reflected by this mirror
* @constructor
* @extends ValueMirror
*/
function BooleanMirror(value) {
%_Call(ValueMirror, this, MirrorType.BOOLEAN_TYPE, value);
}
inherits(BooleanMirror, ValueMirror);
BooleanMirror.prototype.toText = function() {
return this.value_ ? 'true' : 'false';
};
/**
* Mirror object for number values.
* @param {number} value The number value reflected by this mirror
* @constructor
* @extends ValueMirror
*/
function NumberMirror(value) {
%_Call(ValueMirror, this, MirrorType.NUMBER_TYPE, value);
}
inherits(NumberMirror, ValueMirror);
NumberMirror.prototype.toText = function() {
return '' + this.value_;
};
/**
* Mirror object for string values.
* @param {string} value The string value reflected by this mirror
* @constructor
* @extends ValueMirror
*/
function StringMirror(value) {
%_Call(ValueMirror, this, MirrorType.STRING_TYPE, value);
}
inherits(StringMirror, ValueMirror);
StringMirror.prototype.length = function() {
return this.value_.length;
};
StringMirror.prototype.getTruncatedValue = function(maxLength) {
if (maxLength != -1 && this.length() > maxLength) {
return this.value_.substring(0, maxLength) +
'... (length: ' + this.length() + ')';
}
return this.value_;
};
StringMirror.prototype.toText = function() {
return this.getTruncatedValue(kMaxProtocolStringLength);
};
/**
* Mirror object for a Symbol
* @param {Object} value The Symbol
* @constructor
* @extends Mirror
*/
function SymbolMirror(value) {
%_Call(ValueMirror, this, MirrorType.SYMBOL_TYPE, value);
}
inherits(SymbolMirror, ValueMirror);
SymbolMirror.prototype.description = function() {
return %SymbolDescription(%ValueOf(this.value_));
}
SymbolMirror.prototype.toText = function() {
return %SymbolDescriptiveString(%ValueOf(this.value_));
}
/**
* Mirror object for objects.
* @param {object} value The object reflected by this mirror
* @constructor
* @extends ValueMirror
*/
function ObjectMirror(value, type) {
type = type || MirrorType.OBJECT_TYPE;
%_Call(ValueMirror, this, type, value);
}
inherits(ObjectMirror, ValueMirror);
ObjectMirror.prototype.className = function() {
return %ClassOf(this.value_);
};
ObjectMirror.prototype.constructorFunction = function() {
return MakeMirror(%DebugGetProperty(this.value_, 'constructor'));
};
ObjectMirror.prototype.prototypeObject = function() {
return MakeMirror(%DebugGetProperty(this.value_, 'prototype'));
};
ObjectMirror.prototype.protoObject = function() {
return MakeMirror(%DebugGetPrototype(this.value_));
};
ObjectMirror.prototype.hasNamedInterceptor = function() {
// Get information on interceptors for this object.
var x = %GetInterceptorInfo(this.value_);
return (x & 2) != 0;
};
ObjectMirror.prototype.hasIndexedInterceptor = function() {
// Get information on interceptors for this object.
var x = %GetInterceptorInfo(this.value_);
return (x & 1) != 0;
};
/**
* Return the property names for this object.
* @param {number} kind Indicate whether named, indexed or both kinds of
* properties are requested
* @param {number} limit Limit the number of names returend to the specified
value
* @return {Array} Property names for this object
*/
ObjectMirror.prototype.propertyNames = function() {
return %GetOwnPropertyKeys(this.value_, PROPERTY_FILTER_NONE);
};
/**
* Return the properties for this object as an array of PropertyMirror objects.
* @param {number} kind Indicate whether named, indexed or both kinds of
* properties are requested
* @param {number} limit Limit the number of properties returned to the
specified value
* @return {Array} Property mirrors for this object
*/
ObjectMirror.prototype.properties = function() {
var names = this.propertyNames();
var properties = new GlobalArray(names.length);
for (var i = 0; i < names.length; i++) {
properties[i] = this.property(names[i]);
}
return properties;
};
/**
* Return the internal properties for this object as an array of
* InternalPropertyMirror objects.
* @return {Array} Property mirrors for this object
*/
ObjectMirror.prototype.internalProperties = function() {
return ObjectMirror.GetInternalProperties(this.value_);
}
ObjectMirror.prototype.property = function(name) {
var details = %DebugGetPropertyDetails(this.value_, name);
if (details) {
return new PropertyMirror(this, name, details);
}
// Nothing found.
return GetUndefinedMirror();
};
/**
* Try to find a property from its value.
* @param {Mirror} value The property value to look for
* @return {PropertyMirror} The property with the specified value. If no
* property was found with the specified value UndefinedMirror is returned
*/
ObjectMirror.prototype.lookupProperty = function(value) {
var properties = this.properties();
// Look for property value in properties.
for (var i = 0; i < properties.length; i++) {
// Skip properties which are defined through accessors.
var property = properties[i];
if (property.propertyType() == PropertyType.Data) {
if (property.value_ === value.value_) {
return property;
}
}
}
// Nothing found.
return GetUndefinedMirror();
};
/**
* Returns objects which has direct references to this object
* @param {number} opt_max_objects Optional parameter specifying the maximum
* number of referencing objects to return.
* @return {Array} The objects which has direct references to this object.
*/
ObjectMirror.prototype.referencedBy = function(opt_max_objects) {
// Find all objects with direct references to this object.
var result = %DebugReferencedBy(this.value_,
Mirror.prototype, opt_max_objects || 0);
// Make mirrors for all the references found.
for (var i = 0; i < result.length; i++) {
result[i] = MakeMirror(result[i]);
}
return result;
};
ObjectMirror.prototype.toText = function() {
var name;
var ctor = this.constructorFunction();
if (!ctor.isFunction()) {
name = this.className();
} else {
name = ctor.name();
if (!name) {
name = this.className();
}
}
return '#<' + name + '>';
};
/**
* Return the internal properties of the value, such as [[PrimitiveValue]] of
* scalar wrapper objects, properties of the bound function and properties of
* the promise.
* This method is done static to be accessible from Debug API with the bare
* values without mirrors.
* @return {Array} array (possibly empty) of InternalProperty instances
*/
ObjectMirror.GetInternalProperties = function(value) {
var properties = %DebugGetInternalProperties(value);
var result = [];
for (var i = 0; i < properties.length; i += 2) {
result.push(new InternalPropertyMirror(properties[i], properties[i + 1]));
}
return result;
}
/**
* Mirror object for functions.
* @param {function} value The function object reflected by this mirror.
* @constructor
* @extends ObjectMirror
*/
function FunctionMirror(value) {
%_Call(ObjectMirror, this, value, MirrorType.FUNCTION_TYPE);
this.resolved_ = true;
}
inherits(FunctionMirror, ObjectMirror);
/**
* Returns whether the function is resolved.
* @return {boolean} True if the function is resolved. Unresolved functions can
* only originate as functions from stack frames
*/
FunctionMirror.prototype.resolved = function() {
return this.resolved_;
};
/**
* Returns the name of the function.
* @return {string} Name of the function
*/
FunctionMirror.prototype.name = function() {
return %FunctionGetName(this.value_);
};
/**
* Returns the displayName if it is set, otherwise name, otherwise inferred
* name.
* @return {string} Name of the function
*/
FunctionMirror.prototype.debugName = function() {
return %FunctionGetDebugName(this.value_);
}
/**
* Returns the inferred name of the function.
* @return {string} Name of the function
*/
FunctionMirror.prototype.inferredName = function() {
return %FunctionGetInferredName(this.value_);
};
/**
* Returns the source code for the function.
* @return {string or undefined} The source code for the function. If the
* function is not resolved undefined will be returned.
*/
FunctionMirror.prototype.source = function() {
// Return source if function is resolved. Otherwise just fall through to
// return undefined.
if (this.resolved()) {
return %FunctionToString(this.value_);
}
};
/**
* Returns the script object for the function.
* @return {ScriptMirror or undefined} Script object for the function or
* undefined if the function has no script
*/
FunctionMirror.prototype.script = function() {
// Return script if function is resolved. Otherwise just fall through
// to return undefined.
if (this.resolved()) {
if (this.script_) {
return this.script_;
}
var script = %FunctionGetScript(this.value_);
if (script) {
return this.script_ = MakeMirror(script);
}
}
};
/**
* Returns the script source position for the function. Only makes sense
* for functions which has a script defined.
* @return {Number or undefined} in-script position for the function
*/
FunctionMirror.prototype.sourcePosition_ = function() {
// Return position if function is resolved. Otherwise just fall
// through to return undefined.
if (this.resolved()) {
return %FunctionGetScriptSourcePosition(this.value_);
}
};
/**
* Returns the script source location object for the function. Only makes sense
* for functions which has a script defined.
* @return {Location or undefined} in-script location for the function begin
*/
FunctionMirror.prototype.sourceLocation = function() {
if (this.resolved()) {
var script = this.script();
if (script) {
return script.locationFromPosition(this.sourcePosition_(), true);
}
}
};
/**
* Returns objects constructed by this function.
* @param {number} opt_max_instances Optional parameter specifying the maximum
* number of instances to return.
* @return {Array or undefined} The objects constructed by this function.
*/
FunctionMirror.prototype.constructedBy = function(opt_max_instances) {
if (this.resolved()) {
// Find all objects constructed from this function.
var result = %DebugConstructedBy(this.value_, opt_max_instances || 0);
// Make mirrors for all the instances found.
for (var i = 0; i < result.length; i++) {
result[i] = MakeMirror(result[i]);
}
return result;
} else {
return [];
}
};
FunctionMirror.prototype.scopeCount = function() {
if (this.resolved()) {
if (IS_UNDEFINED(this.scopeCount_)) {
this.scopeCount_ = %GetFunctionScopeCount(this.value());
}
return this.scopeCount_;
} else {
return 0;
}
};
FunctionMirror.prototype.scope = function(index) {
if (this.resolved()) {
return new ScopeMirror(UNDEFINED, this, UNDEFINED, index);
}
};
FunctionMirror.prototype.toText = function() {
return this.source();
};
FunctionMirror.prototype.context = function() {
if (this.resolved()) {
if (!this._context)
this._context = new ContextMirror(%FunctionGetContextData(this.value_));
return this._context;
}
};
/**
* Mirror object for unresolved functions.
* @param {string} value The name for the unresolved function reflected by this
* mirror.
* @constructor
* @extends ObjectMirror
*/
function UnresolvedFunctionMirror(value) {
// Construct this using the ValueMirror as an unresolved function is not a
// real object but just a string.
%_Call(ValueMirror, this, MirrorType.FUNCTION_TYPE, value);
this.propertyCount_ = 0;
this.elementCount_ = 0;
this.resolved_ = false;
}
inherits(UnresolvedFunctionMirror, FunctionMirror);
UnresolvedFunctionMirror.prototype.className = function() {
return 'Function';
};
UnresolvedFunctionMirror.prototype.constructorFunction = function() {
return GetUndefinedMirror();
};
UnresolvedFunctionMirror.prototype.prototypeObject = function() {
return GetUndefinedMirror();
};
UnresolvedFunctionMirror.prototype.protoObject = function() {
return GetUndefinedMirror();
};
UnresolvedFunctionMirror.prototype.name = function() {
return this.value_;
};
UnresolvedFunctionMirror.prototype.debugName = function() {
return this.value_;
};
UnresolvedFunctionMirror.prototype.inferredName = function() {
return UNDEFINED;
};
UnresolvedFunctionMirror.prototype.propertyNames = function(kind, limit) {
return [];
};
/**
* Mirror object for arrays.
* @param {Array} value The Array object reflected by this mirror
* @constructor
* @extends ObjectMirror
*/
function ArrayMirror(value) {
%_Call(ObjectMirror, this, value);
}
inherits(ArrayMirror, ObjectMirror);
ArrayMirror.prototype.length = function() {
return this.value_.length;
};
ArrayMirror.prototype.indexedPropertiesFromRange = function(opt_from_index,
opt_to_index) {
var from_index = opt_from_index || 0;
var to_index = opt_to_index || this.length() - 1;
if (from_index > to_index) return new GlobalArray();
var values = new GlobalArray(to_index - from_index + 1);
for (var i = from_index; i <= to_index; i++) {
var details = %DebugGetPropertyDetails(this.value_, TO_STRING(i));
var value;
if (details) {
value = new PropertyMirror(this, i, details);
} else {
value = GetUndefinedMirror();
}
values[i - from_index] = value;
}
return values;
};
/**
* Mirror object for dates.
* @param {Date} value The Date object reflected by this mirror
* @constructor
* @extends ObjectMirror
*/
function DateMirror(value) {
%_Call(ObjectMirror, this, value);
}
inherits(DateMirror, ObjectMirror);
DateMirror.prototype.toText = function() {
var s = JSONStringify(this.value_);
return s.substring(1, s.length - 1); // cut quotes
};
/**
* Mirror object for regular expressions.
* @param {RegExp} value The RegExp object reflected by this mirror
* @constructor
* @extends ObjectMirror
*/
function RegExpMirror(value) {
%_Call(ObjectMirror, this, value, MirrorType.REGEXP_TYPE);
}
inherits(RegExpMirror, ObjectMirror);
/**
* Returns the source to the regular expression.
* @return {string or undefined} The source to the regular expression
*/
RegExpMirror.prototype.source = function() {
return this.value_.source;
};
/**
* Returns whether this regular expression has the global (g) flag set.
* @return {boolean} Value of the global flag
*/
RegExpMirror.prototype.global = function() {
return this.value_.global;
};
/**
* Returns whether this regular expression has the ignore case (i) flag set.
* @return {boolean} Value of the ignore case flag
*/
RegExpMirror.prototype.ignoreCase = function() {
return this.value_.ignoreCase;
};
/**
* Returns whether this regular expression has the multiline (m) flag set.
* @return {boolean} Value of the multiline flag
*/
RegExpMirror.prototype.multiline = function() {
return this.value_.multiline;
};
/**
* Returns whether this regular expression has the sticky (y) flag set.
* @return {boolean} Value of the sticky flag
*/
RegExpMirror.prototype.sticky = function() {
return this.value_.sticky;
};
/**
* Returns whether this regular expression has the unicode (u) flag set.
* @return {boolean} Value of the unicode flag
*/
RegExpMirror.prototype.unicode = function() {
return this.value_.unicode;
};
RegExpMirror.prototype.toText = function() {
// Simpel to text which is used when on specialization in subclass.
return "/" + this.source() + "/";
};
/**
* Mirror object for error objects.
* @param {Error} value The error object reflected by this mirror
* @constructor
* @extends ObjectMirror
*/
function ErrorMirror(value) {
%_Call(ObjectMirror, this, value, MirrorType.ERROR_TYPE);
}
inherits(ErrorMirror, ObjectMirror);
/**
* Returns the message for this eror object.
* @return {string or undefined} The message for this eror object
*/
ErrorMirror.prototype.message = function() {
return this.value_.message;
};
ErrorMirror.prototype.toText = function() {
// Use the same text representation as in messages.js.
var text;
try {
text = %ErrorToString(this.value_);
} catch (e) {
text = '#<Error>';
}
return text;
};
/**
* Mirror object for a Promise object.
* @param {Object} value The Promise object
* @constructor
* @extends ObjectMirror
*/
function PromiseMirror(value) {
%_Call(ObjectMirror, this, value, MirrorType.PROMISE_TYPE);
}
inherits(PromiseMirror, ObjectMirror);
function PromiseGetStatus_(value) {
var status = %PromiseStatus(value);
if (status == 0) return "pending";
if (status == 1) return "resolved";
return "rejected";
}
function PromiseGetValue_(value) {
return %PromiseResult(value);
}
PromiseMirror.prototype.status = function() {
return PromiseGetStatus_(this.value_);
};
PromiseMirror.prototype.promiseValue = function() {
return MakeMirror(PromiseGetValue_(this.value_));
};
function MapMirror(value) {
%_Call(ObjectMirror, this, value, MirrorType.MAP_TYPE);
}
inherits(MapMirror, ObjectMirror);
/**
* Returns an array of key/value pairs of a map.
* This will keep keys alive for WeakMaps.
*
* @param {number=} opt_limit Max elements to return.
* @returns {Array.<Object>} Array of key/value pairs of a map.
*/
MapMirror.prototype.entries = function(opt_limit) {
var result = [];
if (IS_WEAKMAP(this.value_)) {
var entries = %GetWeakMapEntries(this.value_, opt_limit || 0);
for (var i = 0; i < entries.length; i += 2) {
result.push({
key: entries[i],
value: entries[i + 1]
});
}
return result;
}
var iter = %_Call(MapEntries, this.value_);
var next;
while ((!opt_limit || result.length < opt_limit) &&
!(next = iter.next()).done) {
result.push({
key: next.value[0],
value: next.value[1]
});
}
return result;
};
function SetMirror(value) {
%_Call(ObjectMirror, this, value, MirrorType.SET_TYPE);
}
inherits(SetMirror, ObjectMirror);
function IteratorGetValues_(iter, next_function, opt_limit) {
var result = [];
var next;
while ((!opt_limit || result.length < opt_limit) &&
!(next = %_Call(next_function, iter)).done) {
result.push(next.value);
}
return result;
}
/**
* Returns an array of elements of a set.
* This will keep elements alive for WeakSets.
*
* @param {number=} opt_limit Max elements to return.
* @returns {Array.<Object>} Array of elements of a set.
*/
SetMirror.prototype.values = function(opt_limit) {
if (IS_WEAKSET(this.value_)) {
return %GetWeakSetValues(this.value_, opt_limit || 0);
}
var iter = %_Call(SetValues, this.value_);
return IteratorGetValues_(iter, SetIteratorNext, opt_limit);
};
function IteratorMirror(value) {
%_Call(ObjectMirror, this, value, MirrorType.ITERATOR_TYPE);
}
inherits(IteratorMirror, ObjectMirror);
/**
* Returns a preview of elements of an iterator.
* Does not change the backing iterator state.
*
* @param {number=} opt_limit Max elements to return.
* @returns {Array.<Object>} Array of elements of an iterator.
*/
IteratorMirror.prototype.preview = function(opt_limit) {
if (IS_MAP_ITERATOR(this.value_)) {
return IteratorGetValues_(%MapIteratorClone(this.value_),
MapIteratorNext,
opt_limit);
} else if (IS_SET_ITERATOR(this.value_)) {
return IteratorGetValues_(%SetIteratorClone(this.value_),
SetIteratorNext,
opt_limit);
}
};
/**
* Mirror object for a Generator object.
* @param {Object} data The Generator object
* @constructor
* @extends Mirror
*/
function GeneratorMirror(value) {
%_Call(ObjectMirror, this, value, MirrorType.GENERATOR_TYPE);
}
inherits(GeneratorMirror, ObjectMirror);
function GeneratorGetStatus_(value) {
var continuation = %GeneratorGetContinuation(value);
if (continuation < -1) return "running";
if (continuation == -1) return "closed";
return "suspended";
}
GeneratorMirror.prototype.status = function() {
return GeneratorGetStatus_(this.value_);
};
GeneratorMirror.prototype.sourcePosition_ = function() {
return %GeneratorGetSourcePosition(this.value_);
};
GeneratorMirror.prototype.sourceLocation = function() {
var pos = this.sourcePosition_();
if (!IS_UNDEFINED(pos)) {
var script = this.func().script();
if (script) {
return script.locationFromPosition(pos, true);
}
}
};
GeneratorMirror.prototype.func = function() {
if (!this.func_) {
this.func_ = MakeMirror(%GeneratorGetFunction(this.value_));
}
return this.func_;
};
GeneratorMirror.prototype.receiver = function() {
if (!this.receiver_) {
this.receiver_ = MakeMirror(%GeneratorGetReceiver(this.value_));
}
return this.receiver_;
};
GeneratorMirror.prototype.scopeCount = function() {
// This value can change over time as the underlying generator is suspended
// at different locations.
return %GetGeneratorScopeCount(this.value());
};
GeneratorMirror.prototype.scope = function(index) {
return new ScopeMirror(UNDEFINED, UNDEFINED, this, index);
};
GeneratorMirror.prototype.allScopes = function() {
var scopes = [];
for (let i = 0; i < this.scopeCount(); i++) {
scopes.push(this.scope(i));
}
return scopes;
};
/**
* Base mirror object for properties.
* @param {ObjectMirror} mirror The mirror object having this property
* @param {string} name The name of the property
* @param {Array} details Details about the property
* @constructor
* @extends Mirror
*/
function PropertyMirror(mirror, name, details) {
%_Call(Mirror, this, MirrorType.PROPERTY_TYPE);
this.mirror_ = mirror;
this.name_ = name;
this.value_ = details[0];
this.details_ = details[1];
this.is_interceptor_ = details[2];
if (details.length > 3) {
this.exception_ = details[3];
this.getter_ = details[4];
this.setter_ = details[5];
}
}
inherits(PropertyMirror, Mirror);
PropertyMirror.prototype.isReadOnly = function() {
return (this.attributes() & PropertyAttribute.ReadOnly) != 0;
};
PropertyMirror.prototype.isEnum = function() {
return (this.attributes() & PropertyAttribute.DontEnum) == 0;
};
PropertyMirror.prototype.canDelete = function() {
return (this.attributes() & PropertyAttribute.DontDelete) == 0;
};
PropertyMirror.prototype.name = function() {
return this.name_;
};
PropertyMirror.prototype.toText = function() {
if (IS_SYMBOL(this.name_)) return %SymbolDescriptiveString(this.name_);
return this.name_;
};
PropertyMirror.prototype.isIndexed = function() {
for (var i = 0; i < this.name_.length; i++) {
if (this.name_[i] < '0' || '9' < this.name_[i]) {
return false;
}
}
return true;
};
PropertyMirror.prototype.value = function() {
return MakeMirror(this.value_, false);
};
/**
* Returns whether this property value is an exception.
* @return {boolean} True if this property value is an exception
*/
PropertyMirror.prototype.isException = function() {
return this.exception_ ? true : false;
};
PropertyMirror.prototype.attributes = function() {
return %DebugPropertyAttributesFromDetails(this.details_);
};
PropertyMirror.prototype.propertyType = function() {
return %DebugPropertyKindFromDetails(this.details_);
};
/**
* Returns whether this property has a getter defined through __defineGetter__.
* @return {boolean} True if this property has a getter
*/
PropertyMirror.prototype.hasGetter = function() {
return this.getter_ ? true : false;
};
/**
* Returns whether this property has a setter defined through __defineSetter__.
* @return {boolean} True if this property has a setter
*/
PropertyMirror.prototype.hasSetter = function() {
return this.setter_ ? true : false;
};
/**
* Returns the getter for this property defined through __defineGetter__.
* @return {Mirror} FunctionMirror reflecting the getter function or
* UndefinedMirror if there is no getter for this property
*/
PropertyMirror.prototype.getter = function() {
if (this.hasGetter()) {
return MakeMirror(this.getter_);
} else {
return GetUndefinedMirror();
}
};
/**
* Returns the setter for this property defined through __defineSetter__.
* @return {Mirror} FunctionMirror reflecting the setter function or
* UndefinedMirror if there is no setter for this property
*/
PropertyMirror.prototype.setter = function() {
if (this.hasSetter()) {
return MakeMirror(this.setter_);
} else {
return GetUndefinedMirror();
}
};
/**
* Returns whether this property is natively implemented by the host or a set
* through JavaScript code.
* @return {boolean} True if the property is
* UndefinedMirror if there is no setter for this property
*/
PropertyMirror.prototype.isNative = function() {
return this.is_interceptor_ ||
((this.propertyType() == PropertyType.Accessor) &&
!this.hasGetter() && !this.hasSetter());
};
/**
* Mirror object for internal properties. Internal property reflects properties
* not accessible from user code such as [[BoundThis]] in bound function.
* Their names are merely symbolic.
* @param {string} name The name of the property
* @param {value} property value
* @constructor
* @extends Mirror
*/
function InternalPropertyMirror(name, value) {
%_Call(Mirror, this, MirrorType.INTERNAL_PROPERTY_TYPE);
this.name_ = name;
this.value_ = value;
}
inherits(InternalPropertyMirror, Mirror);
InternalPropertyMirror.prototype.name = function() {
return this.name_;
};
InternalPropertyMirror.prototype.value = function() {
return MakeMirror(this.value_, false);
};
var kFrameDetailsFrameIdIndex = 0;
var kFrameDetailsReceiverIndex = 1;
var kFrameDetailsFunctionIndex = 2;
var kFrameDetailsScriptIndex = 3;
var kFrameDetailsArgumentCountIndex = 4;
var kFrameDetailsLocalCountIndex = 5;
var kFrameDetailsSourcePositionIndex = 6;
var kFrameDetailsConstructCallIndex = 7;
var kFrameDetailsAtReturnIndex = 8;
var kFrameDetailsFlagsIndex = 9;
var kFrameDetailsFirstDynamicIndex = 10;
var kFrameDetailsNameIndex = 0;
var kFrameDetailsValueIndex = 1;
var kFrameDetailsNameValueSize = 2;
var kFrameDetailsFlagDebuggerFrameMask = 1 << 0;
var kFrameDetailsFlagOptimizedFrameMask = 1 << 1;
var kFrameDetailsFlagInlinedFrameIndexMask = 7 << 2;
/**
* Wrapper for the frame details information retreived from the VM. The frame
* details from the VM is an array with the following content. See runtime.cc
* Runtime_GetFrameDetails.
* 0: Id
* 1: Receiver
* 2: Function
* 3: Script
* 4: Argument count
* 5: Local count
* 6: Source position
* 7: Construct call
* 8: Is at return
* 9: Flags (debugger frame, optimized frame, inlined frame index)
* Arguments name, value
* Locals name, value
* Return value if any
* @param {number} break_id Current break id
* @param {number} index Frame number
* @constructor
*/
function FrameDetails(break_id, index) {
this.break_id_ = break_id;
this.details_ = %GetFrameDetails(break_id, index);
}
FrameDetails.prototype.frameId = function() {
%CheckExecutionState(this.break_id_);
return this.details_[kFrameDetailsFrameIdIndex];
};
FrameDetails.prototype.receiver = function() {
%CheckExecutionState(this.break_id_);
return this.details_[kFrameDetailsReceiverIndex];
};
FrameDetails.prototype.func = function() {
%CheckExecutionState(this.break_id_);
return this.details_[kFrameDetailsFunctionIndex];
};
FrameDetails.prototype.script = function() {
%CheckExecutionState(this.break_id_);
return this.details_[kFrameDetailsScriptIndex];
};
FrameDetails.prototype.isConstructCall = function() {
%CheckExecutionState(this.break_id_);
return this.details_[kFrameDetailsConstructCallIndex];
};
FrameDetails.prototype.isAtReturn = function() {
%CheckExecutionState(this.break_id_);
return this.details_[kFrameDetailsAtReturnIndex];
};
FrameDetails.prototype.isDebuggerFrame = function() {
%CheckExecutionState(this.break_id_);
var f = kFrameDetailsFlagDebuggerFrameMask;
return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
};
FrameDetails.prototype.isOptimizedFrame = function() {
%CheckExecutionState(this.break_id_);
var f = kFrameDetailsFlagOptimizedFrameMask;
return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
};
FrameDetails.prototype.isInlinedFrame = function() {
return this.inlinedFrameIndex() > 0;
};
FrameDetails.prototype.inlinedFrameIndex = function() {
%CheckExecutionState(this.break_id_);
var f = kFrameDetailsFlagInlinedFrameIndexMask;
return (this.details_[kFrameDetailsFlagsIndex] & f) >> 2;
};
FrameDetails.prototype.argumentCount = function() {
%CheckExecutionState(this.break_id_);
return this.details_[kFrameDetailsArgumentCountIndex];
};
FrameDetails.prototype.argumentName = function(index) {
%CheckExecutionState(this.break_id_);
if (index >= 0 && index < this.argumentCount()) {
return this.details_[kFrameDetailsFirstDynamicIndex +
index * kFrameDetailsNameValueSize +
kFrameDetailsNameIndex];
}
};
FrameDetails.prototype.argumentValue = function(index) {
%CheckExecutionState(this.break_id_);
if (index >= 0 && index < this.argumentCount()) {
return this.details_[kFrameDetailsFirstDynamicIndex +
index * kFrameDetailsNameValueSize +
kFrameDetailsValueIndex];
}
};
FrameDetails.prototype.localCount = function() {
%CheckExecutionState(this.break_id_);
return this.details_[kFrameDetailsLocalCountIndex];
};
FrameDetails.prototype.sourcePosition = function() {
%CheckExecutionState(this.break_id_);
return this.details_[kFrameDetailsSourcePositionIndex];
};
FrameDetails.prototype.localName = function(index) {
%CheckExecutionState(this.break_id_);
if (index >= 0 && index < this.localCount()) {
var locals_offset = kFrameDetailsFirstDynamicIndex +
this.argumentCount() * kFrameDetailsNameValueSize;
return this.details_[locals_offset +
index * kFrameDetailsNameValueSize +
kFrameDetailsNameIndex];
}
};
FrameDetails.prototype.localValue = function(index) {
%CheckExecutionState(this.break_id_);
if (index >= 0 && index < this.localCount()) {
var locals_offset = kFrameDetailsFirstDynamicIndex +
this.argumentCount() * kFrameDetailsNameValueSize;
return this.details_[locals_offset +
index * kFrameDetailsNameValueSize +
kFrameDetailsValueIndex];
}
};
FrameDetails.prototype.returnValue = function() {
%CheckExecutionState(this.break_id_);
var return_value_offset =
kFrameDetailsFirstDynamicIndex +
(this.argumentCount() + this.localCount()) * kFrameDetailsNameValueSize;
if (this.details_[kFrameDetailsAtReturnIndex]) {
return this.details_[return_value_offset];
}
};
FrameDetails.prototype.scopeCount = function() {
if (IS_UNDEFINED(this.scopeCount_)) {
this.scopeCount_ = %GetScopeCount(this.break_id_, this.frameId());
}
return this.scopeCount_;
};
/**
* Mirror object for stack frames.
* @param {number} break_id The break id in the VM for which this frame is
valid
* @param {number} index The frame index (top frame is index 0)
* @constructor
* @extends Mirror
*/
function FrameMirror(break_id, index) {
%_Call(Mirror, this, MirrorType.FRAME_TYPE);
this.break_id_ = break_id;
this.index_ = index;
this.details_ = new FrameDetails(break_id, index);
}
inherits(FrameMirror, Mirror);
FrameMirror.prototype.details = function() {
return this.details_;
};
FrameMirror.prototype.index = function() {
return this.index_;
};
FrameMirror.prototype.func = function() {
if (this.func_) {
return this.func_;
}
// Get the function for this frame from the VM.
var f = this.details_.func();
// Create a function mirror. NOTE: MakeMirror cannot be used here as the
// value returned from the VM might be a string if the function for the
// frame is unresolved.
if (IS_FUNCTION(f)) {
return this.func_ = MakeMirror(f);
} else {
return new UnresolvedFunctionMirror(f);
}
};
FrameMirror.prototype.script = function() {
if (!this.script_) {
this.script_ = MakeMirror(this.details_.script());
}
return this.script_;
}
FrameMirror.prototype.receiver = function() {
return MakeMirror(this.details_.receiver());
};
FrameMirror.prototype.isConstructCall = function() {
return this.details_.isConstructCall();
};
FrameMirror.prototype.isAtReturn = function() {
return this.details_.isAtReturn();
};
FrameMirror.prototype.isDebuggerFrame = function() {
return this.details_.isDebuggerFrame();
};
FrameMirror.prototype.isOptimizedFrame = function() {
return this.details_.isOptimizedFrame();
};
FrameMirror.prototype.isInlinedFrame = function() {
return this.details_.isInlinedFrame();
};
FrameMirror.prototype.inlinedFrameIndex = function() {
return this.details_.inlinedFrameIndex();
};
FrameMirror.prototype.argumentCount = function() {
return this.details_.argumentCount();
};
FrameMirror.prototype.argumentName = function(index) {
return this.details_.argumentName(index);
};
FrameMirror.prototype.argumentValue = function(index) {
return MakeMirror(this.details_.argumentValue(index));
};
FrameMirror.prototype.localCount = function() {
return this.details_.localCount();
};
FrameMirror.prototype.localName = function(index) {
return this.details_.localName(index);
};
FrameMirror.prototype.localValue = function(index) {
return MakeMirror(this.details_.localValue(index));
};
FrameMirror.prototype.returnValue = function() {
return MakeMirror(this.details_.returnValue());
};
FrameMirror.prototype.sourcePosition = function() {
return this.details_.sourcePosition();
};
FrameMirror.prototype.sourceLocation = function() {
var script = this.script();
if (script) {
return script.locationFromPosition(this.sourcePosition(), true);
}
};
FrameMirror.prototype.sourceLine = function() {
var location = this.sourceLocation();
if (location) {
return location.line;
}
};
FrameMirror.prototype.sourceColumn = function() {
var location = this.sourceLocation();
if (location) {
return location.column;
}
};
FrameMirror.prototype.sourceLineText = function() {
var location = this.sourceLocation();
if (location) {
return location.sourceText;
}
};
FrameMirror.prototype.scopeCount = function() {
return this.details_.scopeCount();
};
FrameMirror.prototype.scope = function(index) {
return new ScopeMirror(this, UNDEFINED, UNDEFINED, index);
};
FrameMirror.prototype.allScopes = function(opt_ignore_nested_scopes) {
var scopeDetails = %GetAllScopesDetails(this.break_id_,
this.details_.frameId(),
this.details_.inlinedFrameIndex(),
!!opt_ignore_nested_scopes);
var result = [];
for (var i = 0; i < scopeDetails.length; ++i) {
result.push(new ScopeMirror(this, UNDEFINED, UNDEFINED, i,
scopeDetails[i]));
}
return result;
};
FrameMirror.prototype.evaluate = function(source, throw_on_side_effect = false) {
return MakeMirror(%DebugEvaluate(this.break_id_,
this.details_.frameId(),
this.details_.inlinedFrameIndex(),
source,
throw_on_side_effect));
};
FrameMirror.prototype.invocationText = function() {
// Format frame invoaction (receiver, function and arguments).
var result = '';
var func = this.func();
var receiver = this.receiver();
if (this.isConstructCall()) {
// For constructor frames display new followed by the function name.
result += 'new ';
result += func.name() ? func.name() : '[anonymous]';
} else if (this.isDebuggerFrame()) {
result += '[debugger]';
} else {
// If the receiver has a className which is 'global' don't display it.
var display_receiver =
!receiver.className || (receiver.className() != 'global');
if (display_receiver) {
result += receiver.toText();
}
// Try to find the function as a property in the receiver. Include the
// prototype chain in the lookup.
var property = GetUndefinedMirror();
if (receiver.isObject()) {
for (var r = receiver;
!r.isNull() && property.isUndefined();
r = r.protoObject()) {
property = r.lookupProperty(func);
}
}
if (!property.isUndefined()) {
// The function invoked was found on the receiver. Use the property name
// for the backtrace.
if (!property.isIndexed()) {
if (display_receiver) {
result += '.';
}
result += property.toText();
} else {
result += '[';
result += property.toText();
result += ']';
}
// Also known as - if the name in the function doesn't match the name
// under which it was looked up.
if (func.name() && func.name() != property.name()) {
result += '(aka ' + func.name() + ')';
}
} else {
// The function invoked was not found on the receiver. Use the function
// name if available for the backtrace.
if (display_receiver) {
result += '.';
}
result += func.name() ? func.name() : '[anonymous]';
}
}
// Render arguments for normal frames.
if (!this.isDebuggerFrame()) {
result += '(';
for (var i = 0; i < this.argumentCount(); i++) {
if (i != 0) result += ', ';
if (this.argumentName(i)) {
result += this.argumentName(i);
result += '=';
}
result += this.argumentValue(i).toText();
}
result += ')';
}
if (this.isAtReturn()) {
result += ' returning ';
result += this.returnValue().toText();
}
return result;
};
FrameMirror.prototype.sourceAndPositionText = function() {
// Format source and position.
var result = '';
var func = this.func();
if (func.resolved()) {
var script = func.script();
if (script) {
if (script.name()) {
result += script.name();
} else {
result += '[unnamed]';
}
if (!this.isDebuggerFrame()) {
var location = this.sourceLocation();
result += ' line ';
result += !IS_UNDEFINED(location) ? (location.line + 1) : '?';
result += ' column ';
result += !IS_UNDEFINED(location) ? (location.column + 1) : '?';
if (!IS_UNDEFINED(this.sourcePosition())) {
result += ' (position ' + (this.sourcePosition() + 1) + ')';
}
}
} else {
result += '[no source]';
}
} else {
result += '[unresolved]';
}
return result;
};
FrameMirror.prototype.localsText = function() {
// Format local variables.
var result = '';
var locals_count = this.localCount();
if (locals_count > 0) {
for (var i = 0; i < locals_count; ++i) {
result += ' var ';
result += this.localName(i);
result += ' = ';
result += this.localValue(i).toText();
if (i < locals_count - 1) result += '\n';
}
}
return result;
};
FrameMirror.prototype.restart = function() {
var result = %LiveEditRestartFrame(this.break_id_, this.index_);
if (IS_UNDEFINED(result)) {
result = "Failed to find requested frame";
}
return result;
};
FrameMirror.prototype.toText = function(opt_locals) {
var result = '';
result += '#' + (this.index() <= 9 ? '0' : '') + this.index();
result += ' ';
result += this.invocationText();
result += ' ';
result += this.sourceAndPositionText();
if (opt_locals) {
result += '\n';
result += this.localsText();
}
return result;
};
// This indexes correspond definitions in debug-scopes.h.
var kScopeDetailsTypeIndex = 0;
var kScopeDetailsObjectIndex = 1;
var kScopeDetailsNameIndex = 2;
var kScopeDetailsStartPositionIndex = 3;
var kScopeDetailsEndPositionIndex = 4;
var kScopeDetailsFunctionIndex = 5;
function ScopeDetails(frame, fun, gen, index, opt_details) {
if (frame) {
this.break_id_ = frame.break_id_;
this.details_ = opt_details ||
%GetScopeDetails(frame.break_id_,
frame.details_.frameId(),
frame.details_.inlinedFrameIndex(),
index);
this.frame_id_ = frame.details_.frameId();
this.inlined_frame_id_ = frame.details_.inlinedFrameIndex();
} else if (fun) {
this.details_ = opt_details || %GetFunctionScopeDetails(fun.value(), index);
this.fun_value_ = fun.value();
this.break_id_ = UNDEFINED;
} else {
this.details_ =
opt_details || %GetGeneratorScopeDetails(gen.value(), index);
this.gen_value_ = gen.value();
this.break_id_ = UNDEFINED;
}
this.index_ = index;
}
ScopeDetails.prototype.type = function() {
if (!IS_UNDEFINED(this.break_id_)) {
%CheckExecutionState(this.break_id_);
}
return this.details_[kScopeDetailsTypeIndex];
};
ScopeDetails.prototype.object = function() {
if (!IS_UNDEFINED(this.break_id_)) {
%CheckExecutionState(this.break_id_);
}
return this.details_[kScopeDetailsObjectIndex];
};
ScopeDetails.prototype.name = function() {
if (!IS_UNDEFINED(this.break_id_)) {
%CheckExecutionState(this.break_id_);
}
return this.details_[kScopeDetailsNameIndex];
};
ScopeDetails.prototype.startPosition = function() {
if (!IS_UNDEFINED(this.break_id_)) {
%CheckExecutionState(this.break_id_);
}
return this.details_[kScopeDetailsStartPositionIndex];
}
ScopeDetails.prototype.endPosition = function() {
if (!IS_UNDEFINED(this.break_id_)) {
%CheckExecutionState(this.break_id_);
}
return this.details_[kScopeDetailsEndPositionIndex];
}
ScopeDetails.prototype.func = function() {
if (!IS_UNDEFINED(this.break_id_)) {
%CheckExecutionState(this.break_id_);
}
return this.details_[kScopeDetailsFunctionIndex];
}
ScopeDetails.prototype.setVariableValueImpl = function(name, new_value) {
var raw_res;
if (!IS_UNDEFINED(this.break_id_)) {
%CheckExecutionState(this.break_id_);
raw_res = %SetScopeVariableValue(this.break_id_, this.frame_id_,
this.inlined_frame_id_, this.index_, name, new_value);
} else if (!IS_UNDEFINED(this.fun_value_)) {
raw_res = %SetScopeVariableValue(this.fun_value_, null, null, this.index_,
name, new_value);
} else {
raw_res = %SetScopeVariableValue(this.gen_value_, null, null, this.index_,
name, new_value);
}
if (!raw_res) throw %make_error(kDebugger, "Failed to set variable value");
};
/**
* Mirror object for scope of frame or function. Either frame or function must
* be specified.
* @param {FrameMirror} frame The frame this scope is a part of
* @param {FunctionMirror} function The function this scope is a part of
* @param {GeneratorMirror} gen The generator this scope is a part of
* @param {number} index The scope index in the frame
* @param {Array=} opt_details Raw scope details data
* @constructor
* @extends Mirror
*/
function ScopeMirror(frame, fun, gen, index, opt_details) {
%_Call(Mirror, this, MirrorType.SCOPE_TYPE);
if (frame) {
this.frame_index_ = frame.index_;
} else {
this.frame_index_ = UNDEFINED;
}
this.scope_index_ = index;
this.details_ = new ScopeDetails(frame, fun, gen, index, opt_details);
}
inherits(ScopeMirror, Mirror);
ScopeMirror.prototype.details = function() {
return this.details_;
};
ScopeMirror.prototype.frameIndex = function() {
return this.frame_index_;
};
ScopeMirror.prototype.scopeIndex = function() {
return this.scope_index_;
};
ScopeMirror.prototype.scopeType = function() {
return this.details_.type();
};
ScopeMirror.prototype.scopeObject = function() {
// For local, closure and script scopes create a mirror
// as these objects are created on the fly materializing the local
// or closure scopes and therefore will not preserve identity.
return MakeMirror(this.details_.object());
};
ScopeMirror.prototype.setVariableValue = function(name, new_value) {
this.details_.setVariableValueImpl(name, new_value);
};
/**
* Mirror object for script source.
* @param {Script} script The script object
* @constructor
* @extends Mirror
*/
function ScriptMirror(script) {
%_Call(Mirror, this, MirrorType.SCRIPT_TYPE);
this.script_ = script;
this.context_ = new ContextMirror(script.context_data);
}
inherits(ScriptMirror, Mirror);
ScriptMirror.prototype.value = function() {
return this.script_;
};
ScriptMirror.prototype.name = function() {
return this.script_.name || this.script_.source_url;
};
ScriptMirror.prototype.id = function() {
return this.script_.id;
};
ScriptMirror.prototype.source = function() {
return this.script_.source;
};
ScriptMirror.prototype.setSource = function(source) {
if (!IS_STRING(source)) throw %make_error(kDebugger, "Source is not a string");
%DebugSetScriptSource(this.script_, source);
};
ScriptMirror.prototype.lineOffset = function() {
return this.script_.line_offset;
};
ScriptMirror.prototype.columnOffset = function() {
return this.script_.column_offset;
};
ScriptMirror.prototype.data = function() {
return this.script_.data;
};
ScriptMirror.prototype.scriptType = function() {
return this.script_.type;
};
ScriptMirror.prototype.compilationType = function() {
return this.script_.compilation_type;
};
ScriptMirror.prototype.lineCount = function() {
return %ScriptLineCount(this.script_);
};
ScriptMirror.prototype.locationFromPosition = function(
position, include_resource_offset) {
return %ScriptPositionInfo(this.script_, position, !!include_resource_offset);
};
ScriptMirror.prototype.context = function() {
return this.context_;
};
ScriptMirror.prototype.evalFromScript = function() {
return MakeMirror(this.script_.eval_from_script);
};
ScriptMirror.prototype.evalFromFunctionName = function() {
return MakeMirror(this.script_.eval_from_function_name);
};
ScriptMirror.prototype.evalFromLocation = function() {
var eval_from_script = this.evalFromScript();
if (!eval_from_script.isUndefined()) {
var position = this.script_.eval_from_script_position;
return eval_from_script.locationFromPosition(position, true);
}
};
ScriptMirror.prototype.toText = function() {
var result = '';
result += this.name();
result += ' (lines: ';
if (this.lineOffset() > 0) {
result += this.lineOffset();
result += '-';
result += this.lineOffset() + this.lineCount() - 1;
} else {
result += this.lineCount();
}
result += ')';
return result;
};
/**
* Mirror object for context.
* @param {Object} data The context data
* @constructor
* @extends Mirror
*/
function ContextMirror(data) {
%_Call(Mirror, this, MirrorType.CONTEXT_TYPE);
this.data_ = data;
}
inherits(ContextMirror, Mirror);
ContextMirror.prototype.data = function() {
return this.data_;
};
// ----------------------------------------------------------------------------
// Exports
utils.InstallConstants(global, [
"MakeMirror", MakeMirror,
"ScopeType", ScopeType,
"PropertyType", PropertyType,
"PropertyAttribute", PropertyAttribute,
"Mirror", Mirror,
"ValueMirror", ValueMirror,
"UndefinedMirror", UndefinedMirror,
"NullMirror", NullMirror,
"BooleanMirror", BooleanMirror,
"NumberMirror", NumberMirror,
"StringMirror", StringMirror,
"SymbolMirror", SymbolMirror,
"ObjectMirror", ObjectMirror,
"FunctionMirror", FunctionMirror,
"UnresolvedFunctionMirror", UnresolvedFunctionMirror,
"ArrayMirror", ArrayMirror,
"DateMirror", DateMirror,
"RegExpMirror", RegExpMirror,
"ErrorMirror", ErrorMirror,
"PromiseMirror", PromiseMirror,
"MapMirror", MapMirror,
"SetMirror", SetMirror,
"IteratorMirror", IteratorMirror,
"GeneratorMirror", GeneratorMirror,
"PropertyMirror", PropertyMirror,
"InternalPropertyMirror", InternalPropertyMirror,
"FrameMirror", FrameMirror,
"ScriptMirror", ScriptMirror,
"ScopeMirror", ScopeMirror,
"FrameDetails", FrameDetails,
]);
})
......@@ -600,13 +600,12 @@ void V8Debugger::ScriptCompiled(v8::Local<v8::debug::Script> script,
}
void V8Debugger::BreakProgramRequested(
v8::Local<v8::Context> pausedContext, v8::Local<v8::Object>,
v8::Local<v8::Context> pausedContext,
const std::vector<v8::debug::BreakpointId>& break_points_hit) {
handleProgramBreak(pausedContext, v8::Local<v8::Value>(), break_points_hit);
}
void V8Debugger::ExceptionThrown(v8::Local<v8::Context> pausedContext,
v8::Local<v8::Object>,
v8::Local<v8::Value> exception,
v8::Local<v8::Value> promise,
bool isUncaught) {
......
......@@ -175,10 +175,10 @@ class V8Debugger : public v8::debug::DebugDelegate {
void ScriptCompiled(v8::Local<v8::debug::Script> script, bool is_live_edited,
bool has_compile_error) override;
void BreakProgramRequested(
v8::Local<v8::Context> paused_context, v8::Local<v8::Object>,
v8::Local<v8::Context> paused_context,
const std::vector<v8::debug::BreakpointId>& break_points_hit) override;
void ExceptionThrown(v8::Local<v8::Context> paused_context,
v8::Local<v8::Object>, v8::Local<v8::Value> exception,
v8::Local<v8::Value> exception,
v8::Local<v8::Value> promise, bool is_uncaught) override;
bool IsFunctionBlackboxed(v8::Local<v8::debug::Script> script,
const v8::debug::Location& start,
......
......@@ -170,18 +170,6 @@ Node* IntrinsicsGenerator::IsTypedArray(
return IsInstanceType(input, JS_TYPED_ARRAY_TYPE);
}
Node* IntrinsicsGenerator::IsJSMap(
const InterpreterAssembler::RegListNodePair& args, Node* context) {
Node* input = __ LoadRegisterFromRegisterList(args, 0);
return IsInstanceType(input, JS_MAP_TYPE);
}
Node* IntrinsicsGenerator::IsJSSet(
const InterpreterAssembler::RegListNodePair& args, Node* context) {
Node* input = __ LoadRegisterFromRegisterList(args, 0);
return IsInstanceType(input, JS_SET_TYPE);
}
Node* IntrinsicsGenerator::IsJSWeakMap(
const InterpreterAssembler::RegListNodePair& args, Node* context) {
Node* input = __ LoadRegisterFromRegisterList(args, 0);
......
......@@ -27,10 +27,8 @@ namespace interpreter {
V(CreateAsyncFromSyncIterator, create_async_from_sync_iterator, 1) \
V(HasProperty, has_property, 2) \
V(IsArray, is_array, 1) \
V(IsJSMap, is_js_map, 1) \
V(IsJSProxy, is_js_proxy, 1) \
V(IsJSReceiver, is_js_receiver, 1) \
V(IsJSSet, is_js_set, 1) \
V(IsJSWeakMap, is_js_weak_map, 1) \
V(IsJSWeakSet, is_js_weak_set, 1) \
V(IsSmi, is_smi, 1) \
......
......@@ -13,18 +13,6 @@
namespace v8 {
namespace internal {
RUNTIME_FUNCTION(Runtime_IsJSMapIterator) {
SealHandleScope shs(isolate);
DCHECK_EQ(1, args.length());
return isolate->heap()->ToBoolean(args[0]->IsJSMapIterator());
}
RUNTIME_FUNCTION(Runtime_IsJSSetIterator) {
SealHandleScope shs(isolate);
DCHECK_EQ(1, args.length());
return isolate->heap()->ToBoolean(args[0]->IsJSSetIterator());
}
RUNTIME_FUNCTION(Runtime_TheHole) {
SealHandleScope shs(isolate);
DCHECK_EQ(0, args.length());
......@@ -123,6 +111,14 @@ RUNTIME_FUNCTION(Runtime_WeakCollectionDelete) {
return isolate->heap()->ToBoolean(was_present);
}
RUNTIME_FUNCTION(Runtime_GetWeakSetValues) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, holder, 0);
CONVERT_NUMBER_CHECKED(int, max_values, Int32, args[1]);
CHECK_GE(max_values, 0);
return *JSWeakCollection::GetEntries(holder, max_values);
}
RUNTIME_FUNCTION(Runtime_WeakCollectionSet) {
HandleScope scope(isolate);
......@@ -147,30 +143,6 @@ RUNTIME_FUNCTION(Runtime_WeakCollectionSet) {
return *weak_collection;
}
RUNTIME_FUNCTION(Runtime_GetWeakSetValues) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, holder, 0);
CONVERT_NUMBER_CHECKED(int, max_values, Int32, args[1]);
CHECK_GE(max_values, 0);
return *JSWeakCollection::GetEntries(holder, max_values);
}
RUNTIME_FUNCTION(Runtime_IsJSMap) {
SealHandleScope shs(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_CHECKED(Object, obj, 0);
return isolate->heap()->ToBoolean(obj->IsJSMap());
}
RUNTIME_FUNCTION(Runtime_IsJSSet) {
SealHandleScope shs(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_CHECKED(Object, obj, 0);
return isolate->heap()->ToBoolean(obj->IsJSSet());
}
RUNTIME_FUNCTION(Runtime_IsJSWeakMap) {
SealHandleScope shs(isolate);
DCHECK_EQ(1, args.length());
......
......@@ -139,44 +139,6 @@ RUNTIME_FUNCTION(Runtime_ScheduleBreak) {
return isolate->heap()->undefined_value();
}
static Handle<Object> DebugGetProperty(LookupIterator* it,
bool* has_caught = nullptr) {
for (; it->IsFound(); it->Next()) {
switch (it->state()) {
case LookupIterator::NOT_FOUND:
case LookupIterator::TRANSITION:
UNREACHABLE();
case LookupIterator::ACCESS_CHECK:
// Ignore access checks.
break;
case LookupIterator::INTEGER_INDEXED_EXOTIC:
case LookupIterator::INTERCEPTOR:
case LookupIterator::JSPROXY:
return it->isolate()->factory()->undefined_value();
case LookupIterator::ACCESSOR: {
Handle<Object> accessors = it->GetAccessors();
if (!accessors->IsAccessorInfo()) {
return it->isolate()->factory()->undefined_value();
}
MaybeHandle<Object> maybe_result =
JSObject::GetPropertyWithAccessor(it);
Handle<Object> result;
if (!maybe_result.ToHandle(&result)) {
result = handle(it->isolate()->pending_exception(), it->isolate());
it->isolate()->clear_pending_exception();
if (has_caught != nullptr) *has_caught = true;
}
return result;
}
case LookupIterator::DATA:
return it->GetDataValue();
}
}
return it->isolate()->factory()->undefined_value();
}
template <class IteratorType>
static MaybeHandle<JSArray> GetIteratorInternalProperties(
Isolate* isolate, Handle<IteratorType> object) {
......@@ -332,627 +294,6 @@ MaybeHandle<JSArray> Runtime::GetInternalProperties(Isolate* isolate,
return factory->NewJSArray(0);
}
RUNTIME_FUNCTION(Runtime_DebugGetInternalProperties) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
RETURN_RESULT_OR_FAILURE(isolate,
Runtime::GetInternalProperties(isolate, obj));
}
// Get debugger related details for an object property, in the following format:
// 0: Property value
// 1: Property details
// 2: Property value is exception
// 3: Getter function if defined
// 4: Setter function if defined
// Items 2-4 are only filled if the property has either a getter or a setter.
RUNTIME_FUNCTION(Runtime_DebugGetPropertyDetails) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, name_obj, 1);
// Convert the {name_obj} to a Name.
Handle<Name> name;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
Object::ToName(isolate, name_obj));
// Make sure to set the current context to the context before the debugger was
// entered (if the debugger is entered). The reason for switching context here
// is that for some property lookups (accessors and interceptors) callbacks
// into the embedding application can occur, and the embedding application
// could have the assumption that its own native context is the current
// context and not some internal debugger context.
SaveContext save(isolate);
if (isolate->debug()->in_debug_scope()) {
isolate->set_context(*isolate->debug()->debugger_entry()->GetContext());
}
// Check if the name is trivially convertible to an index and get the element
// if so.
uint32_t index;
// TODO(verwaest): Make sure DebugGetProperty can handle arrays, and remove
// this special case.
if (name->AsArrayIndex(&index)) {
Handle<FixedArray> details = isolate->factory()->NewFixedArray(2);
Handle<Object> element_or_char;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, element_or_char, JSReceiver::GetElement(isolate, obj, index));
details->set(0, *element_or_char);
details->set(1, PropertyDetails::Empty().AsSmi());
return *isolate->factory()->NewJSArrayWithElements(details);
}
LookupIterator it(obj, name, LookupIterator::OWN);
bool has_caught = false;
Handle<Object> value = DebugGetProperty(&it, &has_caught);
if (!it.IsFound()) return isolate->heap()->undefined_value();
Handle<Object> maybe_pair;
if (it.state() == LookupIterator::ACCESSOR) {
maybe_pair = it.GetAccessors();
}
// If the callback object is a fixed array then it contains JavaScript
// getter and/or setter.
bool has_js_accessors = !maybe_pair.is_null() && maybe_pair->IsAccessorPair();
Handle<FixedArray> details =
isolate->factory()->NewFixedArray(has_js_accessors ? 6 : 3);
details->set(0, *value);
// TODO(verwaest): Get rid of this random way of handling interceptors.
PropertyDetails d = it.state() == LookupIterator::INTERCEPTOR
? PropertyDetails::Empty()
: it.property_details();
details->set(1, d.AsSmi());
details->set(
2, isolate->heap()->ToBoolean(it.state() == LookupIterator::INTERCEPTOR));
if (has_js_accessors) {
Handle<AccessorPair> accessors = Handle<AccessorPair>::cast(maybe_pair);
details->set(3, isolate->heap()->ToBoolean(has_caught));
Handle<Object> getter =
AccessorPair::GetComponent(accessors, ACCESSOR_GETTER);
Handle<Object> setter =
AccessorPair::GetComponent(accessors, ACCESSOR_SETTER);
details->set(4, *getter);
details->set(5, *setter);
}
return *isolate->factory()->NewJSArrayWithElements(details);
}
RUNTIME_FUNCTION(Runtime_DebugGetProperty) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
LookupIterator it(obj, name);
return *DebugGetProperty(&it);
}
// Return the property kind calculated from the property details.
// args[0]: smi with property details.
RUNTIME_FUNCTION(Runtime_DebugPropertyKindFromDetails) {
SealHandleScope shs(isolate);
DCHECK_EQ(1, args.length());
CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
return Smi::FromInt(static_cast<int>(details.kind()));
}
// Return the property attribute calculated from the property details.
// args[0]: smi with property details.
RUNTIME_FUNCTION(Runtime_DebugPropertyAttributesFromDetails) {
SealHandleScope shs(isolate);
DCHECK_EQ(1, args.length());
CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
return Smi::FromInt(static_cast<int>(details.attributes()));
}
RUNTIME_FUNCTION(Runtime_CheckExecutionState) {
SealHandleScope shs(isolate);
DCHECK_EQ(1, args.length());
CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
CHECK(isolate->debug()->CheckExecutionState(break_id));
return isolate->heap()->true_value();
}
RUNTIME_FUNCTION(Runtime_GetFrameCount) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
CHECK(isolate->debug()->CheckExecutionState(break_id));
// Count all frames which are relevant to debugging stack trace.
int n = 0;
StackFrame::Id id = isolate->debug()->break_frame_id();
if (id == StackFrame::NO_ID) {
// If there is no JavaScript stack frame count is 0.
return Smi::kZero;
}
std::vector<FrameSummary> frames;
for (StackTraceFrameIterator it(isolate, id); !it.done(); it.Advance()) {
frames.clear();
it.frame()->Summarize(&frames);
for (size_t i = frames.size(); i != 0; i--) {
// Omit functions from native and extension scripts.
if (frames[i - 1].is_subject_to_debugging()) n++;
}
}
return Smi::FromInt(n);
}
static const int kFrameDetailsFrameIdIndex = 0;
static const int kFrameDetailsReceiverIndex = 1;
static const int kFrameDetailsFunctionIndex = 2;
static const int kFrameDetailsScriptIndex = 3;
static const int kFrameDetailsArgumentCountIndex = 4;
static const int kFrameDetailsLocalCountIndex = 5;
static const int kFrameDetailsSourcePositionIndex = 6;
static const int kFrameDetailsConstructCallIndex = 7;
static const int kFrameDetailsAtReturnIndex = 8;
static const int kFrameDetailsFlagsIndex = 9;
static const int kFrameDetailsFirstDynamicIndex = 10;
// Return an array with frame details
// args[0]: number: break id
// args[1]: number: frame index
//
// The array returned contains the following information:
// 0: Frame id
// 1: Receiver
// 2: Function
// 3: Script
// 4: Argument count
// 5: Local count
// 6: Source position
// 7: Constructor call
// 8: Is at return
// 9: Flags
// Arguments name, value
// Locals name, value
// Return value if any
RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
CHECK(isolate->debug()->CheckExecutionState(break_id));
CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
Heap* heap = isolate->heap();
// Find the relevant frame with the requested index.
StackFrame::Id id = isolate->debug()->break_frame_id();
if (id == StackFrame::NO_ID) {
// If there are no JavaScript stack frames return undefined.
return heap->undefined_value();
}
StackTraceFrameIterator it(isolate, id);
// Inlined frame index in optimized frame, starting from outer function.
int inlined_frame_index =
DebugFrameHelper::FindIndexedNonNativeFrame(&it, index);
if (inlined_frame_index == -1) return heap->undefined_value();
FrameInspector frame_inspector(it.frame(), inlined_frame_index, isolate);
// Traverse the saved contexts chain to find the active context for the
// selected frame.
SaveContext* save =
DebugFrameHelper::FindSavedContextForFrame(isolate, it.frame());
// Get the frame id.
Handle<Object> frame_id(DebugFrameHelper::WrapFrameId(it.frame()->id()),
isolate);
if (frame_inspector.IsWasm()) {
// Create the details array (no dynamic information for wasm).
Handle<FixedArray> details =
isolate->factory()->NewFixedArray(kFrameDetailsFirstDynamicIndex);
// Add the frame id.
details->set(kFrameDetailsFrameIdIndex, *frame_id);
// Add the function name.
Handle<String> func_name = frame_inspector.GetFunctionName();
details->set(kFrameDetailsFunctionIndex, *func_name);
// Add the script wrapper
Handle<Object> script_wrapper =
Script::GetWrapper(frame_inspector.GetScript());
details->set(kFrameDetailsScriptIndex, *script_wrapper);
// Add the arguments count.
details->set(kFrameDetailsArgumentCountIndex, Smi::kZero);
// Add the locals count
details->set(kFrameDetailsLocalCountIndex, Smi::kZero);
// Add the source position.
int position = frame_inspector.GetSourcePosition();
details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
// Add the constructor information.
details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(false));
// Add the at return information.
details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(false));
// Add flags to indicate information on whether this frame is
// bit 0: invoked in the debugger context.
// bit 1: optimized frame.
// bit 2: inlined in optimized frame
int flags = inlined_frame_index << 2;
if (*save->context() == *isolate->debug()->debug_context()) {
flags |= 1 << 0;
}
details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
return *isolate->factory()->NewJSArrayWithElements(details);
}
// Find source position in unoptimized code.
int position = frame_inspector.GetSourcePosition();
// Handle JavaScript frames.
bool is_optimized = it.frame()->is_optimized();
// Check for constructor frame.
bool constructor = frame_inspector.IsConstructor();
// Get scope info and read from it for local variable information.
Handle<JSFunction> function =
Handle<JSFunction>::cast(frame_inspector.GetFunction());
CHECK(function->shared()->IsSubjectToDebugging());
Handle<SharedFunctionInfo> shared(function->shared());
Handle<ScopeInfo> scope_info(shared->scope_info());
DCHECK(*scope_info != ScopeInfo::Empty(isolate));
// Get the locals names and values into a temporary array.
Handle<Object> maybe_context = frame_inspector.GetContext();
const int local_count_with_synthetic = maybe_context->IsContext()
? scope_info->LocalCount()
: scope_info->StackLocalCount();
int local_count = local_count_with_synthetic;
for (int slot = 0; slot < local_count_with_synthetic; ++slot) {
// Hide compiler-introduced temporary variables, whether on the stack or on
// the context.
if (ScopeInfo::VariableIsSynthetic(scope_info->LocalName(slot))) {
local_count--;
}
}
std::vector<Handle<Object>> locals;
// Fill in the values of the locals.
int i = 0;
for (; i < scope_info->StackLocalCount(); ++i) {
// Use the value from the stack.
if (ScopeInfo::VariableIsSynthetic(scope_info->LocalName(i))) continue;
locals.emplace_back(scope_info->LocalName(i), isolate);
Handle<Object> value =
frame_inspector.GetExpression(scope_info->StackLocalIndex(i));
// TODO(yangguo): We convert optimized out values to {undefined} when they
// are passed to the debugger. Eventually we should handle them somehow.
if (value->IsOptimizedOut(isolate)) {
value = isolate->factory()->undefined_value();
}
locals.push_back(value);
}
if (static_cast<int>(locals.size()) < local_count * 2) {
// Get the context containing declarations.
DCHECK(maybe_context->IsContext());
Handle<Context> context(Context::cast(*maybe_context)->closure_context());
for (; i < scope_info->LocalCount(); ++i) {
Handle<String> name(scope_info->LocalName(i));
if (ScopeInfo::VariableIsSynthetic(*name)) continue;
VariableMode mode;
InitializationFlag init_flag;
MaybeAssignedFlag maybe_assigned_flag;
locals.push_back(name);
int context_slot_index = ScopeInfo::ContextSlotIndex(
scope_info, name, &mode, &init_flag, &maybe_assigned_flag);
Object* value = context->get(context_slot_index);
locals.emplace_back(value, isolate);
}
}
// Check whether this frame is positioned at return. If not top
// frame or if the frame is optimized it cannot be at a return.
bool at_return = false;
if (!is_optimized && index == 0) {
at_return = isolate->debug()->IsBreakAtReturn(it.javascript_frame());
}
// If positioned just before return find the value to be returned and add it
// to the frame information.
Handle<Object> return_value = isolate->factory()->undefined_value();
if (at_return) {
return_value = handle(isolate->debug()->return_value(), isolate);
}
// Now advance to the arguments adapter frame (if any). It contains all
// the provided parameters whereas the function frame always have the number
// of arguments matching the functions parameters. The rest of the
// information (except for what is collected above) is the same.
if ((inlined_frame_index == 0) &&
it.javascript_frame()->has_adapted_arguments()) {
it.AdvanceOneFrame();
DCHECK(it.frame()->is_arguments_adaptor());
frame_inspector.SetArgumentsFrame(it.frame());
}
// Find the number of arguments to fill. At least fill the number of
// parameters for the function and fill more if more parameters are provided.
int argument_count = scope_info->ParameterCount();
if (argument_count < frame_inspector.GetParametersCount()) {
argument_count = frame_inspector.GetParametersCount();
}
// Calculate the size of the result.
int details_size = kFrameDetailsFirstDynamicIndex +
2 * (argument_count + local_count) + (at_return ? 1 : 0);
Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
// Add the frame id.
details->set(kFrameDetailsFrameIdIndex, *frame_id);
// Add the function (same as in function frame).
details->set(kFrameDetailsFunctionIndex, *(frame_inspector.GetFunction()));
// Add the script wrapper
Handle<Object> script_wrapper =
Script::GetWrapper(frame_inspector.GetScript());
details->set(kFrameDetailsScriptIndex, *script_wrapper);
// Add the arguments count.
details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
// Add the locals count
details->set(kFrameDetailsLocalCountIndex, Smi::FromInt(local_count));
// Add the source position.
if (position != kNoSourcePosition) {
details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
} else {
details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value());
}
// Add the constructor information.
details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor));
// Add the at return information.
details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return));
// Add flags to indicate information on whether this frame is
// bit 0: invoked in the debugger context.
// bit 1: optimized frame.
// bit 2: inlined in optimized frame
int flags = 0;
if (*save->context() == *isolate->debug()->debug_context()) {
flags |= 1 << 0;
}
if (is_optimized) {
flags |= 1 << 1;
flags |= inlined_frame_index << 2;
}
details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
// Fill the dynamic part.
int details_index = kFrameDetailsFirstDynamicIndex;
// Add arguments name and value.
for (int i = 0; i < argument_count; i++) {
// Name of the argument.
if (i < scope_info->ParameterCount()) {
details->set(details_index++, scope_info->ParameterName(i));
} else {
details->set(details_index++, heap->undefined_value());
}
// Parameter value.
if (i < frame_inspector.GetParametersCount()) {
// Get the value from the stack.
details->set(details_index++, *(frame_inspector.GetParameter(i)));
} else {
details->set(details_index++, heap->undefined_value());
}
}
// Add locals name and value from the temporary copy from the function frame.
for (const auto& local : locals) details->set(details_index++, *local);
// Add the value being returned.
if (at_return) {
details->set(details_index++, *return_value);
}
// Add the receiver (same as in function frame).
Handle<Object> receiver = frame_inspector.GetReceiver();
DCHECK(function->shared()->IsUserJavaScript());
// Optimized frames only restore the receiver as best-effort (see
// OptimizedFrame::Summarize).
DCHECK_IMPLIES(!is_optimized && is_sloppy(shared->language_mode()),
receiver->IsJSReceiver());
details->set(kFrameDetailsReceiverIndex, *receiver);
DCHECK_EQ(details_size, details_index);
return *isolate->factory()->NewJSArrayWithElements(details);
}
RUNTIME_FUNCTION(Runtime_GetScopeCount) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
CHECK(isolate->debug()->CheckExecutionState(break_id));
CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
// Get the frame where the debugging is performed.
StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
StackTraceFrameIterator it(isolate, id);
StandardFrame* frame = it.frame();
if (it.frame()->is_wasm()) return 0;
FrameInspector frame_inspector(frame, 0, isolate);
// Count the visible scopes.
int n = 0;
for (ScopeIterator it(isolate, &frame_inspector); !it.Done(); it.Next()) {
n++;
}
return Smi::FromInt(n);
}
// Return an array with scope details
// args[0]: number: break id
// args[1]: number: frame index
// args[2]: number: inlined frame index
// args[3]: number: scope index
//
// The array returned contains the following information:
// 0: Scope type
// 1: Scope object
RUNTIME_FUNCTION(Runtime_GetScopeDetails) {
HandleScope scope(isolate);
DCHECK_EQ(4, args.length());
CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
CHECK(isolate->debug()->CheckExecutionState(break_id));
CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
// Get the frame where the debugging is performed.
StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
StackTraceFrameIterator frame_it(isolate, id);
// Wasm has no scopes, this must be javascript.
JavaScriptFrame* frame = JavaScriptFrame::cast(frame_it.frame());
FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
// Find the requested scope.
int n = 0;
ScopeIterator it(isolate, &frame_inspector);
for (; !it.Done() && n < index; it.Next()) {
n++;
}
if (it.Done()) {
return isolate->heap()->undefined_value();
}
RETURN_RESULT_OR_FAILURE(isolate, it.MaterializeScopeDetails());
}
// Return an array of scope details
// args[0]: number: break id
// args[1]: number: frame index
// args[2]: number: inlined frame index
// args[3]: boolean: ignore nested scopes
//
// The array returned contains arrays with the following information:
// 0: Scope type
// 1: Scope object
RUNTIME_FUNCTION(Runtime_GetAllScopesDetails) {
HandleScope scope(isolate);
DCHECK(args.length() == 3 || args.length() == 4);
CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
CHECK(isolate->debug()->CheckExecutionState(break_id));
CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
CONVERT_NUMBER_CHECKED(int, inlined_frame_index, Int32, args[2]);
ScopeIterator::Option option = ScopeIterator::DEFAULT;
if (args.length() == 4) {
CONVERT_BOOLEAN_ARG_CHECKED(flag, 3);
if (flag) option = ScopeIterator::IGNORE_NESTED_SCOPES;
}
// Get the frame where the debugging is performed.
StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
StackTraceFrameIterator frame_it(isolate, id);
StandardFrame* frame = frame_it.frame();
// Handle wasm frames specially. They provide exactly two scopes (global /
// local).
if (frame->is_wasm_interpreter_entry()) {
Handle<WasmDebugInfo> debug_info(
WasmInterpreterEntryFrame::cast(frame)->debug_info(), isolate);
return *WasmDebugInfo::GetScopeDetails(debug_info, frame->fp(),
inlined_frame_index);
}
FrameInspector frame_inspector(frame, inlined_frame_index, isolate);
std::vector<Handle<JSObject>> result;
ScopeIterator it(isolate, &frame_inspector, option);
for (; !it.Done(); it.Next()) {
Handle<JSObject> details;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details,
it.MaterializeScopeDetails());
result.push_back(details);
}
int result_size = static_cast<int>(result.size());
Handle<FixedArray> array = isolate->factory()->NewFixedArray(result_size);
for (int i = 0; i < result_size; ++i) {
array->set(i, *result[i]);
}
return *isolate->factory()->NewJSArrayWithElements(array);
}
RUNTIME_FUNCTION(Runtime_GetFunctionScopeCount) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
// Check arguments.
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
// Count the visible scopes.
int n = 0;
if (function->IsJSFunction()) {
for (ScopeIterator it(isolate, Handle<JSFunction>::cast(function));
!it.Done(); it.Next()) {
n++;
}
}
return Smi::FromInt(n);
}
RUNTIME_FUNCTION(Runtime_GetFunctionScopeDetails) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
// Check arguments.
CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
// Find the requested scope.
int n = 0;
ScopeIterator it(isolate, fun);
for (; !it.Done() && n < index; it.Next()) {
n++;
}
if (it.Done()) {
return isolate->heap()->undefined_value();
}
RETURN_RESULT_OR_FAILURE(isolate, it.MaterializeScopeDetails());
}
RUNTIME_FUNCTION(Runtime_GetGeneratorScopeCount) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
......@@ -1018,52 +359,22 @@ static bool SetScopeVariableValue(ScopeIterator* it, int index,
return it->SetVariableValue(variable_name, new_value);
}
// Change variable value in closure or local scope
// args[0]: number or JsFunction: break id or function
// args[1]: number: frame index (when arg[0] is break id)
// args[2]: number: inlined frame index (when arg[0] is break id)
// args[3]: number: scope index
// args[4]: string: variable name
// args[5]: object: new value
// args[1]: number: scope index
// args[2]: string: variable name
// args[3]: object: new value
//
// Return true if success and false otherwise
RUNTIME_FUNCTION(Runtime_SetScopeVariableValue) {
RUNTIME_FUNCTION(Runtime_SetGeneratorScopeVariableValue) {
HandleScope scope(isolate);
DCHECK_EQ(6, args.length());
// Check arguments.
CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
CONVERT_ARG_HANDLE_CHECKED(String, variable_name, 4);
CONVERT_ARG_HANDLE_CHECKED(Object, new_value, 5);
bool res;
if (args[0]->IsNumber()) {
CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
CHECK(isolate->debug()->CheckExecutionState(break_id));
CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
// Get the frame where the debugging is performed.
StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
StackTraceFrameIterator frame_it(isolate, id);
// Wasm has no scopes, this must be javascript.
JavaScriptFrame* frame = JavaScriptFrame::cast(frame_it.frame());
FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
ScopeIterator it(isolate, &frame_inspector);
res = SetScopeVariableValue(&it, index, variable_name, new_value);
} else if (args[0]->IsJSFunction()) {
CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
ScopeIterator it(isolate, fun);
res = SetScopeVariableValue(&it, index, variable_name, new_value);
} else {
CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, gen, 0);
ScopeIterator it(isolate, gen);
res = SetScopeVariableValue(&it, index, variable_name, new_value);
}
DCHECK_EQ(4, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, gen, 0);
CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
CONVERT_ARG_HANDLE_CHECKED(String, variable_name, 2);
CONVERT_ARG_HANDLE_CHECKED(Object, new_value, 3);
ScopeIterator it(isolate, gen);
bool res = SetScopeVariableValue(&it, index, variable_name, new_value);
return isolate->heap()->ToBoolean(res);
}
......@@ -1086,24 +397,6 @@ RUNTIME_FUNCTION(Runtime_GetBreakLocations) {
}
// Change the state of break on exceptions.
// args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
// args[1]: Boolean indicating on/off.
RUNTIME_FUNCTION(Runtime_ChangeBreakOnException) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
CONVERT_BOOLEAN_ARG_CHECKED(enable, 1);
// If the number doesn't match an enum value, the ChangeBreakOnException
// function will default to affecting caught exceptions.
ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
// Update break point state.
isolate->debug()->ChangeBreakOnException(type, enable);
return isolate->heap()->undefined_value();
}
// Returns the state of break on exceptions
// args[0]: boolean indicating uncaught exceptions
RUNTIME_FUNCTION(Runtime_IsBreakOnException) {
......@@ -1116,37 +409,6 @@ RUNTIME_FUNCTION(Runtime_IsBreakOnException) {
return Smi::FromInt(result);
}
// Prepare for stepping
// args[0]: break id for checking execution state
// args[1]: step action from the enumeration StepAction
// args[2]: number of times to perform the step, for step out it is the number
// of frames to step down.
RUNTIME_FUNCTION(Runtime_PrepareStep) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
CHECK(isolate->debug()->CheckExecutionState(break_id));
if (!args[1]->IsNumber()) {
return isolate->Throw(isolate->heap()->illegal_argument_string());
}
// Get the step action and check validity.
StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
if (step_action != StepIn && step_action != StepNext &&
step_action != StepOut) {
return isolate->Throw(isolate->heap()->illegal_argument_string());
}
// Clear all current stepping setup.
isolate->debug()->ClearStepping();
// Prepare step.
isolate->debug()->PrepareStep(static_cast<StepAction>(step_action));
return isolate->heap()->undefined_value();
}
// Clear all stepping set by PrepareStep.
RUNTIME_FUNCTION(Runtime_ClearStepping) {
HandleScope scope(isolate);
......@@ -1156,45 +418,6 @@ RUNTIME_FUNCTION(Runtime_ClearStepping) {
return isolate->heap()->undefined_value();
}
RUNTIME_FUNCTION(Runtime_DebugEvaluate) {
HandleScope scope(isolate);
// Check the execution state and decode arguments frame and source to be
// evaluated.
DCHECK_EQ(5, args.length());
CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
CHECK(isolate->debug()->CheckExecutionState(break_id));
CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
CONVERT_ARG_HANDLE_CHECKED(String, source, 3);
CONVERT_BOOLEAN_ARG_CHECKED(throw_on_side_effect, 4);
StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
RETURN_RESULT_OR_FAILURE(
isolate, DebugEvaluate::Local(isolate, id, inlined_jsframe_index, source,
throw_on_side_effect));
}
RUNTIME_FUNCTION(Runtime_DebugEvaluateGlobal) {
HandleScope scope(isolate);
// Check the execution state and decode arguments frame and source to be
// evaluated.
DCHECK_EQ(2, args.length());
CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
CHECK(isolate->debug()->CheckExecutionState(break_id));
CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
RETURN_RESULT_OR_FAILURE(isolate,
DebugEvaluate::Global(isolate, source, false));
}
RUNTIME_FUNCTION(Runtime_DebugGetLoadedScripts) {
HandleScope scope(isolate);
DCHECK_EQ(0, args.length());
......@@ -1226,146 +449,6 @@ RUNTIME_FUNCTION(Runtime_DebugGetLoadedScripts) {
return *isolate->factory()->NewJSArrayWithElements(instances);
}
static bool HasInPrototypeChainIgnoringProxies(Isolate* isolate,
JSObject* object,
Object* proto) {
PrototypeIterator iter(isolate, object, kStartAtReceiver);
while (true) {
iter.AdvanceIgnoringProxies();
if (iter.IsAtEnd()) return false;
if (iter.GetCurrent() == proto) return true;
}
}
// Scan the heap for objects with direct references to an object
// args[0]: the object to find references to
// args[1]: constructor function for instances to exclude (Mirror)
// args[2]: the the maximum number of objects to return
RUNTIME_FUNCTION(Runtime_DebugReferencedBy) {
HandleScope scope(isolate);
DCHECK_EQ(3, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, filter, 1);
CHECK(filter->IsUndefined(isolate) || filter->IsJSObject());
CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
CHECK_GE(max_references, 0);
std::vector<Handle<JSObject>> instances;
Heap* heap = isolate->heap();
{
HeapIterator iterator(heap, HeapIterator::kFilterUnreachable);
// Get the constructor function for context extension and arguments array.
Object* arguments_fun = isolate->sloppy_arguments_map()->GetConstructor();
HeapObject* heap_obj;
while ((heap_obj = iterator.next()) != nullptr) {
if (!heap_obj->IsJSObject()) continue;
JSObject* obj = JSObject::cast(heap_obj);
if (obj->IsJSContextExtensionObject()) continue;
if (obj->map()->GetConstructor() == arguments_fun) continue;
if (!obj->ReferencesObject(*target)) continue;
// Check filter if supplied. This is normally used to avoid
// references from mirror objects.
if (!filter->IsUndefined(isolate) &&
HasInPrototypeChainIgnoringProxies(isolate, obj, *filter)) {
continue;
}
if (obj->IsJSGlobalObject()) {
obj = JSGlobalObject::cast(obj)->global_proxy();
}
instances.emplace_back(obj);
if (static_cast<int32_t>(instances.size()) == max_references) break;
}
// Iterate the rest of the heap to satisfy HeapIterator constraints.
while (iterator.next()) {
}
}
Handle<FixedArray> result;
if (instances.size() == 1 && instances.back().is_identical_to(target)) {
// Check for circular reference only. This can happen when the object is
// only referenced from mirrors and has a circular reference in which case
// the object is not really alive and would have been garbage collected if
// not referenced from the mirror.
result = isolate->factory()->empty_fixed_array();
} else {
int instances_size = static_cast<int>(instances.size());
result = isolate->factory()->NewFixedArray(instances_size);
for (int i = 0; i < instances_size; ++i) result->set(i, *instances[i]);
}
return *isolate->factory()->NewJSArrayWithElements(result);
}
// Scan the heap for objects constructed by a specific function.
// args[0]: the constructor to find instances of
// args[1]: the the maximum number of objects to return
RUNTIME_FUNCTION(Runtime_DebugConstructedBy) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0);
CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
CHECK_GE(max_references, 0);
std::vector<Handle<JSObject>> instances;
Heap* heap = isolate->heap();
{
HeapIterator iterator(heap, HeapIterator::kFilterUnreachable);
HeapObject* heap_obj;
while ((heap_obj = iterator.next()) != nullptr) {
if (!heap_obj->IsJSObject()) continue;
JSObject* obj = JSObject::cast(heap_obj);
if (obj->map()->GetConstructor() != *constructor) continue;
instances.emplace_back(obj);
if (static_cast<int32_t>(instances.size()) == max_references) break;
}
// Iterate the rest of the heap to satisfy HeapIterator constraints.
while (iterator.next()) {
}
}
int instances_size = static_cast<int>(instances.size());
Handle<FixedArray> result = isolate->factory()->NewFixedArray(instances_size);
for (int i = 0; i < instances_size; ++i) result->set(i, *instances[i]);
return *isolate->factory()->NewJSArrayWithElements(result);
}
// Find the effective prototype object as returned by __proto__.
// args[0]: the object to find the prototype for.
RUNTIME_FUNCTION(Runtime_DebugGetPrototype) {
HandleScope shs(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
// TODO(1543): Come up with a solution for clients to handle potential errors
// thrown by an intermediate proxy.
RETURN_RESULT_OR_FAILURE(isolate, JSReceiver::GetPrototype(isolate, obj));
}
// Patches script source (should be called upon BeforeCompile event).
// TODO(5530): Remove once uses in debug.js are gone.
RUNTIME_FUNCTION(Runtime_DebugSetScriptSource) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSValue, script_wrapper, 0);
CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
CHECK(script_wrapper->value()->IsScript());
Handle<Script> script(Script::cast(script_wrapper->value()));
// The following condition is not guaranteed to hold and a failure is also
// propagated to callers. Hence we fail gracefully here and don't crash.
if (script->compilation_state() != Script::COMPILATION_STATE_INITIAL) {
return isolate->ThrowIllegalOperation();
}
script->set_source(*source);
return isolate->heap()->undefined_value();
}
RUNTIME_FUNCTION(Runtime_FunctionGetInferredName) {
SealHandleScope shs(isolate);
......@@ -1379,22 +462,6 @@ RUNTIME_FUNCTION(Runtime_FunctionGetInferredName) {
}
RUNTIME_FUNCTION(Runtime_FunctionGetDebugName) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
if (function->IsJSBoundFunction()) {
RETURN_RESULT_OR_FAILURE(
isolate, JSBoundFunction::GetName(
isolate, Handle<JSBoundFunction>::cast(function)));
} else {
return *JSFunction::GetDebugName(Handle<JSFunction>::cast(function));
}
}
RUNTIME_FUNCTION(Runtime_GetDebugContext) {
HandleScope scope(isolate);
DCHECK_EQ(0, args.length());
......@@ -1465,26 +532,6 @@ RUNTIME_FUNCTION(Runtime_GetScript) {
return *Script::GetWrapper(found);
}
// TODO(5530): Remove once uses in debug.js are gone.
RUNTIME_FUNCTION(Runtime_ScriptLineCount) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_CHECKED(JSValue, script, 0);
CHECK(script->value()->IsScript());
Handle<Script> script_handle(Script::cast(script->value()), isolate);
if (script_handle->type() == Script::TYPE_WASM) {
// Return 0 for now; this function will disappear soon anyway.
return Smi::FromInt(0);
}
Script::InitLineEnds(script_handle);
FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
return Smi::FromInt(line_ends_array->length());
}
namespace {
int ScriptLinePosition(Handle<Script> script, int line) {
......
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/runtime/runtime-utils.h"
#include "src/arguments.h"
#include "src/base/platform/time.h"
#include "src/conversions-inl.h"
#include "src/futex-emulation.h"
#include "src/globals.h"
namespace v8 {
namespace internal {
RUNTIME_FUNCTION(Runtime_ErrorToString) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, recv, 0);
RETURN_RESULT_OR_FAILURE(isolate, ErrorUtils::ToString(isolate, recv));
}
RUNTIME_FUNCTION(Runtime_IsJSError) {
SealHandleScope shs(isolate);
DCHECK_EQ(1, args.length());
return isolate->heap()->ToBoolean(args[0]->IsJSError());
}
} // namespace internal
} // namespace v8
......@@ -80,13 +80,6 @@ RUNTIME_FUNCTION(Runtime_FunctionGetScriptSourcePosition) {
return Smi::FromInt(pos);
}
RUNTIME_FUNCTION(Runtime_FunctionGetContextData) {
SealHandleScope shs(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_CHECKED(JSFunction, fun, 0);
return fun->native_context()->debug_context_id();
}
RUNTIME_FUNCTION(Runtime_FunctionIsAPIFunction) {
SealHandleScope shs(isolate);
......@@ -205,15 +198,5 @@ RUNTIME_FUNCTION(Runtime_IsFunction) {
}
RUNTIME_FUNCTION(Runtime_FunctionToString) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
return function->IsJSBoundFunction()
? *JSBoundFunction::ToString(
Handle<JSBoundFunction>::cast(function))
: *JSFunction::ToString(Handle<JSFunction>::cast(function));
}
} // namespace internal
} // namespace v8
......@@ -11,12 +11,6 @@
namespace v8 {
namespace internal {
RUNTIME_FUNCTION(Runtime_IsJSGeneratorObject) {
SealHandleScope shs(isolate);
DCHECK_EQ(1, args.length());
return isolate->heap()->ToBoolean(args[0]->IsJSGeneratorObject());
}
RUNTIME_FUNCTION(Runtime_CreateJSGeneratorObject) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
......@@ -58,14 +52,6 @@ RUNTIME_FUNCTION(Runtime_GeneratorGetFunction) {
return generator->function();
}
RUNTIME_FUNCTION(Runtime_GeneratorGetReceiver) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
return generator->receiver();
}
RUNTIME_FUNCTION(Runtime_GeneratorGetInputOrDebugPos) {
// Runtime call is implemented in InterpreterIntrinsics and lowered in
// JSIntrinsicLowering
......@@ -96,23 +82,6 @@ RUNTIME_FUNCTION(Runtime_GeneratorGetResumeMode) {
UNREACHABLE();
}
RUNTIME_FUNCTION(Runtime_GeneratorGetContinuation) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
return Smi::FromInt(generator->continuation());
}
RUNTIME_FUNCTION(Runtime_GeneratorGetSourcePosition) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
if (!generator->is_suspended()) return isolate->heap()->undefined_value();
return Smi::FromInt(generator->source_position());
}
// Return true if {generator}'s PC has a catch handler. This allows
// catch prediction to happen from the AsyncGeneratorResumeNext stub.
RUNTIME_FUNCTION(Runtime_AsyncGeneratorHasCatchHandlerForPC) {
......
......@@ -30,12 +30,6 @@ RUNTIME_FUNCTION(Runtime_CheckIsBootstrapping) {
return isolate->heap()->undefined_value();
}
RUNTIME_FUNCTION(Runtime_IsScriptWrapper) {
SealHandleScope shs(isolate);
DCHECK_EQ(1, args.length());
return isolate->heap()->ToBoolean(args[0]->IsScriptWrapper());
}
RUNTIME_FUNCTION(Runtime_ExportFromRuntime) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
......
......@@ -266,41 +266,5 @@ RUNTIME_FUNCTION(Runtime_LiveEditCompareStrings) {
return *result;
}
// Restarts a call frame and completely drops all frames above.
// Returns true if successful. Otherwise returns undefined or an error message.
RUNTIME_FUNCTION(Runtime_LiveEditRestartFrame) {
HandleScope scope(isolate);
CHECK(isolate->debug()->live_edit_enabled());
DCHECK_EQ(2, args.length());
CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
CHECK(isolate->debug()->CheckExecutionState(break_id));
CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
Heap* heap = isolate->heap();
// Find the relevant frame with the requested index.
StackFrame::Id id = isolate->debug()->break_frame_id();
if (id == StackFrame::NO_ID) {
// If there are no JavaScript stack frames return undefined.
return heap->undefined_value();
}
StackTraceFrameIterator it(isolate, id);
int inlined_jsframe_index =
DebugFrameHelper::FindIndexedNonNativeFrame(&it, index);
// Liveedit is not supported on Wasm.
if (inlined_jsframe_index == -1 || it.is_wasm()) {
return heap->undefined_value();
}
// We don't really care what the inlined frame index is, since we are
// throwing away the entire frame anyways.
const char* error_message = LiveEdit::RestartFrame(it.javascript_frame());
if (error_message) {
return *(isolate->factory()->InternalizeUtf8String(error_message));
}
return heap->true_value();
}
} // namespace internal
} // namespace v8
......@@ -687,24 +687,6 @@ RUNTIME_FUNCTION(Runtime_GetOwnPropertyKeys) {
}
// Return information on whether an object has a named or indexed interceptor.
// args[0]: object
RUNTIME_FUNCTION(Runtime_GetInterceptorInfo) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
if (!args[0]->IsJSObject()) {
return Smi::kZero;
}
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
int result = 0;
if (obj->HasNamedInterceptor()) result |= 2;
if (obj->HasIndexedInterceptor()) result |= 1;
return Smi::FromInt(result);
}
RUNTIME_FUNCTION(Runtime_ToFastProperties) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
......
......@@ -31,14 +31,6 @@ RUNTIME_FUNCTION(Runtime_CreatePrivateFieldSymbol) {
return *symbol;
}
RUNTIME_FUNCTION(Runtime_SymbolDescription) {
SealHandleScope shs(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_CHECKED(Symbol, symbol, 0);
return symbol->name();
}
RUNTIME_FUNCTION(Runtime_SymbolDescriptiveString) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
......
......@@ -97,8 +97,6 @@ namespace internal {
#define FOR_EACH_INTRINSIC_COLLECTIONS(F) \
F(GetWeakMapEntries, 2, 1) \
F(GetWeakSetValues, 2, 1) \
F(IsJSMap, 1, 1) \
F(IsJSSet, 1, 1) \
F(IsJSWeakMap, 1, 1) \
F(IsJSWeakSet, 1, 1) \
F(MapGrow, 1, 1) \
......@@ -127,62 +125,37 @@ namespace internal {
F(IsDate, 1, 1)
#define FOR_EACH_INTRINSIC_DEBUG(F) \
F(ChangeBreakOnException, 2, 1) \
F(CheckExecutionState, 1, 1) \
F(ClearStepping, 0, 1) \
F(CollectGarbage, 1, 1) \
F(DebugApplyInstrumentation, 1, 1) \
F(DebugBreakAtEntry, 1, 1) \
F(DebugCollectCoverage, 0, 1) \
F(DebugConstructedBy, 2, 1) \
F(DebugEvaluate, 5, 1) \
F(DebugEvaluateGlobal, 2, 1) \
F(DebugGetInternalProperties, 1, 1) \
F(DebugGetLoadedScripts, 0, 1) \
F(DebugGetProperty, 2, 1) \
F(DebugGetPropertyDetails, 2, 1) \
F(DebugGetPrototype, 1, 1) \
F(DebugIsActive, 0, 1) \
F(DebugOnFunctionCall, 2, 1) \
F(DebugPopPromise, 0, 1) \
F(DebugPrepareStepInSuspendedGenerator, 0, 1) \
F(DebugPropertyAttributesFromDetails, 1, 1) \
F(DebugPropertyKindFromDetails, 1, 1) \
F(DebugPushPromise, 1, 1) \
F(DebugAsyncFunctionSuspended, 1, 1) \
F(DebugAsyncFunctionFinished, 2, 1) \
F(DebugReferencedBy, 3, 1) \
F(DebugSetScriptSource, 2, 1) \
F(DebugToggleBlockCoverage, 1, 1) \
F(DebugTogglePreciseCoverage, 1, 1) \
F(FunctionGetDebugName, 1, 1) \
F(FunctionGetInferredName, 1, 1) \
F(GetAllScopesDetails, 4, 1) \
F(GetBreakLocations, 1, 1) \
F(GetDebugContext, 0, 1) \
F(GetFrameCount, 1, 1) \
F(GetFrameDetails, 2, 1) \
F(GetFunctionScopeCount, 1, 1) \
F(GetFunctionScopeDetails, 2, 1) \
F(GetGeneratorScopeCount, 1, 1) \
F(GetGeneratorScopeDetails, 2, 1) \
F(GetHeapUsage, 0, 1) \
F(GetScopeCount, 2, 1) \
F(GetScopeDetails, 4, 1) \
F(GetScript, 1, 1) \
F(HandleDebuggerStatement, 0, 1) \
F(IncBlockCounter, 2, 1) \
F(IsBreakOnException, 1, 1) \
F(PrepareStep, 2, 1) \
F(ScheduleBreak, 0, 1) \
F(ScriptLineCount, 1, 1) \
F(ScriptLocationFromLine2, 4, 1) \
F(ScriptLocationFromLine, 4, 1) \
F(ScriptPositionInfo2, 3, 1) \
F(ScriptPositionInfo, 3, 1) \
F(SetScopeVariableValue, 6, 1)
#define FOR_EACH_INTRINSIC_ERROR(F) F(ErrorToString, 1, 1)
F(SetGeneratorScopeVariableValue, 4, 1)
#define FOR_EACH_INTRINSIC_FORIN(F) \
F(ForInEnumerate, 1, 1) \
......@@ -210,14 +183,12 @@ namespace internal {
#define FOR_EACH_INTRINSIC_FUNCTION(F) \
F(Call, -1 /* >= 2 */, 1) \
F(FunctionGetContextData, 1, 1) \
F(FunctionGetName, 1, 1) \
F(FunctionGetScript, 1, 1) \
F(FunctionGetScriptId, 1, 1) \
F(FunctionGetScriptSourcePosition, 1, 1) \
F(FunctionGetSourceCode, 1, 1) \
F(FunctionIsAPIFunction, 1, 1) \
F(FunctionToString, 1, 1) \
F(IsConstructor, 1, 1) \
F(IsFunction, 1, 1) \
F(SetCode, 2, 1) \
......@@ -230,12 +201,9 @@ namespace internal {
F(AsyncGeneratorYield, 3, 1) \
F(CreateJSGeneratorObject, 2, 1) \
F(GeneratorClose, 1, 1) \
F(GeneratorGetContinuation, 1, 1) \
F(GeneratorGetFunction, 1, 1) \
F(GeneratorGetInputOrDebugPos, 1, 1) \
F(GeneratorGetReceiver, 1, 1) \
F(GeneratorGetResumeMode, 1, 1) \
F(GeneratorGetSourcePosition, 1, 1)
F(GeneratorGetResumeMode, 1, 1)
#ifdef V8_INTL_SUPPORT
#define FOR_EACH_INTRINSIC_INTL(F) \
......@@ -330,8 +298,7 @@ namespace internal {
F(LiveEditPatchFunctionPositions, 2, 1) \
F(LiveEditReplaceFunctionCode, 2, 1) \
F(LiveEditReplaceRefToNestedFunction, 3, 1) \
F(LiveEditReplaceScript, 3, 1) \
F(LiveEditRestartFrame, 2, 1)
F(LiveEditReplaceScript, 3, 1)
#define FOR_EACH_INTRINSIC_MATHS(F) F(GenerateRandomNumbers, 0, 1)
......@@ -372,7 +339,6 @@ namespace internal {
F(DefineSetterPropertyUnchecked, 4, 1) \
F(DeleteProperty, 3, 1) \
F(GetFunctionName, 1, 1) \
F(GetInterceptorInfo, 1, 1) \
F(GetOwnPropertyDescriptor, 2, 1) \
F(GetOwnPropertyKeys, 2, 1) \
F(GetProperty, 2, 1) \
......@@ -511,7 +477,6 @@ namespace internal {
#define FOR_EACH_INTRINSIC_SYMBOL(F) \
F(CreatePrivateFieldSymbol, 0, 1) \
F(CreatePrivateSymbol, -1 /* <= 1 */, 1) \
F(SymbolDescription, 1, 1) \
F(SymbolDescriptiveString, 1, 1) \
F(SymbolIsPrivate, 1, 1)
......@@ -564,12 +529,7 @@ namespace internal {
F(InNewSpace, 1, 1) \
F(IsAsmWasmCode, 1, 1) \
F(IsConcurrentRecompilationSupported, 0, 1) \
F(IsJSError, 1, 1) \
F(IsJSGeneratorObject, 1, 1) \
F(IsJSMapIterator, 1, 1) \
F(IsJSSetIterator, 1, 1) \
F(IsLiftoffFunction, 1, 1) \
F(IsScriptWrapper, 1, 1) \
F(IsWasmCode, 1, 1) \
F(IsWasmTrapHandlerEnabled, 0, 1) \
F(NativeScriptsCount, 0, 1) \
......@@ -676,7 +636,6 @@ namespace internal {
FOR_EACH_INTRINSIC_COMPILER(F) \
FOR_EACH_INTRINSIC_DATE(F) \
FOR_EACH_INTRINSIC_DEBUG(F) \
FOR_EACH_INTRINSIC_ERROR(F) \
FOR_EACH_INTRINSIC_FORIN(F) \
FOR_EACH_INTRINSIC_FUNCTION(F) \
FOR_EACH_INTRINSIC_GENERATOR(F) \
......
......@@ -2967,7 +2967,6 @@ TEST(BytecodeGraphBuilderIllegalConstDeclaration) {
class CountBreakDebugDelegate : public v8::debug::DebugDelegate {
public:
void BreakProgramRequested(v8::Local<v8::Context> paused_context,
v8::Local<v8::Object> exec_state,
const std::vector<int>&) override {
debug_break_count++;
}
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -87,7 +87,6 @@ class BreakHandler : public debug::DebugDelegate {
std::vector<BreakPoint> expected_breaks_;
void BreakProgramRequested(v8::Local<v8::Context> paused_context,
v8::Local<v8::Object> exec_state,
const std::vector<int>&) override {
printf("Break #%d\n", count_);
CHECK_GT(expected_breaks_.size(), count_);
......@@ -193,7 +192,6 @@ class CollectValuesBreakHandler : public debug::DebugDelegate {
std::vector<BreakpointValues> expected_values_;
void BreakProgramRequested(v8::Local<v8::Context> paused_context,
v8::Local<v8::Object> exec_state,
const std::vector<int>&) override {
printf("Break #%d\n", count_);
CHECK_GT(expected_values_.size(), count_);
......
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
Debug = debug.Debug
function foo(){}
let breakpoint_count = 0;
let last_source_line = 0;
let last_source_column = 0;
function listener(event, exec_state, event_data, data) {
if (event == Debug.DebugEvent.Break) {
++breakpoint_count;
last_source_line = exec_state.frame(0).sourceLine();
last_source_column = exec_state.frame(0).sourceColumn();
}
};
Debug.setListener(listener);
// Run without breakpoints.
foo();
assertEquals(breakpoint_count, 0);
// Run with breakpoint.
const breakpoint = Debug.setBreakPoint(foo, 0);
foo();
assertEquals(breakpoint_count, 1);
assertEquals(last_source_line, 7);
assertEquals(last_source_column, 15);
foo();
assertEquals(breakpoint_count, 2);
assertEquals(last_source_line, 7);
assertEquals(last_source_column, 15);
// Run without breakpoints
Debug.clearBreakPoint(breakpoint);
foo();
assertEquals(breakpoint_count, 2);
......@@ -88,11 +88,6 @@ var array_script = Debug.findScript('native array.js');
assertEquals('native array.js', array_script.name);
assertEquals(Debug.ScriptType.Native, array_script.type);
// Test a debugger script.
var debug_delay_script = Debug.findScript('native debug.js');
assertEquals('native debug.js', debug_delay_script.name);
assertEquals(Debug.ScriptType.Native, debug_delay_script.type);
// Test an extension script.
var extension_gc_script = Debug.findScript('v8/gc');
if (extension_gc_script) {
......
......@@ -284,7 +284,7 @@ class DebugWrapper {
}
function setScopeVariableValue(name, value) {
const res = %SetScopeVariableValue(gen, null, null, index, name, value);
const res = %SetGeneratorScopeVariableValue(gen, index, name, value);
if (!res) throw new Error("Failed to set variable '" + name + "' value");
}
......
Check that inspector correctly change break on exception state.
Tests for break on exception.
Running test: noBreakOnExceptionAfterEnabled
Running test: testPauseOnInitialState
Running test: breakOnUncaughtException
paused in throwUncaughtException
evaluate 'caught()'..
Running test: breakOnCaughtException
paused in throwUncaughtException
paused in throwCaughtException
evaluate 'uncaught()'..
Running test: noBreakInEvaluateInSilentMode
evaluate 'uncaughtFinally()'..
evaluate 'caughtFinally()'..
Running test: testPauseOnExceptionOff
evaluate 'caught()'..
evaluate 'uncaught()'..
evaluate 'uncaughtFinally()'..
evaluate 'caughtFinally()'..
Running test: testBreakOnUncaughtException
evaluate 'caught()'..
evaluate 'uncaught()'..
paused on exception:
{
description : 1
type : number
uncaught : true
value : 1
}
evaluate 'uncaughtFinally()'..
paused on exception:
{
description : 1
type : number
uncaught : true
value : 1
}
evaluate 'caughtFinally()'..
paused on exception:
{
description : 1
type : number
uncaught : true
value : 1
}
Running test: testBreakOnAll
evaluate 'caught()'..
paused on exception:
{
description : 1
type : number
uncaught : false
value : 1
}
evaluate 'uncaught()'..
paused on exception:
{
description : 1
type : number
uncaught : true
value : 1
}
evaluate 'uncaughtFinally()'..
paused on exception:
{
description : 1
type : number
uncaught : true
value : 1
}
evaluate 'caughtFinally()'..
paused on exception:
{
description : 1
type : number
uncaught : true
value : 1
}
Running test: testTryFinallyOriginalMessage
evaluate '
try {
throw 1;
} finally {
}
'..
paused on exception:
{
description : 1
type : number
uncaught : true
value : 1
}
Running test: testPromiseRejectedByCallback
evaluate '
function fun() { eval("throw 'rejection';") }
var p = new Promise(function(res, rej) { fun(); res(); });
var r;
p.then(() => { r = 'resolved'; }, (e) => { r = 'rejected' + e; });
'..
paused on exception:
{
type : string
uncaught : true
value : rejection
}
r =
{
type : string
value : rejectedrejection
}
Running test: testBreakOnExceptionAfterReconnect
evaluate 'f()'..
paused on exception:
{
className : Error
description : Error at f (<anonymous>:106:144) at <anonymous>:137:154
objectId : <objectId>
subtype : error
type : object
uncaught : true
}
reconnect..
evaluate 'f()'..
paused on exception:
{
className : Error
description : Error at f (<anonymous>:106:144) at <anonymous>:137:154
objectId : <objectId>
subtype : error
type : object
uncaught : true
}
Running test: testBreakOnExceptionInSilentMode
evaluate 'caught()'
evaluate 'uncaught()'
evaluate 'uncaughtFinally()'
evaluate 'caughtFinally()'
// Copyright 2016 the V8 project authors. All rights reserved.
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
let {session, contextGroup, Protocol} = InspectorTest.start("Check that inspector correctly change break on exception state.");
let {session, contextGroup, Protocol} = InspectorTest.start(
'Tests for break on exception.');
contextGroup.addScript(`
function scheduleUncaughtException()
{
setTimeout(throwUncaughtException, 0);
Protocol.Debugger.enable();
Protocol.Debugger.onPaused(({params:{data}}) => {
InspectorTest.log('paused on exception:');
InspectorTest.logMessage(data);
Protocol.Debugger.resume();
});
contextGroup.addInlineScript(`
function throws() {
throw 1;
}
function caught() {
try {
throws();
} catch (e) {
}
}
function throwUncaughtException()
{
throw new Error();
function uncaught() {
throws();
}
function throwCaughtException()
{
throw new Error();
}`);
function uncaughtFinally() {
try {
throws();
} finally {
}
}
function caughtFinally() {
L: try {
throws();
} finally {
break L;
}
}
`, 'test.js');
Protocol.Debugger.onPaused(message => {
InspectorTest.log("paused in " + message.params.callFrames[0].functionName);
Protocol.Debugger.resume();
});
InspectorTest.runAsyncTestSuite([
async function testPauseOnInitialState() {
await evaluate('caught()');
await evaluate('uncaught()');
await evaluate('uncaughtFinally()');
await evaluate('caughtFinally()');
},
Protocol.Runtime.enable();
async function testPauseOnExceptionOff() {
await Protocol.Debugger.setPauseOnExceptions({state: 'none'});
await evaluate('caught()');
await evaluate('uncaught()');
await evaluate('uncaughtFinally()');
await evaluate('caughtFinally()');
await Protocol.Debugger.setPauseOnExceptions({state: 'none'});
},
async function testBreakOnUncaughtException() {
await Protocol.Debugger.setPauseOnExceptions({state: 'uncaught'});
await evaluate('caught()');
await evaluate('uncaught()');
await evaluate('uncaughtFinally()');
await evaluate('caughtFinally()');
await Protocol.Debugger.setPauseOnExceptions({state: 'none'});
},
InspectorTest.runTestSuite([
function noBreakOnExceptionAfterEnabled(next)
{
Protocol.Debugger.enable();
Protocol.Debugger.setPauseOnExceptions({ state: "all" });
Protocol.Debugger.disable();
Protocol.Debugger.enable();
Protocol.Runtime.evaluate({ expression: "scheduleUncaughtException()" })
.then(() => Protocol.Runtime.evaluate({ expression: "throwCaughtException()" }))
.then(() => Protocol.Debugger.disable())
.then(next);
async function testBreakOnAll() {
await Protocol.Debugger.setPauseOnExceptions({state: 'all'});
await evaluate('caught()');
await evaluate('uncaught()');
await evaluate('uncaughtFinally()');
await evaluate('caughtFinally()');
await Protocol.Debugger.setPauseOnExceptions({state: 'none'});
},
function breakOnUncaughtException(next)
{
Protocol.Debugger.enable();
Protocol.Debugger.setPauseOnExceptions({ state: "uncaught" });
Protocol.Runtime.evaluate({ expression: "scheduleUncaughtException()" })
.then(() => Protocol.Runtime.onceExceptionThrown())
.then(() => Protocol.Runtime.evaluate({ expression: "throwCaughtException()" }))
.then(() => Protocol.Debugger.disable())
.then(next);
async function testTryFinallyOriginalMessage() {
await Protocol.Debugger.setPauseOnExceptions({state: 'all'});
await evaluate(`
try {
throw 1;
} finally {
}
`);
await Protocol.Debugger.setPauseOnExceptions({state: 'none'});
},
function breakOnCaughtException(next)
{
Protocol.Debugger.enable();
Protocol.Debugger.setPauseOnExceptions({ state: "all" });
Protocol.Runtime.evaluate({ expression: "scheduleUncaughtException()" })
.then(() => Protocol.Runtime.onceExceptionThrown())
.then(() => Protocol.Runtime.evaluate({ expression: "throwCaughtException()" }))
.then(() => Protocol.Debugger.disable())
.then(next);
async function testPromiseRejectedByCallback() {
await Protocol.Debugger.setPauseOnExceptions({state: 'uncaught'});
await evaluate(`
function fun() { eval("throw 'rejection';") }
var p = new Promise(function(res, rej) { fun(); res(); });
var r;
p.then(() => { r = 'resolved'; }, (e) => { r = 'rejected' + e; });
`);
InspectorTest.log('r = ');
InspectorTest.logMessage((await Protocol.Runtime.evaluate({
expression: 'r'
})).result.result);
await Protocol.Debugger.setPauseOnExceptions({state: 'none'});
},
function noBreakInEvaluateInSilentMode(next)
{
Protocol.Debugger.enable();
Protocol.Debugger.setPauseOnExceptions({ state: "all" })
.then(() => Protocol.Runtime.evaluate({ expression: "throwCaughtException()", silent: true }))
.then(() => Protocol.Debugger.disable())
.then(next);
async function testBreakOnExceptionAfterReconnect() {
contextGroup.addInlineScript('function f() { throw new Error(); }');
await Protocol.Debugger.setPauseOnExceptions({state: 'uncaught'});
await evaluate('f()');
InspectorTest.log('\nreconnect..');
session.reconnect();
await evaluate('f()');
await Protocol.Debugger.setPauseOnExceptions({state: 'none'});
},
async function testBreakOnExceptionInSilentMode(next) {
await Protocol.Debugger.setPauseOnExceptions({ state: "all" });
InspectorTest.log(`evaluate 'caught()'`);
await Protocol.Runtime.evaluate({expression: 'caught()', silent: true});
InspectorTest.log(`evaluate 'uncaught()'`);
await Protocol.Runtime.evaluate({expression: 'uncaught()', silent: true});
InspectorTest.log(`evaluate 'uncaughtFinally()'`);
await Protocol.Runtime.evaluate({
expression: 'uncaughtFinally()',
silent: true
});
InspectorTest.log(`evaluate 'caughtFinally()'`);
await Protocol.Runtime.evaluate({
xpression: 'caughtFinally()',
silent: true
});
await Protocol.Debugger.setPauseOnExceptions({state: 'none'});
}
]);
async function evaluate(expression) {
InspectorTest.log(`\nevaluate '${expression}'..`);
contextGroup.addInlineScript(expression);
await InspectorTest.waitForPendingTasks();
}
Test for Debugger.evaluateOnCallFrame
Running test: testFoo
Set breakpoint before a = x.
foo()
x =
{
type : undefined
}
a =
{
type : undefined
}
foo("Hello, world!")
x =
{
type : string
value : Hello, world!
}
a =
{
type : undefined
}
Set breakpoint after a = x.
foo("Hello, world!")
x =
{
type : string
value : Hello, world!
}
a =
{
type : string
value : Hello, world!
}
Running test: testZoo
Set breakpoint before y = 0.
zoo("Hello, world!")
x =
{
type : string
value : Hello, world!
}
a =
{
type : undefined
}
Running test: testBar
Set breakpoint before a = x.
bar(undefined, "Hello, world!")
x =
{
type : undefined
}
a =
{
type : undefined
}
Set breakpoint after a = x.
bar(undefined, "Hello, world!")
x =
{
type : string
value : Hello, world!
}
a =
{
type : string
value : Hello, world!
}
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
const {session, contextGroup, Protocol} =
InspectorTest.start(`Test for Debugger.evaluateOnCallFrame`);
Protocol.Debugger.enable();
InspectorTest.runAsyncTestSuite([
async function testFoo() {
contextGroup.addInlineScript(`
function foo(x) {
var a;
y = 0;
a = x;
y = 0;
}
`, 'foo.js');
InspectorTest.log('Set breakpoint before a = x.');
let {result:{breakpointId}} = await Protocol.Debugger.setBreakpointByUrl({
lineNumber: 14,
url: 'foo.js'
});
await evaluateOnDump('foo()', ['x', 'a']);
await evaluateOnDump('foo("Hello, world!")', ['x', 'a']);
await Protocol.Debugger.removeBreakpoint({
breakpointId
});
InspectorTest.log('Set breakpoint after a = x.');
await Protocol.Debugger.setBreakpointByUrl({
lineNumber: 16,
url: 'foo.js'
});
await evaluateOnDump('foo("Hello, world!")', ['x', 'a']);
},
async function testZoo() {
contextGroup.addInlineScript(`
x = undefined;
function zoo(t) {
var a = x;
Object.prototype.x = 42;
x = t;
y = 0;
delete Object.prototype.x;
x = a;
}
`, 'zoo.js');
InspectorTest.log('Set breakpoint before y = 0.');
await Protocol.Debugger.setBreakpointByUrl({
lineNumber: 47,
url: 'zoo.js'
});
await evaluateOnDump('zoo("Hello, world!")', ['x', 'a']);
},
async function testBar() {
contextGroup.addInlineScript(`
y = 0;
x = 'Goodbye, world!';
function bar(x, b) {
var a;
function barbar() {
y = 0;
x = b;
a = x;
}
barbar();
y = 0;
}
`, 'bar.js');
InspectorTest.log('Set breakpoint before a = x.');
let {result:{breakpointId}} = await Protocol.Debugger.setBreakpointByUrl({
lineNumber: 68,
url: 'bar.js'
});
await evaluateOnDump('bar(undefined, "Hello, world!")', ['x', 'a']);
await Protocol.Debugger.removeBreakpoint({
breakpointId
});
InspectorTest.log('Set breakpoint after a = x.');
await Protocol.Debugger.setBreakpointByUrl({
lineNumber: 73,
url: 'bar.js'
});
await evaluateOnDump('bar(undefined, "Hello, world!")', ['x', 'a']);
}
]);
async function evaluateOnDump(expression, variables) {
InspectorTest.log(expression);
Protocol.Runtime.evaluate({
expression: `${expression}//# sourceURL=expr.js`
});
const {params:{callFrames:[{callFrameId}]}} =
await Protocol.Debugger.oncePaused();
for (const variable of variables) {
InspectorTest.log(`${variable} = `);
const {result:{result}} = await Protocol.Debugger.evaluateOnCallFrame({
callFrameId,
expression: variable
});
InspectorTest.logMessage(result);
}
await Protocol.Debugger.resume();
InspectorTest.log('');
}
// Copyright 2013 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: --allow-natives-syntax --gc-global --throws
var f = eval("(function f() { throw 'kaboom'; })");
// Prepare that next MessageHandler::MakeMessageObject will result in
// reclamation of existing script wrapper while weak handle is used.
%FunctionGetScript(f);
%SetAllocationTimeout(1000, 2);
// This call throws to the console but the --throws flag passed to this
// test will make sure we don't count it as an actual failure.
f();
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
%FunctionGetScript({});
%FunctionGetSourceCode({});
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