| Index: src/isolate.cc
|
| diff --git a/src/isolate.cc b/src/isolate.cc
|
| index 13627ad968b26e07249d4c489bbbf3910a2a3e02..5c7423288ffdf3a36087c8d0e562b79e80f8b9c5 100644
|
| --- a/src/isolate.cc
|
| +++ b/src/isolate.cc
|
| @@ -329,12 +329,34 @@ static Handle<FixedArray> MaybeGrow(Isolate* isolate,
|
| }
|
|
|
| class StackTraceHelper {
|
| + private:
|
| + enum FrameSkipMode {
|
| + SKIP_FIRST,
|
| + SKIP_UNTIL_SEEN,
|
| + SKIP_NONE,
|
| + };
|
| +
|
| public:
|
| StackTraceHelper(Isolate* isolate, Handle<Object> caller)
|
| : isolate_(isolate), caller_(caller) {
|
| - // If the caller parameter is a function we skip frames until we're
|
| - // under it before starting to collect.
|
| - seen_caller_ = !caller->IsJSFunction();
|
| + // The caller parameter can be used to skip a specific set of frames in the
|
| + // stack trace. It can be:
|
| + // * null, when called from a standard error constructor. We unconditionally
|
| + // skip the top frame, which is always a builtin-exit frame for the error
|
| + // constructor builtin.
|
| + // * a JSFunction, when called by the user from Error.captureStackTrace().
|
| + // We skip each frame until encountering the caller function.
|
| + // * For any other value, all frames are included in the trace.
|
| + if (caller_.is_null()) {
|
| + mode_ = SKIP_FIRST;
|
| + skip_next_frame_ = true;
|
| + } else if (caller_->IsJSFunction()) {
|
| + mode_ = SKIP_UNTIL_SEEN;
|
| + skip_next_frame_ = true;
|
| + } else {
|
| + mode_ = SKIP_NONE;
|
| + skip_next_frame_ = false;
|
| + }
|
| encountered_strict_function_ = false;
|
| sloppy_frames_ = 0;
|
| }
|
| @@ -356,26 +378,34 @@ class StackTraceHelper {
|
| // Determines whether the given stack frame should be displayed in a stack
|
| // trace.
|
| bool IsVisibleInStackTrace(JSFunction* fun) {
|
| - return IsAfterCaller(fun) && IsNotInNativeScript(fun) &&
|
| + return ShouldIncludeFrame(fun) && IsNotInNativeScript(fun) &&
|
| IsInSameSecurityContext(fun);
|
| }
|
|
|
| int sloppy_frames() const { return sloppy_frames_; }
|
|
|
| private:
|
| - // The caller is the error constructor that asked
|
| - // for the stack trace to be collected. The first time a construct
|
| - // call to this function is encountered it is skipped. The seen_caller
|
| - // in/out parameter is used to remember if the caller has been seen
|
| - // yet.
|
| - bool IsAfterCaller(JSFunction* fun) {
|
| - if ((fun == *caller_) && !(seen_caller_)) {
|
| - seen_caller_ = true;
|
| - return false;
|
| + // This mechanism excludes a number of uninteresting frames from the stack
|
| + // trace. This can be be the first frame (which will be a builtin-exit frame
|
| + // for the error constructor builtin) or every frame until encountering a
|
| + // user-specified function.
|
| + bool ShouldIncludeFrame(JSFunction* fun) {
|
| + switch (mode_) {
|
| + case SKIP_NONE:
|
| + return true;
|
| + case SKIP_FIRST:
|
| + if (!skip_next_frame_) return true;
|
| + skip_next_frame_ = false;
|
| + return false;
|
| + case SKIP_UNTIL_SEEN:
|
| + if (skip_next_frame_ && (fun == *caller_)) {
|
| + skip_next_frame_ = false;
|
| + return false;
|
| + }
|
| + return !skip_next_frame_;
|
| }
|
| - // Skip all frames until we've seen the caller.
|
| - if (!seen_caller_) return false;
|
| - return true;
|
| + UNREACHABLE();
|
| + return false;
|
| }
|
|
|
| bool IsNotInNativeScript(JSFunction* fun) {
|
| @@ -394,9 +424,11 @@ class StackTraceHelper {
|
| }
|
|
|
| Isolate* isolate_;
|
| +
|
| + FrameSkipMode mode_;
|
| Handle<Object> caller_;
|
| + bool skip_next_frame_;
|
|
|
| - bool seen_caller_;
|
| int sloppy_frames_;
|
| bool encountered_strict_function_;
|
| };
|
| @@ -531,8 +563,9 @@ MaybeHandle<JSReceiver> Isolate::CaptureAndSetDetailedStackTrace(
|
| Handle<JSArray> stack_trace = CaptureCurrentStackTrace(
|
| stack_trace_for_uncaught_exceptions_frame_limit_,
|
| stack_trace_for_uncaught_exceptions_options_);
|
| + // TODO(jgruber): Set back to STRICT once we have eagerly formatted traces.
|
| RETURN_ON_EXCEPTION(
|
| - this, JSReceiver::SetProperty(error_object, key, stack_trace, STRICT),
|
| + this, JSReceiver::SetProperty(error_object, key, stack_trace, SLOPPY),
|
| JSReceiver);
|
| }
|
| return error_object;
|
| @@ -543,8 +576,9 @@ MaybeHandle<JSReceiver> Isolate::CaptureAndSetSimpleStackTrace(
|
| // Capture stack trace for simple stack trace string formatting.
|
| Handle<Name> key = factory()->stack_trace_symbol();
|
| Handle<Object> stack_trace = CaptureSimpleStackTrace(error_object, caller);
|
| + // TODO(jgruber): Set back to STRICT once we have eagerly formatted traces.
|
| RETURN_ON_EXCEPTION(
|
| - this, JSReceiver::SetProperty(error_object, key, stack_trace, STRICT),
|
| + this, JSReceiver::SetProperty(error_object, key, stack_trace, SLOPPY),
|
| JSReceiver);
|
| return error_object;
|
| }
|
|
|