diff options
Diffstat (limited to 'Source/JavaScriptCore/API')
-rw-r--r-- | Source/JavaScriptCore/API/APICast.h | 2 | ||||
-rw-r--r-- | Source/JavaScriptCore/API/JSBase.cpp | 8 | ||||
-rw-r--r-- | Source/JavaScriptCore/API/JSCallbackConstructor.cpp | 7 | ||||
-rw-r--r-- | Source/JavaScriptCore/API/JSCallbackFunction.cpp | 38 | ||||
-rw-r--r-- | Source/JavaScriptCore/API/JSCallbackFunction.h | 3 | ||||
-rw-r--r-- | Source/JavaScriptCore/API/JSCallbackObject.cpp | 3 | ||||
-rw-r--r-- | Source/JavaScriptCore/API/JSCallbackObject.h | 4 | ||||
-rw-r--r-- | Source/JavaScriptCore/API/JSCallbackObjectFunctions.h | 45 | ||||
-rw-r--r-- | Source/JavaScriptCore/API/JSClassRef.cpp | 15 | ||||
-rw-r--r-- | Source/JavaScriptCore/API/JSContextRef.cpp | 55 | ||||
-rw-r--r-- | Source/JavaScriptCore/API/JSObjectRef.cpp | 20 | ||||
-rw-r--r-- | Source/JavaScriptCore/API/JSValueRef.cpp | 4 | ||||
-rw-r--r-- | Source/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp | 2 | ||||
-rw-r--r-- | Source/JavaScriptCore/API/tests/testapi.c | 96 | ||||
-rw-r--r-- | Source/JavaScriptCore/API/tests/testapi.js | 6 |
15 files changed, 173 insertions, 135 deletions
diff --git a/Source/JavaScriptCore/API/APICast.h b/Source/JavaScriptCore/API/APICast.h index 4294d3d68..f019a7a4b 100644 --- a/Source/JavaScriptCore/API/APICast.h +++ b/Source/JavaScriptCore/API/APICast.h @@ -69,7 +69,7 @@ inline JSC::JSValue toJS(JSC::ExecState* exec, JSValueRef v) if (!jsCell) return JSC::JSValue(); if (jsCell->isAPIValueWrapper()) - return static_cast<JSC::JSAPIValueWrapper*>(jsCell)->value(); + return JSC::jsCast<JSC::JSAPIValueWrapper*>(jsCell)->value(); return jsCell; #else return JSC::JSValue::decode(reinterpret_cast<JSC::EncodedJSValue>(const_cast<OpaqueJSValue*>(v))); diff --git a/Source/JavaScriptCore/API/JSBase.cpp b/Source/JavaScriptCore/API/JSBase.cpp index eafd8c60b..d0ffa3114 100644 --- a/Source/JavaScriptCore/API/JSBase.cpp +++ b/Source/JavaScriptCore/API/JSBase.cpp @@ -100,13 +100,7 @@ void JSGarbageCollect(JSContextRef ctx) ExecState* exec = toJS(ctx); APIEntryShim entryShim(exec, false); - JSGlobalData& globalData = exec->globalData(); - if (!globalData.heap.isBusy()) - globalData.heap.collectAllGarbage(); - - // FIXME: Perhaps we should trigger a second mark and sweep - // once the garbage collector is done if this is called when - // the collector is busy. + exec->globalData().heap.reportAbandonedObjectGraph(); } void JSReportExtraMemoryCost(JSContextRef ctx, size_t size) diff --git a/Source/JavaScriptCore/API/JSCallbackConstructor.cpp b/Source/JavaScriptCore/API/JSCallbackConstructor.cpp index 1349e4f3f..c8b4c0659 100644 --- a/Source/JavaScriptCore/API/JSCallbackConstructor.cpp +++ b/Source/JavaScriptCore/API/JSCallbackConstructor.cpp @@ -70,7 +70,7 @@ static EncodedJSValue JSC_HOST_CALL constructJSCallback(ExecState* exec) JSContextRef ctx = toRef(exec); JSObjectRef constructorRef = toRef(constructor); - JSObjectCallAsConstructorCallback callback = static_cast<JSCallbackConstructor*>(constructor)->callback(); + JSObjectCallAsConstructorCallback callback = jsCast<JSCallbackConstructor*>(constructor)->callback(); if (callback) { int argumentCount = static_cast<int>(exec->argumentCount()); Vector<JSValueRef, 16> arguments(argumentCount); @@ -85,10 +85,13 @@ static EncodedJSValue JSC_HOST_CALL constructJSCallback(ExecState* exec) } if (exception) throwError(exec, toJS(exec, exception)); + // result must be a valid JSValue. + if (!result) + return throwVMTypeError(exec); return JSValue::encode(toJS(result)); } - return JSValue::encode(toJS(JSObjectMake(ctx, static_cast<JSCallbackConstructor*>(constructor)->classRef(), 0))); + return JSValue::encode(toJS(JSObjectMake(ctx, jsCast<JSCallbackConstructor*>(constructor)->classRef(), 0))); } ConstructType JSCallbackConstructor::getConstructData(JSCell*, ConstructData& constructData) diff --git a/Source/JavaScriptCore/API/JSCallbackFunction.cpp b/Source/JavaScriptCore/API/JSCallbackFunction.cpp index 3fbc00470..d287ab778 100644 --- a/Source/JavaScriptCore/API/JSCallbackFunction.cpp +++ b/Source/JavaScriptCore/API/JSCallbackFunction.cpp @@ -30,7 +30,6 @@ #include "APICast.h" #include "CodeBlock.h" #include "ExceptionHelpers.h" -#include "JSCallbackObject.h" #include "JSFunction.h" #include "FunctionPrototype.h" #include <runtime/JSGlobalObject.h> @@ -71,11 +70,15 @@ EncodedJSValue JSCallbackFunction::call(ExecState* exec) JSValueRef result; { APICallbackShim callbackShim(exec); - result = static_cast<JSCallbackFunction*>(toJS(functionRef))->m_callback(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), &exception); + result = jsCast<JSCallbackFunction*>(toJS(functionRef))->m_callback(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), &exception); } if (exception) throwError(exec, toJS(exec, exception)); + // result must be a valid JSValue. + if (!result) + return JSValue::encode(jsUndefined()); + return JSValue::encode(toJS(exec, result)); } @@ -85,35 +88,4 @@ CallType JSCallbackFunction::getCallData(JSCell*, CallData& callData) return CallTypeHost; } -JSValueRef JSCallbackFunction::toStringCallback(JSContextRef ctx, JSObjectRef, JSObjectRef thisObject, size_t, const JSValueRef[], JSValueRef* exception) -{ - JSObject* object = toJS(thisObject); - if (object->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) { - for (JSClassRef jsClass = jsCast<JSCallbackObject<JSNonFinalObject>*>(object)->classRef(); jsClass; jsClass = jsClass->parentClass) - if (jsClass->convertToType) - return jsClass->convertToType(ctx, thisObject, kJSTypeString, exception); - } else if (object->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) { - for (JSClassRef jsClass = jsCast<JSCallbackObject<JSGlobalObject>*>(object)->classRef(); jsClass; jsClass = jsClass->parentClass) - if (jsClass->convertToType) - return jsClass->convertToType(ctx, thisObject, kJSTypeString, exception); - } - return 0; -} - -JSValueRef JSCallbackFunction::valueOfCallback(JSContextRef ctx, JSObjectRef, JSObjectRef thisObject, size_t, const JSValueRef[], JSValueRef* exception) -{ - JSObject* object = toJS(thisObject); - if (object->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) { - for (JSClassRef jsClass = jsCast<JSCallbackObject<JSNonFinalObject>*>(object)->classRef(); jsClass; jsClass = jsClass->parentClass) - if (jsClass->convertToType) - return jsClass->convertToType(ctx, thisObject, kJSTypeNumber, exception); - } else if (object->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) { - for (JSClassRef jsClass = jsCast<JSCallbackObject<JSGlobalObject>*>(object)->classRef(); jsClass; jsClass = jsClass->parentClass) - if (jsClass->convertToType) - return jsClass->convertToType(ctx, thisObject, kJSTypeNumber, exception); - } - return 0; -} - - } // namespace JSC diff --git a/Source/JavaScriptCore/API/JSCallbackFunction.h b/Source/JavaScriptCore/API/JSCallbackFunction.h index b61d45c86..fec4136f8 100644 --- a/Source/JavaScriptCore/API/JSCallbackFunction.h +++ b/Source/JavaScriptCore/API/JSCallbackFunction.h @@ -55,9 +55,6 @@ public: return Structure::create(globalData, globalObject, proto, TypeInfo(ObjectType, StructureFlags), &s_info); } - static JSValueRef toStringCallback(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception); - static JSValueRef valueOfCallback(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception); - private: static CallType getCallData(JSCell*, CallData&); diff --git a/Source/JavaScriptCore/API/JSCallbackObject.cpp b/Source/JavaScriptCore/API/JSCallbackObject.cpp index ef9cb925c..68c26824d 100644 --- a/Source/JavaScriptCore/API/JSCallbackObject.cpp +++ b/Source/JavaScriptCore/API/JSCallbackObject.cpp @@ -65,8 +65,7 @@ void JSCallbackObjectData::finalize(Handle<Unknown> handle, void* context) for (; jsClass; jsClass = jsClass->parentClass) if (JSObjectFinalizeCallback finalize = jsClass->finalize) finalize(thisRef); - HandleSlot slot = handle.slot(); - HandleHeap::heapFor(slot)->deallocate(slot); + WeakSet::deallocate(WeakImpl::asWeakImpl(handle.slot())); } } // namespace JSC diff --git a/Source/JavaScriptCore/API/JSCallbackObject.h b/Source/JavaScriptCore/API/JSCallbackObject.h index 8f907167e..9aca0c7e1 100644 --- a/Source/JavaScriptCore/API/JSCallbackObject.h +++ b/Source/JavaScriptCore/API/JSCallbackObject.h @@ -89,7 +89,7 @@ struct JSCallbackObjectData : WeakHandleOwner { void setPrivateProperty(JSGlobalData& globalData, JSCell* owner, const Identifier& propertyName, JSValue value) { WriteBarrier<Unknown> empty; - m_propertyMap.add(propertyName.impl(), empty).first->second.set(globalData, owner, value); + m_propertyMap.add(propertyName.impl(), empty).iterator->second.set(globalData, owner, value); } void deletePrivateProperty(const Identifier& propertyName) @@ -175,6 +175,8 @@ private: static void destroy(JSCell*); + static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType); + static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&); static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); diff --git a/Source/JavaScriptCore/API/JSCallbackObjectFunctions.h b/Source/JavaScriptCore/API/JSCallbackObjectFunctions.h index cab5883da..b909dde71 100644 --- a/Source/JavaScriptCore/API/JSCallbackObjectFunctions.h +++ b/Source/JavaScriptCore/API/JSCallbackObjectFunctions.h @@ -46,7 +46,7 @@ template <class Parent> inline JSCallbackObject<Parent>* JSCallbackObject<Parent>::asCallbackObject(JSValue value) { ASSERT(asObject(value)->inherits(&s_info)); - return static_cast<JSCallbackObject*>(asObject(value)); + return jsCast<JSCallbackObject*>(asObject(value)); } template <class Parent> @@ -80,7 +80,7 @@ void JSCallbackObject<Parent>::finishCreation(JSGlobalData& globalData) ASSERT(Parent::inherits(&s_info)); ASSERT(Parent::isGlobalObject()); Base::finishCreation(globalData); - init(static_cast<JSGlobalObject*>(this)->globalExec()); + init(jsCast<JSGlobalObject*>(this)->globalExec()); } template <class Parent> @@ -102,14 +102,11 @@ void JSCallbackObject<Parent>::init(ExecState* exec) initialize(toRef(exec), toRef(this)); } - bool needsFinalizer = false; - for (JSClassRef jsClassPtr = classRef(); jsClassPtr && !needsFinalizer; jsClassPtr = jsClassPtr->parentClass) - needsFinalizer = jsClassPtr->finalize; - if (needsFinalizer) { - HandleSlot slot = exec->globalData().heap.handleHeap()->allocate(); - HandleHeap::heapFor(slot)->makeWeak(slot, m_callbackObjectData.get(), classRef()); - HandleHeap::heapFor(slot)->writeBarrier(slot, this); - *slot = this; + for (JSClassRef jsClassPtr = classRef(); jsClassPtr; jsClassPtr = jsClassPtr->parentClass) { + if (jsClassPtr->finalize) { + WeakSet::allocate(this, m_callbackObjectData.get(), classRef()); + break; + } } } @@ -184,6 +181,30 @@ bool JSCallbackObject<Parent>::getOwnPropertySlot(JSCell* cell, ExecState* exec, } template <class Parent> +JSValue JSCallbackObject<Parent>::defaultValue(const JSObject* object, ExecState* exec, PreferredPrimitiveType hint) +{ + const JSCallbackObject* thisObject = jsCast<const JSCallbackObject*>(object); + JSContextRef ctx = toRef(exec); + JSObjectRef thisRef = toRef(thisObject); + ::JSType jsHint = hint == PreferString ? kJSTypeString : kJSTypeNumber; + + for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) { + if (JSObjectConvertToTypeCallback convertToType = jsClass->convertToType) { + JSValueRef exception = 0; + JSValueRef result = convertToType(ctx, thisRef, jsHint, &exception); + if (exception) { + throwError(exec, toJS(exec, exception)); + return jsUndefined(); + } + if (result) + return toJS(exec, result); + } + } + + return Parent::defaultValue(object, exec, hint); +} + +template <class Parent> bool JSCallbackObject<Parent>::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { JSCallbackObject* thisObject = jsCast<JSCallbackObject*>(object); @@ -333,7 +354,7 @@ EncodedJSValue JSCallbackObject<Parent>::construct(ExecState* exec) JSContextRef execRef = toRef(exec); JSObjectRef constructorRef = toRef(constructor); - for (JSClassRef jsClass = static_cast<JSCallbackObject<Parent>*>(constructor)->classRef(); jsClass; jsClass = jsClass->parentClass) { + for (JSClassRef jsClass = jsCast<JSCallbackObject<Parent>*>(constructor)->classRef(); jsClass; jsClass = jsClass->parentClass) { if (JSObjectCallAsConstructorCallback callAsConstructor = jsClass->callAsConstructor) { int argumentCount = static_cast<int>(exec->argumentCount()); Vector<JSValueRef, 16> arguments(argumentCount); @@ -399,7 +420,7 @@ EncodedJSValue JSCallbackObject<Parent>::call(ExecState* exec) JSObjectRef functionRef = toRef(exec->callee()); JSObjectRef thisObjRef = toRef(exec->hostThisValue().toThisObject(exec)); - for (JSClassRef jsClass = static_cast<JSCallbackObject<Parent>*>(toJS(functionRef))->classRef(); jsClass; jsClass = jsClass->parentClass) { + for (JSClassRef jsClass = jsCast<JSCallbackObject<Parent>*>(toJS(functionRef))->classRef(); jsClass; jsClass = jsClass->parentClass) { if (JSObjectCallAsFunctionCallback callAsFunction = jsClass->callAsFunction) { int argumentCount = static_cast<int>(exec->argumentCount()); Vector<JSValueRef, 16> arguments(argumentCount); diff --git a/Source/JavaScriptCore/API/JSClassRef.cpp b/Source/JavaScriptCore/API/JSClassRef.cpp index 298c734ea..08fa5c5e0 100644 --- a/Source/JavaScriptCore/API/JSClassRef.cpp +++ b/Source/JavaScriptCore/API/JSClassRef.cpp @@ -164,7 +164,7 @@ OpaqueJSClassContextData::OpaqueJSClassContextData(JSC::JSGlobalData&, OpaqueJSC OpaqueJSClassContextData& OpaqueJSClass::contextData(ExecState* exec) { - OwnPtr<OpaqueJSClassContextData>& contextData = exec->globalData().opaqueJSClassData.add(this, nullptr).first->second; + OwnPtr<OpaqueJSClassContextData>& contextData = exec->globalData().opaqueJSClassData.add(this, nullptr).iterator->second; if (!contextData) contextData = adoptPtr(new OpaqueJSClassContextData(exec->globalData(), this)); return *contextData; @@ -204,17 +204,6 @@ JSObject* OpaqueJSClass::prototype(ExecState* exec) * DerivedClass | DerivedClassPrototype */ - if (convertToType) { - if (!prototypeClass) - prototypeClass = OpaqueJSClass::create(&kJSClassDefinitionEmpty).leakRef(); - if (!prototypeClass->m_staticFunctions) - prototypeClass->m_staticFunctions = adoptPtr(new OpaqueJSClassStaticFunctionsTable); - const Identifier& toString = exec->propertyNames().toString; - const Identifier& valueOf = exec->propertyNames().valueOf; - prototypeClass->m_staticFunctions->add(StringImpl::create(toString.characters(), toString.length()), adoptPtr(new StaticFunctionEntry(&JSCallbackFunction::toStringCallback, 0))); - prototypeClass->m_staticFunctions->add(StringImpl::create(valueOf.characters(), valueOf.length()), adoptPtr(new StaticFunctionEntry(&JSCallbackFunction::valueOfCallback, 0))); - } - if (!prototypeClass) return 0; @@ -222,7 +211,7 @@ JSObject* OpaqueJSClass::prototype(ExecState* exec) if (!jsClassData.cachedPrototype) { // Recursive, but should be good enough for our purposes - jsClassData.cachedPrototype = PassWeak<JSObject>(exec->globalData(), JSCallbackObject<JSNonFinalObject>::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), prototypeClass, &jsClassData), 0); // set jsClassData as the object's private data, so it can clear our reference on destruction + jsClassData.cachedPrototype = PassWeak<JSObject>(JSCallbackObject<JSNonFinalObject>::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), prototypeClass, &jsClassData), 0); // set jsClassData as the object's private data, so it can clear our reference on destruction if (parentClass) { if (JSObject* prototype = parentClass->prototype(exec)) jsClassData.cachedPrototype->setPrototype(exec->globalData(), prototype); diff --git a/Source/JavaScriptCore/API/JSContextRef.cpp b/Source/JavaScriptCore/API/JSContextRef.cpp index 71cb1ab74..746febfbb 100644 --- a/Source/JavaScriptCore/API/JSContextRef.cpp +++ b/Source/JavaScriptCore/API/JSContextRef.cpp @@ -38,15 +38,13 @@ #include "UStringBuilder.h" #include <wtf/text/StringHash.h> - -#if OS(DARWIN) -#include <mach-o/dyld.h> - -static const int32_t webkitFirstVersionWithConcurrentGlobalContexts = 0x2100500; // 528.5.0 -#endif - using namespace JSC; +// From the API's perspective, a context group remains alive iff +// (a) it has been JSContextGroupRetained +// OR +// (b) one of its contexts has been JSContextRetained + JSContextGroupRef JSContextGroupCreate() { initializeThreading(); @@ -64,22 +62,11 @@ void JSContextGroupRelease(JSContextGroupRef group) toJS(group)->deref(); } +// From the API's perspective, a global context remains alive iff it has been JSGlobalContextRetained. + JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass) { initializeThreading(); -#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. -#ifndef BUILDING_ON_LEOPARD - if (NSVersionOfLinkTimeLibrary("JavaScriptCore") <= webkitFirstVersionWithConcurrentGlobalContexts) { -#else - { -#endif - JSLock lock(LockForReal); - return JSGlobalContextCreateInGroup(toRef(&JSGlobalData::sharedInstance()), globalObjectClass); - } -#endif // OS(DARWIN) - return JSGlobalContextCreateInGroup(0, globalObjectClass); } @@ -125,33 +112,13 @@ void JSGlobalContextRelease(JSGlobalContextRef ctx) JSLock lock(exec); JSGlobalData& globalData = exec->globalData(); - JSGlobalObject* dgo = exec->dynamicGlobalObject(); IdentifierTable* savedIdentifierTable = wtfThreadData().setCurrentIdentifierTable(globalData.identifierTable); - // One reference is held by JSGlobalObject, another added by JSGlobalContextRetain(). - bool releasingContextGroup = globalData.refCount() == 2; - bool releasingGlobalObject = Heap::heap(dgo)->unprotect(dgo); - // If this is the last reference to a global data, it should also - // be the only remaining reference to the global object too! - ASSERT(!releasingContextGroup || releasingGlobalObject); - - // An API 'JSGlobalContextRef' retains two things - a global object and a - // global data (or context group, in API terminology). - // * If this is the last reference to any contexts in the given context group, - // call destroy on the heap (the global data is being freed). - // * If this was the last reference to the global object, then unprotecting - // it may release a lot of GC memory - tickle the activity callback to - // garbage collect soon. - // * If there are more references remaining the the global object, then do nothing - // (specifically that is more protects, which we assume come from other JSGlobalContextRefs). - if (releasingContextGroup) { - globalData.clearBuiltinStructures(); - globalData.heap.destroy(); - } else if (releasingGlobalObject) { + bool protectCountIsZero = Heap::heap(exec->dynamicGlobalObject())->unprotect(exec->dynamicGlobalObject()); + if (protectCountIsZero) { globalData.heap.activityCallback()->synchronize(); - (*globalData.heap.activityCallback())(); + globalData.heap.reportAbandonedObjectGraph(); } - globalData.deref(); wtfThreadData().setCurrentIdentifierTable(savedIdentifierTable); @@ -210,7 +177,7 @@ JSStringRef JSContextCreateBacktrace(JSContextRef ctx, unsigned maxStackSize) exec->interpreter()->retrieveLastCaller(callFrame, signedLineNumber, sourceID, urlString, function); if (function) - functionName = asFunction(function)->name(exec); + functionName = jsCast<JSFunction*>(function)->name(exec); else { // Caller is unknown, but if frame is empty we should still add the frame, because // something called us, and gave us arguments. diff --git a/Source/JavaScriptCore/API/JSObjectRef.cpp b/Source/JavaScriptCore/API/JSObjectRef.cpp index 17329ad87..e01214d5e 100644 --- a/Source/JavaScriptCore/API/JSObjectRef.cpp +++ b/Source/JavaScriptCore/API/JSObjectRef.cpp @@ -341,9 +341,9 @@ void* JSObjectGetPrivate(JSObjectRef object) JSObject* jsObject = toJS(object); if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) - return static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivate(); + return jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivate(); if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) - return static_cast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->getPrivate(); + return jsCast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->getPrivate(); return 0; } @@ -353,11 +353,11 @@ bool JSObjectSetPrivate(JSObjectRef object, void* data) JSObject* jsObject = toJS(object); if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) { - static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivate(data); + jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivate(data); return true; } if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) { - static_cast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->setPrivate(data); + jsCast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->setPrivate(data); return true; } @@ -372,9 +372,9 @@ JSValueRef JSObjectGetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSSt JSValue result; Identifier name(propertyName->identifier(&exec->globalData())); if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) - result = static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivateProperty(name); + result = jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivateProperty(name); else if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) - result = static_cast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->getPrivateProperty(name); + result = jsCast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->getPrivateProperty(name); return toRef(exec, result); } @@ -386,11 +386,11 @@ bool JSObjectSetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRe JSValue jsValue = value ? toJS(exec, value) : JSValue(); Identifier name(propertyName->identifier(&exec->globalData())); if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) { - static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivateProperty(exec->globalData(), name, jsValue); + jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivateProperty(exec->globalData(), name, jsValue); return true; } if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) { - static_cast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->setPrivateProperty(exec->globalData(), name, jsValue); + jsCast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->setPrivateProperty(exec->globalData(), name, jsValue); return true; } return false; @@ -403,11 +403,11 @@ bool JSObjectDeletePrivateProperty(JSContextRef ctx, JSObjectRef object, JSStrin JSObject* jsObject = toJS(object); Identifier name(propertyName->identifier(&exec->globalData())); if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) { - static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->deletePrivateProperty(name); + jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->deletePrivateProperty(name); return true; } if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) { - static_cast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->deletePrivateProperty(name); + jsCast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->deletePrivateProperty(name); return true; } return false; diff --git a/Source/JavaScriptCore/API/JSValueRef.cpp b/Source/JavaScriptCore/API/JSValueRef.cpp index 1b4e03bde..9b7268a2d 100644 --- a/Source/JavaScriptCore/API/JSValueRef.cpp +++ b/Source/JavaScriptCore/API/JSValueRef.cpp @@ -130,9 +130,9 @@ bool JSValueIsObjectOfClass(JSContextRef ctx, JSValueRef value, JSClassRef jsCla if (JSObject* o = jsValue.getObject()) { if (o->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) - return static_cast<JSCallbackObject<JSGlobalObject>*>(o)->inherits(jsClass); + return jsCast<JSCallbackObject<JSGlobalObject>*>(o)->inherits(jsClass); if (o->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) - return static_cast<JSCallbackObject<JSNonFinalObject>*>(o)->inherits(jsClass); + return jsCast<JSCallbackObject<JSNonFinalObject>*>(o)->inherits(jsClass); } return false; } diff --git a/Source/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp b/Source/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp index 4292a60bd..bdd56f602 100644 --- a/Source/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp +++ b/Source/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp @@ -65,7 +65,7 @@ JSObjectRef JSWeakObjectMapGet(JSContextRef ctx, JSWeakObjectMapRef map, void* k { ExecState* exec = toJS(ctx); APIEntryShim entryShim(exec); - return toRef(static_cast<JSObject*>(map->map().get(key))); + return toRef(jsCast<JSObject*>(map->map().get(key))); } void JSWeakObjectMapRemove(JSContextRef ctx, JSWeakObjectMapRef map, void* key) diff --git a/Source/JavaScriptCore/API/tests/testapi.c b/Source/JavaScriptCore/API/tests/testapi.c index efcfc0d12..91978bbfd 100644 --- a/Source/JavaScriptCore/API/tests/testapi.c +++ b/Source/JavaScriptCore/API/tests/testapi.c @@ -311,6 +311,16 @@ static JSValueRef MyObject_convertToType(JSContextRef context, JSObjectRef objec return JSValueMakeNull(context); } +static JSValueRef MyObject_convertToTypeWrapper(JSContextRef context, JSObjectRef object, JSType type, JSValueRef* exception) +{ + UNUSED_PARAM(context); + UNUSED_PARAM(object); + UNUSED_PARAM(type); + UNUSED_PARAM(exception); + // Forward to default object class + return 0; +} + static bool MyObject_set_nullGetForwardSet(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception) { UNUSED_PARAM(ctx); @@ -355,14 +365,65 @@ JSClassDefinition MyObject_definition = { MyObject_convertToType, }; +JSClassDefinition MyObject_convertToTypeWrapperDefinition = { + 0, + kJSClassAttributeNone, + + "MyObject", + NULL, + + NULL, + NULL, + + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + MyObject_convertToTypeWrapper, +}; + +JSClassDefinition MyObject_nullWrapperDefinition = { + 0, + kJSClassAttributeNone, + + "MyObject", + NULL, + + NULL, + NULL, + + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + static JSClassRef MyObject_class(JSContextRef context) { UNUSED_PARAM(context); static JSClassRef jsClass; - if (!jsClass) - jsClass = JSClassCreate(&MyObject_definition); - + if (!jsClass) { + JSClassRef baseClass = JSClassCreate(&MyObject_definition); + MyObject_convertToTypeWrapperDefinition.parentClass = baseClass; + JSClassRef wrapperClass = JSClassCreate(&MyObject_convertToTypeWrapperDefinition); + MyObject_nullWrapperDefinition.parentClass = wrapperClass; + jsClass = JSClassCreate(&MyObject_nullWrapperDefinition); + } + return jsClass; } @@ -617,9 +678,22 @@ static JSValueRef Base_callAsFunction(JSContextRef ctx, JSObjectRef function, JS return JSValueMakeNumber(ctx, 1); // distinguish base call from derived call } +static JSValueRef Base_returnHardNull(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + UNUSED_PARAM(ctx); + UNUSED_PARAM(function); + UNUSED_PARAM(thisObject); + UNUSED_PARAM(argumentCount); + UNUSED_PARAM(arguments); + UNUSED_PARAM(exception); + + return 0; // should convert to undefined! +} + static JSStaticFunction Base_staticFunctions[] = { { "baseProtoDup", NULL, kJSPropertyAttributeNone }, { "baseProto", Base_callAsFunction, kJSPropertyAttributeNone }, + { "baseHardNull", Base_returnHardNull, kJSPropertyAttributeNone }, { 0, 0, 0 } }; @@ -791,6 +865,17 @@ static JSObjectRef myConstructor_callAsConstructor(JSContextRef context, JSObjec return result; } +static JSObjectRef myBadConstructor_callAsConstructor(JSContextRef context, JSObjectRef constructorObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + UNUSED_PARAM(context); + UNUSED_PARAM(constructorObject); + UNUSED_PARAM(argumentCount); + UNUSED_PARAM(arguments); + UNUSED_PARAM(exception); + + return 0; +} + static void globalObject_initialize(JSContextRef context, JSObjectRef object) { @@ -1387,6 +1472,11 @@ int main(int argc, char* argv[]) JSObjectSetProperty(context, globalObject, myConstructorIString, myConstructor, kJSPropertyAttributeNone, NULL); JSStringRelease(myConstructorIString); + JSStringRef myBadConstructorIString = JSStringCreateWithUTF8CString("MyBadConstructor"); + JSObjectRef myBadConstructor = JSObjectMakeConstructor(context, NULL, myBadConstructor_callAsConstructor); + JSObjectSetProperty(context, globalObject, myBadConstructorIString, myBadConstructor, kJSPropertyAttributeNone, NULL); + JSStringRelease(myBadConstructorIString); + ASSERT(!JSObjectSetPrivate(myConstructor, (void*)1)); ASSERT(!JSObjectGetPrivate(myConstructor)); diff --git a/Source/JavaScriptCore/API/tests/testapi.js b/Source/JavaScriptCore/API/tests/testapi.js index 5257b882e..28fa54433 100644 --- a/Source/JavaScriptCore/API/tests/testapi.js +++ b/Source/JavaScriptCore/API/tests/testapi.js @@ -155,7 +155,7 @@ shouldBe("typeof myObject", "object"); shouldBe("MyObject ? 1 : 0", true); // toBoolean shouldBe("+MyObject", 1); // toNumber shouldBe("(Object.prototype.toString.call(MyObject))", "[object MyObject]"); // Object.prototype.toString -shouldBe("(MyObject.toString())", "MyObjectAsString"); // toString +shouldBe("(MyObject.toString())", "[object MyObject]"); // toString shouldBe("String(MyObject)", "MyObjectAsString"); // toString shouldBe("MyObject - 0", 1); // toNumber shouldBe("MyObject.valueOf()", 1); // valueOf @@ -167,6 +167,8 @@ shouldBe("constructedObject.value", 1); shouldBe("myObject instanceof MyObject", true); shouldBe("(new Object()) instanceof MyObject", false); +shouldThrow("new MyBadConstructor()"); + MyObject.nullGetSet = 1; shouldBe("MyObject.nullGetSet", 1); shouldThrow("MyObject.nullCall()"); @@ -186,6 +188,8 @@ shouldBe("derived.protoOnly()", 2); shouldBe("derived.protoDup", 2); shouldBe("derived.derivedOnly", 2) +shouldBe("derived.baseHardNull()", undefined) + // base properties throw 1 when set; derived, 2 shouldBe("derived.baseDup = 0", 2); shouldBe("derived.baseOnly = 0", 1); |