X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/6fe7ccc865dc7d7541b93c5bcaf6368d2c98a174..81345200c95645a1b0d2635520f96ad55dfde63f:/API/JSValueRef.cpp?ds=inline diff --git a/API/JSValueRef.cpp b/API/JSValueRef.cpp index 9b7268a..a0be8f0 100644 --- a/API/JSValueRef.cpp +++ b/API/JSValueRef.cpp @@ -10,46 +10,68 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "JSValueRef.h" #include "APICast.h" -#include "APIShims.h" +#include "JSAPIWrapperObject.h" +#include "JSCJSValue.h" #include "JSCallbackObject.h" - -#include -#include -#include -#include -#include -#include -#include -#include +#include "JSGlobalObject.h" +#include "JSONObject.h" +#include "JSString.h" +#include "LiteralParser.h" +#include "JSCInlines.h" +#include "Protect.h" #include #include +#include #include // for std::min +#if PLATFORM(MAC) +#include +#endif + +#if ENABLE(REMOTE_INSPECTOR) +#include "JSGlobalObjectInspectorController.h" +#endif + using namespace JSC; +#if PLATFORM(MAC) +static bool evernoteHackNeeded() +{ + static const int32_t webkitLastVersionWithEvernoteHack = 35133959; + static bool hackNeeded = CFEqual(CFBundleGetIdentifier(CFBundleGetMainBundle()), CFSTR("com.evernote.Evernote")) + && NSVersionOfLinkTimeLibrary("JavaScriptCore") <= webkitLastVersionWithEvernoteHack; + + return hackNeeded; +} +#endif + ::JSType JSValueGetType(JSContextRef ctx, JSValueRef value) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return kJSTypeUndefined; + } ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); + JSLockHolder locker(exec); JSValue jsValue = toJS(exec, value); @@ -69,8 +91,12 @@ using namespace JSC; bool JSValueIsUndefined(JSContextRef ctx, JSValueRef value) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return false; + } ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); + JSLockHolder locker(exec); JSValue jsValue = toJS(exec, value); return jsValue.isUndefined(); @@ -78,8 +104,12 @@ bool JSValueIsUndefined(JSContextRef ctx, JSValueRef value) bool JSValueIsNull(JSContextRef ctx, JSValueRef value) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return false; + } ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); + JSLockHolder locker(exec); JSValue jsValue = toJS(exec, value); return jsValue.isNull(); @@ -87,8 +117,12 @@ bool JSValueIsNull(JSContextRef ctx, JSValueRef value) bool JSValueIsBoolean(JSContextRef ctx, JSValueRef value) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return false; + } ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); + JSLockHolder locker(exec); JSValue jsValue = toJS(exec, value); return jsValue.isBoolean(); @@ -96,8 +130,12 @@ bool JSValueIsBoolean(JSContextRef ctx, JSValueRef value) bool JSValueIsNumber(JSContextRef ctx, JSValueRef value) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return false; + } ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); + JSLockHolder locker(exec); JSValue jsValue = toJS(exec, value); return jsValue.isNumber(); @@ -105,8 +143,12 @@ bool JSValueIsNumber(JSContextRef ctx, JSValueRef value) bool JSValueIsString(JSContextRef ctx, JSValueRef value) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return false; + } ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); + JSLockHolder locker(exec); JSValue jsValue = toJS(exec, value); return jsValue.isString(); @@ -114,8 +156,12 @@ bool JSValueIsString(JSContextRef ctx, JSValueRef value) bool JSValueIsObject(JSContextRef ctx, JSValueRef value) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return false; + } ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); + JSLockHolder locker(exec); JSValue jsValue = toJS(exec, value); return jsValue.isObject(); @@ -123,41 +169,64 @@ bool JSValueIsObject(JSContextRef ctx, JSValueRef value) bool JSValueIsObjectOfClass(JSContextRef ctx, JSValueRef value, JSClassRef jsClass) { + if (!ctx || !jsClass) { + ASSERT_NOT_REACHED(); + return false; + } ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); + JSLockHolder locker(exec); JSValue jsValue = toJS(exec, value); if (JSObject* o = jsValue.getObject()) { - if (o->inherits(&JSCallbackObject::s_info)) + if (o->inherits(JSProxy::info())) + o = jsCast(o)->target(); + + if (o->inherits(JSCallbackObject::info())) return jsCast*>(o)->inherits(jsClass); - if (o->inherits(&JSCallbackObject::s_info)) - return jsCast*>(o)->inherits(jsClass); + if (o->inherits(JSCallbackObject::info())) + return jsCast*>(o)->inherits(jsClass); +#if JSC_OBJC_API_ENABLED + if (o->inherits(JSCallbackObject::info())) + return jsCast*>(o)->inherits(jsClass); +#endif } return false; } bool JSValueIsEqual(JSContextRef ctx, JSValueRef a, JSValueRef b, JSValueRef* exception) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return false; + } ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); + JSLockHolder locker(exec); JSValue jsA = toJS(exec, a); JSValue jsB = toJS(exec, b); bool result = JSValue::equal(exec, jsA, jsB); // false if an exception is thrown if (exec->hadException()) { + JSValue exceptionValue = exec->exception(); if (exception) - *exception = toRef(exec, exec->exception()); + *exception = toRef(exec, exceptionValue); exec->clearException(); +#if ENABLE(REMOTE_INSPECTOR) + exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue); +#endif } return result; } bool JSValueIsStrictEqual(JSContextRef ctx, JSValueRef a, JSValueRef b) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return false; + } ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); + JSLockHolder locker(exec); JSValue jsA = toJS(exec, a); JSValue jsB = toJS(exec, b); @@ -167,94 +236,129 @@ bool JSValueIsStrictEqual(JSContextRef ctx, JSValueRef a, JSValueRef b) bool JSValueIsInstanceOfConstructor(JSContextRef ctx, JSValueRef value, JSObjectRef constructor, JSValueRef* exception) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return false; + } ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); + JSLockHolder locker(exec); JSValue jsValue = toJS(exec, value); JSObject* jsConstructor = toJS(constructor); if (!jsConstructor->structure()->typeInfo().implementsHasInstance()) return false; - bool result = jsConstructor->methodTable()->hasInstance(jsConstructor, exec, jsValue, jsConstructor->get(exec, exec->propertyNames().prototype)); // false if an exception is thrown + bool result = jsConstructor->hasInstance(exec, jsValue); // false if an exception is thrown if (exec->hadException()) { + JSValue exceptionValue = exec->exception(); if (exception) - *exception = toRef(exec, exec->exception()); + *exception = toRef(exec, exceptionValue); exec->clearException(); +#if ENABLE(REMOTE_INSPECTOR) + exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue); +#endif } return result; } JSValueRef JSValueMakeUndefined(JSContextRef ctx) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return 0; + } ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); + JSLockHolder locker(exec); return toRef(exec, jsUndefined()); } JSValueRef JSValueMakeNull(JSContextRef ctx) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return 0; + } ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); + JSLockHolder locker(exec); return toRef(exec, jsNull()); } JSValueRef JSValueMakeBoolean(JSContextRef ctx, bool value) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return 0; + } ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); + JSLockHolder locker(exec); return toRef(exec, jsBoolean(value)); } JSValueRef JSValueMakeNumber(JSContextRef ctx, double value) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return 0; + } ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); - - // Our JSValue representation relies on a standard bit pattern for NaN. NaNs - // generated internally to JavaScriptCore naturally have that representation, - // but an external NaN might not. - if (isnan(value)) - value = std::numeric_limits::quiet_NaN(); + JSLockHolder locker(exec); - return toRef(exec, jsNumber(value)); + return toRef(exec, jsNumber(purifyNaN(value))); } JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return 0; + } ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); + JSLockHolder locker(exec); - return toRef(exec, jsString(exec, string->ustring())); + return toRef(exec, jsString(exec, string->string())); } JSValueRef JSValueMakeFromJSONString(JSContextRef ctx, JSStringRef string) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return 0; + } ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); - UString str = string->ustring(); - if (str.is8Bit()) { - LiteralParser parser(exec, str.characters8(), str.length(), StrictJSON); + JSLockHolder locker(exec); + String str = string->string(); + unsigned length = str.length(); + if (!length || str.is8Bit()) { + LiteralParser parser(exec, str.characters8(), length, StrictJSON); return toRef(exec, parser.tryLiteralParse()); } - LiteralParser parser(exec, str.characters16(), str.length(), StrictJSON); + LiteralParser parser(exec, str.characters16(), length, StrictJSON); return toRef(exec, parser.tryLiteralParse()); } JSStringRef JSValueCreateJSONString(JSContextRef ctx, JSValueRef apiValue, unsigned indent, JSValueRef* exception) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return 0; + } ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); + JSLockHolder locker(exec); JSValue value = toJS(exec, apiValue); - UString result = JSONStringify(exec, value, indent); + String result = JSONStringify(exec, value, indent); if (exception) *exception = 0; if (exec->hadException()) { + JSValue exceptionValue = exec->exception(); if (exception) - *exception = toRef(exec, exec->exception()); + *exception = toRef(exec, exceptionValue); exec->clearException(); +#if ENABLE(REMOTE_INSPECTOR) + exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue); +#endif return 0; } return OpaqueJSString::create(result).leakRef(); @@ -262,8 +366,12 @@ JSStringRef JSValueCreateJSONString(JSContextRef ctx, JSValueRef apiValue, unsig bool JSValueToBoolean(JSContextRef ctx, JSValueRef value) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return false; + } ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); + JSLockHolder locker(exec); JSValue jsValue = toJS(exec, value); return jsValue.toBoolean(exec); @@ -271,33 +379,49 @@ bool JSValueToBoolean(JSContextRef ctx, JSValueRef value) double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return PNaN; + } ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); + JSLockHolder locker(exec); JSValue jsValue = toJS(exec, value); double number = jsValue.toNumber(exec); if (exec->hadException()) { + JSValue exceptionValue = exec->exception(); if (exception) - *exception = toRef(exec, exec->exception()); + *exception = toRef(exec, exceptionValue); exec->clearException(); - number = std::numeric_limits::quiet_NaN(); +#if ENABLE(REMOTE_INSPECTOR) + exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue); +#endif + number = PNaN; } return number; } JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef* exception) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return 0; + } ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); + JSLockHolder locker(exec); JSValue jsValue = toJS(exec, value); RefPtr stringRef(OpaqueJSString::create(jsValue.toString(exec)->value(exec))); if (exec->hadException()) { + JSValue exceptionValue = exec->exception(); if (exception) - *exception = toRef(exec, exec->exception()); + *exception = toRef(exec, exceptionValue); exec->clearException(); +#if ENABLE(REMOTE_INSPECTOR) + exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue); +#endif stringRef.clear(); } return stringRef.release().leakRef(); @@ -305,25 +429,37 @@ JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef* JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exception) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return 0; + } ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); + JSLockHolder locker(exec); JSValue jsValue = toJS(exec, value); JSObjectRef objectRef = toRef(jsValue.toObject(exec)); if (exec->hadException()) { + JSValue exceptionValue = exec->exception(); if (exception) - *exception = toRef(exec, exec->exception()); + *exception = toRef(exec, exceptionValue); exec->clearException(); +#if ENABLE(REMOTE_INSPECTOR) + exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue); +#endif objectRef = 0; } return objectRef; -} +} void JSValueProtect(JSContextRef ctx, JSValueRef value) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return; + } ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); + JSLockHolder locker(exec); JSValue jsValue = toJSForGC(exec, value); gcProtect(jsValue); @@ -331,8 +467,13 @@ void JSValueProtect(JSContextRef ctx, JSValueRef value) void JSValueUnprotect(JSContextRef ctx, JSValueRef value) { +#if PLATFORM(MAC) + if ((!value || !ctx) && evernoteHackNeeded()) + return; +#endif + ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); + JSLockHolder locker(exec); JSValue jsValue = toJSForGC(exec, value); gcUnprotect(jsValue);