summaryrefslogtreecommitdiffstats
path: root/js/src/tests/non262/extensions/mutable-proto-special-form.js
blob: b196507f25990d1f5009b86bf8b4b81d845a63c3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/licenses/publicdomain/

//-----------------------------------------------------------------------------
var BUGNUMBER = 948583;
var summary =
  "Make __proto__ in object literals a special form not influenced by " +
  "|Object.prototype|";

print(BUGNUMBER + ": " + summary);

/**************
 * BEGIN TEST *
 **************/

var passed = true;

function performProtoTests(msg)
{
  print("Testing " + msg);
  assertEq(passed, true, "passed wrong at start of test set");

  assertEq(Object.getPrototypeOf({ __proto__: null }), null);
  assertEq(Object.getPrototypeOf({ __proto__: undefined }), Object.prototype);
  assertEq(Object.getPrototypeOf({ __proto__: 17 }), Object.prototype);

  var obj = {};
  assertEq(Object.getPrototypeOf({ __proto__: obj }), obj);

  assertEq(passed, true, "passed wrong at end of test set");
  print("Tests of " + msg + " passed!");
}

function poisonProto(obj)
{
  Object.defineProperty(obj, "__proto__",
                        {
                          configurable: true,
                          enumerable: true,
                          set: function(v) { passed = false; },
                        });
}

performProtoTests("initial behavior");

var desc = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__");
var setProto = desc.set;
delete Object.prototype.__proto__;

performProtoTests("behavior after Object.prototype.__proto__ deletion");

Object.defineProperty(Object.prototype, "__proto__",
                      {
                        configurable: true,
                        enumerable: false,
                        set: function(v) { passed = false; },
                      });

performProtoTests("behavior after making Object.prototype.__proto__ a " +
                  "custom setter");

Object.defineProperty(Object.prototype, "__proto__", { set: undefined });

performProtoTests("behavior after making Object.prototype.__proto__'s " +
                  "[[Set]] === undefined");

try
{
  var superProto = Object.create(null);
  poisonProto(superProto);
  setProto.call(Object.prototype, superProto);

  performProtoTests("behavior after mutating Object.prototype.[[Prototype]]");

  // Note: The handler below will have to be updated to exempt a scriptable
  //       getPrototypeOf trap (to instead consult the target whose [[Prototype]]
  //       is safely non-recursive), if we ever implement one.
  var death = new Proxy(Object.create(null),
                        new Proxy({}, { get: function() { passed = false; } }));

  setProto.call(Object.prototype, death);

  performProtoTests("behavior after making Object.prototype.[[Prototype]] a " +
                    "proxy that throws for any access");
}
catch (e) {}

if (typeof reportCompare === "function")
  reportCompare(true, true);

print("Tests complete");