1 : #include "tests.h"
2 : #include "jsscript.h"
3 : #include "jscntxt.h"
4 :
5 : #include "jscntxtinlines.h"
6 : #include "jsobjinlines.h"
7 :
8 : using namespace js;
9 :
10 : struct VersionFixture;
11 :
12 : /*
13 : * Fast-native callbacks for use from JS.
14 : * They set their results on the current fixture instance.
15 : */
16 :
17 : static VersionFixture *callbackData = NULL;
18 :
19 : JSBool CheckVersionHasXML(JSContext *cx, unsigned argc, jsval *vp);
20 : JSBool DisableXMLOption(JSContext *cx, unsigned argc, jsval *vp);
21 : JSBool CallSetVersion17(JSContext *cx, unsigned argc, jsval *vp);
22 : JSBool CheckNewScriptNoXML(JSContext *cx, unsigned argc, jsval *vp);
23 : JSBool OverrideVersion15(JSContext *cx, unsigned argc, jsval *vp);
24 : JSBool CaptureVersion(JSContext *cx, unsigned argc, jsval *vp);
25 : JSBool CheckOverride(JSContext *cx, unsigned argc, jsval *vp);
26 : JSBool EvalScriptVersion16(JSContext *cx, unsigned argc, jsval *vp);
27 :
28 : struct VersionFixture : public JSAPITest
29 8 : {
30 : JSVersion captured;
31 :
32 4 : virtual bool init() {
33 4 : if (!JSAPITest::init())
34 0 : return false;
35 4 : callbackData = this;
36 4 : captured = JSVERSION_UNKNOWN;
37 4 : return JS_DefineFunction(cx, global, "checkVersionHasXML", CheckVersionHasXML, 0, 0) &&
38 4 : JS_DefineFunction(cx, global, "disableXMLOption", DisableXMLOption, 0, 0) &&
39 4 : JS_DefineFunction(cx, global, "callSetVersion17", CallSetVersion17, 0, 0) &&
40 4 : JS_DefineFunction(cx, global, "checkNewScriptNoXML", CheckNewScriptNoXML, 0, 0) &&
41 4 : JS_DefineFunction(cx, global, "overrideVersion15", OverrideVersion15, 0, 0) &&
42 4 : JS_DefineFunction(cx, global, "captureVersion", CaptureVersion, 0, 0) &&
43 4 : JS_DefineFunction(cx, global, "checkOverride", CheckOverride, 1, 0) &&
44 : JS_DefineFunction(cx, global, "evalScriptVersion16",
45 28 : EvalScriptVersion16, 0, 0);
46 : }
47 :
48 2 : JSScript *fakeScript(const char *contents, size_t length) {
49 2 : return JS_CompileScript(cx, global, contents, length, "<test>", 1);
50 : }
51 :
52 2 : bool hasXML(unsigned version) {
53 2 : return VersionHasXML(JSVersion(version));
54 : }
55 :
56 1 : bool hasXML(JSScript *script) {
57 1 : return hasXML(script->getVersion());
58 : }
59 :
60 4 : bool hasXML() {
61 4 : return OptionsHasXML(JS_GetOptions(cx));
62 : }
63 :
64 : bool checkOptionsHasNoXML() {
65 : CHECK(!OptionsHasXML(JS_GetOptions(cx)));
66 : return true;
67 : }
68 :
69 1 : bool disableXMLOption() {
70 1 : JS_SetOptions(cx, JS_GetOptions(cx) & ~JSOPTION_XML);
71 1 : return true;
72 : }
73 :
74 3 : bool checkVersionIsOverridden() {
75 3 : CHECK(cx->isVersionOverridden());
76 3 : return true;
77 : }
78 :
79 : /* Check that script compilation results in a version without XML. */
80 1 : bool checkNewScriptNoXML() {
81 1 : JSScript *script = fakeScript("", 0);
82 1 : CHECK(script);
83 1 : CHECK(!hasXML(script->getVersion()));
84 1 : return true;
85 : }
86 :
87 1 : bool checkVersionHasXML() {
88 1 : CHECK(VersionHasXML(cx->findVersion()));
89 1 : return true;
90 : }
91 :
92 4 : bool setVersion(JSVersion version) {
93 4 : CHECK(JS_GetVersion(cx) != version);
94 4 : JS_SetVersion(cx, version);
95 4 : return true;
96 : }
97 :
98 2 : bool evalVersion(const jschar *chars, size_t len, JSVersion version) {
99 2 : CHECK(JS_GetVersion(cx) != version);
100 : jsval rval;
101 2 : CHECK(JS_EvaluateUCScriptForPrincipalsVersion(
102 : cx, global, NULL, chars, len, "<test>", 0, &rval, version));
103 2 : return true;
104 : }
105 :
106 2 : bool toggleXML(bool shouldEnable) {
107 2 : CHECK_EQUAL(hasXML(), !shouldEnable);
108 2 : JS_ToggleOptions(cx, JSOPTION_XML);
109 2 : CHECK_EQUAL(hasXML(), shouldEnable);
110 2 : return true;
111 : }
112 :
113 1 : bool disableXML() {
114 1 : return toggleXML(false);
115 : }
116 :
117 1 : bool enableXML() {
118 1 : return toggleXML(true);
119 : }
120 : };
121 :
122 : /* Callbacks to throw into JS-land. */
123 :
124 : JSBool
125 1 : CallSetVersion17(JSContext *cx, unsigned argc, jsval *vp)
126 : {
127 1 : return callbackData->setVersion(JSVERSION_1_7);
128 : }
129 :
130 : JSBool
131 1 : CheckVersionHasXML(JSContext *cx, unsigned argc, jsval *vp)
132 : {
133 1 : return callbackData->checkVersionHasXML();
134 : }
135 :
136 : JSBool
137 1 : DisableXMLOption(JSContext *cx, unsigned argc, jsval *vp)
138 : {
139 1 : return callbackData->disableXMLOption();
140 : }
141 :
142 : JSBool
143 1 : CheckNewScriptNoXML(JSContext *cx, unsigned argc, jsval *vp)
144 : {
145 1 : return callbackData->checkNewScriptNoXML();
146 : }
147 :
148 : JSBool
149 3 : OverrideVersion15(JSContext *cx, unsigned argc, jsval *vp)
150 : {
151 3 : if (!callbackData->setVersion(JSVERSION_1_5))
152 0 : return false;
153 3 : return callbackData->checkVersionIsOverridden();
154 : }
155 :
156 : JSBool
157 2 : EvalScriptVersion16(JSContext *cx, unsigned argc, jsval *vp)
158 : {
159 2 : JS_ASSERT(argc == 1);
160 2 : jsval *argv = JS_ARGV(cx, vp);
161 2 : JS_ASSERT(JSVAL_IS_STRING(argv[0]));
162 2 : JSString *str = JSVAL_TO_STRING(argv[0]);
163 2 : const jschar *chars = str->getChars(cx);
164 2 : JS_ASSERT(chars);
165 2 : size_t len = str->length();
166 2 : return callbackData->evalVersion(chars, len, JSVERSION_1_6);
167 : }
168 :
169 : JSBool
170 3 : CaptureVersion(JSContext *cx, unsigned argc, jsval *vp)
171 : {
172 3 : callbackData->captured = JS_GetVersion(cx);
173 3 : return true;
174 : }
175 :
176 : JSBool
177 5 : CheckOverride(JSContext *cx, unsigned argc, jsval *vp)
178 : {
179 5 : JS_ASSERT(argc == 1);
180 5 : jsval *argv = JS_ARGV(cx, vp);
181 5 : JS_ASSERT(JSVAL_IS_BOOLEAN(argv[0]));
182 5 : bool shouldHaveOverride = !!JSVAL_TO_BOOLEAN(argv[0]);
183 5 : return shouldHaveOverride == cx->isVersionOverridden();
184 : }
185 :
186 : /*
187 : * See bug 611462. We are checking that the XML option setting from a JSAPI
188 : * call is propagated to newly compiled scripts, instead of inheriting the XML
189 : * setting from a script on the stack.
190 : */
191 4 : BEGIN_FIXTURE_TEST(VersionFixture, testOptionsAreUsedForVersionFlags)
192 : {
193 1 : callbackData = this;
194 :
195 : /* Enable XML and compile a script to activate. */
196 1 : enableXML();
197 : const char toActivateChars[] =
198 : "checkVersionHasXML();"
199 : "disableXMLOption();"
200 : "callSetVersion17();"
201 1 : "checkNewScriptNoXML();";
202 1 : JSScript *toActivate = fakeScript(toActivateChars, sizeof(toActivateChars) - 1);
203 1 : CHECK(toActivate);
204 1 : CHECK(hasXML(toActivate));
205 :
206 1 : disableXML();
207 :
208 : /* Activate the script. */
209 : jsval dummy;
210 1 : CHECK(JS_ExecuteScript(cx, global, toActivate, &dummy));
211 1 : return true;
212 : }
213 1 : END_FIXTURE_TEST(VersionFixture, testOptionsAreUsedForVersionFlags)
214 :
215 : /*
216 : * When re-entering the virtual machine through a *Version API the version
217 : * is no longer forced -- it continues with its natural push/pop oriented
218 : * version progression. This is maintained by the |AutoVersionAPI| class in
219 : * jsapi.cpp.
220 : */
221 4 : BEGIN_FIXTURE_TEST(VersionFixture, testEntryLosesOverride)
222 : {
223 1 : EXEC("overrideVersion15(); evalScriptVersion16('checkOverride(false); captureVersion()');");
224 1 : CHECK_EQUAL(captured, JSVERSION_1_6);
225 :
226 : /*
227 : * Override gets propagated to default version as non-override when you leave the VM's execute
228 : * call.
229 : */
230 1 : CHECK_EQUAL(JS_GetVersion(cx), JSVERSION_1_5);
231 1 : CHECK(!cx->isVersionOverridden());
232 1 : return true;
233 : }
234 1 : END_FIXTURE_TEST(VersionFixture, testEntryLosesOverride)
235 :
236 : /*
237 : * EvalScriptVersion does not propagate overrides to its caller, it
238 : * restores things exactly as they were before the call. This is as opposed to
239 : * the normal (no Version suffix) API which propagates overrides
240 : * to the caller.
241 : */
242 4 : BEGIN_FIXTURE_TEST(VersionFixture, testReturnLosesOverride)
243 : {
244 1 : CHECK_EQUAL(JS_GetVersion(cx), JSVERSION_ECMA_5);
245 1 : EXEC(
246 : "checkOverride(false);"
247 : "evalScriptVersion16('overrideVersion15();');"
248 : "checkOverride(false);"
249 : "captureVersion();"
250 : );
251 1 : CHECK_EQUAL(captured, JSVERSION_ECMA_5);
252 1 : return true;
253 : }
254 1 : END_FIXTURE_TEST(VersionFixture, testReturnLosesOverride)
255 :
256 4 : BEGIN_FIXTURE_TEST(VersionFixture, testEvalPropagatesOverride)
257 : {
258 1 : CHECK_EQUAL(JS_GetVersion(cx), JSVERSION_ECMA_5);
259 1 : EXEC(
260 : "checkOverride(false);"
261 : "eval('overrideVersion15();');"
262 : "checkOverride(true);"
263 : "captureVersion();"
264 : );
265 1 : CHECK_EQUAL(captured, JSVERSION_1_5);
266 1 : return true;
267 : }
268 3 : END_FIXTURE_TEST(VersionFixture, testEvalPropagatesOverride)
|