summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/API/tests
diff options
context:
space:
mode:
authorKonstantin Tokarev <annulen@yandex.ru>2016-08-25 19:20:41 +0300
committerKonstantin Tokarev <annulen@yandex.ru>2017-02-02 12:30:55 +0000
commit6882a04fb36642862b11efe514251d32070c3d65 (patch)
treeb7959826000b061fd5ccc7512035c7478742f7b0 /Source/JavaScriptCore/API/tests
parentab6df191029eeeb0b0f16f127d553265659f739e (diff)
downloadqtwebkit-6882a04fb36642862b11efe514251d32070c3d65.tar.gz
Imported QtWebKit TP3 (git b57bc6801f1876c3220d5a4bfea33d620d477443)
Change-Id: I3b1d8a2808782c9f34d50240000e20cb38d3680f Reviewed-by: Konstantin Tokarev <annulen@yandex.ru>
Diffstat (limited to 'Source/JavaScriptCore/API/tests')
-rw-r--r--Source/JavaScriptCore/API/tests/CompareAndSwapTest.cpp118
-rw-r--r--Source/JavaScriptCore/API/tests/CompareAndSwapTest.h40
-rw-r--r--Source/JavaScriptCore/API/tests/CurrentThisInsideBlockGetterTest.h38
-rw-r--r--Source/JavaScriptCore/API/tests/CustomGlobalObjectClassTest.c145
-rw-r--r--Source/JavaScriptCore/API/tests/CustomGlobalObjectClassTest.h33
-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.h40
-rw-r--r--Source/JavaScriptCore/API/tests/GlobalContextWithFinalizerTest.cpp56
-rw-r--r--Source/JavaScriptCore/API/tests/GlobalContextWithFinalizerTest.h42
-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.h6
-rw-r--r--Source/JavaScriptCore/API/tests/JSNodeList.c8
-rw-r--r--Source/JavaScriptCore/API/tests/JSNodeList.h6
-rw-r--r--Source/JavaScriptCore/API/tests/Node.c6
-rw-r--r--Source/JavaScriptCore/API/tests/Node.h6
-rw-r--r--Source/JavaScriptCore/API/tests/NodeList.c6
-rw-r--r--Source/JavaScriptCore/API/tests/NodeList.h6
-rw-r--r--Source/JavaScriptCore/API/tests/PingPongStackOverflowTest.cpp182
-rw-r--r--Source/JavaScriptCore/API/tests/PingPongStackOverflowTest.h39
-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/minidom.c9
-rw-r--r--Source/JavaScriptCore/API/tests/minidom.js6
-rw-r--r--Source/JavaScriptCore/API/tests/testapi.c434
-rw-r--r--Source/JavaScriptCore/API/tests/testapi.js25
-rw-r--r--Source/JavaScriptCore/API/tests/testapi.mm841
28 files changed, 1505 insertions, 1103 deletions
diff --git a/Source/JavaScriptCore/API/tests/CompareAndSwapTest.cpp b/Source/JavaScriptCore/API/tests/CompareAndSwapTest.cpp
new file mode 100644
index 000000000..525ebc9cc
--- /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::weakCompareAndSwap(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..73fa0de13
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/CompareAndSwapTest.h
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+#ifndef CompareAndSwapTest_h
+#define CompareAndSwapTest_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Regression test for webkit.org/b/142513 */
+void testCompareAndSwap();
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* CompareAndSwapTest_h */
diff --git a/Source/JavaScriptCore/API/tests/CurrentThisInsideBlockGetterTest.h b/Source/JavaScriptCore/API/tests/CurrentThisInsideBlockGetterTest.h
new file mode 100644
index 000000000..f228333c4
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/CurrentThisInsideBlockGetterTest.h
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#ifndef CurrentThisInsideBlockGetterTest_h
+#define CurrentThisInsideBlockGetterTest_h
+
+#include <JavaScriptCore/JavaScriptCore.h>
+
+#if JSC_OBJC_API_ENABLED
+
+void currentThisInsideBlockGetterTest();
+
+#endif // JSC_OBJC_API_ENABLED
+
+
+#endif // CurrentThisInsideBlockGetterTest_h
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..86914ca6f
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/CustomGlobalObjectClassTest.h
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+#ifndef CustomGlobalObjectClassTest_h
+#define CustomGlobalObjectClassTest_h
+
+void customGlobalObjectClassTest(void);
+void globalObjectSetPrototypeTest(void);
+void globalObjectPrivatePropertyTest(void);
+
+#endif // CustomGlobalObjectClassTest_h
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..fc8cc10aa
--- /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.append("function foo() { var startTime = currentCPUTime(); while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > ");
+ scriptBuilder.appendNumber(timeAfterWatchdogShouldHaveFired / 1000.0);
+ scriptBuilder.append(") 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.append("var startTime = currentCPUTime();"
+ "function recurse(i) {"
+ "'use strict';"
+ "if (i % 1000 === 0) {"
+ "if (currentCPUTime() - startTime >");
+ scriptBuilder.appendNumber(timeAfterWatchdogShouldHaveFired / 1000.0);
+ scriptBuilder.append(" ) { return; }");
+ scriptBuilder.append(" }");
+ scriptBuilder.append(" return recurse(i + 1); }");
+ scriptBuilder.append("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.append("function foo() { var startTime = currentCPUTime(); try { while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > ");
+ scriptBuilder.appendNumber(timeAfterWatchdogShouldHaveFired / 1000.0);
+ scriptBuilder.append(") 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.append("function foo() { var startTime = currentCPUTime(); while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > ");
+ scriptBuilder.appendNumber(timeAfterWatchdogShouldHaveFired / 1000.0);
+ scriptBuilder.append(") 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.append("function foo() { var startTime = currentCPUTime(); while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > ");
+ scriptBuilder.appendNumber(timeAfterWatchdogShouldHaveFired / 1000.0);
+ scriptBuilder.append(") 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.append("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.append(") 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..8294a86a6
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/ExecutionTimeLimitTest.h
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+#ifndef ExecutionTimeLimitTest_h
+#define ExecutionTimeLimitTest_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Returns 1 if failures were encountered. Else, returns 0. */
+int testExecutionTimeLimit();
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ExecutionTimeLimitTest_h */
diff --git a/Source/JavaScriptCore/API/tests/GlobalContextWithFinalizerTest.cpp b/Source/JavaScriptCore/API/tests/GlobalContextWithFinalizerTest.cpp
new file mode 100644
index 000000000..7023bc365
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/GlobalContextWithFinalizerTest.cpp
@@ -0,0 +1,56 @@
+/*
+ * 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"
+#include <wtf/DataLog.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..55b439fff
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/GlobalContextWithFinalizerTest.h
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+#ifndef GlobalContextWithFinalizerTest_h
+#define GlobalContextWithFinalizerTest_h
+
+#include "JSContextRefPrivate.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Returns 1 if failures were encountered. Else, returns 0. */
+int testGlobalContextWithFinalizer();
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* GlobalContextWithFinalizerTest_h */
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..a6aee2f7b 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
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..d3eb52bb9 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
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..41b5d493a 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
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..020b76f59 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
diff --git a/Source/JavaScriptCore/API/tests/PingPongStackOverflowTest.cpp b/Source/JavaScriptCore/API/tests/PingPongStackOverflowTest.cpp
new file mode 100644
index 000000000..33f0772b3
--- /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.append("dummy.valueOf([0]");
+ for (int i = 1; i < 35000; i++) {
+ builder.append(", [");
+ builder.appendNumber(i);
+ builder.append("]");
+ }
+ builder.append(");");
+
+ 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 origReservedZoneSize = Options::reservedZoneSize();
+ auto origErrorModeReservedZoneSize = Options::errorModeReservedZoneSize();
+ auto origUseLLInt = Options::useLLInt();
+ auto origMaxPerThreadStackUsage = Options::maxPerThreadStackUsage();
+
+ Options::reservedZoneSize() = 128 * KB;
+ Options::errorModeReservedZoneSize() = 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::reservedZoneSize();
+
+ 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::reservedZoneSize() = origReservedZoneSize;
+ Options::errorModeReservedZoneSize() = origErrorModeReservedZoneSize;
+ 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..7f5911bcf
--- /dev/null
+++ b/Source/JavaScriptCore/API/tests/PingPongStackOverflowTest.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.
+ */
+
+#ifndef PingPongStackOverflowTest_h
+#define PingPongStackOverflowTest_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int testPingPongStackOverflow();
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* PingPongStackOverflowTest_h */
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/minidom.c b/Source/JavaScriptCore/API/tests/minidom.c
index 8614e51e9..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"
@@ -105,6 +107,7 @@ static char* createStringWithContentsOfFile(const char* fileName)
FILE* f = fopen(fileName, "r");
if (!f) {
fprintf(stderr, "Could not open file: %s\n", fileName);
+ free(buffer);
return 0;
}
diff --git a/Source/JavaScriptCore/API/tests/minidom.js b/Source/JavaScriptCore/API/tests/minidom.js
index 480896052..85134d7cb 100644
--- a/Source/JavaScriptCore/API/tests/minidom.js
+++ b/Source/JavaScriptCore/API/tests/minidom.js
@@ -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/testapi.c b/Source/JavaScriptCore/API/tests/testapi.c
index be18b2bf7..cbf9daf18 100644
--- a/Source/JavaScriptCore/API/tests/testapi.c
+++ b/Source/JavaScriptCore/API/tests/testapi.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006, 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
@@ -10,19 +10,21 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <wtf/Platform.h>
+
#include "JavaScriptCore.h"
#include "JSBasePrivate.h"
#include "JSContextRefPrivate.h"
@@ -33,34 +35,21 @@
#define ASSERT_DISABLED 0
#include <wtf/Assertions.h>
-#if PLATFORM(MAC) || PLATFORM(IOS)
-#include <mach/mach.h>
-#include <mach/mach_time.h>
-#include <sys/time.h>
-#endif
-
#if OS(WINDOWS)
#include <windows.h>
#endif
-#if COMPILER(MSVC)
-
-#include <wtf/MathExtras.h>
-
-static double nan(const char*)
-{
- return std::numeric_limits<double>::quiet_NaN();
-}
-
-using std::isinf;
-using std::isnan;
-
-#endif
+#include "CompareAndSwapTest.h"
+#include "CustomGlobalObjectClassTest.h"
+#include "ExecutionTimeLimitTest.h"
+#include "GlobalContextWithFinalizerTest.h"
+#include "PingPongStackOverflowTest.h"
#if JSC_OBJC_API_ENABLED
void testObjectiveCAPI(void);
#endif
+bool assertTrue(bool value, const char* message);
extern void JSSynchronousGarbageCollectForDebugging(JSContextRef);
static JSGlobalContextRef context;
@@ -93,11 +82,13 @@ static void assertEqualsAsUTF8String(JSValueRef value, const char* expectedValue
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;
}
}
@@ -132,7 +123,11 @@ static void assertEqualsAsCharactersPtr(JSValueRef value, const char* expectedVa
}
if (jsLength != (size_t)cfLength) {
- fprintf(stderr, "assertEqualsAsCharactersPtr failed: jsLength(%ld) != cfLength(%ld)\n", jsLength, 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;
}
@@ -582,7 +577,6 @@ static JSValueRef EvilExceptionObject_convertToType(JSContextRef context, JSObje
break;
default:
return JSValueMakeNull(context);
- break;
}
JSValueRef func = JSObjectGetProperty(context, object, funcName, exception);
@@ -904,10 +898,8 @@ static void globalObject_initialize(JSContextRef context, JSObjectRef object)
// Ensure that an execution context is passed in
ASSERT(context);
- // Ensure that the global object is set to the object that we were passed
JSObjectRef globalObject = JSContextGetGlobalObject(context);
ASSERT(globalObject);
- ASSERT(object == globalObject);
// Ensure that the standard global properties have been set on the global object
JSStringRef array = JSStringCreateWithUTF8CString("Array");
@@ -966,6 +958,7 @@ static JSStaticValue globalObject_staticValues[] = {
static JSStaticFunction globalObject_staticFunctions[] = {
{ "globalStaticFunction", globalObject_call, kJSPropertyAttributeNone },
+ { "globalStaticFunction2", globalObject_call, kJSPropertyAttributeNone },
{ "gc", functionGC, kJSPropertyAttributeNone },
{ 0, 0, 0 }
};
@@ -990,7 +983,7 @@ static void makeGlobalNumberValue(JSContextRef context) {
v = NULL;
}
-static bool assertTrue(bool value, const char* message)
+bool assertTrue(bool value, const char* message)
{
if (!value) {
if (message)
@@ -1043,85 +1036,104 @@ static bool checkForCycleInPrototypeChain()
return result;
}
-static void checkConstnessInJSObjectNames()
+static JSValueRef valueToObjectExceptionCallAsFunction(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
- JSStaticFunction fun;
- fun.name = "something";
- JSStaticValue val;
- val.name = "something";
+ 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);
}
-
-#if PLATFORM(MAC) || PLATFORM(IOS)
-static double currentCPUTime()
+static bool valueToObjectExceptionTest()
{
- mach_msg_type_number_t infoCount = THREAD_BASIC_INFO_COUNT;
- thread_basic_info_data_t info;
+ 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);
- /* Get thread information */
- mach_port_t threadPort = mach_thread_self();
- thread_info(threadPort, THREAD_BASIC_INFO, (thread_info_t)(&info), &infoCount);
- mach_port_deallocate(mach_task_self(), threadPort);
+ 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);
- double time = info.user_time.seconds + info.user_time.microseconds / 1000000.;
- time += info.system_time.seconds + info.system_time.microseconds / 1000000.;
+ JSStringRelease(test);
+ JSClassRelease(globalObjectClass);
+ JSGlobalContextRelease(testContext);
- return time;
+ return true;
}
-static JSValueRef currentCPUTime_callAsFunction(JSContextRef ctx, JSObjectRef functionObject, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+static bool globalContextNameTest()
{
- UNUSED_PARAM(functionObject);
- UNUSED_PARAM(thisObject);
- UNUSED_PARAM(argumentCount);
- UNUSED_PARAM(arguments);
- UNUSED_PARAM(exception);
+ bool result = true;
+ JSGlobalContextRef context = JSGlobalContextCreate(0);
- ASSERT(JSContextGetGlobalContext(ctx) == context);
- return JSValueMakeNumber(ctx, currentCPUTime());
-}
+ JSStringRef str = JSGlobalContextCopyName(context);
+ result &= assertTrue(!str, "Default context name is NULL");
-bool shouldTerminateCallbackWasCalled = false;
-static bool shouldTerminateCallback(JSContextRef ctx, void* context)
-{
- UNUSED_PARAM(ctx);
- UNUSED_PARAM(context);
- shouldTerminateCallbackWasCalled = true;
- return true;
-}
+ JSStringRef name1 = JSStringCreateWithUTF8CString("name1");
+ JSStringRef name2 = JSStringCreateWithUTF8CString("name2");
-bool cancelTerminateCallbackWasCalled = false;
-static bool cancelTerminateCallback(JSContextRef ctx, void* context)
-{
- UNUSED_PARAM(ctx);
- UNUSED_PARAM(context);
- cancelTerminateCallbackWasCalled = true;
- return false;
+ 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;
}
-int extendTerminateCallbackCalled = 0;
-static bool extendTerminateCallback(JSContextRef ctx, void* context)
+static void checkConstnessInJSObjectNames()
{
- UNUSED_PARAM(context);
- extendTerminateCallbackCalled++;
- if (extendTerminateCallbackCalled == 1) {
- JSContextGroupRef contextGroup = JSContextGetGroup(ctx);
- JSContextGroupSetExecutionTimeLimit(contextGroup, .200f, extendTerminateCallback, 0);
- return false;
- }
- return true;
+ JSStaticFunction fun;
+ fun.name = "something";
+ JSStaticValue val;
+ val.name = "something";
}
-#endif /* PLATFORM(MAC) || PLATFORM(IOS) */
int main(int argc, char* argv[])
{
#if OS(WINDOWS)
+#if defined(_M_X64) || defined(__x86_64__)
+ // The VS2013 runtime has a bug where it mis-detects AVX-capable processors
+ // if the feature has been disabled in firmware. This causes us to crash
+ // in some of the math functions. For now, we disable those optimizations
+ // because Microsoft is not going to fix the problem in VS2013.
+ // FIXME: http://webkit.org/b/141449: Remove this workaround when we switch to VS2015+.
+ _set_FMA3_enable(0);
+#endif
+
// 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
@@ -1171,6 +1183,13 @@ int main(int argc, char* argv[])
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);
@@ -1228,6 +1247,8 @@ int main(int argc, char* argv[])
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));
@@ -1388,8 +1409,10 @@ int main(int argc, char* argv[])
} else
printf("PASS: Correctly serialised with indent of 4.\n");
JSStringRelease(str);
- JSStringRef src = JSStringCreateWithUTF8CString("({get a(){ throw '';}})");
- JSValueRef unstringifiableObj = JSEvaluateScript(context, src, NULL, NULL, 1, NULL);
+
+ str = JSStringCreateWithUTF8CString("({get a(){ throw '';}})");
+ JSValueRef unstringifiableObj = JSEvaluateScript(context, str, NULL, NULL, 1, NULL);
+ JSStringRelease(str);
str = JSValueCreateJSONString(context, unstringifiableObj, 4, 0);
if (str) {
@@ -1572,7 +1595,27 @@ int main(int argc, char* argv[])
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, 1);
+ 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);
@@ -1606,7 +1649,7 @@ int main(int argc, char* argv[])
JSStringRelease(functionBody);
string = JSValueToStringCopy(context, function, NULL);
- assertEqualsAsUTF8String(JSValueMakeString(context, string), "function foo(foo) { return foo;\n}");
+ assertEqualsAsUTF8String(JSValueMakeString(context, string), "function foo(foo) {\nreturn foo;\n}");
JSStringRelease(string);
JSStringRef print = JSStringCreateWithUTF8CString("print");
@@ -1737,6 +1780,28 @@ int main(int argc, char* argv[])
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;
@@ -1765,6 +1830,7 @@ int main(int argc, char* argv[])
}
JSStringRelease(script);
+ exception = NULL;
result = scriptObject ? JSScriptEvaluate(context, scriptObject, 0, &exception) : 0;
if (result && JSValueIsUndefined(context, result))
printf("PASS: Test script executed successfully.\n");
@@ -1781,158 +1847,53 @@ int main(int argc, char* argv[])
free(scriptUTF8);
}
-#if PLATFORM(MAC) || PLATFORM(IOS)
- JSStringRef currentCPUTimeStr = JSStringCreateWithUTF8CString("currentCPUTime");
- JSObjectRef currentCPUTimeFunction = JSObjectMakeFunctionWithCallback(context, currentCPUTimeStr, currentCPUTime_callAsFunction);
- JSObjectSetProperty(context, globalObject, currentCPUTimeStr, currentCPUTimeFunction, kJSPropertyAttributeNone, NULL);
- JSStringRelease(currentCPUTimeStr);
-
- /* Test script timeout: */
- JSContextGroupSetExecutionTimeLimit(contextGroup, .10f, shouldTerminateCallback, 0);
- {
- const char* loopForeverScript = "var startTime = currentCPUTime(); while (true) { if (currentCPUTime() - startTime > .150) break; } ";
- JSStringRef script = JSStringCreateWithUTF8CString(loopForeverScript);
- double startTime;
- double endTime;
- exception = NULL;
- shouldTerminateCallbackWasCalled = false;
- startTime = currentCPUTime();
- v = JSEvaluateScript(context, script, NULL, NULL, 1, &exception);
- endTime = currentCPUTime();
-
- if (((endTime - startTime) < .150f) && shouldTerminateCallbackWasCalled)
- printf("PASS: script timed out as expected.\n");
- else {
- if (!((endTime - startTime) < .150f))
- printf("FAIL: script did not timed out as expected.\n");
- if (!shouldTerminateCallbackWasCalled)
- printf("FAIL: script timeout callback was not called.\n");
- failed = true;
- }
-
- if (!exception) {
- printf("FAIL: TerminatedExecutionException was not thrown.\n");
- failed = true;
- }
- }
-
- /* Test the script timeout's TerminatedExecutionException should NOT be catchable: */
- JSContextGroupSetExecutionTimeLimit(contextGroup, 0.10f, shouldTerminateCallback, 0);
- {
- const char* loopForeverScript = "var startTime = currentCPUTime(); try { while (true) { if (currentCPUTime() - startTime > .150) break; } } catch(e) { }";
- JSStringRef script = JSStringCreateWithUTF8CString(loopForeverScript);
- double startTime;
- double endTime;
- exception = NULL;
- shouldTerminateCallbackWasCalled = false;
- startTime = currentCPUTime();
- v = JSEvaluateScript(context, script, NULL, NULL, 1, &exception);
- endTime = currentCPUTime();
-
- if (((endTime - startTime) >= .150f) || !shouldTerminateCallbackWasCalled) {
- if (!((endTime - startTime) < .150f))
- printf("FAIL: script did not timed out as expected.\n");
- if (!shouldTerminateCallbackWasCalled)
- printf("FAIL: script timeout callback was not called.\n");
- failed = true;
- }
-
- if (exception)
- printf("PASS: TerminatedExecutionException was not catchable as expected.\n");
- else {
- printf("FAIL: TerminatedExecutionException was caught.\n");
- failed = true;
- }
- }
-
- /* Test script timeout with no callback: */
- JSContextGroupSetExecutionTimeLimit(contextGroup, .10f, 0, 0);
+ // Check Promise is not exposed.
{
- const char* loopForeverScript = "var startTime = currentCPUTime(); while (true) { if (currentCPUTime() - startTime > .150) break; } ";
- JSStringRef script = JSStringCreateWithUTF8CString(loopForeverScript);
- double startTime;
- double endTime;
- exception = NULL;
- startTime = currentCPUTime();
- v = JSEvaluateScript(context, script, NULL, NULL, 1, &exception);
- endTime = currentCPUTime();
-
- if (((endTime - startTime) < .150f) && shouldTerminateCallbackWasCalled)
- printf("PASS: script timed out as expected when no callback is specified.\n");
- else {
- if (!((endTime - startTime) < .150f))
- printf("FAIL: script did not timed out as expected when no callback is specified.\n");
- failed = true;
+ JSObjectRef globalObject = JSContextGetGlobalObject(context);
+ {
+ JSStringRef promiseProperty = JSStringCreateWithUTF8CString("Promise");
+ ASSERT(JSObjectHasProperty(context, globalObject, promiseProperty));
+ JSStringRelease(promiseProperty);
}
-
- if (!exception) {
- printf("FAIL: TerminatedExecutionException was not thrown.\n");
- failed = true;
+ {
+ 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");
}
- /* Test script timeout cancellation: */
- JSContextGroupSetExecutionTimeLimit(contextGroup, 0.10f, cancelTerminateCallback, 0);
+ // Check microtasks.
{
- const char* loopForeverScript = "var startTime = currentCPUTime(); while (true) { if (currentCPUTime() - startTime > .150) break; } ";
- JSStringRef script = JSStringCreateWithUTF8CString(loopForeverScript);
- double startTime;
- double endTime;
- exception = NULL;
- startTime = currentCPUTime();
- v = JSEvaluateScript(context, script, NULL, NULL, 1, &exception);
- endTime = currentCPUTime();
-
- if (((endTime - startTime) >= .150f) && cancelTerminateCallbackWasCalled && !exception)
- printf("PASS: script timeout was cancelled as expected.\n");
- else {
- if (((endTime - startTime) < .150) || exception)
- printf("FAIL: script timeout was not cancelled.\n");
- if (!cancelTerminateCallbackWasCalled)
- printf("FAIL: script timeout callback was not called.\n");
- failed = true;
- }
-
- if (exception) {
- printf("FAIL: Unexpected TerminatedExecutionException thrown.\n");
- failed = true;
+ 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);
}
- /* Test script timeout extension: */
- JSContextGroupSetExecutionTimeLimit(contextGroup, 0.100f, extendTerminateCallback, 0);
- {
- const char* loopForeverScript = "var startTime = currentCPUTime(); while (true) { if (currentCPUTime() - startTime > .500) break; } ";
- JSStringRef script = JSStringCreateWithUTF8CString(loopForeverScript);
- double startTime;
- double endTime;
- double deltaTime;
- exception = NULL;
- startTime = currentCPUTime();
- v = JSEvaluateScript(context, script, NULL, NULL, 1, &exception);
- endTime = currentCPUTime();
- deltaTime = endTime - startTime;
-
- if ((deltaTime >= .300f) && (deltaTime < .500f) && (extendTerminateCallbackCalled == 2) && exception)
- printf("PASS: script timeout was extended as expected.\n");
- else {
- if (deltaTime < .200f)
- printf("FAIL: script timeout was not extended as expected.\n");
- else if (deltaTime >= .500f)
- printf("FAIL: script did not timeout.\n");
-
- if (extendTerminateCallbackCalled < 1)
- printf("FAIL: script timeout callback was not called.\n");
- if (extendTerminateCallbackCalled < 2)
- printf("FAIL: script timeout callback was not called after timeout extension.\n");
-
- if (!exception)
- printf("FAIL: TerminatedExecutionException was not thrown during timeout extension test.\n");
-
- failed = true;
- }
- }
-#endif /* PLATFORM(MAC) || PLATFORM(IOS) */
+ failed = testExecutionTimeLimit() || failed;
+ failed = testGlobalContextWithFinalizer() || failed;
+ failed = testPingPongStackOverflow() || failed;
// Clear out local variables pointing at JSObjectRefs to allow their values to be collected
function = NULL;
@@ -1975,6 +1936,15 @@ int main(int argc, char* argv[])
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");
@@ -1996,6 +1966,7 @@ static char* createStringWithContentsOfFile(const char* fileName)
FILE* f = fopen(fileName, "r");
if (!f) {
fprintf(stderr, "Could not open file: %s\n", fileName);
+ free(buffer);
return 0;
}
@@ -2014,3 +1985,10 @@ static char* createStringWithContentsOfFile(const char* fileName)
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
index 47c20a830..88d3701c2 100644
--- a/Source/JavaScriptCore/API/tests/testapi.js
+++ b/Source/JavaScriptCore/API/tests/testapi.js
@@ -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,17 +10,17 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
function bludgeonArguments() { if (0) arguments; return function g() {} }
@@ -74,6 +74,20 @@ function globalStaticFunction()
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;
@@ -253,6 +267,9 @@ 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)
diff --git a/Source/JavaScriptCore/API/tests/testapi.mm b/Source/JavaScriptCore/API/tests/testapi.mm
deleted file mode 100644
index defb46e70..000000000
--- a/Source/JavaScriptCore/API/tests/testapi.mm
+++ /dev/null
@@ -1,841 +0,0 @@
-/*
- * 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. ``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.
- */
-
-#import <JavaScriptCore/JavaScriptCore.h>
-
-extern "C" void JSSynchronousGarbageCollectForDebugging(JSContextRef);
-
-extern "C" bool _Block_has_signature(id);
-extern "C" const char * _Block_signature(id);
-
-extern int failed;
-extern "C" void testObjectiveCAPI(void);
-
-#if JSC_OBJC_API_ENABLED
-
-@protocol ParentObject <JSExport>
-@end
-
-@interface ParentObject : NSObject<ParentObject>
-+ (NSString *)parentTest;
-@end
-
-@implementation ParentObject
-+ (NSString *)parentTest
-{
- return [self description];
-}
-@end
-
-@protocol TestObject <JSExport>
-@property int variable;
-@property (readonly) int six;
-@property CGPoint point;
-+ (NSString *)classTest;
-+ (NSString *)parentTest;
-- (NSString *)getString;
-JSExportAs(testArgumentTypes,
-- (NSString *)testArgumentTypesWithInt:(int)i double:(double)d boolean:(BOOL)b string:(NSString *)s number:(NSNumber *)n array:(NSArray *)a dictionary:(NSDictionary *)o
-);
-- (void)callback:(JSValue *)function;
-- (void)bogusCallback:(void(^)(int))function;
-@end
-
-@interface TestObject : ParentObject <TestObject>
-@property int six;
-+ (id)testObject;
-@end
-
-@implementation TestObject
-@synthesize variable;
-@synthesize six;
-@synthesize point;
-+ (id)testObject
-{
- return [[TestObject alloc] init];
-}
-+ (NSString *)classTest
-{
- return @"classTest - okay";
-}
-- (NSString *)getString
-{
- return @"42";
-}
-- (NSString *)testArgumentTypesWithInt:(int)i double:(double)d boolean:(BOOL)b string:(NSString *)s number:(NSNumber *)n array:(NSArray *)a dictionary:(NSDictionary *)o
-{
- return [NSString stringWithFormat:@"%d,%g,%d,%@,%d,%@,%@", i, d, b==YES?true:false,s,[n intValue],a[1],o[@"x"]];
-}
-- (void)callback:(JSValue *)function
-{
- [function callWithArguments:[NSArray arrayWithObject:[NSNumber numberWithInt:42]]];
-}
-- (void)bogusCallback:(void(^)(int))function
-{
- function(42);
-}
-@end
-
-bool testXYZTested = false;
-
-@protocol TextXYZ <JSExport>
-@property int x;
-@property (readonly) int y;
-@property (assign) JSValue *onclick;
-@property (assign) JSValue *weakOnclick;
-- (void)test:(NSString *)message;
-@end
-
-@interface TextXYZ : NSObject <TextXYZ>
-@property int x;
-@property int y;
-@property int z;
-- (void)click;
-@end
-
-@implementation TextXYZ {
- JSManagedValue *m_weakOnclickHandler;
- JSManagedValue *m_onclickHandler;
-}
-@synthesize x;
-@synthesize y;
-@synthesize z;
-- (void)test:(NSString *)message
-{
- testXYZTested = [message isEqual:@"test"] && x == 13 & y == 4 && z == 5;
-}
-- (void)setWeakOnclick:(JSValue *)value
-{
- m_weakOnclickHandler = [JSManagedValue managedValueWithValue:value];
-}
-
-- (void)setOnclick:(JSValue *)value
-{
- m_onclickHandler = [JSManagedValue managedValueWithValue:value];
- [value.context.virtualMachine addManagedReference:m_onclickHandler withOwner:self];
-}
-- (JSValue *)weakOnclick
-{
- return [m_weakOnclickHandler value];
-}
-- (JSValue *)onclick
-{
- return [m_onclickHandler value];
-}
-- (void)click
-{
- if (!m_onclickHandler)
- return;
-
- JSValue *function = [m_onclickHandler value];
- [function callWithArguments:[NSArray array]];
-}
-- (void)dealloc
-{
- [[m_onclickHandler value].context.virtualMachine removeManagedReference:m_onclickHandler withOwner:self];
-}
-@end
-
-@class TinyDOMNode;
-
-@protocol TinyDOMNode <JSExport>
-- (void)appendChild:(TinyDOMNode *)child;
-- (NSUInteger)numberOfChildren;
-- (TinyDOMNode *)childAtIndex:(NSUInteger)index;
-- (void)removeChildAtIndex:(NSUInteger)index;
-@end
-
-@interface TinyDOMNode : NSObject<TinyDOMNode>
-+ (JSVirtualMachine *)sharedVirtualMachine;
-+ (void)clearSharedVirtualMachine;
-@end
-
-@implementation TinyDOMNode {
- NSMutableArray *m_children;
-}
-
-static JSVirtualMachine *sharedInstance = nil;
-
-+ (JSVirtualMachine *)sharedVirtualMachine
-{
- if (!sharedInstance)
- sharedInstance = [[JSVirtualMachine alloc] init];
- return sharedInstance;
-}
-
-+ (void)clearSharedVirtualMachine
-{
- sharedInstance = nil;
-}
-
-- (id)init
-{
- self = [super init];
- if (!self)
- return nil;
-
- m_children = [[NSMutableArray alloc] initWithCapacity:0];
-
- return self;
-}
-
-- (void)dealloc
-{
- NSEnumerator *enumerator = [m_children objectEnumerator];
- id nextChild;
- while ((nextChild = [enumerator nextObject]))
- [[TinyDOMNode sharedVirtualMachine] removeManagedReference:nextChild withOwner:self];
-
-#if !__has_feature(objc_arc)
- [super dealloc];
-#endif
-}
-
-- (void)appendChild:(TinyDOMNode *)child
-{
- [[TinyDOMNode sharedVirtualMachine] addManagedReference:child withOwner:self];
- [m_children addObject:child];
-}
-
-- (NSUInteger)numberOfChildren
-{
- return [m_children count];
-}
-
-- (TinyDOMNode *)childAtIndex:(NSUInteger)index
-{
- if (index >= [m_children count])
- return nil;
- return [m_children objectAtIndex:index];
-}
-
-- (void)removeChildAtIndex:(NSUInteger)index
-{
- if (index >= [m_children count])
- return;
- [[TinyDOMNode sharedVirtualMachine] removeManagedReference:[m_children objectAtIndex:index] withOwner:self];
- [m_children removeObjectAtIndex:index];
-}
-
-@end
-
-static void checkResult(NSString *description, bool passed)
-{
- NSLog(@"TEST: \"%@\": %@", description, passed ? @"PASSED" : @"FAILED");
- if (!passed)
- failed = 1;
-}
-
-static bool blockSignatureContainsClass()
-{
- static bool containsClass = ^{
- id block = ^(NSString *string){ return string; };
- return _Block_has_signature(block) && strstr(_Block_signature(block), "NSString");
- }();
- return containsClass;
-}
-
-void testObjectiveCAPI()
-{
- NSLog(@"Testing Objective-C API");
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- JSValue *result = [context evaluateScript:@"2 + 2"];
- checkResult(@"2 + 2", [result isNumber] && [result toInt32] == 4);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- NSString *result = [NSString stringWithFormat:@"Two plus two is %@", [context evaluateScript:@"2 + 2"]];
- checkResult(@"stringWithFormat", [result isEqual:@"Two plus two is 4"]);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- context[@"message"] = @"Hello";
- JSValue *result = [context evaluateScript:@"message + ', World!'"];
- checkResult(@"Hello, World!", [result isString] && [result isEqualToObject:@"Hello, World!"]);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- JSValue *result = [context evaluateScript:@"({ x:42 })"];
- checkResult(@"({ x:42 })", [result isObject] && [result[@"x"] isEqualToObject:@42]);
- id obj = [result toObject];
- checkResult(@"Check dictionary literal", [obj isKindOfClass:[NSDictionary class]]);
- id num = (NSDictionary *)obj[@"x"];
- checkResult(@"Check numeric literal", [num isKindOfClass:[NSNumber class]]);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- __block int result;
- context[@"blockCallback"] = ^(int value){
- result = value;
- };
- [context evaluateScript:@"blockCallback(42)"];
- checkResult(@"blockCallback", result == 42);
- }
-
- if (blockSignatureContainsClass()) {
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- __block bool result = false;
- context[@"blockCallback"] = ^(NSString *value){
- result = [@"42" isEqualToString:value] == YES;
- };
- [context evaluateScript:@"blockCallback(42)"];
- checkResult(@"blockCallback(NSString *)", result);
- }
- } else
- NSLog(@"Skipping 'blockCallback(NSString *)' test case");
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- checkResult(@"!context.exception", !context.exception);
- [context evaluateScript:@"!@#$%^&*() THIS IS NOT VALID JAVASCRIPT SYNTAX !@#$%^&*()"];
- checkResult(@"context.exception", context.exception);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- __block bool caught = false;
- context.exceptionHandler = ^(JSContext *context, JSValue *exception) {
- (void)context;
- (void)exception;
- caught = true;
- };
- [context evaluateScript:@"!@#$%^&*() THIS IS NOT VALID JAVASCRIPT SYNTAX !@#$%^&*()"];
- checkResult(@"JSContext.exceptionHandler", caught);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- context[@"callback"] = ^{
- JSContext *context = [JSContext currentContext];
- context.exception = [JSValue valueWithNewErrorFromMessage:@"Something went wrong." inContext:context];
- };
- JSValue *result = [context evaluateScript:@"var result; try { callback(); } catch (e) { result = 'Caught exception'; }"];
- checkResult(@"Explicit throw in callback - was caught by JavaScript", [result isEqualToObject:@"Caught exception"]);
- checkResult(@"Explicit throw in callback - not thrown to Objective-C", !context.exception);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- context[@"callback"] = ^{
- JSContext *context = [JSContext currentContext];
- [context evaluateScript:@"!@#$%^&*() THIS IS NOT VALID JAVASCRIPT SYNTAX !@#$%^&*()"];
- };
- JSValue *result = [context evaluateScript:@"var result; try { callback(); } catch (e) { result = 'Caught exception'; }"];
- checkResult(@"Implicit throw in callback - was caught by JavaScript", [result isEqualToObject:@"Caught exception"]);
- checkResult(@"Implicit throw in callback - not thrown to Objective-C", !context.exception);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- [context evaluateScript:
- @"function sum(array) { \
- var result = 0; \
- for (var i in array) \
- result += array[i]; \
- return result; \
- }"];
- JSValue *array = [JSValue valueWithObject:@[@13, @2, @7] inContext:context];
- JSValue *sumFunction = context[@"sum"];
- JSValue *result = [sumFunction callWithArguments:@[ array ]];
- checkResult(@"sum([13, 2, 7])", [result toInt32] == 22);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- JSValue *mulAddFunction = [context evaluateScript:
- @"(function(array, object) { \
- var result = []; \
- for (var i in array) \
- result.push(array[i] * object.x + object.y); \
- return result; \
- })"];
- JSValue *result = [mulAddFunction callWithArguments:@[ @[ @2, @4, @8 ], @{ @"x":@0.5, @"y":@42 } ]];
- checkResult(@"mulAddFunction", [result isObject] && [[result toString] isEqual:@"43,44,46"]);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- JSValue *array = [JSValue valueWithNewArrayInContext:context];
- checkResult(@"arrayLengthEmpty", [[array[@"length"] toNumber] unsignedIntegerValue] == 0);
- JSValue *value1 = [JSValue valueWithInt32:42 inContext:context];
- JSValue *value2 = [JSValue valueWithInt32:24 inContext:context];
- NSUInteger lowIndex = 5;
- NSUInteger maxLength = UINT_MAX;
-
- [array setValue:value1 atIndex:lowIndex];
- checkResult(@"array.length after put to low index", [[array[@"length"] toNumber] unsignedIntegerValue] == (lowIndex + 1));
-
- [array setValue:value1 atIndex:(maxLength - 1)];
- checkResult(@"array.length after put to maxLength - 1", [[array[@"length"] toNumber] unsignedIntegerValue] == maxLength);
-
- [array setValue:value2 atIndex:maxLength];
- checkResult(@"array.length after put to maxLength", [[array[@"length"] toNumber] unsignedIntegerValue] == maxLength);
-
- [array setValue:value2 atIndex:(maxLength + 1)];
- checkResult(@"array.length after put to maxLength + 1", [[array[@"length"] toNumber] unsignedIntegerValue] == maxLength);
-
- checkResult(@"valueAtIndex:0 is undefined", [[array valueAtIndex:0] isUndefined]);
- checkResult(@"valueAtIndex:lowIndex", [[array valueAtIndex:lowIndex] toInt32] == 42);
- checkResult(@"valueAtIndex:maxLength - 1", [[array valueAtIndex:(maxLength - 1)] toInt32] == 42);
- checkResult(@"valueAtIndex:maxLength", [[array valueAtIndex:maxLength] toInt32] == 24);
- checkResult(@"valueAtIndex:maxLength + 1", [[array valueAtIndex:(maxLength + 1)] toInt32] == 24);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- JSValue *object = [JSValue valueWithNewObjectInContext:context];
-
- object[@"point"] = @{ @"x":@1, @"y":@2 };
- object[@"point"][@"x"] = @3;
- CGPoint point = [object[@"point"] toPoint];
- checkResult(@"toPoint", point.x == 3 && point.y == 2);
-
- object[@{ @"toString":^{ return @"foo"; } }] = @"bar";
- checkResult(@"toString in object literal used as subscript", [[object[@"foo"] toString] isEqual:@"bar"]);
-
- object[[@"foobar" substringToIndex:3]] = @"bar";
- checkResult(@"substring used as subscript", [[object[@"foo"] toString] isEqual:@"bar"]);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- TextXYZ *testXYZ = [[TextXYZ alloc] init];
- context[@"testXYZ"] = testXYZ;
- testXYZ.x = 3;
- testXYZ.y = 4;
- testXYZ.z = 5;
- [context evaluateScript:@"testXYZ.x = 13; testXYZ.y = 14;"];
- [context evaluateScript:@"testXYZ.test('test')"];
- checkResult(@"TextXYZ - testXYZTested", testXYZTested);
- JSValue *result = [context evaluateScript:@"testXYZ.x + ',' + testXYZ.y + ',' + testXYZ.z"];
- checkResult(@"TextXYZ - result", [result isEqualToObject:@"13,4,undefined"]);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- [context[@"Object"][@"prototype"] defineProperty:@"getterProperty" descriptor:@{
- JSPropertyDescriptorGetKey:^{
- return [JSContext currentThis][@"x"];
- }
- }];
- JSValue *object = [JSValue valueWithObject:@{ @"x":@101 } inContext:context];
- int result = [object [@"getterProperty"] toInt32];
- checkResult(@"getterProperty", result == 101);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- context[@"concatenate"] = ^{
- NSArray *arguments = [JSContext currentArguments];
- if (![arguments count])
- return @"";
- NSString *message = [arguments[0] description];
- for (NSUInteger index = 1; index < [arguments count]; ++index)
- message = [NSString stringWithFormat:@"%@ %@", message, arguments[index]];
- return message;
- };
- JSValue *result = [context evaluateScript:@"concatenate('Hello,', 'World!')"];
- checkResult(@"concatenate", [result isEqualToObject:@"Hello, World!"]);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- context[@"foo"] = @YES;
- checkResult(@"@YES is boolean", [context[@"foo"] isBoolean]);
- JSValue *result = [context evaluateScript:@"typeof foo"];
- checkResult(@"@YES is boolean", [result isEqualToObject:@"boolean"]);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- TestObject* testObject = [TestObject testObject];
- context[@"testObject"] = testObject;
- JSValue *result = [context evaluateScript:@"String(testObject)"];
- checkResult(@"String(testObject)", [result isEqualToObject:@"[object TestObject]"]);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- TestObject* testObject = [TestObject testObject];
- context[@"testObject"] = testObject;
- JSValue *result = [context evaluateScript:@"String(testObject.__proto__)"];
- checkResult(@"String(testObject.__proto__)", [result isEqualToObject:@"[object TestObjectPrototype]"]);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- context[@"TestObject"] = [TestObject class];
- JSValue *result = [context evaluateScript:@"String(TestObject)"];
- checkResult(@"String(TestObject)", [result isEqualToObject:@"[object TestObjectConstructor]"]);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- JSValue* value = [JSValue valueWithObject:[TestObject class] inContext:context];
- checkResult(@"[value toObject] == [TestObject class]", [value toObject] == [TestObject class]);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- context[@"TestObject"] = [TestObject class];
- JSValue *result = [context evaluateScript:@"TestObject.parentTest()"];
- checkResult(@"TestObject.parentTest()", [result isEqualToObject:@"TestObject"]);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- TestObject* testObject = [TestObject testObject];
- context[@"testObjectA"] = testObject;
- context[@"testObjectB"] = testObject;
- JSValue *result = [context evaluateScript:@"testObjectA == testObjectB"];
- checkResult(@"testObjectA == testObjectB", [result isBoolean] && [result toBool]);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- TestObject* testObject = [TestObject testObject];
- context[@"testObject"] = testObject;
- testObject.point = (CGPoint){3,4};
- JSValue *result = [context evaluateScript:@"var result = JSON.stringify(testObject.point); testObject.point = {x:12,y:14}; result"];
- checkResult(@"testObject.point - result", [result isEqualToObject:@"{\"x\":3,\"y\":4}"]);
- checkResult(@"testObject.point - {x:12,y:14}", testObject.point.x == 12 && testObject.point.y == 14);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- TestObject* testObject = [TestObject testObject];
- testObject.six = 6;
- context[@"testObject"] = testObject;
- context[@"mul"] = ^(int x, int y){ return x * y; };
- JSValue *result = [context evaluateScript:@"mul(testObject.six, 7)"];
- checkResult(@"mul(testObject.six, 7)", [result isNumber] && [result toInt32] == 42);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- TestObject* testObject = [TestObject testObject];
- context[@"testObject"] = testObject;
- context[@"testObject"][@"variable"] = @4;
- [context evaluateScript:@"++testObject.variable"];
- checkResult(@"++testObject.variable", testObject.variable == 5);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- context[@"point"] = @{ @"x":@6, @"y":@7 };
- JSValue *result = [context evaluateScript:@"point.x + ',' + point.y"];
- checkResult(@"point.x + ',' + point.y", [result isEqualToObject:@"6,7"]);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- context[@"point"] = @{ @"x":@6, @"y":@7 };
- JSValue *result = [context evaluateScript:@"point.x + ',' + point.y"];
- checkResult(@"point.x + ',' + point.y", [result isEqualToObject:@"6,7"]);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- TestObject* testObject = [TestObject testObject];
- context[@"testObject"] = testObject;
- JSValue *result = [context evaluateScript:@"testObject.getString()"];
- checkResult(@"testObject.getString()", [result isString] && [result toInt32] == 42);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- TestObject* testObject = [TestObject testObject];
- context[@"testObject"] = testObject;
- JSValue *result = [context evaluateScript:@"testObject.testArgumentTypes(101,0.5,true,'foo',666,[false,'bar',false],{x:'baz'})"];
- checkResult(@"testObject.testArgumentTypes", [result isEqualToObject:@"101,0.5,1,foo,666,bar,baz"]);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- TestObject* testObject = [TestObject testObject];
- context[@"testObject"] = testObject;
- JSValue *result = [context evaluateScript:@"testObject.getString.call(testObject)"];
- checkResult(@"testObject.getString.call(testObject)", [result isString] && [result toInt32] == 42);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- TestObject* testObject = [TestObject testObject];
- context[@"testObject"] = testObject;
- checkResult(@"testObject.getString.call({}) pre", !context.exception);
- [context evaluateScript:@"testObject.getString.call({})"];
- checkResult(@"testObject.getString.call({}) post", context.exception);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- TestObject* testObject = [TestObject testObject];
- context[@"testObject"] = testObject;
- JSValue *result = [context evaluateScript:@"var result = 0; testObject.callback(function(x){ result = x; }); result"];
- checkResult(@"testObject.callback", [result isNumber] && [result toInt32] == 42);
- result = [context evaluateScript:@"testObject.bogusCallback"];
- checkResult(@"testObject.bogusCallback == undefined", [result isUndefined]);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- TestObject *testObject = [TestObject testObject];
- context[@"testObject"] = testObject;
- JSValue *result = [context evaluateScript:@"Function.prototype.toString.call(testObject.callback)"];
- checkResult(@"Function.prototype.toString", !context.exception && ![result isUndefined]);
- }
-
- @autoreleasepool {
- JSContext *context1 = [[JSContext alloc] init];
- JSContext *context2 = [[JSContext alloc] initWithVirtualMachine:context1.virtualMachine];
- JSValue *value = [JSValue valueWithDouble:42 inContext:context2];
- context1[@"passValueBetweenContexts"] = value;
- JSValue *result = [context1 evaluateScript:@"passValueBetweenContexts"];
- checkResult(@"[value isEqualToObject:result]", [value isEqualToObject:result]);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- context[@"handleTheDictionary"] = ^(NSDictionary *dict) {
- NSDictionary *expectedDict = @{
- @"foo" : [NSNumber numberWithInt:1],
- @"bar" : @{
- @"baz": [NSNumber numberWithInt:2]
- }
- };
- checkResult(@"recursively convert nested dictionaries", [dict isEqualToDictionary:expectedDict]);
- };
- [context evaluateScript:@"var myDict = { \
- 'foo': 1, \
- 'bar': {'baz': 2} \
- }; \
- handleTheDictionary(myDict);"];
-
- context[@"handleTheArray"] = ^(NSArray *array) {
- NSArray *expectedArray = @[@"foo", @"bar", @[@"baz"]];
- checkResult(@"recursively convert nested arrays", [array isEqualToArray:expectedArray]);
- };
- [context evaluateScript:@"var myArray = ['foo', 'bar', ['baz']]; handleTheArray(myArray);"];
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- TestObject *testObject = [TestObject testObject];
- @autoreleasepool {
- context[@"testObject"] = testObject;
- [context evaluateScript:@"var constructor = Object.getPrototypeOf(testObject).constructor; constructor.prototype = undefined;"];
- [context evaluateScript:@"testObject = undefined"];
- }
-
- JSSynchronousGarbageCollectForDebugging([context JSGlobalContextRef]);
-
- @autoreleasepool {
- context[@"testObject"] = testObject;
- }
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- TextXYZ *testXYZ = [[TextXYZ alloc] init];
-
- @autoreleasepool {
- context[@"testXYZ"] = testXYZ;
-
- [context evaluateScript:@" \
- didClick = false; \
- testXYZ.onclick = function() { \
- didClick = true; \
- }; \
- \
- testXYZ.weakOnclick = function() { \
- return 'foo'; \
- }; \
- "];
- }
-
- @autoreleasepool {
- [testXYZ click];
- JSValue *result = [context evaluateScript:@"didClick"];
- checkResult(@"Event handler onclick", [result toBool]);
- }
-
- JSSynchronousGarbageCollectForDebugging([context JSGlobalContextRef]);
-
- @autoreleasepool {
- JSValue *result = [context evaluateScript:@"testXYZ.onclick"];
- checkResult(@"onclick still around after GC", !([result isNull] || [result isUndefined]));
- }
-
-
- @autoreleasepool {
- JSValue *result = [context evaluateScript:@"testXYZ.weakOnclick"];
- checkResult(@"weakOnclick not around after GC", [result isNull] || [result isUndefined]);
- }
-
- @autoreleasepool {
- [context evaluateScript:@" \
- didClick = false; \
- testXYZ = null; \
- "];
- }
-
- JSSynchronousGarbageCollectForDebugging([context JSGlobalContextRef]);
-
- @autoreleasepool {
- [testXYZ click];
- JSValue *result = [context evaluateScript:@"didClick"];
- checkResult(@"Event handler onclick doesn't fire", ![result toBool]);
- }
- }
-
- @autoreleasepool {
- JSVirtualMachine *vm = [[JSVirtualMachine alloc] init];
- TestObject *testObject = [TestObject testObject];
- JSManagedValue *weakValue;
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] initWithVirtualMachine:vm];
- context[@"testObject"] = testObject;
- weakValue = [[JSManagedValue alloc] initWithValue:context[@"testObject"]];
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] initWithVirtualMachine:vm];
- context[@"testObject"] = testObject;
- JSSynchronousGarbageCollectForDebugging([context JSGlobalContextRef]);
- checkResult(@"weak value == nil", ![weakValue value]);
- checkResult(@"root is still alive", ![context[@"testObject"] isUndefined]);
- }
- }
-
- @autoreleasepool {
- JSVirtualMachine *vm = [TinyDOMNode sharedVirtualMachine];
- JSContext *context = [[JSContext alloc] initWithVirtualMachine:vm];
- TinyDOMNode *root = [[TinyDOMNode alloc] init];
- TinyDOMNode *lastNode = root;
- for (NSUInteger i = 0; i < 3; i++) {
- TinyDOMNode *newNode = [[TinyDOMNode alloc] init];
- [lastNode appendChild:newNode];
- lastNode = newNode;
- }
-
- @autoreleasepool {
- context[@"root"] = root;
- context[@"getLastNodeInChain"] = ^(TinyDOMNode *head){
- TinyDOMNode *lastNode = nil;
- while (head) {
- lastNode = head;
- head = [lastNode childAtIndex:0];
- }
- return lastNode;
- };
- [context evaluateScript:@"getLastNodeInChain(root).myCustomProperty = 42;"];
- }
-
- JSSynchronousGarbageCollectForDebugging([context JSGlobalContextRef]);
-
- JSValue *myCustomProperty = [context evaluateScript:@"getLastNodeInChain(root).myCustomProperty"];
- checkResult(@"My custom property == 42", [myCustomProperty isNumber] && [myCustomProperty toInt32] == 42);
-
- [TinyDOMNode clearSharedVirtualMachine];
- }
-
- @autoreleasepool {
- JSVirtualMachine *vm = [TinyDOMNode sharedVirtualMachine];
- JSContext *context = [[JSContext alloc] initWithVirtualMachine:vm];
- TinyDOMNode *root = [[TinyDOMNode alloc] init];
- TinyDOMNode *lastNode = root;
- for (NSUInteger i = 0; i < 3; i++) {
- TinyDOMNode *newNode = [[TinyDOMNode alloc] init];
- [lastNode appendChild:newNode];
- lastNode = newNode;
- }
-
- @autoreleasepool {
- context[@"root"] = root;
- context[@"getLastNodeInChain"] = ^(TinyDOMNode *head){
- TinyDOMNode *lastNode = nil;
- while (head) {
- lastNode = head;
- head = [lastNode childAtIndex:0];
- }
- return lastNode;
- };
- [context evaluateScript:@"getLastNodeInChain(root).myCustomProperty = 42;"];
-
- [root appendChild:[root childAtIndex:0]];
- [root removeChildAtIndex:0];
- }
-
- JSSynchronousGarbageCollectForDebugging([context JSGlobalContextRef]);
-
- JSValue *myCustomProperty = [context evaluateScript:@"getLastNodeInChain(root).myCustomProperty"];
- checkResult(@"duplicate calls to addManagedReference don't cause things to die", [myCustomProperty isNumber] && [myCustomProperty toInt32] == 42);
-
- [TinyDOMNode clearSharedVirtualMachine];
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- JSValue *o = [JSValue valueWithNewObjectInContext:context];
- o[@"foo"] = @"foo";
- JSSynchronousGarbageCollectForDebugging([context JSGlobalContextRef]);
-
- checkResult(@"JSValue correctly protected its internal value", [[o[@"foo"] toString] isEqualToString:@"foo"]);
- }
-
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- TestObject *testObject = [TestObject testObject];
- context[@"testObject"] = testObject;
- [context evaluateScript:@"testObject.__lookupGetter__('variable').call({})"];
- checkResult(@"Make sure we throw an exception when calling getter on incorrect |this|", context.exception);
- }
-
- @autoreleasepool {
- TestObject *testObject = [TestObject testObject];
- JSManagedValue *managedTestObject;
- @autoreleasepool {
- JSContext *context = [[JSContext alloc] init];
- context[@"testObject"] = testObject;
- managedTestObject = [JSManagedValue managedValueWithValue:context[@"testObject"]];
- [context.virtualMachine addManagedReference:managedTestObject withOwner:testObject];
- }
- }
-}
-
-#else
-
-void testObjectiveCAPI()
-{
-}
-
-#endif