X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/ba379fdc102753d6be2c4d937058fe40257329fe..93a3786624b2768d89bfa27e46598dc64e2fb70a:/API/JSValueRef.cpp diff --git a/API/JSValueRef.cpp b/API/JSValueRef.cpp index 2207181..81a2db7 100644 --- a/API/JSValueRef.cpp +++ b/API/JSValueRef.cpp @@ -26,28 +26,52 @@ #include "config.h" #include "JSValueRef.h" -#include #include "APICast.h" +#include "APIShims.h" +#include "JSAPIWrapperObject.h" #include "JSCallbackObject.h" +#include #include +#include #include +#include #include #include -#include -#include #include +#include +#include #include // for std::min -JSType JSValueGetType(JSContextRef ctx, JSValueRef value) +#if PLATFORM(MAC) +#include +#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) { - JSC::ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSC::JSLock lock(exec); + if (!ctx) { + ASSERT_NOT_REACHED(); + return kJSTypeUndefined; + } + ExecState* exec = toJS(ctx); + APIEntryShim entryShim(exec); - JSC::JSValue jsValue = toJS(exec, value); + JSValue jsValue = toJS(exec, value); if (jsValue.isUndefined()) return kJSTypeUndefined; @@ -63,13 +87,14 @@ JSType JSValueGetType(JSContextRef ctx, JSValueRef value) return kJSTypeObject; } -using namespace JSC; // placed here to avoid conflict between JSC::JSType and JSType, above. - bool JSValueIsUndefined(JSContextRef ctx, JSValueRef value) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return false; + } ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); return jsValue.isUndefined(); @@ -77,9 +102,12 @@ bool JSValueIsUndefined(JSContextRef ctx, JSValueRef value) bool JSValueIsNull(JSContextRef ctx, JSValueRef value) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return false; + } ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); return jsValue.isNull(); @@ -87,9 +115,12 @@ bool JSValueIsNull(JSContextRef ctx, JSValueRef value) bool JSValueIsBoolean(JSContextRef ctx, JSValueRef value) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return false; + } ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); return jsValue.isBoolean(); @@ -97,9 +128,12 @@ bool JSValueIsBoolean(JSContextRef ctx, JSValueRef value) bool JSValueIsNumber(JSContextRef ctx, JSValueRef value) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return false; + } ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); return jsValue.isNumber(); @@ -107,9 +141,12 @@ bool JSValueIsNumber(JSContextRef ctx, JSValueRef value) bool JSValueIsString(JSContextRef ctx, JSValueRef value) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return false; + } ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); return jsValue.isString(); @@ -117,9 +154,12 @@ bool JSValueIsString(JSContextRef ctx, JSValueRef value) bool JSValueIsObject(JSContextRef ctx, JSValueRef value) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return false; + } ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); return jsValue.isObject(); @@ -127,26 +167,36 @@ 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); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); if (JSObject* o = jsValue.getObject()) { - if (o->inherits(&JSCallbackObject::info)) - return static_cast*>(o)->inherits(jsClass); - else if (o->inherits(&JSCallbackObject::info)) - return static_cast*>(o)->inherits(jsClass); + if (o->inherits(&JSCallbackObject::s_info)) + return jsCast*>(o)->inherits(jsClass); + if (o->inherits(&JSCallbackObject::s_info)) + return jsCast*>(o)->inherits(jsClass); +#if JSC_OBJC_API_ENABLED + if (o->inherits(&JSCallbackObject::s_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); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsA = toJS(exec, a); JSValue jsB = toJS(exec, b); @@ -162,28 +212,34 @@ bool JSValueIsEqual(JSContextRef ctx, JSValueRef a, JSValueRef b, JSValueRef* ex bool JSValueIsStrictEqual(JSContextRef ctx, JSValueRef a, JSValueRef b) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return false; + } ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsA = toJS(exec, a); JSValue jsB = toJS(exec, b); - return JSValue::strictEqual(jsA, jsB); + return JSValue::strictEqual(exec, jsA, jsB); } bool JSValueIsInstanceOfConstructor(JSContextRef ctx, JSValueRef value, JSObjectRef constructor, JSValueRef* exception) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return false; + } ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); JSObject* jsConstructor = toJS(constructor); if (!jsConstructor->structure()->typeInfo().implementsHasInstance()) return false; - bool result = jsConstructor->hasInstance(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()) { if (exception) *exception = toRef(exec, exec->exception()); @@ -194,54 +250,117 @@ bool JSValueIsInstanceOfConstructor(JSContextRef ctx, JSValueRef value, JSObject JSValueRef JSValueMakeUndefined(JSContextRef ctx) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return 0; + } ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); return toRef(exec, jsUndefined()); } JSValueRef JSValueMakeNull(JSContextRef ctx) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return 0; + } ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); return toRef(exec, jsNull()); } JSValueRef JSValueMakeBoolean(JSContextRef ctx, bool value) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return 0; + } ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); return toRef(exec, jsBoolean(value)); } JSValueRef JSValueMakeNumber(JSContextRef ctx, double value) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return 0; + } ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); - return toRef(exec, jsNumber(exec, value)); + // 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 (std::isnan(value)) + value = QNaN; + + return toRef(exec, jsNumber(value)); } JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return 0; + } ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); + + return toRef(exec, jsString(exec, string->string())); +} - return toRef(exec, jsString(exec, string->ustring())); +JSValueRef JSValueMakeFromJSONString(JSContextRef ctx, JSStringRef string) +{ + if (!ctx) { + ASSERT_NOT_REACHED(); + return 0; + } + ExecState* exec = toJS(ctx); + APIEntryShim entryShim(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.characters(), 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); + JSValue value = toJS(exec, apiValue); + String 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) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return false; + } ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); return jsValue.toBoolean(exec); @@ -249,9 +368,12 @@ bool JSValueToBoolean(JSContextRef ctx, JSValueRef value) double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return QNaN; + } ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); @@ -260,34 +382,40 @@ double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception if (exception) *exception = toRef(exec, exec->exception()); exec->clearException(); - number = NaN; + number = QNaN; } return number; } JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef* exception) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return 0; + } ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); - RefPtr stringRef(OpaqueJSString::create(jsValue.toString(exec))); + RefPtr stringRef(OpaqueJSString::create(jsValue.toString(exec)->value(exec))); if (exec->hadException()) { if (exception) *exception = toRef(exec, exec->exception()); exec->clearException(); stringRef.clear(); } - return stringRef.release().releaseRef(); + return stringRef.release().leakRef(); } JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exception) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return 0; + } ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); @@ -303,20 +431,27 @@ JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exce void JSValueProtect(JSContextRef ctx, JSValueRef value) { + if (!ctx) { + ASSERT_NOT_REACHED(); + return; + } ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); - JSValue jsValue = toJS(exec, value); + JSValue jsValue = toJSForGC(exec, value); gcProtect(jsValue); } void JSValueUnprotect(JSContextRef ctx, JSValueRef value) { +#if PLATFORM(MAC) + if ((!value || !ctx) && evernoteHackNeeded()) + return; +#endif + ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); - JSValue jsValue = toJS(exec, value); + JSValue jsValue = toJSForGC(exec, value); gcUnprotect(jsValue); }