blob: 302708766d4d6e9636fc51744f5601abe0d04758 [file] [log] [blame]
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "tests.h"
#include "jsfriendapi.h"
const size_t N = 1000;
static jsval argv[N];
static JSBool
constructHook(JSContext *cx, unsigned argc, jsval *vp)
{
// Check that arguments were passed properly from JS_New.
JS::RootedObject callee(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
JS::RootedObject obj(cx, JS_NewObjectForConstructor(cx, js::Jsvalify(&js::ObjectClass), vp));
if (!obj) {
JS_ReportError(cx, "test failed, could not construct object");
return false;
}
if (strcmp(JS_GetClass(obj)->name, "Object") != 0) {
JS_ReportError(cx, "test failed, wrong class for 'this'");
return false;
}
if (argc != 3) {
JS_ReportError(cx, "test failed, argc == %d", argc);
return false;
}
if (!JSVAL_IS_INT(argv[2]) || JSVAL_TO_INT(argv[2]) != 2) {
JS_ReportError(cx, "test failed, wrong value in argv[2]");
return false;
}
if (!JS_IsConstructing(cx, vp)) {
JS_ReportError(cx, "test failed, not constructing");
return false;
}
// Perform a side-effect to indicate that this hook was actually called.
if (!JS_SetElement(cx, callee, 0, &argv[0]))
return false;
*vp = OBJECT_TO_JSVAL(obj);
argv[0] = argv[1] = argv[2] = JSVAL_VOID; // trash the argv, perversely
return true;
}
BEGIN_TEST(testNewObject_1)
{
// Root the global argv test array. Only the first 2 entries really need to
// be rooted, since we're only putting integers in the rest.
CHECK(JS_AddNamedValueRoot(cx, &argv[0], "argv0"));
CHECK(JS_AddNamedValueRoot(cx, &argv[1], "argv1"));
JS::RootedValue v(cx);
EVAL("Array", v.address());
JS::RootedObject Array(cx, JSVAL_TO_OBJECT(v));
// With no arguments.
JS::RootedObject obj(cx, JS_New(cx, Array, 0, NULL));
CHECK(obj);
JS::RootedValue rt(cx, OBJECT_TO_JSVAL(obj));
CHECK(JS_IsArrayObject(cx, obj));
uint32_t len;
CHECK(JS_GetArrayLength(cx, obj, &len));
CHECK_EQUAL(len, 0);
// With one argument.
argv[0] = INT_TO_JSVAL(4);
obj = JS_New(cx, Array, 1, argv);
CHECK(obj);
rt = OBJECT_TO_JSVAL(obj);
CHECK(JS_IsArrayObject(cx, obj));
CHECK(JS_GetArrayLength(cx, obj, &len));
CHECK_EQUAL(len, 4);
// With N arguments.
for (size_t i = 0; i < N; i++)
argv[i] = INT_TO_JSVAL(i);
obj = JS_New(cx, Array, N, argv);
CHECK(obj);
rt = OBJECT_TO_JSVAL(obj);
CHECK(JS_IsArrayObject(cx, obj));
CHECK(JS_GetArrayLength(cx, obj, &len));
CHECK_EQUAL(len, N);
CHECK(JS_GetElement(cx, obj, N - 1, v.address()));
CHECK_SAME(v, INT_TO_JSVAL(N - 1));
// With JSClass.construct.
static JSClass cls = {
"testNewObject_1",
0,
JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL,
NULL, NULL, NULL, constructHook
};
JS::RootedObject ctor(cx, JS_NewObject(cx, &cls, NULL, NULL));
CHECK(ctor);
JS::RootedValue rt2(cx, OBJECT_TO_JSVAL(ctor));
obj = JS_New(cx, ctor, 3, argv);
CHECK(obj);
CHECK(JS_GetElement(cx, ctor, 0, v.address()));
CHECK_SAME(v, JSVAL_ZERO);
JS_RemoveValueRoot(cx, &argv[0]);
JS_RemoveValueRoot(cx, &argv[1]);
return true;
}
END_TEST(testNewObject_1)