summaryrefslogtreecommitdiffstats
path: root/js/src/jsapi-tests/testXDR.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jsapi-tests/testXDR.cpp')
-rw-r--r--js/src/jsapi-tests/testXDR.cpp168
1 files changed, 168 insertions, 0 deletions
diff --git a/js/src/jsapi-tests/testXDR.cpp b/js/src/jsapi-tests/testXDR.cpp
new file mode 100644
index 000000000..806a4b743
--- /dev/null
+++ b/js/src/jsapi-tests/testXDR.cpp
@@ -0,0 +1,168 @@
+/* -*- 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 "jsfriendapi.h"
+#include "jsscript.h"
+#include "jsstr.h"
+
+#include "jsapi-tests/tests.h"
+
+#include "jsscriptinlines.h"
+
+static bool
+GetBuildId(JS::BuildIdCharVector* buildId)
+{
+ const char buildid[] = "testXDR";
+ return buildId->append(buildid, sizeof(buildid));
+}
+
+static JSScript*
+FreezeThaw(JSContext* cx, JS::HandleScript script)
+{
+ JS::SetBuildIdOp(cx, GetBuildId);
+
+ // freeze
+ JS::TranscodeBuffer buffer;
+ JS::TranscodeResult rs = JS::EncodeScript(cx, buffer, script);
+ if (rs != JS::TranscodeResult_Ok)
+ return nullptr;
+
+ // thaw
+ JS::RootedScript script2(cx);
+ rs = JS::DecodeScript(cx, buffer, &script2);
+ if (rs != JS::TranscodeResult_Ok)
+ return nullptr;
+ return script2;
+}
+
+enum TestCase {
+ TEST_FIRST,
+ TEST_SCRIPT = TEST_FIRST,
+ TEST_FUNCTION,
+ TEST_SERIALIZED_FUNCTION,
+ TEST_END
+};
+
+BEGIN_TEST(testXDR_bug506491)
+{
+ const char* s =
+ "function makeClosure(s, name, value) {\n"
+ " eval(s);\n"
+ " Math.sin(value);\n"
+ " let n = name, v = value;\n"
+ " return function () { return String(v); };\n"
+ "}\n"
+ "var f = makeClosure('0;', 'status', 'ok');\n";
+
+ // compile
+ JS::CompileOptions options(cx);
+ options.setFileAndLine(__FILE__, __LINE__);
+ JS::RootedScript script(cx);
+ CHECK(JS_CompileScript(cx, s, strlen(s), options, &script));
+ CHECK(script);
+
+ script = FreezeThaw(cx, script);
+ CHECK(script);
+
+ // execute
+ JS::RootedValue v2(cx);
+ CHECK(JS_ExecuteScript(cx, script, &v2));
+
+ // try to break the Block object that is the parent of f
+ JS_GC(cx);
+
+ // confirm
+ EVAL("f() === 'ok';\n", &v2);
+ JS::RootedValue trueval(cx, JS::TrueValue());
+ CHECK_SAME(v2, trueval);
+ return true;
+}
+END_TEST(testXDR_bug506491)
+
+BEGIN_TEST(testXDR_bug516827)
+{
+ // compile an empty script
+ JS::CompileOptions options(cx);
+ options.setFileAndLine(__FILE__, __LINE__);
+ JS::RootedScript script(cx);
+ CHECK(JS_CompileScript(cx, "", 0, options, &script));
+ CHECK(script);
+
+ script = FreezeThaw(cx, script);
+ CHECK(script);
+
+ // execute with null result meaning no result wanted
+ CHECK(JS_ExecuteScript(cx, script));
+ return true;
+}
+END_TEST(testXDR_bug516827)
+
+BEGIN_TEST(testXDR_source)
+{
+ const char* samples[] = {
+ // This can't possibly fail to compress well, can it?
+ "function f(x) { return x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x }",
+ "short",
+ nullptr
+ };
+ for (const char** s = samples; *s; s++) {
+ JS::CompileOptions options(cx);
+ options.setFileAndLine(__FILE__, __LINE__);
+ JS::RootedScript script(cx);
+ CHECK(JS_CompileScript(cx, *s, strlen(*s), options, &script));
+ CHECK(script);
+ script = FreezeThaw(cx, script);
+ CHECK(script);
+ JSString* out = JS_DecompileScript(cx, script, "testing", 0);
+ CHECK(out);
+ bool equal;
+ CHECK(JS_StringEqualsAscii(cx, out, *s, &equal));
+ CHECK(equal);
+ }
+ return true;
+}
+END_TEST(testXDR_source)
+
+BEGIN_TEST(testXDR_sourceMap)
+{
+ const char* sourceMaps[] = {
+ "http://example.com/source-map.json",
+ "file:///var/source-map.json",
+ nullptr
+ };
+ JS::RootedScript script(cx);
+ for (const char** sm = sourceMaps; *sm; sm++) {
+ JS::CompileOptions options(cx);
+ options.setFileAndLine(__FILE__, __LINE__);
+ CHECK(JS_CompileScript(cx, "", 0, options, &script));
+ CHECK(script);
+
+ size_t len = strlen(*sm);
+ JS::UniqueTwoByteChars expected_wrapper(js::InflateString(cx, *sm, &len));
+ char16_t *expected = expected_wrapper.get();
+ CHECK(expected);
+
+ // The script source takes responsibility of free'ing |expected|.
+ CHECK(script->scriptSource()->setSourceMapURL(cx, expected));
+ script = FreezeThaw(cx, script);
+ CHECK(script);
+ CHECK(script->scriptSource());
+ CHECK(script->scriptSource()->hasSourceMapURL());
+
+ const char16_t* actual = script->scriptSource()->sourceMapURL();
+ CHECK(actual);
+
+ while (*expected) {
+ CHECK(*actual);
+ CHECK(*expected == *actual);
+ expected++;
+ actual++;
+ }
+ CHECK(!*actual);
+ }
+ return true;
+}
+END_TEST(testXDR_sourceMap)