js/xpconnect/tests/chrome/test_xrayToJS.xul

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/xpconnect/tests/chrome/test_xrayToJS.xul	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,170 @@
     1.4 +<?xml version="1.0"?>
     1.5 +<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
     1.6 +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
     1.7 +<!--
     1.8 +https://bugzilla.mozilla.org/show_bug.cgi?id=933681
     1.9 +-->
    1.10 +<window title="Mozilla Bug 933681"
    1.11 +        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
    1.12 +  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
    1.13 +
    1.14 +  <!-- test results are displayed in the html:body -->
    1.15 +  <body xmlns="http://www.w3.org/1999/xhtml">
    1.16 +  <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=933681"
    1.17 +     target="_blank">Mozilla Bug 933681</a>
    1.18 +  </body>
    1.19 +
    1.20 +  <!-- test code goes here -->
    1.21 +  <script type="application/javascript">
    1.22 +  <![CDATA[
    1.23 +
    1.24 +  /** Test for ES constructors on Xrayed globals. **/
    1.25 +  SimpleTest.waitForExplicitFinish();
    1.26 +  const Cu = Components.utils;
    1.27 +  let global = Cu.getGlobalForObject.bind(Cu);
    1.28 +
    1.29 +  simpleConstructors = ['Object', 'Function', 'Array', 'Boolean', 'Date', 'Number',
    1.30 +                        'String', 'RegExp', 'Error', 'InternalError', 'EvalError',
    1.31 +                        'RangeError', 'ReferenceError', 'SyntaxError', 'TypeError',
    1.32 +                        'URIError', 'ArrayBuffer', 'Int8Array', 'Uint8Array',
    1.33 +                        'Int16Array', 'Uint16Array', 'Int32Array', 'Uint32Array',
    1.34 +                        'Float32Array', 'Float64Array', 'Uint8ClampedArray',
    1.35 +                        'WeakMap', 'Map', 'Set'];
    1.36 +
    1.37 +  function go() {
    1.38 +    window.iwin = document.getElementById('ifr').contentWindow;
    1.39 +
    1.40 +    // Test constructors that can be instantiated with zero arguments.
    1.41 +    for (var c of simpleConstructors) {
    1.42 +      ok(iwin[c], "Constructors appear: " + c);
    1.43 +      is(iwin[c], Cu.unwaiveXrays(iwin.wrappedJSObject[c]),
    1.44 +         "we end up with the appropriate constructor: " + c);
    1.45 +      is(Cu.unwaiveXrays(Cu.waiveXrays(new iwin[c]).constructor), iwin[c],
    1.46 +         "constructor property is set up right: " + c);
    1.47 +      is(Object.getPrototypeOf(new iwin[c]),
    1.48 +         Cu.unwaiveXrays(Cu.waiveXrays(iwin[c]).prototype),
    1.49 +         "prototype is correct: " + c);
    1.50 +      is(global(new iwin[c]), iwin, "Got the right global: " + c);
    1.51 +    }
    1.52 +
    1.53 +    // Test Object in more detail.
    1.54 +    var num = new iwin.Object(4);
    1.55 +    is(num.valueOf(), 4, "primitive object construction works");
    1.56 +    is(global(num), iwin, "correct global for num");
    1.57 +    var obj = new iwin.Object();
    1.58 +    obj.foo = 2;
    1.59 +    var withProto = iwin.Object.create(obj);
    1.60 +    is(global(withProto), iwin, "correct global for withProto");
    1.61 +    is(withProto.foo, 2, "Inherits properly");
    1.62 +
    1.63 +    // Test Function.
    1.64 +    var primitiveFun = new iwin.Function('return 2');
    1.65 +    is(global(primitiveFun), iwin, "function construction works");
    1.66 +    is(primitiveFun(), 2, "basic function works");
    1.67 +    var doSetFoo = new iwin.Function('arg', 'arg.foo = 2;');
    1.68 +    is(global(doSetFoo), iwin, "function with args works");
    1.69 +    try {
    1.70 +      doSetFoo(new Object());
    1.71 +      ok(false, "should have thrown while setting property on object");
    1.72 +    } catch (e) {
    1.73 +      ok(!!/denied/.test(e), "Threw correctly: " + e);
    1.74 +    }
    1.75 +    var factoryFun = new iwin.Function('return {foo: 32}');
    1.76 +    is(global(factoryFun), iwin, "proper global for factoryFun");
    1.77 +    is(factoryFun().foo, 32, "factoryFun invokable");
    1.78 +    is(global(factoryFun()), iwin, "minted objects live in the content scope");
    1.79 +
    1.80 +    // Test interface objects that don't actually construct things.
    1.81 +    is(iwin.Math.tan(4.5), Math.tan(4.5), "Math.tan works");
    1.82 +    is(iwin.Math.E, Math.E, "Math.E works");
    1.83 +    var json = JSON.stringify({a: 2, b: 'hi', c: {d: 'there'}});
    1.84 +    is(global(iwin.JSON.parse(json)), iwin, "JSON rehydrated into the right context");
    1.85 +    is(iwin.JSON.stringify(iwin.JSON.parse(json)), json, "JSON composition identity holds");
    1.86 +
    1.87 +    // Test proxies.
    1.88 +    var targetObject = new iwin.Object();
    1.89 +    targetObject.foo = 9;
    1.90 +    var forwardingProxy = new iwin.Proxy(targetObject, new iwin.Object());
    1.91 +    is(global(forwardingProxy), iwin, "proxy global correct");
    1.92 +    is(forwardingProxy.foo, 9, "forwards correctly");
    1.93 +    // NB: COW-implemented proxy handlers are super dangerous, and we should not
    1.94 +    // encourage them.
    1.95 +    var handler = {get: function(target, name) { return name * 2; }, __exposedProps__: {get: 'r'}};
    1.96 +    var doublingProxy = new iwin.Proxy(targetObject, handler);
    1.97 +    is(global(doublingProxy), iwin, "doubling proxy global correct");
    1.98 +    is(doublingProxy[3], 6, "Doubles correctly");
    1.99 +    is(doublingProxy[20], 40, "Doubles correctly");
   1.100 +
   1.101 +    // Test eval.
   1.102 +    var toEval = "({a: 2, b: {foo: 'bar'}, f: function() { return window; }})";
   1.103 +    is(global(iwin.eval(toEval)), iwin, "eval creates objects in the correct global");
   1.104 +    is(iwin.eval(toEval).b.foo, 'bar', "eval-ed object looks right");
   1.105 +    is(iwin.eval(toEval).f(), iwin, "evaled function works right");
   1.106 +
   1.107 +    testDate();
   1.108 +
   1.109 +    // We could also test DataView and Iterator here for completeness, but it's
   1.110 +    // more trouble than it's worth.
   1.111 +
   1.112 +
   1.113 +    SimpleTest.finish();
   1.114 +  }
   1.115 +
   1.116 +  function filterOut(array, props) {
   1.117 +    return array.filter(p => props.indexOf(p) == -1);
   1.118 +  }
   1.119 +
   1.120 +  function testXray(classname, xray, xray2, propsToSkip) {
   1.121 +    propsToSkip = propsToSkip || [];
   1.122 +    let xrayProto = Object.getPrototypeOf(xray);
   1.123 +    let localProto = window[classname].prototype;
   1.124 +    let protoProps = filterOut(Object.getOwnPropertyNames(localProto), propsToSkip).sort();
   1.125 +    let protoMethods = protoProps.filter(name => typeof localProto[name] == 'function' &&
   1.126 +                                         name != 'constructor');
   1.127 +    ok(protoMethods.length > 0, "Need something to test");
   1.128 +    is(xrayProto, iwin[classname].prototype, "Xray proto is correct");
   1.129 +    is(xrayProto, xray.__proto__, "Proto accessors agree");
   1.130 +    is(Object.getPrototypeOf(xrayProto), iwin.Object.prototype, "proto proto is correct");
   1.131 +    for (let name of protoMethods) {
   1.132 +      info("Running tests for property: " + name);
   1.133 +      ok(xrayProto.hasOwnProperty(name), "proto should have the property as own");
   1.134 +      ok(!xray.hasOwnProperty(name), "instance should not have the property as own");
   1.135 +      let method = xrayProto[name];
   1.136 +      is(typeof method, 'function', "Methods from Xrays are functions");
   1.137 +      is(global(method), window, "Methods from Xrays are local");
   1.138 +      ok(method instanceof Function, "instanceof works on methods from Xrays");
   1.139 +      is(xrayProto[name], method, "Holder caching works properly");
   1.140 +      is(xray[name], method, "Proto props resolve on the instance");
   1.141 +      let local = localProto[name];
   1.142 +      is(method.length, local.length, "Function.length identical");
   1.143 +      if (method.length == 0) {
   1.144 +        is(xray[name]() + "", local.call(xray) + "",
   1.145 +           "Xray and local method results stringify identically");
   1.146 +         is(xray[name]() + "", xray.wrappedJSObject[name]() + "",
   1.147 +            "Xray and waived method results stringify identically");
   1.148 +      }
   1.149 +    }
   1.150 +    is(Object.getOwnPropertyNames(xrayProto).sort().toSource(),
   1.151 +       protoProps.toSource(), "getOwnPropertyNames works");
   1.152 +
   1.153 +    is(xrayProto.constructor, iwin[classname], "constructor property works");
   1.154 +
   1.155 +    xrayProto.expando = 42;
   1.156 +    is(xray.expando, 42, "Xrayed instances see proto expandos");
   1.157 +    is(xray2.expando, 42, "Xrayed instances see proto expandos");
   1.158 +  }
   1.159 +
   1.160 +  function testDate() {
   1.161 +    // toGMTString is handled oddly in the engine. We don't bother to support
   1.162 +    // it over Xrays.
   1.163 +    //
   1.164 +    // We don't yet support self-hosted functions on Xrays. See bug 972987.
   1.165 +    let propsToSkip = ['toGMTString', 'toLocaleString',
   1.166 +                       'toLocaleDateString', 'toLocaleTimeString'];
   1.167 +    testXray('Date', new iwin.Date(), new iwin.Date(), propsToSkip);
   1.168 +  }
   1.169 +
   1.170 +  ]]>
   1.171 +  </script>
   1.172 +  <iframe id="ifr" onload="go();" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html" />
   1.173 +</window>

mercurial