+bool assertTrue(bool value, const char* message)
+{
+ if (!value) {
+ if (message)
+ fprintf(stderr, "assertTrue failed: '%s'\n", message);
+ else
+ fprintf(stderr, "assertTrue failed.\n");
+ failed = 1;
+ }
+ return value;
+}
+
+static bool checkForCycleInPrototypeChain()
+{
+ bool result = true;
+ JSGlobalContextRef context = JSGlobalContextCreate(0);
+ JSObjectRef object1 = JSObjectMake(context, /* jsClass */ 0, /* data */ 0);
+ JSObjectRef object2 = JSObjectMake(context, /* jsClass */ 0, /* data */ 0);
+ JSObjectRef object3 = JSObjectMake(context, /* jsClass */ 0, /* data */ 0);
+
+ JSObjectSetPrototype(context, object1, JSValueMakeNull(context));
+ ASSERT(JSValueIsNull(context, JSObjectGetPrototype(context, object1)));
+
+ // object1 -> object1
+ JSObjectSetPrototype(context, object1, object1);
+ result &= assertTrue(JSValueIsNull(context, JSObjectGetPrototype(context, object1)), "It is possible to assign self as a prototype");
+
+ // object1 -> object2 -> object1
+ JSObjectSetPrototype(context, object2, object1);
+ ASSERT(JSValueIsStrictEqual(context, JSObjectGetPrototype(context, object2), object1));
+ JSObjectSetPrototype(context, object1, object2);
+ result &= assertTrue(JSValueIsNull(context, JSObjectGetPrototype(context, object1)), "It is possible to close a prototype chain cycle");
+
+ // object1 -> object2 -> object3 -> object1
+ JSObjectSetPrototype(context, object2, object3);
+ ASSERT(JSValueIsStrictEqual(context, JSObjectGetPrototype(context, object2), object3));
+ JSObjectSetPrototype(context, object1, object2);
+ ASSERT(JSValueIsStrictEqual(context, JSObjectGetPrototype(context, object1), object2));
+ JSObjectSetPrototype(context, object3, object1);
+ result &= assertTrue(!JSValueIsStrictEqual(context, JSObjectGetPrototype(context, object3), object1), "It is possible to close a prototype chain cycle");
+
+ JSValueRef exception;
+ JSStringRef code = JSStringCreateWithUTF8CString("o = { }; p = { }; o.__proto__ = p; p.__proto__ = o");
+ JSStringRef file = JSStringCreateWithUTF8CString("");
+ result &= assertTrue(!JSEvaluateScript(context, code, /* thisObject*/ 0, file, 1, &exception)
+ , "An exception should be thrown");
+
+ JSStringRelease(code);
+ JSStringRelease(file);
+ JSGlobalContextRelease(context);
+ return result;
+}
+
+static JSValueRef valueToObjectExceptionCallAsFunction(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ UNUSED_PARAM(function);
+ UNUSED_PARAM(thisObject);
+ UNUSED_PARAM(argumentCount);
+ UNUSED_PARAM(arguments);
+ JSValueRef jsUndefined = JSValueMakeUndefined(JSContextGetGlobalContext(ctx));
+ JSValueToObject(JSContextGetGlobalContext(ctx), jsUndefined, exception);
+
+ return JSValueMakeUndefined(ctx);
+}
+static bool valueToObjectExceptionTest()
+{
+ JSGlobalContextRef testContext;
+ JSClassDefinition globalObjectClassDefinition = kJSClassDefinitionEmpty;
+ globalObjectClassDefinition.initialize = globalObject_initialize;
+ globalObjectClassDefinition.staticValues = globalObject_staticValues;
+ globalObjectClassDefinition.staticFunctions = globalObject_staticFunctions;
+ globalObjectClassDefinition.attributes = kJSClassAttributeNoAutomaticPrototype;
+ JSClassRef globalObjectClass = JSClassCreate(&globalObjectClassDefinition);
+ testContext = JSGlobalContextCreateInGroup(NULL, globalObjectClass);
+ JSObjectRef globalObject = JSContextGetGlobalObject(testContext);
+
+ JSStringRef valueToObject = JSStringCreateWithUTF8CString("valueToObject");
+ JSObjectRef valueToObjectFunction = JSObjectMakeFunctionWithCallback(testContext, valueToObject, valueToObjectExceptionCallAsFunction);
+ JSObjectSetProperty(testContext, globalObject, valueToObject, valueToObjectFunction, kJSPropertyAttributeNone, NULL);
+ JSStringRelease(valueToObject);
+
+ JSStringRef test = JSStringCreateWithUTF8CString("valueToObject();");
+ JSEvaluateScript(testContext, test, NULL, NULL, 1, NULL);
+
+ JSStringRelease(test);
+ JSClassRelease(globalObjectClass);
+ JSGlobalContextRelease(testContext);
+
+ return true;
+}
+
+static bool globalContextNameTest()
+{
+ bool result = true;
+ JSGlobalContextRef context = JSGlobalContextCreate(0);
+
+ JSStringRef str = JSGlobalContextCopyName(context);
+ result &= assertTrue(!str, "Default context name is NULL");
+
+ JSStringRef name1 = JSStringCreateWithUTF8CString("name1");
+ JSStringRef name2 = JSStringCreateWithUTF8CString("name2");
+
+ JSGlobalContextSetName(context, name1);
+ JSStringRef fetchName1 = JSGlobalContextCopyName(context);
+ JSGlobalContextSetName(context, name2);
+ JSStringRef fetchName2 = JSGlobalContextCopyName(context);
+ JSGlobalContextSetName(context, NULL);
+ JSStringRef fetchName3 = JSGlobalContextCopyName(context);
+
+ result &= assertTrue(JSStringIsEqual(name1, fetchName1), "Unexpected Context name");
+ result &= assertTrue(JSStringIsEqual(name2, fetchName2), "Unexpected Context name");
+ result &= assertTrue(!JSStringIsEqual(fetchName1, fetchName2), "Unexpected Context name");
+ result &= assertTrue(!fetchName3, "Unexpected Context name");
+
+ JSStringRelease(name1);
+ JSStringRelease(name2);
+ JSStringRelease(fetchName1);
+ JSStringRelease(fetchName2);
+
+ return result;
+}
+
+static void checkConstnessInJSObjectNames()
+{
+ JSStaticFunction fun;
+ fun.name = "something";
+ JSStaticValue val;
+ val.name = "something";
+}
+
+