js/src/jsapi-tests/testXDR.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * vim: set ts=8 sts=4 et sw=4 tw=99:
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "jsfriendapi.h"
     8 #include "jsscript.h"
     9 #include "jsstr.h"
    11 #include "jsapi-tests/tests.h"
    13 #include "jsscriptinlines.h"
    15 static JSScript *
    16 CompileScriptForPrincipalsVersionOrigin(JSContext *cx, JS::HandleObject obj,
    17                                         JSPrincipals *originPrincipals,
    18                                         const char *bytes, size_t nbytes,
    19                                         const char *filename, unsigned lineno,
    20                                         JSVersion version)
    21 {
    22     size_t nchars;
    23     if (!JS_DecodeBytes(cx, bytes, nbytes, nullptr, &nchars))
    24         return nullptr;
    25     jschar *chars = static_cast<jschar *>(JS_malloc(cx, nchars * sizeof(jschar)));
    26     if (!chars)
    27         return nullptr;
    28     JS_ALWAYS_TRUE(JS_DecodeBytes(cx, bytes, nbytes, chars, &nchars));
    29     JS::CompileOptions options(cx);
    30     options.setOriginPrincipals(originPrincipals)
    31            .setFileAndLine(filename, lineno)
    32            .setVersion(version);
    33     JSScript *script = JS::Compile(cx, obj, options, chars, nchars);
    34     free(chars);
    35     return script;
    36 }
    38 static JSScript *
    39 FreezeThaw(JSContext *cx, JS::HandleScript script)
    40 {
    41     // freeze
    42     uint32_t nbytes;
    43     void *memory = JS_EncodeScript(cx, script, &nbytes);
    44     if (!memory)
    45         return nullptr;
    47     // thaw
    48     JSScript *script2 = JS_DecodeScript(cx, memory, nbytes,
    49                                         script->originPrincipals());
    50     js_free(memory);
    51     return script2;
    52 }
    54 static JSScript *
    55 GetScript(JSContext *cx, JS::HandleObject funobj)
    56 {
    57     JS::RootedFunction fun(cx, JS_GetObjectFunction(funobj));
    58     return JS_GetFunctionScript(cx, fun);
    59 }
    61 static JSObject *
    62 FreezeThaw(JSContext *cx, JS::HandleObject funobj)
    63 {
    64     // freeze
    65     uint32_t nbytes;
    66     void *memory = JS_EncodeInterpretedFunction(cx, funobj, &nbytes);
    67     if (!memory)
    68         return nullptr;
    70     // thaw
    71     JSScript *script = GetScript(cx, funobj);
    72     JSObject *funobj2 = JS_DecodeInterpretedFunction(cx, memory, nbytes,
    73                                                      script->originPrincipals());
    74     js_free(memory);
    75     return funobj2;
    76 }
    78 static TestJSPrincipals testPrincipal0(1);
    79 static TestJSPrincipals testPrincipal1(1);
    81 BEGIN_TEST(testXDR_principals)
    82 {
    83     JSScript *script;
    84     JSCompartment *compartment = js::GetContextCompartment(cx);
    85     for (int i = TEST_FIRST; i != TEST_END; ++i) {
    86         // Appease the new JSAPI assertions. The stuff being tested here is
    87         // going away anyway.
    88         JS_SetCompartmentPrincipals(compartment, &testPrincipal0);
    89         script = createScriptViaXDR(nullptr, i);
    90         CHECK(script);
    91         CHECK(JS_GetScriptPrincipals(script) == &testPrincipal0);
    92         CHECK(JS_GetScriptOriginPrincipals(script) == &testPrincipal0);
    94         script = createScriptViaXDR(&testPrincipal0, i);
    95         CHECK(script);
    96         CHECK(JS_GetScriptPrincipals(script) == &testPrincipal0);
    97         CHECK(JS_GetScriptOriginPrincipals(script) == &testPrincipal0);
    99         script = createScriptViaXDR(&testPrincipal1, i);
   100         CHECK(script);
   101         CHECK(JS_GetScriptPrincipals(script) == &testPrincipal0);
   102         CHECK(JS_GetScriptOriginPrincipals(script) == &testPrincipal1);
   103     }
   105     return true;
   106 }
   108 enum TestCase {
   109     TEST_FIRST,
   110     TEST_SCRIPT = TEST_FIRST,
   111     TEST_FUNCTION,
   112     TEST_SERIALIZED_FUNCTION,
   113     TEST_END
   114 };
   116 JSScript *createScriptViaXDR(JSPrincipals *orig, int testCase)
   117 {
   118     const char src[] =
   119         "function f() { return 1; }\n"
   120         "f;\n";
   122     JS::RootedObject global(cx, JS::CurrentGlobalOrNull(cx));
   123     JS::RootedScript script(cx, CompileScriptForPrincipalsVersionOrigin(cx, global, orig,
   124                                                                         src, strlen(src), "test", 1,
   125                                                                         JSVERSION_DEFAULT));
   126     if (!script)
   127         return nullptr;
   129     if (testCase == TEST_SCRIPT || testCase == TEST_SERIALIZED_FUNCTION) {
   130         script = FreezeThaw(cx, script);
   131         if (!script)
   132             return nullptr;
   133         if (testCase == TEST_SCRIPT)
   134             return script;
   135     }
   137     JS::RootedValue v(cx);
   138     bool ok = JS_ExecuteScript(cx, global, script, &v);
   139     if (!ok || !v.isObject())
   140         return nullptr;
   141     JS::RootedObject funobj(cx, &v.toObject());
   142     if (testCase == TEST_FUNCTION) {
   143         funobj = FreezeThaw(cx, funobj);
   144         if (!funobj)
   145             return nullptr;
   146     }
   147     return GetScript(cx, funobj);
   148 }
   150 END_TEST(testXDR_principals)
   152 BEGIN_TEST(testXDR_bug506491)
   153 {
   154     const char *s =
   155         "function makeClosure(s, name, value) {\n"
   156         "    eval(s);\n"
   157         "    Math.sin(value);\n"
   158         "    return let (n = name, v = value) function () { return String(v); };\n"
   159         "}\n"
   160         "var f = makeClosure('0;', 'status', 'ok');\n";
   162     // compile
   163     JS::CompileOptions options(cx);
   164     options.setFileAndLine(__FILE__, __LINE__);
   165     JS::RootedScript script(cx, JS_CompileScript(cx, global, s, strlen(s),
   166                                                  options));
   167     CHECK(script);
   169     script = FreezeThaw(cx, script);
   170     CHECK(script);
   172     // execute
   173     JS::RootedValue v2(cx);
   174     CHECK(JS_ExecuteScript(cx, global, script, &v2));
   176     // try to break the Block object that is the parent of f
   177     JS_GC(rt);
   179     // confirm
   180     EVAL("f() === 'ok';\n", &v2);
   181     JS::RootedValue trueval(cx, JSVAL_TRUE);
   182     CHECK_SAME(v2, trueval);
   183     return true;
   184 }
   185 END_TEST(testXDR_bug506491)
   187 BEGIN_TEST(testXDR_bug516827)
   188 {
   189     // compile an empty script
   190     JS::CompileOptions options(cx);
   191     options.setFileAndLine(__FILE__, __LINE__);
   192     JS::RootedScript script(cx, JS_CompileScript(cx, global, "", 0, options));
   193     CHECK(script);
   195     script = FreezeThaw(cx, script);
   196     CHECK(script);
   198     // execute with null result meaning no result wanted
   199     CHECK(JS_ExecuteScript(cx, global, script));
   200     return true;
   201 }
   202 END_TEST(testXDR_bug516827)
   204 BEGIN_TEST(testXDR_source)
   205 {
   206     const char *samples[] = {
   207         // This can't possibly fail to compress well, can it?
   208         "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 }",
   209         "short",
   210         nullptr
   211     };
   212     for (const char **s = samples; *s; s++) {
   213         JS::CompileOptions options(cx);
   214         options.setFileAndLine(__FILE__, __LINE__);
   215         JS::RootedScript script(cx, JS_CompileScript(cx, global, *s, strlen(*s),
   216                                                      options));
   217         CHECK(script);
   218         script = FreezeThaw(cx, script);
   219         CHECK(script);
   220         JSString *out = JS_DecompileScript(cx, script, "testing", 0);
   221         CHECK(out);
   222         bool equal;
   223         CHECK(JS_StringEqualsAscii(cx, out, *s, &equal));
   224         CHECK(equal);
   225     }
   226     return true;
   227 }
   228 END_TEST(testXDR_source)
   230 BEGIN_TEST(testXDR_sourceMap)
   231 {
   232     const char *sourceMaps[] = {
   233         "http://example.com/source-map.json",
   234         "file:///var/source-map.json",
   235         nullptr
   236     };
   237     JS::RootedScript script(cx);
   238     for (const char **sm = sourceMaps; *sm; sm++) {
   239         JS::CompileOptions options(cx);
   240         options.setFileAndLine(__FILE__, __LINE__);
   241         script = JS_CompileScript(cx, global, "", 0, options);
   242         CHECK(script);
   244         size_t len = strlen(*sm);
   245         jschar *expected = js::InflateString(cx, *sm, &len);
   246         CHECK(expected);
   248         // The script source takes responsibility of free'ing |expected|.
   249         CHECK(script->scriptSource()->setSourceMapURL(cx, expected));
   250         script = FreezeThaw(cx, script);
   251         CHECK(script);
   252         CHECK(script->scriptSource());
   253         CHECK(script->scriptSource()->hasSourceMapURL());
   255         const jschar *actual = script->scriptSource()->sourceMapURL();
   256         CHECK(actual);
   258         while (*expected) {
   259             CHECK(*actual);
   260             CHECK(*expected == *actual);
   261             expected++;
   262             actual++;
   263         }
   264         CHECK(!*actual);
   265     }
   266     return true;
   267 }
   268 END_TEST(testXDR_sourceMap)

mercurial