11cb0ef41Sopenharmony_ci// Flags: --expose-internals
21cb0ef41Sopenharmony_ci'use strict';
31cb0ef41Sopenharmony_ci
41cb0ef41Sopenharmony_ciconst { mustNotCall } = require('../common');
51cb0ef41Sopenharmony_ciconst assert = require('assert');
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ciconst {
81cb0ef41Sopenharmony_ci  RegExpPrototypeExec,
91cb0ef41Sopenharmony_ci  RegExpPrototypeSymbolReplace,
101cb0ef41Sopenharmony_ci  RegExpPrototypeSymbolSearch,
111cb0ef41Sopenharmony_ci  RegExpPrototypeSymbolSplit,
121cb0ef41Sopenharmony_ci  SafeStringPrototypeSearch,
131cb0ef41Sopenharmony_ci  hardenRegExp,
141cb0ef41Sopenharmony_ci} = require('internal/test/binding').primordials;
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ciconst {
171cb0ef41Sopenharmony_ci  SideEffectFreeRegExpPrototypeExec,
181cb0ef41Sopenharmony_ci  SideEffectFreeRegExpPrototypeSymbolReplace,
191cb0ef41Sopenharmony_ci  SideEffectFreeRegExpPrototypeSymbolSplit,
201cb0ef41Sopenharmony_ci} = require('internal/util');
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_ciObject.defineProperties(RegExp.prototype, {
241cb0ef41Sopenharmony_ci  [Symbol.match]: {
251cb0ef41Sopenharmony_ci    get: mustNotCall('get %RegExp.prototype%[@@match]'),
261cb0ef41Sopenharmony_ci    set: mustNotCall('set %RegExp.prototype%[@@match]'),
271cb0ef41Sopenharmony_ci  },
281cb0ef41Sopenharmony_ci  [Symbol.matchAll]: {
291cb0ef41Sopenharmony_ci    get: mustNotCall('get %RegExp.prototype%[@@matchAll]'),
301cb0ef41Sopenharmony_ci    set: mustNotCall('set %RegExp.prototype%[@@matchAll]'),
311cb0ef41Sopenharmony_ci  },
321cb0ef41Sopenharmony_ci  [Symbol.replace]: {
331cb0ef41Sopenharmony_ci    get: mustNotCall('get %RegExp.prototype%[@@replace]'),
341cb0ef41Sopenharmony_ci    set: mustNotCall('set %RegExp.prototype%[@@replace]'),
351cb0ef41Sopenharmony_ci  },
361cb0ef41Sopenharmony_ci  [Symbol.search]: {
371cb0ef41Sopenharmony_ci    get: mustNotCall('get %RegExp.prototype%[@@search]'),
381cb0ef41Sopenharmony_ci    set: mustNotCall('set %RegExp.prototype%[@@search]'),
391cb0ef41Sopenharmony_ci  },
401cb0ef41Sopenharmony_ci  [Symbol.split]: {
411cb0ef41Sopenharmony_ci    get: mustNotCall('get %RegExp.prototype%[@@split]'),
421cb0ef41Sopenharmony_ci    set: mustNotCall('set %RegExp.prototype%[@@split]'),
431cb0ef41Sopenharmony_ci  },
441cb0ef41Sopenharmony_ci  dotAll: {
451cb0ef41Sopenharmony_ci    get: mustNotCall('get %RegExp.prototype%.dotAll'),
461cb0ef41Sopenharmony_ci    set: mustNotCall('set %RegExp.prototype%.dotAll'),
471cb0ef41Sopenharmony_ci  },
481cb0ef41Sopenharmony_ci  exec: {
491cb0ef41Sopenharmony_ci    get: mustNotCall('get %RegExp.prototype%.exec'),
501cb0ef41Sopenharmony_ci    set: mustNotCall('set %RegExp.prototype%.exec'),
511cb0ef41Sopenharmony_ci  },
521cb0ef41Sopenharmony_ci  flags: {
531cb0ef41Sopenharmony_ci    get: mustNotCall('get %RegExp.prototype%.flags'),
541cb0ef41Sopenharmony_ci    set: mustNotCall('set %RegExp.prototype%.flags'),
551cb0ef41Sopenharmony_ci  },
561cb0ef41Sopenharmony_ci  global: {
571cb0ef41Sopenharmony_ci    get: mustNotCall('get %RegExp.prototype%.global'),
581cb0ef41Sopenharmony_ci    set: mustNotCall('set %RegExp.prototype%.global'),
591cb0ef41Sopenharmony_ci  },
601cb0ef41Sopenharmony_ci  hasIndices: {
611cb0ef41Sopenharmony_ci    get: mustNotCall('get %RegExp.prototype%.hasIndices'),
621cb0ef41Sopenharmony_ci    set: mustNotCall('set %RegExp.prototype%.hasIndices'),
631cb0ef41Sopenharmony_ci  },
641cb0ef41Sopenharmony_ci  ignoreCase: {
651cb0ef41Sopenharmony_ci    get: mustNotCall('get %RegExp.prototype%.ignoreCase'),
661cb0ef41Sopenharmony_ci    set: mustNotCall('set %RegExp.prototype%.ignoreCase'),
671cb0ef41Sopenharmony_ci  },
681cb0ef41Sopenharmony_ci  multiline: {
691cb0ef41Sopenharmony_ci    get: mustNotCall('get %RegExp.prototype%.multiline'),
701cb0ef41Sopenharmony_ci    set: mustNotCall('set %RegExp.prototype%.multiline'),
711cb0ef41Sopenharmony_ci  },
721cb0ef41Sopenharmony_ci  source: {
731cb0ef41Sopenharmony_ci    get: mustNotCall('get %RegExp.prototype%.source'),
741cb0ef41Sopenharmony_ci    set: mustNotCall('set %RegExp.prototype%.source'),
751cb0ef41Sopenharmony_ci  },
761cb0ef41Sopenharmony_ci  sticky: {
771cb0ef41Sopenharmony_ci    get: mustNotCall('get %RegExp.prototype%.sticky'),
781cb0ef41Sopenharmony_ci    set: mustNotCall('set %RegExp.prototype%.sticky'),
791cb0ef41Sopenharmony_ci  },
801cb0ef41Sopenharmony_ci  test: {
811cb0ef41Sopenharmony_ci    get: mustNotCall('get %RegExp.prototype%.test'),
821cb0ef41Sopenharmony_ci    set: mustNotCall('set %RegExp.prototype%.test'),
831cb0ef41Sopenharmony_ci  },
841cb0ef41Sopenharmony_ci  toString: {
851cb0ef41Sopenharmony_ci    get: mustNotCall('get %RegExp.prototype%.toString'),
861cb0ef41Sopenharmony_ci    set: mustNotCall('set %RegExp.prototype%.toString'),
871cb0ef41Sopenharmony_ci  },
881cb0ef41Sopenharmony_ci  unicode: {
891cb0ef41Sopenharmony_ci    get: mustNotCall('get %RegExp.prototype%.unicode'),
901cb0ef41Sopenharmony_ci    set: mustNotCall('set %RegExp.prototype%.unicode'),
911cb0ef41Sopenharmony_ci  },
921cb0ef41Sopenharmony_ci});
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_cihardenRegExp(hardenRegExp(/1/));
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci// IMO there are no valid use cases in node core to use RegExpPrototypeSymbolMatch
971cb0ef41Sopenharmony_ci// or RegExpPrototypeSymbolMatchAll, they are inherently unsafe.
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ciassert.strictEqual(RegExpPrototypeExec(/foo/, 'bar'), null);
1001cb0ef41Sopenharmony_ciassert.strictEqual(RegExpPrototypeExec(hardenRegExp(/foo/), 'bar'), null);
1011cb0ef41Sopenharmony_ciassert.strictEqual(SideEffectFreeRegExpPrototypeExec(/foo/, 'bar'), null);
1021cb0ef41Sopenharmony_ciassert.strictEqual(SideEffectFreeRegExpPrototypeExec(hardenRegExp(/foo/), 'bar'), null);
1031cb0ef41Sopenharmony_ci{
1041cb0ef41Sopenharmony_ci  const expected = ['bar'];
1051cb0ef41Sopenharmony_ci  Object.defineProperties(expected, {
1061cb0ef41Sopenharmony_ci    index: { __proto__: null, configurable: true, writable: true, enumerable: true, value: 0 },
1071cb0ef41Sopenharmony_ci    input: { __proto__: null, configurable: true, writable: true, enumerable: true, value: 'bar' },
1081cb0ef41Sopenharmony_ci    groups: { __proto__: null, configurable: true, writable: true, enumerable: true },
1091cb0ef41Sopenharmony_ci  });
1101cb0ef41Sopenharmony_ci  const actual = SideEffectFreeRegExpPrototypeExec(/bar/, 'bar');
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci  // assert.deepStrictEqual(actual, expected) doesn't work for cross-realm comparison.
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ci  assert.strictEqual(Array.isArray(actual), Array.isArray(expected));
1151cb0ef41Sopenharmony_ci  assert.deepStrictEqual(Reflect.ownKeys(actual), Reflect.ownKeys(expected));
1161cb0ef41Sopenharmony_ci  for (const key of Reflect.ownKeys(expected)) {
1171cb0ef41Sopenharmony_ci    assert.deepStrictEqual(
1181cb0ef41Sopenharmony_ci      Reflect.getOwnPropertyDescriptor(actual, key),
1191cb0ef41Sopenharmony_ci      Reflect.getOwnPropertyDescriptor(expected, key),
1201cb0ef41Sopenharmony_ci    );
1211cb0ef41Sopenharmony_ci  }
1221cb0ef41Sopenharmony_ci}
1231cb0ef41Sopenharmony_ci{
1241cb0ef41Sopenharmony_ci  const myRegex = hardenRegExp(/a/);
1251cb0ef41Sopenharmony_ci  assert.strictEqual(RegExpPrototypeSymbolReplace(myRegex, 'baar', 'e'), 'bear');
1261cb0ef41Sopenharmony_ci}
1271cb0ef41Sopenharmony_ci{
1281cb0ef41Sopenharmony_ci  const myRegex = /a/;
1291cb0ef41Sopenharmony_ci  assert.strictEqual(SideEffectFreeRegExpPrototypeSymbolReplace(myRegex, 'baar', 'e'), 'bear');
1301cb0ef41Sopenharmony_ci}
1311cb0ef41Sopenharmony_ci{
1321cb0ef41Sopenharmony_ci  const myRegex = hardenRegExp(/a/g);
1331cb0ef41Sopenharmony_ci  assert.strictEqual(RegExpPrototypeSymbolReplace(myRegex, 'baar', 'e'), 'beer');
1341cb0ef41Sopenharmony_ci}
1351cb0ef41Sopenharmony_ci{
1361cb0ef41Sopenharmony_ci  const myRegex = /a/g;
1371cb0ef41Sopenharmony_ci  assert.strictEqual(SideEffectFreeRegExpPrototypeSymbolReplace(myRegex, 'baar', 'e'), 'beer');
1381cb0ef41Sopenharmony_ci}
1391cb0ef41Sopenharmony_ci{
1401cb0ef41Sopenharmony_ci  const myRegex = hardenRegExp(/a/);
1411cb0ef41Sopenharmony_ci  assert.strictEqual(RegExpPrototypeSymbolSearch(myRegex, 'baar'), 1);
1421cb0ef41Sopenharmony_ci}
1431cb0ef41Sopenharmony_ci{
1441cb0ef41Sopenharmony_ci  const myRegex = /a/;
1451cb0ef41Sopenharmony_ci  assert.strictEqual(SafeStringPrototypeSearch('baar', myRegex), 1);
1461cb0ef41Sopenharmony_ci}
1471cb0ef41Sopenharmony_ci{
1481cb0ef41Sopenharmony_ci  const myRegex = hardenRegExp(/a/);
1491cb0ef41Sopenharmony_ci  assert.deepStrictEqual(RegExpPrototypeSymbolSplit(myRegex, 'baar', 0), []);
1501cb0ef41Sopenharmony_ci}
1511cb0ef41Sopenharmony_ci{
1521cb0ef41Sopenharmony_ci  const myRegex = /a/;
1531cb0ef41Sopenharmony_ci  const expected = [];
1541cb0ef41Sopenharmony_ci  const actual = SideEffectFreeRegExpPrototypeSymbolSplit(myRegex, 'baar', 0);
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_ci  // assert.deepStrictEqual(actual, expected) doesn't work for cross-realm comparison.
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ci  assert.strictEqual(Array.isArray(actual), Array.isArray(expected));
1591cb0ef41Sopenharmony_ci  assert.deepStrictEqual(Reflect.ownKeys(actual), Reflect.ownKeys(expected));
1601cb0ef41Sopenharmony_ci  for (const key of Reflect.ownKeys(expected)) {
1611cb0ef41Sopenharmony_ci    assert.deepStrictEqual(
1621cb0ef41Sopenharmony_ci      Reflect.getOwnPropertyDescriptor(actual, key),
1631cb0ef41Sopenharmony_ci      Reflect.getOwnPropertyDescriptor(expected, key),
1641cb0ef41Sopenharmony_ci    );
1651cb0ef41Sopenharmony_ci  }
1661cb0ef41Sopenharmony_ci}
1671cb0ef41Sopenharmony_ci{
1681cb0ef41Sopenharmony_ci  const myRegex = hardenRegExp(/a/);
1691cb0ef41Sopenharmony_ci  assert.deepStrictEqual(RegExpPrototypeSymbolSplit(myRegex, 'baar', 1), ['b']);
1701cb0ef41Sopenharmony_ci}
1711cb0ef41Sopenharmony_ci{
1721cb0ef41Sopenharmony_ci  const myRegex = hardenRegExp(/a/);
1731cb0ef41Sopenharmony_ci  assert.deepStrictEqual(RegExpPrototypeSymbolSplit(myRegex, 'baar'), ['b', '', 'r']);
1741cb0ef41Sopenharmony_ci}
175