Commit 989d7b96 authored by jgruber's avatar jgruber Committed by Commit Bot

[error] Lazy stack trace formatting for Error.captureStackTrace

This reinstates the old behavior of Error.captureStackTrace prior to
4feafee9.  Like the builtin Error constructors, captureStackTrace now formats
the stack trace lazily once it is accessed.

Bug: v8:5962
Change-Id: I03821b73d26b7b40809a1fea98f9c820bfa05d6b
Reviewed-on: https://chromium-review.googlesource.com/574530Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46727}
parent a8d94c66
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "src/builtins/builtins.h" #include "src/builtins/builtins.h"
#include "src/builtins/builtins-utils.h" #include "src/builtins/builtins-utils.h"
#include "src/accessors.h"
#include "src/counters.h" #include "src/counters.h"
#include "src/messages.h" #include "src/messages.h"
#include "src/objects-inl.h" #include "src/objects-inl.h"
...@@ -40,10 +41,12 @@ BUILTIN(ErrorConstructor) { ...@@ -40,10 +41,12 @@ BUILTIN(ErrorConstructor) {
BUILTIN(ErrorCaptureStackTrace) { BUILTIN(ErrorCaptureStackTrace) {
HandleScope scope(isolate); HandleScope scope(isolate);
Handle<Object> object_obj = args.atOrUndefined(isolate, 1); Handle<Object> object_obj = args.atOrUndefined(isolate, 1);
if (!object_obj->IsJSObject()) { if (!object_obj->IsJSObject()) {
THROW_NEW_ERROR_RETURN_FAILURE( THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kInvalidArgument, object_obj)); isolate, NewTypeError(MessageTemplate::kInvalidArgument, object_obj));
} }
Handle<JSObject> object = Handle<JSObject>::cast(object_obj); Handle<JSObject> object = Handle<JSObject>::cast(object_obj);
Handle<Object> caller = args.atOrUndefined(isolate, 2); Handle<Object> caller = args.atOrUndefined(isolate, 2);
FrameSkipMode mode = caller->IsJSFunction() ? SKIP_UNTIL_SEEN : SKIP_FIRST; FrameSkipMode mode = caller->IsJSFunction() ? SKIP_UNTIL_SEEN : SKIP_FIRST;
...@@ -52,27 +55,24 @@ BUILTIN(ErrorCaptureStackTrace) { ...@@ -52,27 +55,24 @@ BUILTIN(ErrorCaptureStackTrace) {
RETURN_FAILURE_ON_EXCEPTION(isolate, RETURN_FAILURE_ON_EXCEPTION(isolate,
isolate->CaptureAndSetDetailedStackTrace(object)); isolate->CaptureAndSetDetailedStackTrace(object));
RETURN_FAILURE_ON_EXCEPTION(
isolate, isolate->CaptureAndSetSimpleStackTrace(object, mode, caller));
// Add the stack accessors.
Handle<AccessorInfo> error_stack =
Accessors::ErrorStackInfo(isolate, DONT_ENUM);
// Eagerly format the stack trace and set the stack property. // Explicitly check for frozen objects. Other access checks are performed by
// the LookupIterator in SetAccessor below.
Handle<Object> stack_trace = if (!JSObject::IsExtensible(object)) {
isolate->CaptureSimpleStackTrace(object, mode, caller); return isolate->Throw(*isolate->factory()->NewTypeError(
if (!stack_trace->IsJSArray()) return isolate->heap()->undefined_value(); MessageTemplate::kDefineDisallowed,
handle(error_stack->name(), isolate)));
Handle<Object> formatted_stack_trace; }
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, formatted_stack_trace, RETURN_FAILURE_ON_EXCEPTION(isolate,
ErrorUtils::FormatStackTrace(isolate, object, stack_trace)); JSObject::SetAccessor(object, error_stack));
PropertyDescriptor desc;
desc.set_configurable(true);
desc.set_writable(true);
desc.set_value(formatted_stack_trace);
Maybe<bool> status = JSReceiver::DefineOwnProperty(
isolate, object, isolate->factory()->stack_string(), &desc,
Object::THROW_ON_ERROR);
if (!status.IsJust()) return isolate->heap()->exception();
CHECK(status.FromJust());
return isolate->heap()->undefined_value(); return isolate->heap()->undefined_value();
} }
......
...@@ -391,9 +391,7 @@ assertTrue(desc.writable); ...@@ -391,9 +391,7 @@ assertTrue(desc.writable);
// Check that exceptions thrown within prepareStackTrace throws an exception. // Check that exceptions thrown within prepareStackTrace throws an exception.
Error.prepareStackTrace = function(e, frames) { throw 42; } Error.prepareStackTrace = function(e, frames) { throw 42; }
assertThrows(() => new Error().stack);
var x = {}
assertThrows(() => Error.captureStackTrace(x));
// Check that we don't crash when CaptureSimpleStackTrace returns undefined. // Check that we don't crash when CaptureSimpleStackTrace returns undefined.
var o = {}; var o = {};
......
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