[wasm] Provide correct eval origin for asm.js code
This CL moves all methods related to scripts and eval origin (HasScript, GetScript, IsEval, GetEvalOrigin) from JSStackFrame to StackFrameBase, because it also applies to WasmFrames. This makes the AppendFileLocation method append the same information to WasmStackFrames and AsmJsWasmStackFrames than to JSStackFrames. R=titzer@chromium.org, mstarzinger@chromium.org BUG=v8:4203 Review-Url: https://codereview.chromium.org/2557923005 Cr-Commit-Position: refs/heads/master@{#41642}
This commit is contained in:
parent
9b6808bfb5
commit
c4057d4645
236
src/messages.cc
236
src/messages.cc
@ -165,6 +165,115 @@ std::unique_ptr<char[]> MessageHandler::GetLocalizedMessage(
|
||||
return GetMessage(isolate, data)->ToCString(DISALLOW_NULLS);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
Object* EvalFromFunctionName(Isolate* isolate, Handle<Script> script) {
|
||||
if (script->eval_from_shared()->IsUndefined(isolate))
|
||||
return isolate->heap()->undefined_value();
|
||||
|
||||
Handle<SharedFunctionInfo> shared(
|
||||
SharedFunctionInfo::cast(script->eval_from_shared()));
|
||||
// Find the name of the function calling eval.
|
||||
if (shared->name()->BooleanValue()) {
|
||||
return shared->name();
|
||||
}
|
||||
|
||||
return shared->inferred_name();
|
||||
}
|
||||
|
||||
Object* EvalFromScript(Isolate* isolate, Handle<Script> script) {
|
||||
if (script->eval_from_shared()->IsUndefined(isolate))
|
||||
return isolate->heap()->undefined_value();
|
||||
|
||||
Handle<SharedFunctionInfo> eval_from_shared(
|
||||
SharedFunctionInfo::cast(script->eval_from_shared()));
|
||||
return eval_from_shared->script()->IsScript()
|
||||
? eval_from_shared->script()
|
||||
: isolate->heap()->undefined_value();
|
||||
}
|
||||
|
||||
MaybeHandle<String> FormatEvalOrigin(Isolate* isolate, Handle<Script> script) {
|
||||
Handle<Object> sourceURL(script->GetNameOrSourceURL(), isolate);
|
||||
if (!sourceURL->IsUndefined(isolate)) {
|
||||
DCHECK(sourceURL->IsString());
|
||||
return Handle<String>::cast(sourceURL);
|
||||
}
|
||||
|
||||
IncrementalStringBuilder builder(isolate);
|
||||
builder.AppendCString("eval at ");
|
||||
|
||||
Handle<Object> eval_from_function_name =
|
||||
handle(EvalFromFunctionName(isolate, script), isolate);
|
||||
if (eval_from_function_name->BooleanValue()) {
|
||||
Handle<String> str;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, str, Object::ToString(isolate, eval_from_function_name),
|
||||
String);
|
||||
builder.AppendString(str);
|
||||
} else {
|
||||
builder.AppendCString("<anonymous>");
|
||||
}
|
||||
|
||||
Handle<Object> eval_from_script_obj =
|
||||
handle(EvalFromScript(isolate, script), isolate);
|
||||
if (eval_from_script_obj->IsScript()) {
|
||||
Handle<Script> eval_from_script =
|
||||
Handle<Script>::cast(eval_from_script_obj);
|
||||
builder.AppendCString(" (");
|
||||
if (eval_from_script->compilation_type() == Script::COMPILATION_TYPE_EVAL) {
|
||||
// Eval script originated from another eval.
|
||||
Handle<String> str;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, str, FormatEvalOrigin(isolate, eval_from_script), String);
|
||||
builder.AppendString(str);
|
||||
} else {
|
||||
DCHECK(eval_from_script->compilation_type() !=
|
||||
Script::COMPILATION_TYPE_EVAL);
|
||||
// eval script originated from "real" source.
|
||||
Handle<Object> name_obj = handle(eval_from_script->name(), isolate);
|
||||
if (eval_from_script->name()->IsString()) {
|
||||
builder.AppendString(Handle<String>::cast(name_obj));
|
||||
|
||||
Script::PositionInfo info;
|
||||
if (Script::GetPositionInfo(eval_from_script, script->GetEvalPosition(),
|
||||
&info, Script::NO_OFFSET)) {
|
||||
builder.AppendCString(":");
|
||||
|
||||
Handle<String> str = isolate->factory()->NumberToString(
|
||||
handle(Smi::FromInt(info.line + 1), isolate));
|
||||
builder.AppendString(str);
|
||||
|
||||
builder.AppendCString(":");
|
||||
|
||||
str = isolate->factory()->NumberToString(
|
||||
handle(Smi::FromInt(info.column + 1), isolate));
|
||||
builder.AppendString(str);
|
||||
}
|
||||
} else {
|
||||
DCHECK(!eval_from_script->name()->IsString());
|
||||
builder.AppendCString("unknown source");
|
||||
}
|
||||
}
|
||||
builder.AppendCString(")");
|
||||
}
|
||||
|
||||
Handle<String> result;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(isolate, result, builder.Finish(), String);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Handle<Object> StackFrameBase::GetEvalOrigin() {
|
||||
if (!HasScript()) return isolate_->factory()->undefined_value();
|
||||
return FormatEvalOrigin(isolate_, GetScript()).ToHandleChecked();
|
||||
}
|
||||
|
||||
bool StackFrameBase::IsEval() {
|
||||
return HasScript() &&
|
||||
GetScript()->compilation_type() == Script::COMPILATION_TYPE_EVAL;
|
||||
}
|
||||
|
||||
void JSStackFrame::FromFrameArray(Isolate* isolate, Handle<FrameArray> array,
|
||||
int frame_ix) {
|
||||
DCHECK(!array->IsWasmFrame(frame_ix));
|
||||
@ -179,10 +288,12 @@ void JSStackFrame::FromFrameArray(Isolate* isolate, Handle<FrameArray> array,
|
||||
is_strict_ = (flags & FrameArray::kIsStrict) != 0;
|
||||
}
|
||||
|
||||
JSStackFrame::JSStackFrame() {}
|
||||
|
||||
JSStackFrame::JSStackFrame(Isolate* isolate, Handle<Object> receiver,
|
||||
Handle<JSFunction> function,
|
||||
Handle<AbstractCode> code, int offset)
|
||||
: isolate_(isolate),
|
||||
: StackFrameBase(isolate),
|
||||
receiver_(receiver),
|
||||
function_(function),
|
||||
code_(code),
|
||||
@ -190,8 +301,6 @@ JSStackFrame::JSStackFrame(Isolate* isolate, Handle<Object> receiver,
|
||||
force_constructor_(false),
|
||||
is_strict_(false) {}
|
||||
|
||||
JSStackFrame::JSStackFrame() {}
|
||||
|
||||
Handle<Object> JSStackFrame::GetFunction() const {
|
||||
return Handle<Object>::cast(function_);
|
||||
}
|
||||
@ -298,105 +407,6 @@ Handle<Object> JSStackFrame::GetMethodName() {
|
||||
return isolate_->factory()->null_value();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
Object* EvalFromFunctionName(Isolate* isolate, Handle<Script> script) {
|
||||
if (script->eval_from_shared()->IsUndefined(isolate))
|
||||
return isolate->heap()->undefined_value();
|
||||
|
||||
Handle<SharedFunctionInfo> shared(
|
||||
SharedFunctionInfo::cast(script->eval_from_shared()));
|
||||
// Find the name of the function calling eval.
|
||||
if (shared->name()->BooleanValue()) {
|
||||
return shared->name();
|
||||
}
|
||||
|
||||
return shared->inferred_name();
|
||||
}
|
||||
|
||||
Object* EvalFromScript(Isolate* isolate, Handle<Script> script) {
|
||||
if (script->eval_from_shared()->IsUndefined(isolate))
|
||||
return isolate->heap()->undefined_value();
|
||||
|
||||
Handle<SharedFunctionInfo> eval_from_shared(
|
||||
SharedFunctionInfo::cast(script->eval_from_shared()));
|
||||
return eval_from_shared->script()->IsScript()
|
||||
? eval_from_shared->script()
|
||||
: isolate->heap()->undefined_value();
|
||||
}
|
||||
|
||||
MaybeHandle<String> FormatEvalOrigin(Isolate* isolate, Handle<Script> script) {
|
||||
Handle<Object> sourceURL(script->GetNameOrSourceURL(), isolate);
|
||||
if (!sourceURL->IsUndefined(isolate)) {
|
||||
DCHECK(sourceURL->IsString());
|
||||
return Handle<String>::cast(sourceURL);
|
||||
}
|
||||
|
||||
IncrementalStringBuilder builder(isolate);
|
||||
builder.AppendCString("eval at ");
|
||||
|
||||
Handle<Object> eval_from_function_name =
|
||||
handle(EvalFromFunctionName(isolate, script), isolate);
|
||||
if (eval_from_function_name->BooleanValue()) {
|
||||
Handle<String> str;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, str, Object::ToString(isolate, eval_from_function_name),
|
||||
String);
|
||||
builder.AppendString(str);
|
||||
} else {
|
||||
builder.AppendCString("<anonymous>");
|
||||
}
|
||||
|
||||
Handle<Object> eval_from_script_obj =
|
||||
handle(EvalFromScript(isolate, script), isolate);
|
||||
if (eval_from_script_obj->IsScript()) {
|
||||
Handle<Script> eval_from_script =
|
||||
Handle<Script>::cast(eval_from_script_obj);
|
||||
builder.AppendCString(" (");
|
||||
if (eval_from_script->compilation_type() == Script::COMPILATION_TYPE_EVAL) {
|
||||
// Eval script originated from another eval.
|
||||
Handle<String> str;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, str, FormatEvalOrigin(isolate, eval_from_script), String);
|
||||
builder.AppendString(str);
|
||||
} else {
|
||||
DCHECK(eval_from_script->compilation_type() !=
|
||||
Script::COMPILATION_TYPE_EVAL);
|
||||
// eval script originated from "real" source.
|
||||
Handle<Object> name_obj = handle(eval_from_script->name(), isolate);
|
||||
if (eval_from_script->name()->IsString()) {
|
||||
builder.AppendString(Handle<String>::cast(name_obj));
|
||||
|
||||
Script::PositionInfo info;
|
||||
if (Script::GetPositionInfo(eval_from_script, script->GetEvalPosition(),
|
||||
&info, Script::NO_OFFSET)) {
|
||||
builder.AppendCString(":");
|
||||
|
||||
Handle<String> str = isolate->factory()->NumberToString(
|
||||
handle(Smi::FromInt(info.line + 1), isolate));
|
||||
builder.AppendString(str);
|
||||
|
||||
builder.AppendCString(":");
|
||||
|
||||
str = isolate->factory()->NumberToString(
|
||||
handle(Smi::FromInt(info.column + 1), isolate));
|
||||
builder.AppendString(str);
|
||||
}
|
||||
} else {
|
||||
DCHECK(!eval_from_script->name()->IsString());
|
||||
builder.AppendCString("unknown source");
|
||||
}
|
||||
}
|
||||
builder.AppendCString(")");
|
||||
}
|
||||
|
||||
Handle<String> result;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(isolate, result, builder.Finish(), String);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Handle<Object> JSStackFrame::GetTypeName() {
|
||||
// TODO(jgruber): Check for strict/constructor here as in
|
||||
// CallSitePrototypeGetThis.
|
||||
@ -411,11 +421,6 @@ Handle<Object> JSStackFrame::GetTypeName() {
|
||||
return JSReceiver::GetConstructorName(receiver_object);
|
||||
}
|
||||
|
||||
Handle<Object> JSStackFrame::GetEvalOrigin() {
|
||||
if (!HasScript()) return isolate_->factory()->undefined_value();
|
||||
return FormatEvalOrigin(isolate_, GetScript()).ToHandleChecked();
|
||||
}
|
||||
|
||||
int JSStackFrame::GetLineNumber() {
|
||||
DCHECK_LE(0, GetPosition());
|
||||
if (HasScript()) return Script::GetLineNumber(GetScript(), GetPosition()) + 1;
|
||||
@ -439,11 +444,6 @@ bool JSStackFrame::IsToplevel() {
|
||||
receiver_->IsUndefined(isolate_);
|
||||
}
|
||||
|
||||
bool JSStackFrame::IsEval() {
|
||||
return HasScript() &&
|
||||
GetScript()->compilation_type() == Script::COMPILATION_TYPE_EVAL;
|
||||
}
|
||||
|
||||
bool JSStackFrame::IsConstructor() {
|
||||
if (force_constructor_) return true;
|
||||
if (!receiver_->IsJSObject()) return false;
|
||||
@ -619,6 +619,8 @@ Handle<Script> JSStackFrame::GetScript() const {
|
||||
return handle(Script::cast(function_->shared()->script()), isolate_);
|
||||
}
|
||||
|
||||
WasmStackFrame::WasmStackFrame() {}
|
||||
|
||||
void WasmStackFrame::FromFrameArray(Isolate* isolate, Handle<FrameArray> array,
|
||||
int frame_ix) {
|
||||
// This function is called for both wasm and asm.js->wasm frames.
|
||||
@ -681,6 +683,16 @@ Handle<Object> WasmStackFrame::Null() const {
|
||||
return isolate_->factory()->null_value();
|
||||
}
|
||||
|
||||
bool WasmStackFrame::HasScript() const { return true; }
|
||||
|
||||
Handle<Script> WasmStackFrame::GetScript() const {
|
||||
return WasmInstanceObject::cast(*wasm_instance_)
|
||||
->get_compiled_module()
|
||||
->script();
|
||||
}
|
||||
|
||||
AsmJsWasmStackFrame::AsmJsWasmStackFrame() {}
|
||||
|
||||
void AsmJsWasmStackFrame::FromFrameArray(Isolate* isolate,
|
||||
Handle<FrameArray> array,
|
||||
int frame_ix) {
|
||||
|
@ -56,7 +56,7 @@ class StackFrameBase {
|
||||
virtual Handle<Object> GetScriptNameOrSourceUrl() = 0;
|
||||
virtual Handle<Object> GetMethodName() = 0;
|
||||
virtual Handle<Object> GetTypeName() = 0;
|
||||
virtual Handle<Object> GetEvalOrigin() = 0;
|
||||
virtual Handle<Object> GetEvalOrigin();
|
||||
|
||||
virtual int GetPosition() const = 0;
|
||||
// Return 1-based line number, including line offset.
|
||||
@ -66,11 +66,20 @@ class StackFrameBase {
|
||||
|
||||
virtual bool IsNative() = 0;
|
||||
virtual bool IsToplevel() = 0;
|
||||
virtual bool IsEval() = 0;
|
||||
virtual bool IsEval();
|
||||
virtual bool IsConstructor() = 0;
|
||||
virtual bool IsStrict() const = 0;
|
||||
|
||||
virtual MaybeHandle<String> ToString() = 0;
|
||||
|
||||
protected:
|
||||
StackFrameBase() {}
|
||||
explicit StackFrameBase(Isolate* isolate) : isolate_(isolate) {}
|
||||
Isolate* isolate_;
|
||||
|
||||
private:
|
||||
virtual bool HasScript() const = 0;
|
||||
virtual Handle<Script> GetScript() const = 0;
|
||||
};
|
||||
|
||||
class JSStackFrame : public StackFrameBase {
|
||||
@ -88,7 +97,6 @@ class JSStackFrame : public StackFrameBase {
|
||||
Handle<Object> GetScriptNameOrSourceUrl() override;
|
||||
Handle<Object> GetMethodName() override;
|
||||
Handle<Object> GetTypeName() override;
|
||||
Handle<Object> GetEvalOrigin() override;
|
||||
|
||||
int GetPosition() const override;
|
||||
int GetLineNumber() override;
|
||||
@ -96,7 +104,6 @@ class JSStackFrame : public StackFrameBase {
|
||||
|
||||
bool IsNative() override;
|
||||
bool IsToplevel() override;
|
||||
bool IsEval() override;
|
||||
bool IsConstructor() override;
|
||||
bool IsStrict() const override { return is_strict_; }
|
||||
|
||||
@ -106,10 +113,8 @@ class JSStackFrame : public StackFrameBase {
|
||||
JSStackFrame();
|
||||
void FromFrameArray(Isolate* isolate, Handle<FrameArray> array, int frame_ix);
|
||||
|
||||
bool HasScript() const;
|
||||
Handle<Script> GetScript() const;
|
||||
|
||||
Isolate* isolate_;
|
||||
bool HasScript() const override;
|
||||
Handle<Script> GetScript() const override;
|
||||
|
||||
Handle<Object> receiver_;
|
||||
Handle<JSFunction> function_;
|
||||
@ -134,7 +139,6 @@ class WasmStackFrame : public StackFrameBase {
|
||||
Handle<Object> GetScriptNameOrSourceUrl() override { return Null(); }
|
||||
Handle<Object> GetMethodName() override { return Null(); }
|
||||
Handle<Object> GetTypeName() override { return Null(); }
|
||||
Handle<Object> GetEvalOrigin() override { return Null(); }
|
||||
|
||||
int GetPosition() const override;
|
||||
int GetLineNumber() override { return wasm_func_index_; }
|
||||
@ -142,7 +146,6 @@ class WasmStackFrame : public StackFrameBase {
|
||||
|
||||
bool IsNative() override { return false; }
|
||||
bool IsToplevel() override { return false; }
|
||||
bool IsEval() override { return false; }
|
||||
bool IsConstructor() override { return false; }
|
||||
bool IsStrict() const override { return false; }
|
||||
|
||||
@ -151,7 +154,8 @@ class WasmStackFrame : public StackFrameBase {
|
||||
protected:
|
||||
Handle<Object> Null() const;
|
||||
|
||||
Isolate* isolate_;
|
||||
bool HasScript() const override;
|
||||
Handle<Script> GetScript() const override;
|
||||
|
||||
// TODO(wasm): Use proper typing.
|
||||
Handle<Object> wasm_instance_;
|
||||
@ -160,6 +164,7 @@ class WasmStackFrame : public StackFrameBase {
|
||||
int offset_;
|
||||
|
||||
private:
|
||||
WasmStackFrame();
|
||||
void FromFrameArray(Isolate* isolate, Handle<FrameArray> array, int frame_ix);
|
||||
|
||||
friend class FrameArrayIterator;
|
||||
@ -184,6 +189,7 @@ class AsmJsWasmStackFrame : public WasmStackFrame {
|
||||
|
||||
private:
|
||||
friend class FrameArrayIterator;
|
||||
AsmJsWasmStackFrame();
|
||||
void FromFrameArray(Isolate* isolate, Handle<FrameArray> array, int frame_ix);
|
||||
|
||||
bool is_at_number_conversion_;
|
||||
|
@ -80,7 +80,8 @@ function testAll(expected_stack, expected_frames, input) {
|
||||
var expected_stack = [
|
||||
'^Error: user-thrown$',
|
||||
'^ *at sym \\(' + filename + ':\\d+:9\\)$',
|
||||
'^ *at callSym \\(.*<anonymous>:\\d+:12\\)$',
|
||||
'^ *at callSym \\(eval at testHelper \\(' + filename +
|
||||
':\\d+:19\\), <anonymous>:\\d+:12\\)$',
|
||||
];
|
||||
var expected_frames = [
|
||||
// function pos
|
||||
@ -94,7 +95,8 @@ function testAll(expected_stack, expected_frames, input) {
|
||||
(function testStackForThrowAtConversion() {
|
||||
var expected_stack = [
|
||||
'^TypeError: Cannot convert a Symbol value to a number$',
|
||||
'^ *at callSym \\(.*<anonymous>:\\d+:21\\)$',
|
||||
'^ *at callSym \\(eval at testHelper \\(' + filename +
|
||||
':\\d+:19\\), <anonymous>:\\d+:21\\)$',
|
||||
];
|
||||
var expected_frames = [
|
||||
// function pos
|
||||
|
Loading…
Reference in New Issue
Block a user