diff options
Diffstat (limited to 'JavaScriptCore/API')
28 files changed, 1082 insertions, 204 deletions
diff --git a/JavaScriptCore/API/APICast.h b/JavaScriptCore/API/APICast.h index 4284c44..4294d3d 100644 --- a/JavaScriptCore/API/APICast.h +++ b/JavaScriptCore/API/APICast.h @@ -29,7 +29,6 @@ #include "JSAPIValueWrapper.h" #include "JSGlobalObject.h" #include "JSValue.h" -#include <wtf/Platform.h> #include <wtf/UnusedParam.h> namespace JSC { @@ -112,8 +111,8 @@ inline JSValueRef toRef(JSC::ExecState* exec, JSC::JSValue v) if (!v) return 0; if (!v.isCell()) - return reinterpret_cast<JSValueRef>(asCell(JSC::jsAPIValueWrapper(exec, v))); - return reinterpret_cast<JSValueRef>(asCell(v)); + return reinterpret_cast<JSValueRef>(JSC::jsAPIValueWrapper(exec, v).asCell()); + return reinterpret_cast<JSValueRef>(v.asCell()); #else UNUSED_PARAM(exec); return reinterpret_cast<JSValueRef>(JSC::JSValue::encode(v)); diff --git a/JavaScriptCore/API/APIShims.h b/JavaScriptCore/API/APIShims.h index d7276ec..892068d 100644 --- a/JavaScriptCore/API/APIShims.h +++ b/JavaScriptCore/API/APIShims.h @@ -28,6 +28,7 @@ #include "CallFrame.h" #include "JSLock.h" +#include <wtf/WTFThreadData.h> namespace JSC { @@ -35,7 +36,7 @@ class APIEntryShimWithoutLock { protected: APIEntryShimWithoutLock(JSGlobalData* globalData, bool registerThread) : m_globalData(globalData) - , m_entryIdentifierTable(setCurrentIdentifierTable(globalData->identifierTable)) + , m_entryIdentifierTable(wtfThreadData().setCurrentIdentifierTable(globalData->identifierTable)) { if (registerThread) globalData->heap.registerThread(); @@ -45,7 +46,7 @@ protected: ~APIEntryShimWithoutLock() { m_globalData->timeoutChecker.stop(); - setCurrentIdentifierTable(m_entryIdentifierTable); + wtfThreadData().setCurrentIdentifierTable(m_entryIdentifierTable); } private: @@ -65,7 +66,7 @@ public: // JSPropertyNameAccumulator only has a globalData. APIEntryShim(JSGlobalData* globalData, bool registerThread = true) : APIEntryShimWithoutLock(globalData, registerThread) - , m_lock(globalData->isSharedInstance ? LockForReal : SilenceAssertionsOnly) + , m_lock(globalData->isSharedInstance() ? LockForReal : SilenceAssertionsOnly) { } @@ -79,14 +80,12 @@ public: : m_dropAllLocks(exec) , m_globalData(&exec->globalData()) { - resetCurrentIdentifierTable(); - m_globalData->timeoutChecker.start(); + wtfThreadData().resetCurrentIdentifierTable(); } ~APICallbackShim() { - m_globalData->timeoutChecker.stop(); - setCurrentIdentifierTable(m_globalData->identifierTable); + wtfThreadData().setCurrentIdentifierTable(m_globalData->identifierTable); } private: diff --git a/JavaScriptCore/API/JSBase.cpp b/JavaScriptCore/API/JSBase.cpp index ebfeafa..c5f1b15 100644 --- a/JavaScriptCore/API/JSBase.cpp +++ b/JavaScriptCore/API/JSBase.cpp @@ -38,6 +38,7 @@ #include <runtime/JSGlobalObject.h> #include <runtime/JSLock.h> #include <runtime/JSObject.h> +#include <wtf/text/StringHash.h> using namespace JSC; diff --git a/JavaScriptCore/API/JSCallbackConstructor.cpp b/JavaScriptCore/API/JSCallbackConstructor.cpp index 9c5f6d7..66c6b88 100644 --- a/JavaScriptCore/API/JSCallbackConstructor.cpp +++ b/JavaScriptCore/API/JSCallbackConstructor.cpp @@ -28,6 +28,7 @@ #include "APIShims.h" #include "APICast.h" +#include <runtime/Error.h> #include <runtime/JSGlobalObject.h> #include <runtime/JSLock.h> #include <runtime/ObjectPrototype.h> @@ -37,8 +38,8 @@ namespace JSC { const ClassInfo JSCallbackConstructor::info = { "CallbackConstructor", 0, 0, 0 }; -JSCallbackConstructor::JSCallbackConstructor(NonNullPassRefPtr<Structure> structure, JSClassRef jsClass, JSObjectCallAsConstructorCallback callback) - : JSObject(structure) +JSCallbackConstructor::JSCallbackConstructor(JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, JSClassRef jsClass, JSObjectCallAsConstructorCallback callback) + : JSObjectWithGlobalObject(globalObject, structure) , m_class(jsClass) , m_callback(callback) { @@ -52,17 +53,18 @@ JSCallbackConstructor::~JSCallbackConstructor() JSClassRelease(m_class); } -static JSObject* constructJSCallback(ExecState* exec, JSObject* constructor, const ArgList& args) +static EncodedJSValue JSC_HOST_CALL constructJSCallback(ExecState* exec) { + JSObject* constructor = exec->callee(); JSContextRef ctx = toRef(exec); JSObjectRef constructorRef = toRef(constructor); JSObjectCallAsConstructorCallback callback = static_cast<JSCallbackConstructor*>(constructor)->callback(); if (callback) { - int argumentCount = static_cast<int>(args.size()); + int argumentCount = static_cast<int>(exec->argumentCount()); Vector<JSValueRef, 16> arguments(argumentCount); for (int i = 0; i < argumentCount; i++) - arguments[i] = toRef(exec, args.at(i)); + arguments[i] = toRef(exec, exec->argument(i)); JSValueRef exception = 0; JSObjectRef result; @@ -71,11 +73,11 @@ static JSObject* constructJSCallback(ExecState* exec, JSObject* constructor, con result = callback(ctx, constructorRef, argumentCount, arguments.data(), &exception); } if (exception) - exec->setException(toJS(exec, exception)); - return toJS(result); + throwError(exec, toJS(exec, exception)); + return JSValue::encode(toJS(result)); } - return toJS(JSObjectMake(ctx, static_cast<JSCallbackConstructor*>(constructor)->classRef(), 0)); + return JSValue::encode(toJS(JSObjectMake(ctx, static_cast<JSCallbackConstructor*>(constructor)->classRef(), 0))); } ConstructType JSCallbackConstructor::getConstructData(ConstructData& constructData) diff --git a/JavaScriptCore/API/JSCallbackConstructor.h b/JavaScriptCore/API/JSCallbackConstructor.h index e529947..a6d64cc 100644 --- a/JavaScriptCore/API/JSCallbackConstructor.h +++ b/JavaScriptCore/API/JSCallbackConstructor.h @@ -27,13 +27,13 @@ #define JSCallbackConstructor_h #include "JSObjectRef.h" -#include <runtime/JSObject.h> +#include <runtime/JSObjectWithGlobalObject.h> namespace JSC { -class JSCallbackConstructor : public JSObject { +class JSCallbackConstructor : public JSObjectWithGlobalObject { public: - JSCallbackConstructor(NonNullPassRefPtr<Structure>, JSClassRef, JSObjectCallAsConstructorCallback); + JSCallbackConstructor(JSGlobalObject*, NonNullPassRefPtr<Structure>, JSClassRef, JSObjectCallAsConstructorCallback); virtual ~JSCallbackConstructor(); JSClassRef classRef() const { return m_class; } JSObjectCallAsConstructorCallback callback() const { return m_callback; } diff --git a/JavaScriptCore/API/JSCallbackFunction.cpp b/JavaScriptCore/API/JSCallbackFunction.cpp index 0e434d9..c488aa6 100644 --- a/JavaScriptCore/API/JSCallbackFunction.cpp +++ b/JavaScriptCore/API/JSCallbackFunction.cpp @@ -24,12 +24,12 @@ */ #include "config.h" -#include <wtf/Platform.h> #include "JSCallbackFunction.h" #include "APIShims.h" #include "APICast.h" #include "CodeBlock.h" +#include "ExceptionHelpers.h" #include "JSFunction.h" #include "FunctionPrototype.h" #include <runtime/JSGlobalObject.h> @@ -42,33 +42,33 @@ ASSERT_CLASS_FITS_IN_CELL(JSCallbackFunction); const ClassInfo JSCallbackFunction::info = { "CallbackFunction", &InternalFunction::info, 0, 0 }; -JSCallbackFunction::JSCallbackFunction(ExecState* exec, JSObjectCallAsFunctionCallback callback, const Identifier& name) - : InternalFunction(&exec->globalData(), exec->lexicalGlobalObject()->callbackFunctionStructure(), name) +JSCallbackFunction::JSCallbackFunction(ExecState* exec, JSGlobalObject* globalObject, JSObjectCallAsFunctionCallback callback, const Identifier& name) + : InternalFunction(&exec->globalData(), globalObject, globalObject->callbackFunctionStructure(), name) , m_callback(callback) { } -JSValue JSCallbackFunction::call(ExecState* exec, JSObject* functionObject, JSValue thisValue, const ArgList& args) +EncodedJSValue JSCallbackFunction::call(ExecState* exec) { JSContextRef execRef = toRef(exec); - JSObjectRef functionRef = toRef(functionObject); - JSObjectRef thisObjRef = toRef(thisValue.toThisObject(exec)); + JSObjectRef functionRef = toRef(exec->callee()); + JSObjectRef thisObjRef = toRef(exec->hostThisValue().toThisObject(exec)); - int argumentCount = static_cast<int>(args.size()); + int argumentCount = static_cast<int>(exec->argumentCount()); Vector<JSValueRef, 16> arguments(argumentCount); for (int i = 0; i < argumentCount; i++) - arguments[i] = toRef(exec, args.at(i)); + arguments[i] = toRef(exec, exec->argument(i)); JSValueRef exception = 0; JSValueRef result; { APICallbackShim callbackShim(exec); - result = static_cast<JSCallbackFunction*>(functionObject)->m_callback(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), &exception); + result = static_cast<JSCallbackFunction*>(toJS(functionRef))->m_callback(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), &exception); } if (exception) - exec->setException(toJS(exec, exception)); + throwError(exec, toJS(exec, exception)); - return toJS(exec, result); + return JSValue::encode(toJS(exec, result)); } CallType JSCallbackFunction::getCallData(CallData& callData) diff --git a/JavaScriptCore/API/JSCallbackFunction.h b/JavaScriptCore/API/JSCallbackFunction.h index 10dae6b..b119b97 100644 --- a/JavaScriptCore/API/JSCallbackFunction.h +++ b/JavaScriptCore/API/JSCallbackFunction.h @@ -33,7 +33,7 @@ namespace JSC { class JSCallbackFunction : public InternalFunction { public: - JSCallbackFunction(ExecState*, JSObjectCallAsFunctionCallback, const Identifier& name); + JSCallbackFunction(ExecState*, JSGlobalObject*, JSObjectCallAsFunctionCallback, const Identifier& name); static const ClassInfo info; @@ -48,7 +48,7 @@ private: virtual CallType getCallData(CallData&); virtual const ClassInfo* classInfo() const { return &info; } - static JSValue JSC_HOST_CALL call(ExecState*, JSObject*, JSValue, const ArgList&); + static EncodedJSValue JSC_HOST_CALL call(ExecState*); JSObjectCallAsFunctionCallback m_callback; }; diff --git a/JavaScriptCore/API/JSCallbackObject.cpp b/JavaScriptCore/API/JSCallbackObject.cpp index 2fde0f8..abd2adc 100644 --- a/JavaScriptCore/API/JSCallbackObject.cpp +++ b/JavaScriptCore/API/JSCallbackObject.cpp @@ -28,14 +28,15 @@ #include "JSCallbackObject.h" #include "Collector.h" +#include <wtf/text/StringHash.h> namespace JSC { -ASSERT_CLASS_FITS_IN_CELL(JSCallbackObject<JSObject>); +ASSERT_CLASS_FITS_IN_CELL(JSCallbackObject<JSObjectWithGlobalObject>); ASSERT_CLASS_FITS_IN_CELL(JSCallbackObject<JSGlobalObject>); // Define the two types of JSCallbackObjects we support. -template <> const ClassInfo JSCallbackObject<JSObject>::info = { "CallbackObject", 0, 0, 0 }; +template <> const ClassInfo JSCallbackObject<JSObjectWithGlobalObject>::info = { "CallbackObject", 0, 0, 0 }; template <> const ClassInfo JSCallbackObject<JSGlobalObject>::info = { "CallbackGlobalObject", 0, 0, 0 }; } // namespace JSC diff --git a/JavaScriptCore/API/JSCallbackObject.h b/JavaScriptCore/API/JSCallbackObject.h index adb5b60..83442b2 100644 --- a/JavaScriptCore/API/JSCallbackObject.h +++ b/JavaScriptCore/API/JSCallbackObject.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc. All rights reserved. * Copyright (C) 2007 Eric Seidel <eric@webkit.org> * * Redistribution and use in source and binary forms, with or without @@ -30,14 +30,93 @@ #include "JSObjectRef.h" #include "JSValueRef.h" #include "JSObject.h" +#include <wtf/PassOwnPtr.h> namespace JSC { +struct JSCallbackObjectData { + JSCallbackObjectData(void* privateData, JSClassRef jsClass) + : privateData(privateData) + , jsClass(jsClass) + { + JSClassRetain(jsClass); + } + + ~JSCallbackObjectData() + { + JSClassRelease(jsClass); + } + + JSValue getPrivateProperty(const Identifier& propertyName) const + { + if (!m_privateProperties) + return JSValue(); + return m_privateProperties->getPrivateProperty(propertyName); + } + + void setPrivateProperty(const Identifier& propertyName, JSValue value) + { + if (!m_privateProperties) + m_privateProperties = adoptPtr(new JSPrivatePropertyMap); + m_privateProperties->setPrivateProperty(propertyName, value); + } + + void deletePrivateProperty(const Identifier& propertyName) + { + if (!m_privateProperties) + return; + m_privateProperties->deletePrivateProperty(propertyName); + } + + void markChildren(MarkStack& markStack) + { + if (!m_privateProperties) + return; + m_privateProperties->markChildren(markStack); + } + + void* privateData; + JSClassRef jsClass; + struct JSPrivatePropertyMap { + JSValue getPrivateProperty(const Identifier& propertyName) const + { + PrivatePropertyMap::const_iterator location = m_propertyMap.find(propertyName.impl()); + if (location == m_propertyMap.end()) + return JSValue(); + return location->second; + } + + void setPrivateProperty(const Identifier& propertyName, JSValue value) + { + m_propertyMap.set(propertyName.impl(), value); + } + + void deletePrivateProperty(const Identifier& propertyName) + { + m_propertyMap.remove(propertyName.impl()); + } + + void markChildren(MarkStack& markStack) + { + for (PrivatePropertyMap::iterator ptr = m_propertyMap.begin(); ptr != m_propertyMap.end(); ++ptr) { + if (ptr->second) + markStack.append(ptr->second); + } + } + + private: + typedef HashMap<RefPtr<StringImpl>, JSValue, IdentifierRepHash> PrivatePropertyMap; + PrivatePropertyMap m_propertyMap; + }; + OwnPtr<JSPrivatePropertyMap> m_privateProperties; +}; + + template <class Base> class JSCallbackObject : public Base { public: - JSCallbackObject(ExecState*, NonNullPassRefPtr<Structure>, JSClassRef, void* data); - JSCallbackObject(JSClassRef); + JSCallbackObject(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, JSClassRef, void* data); + JSCallbackObject(JSClassRef, NonNullPassRefPtr<Structure>); virtual ~JSCallbackObject(); void setPrivate(void* data); @@ -52,6 +131,21 @@ public: { return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), Base::AnonymousSlotCount); } + + JSValue getPrivateProperty(const Identifier& propertyName) const + { + return m_callbackObjectData->getPrivateProperty(propertyName); + } + + void setPrivateProperty(const Identifier& propertyName, JSValue value) + { + m_callbackObjectData->setPrivateProperty(propertyName, value); + } + + void deletePrivateProperty(const Identifier& propertyName) + { + m_callbackObjectData->deletePrivateProperty(propertyName); + } protected: static const unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesHasInstance | OverridesMarkChildren | OverridesGetPropertyNames | Base::StructureFlags; @@ -79,34 +173,23 @@ private: virtual CallType getCallData(CallData&); virtual const ClassInfo* classInfo() const { return &info; } + virtual void markChildren(MarkStack& markStack) + { + Base::markChildren(markStack); + m_callbackObjectData->markChildren(markStack); + } + void init(ExecState*); static JSCallbackObject* asCallbackObject(JSValue); - static JSValue JSC_HOST_CALL call(ExecState*, JSObject* functionObject, JSValue thisValue, const ArgList&); - static JSObject* construct(ExecState*, JSObject* constructor, const ArgList&); + static EncodedJSValue JSC_HOST_CALL call(ExecState*); + static EncodedJSValue JSC_HOST_CALL construct(ExecState*); - static JSValue staticValueGetter(ExecState*, const Identifier&, const PropertySlot&); - static JSValue staticFunctionGetter(ExecState*, const Identifier&, const PropertySlot&); - static JSValue callbackGetter(ExecState*, const Identifier&, const PropertySlot&); - - struct JSCallbackObjectData { - JSCallbackObjectData(void* privateData, JSClassRef jsClass) - : privateData(privateData) - , jsClass(jsClass) - { - JSClassRetain(jsClass); - } - - ~JSCallbackObjectData() - { - JSClassRelease(jsClass); - } - - void* privateData; - JSClassRef jsClass; - }; - + static JSValue staticValueGetter(ExecState*, JSValue, const Identifier&); + static JSValue staticFunctionGetter(ExecState*, JSValue, const Identifier&); + static JSValue callbackGetter(ExecState*, JSValue, const Identifier&); + OwnPtr<JSCallbackObjectData> m_callbackObjectData; }; diff --git a/JavaScriptCore/API/JSCallbackObjectFunctions.h b/JavaScriptCore/API/JSCallbackObjectFunctions.h index 4b28a99..de5d842 100644 --- a/JavaScriptCore/API/JSCallbackObjectFunctions.h +++ b/JavaScriptCore/API/JSCallbackObjectFunctions.h @@ -27,8 +27,10 @@ #include "APIShims.h" #include "APICast.h" #include "Error.h" +#include "ExceptionHelpers.h" #include "JSCallbackFunction.h" #include "JSClassRef.h" +#include "JSFunction.h" #include "JSGlobalObject.h" #include "JSLock.h" #include "JSObjectRef.h" @@ -48,9 +50,9 @@ inline JSCallbackObject<Base>* JSCallbackObject<Base>::asCallbackObject(JSValue } template <class Base> -JSCallbackObject<Base>::JSCallbackObject(ExecState* exec, NonNullPassRefPtr<Structure> structure, JSClassRef jsClass, void* data) - : Base(structure) - , m_callbackObjectData(new JSCallbackObjectData(data, jsClass)) +JSCallbackObject<Base>::JSCallbackObject(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, JSClassRef jsClass, void* data) + : Base(globalObject, structure) + , m_callbackObjectData(adoptPtr(new JSCallbackObjectData(data, jsClass))) { init(exec); } @@ -58,9 +60,9 @@ JSCallbackObject<Base>::JSCallbackObject(ExecState* exec, NonNullPassRefPtr<Stru // Global object constructor. // FIXME: Move this into a separate JSGlobalCallbackObject class derived from this one. template <class Base> -JSCallbackObject<Base>::JSCallbackObject(JSClassRef jsClass) - : Base() - , m_callbackObjectData(new JSCallbackObjectData(0, jsClass)) +JSCallbackObject<Base>::JSCallbackObject(JSClassRef jsClass, NonNullPassRefPtr<Structure> structure) + : Base(structure) + , m_callbackObjectData(adoptPtr(new JSCallbackObjectData(0, jsClass))) { ASSERT(Base::isGlobalObject()); init(static_cast<JSGlobalObject*>(this)->globalExec()); @@ -133,7 +135,7 @@ bool JSCallbackObject<Base>::getOwnPropertySlot(ExecState* exec, const Identifie value = getProperty(ctx, thisRef, propertyNameRef.get(), &exception); } if (exception) { - exec->setException(toJS(exec, exception)); + throwError(exec, toJS(exec, exception)); slot.setValue(jsUndefined()); return true; } @@ -144,14 +146,14 @@ bool JSCallbackObject<Base>::getOwnPropertySlot(ExecState* exec, const Identifie } if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) { - if (staticValues->contains(propertyName.ustring().rep())) { + if (staticValues->contains(propertyName.impl())) { slot.setCustom(this, staticValueGetter); return true; } } if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) { - if (staticFunctions->contains(propertyName.ustring().rep())) { + if (staticFunctions->contains(propertyName.impl())) { slot.setCustom(this, staticFunctionGetter); return true; } @@ -205,13 +207,13 @@ void JSCallbackObject<Base>::put(ExecState* exec, const Identifier& propertyName result = setProperty(ctx, thisRef, propertyNameRef.get(), valueRef, &exception); } if (exception) - exec->setException(toJS(exec, exception)); + throwError(exec, toJS(exec, exception)); if (result || exception) return; } if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) { - if (StaticValueEntry* entry = staticValues->get(propertyName.ustring().rep())) { + if (StaticValueEntry* entry = staticValues->get(propertyName.impl())) { if (entry->attributes & kJSPropertyAttributeReadOnly) return; if (JSObjectSetPropertyCallback setProperty = entry->setProperty) { @@ -224,16 +226,16 @@ void JSCallbackObject<Base>::put(ExecState* exec, const Identifier& propertyName result = setProperty(ctx, thisRef, propertyNameRef.get(), valueRef, &exception); } if (exception) - exec->setException(toJS(exec, exception)); + throwError(exec, toJS(exec, exception)); if (result || exception) return; } else - throwError(exec, ReferenceError, "Attempt to set a property that is not settable."); + throwError(exec, createReferenceError(exec, "Attempt to set a property that is not settable.")); } } if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) { - if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.ustring().rep())) { + if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.impl())) { if (entry->attributes & kJSPropertyAttributeReadOnly) return; JSCallbackObject<Base>::putDirect(propertyName, value); // put as override property @@ -263,13 +265,13 @@ bool JSCallbackObject<Base>::deleteProperty(ExecState* exec, const Identifier& p result = deleteProperty(ctx, thisRef, propertyNameRef.get(), &exception); } if (exception) - exec->setException(toJS(exec, exception)); + throwError(exec, toJS(exec, exception)); if (result || exception) return true; } if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) { - if (StaticValueEntry* entry = staticValues->get(propertyName.ustring().rep())) { + if (StaticValueEntry* entry = staticValues->get(propertyName.impl())) { if (entry->attributes & kJSPropertyAttributeDontDelete) return false; return true; @@ -277,7 +279,7 @@ bool JSCallbackObject<Base>::deleteProperty(ExecState* exec, const Identifier& p } if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) { - if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.ustring().rep())) { + if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.impl())) { if (entry->attributes & kJSPropertyAttributeDontDelete) return false; return true; @@ -307,17 +309,18 @@ ConstructType JSCallbackObject<Base>::getConstructData(ConstructData& constructD } template <class Base> -JSObject* JSCallbackObject<Base>::construct(ExecState* exec, JSObject* constructor, const ArgList& args) +EncodedJSValue JSCallbackObject<Base>::construct(ExecState* exec) { + JSObject* constructor = exec->callee(); JSContextRef execRef = toRef(exec); JSObjectRef constructorRef = toRef(constructor); for (JSClassRef jsClass = static_cast<JSCallbackObject<Base>*>(constructor)->classRef(); jsClass; jsClass = jsClass->parentClass) { if (JSObjectCallAsConstructorCallback callAsConstructor = jsClass->callAsConstructor) { - int argumentCount = static_cast<int>(args.size()); + int argumentCount = static_cast<int>(exec->argumentCount()); Vector<JSValueRef, 16> arguments(argumentCount); for (int i = 0; i < argumentCount; i++) - arguments[i] = toRef(exec, args.at(i)); + arguments[i] = toRef(exec, exec->argument(i)); JSValueRef exception = 0; JSObject* result; { @@ -325,13 +328,13 @@ JSObject* JSCallbackObject<Base>::construct(ExecState* exec, JSObject* construct result = toJS(callAsConstructor(execRef, constructorRef, argumentCount, arguments.data(), &exception)); } if (exception) - exec->setException(toJS(exec, exception)); - return result; + throwError(exec, toJS(exec, exception)); + return JSValue::encode(result); } } ASSERT_NOT_REACHED(); // getConstructData should prevent us from reaching here - return 0; + return JSValue::encode(JSValue()); } template <class Base> @@ -350,7 +353,7 @@ bool JSCallbackObject<Base>::hasInstance(ExecState* exec, JSValue value, JSValue result = hasInstance(execRef, thisRef, valueRef, &exception); } if (exception) - exec->setException(toJS(exec, exception)); + throwError(exec, toJS(exec, exception)); return result; } } @@ -370,18 +373,18 @@ CallType JSCallbackObject<Base>::getCallData(CallData& callData) } template <class Base> -JSValue JSCallbackObject<Base>::call(ExecState* exec, JSObject* functionObject, JSValue thisValue, const ArgList& args) +EncodedJSValue JSCallbackObject<Base>::call(ExecState* exec) { JSContextRef execRef = toRef(exec); - JSObjectRef functionRef = toRef(functionObject); - JSObjectRef thisObjRef = toRef(thisValue.toThisObject(exec)); + JSObjectRef functionRef = toRef(exec->callee()); + JSObjectRef thisObjRef = toRef(exec->hostThisValue().toThisObject(exec)); - for (JSClassRef jsClass = static_cast<JSCallbackObject<Base>*>(functionObject)->classRef(); jsClass; jsClass = jsClass->parentClass) { + for (JSClassRef jsClass = static_cast<JSCallbackObject<Base>*>(toJS(functionRef))->classRef(); jsClass; jsClass = jsClass->parentClass) { if (JSObjectCallAsFunctionCallback callAsFunction = jsClass->callAsFunction) { - int argumentCount = static_cast<int>(args.size()); + int argumentCount = static_cast<int>(exec->argumentCount()); Vector<JSValueRef, 16> arguments(argumentCount); for (int i = 0; i < argumentCount; i++) - arguments[i] = toRef(exec, args.at(i)); + arguments[i] = toRef(exec, exec->argument(i)); JSValueRef exception = 0; JSValue result; { @@ -389,13 +392,13 @@ JSValue JSCallbackObject<Base>::call(ExecState* exec, JSObject* functionObject, result = toJS(exec, callAsFunction(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), &exception)); } if (exception) - exec->setException(toJS(exec, exception)); - return result; + throwError(exec, toJS(exec, exception)); + return JSValue::encode(result); } } ASSERT_NOT_REACHED(); // getCallData should prevent us from reaching here - return JSValue(); + return JSValue::encode(JSValue()); } template <class Base> @@ -414,7 +417,7 @@ void JSCallbackObject<Base>::getOwnPropertyNames(ExecState* exec, PropertyNameAr typedef OpaqueJSClassStaticValuesTable::const_iterator iterator; iterator end = staticValues->end(); for (iterator it = staticValues->begin(); it != end; ++it) { - UString::Rep* name = it->first.get(); + StringImpl* name = it->first.get(); StaticValueEntry* entry = it->second; if (entry->getProperty && (!(entry->attributes & kJSPropertyAttributeDontEnum) || (mode == IncludeDontEnumProperties))) propertyNames.add(Identifier(exec, name)); @@ -425,7 +428,7 @@ void JSCallbackObject<Base>::getOwnPropertyNames(ExecState* exec, PropertyNameAr typedef OpaqueJSClassStaticFunctionsTable::const_iterator iterator; iterator end = staticFunctions->end(); for (iterator it = staticFunctions->begin(); it != end; ++it) { - UString::Rep* name = it->first.get(); + StringImpl* name = it->first.get(); StaticFunctionEntry* entry = it->second; if (!(entry->attributes & kJSPropertyAttributeDontEnum) || (mode == IncludeDontEnumProperties)) propertyNames.add(Identifier(exec, name)); @@ -456,7 +459,7 @@ double JSCallbackObject<Base>::toNumber(ExecState* exec) const value = convertToType(ctx, thisRef, kJSTypeNumber, &exception); } if (exception) { - exec->setException(toJS(exec, exception)); + throwError(exec, toJS(exec, exception)); return 0; } @@ -483,7 +486,7 @@ UString JSCallbackObject<Base>::toString(ExecState* exec) const value = convertToType(ctx, thisRef, kJSTypeString, &exception); } if (exception) { - exec->setException(toJS(exec, exception)); + throwError(exec, toJS(exec, exception)); return ""; } if (value) @@ -516,16 +519,16 @@ bool JSCallbackObject<Base>::inherits(JSClassRef c) const } template <class Base> -JSValue JSCallbackObject<Base>::staticValueGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +JSValue JSCallbackObject<Base>::staticValueGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName) { - JSCallbackObject* thisObj = asCallbackObject(slot.slotBase()); + JSCallbackObject* thisObj = asCallbackObject(slotBase); JSObjectRef thisRef = toRef(thisObj); RefPtr<OpaqueJSString> propertyNameRef; for (JSClassRef jsClass = thisObj->classRef(); jsClass; jsClass = jsClass->parentClass) if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) - if (StaticValueEntry* entry = staticValues->get(propertyName.ustring().rep())) + if (StaticValueEntry* entry = staticValues->get(propertyName.impl())) if (JSObjectGetPropertyCallback getProperty = entry->getProperty) { if (!propertyNameRef) propertyNameRef = OpaqueJSString::create(propertyName.ustring()); @@ -536,20 +539,20 @@ JSValue JSCallbackObject<Base>::staticValueGetter(ExecState* exec, const Identif value = getProperty(toRef(exec), thisRef, propertyNameRef.get(), &exception); } if (exception) { - exec->setException(toJS(exec, exception)); + throwError(exec, toJS(exec, exception)); return jsUndefined(); } if (value) return toJS(exec, value); } - return throwError(exec, ReferenceError, "Static value property defined with NULL getProperty callback."); + return throwError(exec, createReferenceError(exec, "Static value property defined with NULL getProperty callback.")); } template <class Base> -JSValue JSCallbackObject<Base>::staticFunctionGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +JSValue JSCallbackObject<Base>::staticFunctionGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName) { - JSCallbackObject* thisObj = asCallbackObject(slot.slotBase()); + JSCallbackObject* thisObj = asCallbackObject(slotBase); // Check for cached or override property. PropertySlot slot2(thisObj); @@ -558,9 +561,10 @@ JSValue JSCallbackObject<Base>::staticFunctionGetter(ExecState* exec, const Iden for (JSClassRef jsClass = thisObj->classRef(); jsClass; jsClass = jsClass->parentClass) { if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) { - if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.ustring().rep())) { + if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.impl())) { if (JSObjectCallAsFunctionCallback callAsFunction = entry->callAsFunction) { - JSObject* o = new (exec) JSCallbackFunction(exec, callAsFunction, propertyName); + + JSObject* o = new (exec) JSCallbackFunction(exec, asGlobalObject(thisObj->getAnonymousValue(0)), callAsFunction, propertyName); thisObj->putDirect(propertyName, o, entry->attributes); return o; } @@ -568,13 +572,13 @@ JSValue JSCallbackObject<Base>::staticFunctionGetter(ExecState* exec, const Iden } } - return throwError(exec, ReferenceError, "Static function property defined with NULL callAsFunction callback."); + return throwError(exec, createReferenceError(exec, "Static function property defined with NULL callAsFunction callback.")); } template <class Base> -JSValue JSCallbackObject<Base>::callbackGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +JSValue JSCallbackObject<Base>::callbackGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName) { - JSCallbackObject* thisObj = asCallbackObject(slot.slotBase()); + JSCallbackObject* thisObj = asCallbackObject(slotBase); JSObjectRef thisRef = toRef(thisObj); RefPtr<OpaqueJSString> propertyNameRef; @@ -590,14 +594,14 @@ JSValue JSCallbackObject<Base>::callbackGetter(ExecState* exec, const Identifier value = getProperty(toRef(exec), thisRef, propertyNameRef.get(), &exception); } if (exception) { - exec->setException(toJS(exec, exception)); + throwError(exec, toJS(exec, exception)); return jsUndefined(); } if (value) return toJS(exec, value); } - return throwError(exec, ReferenceError, "hasProperty callback returned true for a property that doesn't exist."); + return throwError(exec, createReferenceError(exec, "hasProperty callback returned true for a property that doesn't exist.")); } } // namespace JSC diff --git a/JavaScriptCore/API/JSClassRef.cpp b/JavaScriptCore/API/JSClassRef.cpp index 747aa16..decf493 100644 --- a/JavaScriptCore/API/JSClassRef.cpp +++ b/JavaScriptCore/API/JSClassRef.cpp @@ -33,6 +33,7 @@ #include <runtime/JSGlobalObject.h> #include <runtime/ObjectPrototype.h> #include <runtime/Identifier.h> +#include <wtf/text/StringHash.h> #include <wtf/unicode/UTF8.h> using namespace std; @@ -44,13 +45,13 @@ const JSClassDefinition kJSClassDefinitionEmpty = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 static inline UString tryCreateStringFromUTF8(const char* string) { if (!string) - return UString::null(); + return UString(); size_t length = strlen(string); Vector<UChar, 1024> buffer(length); UChar* p = buffer.data(); if (conversionOK != convertUTF8ToUTF16(&string, string + length, &p, p + length)) - return UString::null(); + return UString(); return UString(buffer.data(), p - buffer.data()); } @@ -82,7 +83,9 @@ OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass* if (!valueName.isNull()) { // Use a local variable here to sidestep an RVCT compiler bug. StaticValueEntry* entry = new StaticValueEntry(staticValue->getProperty, staticValue->setProperty, staticValue->attributes); - m_staticValues->add(valueName.rep()->ref(), entry); + StringImpl* impl = valueName.impl(); + impl->ref(); + m_staticValues->add(impl, entry); } ++staticValue; } @@ -95,7 +98,9 @@ OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass* if (!functionName.isNull()) { // Use a local variable here to sidestep an RVCT compiler bug. StaticFunctionEntry* entry = new StaticFunctionEntry(staticFunction->callAsFunction, staticFunction->attributes); - m_staticFunctions->add(functionName.rep()->ref(), entry); + StringImpl* impl = functionName.impl(); + impl->ref(); + m_staticFunctions->add(impl, entry); } ++staticFunction; } @@ -107,7 +112,8 @@ OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass* OpaqueJSClass::~OpaqueJSClass() { - ASSERT(!m_className.rep()->isIdentifier()); + // The empty string is shared across threads & is an identifier, in all other cases we should have done a deep copy in className(), below. + ASSERT(!m_className.length() || !m_className.impl()->isIdentifier()); if (m_staticValues) { OpaqueJSClassStaticValuesTable::const_iterator end = m_staticValues->end(); @@ -167,7 +173,7 @@ OpaqueJSClassContextData::OpaqueJSClassContextData(OpaqueJSClass* jsClass) 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); + staticValues->add(StringImpl::create(it->first->characters(), it->first->length()), entry); } } else staticValues = 0; @@ -179,7 +185,7 @@ OpaqueJSClassContextData::OpaqueJSClassContextData(OpaqueJSClass* jsClass) 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); + staticFunctions->add(StringImpl::create(it->first->characters(), it->first->length()), entry); } } else @@ -210,7 +216,7 @@ OpaqueJSClassContextData& OpaqueJSClass::contextData(ExecState* exec) UString OpaqueJSClass::className() { // Make a deep copy, so that the caller has no chance to put the original into IdentifierTable. - return UString(m_className.data(), m_className.size()); + return UString(m_className.characters(), m_className.length()); } OpaqueJSClassStaticValuesTable* OpaqueJSClass::staticValues(JSC::ExecState* exec) @@ -250,7 +256,7 @@ JSObject* OpaqueJSClass::prototype(ExecState* exec) if (!jsClassData.cachedPrototype) { // Recursive, but should be good enough for our purposes - jsClassData.cachedPrototype = new (exec) JSCallbackObject<JSObject>(exec, exec->lexicalGlobalObject()->callbackObjectStructure(), prototypeClass, &jsClassData); // set jsClassData as the object's private data, so it can clear our reference on destruction + jsClassData.cachedPrototype = new (exec) JSCallbackObject<JSObjectWithGlobalObject>(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), prototypeClass, &jsClassData); // 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(prototype); diff --git a/JavaScriptCore/API/JSClassRef.h b/JavaScriptCore/API/JSClassRef.h index ae60aad..5062093 100644 --- a/JavaScriptCore/API/JSClassRef.h +++ b/JavaScriptCore/API/JSClassRef.h @@ -33,7 +33,6 @@ #include <runtime/UString.h> #include <runtime/WeakGCPtr.h> #include <wtf/HashMap.h> -#include <wtf/RefCounted.h> struct StaticValueEntry : FastAllocBase { StaticValueEntry(JSObjectGetPropertyCallback _getProperty, JSObjectSetPropertyCallback _setProperty, JSPropertyAttributes _attributes) @@ -56,8 +55,8 @@ struct StaticFunctionEntry : FastAllocBase { JSPropertyAttributes attributes; }; -typedef HashMap<RefPtr<JSC::UString::Rep>, StaticValueEntry*> OpaqueJSClassStaticValuesTable; -typedef HashMap<RefPtr<JSC::UString::Rep>, StaticFunctionEntry*> OpaqueJSClassStaticFunctionsTable; +typedef HashMap<RefPtr<StringImpl>, StaticValueEntry*> OpaqueJSClassStaticValuesTable; +typedef HashMap<RefPtr<StringImpl>, StaticFunctionEntry*> OpaqueJSClassStaticFunctionsTable; struct OpaqueJSClass; diff --git a/JavaScriptCore/API/JSContextRef.cpp b/JavaScriptCore/API/JSContextRef.cpp index 6bdc3c8..ccab953 100644 --- a/JavaScriptCore/API/JSContextRef.cpp +++ b/JavaScriptCore/API/JSContextRef.cpp @@ -33,7 +33,7 @@ #include "JSClassRef.h" #include "JSGlobalObject.h" #include "JSObject.h" -#include <wtf/Platform.h> +#include <wtf/text/StringHash.h> #if OS(DARWIN) #include <mach-o/dyld.h> @@ -46,7 +46,7 @@ using namespace JSC; JSContextGroupRef JSContextGroupCreate() { initializeThreading(); - return toRef(JSGlobalData::createNonDefault().releaseRef()); + return toRef(JSGlobalData::createContextGroup(ThreadStackTypeSmall).leakRef()); } JSContextGroupRef JSContextGroupRetain(JSContextGroupRef group) @@ -84,7 +84,7 @@ 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::createContextGroup(ThreadStackTypeSmall); APIEntryShim entryShim(globalData.get(), false); @@ -97,7 +97,7 @@ JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClass return JSGlobalContextRetain(toGlobalRef(globalObject->globalExec())); } - JSGlobalObject* globalObject = new (globalData.get()) JSCallbackObject<JSGlobalObject>(globalObjectClass); + JSGlobalObject* globalObject = new (globalData.get()) JSCallbackObject<JSGlobalObject>(globalObjectClass, JSCallbackObject<JSGlobalObject>::createStructure(jsNull())); ExecState* exec = globalObject->globalExec(); JSValue prototype = globalObjectClass->prototype(exec); if (!prototype) @@ -120,18 +120,35 @@ JSGlobalContextRef JSGlobalContextRetain(JSGlobalContextRef ctx) void JSGlobalContextRelease(JSGlobalContextRef ctx) { ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec, false); - - gcUnprotect(exec->dynamicGlobalObject()); + JSLock lock(exec); 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. + 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 - run the garbage collector now. + // * 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.heap.destroy(); - } else + else if (releasingGlobalObject) globalData.heap.collectAllGarbage(); globalData.deref(); + + wtfThreadData().setCurrentIdentifierTable(savedIdentifierTable); } JSObjectRef JSContextGetGlobalObject(JSContextRef ctx) diff --git a/JavaScriptCore/API/JSObjectRef.cpp b/JavaScriptCore/API/JSObjectRef.cpp index faaa4eb..4198ca8 100644 --- a/JavaScriptCore/API/JSObjectRef.cpp +++ b/JavaScriptCore/API/JSObjectRef.cpp @@ -26,6 +26,7 @@ #include "config.h" #include "JSObjectRef.h" +#include "JSObjectRefPrivate.h" #include "APICast.h" #include "CodeBlock.h" @@ -48,7 +49,6 @@ #include "ObjectPrototype.h" #include "PropertyNameArray.h" #include "RegExpConstructor.h" -#include <wtf/Platform.h> using namespace JSC; @@ -59,7 +59,7 @@ JSClassRef JSClassCreate(const JSClassDefinition* definition) ? OpaqueJSClass::createNoAutomaticPrototype(definition) : OpaqueJSClass::create(definition); - return jsClass.release().releaseRef(); + return jsClass.release().leakRef(); } JSClassRef JSClassRetain(JSClassRef jsClass) @@ -81,7 +81,7 @@ JSObjectRef JSObjectMake(JSContextRef ctx, JSClassRef jsClass, void* data) if (!jsClass) return toRef(new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure())); // slightly more efficient - JSCallbackObject<JSObject>* object = new (exec) JSCallbackObject<JSObject>(exec, exec->lexicalGlobalObject()->callbackObjectStructure(), jsClass, data); + JSCallbackObject<JSObjectWithGlobalObject>* object = new (exec) JSCallbackObject<JSObjectWithGlobalObject>(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), jsClass, data); if (JSObject* prototype = jsClass->prototype(exec)) object->setPrototype(prototype); @@ -95,7 +95,7 @@ JSObjectRef JSObjectMakeFunctionWithCallback(JSContextRef ctx, JSStringRef name, Identifier nameID = name ? name->identifier(&exec->globalData()) : Identifier(exec, "anonymous"); - return toRef(new (exec) JSCallbackFunction(exec, callAsFunction, nameID)); + return toRef(new (exec) JSCallbackFunction(exec, exec->lexicalGlobalObject(), callAsFunction, nameID)); } JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObjectCallAsConstructorCallback callAsConstructor) @@ -107,7 +107,7 @@ JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObje if (!jsPrototype) jsPrototype = exec->lexicalGlobalObject()->objectPrototype(); - JSCallbackConstructor* constructor = new (exec) JSCallbackConstructor(exec->lexicalGlobalObject()->callbackConstructorStructure(), jsClass, callAsConstructor); + JSCallbackConstructor* constructor = new (exec) JSCallbackConstructor(exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackConstructorStructure(), jsClass, callAsConstructor); constructor->putDirect(exec->propertyNames().prototype, jsPrototype, DontEnum | DontDelete | ReadOnly); return toRef(constructor); } @@ -184,11 +184,10 @@ JSObjectRef JSObjectMakeError(JSContextRef ctx, size_t argumentCount, const JSVa ExecState* exec = toJS(ctx); APIEntryShim entryShim(exec); - MarkedArgumentBuffer argList; - for (size_t i = 0; i < argumentCount; ++i) - argList.append(toJS(exec, arguments[i])); + JSValue message = argumentCount ? toJS(exec, arguments[0]) : jsUndefined(); + Structure* errorStructure = exec->lexicalGlobalObject()->errorStructure(); + JSObject* result = ErrorInstance::create(exec, errorStructure, message); - JSObject* result = constructError(exec, argList); if (exec->hadException()) { if (exception) *exception = toRef(exec, exec->exception()); @@ -236,7 +235,7 @@ void JSObjectSetPrototype(JSContextRef ctx, JSObjectRef object, JSValueRef value JSObject* jsObject = toJS(object); JSValue jsValue = toJS(exec, value); - jsObject->setPrototype(jsValue.isObject() ? jsValue : jsNull()); + jsObject->setPrototypeWithCycleCheck(jsValue.isObject() ? jsValue : jsNull()); } bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName) @@ -343,8 +342,8 @@ void* JSObjectGetPrivate(JSObjectRef object) if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::info)) return static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivate(); - else if (jsObject->inherits(&JSCallbackObject<JSObject>::info)) - return static_cast<JSCallbackObject<JSObject>*>(jsObject)->getPrivate(); + else if (jsObject->inherits(&JSCallbackObject<JSObjectWithGlobalObject>::info)) + return static_cast<JSCallbackObject<JSObjectWithGlobalObject>*>(jsObject)->getPrivate(); return 0; } @@ -356,14 +355,63 @@ bool JSObjectSetPrivate(JSObjectRef object, void* data) if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::info)) { static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivate(data); return true; - } else if (jsObject->inherits(&JSCallbackObject<JSObject>::info)) { - static_cast<JSCallbackObject<JSObject>*>(jsObject)->setPrivate(data); + } else if (jsObject->inherits(&JSCallbackObject<JSObjectWithGlobalObject>::info)) { + static_cast<JSCallbackObject<JSObjectWithGlobalObject>*>(jsObject)->setPrivate(data); return true; } return false; } +JSValueRef JSObjectGetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName) +{ + ExecState* exec = toJS(ctx); + APIEntryShim entryShim(exec); + JSObject* jsObject = toJS(object); + JSValue result; + Identifier name(propertyName->identifier(&exec->globalData())); + if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::info)) + result = static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivateProperty(name); + else if (jsObject->inherits(&JSCallbackObject<JSObjectWithGlobalObject>::info)) + result = static_cast<JSCallbackObject<JSObjectWithGlobalObject>*>(jsObject)->getPrivateProperty(name); + return toRef(exec, result); +} + +bool JSObjectSetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value) +{ + ExecState* exec = toJS(ctx); + APIEntryShim entryShim(exec); + JSObject* jsObject = toJS(object); + JSValue jsValue = value ? toJS(exec, value) : JSValue(); + Identifier name(propertyName->identifier(&exec->globalData())); + if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::info)) { + static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivateProperty(name, jsValue); + return true; + } + if (jsObject->inherits(&JSCallbackObject<JSObjectWithGlobalObject>::info)) { + static_cast<JSCallbackObject<JSObjectWithGlobalObject>*>(jsObject)->setPrivateProperty(name, jsValue); + return true; + } + return false; +} + +bool JSObjectDeletePrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName) +{ + ExecState* exec = toJS(ctx); + APIEntryShim entryShim(exec); + JSObject* jsObject = toJS(object); + Identifier name(propertyName->identifier(&exec->globalData())); + if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::info)) { + static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->deletePrivateProperty(name); + return true; + } + if (jsObject->inherits(&JSCallbackObject<JSObjectWithGlobalObject>::info)) { + static_cast<JSCallbackObject<JSObjectWithGlobalObject>*>(jsObject)->deletePrivateProperty(name); + return true; + } + return false; +} + bool JSObjectIsFunction(JSContextRef, JSObjectRef object) { CallData callData; @@ -459,7 +507,7 @@ JSPropertyNameArrayRef JSObjectCopyPropertyNames(JSContextRef ctx, JSObjectRef o size_t size = array.size(); propertyNames->array.reserveInitialCapacity(size); for (size_t i = 0; i < size; ++i) - propertyNames->array.append(JSRetainPtr<JSStringRef>(Adopt, OpaqueJSString::create(array[i].ustring()).releaseRef())); + propertyNames->array.append(JSRetainPtr<JSStringRef>(Adopt, OpaqueJSString::create(array[i].ustring()).leakRef())); return JSPropertyNameArrayRetain(propertyNames); } diff --git a/JavaScriptCore/API/JSObjectRefPrivate.h b/JavaScriptCore/API/JSObjectRefPrivate.h new file mode 100644 index 0000000..32e80ab --- /dev/null +++ b/JavaScriptCore/API/JSObjectRefPrivate.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef JSObjectRefPrivate_h +#define JSObjectRefPrivate_h + +#include <JavaScriptCore/JSObjectRef.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + @function + @abstract Sets a private property on an object. This private property cannot be accessed from within JavaScript. + @param ctx The execution context to use. + @param object The JSObject whose private property you want to set. + @param propertyName A JSString containing the property's name. + @param value A JSValue to use as the property's value. This may be NULL. + @result true if object can store private data, otherwise false. + @discussion This API allows you to store JS values directly an object in a way that will be ensure that they are kept alive without exposing them to JavaScript code and without introducing the reference cycles that may occur when using JSValueProtect. + + The default object class does not allocate storage for private data. Only objects created with a non-NULL JSClass can store private properties. + */ +JS_EXPORT bool JSObjectSetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value); + +/*! + @function + @abstract Gets a private property from an object. + @param ctx The execution context to use. + @param object The JSObject whose private property you want to get. + @param propertyName A JSString containing the property's name. + @result The property's value if object has the property, otherwise NULL. + */ +JS_EXPORT JSValueRef JSObjectGetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName); + +/*! + @function + @abstract Deletes a private property from an object. + @param ctx The execution context to use. + @param object The JSObject whose private property you want to delete. + @param propertyName A JSString containing the property's name. + @result true if object can store private data, otherwise false. + @discussion The default object class does not allocate storage for private data. Only objects created with a non-NULL JSClass can store private data. + */ +JS_EXPORT bool JSObjectDeletePrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName); + +#ifdef __cplusplus +} +#endif + +#endif // JSObjectRefPrivate_h diff --git a/JavaScriptCore/API/JSRetainPtr.h b/JavaScriptCore/API/JSRetainPtr.h index 69c6de1..a884f38 100644 --- a/JavaScriptCore/API/JSRetainPtr.h +++ b/JavaScriptCore/API/JSRetainPtr.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2005, 2006, 2007, 2010 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,23 +37,20 @@ inline void JSRelease(JSStringRef string) { JSStringRelease(string); } enum AdoptTag { Adopt }; -template <typename T> class JSRetainPtr { +template<typename T> class JSRetainPtr { public: - JSRetainPtr() : m_ptr(0) {} + JSRetainPtr() : m_ptr(0) { } JSRetainPtr(T ptr) : m_ptr(ptr) { if (ptr) JSRetain(ptr); } - JSRetainPtr(AdoptTag, T ptr) : m_ptr(ptr) { } - - JSRetainPtr(const JSRetainPtr& o) : m_ptr(o.m_ptr) { if (T ptr = m_ptr) JSRetain(ptr); } - - ~JSRetainPtr() { if (T ptr = m_ptr) JSRelease(ptr); } - - template <typename U> JSRetainPtr(const JSRetainPtr<U>& o) : m_ptr(o.get()) { if (T ptr = m_ptr) JSRetain(ptr); } + JSRetainPtr(const JSRetainPtr&); + template<typename U> JSRetainPtr(const JSRetainPtr<U>&); + ~JSRetainPtr(); T get() const { return m_ptr; } - T releaseRef() { T tmp = m_ptr; m_ptr = 0; return tmp; } - + void clear(); + T leakRef(); + T operator->() const { return m_ptr; } bool operator!() const { return !m_ptr; } @@ -63,19 +60,57 @@ public: operator UnspecifiedBoolType() const { return m_ptr ? &JSRetainPtr::m_ptr : 0; } JSRetainPtr& operator=(const JSRetainPtr&); - template <typename U> JSRetainPtr& operator=(const JSRetainPtr<U>&); + template<typename U> JSRetainPtr& operator=(const JSRetainPtr<U>&); JSRetainPtr& operator=(T); - template <typename U> JSRetainPtr& operator=(U*); + template<typename U> JSRetainPtr& operator=(U*); void adopt(T); void swap(JSRetainPtr&); + // FIXME: Remove releaseRef once we change all callers to call leakRef instead. + T releaseRef() { return leakRef(); } + private: T m_ptr; }; -template <typename T> inline JSRetainPtr<T>& JSRetainPtr<T>::operator=(const JSRetainPtr<T>& o) +template<typename T> inline JSRetainPtr<T>::JSRetainPtr(const JSRetainPtr& o) + : m_ptr(o.m_ptr) +{ + if (m_ptr) + JSRetain(m_ptr); +} + +template<typename T> template<typename U> inline JSRetainPtr<T>::JSRetainPtr(const JSRetainPtr<U>& o) + : m_ptr(o.get()) +{ + if (m_ptr) + JSRetain(m_ptr); +} + +template<typename T> inline JSRetainPtr<T>::~JSRetainPtr() +{ + if (m_ptr) + JSRelease(m_ptr); +} + +template<typename T> inline void JSRetainPtr<T>::clear() +{ + if (T ptr = m_ptr) { + m_ptr = 0; + JSRelease(ptr); + } +} + +template<typename T> inline T JSRetainPtr<T>::leakRef() +{ + T ptr = m_ptr; + m_ptr = 0; + return ptr; +} + +template<typename T> inline JSRetainPtr<T>& JSRetainPtr<T>::operator=(const JSRetainPtr<T>& o) { T optr = o.get(); if (optr) @@ -87,7 +122,7 @@ template <typename T> inline JSRetainPtr<T>& JSRetainPtr<T>::operator=(const JSR return *this; } -template <typename T> template <typename U> inline JSRetainPtr<T>& JSRetainPtr<T>::operator=(const JSRetainPtr<U>& o) +template<typename T> template<typename U> inline JSRetainPtr<T>& JSRetainPtr<T>::operator=(const JSRetainPtr<U>& o) { T optr = o.get(); if (optr) @@ -99,7 +134,7 @@ template <typename T> template <typename U> inline JSRetainPtr<T>& JSRetainPtr<T return *this; } -template <typename T> inline JSRetainPtr<T>& JSRetainPtr<T>::operator=(T optr) +template<typename T> inline JSRetainPtr<T>& JSRetainPtr<T>::operator=(T optr) { if (optr) JSRetain(optr); @@ -110,7 +145,7 @@ template <typename T> inline JSRetainPtr<T>& JSRetainPtr<T>::operator=(T optr) return *this; } -template <typename T> inline void JSRetainPtr<T>::adopt(T optr) +template<typename T> inline void JSRetainPtr<T>::adopt(T optr) { T ptr = m_ptr; m_ptr = optr; @@ -118,7 +153,7 @@ template <typename T> inline void JSRetainPtr<T>::adopt(T optr) JSRelease(ptr); } -template <typename T> template <typename U> inline JSRetainPtr<T>& JSRetainPtr<T>::operator=(U* optr) +template<typename T> template<typename U> inline JSRetainPtr<T>& JSRetainPtr<T>::operator=(U* optr) { if (optr) JSRetain(optr); @@ -129,42 +164,42 @@ template <typename T> template <typename U> inline JSRetainPtr<T>& JSRetainPtr<T return *this; } -template <class T> inline void JSRetainPtr<T>::swap(JSRetainPtr<T>& o) +template<typename T> inline void JSRetainPtr<T>::swap(JSRetainPtr<T>& o) { std::swap(m_ptr, o.m_ptr); } -template <class T> inline void swap(JSRetainPtr<T>& a, JSRetainPtr<T>& b) +template<typename T> inline void swap(JSRetainPtr<T>& a, JSRetainPtr<T>& b) { a.swap(b); } -template <typename T, typename U> inline bool operator==(const JSRetainPtr<T>& a, const JSRetainPtr<U>& b) +template<typename T, typename U> inline bool operator==(const JSRetainPtr<T>& a, const JSRetainPtr<U>& b) { return a.get() == b.get(); } -template <typename T, typename U> inline bool operator==(const JSRetainPtr<T>& a, U* b) +template<typename T, typename U> inline bool operator==(const JSRetainPtr<T>& a, U* b) { return a.get() == b; } -template <typename T, typename U> inline bool operator==(T* a, const JSRetainPtr<U>& b) +template<typename T, typename U> inline bool operator==(T* a, const JSRetainPtr<U>& b) { return a == b.get(); } -template <typename T, typename U> inline bool operator!=(const JSRetainPtr<T>& a, const JSRetainPtr<U>& b) +template<typename T, typename U> inline bool operator!=(const JSRetainPtr<T>& a, const JSRetainPtr<U>& b) { return a.get() != b.get(); } -template <typename T, typename U> inline bool operator!=(const JSRetainPtr<T>& a, U* b) +template<typename T, typename U> inline bool operator!=(const JSRetainPtr<T>& a, U* b) { return a.get() != b; } -template <typename T, typename U> inline bool operator!=(T* a, const JSRetainPtr<U>& b) +template<typename T, typename U> inline bool operator!=(T* a, const JSRetainPtr<U>& b) { return a != b.get(); } diff --git a/JavaScriptCore/API/JSStringRef.cpp b/JavaScriptCore/API/JSStringRef.cpp index 8e236e4..ea31da6 100644 --- a/JavaScriptCore/API/JSStringRef.cpp +++ b/JavaScriptCore/API/JSStringRef.cpp @@ -36,7 +36,7 @@ using namespace WTF::Unicode; JSStringRef JSStringCreateWithCharacters(const JSChar* chars, size_t numChars) { initializeThreading(); - return OpaqueJSString::create(chars, numChars).releaseRef(); + return OpaqueJSString::create(chars, numChars).leakRef(); } JSStringRef JSStringCreateWithUTF8CString(const char* string) @@ -47,11 +47,11 @@ JSStringRef JSStringCreateWithUTF8CString(const char* string) Vector<UChar, 1024> buffer(length); UChar* p = buffer.data(); if (conversionOK == convertUTF8ToUTF16(&string, string + length, &p, p + length)) - return OpaqueJSString::create(buffer.data(), p - buffer.data()).releaseRef(); + return OpaqueJSString::create(buffer.data(), p - buffer.data()).leakRef(); } // Null string. - return OpaqueJSString::create().releaseRef(); + return OpaqueJSString::create().leakRef(); } JSStringRef JSStringRetain(JSStringRef string) diff --git a/JavaScriptCore/API/JSStringRef.h b/JavaScriptCore/API/JSStringRef.h index 92135b1..c5c1544 100644 --- a/JavaScriptCore/API/JSStringRef.h +++ b/JavaScriptCore/API/JSStringRef.h @@ -38,7 +38,7 @@ extern "C" { #endif #if !defined(WIN32) && !defined(_WIN32) && !defined(__WINSCW__) \ - && !(defined(__CC_ARM) || defined(__ARMCC__)) /* RVCT */ + && !((defined(__CC_ARM) || defined(__ARMCC__)) && !defined(__linux__)) /* RVCT */ /*! @typedef JSChar @abstract A Unicode character. diff --git a/JavaScriptCore/API/JSStringRefBSTR.cpp b/JavaScriptCore/API/JSStringRefBSTR.cpp index a7d3e99..70f4254 100644 --- a/JavaScriptCore/API/JSStringRefBSTR.cpp +++ b/JavaScriptCore/API/JSStringRefBSTR.cpp @@ -24,7 +24,7 @@ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ + */ #include "config.h" #include "JSStringRefBSTR.h" diff --git a/JavaScriptCore/API/JSStringRefCF.cpp b/JavaScriptCore/API/JSStringRefCF.cpp index d1f6fe3..e0961d0 100644 --- a/JavaScriptCore/API/JSStringRefCF.cpp +++ b/JavaScriptCore/API/JSStringRefCF.cpp @@ -45,9 +45,9 @@ JSStringRef JSStringCreateWithCFString(CFStringRef string) OwnArrayPtr<UniChar> buffer(new UniChar[length]); CFStringGetCharacters(string, CFRangeMake(0, length), buffer.get()); COMPILE_ASSERT(sizeof(UniChar) == sizeof(UChar), unichar_and_uchar_must_be_same_size); - return OpaqueJSString::create(reinterpret_cast<UChar*>(buffer.get()), length).releaseRef(); + return OpaqueJSString::create(reinterpret_cast<UChar*>(buffer.get()), length).leakRef(); } else { - return OpaqueJSString::create(0, 0).releaseRef(); + return OpaqueJSString::create(0, 0).leakRef(); } } diff --git a/JavaScriptCore/API/JSValueRef.cpp b/JavaScriptCore/API/JSValueRef.cpp index 518fc7b..faf4712 100644 --- a/JavaScriptCore/API/JSValueRef.cpp +++ b/JavaScriptCore/API/JSValueRef.cpp @@ -26,19 +26,21 @@ #include "config.h" #include "JSValueRef.h" -#include <wtf/Platform.h> #include "APICast.h" #include "APIShims.h" #include "JSCallbackObject.h" #include <runtime/JSGlobalObject.h> +#include <runtime/JSONObject.h> #include <runtime/JSString.h> +#include <runtime/LiteralParser.h> #include <runtime/Operations.h> #include <runtime/Protect.h> #include <runtime/UString.h> #include <runtime/JSValue.h> #include <wtf/Assertions.h> +#include <wtf/text/StringHash.h> #include <algorithm> // for std::min @@ -129,8 +131,8 @@ bool JSValueIsObjectOfClass(JSContextRef ctx, JSValueRef value, JSClassRef jsCla if (JSObject* o = jsValue.getObject()) { if (o->inherits(&JSCallbackObject<JSGlobalObject>::info)) return static_cast<JSCallbackObject<JSGlobalObject>*>(o)->inherits(jsClass); - else if (o->inherits(&JSCallbackObject<JSObject>::info)) - return static_cast<JSCallbackObject<JSObject>*>(o)->inherits(jsClass); + else if (o->inherits(&JSCallbackObject<JSObjectWithGlobalObject>::info)) + return static_cast<JSCallbackObject<JSObjectWithGlobalObject>*>(o)->inherits(jsClass); } return false; } @@ -217,7 +219,7 @@ JSValueRef JSValueMakeNumber(JSContextRef ctx, double value) if (isnan(value)) value = NaN; - return toRef(exec, jsNumber(exec, value)); + return toRef(exec, jsNumber(value)); } JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string) @@ -228,6 +230,31 @@ JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string) return toRef(exec, jsString(exec, string->ustring())); } +JSValueRef JSValueMakeFromJSONString(JSContextRef ctx, JSStringRef string) +{ + ExecState* exec = toJS(ctx); + APIEntryShim entryShim(exec); + LiteralParser parser(exec, string->ustring(), LiteralParser::StrictJSON); + return toRef(exec, parser.tryLiteralParse()); +} + +JSStringRef JSValueCreateJSONString(JSContextRef ctx, JSValueRef apiValue, unsigned indent, JSValueRef* exception) +{ + ExecState* exec = toJS(ctx); + APIEntryShim entryShim(exec); + JSValue value = toJS(exec, apiValue); + UString result = JSONStringify(exec, value, indent); + if (exception) + *exception = 0; + if (exec->hadException()) { + if (exception) + *exception = toRef(exec, exec->exception()); + exec->clearException(); + return 0; + } + return OpaqueJSString::create(result).leakRef(); +} + bool JSValueToBoolean(JSContextRef ctx, JSValueRef value) { ExecState* exec = toJS(ctx); @@ -268,7 +295,7 @@ JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef* exec->clearException(); stringRef.clear(); } - return stringRef.release().releaseRef(); + return stringRef.release().leakRef(); } JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exception) diff --git a/JavaScriptCore/API/JSValueRef.h b/JavaScriptCore/API/JSValueRef.h index 7a7bf93..4186db8 100644 --- a/JavaScriptCore/API/JSValueRef.h +++ b/JavaScriptCore/API/JSValueRef.h @@ -27,6 +27,7 @@ #define JSValueRef_h #include <JavaScriptCore/JSBase.h> +#include <JavaScriptCore/WebKitAvailability.h> #ifndef __cplusplus #include <stdbool.h> @@ -208,6 +209,28 @@ JS_EXPORT JSValueRef JSValueMakeNumber(JSContextRef ctx, double number); */ JS_EXPORT JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string); +/* Converting to and from JSON formatted strings */ + +/*! + @function + @abstract Creates a JavaScript value from a JSON formatted string. + @param ctx The execution context to use. + @param string The JSString containing the JSON string to be parsed. + @result A JSValue containing the parsed value, or NULL if the input is invalid. + */ +JS_EXPORT JSValueRef JSValueMakeFromJSONString(JSContextRef ctx, JSStringRef string) AVAILABLE_AFTER_WEBKIT_VERSION_4_0; + +/*! + @function + @abstract Creates a JavaScript string containing the JSON serialized representation of a JS value. + @param ctx The execution context to use. + @param value The value to serialize. + @param indent The number of spaces to indent when nesting. If 0, the resulting JSON will not contains newlines. The size of the indent is clamped to 10 spaces. + @param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. + @result A JSString with the result of serialization, or NULL if an exception is thrown. + */ +JS_EXPORT JSStringRef JSValueCreateJSONString(JSContextRef ctx, JSValueRef value, unsigned indent, JSValueRef* exception) AVAILABLE_AFTER_WEBKIT_VERSION_4_0; + /* Converting to primitive values */ /*! diff --git a/JavaScriptCore/API/JSWeakObjectMapRefInternal.h b/JavaScriptCore/API/JSWeakObjectMapRefInternal.h new file mode 100644 index 0000000..64e1f4d --- /dev/null +++ b/JavaScriptCore/API/JSWeakObjectMapRefInternal.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef JSWeakObjectMapRefInternal_h +#define JSWeakObjectMapRefInternal_h + +#include "WeakGCMap.h" +#include <wtf/RefCounted.h> + +namespace JSC { + +class JSObject; + +} + +typedef void (*JSWeakMapDestroyedCallback)(struct OpaqueJSWeakObjectMap*, void*); + +typedef JSC::WeakGCMap<void*, JSC::JSObject*> WeakMapType; + +struct OpaqueJSWeakObjectMap : public RefCounted<OpaqueJSWeakObjectMap> { +public: + static PassRefPtr<OpaqueJSWeakObjectMap> create(void* data, JSWeakMapDestroyedCallback callback) + { + return adoptRef(new OpaqueJSWeakObjectMap(data, callback)); + } + + WeakMapType& map() { return m_map; } + + ~OpaqueJSWeakObjectMap() + { + m_callback(this, m_data); + } + +private: + OpaqueJSWeakObjectMap(void* data, JSWeakMapDestroyedCallback callback) + : m_data(data) + , m_callback(callback) + { + } + WeakMapType m_map; + void* m_data; + JSWeakMapDestroyedCallback m_callback; +}; + + +#endif // JSWeakObjectMapInternal_h diff --git a/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp b/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp new file mode 100644 index 0000000..8182075 --- /dev/null +++ b/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSWeakObjectMapRefPrivate.h" + +#include "APICast.h" +#include "APIShims.h" +#include "JSCallbackObject.h" +#include "JSValue.h" +#include "JSWeakObjectMapRefInternal.h" +#include <wtf/HashMap.h> +#include <wtf/text/StringHash.h> + +using namespace WTF; +using namespace JSC; + +#ifdef __cplusplus +extern "C" { +#endif + +JSWeakObjectMapRef JSWeakObjectMapCreate(JSContextRef context, void* privateData, JSWeakMapDestroyedCallback callback) +{ + ExecState* exec = toJS(context); + APIEntryShim entryShim(exec); + RefPtr<OpaqueJSWeakObjectMap> map = OpaqueJSWeakObjectMap::create(privateData, callback); + exec->lexicalGlobalObject()->registerWeakMap(map.get()); + return map.get(); +} + +void JSWeakObjectMapSet(JSContextRef ctx, JSWeakObjectMapRef map, void* key, JSObjectRef object) +{ + ExecState* exec = toJS(ctx); + APIEntryShim entryShim(exec); + JSObject* obj = toJS(object); + if (!obj) + return; + ASSERT(obj->inherits(&JSCallbackObject<JSGlobalObject>::info) || obj->inherits(&JSCallbackObject<JSObjectWithGlobalObject>::info)); + map->map().set(key, obj); +} + +JSObjectRef JSWeakObjectMapGet(JSContextRef ctx, JSWeakObjectMapRef map, void* key) +{ + ExecState* exec = toJS(ctx); + APIEntryShim entryShim(exec); + return toRef(static_cast<JSObject*>(map->map().get(key))); +} + +bool JSWeakObjectMapClear(JSContextRef ctx, JSWeakObjectMapRef map, void* key, JSObjectRef object) +{ + ExecState* exec = toJS(ctx); + APIEntryShim entryShim(exec); + JSObject* obj = toJS(object); + if (map->map().uncheckedRemove(key, obj)) + return true; + return false; +} + +#ifdef __cplusplus +} +#endif diff --git a/JavaScriptCore/API/JSWeakObjectMapRefPrivate.h b/JavaScriptCore/API/JSWeakObjectMapRefPrivate.h new file mode 100644 index 0000000..d36111c --- /dev/null +++ b/JavaScriptCore/API/JSWeakObjectMapRefPrivate.h @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef JSWeakObjectMapRefPrivate_h +#define JSWeakObjectMapRefPrivate_h + +#include <JavaScriptCore/JSContextRef.h> +#include <JavaScriptCore/JSValueRef.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/*! @typedef JSWeakObjectMapRef A weak map for storing JSObjectRefs */ +typedef struct OpaqueJSWeakObjectMap* JSWeakObjectMapRef; + +/*! + @typedef JSWeakMapDestroyedCallback + @abstract The callback invoked when a JSWeakObjectMapRef is being destroyed. + @param map The map that is being destroyed. + @param data The private data (if any) that was associated with the map instance. + */ +typedef void (*JSWeakMapDestroyedCallback)(JSWeakObjectMapRef map, void* data); + +/*! + @function + @abstract Creates a weak value map that can be used to reference user defined objects without preventing them from being collected. + @param ctx The execution context to use. + @param data A void* to set as the map's private data. Pass NULL to specify no private data. + @param destructor A function to call when the weak map is destroyed. + @result A JSWeakObjectMapRef bound to the given context, data and destructor. + @discussion The JSWeakObjectMapRef can be used as a storage mechanism to hold custom JS objects without forcing those objects to + remain live as JSValueProtect would. Any objects that are intended to be stored in a weak map must be user defined objects that + remove themselves from the map in their finalizer. + */ +JS_EXPORT JSWeakObjectMapRef JSWeakObjectMapCreate(JSContextRef ctx, void* data, JSWeakMapDestroyedCallback destructor); + +/*! + @function + @abstract Associates a JSObjectRef with the given key in a JSWeakObjectMap. + @param ctx The execution context to use. + @param map The map to operate on. + @param key The key to associate a weak reference with. + @param object The user defined object to associate with the key. + */ +JS_EXPORT void JSWeakObjectMapSet(JSContextRef ctx, JSWeakObjectMapRef map, void* key, JSObjectRef); + +/*! + @function + @abstract Retrieves the JSObjectRef associated with a key. + @param ctx The execution context to use. + @param map The map to query. + @param key The key to search for. + @result Either the live object associated with the provided key, or NULL. + */ +JS_EXPORT JSObjectRef JSWeakObjectMapGet(JSContextRef ctx, JSWeakObjectMapRef map, void* key); + +/*! + @function + @abstract Clears the association between a key and an object in a JSWeakObjectMapRef + @param ctx The execution context to use. + @param map The map to clear the key association from. + @param key The key to use. + @param object The old object value. + @result Returns true if the key/object association was present in map, and has been removed. + */ +JS_EXPORT bool JSWeakObjectMapClear(JSContextRef ctx, JSWeakObjectMapRef map, void* key, JSObjectRef object); + +#ifdef __cplusplus +} +#endif + +#endif // JSWeakObjectMapPrivate_h diff --git a/JavaScriptCore/API/OpaqueJSString.cpp b/JavaScriptCore/API/OpaqueJSString.cpp index f740abe..9a116e6 100644 --- a/JavaScriptCore/API/OpaqueJSString.cpp +++ b/JavaScriptCore/API/OpaqueJSString.cpp @@ -35,7 +35,7 @@ using namespace JSC; PassRefPtr<OpaqueJSString> OpaqueJSString::create(const UString& ustring) { if (!ustring.isNull()) - return adoptRef(new OpaqueJSString(ustring.data(), ustring.size())); + return adoptRef(new OpaqueJSString(ustring.characters(), ustring.length())); return 0; } @@ -43,7 +43,7 @@ UString OpaqueJSString::ustring() const { if (this && m_characters) return UString(m_characters, m_length); - return UString::null(); + return UString(); } Identifier OpaqueJSString::identifier(JSGlobalData* globalData) const diff --git a/JavaScriptCore/API/WebKitAvailability.h b/JavaScriptCore/API/WebKitAvailability.h index 8402528..0e4f091 100644 --- a/JavaScriptCore/API/WebKitAvailability.h +++ b/JavaScriptCore/API/WebKitAvailability.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2008, 2009, 2010 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -42,7 +42,7 @@ #define WEBKIT_VERSION_LATEST 0x9999 #ifdef __APPLE__ -#import <AvailabilityMacros.h> +#include <AvailabilityMacros.h> #else /* * For non-Mac platforms, require the newest version. @@ -86,6 +86,9 @@ #elif !defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6 /* WebKit 3.0 is the version that shipped on Mac OS X 10.5. */ #define WEBKIT_VERSION_MIN_REQUIRED WEBKIT_VERSION_3_0 + #elif !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7 + /* WebKit 4.0 is the version that shipped on Mac OS X 10.6. */ + #define WEBKIT_VERSION_MIN_REQUIRED WEBKIT_VERSION_4_0 #else #define WEBKIT_VERSION_MIN_REQUIRED WEBKIT_VERSION_LATEST #endif @@ -645,9 +648,9 @@ * * Used on declarations introduced in WebKit 4.0 */ -#if WEBKIT_VERSION_MAX_ALLOWED < WEBKIT_VERSION_LATEST +#if WEBKIT_VERSION_MAX_ALLOWED < WEBKIT_VERSION_4_0 #define AVAILABLE_IN_WEBKIT_VERSION_4_0 UNAVAILABLE_ATTRIBUTE -#elif WEBKIT_VERSION_MIN_REQUIRED < WEBKIT_VERSION_LATEST +#elif WEBKIT_VERSION_MIN_REQUIRED < WEBKIT_VERSION_4_0 #define AVAILABLE_IN_WEBKIT_VERSION_4_0 WEAK_IMPORT_ATTRIBUTE #else #define AVAILABLE_IN_WEBKIT_VERSION_4_0 @@ -659,7 +662,7 @@ * Used on declarations introduced in WebKit 4.0, * and deprecated in WebKit 4.0 */ -#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_4_0 #define AVAILABLE_IN_WEBKIT_VERSION_4_0_BUT_DEPRECATED DEPRECATED_ATTRIBUTE #else #define AVAILABLE_IN_WEBKIT_VERSION_4_0_BUT_DEPRECATED AVAILABLE_IN_WEBKIT_VERSION_4_0 @@ -671,7 +674,7 @@ * Used on declarations introduced in WebKit 1.0, * but later deprecated in WebKit 4.0 */ -#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_4_0 #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE #else #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER @@ -683,7 +686,7 @@ * Used on declarations introduced in WebKit 1.1, * but later deprecated in WebKit 4.0 */ -#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_4_0 #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE #else #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER @@ -695,7 +698,7 @@ * Used on declarations introduced in WebKit 1.2, * but later deprecated in WebKit 4.0 */ -#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_4_0 #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE #else #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER @@ -707,7 +710,7 @@ * Used on declarations introduced in WebKit 1.3, * but later deprecated in WebKit 4.0 */ -#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_4_0 #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE #else #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER @@ -719,7 +722,7 @@ * Used on declarations introduced in WebKit 2.0, * but later deprecated in WebKit 4.0 */ -#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_4_0 #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE #else #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER @@ -731,7 +734,7 @@ * Used on declarations introduced in WebKit 3.0, * but later deprecated in WebKit 4.0 */ -#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_4_0 #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE #else #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER @@ -743,7 +746,7 @@ * Used on declarations introduced in WebKit 3.1, * but later deprecated in WebKit 4.0 */ -#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_4_0 #define AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE #else #define AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER @@ -754,11 +757,148 @@ * * Used on types deprecated in WebKit 4.0 */ -#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_4_0 #define DEPRECATED_IN_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE #else #define DEPRECATED_IN_WEBKIT_VERSION_4_0 #endif + + + + +/* + * AVAILABLE_AFTER_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced after WebKit 4.0 + */ +#if WEBKIT_VERSION_MAX_ALLOWED < WEBKIT_VERSION_LATEST + #define AVAILABLE_AFTER_WEBKIT_VERSION_4_0 UNAVAILABLE_ATTRIBUTE +#elif WEBKIT_VERSION_MIN_REQUIRED < WEBKIT_VERSION_LATEST + #define AVAILABLE_AFTER_WEBKIT_VERSION_4_0 WEAK_IMPORT_ATTRIBUTE +#else + #define AVAILABLE_AFTER_WEBKIT_VERSION_4_0 +#endif + +/* + * AVAILABLE_AFTER_WEBKIT_VERSION_4_0_BUT_DEPRECATED + * + * Used on declarations introduced after WebKit 4.0, + * and deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define AVAILABLE_AFTER_WEBKIT_VERSION_4_0_BUT_DEPRECATED DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_AFTER_WEBKIT_VERSION_4_0_BUT_DEPRECATED AVAILABLE_AFTER_WEBKIT_VERSION_4_0 +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 1.0, + * but later deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 1.1, + * but later deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 1.2, + * but later deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 1.3, + * but later deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 2.0, + * but later deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 3.0, + * but later deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 3.1, + * but later deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_4_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 4.0 + * but later deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define AVAILABLE_WEBKIT_VERSION_4_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_4_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_4_0_AND_LATER +#endif + +/* + * DEPRECATED_AFTER_WEBKIT_VERSION_4_0 + * + * Used on types deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define DEPRECATED_AFTER_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define DEPRECATED_AFTER_WEBKIT_VERSION_4_0 +#endif + + #endif /* __WebKitAvailability__ */ diff --git a/JavaScriptCore/API/tests/testapi.c b/JavaScriptCore/API/tests/testapi.c index ebc0cfb..1ecfc7e 100644 --- a/JavaScriptCore/API/tests/testapi.c +++ b/JavaScriptCore/API/tests/testapi.c @@ -26,6 +26,7 @@ #include "JavaScriptCore.h" #include "JSBasePrivate.h" #include "JSContextRefPrivate.h" +#include "JSObjectRefPrivate.h" #include <math.h> #define ASSERT_DISABLED 0 #include <wtf/Assertions.h> @@ -754,6 +755,8 @@ static void testInitializeFinalize() static JSValueRef jsNumberValue = NULL; +static JSObjectRef aHeapRef = NULL; + static void makeGlobalNumberValue(JSContextRef context) { JSValueRef v = JSValueMakeNumber(context, 420); JSValueProtect(context, v); @@ -761,6 +764,59 @@ static void makeGlobalNumberValue(JSContextRef context) { v = NULL; } +static bool assertTrue(bool value, const char* message) +{ + if (!value) { + if (message) + fprintf(stderr, "assertTrue failed: '%s'\n", message); + else + fprintf(stderr, "assertTrue failed.\n"); + failed = 1; + } + return value; +} + +static bool checkForCycleInPrototypeChain() +{ + bool result = true; + JSGlobalContextRef context = JSGlobalContextCreate(0); + JSObjectRef object1 = JSObjectMake(context, /* jsClass */ 0, /* data */ 0); + JSObjectRef object2 = JSObjectMake(context, /* jsClass */ 0, /* data */ 0); + JSObjectRef object3 = JSObjectMake(context, /* jsClass */ 0, /* data */ 0); + + JSObjectSetPrototype(context, object1, JSValueMakeNull(context)); + ASSERT(JSValueIsNull(context, JSObjectGetPrototype(context, object1))); + + // object1 -> object1 + JSObjectSetPrototype(context, object1, object1); + result &= assertTrue(JSValueIsNull(context, JSObjectGetPrototype(context, object1)), "It is possible to assign self as a prototype"); + + // object1 -> object2 -> object1 + JSObjectSetPrototype(context, object2, object1); + ASSERT(JSValueIsStrictEqual(context, JSObjectGetPrototype(context, object2), object1)); + JSObjectSetPrototype(context, object1, object2); + result &= assertTrue(JSValueIsNull(context, JSObjectGetPrototype(context, object1)), "It is possible to close a prototype chain cycle"); + + // object1 -> object2 -> object3 -> object1 + JSObjectSetPrototype(context, object2, object3); + ASSERT(JSValueIsStrictEqual(context, JSObjectGetPrototype(context, object2), object3)); + JSObjectSetPrototype(context, object1, object2); + ASSERT(JSValueIsStrictEqual(context, JSObjectGetPrototype(context, object1), object2)); + JSObjectSetPrototype(context, object3, object1); + result &= assertTrue(!JSValueIsStrictEqual(context, JSObjectGetPrototype(context, object3), object1), "It is possible to close a prototype chain cycle"); + + JSValueRef exception; + JSStringRef code = JSStringCreateWithUTF8CString("o = { }; p = { }; o.__proto__ = p; p.__proto__ = o"); + JSStringRef file = JSStringCreateWithUTF8CString(""); + result &= assertTrue(!JSEvaluateScript(context, code, /* thisObject*/ 0, file, 1, &exception) + , "An exception should be thrown"); + + JSStringRelease(code); + JSStringRelease(file); + JSGlobalContextRelease(context); + return result; +} + int main(int argc, char* argv[]) { const char *scriptPath = "testapi.js"; @@ -870,8 +926,119 @@ int main(int argc, char* argv[]) JSObjectSetProperty(context, globalObject, EmptyObjectIString, EmptyObject, kJSPropertyAttributeNone, NULL); JSStringRelease(EmptyObjectIString); + JSStringRef lengthStr = JSStringCreateWithUTF8CString("length"); + JSObjectRef aStackRef = JSObjectMakeArray(context, 0, 0, 0); + aHeapRef = aStackRef; + JSObjectSetProperty(context, aHeapRef, lengthStr, JSValueMakeNumber(context, 10), 0, 0); + JSStringRef privatePropertyName = JSStringCreateWithUTF8CString("privateProperty"); + if (!JSObjectSetPrivateProperty(context, myObject, privatePropertyName, aHeapRef)) { + printf("FAIL: Could not set private property.\n"); + failed = 1; + } else + printf("PASS: Set private property.\n"); + aStackRef = 0; + if (JSObjectSetPrivateProperty(context, aHeapRef, privatePropertyName, aHeapRef)) { + printf("FAIL: JSObjectSetPrivateProperty should fail on non-API objects.\n"); + failed = 1; + } else + printf("PASS: Did not allow JSObjectSetPrivateProperty on a non-API object.\n"); + if (JSObjectGetPrivateProperty(context, myObject, privatePropertyName) != aHeapRef) { + printf("FAIL: Could not retrieve private property.\n"); + failed = 1; + } else + printf("PASS: Retrieved private property.\n"); + if (JSObjectGetPrivateProperty(context, aHeapRef, privatePropertyName)) { + printf("FAIL: JSObjectGetPrivateProperty should return NULL when called on a non-API object.\n"); + failed = 1; + } else + printf("PASS: JSObjectGetPrivateProperty return NULL.\n"); + + if (JSObjectGetProperty(context, myObject, privatePropertyName, 0) == aHeapRef) { + printf("FAIL: Accessed private property through ordinary property lookup.\n"); + failed = 1; + } else + printf("PASS: Cannot access private property through ordinary property lookup.\n"); + + JSGarbageCollect(context); + + for (int i = 0; i < 10000; i++) + JSObjectMake(context, 0, 0); + + aHeapRef = JSValueToObject(context, JSObjectGetPrivateProperty(context, myObject, privatePropertyName), 0); + if (JSValueToNumber(context, JSObjectGetProperty(context, aHeapRef, lengthStr, 0), 0) != 10) { + printf("FAIL: Private property has been collected.\n"); + failed = 1; + } else + printf("PASS: Private property does not appear to have been collected.\n"); + JSStringRelease(lengthStr); + + if (!JSObjectSetPrivateProperty(context, myObject, privatePropertyName, 0)) { + printf("FAIL: Could not set private property to NULL.\n"); + failed = 1; + } else + printf("PASS: Set private property to NULL.\n"); + if (JSObjectGetPrivateProperty(context, myObject, privatePropertyName)) { + printf("FAIL: Could not retrieve private property.\n"); + failed = 1; + } else + printf("PASS: Retrieved private property.\n"); + + JSStringRef validJSON = JSStringCreateWithUTF8CString("{\"aProperty\":true}"); + JSValueRef jsonObject = JSValueMakeFromJSONString(context, validJSON); + JSStringRelease(validJSON); + if (!JSValueIsObject(context, jsonObject)) { + printf("FAIL: Did not parse valid JSON correctly\n"); + failed = 1; + } else + printf("PASS: Parsed valid JSON string.\n"); + JSStringRef propertyName = JSStringCreateWithUTF8CString("aProperty"); + assertEqualsAsBoolean(JSObjectGetProperty(context, JSValueToObject(context, jsonObject, 0), propertyName, 0), true); + JSStringRelease(propertyName); + JSStringRef invalidJSON = JSStringCreateWithUTF8CString("fail!"); + if (JSValueMakeFromJSONString(context, invalidJSON)) { + printf("FAIL: Should return null for invalid JSON data\n"); + failed = 1; + } else + printf("PASS: Correctly returned null for invalid JSON data.\n"); JSValueRef exception; + JSStringRef str = JSValueCreateJSONString(context, jsonObject, 0, 0); + if (!JSStringIsEqualToUTF8CString(str, "{\"aProperty\":true}")) { + printf("FAIL: Did not correctly serialise with indent of 0.\n"); + failed = 1; + } else + printf("PASS: Correctly serialised with indent of 0.\n"); + JSStringRelease(str); + str = JSValueCreateJSONString(context, jsonObject, 4, 0); + if (!JSStringIsEqualToUTF8CString(str, "{\n \"aProperty\": true\n}")) { + printf("FAIL: Did not correctly serialise with indent of 4.\n"); + failed = 1; + } else + printf("PASS: Correctly serialised with indent of 4.\n"); + JSStringRelease(str); + JSStringRef src = JSStringCreateWithUTF8CString("({get a(){ throw '';}})"); + JSValueRef unstringifiableObj = JSEvaluateScript(context, src, NULL, NULL, 1, NULL); + + str = JSValueCreateJSONString(context, unstringifiableObj, 4, 0); + if (str) { + printf("FAIL: Didn't return null when attempting to serialize unserializable value.\n"); + JSStringRelease(str); + failed = 1; + } else + printf("PASS: returned null when attempting to serialize unserializable value.\n"); + + str = JSValueCreateJSONString(context, unstringifiableObj, 4, &exception); + if (str) { + printf("FAIL: Didn't return null when attempting to serialize unserializable value.\n"); + JSStringRelease(str); + failed = 1; + } else + printf("PASS: returned null when attempting to serialize unserializable value.\n"); + if (!exception) { + printf("FAIL: Did not set exception on serialisation error\n"); + failed = 1; + } else + printf("PASS: set exception on serialisation error\n"); // Conversions that throw exceptions exception = NULL; ASSERT(NULL == JSValueToObject(context, jsNull, &exception)); @@ -1244,6 +1411,13 @@ int main(int argc, char* argv[]) printf("PASS: Infinite prototype chain does not occur.\n"); + if (checkForCycleInPrototypeChain()) + printf("PASS: A cycle in a prototype chain can't be created.\n"); + else { + printf("FAIL: A cycle in a prototype chain can be created.\n"); + failed = true; + } + if (failed) { printf("FAIL: Some tests failed.\n"); return 1; |
