summaryrefslogtreecommitdiffstats
path: root/js/src/tests/ecma_5/RegExp/instance-property-storage-introspection.js
blob: 1f7c7042f03b49043c981ca1bd7a07a454c71382 (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
129
130
131
/*
 * 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: "RegExp.prototype",
                 get: function() { return RegExp.prototype; } },
               { 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(RegExp.prototype, "RegExp.prototype", 0);
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!");