1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sw=4 et tw=99:
3 : *
4 : * Test script cloning.
5 : */
6 :
7 : #include "tests.h"
8 : #include "jsdbgapi.h"
9 :
10 4 : BEGIN_TEST(test_cloneScript)
11 : {
12 : JSObject *A, *B;
13 :
14 1 : CHECK(A = createGlobal());
15 1 : CHECK(B = createGlobal());
16 :
17 : const char *source =
18 : "var i = 0;\n"
19 : "var sum = 0;\n"
20 : "while (i < 10) {\n"
21 : " sum += i;\n"
22 : " ++i;\n"
23 : "}\n"
24 1 : "(sum);\n";
25 :
26 : JSObject *obj;
27 :
28 : // compile for A
29 : {
30 2 : JSAutoEnterCompartment a;
31 1 : if (!a.enter(cx, A))
32 0 : return false;
33 :
34 : JSFunction *fun;
35 1 : CHECK(fun = JS_CompileFunction(cx, A, "f", 0, NULL, source, strlen(source), __FILE__, 1));
36 1 : CHECK(obj = JS_GetFunctionObject(fun));
37 : }
38 :
39 : // clone into B
40 : {
41 2 : JSAutoEnterCompartment b;
42 1 : if (!b.enter(cx, B))
43 0 : return false;
44 :
45 1 : CHECK(JS_CloneFunctionObject(cx, obj, B));
46 : }
47 :
48 1 : return true;
49 : }
50 1 : END_TEST(test_cloneScript)
51 :
52 : void
53 2 : DestroyPrincipals(JSPrincipals *principals)
54 : {
55 2 : delete principals;
56 2 : }
57 :
58 : struct Principals : public JSPrincipals
59 : {
60 : public:
61 2 : Principals()
62 2 : {
63 2 : refcount = 0;
64 2 : }
65 : };
66 :
67 : class AutoDropPrincipals
68 : {
69 : JSRuntime *rt;
70 : JSPrincipals *principals;
71 :
72 : public:
73 2 : AutoDropPrincipals(JSRuntime *rt, JSPrincipals *principals)
74 2 : : rt(rt), principals(principals)
75 : {
76 2 : JS_HoldPrincipals(principals);
77 2 : }
78 :
79 2 : ~AutoDropPrincipals()
80 : {
81 2 : JS_DropPrincipals(rt, principals);
82 2 : }
83 : };
84 :
85 4 : BEGIN_TEST(test_cloneScriptWithPrincipals)
86 : {
87 1 : JS_InitDestroyPrincipalsCallback(rt, DestroyPrincipals);
88 :
89 1 : JSPrincipals *principalsA = new Principals();
90 2 : AutoDropPrincipals dropA(rt, principalsA);
91 1 : JSPrincipals *principalsB = new Principals();
92 2 : AutoDropPrincipals dropB(rt, principalsB);
93 :
94 : JSObject *A, *B;
95 :
96 1 : CHECK(A = createGlobal(principalsA));
97 1 : CHECK(B = createGlobal(principalsB));
98 :
99 1 : const char *argnames[] = { "arg" };
100 1 : const char *source = "return function() { return arg; }";
101 :
102 : JSObject *obj;
103 :
104 : // Compile in A
105 : {
106 2 : JSAutoEnterCompartment a;
107 1 : if (!a.enter(cx, A))
108 0 : return false;
109 :
110 : JSFunction *fun;
111 1 : CHECK(fun = JS_CompileFunctionForPrincipals(cx, A, principalsA, "f",
112 : mozilla::ArrayLength(argnames), argnames,
113 : source, strlen(source), __FILE__, 1));
114 :
115 : JSScript *script;
116 1 : CHECK(script = JS_GetFunctionScript(cx, fun));
117 :
118 1 : CHECK(JS_GetScriptPrincipals(script) == principalsA);
119 1 : CHECK(obj = JS_GetFunctionObject(fun));
120 : }
121 :
122 : // Clone into B
123 : {
124 2 : JSAutoEnterCompartment b;
125 1 : if (!b.enter(cx, B))
126 0 : return false;
127 :
128 : JSObject *cloned;
129 1 : CHECK(cloned = JS_CloneFunctionObject(cx, obj, B));
130 :
131 : JSFunction *fun;
132 1 : CHECK(fun = JS_ValueToFunction(cx, JS::ObjectValue(*cloned)));
133 :
134 : JSScript *script;
135 1 : CHECK(script = JS_GetFunctionScript(cx, fun));
136 :
137 1 : CHECK(JS_GetScriptPrincipals(script) == principalsB);
138 :
139 : JS::Value v;
140 1 : JS::Value args[] = { JS::Int32Value(1) };
141 1 : CHECK(JS_CallFunctionValue(cx, B, JS::ObjectValue(*cloned), 1, args, &v));
142 1 : CHECK(v.isObject());
143 :
144 1 : JSObject *funobj = &v.toObject();
145 1 : CHECK(JS_ObjectIsFunction(cx, funobj));
146 1 : CHECK(fun = JS_ValueToFunction(cx, v));
147 1 : CHECK(script = JS_GetFunctionScript(cx, fun));
148 1 : CHECK(JS_GetScriptPrincipals(script) == principalsB);
149 : }
150 :
151 1 : return true;
152 : }
153 3 : END_TEST(test_cloneScriptWithPrincipals)
|