diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-05-20 09:56:07 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-05-20 09:56:07 +0000 |
commit | 41386e9cb918eed93b3f13648cbef387e371e451 (patch) | |
tree | a97f9d7bd1d9d091833286085f72da9d83fd0606 /Source/JavaScriptCore/runtime/ExceptionHelpers.cpp | |
parent | e15dd966d523731101f70ccf768bba12435a0208 (diff) | |
download | WebKitGtk-tarball-41386e9cb918eed93b3f13648cbef387e371e451.tar.gz |
webkitgtk-2.4.9webkitgtk-2.4.9
Diffstat (limited to 'Source/JavaScriptCore/runtime/ExceptionHelpers.cpp')
-rw-r--r-- | Source/JavaScriptCore/runtime/ExceptionHelpers.cpp | 233 |
1 files changed, 56 insertions, 177 deletions
diff --git a/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp b/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp index 46c0cef93..8f44248e3 100644 --- a/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp +++ b/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -31,28 +31,25 @@ #include "CodeBlock.h" #include "CallFrame.h" -#include "ErrorHandlingScope.h" -#include "Exception.h" +#include "ErrorInstance.h" #include "JSGlobalObjectFunctions.h" +#include "JSObject.h" #include "JSNotAnObject.h" #include "Interpreter.h" #include "Nodes.h" -#include "JSCInlines.h" -#include "RuntimeType.h" -#include <wtf/text/StringBuilder.h> -#include <wtf/text/StringView.h> +#include "Operations.h" namespace JSC { STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(TerminatedExecutionError); -const ClassInfo TerminatedExecutionError::s_info = { "TerminatedExecutionError", &Base::s_info, 0, CREATE_METHOD_TABLE(TerminatedExecutionError) }; +const ClassInfo TerminatedExecutionError::s_info = { "TerminatedExecutionError", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(TerminatedExecutionError) }; JSValue TerminatedExecutionError::defaultValue(const JSObject*, ExecState* exec, PreferredPrimitiveType hint) { if (hint == PreferString) return jsNontrivialString(exec, String(ASCIILiteral("JavaScript execution terminated."))); - return JSValue(PNaN); + return JSValue(QNaN); } JSObject* createTerminatedExecutionException(VM* vm) @@ -60,235 +57,117 @@ JSObject* createTerminatedExecutionException(VM* vm) return TerminatedExecutionError::create(*vm); } -bool isTerminatedExecutionException(Exception* exception) +bool isTerminatedExecutionException(JSObject* object) { - return exception->value().inherits(TerminatedExecutionError::info()); + return object->inherits(TerminatedExecutionError::info()); } +bool isTerminatedExecutionException(JSValue value) +{ + return value.inherits(TerminatedExecutionError::info()); +} + + JSObject* createStackOverflowError(ExecState* exec) { return createRangeError(exec, ASCIILiteral("Maximum call stack size exceeded.")); } +JSObject* createStackOverflowError(JSGlobalObject* globalObject) +{ + return createRangeError(globalObject, ASCIILiteral("Maximum call stack size exceeded.")); +} + JSObject* createUndefinedVariableError(ExecState* exec, const Identifier& ident) { - if (exec->propertyNames().isPrivateName(ident)) { - String message(makeString("Can't find private variable: @", exec->propertyNames().getPublicName(ident).string())); - return createReferenceError(exec, message); - } String message(makeString("Can't find variable: ", ident.string())); return createReferenceError(exec, message); } JSString* errorDescriptionForValue(ExecState* exec, JSValue v) { + VM& vm = exec->vm(); + if (v.isNull()) + return vm.smallStrings.nullString(); + if (v.isUndefined()) + return vm.smallStrings.undefinedString(); + if (v.isInt32()) + return jsString(&vm, vm.numericStrings.add(v.asInt32())); + if (v.isDouble()) + return jsString(&vm, vm.numericStrings.add(v.asDouble())); + if (v.isTrue()) + return vm.smallStrings.trueString(); + if (v.isFalse()) + return vm.smallStrings.falseString(); if (v.isString()) - return jsNontrivialString(exec, makeString('"', asString(v)->value(exec), '"')); + return jsCast<JSString*>(v.asCell()); if (v.isObject()) { CallData callData; JSObject* object = asObject(v); if (object->methodTable()->getCallData(object, callData) != CallTypeNone) - return exec->vm().smallStrings.functionString(); - return jsString(exec, JSObject::calculatedClassName(object)); + return vm.smallStrings.functionString(); + return jsString(exec, object->methodTable()->className(object)); } - return v.toString(exec); -} -static String defaultApproximateSourceError(const String& originalMessage, const String& sourceText) -{ - return makeString(originalMessage, " (near '...", sourceText, "...')"); -} - -static String defaultSourceAppender(const String& originalMessage, const String& sourceText, RuntimeType, ErrorInstance::SourceTextWhereErrorOccurred occurrence) -{ - if (occurrence == ErrorInstance::FoundApproximateSource) - return defaultApproximateSourceError(originalMessage, sourceText); - - ASSERT(occurrence == ErrorInstance::FoundExactSource); - return makeString(originalMessage, " (evaluating '", sourceText, "')"); -} - -static String functionCallBase(const String& sourceText) -{ - // This function retrieves the 'foo.bar' substring from 'foo.bar(baz)'. - // FIXME: This function has simple processing of /* */ style comments. - // It doesn't properly handle embedded comments of string literals that contain - // parenthesis or comment constructs, e.g. foo.bar("/abc\)*/"). - // https://bugs.webkit.org/show_bug.cgi?id=146304 - - unsigned sourceLength = sourceText.length(); - unsigned idx = sourceLength - 1; - if (sourceLength < 2 || sourceText[idx] != ')') { - // For function calls that have many new lines in between their open parenthesis - // and their closing parenthesis, the text range passed into the message appender - // will not inlcude the text in between these parentheses, it will just be the desired - // text that precedes the parentheses. - return sourceText; - } - - unsigned parenStack = 1; - bool isInMultiLineComment = false; - idx -= 1; - // Note that we're scanning text right to left instead of the more common left to right, - // so syntax detection is backwards. - while (parenStack > 0) { - UChar curChar = sourceText[idx]; - if (isInMultiLineComment) { - if (idx > 0 && curChar == '*' && sourceText[idx - 1] == '/') { - isInMultiLineComment = false; - idx -= 1; - } - } else if (curChar == '(') - parenStack -= 1; - else if (curChar == ')') - parenStack += 1; - else if (idx > 0 && curChar == '/' && sourceText[idx - 1] == '*') { - isInMultiLineComment = true; - idx -= 1; - } - - if (!idx) - break; - - idx -= 1; - } - - return sourceText.left(idx + 1); -} - -static String notAFunctionSourceAppender(const String& originalMessage, const String& sourceText, RuntimeType type, ErrorInstance::SourceTextWhereErrorOccurred occurrence) -{ - ASSERT(type != TypeFunction); - - if (occurrence == ErrorInstance::FoundApproximateSource) - return defaultApproximateSourceError(originalMessage, sourceText); - - ASSERT(occurrence == ErrorInstance::FoundExactSource); - auto notAFunctionIndex = originalMessage.reverseFind("is not a function"); - RELEASE_ASSERT(notAFunctionIndex != notFound); - StringView displayValue; - if (originalMessage.is8Bit()) - displayValue = StringView(originalMessage.characters8(), notAFunctionIndex - 1); - else - displayValue = StringView(originalMessage.characters16(), notAFunctionIndex - 1); - - String base = functionCallBase(sourceText); - StringBuilder builder; - builder.append(base); - builder.appendLiteral(" is not a function. (In '"); - builder.append(sourceText); - builder.appendLiteral("', '"); - builder.append(base); - builder.appendLiteral("' is "); - if (type == TypeObject) - builder.appendLiteral("an instance of "); - builder.append(displayValue); - builder.appendLiteral(")"); - - return builder.toString(); -} - -static String invalidParameterInSourceAppender(const String& originalMessage, const String& sourceText, RuntimeType type, ErrorInstance::SourceTextWhereErrorOccurred occurrence) -{ - ASSERT_UNUSED(type, type != TypeObject); - - if (occurrence == ErrorInstance::FoundApproximateSource) - return defaultApproximateSourceError(originalMessage, sourceText); - - ASSERT(occurrence == ErrorInstance::FoundExactSource); - auto inIndex = sourceText.reverseFind("in"); - RELEASE_ASSERT(inIndex != notFound); - if (sourceText.find("in") != inIndex) - return makeString(originalMessage, " (evaluating '", sourceText, "')"); - - static const unsigned inLength = 2; - String rightHandSide = sourceText.substring(inIndex + inLength).simplifyWhiteSpace(); - return makeString(rightHandSide, " is not an Object. (evaluating '", sourceText, "')"); + // The JSValue should never be empty, so this point in the code should never be reached. + ASSERT_NOT_REACHED(); + return vm.smallStrings.emptyString(); } - -static String invalidParameterInstanceofSourceAppender(const String& originalMessage, const String& sourceText, RuntimeType, ErrorInstance::SourceTextWhereErrorOccurred occurrence) -{ - if (occurrence == ErrorInstance::FoundApproximateSource) - return defaultApproximateSourceError(originalMessage, sourceText); - - ASSERT(occurrence == ErrorInstance::FoundExactSource); - auto instanceofIndex = sourceText.reverseFind("instanceof"); - RELEASE_ASSERT(instanceofIndex != notFound); - if (sourceText.find("instanceof") != instanceofIndex) - return makeString(originalMessage, " (evaluating '", sourceText, "')"); - - static const unsigned instanceofLength = 10; - String rightHandSide = sourceText.substring(instanceofIndex + instanceofLength).simplifyWhiteSpace(); - return makeString(rightHandSide, " is not a function. (evaluating '", sourceText, "')"); -} - -JSObject* createError(ExecState* exec, JSValue value, const String& message, ErrorInstance::SourceAppender appender) -{ - String errorMessage = makeString(errorDescriptionForValue(exec, value)->value(exec), ' ', message); - JSObject* exception = createTypeError(exec, errorMessage, appender, runtimeTypeForValue(value)); - ASSERT(exception->isErrorInstance()); - return exception; -} - -JSObject* createInvalidFunctionApplyParameterError(ExecState* exec, JSValue value) + +JSObject* createError(ExecState* exec, ErrorFactory errorFactory, JSValue value, const String& message) { - JSObject* exception = createTypeError(exec, makeString("second argument to Function.prototype.apply must be an Array-like object"), defaultSourceAppender, runtimeTypeForValue(value)); + String errorMessage = makeString(errorDescriptionForValue(exec, value)->value(exec), " ", message); + JSObject* exception = errorFactory(exec, errorMessage); ASSERT(exception->isErrorInstance()); + static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage(); return exception; } -JSObject* createInvalidInParameterError(ExecState* exec, JSValue value) -{ - return createError(exec, value, makeString("is not an Object."), invalidParameterInSourceAppender); -} - -JSObject* createInvalidInstanceofParameterError(ExecState* exec, JSValue value) +JSObject* createInvalidParameterError(ExecState* exec, const char* op, JSValue value) { - return createError(exec, value, makeString("is not a function."), invalidParameterInstanceofSourceAppender); + return createError(exec, createTypeError, value, makeString("is not a valid argument for '", op, "'")); } JSObject* createNotAConstructorError(ExecState* exec, JSValue value) { - return createError(exec, value, ASCIILiteral("is not a constructor"), defaultSourceAppender); + return createError(exec, createTypeError, value, "is not a constructor"); } JSObject* createNotAFunctionError(ExecState* exec, JSValue value) { - return createError(exec, value, ASCIILiteral("is not a function"), notAFunctionSourceAppender); + return createError(exec, createTypeError, value, "is not a function"); } JSObject* createNotAnObjectError(ExecState* exec, JSValue value) { - return createError(exec, value, ASCIILiteral("is not an object"), defaultSourceAppender); + return createError(exec, createTypeError, value, "is not an object"); } JSObject* createErrorForInvalidGlobalAssignment(ExecState* exec, const String& propertyName) { - return createReferenceError(exec, makeString("Strict mode forbids implicit creation of global property '", propertyName, '\'')); + return createReferenceError(exec, makeString("Strict mode forbids implicit creation of global property '", propertyName, "'")); } -JSObject* createTDZError(ExecState* exec) +JSObject* createOutOfMemoryError(JSGlobalObject* globalObject) { - return createReferenceError(exec, "Cannot access uninitialized variable."); + return createError(globalObject, ASCIILiteral("Out of memory")); } JSObject* throwOutOfMemoryError(ExecState* exec) { - return exec->vm().throwException(exec, createOutOfMemoryError(exec)); + return exec->vm().throwException(exec, createOutOfMemoryError(exec->lexicalGlobalObject())); } JSObject* throwStackOverflowError(ExecState* exec) { - VM& vm = exec->vm(); - ErrorHandlingScope errorScope(vm); - return vm.throwException(exec, createStackOverflowError(exec)); + Interpreter::ErrorHandlingMode mode(exec); + return exec->vm().throwException(exec, createStackOverflowError(exec)); } JSObject* throwTerminatedExecutionException(ExecState* exec) { - VM& vm = exec->vm(); - ErrorHandlingScope errorScope(vm); - return vm.throwException(exec, createTerminatedExecutionException(&vm)); + Interpreter::ErrorHandlingMode mode(exec); + return exec->vm().throwException(exec, createTerminatedExecutionException(&exec->vm())); } } // namespace JSC |