JSValue VM::throwException(ExecState* exec, JSValue error) { if (Options::breakOnThrow()) { dataLog("In call frame ", RawPointer(exec), " for code block ", *exec->codeBlock(), "\n"); CRASH(); } ASSERT(exec == topCallFrame || exec == exec->lexicalGlobalObject()->globalExec() || exec == exec->vmEntryGlobalObject()->globalExec()); Vector<StackFrame> stackTrace; interpreter->getStackTrace(stackTrace); m_exceptionStack = RefCountedArray<StackFrame>(stackTrace); m_exception = error; if (stackTrace.isEmpty() || !error.isObject()) return error; JSObject* exception = asObject(error); StackFrame stackFrame; for (unsigned i = 0 ; i < stackTrace.size(); ++i) { stackFrame = stackTrace.at(i); if (stackFrame.bytecodeOffset) break; } if (!hasErrorInfo(exec, exception)) { // FIXME: We should only really be adding these properties to VM generated exceptions, // but the inspector currently requires these for all thrown objects. unsigned line; unsigned column; stackFrame.computeLineAndColumn(line, column); exception->putDirect(*this, Identifier(this, "line"), jsNumber(line), ReadOnly | DontDelete); exception->putDirect(*this, Identifier(this, "column"), jsNumber(column), ReadOnly | DontDelete); if (!stackFrame.sourceURL.isEmpty()) exception->putDirect(*this, Identifier(this, "sourceURL"), jsString(this, stackFrame.sourceURL), ReadOnly | DontDelete); } if (exception->isErrorInstance() && static_cast<ErrorInstance*>(exception)->appendSourceToMessage()) { FindFirstCallerFrameWithCodeblockFunctor functor(exec); topCallFrame->iterate(functor); CallFrame* callFrame = functor.foundCallFrame(); unsigned stackIndex = functor.index(); if (callFrame && callFrame->codeBlock()) { stackFrame = stackTrace.at(stackIndex); appendSourceToError(callFrame, static_cast<ErrorInstance*>(exception), stackFrame.bytecodeOffset); } } if (exception->hasProperty(exec, this->propertyNames->stack)) return error; exception->putDirect(*this, propertyNames->stack, interpreter->stackTraceAsString(topCallFrame, stackTrace), DontEnum); return error; }
JSValue VM::throwException(ExecState* exec, JSValue error) { ASSERT(exec == topCallFrame || exec == exec->lexicalGlobalObject()->globalExec() || exec == exec->dynamicGlobalObject()->globalExec()); Vector<StackFrame> stackTrace; interpreter->getStackTrace(stackTrace); m_exceptionStack = RefCountedArray<StackFrame>(stackTrace); m_exception = error; if (stackTrace.isEmpty() || !error.isObject()) return error; JSObject* exception = asObject(error); StackFrame stackFrame; for (unsigned i = 0 ; i < stackTrace.size(); ++i) { stackFrame = stackTrace.at(i); if (stackFrame.bytecodeOffset) break; } unsigned bytecodeOffset = stackFrame.bytecodeOffset; if (!hasErrorInfo(exec, exception)) { // FIXME: We should only really be adding these properties to VM generated exceptions, // but the inspector currently requires these for all thrown objects. unsigned line; unsigned column; stackFrame.computeLineAndColumn(line, column); exception->putDirect(*this, Identifier(this, "line"), jsNumber(line), ReadOnly | DontDelete); exception->putDirect(*this, Identifier(this, "column"), jsNumber(column), ReadOnly | DontDelete); if (!stackFrame.sourceURL.isEmpty()) exception->putDirect(*this, Identifier(this, "sourceURL"), jsString(this, stackFrame.sourceURL), ReadOnly | DontDelete); } if (exception->isErrorInstance() && static_cast<ErrorInstance*>(exception)->appendSourceToMessage()) { unsigned stackIndex = 0; CallFrame* callFrame; for (callFrame = exec; callFrame && !callFrame->codeBlock(); callFrame = callFrame->callerFrame()->removeHostCallFrameFlag()) stackIndex++; if (callFrame && callFrame->codeBlock()) { stackFrame = stackTrace.at(stackIndex); bytecodeOffset = stackFrame.bytecodeOffset; appendSourceToError(callFrame, static_cast<ErrorInstance*>(exception), bytecodeOffset); } } if (exception->hasProperty(exec, this->propertyNames->stack)) return error; exception->putDirect(*this, propertyNames->stack, interpreter->stackTraceAsString(topCallFrame, stackTrace), DontEnum); return error; }
void ErrorInstance::finishCreation(ExecState* exec, VM& vm, const String& message, bool useCurrentFrame) { Base::finishCreation(vm); ASSERT(inherits(info())); if (!message.isNull()) putDirect(vm, vm.propertyNames->message, jsString(&vm, message), DontEnum); unsigned bytecodeOffset = hasSourceAppender(); CallFrame* callFrame = nullptr; bool hasTrace = addErrorInfoAndGetBytecodeOffset(exec, vm, this, useCurrentFrame, callFrame, bytecodeOffset); if (hasTrace && callFrame && hasSourceAppender()) { if (callFrame && callFrame->codeBlock()) appendSourceToError(callFrame, this, bytecodeOffset); } }