diff options
Diffstat (limited to 'JavaScriptCore/runtime/ExceptionHelpers.cpp')
| -rw-r--r-- | JavaScriptCore/runtime/ExceptionHelpers.cpp | 157 |
1 files changed, 53 insertions, 104 deletions
diff --git a/JavaScriptCore/runtime/ExceptionHelpers.cpp b/JavaScriptCore/runtime/ExceptionHelpers.cpp index b9c6319..1ef264c 100644 --- a/JavaScriptCore/runtime/ExceptionHelpers.cpp +++ b/JavaScriptCore/runtime/ExceptionHelpers.cpp @@ -31,11 +31,13 @@ #include "CodeBlock.h" #include "CallFrame.h" +#include "ErrorInstance.h" #include "JSGlobalObjectFunctions.h" #include "JSObject.h" #include "JSNotAnObject.h" #include "Interpreter.h" #include "Nodes.h" +#include "UStringConcatenate.h" namespace JSC { @@ -46,151 +48,98 @@ public: { } - virtual bool isWatchdogException() const { return true; } + virtual ComplType exceptionType() const { return Interrupted; } virtual UString toString(ExecState*) const { return "JavaScript execution exceeded timeout."; } }; -JSValue createInterruptedExecutionException(JSGlobalData* globalData) +JSObject* createInterruptedExecutionException(JSGlobalData* globalData) { return new (globalData) InterruptedExecutionError(globalData); } -static JSValue createError(ExecState* exec, ErrorType e, const char* msg) +class TerminatedExecutionError : public JSObject { +public: + TerminatedExecutionError(JSGlobalData* globalData) + : JSObject(globalData->terminatedExecutionErrorStructure) + { + } + + virtual ComplType exceptionType() const { return Terminated; } + + virtual UString toString(ExecState*) const { return "JavaScript execution terminated."; } +}; + +JSObject* createTerminatedExecutionException(JSGlobalData* globalData) { - return Error::create(exec, e, msg, -1, -1, UString()); + return new (globalData) TerminatedExecutionError(globalData); } -JSValue createStackOverflowError(ExecState* exec) +JSObject* createStackOverflowError(ExecState* exec) { - return createError(exec, RangeError, "Maximum call stack size exceeded."); + return createRangeError(exec, "Maximum call stack size exceeded."); } -JSValue createTypeError(ExecState* exec, const char* message) +JSObject* createStackOverflowError(JSGlobalObject* globalObject) { - return createError(exec, TypeError, message); + return createRangeError(globalObject, "Maximum call stack size exceeded."); } -JSValue createUndefinedVariableError(ExecState* exec, const Identifier& ident, unsigned bytecodeOffset, CodeBlock* codeBlock) +JSObject* createUndefinedVariableError(ExecState* exec, const Identifier& ident) { - int startOffset = 0; - int endOffset = 0; - int divotPoint = 0; - int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset); - JSObject* exception = Error::create(exec, ReferenceError, makeString("Can't find variable: ", ident.ustring()), line, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL()); - exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete); - exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete); - exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete); - return exception; + UString message(makeUString("Can't find variable: ", ident.ustring())); + return createReferenceError(exec, message); } -static UString createErrorMessage(ExecState* exec, CodeBlock* codeBlock, int, int expressionStart, int expressionStop, JSValue value, UString error) +JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValue value) { - if (!expressionStop || expressionStart > codeBlock->source()->length()) - return makeString(value.toString(exec), " is ", error); - if (expressionStart < expressionStop) - return makeString("Result of expression '", codeBlock->source()->getRange(expressionStart, expressionStop), "' [", value.toString(exec), "] is ", error, "."); - - // No range information, so give a few characters of context - const UChar* data = codeBlock->source()->data(); - int dataLength = codeBlock->source()->length(); - int start = expressionStart; - int stop = expressionStart; - // Get up to 20 characters of context to the left and right of the divot, clamping to the line. - // then strip whitespace. - while (start > 0 && (expressionStart - start < 20) && data[start - 1] != '\n') - start--; - while (start < (expressionStart - 1) && isStrWhiteSpace(data[start])) - start++; - while (stop < dataLength && (stop - expressionStart < 20) && data[stop] != '\n') - stop++; - while (stop > expressionStart && isStrWhiteSpace(data[stop])) - stop--; - return makeString("Result of expression near '...", codeBlock->source()->getRange(start, stop), "...' [", value.toString(exec), "] is ", error, "."); + UString errorMessage = makeUString("'", value.toString(exec), "' is not a valid argument for '", op, "'"); + JSObject* exception = createTypeError(exec, errorMessage); + ASSERT(exception->isErrorInstance()); + static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage(); + return exception; } -JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValue value, unsigned bytecodeOffset, CodeBlock* codeBlock) +JSObject* createNotAConstructorError(ExecState* exec, JSValue value) { - int startOffset = 0; - int endOffset = 0; - int divotPoint = 0; - int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset); - UString errorMessage = createErrorMessage(exec, codeBlock, line, divotPoint, divotPoint + endOffset, value, makeString("not a valid argument for '", op, "'")); - JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL()); - exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete); - exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete); - exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete); + UString errorMessage = makeUString("'", value.toString(exec), "' is not a constructor"); + JSObject* exception = createTypeError(exec, errorMessage); + ASSERT(exception->isErrorInstance()); + static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage(); return exception; } -JSObject* createNotAConstructorError(ExecState* exec, JSValue value, unsigned bytecodeOffset, CodeBlock* codeBlock) +JSObject* createNotAFunctionError(ExecState* exec, JSValue value) { - int startOffset = 0; - int endOffset = 0; - int divotPoint = 0; - int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset); - - // We're in a "new" expression, so we need to skip over the "new.." part - int startPoint = divotPoint - (startOffset ? startOffset - 4 : 0); // -4 for "new " - const UChar* data = codeBlock->source()->data(); - while (startPoint < divotPoint && isStrWhiteSpace(data[startPoint])) - startPoint++; - - UString errorMessage = createErrorMessage(exec, codeBlock, line, startPoint, divotPoint, value, "not a constructor"); - JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL()); - exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete); - exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete); - exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete); + UString errorMessage = makeUString("'", value.toString(exec), "' is not a function"); + JSObject* exception = createTypeError(exec, errorMessage); + ASSERT(exception->isErrorInstance()); + static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage(); return exception; } -JSValue createNotAFunctionError(ExecState* exec, JSValue value, unsigned bytecodeOffset, CodeBlock* codeBlock) +JSObject* createNotAnObjectError(ExecState* exec, JSValue value) { - int startOffset = 0; - int endOffset = 0; - int divotPoint = 0; - int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset); - UString errorMessage = createErrorMessage(exec, codeBlock, line, divotPoint - startOffset, divotPoint, value, "not a function"); - JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL()); - exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete); - exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete); - exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete); + UString errorMessage = makeUString("'", value.toString(exec), "' is not an object"); + JSObject* exception = createTypeError(exec, errorMessage); + ASSERT(exception->isErrorInstance()); + static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage(); return exception; } -JSNotAnObjectErrorStub* createNotAnObjectErrorStub(ExecState* exec, bool isNull) +JSObject* createErrorForInvalidGlobalAssignment(ExecState* exec, const UString& propertyName) { - return new (exec) JSNotAnObjectErrorStub(exec, isNull); -} + return createReferenceError(exec, makeUString("Strict mode forbids implicit creation of global property '", propertyName, "'")); +} -JSObject* createNotAnObjectError(ExecState* exec, JSNotAnObjectErrorStub* error, unsigned bytecodeOffset, CodeBlock* codeBlock) +JSObject* throwOutOfMemoryError(ExecState* exec) { - // Both op_construct and op_instanceof require a use of op_get_by_id to get - // the prototype property from an object. The exception messages for exceptions - // thrown by these instances op_get_by_id need to reflect this. - OpcodeID followingOpcodeID; - if (codeBlock->getByIdExceptionInfoForBytecodeOffset(exec, bytecodeOffset, followingOpcodeID)) { - ASSERT(followingOpcodeID == op_construct || followingOpcodeID == op_instanceof); - if (followingOpcodeID == op_construct) - return createNotAConstructorError(exec, error->isNull() ? jsNull() : jsUndefined(), bytecodeOffset, codeBlock); - return createInvalidParamError(exec, "instanceof", error->isNull() ? jsNull() : jsUndefined(), bytecodeOffset, codeBlock); - } - - int startOffset = 0; - int endOffset = 0; - int divotPoint = 0; - int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset); - UString errorMessage = createErrorMessage(exec, codeBlock, line, divotPoint - startOffset, divotPoint, error->isNull() ? jsNull() : jsUndefined(), "not an object"); - JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL()); - exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete); - exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete); - exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete); - return exception; + return throwError(exec, createError(exec, "Out of memory")); } -JSValue throwOutOfMemoryError(ExecState* exec) +JSObject* throwStackOverflowError(ExecState* exec) { - return throwError(exec, GeneralError, "Out of memory"); + return throwError(exec, createStackOverflowError(exec)); } } // namespace JSC |
