diff options
Diffstat (limited to 'JavaScriptCore/runtime')
50 files changed, 639 insertions, 1002 deletions
diff --git a/JavaScriptCore/runtime/Arguments.cpp b/JavaScriptCore/runtime/Arguments.cpp index 450dc7d..5c5e522 100644 --- a/JavaScriptCore/runtime/Arguments.cpp +++ b/JavaScriptCore/runtime/Arguments.cpp @@ -153,6 +153,30 @@ bool Arguments::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& sl return JSObject::getOwnPropertySlot(exec, Identifier(exec, UString::number(i)), slot); } + +void Arguments::createStrictModeCallerIfNecessary(ExecState* exec) +{ + if (d->overrodeCaller) + return; + + d->overrodeCaller = true; + PropertyDescriptor descriptor; + JSValue thrower = createTypeErrorFunction(exec, "Unable to access caller of strict mode function"); + descriptor.setAccessorDescriptor(thrower, thrower, DontEnum | DontDelete | Getter | Setter); + defineOwnProperty(exec, exec->propertyNames().caller, descriptor, false); +} + +void Arguments::createStrictModeCalleeIfNecessary(ExecState* exec) +{ + if (d->overrodeCallee) + return; + + d->overrodeCallee = true; + PropertyDescriptor descriptor; + JSValue thrower = createTypeErrorFunction(exec, "Unable to access callee of strict mode function"); + descriptor.setAccessorDescriptor(thrower, thrower, DontEnum | DontDelete | Getter | Setter); + defineOwnProperty(exec, exec->propertyNames().callee, descriptor, false); +} bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { @@ -172,10 +196,16 @@ bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyNa } if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) { - slot.setValue(d->callee); - return true; + if (!d->isStrictMode) { + slot.setValue(d->callee); + return true; + } + createStrictModeCalleeIfNecessary(exec); } + if (propertyName == exec->propertyNames().caller && d->isStrictMode) + createStrictModeCallerIfNecessary(exec); + return JSObject::getOwnPropertySlot(exec, propertyName, slot); } @@ -197,9 +227,15 @@ bool Arguments::getOwnPropertyDescriptor(ExecState* exec, const Identifier& prop } if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) { - descriptor.setDescriptor(d->callee, DontEnum); - return true; + if (!d->isStrictMode) { + descriptor.setDescriptor(d->callee, DontEnum); + return true; + } + createStrictModeCalleeIfNecessary(exec); } + + if (propertyName == exec->propertyNames().caller && d->isStrictMode) + createStrictModeCallerIfNecessary(exec); return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor); } @@ -249,11 +285,17 @@ void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue val } if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) { - d->overrodeCallee = true; - putDirect(propertyName, value, DontEnum); - return; + if (!d->isStrictMode) { + d->overrodeCallee = true; + putDirect(propertyName, value, DontEnum); + return; + } + createStrictModeCalleeIfNecessary(exec); } + if (propertyName == exec->propertyNames().caller && d->isStrictMode) + createStrictModeCallerIfNecessary(exec); + JSObject::put(exec, propertyName, value, slot); } @@ -294,9 +336,15 @@ bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName) } if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) { - d->overrodeCallee = true; - return true; + if (!d->isStrictMode) { + d->overrodeCallee = true; + return true; + } + createStrictModeCalleeIfNecessary(exec); } + + if (propertyName == exec->propertyNames().caller && !d->isStrictMode) + createStrictModeCallerIfNecessary(exec); return JSObject::deleteProperty(exec, propertyName); } diff --git a/JavaScriptCore/runtime/Arguments.h b/JavaScriptCore/runtime/Arguments.h index 49c8b3b..715a2ac 100644 --- a/JavaScriptCore/runtime/Arguments.h +++ b/JavaScriptCore/runtime/Arguments.h @@ -50,6 +50,8 @@ namespace JSC { JSFunction* callee; bool overrodeLength : 1; bool overrodeCallee : 1; + bool overrodeCaller : 1; + bool isStrictMode : 1; }; @@ -105,6 +107,8 @@ namespace JSC { virtual void put(ExecState*, unsigned propertyName, JSValue, PutPropertySlot&); virtual bool deleteProperty(ExecState*, const Identifier& propertyName); virtual bool deleteProperty(ExecState*, unsigned propertyName); + void createStrictModeCallerIfNecessary(ExecState*); + void createStrictModeCalleeIfNecessary(ExecState*); virtual const ClassInfo* classInfo() const { return &info; } @@ -172,6 +176,10 @@ namespace JSC { d->callee = callee; d->overrodeLength = false; d->overrodeCallee = false; + d->overrodeCaller = false; + d->isStrictMode = callFrame->codeBlock()->isStrictMode(); + if (d->isStrictMode) + copyRegisters(); } inline Arguments::Arguments(CallFrame* callFrame, NoParametersType) @@ -201,6 +209,10 @@ namespace JSC { d->callee = asFunction(callFrame->callee()); d->overrodeLength = false; d->overrodeCallee = false; + d->overrodeCaller = false; + d->isStrictMode = callFrame->codeBlock()->isStrictMode(); + if (d->isStrictMode) + copyRegisters(); } inline void Arguments::copyRegisters() diff --git a/JavaScriptCore/runtime/ArrayPrototype.cpp b/JavaScriptCore/runtime/ArrayPrototype.cpp index 28269ff..6002ebb 100644 --- a/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -180,7 +180,14 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec) unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); unsigned totalSize = length ? length - 1 : 0; +#if OS(SYMBIAN) + // Symbian has very limited stack size available. + // This function could be called recursively and allocating 1K on stack here cause + // stack overflow on Symbian devices. + Vector<RefPtr<StringImpl> > strBuffer(length); +#else Vector<RefPtr<StringImpl>, 256> strBuffer(length); +#endif for (unsigned k = 0; k < length; k++) { JSValue element; if (isRealArray && thisObj->canGetIndex(k)) diff --git a/JavaScriptCore/runtime/Collector.cpp b/JavaScriptCore/runtime/Collector.cpp index 93b91bb..f341646 100644 --- a/JavaScriptCore/runtime/Collector.cpp +++ b/JavaScriptCore/runtime/Collector.cpp @@ -642,19 +642,6 @@ inline bool isPointerAligned(void* p) // Cell size needs to be a power of two for isPossibleCell to be valid. COMPILE_ASSERT(sizeof(CollectorCell) % 2 == 0, Collector_cell_size_is_power_of_two); -#if USE(JSVALUE32) -static bool isHalfCellAligned(void *p) -{ - return (((intptr_t)(p) & (CELL_MASK >> 1)) == 0); -} - -static inline bool isPossibleCell(void* p) -{ - return isHalfCellAligned(p) && p; -} - -#else - static inline bool isCellAligned(void *p) { return (((intptr_t)(p) & CELL_MASK) == 0); @@ -664,7 +651,6 @@ static inline bool isPossibleCell(void* p) { return isCellAligned(p) && p; } -#endif // USE(JSVALUE32) void Heap::markConservatively(MarkStack& markStack, void* start, void* end) { @@ -1145,10 +1131,6 @@ static const char* typeName(JSCell* cell) { if (cell->isString()) return "string"; -#if USE(JSVALUE32) - if (cell->isNumber()) - return "number"; -#endif if (cell->isGetterSetter()) return "Getter-Setter"; if (cell->isAPIValueWrapper()) diff --git a/JavaScriptCore/runtime/Collector.h b/JavaScriptCore/runtime/Collector.h index 05d5c10..237c139 100644 --- a/JavaScriptCore/runtime/Collector.h +++ b/JavaScriptCore/runtime/Collector.h @@ -57,7 +57,7 @@ namespace JSC { class LiveObjectIterator; -#if OS(WINCE) || OS(SYMBIAN) +#if OS(WINCE) || OS(SYMBIAN) || PLATFORM(BREWMP) const size_t BLOCK_SIZE = 64 * 1024; // 64k #else const size_t BLOCK_SIZE = 256 * 1024; // 256k diff --git a/JavaScriptCore/runtime/CommonIdentifiers.cpp b/JavaScriptCore/runtime/CommonIdentifiers.cpp index 3837817..1561102 100644 --- a/JavaScriptCore/runtime/CommonIdentifiers.cpp +++ b/JavaScriptCore/runtime/CommonIdentifiers.cpp @@ -32,6 +32,7 @@ CommonIdentifiers::CommonIdentifiers(JSGlobalData* globalData) , emptyIdentifier(globalData, "") , underscoreProto(globalData, "__proto__") , thisIdentifier(globalData, "this") + , useStrictIdentifier(globalData, "use strict") JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_PROPERTY_NAME) { } diff --git a/JavaScriptCore/runtime/CommonIdentifiers.h b/JavaScriptCore/runtime/CommonIdentifiers.h index de24f4a..1e22b6a 100644 --- a/JavaScriptCore/runtime/CommonIdentifiers.h +++ b/JavaScriptCore/runtime/CommonIdentifiers.h @@ -94,6 +94,7 @@ namespace JSC { const Identifier emptyIdentifier; const Identifier underscoreProto; const Identifier thisIdentifier; + const Identifier useStrictIdentifier; #define JSC_IDENTIFIER_DECLARE_PROPERTY_NAME_GLOBAL(name) const Identifier name; JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(JSC_IDENTIFIER_DECLARE_PROPERTY_NAME_GLOBAL) diff --git a/JavaScriptCore/runtime/DateConversion.cpp b/JavaScriptCore/runtime/DateConversion.cpp index 7eb82e4..d4b8232 100644 --- a/JavaScriptCore/runtime/DateConversion.cpp +++ b/JavaScriptCore/runtime/DateConversion.cpp @@ -57,7 +57,9 @@ double parseDate(ExecState* exec, const UString &date) { if (date == exec->globalData().cachedDateString) return exec->globalData().cachedDateStringValue; - double value = parseDateFromNullTerminatedCharacters(exec, date.utf8().data()); + double value = parseES5DateFromNullTerminatedCharacters(date.utf8().data()); + if (isnan(value)) + value = parseDateFromNullTerminatedCharacters(exec, date.utf8().data()); exec->globalData().cachedDateString = date; exec->globalData().cachedDateStringValue = value; return value; diff --git a/JavaScriptCore/runtime/Error.cpp b/JavaScriptCore/runtime/Error.cpp index a2be473..e35424b 100644 --- a/JavaScriptCore/runtime/Error.cpp +++ b/JavaScriptCore/runtime/Error.cpp @@ -195,4 +195,47 @@ JSObject* throwSyntaxError(ExecState* exec) return throwError(exec, createSyntaxError(exec, "Syntax error")); } +class StrictModeTypeErrorFunction : public InternalFunction { +public: + StrictModeTypeErrorFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, const UString& message) + : InternalFunction(&exec->globalData(), globalObject, structure, exec->globalData().propertyNames->emptyIdentifier) + , m_message(message) + { + } + + static EncodedJSValue JSC_HOST_CALL constructThrowTypeError(ExecState* exec) + { + throwTypeError(exec, static_cast<StrictModeTypeErrorFunction*>(exec->callee())->m_message); + return JSValue::encode(jsNull()); + } + + ConstructType getConstructData(ConstructData& constructData) + { + constructData.native.function = constructThrowTypeError; + return ConstructTypeHost; + } + + static EncodedJSValue JSC_HOST_CALL callThrowTypeError(ExecState* exec) + { + throwTypeError(exec, static_cast<StrictModeTypeErrorFunction*>(exec->callee())->m_message); + return JSValue::encode(jsNull()); + } + + CallType getCallData(CallData& callData) + { + callData.native.function = callThrowTypeError; + return CallTypeHost; + } + +private: + UString m_message; +}; + +COMPILE_ASSERT(sizeof(StrictModeTypeErrorFunction) <= sizeof(CollectorCell), sizeof_StrictModeTypeErrorFunction_must_be_less_than_CollectorCell); + +JSValue createTypeErrorFunction(ExecState* exec, const UString& message) +{ + return new (exec) StrictModeTypeErrorFunction(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->internalFunctionStructure(), message); +} + } // namespace JSC diff --git a/JavaScriptCore/runtime/Error.h b/JavaScriptCore/runtime/Error.h index 1a0ece5..bfde7dc 100644 --- a/JavaScriptCore/runtime/Error.h +++ b/JavaScriptCore/runtime/Error.h @@ -73,6 +73,8 @@ namespace JSC { inline EncodedJSValue throwVMError(ExecState* exec, JSValue error) { return JSValue::encode(throwError(exec, error)); } inline EncodedJSValue throwVMTypeError(ExecState* exec) { return JSValue::encode(throwTypeError(exec)); } + JSValue createTypeErrorFunction(ExecState* exec, const UString& message); + } // namespace JSC #endif // Error_h diff --git a/JavaScriptCore/runtime/ExceptionHelpers.cpp b/JavaScriptCore/runtime/ExceptionHelpers.cpp index 9a6fe5e..a1e28d1 100644 --- a/JavaScriptCore/runtime/ExceptionHelpers.cpp +++ b/JavaScriptCore/runtime/ExceptionHelpers.cpp @@ -36,7 +36,7 @@ #include "JSNotAnObject.h" #include "Interpreter.h" #include "Nodes.h" -#include "StringConcatenate.h" +#include "UStringConcatenate.h" namespace JSC { @@ -90,7 +90,7 @@ JSValue createUndefinedVariableError(ExecState* exec, const Identifier& ident, u int endOffset = 0; int divotPoint = 0; int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset); - UString message(makeString("Can't find variable: ", ident.ustring())); + 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; } @@ -98,9 +98,9 @@ JSValue createUndefinedVariableError(ExecState* exec, const Identifier& ident, u static UString createErrorMessage(ExecState* exec, CodeBlock* codeBlock, int, int expressionStart, int expressionStop, JSValue value, UString error) { if (!expressionStop || expressionStart > codeBlock->source()->length()) - return makeString(value.toString(exec), " is ", error); + return makeUString(value.toString(exec), " is ", error); if (expressionStart < expressionStop) - return makeString("Result of expression '", codeBlock->source()->getRange(expressionStart, expressionStop), "' [", value.toString(exec), "] is ", error, "."); + 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(); @@ -117,7 +117,7 @@ static UString createErrorMessage(ExecState* exec, CodeBlock* codeBlock, int, in stop++; while (stop > expressionStart && isStrWhiteSpace(data[stop])) stop--; - return makeString("Result of expression near '...", codeBlock->source()->getRange(start, stop), "...' [", value.toString(exec), "] is ", error, "."); + return makeUString("Result of expression near '...", codeBlock->source()->getRange(start, stop), "...' [", value.toString(exec), "] is ", error, "."); } JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValue value, unsigned bytecodeOffset, CodeBlock* codeBlock) @@ -126,7 +126,7 @@ JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValue value 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, "'")); + 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; } @@ -192,4 +192,9 @@ JSValue throwOutOfMemoryError(ExecState* exec) return throwError(exec, createError(exec, "Out of memory")); } +JSObject* createErrorForInvalidGlobalAssignment(ExecState* exec, const UString& propertyName) +{ + return createReferenceError(exec, makeUString("Strict mode forbids implicit creation of global property '", propertyName, "'")); +} + } // namespace JSC diff --git a/JavaScriptCore/runtime/ExceptionHelpers.h b/JavaScriptCore/runtime/ExceptionHelpers.h index 3e6de86..9b6f1f2 100644 --- a/JavaScriptCore/runtime/ExceptionHelpers.h +++ b/JavaScriptCore/runtime/ExceptionHelpers.h @@ -54,6 +54,7 @@ namespace JSC { JSValue createNotAFunctionError(ExecState*, JSValue, unsigned bytecodeOffset, CodeBlock*); JSObject* createNotAnObjectError(ExecState*, JSNotAnObjectErrorStub*, unsigned bytecodeOffset, CodeBlock*); JSValue throwOutOfMemoryError(ExecState*); + JSObject* createErrorForInvalidGlobalAssignment(ExecState*, const UString&); } // namespace JSC diff --git a/JavaScriptCore/runtime/Executable.cpp b/JavaScriptCore/runtime/Executable.cpp index 871f3e2..2ad4b2d 100644 --- a/JavaScriptCore/runtime/Executable.cpp +++ b/JavaScriptCore/runtime/Executable.cpp @@ -30,7 +30,7 @@ #include "CodeBlock.h" #include "JIT.h" #include "Parser.h" -#include "StringBuilder.h" +#include "UStringBuilder.h" #include "Vector.h" namespace JSC { @@ -45,8 +45,8 @@ VPtrHackExecutable::~VPtrHackExecutable() { } -EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source) - : ScriptExecutable(exec, source) +EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext) + : ScriptExecutable(exec, source, inStrictContext) { } @@ -55,7 +55,7 @@ EvalExecutable::~EvalExecutable() } ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source) - : ScriptExecutable(exec, source) + : ScriptExecutable(exec, source, false) { } @@ -63,8 +63,8 @@ ProgramExecutable::~ProgramExecutable() { } -FunctionExecutable::FunctionExecutable(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine) - : ScriptExecutable(globalData, source) +FunctionExecutable::FunctionExecutable(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext, int firstLine, int lastLine) + : ScriptExecutable(globalData, source, inStrictContext) , m_numCapturedVariables(0) , m_forceUsesArguments(forceUsesArguments) , m_parameters(parameters) @@ -75,8 +75,8 @@ FunctionExecutable::FunctionExecutable(JSGlobalData* globalData, const Identifie m_lastLine = lastLine; } -FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine) - : ScriptExecutable(exec, source) +FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext, int firstLine, int lastLine) + : ScriptExecutable(exec, source, inStrictContext) , m_numCapturedVariables(0) , m_forceUsesArguments(forceUsesArguments) , m_parameters(parameters) @@ -96,7 +96,7 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scope JSObject* exception = 0; JSGlobalData* globalData = &exec->globalData(); JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject(); - RefPtr<EvalNode> evalNode = globalData->parser->parse<EvalNode>(globalData, lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, 0, &exception); + RefPtr<EvalNode> evalNode = globalData->parser->parse<EvalNode>(lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, 0, isStrictMode() ? JSParseStrict : JSParseNormal, &exception); if (!evalNode) { ASSERT(exception); return exception; @@ -131,7 +131,7 @@ JSObject* ProgramExecutable::checkSyntax(ExecState* exec) JSObject* exception = 0; JSGlobalData* globalData = &exec->globalData(); JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject(); - RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(globalData, lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, 0, &exception); + RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, 0, JSParseNormal, &exception); if (programNode) return 0; ASSERT(exception); @@ -145,7 +145,7 @@ JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* sc JSObject* exception = 0; JSGlobalData* globalData = &exec->globalData(); JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject(); - RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(globalData, lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, 0, &exception); + RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, 0, isStrictMode() ? JSParseStrict : JSParseNormal, &exception); if (!programNode) { ASSERT(exception); return exception; @@ -178,7 +178,7 @@ JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChain { JSObject* exception = 0; JSGlobalData* globalData = scopeChainNode->globalData; - RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, exec->lexicalGlobalObject(), 0, 0, m_source, m_parameters.get(), &exception); + RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(exec->lexicalGlobalObject(), 0, 0, m_source, m_parameters.get(), isStrictMode() ? JSParseStrict : JSParseNormal, &exception); if (!body) { ASSERT(exception); return exception; @@ -219,7 +219,7 @@ JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, Scope { JSObject* exception = 0; JSGlobalData* globalData = scopeChainNode->globalData; - RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, exec->lexicalGlobalObject(), 0, 0, m_source, m_parameters.get(), &exception); + RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(exec->lexicalGlobalObject(), 0, 0, m_source, m_parameters.get(), isStrictMode() ? JSParseStrict : JSParseNormal, &exception); if (!body) { ASSERT(exception); return exception; @@ -264,12 +264,14 @@ void FunctionExecutable::markAggregate(MarkStack& markStack) m_codeBlockForConstruct->markAggregate(markStack); } -PassOwnPtr<ExceptionInfo> FunctionExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock) +PassOwnPtr<ExceptionInfo> FunctionExecutable::reparseExceptionInfo(ScopeChainNode* scopeChainNode, CodeBlock* codeBlock) { JSObject* exception = 0; - RefPtr<FunctionBodyNode> newFunctionBody = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, 0, m_source, m_parameters.get(), &exception); + JSGlobalData* globalData = scopeChainNode->globalData; + RefPtr<FunctionBodyNode> newFunctionBody = globalData->parser->parse<FunctionBodyNode>(scopeChainNode->globalObject, 0, 0, m_source, m_parameters.get(), isStrictMode() ? JSParseStrict : JSParseNormal, &exception); if (!newFunctionBody) return PassOwnPtr<ExceptionInfo>(); + ASSERT(newFunctionBody->isStrictMode() == isStrictMode()); if (m_forceUsesArguments) newFunctionBody->setUsesArguments(); newFunctionBody->finishParsing(m_parameters, m_name); @@ -298,10 +300,12 @@ PassOwnPtr<ExceptionInfo> FunctionExecutable::reparseExceptionInfo(JSGlobalData* return newCodeBlock->extractExceptionInfo(); } -PassOwnPtr<ExceptionInfo> EvalExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock) +PassOwnPtr<ExceptionInfo> EvalExecutable::reparseExceptionInfo(ScopeChainNode* scopeChainNode, CodeBlock* codeBlock) { JSObject* exception = 0; - RefPtr<EvalNode> newEvalBody = globalData->parser->parse<EvalNode>(globalData, 0, 0, 0, m_source, 0, &exception); + JSGlobalData* globalData = scopeChainNode->globalData; + RefPtr<EvalNode> newEvalBody = globalData->parser->parse<EvalNode>(scopeChainNode->globalObject, 0, 0, m_source, 0, isStrictMode() ? JSParseStrict : JSParseNormal, &exception); + ASSERT(newEvalBody->isStrictMode() == isStrictMode()); if (!newEvalBody) return PassOwnPtr<ExceptionInfo>(); @@ -341,7 +345,7 @@ void FunctionExecutable::recompile(ExecState*) PassRefPtr<FunctionExecutable> FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception) { JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject(); - RefPtr<ProgramNode> program = exec->globalData().parser->parse<ProgramNode>(&exec->globalData(), lexicalGlobalObject, debugger, exec, source, 0, exception); + RefPtr<ProgramNode> program = exec->globalData().parser->parse<ProgramNode>(lexicalGlobalObject, debugger, exec, source, 0, JSParseNormal, exception); if (!program) { ASSERT(*exception); return 0; @@ -357,22 +361,22 @@ PassRefPtr<FunctionExecutable> FunctionExecutable::fromGlobalCode(const Identifi FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body(); ASSERT(body); - return FunctionExecutable::create(&exec->globalData(), functionName, body->source(), body->usesArguments(), body->parameters(), body->lineNo(), body->lastLine()); + return FunctionExecutable::create(&exec->globalData(), functionName, body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine()); } UString FunctionExecutable::paramString() const { FunctionParameters& parameters = *m_parameters; - StringBuilder builder; + UStringBuilder builder; for (size_t pos = 0; pos < parameters.size(); ++pos) { if (!builder.isEmpty()) builder.append(", "); builder.append(parameters[pos].ustring()); } - return builder.build(); + return builder.toUString(); } -PassOwnPtr<ExceptionInfo> ProgramExecutable::reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*) +PassOwnPtr<ExceptionInfo> ProgramExecutable::reparseExceptionInfo(ScopeChainNode*, CodeBlock*) { // CodeBlocks for program code are transient and therefore do not gain from from throwing out their exception information. return PassOwnPtr<ExceptionInfo>(); diff --git a/JavaScriptCore/runtime/Executable.h b/JavaScriptCore/runtime/Executable.h index feab7ef..4c4ca56 100644 --- a/JavaScriptCore/runtime/Executable.h +++ b/JavaScriptCore/runtime/Executable.h @@ -138,10 +138,10 @@ namespace JSC { class ScriptExecutable : public ExecutableBase { public: - ScriptExecutable(JSGlobalData* globalData, const SourceCode& source) + ScriptExecutable(JSGlobalData* globalData, const SourceCode& source, bool isInStrictContext) : ExecutableBase(NUM_PARAMETERS_NOT_COMPILED) , m_source(source) - , m_features(0) + , m_features(isInStrictContext ? StrictModeFeature : 0) { #if ENABLE(CODEBLOCK_SAMPLING) relaxAdoptionRequirement(); @@ -152,10 +152,10 @@ namespace JSC { #endif } - ScriptExecutable(ExecState* exec, const SourceCode& source) + ScriptExecutable(ExecState* exec, const SourceCode& source, bool isInStrictContext) : ExecutableBase(NUM_PARAMETERS_NOT_COMPILED) , m_source(source) - , m_features(0) + , m_features(isInStrictContext ? StrictModeFeature : 0) { #if ENABLE(CODEBLOCK_SAMPLING) relaxAdoptionRequirement(); @@ -175,8 +175,9 @@ namespace JSC { bool usesEval() const { return m_features & EvalFeature; } bool usesArguments() const { return m_features & ArgumentsFeature; } bool needsActivation() const { return m_hasCapturedVariables || m_features & (EvalFeature | WithFeature | CatchFeature); } + bool isStrictMode() const { return m_features & StrictModeFeature; } - virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*) = 0; + virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(ScopeChainNode*, CodeBlock*) = 0; protected: void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine) @@ -214,7 +215,7 @@ namespace JSC { return *m_evalCodeBlock; } - static PassRefPtr<EvalExecutable> create(ExecState* exec, const SourceCode& source) { return adoptRef(new EvalExecutable(exec, source)); } + static PassRefPtr<EvalExecutable> create(ExecState* exec, const SourceCode& source, bool isInStrictContext) { return adoptRef(new EvalExecutable(exec, source, isInStrictContext)); } #if ENABLE(JIT) JITCode& generatedJITCode() @@ -224,11 +225,11 @@ namespace JSC { #endif private: - EvalExecutable(ExecState*, const SourceCode&); + EvalExecutable(ExecState*, const SourceCode&, bool); JSObject* compileInternal(ExecState*, ScopeChainNode*); - virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*); + virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(ScopeChainNode*, CodeBlock*); OwnPtr<EvalCodeBlock> m_evalCodeBlock; }; @@ -271,7 +272,7 @@ namespace JSC { JSObject* compileInternal(ExecState*, ScopeChainNode*); - virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*); + virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(ScopeChainNode*, CodeBlock*); OwnPtr<ProgramCodeBlock> m_programCodeBlock; }; @@ -279,14 +280,14 @@ namespace JSC { class FunctionExecutable : public ScriptExecutable { friend class JIT; public: - static PassRefPtr<FunctionExecutable> create(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine) + static PassRefPtr<FunctionExecutable> create(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine) { - return adoptRef(new FunctionExecutable(exec, name, source, forceUsesArguments, parameters, firstLine, lastLine)); + return adoptRef(new FunctionExecutable(exec, name, source, forceUsesArguments, parameters, isInStrictContext, firstLine, lastLine)); } - static PassRefPtr<FunctionExecutable> create(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine) + static PassRefPtr<FunctionExecutable> create(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine) { - return adoptRef(new FunctionExecutable(globalData, name, source, forceUsesArguments, parameters, firstLine, lastLine)); + return adoptRef(new FunctionExecutable(globalData, name, source, forceUsesArguments, parameters, isInStrictContext, firstLine, lastLine)); } ~FunctionExecutable(); @@ -358,13 +359,13 @@ namespace JSC { static PassRefPtr<FunctionExecutable> fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception); private: - FunctionExecutable(JSGlobalData*, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, int firstLine, int lastLine); - FunctionExecutable(ExecState*, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, int firstLine, int lastLine); + FunctionExecutable(JSGlobalData*, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool, int firstLine, int lastLine); + FunctionExecutable(ExecState*, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool, int firstLine, int lastLine); JSObject* compileForCallInternal(ExecState*, ScopeChainNode*); JSObject* compileForConstructInternal(ExecState*, ScopeChainNode*); - virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*); + virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(ScopeChainNode*, CodeBlock*); unsigned m_numCapturedVariables : 31; bool m_forceUsesArguments : 1; diff --git a/JavaScriptCore/runtime/FunctionConstructor.cpp b/JavaScriptCore/runtime/FunctionConstructor.cpp index f72a273..9b59720 100644 --- a/JavaScriptCore/runtime/FunctionConstructor.cpp +++ b/JavaScriptCore/runtime/FunctionConstructor.cpp @@ -30,8 +30,8 @@ #include "Lexer.h" #include "Nodes.h" #include "Parser.h" -#include "StringBuilder.h" -#include "StringConcatenate.h" +#include "UStringBuilder.h" +#include "UStringConcatenate.h" namespace JSC { @@ -81,9 +81,9 @@ JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifi if (args.isEmpty()) program = "(function() { \n})"; else if (args.size() == 1) - program = makeString("(function() { ", args.at(0).toString(exec), "\n})"); + program = makeUString("(function() { ", args.at(0).toString(exec), "\n})"); else { - StringBuilder builder; + UStringBuilder builder; builder.append("(function("); builder.append(args.at(0).toString(exec)); for (size_t i = 1; i < args.size() - 1; i++) { @@ -93,7 +93,7 @@ JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifi builder.append(") { "); builder.append(args.at(args.size() - 1).toString(exec)); builder.append("\n})"); - program = builder.build(); + program = builder.toUString(); } JSGlobalObject* globalObject = exec->lexicalGlobalObject(); diff --git a/JavaScriptCore/runtime/FunctionPrototype.cpp b/JavaScriptCore/runtime/FunctionPrototype.cpp index c740624..ef42cdc 100644 --- a/JavaScriptCore/runtime/FunctionPrototype.cpp +++ b/JavaScriptCore/runtime/FunctionPrototype.cpp @@ -77,7 +77,7 @@ static inline void insertSemicolonIfNeeded(UString& functionBody) UChar ch = functionBody[i]; if (!Lexer::isWhiteSpace(ch) && !Lexer::isLineTerminator(ch)) { if (ch != ';' && ch != '}') - functionBody = makeString(functionBody.substringSharingImpl(0, i + 1), ";", functionBody.substringSharingImpl(i + 1, functionBody.length() - (i + 1))); + functionBody = makeUString(functionBody.substringSharingImpl(0, i + 1), ";", functionBody.substringSharingImpl(i + 1, functionBody.length() - (i + 1))); return; } } diff --git a/JavaScriptCore/runtime/JSActivation.cpp b/JavaScriptCore/runtime/JSActivation.cpp index d121518..795ad1f 100644 --- a/JavaScriptCore/runtime/JSActivation.cpp +++ b/JavaScriptCore/runtime/JSActivation.cpp @@ -186,6 +186,11 @@ JSObject* JSActivation::toThisObject(ExecState* exec) const return exec->globalThisValue(); } +JSValue JSActivation::toStrictThisObject(ExecState*) const +{ + return jsNull(); +} + bool JSActivation::isDynamicScope(bool& requiresDynamicChecks) const { requiresDynamicChecks = d()->functionExecutable->usesEval(); diff --git a/JavaScriptCore/runtime/JSActivation.h b/JavaScriptCore/runtime/JSActivation.h index 9ff9168..6dd6d70 100644 --- a/JavaScriptCore/runtime/JSActivation.h +++ b/JavaScriptCore/runtime/JSActivation.h @@ -60,6 +60,7 @@ namespace JSC { virtual bool deleteProperty(ExecState*, const Identifier& propertyName); virtual JSObject* toThisObject(ExecState*) const; + virtual JSValue toStrictThisObject(ExecState*) const; void copyRegisters(); diff --git a/JavaScriptCore/runtime/JSCell.h b/JavaScriptCore/runtime/JSCell.h index cfa1454..1a7f8b2 100644 --- a/JavaScriptCore/runtime/JSCell.h +++ b/JavaScriptCore/runtime/JSCell.h @@ -75,9 +75,6 @@ namespace JSC { } // Querying the type. -#if USE(JSVALUE32) - bool isNumber() const; -#endif bool isString() const; bool isObject() const; virtual bool isGetterSetter() const; @@ -156,13 +153,6 @@ namespace JSC { { } -#if USE(JSVALUE32) - inline bool JSCell::isNumber() const - { - return m_structure->typeInfo().type() == NumberType; - } -#endif - inline bool JSCell::isObject() const { return m_structure->typeInfo().type() == ObjectType; @@ -253,13 +243,13 @@ namespace JSC { return false; } -#if !USE(JSVALUE32_64) +#if USE(JSVALUE64) ALWAYS_INLINE JSCell* JSValue::asCell() const { ASSERT(isCell()); return m_ptr; } -#endif // !USE(JSVALUE32_64) +#endif // USE(JSVALUE64) inline JSValue JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const { diff --git a/JavaScriptCore/runtime/JSFunction.cpp b/JavaScriptCore/runtime/JSFunction.cpp index 7eb9ba5..fdaa509 100644 --- a/JavaScriptCore/runtime/JSFunction.cpp +++ b/JavaScriptCore/runtime/JSFunction.cpp @@ -122,6 +122,15 @@ JSFunction::~JSFunction() } } +static const char* StrictModeCallerAccessError = "Cannot access caller property of a strict mode function"; +static const char* StrictModeArgumentsAccessError = "Cannot access arguments property of a strict mode function"; + +static void createDescriptorForThrowingProperty(ExecState* exec, PropertyDescriptor& descriptor, const char* message) +{ + JSValue thrower = createTypeErrorFunction(exec, message); + descriptor.setAccessorDescriptor(thrower, thrower, DontEnum | DontDelete | Getter | Setter); +} + const UString& JSFunction::name(ExecState* exec) { return asString(getDirect(exec->globalData().propertyNames->name))->tryGetValue(); @@ -209,6 +218,12 @@ bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyN } if (propertyName == exec->propertyNames().arguments) { + if (jsExecutable()->isStrictMode()) { + throwTypeError(exec, "Can't access arguments object of a strict mode function"); + slot.setValue(jsNull()); + return true; + } + slot.setCacheableCustom(this, argumentsGetter); return true; } @@ -219,6 +234,11 @@ bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyN } if (propertyName == exec->propertyNames().caller) { + if (jsExecutable()->isStrictMode()) { + throwTypeError(exec, StrictModeCallerAccessError); + slot.setValue(jsNull()); + return true; + } slot.setCacheableCustom(this, callerGetter); return true; } @@ -226,35 +246,41 @@ bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyN return Base::getOwnPropertySlot(exec, propertyName, slot); } - bool JSFunction::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) - { - if (isHostFunction()) - return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); - - if (propertyName == exec->propertyNames().prototype) { - PropertySlot slot; - getOwnPropertySlot(exec, propertyName, slot); - return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); - } - - if (propertyName == exec->propertyNames().arguments) { +bool JSFunction::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + if (isHostFunction()) + return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); + + if (propertyName == exec->propertyNames().prototype) { + PropertySlot slot; + getOwnPropertySlot(exec, propertyName, slot); + return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); + } + + if (propertyName == exec->propertyNames().arguments) { + if (jsExecutable()->isStrictMode()) + createDescriptorForThrowingProperty(exec, descriptor, StrictModeArgumentsAccessError); + else descriptor.setDescriptor(exec->interpreter()->retrieveArguments(exec, this), ReadOnly | DontEnum | DontDelete); - return true; - } - - if (propertyName == exec->propertyNames().length) { - descriptor.setDescriptor(jsNumber(exec, jsExecutable()->parameterCount()), ReadOnly | DontEnum | DontDelete); - return true; - } - - if (propertyName == exec->propertyNames().caller) { + return true; + } + + if (propertyName == exec->propertyNames().length) { + descriptor.setDescriptor(jsNumber(exec, jsExecutable()->parameterCount()), ReadOnly | DontEnum | DontDelete); + return true; + } + + if (propertyName == exec->propertyNames().caller) { + if (jsExecutable()->isStrictMode()) + createDescriptorForThrowingProperty(exec, descriptor, StrictModeCallerAccessError); + else descriptor.setDescriptor(exec->interpreter()->retrieveCaller(exec, this), ReadOnly | DontEnum | DontDelete); - return true; - } - - return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); + return true; } + return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); +} + void JSFunction::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { if (!isHostFunction() && (mode == IncludeDontEnumProperties)) { @@ -272,6 +298,16 @@ void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValue va Base::put(exec, propertyName, value, slot); return; } + if (jsExecutable()->isStrictMode()) { + if (propertyName == exec->propertyNames().arguments) { + throwTypeError(exec, StrictModeArgumentsAccessError); + return; + } + if (propertyName == exec->propertyNames().caller) { + throwTypeError(exec, StrictModeCallerAccessError); + return; + } + } if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length) return; Base::put(exec, propertyName, value, slot); diff --git a/JavaScriptCore/runtime/JSGlobalData.cpp b/JavaScriptCore/runtime/JSGlobalData.cpp index 5eaa59b..1404ddf 100644 --- a/JavaScriptCore/runtime/JSGlobalData.cpp +++ b/JavaScriptCore/runtime/JSGlobalData.cpp @@ -50,6 +50,7 @@ #include "Nodes.h" #include "Parser.h" #include "RegExpCache.h" +#include "StrictEvalActivation.h" #include <wtf/WTFThreadData.h> #if ENABLE(REGEXP_TRACING) #include "RegExp.h" @@ -124,6 +125,7 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread , interruptedExecutionErrorStructure(JSObject::createStructure(jsNull())) , terminatedExecutionErrorStructure(JSObject::createStructure(jsNull())) , staticScopeStructure(JSStaticScopeObject::createStructure(jsNull())) + , strictEvalActivationStructure(StrictEvalActivation::createStructure(jsNull())) , stringStructure(JSString::createStructure(jsNull())) , notAnObjectErrorStubStructure(JSNotAnObjectErrorStub::createStructure(jsNull())) , notAnObjectStructure(JSNotAnObject::createStructure(jsNull())) @@ -131,9 +133,6 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread , getterSetterStructure(GetterSetter::createStructure(jsNull())) , apiWrapperStructure(JSAPIValueWrapper::createStructure(jsNull())) , dummyMarkableCellStructure(JSCell::createDummyStructure()) -#if USE(JSVALUE32) - , numberStructure(JSNumberCell::createStructure(jsNull())) -#endif , identifierTable(globalDataType == Default ? wtfThreadData().currentIdentifierTable() : createIdentifierTable()) , propertyNames(new CommonIdentifiers(this)) , emptyList(new MarkedArgumentBuffer) diff --git a/JavaScriptCore/runtime/JSGlobalData.h b/JavaScriptCore/runtime/JSGlobalData.h index 8e2ed61..775d026 100644 --- a/JavaScriptCore/runtime/JSGlobalData.h +++ b/JavaScriptCore/runtime/JSGlobalData.h @@ -145,6 +145,7 @@ namespace JSC { RefPtr<Structure> interruptedExecutionErrorStructure; RefPtr<Structure> terminatedExecutionErrorStructure; RefPtr<Structure> staticScopeStructure; + RefPtr<Structure> strictEvalActivationStructure; RefPtr<Structure> stringStructure; RefPtr<Structure> notAnObjectErrorStubStructure; RefPtr<Structure> notAnObjectStructure; @@ -153,10 +154,6 @@ namespace JSC { RefPtr<Structure> apiWrapperStructure; RefPtr<Structure> dummyMarkableCellStructure; -#if USE(JSVALUE32) - RefPtr<Structure> numberStructure; -#endif - static void storeVPtrs(); static JS_EXPORTDATA void* jsArrayVPtr; static JS_EXPORTDATA void* jsByteArrayVPtr; diff --git a/JavaScriptCore/runtime/JSGlobalObject.cpp b/JavaScriptCore/runtime/JSGlobalObject.cpp index 89c042a..903e573 100644 --- a/JavaScriptCore/runtime/JSGlobalObject.cpp +++ b/JavaScriptCore/runtime/JSGlobalObject.cpp @@ -204,6 +204,7 @@ void JSGlobalObject::reset(JSValue prototype) d()->functionPrototype = new (exec) FunctionPrototype(exec, this, FunctionPrototype::createStructure(jsNull())); // The real prototype will be set once ObjectPrototype is created. d()->prototypeFunctionStructure = PrototypeFunction::createStructure(d()->functionPrototype); + d()->internalFunctionStructure = InternalFunction::createStructure(d()->functionPrototype); NativeFunctionWrapper* callFunction = 0; NativeFunctionWrapper* applyFunction = 0; d()->functionPrototype->addFunctionProperties(exec, this, d()->prototypeFunctionStructure.get(), &callFunction, &applyFunction); diff --git a/JavaScriptCore/runtime/JSGlobalObject.h b/JavaScriptCore/runtime/JSGlobalObject.h index f5d2fb0..36fa70b 100644 --- a/JavaScriptCore/runtime/JSGlobalObject.h +++ b/JavaScriptCore/runtime/JSGlobalObject.h @@ -148,6 +148,7 @@ namespace JSC { RefPtr<Structure> regExpMatchesArrayStructure; RefPtr<Structure> regExpStructure; RefPtr<Structure> stringObjectStructure; + RefPtr<Structure> internalFunctionStructure; SymbolTable symbolTable; unsigned profileGroup; @@ -243,6 +244,7 @@ namespace JSC { Structure* functionStructure() const { return d()->functionStructure.get(); } Structure* numberObjectStructure() const { return d()->numberObjectStructure.get(); } Structure* prototypeFunctionStructure() const { return d()->prototypeFunctionStructure.get(); } + Structure* internalFunctionStructure() const { return d()->internalFunctionStructure.get(); } Structure* regExpMatchesArrayStructure() const { return d()->regExpMatchesArrayStructure.get(); } Structure* regExpStructure() const { return d()->regExpStructure.get(); } Structure* stringObjectStructure() const { return d()->stringObjectStructure.get(); } @@ -384,16 +386,8 @@ namespace JSC { if (typeInfo().type() == ObjectType) return m_prototype; -#if USE(JSVALUE32) - if (typeInfo().type() == StringType) - return exec->lexicalGlobalObject()->stringPrototype(); - - ASSERT(typeInfo().type() == NumberType); - return exec->lexicalGlobalObject()->numberPrototype(); -#else ASSERT(typeInfo().type() == StringType); return exec->lexicalGlobalObject()->stringPrototype(); -#endif } inline StructureChain* Structure::prototypeChain(ExecState* exec) const diff --git a/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp index 1e20f7f..ed06fa5 100644 --- a/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp +++ b/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp @@ -35,7 +35,7 @@ #include "LiteralParser.h" #include "Nodes.h" #include "Parser.h" -#include "StringBuilder.h" +#include "UStringBuilder.h" #include "dtoa.h" #include <stdio.h> #include <stdlib.h> @@ -450,7 +450,7 @@ EncodedJSValue JSC_HOST_CALL globalFuncEval(ExecState* exec) if (JSValue parsedObject = preparser.tryLiteralParse()) return JSValue::encode(parsedObject); - RefPtr<EvalExecutable> eval = EvalExecutable::create(exec, makeSource(s)); + RefPtr<EvalExecutable> eval = EvalExecutable::create(exec, makeSource(s), false); JSObject* error = eval->compile(exec, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node()); if (error) return throwVMError(exec, error); @@ -563,7 +563,7 @@ EncodedJSValue JSC_HOST_CALL globalFuncEscape(ExecState* exec) EncodedJSValue JSC_HOST_CALL globalFuncUnescape(ExecState* exec) { - StringBuilder builder; + UStringBuilder builder; UString str = exec->argument(0).toString(exec); int k = 0; int len = str.length(); @@ -585,7 +585,7 @@ EncodedJSValue JSC_HOST_CALL globalFuncUnescape(ExecState* exec) builder.append(*c); } - return JSValue::encode(jsString(exec, builder.build())); + return JSValue::encode(jsString(exec, builder.toUString())); } #ifndef NDEBUG diff --git a/JavaScriptCore/runtime/JSImmediate.h b/JavaScriptCore/runtime/JSImmediate.h index 9127b6a..ffa446e 100644 --- a/JavaScriptCore/runtime/JSImmediate.h +++ b/JavaScriptCore/runtime/JSImmediate.h @@ -22,7 +22,7 @@ #ifndef JSImmediate_h #define JSImmediate_h -#if !USE(JSVALUE32_64) +#if USE(JSVALUE64) #include <wtf/Assertions.h> #include <wtf/AlwaysInline.h> @@ -44,7 +44,6 @@ namespace JSC { class JSObject; class UString; -#if USE(JSVALUE64) inline intptr_t reinterpretDoubleToIntptr(double value) { return WTF::bitwise_cast<intptr_t>(value); @@ -54,7 +53,6 @@ namespace JSC { { return WTF::bitwise_cast<double>(value); } -#endif /* * A JSValue* is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged @@ -159,16 +157,12 @@ namespace JSC { friend JSValue jsNumber(JSGlobalData* globalData, long long i); friend JSValue jsNumber(JSGlobalData* globalData, unsigned long long i); -#if USE(JSVALUE64) // If all bits in the mask are set, this indicates an integer number, // if any but not all are set this value is a double precision number. static const intptr_t TagTypeNumber = 0xffff000000000000ll; // This value is 2^48, used to encode doubles such that the encoded value will begin // with a 16-bit pattern within the range 0x0001..0xFFFE. static const intptr_t DoubleEncodeOffset = 0x1000000000000ll; -#elif USE(JSVALUE32) - static const intptr_t TagTypeNumber = 0x1; // bottom bit set indicates integer, this dominates the following bit -#endif static const intptr_t TagBitTypeOther = 0x2; // second bit set indicates immediate other than an integer static const intptr_t TagMask = TagTypeNumber | TagBitTypeOther; @@ -181,11 +175,7 @@ namespace JSC { static const intptr_t FullTagTypeUndefined = TagBitTypeOther | ExtendedTagBitUndefined; static const intptr_t FullTagTypeNull = TagBitTypeOther; -#if USE(JSVALUE64) static const int32_t IntegerPayloadShift = 0; -#else - static const int32_t IntegerPayloadShift = 1; -#endif static const int32_t ExtendedPayloadShift = 4; static const intptr_t ExtendedPayloadBitBoolValue = 1 << ExtendedPayloadShift; @@ -204,19 +194,13 @@ namespace JSC { static ALWAYS_INLINE bool isIntegerNumber(JSValue v) { -#if USE(JSVALUE64) return (rawValue(v) & TagTypeNumber) == TagTypeNumber; -#else - return isNumber(v); -#endif } -#if USE(JSVALUE64) static ALWAYS_INLINE bool isDouble(JSValue v) { return isNumber(v) && !isIntegerNumber(v); } -#endif static ALWAYS_INLINE bool isPositiveIntegerNumber(JSValue v) { @@ -260,11 +244,7 @@ namespace JSC { static ALWAYS_INLINE bool areBothImmediateIntegerNumbers(JSValue v1, JSValue v2) { -#if USE(JSVALUE64) return (rawValue(v1) & rawValue(v2) & TagTypeNumber) == TagTypeNumber; -#else - return rawValue(v1) & rawValue(v2) & TagTypeNumber; -#endif } static double toDouble(JSValue); @@ -285,13 +265,8 @@ namespace JSC { static JSValue oneImmediate(); private: -#if USE(JSVALUE64) static const int minImmediateInt = ((-INT_MAX) - 1); static const int maxImmediateInt = INT_MAX; -#else - static const int minImmediateInt = ((-INT_MAX) - 1) >> IntegerPayloadShift; - static const int maxImmediateInt = INT_MAX >> IntegerPayloadShift; -#endif static const unsigned maxImmediateUInt = maxImmediateInt; static ALWAYS_INLINE JSValue makeValue(intptr_t integer) @@ -302,21 +277,15 @@ namespace JSC { // With USE(JSVALUE64) we want the argument to be zero extended, so the // integer doesn't interfere with the tag bits in the upper word. In the default encoding, // if intptr_t id larger then int32_t we sign extend the value through the upper word. -#if USE(JSVALUE64) static ALWAYS_INLINE JSValue makeInt(uint32_t value) -#else - static ALWAYS_INLINE JSValue makeInt(int32_t value) -#endif { return makeValue((static_cast<intptr_t>(value) << IntegerPayloadShift) | TagTypeNumber); } -#if USE(JSVALUE64) static ALWAYS_INLINE JSValue makeDouble(double value) { return makeValue(reinterpretDoubleToIntptr(value) + DoubleEncodeOffset); } -#endif static ALWAYS_INLINE JSValue makeBool(bool b) { @@ -336,12 +305,10 @@ namespace JSC { template<typename T> static JSValue fromNumberOutsideIntegerRange(T); -#if USE(JSVALUE64) static ALWAYS_INLINE double doubleValue(JSValue v) { return reinterpretIntptrToDouble(rawValue(v) - DoubleEncodeOffset); } -#endif static ALWAYS_INLINE int32_t intValue(JSValue v) { @@ -371,7 +338,6 @@ namespace JSC { ALWAYS_INLINE JSValue JSImmediate::zeroImmediate() { return makeInt(0); } ALWAYS_INLINE JSValue JSImmediate::oneImmediate() { return makeInt(1); } -#if USE(JSVALUE64) inline bool doubleToBoolean(double value) { return value < 0.0 || value > 0.0; @@ -383,13 +349,6 @@ namespace JSC { return isNumber(v) ? isIntegerNumber(v) ? v != zeroImmediate() : doubleToBoolean(doubleValue(v)) : v == trueImmediate(); } -#else - ALWAYS_INLINE bool JSImmediate::toBoolean(JSValue v) - { - ASSERT(isImmediate(v)); - return isIntegerNumber(v) ? v != zeroImmediate() : v == trueImmediate(); - } -#endif ALWAYS_INLINE uint32_t JSImmediate::getTruncatedUInt32(JSValue v) { @@ -398,19 +357,11 @@ namespace JSC { return intValue(v); } -#if USE(JSVALUE64) template<typename T> inline JSValue JSImmediate::fromNumberOutsideIntegerRange(T value) { return makeDouble(static_cast<double>(value)); } -#else - template<typename T> - inline JSValue JSImmediate::fromNumberOutsideIntegerRange(T) - { - return JSValue(); - } -#endif ALWAYS_INLINE JSValue JSImmediate::from(char i) { @@ -439,10 +390,6 @@ namespace JSC { ALWAYS_INLINE JSValue JSImmediate::from(int i) { -#if !USE(JSVALUE64) - if ((i < minImmediateInt) | (i > maxImmediateInt)) - return fromNumberOutsideIntegerRange(i); -#endif return makeInt(i); } @@ -505,14 +452,10 @@ namespace JSC { if (isIntegerNumber(v)) return intValue(v); -#if USE(JSVALUE64) if (isNumber(v)) { ASSERT(isDouble(v)); return doubleValue(v); } -#else - ASSERT(!isNumber(v)); -#endif if (rawValue(v) == FullTagTypeUndefined) return nonInlineNaN(); @@ -670,11 +613,7 @@ namespace JSC { static ALWAYS_INLINE JSValue rightShiftImmediateNumbers(JSValue val, JSValue shift) { ASSERT(canDoFastRshift(val, shift) || canDoFastUrshift(val, shift)); -#if USE(JSVALUE64) return JSImmediate::makeValue(static_cast<intptr_t>(static_cast<uint32_t>(static_cast<int32_t>(JSImmediate::rawValue(val)) >> ((JSImmediate::rawValue(shift) >> JSImmediate::IntegerPayloadShift) & 0x1f))) | JSImmediate::TagTypeNumber); -#else - return JSImmediate::makeValue((JSImmediate::rawValue(val) >> ((JSImmediate::rawValue(shift) >> JSImmediate::IntegerPayloadShift) & 0x1f)) | JSImmediate::TagTypeNumber); -#endif } static ALWAYS_INLINE bool canDoFastAdditiveOperations(JSValue v) @@ -718,6 +657,6 @@ namespace JSC { } // namespace JSC -#endif // !USE(JSVALUE32_64) +#endif // USE(JSVALUE64) #endif // JSImmediate_h diff --git a/JavaScriptCore/runtime/JSNumberCell.cpp b/JavaScriptCore/runtime/JSNumberCell.cpp index 77388e0..6fa6b2a 100644 --- a/JavaScriptCore/runtime/JSNumberCell.cpp +++ b/JavaScriptCore/runtime/JSNumberCell.cpp @@ -23,75 +23,6 @@ #include "config.h" #include "JSNumberCell.h" -#if USE(JSVALUE32) - -#include "NumberObject.h" -#include "UString.h" - -namespace JSC { - -JSValue JSNumberCell::toPrimitive(ExecState*, PreferredPrimitiveType) const -{ - return const_cast<JSNumberCell*>(this); -} - -bool JSNumberCell::getPrimitiveNumber(ExecState*, double& number, JSValue& value) -{ - number = m_value; - value = this; - return true; -} - -bool JSNumberCell::toBoolean(ExecState*) const -{ - return m_value < 0.0 || m_value > 0.0; // false for NaN -} - -double JSNumberCell::toNumber(ExecState*) const -{ - return m_value; -} - -UString JSNumberCell::toString(ExecState*) const -{ - return UString::number(m_value); -} - -JSObject* JSNumberCell::toObject(ExecState* exec) const -{ - return constructNumber(exec, const_cast<JSNumberCell*>(this)); -} - -JSObject* JSNumberCell::toThisObject(ExecState* exec) const -{ - return constructNumber(exec, const_cast<JSNumberCell*>(this)); -} - -bool JSNumberCell::getUInt32(uint32_t& uint32) const -{ - uint32 = static_cast<uint32_t>(m_value); - return uint32 == m_value; -} - -JSValue JSNumberCell::getJSNumber() -{ - return this; -} - -JSValue jsNumberCell(ExecState* exec, double d) -{ - return new (exec) JSNumberCell(exec, d); -} - -JSValue jsNumberCell(JSGlobalData* globalData, double d) -{ - return new (globalData) JSNumberCell(globalData, d); -} - -} // namespace JSC - -#else // USE(JSVALUE32) - // Keep our exported symbols lists happy. namespace JSC { @@ -105,4 +36,3 @@ JSValue jsNumberCell(ExecState*, double) } // namespace JSC -#endif // USE(JSVALUE32) diff --git a/JavaScriptCore/runtime/JSNumberCell.h b/JavaScriptCore/runtime/JSNumberCell.h index cdd2d8c..a25c531 100644 --- a/JavaScriptCore/runtime/JSNumberCell.h +++ b/JavaScriptCore/runtime/JSNumberCell.h @@ -35,167 +35,6 @@ namespace JSC { extern const double NaN; extern const double Inf; -#if USE(JSVALUE32) - JSValue jsNumberCell(ExecState*, double); - - class Identifier; - class JSCell; - class JSObject; - class JSString; - class PropertySlot; - - struct ClassInfo; - struct Instruction; - - class JSNumberCell : public JSCell { - friend class JIT; - friend JSValue jsNumberCell(JSGlobalData*, double); - friend JSValue jsNumberCell(ExecState*, double); - - public: - double value() const { return m_value; } - - virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const; - virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value); - virtual bool toBoolean(ExecState*) const; - virtual double toNumber(ExecState*) const; - virtual UString toString(ExecState*) const; - virtual JSObject* toObject(ExecState*) const; - - virtual JSObject* toThisObject(ExecState*) const; - virtual JSValue getJSNumber(); - - void* operator new(size_t size, ExecState* exec) - { - return exec->heap()->allocateNumber(size); - } - - void* operator new(size_t size, JSGlobalData* globalData) - { - return globalData->heap.allocateNumber(size); - } - - static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(NumberType, OverridesGetOwnPropertySlot | NeedsThisConversion), AnonymousSlotCount); } - - private: - JSNumberCell(JSGlobalData* globalData, double value) - : JSCell(globalData->numberStructure.get()) - , m_value(value) - { - } - - JSNumberCell(ExecState* exec, double value) - : JSCell(exec->globalData().numberStructure.get()) - , m_value(value) - { - } - - virtual bool getUInt32(uint32_t&) const; - - double m_value; - }; - - JSValue jsNumberCell(JSGlobalData*, double); - - inline bool isNumberCell(JSValue v) - { - return v.isCell() && v.asCell()->isNumber(); - } - - inline JSNumberCell* asNumberCell(JSValue v) - { - ASSERT(isNumberCell(v)); - return static_cast<JSNumberCell*>(v.asCell()); - } - - ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, ExecState* exec, double d) - { - *this = jsNumberCell(exec, d); - } - - inline JSValue::JSValue(ExecState* exec, double d) - { - JSValue v = JSImmediate::from(d); - *this = v ? v : jsNumberCell(exec, d); - } - - inline JSValue::JSValue(ExecState* exec, int i) - { - JSValue v = JSImmediate::from(i); - *this = v ? v : jsNumberCell(exec, i); - } - - inline JSValue::JSValue(ExecState* exec, unsigned i) - { - JSValue v = JSImmediate::from(i); - *this = v ? v : jsNumberCell(exec, i); - } - - inline JSValue::JSValue(ExecState* exec, long i) - { - JSValue v = JSImmediate::from(i); - *this = v ? v : jsNumberCell(exec, i); - } - - inline JSValue::JSValue(ExecState* exec, unsigned long i) - { - JSValue v = JSImmediate::from(i); - *this = v ? v : jsNumberCell(exec, i); - } - - inline JSValue::JSValue(ExecState* exec, long long i) - { - JSValue v = JSImmediate::from(i); - *this = v ? v : jsNumberCell(exec, static_cast<double>(i)); - } - - inline JSValue::JSValue(ExecState* exec, unsigned long long i) - { - JSValue v = JSImmediate::from(i); - *this = v ? v : jsNumberCell(exec, static_cast<double>(i)); - } - - inline JSValue::JSValue(JSGlobalData* globalData, double d) - { - JSValue v = JSImmediate::from(d); - *this = v ? v : jsNumberCell(globalData, d); - } - - inline JSValue::JSValue(JSGlobalData* globalData, int i) - { - JSValue v = JSImmediate::from(i); - *this = v ? v : jsNumberCell(globalData, i); - } - - inline JSValue::JSValue(JSGlobalData* globalData, unsigned i) - { - JSValue v = JSImmediate::from(i); - *this = v ? v : jsNumberCell(globalData, i); - } - - inline bool JSValue::isDouble() const - { - return isNumberCell(asValue()); - } - - inline double JSValue::asDouble() const - { - return asNumberCell(asValue())->value(); - } - - inline bool JSValue::isNumber() const - { - return JSImmediate::isNumber(asValue()) || isDouble(); - } - - inline double JSValue::uncheckedGetNumber() const - { - ASSERT(isNumber()); - return JSImmediate::isImmediate(asValue()) ? JSImmediate::toDouble(asValue()) : asDouble(); - } - -#endif // USE(JSVALUE32) - #if USE(JSVALUE64) ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, ExecState*, double d) { @@ -295,7 +134,7 @@ namespace JSC { #endif // USE(JSVALUE64) -#if USE(JSVALUE32) || USE(JSVALUE64) +#if USE(JSVALUE64) inline JSValue::JSValue(ExecState*, char i) { @@ -351,7 +190,7 @@ namespace JSC { return true; } -#endif // USE(JSVALUE32) || USE(JSVALUE64) +#endif // USE(JSVALUE64) } // namespace JSC diff --git a/JavaScriptCore/runtime/JSONObject.cpp b/JavaScriptCore/runtime/JSONObject.cpp index ba50721..0794189 100644 --- a/JavaScriptCore/runtime/JSONObject.cpp +++ b/JavaScriptCore/runtime/JSONObject.cpp @@ -34,8 +34,8 @@ #include "LiteralParser.h" #include "Lookup.h" #include "PropertyNameArray.h" -#include "StringBuilder.h" -#include "StringConcatenate.h" +#include "UStringBuilder.h" +#include "UStringConcatenate.h" #include <wtf/MathExtras.h> namespace JSC { @@ -85,7 +85,7 @@ private: JSObject* object() const { return m_object; } - bool appendNextProperty(Stringifier&, StringBuilder&); + bool appendNextProperty(Stringifier&, UStringBuilder&); private: JSObject* const m_object; @@ -98,17 +98,17 @@ private: friend class Holder; - static void appendQuotedString(StringBuilder&, const UString&); + static void appendQuotedString(UStringBuilder&, const UString&); JSValue toJSON(JSValue, const PropertyNameForFunctionCall&); enum StringifyResult { StringifyFailed, StringifySucceeded, StringifyFailedDueToUndefinedValue }; - StringifyResult appendStringifiedValue(StringBuilder&, JSValue, JSObject* holder, const PropertyNameForFunctionCall&); + StringifyResult appendStringifiedValue(UStringBuilder&, JSValue, JSObject* holder, const PropertyNameForFunctionCall&); bool willIndent() const; void indent(); void unindent(); - void startNewLine(StringBuilder&) const; + void startNewLine(UStringBuilder&) const; Stringifier* const m_nextStringifierToMark; ExecState* const m_exec; @@ -270,21 +270,21 @@ JSValue Stringifier::stringify(JSValue value) PropertyNameForFunctionCall emptyPropertyName(m_exec->globalData().propertyNames->emptyIdentifier); object->putDirect(m_exec->globalData().propertyNames->emptyIdentifier, value); - StringBuilder result; + UStringBuilder result; if (appendStringifiedValue(result, value, object, emptyPropertyName) != StringifySucceeded) return jsUndefined(); if (m_exec->hadException()) return jsNull(); - return jsString(m_exec, result.build()); + return jsString(m_exec, result.toUString()); } -void Stringifier::appendQuotedString(StringBuilder& builder, const UString& value) +void Stringifier::appendQuotedString(UStringBuilder& builder, const UString& value) { int length = value.length(); // String length plus 2 for quote marks plus 8 so we can accomodate a few escaped characters. - builder.reserveCapacity(builder.size() + length + 2 + 8); + builder.reserveCapacity(builder.length() + length + 2 + 8); builder.append('"'); @@ -361,7 +361,7 @@ inline JSValue Stringifier::toJSON(JSValue value, const PropertyNameForFunctionC return call(m_exec, object, callType, callData, value, args); } -Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder& builder, JSValue value, JSObject* holder, const PropertyNameForFunctionCall& propertyName) +Stringifier::StringifyResult Stringifier::appendStringifiedValue(UStringBuilder& builder, JSValue value, JSObject* holder, const PropertyNameForFunctionCall& propertyName) { // Call the toJSON function. value = toJSON(value, propertyName); @@ -466,7 +466,7 @@ inline void Stringifier::indent() // Use a single shared string, m_repeatedGap, so we don't keep allocating new ones as we indent and unindent. unsigned newSize = m_indent.length() + m_gap.length(); if (newSize > m_repeatedGap.length()) - m_repeatedGap = makeString(m_repeatedGap, m_gap); + m_repeatedGap = makeUString(m_repeatedGap, m_gap); ASSERT(newSize <= m_repeatedGap.length()); m_indent = m_repeatedGap.substringSharingImpl(0, newSize); } @@ -477,7 +477,7 @@ inline void Stringifier::unindent() m_indent = m_repeatedGap.substringSharingImpl(0, m_indent.length() - m_gap.length()); } -inline void Stringifier::startNewLine(StringBuilder& builder) const +inline void Stringifier::startNewLine(UStringBuilder& builder) const { if (m_gap.isEmpty()) return; @@ -492,7 +492,7 @@ inline Stringifier::Holder::Holder(JSObject* object) { } -bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBuilder& builder) +bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, UStringBuilder& builder) { ASSERT(m_index <= m_size); @@ -521,7 +521,7 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBui // Last time through, finish up and return false. if (m_index == m_size) { stringifier.unindent(); - if (m_size && builder[builder.size() - 1] != '{') + if (m_size && builder[builder.length() - 1] != '{') stringifier.startNewLine(builder); builder.append(m_isArray ? ']' : '}'); return false; @@ -562,7 +562,7 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBui if (exec->hadException()) return false; - rollBackPoint = builder.size(); + rollBackPoint = builder.length(); // Append the separator string. if (builder[rollBackPoint - 1] != '{') diff --git a/JavaScriptCore/runtime/JSObject.cpp b/JavaScriptCore/runtime/JSObject.cpp index cabc428..30e40e4 100644 --- a/JavaScriptCore/runtime/JSObject.cpp +++ b/JavaScriptCore/runtime/JSObject.cpp @@ -43,6 +43,8 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(JSObject); +const char* StrictModeReadonlyPropertyWriteError = "Attempted to assign to readonly property."; + static inline void getClassPropertyNames(ExecState* exec, const ClassInfo* classInfo, PropertyNameArray& propertyNames, EnumerationMode mode) { // Add properties from the static hashtables of properties @@ -114,15 +116,19 @@ void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValue valu for (JSObject* obj = this; !obj->structure()->hasGetterSetterProperties(); obj = asObject(prototype)) { prototype = obj->prototype(); if (prototype.isNull()) { - putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot); + if (!putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot) && slot.isStrictMode()) + throwTypeError(exec, StrictModeReadonlyPropertyWriteError); return; } } unsigned attributes; JSCell* specificValue; - if ((m_structure->get(propertyName, attributes, specificValue) != WTF::notFound) && attributes & ReadOnly) + if ((m_structure->get(propertyName, attributes, specificValue) != WTF::notFound) && attributes & ReadOnly) { + if (slot.isStrictMode()) + throwError(exec, createTypeError(exec, StrictModeReadonlyPropertyWriteError)); return; + } for (JSObject* obj = this; ; obj = asObject(prototype)) { if (JSValue gs = obj->getDirect(propertyName)) { @@ -151,7 +157,8 @@ void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValue valu break; } - putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot); + if (!putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot) && slot.isStrictMode()) + throwTypeError(exec, StrictModeReadonlyPropertyWriteError); return; } @@ -489,6 +496,11 @@ JSObject* JSObject::toThisObject(ExecState*) const return const_cast<JSObject*>(this); } +JSValue JSObject::toStrictThisObject(ExecState*) const +{ + return const_cast<JSObject*>(this); +} + JSObject* JSObject::unwrappedObject() { return this; @@ -702,4 +714,9 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName return true; } +JSObject* throwTypeError(ExecState* exec, const UString& message) +{ + return throwError(exec, createTypeError(exec, message)); +} + } // namespace JSC diff --git a/JavaScriptCore/runtime/JSObject.h b/JavaScriptCore/runtime/JSObject.h index 4201703..8981469 100644 --- a/JavaScriptCore/runtime/JSObject.h +++ b/JavaScriptCore/runtime/JSObject.h @@ -55,6 +55,9 @@ namespace JSC { class Structure; struct HashTable; + JSObject* throwTypeError(ExecState*, const UString&); + extern const char* StrictModeReadonlyPropertyWriteError; + // ECMA 262-3 8.6.1 // Property attributes enum Attribute { @@ -140,6 +143,7 @@ namespace JSC { virtual JSObject* toObject(ExecState*) const; virtual JSObject* toThisObject(ExecState*) const; + virtual JSValue toStrictThisObject(ExecState*) const; virtual JSObject* unwrappedObject(); bool getPropertySpecificValue(ExecState* exec, const Identifier& propertyName, JSCell*& specificFunction) const; @@ -175,9 +179,9 @@ namespace JSC { bool hasCustomProperties() { return !m_structure->isEmpty(); } bool hasGetterSetterProperties() { return m_structure->hasGetterSetterProperties(); } - void putDirect(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot); + bool putDirect(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot); void putDirect(const Identifier& propertyName, JSValue value, unsigned attr = 0); - void putDirect(const Identifier& propertyName, JSValue value, PutPropertySlot&); + bool putDirect(const Identifier& propertyName, JSValue value, PutPropertySlot&); void putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attr = 0); void putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot); @@ -205,6 +209,7 @@ namespace JSC { virtual bool isVariableObject() const { return false; } virtual bool isActivationObject() const { return false; } virtual bool isNotAnObjectErrorStub() const { return false; } + virtual bool isStrictModeFunction() const { return false; } virtual ComplType exceptionType() const { return Throw; } @@ -248,9 +253,6 @@ namespace JSC { void getString(ExecState* exec); void isObject(); void isString(); -#if USE(JSVALUE32) - void isNumber(); -#endif ConstPropertyStorage propertyStorage() const { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); } PropertyStorage propertyStorage() { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); } @@ -265,8 +267,8 @@ namespace JSC { return reinterpret_cast<JSValue*>(&propertyStorage()[offset]); } - void putDirectInternal(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot, JSCell*); - void putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot); + bool putDirectInternal(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot, JSCell*); + bool putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot); void putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue value, unsigned attr = 0); bool inlineGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); @@ -299,9 +301,7 @@ inline JSObject::JSObject(NonNullPassRefPtr<Structure> structure) ASSERT(m_structure->propertyStorageCapacity() == inlineStorageCapacity); ASSERT(m_structure->isEmpty()); ASSERT(prototype().isNull() || Heap::heap(this) == Heap::heap(prototype())); -#if USE(JSVALUE64) || USE(JSVALUE32_64) ASSERT(OBJECT_OFFSETOF(JSObject, m_inlineStorage) % sizeof(double) == 0); -#endif } inline JSObject::~JSObject() @@ -450,7 +450,7 @@ inline JSValue JSObject::get(ExecState* exec, unsigned propertyName) const return jsUndefined(); } -inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot, JSCell* specificFunction) +inline bool JSObject::putDirectInternal(const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot, JSCell* specificFunction) { ASSERT(value); ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); @@ -465,7 +465,8 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue if (currentSpecificFunction && (specificFunction != currentSpecificFunction)) m_structure->despecifyDictionaryFunction(propertyName); if (checkReadOnly && currentAttributes & ReadOnly) - return; + return false; + putDirectOffset(offset, value); // At this point, the objects structure only has a specific value set if previously there // had been one set, and if the new value being specified is the same (otherwise we would @@ -475,7 +476,7 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue // If there was previously a value, and the new value is the same, then we cannot cache. if (!currentSpecificFunction || (specificFunction != currentSpecificFunction)) slot.setExistingProperty(this, offset); - return; + return true; } size_t currentCapacity = m_structure->propertyStorageCapacity(); @@ -488,7 +489,7 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue // See comment on setNewProperty call below. if (!specificFunction) slot.setNewProperty(this, offset); - return; + return true; } size_t offset; @@ -504,7 +505,7 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue // so leave the slot in an uncachable state. if (!specificFunction) slot.setNewProperty(this, offset); - return; + return true; } unsigned currentAttributes; @@ -512,7 +513,7 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue offset = m_structure->get(propertyName, currentAttributes, currentSpecificFunction); if (offset != WTF::notFound) { if (checkReadOnly && currentAttributes & ReadOnly) - return; + return false; // There are three possibilities here: // (1) There is an existing specific value set, and we're overwriting with *the same value*. @@ -527,7 +528,7 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue // case (1) Do the put, then return leaving the slot uncachable. if (specificFunction == currentSpecificFunction) { putDirectOffset(offset, value); - return; + return true; } // case (2) Despecify, fall through to (3). setStructure(Structure::despecifyFunctionTransition(m_structure, propertyName)); @@ -536,7 +537,7 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue // case (3) set the slot, do the put, return. slot.setExistingProperty(this, offset); putDirectOffset(offset, value); - return; + return true; } // If we have a specific function, we may have got to this point if there is @@ -561,14 +562,15 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue // so leave the slot in an uncachable state. if (!specificFunction) slot.setNewProperty(this, offset); + return true; } -inline void JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot) +inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot) { ASSERT(value); ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); - putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, getJSFunction(globalData, value)); + return putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, getJSFunction(globalData, value)); } inline void JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes) @@ -577,12 +579,12 @@ inline void JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi putDirectInternal(propertyName, value, attributes, false, slot, getJSFunction(globalData, value)); } -inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot) +inline bool JSObject::putDirect(const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot) { ASSERT(value); ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); - putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, 0); + return putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, 0); } inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, unsigned attributes) @@ -591,9 +593,9 @@ inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, u putDirectInternal(propertyName, value, attributes, false, slot, 0); } -inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, PutPropertySlot& slot) +inline bool JSObject::putDirect(const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { - putDirectInternal(propertyName, value, 0, false, slot, 0); + return putDirectInternal(propertyName, value, 0, false, slot, 0); } inline void JSObject::putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot) @@ -698,10 +700,11 @@ inline void JSValue::put(ExecState* exec, const Identifier& propertyName, JSValu asCell()->put(exec, propertyName, value, slot); } -inline void JSValue::putDirect(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) +inline void JSValue::putDirect(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { ASSERT(isCell() && isObject()); - asObject(asCell())->putDirect(propertyName, value, slot); + if (!asObject(asCell())->putDirect(propertyName, value, slot) && slot.isStrictMode()) + throwTypeError(exec, StrictModeReadonlyPropertyWriteError); } inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue value) @@ -756,6 +759,13 @@ inline JSString* JSValue::toThisJSString(ExecState* exec) const return isString() ? static_cast<JSString*>(asCell()) : jsString(exec, toThisObject(exec)->toString(exec)); } +inline JSValue JSValue::toStrictThisObject(ExecState* exec) const +{ + if (!isObject()) + return *this; + return asObject(asCell())->toStrictThisObject(exec); +} + } // namespace JSC #endif // JSObject_h diff --git a/JavaScriptCore/runtime/JSStaticScopeObject.cpp b/JavaScriptCore/runtime/JSStaticScopeObject.cpp index ad10218..7ab1d1c 100644 --- a/JavaScriptCore/runtime/JSStaticScopeObject.cpp +++ b/JavaScriptCore/runtime/JSStaticScopeObject.cpp @@ -42,6 +42,11 @@ JSObject* JSStaticScopeObject::toThisObject(ExecState* exec) const return exec->globalThisValue(); } +JSValue JSStaticScopeObject::toStrictThisObject(ExecState*) const +{ + return jsNull(); +} + void JSStaticScopeObject::put(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot&) { if (symbolTablePut(propertyName, value)) diff --git a/JavaScriptCore/runtime/JSStaticScopeObject.h b/JavaScriptCore/runtime/JSStaticScopeObject.h index c0519c1..e69356a 100644 --- a/JavaScriptCore/runtime/JSStaticScopeObject.h +++ b/JavaScriptCore/runtime/JSStaticScopeObject.h @@ -53,6 +53,7 @@ namespace JSC{ virtual void markChildren(MarkStack&); bool isDynamicScope(bool& requiresDynamicChecks) const; virtual JSObject* toThisObject(ExecState*) const; + virtual JSValue toStrictThisObject(ExecState*) const; virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&); void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes); diff --git a/JavaScriptCore/runtime/JSStringBuilder.h b/JavaScriptCore/runtime/JSStringBuilder.h index 25fe685..49d4a63 100644 --- a/JavaScriptCore/runtime/JSStringBuilder.h +++ b/JavaScriptCore/runtime/JSStringBuilder.h @@ -28,7 +28,7 @@ #include "ExceptionHelpers.h" #include "JSString.h" -#include "StringConcatenate.h" +#include "UStringConcatenate.h" #include "Vector.h" namespace JSC { @@ -87,7 +87,7 @@ protected: template<typename StringType1, typename StringType2> inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2) { - PassRefPtr<StringImpl> result = tryMakeString(string1, string2); + PassRefPtr<StringImpl> result = WTF::tryMakeString(string1, string2); if (!result) return throwOutOfMemoryError(exec); return jsNontrivialString(exec, result); @@ -96,7 +96,7 @@ inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, Stri template<typename StringType1, typename StringType2, typename StringType3> inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2, StringType3 string3) { - PassRefPtr<StringImpl> result = tryMakeString(string1, string2, string3); + PassRefPtr<StringImpl> result = WTF::tryMakeString(string1, string2, string3); if (!result) return throwOutOfMemoryError(exec); return jsNontrivialString(exec, result); @@ -105,7 +105,7 @@ inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, Stri template<typename StringType1, typename StringType2, typename StringType3, typename StringType4> inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4) { - PassRefPtr<StringImpl> result = tryMakeString(string1, string2, string3, string4); + PassRefPtr<StringImpl> result = WTF::tryMakeString(string1, string2, string3, string4); if (!result) return throwOutOfMemoryError(exec); return jsNontrivialString(exec, result); @@ -114,7 +114,7 @@ inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, Stri template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5> inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5) { - PassRefPtr<StringImpl> result = tryMakeString(string1, string2, string3, string4, string5); + PassRefPtr<StringImpl> result = WTF::tryMakeString(string1, string2, string3, string4, string5); if (!result) return throwOutOfMemoryError(exec); return jsNontrivialString(exec, result); @@ -123,7 +123,7 @@ inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, Stri template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6> inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6) { - PassRefPtr<StringImpl> result = tryMakeString(string1, string2, string3, string4, string5, string6); + PassRefPtr<StringImpl> result = WTF::tryMakeString(string1, string2, string3, string4, string5, string6); if (!result) return throwOutOfMemoryError(exec); return jsNontrivialString(exec, result); diff --git a/JavaScriptCore/runtime/JSValue.h b/JavaScriptCore/runtime/JSValue.h index b5834c1..b5dcbec 100644 --- a/JavaScriptCore/runtime/JSValue.h +++ b/JavaScriptCore/runtime/JSValue.h @@ -80,7 +80,7 @@ namespace JSC { public: static EncodedJSValue encode(JSValue value); static JSValue decode(EncodedJSValue ptr); -#if !USE(JSVALUE32_64) +#if USE(JSVALUE64) private: static JSValue makeImmediate(intptr_t value); intptr_t immediateValue(); @@ -193,6 +193,7 @@ namespace JSC { bool needsThisConversion() const; JSObject* toThisObject(ExecState*) const; + JSValue toStrictThisObject(ExecState*) const; UString toThisString(ExecState*) const; JSString* toThisJSString(ExecState*) const; diff --git a/JavaScriptCore/runtime/JSZombie.h b/JavaScriptCore/runtime/JSZombie.h index 711f673..da45699 100644 --- a/JavaScriptCore/runtime/JSZombie.h +++ b/JavaScriptCore/runtime/JSZombie.h @@ -60,6 +60,7 @@ public: virtual bool deleteProperty(ExecState*, const Identifier&) { ASSERT_NOT_REACHED(); return false; } virtual bool deleteProperty(ExecState*, unsigned) { ASSERT_NOT_REACHED(); return false; } virtual JSObject* toThisObject(ExecState*) const { ASSERT_NOT_REACHED(); return 0; } + virtual JSValue toStrictThisObject(ExecState*) const { ASSERT_NOT_REACHED(); return JSValue(); } virtual JSValue getJSNumber() { ASSERT_NOT_REACHED(); return jsNull(); } virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&) { ASSERT_NOT_REACHED(); return false; } virtual bool getOwnPropertySlot(ExecState*, unsigned, PropertySlot&) { ASSERT_NOT_REACHED(); return false; } diff --git a/JavaScriptCore/runtime/LiteralParser.cpp b/JavaScriptCore/runtime/LiteralParser.cpp index cc33bae..f1df15f 100644 --- a/JavaScriptCore/runtime/LiteralParser.cpp +++ b/JavaScriptCore/runtime/LiteralParser.cpp @@ -29,7 +29,7 @@ #include "JSArray.h" #include "JSString.h" #include "Lexer.h" -#include "StringBuilder.h" +#include "UStringBuilder.h" #include <wtf/ASCIICType.h> #include <wtf/dtoa.h> @@ -135,7 +135,7 @@ template <LiteralParser::ParserMode mode> inline LiteralParser::TokenType Litera { ++m_ptr; const UChar* runStart; - StringBuilder builder; + UStringBuilder builder; do { runStart = m_ptr; while (m_ptr < m_end && isSafeStringCharacter<mode>(*m_ptr)) @@ -200,7 +200,7 @@ template <LiteralParser::ParserMode mode> inline LiteralParser::TokenType Litera if (m_ptr >= m_end || *m_ptr != '"') return TokError; - token.stringToken = builder.build(); + token.stringToken = builder.toUString(); token.type = TokString; token.end = ++m_ptr; return TokString; diff --git a/JavaScriptCore/runtime/NumberObject.h b/JavaScriptCore/runtime/NumberObject.h index 6c18cdd..e82b593 100644 --- a/JavaScriptCore/runtime/NumberObject.h +++ b/JavaScriptCore/runtime/NumberObject.h @@ -37,11 +37,7 @@ namespace JSC { } protected: -#if USE(JSVALUE32) - static const unsigned StructureFlags = OverridesMarkChildren | JSWrapperObject::StructureFlags; -#else static const unsigned StructureFlags = JSWrapperObject::StructureFlags; -#endif private: virtual const ClassInfo* classInfo() const { return &info; } diff --git a/JavaScriptCore/runtime/NumberPrototype.cpp b/JavaScriptCore/runtime/NumberPrototype.cpp index e18553b..4a2ca74 100644 --- a/JavaScriptCore/runtime/NumberPrototype.cpp +++ b/JavaScriptCore/runtime/NumberPrototype.cpp @@ -25,10 +25,8 @@ #include "Error.h" #include "JSFunction.h" #include "JSString.h" -#include "JSStringBuilder.h" #include "Operations.h" #include "PrototypeFunction.h" -#include "StringBuilder.h" #include "dtoa.h" #include <wtf/Assertions.h> #include <wtf/DecimalNumber.h> @@ -119,8 +117,8 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToExponential(ExecState* exec) // Round if the argument is not undefined, always format as exponential. NumberToStringBuffer buffer; unsigned length = isUndefined - ? DecimalNumber(x).toStringExponential(buffer) - : DecimalNumber(x, RoundingSignificantFigures, decimalPlacesInExponent + 1).toStringExponential(buffer); + ? DecimalNumber(x).toStringExponential(buffer, WTF::NumberToStringBufferLength) + : DecimalNumber(x, RoundingSignificantFigures, decimalPlacesInExponent + 1).toStringExponential(buffer, WTF::NumberToStringBufferLength); return JSValue::encode(jsString(exec, UString(buffer, length))); } @@ -156,7 +154,7 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState* exec) // Convert to decimal with rounding, and format as decimal. NumberToStringBuffer buffer; - unsigned length = DecimalNumber(x, RoundingDecimalPlaces, decimalPlaces).toStringDecimal(buffer); + unsigned length = DecimalNumber(x, RoundingDecimalPlaces, decimalPlaces).toStringDecimal(buffer, WTF::NumberToStringBufferLength); return JSValue::encode(jsString(exec, UString(buffer, length))); } @@ -198,8 +196,8 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState* exec) // 1234 (1.234e+3) requires 4 digits. (See ECMA-262 15.7.4.7.10.c) NumberToStringBuffer buffer; unsigned length = number.exponent() >= -6 && number.exponent() < significantFigures - ? number.toStringDecimal(buffer) - : number.toStringExponential(buffer); + ? number.toStringDecimal(buffer, WTF::NumberToStringBufferLength) + : number.toStringExponential(buffer, WTF::NumberToStringBufferLength); return JSValue::encode(jsString(exec, UString(buffer, length))); } diff --git a/JavaScriptCore/runtime/Operations.h b/JavaScriptCore/runtime/Operations.h index eed1f16..9226953 100644 --- a/JavaScriptCore/runtime/Operations.h +++ b/JavaScriptCore/runtime/Operations.h @@ -460,7 +460,7 @@ namespace JSC { } } - ALWAYS_INLINE JSValue resolveBase(CallFrame* callFrame, Identifier& property, ScopeChainNode* scopeChain) + ALWAYS_INLINE JSValue resolveBase(CallFrame* callFrame, Identifier& property, ScopeChainNode* scopeChain, bool isStrictPut) { ScopeChainIterator iter = scopeChain->begin(); ScopeChainIterator next = iter; @@ -472,7 +472,9 @@ namespace JSC { JSObject* base; while (true) { base = *iter; - if (next == end || base->getPropertySlot(callFrame, property, slot)) + if (next == end) + return isStrictPut ? JSValue() : base; + if (base->getPropertySlot(callFrame, property, slot)) return base; iter = next; diff --git a/JavaScriptCore/runtime/PutPropertySlot.h b/JavaScriptCore/runtime/PutPropertySlot.h index eb8ea8a..4b0b394 100644 --- a/JavaScriptCore/runtime/PutPropertySlot.h +++ b/JavaScriptCore/runtime/PutPropertySlot.h @@ -38,9 +38,10 @@ namespace JSC { public: enum Type { Uncachable, ExistingProperty, NewProperty }; - PutPropertySlot() + PutPropertySlot(bool isStrictMode = false) : m_type(Uncachable) , m_base(0) + , m_isStrictMode(isStrictMode) { } @@ -61,6 +62,7 @@ namespace JSC { Type type() const { return m_type; } JSObject* base() const { return m_base; } + bool isStrictMode() const { return m_isStrictMode; } bool isCacheable() const { return m_type != Uncachable; } size_t cachedOffset() const { ASSERT(isCacheable()); @@ -70,6 +72,7 @@ namespace JSC { Type m_type; JSObject* m_base; size_t m_offset; + bool m_isStrictMode; }; } // namespace JSC diff --git a/JavaScriptCore/runtime/RegExpConstructor.cpp b/JavaScriptCore/runtime/RegExpConstructor.cpp index 214e528..b9aa587 100644 --- a/JavaScriptCore/runtime/RegExpConstructor.cpp +++ b/JavaScriptCore/runtime/RegExpConstructor.cpp @@ -35,7 +35,7 @@ #include "RegExpPrototype.h" #include "RegExp.h" #include "RegExpCache.h" -#include "StringConcatenate.h" +#include "UStringConcatenate.h" #include <wtf/PassOwnPtr.h> namespace JSC { @@ -307,7 +307,7 @@ JSObject* constructRegExp(ExecState* exec, const ArgList& args) RefPtr<RegExp> regExp = exec->globalData().regExpCache()->lookupOrCreate(pattern, flags); if (!regExp->isValid()) - return throwError(exec, createSyntaxError(exec, makeString("Invalid regular expression: ", regExp->errorMessage()))); + return throwError(exec, createSyntaxError(exec, makeUString("Invalid regular expression: ", regExp->errorMessage()))); return new (exec) RegExpObject(exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->regExpStructure(), regExp.release()); } diff --git a/JavaScriptCore/runtime/RegExpObject.cpp b/JavaScriptCore/runtime/RegExpObject.cpp index 4462879..7d14814 100644 --- a/JavaScriptCore/runtime/RegExpObject.cpp +++ b/JavaScriptCore/runtime/RegExpObject.cpp @@ -29,7 +29,7 @@ #include "Lookup.h" #include "RegExpConstructor.h" #include "RegExpPrototype.h" -#include "StringConcatenate.h" +#include "UStringConcatenate.h" #include <wtf/PassOwnPtr.h> namespace JSC { @@ -146,7 +146,7 @@ bool RegExpObject::match(ExecState* exec) UString input = !exec->argumentCount() ? regExpConstructor->input() : exec->argument(0).toString(exec); if (input.isNull()) { - throwError(exec, createError(exec, makeString("No input to ", toString(exec), "."))); + throwError(exec, createError(exec, makeUString("No input to ", toString(exec), "."))); return false; } diff --git a/JavaScriptCore/runtime/RegExpPrototype.cpp b/JavaScriptCore/runtime/RegExpPrototype.cpp index d66f5d7..0a4c8bf 100644 --- a/JavaScriptCore/runtime/RegExpPrototype.cpp +++ b/JavaScriptCore/runtime/RegExpPrototype.cpp @@ -34,6 +34,7 @@ #include "RegExpObject.h" #include "RegExp.h" #include "RegExpCache.h" +#include "UStringConcatenate.h" namespace JSC { @@ -94,7 +95,7 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec) } if (!regExp->isValid()) - return throwVMError(exec, createSyntaxError(exec, makeString("Invalid regular expression: ", regExp->errorMessage()))); + return throwVMError(exec, createSyntaxError(exec, makeUString("Invalid regular expression: ", regExp->errorMessage()))); asRegExpObject(thisValue)->setRegExp(regExp.release()); asRegExpObject(thisValue)->setLastIndex(0); diff --git a/JavaScriptCore/runtime/StrictEvalActivation.cpp b/JavaScriptCore/runtime/StrictEvalActivation.cpp new file mode 100644 index 0000000..5bb013b --- /dev/null +++ b/JavaScriptCore/runtime/StrictEvalActivation.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "StrictEvalActivation.h" + +namespace JSC { + +StrictEvalActivation::StrictEvalActivation(ExecState* exec) + : JSObject(exec->globalData().strictEvalActivationStructure) +{ +} + +bool StrictEvalActivation::deleteProperty(ExecState*, const Identifier&) +{ + return false; +} + +JSObject* StrictEvalActivation::toThisObject(ExecState* exec) const +{ + return exec->globalThisValue(); +} + +JSValue StrictEvalActivation::toStrictThisObject(ExecState*) const +{ + return jsNull(); +} + +} diff --git a/JavaScriptCore/runtime/StrictEvalActivation.h b/JavaScriptCore/runtime/StrictEvalActivation.h new file mode 100644 index 0000000..1385eec --- /dev/null +++ b/JavaScriptCore/runtime/StrictEvalActivation.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef StrictEvalActivation_h +#define StrictEvalActivation_h + +#include "JSObject.h" + +namespace JSC { + +class StrictEvalActivation : public JSObject { +public: + StrictEvalActivation(ExecState*); + virtual bool deleteProperty(ExecState*, const Identifier&); + virtual JSObject* toThisObject(ExecState*) const; + virtual JSValue toStrictThisObject(ExecState*) const; +}; + +} // namespace JSC + +#endif // StrictEvalActivation_h diff --git a/JavaScriptCore/runtime/StringConcatenate.h b/JavaScriptCore/runtime/StringConcatenate.h deleted file mode 100644 index 18a52ef..0000000 --- a/JavaScriptCore/runtime/StringConcatenate.h +++ /dev/null @@ -1,428 +0,0 @@ -/* - * Copyright (C) 2010 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 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. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef StringConcatenate_h -#define StringConcatenate_h - -#include "UString.h" - -namespace JSC { - -template<typename StringType> -class StringTypeAdapter { -}; - -template<> -class StringTypeAdapter<char*> { -public: - StringTypeAdapter<char*>(char* buffer) - : m_buffer((unsigned char*)buffer) - , m_length(strlen(buffer)) - { - } - - unsigned length() { return m_length; } - - void writeTo(UChar* destination) - { - for (unsigned i = 0; i < m_length; ++i) - destination[i] = m_buffer[i]; - } - -private: - const unsigned char* m_buffer; - unsigned m_length; -}; - -template<> -class StringTypeAdapter<const char*> { -public: - StringTypeAdapter<const char*>(const char* buffer) - : m_buffer((unsigned char*)buffer) - , m_length(strlen(buffer)) - { - } - - unsigned length() { return m_length; } - - void writeTo(UChar* destination) - { - for (unsigned i = 0; i < m_length; ++i) - destination[i] = m_buffer[i]; - } - -private: - const unsigned char* m_buffer; - unsigned m_length; -}; - -template<> -class StringTypeAdapter<UString> { -public: - StringTypeAdapter<UString>(UString& string) - : m_data(string.characters()) - , m_length(string.length()) - { - } - - unsigned length() { return m_length; } - - void writeTo(UChar* destination) - { - for (unsigned i = 0; i < m_length; ++i) - destination[i] = m_data[i]; - } - -private: - const UChar* m_data; - unsigned m_length; -}; - -inline void sumWithOverflow(unsigned& total, unsigned addend, bool& overflow) -{ - unsigned oldTotal = total; - total = oldTotal + addend; - if (total < oldTotal) - overflow = true; -} - -template<typename StringType1, typename StringType2> -PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2) -{ - StringTypeAdapter<StringType1> adapter1(string1); - StringTypeAdapter<StringType2> adapter2(string2); - - UChar* buffer; - bool overflow = false; - unsigned length = adapter1.length(); - sumWithOverflow(length, adapter2.length(), overflow); - if (overflow) - return 0; - PassRefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) - return 0; - - UChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - - return resultImpl; -} - -template<typename StringType1, typename StringType2, typename StringType3> -PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3) -{ - StringTypeAdapter<StringType1> adapter1(string1); - StringTypeAdapter<StringType2> adapter2(string2); - StringTypeAdapter<StringType3> adapter3(string3); - - UChar* buffer = 0; - bool overflow = false; - unsigned length = adapter1.length(); - sumWithOverflow(length, adapter2.length(), overflow); - sumWithOverflow(length, adapter3.length(), overflow); - if (overflow) - return 0; - PassRefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) - return 0; - - UChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - result += adapter2.length(); - adapter3.writeTo(result); - - return resultImpl; -} - -template<typename StringType1, typename StringType2, typename StringType3, typename StringType4> -PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4) -{ - StringTypeAdapter<StringType1> adapter1(string1); - StringTypeAdapter<StringType2> adapter2(string2); - StringTypeAdapter<StringType3> adapter3(string3); - StringTypeAdapter<StringType4> adapter4(string4); - - UChar* buffer; - bool overflow = false; - unsigned length = adapter1.length(); - sumWithOverflow(length, adapter2.length(), overflow); - sumWithOverflow(length, adapter3.length(), overflow); - sumWithOverflow(length, adapter4.length(), overflow); - if (overflow) - return 0; - PassRefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) - return 0; - - UChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - result += adapter2.length(); - adapter3.writeTo(result); - result += adapter3.length(); - adapter4.writeTo(result); - - return resultImpl; -} - -template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5> -PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5) -{ - StringTypeAdapter<StringType1> adapter1(string1); - StringTypeAdapter<StringType2> adapter2(string2); - StringTypeAdapter<StringType3> adapter3(string3); - StringTypeAdapter<StringType4> adapter4(string4); - StringTypeAdapter<StringType5> adapter5(string5); - - UChar* buffer; - bool overflow = false; - unsigned length = adapter1.length(); - sumWithOverflow(length, adapter2.length(), overflow); - sumWithOverflow(length, adapter3.length(), overflow); - sumWithOverflow(length, adapter4.length(), overflow); - sumWithOverflow(length, adapter5.length(), overflow); - if (overflow) - return 0; - PassRefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) - return 0; - - UChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - result += adapter2.length(); - adapter3.writeTo(result); - result += adapter3.length(); - adapter4.writeTo(result); - result += adapter4.length(); - adapter5.writeTo(result); - - return resultImpl; -} - -template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6> -PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6) -{ - StringTypeAdapter<StringType1> adapter1(string1); - StringTypeAdapter<StringType2> adapter2(string2); - StringTypeAdapter<StringType3> adapter3(string3); - StringTypeAdapter<StringType4> adapter4(string4); - StringTypeAdapter<StringType5> adapter5(string5); - StringTypeAdapter<StringType6> adapter6(string6); - - UChar* buffer; - bool overflow = false; - unsigned length = adapter1.length(); - sumWithOverflow(length, adapter2.length(), overflow); - sumWithOverflow(length, adapter3.length(), overflow); - sumWithOverflow(length, adapter4.length(), overflow); - sumWithOverflow(length, adapter5.length(), overflow); - sumWithOverflow(length, adapter6.length(), overflow); - if (overflow) - return 0; - PassRefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) - return 0; - - UChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - result += adapter2.length(); - adapter3.writeTo(result); - result += adapter3.length(); - adapter4.writeTo(result); - result += adapter4.length(); - adapter5.writeTo(result); - result += adapter5.length(); - adapter6.writeTo(result); - - return resultImpl; -} - -template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7> -PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7) -{ - StringTypeAdapter<StringType1> adapter1(string1); - StringTypeAdapter<StringType2> adapter2(string2); - StringTypeAdapter<StringType3> adapter3(string3); - StringTypeAdapter<StringType4> adapter4(string4); - StringTypeAdapter<StringType5> adapter5(string5); - StringTypeAdapter<StringType6> adapter6(string6); - StringTypeAdapter<StringType7> adapter7(string7); - - UChar* buffer; - bool overflow = false; - unsigned length = adapter1.length(); - sumWithOverflow(length, adapter2.length(), overflow); - sumWithOverflow(length, adapter3.length(), overflow); - sumWithOverflow(length, adapter4.length(), overflow); - sumWithOverflow(length, adapter5.length(), overflow); - sumWithOverflow(length, adapter6.length(), overflow); - sumWithOverflow(length, adapter7.length(), overflow); - if (overflow) - return 0; - PassRefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) - return 0; - - UChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - result += adapter2.length(); - adapter3.writeTo(result); - result += adapter3.length(); - adapter4.writeTo(result); - result += adapter4.length(); - adapter5.writeTo(result); - result += adapter5.length(); - adapter6.writeTo(result); - result += adapter6.length(); - adapter7.writeTo(result); - - return resultImpl; -} - -template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8> -PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8) -{ - StringTypeAdapter<StringType1> adapter1(string1); - StringTypeAdapter<StringType2> adapter2(string2); - StringTypeAdapter<StringType3> adapter3(string3); - StringTypeAdapter<StringType4> adapter4(string4); - StringTypeAdapter<StringType5> adapter5(string5); - StringTypeAdapter<StringType6> adapter6(string6); - StringTypeAdapter<StringType7> adapter7(string7); - StringTypeAdapter<StringType8> adapter8(string8); - - UChar* buffer; - bool overflow = false; - unsigned length = adapter1.length(); - sumWithOverflow(length, adapter2.length(), overflow); - sumWithOverflow(length, adapter3.length(), overflow); - sumWithOverflow(length, adapter4.length(), overflow); - sumWithOverflow(length, adapter5.length(), overflow); - sumWithOverflow(length, adapter6.length(), overflow); - sumWithOverflow(length, adapter7.length(), overflow); - sumWithOverflow(length, adapter8.length(), overflow); - if (overflow) - return 0; - PassRefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) - return 0; - - UChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - result += adapter2.length(); - adapter3.writeTo(result); - result += adapter3.length(); - adapter4.writeTo(result); - result += adapter4.length(); - adapter5.writeTo(result); - result += adapter5.length(); - adapter6.writeTo(result); - result += adapter6.length(); - adapter7.writeTo(result); - result += adapter7.length(); - adapter8.writeTo(result); - - return resultImpl; -} - -template<typename StringType1, typename StringType2> -UString makeString(StringType1 string1, StringType2 string2) -{ - PassRefPtr<StringImpl> resultImpl = tryMakeString(string1, string2); - if (!resultImpl) - CRASH(); - return resultImpl; -} - -template<typename StringType1, typename StringType2, typename StringType3> -UString makeString(StringType1 string1, StringType2 string2, StringType3 string3) -{ - PassRefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3); - if (!resultImpl) - CRASH(); - return resultImpl; -} - -template<typename StringType1, typename StringType2, typename StringType3, typename StringType4> -UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4) -{ - PassRefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4); - if (!resultImpl) - CRASH(); - return resultImpl; -} - -template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5> -UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5) -{ - PassRefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5); - if (!resultImpl) - CRASH(); - return resultImpl; -} - -template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6> -UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6) -{ - PassRefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6); - if (!resultImpl) - CRASH(); - return resultImpl; -} - -template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7> -UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7) -{ - PassRefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7); - if (!resultImpl) - CRASH(); - return resultImpl; -} - -template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8> -UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8) -{ - PassRefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8); - if (!resultImpl) - CRASH(); - return resultImpl; -} - -} // namespace JSC - -#endif diff --git a/JavaScriptCore/runtime/StringPrototype.cpp b/JavaScriptCore/runtime/StringPrototype.cpp index 91e9b06..37436f9 100644 --- a/JavaScriptCore/runtime/StringPrototype.cpp +++ b/JavaScriptCore/runtime/StringPrototype.cpp @@ -206,7 +206,8 @@ static NEVER_INLINE UString substituteBackreferencesSlow(const UString& replacem substitutedReplacement.append(replacement.characters() + offset, i - offset); i += 1 + advance; offset = i + 1; - substitutedReplacement.append(source.characters() + backrefStart, backrefLength); + if (backrefStart >= 0) + substitutedReplacement.append(source.characters() + backrefStart, backrefLength); } while ((i = replacement.find('$', i + 1)) != notFound); if (replacement.length() - offset) @@ -275,12 +276,16 @@ static ALWAYS_INLINE JSValue jsSpliceSubstringsWithSeparators(ExecState* exec, J int bufferPos = 0; for (int i = 0; i < maxCount; i++) { if (i < rangeCount) { - StringImpl::copyChars(buffer + bufferPos, source.characters() + substringRanges[i].position, substringRanges[i].length); - bufferPos += substringRanges[i].length; + if (int srcLen = substringRanges[i].length) { + StringImpl::copyChars(buffer + bufferPos, source.characters() + substringRanges[i].position, srcLen); + bufferPos += srcLen; + } } if (i < separatorCount) { - StringImpl::copyChars(buffer + bufferPos, separators[i].characters(), separators[i].length()); - bufferPos += separators[i].length(); + if (int sepLen = separators[i].length()) { + StringImpl::copyChars(buffer + bufferPos, separators[i].characters(), sepLen); + bufferPos += sepLen; + } } } @@ -302,6 +307,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec) if (pattern.inherits(&RegExpObject::info)) { const UString& source = sourceVal->value(exec); + unsigned sourceLen = source.length(); if (exec->hadException()) return JSValue::encode(JSValue()); RegExp* reg = asRegExpObject(pattern)->regExp(); @@ -330,7 +336,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec) regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector); if (matchIndex < 0) break; - + sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex)); int completeMatchStart = ovector[0]; @@ -347,7 +353,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec) cachedCall.setArgument(i++, jsNumber(exec, completeMatchStart)); cachedCall.setArgument(i++, sourceVal); - + cachedCall.setThis(exec->globalThisValue()); JSValue result = cachedCall.call(); if (LIKELY(result.isString())) @@ -363,10 +369,10 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec) // special case of empty match if (matchLen == 0) { startPosition++; - if (startPosition > source.length()) + if (startPosition > sourceLen) break; } - } + } } else { do { int matchIndex; @@ -376,16 +382,16 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec) if (matchIndex < 0) break; - sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex)); - if (callType != CallTypeNone) { + sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex)); + int completeMatchStart = ovector[0]; MarkedArgumentBuffer args; for (unsigned i = 0; i < reg->numSubpatterns() + 1; ++i) { int matchStart = ovector[i * 2]; int matchLen = ovector[i * 2 + 1] - matchStart; - + if (matchStart < 0) args.append(jsUndefined()); else @@ -398,8 +404,17 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec) replacements.append(call(exec, replacement, callType, callData, exec->globalThisValue(), args).toString(exec)); if (exec->hadException()) break; - } else - replacements.append(substituteBackreferences(replacementString, source, ovector, reg)); + } else { + int replLen = replacementString.length(); + if (lastIndex < matchIndex || replLen) { + sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex)); + + if (replLen) + replacements.append(substituteBackreferences(replacementString, source, ovector, reg)); + else + replacements.append(UString()); + } + } lastIndex = matchIndex + matchLen; startPosition = lastIndex; @@ -407,7 +422,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec) // special case of empty match if (matchLen == 0) { startPosition++; - if (startPosition > source.length()) + if (startPosition > sourceLen) break; } } while (global); @@ -416,8 +431,8 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec) if (!lastIndex && replacements.isEmpty()) return JSValue::encode(sourceVal); - if (static_cast<unsigned>(lastIndex) < source.length()) - sourceRanges.append(StringRange(lastIndex, source.length() - lastIndex)); + if (static_cast<unsigned>(lastIndex) < sourceLen) + sourceRanges.append(StringRange(lastIndex, sourceLen - lastIndex)); return JSValue::encode(jsSpliceSubstringsWithSeparators(exec, sourceVal, source, sourceRanges.data(), sourceRanges.size(), replacements.data(), replacements.size())); } diff --git a/JavaScriptCore/runtime/StringBuilder.h b/JavaScriptCore/runtime/UStringBuilder.h index 27aa57f..31ccf38 100644 --- a/JavaScriptCore/runtime/StringBuilder.h +++ b/JavaScriptCore/runtime/UStringBuilder.h @@ -23,65 +23,21 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef StringBuilder_h -#define StringBuilder_h +#ifndef UStringBuilder_h +#define UStringBuilder_h -#include <wtf/Vector.h> +#include <wtf/text/StringBuilder.h> namespace JSC { -class StringBuilder { +class UStringBuilder : public StringBuilder { public: - void append(const UChar u) - { - buffer.append(u); - } + using StringBuilder::append; + void append(const UString& str) { append(String(str.impl())); } - void append(const char* str) - { - append(str, strlen(str)); - } - - void append(const char* str, size_t len) - { - reserveCapacity(buffer.size() + len); - for (size_t i = 0; i < len; i++) - buffer.append(static_cast<unsigned char>(str[i])); - } - - void append(const UChar* str, size_t len) - { - buffer.append(str, len); - } - - void append(const UString& str) - { - buffer.append(str.characters(), str.length()); - } - - bool isEmpty() { return buffer.isEmpty(); } - void reserveCapacity(size_t newCapacity) - { - if (newCapacity < buffer.capacity()) - return; - buffer.reserveCapacity(std::max(newCapacity, buffer.capacity() + buffer.capacity() / 4 + 1)); - } - void resize(size_t size) { buffer.resize(size); } - size_t size() const { return buffer.size(); } - - UChar operator[](size_t i) const { return buffer.at(i); } - - UString build() - { - buffer.shrinkToFit(); - ASSERT(buffer.data() || !buffer.size()); - return UString::adopt(buffer); - } - -protected: - Vector<UChar, 64> buffer; + UString toUString() { return toString().impl(); } }; -} +} // namespace JSC -#endif +#endif // UStringBuilder_h diff --git a/JavaScriptCore/runtime/UStringConcatenate.h b/JavaScriptCore/runtime/UStringConcatenate.h new file mode 100644 index 0000000..0990c72 --- /dev/null +++ b/JavaScriptCore/runtime/UStringConcatenate.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef UStringConcatenate_h +#define UStringConcatenate_h + +#include "UString.h" +#include <wtf/text/StringConcatenate.h> + +namespace WTF { + +template<> +class StringTypeAdapter<JSC::UString> { +public: + StringTypeAdapter<JSC::UString>(JSC::UString& string) + : m_data(string.characters()) + , m_length(string.length()) + { + } + + unsigned length() { return m_length; } + + void writeTo(UChar* destination) + { + for (unsigned i = 0; i < m_length; ++i) + destination[i] = m_data[i]; + } + +private: + const UChar* m_data; + unsigned m_length; +}; + +}; // namespace WTF + +namespace JSC { + +template<typename StringType1, typename StringType2> +UString makeUString(StringType1 string1, StringType2 string2) +{ + PassRefPtr<StringImpl> resultImpl = WTF::tryMakeString(string1, string2); + if (!resultImpl) + CRASH(); + return resultImpl; +} + +template<typename StringType1, typename StringType2, typename StringType3> +UString makeUString(StringType1 string1, StringType2 string2, StringType3 string3) +{ + PassRefPtr<StringImpl> resultImpl = WTF::tryMakeString(string1, string2, string3); + if (!resultImpl) + CRASH(); + return resultImpl; +} + +template<typename StringType1, typename StringType2, typename StringType3, typename StringType4> +UString makeUString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4) +{ + PassRefPtr<StringImpl> resultImpl = WTF::tryMakeString(string1, string2, string3, string4); + if (!resultImpl) + CRASH(); + return resultImpl; +} + +template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5> +UString makeUString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5) +{ + PassRefPtr<StringImpl> resultImpl = WTF::tryMakeString(string1, string2, string3, string4, string5); + if (!resultImpl) + CRASH(); + return resultImpl; +} + +template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6> +UString makeUString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6) +{ + PassRefPtr<StringImpl> resultImpl = WTF::tryMakeString(string1, string2, string3, string4, string5, string6); + if (!resultImpl) + CRASH(); + return resultImpl; +} + +template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7> +UString makeUString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7) +{ + PassRefPtr<StringImpl> resultImpl = WTF::tryMakeString(string1, string2, string3, string4, string5, string6, string7); + if (!resultImpl) + CRASH(); + return resultImpl; +} + +template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8> +UString makeUString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8) +{ + PassRefPtr<StringImpl> resultImpl = WTF::tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8); + if (!resultImpl) + CRASH(); + return resultImpl; +} + +} // namespace JSC + +#endif |