js/src/tests/js1_8_5/extensions/clone-object.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 // |reftest| skip-if(!xulRuntime.shell)
     2 // -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     3 // Any copyright is dedicated to the Public Domain.
     4 // http://creativecommons.org/licenses/publicdomain/
     6 // Assert that cloning b does the right thing as far as we can tell.
     7 // Caveat: getters in b must produce the same value each time they're
     8 // called. We may call them several times.
     9 //
    10 // If desc is provided, then the very first thing we do to b is clone it.
    11 // (The self-modifying object test counts on this.)
    12 //
    13 function check(b, desc) {
    14     function classOf(obj) {
    15         return Object.prototype.toString.call(obj);
    16     }
    18     function ownProperties(obj) {
    19         return Object.getOwnPropertyNames(obj).
    20             map(function (p) { return [p, Object.getOwnPropertyDescriptor(obj, p)]; });
    21     }
    23     function isCloneable(pair) {
    24         return typeof pair[0] === 'string' && pair[1].enumerable;
    25     }
    27     function notIndex(p) {
    28         var u = p >>> 0;
    29         return !("" + u == p && u != 0xffffffff);
    30     }
    32     function assertIsCloneOf(a, b, path) {
    33         assertEq(a === b, false);
    35         var ca = classOf(a);
    36         assertEq(ca, classOf(b), path);
    38         assertEq(Object.getPrototypeOf(a),
    39                  ca == "[object Object]" ? Object.prototype : Array.prototype,
    40                  path);
    42         // 'b', the original object, may have non-enumerable or XMLName
    43         // properties; ignore them.  'a', the clone, should not have any
    44         // non-enumerable properties (except .length, if it's an Array) or
    45         // XMLName properties.
    46         var pb = ownProperties(b).filter(isCloneable);
    47         var pa = ownProperties(a);
    48         for (var i = 0; i < pa.length; i++) {
    49             assertEq(typeof pa[i][0], "string", "clone should not have E4X properties " + path);
    50             if (!pa[i][1].enumerable) {
    51                 if (Array.isArray(a) && pa[i][0] == "length") {
    52                     // remove it so that the comparisons below will work
    53                     pa.splice(i, 1);
    54                     i--;
    55                 } else {
    56                     throw new Error("non-enumerable clone property " + uneval(pa[i][0]) + " " + path);
    57                 }
    58             }
    59         }
    61         // Check that, apart from properties whose names are array indexes, 
    62         // the enumerable properties appear in the same order.
    63         var aNames = pa.map(function (pair) { return pair[1]; }).filter(notIndex);
    64         var bNames = pa.map(function (pair) { return pair[1]; }).filter(notIndex);
    65         assertEq(aNames.join(","), bNames.join(","), path);
    67         // Check that the lists are the same when including array indexes.
    68         function byName(a, b) { a = a[0]; b = b[0]; return a < b ? -1 : a === b ? 0 : 1; }
    69         pa.sort(byName);
    70         pb.sort(byName);
    71         assertEq(pa.length, pb.length, "should see the same number of properties " + path);
    72         for (var i = 0; i < pa.length; i++) {
    73             var aName = pa[i][0];
    74             var bName = pb[i][0];
    75             assertEq(aName, bName, path);
    77             var path2 = path + "." + aName;
    78             var da = pa[i][1];
    79             var db = pb[i][1];
    80             assertEq(da.configurable, true, path2);
    81             assertEq(da.writable, true, path2);
    82             assertEq("value" in da, true, path2);
    83             var va = da.value;
    84             var vb = b[pb[i][0]];
    85             if (typeof va === "object" && va !== null)
    86                 queue.push([va, vb, path2]);
    87             else
    88                 assertEq(va, vb, path2);
    89         }
    90     }
    92     var banner = "while testing clone of " + (desc || uneval(b));
    93     var a = deserialize(serialize(b));
    94     var queue = [[a, b, banner]];
    95     while (queue.length) {
    96         var triple = queue.shift();
    97         assertIsCloneOf(triple[0], triple[1], triple[2]);
    98     }
   100     return a; // for further testing
   101 }
   103 function test() {
   104     check({});
   105     check([]);
   106     check({x: 0});
   107     check({x: 0.7, p: "forty-two", y: null, z: undefined});
   108     check(Array.prototype);
   109     check(Object.prototype);
   111     // before and after
   112     var b, a;
   114     // Slow array.
   115     b = [, 1, 2, 3];
   116     b.expando = true;
   117     b[5] = 5;
   118     b[0] = 0;
   119     b[4] = 4;
   120     delete b[2];
   121     check(b);
   123     // Check cloning properties other than basic data properties. (check()
   124     // asserts that the properties of the clone are configurable, writable,
   125     // enumerable data properties.)
   126     b = {};
   127     Object.defineProperties(b, {
   128         x: {enumerable: true, get: function () { return 12479; }},
   129         y: {enumerable: true, configurable: true, writable: false, value: 0},
   130         z: {enumerable: true, configurable: false, writable: true, value: 0},
   131         hidden: {enumerable:false, value: 1334}});
   132     check(b);
   134     // Check corner cases involving property names.
   135     b = {"-1": -1,
   136          0xffffffff: null,
   137          0x100000000: null,
   138          "": 0,
   139          "\xff\x7f\u7fff\uffff\ufeff\ufffe": 1, // random unicode id
   140          "\ud800 \udbff \udc00 \udfff": 2}; // busted surrogate pairs
   141     check(b);
   143     b = [];
   144     b[-1] = -1;
   145     b[0xffffffff] = null;
   146     b[0x100000000] = null;
   147     b[""] = 0;
   148     b["\xff\x7f\u7fff\uffff\ufeff\ufffe"] = 1;
   149     b["\ud800 \udbff \udc00 \udfff"] = 2;
   150     check(b);
   152     // An array's .length property is not enumerable, so it is not cloned.
   153     b = Array(5);
   154     assertEq(b.length, 5);
   155     a = check(b);
   156     assertEq(a.length, 0);
   158     b[1] = "ok";
   159     a = check(b);
   160     assertEq(a.length, 2);
   162     // Check that prototypes are not cloned, per spec.
   163     b = Object.create({x:1});
   164     b.y = 2;
   165     b.z = 3;
   166     check(b);
   168     // Check that cloning does not separate merge points in the tree.
   169     var same = {};
   170     b = {one: same, two: same};
   171     a = check(b);
   172     assertEq(a.one === a.two, true);
   174     b = [same, same];
   175     a = check(b);
   176     assertEq(a[0] === a[1], true);
   178     // Try cloning a deep object. Don't fail with "too much recursion".
   179     b = {};
   180     var current = b;
   181     for (var i = 0; i < 10000; i++) {
   182         var next = {};
   183         current['x' + i] = next;
   184         current = next;
   185     }
   186     check(b, "deepObject");  // takes 2 seconds :-\
   188     /*
   189       XXX TODO spin this out into its own test
   190     // This fails quickly with an OOM error. An exception would be nicer.
   191     function Infinitree() {
   192         return { get left() { return new Infinitree; },
   193                  get right() { return new Infinitree; }};
   194     }
   195     var threw = false;
   196     try {
   197         serialize(new Infinitree);
   198     } catch (exc) {
   199         threw = true;
   200     }
   201     assertEq(threw, true);
   202     */
   204     // Clone an array with holes.
   205     check([0, 1, 2, , 4, 5, 6]);
   207     // Array holes should not take up space.
   208     b = [];
   209     b[255] = 1;
   210     check(b);
   211     assertEq(serialize(b).clonebuffer.length < 255, true);
   213     // Self-modifying object.
   214     // This should never read through to b's prototype.
   215     b = Object.create({y: 2}, 
   216                       {x: {enumerable: true,
   217                            configurable: true,
   218                            get: function() { if (this.hasOwnProperty("y")) delete this.y; return 1; }},
   219                        y: {enumerable: true,
   220                            configurable: true,
   221                            writable: true,
   222                            value: 3}});
   223     check(b, "selfModifyingObject");
   225     // Ignore properties with object-ids.
   226     var uri = "http://example.net";
   227     b = {x: 1, y: 2};
   228     Object.defineProperty(b, Array(uri, "x"), {enumerable: true, value: 3});
   229     Object.defineProperty(b, Array(uri, "y"), {enumerable: true, value: 5});
   230     check(b);
   231 }
   233 test();
   234 reportCompare(0, 0, 'ok');

mercurial