[runtime] Fix detection of construct frames in stack traces.
This removes the heuristic from {JSStackFrame::IsConstructor} that tried to infer whether a frame was called as a constructor or not from the receiver value. We are now carrying along the appropriate bit derived from the frame type instead. R=jgruber@chromium.org TEST=message/regress/regress-5727 BUG=v8:5727 Change-Id: I0e2f1d0f95485c84c4ebcd3cbfe0123c6afd2e01 Reviewed-on: https://chromium-review.googlesource.com/500313 Commit-Queue: Michael Starzinger <mstarzinger@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Cr-Commit-Position: refs/heads/master@{#45972}
This commit is contained in:
parent
d5dd51ae6d
commit
e47f37ebd0
@ -518,18 +518,18 @@ Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object,
|
||||
Handle<AbstractCode> abstract_code = summ.abstract_code();
|
||||
const int offset = frames[i].code_offset();
|
||||
|
||||
bool force_constructor = false;
|
||||
bool is_constructor = frames[i].is_constructor();
|
||||
if (frame->type() == StackFrame::BUILTIN) {
|
||||
// Help CallSite::IsConstructor correctly detect hand-written
|
||||
// construct stubs.
|
||||
if (Code::cast(*abstract_code)->is_construct_stub()) {
|
||||
force_constructor = true;
|
||||
is_constructor = true;
|
||||
}
|
||||
}
|
||||
|
||||
int flags = 0;
|
||||
if (helper.IsStrictFrame(*fun)) flags |= FrameArray::kIsStrict;
|
||||
if (force_constructor) flags |= FrameArray::kForceConstructor;
|
||||
if (is_constructor) flags |= FrameArray::kIsConstructor;
|
||||
|
||||
elements = FrameArray::AppendJSFrame(
|
||||
elements, TheHoleToUndefined(this, recv), fun, abstract_code,
|
||||
@ -551,7 +551,7 @@ Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object,
|
||||
|
||||
int flags = 0;
|
||||
if (helper.IsStrictFrame(*fun)) flags |= FrameArray::kIsStrict;
|
||||
if (exit_frame->IsConstructor()) flags |= FrameArray::kForceConstructor;
|
||||
if (exit_frame->IsConstructor()) flags |= FrameArray::kIsConstructor;
|
||||
|
||||
elements = FrameArray::AppendJSFrame(elements, recv, fun,
|
||||
Handle<AbstractCode>::cast(code),
|
||||
|
@ -302,7 +302,7 @@ void JSStackFrame::FromFrameArray(Isolate* isolate, Handle<FrameArray> array,
|
||||
offset_ = array->Offset(frame_ix)->value();
|
||||
|
||||
const int flags = array->Flags(frame_ix)->value();
|
||||
force_constructor_ = (flags & FrameArray::kForceConstructor) != 0;
|
||||
is_constructor_ = (flags & FrameArray::kIsConstructor) != 0;
|
||||
is_strict_ = (flags & FrameArray::kIsStrict) != 0;
|
||||
}
|
||||
|
||||
@ -316,7 +316,7 @@ JSStackFrame::JSStackFrame(Isolate* isolate, Handle<Object> receiver,
|
||||
function_(function),
|
||||
code_(code),
|
||||
offset_(offset),
|
||||
force_constructor_(false),
|
||||
is_constructor_(false),
|
||||
is_strict_(false) {}
|
||||
|
||||
Handle<Object> JSStackFrame::GetFunction() const {
|
||||
@ -458,15 +458,6 @@ bool JSStackFrame::IsToplevel() {
|
||||
return receiver_->IsJSGlobalProxy() || receiver_->IsNullOrUndefined(isolate_);
|
||||
}
|
||||
|
||||
bool JSStackFrame::IsConstructor() {
|
||||
if (force_constructor_) return true;
|
||||
if (!receiver_->IsJSObject()) return false;
|
||||
Handle<Object> constructor =
|
||||
JSReceiver::GetDataProperty(Handle<JSObject>::cast(receiver_),
|
||||
isolate_->factory()->constructor_string());
|
||||
return constructor.is_identical_to(function_);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool IsNonEmptyString(Handle<Object> object) {
|
||||
|
@ -106,7 +106,7 @@ class JSStackFrame : public StackFrameBase {
|
||||
|
||||
bool IsNative() override;
|
||||
bool IsToplevel() override;
|
||||
bool IsConstructor() override;
|
||||
bool IsConstructor() override { return is_constructor_; }
|
||||
bool IsStrict() const override { return is_strict_; }
|
||||
|
||||
MaybeHandle<String> ToString() override;
|
||||
@ -123,7 +123,7 @@ class JSStackFrame : public StackFrameBase {
|
||||
Handle<AbstractCode> code_;
|
||||
int offset_;
|
||||
|
||||
bool force_constructor_;
|
||||
bool is_constructor_;
|
||||
bool is_strict_;
|
||||
|
||||
friend class FrameArrayIterator;
|
||||
|
@ -48,7 +48,7 @@ class FrameArray : public FixedArray {
|
||||
kIsWasmInterpretedFrame = 1 << 1,
|
||||
kIsAsmJsWasmFrame = 1 << 2,
|
||||
kIsStrict = 1 << 3,
|
||||
kForceConstructor = 1 << 4,
|
||||
kIsConstructor = 1 << 4,
|
||||
kAsmJsAtNumberConversion = 1 << 5
|
||||
};
|
||||
|
||||
|
11
test/message/regress/regress-5727.js
Normal file
11
test/message/regress/regress-5727.js
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright 2017 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 Foo(do_throw) {
|
||||
if (do_throw) throw new Error("get me outta here");
|
||||
}
|
||||
var foo = new Foo(false);
|
||||
(function caller() {
|
||||
Foo.call(foo, true);
|
||||
})();
|
11
test/message/regress/regress-5727.out
Normal file
11
test/message/regress/regress-5727.out
Normal file
@ -0,0 +1,11 @@
|
||||
# Copyright 2017 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.
|
||||
|
||||
*%(basename)s:6: Error: get me outta here
|
||||
if (do_throw) throw new Error("get me outta here");
|
||||
^
|
||||
Error: get me outta here
|
||||
at Foo (*%(basename)s:6:23)
|
||||
at caller (*%(basename)s:10:7)
|
||||
at *%(basename)s:11:3
|
@ -46,7 +46,8 @@ function getStack(error) {
|
||||
filter(function(line) {
|
||||
return /^\s*at @?[a-zA-Z0-9_]/.test(line);
|
||||
}).
|
||||
map(line => line.replace(/^\s*at (@?[a-zA-Z0-9_\.\[\]]+)(.*)/, "$1"));
|
||||
map(line =>
|
||||
line.replace(/^\s*at (@?(?:new )?[a-zA-Z0-9_\.\[\]]+)(.*)/, "$1"));
|
||||
|
||||
// remove `Promise.then()` invocation by assertEqualsAsync()
|
||||
if (stack[2] === "assertEqualsAsync") return [];
|
||||
@ -96,6 +97,6 @@ assertEqualsAsync(
|
||||
}),
|
||||
"should call Promise[@@Species] after non-internal Then");
|
||||
assertEquals([
|
||||
"@@Species: [@testThenOnReturnedPromise > Promise.then > FakePromise]",
|
||||
"@@Species: [@testThenOnReturnedPromise > Promise.then > new FakePromise]",
|
||||
"Then: foo"
|
||||
], log);
|
||||
|
Loading…
Reference in New Issue
Block a user