summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/API/tests
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/JavaScriptCore/API/tests
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/JavaScriptCore/API/tests')
-rw-r--r--Source/JavaScriptCore/API/tests/CompareAndSwapTest.cpp118
-rw-r--r--Source/JavaScriptCore/API/tests/CompareAndSwapTest.h37
-rw-r--r--Source/JavaScriptCore/API/tests/CurrentThisInsideBlockGetterTest.h34
-rw-r--r--Source/JavaScriptCore/API/tests/CustomGlobalObjectClassTest.c145
-rw-r--r--Source/JavaScriptCore/API/tests/CustomGlobalObjectClassTest.h30
-rw-r--r--Source/JavaScriptCore/API/tests/DateTests.h32
-rw-r--r--Source/JavaScriptCore/API/tests/ExecutionTimeLimitTest.cpp374
-rw-r--r--Source/JavaScriptCore/API/tests/ExecutionTimeLimitTest.h37
-rw-r--r--Source/JavaScriptCore/API/tests/FunctionOverridesTest.cpp91
-rw-r--r--Source/JavaScriptCore/API/tests/FunctionOverridesTest.h37
-rw-r--r--Source/JavaScriptCore/API/tests/GlobalContextWithFinalizerTest.cpp55
-rw-r--r--Source/JavaScriptCore/API/tests/GlobalContextWithFinalizerTest.h39
-rw-r--r--Source/JavaScriptCore/API/tests/JSExportTests.h34
-rw-r--r--Source/JavaScriptCore/API/tests/JSNode.c8
-rw-r--r--Source/JavaScriptCore/API/tests/JSNode.h11
-rw-r--r--Source/JavaScriptCore/API/tests/JSNodeList.c8
-rw-r--r--Source/JavaScriptCore/API/tests/JSNodeList.h11
-rw-r--r--Source/JavaScriptCore/API/tests/JSONParseTest.cpp69
-rw-r--r--Source/JavaScriptCore/API/tests/JSONParseTest.h36
-rw-r--r--Source/JavaScriptCore/API/tests/Node.c6
-rw-r--r--Source/JavaScriptCore/API/tests/Node.h11
-rw-r--r--Source/JavaScriptCore/API/tests/NodeList.c6
-rw-r--r--Source/JavaScriptCore/API/tests/NodeList.h11
-rw-r--r--Source/JavaScriptCore/API/tests/PingPongStackOverflowTest.cpp182
-rw-r--r--Source/JavaScriptCore/API/tests/PingPongStackOverflowTest.h36
-rw-r--r--Source/JavaScriptCore/API/tests/Regress141275.h34
-rw-r--r--Source/JavaScriptCore/API/tests/Regress141809.h34
-rw-r--r--Source/JavaScriptCore/API/tests/TypedArrayCTest.cpp268
-rw-r--r--Source/JavaScriptCore/API/tests/TypedArrayCTest.h36
-rw-r--r--Source/JavaScriptCore/API/tests/minidom.c8
-rw-r--r--Source/JavaScriptCore/API/tests/minidom.html9
-rw-r--r--Source/JavaScriptCore/API/tests/minidom.js110
-rw-r--r--Source/JavaScriptCore/API/tests/testapi-function-overrides.js16
-rw-r--r--Source/JavaScriptCore/API/tests/testapi.c1989
-rw-r--r--Source/JavaScriptCore/API/tests/testapi.js307
35 files changed, 4226 insertions, 43 deletions
diff --git a/Source/JavaScriptCore/API/tests/CompareAndSwapTest.cpp b/Source/JavaScriptCore/API/tests/CompareAndSwapTest.cpp
new file mode 100644
index 000000000..e78086c3a
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/CompareAndSwapTest.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2015 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 "CompareAndSwapTest.h"
+
+#include <stdio.h>
+#include <wtf/Atomics.h>
+#include <wtf/Threading.h>
+
+class Bitmap {
+public:
+ Bitmap() { clearAll(); }
+
+ inline void clearAll();
+ inline bool concurrentTestAndSet(size_t n);
+ inline size_t numBits() const { return words * wordSize; }
+
+private:
+ static const size_t Size = 4096*10;
+
+ static const unsigned wordSize = sizeof(uint8_t) * 8;
+ static const unsigned words = (Size + wordSize - 1) / wordSize;
+ static const uint8_t one = 1;
+
+ uint8_t bits[words];
+};
+
+inline void Bitmap::clearAll()
+{
+ memset(&bits, 0, sizeof(bits));
+}
+
+inline bool Bitmap::concurrentTestAndSet(size_t n)
+{
+ uint8_t mask = one << (n % wordSize);
+ size_t index = n / wordSize;
+ uint8_t* wordPtr = &bits[index];
+ uint8_t oldValue;
+ do {
+ oldValue = *wordPtr;
+ if (oldValue & mask)
+ return true;
+ } while (!WTF::atomicCompareExchangeWeakRelaxed(wordPtr, oldValue, static_cast<uint8_t>(oldValue | mask)));
+ return false;
+}
+
+struct Data {
+ Bitmap* bitmap;
+ int id;
+ int numThreads;
+};
+
+static void setBitThreadFunc(void* p)
+{
+ Data* data = reinterpret_cast<Data*>(p);
+ Bitmap* bitmap = data->bitmap;
+ size_t numBits = bitmap->numBits();
+
+ // The computed start index here is heuristic that seems to maximize (anecdotally)
+ // the chance for the CAS issue to manifest.
+ size_t start = (numBits * (data->numThreads - data->id)) / data->numThreads;
+
+ printf(" started Thread %d\n", data->id);
+ for (size_t i = start; i < numBits; i++)
+ while (!bitmap->concurrentTestAndSet(i)) { }
+ for (size_t i = 0; i < start; i++)
+ while (!bitmap->concurrentTestAndSet(i)) { }
+
+ printf(" finished Thread %d\n", data->id);
+}
+
+void testCompareAndSwap()
+{
+ Bitmap bitmap;
+ const int numThreads = 5;
+ ThreadIdentifier threadIDs[numThreads];
+ Data data[numThreads];
+
+ WTF::initializeThreading();
+
+ printf("Starting %d threads for CompareAndSwap test. Test should complete without hanging.\n", numThreads);
+ for (int i = 0; i < numThreads; i++) {
+ data[i].bitmap = &bitmap;
+ data[i].id = i;
+ data[i].numThreads = numThreads;
+ std::function<void()> threadFunc = std::bind(setBitThreadFunc, &data[i]);
+ threadIDs[i] = createThread("setBitThreadFunc", threadFunc);
+ }
+
+ printf("Waiting for %d threads to join\n", numThreads);
+ for (int i = 0; i < numThreads; i++)
+ waitForThreadCompletion(threadIDs[i]);
+
+ printf("PASS: CompareAndSwap test completed without a hang\n");
+}
diff --git a/Source/JavaScriptCore/API/tests/CompareAndSwapTest.h b/Source/JavaScriptCore/API/tests/CompareAndSwapTest.h
new file mode 100644
index 000000000..4a1fc59c6
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/CompareAndSwapTest.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Regression test for webkit.org/b/142513 */
+void testCompareAndSwap();
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
diff --git a/Source/JavaScriptCore/API/tests/CurrentThisInsideBlockGetterTest.h b/Source/JavaScriptCore/API/tests/CurrentThisInsideBlockGetterTest.h
new file mode 100644
index 000000000..ab68f8057
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/CurrentThisInsideBlockGetterTest.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#pragma once
+
+#include <JavaScriptCore/JavaScriptCore.h>
+
+#if JSC_OBJC_API_ENABLED
+
+void currentThisInsideBlockGetterTest();
+
+#endif // JSC_OBJC_API_ENABLED
diff --git a/Source/JavaScriptCore/API/tests/CustomGlobalObjectClassTest.c b/Source/JavaScriptCore/API/tests/CustomGlobalObjectClassTest.c
new file mode 100644
index 000000000..62e63978e
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/CustomGlobalObjectClassTest.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2014 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. ``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
+ * 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 "CustomGlobalObjectClassTest.h"
+
+#include <JavaScriptCore/JSObjectRefPrivate.h>
+#include <JavaScriptCore/JavaScriptCore.h>
+#include <stdio.h>
+
+extern bool assertTrue(bool value, const char* message);
+
+static bool executedCallback = false;
+
+static JSValueRef jsDoSomething(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argc, const JSValueRef args[], JSValueRef* exception)
+{
+ (void)function;
+ (void)thisObject;
+ (void)argc;
+ (void)args;
+ (void)exception;
+ executedCallback = true;
+ return JSValueMakeNull(ctx);
+}
+
+static JSStaticFunction bridgedFunctions[] = {
+ {"doSomething", jsDoSomething, kJSPropertyAttributeDontDelete},
+ {0, 0, 0},
+};
+
+static JSClassRef bridgedObjectClass = NULL;
+static JSClassDefinition bridgedClassDef;
+
+static JSClassRef jsClassRef()
+{
+ if (!bridgedObjectClass) {
+ bridgedClassDef = kJSClassDefinitionEmpty;
+ bridgedClassDef.className = "BridgedObject";
+ bridgedClassDef.staticFunctions = bridgedFunctions;
+ bridgedObjectClass = JSClassCreate(&bridgedClassDef);
+ }
+ return bridgedObjectClass;
+}
+
+void customGlobalObjectClassTest()
+{
+ JSClassRef bridgedObjectJsClassRef = jsClassRef();
+ JSGlobalContextRef globalContext = JSGlobalContextCreate(bridgedObjectJsClassRef);
+
+ JSObjectRef globalObj = JSContextGetGlobalObject(globalContext);
+
+ JSPropertyNameArrayRef propertyNames = JSObjectCopyPropertyNames(globalContext, globalObj);
+ size_t propertyCount = JSPropertyNameArrayGetCount(propertyNames);
+ assertTrue(propertyCount == 1, "Property count == 1");
+
+ JSStringRef propertyNameRef = JSPropertyNameArrayGetNameAtIndex(propertyNames, 0);
+ size_t propertyNameLength = JSStringGetLength(propertyNameRef);
+ size_t bufferSize = sizeof(char) * (propertyNameLength + 1);
+ char* buffer = (char*)malloc(bufferSize);
+ JSStringGetUTF8CString(propertyNameRef, buffer, bufferSize);
+ buffer[propertyNameLength] = '\0';
+ assertTrue(!strncmp(buffer, "doSomething", propertyNameLength), "First property name is doSomething");
+ free(buffer);
+
+ bool hasMethod = JSObjectHasProperty(globalContext, globalObj, propertyNameRef);
+ assertTrue(hasMethod, "Property found by name");
+
+ JSValueRef doSomethingProperty =
+ JSObjectGetProperty(globalContext, globalObj, propertyNameRef, NULL);
+ assertTrue(!JSValueIsUndefined(globalContext, doSomethingProperty), "Property is defined");
+
+ bool globalObjectClassMatchesClassRef = JSValueIsObjectOfClass(globalContext, globalObj, bridgedObjectJsClassRef);
+ assertTrue(globalObjectClassMatchesClassRef, "Global object is the right class");
+
+ JSStringRef script = JSStringCreateWithUTF8CString("doSomething();");
+ JSEvaluateScript(globalContext, script, NULL, NULL, 1, NULL);
+ JSStringRelease(script);
+
+ assertTrue(executedCallback, "Executed custom global object callback");
+}
+
+void globalObjectSetPrototypeTest()
+{
+ JSClassDefinition definition = kJSClassDefinitionEmpty;
+ definition.className = "Global";
+ JSClassRef global = JSClassCreate(&definition);
+ JSGlobalContextRef context = JSGlobalContextCreate(global);
+ JSObjectRef object = JSContextGetGlobalObject(context);
+
+ JSObjectRef above = JSObjectMake(context, 0, 0);
+ JSStringRef test = JSStringCreateWithUTF8CString("test");
+ JSValueRef value = JSValueMakeString(context, test);
+ JSObjectSetProperty(context, above, test, value, kJSPropertyAttributeDontEnum, 0);
+
+ JSObjectSetPrototype(context, object, above);
+ JSStringRef script = JSStringCreateWithUTF8CString("test === \"test\"");
+ JSValueRef result = JSEvaluateScript(context, script, 0, 0, 0, 0);
+
+ assertTrue(JSValueToBoolean(context, result), "test === \"test\"");
+
+ JSStringRelease(test);
+ JSStringRelease(script);
+}
+
+void globalObjectPrivatePropertyTest()
+{
+ JSClassDefinition definition = kJSClassDefinitionEmpty;
+ definition.className = "Global";
+ JSClassRef global = JSClassCreate(&definition);
+ JSGlobalContextRef context = JSGlobalContextCreate(global);
+ JSObjectRef globalObject = JSContextGetGlobalObject(context);
+
+ JSStringRef privateName = JSStringCreateWithUTF8CString("private");
+ JSValueRef privateValue = JSValueMakeString(context, privateName);
+ assertTrue(JSObjectSetPrivateProperty(context, globalObject, privateName, privateValue), "JSObjectSetPrivateProperty succeeded");
+ JSValueRef result = JSObjectGetPrivateProperty(context, globalObject, privateName);
+ assertTrue(JSValueIsStrictEqual(context, privateValue, result), "privateValue === \"private\"");
+
+ assertTrue(JSObjectDeletePrivateProperty(context, globalObject, privateName), "JSObjectDeletePrivateProperty succeeded");
+ result = JSObjectGetPrivateProperty(context, globalObject, privateName);
+ assertTrue(JSValueIsNull(context, result), "Deleted private property is indeed no longer present");
+
+ JSStringRelease(privateName);
+}
diff --git a/Source/JavaScriptCore/API/tests/CustomGlobalObjectClassTest.h b/Source/JavaScriptCore/API/tests/CustomGlobalObjectClassTest.h
new file mode 100644
index 000000000..3d2a520a7
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/CustomGlobalObjectClassTest.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2014 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. ``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
+ * 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.
+ */
+
+#pragma once
+
+void customGlobalObjectClassTest(void);
+void globalObjectSetPrototypeTest(void);
+void globalObjectPrivatePropertyTest(void);
diff --git a/Source/JavaScriptCore/API/tests/DateTests.h b/Source/JavaScriptCore/API/tests/DateTests.h
new file mode 100644
index 000000000..eeb47a165
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/DateTests.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#import <JavaScriptCore/JavaScriptCore.h>
+
+#if JSC_OBJC_API_ENABLED
+
+void runDateTests();
+
+#endif // JSC_OBJC_API_ENABLED
diff --git a/Source/JavaScriptCore/API/tests/ExecutionTimeLimitTest.cpp b/Source/JavaScriptCore/API/tests/ExecutionTimeLimitTest.cpp
new file mode 100644
index 000000000..d5e53243b
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/ExecutionTimeLimitTest.cpp
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 2015 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 "ExecutionTimeLimitTest.h"
+
+#include "InitializeThreading.h"
+#include "JSContextRefPrivate.h"
+#include "JavaScriptCore.h"
+#include "Options.h"
+#include <chrono>
+#include <wtf/CurrentTime.h>
+#include <wtf/text/StringBuilder.h>
+
+using namespace std::chrono;
+using JSC::Options;
+
+static JSGlobalContextRef context = nullptr;
+
+static JSValueRef currentCPUTimeAsJSFunctionCallback(JSContextRef ctx, JSObjectRef functionObject, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ UNUSED_PARAM(functionObject);
+ UNUSED_PARAM(thisObject);
+ UNUSED_PARAM(argumentCount);
+ UNUSED_PARAM(arguments);
+ UNUSED_PARAM(exception);
+
+ ASSERT(JSContextGetGlobalContext(ctx) == context);
+ return JSValueMakeNumber(ctx, currentCPUTime().count() / 1000000.);
+}
+
+bool shouldTerminateCallbackWasCalled = false;
+static bool shouldTerminateCallback(JSContextRef, void*)
+{
+ shouldTerminateCallbackWasCalled = true;
+ return true;
+}
+
+bool cancelTerminateCallbackWasCalled = false;
+static bool cancelTerminateCallback(JSContextRef, void*)
+{
+ cancelTerminateCallbackWasCalled = true;
+ return false;
+}
+
+int extendTerminateCallbackCalled = 0;
+static bool extendTerminateCallback(JSContextRef ctx, void*)
+{
+ extendTerminateCallbackCalled++;
+ if (extendTerminateCallbackCalled == 1) {
+ JSContextGroupRef contextGroup = JSContextGetGroup(ctx);
+ JSContextGroupSetExecutionTimeLimit(contextGroup, .200f, extendTerminateCallback, 0);
+ return false;
+ }
+ return true;
+}
+
+struct TierOptions {
+ const char* tier;
+ unsigned timeLimitAdjustmentMillis;
+ const char* optionsStr;
+};
+
+static void testResetAfterTimeout(bool& failed)
+{
+ JSValueRef v = nullptr;
+ JSValueRef exception = nullptr;
+ const char* reentryScript = "100";
+ JSStringRef script = JSStringCreateWithUTF8CString(reentryScript);
+ v = JSEvaluateScript(context, script, nullptr, nullptr, 1, &exception);
+ if (exception) {
+ printf("FAIL: Watchdog timeout was not reset.\n");
+ failed = true;
+ } else if (!JSValueIsNumber(context, v) || JSValueToNumber(context, v, nullptr) != 100) {
+ printf("FAIL: Script result is not as expected.\n");
+ failed = true;
+ }
+}
+
+int testExecutionTimeLimit()
+{
+ static const TierOptions tierOptionsList[] = {
+ { "LLINT", 0, "--useConcurrentJIT=false --useLLInt=true --useJIT=false" },
+ { "Baseline", 0, "--useConcurrentJIT=false --useLLInt=true --useJIT=true --useDFGJIT=false" },
+ { "DFG", 0, "--useConcurrentJIT=false --useLLInt=true --useJIT=true --useDFGJIT=true --useFTLJIT=false" },
+ { "FTL", 200, "--useConcurrentJIT=false --useLLInt=true --useJIT=true --useDFGJIT=true --useFTLJIT=true" },
+ };
+
+ bool failed = false;
+
+ JSC::initializeThreading();
+ Options::initialize(); // Ensure options is initialized first.
+
+ for (auto tierOptions : tierOptionsList) {
+ StringBuilder savedOptionsBuilder;
+ Options::dumpAllOptionsInALine(savedOptionsBuilder);
+
+ Options::setOptions(tierOptions.optionsStr);
+
+ unsigned tierAdjustmentMillis = tierOptions.timeLimitAdjustmentMillis;
+ double timeLimit;
+
+ context = JSGlobalContextCreateInGroup(nullptr, nullptr);
+
+ JSContextGroupRef contextGroup = JSContextGetGroup(context);
+ JSObjectRef globalObject = JSContextGetGlobalObject(context);
+ ASSERT(JSValueIsObject(context, globalObject));
+
+ JSValueRef exception = nullptr;
+
+ JSStringRef currentCPUTimeStr = JSStringCreateWithUTF8CString("currentCPUTime");
+ JSObjectRef currentCPUTimeFunction = JSObjectMakeFunctionWithCallback(context, currentCPUTimeStr, currentCPUTimeAsJSFunctionCallback);
+ JSObjectSetProperty(context, globalObject, currentCPUTimeStr, currentCPUTimeFunction, kJSPropertyAttributeNone, nullptr);
+ JSStringRelease(currentCPUTimeStr);
+
+ /* Test script timeout: */
+ timeLimit = (100 + tierAdjustmentMillis) / 1000.0;
+ JSContextGroupSetExecutionTimeLimit(contextGroup, timeLimit, shouldTerminateCallback, 0);
+ {
+ unsigned timeAfterWatchdogShouldHaveFired = 300 + tierAdjustmentMillis;
+
+ StringBuilder scriptBuilder;
+ scriptBuilder.appendLiteral("function foo() { var startTime = currentCPUTime(); while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > ");
+ scriptBuilder.appendNumber(timeAfterWatchdogShouldHaveFired / 1000.0);
+ scriptBuilder.appendLiteral(") break; } } foo();");
+
+ JSStringRef script = JSStringCreateWithUTF8CString(scriptBuilder.toString().utf8().data());
+ exception = nullptr;
+ shouldTerminateCallbackWasCalled = false;
+ auto startTime = currentCPUTime();
+ JSEvaluateScript(context, script, nullptr, nullptr, 1, &exception);
+ auto endTime = currentCPUTime();
+
+ if (((endTime - startTime) < milliseconds(timeAfterWatchdogShouldHaveFired)) && shouldTerminateCallbackWasCalled)
+ printf("PASS: %s script timed out as expected.\n", tierOptions.tier);
+ else {
+ if ((endTime - startTime) >= milliseconds(timeAfterWatchdogShouldHaveFired))
+ printf("FAIL: %s script did not time out as expected.\n", tierOptions.tier);
+ if (!shouldTerminateCallbackWasCalled)
+ printf("FAIL: %s script timeout callback was not called.\n", tierOptions.tier);
+ failed = true;
+ }
+
+ if (!exception) {
+ printf("FAIL: %s TerminatedExecutionException was not thrown.\n", tierOptions.tier);
+ failed = true;
+ }
+
+ testResetAfterTimeout(failed);
+ }
+
+ /* Test script timeout with tail calls: */
+ timeLimit = (100 + tierAdjustmentMillis) / 1000.0;
+ JSContextGroupSetExecutionTimeLimit(contextGroup, timeLimit, shouldTerminateCallback, 0);
+ {
+ unsigned timeAfterWatchdogShouldHaveFired = 300 + tierAdjustmentMillis;
+
+ StringBuilder scriptBuilder;
+ scriptBuilder.appendLiteral("var startTime = currentCPUTime();"
+ "function recurse(i) {"
+ "'use strict';"
+ "if (i % 1000 === 0) {"
+ "if (currentCPUTime() - startTime >");
+ scriptBuilder.appendNumber(timeAfterWatchdogShouldHaveFired / 1000.0);
+ scriptBuilder.appendLiteral(" ) { return; }");
+ scriptBuilder.appendLiteral(" }");
+ scriptBuilder.appendLiteral(" return recurse(i + 1); }");
+ scriptBuilder.appendLiteral("recurse(0);");
+
+ JSStringRef script = JSStringCreateWithUTF8CString(scriptBuilder.toString().utf8().data());
+ exception = nullptr;
+ shouldTerminateCallbackWasCalled = false;
+ auto startTime = currentCPUTime();
+ JSEvaluateScript(context, script, nullptr, nullptr, 1, &exception);
+ auto endTime = currentCPUTime();
+
+ if (((endTime - startTime) < milliseconds(timeAfterWatchdogShouldHaveFired)) && shouldTerminateCallbackWasCalled)
+ printf("PASS: %s script with infinite tail calls timed out as expected .\n", tierOptions.tier);
+ else {
+ if ((endTime - startTime) >= milliseconds(timeAfterWatchdogShouldHaveFired))
+ printf("FAIL: %s script with infinite tail calls did not time out as expected.\n", tierOptions.tier);
+ if (!shouldTerminateCallbackWasCalled)
+ printf("FAIL: %s script with infinite tail calls' timeout callback was not called.\n", tierOptions.tier);
+ failed = true;
+ }
+
+ if (!exception) {
+ printf("FAIL: %s TerminatedExecutionException was not thrown.\n", tierOptions.tier);
+ failed = true;
+ }
+
+ testResetAfterTimeout(failed);
+ }
+
+ /* Test the script timeout's TerminatedExecutionException should NOT be catchable: */
+ timeLimit = (100 + tierAdjustmentMillis) / 1000.0;
+ JSContextGroupSetExecutionTimeLimit(contextGroup, timeLimit, shouldTerminateCallback, 0);
+ {
+ unsigned timeAfterWatchdogShouldHaveFired = 300 + tierAdjustmentMillis;
+
+ StringBuilder scriptBuilder;
+ scriptBuilder.appendLiteral("function foo() { var startTime = currentCPUTime(); try { while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > ");
+ scriptBuilder.appendNumber(timeAfterWatchdogShouldHaveFired / 1000.0);
+ scriptBuilder.appendLiteral(") break; } } catch(e) { } } foo();");
+
+ JSStringRef script = JSStringCreateWithUTF8CString(scriptBuilder.toString().utf8().data());
+ exception = nullptr;
+ shouldTerminateCallbackWasCalled = false;
+
+ auto startTime = currentCPUTime();
+ JSEvaluateScript(context, script, nullptr, nullptr, 1, &exception);
+ auto endTime = currentCPUTime();
+
+ if (((endTime - startTime) >= milliseconds(timeAfterWatchdogShouldHaveFired)) || !shouldTerminateCallbackWasCalled) {
+ if (!((endTime - startTime) < milliseconds(timeAfterWatchdogShouldHaveFired)))
+ printf("FAIL: %s script did not time out as expected.\n", tierOptions.tier);
+ if (!shouldTerminateCallbackWasCalled)
+ printf("FAIL: %s script timeout callback was not called.\n", tierOptions.tier);
+ failed = true;
+ }
+
+ if (exception)
+ printf("PASS: %s TerminatedExecutionException was not catchable as expected.\n", tierOptions.tier);
+ else {
+ printf("FAIL: %s TerminatedExecutionException was caught.\n", tierOptions.tier);
+ failed = true;
+ }
+
+ testResetAfterTimeout(failed);
+ }
+
+ /* Test script timeout with no callback: */
+ timeLimit = (100 + tierAdjustmentMillis) / 1000.0;
+ JSContextGroupSetExecutionTimeLimit(contextGroup, timeLimit, 0, 0);
+ {
+ unsigned timeAfterWatchdogShouldHaveFired = 300 + tierAdjustmentMillis;
+
+ StringBuilder scriptBuilder;
+ scriptBuilder.appendLiteral("function foo() { var startTime = currentCPUTime(); while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > ");
+ scriptBuilder.appendNumber(timeAfterWatchdogShouldHaveFired / 1000.0);
+ scriptBuilder.appendLiteral(") break; } } foo();");
+
+ JSStringRef script = JSStringCreateWithUTF8CString(scriptBuilder.toString().utf8().data());
+ exception = nullptr;
+ shouldTerminateCallbackWasCalled = false;
+
+ auto startTime = currentCPUTime();
+ JSEvaluateScript(context, script, nullptr, nullptr, 1, &exception);
+ auto endTime = currentCPUTime();
+
+ if (((endTime - startTime) < milliseconds(timeAfterWatchdogShouldHaveFired)) && !shouldTerminateCallbackWasCalled)
+ printf("PASS: %s script timed out as expected when no callback is specified.\n", tierOptions.tier);
+ else {
+ if ((endTime - startTime) >= milliseconds(timeAfterWatchdogShouldHaveFired))
+ printf("FAIL: %s script did not time out as expected when no callback is specified.\n", tierOptions.tier);
+ else
+ printf("FAIL: %s script called stale callback function.\n", tierOptions.tier);
+ failed = true;
+ }
+
+ if (!exception) {
+ printf("FAIL: %s TerminatedExecutionException was not thrown.\n", tierOptions.tier);
+ failed = true;
+ }
+
+ testResetAfterTimeout(failed);
+ }
+
+ /* Test script timeout cancellation: */
+ timeLimit = (100 + tierAdjustmentMillis) / 1000.0;
+ JSContextGroupSetExecutionTimeLimit(contextGroup, timeLimit, cancelTerminateCallback, 0);
+ {
+ unsigned timeAfterWatchdogShouldHaveFired = 300 + tierAdjustmentMillis;
+
+ StringBuilder scriptBuilder;
+ scriptBuilder.appendLiteral("function foo() { var startTime = currentCPUTime(); while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > ");
+ scriptBuilder.appendNumber(timeAfterWatchdogShouldHaveFired / 1000.0);
+ scriptBuilder.appendLiteral(") break; } } foo();");
+
+ JSStringRef script = JSStringCreateWithUTF8CString(scriptBuilder.toString().utf8().data());
+ exception = nullptr;
+ cancelTerminateCallbackWasCalled = false;
+
+ auto startTime = currentCPUTime();
+ JSEvaluateScript(context, script, nullptr, nullptr, 1, &exception);
+ auto endTime = currentCPUTime();
+
+ if (((endTime - startTime) >= milliseconds(timeAfterWatchdogShouldHaveFired)) && cancelTerminateCallbackWasCalled && !exception)
+ printf("PASS: %s script timeout was cancelled as expected.\n", tierOptions.tier);
+ else {
+ if (((endTime - startTime) < milliseconds(timeAfterWatchdogShouldHaveFired)) || exception)
+ printf("FAIL: %s script timeout was not cancelled.\n", tierOptions.tier);
+ if (!cancelTerminateCallbackWasCalled)
+ printf("FAIL: %s script timeout callback was not called.\n", tierOptions.tier);
+ failed = true;
+ }
+
+ if (exception) {
+ printf("FAIL: %s Unexpected TerminatedExecutionException thrown.\n", tierOptions.tier);
+ failed = true;
+ }
+ }
+
+ /* Test script timeout extension: */
+ timeLimit = (100 + tierAdjustmentMillis) / 1000.0;
+ JSContextGroupSetExecutionTimeLimit(contextGroup, timeLimit, extendTerminateCallback, 0);
+ {
+ unsigned timeBeforeExtendedDeadline = 250 + tierAdjustmentMillis;
+ unsigned timeAfterExtendedDeadline = 600 + tierAdjustmentMillis;
+ unsigned maxBusyLoopTime = 750 + tierAdjustmentMillis;
+
+ StringBuilder scriptBuilder;
+ scriptBuilder.appendLiteral("function foo() { var startTime = currentCPUTime(); while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > ");
+ scriptBuilder.appendNumber(maxBusyLoopTime / 1000.0); // in seconds.
+ scriptBuilder.appendLiteral(") break; } } foo();");
+
+ JSStringRef script = JSStringCreateWithUTF8CString(scriptBuilder.toString().utf8().data());
+ exception = nullptr;
+ extendTerminateCallbackCalled = 0;
+
+ auto startTime = currentCPUTime();
+ JSEvaluateScript(context, script, nullptr, nullptr, 1, &exception);
+ auto endTime = currentCPUTime();
+ auto deltaTime = endTime - startTime;
+
+ if ((deltaTime >= milliseconds(timeBeforeExtendedDeadline)) && (deltaTime < milliseconds(timeAfterExtendedDeadline)) && (extendTerminateCallbackCalled == 2) && exception)
+ printf("PASS: %s script timeout was extended as expected.\n", tierOptions.tier);
+ else {
+ if (deltaTime < milliseconds(timeBeforeExtendedDeadline))
+ printf("FAIL: %s script timeout was not extended as expected.\n", tierOptions.tier);
+ else if (deltaTime >= milliseconds(timeAfterExtendedDeadline))
+ printf("FAIL: %s script did not timeout.\n", tierOptions.tier);
+
+ if (extendTerminateCallbackCalled < 1)
+ printf("FAIL: %s script timeout callback was not called.\n", tierOptions.tier);
+ if (extendTerminateCallbackCalled < 2)
+ printf("FAIL: %s script timeout callback was not called after timeout extension.\n", tierOptions.tier);
+
+ if (!exception)
+ printf("FAIL: %s TerminatedExecutionException was not thrown during timeout extension test.\n", tierOptions.tier);
+
+ failed = true;
+ }
+ }
+
+ JSGlobalContextRelease(context);
+
+ Options::setOptions(savedOptionsBuilder.toString().ascii().data());
+ }
+
+ return failed;
+}
diff --git a/Source/JavaScriptCore/API/tests/ExecutionTimeLimitTest.h b/Source/JavaScriptCore/API/tests/ExecutionTimeLimitTest.h
new file mode 100644
index 000000000..2c937d08d
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/ExecutionTimeLimitTest.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Returns 1 if failures were encountered. Else, returns 0. */
+int testExecutionTimeLimit();
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
diff --git a/Source/JavaScriptCore/API/tests/FunctionOverridesTest.cpp b/Source/JavaScriptCore/API/tests/FunctionOverridesTest.cpp
new file mode 100644
index 000000000..a325f8393
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/FunctionOverridesTest.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2016 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 "FunctionOverridesTest.h"
+
+#include "FunctionOverrides.h"
+#include "InitializeThreading.h"
+#include "JSContextRefPrivate.h"
+#include "JavaScriptCore.h"
+#include "Options.h"
+#include <string>
+
+using JSC::Options;
+
+int testFunctionOverrides()
+{
+ bool failed = false;
+
+ JSC::initializeThreading();
+ Options::initialize(); // Ensure options is initialized first.
+
+ const char* oldFunctionOverrides = Options::functionOverrides();
+
+ Options::functionOverrides() = "testapi-function-overrides.js";
+ JSC::FunctionOverrides::reinstallOverrides();
+
+ JSGlobalContextRef context = JSGlobalContextCreateInGroup(nullptr, nullptr);
+
+ JSObjectRef globalObject = JSContextGetGlobalObject(context);
+ ASSERT_UNUSED(globalObject, JSValueIsObject(context, globalObject));
+
+ const char* scriptString =
+ "var str = '';" "\n"
+ "function f1() { /* Original f1 */ }" "\n"
+ "str += f1 + '\\n';" "\n"
+ "var f2 = function() {" "\n"
+ " // Original f2" "\n"
+ "}" "\n"
+ "str += f2 + '\\n';" "\n"
+ "str += (function() { /* Original f3 */ }) + '\\n';" "\n"
+ "var f4Source = '/* Original f4 */'" "\n"
+ "var f4 = new Function(f4Source);" "\n"
+ "str += f4 + '\\n';" "\n"
+ "\n"
+ "var expectedStr =" "\n"
+ "'function f1() { /* Overridden f1 */ }\\n"
+ "function () { /* Overridden f2 */ }\\n"
+ "function () { /* Overridden f3 */ }\\n"
+ "function anonymous() { /* Overridden f4 */ }\\n';"
+ "var result = (str == expectedStr);" "\n"
+ "result";
+
+ JSStringRef script = JSStringCreateWithUTF8CString(scriptString);
+ JSValueRef exception = nullptr;
+ JSValueRef resultRef = JSEvaluateScript(context, script, nullptr, nullptr, 1, &exception);
+
+ if (!JSValueIsBoolean(context, resultRef) || !JSValueToBoolean(context, resultRef))
+ failed = true;
+
+ JSGlobalContextRelease(context);
+
+ JSC::Options::functionOverrides() = oldFunctionOverrides;
+ JSC::FunctionOverrides::reinstallOverrides();
+
+ printf("%s: function override tests.\n", failed ? "FAIL" : "PASS");
+
+ return failed;
+}
diff --git a/Source/JavaScriptCore/API/tests/FunctionOverridesTest.h b/Source/JavaScriptCore/API/tests/FunctionOverridesTest.h
new file mode 100644
index 000000000..16237e5d2
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/FunctionOverridesTest.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Returns 1 if failures were encountered. Else, returns 0. */
+int testFunctionOverrides();
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
diff --git a/Source/JavaScriptCore/API/tests/GlobalContextWithFinalizerTest.cpp b/Source/JavaScriptCore/API/tests/GlobalContextWithFinalizerTest.cpp
new file mode 100644
index 000000000..0486a26c0
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/GlobalContextWithFinalizerTest.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 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 "GlobalContextWithFinalizerTest.h"
+
+#include "JavaScriptCore.h"
+
+static bool failed = true;
+
+static void finalize(JSObjectRef)
+{
+ failed = false;
+}
+
+int testGlobalContextWithFinalizer()
+{
+ JSClassDefinition def = kJSClassDefinitionEmpty;
+ def.className = "testClass";
+ def.finalize = finalize;
+ JSClassRef classRef = JSClassCreate(&def);
+
+ JSGlobalContextRef ref = JSGlobalContextCreateInGroup(nullptr, classRef);
+ JSGlobalContextRelease(ref);
+ JSClassRelease(classRef);
+
+ if (failed)
+ printf("FAIL: JSGlobalContextRef did not call its JSClassRef finalizer.\n");
+ else
+ printf("PASS: JSGlobalContextRef called its JSClassRef finalizer as expected.\n");
+
+ return failed;
+}
diff --git a/Source/JavaScriptCore/API/tests/GlobalContextWithFinalizerTest.h b/Source/JavaScriptCore/API/tests/GlobalContextWithFinalizerTest.h
new file mode 100644
index 000000000..1961350e0
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/GlobalContextWithFinalizerTest.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#pragma once
+
+#include "JSContextRefPrivate.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Returns 1 if failures were encountered. Else, returns 0. */
+int testGlobalContextWithFinalizer();
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
diff --git a/Source/JavaScriptCore/API/tests/JSExportTests.h b/Source/JavaScriptCore/API/tests/JSExportTests.h
new file mode 100644
index 000000000..9d501ee7e
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/JSExportTests.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#import <Foundation/Foundation.h>
+#import <JavaScriptCore/JavaScriptCore.h>
+
+#if JSC_OBJC_API_ENABLED
+
+void runJSExportTests();
+
+#endif // JSC_OBJC_API_ENABLED
+
diff --git a/Source/JavaScriptCore/API/tests/JSNode.c b/Source/JavaScriptCore/API/tests/JSNode.c
index d9a40bea6..d0a0dc3ec 100644
--- a/Source/JavaScriptCore/API/tests/JSNode.c
+++ b/Source/JavaScriptCore/API/tests/JSNode.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +10,10 @@
* 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
@@ -23,6 +23,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <wtf/Platform.h>
+
#include "JSNode.h"
#include "JSNodeList.h"
#include "JSObjectRef.h"
diff --git a/Source/JavaScriptCore/API/tests/JSNode.h b/Source/JavaScriptCore/API/tests/JSNode.h
index 7725733ca..dc3e1caa2 100644
--- a/Source/JavaScriptCore/API/tests/JSNode.h
+++ b/Source/JavaScriptCore/API/tests/JSNode.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +10,10 @@
* 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
@@ -23,8 +23,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef JSNode_h
-#define JSNode_h
+#pragma once
#include "JSBase.h"
#include "Node.h"
@@ -33,5 +32,3 @@
extern JSObjectRef JSNode_new(JSContextRef context, Node* node);
extern JSClassRef JSNode_class(JSContextRef context);
extern JSObjectRef JSNode_construct(JSContextRef context, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
-
-#endif /* JSNode_h */
diff --git a/Source/JavaScriptCore/API/tests/JSNodeList.c b/Source/JavaScriptCore/API/tests/JSNodeList.c
index 61d7041a4..f037e094a 100644
--- a/Source/JavaScriptCore/API/tests/JSNodeList.c
+++ b/Source/JavaScriptCore/API/tests/JSNodeList.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +10,10 @@
* 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
@@ -23,6 +23,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <wtf/Platform.h>
+
#include "JSNode.h"
#include "JSNodeList.h"
#include "JSObjectRef.h"
diff --git a/Source/JavaScriptCore/API/tests/JSNodeList.h b/Source/JavaScriptCore/API/tests/JSNodeList.h
index f9309142e..c2d2bb9a0 100644
--- a/Source/JavaScriptCore/API/tests/JSNodeList.h
+++ b/Source/JavaScriptCore/API/tests/JSNodeList.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +10,10 @@
* 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
@@ -23,12 +23,9 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef JSNodeList_h
-#define JSNodeList_h
+#pragma once
#include "JSBase.h"
#include "NodeList.h"
extern JSObjectRef JSNodeList_new(JSContextRef, NodeList*);
-
-#endif /* JSNodeList_h */
diff --git a/Source/JavaScriptCore/API/tests/JSONParseTest.cpp b/Source/JavaScriptCore/API/tests/JSONParseTest.cpp
new file mode 100644
index 000000000..d7e2bca21
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/JSONParseTest.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 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 "JSONParseTest.h"
+
+#include "JSCInlines.h"
+#include "JSGlobalObject.h"
+#include "JSONObject.h"
+#include "VM.h"
+#include <wtf/RefPtr.h>
+
+using namespace JSC;
+
+int testJSONParse()
+{
+ bool failed = false;
+
+ RefPtr<VM> vm = VM::create();
+
+ JSLockHolder locker(vm.get());
+ JSGlobalObject* globalObject = JSGlobalObject::create(*vm, JSGlobalObject::createStructure(*vm, jsNull()));
+
+ ExecState* exec = globalObject->globalExec();
+ JSValue v0 = JSONParse(exec, "");
+ JSValue v1 = JSONParse(exec, "#$%^");
+ JSValue v2 = JSONParse(exec, String());
+ UChar emptyUCharArray[1] = { '\0' };
+ JSValue v3 = JSONParse(exec, String(emptyUCharArray, 0));
+ JSValue v4;
+ JSValue v5 = JSONParse(exec, "123");
+
+ failed = failed || (v0 != v1);
+ failed = failed || (v1 != v2);
+ failed = failed || (v2 != v3);
+ failed = failed || (v3 != v4);
+ failed = failed || (v4 == v5);
+
+ vm = nullptr;
+
+ if (failed)
+ printf("FAIL: JSONParse String test.\n");
+ else
+ printf("PASS: JSONParse String test.\n");
+
+ return failed;
+}
diff --git a/Source/JavaScriptCore/API/tests/JSONParseTest.h b/Source/JavaScriptCore/API/tests/JSONParseTest.h
new file mode 100644
index 000000000..13842f92e
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/JSONParseTest.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int testJSONParse();
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
diff --git a/Source/JavaScriptCore/API/tests/Node.c b/Source/JavaScriptCore/API/tests/Node.c
index 913da0a2a..db687e952 100644
--- a/Source/JavaScriptCore/API/tests/Node.c
+++ b/Source/JavaScriptCore/API/tests/Node.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +10,10 @@
* 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
diff --git a/Source/JavaScriptCore/API/tests/Node.h b/Source/JavaScriptCore/API/tests/Node.h
index e9250b3ae..bdb1f2c55 100644
--- a/Source/JavaScriptCore/API/tests/Node.h
+++ b/Source/JavaScriptCore/API/tests/Node.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +10,10 @@
* 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
@@ -23,8 +23,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef Node_h
-#define Node_h
+#pragma once
typedef struct __Node Node;
typedef struct __NodeLink NodeLink;
@@ -46,5 +45,3 @@ extern void Node_deref(Node* node);
extern void Node_appendChild(Node* node, Node* child);
extern void Node_removeChild(Node* node, Node* child);
extern void Node_replaceChild(Node* node, Node* newChild, Node* oldChild);
-
-#endif /* Node_h */
diff --git a/Source/JavaScriptCore/API/tests/NodeList.c b/Source/JavaScriptCore/API/tests/NodeList.c
index ae4c17062..69f4cd5c4 100644
--- a/Source/JavaScriptCore/API/tests/NodeList.c
+++ b/Source/JavaScriptCore/API/tests/NodeList.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +10,10 @@
* 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
diff --git a/Source/JavaScriptCore/API/tests/NodeList.h b/Source/JavaScriptCore/API/tests/NodeList.h
index 25b95bf4d..51163c2be 100644
--- a/Source/JavaScriptCore/API/tests/NodeList.h
+++ b/Source/JavaScriptCore/API/tests/NodeList.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +10,10 @@
* 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
@@ -23,8 +23,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef NodeList_h
-#define NodeList_h
+#pragma once
#include "Node.h"
@@ -38,5 +37,3 @@ extern unsigned NodeList_length(NodeList*);
extern Node* NodeList_item(NodeList*, unsigned);
extern void NodeList_ref(NodeList*);
extern void NodeList_deref(NodeList*);
-
-#endif /* NodeList_h */
diff --git a/Source/JavaScriptCore/API/tests/PingPongStackOverflowTest.cpp b/Source/JavaScriptCore/API/tests/PingPongStackOverflowTest.cpp
new file mode 100644
index 000000000..ef4b914c1
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/PingPongStackOverflowTest.cpp
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2015 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 "PingPongStackOverflowTest.h"
+
+#include "InitializeThreading.h"
+#include "JSContextRefPrivate.h"
+#include "JavaScriptCore.h"
+#include "Options.h"
+#include <wtf/text/StringBuilder.h>
+
+using JSC::Options;
+
+static JSGlobalContextRef context = nullptr;
+static int nativeRecursionCount = 0;
+
+static bool PingPongStackOverflowObject_hasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef possibleValue, JSValueRef* exception)
+{
+ UNUSED_PARAM(context);
+ UNUSED_PARAM(constructor);
+
+ JSStringRef hasInstanceName = JSStringCreateWithUTF8CString("hasInstance");
+ JSValueRef hasInstance = JSObjectGetProperty(context, constructor, hasInstanceName, exception);
+ JSStringRelease(hasInstanceName);
+ if (!hasInstance)
+ return false;
+
+ int countAtEntry = nativeRecursionCount++;
+
+ JSValueRef result = 0;
+ if (nativeRecursionCount < 100) {
+ JSObjectRef function = JSValueToObject(context, hasInstance, exception);
+ result = JSObjectCallAsFunction(context, function, constructor, 1, &possibleValue, exception);
+ } else {
+ StringBuilder builder;
+ builder.appendLiteral("dummy.valueOf([0]");
+ for (int i = 1; i < 35000; i++) {
+ builder.appendLiteral(", [");
+ builder.appendNumber(i);
+ builder.appendLiteral("]");
+ }
+ builder.appendLiteral(");");
+
+ JSStringRef script = JSStringCreateWithUTF8CString(builder.toString().utf8().data());
+ result = JSEvaluateScript(context, script, NULL, NULL, 1, exception);
+ JSStringRelease(script);
+ }
+
+ --nativeRecursionCount;
+ if (nativeRecursionCount != countAtEntry)
+ printf(" ERROR: PingPongStackOverflow test saw a recursion count mismatch\n");
+
+ return result && JSValueToBoolean(context, result);
+}
+
+JSClassDefinition PingPongStackOverflowObject_definition = {
+ 0,
+ kJSClassAttributeNone,
+
+ "PingPongStackOverflowObject",
+ NULL,
+
+ NULL,
+ NULL,
+
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ PingPongStackOverflowObject_hasInstance,
+ NULL,
+};
+
+static JSClassRef PingPongStackOverflowObject_class(JSContextRef context)
+{
+ UNUSED_PARAM(context);
+
+ static JSClassRef jsClass;
+ if (!jsClass)
+ jsClass = JSClassCreate(&PingPongStackOverflowObject_definition);
+
+ return jsClass;
+}
+
+// This tests tests a stack overflow on VM reentry into a JS function from a native function
+// after ping-pong'ing back and forth between JS and native functions multiple times.
+// This test should not hang or crash.
+int testPingPongStackOverflow()
+{
+ bool failed = false;
+
+ JSC::initializeThreading();
+ Options::initialize(); // Ensure options is initialized first.
+
+ auto origSoftReservedZoneSize = Options::softReservedZoneSize();
+ auto origReservedZoneSize = Options::reservedZoneSize();
+ auto origUseLLInt = Options::useLLInt();
+ auto origMaxPerThreadStackUsage = Options::maxPerThreadStackUsage();
+
+ Options::softReservedZoneSize() = 128 * KB;
+ Options::reservedZoneSize() = 64 * KB;
+#if ENABLE(JIT)
+ // Normally, we want to disable the LLINT to force the use of JITted code which is necessary for
+ // reproducing the regression in https://bugs.webkit.org/show_bug.cgi?id=148749. However, we only
+ // want to do this if the LLINT isn't the only available execution engine.
+ Options::useLLInt() = false;
+#endif
+
+ const char* scriptString =
+ "var count = 0;" \
+ "PingPongStackOverflowObject.hasInstance = function f() {" \
+ " return (undefined instanceof PingPongStackOverflowObject);" \
+ "};" \
+ "PingPongStackOverflowObject.__proto__ = undefined;" \
+ "undefined instanceof PingPongStackOverflowObject;";
+
+ JSValueRef scriptResult = nullptr;
+ JSValueRef exception = nullptr;
+ JSStringRef script = JSStringCreateWithUTF8CString(scriptString);
+
+ nativeRecursionCount = 0;
+ context = JSGlobalContextCreateInGroup(nullptr, nullptr);
+
+ JSObjectRef globalObject = JSContextGetGlobalObject(context);
+ ASSERT(JSValueIsObject(context, globalObject));
+
+ JSObjectRef PingPongStackOverflowObject = JSObjectMake(context, PingPongStackOverflowObject_class(context), NULL);
+ JSStringRef PingPongStackOverflowObjectString = JSStringCreateWithUTF8CString("PingPongStackOverflowObject");
+ JSObjectSetProperty(context, globalObject, PingPongStackOverflowObjectString, PingPongStackOverflowObject, kJSPropertyAttributeNone, NULL);
+ JSStringRelease(PingPongStackOverflowObjectString);
+
+ unsigned stackSize = 32 * KB;
+ Options::maxPerThreadStackUsage() = stackSize + Options::softReservedZoneSize();
+
+ exception = nullptr;
+ scriptResult = JSEvaluateScript(context, script, nullptr, nullptr, 1, &exception);
+
+ if (!exception) {
+ printf("FAIL: PingPongStackOverflowError not thrown in PingPongStackOverflow test\n");
+ failed = true;
+ } else if (nativeRecursionCount) {
+ printf("FAIL: Unbalanced native recursion count: %d in PingPongStackOverflow test\n", nativeRecursionCount);
+ failed = true;
+ } else {
+ printf("PASS: PingPongStackOverflow test.\n");
+ }
+
+ Options::softReservedZoneSize() = origSoftReservedZoneSize;
+ Options::reservedZoneSize() = origReservedZoneSize;
+ Options::useLLInt() = origUseLLInt;
+ Options::maxPerThreadStackUsage() = origMaxPerThreadStackUsage;
+
+ return failed;
+}
diff --git a/Source/JavaScriptCore/API/tests/PingPongStackOverflowTest.h b/Source/JavaScriptCore/API/tests/PingPongStackOverflowTest.h
new file mode 100644
index 000000000..a2046693f
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/PingPongStackOverflowTest.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int testPingPongStackOverflow();
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
diff --git a/Source/JavaScriptCore/API/tests/Regress141275.h b/Source/JavaScriptCore/API/tests/Regress141275.h
new file mode 100644
index 000000000..bf3492afa
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/Regress141275.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#import <Foundation/Foundation.h>
+#import <JavaScriptCore/JavaScriptCore.h>
+
+#if JSC_OBJC_API_ENABLED
+
+void runRegress141275();
+
+#endif // JSC_OBJC_API_ENABLED
+
diff --git a/Source/JavaScriptCore/API/tests/Regress141809.h b/Source/JavaScriptCore/API/tests/Regress141809.h
new file mode 100644
index 000000000..43b099c94
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/Regress141809.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#import <Foundation/Foundation.h>
+#import <JavaScriptCore/JavaScriptCore.h>
+
+#if JSC_OBJC_API_ENABLED
+
+void runRegress141809();
+
+#endif // JSC_OBJC_API_ENABLED
+
diff --git a/Source/JavaScriptCore/API/tests/TypedArrayCTest.cpp b/Source/JavaScriptCore/API/tests/TypedArrayCTest.cpp
new file mode 100644
index 000000000..8ec8cdd5d
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/TypedArrayCTest.cpp
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2016 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 "TypedArrayCTest.h"
+
+#include "JavaScriptCore.h"
+#include <wtf/Assertions.h>
+
+extern "C" void JSSynchronousGarbageCollectForDebugging(JSContextRef);
+
+static void id(void*, void*) { }
+static void freePtr(void* ptr, void*)
+{
+ free(ptr);
+}
+
+static const unsigned numLengths = 3;
+
+static const unsigned lengths[numLengths] =
+{
+ 0,
+ 1,
+ 10,
+};
+
+static const unsigned byteSizes[kJSTypedArrayTypeArrayBuffer] =
+{
+ 1, // kJSTypedArrayTypeInt8Array
+ 2, // kJSTypedArrayTypeInt16Array
+ 4, // kJSTypedArrayTypeInt32Array
+ 1, // kJSTypedArrayTypeUint8Array
+ 1, // kJSTypedArrayTypeUint8ClampedArray
+ 2, // kJSTypedArrayTypeUint16Array
+ 4, // kJSTypedArrayTypeUint32Array
+ 4, // kJSTypedArrayTypeFloat32Array
+ 8, // kJSTypedArrayTypeFloat64Array
+};
+
+static const char* typeToString[kJSTypedArrayTypeArrayBuffer] =
+{
+ "kJSTypedArrayTypeInt8Array",
+ "kJSTypedArrayTypeInt16Array",
+ "kJSTypedArrayTypeInt32Array",
+ "kJSTypedArrayTypeUint8Array",
+ "kJSTypedArrayTypeUint8ClampedArray",
+ "kJSTypedArrayTypeUint16Array",
+ "kJSTypedArrayTypeUint32Array",
+ "kJSTypedArrayTypeFloat32Array",
+ "kJSTypedArrayTypeFloat64Array",
+};
+
+inline int unexpectedException(const char* name)
+{
+ fprintf(stderr, "%s FAILED: unexpected exception\n", name);
+ return 1;
+}
+
+static int assertEqualsAsNumber(JSGlobalContextRef context, JSValueRef value, double expectedValue)
+{
+ double number = JSValueToNumber(context, value, nullptr);
+ if (number != expectedValue && !(isnan(number) && isnan(expectedValue))) {
+ fprintf(stderr, "assertEqualsAsNumber FAILED: %p, %lf\n", value, expectedValue);
+ return 1;
+ }
+ return 0;
+}
+
+static int testAccess(JSGlobalContextRef context, JSObjectRef typedArray, JSTypedArrayType type, unsigned elementLength, void* expectedPtr = nullptr, JSObjectRef expectedBuffer = nullptr, unsigned expectedOffset = 0)
+{
+ JSValueRef exception = nullptr;
+ // Test typedArray basic functions.
+ JSTypedArrayType actualType = JSValueGetTypedArrayType(context, typedArray, &exception);
+ if (type != actualType || exception) {
+ fprintf(stderr, "TypedArray type FAILED: %p, got: %s, expected: %s\n", typedArray, typeToString[actualType], typeToString[type]);
+ return 1;
+ }
+
+ unsigned length = JSObjectGetTypedArrayLength(context, typedArray, &exception);
+ if (elementLength != length || exception) {
+ fprintf(stderr, "TypedArray length FAILED: %p (%s), got: %d, expected: %d\n", typedArray, typeToString[type], length, elementLength);
+ return 1;
+ }
+
+ unsigned byteLength = JSObjectGetTypedArrayByteLength(context, typedArray, &exception);
+ unsigned expectedLength = byteSizes[type] * elementLength;
+ if (byteLength != expectedLength || exception) {
+ fprintf(stderr, "TypedArray byteLength FAILED: %p (%s), got: %d, expected: %d\n", typedArray, typeToString[type], byteLength, expectedLength);
+ return 1;
+ }
+
+ unsigned offset = JSObjectGetTypedArrayByteOffset(context, typedArray, &exception);
+ if (expectedOffset != offset || exception) {
+ fprintf(stderr, "TypedArray byteOffset FAILED: %p (%s), got: %d, expected: %d\n", typedArray, typeToString[type], offset, expectedOffset);
+ return 1;
+ }
+
+ void* ptr = JSObjectGetTypedArrayBytesPtr(context, typedArray, &exception);
+ if (exception)
+ return unexpectedException("TypedArray get bytes ptr");
+
+ JSObjectRef buffer = JSObjectGetTypedArrayBuffer(context, typedArray, &exception);
+ if (exception)
+ return unexpectedException("TypedArray get buffer");
+
+ void* bufferPtr = JSObjectGetArrayBufferBytesPtr(context, buffer, &exception);
+ if (exception)
+ return unexpectedException("ArrayBuffer get bytes ptr");
+
+ if (bufferPtr != ptr) {
+ fprintf(stderr, "FAIL: TypedArray bytes ptr and ArrayBuffer byte ptr were not the same: %p (%s) TypedArray: %p, ArrayBuffer: %p\n", typedArray, typeToString[type], ptr, bufferPtr);
+ return 1;
+ }
+
+ if (expectedPtr && ptr != expectedPtr) {
+ fprintf(stderr, "FAIL: TypedArray bytes ptr and the ptr used to construct the array were not the same: %p (%s) TypedArray: %p, bytes ptr: %p\n", typedArray, typeToString[type], ptr, expectedPtr);
+ return 1;
+ }
+
+ if (expectedBuffer && expectedBuffer != buffer) {
+ fprintf(stderr, "FAIL: TypedArray buffer and the ArrayBuffer buffer used to construct the array were not the same: %p (%s) TypedArray buffer: %p, data: %p\n", typedArray, typeToString[type], buffer, expectedBuffer);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int testConstructors(JSGlobalContextRef context, JSTypedArrayType type, unsigned length)
+{
+ int failed = 0;
+ JSValueRef exception = nullptr;
+ JSObjectRef typedArray;
+
+ // Test create with length.
+ typedArray = JSObjectMakeTypedArray(context, type, length, &exception);
+ failed = failed || exception || testAccess(context, typedArray, type, length);
+
+ void* ptr = calloc(length, byteSizes[type]); // This is to be freed by data
+ JSObjectRef data = JSObjectMakeArrayBufferWithBytesNoCopy(context, ptr, length * byteSizes[type], freePtr, nullptr, &exception);
+ failed = failed || exception;
+
+ // Test create with existing ptr.
+ typedArray = JSObjectMakeTypedArrayWithBytesNoCopy(context, type, ptr, length * byteSizes[type], id, nullptr, &exception);
+ failed = failed || exception || testAccess(context, typedArray, type, length, ptr);
+
+ // Test create with existing ArrayBuffer.
+ typedArray = JSObjectMakeTypedArrayWithArrayBuffer(context, type, data, &exception);
+ failed = failed || exception || testAccess(context, typedArray, type, length, ptr, data);
+
+ // Test create with existing ArrayBuffer and offset.
+ typedArray = JSObjectMakeTypedArrayWithArrayBufferAndOffset(context, type, data, 0, length, &exception);
+ failed = failed || exception || testAccess(context, typedArray, type, length, ptr, data);
+
+ typedArray = JSObjectMakeTypedArrayWithArrayBufferAndOffset(context, type, data, byteSizes[type], length-1, &exception);
+ if (!length)
+ failed = failed || !exception;
+ else
+ failed = failed || testAccess(context, typedArray, type, length-1, ptr, data, byteSizes[type]) || exception;
+
+ exception = nullptr;
+ typedArray = JSObjectMakeTypedArrayWithArrayBufferAndOffset(context, type, data, byteSizes[type], 3, &exception);
+ if (length < 2)
+ failed = failed || !exception;
+ else
+ failed = failed || testAccess(context, typedArray, type, 3, ptr, data, byteSizes[type]) || exception;
+
+ if (byteSizes[type] > 1) {
+ exception = nullptr;
+ typedArray = JSObjectMakeTypedArrayWithArrayBufferAndOffset(context, type, data, 1, length-1, &exception);
+ failed = failed || !exception;
+ }
+
+ typedArray = JSObjectMakeTypedArrayWithArrayBufferAndOffset(context, type, data, byteSizes[type], length, &exception);
+ failed = failed || !exception;
+
+ exception = nullptr;
+ typedArray = JSObjectMakeTypedArrayWithArrayBufferAndOffset(context, type, data, byteSizes[type], 0, &exception);
+ if (!length)
+ failed = failed || !exception;
+ else
+ failed = failed || testAccess(context, typedArray, type, 0, ptr, data, byteSizes[type]) || exception;
+
+ return failed;
+}
+
+template <typename Functor>
+static int forEachTypedArrayType(const Functor& functor)
+{
+ int failed = 0;
+ for (unsigned i = 0; i < kJSTypedArrayTypeArrayBuffer; i++)
+ failed = failed || functor(static_cast<JSTypedArrayType>(i));
+ return failed;
+}
+
+int testTypedArrayCAPI()
+{
+ int failed = 0;
+ JSGlobalContextRef context = JSGlobalContextCreate(nullptr);
+
+ failed = failed || forEachTypedArrayType([&](JSTypedArrayType type) {
+ int failed = 0;
+ for (unsigned i = 0; i < numLengths; i++)
+ failed = failed || testConstructors(context, type, lengths[i]);
+ return failed;
+ });
+
+ // Test making a typedArray from scratch length.
+ volatile JSObjectRef typedArray = JSObjectMakeTypedArray(context, kJSTypedArrayTypeUint32Array, 10, nullptr);
+ JSObjectRef data = JSObjectGetTypedArrayBuffer(context, typedArray, nullptr);
+ unsigned* buffer = static_cast<unsigned*>(JSObjectGetArrayBufferBytesPtr(context, data, nullptr));
+
+ ASSERT(JSObjectGetTypedArrayLength(context, typedArray, nullptr) == 10);
+
+ // Test buffer is connected to typedArray.
+ buffer[1] = 1;
+ JSValueRef v = JSObjectGetPropertyAtIndex(context, typedArray, 1, nullptr);
+ failed = failed || assertEqualsAsNumber(context, v, 1);
+
+ // Test passing a buffer from a new array to an old array
+ typedArray = JSObjectMakeTypedArrayWithBytesNoCopy(context, kJSTypedArrayTypeUint32Array, buffer, 40, id, nullptr, nullptr);
+ buffer = static_cast<unsigned*>(JSObjectGetTypedArrayBytesPtr(context, typedArray, nullptr));
+ ASSERT(buffer[1] == 1);
+ buffer[1] = 20;
+ ASSERT(((unsigned*)JSObjectGetArrayBufferBytesPtr(context, data, nullptr))[1] == 20);
+
+ // Test constructing with data and the data returned are the same even with an offset.
+ typedArray = JSObjectMakeTypedArrayWithArrayBufferAndOffset(context, kJSTypedArrayTypeUint32Array, data, 4, 9, nullptr);
+ failed = failed || assertEqualsAsNumber(context, JSObjectGetPropertyAtIndex(context, typedArray, 0, nullptr), 20);
+ ASSERT(data == JSObjectGetTypedArrayBuffer(context, typedArray, nullptr));
+
+ // Test attempting to allocate an array too big for memory.
+ forEachTypedArrayType([&](JSTypedArrayType type) {
+ JSValueRef exception = nullptr;
+ JSObjectMakeTypedArray(context, type, UINT_MAX, &exception);
+ return !exception;
+ });
+
+ JSGlobalContextRelease(context);
+
+ if (!failed)
+ printf("PASS: Typed Array C API Tests.\n");
+ else
+ printf("FAIL: Some Typed Array C API Tests failed.\n");
+
+ return failed;
+}
diff --git a/Source/JavaScriptCore/API/tests/TypedArrayCTest.h b/Source/JavaScriptCore/API/tests/TypedArrayCTest.h
new file mode 100644
index 000000000..dc66881e8
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/TypedArrayCTest.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int testTypedArrayCAPI(void);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
diff --git a/Source/JavaScriptCore/API/tests/minidom.c b/Source/JavaScriptCore/API/tests/minidom.c
index f4ccf91e4..02b41a9c7 100644
--- a/Source/JavaScriptCore/API/tests/minidom.c
+++ b/Source/JavaScriptCore/API/tests/minidom.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Apple Inc. All rights reserved.
* Copyright (C) 2007 Alp Toker <alp@atoker.com>
*
* Redistribution and use in source and binary forms, with or without
@@ -11,10 +11,10 @@
* 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
@@ -24,6 +24,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <wtf/Platform.h>
+
#include "JSContextRef.h"
#include "JSNode.h"
#include "JSObjectRef.h"
diff --git a/Source/JavaScriptCore/API/tests/minidom.html b/Source/JavaScriptCore/API/tests/minidom.html
new file mode 100644
index 000000000..7ea474752
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/minidom.html
@@ -0,0 +1,9 @@
+<html>
+<head>
+<script src="minidom.js"></script>
+</head>
+
+<body onload="test()">
+ <pre id='pre'></pre>
+</body>
+</html>
diff --git a/Source/JavaScriptCore/API/tests/minidom.js b/Source/JavaScriptCore/API/tests/minidom.js
new file mode 100644
index 000000000..85134d7cb
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/minidom.js
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2006 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. ``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
+ * 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.
+ */
+
+function shouldBe(a, b)
+{
+ var evalA;
+ try {
+ evalA = eval(a);
+ } catch(e) {
+ evalA = e;
+ }
+
+ if (evalA == b || isNaN(evalA) && typeof evalA == 'number' && isNaN(b) && typeof b == 'number')
+ print("PASS: " + a + " should be " + b + " and is.", "green");
+ else
+ print("__FAIL__: " + a + " should be " + b + " but instead is " + evalA + ".", "red");
+}
+
+function test()
+{
+ print("Node is " + Node);
+ for (var p in Node)
+ print(p + ": " + Node[p]);
+
+ node = new Node();
+ print("node is " + node);
+ for (var p in node)
+ print(p + ": " + node[p]);
+
+ child1 = new Node();
+ child2 = new Node();
+ child3 = new Node();
+
+ node.appendChild(child1);
+ node.appendChild(child2);
+
+ var childNodes = node.childNodes;
+
+ for (var i = 0; i < childNodes.length + 1; i++) {
+ print("item " + i + ": " + childNodes.item(i));
+ }
+
+ for (var i = 0; i < childNodes.length + 1; i++) {
+ print(i + ": " + childNodes[i]);
+ }
+
+ node.removeChild(child1);
+ node.replaceChild(child3, child2);
+
+ for (var i = 0; i < childNodes.length + 1; i++) {
+ print("item " + i + ": " + childNodes.item(i));
+ }
+
+ for (var i = 0; i < childNodes.length + 1; i++) {
+ print(i + ": " + childNodes[i]);
+ }
+
+ try {
+ node.appendChild(null);
+ } catch(e) {
+ print("caught: " + e);
+ }
+
+ try {
+ var o = new Object();
+ o.appendChild = node.appendChild;
+ o.appendChild(node);
+ } catch(e) {
+ print("caught: " + e);
+ }
+
+ try {
+ node.appendChild();
+ } catch(e) {
+ print("caught: " + e);
+ }
+
+ oldNodeType = node.nodeType;
+ node.nodeType = 1;
+ shouldBe("node.nodeType", oldNodeType);
+
+ shouldBe("node instanceof Node", true);
+ shouldBe("new Object() instanceof Node", false);
+
+ print(Node);
+}
+
+test();
diff --git a/Source/JavaScriptCore/API/tests/testapi-function-overrides.js b/Source/JavaScriptCore/API/tests/testapi-function-overrides.js
new file mode 100644
index 000000000..363cced04
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/testapi-function-overrides.js
@@ -0,0 +1,16 @@
+// testapi function overrides for testing.
+override %%%{ /* Original f1 */ }%%%
+with %%%{ /* Overridden f1 */ }%%%
+
+override #$%{
+ // Original f2
+}#$%
+with $$${ /* Overridden f2 */ }$$$
+
+override %%%{ /* Original f3 */ }%%%
+with %%%{ /* Overridden f3 */ }%%%
+
+override %%%{
+/* Original f4 */
+}%%%
+with %%%{ /* Overridden f4 */ }%%%
diff --git a/Source/JavaScriptCore/API/tests/testapi.c b/Source/JavaScriptCore/API/tests/testapi.c
new file mode 100644
index 000000000..b6c24518b
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/testapi.c
@@ -0,0 +1,1989 @@
+/*
+ * Copyright (C) 2006, 2015-2016 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. ``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
+ * 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 <wtf/Platform.h>
+
+#include "JavaScriptCore.h"
+#include "JSBasePrivate.h"
+#include "JSContextRefPrivate.h"
+#include "JSObjectRefPrivate.h"
+#include "JSScriptRefPrivate.h"
+#include "JSStringRefPrivate.h"
+#include <math.h>
+#define ASSERT_DISABLED 0
+#include <wtf/Assertions.h>
+
+#if OS(WINDOWS)
+#include <windows.h>
+#endif
+
+#include "CompareAndSwapTest.h"
+#include "CustomGlobalObjectClassTest.h"
+#include "ExecutionTimeLimitTest.h"
+#include "FunctionOverridesTest.h"
+#include "GlobalContextWithFinalizerTest.h"
+#include "JSONParseTest.h"
+#include "PingPongStackOverflowTest.h"
+#include "TypedArrayCTest.h"
+
+#if JSC_OBJC_API_ENABLED
+void testObjectiveCAPI(void);
+#endif
+
+bool assertTrue(bool value, const char* message);
+
+static JSGlobalContextRef context;
+int failed;
+static void assertEqualsAsBoolean(JSValueRef value, bool expectedValue)
+{
+ if (JSValueToBoolean(context, value) != expectedValue) {
+ fprintf(stderr, "assertEqualsAsBoolean failed: %p, %d\n", value, expectedValue);
+ failed = 1;
+ }
+}
+
+static void assertEqualsAsNumber(JSValueRef value, double expectedValue)
+{
+ double number = JSValueToNumber(context, value, NULL);
+
+ // FIXME <rdar://4668451> - On i386 the isnan(double) macro tries to map to the isnan(float) function,
+ // causing a build break with -Wshorten-64-to-32 enabled. The issue is known by the appropriate team.
+ // After that's resolved, we can remove these casts
+ if (number != expectedValue && !(isnan((float)number) && isnan((float)expectedValue))) {
+ fprintf(stderr, "assertEqualsAsNumber failed: %p, %lf\n", value, expectedValue);
+ failed = 1;
+ }
+}
+
+static void assertEqualsAsUTF8String(JSValueRef value, const char* expectedValue)
+{
+ JSStringRef valueAsString = JSValueToStringCopy(context, value, NULL);
+
+ size_t jsSize = JSStringGetMaximumUTF8CStringSize(valueAsString);
+ char* jsBuffer = (char*)malloc(jsSize);
+ JSStringGetUTF8CString(valueAsString, jsBuffer, jsSize);
+
+ unsigned i;
+ for (i = 0; jsBuffer[i]; i++) {
+ if (jsBuffer[i] != expectedValue[i]) {
+ fprintf(stderr, "assertEqualsAsUTF8String failed at character %d: %c(%d) != %c(%d)\n", i, jsBuffer[i], jsBuffer[i], expectedValue[i], expectedValue[i]);
+ fprintf(stderr, "value: %s\n", jsBuffer);
+ fprintf(stderr, "expectedValue: %s\n", expectedValue);
+ failed = 1;
+ }
+ }
+
+ if (jsSize < strlen(jsBuffer) + 1) {
+ fprintf(stderr, "assertEqualsAsUTF8String failed: jsSize was too small\n");
+ failed = 1;
+ }
+
+ free(jsBuffer);
+ JSStringRelease(valueAsString);
+}
+
+static void assertEqualsAsCharactersPtr(JSValueRef value, const char* expectedValue)
+{
+ JSStringRef valueAsString = JSValueToStringCopy(context, value, NULL);
+
+ size_t jsLength = JSStringGetLength(valueAsString);
+ const JSChar* jsBuffer = JSStringGetCharactersPtr(valueAsString);
+
+ CFStringRef expectedValueAsCFString = CFStringCreateWithCString(kCFAllocatorDefault,
+ expectedValue,
+ kCFStringEncodingUTF8);
+ CFIndex cfLength = CFStringGetLength(expectedValueAsCFString);
+ UniChar* cfBuffer = (UniChar*)malloc(cfLength * sizeof(UniChar));
+ CFStringGetCharacters(expectedValueAsCFString, CFRangeMake(0, cfLength), cfBuffer);
+ CFRelease(expectedValueAsCFString);
+
+ if (memcmp(jsBuffer, cfBuffer, cfLength * sizeof(UniChar)) != 0) {
+ fprintf(stderr, "assertEqualsAsCharactersPtr failed: jsBuffer != cfBuffer\n");
+ failed = 1;
+ }
+
+ if (jsLength != (size_t)cfLength) {
+#if OS(WINDOWS)
+ fprintf(stderr, "assertEqualsAsCharactersPtr failed: jsLength(%Iu) != cfLength(%Iu)\n", jsLength, (size_t)cfLength);
+#else
+ fprintf(stderr, "assertEqualsAsCharactersPtr failed: jsLength(%zu) != cfLength(%zu)\n", jsLength, (size_t)cfLength);
+#endif
+ failed = 1;
+ }
+
+ free(cfBuffer);
+ JSStringRelease(valueAsString);
+}
+
+static bool timeZoneIsPST()
+{
+ char timeZoneName[70];
+ struct tm gtm;
+ memset(&gtm, 0, sizeof(gtm));
+ strftime(timeZoneName, sizeof(timeZoneName), "%Z", &gtm);
+
+ return 0 == strcmp("PST", timeZoneName);
+}
+
+static JSValueRef jsGlobalValue; // non-stack value for testing JSValueProtect()
+
+/* MyObject pseudo-class */
+
+static bool MyObject_hasProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName)
+{
+ UNUSED_PARAM(context);
+ UNUSED_PARAM(object);
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "alwaysOne")
+ || JSStringIsEqualToUTF8CString(propertyName, "cantFind")
+ || JSStringIsEqualToUTF8CString(propertyName, "throwOnGet")
+ || JSStringIsEqualToUTF8CString(propertyName, "myPropertyName")
+ || JSStringIsEqualToUTF8CString(propertyName, "hasPropertyLie")
+ || JSStringIsEqualToUTF8CString(propertyName, "0")) {
+ return true;
+ }
+
+ return false;
+}
+
+static JSValueRef MyObject_getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+ UNUSED_PARAM(context);
+ UNUSED_PARAM(object);
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "alwaysOne")) {
+ return JSValueMakeNumber(context, 1);
+ }
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "myPropertyName")) {
+ return JSValueMakeNumber(context, 1);
+ }
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "cantFind")) {
+ return JSValueMakeUndefined(context);
+ }
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "hasPropertyLie")) {
+ return 0;
+ }
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "throwOnGet")) {
+ return JSEvaluateScript(context, JSStringCreateWithUTF8CString("throw 'an exception'"), object, JSStringCreateWithUTF8CString("test script"), 1, exception);
+ }
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "0")) {
+ *exception = JSValueMakeNumber(context, 1);
+ return JSValueMakeNumber(context, 1);
+ }
+
+ return JSValueMakeNull(context);
+}
+
+static bool MyObject_setProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
+{
+ UNUSED_PARAM(context);
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(value);
+ UNUSED_PARAM(exception);
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "cantSet"))
+ return true; // pretend we set the property in order to swallow it
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "throwOnSet")) {
+ JSEvaluateScript(context, JSStringCreateWithUTF8CString("throw 'an exception'"), object, JSStringCreateWithUTF8CString("test script"), 1, exception);
+ }
+
+ return false;
+}
+
+static bool MyObject_deleteProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+ UNUSED_PARAM(context);
+ UNUSED_PARAM(object);
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "cantDelete"))
+ return true;
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "throwOnDelete")) {
+ JSEvaluateScript(context, JSStringCreateWithUTF8CString("throw 'an exception'"), object, JSStringCreateWithUTF8CString("test script"), 1, exception);
+ return false;
+ }
+
+ return false;
+}
+
+static void MyObject_getPropertyNames(JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames)
+{
+ UNUSED_PARAM(context);
+ UNUSED_PARAM(object);
+
+ JSStringRef propertyName;
+
+ propertyName = JSStringCreateWithUTF8CString("alwaysOne");
+ JSPropertyNameAccumulatorAddName(propertyNames, propertyName);
+ JSStringRelease(propertyName);
+
+ propertyName = JSStringCreateWithUTF8CString("myPropertyName");
+ JSPropertyNameAccumulatorAddName(propertyNames, propertyName);
+ JSStringRelease(propertyName);
+}
+
+static JSValueRef MyObject_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ UNUSED_PARAM(context);
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(thisObject);
+ UNUSED_PARAM(exception);
+
+ if (argumentCount > 0 && JSValueIsString(context, arguments[0]) && JSStringIsEqualToUTF8CString(JSValueToStringCopy(context, arguments[0], 0), "throwOnCall")) {
+ JSEvaluateScript(context, JSStringCreateWithUTF8CString("throw 'an exception'"), object, JSStringCreateWithUTF8CString("test script"), 1, exception);
+ return JSValueMakeUndefined(context);
+ }
+
+ if (argumentCount > 0 && JSValueIsStrictEqual(context, arguments[0], JSValueMakeNumber(context, 0)))
+ return JSValueMakeNumber(context, 1);
+
+ return JSValueMakeUndefined(context);
+}
+
+static JSObjectRef MyObject_callAsConstructor(JSContextRef context, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ UNUSED_PARAM(context);
+ UNUSED_PARAM(object);
+
+ if (argumentCount > 0 && JSValueIsString(context, arguments[0]) && JSStringIsEqualToUTF8CString(JSValueToStringCopy(context, arguments[0], 0), "throwOnConstruct")) {
+ JSEvaluateScript(context, JSStringCreateWithUTF8CString("throw 'an exception'"), object, JSStringCreateWithUTF8CString("test script"), 1, exception);
+ return object;
+ }
+
+ if (argumentCount > 0 && JSValueIsStrictEqual(context, arguments[0], JSValueMakeNumber(context, 0)))
+ return JSValueToObject(context, JSValueMakeNumber(context, 1), exception);
+
+ return JSValueToObject(context, JSValueMakeNumber(context, 0), exception);
+}
+
+static bool MyObject_hasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef possibleValue, JSValueRef* exception)
+{
+ UNUSED_PARAM(context);
+ UNUSED_PARAM(constructor);
+
+ if (JSValueIsString(context, possibleValue) && JSStringIsEqualToUTF8CString(JSValueToStringCopy(context, possibleValue, 0), "throwOnHasInstance")) {
+ JSEvaluateScript(context, JSStringCreateWithUTF8CString("throw 'an exception'"), constructor, JSStringCreateWithUTF8CString("test script"), 1, exception);
+ return false;
+ }
+
+ JSStringRef numberString = JSStringCreateWithUTF8CString("Number");
+ JSObjectRef numberConstructor = JSValueToObject(context, JSObjectGetProperty(context, JSContextGetGlobalObject(context), numberString, exception), exception);
+ JSStringRelease(numberString);
+
+ return JSValueIsInstanceOfConstructor(context, possibleValue, numberConstructor, exception);
+}
+
+static JSValueRef MyObject_convertToType(JSContextRef context, JSObjectRef object, JSType type, JSValueRef* exception)
+{
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(exception);
+
+ switch (type) {
+ case kJSTypeNumber:
+ return JSValueMakeNumber(context, 1);
+ case kJSTypeString:
+ {
+ JSStringRef string = JSStringCreateWithUTF8CString("MyObjectAsString");
+ JSValueRef result = JSValueMakeString(context, string);
+ JSStringRelease(string);
+ return result;
+ }
+ default:
+ break;
+ }
+
+ // string conversion -- forward to default object class
+ return JSValueMakeNull(context);
+}
+
+static JSValueRef MyObject_convertToTypeWrapper(JSContextRef context, JSObjectRef object, JSType type, JSValueRef* exception)
+{
+ UNUSED_PARAM(context);
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(type);
+ UNUSED_PARAM(exception);
+ // Forward to default object class
+ return 0;
+}
+
+static bool MyObject_set_nullGetForwardSet(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
+{
+ UNUSED_PARAM(ctx);
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(propertyName);
+ UNUSED_PARAM(value);
+ UNUSED_PARAM(exception);
+ return false; // Forward to parent class.
+}
+
+static JSStaticValue evilStaticValues[] = {
+ { "nullGetSet", 0, 0, kJSPropertyAttributeNone },
+ { "nullGetForwardSet", 0, MyObject_set_nullGetForwardSet, kJSPropertyAttributeNone },
+ { 0, 0, 0, 0 }
+};
+
+static JSStaticFunction evilStaticFunctions[] = {
+ { "nullCall", 0, kJSPropertyAttributeNone },
+ { 0, 0, 0 }
+};
+
+JSClassDefinition MyObject_definition = {
+ 0,
+ kJSClassAttributeNone,
+
+ "MyObject",
+ NULL,
+
+ evilStaticValues,
+ evilStaticFunctions,
+
+ NULL,
+ NULL,
+ MyObject_hasProperty,
+ MyObject_getProperty,
+ MyObject_setProperty,
+ MyObject_deleteProperty,
+ MyObject_getPropertyNames,
+ MyObject_callAsFunction,
+ MyObject_callAsConstructor,
+ MyObject_hasInstance,
+ MyObject_convertToType,
+};
+
+JSClassDefinition MyObject_convertToTypeWrapperDefinition = {
+ 0,
+ kJSClassAttributeNone,
+
+ "MyObject",
+ NULL,
+
+ NULL,
+ NULL,
+
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ MyObject_convertToTypeWrapper,
+};
+
+JSClassDefinition MyObject_nullWrapperDefinition = {
+ 0,
+ kJSClassAttributeNone,
+
+ "MyObject",
+ NULL,
+
+ NULL,
+ NULL,
+
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+};
+
+static JSClassRef MyObject_class(JSContextRef context)
+{
+ UNUSED_PARAM(context);
+
+ static JSClassRef jsClass;
+ if (!jsClass) {
+ JSClassRef baseClass = JSClassCreate(&MyObject_definition);
+ MyObject_convertToTypeWrapperDefinition.parentClass = baseClass;
+ JSClassRef wrapperClass = JSClassCreate(&MyObject_convertToTypeWrapperDefinition);
+ MyObject_nullWrapperDefinition.parentClass = wrapperClass;
+ jsClass = JSClassCreate(&MyObject_nullWrapperDefinition);
+ }
+
+ return jsClass;
+}
+
+static JSValueRef PropertyCatchalls_getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+ UNUSED_PARAM(context);
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(propertyName);
+ UNUSED_PARAM(exception);
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "x")) {
+ static size_t count;
+ if (count++ < 5)
+ return NULL;
+
+ // Swallow all .x gets after 5, returning null.
+ return JSValueMakeNull(context);
+ }
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "y")) {
+ static size_t count;
+ if (count++ < 5)
+ return NULL;
+
+ // Swallow all .y gets after 5, returning null.
+ return JSValueMakeNull(context);
+ }
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "z")) {
+ static size_t count;
+ if (count++ < 5)
+ return NULL;
+
+ // Swallow all .y gets after 5, returning null.
+ return JSValueMakeNull(context);
+ }
+
+ return NULL;
+}
+
+static bool PropertyCatchalls_setProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
+{
+ UNUSED_PARAM(context);
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(propertyName);
+ UNUSED_PARAM(value);
+ UNUSED_PARAM(exception);
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "x")) {
+ static size_t count;
+ if (count++ < 5)
+ return false;
+
+ // Swallow all .x sets after 4.
+ return true;
+ }
+
+ if (JSStringIsEqualToUTF8CString(propertyName, "make_throw") || JSStringIsEqualToUTF8CString(propertyName, "0")) {
+ *exception = JSValueMakeNumber(context, 5);
+ return true;
+ }
+
+ return false;
+}
+
+static void PropertyCatchalls_getPropertyNames(JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames)
+{
+ UNUSED_PARAM(context);
+ UNUSED_PARAM(object);
+
+ static size_t count;
+ static const char* numbers[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
+
+ // Provide a property of a different name every time.
+ JSStringRef propertyName = JSStringCreateWithUTF8CString(numbers[count++ % 10]);
+ JSPropertyNameAccumulatorAddName(propertyNames, propertyName);
+ JSStringRelease(propertyName);
+}
+
+JSClassDefinition PropertyCatchalls_definition = {
+ 0,
+ kJSClassAttributeNone,
+
+ "PropertyCatchalls",
+ NULL,
+
+ NULL,
+ NULL,
+
+ NULL,
+ NULL,
+ NULL,
+ PropertyCatchalls_getProperty,
+ PropertyCatchalls_setProperty,
+ NULL,
+ PropertyCatchalls_getPropertyNames,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+};
+
+static JSClassRef PropertyCatchalls_class(JSContextRef context)
+{
+ UNUSED_PARAM(context);
+
+ static JSClassRef jsClass;
+ if (!jsClass)
+ jsClass = JSClassCreate(&PropertyCatchalls_definition);
+
+ return jsClass;
+}
+
+static bool EvilExceptionObject_hasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef possibleValue, JSValueRef* exception)
+{
+ UNUSED_PARAM(context);
+ UNUSED_PARAM(constructor);
+
+ JSStringRef hasInstanceName = JSStringCreateWithUTF8CString("hasInstance");
+ JSValueRef hasInstance = JSObjectGetProperty(context, constructor, hasInstanceName, exception);
+ JSStringRelease(hasInstanceName);
+ if (!hasInstance)
+ return false;
+ JSObjectRef function = JSValueToObject(context, hasInstance, exception);
+ JSValueRef result = JSObjectCallAsFunction(context, function, constructor, 1, &possibleValue, exception);
+ return result && JSValueToBoolean(context, result);
+}
+
+static JSValueRef EvilExceptionObject_convertToType(JSContextRef context, JSObjectRef object, JSType type, JSValueRef* exception)
+{
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(exception);
+ JSStringRef funcName;
+ switch (type) {
+ case kJSTypeNumber:
+ funcName = JSStringCreateWithUTF8CString("toNumber");
+ break;
+ case kJSTypeString:
+ funcName = JSStringCreateWithUTF8CString("toStringExplicit");
+ break;
+ default:
+ return JSValueMakeNull(context);
+ }
+
+ JSValueRef func = JSObjectGetProperty(context, object, funcName, exception);
+ JSStringRelease(funcName);
+ JSObjectRef function = JSValueToObject(context, func, exception);
+ if (!function)
+ return JSValueMakeNull(context);
+ JSValueRef value = JSObjectCallAsFunction(context, function, object, 0, NULL, exception);
+ if (!value) {
+ JSStringRef errorString = JSStringCreateWithUTF8CString("convertToType failed");
+ JSValueRef errorStringRef = JSValueMakeString(context, errorString);
+ JSStringRelease(errorString);
+ return errorStringRef;
+ }
+ return value;
+}
+
+JSClassDefinition EvilExceptionObject_definition = {
+ 0,
+ kJSClassAttributeNone,
+
+ "EvilExceptionObject",
+ NULL,
+
+ NULL,
+ NULL,
+
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ EvilExceptionObject_hasInstance,
+ EvilExceptionObject_convertToType,
+};
+
+static JSClassRef EvilExceptionObject_class(JSContextRef context)
+{
+ UNUSED_PARAM(context);
+
+ static JSClassRef jsClass;
+ if (!jsClass)
+ jsClass = JSClassCreate(&EvilExceptionObject_definition);
+
+ return jsClass;
+}
+
+JSClassDefinition EmptyObject_definition = {
+ 0,
+ kJSClassAttributeNone,
+
+ NULL,
+ NULL,
+
+ NULL,
+ NULL,
+
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+};
+
+static JSClassRef EmptyObject_class(JSContextRef context)
+{
+ UNUSED_PARAM(context);
+
+ static JSClassRef jsClass;
+ if (!jsClass)
+ jsClass = JSClassCreate(&EmptyObject_definition);
+
+ return jsClass;
+}
+
+
+static JSValueRef Base_get(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(propertyName);
+ UNUSED_PARAM(exception);
+
+ return JSValueMakeNumber(ctx, 1); // distinguish base get form derived get
+}
+
+static bool Base_set(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
+{
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(propertyName);
+ UNUSED_PARAM(value);
+
+ *exception = JSValueMakeNumber(ctx, 1); // distinguish base set from derived set
+ return true;
+}
+
+static JSValueRef Base_callAsFunction(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ UNUSED_PARAM(function);
+ UNUSED_PARAM(thisObject);
+ UNUSED_PARAM(argumentCount);
+ UNUSED_PARAM(arguments);
+ UNUSED_PARAM(exception);
+
+ return JSValueMakeNumber(ctx, 1); // distinguish base call from derived call
+}
+
+static JSValueRef Base_returnHardNull(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ UNUSED_PARAM(ctx);
+ UNUSED_PARAM(function);
+ UNUSED_PARAM(thisObject);
+ UNUSED_PARAM(argumentCount);
+ UNUSED_PARAM(arguments);
+ UNUSED_PARAM(exception);
+
+ return 0; // should convert to undefined!
+}
+
+static JSStaticFunction Base_staticFunctions[] = {
+ { "baseProtoDup", NULL, kJSPropertyAttributeNone },
+ { "baseProto", Base_callAsFunction, kJSPropertyAttributeNone },
+ { "baseHardNull", Base_returnHardNull, kJSPropertyAttributeNone },
+ { 0, 0, 0 }
+};
+
+static JSStaticValue Base_staticValues[] = {
+ { "baseDup", Base_get, Base_set, kJSPropertyAttributeNone },
+ { "baseOnly", Base_get, Base_set, kJSPropertyAttributeNone },
+ { 0, 0, 0, 0 }
+};
+
+static bool TestInitializeFinalize;
+static void Base_initialize(JSContextRef context, JSObjectRef object)
+{
+ UNUSED_PARAM(context);
+
+ if (TestInitializeFinalize) {
+ ASSERT((void*)1 == JSObjectGetPrivate(object));
+ JSObjectSetPrivate(object, (void*)2);
+ }
+}
+
+static unsigned Base_didFinalize;
+static void Base_finalize(JSObjectRef object)
+{
+ UNUSED_PARAM(object);
+ if (TestInitializeFinalize) {
+ ASSERT((void*)4 == JSObjectGetPrivate(object));
+ Base_didFinalize = true;
+ }
+}
+
+static JSClassRef Base_class(JSContextRef context)
+{
+ UNUSED_PARAM(context);
+
+ static JSClassRef jsClass;
+ if (!jsClass) {
+ JSClassDefinition definition = kJSClassDefinitionEmpty;
+ definition.staticValues = Base_staticValues;
+ definition.staticFunctions = Base_staticFunctions;
+ definition.initialize = Base_initialize;
+ definition.finalize = Base_finalize;
+ jsClass = JSClassCreate(&definition);
+ }
+ return jsClass;
+}
+
+static JSValueRef Derived_get(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(propertyName);
+ UNUSED_PARAM(exception);
+
+ return JSValueMakeNumber(ctx, 2); // distinguish base get form derived get
+}
+
+static bool Derived_set(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
+{
+ UNUSED_PARAM(ctx);
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(propertyName);
+ UNUSED_PARAM(value);
+
+ *exception = JSValueMakeNumber(ctx, 2); // distinguish base set from derived set
+ return true;
+}
+
+static JSValueRef Derived_callAsFunction(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ UNUSED_PARAM(function);
+ UNUSED_PARAM(thisObject);
+ UNUSED_PARAM(argumentCount);
+ UNUSED_PARAM(arguments);
+ UNUSED_PARAM(exception);
+
+ return JSValueMakeNumber(ctx, 2); // distinguish base call from derived call
+}
+
+static JSStaticFunction Derived_staticFunctions[] = {
+ { "protoOnly", Derived_callAsFunction, kJSPropertyAttributeNone },
+ { "protoDup", NULL, kJSPropertyAttributeNone },
+ { "baseProtoDup", Derived_callAsFunction, kJSPropertyAttributeNone },
+ { 0, 0, 0 }
+};
+
+static JSStaticValue Derived_staticValues[] = {
+ { "derivedOnly", Derived_get, Derived_set, kJSPropertyAttributeNone },
+ { "protoDup", Derived_get, Derived_set, kJSPropertyAttributeNone },
+ { "baseDup", Derived_get, Derived_set, kJSPropertyAttributeNone },
+ { 0, 0, 0, 0 }
+};
+
+static void Derived_initialize(JSContextRef context, JSObjectRef object)
+{
+ UNUSED_PARAM(context);
+
+ if (TestInitializeFinalize) {
+ ASSERT((void*)2 == JSObjectGetPrivate(object));
+ JSObjectSetPrivate(object, (void*)3);
+ }
+}
+
+static void Derived_finalize(JSObjectRef object)
+{
+ if (TestInitializeFinalize) {
+ ASSERT((void*)3 == JSObjectGetPrivate(object));
+ JSObjectSetPrivate(object, (void*)4);
+ }
+}
+
+static JSClassRef Derived_class(JSContextRef context)
+{
+ static JSClassRef jsClass;
+ if (!jsClass) {
+ JSClassDefinition definition = kJSClassDefinitionEmpty;
+ definition.parentClass = Base_class(context);
+ definition.staticValues = Derived_staticValues;
+ definition.staticFunctions = Derived_staticFunctions;
+ definition.initialize = Derived_initialize;
+ definition.finalize = Derived_finalize;
+ jsClass = JSClassCreate(&definition);
+ }
+ return jsClass;
+}
+
+static JSClassRef Derived2_class(JSContextRef context)
+{
+ static JSClassRef jsClass;
+ if (!jsClass) {
+ JSClassDefinition definition = kJSClassDefinitionEmpty;
+ definition.parentClass = Derived_class(context);
+ jsClass = JSClassCreate(&definition);
+ }
+ return jsClass;
+}
+
+static JSValueRef print_callAsFunction(JSContextRef ctx, JSObjectRef functionObject, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ UNUSED_PARAM(functionObject);
+ UNUSED_PARAM(thisObject);
+ UNUSED_PARAM(exception);
+
+ ASSERT(JSContextGetGlobalContext(ctx) == context);
+
+ if (argumentCount > 0) {
+ JSStringRef string = JSValueToStringCopy(ctx, arguments[0], NULL);
+ size_t sizeUTF8 = JSStringGetMaximumUTF8CStringSize(string);
+ char* stringUTF8 = (char*)malloc(sizeUTF8);
+ JSStringGetUTF8CString(string, stringUTF8, sizeUTF8);
+ printf("%s\n", stringUTF8);
+ free(stringUTF8);
+ JSStringRelease(string);
+ }
+
+ return JSValueMakeUndefined(ctx);
+}
+
+static JSObjectRef myConstructor_callAsConstructor(JSContextRef context, JSObjectRef constructorObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ UNUSED_PARAM(constructorObject);
+ UNUSED_PARAM(exception);
+
+ JSObjectRef result = JSObjectMake(context, NULL, NULL);
+ if (argumentCount > 0) {
+ JSStringRef value = JSStringCreateWithUTF8CString("value");
+ JSObjectSetProperty(context, result, value, arguments[0], kJSPropertyAttributeNone, NULL);
+ JSStringRelease(value);
+ }
+
+ return result;
+}
+
+static JSObjectRef myBadConstructor_callAsConstructor(JSContextRef context, JSObjectRef constructorObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ UNUSED_PARAM(context);
+ UNUSED_PARAM(constructorObject);
+ UNUSED_PARAM(argumentCount);
+ UNUSED_PARAM(arguments);
+ UNUSED_PARAM(exception);
+
+ return 0;
+}
+
+
+static void globalObject_initialize(JSContextRef context, JSObjectRef object)
+{
+ UNUSED_PARAM(object);
+ // Ensure that an execution context is passed in
+ ASSERT(context);
+
+ JSObjectRef globalObject = JSContextGetGlobalObject(context);
+ ASSERT(globalObject);
+
+ // Ensure that the standard global properties have been set on the global object
+ JSStringRef array = JSStringCreateWithUTF8CString("Array");
+ JSObjectRef arrayConstructor = JSValueToObject(context, JSObjectGetProperty(context, globalObject, array, NULL), NULL);
+ JSStringRelease(array);
+
+ UNUSED_PARAM(arrayConstructor);
+ ASSERT(arrayConstructor);
+}
+
+static JSValueRef globalObject_get(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(propertyName);
+ UNUSED_PARAM(exception);
+
+ return JSValueMakeNumber(ctx, 3);
+}
+
+static bool globalObject_set(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
+{
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(propertyName);
+ UNUSED_PARAM(value);
+
+ *exception = JSValueMakeNumber(ctx, 3);
+ return true;
+}
+
+static JSValueRef globalObject_call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ UNUSED_PARAM(function);
+ UNUSED_PARAM(thisObject);
+ UNUSED_PARAM(argumentCount);
+ UNUSED_PARAM(arguments);
+ UNUSED_PARAM(exception);
+
+ return JSValueMakeNumber(ctx, 3);
+}
+
+static JSValueRef functionGC(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ UNUSED_PARAM(function);
+ UNUSED_PARAM(thisObject);
+ UNUSED_PARAM(argumentCount);
+ UNUSED_PARAM(arguments);
+ UNUSED_PARAM(exception);
+ JSGarbageCollect(context);
+ return JSValueMakeUndefined(context);
+}
+
+static JSStaticValue globalObject_staticValues[] = {
+ { "globalStaticValue", globalObject_get, globalObject_set, kJSPropertyAttributeNone },
+ { 0, 0, 0, 0 }
+};
+
+static JSStaticFunction globalObject_staticFunctions[] = {
+ { "globalStaticFunction", globalObject_call, kJSPropertyAttributeNone },
+ { "globalStaticFunction2", globalObject_call, kJSPropertyAttributeNone },
+ { "gc", functionGC, kJSPropertyAttributeNone },
+ { 0, 0, 0 }
+};
+
+static char* createStringWithContentsOfFile(const char* fileName);
+
+static void testInitializeFinalize()
+{
+ JSObjectRef o = JSObjectMake(context, Derived_class(context), (void*)1);
+ UNUSED_PARAM(o);
+ ASSERT(JSObjectGetPrivate(o) == (void*)3);
+}
+
+static JSValueRef jsNumberValue = NULL;
+
+static JSObjectRef aHeapRef = NULL;
+
+static void makeGlobalNumberValue(JSContextRef context) {
+ JSValueRef v = JSValueMakeNumber(context, 420);
+ JSValueProtect(context, v);
+ jsNumberValue = v;
+ v = NULL;
+}
+
+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;
+}
+
+static JSValueRef valueToObjectExceptionCallAsFunction(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ UNUSED_PARAM(function);
+ UNUSED_PARAM(thisObject);
+ UNUSED_PARAM(argumentCount);
+ UNUSED_PARAM(arguments);
+ JSValueRef jsUndefined = JSValueMakeUndefined(JSContextGetGlobalContext(ctx));
+ JSValueToObject(JSContextGetGlobalContext(ctx), jsUndefined, exception);
+
+ return JSValueMakeUndefined(ctx);
+}
+static bool valueToObjectExceptionTest()
+{
+ JSGlobalContextRef testContext;
+ JSClassDefinition globalObjectClassDefinition = kJSClassDefinitionEmpty;
+ globalObjectClassDefinition.initialize = globalObject_initialize;
+ globalObjectClassDefinition.staticValues = globalObject_staticValues;
+ globalObjectClassDefinition.staticFunctions = globalObject_staticFunctions;
+ globalObjectClassDefinition.attributes = kJSClassAttributeNoAutomaticPrototype;
+ JSClassRef globalObjectClass = JSClassCreate(&globalObjectClassDefinition);
+ testContext = JSGlobalContextCreateInGroup(NULL, globalObjectClass);
+ JSObjectRef globalObject = JSContextGetGlobalObject(testContext);
+
+ JSStringRef valueToObject = JSStringCreateWithUTF8CString("valueToObject");
+ JSObjectRef valueToObjectFunction = JSObjectMakeFunctionWithCallback(testContext, valueToObject, valueToObjectExceptionCallAsFunction);
+ JSObjectSetProperty(testContext, globalObject, valueToObject, valueToObjectFunction, kJSPropertyAttributeNone, NULL);
+ JSStringRelease(valueToObject);
+
+ JSStringRef test = JSStringCreateWithUTF8CString("valueToObject();");
+ JSEvaluateScript(testContext, test, NULL, NULL, 1, NULL);
+
+ JSStringRelease(test);
+ JSClassRelease(globalObjectClass);
+ JSGlobalContextRelease(testContext);
+
+ return true;
+}
+
+static bool globalContextNameTest()
+{
+ bool result = true;
+ JSGlobalContextRef context = JSGlobalContextCreate(0);
+
+ JSStringRef str = JSGlobalContextCopyName(context);
+ result &= assertTrue(!str, "Default context name is NULL");
+
+ JSStringRef name1 = JSStringCreateWithUTF8CString("name1");
+ JSStringRef name2 = JSStringCreateWithUTF8CString("name2");
+
+ JSGlobalContextSetName(context, name1);
+ JSStringRef fetchName1 = JSGlobalContextCopyName(context);
+ JSGlobalContextSetName(context, name2);
+ JSStringRef fetchName2 = JSGlobalContextCopyName(context);
+ JSGlobalContextSetName(context, NULL);
+ JSStringRef fetchName3 = JSGlobalContextCopyName(context);
+
+ result &= assertTrue(JSStringIsEqual(name1, fetchName1), "Unexpected Context name");
+ result &= assertTrue(JSStringIsEqual(name2, fetchName2), "Unexpected Context name");
+ result &= assertTrue(!JSStringIsEqual(fetchName1, fetchName2), "Unexpected Context name");
+ result &= assertTrue(!fetchName3, "Unexpected Context name");
+
+ JSStringRelease(name1);
+ JSStringRelease(name2);
+ JSStringRelease(fetchName1);
+ JSStringRelease(fetchName2);
+
+ return result;
+}
+
+static void checkConstnessInJSObjectNames()
+{
+ JSStaticFunction fun;
+ fun.name = "something";
+ JSStaticValue val;
+ val.name = "something";
+}
+
+int main(int argc, char* argv[])
+{
+#if OS(WINDOWS)
+ // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
+ // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
+ // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
+ ::SetErrorMode(0);
+#endif
+
+ testCompareAndSwap();
+
+#if JSC_OBJC_API_ENABLED
+ testObjectiveCAPI();
+#endif
+
+ const char *scriptPath = "testapi.js";
+ if (argc > 1) {
+ scriptPath = argv[1];
+ }
+
+ // Test garbage collection with a fresh context
+ context = JSGlobalContextCreateInGroup(NULL, NULL);
+ TestInitializeFinalize = true;
+ testInitializeFinalize();
+ JSGlobalContextRelease(context);
+ TestInitializeFinalize = false;
+
+ ASSERT(Base_didFinalize);
+
+ JSClassDefinition globalObjectClassDefinition = kJSClassDefinitionEmpty;
+ globalObjectClassDefinition.initialize = globalObject_initialize;
+ globalObjectClassDefinition.staticValues = globalObject_staticValues;
+ globalObjectClassDefinition.staticFunctions = globalObject_staticFunctions;
+ globalObjectClassDefinition.attributes = kJSClassAttributeNoAutomaticPrototype;
+ JSClassRef globalObjectClass = JSClassCreate(&globalObjectClassDefinition);
+ context = JSGlobalContextCreateInGroup(NULL, globalObjectClass);
+
+ JSContextGroupRef contextGroup = JSContextGetGroup(context);
+
+ JSGlobalContextRetain(context);
+ JSGlobalContextRelease(context);
+ ASSERT(JSContextGetGlobalContext(context) == context);
+
+ JSReportExtraMemoryCost(context, 0);
+ JSReportExtraMemoryCost(context, 1);
+ JSReportExtraMemoryCost(context, 1024);
+
+ JSObjectRef globalObject = JSContextGetGlobalObject(context);
+ ASSERT(JSValueIsObject(context, globalObject));
+
+ JSValueRef jsUndefined = JSValueMakeUndefined(context);
+ JSValueRef jsNull = JSValueMakeNull(context);
+ JSValueRef jsTrue = JSValueMakeBoolean(context, true);
+ JSValueRef jsFalse = JSValueMakeBoolean(context, false);
+ JSValueRef jsZero = JSValueMakeNumber(context, 0);
+ JSValueRef jsOne = JSValueMakeNumber(context, 1);
+ JSValueRef jsOneThird = JSValueMakeNumber(context, 1.0 / 3.0);
+ JSObjectRef jsObjectNoProto = JSObjectMake(context, NULL, NULL);
+ JSObjectSetPrototype(context, jsObjectNoProto, JSValueMakeNull(context));
+
+ JSObjectSetPrivate(globalObject, (void*)123);
+ if (JSObjectGetPrivate(globalObject) != (void*)123) {
+ printf("FAIL: Didn't return private data when set by JSObjectSetPrivate().\n");
+ failed = 1;
+ } else
+ printf("PASS: returned private data when set by JSObjectSetPrivate().\n");
+
+ // FIXME: test funny utf8 characters
+ JSStringRef jsEmptyIString = JSStringCreateWithUTF8CString("");
+ JSValueRef jsEmptyString = JSValueMakeString(context, jsEmptyIString);
+
+ JSStringRef jsOneIString = JSStringCreateWithUTF8CString("1");
+ JSValueRef jsOneString = JSValueMakeString(context, jsOneIString);
+
+ UniChar singleUniChar = 65; // Capital A
+ CFMutableStringRef cfString =
+ CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorDefault,
+ &singleUniChar,
+ 1,
+ 1,
+ kCFAllocatorNull);
+
+ JSStringRef jsCFIString = JSStringCreateWithCFString(cfString);
+ JSValueRef jsCFString = JSValueMakeString(context, jsCFIString);
+
+ CFStringRef cfEmptyString = CFStringCreateWithCString(kCFAllocatorDefault, "", kCFStringEncodingUTF8);
+
+ JSStringRef jsCFEmptyIString = JSStringCreateWithCFString(cfEmptyString);
+ JSValueRef jsCFEmptyString = JSValueMakeString(context, jsCFEmptyIString);
+
+ CFIndex cfStringLength = CFStringGetLength(cfString);
+ UniChar* buffer = (UniChar*)malloc(cfStringLength * sizeof(UniChar));
+ CFStringGetCharacters(cfString,
+ CFRangeMake(0, cfStringLength),
+ buffer);
+ JSStringRef jsCFIStringWithCharacters = JSStringCreateWithCharacters((JSChar*)buffer, cfStringLength);
+ JSValueRef jsCFStringWithCharacters = JSValueMakeString(context, jsCFIStringWithCharacters);
+
+ JSStringRef jsCFEmptyIStringWithCharacters = JSStringCreateWithCharacters((JSChar*)buffer, CFStringGetLength(cfEmptyString));
+ free(buffer);
+ JSValueRef jsCFEmptyStringWithCharacters = JSValueMakeString(context, jsCFEmptyIStringWithCharacters);
+
+ JSChar constantString[] = { 'H', 'e', 'l', 'l', 'o', };
+ JSStringRef constantStringRef = JSStringCreateWithCharactersNoCopy(constantString, sizeof(constantString) / sizeof(constantString[0]));
+ ASSERT(JSStringGetCharactersPtr(constantStringRef) == constantString);
+ JSStringRelease(constantStringRef);
+
+ ASSERT(JSValueGetType(context, NULL) == kJSTypeNull);
+ ASSERT(JSValueGetType(context, jsUndefined) == kJSTypeUndefined);
+ ASSERT(JSValueGetType(context, jsNull) == kJSTypeNull);
+ ASSERT(JSValueGetType(context, jsTrue) == kJSTypeBoolean);
+ ASSERT(JSValueGetType(context, jsFalse) == kJSTypeBoolean);
+ ASSERT(JSValueGetType(context, jsZero) == kJSTypeNumber);
+ ASSERT(JSValueGetType(context, jsOne) == kJSTypeNumber);
+ ASSERT(JSValueGetType(context, jsOneThird) == kJSTypeNumber);
+ ASSERT(JSValueGetType(context, jsEmptyString) == kJSTypeString);
+ ASSERT(JSValueGetType(context, jsOneString) == kJSTypeString);
+ ASSERT(JSValueGetType(context, jsCFString) == kJSTypeString);
+ ASSERT(JSValueGetType(context, jsCFStringWithCharacters) == kJSTypeString);
+ ASSERT(JSValueGetType(context, jsCFEmptyString) == kJSTypeString);
+ ASSERT(JSValueGetType(context, jsCFEmptyStringWithCharacters) == kJSTypeString);
+
+ ASSERT(!JSValueIsBoolean(context, NULL));
+ ASSERT(!JSValueIsObject(context, NULL));
+ ASSERT(!JSValueIsArray(context, NULL));
+ ASSERT(!JSValueIsDate(context, NULL));
+ ASSERT(!JSValueIsString(context, NULL));
+ ASSERT(!JSValueIsNumber(context, NULL));
+ ASSERT(!JSValueIsUndefined(context, NULL));
+ ASSERT(JSValueIsNull(context, NULL));
+ ASSERT(!JSObjectCallAsFunction(context, NULL, NULL, 0, NULL, NULL));
+ ASSERT(!JSObjectCallAsConstructor(context, NULL, 0, NULL, NULL));
+ ASSERT(!JSObjectIsConstructor(context, NULL));
+ ASSERT(!JSObjectIsFunction(context, NULL));
+
+ JSStringRef nullString = JSStringCreateWithUTF8CString(0);
+ const JSChar* characters = JSStringGetCharactersPtr(nullString);
+ if (characters) {
+ printf("FAIL: Didn't return null when accessing character pointer of a null String.\n");
+ failed = 1;
+ } else
+ printf("PASS: returned null when accessing character pointer of a null String.\n");
+
+ JSStringRef emptyString = JSStringCreateWithCFString(CFSTR(""));
+ characters = JSStringGetCharactersPtr(emptyString);
+ if (!characters) {
+ printf("FAIL: Returned null when accessing character pointer of an empty String.\n");
+ failed = 1;
+ } else
+ printf("PASS: returned empty when accessing character pointer of an empty String.\n");
+
+ size_t length = JSStringGetLength(nullString);
+ if (length) {
+ printf("FAIL: Didn't return 0 length for null String.\n");
+ failed = 1;
+ } else
+ printf("PASS: returned 0 length for null String.\n");
+ JSStringRelease(nullString);
+
+ length = JSStringGetLength(emptyString);
+ if (length) {
+ printf("FAIL: Didn't return 0 length for empty String.\n");
+ failed = 1;
+ } else
+ printf("PASS: returned 0 length for empty String.\n");
+ JSStringRelease(emptyString);
+
+ JSObjectRef propertyCatchalls = JSObjectMake(context, PropertyCatchalls_class(context), NULL);
+ JSStringRef propertyCatchallsString = JSStringCreateWithUTF8CString("PropertyCatchalls");
+ JSObjectSetProperty(context, globalObject, propertyCatchallsString, propertyCatchalls, kJSPropertyAttributeNone, NULL);
+ JSStringRelease(propertyCatchallsString);
+
+ JSObjectRef myObject = JSObjectMake(context, MyObject_class(context), NULL);
+ JSStringRef myObjectIString = JSStringCreateWithUTF8CString("MyObject");
+ JSObjectSetProperty(context, globalObject, myObjectIString, myObject, kJSPropertyAttributeNone, NULL);
+ JSStringRelease(myObjectIString);
+
+ JSObjectRef EvilExceptionObject = JSObjectMake(context, EvilExceptionObject_class(context), NULL);
+ JSStringRef EvilExceptionObjectIString = JSStringCreateWithUTF8CString("EvilExceptionObject");
+ JSObjectSetProperty(context, globalObject, EvilExceptionObjectIString, EvilExceptionObject, kJSPropertyAttributeNone, NULL);
+ JSStringRelease(EvilExceptionObjectIString);
+
+ JSObjectRef EmptyObject = JSObjectMake(context, EmptyObject_class(context), NULL);
+ JSStringRef EmptyObjectIString = JSStringCreateWithUTF8CString("EmptyObject");
+ 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 nullJSON = JSStringCreateWithUTF8CString(0);
+ JSValueRef nullJSONObject = JSValueMakeFromJSONString(context, nullJSON);
+ if (nullJSONObject) {
+ printf("FAIL: Did not parse null String as JSON correctly\n");
+ failed = 1;
+ } else
+ printf("PASS: Parsed null String as JSON correctly.\n");
+ JSStringRelease(nullJSON);
+
+ 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);
+
+ str = JSStringCreateWithUTF8CString("({get a(){ throw '';}})");
+ JSValueRef unstringifiableObj = JSEvaluateScript(context, str, NULL, NULL, 1, NULL);
+ JSStringRelease(str);
+
+ 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));
+ ASSERT(exception);
+
+ exception = NULL;
+ // FIXME <rdar://4668451> - On i386 the isnan(double) macro tries to map to the isnan(float) function,
+ // causing a build break with -Wshorten-64-to-32 enabled. The issue is known by the appropriate team.
+ // After that's resolved, we can remove these casts
+ ASSERT(isnan((float)JSValueToNumber(context, jsObjectNoProto, &exception)));
+ ASSERT(exception);
+
+ exception = NULL;
+ ASSERT(!JSValueToStringCopy(context, jsObjectNoProto, &exception));
+ ASSERT(exception);
+
+ ASSERT(JSValueToBoolean(context, myObject));
+
+ exception = NULL;
+ ASSERT(!JSValueIsEqual(context, jsObjectNoProto, JSValueMakeNumber(context, 1), &exception));
+ ASSERT(exception);
+
+ exception = NULL;
+ JSObjectGetPropertyAtIndex(context, myObject, 0, &exception);
+ ASSERT(1 == JSValueToNumber(context, exception, NULL));
+
+ assertEqualsAsBoolean(jsUndefined, false);
+ assertEqualsAsBoolean(jsNull, false);
+ assertEqualsAsBoolean(jsTrue, true);
+ assertEqualsAsBoolean(jsFalse, false);
+ assertEqualsAsBoolean(jsZero, false);
+ assertEqualsAsBoolean(jsOne, true);
+ assertEqualsAsBoolean(jsOneThird, true);
+ assertEqualsAsBoolean(jsEmptyString, false);
+ assertEqualsAsBoolean(jsOneString, true);
+ assertEqualsAsBoolean(jsCFString, true);
+ assertEqualsAsBoolean(jsCFStringWithCharacters, true);
+ assertEqualsAsBoolean(jsCFEmptyString, false);
+ assertEqualsAsBoolean(jsCFEmptyStringWithCharacters, false);
+
+ assertEqualsAsNumber(jsUndefined, nan(""));
+ assertEqualsAsNumber(jsNull, 0);
+ assertEqualsAsNumber(jsTrue, 1);
+ assertEqualsAsNumber(jsFalse, 0);
+ assertEqualsAsNumber(jsZero, 0);
+ assertEqualsAsNumber(jsOne, 1);
+ assertEqualsAsNumber(jsOneThird, 1.0 / 3.0);
+ assertEqualsAsNumber(jsEmptyString, 0);
+ assertEqualsAsNumber(jsOneString, 1);
+ assertEqualsAsNumber(jsCFString, nan(""));
+ assertEqualsAsNumber(jsCFStringWithCharacters, nan(""));
+ assertEqualsAsNumber(jsCFEmptyString, 0);
+ assertEqualsAsNumber(jsCFEmptyStringWithCharacters, 0);
+ ASSERT(sizeof(JSChar) == sizeof(UniChar));
+
+ assertEqualsAsCharactersPtr(jsUndefined, "undefined");
+ assertEqualsAsCharactersPtr(jsNull, "null");
+ assertEqualsAsCharactersPtr(jsTrue, "true");
+ assertEqualsAsCharactersPtr(jsFalse, "false");
+ assertEqualsAsCharactersPtr(jsZero, "0");
+ assertEqualsAsCharactersPtr(jsOne, "1");
+ assertEqualsAsCharactersPtr(jsOneThird, "0.3333333333333333");
+ assertEqualsAsCharactersPtr(jsEmptyString, "");
+ assertEqualsAsCharactersPtr(jsOneString, "1");
+ assertEqualsAsCharactersPtr(jsCFString, "A");
+ assertEqualsAsCharactersPtr(jsCFStringWithCharacters, "A");
+ assertEqualsAsCharactersPtr(jsCFEmptyString, "");
+ assertEqualsAsCharactersPtr(jsCFEmptyStringWithCharacters, "");
+
+ assertEqualsAsUTF8String(jsUndefined, "undefined");
+ assertEqualsAsUTF8String(jsNull, "null");
+ assertEqualsAsUTF8String(jsTrue, "true");
+ assertEqualsAsUTF8String(jsFalse, "false");
+ assertEqualsAsUTF8String(jsZero, "0");
+ assertEqualsAsUTF8String(jsOne, "1");
+ assertEqualsAsUTF8String(jsOneThird, "0.3333333333333333");
+ assertEqualsAsUTF8String(jsEmptyString, "");
+ assertEqualsAsUTF8String(jsOneString, "1");
+ assertEqualsAsUTF8String(jsCFString, "A");
+ assertEqualsAsUTF8String(jsCFStringWithCharacters, "A");
+ assertEqualsAsUTF8String(jsCFEmptyString, "");
+ assertEqualsAsUTF8String(jsCFEmptyStringWithCharacters, "");
+
+ checkConstnessInJSObjectNames();
+
+ ASSERT(JSValueIsStrictEqual(context, jsTrue, jsTrue));
+ ASSERT(!JSValueIsStrictEqual(context, jsOne, jsOneString));
+
+ ASSERT(JSValueIsEqual(context, jsOne, jsOneString, NULL));
+ ASSERT(!JSValueIsEqual(context, jsTrue, jsFalse, NULL));
+
+ CFStringRef cfJSString = JSStringCopyCFString(kCFAllocatorDefault, jsCFIString);
+ CFStringRef cfJSEmptyString = JSStringCopyCFString(kCFAllocatorDefault, jsCFEmptyIString);
+ ASSERT(CFEqual(cfJSString, cfString));
+ ASSERT(CFEqual(cfJSEmptyString, cfEmptyString));
+ CFRelease(cfJSString);
+ CFRelease(cfJSEmptyString);
+
+ CFRelease(cfString);
+ CFRelease(cfEmptyString);
+
+ jsGlobalValue = JSObjectMake(context, NULL, NULL);
+ makeGlobalNumberValue(context);
+ JSValueProtect(context, jsGlobalValue);
+ JSGarbageCollect(context);
+ ASSERT(JSValueIsObject(context, jsGlobalValue));
+ JSValueUnprotect(context, jsGlobalValue);
+ JSValueUnprotect(context, jsNumberValue);
+
+ JSStringRef goodSyntax = JSStringCreateWithUTF8CString("x = 1;");
+ const char* badSyntaxConstant = "x := 1;";
+ JSStringRef badSyntax = JSStringCreateWithUTF8CString(badSyntaxConstant);
+ ASSERT(JSCheckScriptSyntax(context, goodSyntax, NULL, 0, NULL));
+ ASSERT(!JSCheckScriptSyntax(context, badSyntax, NULL, 0, NULL));
+ ASSERT(!JSScriptCreateFromString(contextGroup, 0, 0, badSyntax, 0, 0));
+ ASSERT(!JSScriptCreateReferencingImmortalASCIIText(contextGroup, 0, 0, badSyntaxConstant, strlen(badSyntaxConstant), 0, 0));
+
+ JSValueRef result;
+ JSValueRef v;
+ JSObjectRef o;
+ JSStringRef string;
+
+ result = JSEvaluateScript(context, goodSyntax, NULL, NULL, 1, NULL);
+ ASSERT(result);
+ ASSERT(JSValueIsEqual(context, result, jsOne, NULL));
+
+ exception = NULL;
+ result = JSEvaluateScript(context, badSyntax, NULL, NULL, 1, &exception);
+ ASSERT(!result);
+ ASSERT(JSValueIsObject(context, exception));
+
+ JSStringRef array = JSStringCreateWithUTF8CString("Array");
+ JSObjectRef arrayConstructor = JSValueToObject(context, JSObjectGetProperty(context, globalObject, array, NULL), NULL);
+ JSStringRelease(array);
+ result = JSObjectCallAsConstructor(context, arrayConstructor, 0, NULL, NULL);
+ ASSERT(result);
+ ASSERT(JSValueIsObject(context, result));
+ ASSERT(JSValueIsInstanceOfConstructor(context, result, arrayConstructor, NULL));
+ ASSERT(!JSValueIsInstanceOfConstructor(context, JSValueMakeNull(context), arrayConstructor, NULL));
+
+ o = JSValueToObject(context, result, NULL);
+ exception = NULL;
+ ASSERT(JSValueIsUndefined(context, JSObjectGetPropertyAtIndex(context, o, 0, &exception)));
+ ASSERT(!exception);
+
+ JSObjectSetPropertyAtIndex(context, o, 0, JSValueMakeNumber(context, 1), &exception);
+ ASSERT(!exception);
+
+ exception = NULL;
+ ASSERT(1 == JSValueToNumber(context, JSObjectGetPropertyAtIndex(context, o, 0, &exception), &exception));
+ ASSERT(!exception);
+
+ JSStringRef functionBody;
+ JSObjectRef function;
+
+ exception = NULL;
+ functionBody = JSStringCreateWithUTF8CString("rreturn Array;");
+ JSStringRef line = JSStringCreateWithUTF8CString("line");
+ ASSERT(!JSObjectMakeFunction(context, NULL, 0, NULL, functionBody, NULL, 1, &exception));
+ ASSERT(JSValueIsObject(context, exception));
+ v = JSObjectGetProperty(context, JSValueToObject(context, exception, NULL), line, NULL);
+ assertEqualsAsNumber(v, 2);
+ JSStringRelease(functionBody);
+ JSStringRelease(line);
+
+ exception = NULL;
+ functionBody = JSStringCreateWithUTF8CString("rreturn Array;");
+ line = JSStringCreateWithUTF8CString("line");
+ ASSERT(!JSObjectMakeFunction(context, NULL, 0, NULL, functionBody, NULL, -42, &exception));
+ ASSERT(JSValueIsObject(context, exception));
+ v = JSObjectGetProperty(context, JSValueToObject(context, exception, NULL), line, NULL);
+ assertEqualsAsNumber(v, 2);
+ JSStringRelease(functionBody);
+ JSStringRelease(line);
+
+ exception = NULL;
+ functionBody = JSStringCreateWithUTF8CString("// Line one.\nrreturn Array;");
+ line = JSStringCreateWithUTF8CString("line");
+ ASSERT(!JSObjectMakeFunction(context, NULL, 0, NULL, functionBody, NULL, 1, &exception));
+ ASSERT(JSValueIsObject(context, exception));
+ v = JSObjectGetProperty(context, JSValueToObject(context, exception, NULL), line, NULL);
+ assertEqualsAsNumber(v, 3);
+ JSStringRelease(functionBody);
+ JSStringRelease(line);
+
+ exception = NULL;
+ functionBody = JSStringCreateWithUTF8CString("return Array;");
+ function = JSObjectMakeFunction(context, NULL, 0, NULL, functionBody, NULL, 1, &exception);
+ JSStringRelease(functionBody);
+ ASSERT(!exception);
+ ASSERT(JSObjectIsFunction(context, function));
+ v = JSObjectCallAsFunction(context, function, NULL, 0, NULL, NULL);
+ ASSERT(v);
+ ASSERT(JSValueIsEqual(context, v, arrayConstructor, NULL));
+
+ exception = NULL;
+ function = JSObjectMakeFunction(context, NULL, 0, NULL, jsEmptyIString, NULL, 0, &exception);
+ ASSERT(!exception);
+ v = JSObjectCallAsFunction(context, function, NULL, 0, NULL, &exception);
+ ASSERT(v && !exception);
+ ASSERT(JSValueIsUndefined(context, v));
+
+ exception = NULL;
+ v = NULL;
+ JSStringRef foo = JSStringCreateWithUTF8CString("foo");
+ JSStringRef argumentNames[] = { foo };
+ functionBody = JSStringCreateWithUTF8CString("return foo;");
+ function = JSObjectMakeFunction(context, foo, 1, argumentNames, functionBody, NULL, 1, &exception);
+ ASSERT(function && !exception);
+ JSValueRef arguments[] = { JSValueMakeNumber(context, 2) };
+ JSObjectCallAsFunction(context, function, NULL, 1, arguments, &exception);
+ JSStringRelease(foo);
+ JSStringRelease(functionBody);
+
+ string = JSValueToStringCopy(context, function, NULL);
+ assertEqualsAsUTF8String(JSValueMakeString(context, string), "function foo(foo) {\nreturn foo;\n}");
+ JSStringRelease(string);
+
+ JSStringRef print = JSStringCreateWithUTF8CString("print");
+ JSObjectRef printFunction = JSObjectMakeFunctionWithCallback(context, print, print_callAsFunction);
+ JSObjectSetProperty(context, globalObject, print, printFunction, kJSPropertyAttributeNone, NULL);
+ JSStringRelease(print);
+
+ ASSERT(!JSObjectSetPrivate(printFunction, (void*)1));
+ ASSERT(!JSObjectGetPrivate(printFunction));
+
+ JSStringRef myConstructorIString = JSStringCreateWithUTF8CString("MyConstructor");
+ JSObjectRef myConstructor = JSObjectMakeConstructor(context, NULL, myConstructor_callAsConstructor);
+ JSObjectSetProperty(context, globalObject, myConstructorIString, myConstructor, kJSPropertyAttributeNone, NULL);
+ JSStringRelease(myConstructorIString);
+
+ JSStringRef myBadConstructorIString = JSStringCreateWithUTF8CString("MyBadConstructor");
+ JSObjectRef myBadConstructor = JSObjectMakeConstructor(context, NULL, myBadConstructor_callAsConstructor);
+ JSObjectSetProperty(context, globalObject, myBadConstructorIString, myBadConstructor, kJSPropertyAttributeNone, NULL);
+ JSStringRelease(myBadConstructorIString);
+
+ ASSERT(!JSObjectSetPrivate(myConstructor, (void*)1));
+ ASSERT(!JSObjectGetPrivate(myConstructor));
+
+ string = JSStringCreateWithUTF8CString("Base");
+ JSObjectRef baseConstructor = JSObjectMakeConstructor(context, Base_class(context), NULL);
+ JSObjectSetProperty(context, globalObject, string, baseConstructor, kJSPropertyAttributeNone, NULL);
+ JSStringRelease(string);
+
+ string = JSStringCreateWithUTF8CString("Derived");
+ JSObjectRef derivedConstructor = JSObjectMakeConstructor(context, Derived_class(context), NULL);
+ JSObjectSetProperty(context, globalObject, string, derivedConstructor, kJSPropertyAttributeNone, NULL);
+ JSStringRelease(string);
+
+ string = JSStringCreateWithUTF8CString("Derived2");
+ JSObjectRef derived2Constructor = JSObjectMakeConstructor(context, Derived2_class(context), NULL);
+ JSObjectSetProperty(context, globalObject, string, derived2Constructor, kJSPropertyAttributeNone, NULL);
+ JSStringRelease(string);
+
+ o = JSObjectMake(context, NULL, NULL);
+ JSObjectSetProperty(context, o, jsOneIString, JSValueMakeNumber(context, 1), kJSPropertyAttributeNone, NULL);
+ JSObjectSetProperty(context, o, jsCFIString, JSValueMakeNumber(context, 1), kJSPropertyAttributeDontEnum, NULL);
+ JSPropertyNameArrayRef nameArray = JSObjectCopyPropertyNames(context, o);
+ size_t expectedCount = JSPropertyNameArrayGetCount(nameArray);
+ size_t count;
+ for (count = 0; count < expectedCount; ++count)
+ JSPropertyNameArrayGetNameAtIndex(nameArray, count);
+ JSPropertyNameArrayRelease(nameArray);
+ ASSERT(count == 1); // jsCFString should not be enumerated
+
+ JSValueRef argumentsArrayValues[] = { JSValueMakeNumber(context, 10), JSValueMakeNumber(context, 20) };
+ o = JSObjectMakeArray(context, sizeof(argumentsArrayValues) / sizeof(JSValueRef), argumentsArrayValues, NULL);
+ string = JSStringCreateWithUTF8CString("length");
+ v = JSObjectGetProperty(context, o, string, NULL);
+ assertEqualsAsNumber(v, 2);
+ v = JSObjectGetPropertyAtIndex(context, o, 0, NULL);
+ assertEqualsAsNumber(v, 10);
+ v = JSObjectGetPropertyAtIndex(context, o, 1, NULL);
+ assertEqualsAsNumber(v, 20);
+
+ o = JSObjectMakeArray(context, 0, NULL, NULL);
+ v = JSObjectGetProperty(context, o, string, NULL);
+ assertEqualsAsNumber(v, 0);
+ JSStringRelease(string);
+
+ JSValueRef argumentsDateValues[] = { JSValueMakeNumber(context, 0) };
+ o = JSObjectMakeDate(context, 1, argumentsDateValues, NULL);
+ if (timeZoneIsPST())
+ assertEqualsAsUTF8String(o, "Wed Dec 31 1969 16:00:00 GMT-0800 (PST)");
+
+ string = JSStringCreateWithUTF8CString("an error message");
+ JSValueRef argumentsErrorValues[] = { JSValueMakeString(context, string) };
+ o = JSObjectMakeError(context, 1, argumentsErrorValues, NULL);
+ assertEqualsAsUTF8String(o, "Error: an error message");
+ JSStringRelease(string);
+
+ string = JSStringCreateWithUTF8CString("foo");
+ JSStringRef string2 = JSStringCreateWithUTF8CString("gi");
+ JSValueRef argumentsRegExpValues[] = { JSValueMakeString(context, string), JSValueMakeString(context, string2) };
+ o = JSObjectMakeRegExp(context, 2, argumentsRegExpValues, NULL);
+ assertEqualsAsUTF8String(o, "/foo/gi");
+ JSStringRelease(string);
+ JSStringRelease(string2);
+
+ JSClassDefinition nullDefinition = kJSClassDefinitionEmpty;
+ nullDefinition.attributes = kJSClassAttributeNoAutomaticPrototype;
+ JSClassRef nullClass = JSClassCreate(&nullDefinition);
+ JSClassRelease(nullClass);
+
+ nullDefinition = kJSClassDefinitionEmpty;
+ nullClass = JSClassCreate(&nullDefinition);
+ JSClassRelease(nullClass);
+
+ functionBody = JSStringCreateWithUTF8CString("return this;");
+ function = JSObjectMakeFunction(context, NULL, 0, NULL, functionBody, NULL, 1, NULL);
+ JSStringRelease(functionBody);
+ v = JSObjectCallAsFunction(context, function, NULL, 0, NULL, NULL);
+ ASSERT(JSValueIsEqual(context, v, globalObject, NULL));
+ v = JSObjectCallAsFunction(context, function, o, 0, NULL, NULL);
+ ASSERT(JSValueIsEqual(context, v, o, NULL));
+
+ functionBody = JSStringCreateWithUTF8CString("return eval(\"this\");");
+ function = JSObjectMakeFunction(context, NULL, 0, NULL, functionBody, NULL, 1, NULL);
+ JSStringRelease(functionBody);
+ v = JSObjectCallAsFunction(context, function, NULL, 0, NULL, NULL);
+ ASSERT(JSValueIsEqual(context, v, globalObject, NULL));
+ v = JSObjectCallAsFunction(context, function, o, 0, NULL, NULL);
+ ASSERT(JSValueIsEqual(context, v, o, NULL));
+
+ const char* thisScript = "this;";
+ JSStringRef script = JSStringCreateWithUTF8CString(thisScript);
+ v = JSEvaluateScript(context, script, NULL, NULL, 1, NULL);
+ ASSERT(JSValueIsEqual(context, v, globalObject, NULL));
+ v = JSEvaluateScript(context, script, o, NULL, 1, NULL);
+ ASSERT(JSValueIsEqual(context, v, o, NULL));
+ JSStringRelease(script);
+
+ JSScriptRef scriptObject = JSScriptCreateReferencingImmortalASCIIText(contextGroup, 0, 0, thisScript, strlen(thisScript), 0, 0);
+ v = JSScriptEvaluate(context, scriptObject, NULL, NULL);
+ ASSERT(JSValueIsEqual(context, v, globalObject, NULL));
+ v = JSScriptEvaluate(context, scriptObject, o, NULL);
+ ASSERT(JSValueIsEqual(context, v, o, NULL));
+ JSScriptRelease(scriptObject);
+
+ script = JSStringCreateWithUTF8CString("eval(this);");
+ v = JSEvaluateScript(context, script, NULL, NULL, 1, NULL);
+ ASSERT(JSValueIsEqual(context, v, globalObject, NULL));
+ v = JSEvaluateScript(context, script, o, NULL, 1, NULL);
+ ASSERT(JSValueIsEqual(context, v, o, NULL));
+ JSStringRelease(script);
+
+ script = JSStringCreateWithUTF8CString("[ ]");
+ v = JSEvaluateScript(context, script, NULL, NULL, 1, NULL);
+ ASSERT(JSValueIsArray(context, v));
+ JSStringRelease(script);
+
+ script = JSStringCreateWithUTF8CString("new Date");
+ v = JSEvaluateScript(context, script, NULL, NULL, 1, NULL);
+ ASSERT(JSValueIsDate(context, v));
+ JSStringRelease(script);
+
+ exception = NULL;
+ script = JSStringCreateWithUTF8CString("rreturn Array;");
+ JSStringRef sourceURL = JSStringCreateWithUTF8CString("file:///foo/bar.js");
+ JSStringRef sourceURLKey = JSStringCreateWithUTF8CString("sourceURL");
+ JSEvaluateScript(context, script, NULL, sourceURL, 1, &exception);
+ ASSERT(exception);
+ v = JSObjectGetProperty(context, JSValueToObject(context, exception, NULL), sourceURLKey, NULL);
+ assertEqualsAsUTF8String(v, "file:///foo/bar.js");
+ JSStringRelease(script);
+ JSStringRelease(sourceURL);
+ JSStringRelease(sourceURLKey);
+
+ // Verify that creating a constructor for a class with no static functions does not trigger
+ // an assert inside putDirect or lead to a crash during GC. <https://bugs.webkit.org/show_bug.cgi?id=25785>
+ nullDefinition = kJSClassDefinitionEmpty;
+ nullClass = JSClassCreate(&nullDefinition);
+ JSObjectMakeConstructor(context, nullClass, 0);
+ JSClassRelease(nullClass);
+
+ char* scriptUTF8 = createStringWithContentsOfFile(scriptPath);
+ if (!scriptUTF8) {
+ printf("FAIL: Test script could not be loaded.\n");
+ failed = 1;
+ } else {
+ JSStringRef url = JSStringCreateWithUTF8CString(scriptPath);
+ JSStringRef script = JSStringCreateWithUTF8CString(scriptUTF8);
+ JSStringRef errorMessage = 0;
+ int errorLine = 0;
+ JSScriptRef scriptObject = JSScriptCreateFromString(contextGroup, url, 1, script, &errorMessage, &errorLine);
+ ASSERT((!scriptObject) != (!errorMessage));
+ if (!scriptObject) {
+ printf("FAIL: Test script did not parse\n\t%s:%d\n\t", scriptPath, errorLine);
+ CFStringRef errorCF = JSStringCopyCFString(kCFAllocatorDefault, errorMessage);
+ CFShow(errorCF);
+ CFRelease(errorCF);
+ JSStringRelease(errorMessage);
+ failed = 1;
+ }
+
+ JSStringRelease(script);
+ exception = NULL;
+ result = scriptObject ? JSScriptEvaluate(context, scriptObject, 0, &exception) : 0;
+ if (result && JSValueIsUndefined(context, result))
+ printf("PASS: Test script executed successfully.\n");
+ else {
+ printf("FAIL: Test script returned unexpected value:\n");
+ JSStringRef exceptionIString = JSValueToStringCopy(context, exception, NULL);
+ CFStringRef exceptionCF = JSStringCopyCFString(kCFAllocatorDefault, exceptionIString);
+ CFShow(exceptionCF);
+ CFRelease(exceptionCF);
+ JSStringRelease(exceptionIString);
+ failed = 1;
+ }
+ JSScriptRelease(scriptObject);
+ free(scriptUTF8);
+ }
+
+ // Check Promise is not exposed.
+ {
+ JSObjectRef globalObject = JSContextGetGlobalObject(context);
+ {
+ JSStringRef promiseProperty = JSStringCreateWithUTF8CString("Promise");
+ ASSERT(JSObjectHasProperty(context, globalObject, promiseProperty));
+ JSStringRelease(promiseProperty);
+ }
+ {
+ JSStringRef script = JSStringCreateWithUTF8CString("typeof Promise");
+ JSStringRef function = JSStringCreateWithUTF8CString("function");
+ JSValueRef value = JSEvaluateScript(context, script, NULL, NULL, 1, NULL);
+ ASSERT(JSValueIsString(context, value));
+ JSStringRef valueAsString = JSValueToStringCopy(context, value, NULL);
+ ASSERT(JSStringIsEqual(valueAsString, function));
+ JSStringRelease(valueAsString);
+ JSStringRelease(function);
+ JSStringRelease(script);
+ }
+ printf("PASS: Promise is exposed under JSContext API.\n");
+ }
+
+ // Check microtasks.
+ {
+ JSGlobalContextRef context = JSGlobalContextCreateInGroup(NULL, NULL);
+ {
+ JSObjectRef globalObject = JSContextGetGlobalObject(context);
+ JSValueRef exception;
+ JSStringRef code = JSStringCreateWithUTF8CString("result = 0; Promise.resolve(42).then(function (value) { result = value; });");
+ JSStringRef file = JSStringCreateWithUTF8CString("");
+ assertTrue(JSEvaluateScript(context, code, globalObject, file, 1, &exception), "An exception should not be thrown");
+ JSStringRelease(code);
+ JSStringRelease(file);
+
+ JSStringRef resultProperty = JSStringCreateWithUTF8CString("result");
+ ASSERT(JSObjectHasProperty(context, globalObject, resultProperty));
+
+ JSValueRef resultValue = JSObjectGetProperty(context, globalObject, resultProperty, &exception);
+ assertEqualsAsNumber(resultValue, 42);
+ JSStringRelease(resultProperty);
+ }
+ JSGlobalContextRelease(context);
+ }
+
+ failed = testTypedArrayCAPI() || failed;
+ failed = testExecutionTimeLimit() || failed;
+ failed = testFunctionOverrides() || failed;
+ failed = testGlobalContextWithFinalizer() || failed;
+ failed = testPingPongStackOverflow() || failed;
+ failed = testJSONParse() || failed;
+
+ // Clear out local variables pointing at JSObjectRefs to allow their values to be collected
+ function = NULL;
+ v = NULL;
+ o = NULL;
+ globalObject = NULL;
+ myConstructor = NULL;
+
+ JSStringRelease(jsEmptyIString);
+ JSStringRelease(jsOneIString);
+ JSStringRelease(jsCFIString);
+ JSStringRelease(jsCFEmptyIString);
+ JSStringRelease(jsCFIStringWithCharacters);
+ JSStringRelease(jsCFEmptyIStringWithCharacters);
+ JSStringRelease(goodSyntax);
+ JSStringRelease(badSyntax);
+
+ JSGlobalContextRelease(context);
+ JSClassRelease(globalObjectClass);
+
+ // Test for an infinite prototype chain that used to be created. This test
+ // passes if the call to JSObjectHasProperty() does not hang.
+
+ JSClassDefinition prototypeLoopClassDefinition = kJSClassDefinitionEmpty;
+ prototypeLoopClassDefinition.staticFunctions = globalObject_staticFunctions;
+ JSClassRef prototypeLoopClass = JSClassCreate(&prototypeLoopClassDefinition);
+ JSGlobalContextRef prototypeLoopContext = JSGlobalContextCreateInGroup(NULL, prototypeLoopClass);
+
+ JSStringRef nameProperty = JSStringCreateWithUTF8CString("name");
+ JSObjectHasProperty(prototypeLoopContext, JSContextGetGlobalObject(prototypeLoopContext), nameProperty);
+
+ JSGlobalContextRelease(prototypeLoopContext);
+ JSClassRelease(prototypeLoopClass);
+
+ 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 (valueToObjectExceptionTest())
+ printf("PASS: throwException did not crash when handling an error with appendMessageToError set and no codeBlock available.\n");
+
+ if (globalContextNameTest())
+ printf("PASS: global context name behaves as expected.\n");
+
+ customGlobalObjectClassTest();
+ globalObjectSetPrototypeTest();
+ globalObjectPrivatePropertyTest();
+
+ if (failed) {
+ printf("FAIL: Some tests failed.\n");
+ return 1;
+ }
+
+ printf("PASS: Program exited normally.\n");
+ return 0;
+}
+
+static char* createStringWithContentsOfFile(const char* fileName)
+{
+ char* buffer;
+
+ size_t buffer_size = 0;
+ size_t buffer_capacity = 1024;
+ buffer = (char*)malloc(buffer_capacity);
+
+ FILE* f = fopen(fileName, "r");
+ if (!f) {
+ fprintf(stderr, "Could not open file: %s\n", fileName);
+ free(buffer);
+ return 0;
+ }
+
+ while (!feof(f) && !ferror(f)) {
+ buffer_size += fread(buffer + buffer_size, 1, buffer_capacity - buffer_size, f);
+ if (buffer_size == buffer_capacity) { // guarantees space for trailing '\0'
+ buffer_capacity *= 2;
+ buffer = (char*)realloc(buffer, buffer_capacity);
+ ASSERT(buffer);
+ }
+
+ ASSERT(buffer_size < buffer_capacity);
+ }
+ fclose(f);
+ buffer[buffer_size] = '\0';
+
+ return buffer;
+}
+
+#if OS(WINDOWS)
+extern "C" __declspec(dllexport) int WINAPI dllLauncherEntryPoint(int argc, const char* argv[])
+{
+ return main(argc, const_cast<char**>(argv));
+}
+#endif
diff --git a/Source/JavaScriptCore/API/tests/testapi.js b/Source/JavaScriptCore/API/tests/testapi.js
new file mode 100644
index 000000000..88d3701c2
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/testapi.js
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2006 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. ``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
+ * 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.
+ */
+
+function bludgeonArguments() { if (0) arguments; return function g() {} }
+h = bludgeonArguments();
+gc();
+
+var failed = false;
+function pass(msg)
+{
+ print("PASS: " + msg, "green");
+}
+
+function fail(msg)
+{
+ print("FAIL: " + msg, "red");
+ failed = true;
+}
+
+function shouldBe(a, b)
+{
+ var evalA;
+ try {
+ evalA = eval(a);
+ } catch(e) {
+ evalA = e;
+ }
+
+ if (evalA == b || isNaN(evalA) && typeof evalA == 'number' && isNaN(b) && typeof b == 'number')
+ pass(a + " should be " + b + " and is.");
+ else
+ fail(a + " should be " + b + " but instead is " + evalA + ".");
+}
+
+function shouldThrow(a)
+{
+ var evalA;
+ try {
+ eval(a);
+ } catch(e) {
+ pass(a + " threw: " + e);
+ return;
+ }
+
+ fail(a + " did not throw an exception.");
+}
+
+function globalStaticFunction()
+{
+ return 4;
+}
+
+shouldBe("globalStaticValue", 3);
+shouldBe("globalStaticFunction()", 4);
+shouldBe("this.globalStaticFunction()", 4);
+
+function globalStaticFunction2() {
+ return 10;
+}
+shouldBe("globalStaticFunction2();", 10);
+this.globalStaticFunction2 = function() { return 20; }
+shouldBe("globalStaticFunction2();", 20);
+shouldBe("this.globalStaticFunction2();", 20);
+
+function iAmNotAStaticFunction() { return 10; }
+shouldBe("iAmNotAStaticFunction();", 10);
+this.iAmNotAStaticFunction = function() { return 20; }
+shouldBe("iAmNotAStaticFunction();", 20);
+
+shouldBe("typeof MyObject", "function"); // our object implements 'call'
+MyObject.cantFind = 1;
+shouldBe("MyObject.cantFind", undefined);
+MyObject.regularType = 1;
+shouldBe("MyObject.regularType", 1);
+MyObject.alwaysOne = 2;
+shouldBe("MyObject.alwaysOne", 1);
+MyObject.cantDelete = 1;
+delete MyObject.cantDelete;
+shouldBe("MyObject.cantDelete", 1);
+shouldBe("delete MyObject.throwOnDelete", "an exception");
+MyObject.cantSet = 1;
+shouldBe("MyObject.cantSet", undefined);
+shouldBe("MyObject.throwOnGet", "an exception");
+shouldBe("MyObject.throwOnSet = 5", "an exception");
+shouldBe("MyObject('throwOnCall')", "an exception");
+shouldBe("new MyObject('throwOnConstruct')", "an exception");
+shouldBe("'throwOnHasInstance' instanceof MyObject", "an exception");
+
+MyObject.nullGetForwardSet = 1;
+shouldBe("MyObject.nullGetForwardSet", 1);
+
+var foundMyPropertyName = false;
+var foundRegularType = false;
+for (var p in MyObject) {
+ if (p == "myPropertyName")
+ foundMyPropertyName = true;
+ if (p == "regularType")
+ foundRegularType = true;
+}
+
+if (foundMyPropertyName)
+ pass("MyObject.myPropertyName was enumerated");
+else
+ fail("MyObject.myPropertyName was not enumerated");
+
+if (foundRegularType)
+ pass("MyObject.regularType was enumerated");
+else
+ fail("MyObject.regularType was not enumerated");
+
+var alwaysOneDescriptor = Object.getOwnPropertyDescriptor(MyObject, "alwaysOne");
+shouldBe('typeof alwaysOneDescriptor', "object");
+shouldBe('alwaysOneDescriptor.value', MyObject.alwaysOne);
+shouldBe('alwaysOneDescriptor.configurable', true);
+shouldBe('alwaysOneDescriptor.enumerable', false); // Actually it is.
+var cantFindDescriptor = Object.getOwnPropertyDescriptor(MyObject, "cantFind");
+shouldBe('typeof cantFindDescriptor', "object");
+shouldBe('cantFindDescriptor.value', MyObject.cantFind);
+shouldBe('cantFindDescriptor.configurable', true);
+shouldBe('cantFindDescriptor.enumerable', false);
+try {
+ // If getOwnPropertyDescriptor() returned an access descriptor, this wouldn't throw.
+ Object.getOwnPropertyDescriptor(MyObject, "throwOnGet");
+} catch (e) {
+ pass("getting property descriptor of throwOnGet threw exception");
+}
+var myPropertyNameDescriptor = Object.getOwnPropertyDescriptor(MyObject, "myPropertyName");
+shouldBe('typeof myPropertyNameDescriptor', "object");
+shouldBe('myPropertyNameDescriptor.value', MyObject.myPropertyName);
+shouldBe('myPropertyNameDescriptor.configurable', true);
+shouldBe('myPropertyNameDescriptor.enumerable', false); // Actually it is.
+try {
+ // if getOwnPropertyDescriptor() returned an access descriptor, this wouldn't throw.
+ Object.getOwnPropertyDescriptor(MyObject, "hasPropertyLie");
+} catch (e) {
+ pass("getting property descriptor of hasPropertyLie threw exception");
+}
+shouldBe('Object.getOwnPropertyDescriptor(MyObject, "doesNotExist")', undefined);
+
+myObject = new MyObject();
+
+shouldBe("delete MyObject.regularType", true);
+shouldBe("MyObject.regularType", undefined);
+shouldBe("MyObject(0)", 1);
+shouldBe("MyObject()", undefined);
+shouldBe("typeof myObject", "object");
+shouldBe("MyObject ? 1 : 0", true); // toBoolean
+shouldBe("+MyObject", 1); // toNumber
+shouldBe("(Object.prototype.toString.call(MyObject))", "[object MyObject]"); // Object.prototype.toString
+shouldBe("(MyObject.toString())", "[object MyObject]"); // toString
+shouldBe("String(MyObject)", "MyObjectAsString"); // toString
+shouldBe("MyObject - 0", 1); // toNumber
+shouldBe("MyObject.valueOf()", 1); // valueOf
+
+shouldBe("typeof MyConstructor", "object");
+constructedObject = new MyConstructor(1);
+shouldBe("typeof constructedObject", "object");
+shouldBe("constructedObject.value", 1);
+shouldBe("myObject instanceof MyObject", true);
+shouldBe("(new Object()) instanceof MyObject", false);
+
+shouldThrow("new MyBadConstructor()");
+
+MyObject.nullGetSet = 1;
+shouldBe("MyObject.nullGetSet", 1);
+shouldThrow("MyObject.nullCall()");
+shouldThrow("MyObject.hasPropertyLie");
+
+derived = new Derived();
+
+shouldBe("derived instanceof Derived", true);
+shouldBe("derived instanceof Base", true);
+
+// base properties and functions return 1 when called/gotten; derived, 2
+shouldBe("derived.baseProtoDup()", 2);
+shouldBe("derived.baseProto()", 1);
+shouldBe("derived.baseDup", 2);
+shouldBe("derived.baseOnly", 1);
+shouldBe("derived.protoOnly()", 2);
+shouldBe("derived.protoDup", 2);
+shouldBe("derived.derivedOnly", 2)
+
+shouldBe("derived.baseHardNull()", undefined)
+
+// base properties throw 1 when set; derived, 2
+shouldBe("derived.baseDup = 0", 2);
+shouldBe("derived.baseOnly = 0", 1);
+shouldBe("derived.derivedOnly = 0", 2)
+shouldBe("derived.protoDup = 0", 2);
+
+derived2 = new Derived2();
+
+shouldBe("derived2 instanceof Derived2", true);
+shouldBe("derived2 instanceof Derived", true);
+shouldBe("derived2 instanceof Base", true);
+
+// base properties and functions return 1 when called/gotten; derived, 2
+shouldBe("derived2.baseProtoDup()", 2);
+shouldBe("derived2.baseProto()", 1);
+shouldBe("derived2.baseDup", 2);
+shouldBe("derived2.baseOnly", 1);
+shouldBe("derived2.protoOnly()", 2);
+shouldBe("derived2.protoDup", 2);
+shouldBe("derived2.derivedOnly", 2)
+
+// base properties throw 1 when set; derived, 2
+shouldBe("derived2.baseDup = 0", 2);
+shouldBe("derived2.baseOnly = 0", 1);
+shouldBe("derived2.derivedOnly = 0", 2)
+shouldBe("derived2.protoDup = 0", 2);
+
+shouldBe('Object.getOwnPropertyDescriptor(derived, "baseProto")', undefined);
+shouldBe('Object.getOwnPropertyDescriptor(derived, "baseProtoDup")', undefined);
+var baseDupDescriptor = Object.getOwnPropertyDescriptor(derived, "baseDup");
+shouldBe('typeof baseDupDescriptor', "object");
+shouldBe('baseDupDescriptor.value', derived.baseDup);
+shouldBe('baseDupDescriptor.configurable', true);
+shouldBe('baseDupDescriptor.enumerable', false);
+var baseOnlyDescriptor = Object.getOwnPropertyDescriptor(derived, "baseOnly");
+shouldBe('typeof baseOnlyDescriptor', "object");
+shouldBe('baseOnlyDescriptor.value', derived.baseOnly);
+shouldBe('baseOnlyDescriptor.configurable', true);
+shouldBe('baseOnlyDescriptor.enumerable', false);
+shouldBe('Object.getOwnPropertyDescriptor(derived, "protoOnly")', undefined);
+var protoDupDescriptor = Object.getOwnPropertyDescriptor(derived, "protoDup");
+shouldBe('typeof protoDupDescriptor', "object");
+shouldBe('protoDupDescriptor.value', derived.protoDup);
+shouldBe('protoDupDescriptor.configurable', true);
+shouldBe('protoDupDescriptor.enumerable', false);
+var derivedOnlyDescriptor = Object.getOwnPropertyDescriptor(derived, "derivedOnly");
+shouldBe('typeof derivedOnlyDescriptor', "object");
+shouldBe('derivedOnlyDescriptor.value', derived.derivedOnly);
+shouldBe('derivedOnlyDescriptor.configurable', true);
+shouldBe('derivedOnlyDescriptor.enumerable', false);
+
+shouldBe("undefined instanceof MyObject", false);
+EvilExceptionObject.hasInstance = function f() { return f(); };
+EvilExceptionObject.__proto__ = undefined;
+shouldThrow("undefined instanceof EvilExceptionObject");
+EvilExceptionObject.hasInstance = function () { return true; };
+shouldBe("undefined instanceof EvilExceptionObject", true);
+
+EvilExceptionObject.toNumber = function f() { return f(); }
+shouldThrow("EvilExceptionObject*5");
+EvilExceptionObject.toStringExplicit = function f() { return f(); }
+shouldThrow("String(EvilExceptionObject)");
+
+shouldBe("console", "[object Console]");
+shouldBe("typeof console.log", "function");
+
+shouldBe("EmptyObject", "[object CallbackObject]");
+
+for (var i = 0; i < 6; ++i)
+ PropertyCatchalls.x = i;
+shouldBe("PropertyCatchalls.x", 4);
+
+for (var i = 0; i < 6; ++i)
+ var x = PropertyCatchalls.x;
+shouldBe("x", null);
+var make_throw = 'make_throw';
+shouldThrow("PropertyCatchalls[make_throw]=1");
+make_throw = 0;
+shouldThrow("PropertyCatchalls[make_throw]=1");
+
+for (var i = 0; i < 10; ++i) {
+ for (var p in PropertyCatchalls) {
+ if (p == "x")
+ continue;
+ shouldBe("p", i % 10);
+ break;
+ }
+}
+
+PropertyCatchalls.__proto__ = { y: 1 };
+for (var i = 0; i < 6; ++i)
+ var y = PropertyCatchalls.y;
+shouldBe("y", null);
+
+var o = { __proto__: PropertyCatchalls };
+for (var i = 0; i < 6; ++i)
+ var z = PropertyCatchalls.z;
+shouldBe("z", null);
+
+if (failed)
+ throw "Some tests failed";