]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - API/JSValueRef.cpp
JavaScriptCore-1097.13.tar.gz
[apple/javascriptcore.git] / API / JSValueRef.cpp
index 2207181bd6223e833533c1a2f2b4c4ac792c834f..9b7268a2da63009ef255d00b30cb17be98ceddb6 100644 (file)
 #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
 
-JSType JSValueGetType(JSContextRef ctx, JSValueRef value)
+using namespace JSC;
+
+::JSType JSValueGetType(JSContextRef ctx, JSValueRef value)
 {
-    JSC::ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSC::JSLock lock(exec);
+    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 +67,10 @@ 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)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSValue jsValue = toJS(exec, value);
     return jsValue.isUndefined();
@@ -78,8 +79,7 @@ bool JSValueIsUndefined(JSContextRef ctx, JSValueRef value)
 bool JSValueIsNull(JSContextRef ctx, JSValueRef value)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSValue jsValue = toJS(exec, value);
     return jsValue.isNull();
@@ -88,8 +88,7 @@ bool JSValueIsNull(JSContextRef ctx, JSValueRef value)
 bool JSValueIsBoolean(JSContextRef ctx, JSValueRef value)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSValue jsValue = toJS(exec, value);
     return jsValue.isBoolean();
@@ -98,8 +97,7 @@ bool JSValueIsBoolean(JSContextRef ctx, JSValueRef value)
 bool JSValueIsNumber(JSContextRef ctx, JSValueRef value)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSValue jsValue = toJS(exec, value);
     return jsValue.isNumber();
@@ -108,8 +106,7 @@ bool JSValueIsNumber(JSContextRef ctx, JSValueRef value)
 bool JSValueIsString(JSContextRef ctx, JSValueRef value)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSValue jsValue = toJS(exec, value);
     return jsValue.isString();
@@ -118,8 +115,7 @@ bool JSValueIsString(JSContextRef ctx, JSValueRef value)
 bool JSValueIsObject(JSContextRef ctx, JSValueRef value)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSValue jsValue = toJS(exec, value);
     return jsValue.isObject();
@@ -128,16 +124,15 @@ bool JSValueIsObject(JSContextRef ctx, JSValueRef value)
 bool JSValueIsObjectOfClass(JSContextRef ctx, JSValueRef value, JSClassRef jsClass)
 {
     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<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);
+        if (o->inherits(&JSCallbackObject<JSGlobalObject>::s_info))
+            return jsCast<JSCallbackObject<JSGlobalObject>*>(o)->inherits(jsClass);
+        if (o->inherits(&JSCallbackObject<JSNonFinalObject>::s_info))
+            return jsCast<JSCallbackObject<JSNonFinalObject>*>(o)->inherits(jsClass);
     }
     return false;
 }
@@ -145,8 +140,7 @@ bool JSValueIsObjectOfClass(JSContextRef ctx, JSValueRef value, JSClassRef jsCla
 bool JSValueIsEqual(JSContextRef ctx, JSValueRef a, JSValueRef b, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSValue jsA = toJS(exec, a);
     JSValue jsB = toJS(exec, b);
@@ -163,27 +157,25 @@ bool JSValueIsEqual(JSContextRef ctx, JSValueRef a, JSValueRef b, JSValueRef* ex
 bool JSValueIsStrictEqual(JSContextRef ctx, JSValueRef a, JSValueRef b)
 {
     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)
 {
     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->methodTable()->hasInstance(jsConstructor, exec, jsValue, jsConstructor->get(exec, exec->propertyNames().prototype)); // false if an exception is thrown
     if (exec->hadException()) {
         if (exception)
             *exception = toRef(exec, exec->exception());
@@ -195,8 +187,7 @@ bool JSValueIsInstanceOfConstructor(JSContextRef ctx, JSValueRef value, JSObject
 JSValueRef JSValueMakeUndefined(JSContextRef ctx)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     return toRef(exec, jsUndefined());
 }
@@ -204,8 +195,7 @@ JSValueRef JSValueMakeUndefined(JSContextRef ctx)
 JSValueRef JSValueMakeNull(JSContextRef ctx)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     return toRef(exec, jsNull());
 }
@@ -213,8 +203,7 @@ JSValueRef JSValueMakeNull(JSContextRef ctx)
 JSValueRef JSValueMakeBoolean(JSContextRef ctx, bool value)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     return toRef(exec, jsBoolean(value));
 }
@@ -222,26 +211,59 @@ JSValueRef JSValueMakeBoolean(JSContextRef ctx, bool value)
 JSValueRef JSValueMakeNumber(JSContextRef ctx, double value)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    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<double>::quiet_NaN();
 
-    return toRef(exec, jsNumber(exec, value));
+    return toRef(exec, jsNumber(value));
 }
 
 JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     return toRef(exec, jsString(exec, string->ustring()));
 }
 
+JSValueRef JSValueMakeFromJSONString(JSContextRef ctx, JSStringRef string)
+{
+    ExecState* exec = toJS(ctx);
+    APIEntryShim entryShim(exec);
+    UString str = string->ustring();
+    if (str.is8Bit()) {
+        LiteralParser<LChar> parser(exec, str.characters8(), str.length(), StrictJSON);
+        return toRef(exec, parser.tryLiteralParse());
+    }
+    LiteralParser<UChar> parser(exec, str.characters16(), str.length(), 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);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSValue jsValue = toJS(exec, value);
     return jsValue.toBoolean(exec);
@@ -250,8 +272,7 @@ bool JSValueToBoolean(JSContextRef ctx, JSValueRef value)
 double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSValue jsValue = toJS(exec, value);
 
@@ -260,7 +281,7 @@ double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception
         if (exception)
             *exception = toRef(exec, exec->exception());
         exec->clearException();
-        number = NaN;
+        number = std::numeric_limits<double>::quiet_NaN();
     }
     return number;
 }
@@ -268,26 +289,24 @@ double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception
 JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSValue jsValue = toJS(exec, value);
     
-    RefPtr<OpaqueJSString> stringRef(OpaqueJSString::create(jsValue.toString(exec)));
+    RefPtr<OpaqueJSString> 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)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSValue jsValue = toJS(exec, value);
     
@@ -304,19 +323,17 @@ JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exce
 void JSValueProtect(JSContextRef ctx, JSValueRef value)
 {
     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)
 {
     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);
 }