summaryrefslogtreecommitdiffstats
path: root/js/src/tests/ecma_5/RegExp/instance-property-storage-introspection.js
blob: 998d25e2c0b0461b8ee5153019f8feae4d15dee8 (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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
 * Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/licenses/publicdomain/
 */

var BUGNUMBER = 640072;
var summary =
  "Represent /a/.{lastIndex,global,source,multiline,sticky,ignoreCase} with " +
  "plain old data properties";

print(BUGNUMBER + ": " + summary);

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

function checkDataProperty(obj, p, expect, msg)
{
  var d = Object.getOwnPropertyDescriptor(obj, p);

  assertEq(d.value, expect.value, msg + ": bad value for " + p);
  assertEq(d.writable, expect.writable, msg + ": bad writable for " + p);
  assertEq(d.enumerable, expect.enumerable, msg + ": bad enumerable for " + p);
  assertEq(d.configurable, expect.configurable, msg + ": bad configurable for " + p);

  // Try redefining the property using its initial values: these should all be
  // silent no-ops.
  Object.defineProperty(obj, p, { value: expect.value });
  Object.defineProperty(obj, p, { writable: expect.writable });
  Object.defineProperty(obj, p, { enumerable: expect.enumerable });
  Object.defineProperty(obj, p, { configurable: expect.configurable });

  var d2 = Object.getOwnPropertyDescriptor(obj, p);
  assertEq(d.value, d2.value, msg + ": value changed on redefinition of " + p + "?");
  assertEq(d.writable, d2.writable, msg + ": writable changed on redefinition of " + p + "?");
  assertEq(d.enumerable, d2.enumerable, msg + ": enumerable changed on redefinition of " + p + "?");
  assertEq(d.configurable, d2.configurable, msg + ": configurable changed on redefinition of " + p + "?");
}


// Check a bunch of "empty" regular expressions first.

var choices = [{ msg: "new RegExp()",
                 get: function() { return new RegExp(); } },
               { msg: "/(?:)/",
                 get: Function("return /(?:)/;") }];

function checkRegExp(r, msg, lastIndex)
{
  var expect;

  expect = { value: lastIndex, enumerable: false, configurable: false, writable: true };
  checkDataProperty(r, "lastIndex", expect, msg);
}

checkRegExp(new RegExp(), "new RegExp()", 0);
checkRegExp(/(?:)/, "/(?:)/", 0);
checkRegExp(Function("return /(?:)/;")(), 'Function("return /(?:)/;")()', 0);

for (var i = 0; i < choices.length; i++)
{
  var choice = choices[i];
  var msg = choice.msg;
  var r = choice.get();

  checkRegExp(r, msg, 0);
}

// Now test less generic regular expressions

checkRegExp(/a/gim, "/a/gim", 0);

var r;

do
{
  r = /abcd/mg;
  checkRegExp(r, "/abcd/mg initially", 0);
  r.exec("abcdefg");
  checkRegExp(r, "/abcd/mg step 1", 4);
  r.exec("abcdabcd");
  checkRegExp(r, "/abcd/mg step 2", 8);
  r.exec("abcdabcd");
  checkRegExp(r, "/abcd/mg end", 0);

  r = /cde/ig;
  checkRegExp(r, "/cde/ig initially", 0);
  var obj = r.lastIndex = { valueOf: function() { return 2; } };
  checkRegExp(r, "/cde/ig after lastIndex", obj);
  r.exec("aaacdef");
  checkRegExp(r, "/cde/ig after exec", 6);
  Object.defineProperty(r, "lastIndex", { value: 3 });
  checkRegExp(r, "/cde/ig after define 3", 3);
  Object.defineProperty(r, "lastIndex", { value: obj });
  checkRegExp(r, "/cde/ig after lastIndex", obj);


  // Tricky bits of testing: make sure that redefining lastIndex doesn't change
  // the slot where the lastIndex property is initially stored, even if
  // the redefinition also changes writability.
  r = /a/g;
  checkRegExp(r, "/a/g initially", 0);
  Object.defineProperty(r, "lastIndex", { value: 2 });
  r.exec("aabbbba");
  checkRegExp(r, "/a/g after first exec", 7);
  assertEq(r.lastIndex, 7);
  r.lastIndex = 2;
  checkRegExp(r, "/a/g after assign", 2);
  r.exec("aabbbba");
  assertEq(r.lastIndex, 7); // check in reverse order
  checkRegExp(r, "/a/g after second exec", 7);

  r = /c/g;
  r.lastIndex = 2;
  checkRegExp(r, "/c/g initially", 2);
  Object.defineProperty(r, "lastIndex", { writable: false });
  assertEq(Object.getOwnPropertyDescriptor(r, "lastIndex").writable, false);
  try { r.exec("aabbbba"); } catch (e) { /* swallow error if thrown */ }
  assertEq(Object.getOwnPropertyDescriptor(r, "lastIndex").writable, false);
}
while (Math.random() > 17); // fake loop to discourage RegExp object caching

/******************************************************************************/

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

print("All tests passed!");