diff options
author | Steve Block <steveblock@google.com> | 2010-02-02 14:57:50 +0000 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2010-02-04 15:06:55 +0000 |
commit | d0825bca7fe65beaee391d30da42e937db621564 (patch) | |
tree | 7461c49eb5844ffd1f35d1ba2c8b7584c1620823 /JavaScriptCore/API | |
parent | 3db770bd97c5a59b6c7574ca80a39e5a51c1defd (diff) | |
download | external_webkit-d0825bca7fe65beaee391d30da42e937db621564.zip external_webkit-d0825bca7fe65beaee391d30da42e937db621564.tar.gz external_webkit-d0825bca7fe65beaee391d30da42e937db621564.tar.bz2 |
Merge webkit.org at r54127 : Initial merge by git
Change-Id: Ib661abb595522f50ea406f72d3a0ce17f7193c82
Diffstat (limited to 'JavaScriptCore/API')
-rw-r--r-- | JavaScriptCore/API/APIShims.h | 99 | ||||
-rw-r--r-- | JavaScriptCore/API/JSBase.cpp | 18 | ||||
-rw-r--r-- | JavaScriptCore/API/JSBase.h | 20 | ||||
-rw-r--r-- | JavaScriptCore/API/JSCallbackConstructor.cpp | 3 | ||||
-rw-r--r-- | JavaScriptCore/API/JSCallbackConstructor.h | 2 | ||||
-rw-r--r-- | JavaScriptCore/API/JSCallbackFunction.cpp | 3 | ||||
-rw-r--r-- | JavaScriptCore/API/JSCallbackFunction.h | 2 | ||||
-rw-r--r-- | JavaScriptCore/API/JSCallbackObject.h | 5 | ||||
-rw-r--r-- | JavaScriptCore/API/JSCallbackObjectFunctions.h | 56 | ||||
-rw-r--r-- | JavaScriptCore/API/JSClassRef.cpp | 65 | ||||
-rw-r--r-- | JavaScriptCore/API/JSClassRef.h | 3 | ||||
-rw-r--r-- | JavaScriptCore/API/JSContextRef.cpp | 28 | ||||
-rw-r--r-- | JavaScriptCore/API/JSObjectRef.cpp | 64 | ||||
-rw-r--r-- | JavaScriptCore/API/JSValueRef.cpp | 77 | ||||
-rw-r--r-- | JavaScriptCore/API/OpaqueJSString.cpp | 2 | ||||
-rw-r--r-- | JavaScriptCore/API/tests/testapi.c | 23 | ||||
-rw-r--r-- | JavaScriptCore/API/tests/testapi.js | 77 |
17 files changed, 350 insertions, 197 deletions
diff --git a/JavaScriptCore/API/APIShims.h b/JavaScriptCore/API/APIShims.h new file mode 100644 index 0000000..d7276ec --- /dev/null +++ b/JavaScriptCore/API/APIShims.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2009 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 COMPUTER, 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 COMPUTER, 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 APIShims_h +#define APIShims_h + +#include "CallFrame.h" +#include "JSLock.h" + +namespace JSC { + +class APIEntryShimWithoutLock { +protected: + APIEntryShimWithoutLock(JSGlobalData* globalData, bool registerThread) + : m_globalData(globalData) + , m_entryIdentifierTable(setCurrentIdentifierTable(globalData->identifierTable)) + { + if (registerThread) + globalData->heap.registerThread(); + m_globalData->timeoutChecker.start(); + } + + ~APIEntryShimWithoutLock() + { + m_globalData->timeoutChecker.stop(); + setCurrentIdentifierTable(m_entryIdentifierTable); + } + +private: + JSGlobalData* m_globalData; + IdentifierTable* m_entryIdentifierTable; +}; + +class APIEntryShim : public APIEntryShimWithoutLock { +public: + // Normal API entry + APIEntryShim(ExecState* exec, bool registerThread = true) + : APIEntryShimWithoutLock(&exec->globalData(), registerThread) + , m_lock(exec) + { + } + + // JSPropertyNameAccumulator only has a globalData. + APIEntryShim(JSGlobalData* globalData, bool registerThread = true) + : APIEntryShimWithoutLock(globalData, registerThread) + , m_lock(globalData->isSharedInstance ? LockForReal : SilenceAssertionsOnly) + { + } + +private: + JSLock m_lock; +}; + +class APICallbackShim { +public: + APICallbackShim(ExecState* exec) + : m_dropAllLocks(exec) + , m_globalData(&exec->globalData()) + { + resetCurrentIdentifierTable(); + m_globalData->timeoutChecker.start(); + } + + ~APICallbackShim() + { + m_globalData->timeoutChecker.stop(); + setCurrentIdentifierTable(m_globalData->identifierTable); + } + +private: + JSLock::DropAllLocks m_dropAllLocks; + JSGlobalData* m_globalData; +}; + +} + +#endif diff --git a/JavaScriptCore/API/JSBase.cpp b/JavaScriptCore/API/JSBase.cpp index 4a32d35..ebfeafa 100644 --- a/JavaScriptCore/API/JSBase.cpp +++ b/JavaScriptCore/API/JSBase.cpp @@ -28,6 +28,7 @@ #include "JSBasePrivate.h" #include "APICast.h" +#include "APIShims.h" #include "Completion.h" #include "OpaqueJSString.h" #include "SourceCode.h" @@ -43,8 +44,7 @@ using namespace JSC; JSValueRef JSEvaluateScript(JSContextRef ctx, JSStringRef script, JSObjectRef thisObject, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSObject* jsThisObject = toJS(thisObject); @@ -69,8 +69,7 @@ JSValueRef JSEvaluateScript(JSContextRef ctx, JSStringRef script, JSObjectRef th bool JSCheckScriptSyntax(JSContextRef ctx, JSStringRef script, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); SourceCode source = makeSource(script->ustring(), sourceURL->ustring(), startingLineNumber); Completion completion = checkSyntax(exec->dynamicGlobalObject()->globalExec(), source); @@ -94,12 +93,11 @@ void JSGarbageCollect(JSContextRef ctx) return; ExecState* exec = toJS(ctx); - JSGlobalData& globalData = exec->globalData(); - - JSLock lock(globalData.isSharedInstance ? LockForReal : SilenceAssertionsOnly); + APIEntryShim entryShim(exec, false); + JSGlobalData& globalData = exec->globalData(); if (!globalData.heap.isBusy()) - globalData.heap.collect(); + globalData.heap.collectAllGarbage(); // FIXME: Perhaps we should trigger a second mark and sweep // once the garbage collector is done if this is called when @@ -109,8 +107,6 @@ void JSGarbageCollect(JSContextRef ctx) void JSReportExtraMemoryCost(JSContextRef ctx, size_t size) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); - + APIEntryShim entryShim(exec); exec->globalData().heap.reportExtraMemoryCost(size); } diff --git a/JavaScriptCore/API/JSBase.h b/JavaScriptCore/API/JSBase.h index d1ce9b3..2e16720 100644 --- a/JavaScriptCore/API/JSBase.h +++ b/JavaScriptCore/API/JSBase.h @@ -65,27 +65,15 @@ typedef struct OpaqueJSValue* JSObjectRef; /* JavaScript symbol exports */ #undef JS_EXPORT -#if defined(BUILDING_WX__) +#if defined(JS_NO_EXPORT) #define JS_EXPORT #elif defined(__GNUC__) && !defined(__CC_ARM) && !defined(__ARMCC__) #define JS_EXPORT __attribute__((visibility("default"))) -#elif defined(_WIN32_WCE) - #if defined(JS_BUILDING_JS) - #define JS_EXPORT __declspec(dllexport) - #elif defined(JS_IMPORT_JS) - #define JS_EXPORT __declspec(dllimport) - #else - #define JS_EXPORT - #endif -#elif defined(WIN32) || defined(_WIN32) - /* - * TODO: Export symbols with JS_EXPORT when using MSVC. - * See http://bugs.webkit.org/show_bug.cgi?id=16227 - */ +#elif defined(WIN32) || defined(_WIN32) || defined(_WIN32_WCE) #if defined(BUILDING_JavaScriptCore) || defined(BUILDING_WTF) - #define JS_EXPORT __declspec(dllexport) + #define JS_EXPORT __declspec(dllexport) #else - #define JS_EXPORT __declspec(dllimport) + #define JS_EXPORT __declspec(dllimport) #endif #else #define JS_EXPORT diff --git a/JavaScriptCore/API/JSCallbackConstructor.cpp b/JavaScriptCore/API/JSCallbackConstructor.cpp index 1c33962..9c5f6d7 100644 --- a/JavaScriptCore/API/JSCallbackConstructor.cpp +++ b/JavaScriptCore/API/JSCallbackConstructor.cpp @@ -26,6 +26,7 @@ #include "config.h" #include "JSCallbackConstructor.h" +#include "APIShims.h" #include "APICast.h" #include <runtime/JSGlobalObject.h> #include <runtime/JSLock.h> @@ -66,7 +67,7 @@ static JSObject* constructJSCallback(ExecState* exec, JSObject* constructor, con JSValueRef exception = 0; JSObjectRef result; { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); result = callback(ctx, constructorRef, argumentCount, arguments.data(), &exception); } if (exception) diff --git a/JavaScriptCore/API/JSCallbackConstructor.h b/JavaScriptCore/API/JSCallbackConstructor.h index c4bd7ad..e529947 100644 --- a/JavaScriptCore/API/JSCallbackConstructor.h +++ b/JavaScriptCore/API/JSCallbackConstructor.h @@ -41,7 +41,7 @@ public: static PassRefPtr<Structure> createStructure(JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, StructureFlags)); + return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); } protected: diff --git a/JavaScriptCore/API/JSCallbackFunction.cpp b/JavaScriptCore/API/JSCallbackFunction.cpp index b7dd768..0e434d9 100644 --- a/JavaScriptCore/API/JSCallbackFunction.cpp +++ b/JavaScriptCore/API/JSCallbackFunction.cpp @@ -27,6 +27,7 @@ #include <wtf/Platform.h> #include "JSCallbackFunction.h" +#include "APIShims.h" #include "APICast.h" #include "CodeBlock.h" #include "JSFunction.h" @@ -61,7 +62,7 @@ JSValue JSCallbackFunction::call(ExecState* exec, JSObject* functionObject, JSVa JSValueRef exception = 0; JSValueRef result; { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); result = static_cast<JSCallbackFunction*>(functionObject)->m_callback(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), &exception); } if (exception) diff --git a/JavaScriptCore/API/JSCallbackFunction.h b/JavaScriptCore/API/JSCallbackFunction.h index 0cf25c4..10dae6b 100644 --- a/JavaScriptCore/API/JSCallbackFunction.h +++ b/JavaScriptCore/API/JSCallbackFunction.h @@ -41,7 +41,7 @@ public: // refactor the code so this override isn't necessary static PassRefPtr<Structure> createStructure(JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, StructureFlags)); + return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); } private: diff --git a/JavaScriptCore/API/JSCallbackObject.h b/JavaScriptCore/API/JSCallbackObject.h index d19890a..adb5b60 100644 --- a/JavaScriptCore/API/JSCallbackObject.h +++ b/JavaScriptCore/API/JSCallbackObject.h @@ -50,7 +50,7 @@ public: static PassRefPtr<Structure> createStructure(JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, StructureFlags)); + return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), Base::AnonymousSlotCount); } protected: @@ -61,6 +61,7 @@ private: virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, unsigned, PropertySlot&); + virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&); @@ -69,7 +70,7 @@ private: virtual bool hasInstance(ExecState* exec, JSValue value, JSValue proto); - virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&); + virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties); virtual double toNumber(ExecState*) const; virtual UString toString(ExecState*) const; diff --git a/JavaScriptCore/API/JSCallbackObjectFunctions.h b/JavaScriptCore/API/JSCallbackObjectFunctions.h index ed86a00..4b28a99 100644 --- a/JavaScriptCore/API/JSCallbackObjectFunctions.h +++ b/JavaScriptCore/API/JSCallbackObjectFunctions.h @@ -24,6 +24,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "APIShims.h" #include "APICast.h" #include "Error.h" #include "JSCallbackFunction.h" @@ -79,7 +80,7 @@ void JSCallbackObject<Base>::init(ExecState* exec) // initialize from base to derived for (int i = static_cast<int>(initRoutines.size()) - 1; i >= 0; i--) { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); JSObjectInitializeCallback initialize = initRoutines[i]; initialize(toRef(exec), toRef(this)); } @@ -117,7 +118,7 @@ bool JSCallbackObject<Base>::getOwnPropertySlot(ExecState* exec, const Identifie if (JSObjectHasPropertyCallback hasProperty = jsClass->hasProperty) { if (!propertyNameRef) propertyNameRef = OpaqueJSString::create(propertyName.ustring()); - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); if (hasProperty(ctx, thisRef, propertyNameRef.get())) { slot.setCustom(this, callbackGetter); return true; @@ -128,7 +129,7 @@ bool JSCallbackObject<Base>::getOwnPropertySlot(ExecState* exec, const Identifie JSValueRef exception = 0; JSValueRef value; { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); value = getProperty(ctx, thisRef, propertyNameRef.get(), &exception); } if (exception) { @@ -167,6 +168,25 @@ bool JSCallbackObject<Base>::getOwnPropertySlot(ExecState* exec, unsigned proper } template <class Base> +bool JSCallbackObject<Base>::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + PropertySlot slot; + if (getOwnPropertySlot(exec, propertyName, slot)) { + // Ideally we should return an access descriptor, but returning a value descriptor is better than nothing. + JSValue value = slot.getValue(exec, propertyName); + if (!exec->hadException()) + descriptor.setValue(value); + // We don't know whether the property is configurable, but assume it is. + descriptor.setConfigurable(true); + // We don't know whether the property is enumerable (we could call getOwnPropertyNames() to find out), but assume it isn't. + descriptor.setEnumerable(false); + return true; + } + + return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); +} + +template <class Base> void JSCallbackObject<Base>::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { JSContextRef ctx = toRef(exec); @@ -181,7 +201,7 @@ void JSCallbackObject<Base>::put(ExecState* exec, const Identifier& propertyName JSValueRef exception = 0; bool result; { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); result = setProperty(ctx, thisRef, propertyNameRef.get(), valueRef, &exception); } if (exception) @@ -200,7 +220,7 @@ void JSCallbackObject<Base>::put(ExecState* exec, const Identifier& propertyName JSValueRef exception = 0; bool result; { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); result = setProperty(ctx, thisRef, propertyNameRef.get(), valueRef, &exception); } if (exception) @@ -239,7 +259,7 @@ bool JSCallbackObject<Base>::deleteProperty(ExecState* exec, const Identifier& p JSValueRef exception = 0; bool result; { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); result = deleteProperty(ctx, thisRef, propertyNameRef.get(), &exception); } if (exception) @@ -301,7 +321,7 @@ JSObject* JSCallbackObject<Base>::construct(ExecState* exec, JSObject* construct JSValueRef exception = 0; JSObject* result; { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); result = toJS(callAsConstructor(execRef, constructorRef, argumentCount, arguments.data(), &exception)); } if (exception) @@ -326,7 +346,7 @@ bool JSCallbackObject<Base>::hasInstance(ExecState* exec, JSValue value, JSValue JSValueRef exception = 0; bool result; { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); result = hasInstance(execRef, thisRef, valueRef, &exception); } if (exception) @@ -365,7 +385,7 @@ JSValue JSCallbackObject<Base>::call(ExecState* exec, JSObject* functionObject, JSValueRef exception = 0; JSValue result; { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); result = toJS(exec, callAsFunction(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), &exception)); } if (exception) @@ -379,14 +399,14 @@ JSValue JSCallbackObject<Base>::call(ExecState* exec, JSObject* functionObject, } template <class Base> -void JSCallbackObject<Base>::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSCallbackObject<Base>::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { JSContextRef execRef = toRef(exec); JSObjectRef thisRef = toRef(this); for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) { if (JSObjectGetPropertyNamesCallback getPropertyNames = jsClass->getPropertyNames) { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); getPropertyNames(execRef, thisRef, toRef(&propertyNames)); } @@ -396,7 +416,7 @@ void JSCallbackObject<Base>::getOwnPropertyNames(ExecState* exec, PropertyNameAr for (iterator it = staticValues->begin(); it != end; ++it) { UString::Rep* name = it->first.get(); StaticValueEntry* entry = it->second; - if (entry->getProperty && !(entry->attributes & kJSPropertyAttributeDontEnum)) + if (entry->getProperty && (!(entry->attributes & kJSPropertyAttributeDontEnum) || (mode == IncludeDontEnumProperties))) propertyNames.add(Identifier(exec, name)); } } @@ -407,13 +427,13 @@ void JSCallbackObject<Base>::getOwnPropertyNames(ExecState* exec, PropertyNameAr for (iterator it = staticFunctions->begin(); it != end; ++it) { UString::Rep* name = it->first.get(); StaticFunctionEntry* entry = it->second; - if (!(entry->attributes & kJSPropertyAttributeDontEnum)) + if (!(entry->attributes & kJSPropertyAttributeDontEnum) || (mode == IncludeDontEnumProperties)) propertyNames.add(Identifier(exec, name)); } } } - Base::getOwnPropertyNames(exec, propertyNames); + Base::getOwnPropertyNames(exec, propertyNames, mode); } template <class Base> @@ -432,7 +452,7 @@ double JSCallbackObject<Base>::toNumber(ExecState* exec) const JSValueRef exception = 0; JSValueRef value; { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); value = convertToType(ctx, thisRef, kJSTypeNumber, &exception); } if (exception) { @@ -459,7 +479,7 @@ UString JSCallbackObject<Base>::toString(ExecState* exec) const JSValueRef exception = 0; JSValueRef value; { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); value = convertToType(ctx, thisRef, kJSTypeString, &exception); } if (exception) { @@ -512,7 +532,7 @@ JSValue JSCallbackObject<Base>::staticValueGetter(ExecState* exec, const Identif JSValueRef exception = 0; JSValueRef value; { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); value = getProperty(toRef(exec), thisRef, propertyNameRef.get(), &exception); } if (exception) { @@ -566,7 +586,7 @@ JSValue JSCallbackObject<Base>::callbackGetter(ExecState* exec, const Identifier JSValueRef exception = 0; JSValueRef value; { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); value = getProperty(toRef(exec), thisRef, propertyNameRef.get(), &exception); } if (exception) { diff --git a/JavaScriptCore/API/JSClassRef.cpp b/JavaScriptCore/API/JSClassRef.cpp index afde7ce..c6685bf 100644 --- a/JavaScriptCore/API/JSClassRef.cpp +++ b/JavaScriptCore/API/JSClassRef.cpp @@ -34,6 +34,7 @@ #include <runtime/ObjectPrototype.h> #include <runtime/Identifier.h> +using namespace std; using namespace JSC; const JSClassDefinition kJSClassDefinitionEmpty = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -52,7 +53,7 @@ OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass* , callAsConstructor(definition->callAsConstructor) , hasInstance(definition->hasInstance) , convertToType(definition->convertToType) - , m_className(UString::Rep::createFromUTF8(definition->className)) + , m_className(UString::createFromUTF8(definition->className).rep()->ref()) , m_staticValues(0) , m_staticFunctions(0) { @@ -61,8 +62,9 @@ OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass* if (const JSStaticValue* staticValue = definition->staticValues) { m_staticValues = new OpaqueJSClassStaticValuesTable(); while (staticValue->name) { - m_staticValues->add(UString::Rep::createFromUTF8(staticValue->name), - new StaticValueEntry(staticValue->getProperty, staticValue->setProperty, staticValue->attributes)); + // Use a local variable here to sidestep an RVCT compiler bug. + StaticValueEntry* entry = new StaticValueEntry(staticValue->getProperty, staticValue->setProperty, staticValue->attributes); + m_staticValues->add(UString::createFromUTF8(staticValue->name).rep()->ref(), entry); ++staticValue; } } @@ -70,8 +72,9 @@ OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass* if (const JSStaticFunction* staticFunction = definition->staticFunctions) { m_staticFunctions = new OpaqueJSClassStaticFunctionsTable(); while (staticFunction->name) { - m_staticFunctions->add(UString::Rep::createFromUTF8(staticFunction->name), - new StaticFunctionEntry(staticFunction->callAsFunction, staticFunction->attributes)); + // Use a local variable here to sidestep an RVCT compiler bug. + StaticFunctionEntry* entry = new StaticFunctionEntry(staticFunction->callAsFunction, staticFunction->attributes); + m_staticFunctions->add(UString::createFromUTF8(staticFunction->name).rep()->ref(), entry); ++staticFunction; } } @@ -82,12 +85,12 @@ OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass* OpaqueJSClass::~OpaqueJSClass() { - ASSERT(!m_className.rep()->identifierTable()); + ASSERT(!m_className.rep()->isIdentifier()); if (m_staticValues) { OpaqueJSClassStaticValuesTable::const_iterator end = m_staticValues->end(); for (OpaqueJSClassStaticValuesTable::const_iterator it = m_staticValues->begin(); it != end; ++it) { - ASSERT(!it->first->identifierTable()); + ASSERT(!it->first->isIdentifier()); delete it->second; } delete m_staticValues; @@ -96,7 +99,7 @@ OpaqueJSClass::~OpaqueJSClass() if (m_staticFunctions) { OpaqueJSClassStaticFunctionsTable::const_iterator end = m_staticFunctions->end(); for (OpaqueJSClassStaticFunctionsTable::const_iterator it = m_staticFunctions->begin(); it != end; ++it) { - ASSERT(!it->first->identifierTable()); + ASSERT(!it->first->isIdentifier()); delete it->second; } delete m_staticFunctions; @@ -118,39 +121,32 @@ static void clearReferenceToPrototype(JSObjectRef prototype) jsClassData->cachedPrototype = 0; } -PassRefPtr<OpaqueJSClass> OpaqueJSClass::create(const JSClassDefinition* definition) +PassRefPtr<OpaqueJSClass> OpaqueJSClass::create(const JSClassDefinition* clientDefinition) { - if (const JSStaticFunction* staticFunctions = definition->staticFunctions) { - // copy functions into a prototype class - JSClassDefinition protoDefinition = kJSClassDefinitionEmpty; - protoDefinition.staticFunctions = staticFunctions; - protoDefinition.finalize = clearReferenceToPrototype; - - // We are supposed to use JSClassRetain/Release but since we know that we currently have - // the only reference to this class object we cheat and use a RefPtr instead. - RefPtr<OpaqueJSClass> protoClass = adoptRef(new OpaqueJSClass(&protoDefinition, 0)); - - // remove functions from the original class - JSClassDefinition objectDefinition = *definition; - objectDefinition.staticFunctions = 0; - - return adoptRef(new OpaqueJSClass(&objectDefinition, protoClass.get())); - } + JSClassDefinition definition = *clientDefinition; // Avoid modifying client copy. - return adoptRef(new OpaqueJSClass(definition, 0)); + JSClassDefinition protoDefinition = kJSClassDefinitionEmpty; + protoDefinition.finalize = clearReferenceToPrototype; + swap(definition.staticFunctions, protoDefinition.staticFunctions); // Move static functions to the prototype. + + // We are supposed to use JSClassRetain/Release but since we know that we currently have + // the only reference to this class object we cheat and use a RefPtr instead. + RefPtr<OpaqueJSClass> protoClass = adoptRef(new OpaqueJSClass(&protoDefinition, 0)); + return adoptRef(new OpaqueJSClass(&definition, protoClass.get())); } OpaqueJSClassContextData::OpaqueJSClassContextData(OpaqueJSClass* jsClass) : m_class(jsClass) - , cachedPrototype(0) { if (jsClass->m_staticValues) { staticValues = new OpaqueJSClassStaticValuesTable; OpaqueJSClassStaticValuesTable::const_iterator end = jsClass->m_staticValues->end(); for (OpaqueJSClassStaticValuesTable::const_iterator it = jsClass->m_staticValues->begin(); it != end; ++it) { - ASSERT(!it->first->identifierTable()); - staticValues->add(UString::Rep::createCopying(it->first->data(), it->first->size()), - new StaticValueEntry(it->second->getProperty, it->second->setProperty, it->second->attributes)); + ASSERT(!it->first->isIdentifier()); + // Use a local variable here to sidestep an RVCT compiler bug. + StaticValueEntry* entry = new StaticValueEntry(it->second->getProperty, it->second->setProperty, it->second->attributes); + staticValues->add(UString::Rep::create(it->first->data(), it->first->size()), entry); + } } else @@ -161,9 +157,10 @@ OpaqueJSClassContextData::OpaqueJSClassContextData(OpaqueJSClass* jsClass) staticFunctions = new OpaqueJSClassStaticFunctionsTable; OpaqueJSClassStaticFunctionsTable::const_iterator end = jsClass->m_staticFunctions->end(); for (OpaqueJSClassStaticFunctionsTable::const_iterator it = jsClass->m_staticFunctions->begin(); it != end; ++it) { - ASSERT(!it->first->identifierTable()); - staticFunctions->add(UString::Rep::createCopying(it->first->data(), it->first->size()), - new StaticFunctionEntry(it->second->callAsFunction, it->second->attributes)); + ASSERT(!it->first->isIdentifier()); + // Use a local variable here to sidestep an RVCT compiler bug. + StaticFunctionEntry* entry = new StaticFunctionEntry(it->second->callAsFunction, it->second->attributes); + staticFunctions->add(UString::Rep::create(it->first->data(), it->first->size()), entry); } } else @@ -240,5 +237,5 @@ JSObject* OpaqueJSClass::prototype(ExecState* exec) jsClassData.cachedPrototype->setPrototype(prototype); } } - return jsClassData.cachedPrototype; + return jsClassData.cachedPrototype.get(); } diff --git a/JavaScriptCore/API/JSClassRef.h b/JavaScriptCore/API/JSClassRef.h index c4777dd..ae60aad 100644 --- a/JavaScriptCore/API/JSClassRef.h +++ b/JavaScriptCore/API/JSClassRef.h @@ -31,6 +31,7 @@ #include <runtime/JSObject.h> #include <runtime/Protect.h> #include <runtime/UString.h> +#include <runtime/WeakGCPtr.h> #include <wtf/HashMap.h> #include <wtf/RefCounted.h> @@ -76,7 +77,7 @@ struct OpaqueJSClassContextData : Noncopyable { OpaqueJSClassStaticValuesTable* staticValues; OpaqueJSClassStaticFunctionsTable* staticFunctions; - JSC::JSObject* cachedPrototype; + JSC::WeakGCPtr<JSC::JSObject> cachedPrototype; }; struct OpaqueJSClass : public ThreadSafeShared<OpaqueJSClass> { diff --git a/JavaScriptCore/API/JSContextRef.cpp b/JavaScriptCore/API/JSContextRef.cpp index e6626b7..6bdc3c8 100644 --- a/JavaScriptCore/API/JSContextRef.cpp +++ b/JavaScriptCore/API/JSContextRef.cpp @@ -35,7 +35,7 @@ #include "JSObject.h" #include <wtf/Platform.h> -#if PLATFORM(DARWIN) +#if OS(DARWIN) #include <mach-o/dyld.h> static const int32_t webkitFirstVersionWithConcurrentGlobalContexts = 0x2100500; // 528.5.0 @@ -46,7 +46,7 @@ using namespace JSC; JSContextGroupRef JSContextGroupCreate() { initializeThreading(); - return toRef(JSGlobalData::create().releaseRef()); + return toRef(JSGlobalData::createNonDefault().releaseRef()); } JSContextGroupRef JSContextGroupRetain(JSContextGroupRef group) @@ -63,7 +63,7 @@ void JSContextGroupRelease(JSContextGroupRef group) JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass) { initializeThreading(); -#if PLATFORM(DARWIN) +#if OS(DARWIN) // When running on Tiger or Leopard, or if the application was linked before JSGlobalContextCreate was changed // to use a unique JSGlobalData, we use a shared one for compatibility. #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) @@ -74,7 +74,7 @@ JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass) JSLock lock(LockForReal); return JSGlobalContextCreateInGroup(toRef(&JSGlobalData::sharedInstance()), globalObjectClass); } -#endif // PLATFORM(DARWIN) +#endif // OS(DARWIN) return JSGlobalContextCreateInGroup(0, globalObjectClass); } @@ -84,8 +84,9 @@ JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClass initializeThreading(); JSLock lock(LockForReal); + RefPtr<JSGlobalData> globalData = group ? PassRefPtr<JSGlobalData>(toJS(group)) : JSGlobalData::createNonDefault(); - RefPtr<JSGlobalData> globalData = group ? PassRefPtr<JSGlobalData>(toJS(group)) : JSGlobalData::create(); + APIEntryShim entryShim(globalData.get(), false); #if ENABLE(JSC_MULTIPLE_THREADS) globalData->makeUsableFromMultipleThreads(); @@ -108,12 +109,9 @@ JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClass JSGlobalContextRef JSGlobalContextRetain(JSGlobalContextRef ctx) { ExecState* exec = toJS(ctx); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSGlobalData& globalData = exec->globalData(); - - globalData.heap.registerThread(); - gcProtect(exec->dynamicGlobalObject()); globalData.ref(); return ctx; @@ -122,18 +120,16 @@ JSGlobalContextRef JSGlobalContextRetain(JSGlobalContextRef ctx) void JSGlobalContextRelease(JSGlobalContextRef ctx) { ExecState* exec = toJS(ctx); - JSLock lock(exec); + APIEntryShim entryShim(exec, false); gcUnprotect(exec->dynamicGlobalObject()); JSGlobalData& globalData = exec->globalData(); if (globalData.refCount() == 2) { // One reference is held by JSGlobalObject, another added by JSGlobalContextRetain(). // The last reference was released, this is our last chance to collect. - ASSERT(!globalData.heap.protectedObjectCount()); - ASSERT(!globalData.heap.isBusy()); globalData.heap.destroy(); } else - globalData.heap.collect(); + globalData.heap.collectAllGarbage(); globalData.deref(); } @@ -141,8 +137,7 @@ void JSGlobalContextRelease(JSGlobalContextRef ctx) JSObjectRef JSContextGetGlobalObject(JSContextRef ctx) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); // It is necessary to call toThisObject to get the wrapper object when used with WebCore. return toRef(exec->lexicalGlobalObject()->toThisObject(exec)); @@ -157,8 +152,7 @@ JSContextGroupRef JSContextGetGroup(JSContextRef ctx) JSGlobalContextRef JSContextGetGlobalContext(JSContextRef ctx) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); return toGlobalRef(exec->lexicalGlobalObject()->globalExec()); } diff --git a/JavaScriptCore/API/JSObjectRef.cpp b/JavaScriptCore/API/JSObjectRef.cpp index 06ef578..faaa4eb 100644 --- a/JavaScriptCore/API/JSObjectRef.cpp +++ b/JavaScriptCore/API/JSObjectRef.cpp @@ -76,8 +76,7 @@ void JSClassRelease(JSClassRef jsClass) JSObjectRef JSObjectMake(JSContextRef ctx, JSClassRef jsClass, void* data) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); if (!jsClass) return toRef(new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure())); // slightly more efficient @@ -92,8 +91,7 @@ JSObjectRef JSObjectMake(JSContextRef ctx, JSClassRef jsClass, void* data) JSObjectRef JSObjectMakeFunctionWithCallback(JSContextRef ctx, JSStringRef name, JSObjectCallAsFunctionCallback callAsFunction) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); Identifier nameID = name ? name->identifier(&exec->globalData()) : Identifier(exec, "anonymous"); @@ -103,8 +101,7 @@ JSObjectRef JSObjectMakeFunctionWithCallback(JSContextRef ctx, JSStringRef name, JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObjectCallAsConstructorCallback callAsConstructor) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsPrototype = jsClass ? jsClass->prototype(exec) : 0; if (!jsPrototype) @@ -118,8 +115,7 @@ JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObje JSObjectRef JSObjectMakeFunction(JSContextRef ctx, JSStringRef name, unsigned parameterCount, const JSStringRef parameterNames[], JSStringRef body, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); Identifier nameID = name ? name->identifier(&exec->globalData()) : Identifier(exec, "anonymous"); @@ -141,8 +137,7 @@ JSObjectRef JSObjectMakeFunction(JSContextRef ctx, JSStringRef name, unsigned pa JSObjectRef JSObjectMakeArray(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSObject* result; if (argumentCount) { @@ -167,8 +162,7 @@ JSObjectRef JSObjectMakeArray(JSContextRef ctx, size_t argumentCount, const JSVa JSObjectRef JSObjectMakeDate(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); MarkedArgumentBuffer argList; for (size_t i = 0; i < argumentCount; ++i) @@ -188,8 +182,7 @@ JSObjectRef JSObjectMakeDate(JSContextRef ctx, size_t argumentCount, const JSVal JSObjectRef JSObjectMakeError(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); MarkedArgumentBuffer argList; for (size_t i = 0; i < argumentCount; ++i) @@ -209,8 +202,7 @@ JSObjectRef JSObjectMakeError(JSContextRef ctx, size_t argumentCount, const JSVa JSObjectRef JSObjectMakeRegExp(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); MarkedArgumentBuffer argList; for (size_t i = 0; i < argumentCount; ++i) @@ -230,8 +222,7 @@ JSObjectRef JSObjectMakeRegExp(JSContextRef ctx, size_t argumentCount, const JSV JSValueRef JSObjectGetPrototype(JSContextRef ctx, JSObjectRef object) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSObject* jsObject = toJS(object); return toRef(exec, jsObject->prototype()); @@ -240,8 +231,7 @@ JSValueRef JSObjectGetPrototype(JSContextRef ctx, JSObjectRef object) void JSObjectSetPrototype(JSContextRef ctx, JSObjectRef object, JSValueRef value) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSObject* jsObject = toJS(object); JSValue jsValue = toJS(exec, value); @@ -252,8 +242,7 @@ void JSObjectSetPrototype(JSContextRef ctx, JSObjectRef object, JSValueRef value bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSObject* jsObject = toJS(object); @@ -263,8 +252,7 @@ bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef prope JSValueRef JSObjectGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSObject* jsObject = toJS(object); @@ -280,8 +268,7 @@ JSValueRef JSObjectGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSObject* jsObject = toJS(object); Identifier name(propertyName->identifier(&exec->globalData())); @@ -304,8 +291,7 @@ void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef prope JSValueRef JSObjectGetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSObject* jsObject = toJS(object); @@ -322,8 +308,7 @@ JSValueRef JSObjectGetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsi void JSObjectSetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef value, JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSObject* jsObject = toJS(object); JSValue jsValue = toJS(exec, value); @@ -339,8 +324,7 @@ void JSObjectSetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned p bool JSObjectDeleteProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSObject* jsObject = toJS(object); @@ -389,8 +373,7 @@ bool JSObjectIsFunction(JSContextRef, JSObjectRef object) JSValueRef JSObjectCallAsFunction(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSObject* jsObject = toJS(object); JSObject* jsThisObject = toJS(thisObject); @@ -427,8 +410,7 @@ bool JSObjectIsConstructor(JSContextRef, JSObjectRef object) JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSObject* jsObject = toJS(object); @@ -466,8 +448,7 @@ JSPropertyNameArrayRef JSObjectCopyPropertyNames(JSContextRef ctx, JSObjectRef o { JSObject* jsObject = toJS(object); ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSGlobalData* globalData = &exec->globalData(); @@ -492,7 +473,7 @@ JSPropertyNameArrayRef JSPropertyNameArrayRetain(JSPropertyNameArrayRef array) void JSPropertyNameArrayRelease(JSPropertyNameArrayRef array) { if (--array->refCount == 0) { - JSLock lock(array->globalData->isSharedInstance ? LockForReal : SilenceAssertionsOnly); + APIEntryShim entryShim(array->globalData, false); delete array; } } @@ -510,9 +491,6 @@ JSStringRef JSPropertyNameArrayGetNameAtIndex(JSPropertyNameArrayRef array, size void JSPropertyNameAccumulatorAddName(JSPropertyNameAccumulatorRef array, JSStringRef propertyName) { PropertyNameArray* propertyNames = toJS(array); - - propertyNames->globalData()->heap.registerThread(); - JSLock lock(propertyNames->globalData()->isSharedInstance ? LockForReal : SilenceAssertionsOnly); - + APIEntryShim entryShim(propertyNames->globalData()); propertyNames->add(propertyName->identifier(propertyNames->globalData())); } diff --git a/JavaScriptCore/API/JSValueRef.cpp b/JavaScriptCore/API/JSValueRef.cpp index 31859d6..a12cc34 100644 --- a/JavaScriptCore/API/JSValueRef.cpp +++ b/JavaScriptCore/API/JSValueRef.cpp @@ -28,6 +28,7 @@ #include <wtf/Platform.h> #include "APICast.h" +#include "APIShims.h" #include "JSCallbackObject.h" #include <runtime/JSGlobalObject.h> @@ -41,13 +42,14 @@ #include <algorithm> // for std::min -JSType JSValueGetType(JSContextRef ctx, JSValueRef value) +using namespace JSC; + +::JSType JSValueGetType(JSContextRef ctx, JSValueRef value) { - JSC::ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSC::JSLock lock(exec); + ExecState* exec = toJS(ctx); + APIEntryShim entryShim(exec); - JSC::JSValue jsValue = toJS(exec, value); + JSValue jsValue = toJS(exec, value); if (jsValue.isUndefined()) return kJSTypeUndefined; @@ -63,13 +65,10 @@ JSType JSValueGetType(JSContextRef ctx, JSValueRef value) return kJSTypeObject; } -using namespace JSC; // placed here to avoid conflict between JSC::JSType and JSType, above. - bool JSValueIsUndefined(JSContextRef ctx, JSValueRef value) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); return jsValue.isUndefined(); @@ -78,8 +77,7 @@ bool JSValueIsUndefined(JSContextRef ctx, JSValueRef value) bool JSValueIsNull(JSContextRef ctx, JSValueRef value) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); return jsValue.isNull(); @@ -88,8 +86,7 @@ bool JSValueIsNull(JSContextRef ctx, JSValueRef value) bool JSValueIsBoolean(JSContextRef ctx, JSValueRef value) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); return jsValue.isBoolean(); @@ -98,8 +95,7 @@ bool JSValueIsBoolean(JSContextRef ctx, JSValueRef value) bool JSValueIsNumber(JSContextRef ctx, JSValueRef value) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); return jsValue.isNumber(); @@ -108,8 +104,7 @@ bool JSValueIsNumber(JSContextRef ctx, JSValueRef value) bool JSValueIsString(JSContextRef ctx, JSValueRef value) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); return jsValue.isString(); @@ -118,8 +113,7 @@ bool JSValueIsString(JSContextRef ctx, JSValueRef value) bool JSValueIsObject(JSContextRef ctx, JSValueRef value) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); return jsValue.isObject(); @@ -128,8 +122,7 @@ bool JSValueIsObject(JSContextRef ctx, JSValueRef value) bool JSValueIsObjectOfClass(JSContextRef ctx, JSValueRef value, JSClassRef jsClass) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); @@ -145,8 +138,7 @@ bool JSValueIsObjectOfClass(JSContextRef ctx, JSValueRef value, JSClassRef jsCla bool JSValueIsEqual(JSContextRef ctx, JSValueRef a, JSValueRef b, JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsA = toJS(exec, a); JSValue jsB = toJS(exec, b); @@ -163,8 +155,7 @@ bool JSValueIsEqual(JSContextRef ctx, JSValueRef a, JSValueRef b, JSValueRef* ex bool JSValueIsStrictEqual(JSContextRef ctx, JSValueRef a, JSValueRef b) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsA = toJS(exec, a); JSValue jsB = toJS(exec, b); @@ -175,8 +166,7 @@ bool JSValueIsStrictEqual(JSContextRef ctx, JSValueRef a, JSValueRef b) bool JSValueIsInstanceOfConstructor(JSContextRef ctx, JSValueRef value, JSObjectRef constructor, JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); @@ -195,8 +185,7 @@ bool JSValueIsInstanceOfConstructor(JSContextRef ctx, JSValueRef value, JSObject JSValueRef JSValueMakeUndefined(JSContextRef ctx) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); return toRef(exec, jsUndefined()); } @@ -204,8 +193,7 @@ JSValueRef JSValueMakeUndefined(JSContextRef ctx) JSValueRef JSValueMakeNull(JSContextRef ctx) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); return toRef(exec, jsNull()); } @@ -213,8 +201,7 @@ JSValueRef JSValueMakeNull(JSContextRef ctx) JSValueRef JSValueMakeBoolean(JSContextRef ctx, bool value) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); return toRef(exec, jsBoolean(value)); } @@ -222,8 +209,7 @@ JSValueRef JSValueMakeBoolean(JSContextRef ctx, bool value) JSValueRef JSValueMakeNumber(JSContextRef ctx, double value) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); return toRef(exec, jsNumber(exec, value)); } @@ -231,8 +217,7 @@ JSValueRef JSValueMakeNumber(JSContextRef ctx, double value) JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); return toRef(exec, jsString(exec, string->ustring())); } @@ -240,8 +225,7 @@ JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string) bool JSValueToBoolean(JSContextRef ctx, JSValueRef value) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); return jsValue.toBoolean(exec); @@ -250,8 +234,7 @@ bool JSValueToBoolean(JSContextRef ctx, JSValueRef value) double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); @@ -268,8 +251,7 @@ double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); @@ -286,8 +268,7 @@ JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef* JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); @@ -304,8 +285,7 @@ JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exce void JSValueProtect(JSContextRef ctx, JSValueRef value) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJSForGC(exec, value); gcProtect(jsValue); @@ -314,8 +294,7 @@ void JSValueProtect(JSContextRef ctx, JSValueRef value) void JSValueUnprotect(JSContextRef ctx, JSValueRef value) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJSForGC(exec, value); gcUnprotect(jsValue); diff --git a/JavaScriptCore/API/OpaqueJSString.cpp b/JavaScriptCore/API/OpaqueJSString.cpp index 7c7b1af..f740abe 100644 --- a/JavaScriptCore/API/OpaqueJSString.cpp +++ b/JavaScriptCore/API/OpaqueJSString.cpp @@ -42,7 +42,7 @@ PassRefPtr<OpaqueJSString> OpaqueJSString::create(const UString& ustring) UString OpaqueJSString::ustring() const { if (this && m_characters) - return UString(m_characters, m_length, true); + return UString(m_characters, m_length); return UString::null(); } diff --git a/JavaScriptCore/API/tests/testapi.c b/JavaScriptCore/API/tests/testapi.c index e7aba0f..ebc0cfb 100644 --- a/JavaScriptCore/API/tests/testapi.c +++ b/JavaScriptCore/API/tests/testapi.c @@ -623,6 +623,17 @@ static JSClassRef Derived_class(JSContextRef context) return jsClass; } +static JSClassRef Derived2_class(JSContextRef context) +{ + static JSClassRef jsClass; + if (!jsClass) { + JSClassDefinition definition = kJSClassDefinitionEmpty; + definition.parentClass = Derived_class(context); + jsClass = JSClassCreate(&definition); + } + return jsClass; +} + static JSValueRef print_callAsFunction(JSContextRef ctx, JSObjectRef functionObject, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { UNUSED_PARAM(functionObject); @@ -1070,11 +1081,21 @@ int main(int argc, char* argv[]) ASSERT(!JSObjectSetPrivate(myConstructor, (void*)1)); ASSERT(!JSObjectGetPrivate(myConstructor)); + string = JSStringCreateWithUTF8CString("Base"); + JSObjectRef baseConstructor = JSObjectMakeConstructor(context, Base_class(context), NULL); + JSObjectSetProperty(context, globalObject, string, baseConstructor, kJSPropertyAttributeNone, NULL); + JSStringRelease(string); + string = JSStringCreateWithUTF8CString("Derived"); JSObjectRef derivedConstructor = JSObjectMakeConstructor(context, Derived_class(context), NULL); JSObjectSetProperty(context, globalObject, string, derivedConstructor, kJSPropertyAttributeNone, NULL); JSStringRelease(string); + string = JSStringCreateWithUTF8CString("Derived2"); + JSObjectRef derived2Constructor = JSObjectMakeConstructor(context, Derived2_class(context), NULL); + JSObjectSetProperty(context, globalObject, string, derived2Constructor, kJSPropertyAttributeNone, NULL); + JSStringRelease(string); + o = JSObjectMake(context, NULL, NULL); JSObjectSetProperty(context, o, jsOneIString, JSValueMakeNumber(context, 1), kJSPropertyAttributeNone, NULL); JSObjectSetProperty(context, o, jsCFIString, JSValueMakeNumber(context, 1), kJSPropertyAttributeDontEnum, NULL); @@ -1173,7 +1194,7 @@ int main(int argc, char* argv[]) } else { script = JSStringCreateWithUTF8CString(scriptUTF8); result = JSEvaluateScript(context, script, NULL, NULL, 1, &exception); - if (JSValueIsUndefined(context, result)) + if (result && JSValueIsUndefined(context, result)) printf("PASS: Test script executed successfully.\n"); else { printf("FAIL: Test script returned unexpected value:\n"); diff --git a/JavaScriptCore/API/tests/testapi.js b/JavaScriptCore/API/tests/testapi.js index 82756b5..15c9e50 100644 --- a/JavaScriptCore/API/tests/testapi.js +++ b/JavaScriptCore/API/tests/testapi.js @@ -113,6 +113,35 @@ if (foundRegularType) else fail("MyObject.regularType was not enumerated"); +var alwaysOneDescriptor = Object.getOwnPropertyDescriptor(MyObject, "alwaysOne"); +shouldBe('typeof alwaysOneDescriptor', "object"); +shouldBe('alwaysOneDescriptor.value', MyObject.alwaysOne); +shouldBe('alwaysOneDescriptor.configurable', true); +shouldBe('alwaysOneDescriptor.enumerable', false); // Actually it is. +var cantFindDescriptor = Object.getOwnPropertyDescriptor(MyObject, "cantFind"); +shouldBe('typeof cantFindDescriptor', "object"); +shouldBe('cantFindDescriptor.value', MyObject.cantFind); +shouldBe('cantFindDescriptor.configurable', true); +shouldBe('cantFindDescriptor.enumerable', false); +try { + // If getOwnPropertyDescriptor() returned an access descriptor, this wouldn't throw. + Object.getOwnPropertyDescriptor(MyObject, "throwOnGet"); +} catch (e) { + pass("getting property descriptor of throwOnGet threw exception"); +} +var myPropertyNameDescriptor = Object.getOwnPropertyDescriptor(MyObject, "myPropertyName"); +shouldBe('typeof myPropertyNameDescriptor', "object"); +shouldBe('myPropertyNameDescriptor.value', MyObject.myPropertyName); +shouldBe('myPropertyNameDescriptor.configurable', true); +shouldBe('myPropertyNameDescriptor.enumerable', false); // Actually it is. +try { + // if getOwnPropertyDescriptor() returned an access descriptor, this wouldn't throw. + Object.getOwnPropertyDescriptor(MyObject, "hasPropertyLie"); +} catch (e) { + pass("getting property descriptor of hasPropertyLie threw exception"); +} +shouldBe('Object.getOwnPropertyDescriptor(MyObject, "doesNotExist")', undefined); + myObject = new MyObject(); shouldBe("delete MyObject.regularType", true); @@ -140,6 +169,9 @@ shouldThrow("MyObject.hasPropertyLie"); derived = new Derived(); +shouldBe("derived instanceof Derived", true); +shouldBe("derived instanceof Base", true); + // base properties and functions return 1 when called/gotten; derived, 2 shouldBe("derived.baseProtoDup()", 2); shouldBe("derived.baseProto()", 1); @@ -155,6 +187,51 @@ shouldBe("derived.baseOnly = 0", 1); shouldBe("derived.derivedOnly = 0", 2) shouldBe("derived.protoDup = 0", 2); +derived2 = new Derived2(); + +shouldBe("derived2 instanceof Derived2", true); +shouldBe("derived2 instanceof Derived", true); +shouldBe("derived2 instanceof Base", true); + +// base properties and functions return 1 when called/gotten; derived, 2 +shouldBe("derived2.baseProtoDup()", 2); +shouldBe("derived2.baseProto()", 1); +shouldBe("derived2.baseDup", 2); +shouldBe("derived2.baseOnly", 1); +shouldBe("derived2.protoOnly()", 2); +shouldBe("derived2.protoDup", 2); +shouldBe("derived2.derivedOnly", 2) + +// base properties throw 1 when set; derived, 2 +shouldBe("derived2.baseDup = 0", 2); +shouldBe("derived2.baseOnly = 0", 1); +shouldBe("derived2.derivedOnly = 0", 2) +shouldBe("derived2.protoDup = 0", 2); + +shouldBe('Object.getOwnPropertyDescriptor(derived, "baseProto")', undefined); +shouldBe('Object.getOwnPropertyDescriptor(derived, "baseProtoDup")', undefined); +var baseDupDescriptor = Object.getOwnPropertyDescriptor(derived, "baseDup"); +shouldBe('typeof baseDupDescriptor', "object"); +shouldBe('baseDupDescriptor.value', derived.baseDup); +shouldBe('baseDupDescriptor.configurable', true); +shouldBe('baseDupDescriptor.enumerable', false); +var baseOnlyDescriptor = Object.getOwnPropertyDescriptor(derived, "baseOnly"); +shouldBe('typeof baseOnlyDescriptor', "object"); +shouldBe('baseOnlyDescriptor.value', derived.baseOnly); +shouldBe('baseOnlyDescriptor.configurable', true); +shouldBe('baseOnlyDescriptor.enumerable', false); +shouldBe('Object.getOwnPropertyDescriptor(derived, "protoOnly")', undefined); +var protoDupDescriptor = Object.getOwnPropertyDescriptor(derived, "protoDup"); +shouldBe('typeof protoDupDescriptor', "object"); +shouldBe('protoDupDescriptor.value', derived.protoDup); +shouldBe('protoDupDescriptor.configurable', true); +shouldBe('protoDupDescriptor.enumerable', false); +var derivedOnlyDescriptor = Object.getOwnPropertyDescriptor(derived, "derivedOnly"); +shouldBe('typeof derivedOnlyDescriptor', "object"); +shouldBe('derivedOnlyDescriptor.value', derived.derivedOnly); +shouldBe('derivedOnlyDescriptor.configurable', true); +shouldBe('derivedOnlyDescriptor.enumerable', false); + shouldBe("undefined instanceof MyObject", false); EvilExceptionObject.hasInstance = function f() { return f(); }; EvilExceptionObject.__proto__ = undefined; |