JSObject* createNotAnObjectError(ExecState* exec, JSValue value) { 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; }
JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValue value) { 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; }
JSValue createUndefinedVariableError(ExecState* exec, const Identifier& ident, unsigned bytecodeOffset, CodeBlock* codeBlock) { int startOffset = 0; int endOffset = 0; int divotPoint = 0; int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset); UString message(makeUString("Can't find variable: ", ident.ustring())); JSObject* exception = addErrorInfo(exec, createReferenceError(exec, message), line, codeBlock->ownerExecutable()->source(), divotPoint, startOffset, endOffset); return exception; }
CallIdentifier Profiler::createCallIdentifier(ExecState* exec, JSValue functionValue, const UString& defaultSourceURL, int defaultLineNumber) { if (!functionValue) return CallIdentifier(GlobalCodeExecution, defaultSourceURL, defaultLineNumber); if (!functionValue.isObject()) return CallIdentifier("(unknown)", defaultSourceURL, defaultLineNumber); if (asObject(functionValue)->inherits(&JSFunction::s_info) || asObject(functionValue)->inherits(&InternalFunction::s_info)) return createCallIdentifierFromFunctionImp(exec, asObject(functionValue), defaultSourceURL, defaultLineNumber); return CallIdentifier(makeUString("(", asObject(functionValue)->methodTable()->className(asObject(functionValue)), " object)"), defaultSourceURL, defaultLineNumber); }
// Compatibility hack for the Optimost Ti library. (See <rdar://problem/6595040>.) static inline void insertSemicolonIfNeeded(UString& functionBody) { ASSERT(functionBody[0] == '{'); ASSERT(functionBody[functionBody.length() - 1] == '}'); for (size_t i = functionBody.length() - 2; i > 0; --i) { UChar ch = functionBody[i]; if (!Lexer::isWhiteSpace(ch) && !Lexer::isLineTerminator(ch)) { if (ch != ';' && ch != '}') functionBody = makeUString(functionBody.substringSharingImpl(0, i + 1), ";", functionBody.substringSharingImpl(i + 1, functionBody.length() - (i + 1))); return; } } }
static UString createErrorMessage(ExecState* exec, CodeBlock* codeBlock, int, int expressionStart, int expressionStop, JSValue value, UString error) { if (!expressionStop || expressionStart > codeBlock->source()->length()) return makeUString(value.toString(exec), " is ", error); if (expressionStart < expressionStop) return makeUString("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 makeUString("Result of expression near '...", codeBlock->source()->getRange(start, stop), "...' [", value.toString(exec), "] is ", error, "."); }
CallIdentifier Profiler::createCallIdentifier(ExecState* exec, JSValue functionValue, const UString& defaultSourceURL, int defaultLineNumber) { if (!functionValue) return CallIdentifier(GlobalCodeExecution, defaultSourceURL, defaultLineNumber); if (!functionValue.isObject()) return CallIdentifier("(unknown)", defaultSourceURL, defaultLineNumber); if (asObject(functionValue)->inherits(&JSFunction::info)) { JSFunction* function = asFunction(functionValue); if (!function->executable()->isHostFunction()) return createCallIdentifierFromFunctionImp(exec, function); } if (asObject(functionValue)->inherits(&JSFunction::info)) return CallIdentifier(static_cast<JSFunction*>(asObject(functionValue))->name(exec), defaultSourceURL, defaultLineNumber); if (asObject(functionValue)->inherits(&InternalFunction::info)) return CallIdentifier(static_cast<InternalFunction*>(asObject(functionValue))->name(exec), defaultSourceURL, defaultLineNumber); return CallIdentifier(makeUString("(", asObject(functionValue)->className(), " object)"), defaultSourceURL, defaultLineNumber); }
// ECMA 15.3.2 The Function Constructor JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifier& functionName, const UString& sourceURL, int lineNumber) { // Functions need to have a space following the opening { due to for web compatibility // see https://bugs.webkit.org/show_bug.cgi?id=24350 // We also need \n before the closing } to handle // comments at the end of the last line UString program; if (args.isEmpty()) program = "(function() { \n})"; else if (args.size() == 1) program = makeUString("(function() { ", args.at(0).toString(exec), "\n})"); else { UStringBuilder builder; builder.append("(function("); builder.append(args.at(0).toString(exec)); for (size_t i = 1; i < args.size() - 1; i++) { builder.append(","); builder.append(args.at(i).toString(exec)); } builder.append(") { "); builder.append(args.at(args.size() - 1).toString(exec)); builder.append("\n})"); program = builder.toUString(); } JSGlobalObject* globalObject = exec->lexicalGlobalObject(); JSGlobalData& globalData = globalObject->globalData(); SourceCode source = makeSource(program, sourceURL, lineNumber); JSObject* exception = 0; RefPtr<FunctionExecutable> function = FunctionExecutable::fromGlobalCode(functionName, exec, exec->dynamicGlobalObject()->debugger(), source, &exception); if (!function) { ASSERT(exception); return throwError(exec, exception); } ScopeChain scopeChain(globalObject, &globalData, globalObject, exec->globalThisValue()); return new (exec) JSFunction(exec, function, scopeChain.node()); }
JSObject* createErrorForInvalidGlobalAssignment(ExecState* exec, const UString& propertyName) { return createReferenceError(exec, makeUString("Strict mode forbids implicit creation of global property '", propertyName, "'")); }
JSObject* createUndefinedVariableError(ExecState* exec, const Identifier& ident) { UString message(makeUString("Can't find variable: ", ident.ustring())); return createReferenceError(exec, message); }
JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValue value, unsigned bytecodeOffset, CodeBlock* 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, divotPoint + endOffset, value, makeUString("not a valid argument for '", op, "'")); JSObject* exception = addErrorInfo(exec, createTypeError(exec, errorMessage), line, codeBlock->ownerExecutable()->source(), divotPoint, startOffset, endOffset); return exception; }