Changeset 214289 in webkit


Ignore:
Timestamp:
Mar 22, 2017 6:14:06 PM (7 years ago)
Author:
mark.lam@apple.com
Message:

Add support for Error.stackTraceLimit.
https://bugs.webkit.org/show_bug.cgi?id=169904

Reviewed by Saam Barati.

JSTests:

  • stress/error-stack-trace-limit.js: Added.

Source/JavaScriptCore:

Since there's no standard for this yet, we'll implement Error.stackTraceLimit
based on how Chrome does it. This includes some idiosyncrasies like:

  1. If we set Error.stackTraceLimit = 0, then new Error().stack yields an empty stack trace (Chrome has a title with no stack frame entries).
  2. If we set Error.stackTraceLimit = {] (i.e. to a non-number value), then new Error().stack is undefined.

Chrome and IE defaults their Error.stackTraceLimit to 10. We'll default ours to
100 because 10 may be a bit too skimpy and it is not that costly to allow up to
100 frames instead of 10.

The default value for Error.stackTraceLimit is specified by
Options::defaultErrorStackTraceLimit().

Also, the Exception object now limits the number of stack trace frames it captures
to the limit specified by Options::exceptionStackTraceLimit().

Note: the Exception object captures a stack trace that is not necessarily the
same as the one in an Error object being thrown:

  • The Error object captures the stack trace at the point of object creation.
  • The Exception object captures the stack trace at the point that the exception is thrown. This stack trace is captured even when throwing a value that is not an Error object e.g. a primitive value. The Exception object stack trace is only used by WebInspector to identify where a value is thrown from. Hence, it does not necessary make sense the Exception object stack trace limited by Error.stackTraceLimit. Instead, we have it use own Options::exceptionStackTraceLimit().
  • interpreter/Interpreter.cpp:

(JSC::Interpreter::unwind):

  • jsc.cpp:

(dumpException):

  • runtime/CommonIdentifiers.h:
  • runtime/Error.cpp:

(JSC::addErrorInfoAndGetBytecodeOffset):

  • runtime/ErrorConstructor.cpp:

(JSC::ErrorConstructor::finishCreation):
(JSC::ErrorConstructor::put):
(JSC::ErrorConstructor::deleteProperty):

  • runtime/ErrorConstructor.h:

(JSC::ErrorConstructor::stackTraceLimit):

  • runtime/Exception.cpp:

(JSC::Exception::finishCreation):

  • runtime/Options.h:

LayoutTests:

Rebased test.

  • js/Object-getOwnPropertyNames-expected.txt:
  • js/script-tests/Object-getOwnPropertyNames.js:
Location:
trunk
Files:
1 added
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r214272 r214289  
     12017-03-22  Mark Lam  <mark.lam@apple.com>
     2
     3        Add support for Error.stackTraceLimit.
     4        https://bugs.webkit.org/show_bug.cgi?id=169904
     5
     6        Reviewed by Saam Barati.
     7
     8        * stress/error-stack-trace-limit.js: Added.
     9
    1102017-03-22  Yusuke Suzuki  <utatane.tea@gmail.com>
    211
  • trunk/LayoutTests/ChangeLog

    r214286 r214289  
     12017-03-22  Mark Lam  <mark.lam@apple.com>
     2
     3        Add support for Error.stackTraceLimit.
     4        https://bugs.webkit.org/show_bug.cgi?id=169904
     5
     6        Reviewed by Saam Barati.
     7
     8        Rebased test.
     9
     10        * js/Object-getOwnPropertyNames-expected.txt:
     11        * js/script-tests/Object-getOwnPropertyNames.js:
     12
    1132017-03-22  Carlos Alberto Lopez Perez  <clopez@igalia.com>
    214
  • trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt

    r205856 r214289  
    5858PASS getSortedOwnPropertyNames(RegExp) is ['$&', "$'", '$*', '$+', '$1', '$2', '$3', '$4', '$5', '$6', '$7', '$8', '$9', '$_', '$`', 'input', 'lastMatch', 'lastParen', 'leftContext', 'length', 'multiline', 'name', 'prototype', 'rightContext']
    5959PASS getSortedOwnPropertyNames(RegExp.prototype) is ['compile', 'constructor', 'exec', 'flags', 'global', 'ignoreCase', 'multiline', 'source', 'sticky', 'test', 'toString', 'unicode']
    60 PASS getSortedOwnPropertyNames(Error) is ['length', 'name', 'prototype']
     60PASS getSortedOwnPropertyNames(Error) is ['length', 'name', 'prototype', 'stackTraceLimit']
    6161PASS getSortedOwnPropertyNames(Error.prototype) is ['constructor', 'message', 'name', 'toString']
    6262PASS getSortedOwnPropertyNames(Math) is ['E','LN10','LN2','LOG10E','LOG2E','PI','SQRT1_2','SQRT2','abs','acos','acosh','asin','asinh','atan','atan2','atanh','cbrt','ceil','clz32','cos','cosh','exp','expm1','floor','fround','hypot','imul','log','log10','log1p','log2','max','min','pow','random','round','sign','sin','sinh','sqrt','tan','tanh','trunc']
  • trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js

    r205856 r214289  
    6767    "RegExp": "['$&', \"$'\", '$*', '$+', '$1', '$2', '$3', '$4', '$5', '$6', '$7', '$8', '$9', '$_', '$`', 'input', 'lastMatch', 'lastParen', 'leftContext', 'length', 'multiline', 'name', 'prototype', 'rightContext']",
    6868    "RegExp.prototype": "['compile', 'constructor', 'exec', 'flags', 'global', 'ignoreCase', 'multiline', 'source', 'sticky', 'test', 'toString', 'unicode']",
    69     "Error": "['length', 'name', 'prototype']",
     69    "Error": "['length', 'name', 'prototype', 'stackTraceLimit']",
    7070    "Error.prototype": "['constructor', 'message', 'name', 'toString']",
    7171    "Math": "['E','LN10','LN2','LOG10E','LOG2E','PI','SQRT1_2','SQRT2','abs','acos','acosh','asin','asinh','atan','atan2','atanh','cbrt','ceil','clz32','cos','cosh','exp','expm1','floor','fround','hypot','imul','log','log10','log1p','log2','max','min','pow','random','round','sign','sin','sinh','sqrt','tan','tanh','trunc']",
  • trunk/Source/JavaScriptCore/ChangeLog

    r214272 r214289  
     12017-03-22  Mark Lam  <mark.lam@apple.com>
     2
     3        Add support for Error.stackTraceLimit.
     4        https://bugs.webkit.org/show_bug.cgi?id=169904
     5
     6        Reviewed by Saam Barati.
     7
     8        Since there's no standard for this yet, we'll implement Error.stackTraceLimit
     9        based on how Chrome does it.  This includes some idiosyncrasies like:
     10        1. If we set Error.stackTraceLimit = 0, then new Error().stack yields an empty
     11           stack trace (Chrome has a title with no stack frame entries).
     12        2. If we set Error.stackTraceLimit = {] (i.e. to a non-number value), then
     13           new Error().stack is undefined.
     14
     15        Chrome and IE defaults their Error.stackTraceLimit to 10.  We'll default ours to
     16        100 because 10 may be a bit too skimpy and it is not that costly to allow up to
     17        100 frames instead of 10.
     18
     19        The default value for Error.stackTraceLimit is specified by
     20        Options::defaultErrorStackTraceLimit().
     21
     22        Also, the Exception object now limits the number of stack trace frames it captures
     23        to the limit specified by Options::exceptionStackTraceLimit().
     24
     25        Note: the Exception object captures a stack trace that is not necessarily the
     26        same as the one in an Error object being thrown:
     27
     28        - The Error object captures the stack trace at the point of object creation.
     29
     30        - The Exception object captures the stack trace at the point that the exception
     31          is thrown.  This stack trace is captured even when throwing a value that is not
     32          an Error object e.g. a primitive value.  The Exception object stack trace is
     33          only used by WebInspector to identify where a value is thrown from.  Hence,
     34          it does not necessary make sense the Exception object stack trace limited by
     35          Error.stackTraceLimit.  Instead, we have it use own Options::exceptionStackTraceLimit().
     36
     37        * interpreter/Interpreter.cpp:
     38        (JSC::Interpreter::unwind):
     39        * jsc.cpp:
     40        (dumpException):
     41        * runtime/CommonIdentifiers.h:
     42        * runtime/Error.cpp:
     43        (JSC::addErrorInfoAndGetBytecodeOffset):
     44        * runtime/ErrorConstructor.cpp:
     45        (JSC::ErrorConstructor::finishCreation):
     46        (JSC::ErrorConstructor::put):
     47        (JSC::ErrorConstructor::deleteProperty):
     48        * runtime/ErrorConstructor.h:
     49        (JSC::ErrorConstructor::stackTraceLimit):
     50        * runtime/Exception.cpp:
     51        (JSC::Exception::finishCreation):
     52        * runtime/Options.h:
     53
    1542017-03-22  Yusuke Suzuki  <utatane.tea@gmail.com>
    255
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r214005 r214289  
    683683        exceptionValue = jsNull();
    684684
    685     ASSERT_UNUSED(scope, scope.exception() && scope.exception()->stack().size());
     685    ASSERT_UNUSED(scope, scope.exception() && (!Options::exceptionStackTraceLimit() || scope.exception()->stack().size()));
    686686
    687687    // Calculate an exception handler vPC, unwinding call frames as necessary.
  • trunk/Source/JavaScriptCore/jsc.cpp

    r214016 r214289  
    33513351    }
    33523352   
    3353     if (!stackValue.isUndefinedOrNull())
    3354         printf("%s\n", stackValue.toWTFString(globalObject->globalExec()).utf8().data());
     3353    if (!stackValue.isUndefinedOrNull()) {
     3354        auto stackString = stackValue.toWTFString(globalObject->globalExec());
     3355        if (stackString.length())
     3356            printf("%s\n", stackString.utf8().data());
     3357    }
    33553358
    33563359#undef CHECK_EXCEPTION
  • trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h

    r214045 r214289  
    11/*
    2  *  Copyright (C) 2003, 2007, 2009, 2016 Apple Inc. All rights reserved.
     2 *  Copyright (C) 2003-2017 Apple Inc. All rights reserved.
    33 *
    44 *  This library is free software; you can redistribute it and/or
     
    282282    macro(sourceURL) \
    283283    macro(stack) \
     284    macro(stackTraceLimit) \
    284285    macro(sticky) \
    285286    macro(subarray) \
  • trunk/Source/JavaScriptCore/runtime/Error.cpp

    r209696 r214289  
    22 *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
    33 *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
    4  *  Copyright (C) 2003-2006, 2008, 2016 Apple Inc. All rights reserved.
     4 *  Copyright (C) 2003-2017 Apple Inc. All rights reserved.
    55 *  Copyright (C) 2007 Eric Seidel (eric@webkit.org)
    66 *
     
    158158bool addErrorInfoAndGetBytecodeOffset(ExecState* exec, VM& vm, JSObject* obj, bool useCurrentFrame, CallFrame*& callFrame, unsigned* bytecodeOffset)
    159159{
     160    JSGlobalObject* globalObject = obj->globalObject();
     161    ErrorConstructor* errorConstructor = globalObject->errorConstructor();
     162    if (!errorConstructor->stackTraceLimit())
     163        return false;
     164
    160165    Vector<StackFrame> stackTrace = Vector<StackFrame>();
    161 
    162166    size_t framesToSkip = useCurrentFrame ? 0 : 1;
    163     vm.interpreter->getStackTrace(stackTrace, framesToSkip);
     167    vm.interpreter->getStackTrace(stackTrace, framesToSkip, errorConstructor->stackTraceLimit().value());
    164168    if (!stackTrace.isEmpty()) {
    165169
     
    197201        return true;
    198202    }
     203
     204    obj->putDirect(vm, vm.propertyNames->stack, vm.smallStrings.emptyString(), DontEnum);
    199205    return false;
    200206}
  • trunk/Source/JavaScriptCore/runtime/ErrorConstructor.cpp

    r209229 r214289  
    11/*
    22 *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
    3  *  Copyright (C) 2003, 2008, 2016 Apple Inc. All rights reserved.
     3 *  Copyright (C) 2003-2017 Apple Inc. All rights reserved.
    44 *
    55 *  This library is free software; you can redistribute it and/or
     
    4545    putDirectWithoutTransition(vm, vm.propertyNames->prototype, errorPrototype, DontEnum | DontDelete | ReadOnly);
    4646    putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), DontEnum | ReadOnly);
     47
     48    unsigned defaultStackTraceLimit = Options::defaultErrorStackTraceLimit();
     49    m_stackTraceLimit = defaultStackTraceLimit;
     50    putDirectWithoutTransition(vm, vm.propertyNames->stackTraceLimit, jsNumber(defaultStackTraceLimit), None);
    4751}
    4852
     
    7983}
    8084
     85bool ErrorConstructor::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
     86{
     87    VM& vm = exec->vm();
     88    ErrorConstructor* thisObject = jsCast<ErrorConstructor*>(cell);
     89
     90    if (propertyName == vm.propertyNames->stackTraceLimit) {
     91        if (value.isNumber()) {
     92            double effectiveLimit = value.asNumber();
     93            effectiveLimit = std::max(0., effectiveLimit);
     94            effectiveLimit = std::min(effectiveLimit, static_cast<double>(std::numeric_limits<unsigned>::max()));
     95            thisObject->m_stackTraceLimit = static_cast<unsigned>(effectiveLimit);
     96        } else
     97            thisObject->m_stackTraceLimit = { };
     98    }
     99
     100    return Base::put(thisObject, exec, propertyName, value, slot);
     101}
     102
     103bool ErrorConstructor::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
     104{
     105    VM& vm = exec->vm();
     106    ErrorConstructor* thisObject = jsCast<ErrorConstructor*>(cell);
     107
     108    if (propertyName == vm.propertyNames->stackTraceLimit)
     109        thisObject->m_stackTraceLimit = { };
     110
     111    return Base::deleteProperty(thisObject, exec, propertyName);
     112}
     113
    81114} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/ErrorConstructor.h

    r206525 r214289  
    11/*
    22 *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
    3  *  Copyright (C) 2008 Apple Inc. All rights reserved.
     3 *  Copyright (C) 2008-2017 Apple Inc. All rights reserved.
    44 *
    55 *  This library is free software; you can redistribute it and/or
     
    4747    }
    4848
     49    std::optional<unsigned> stackTraceLimit() const { return m_stackTraceLimit; }
     50
    4951protected:
    5052    void finishCreation(VM&, ErrorPrototype*);
    51        
     53
     54    static bool put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
     55    static bool deleteProperty(JSCell*, ExecState*, PropertyName);
     56
    5257private:
    5358    ErrorConstructor(VM&, Structure*);
    5459    static ConstructType getConstructData(JSCell*, ConstructData&);
    5560    static CallType getCallData(JSCell*, CallData&);
     61
     62    std::optional<unsigned> m_stackTraceLimit;
    5663};
    5764
  • trunk/Source/JavaScriptCore/runtime/Exception.cpp

    r209897 r214289  
    11/*
    2  * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    7878    Vector<StackFrame> stackTrace;
    7979    if (action == StackCaptureAction::CaptureStack)
    80         vm.interpreter->getStackTrace(stackTrace);
     80        vm.interpreter->getStackTrace(stackTrace, 0, Options::exceptionStackTraceLimit());
    8181    m_stack = WTFMove(stackTrace);
    8282}
  • trunk/Source/JavaScriptCore/runtime/Options.h

    r214187 r214289  
    377377    v(unsigned, numberOfGCCyclesToRecordForVerification, 3, Normal, nullptr) \
    378378    \
     379    v(unsigned, exceptionStackTraceLimit, 100, Normal, "Stack trace limit for internal Exception object") \
     380    v(unsigned, defaultErrorStackTraceLimit, 100, Normal, "The default value for Error.stackTraceLimit") \
    379381    v(bool, useExceptionFuzz, false, Normal, nullptr) \
    380382    v(unsigned, fireExceptionFuzzAt, 0, Normal, nullptr) \
Note: See TracChangeset for help on using the changeset viewer.