summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/API
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/API')
-rw-r--r--Source/JavaScriptCore/API/APICast.h2
-rw-r--r--Source/JavaScriptCore/API/JSBase.cpp8
-rw-r--r--Source/JavaScriptCore/API/JSCallbackConstructor.cpp7
-rw-r--r--Source/JavaScriptCore/API/JSCallbackFunction.cpp38
-rw-r--r--Source/JavaScriptCore/API/JSCallbackFunction.h3
-rw-r--r--Source/JavaScriptCore/API/JSCallbackObject.cpp3
-rw-r--r--Source/JavaScriptCore/API/JSCallbackObject.h4
-rw-r--r--Source/JavaScriptCore/API/JSCallbackObjectFunctions.h45
-rw-r--r--Source/JavaScriptCore/API/JSClassRef.cpp15
-rw-r--r--Source/JavaScriptCore/API/JSContextRef.cpp55
-rw-r--r--Source/JavaScriptCore/API/JSObjectRef.cpp20
-rw-r--r--Source/JavaScriptCore/API/JSValueRef.cpp4
-rw-r--r--Source/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp2
-rw-r--r--Source/JavaScriptCore/API/tests/testapi.c96
-rw-r--r--Source/JavaScriptCore/API/tests/testapi.js6
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);