Skip to content

Commit

Permalink
fix a bug in the order of getting flags in RegExp.prototype.flags i…
Browse files Browse the repository at this point in the history
…n the actual version of V8
  • Loading branch information
zloirock committed Jun 4, 2022
1 parent c969457 commit 9017066
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## Changelog
##### Unreleased
- Fixed a bug in the order of getting flags in `RegExp.prototype.flags` in the actual version of V8
- Fixed property descriptors of some `Math` and `Number` constants
- Added NodeJS 18.3 compat data mapping
- Updated Electron 20.0 compat data mapping
Expand Down
3 changes: 2 additions & 1 deletion packages/core-js-compat/src/data.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1063,7 +1063,8 @@ export const data = {
safari: '11.1',
},
'es.regexp.flags': {
chrome: '62',
// modern V8 has a bug with the order getting of flags
// chrome: '62',
firefox: '78',
safari: '11.1',
},
Expand Down
39 changes: 38 additions & 1 deletion packages/core-js/modules/es.regexp.flags.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,50 @@
var global = require('../internals/global');
var DESCRIPTORS = require('../internals/descriptors');
var defineBuiltInAccessor = require('../internals/define-built-in-accessor');
var regExpFlags = require('../internals/regexp-flags');
var fails = require('../internals/fails');

// babel-minify and Closure Compiler transpiles RegExp('.', 'd') -> /./d and it causes SyntaxError
var RegExp = global.RegExp;
var RegExpPrototype = RegExp.prototype;

var FORCED = DESCRIPTORS && fails(function () {
var INDICES_SUPPORT = true;
try {
RegExp('.', 'd');
} catch (error) {
INDICES_SUPPORT = false;
}

var O = {};
// modern V8 bug
var calls = '';
var expected = INDICES_SUPPORT ? 'dgimsy' : 'gimsy';

var addGetter = function (key, chr) {
// eslint-disable-next-line es-x/no-object-defineproperty -- safe
Object.defineProperty(O, key, { get: function () {
calls += chr;
return true;
} });
};

var pairs = {
dotAll: 's',
global: 'g',
ignoreCase: 'i',
multiline: 'm',
sticky: 'y'
};

if (INDICES_SUPPORT) pairs.hasIndices = 'd';

for (var key in pairs) addGetter(key, pairs[key]);

// eslint-disable-next-line es-x/no-object-getownpropertydescriptor -- safe
return Object.getOwnPropertyDescriptor(RegExpPrototype, 'flags').get.call({ dotAll: true, sticky: true }) !== 'sy';
var result = Object.getOwnPropertyDescriptor(RegExpPrototype, 'flags').get.call(O);

return result !== expected || calls !== expected;
});

// `RegExp.prototype.flags` getter
Expand Down
35 changes: 34 additions & 1 deletion tests/compat/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -951,7 +951,40 @@ GLOBAL.tests = {
&& RegExp('.', 's').exec('\n');
}],
'es.regexp.flags': function () {
return Object.getOwnPropertyDescriptor(RegExp.prototype, 'flags').get.call({ dotAll: true, sticky: true }) === 'sy';
var INDICES_SUPPORT = true;
try {
RegExp('.', 'd');
} catch (error) {
INDICES_SUPPORT = false;
}

var O = {};
// modern V8 bug
var calls = '';
var expected = INDICES_SUPPORT ? 'dgimsy' : 'gimsy';

var addGetter = function (key, chr) {
Object.defineProperty(O, key, { get: function () {
calls += chr;
return true;
} });
};

var pairs = {
dotAll: 's',
global: 'g',
ignoreCase: 'i',
multiline: 'm',
sticky: 'y'
};

if (INDICES_SUPPORT) pairs.hasIndices = 'd';

for (var key in pairs) addGetter(key, pairs[key]);

var result = Object.getOwnPropertyDescriptor(RegExp.prototype, 'flags').get.call(O);

return result === expected && calls === expected;
},
'es.regexp.sticky': function () {
return new RegExp('a', 'y').sticky === true;
Expand Down
36 changes: 36 additions & 0 deletions tests/tests/es.regexp.flags.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,41 @@ if (DESCRIPTORS) {
assert.same(/./gmi.flags, 'gim', '/./gmi.flags is "gim"');
assert.same(/./mig.flags, 'gim', '/./mig.flags is "gim"');
assert.same(/./mgi.flags, 'gim', '/./mgi.flags is "gim"');

let INDICES_SUPPORT = true;
try {
RegExp('.', 'd');
} catch (error) {
INDICES_SUPPORT = false;
}

const O = {};
// modern V8 bug
let calls = '';
const expected = INDICES_SUPPORT ? 'dgimsy' : 'gimsy';

function addGetter(key, chr) {
Object.defineProperty(O, key, { get() {
calls += chr;
return true;
} });
}

const pairs = {
dotAll: 's',
global: 'g',
ignoreCase: 'i',
multiline: 'm',
sticky: 'y',
};

if (INDICES_SUPPORT) pairs.hasIndices = 'd';

for (const key in pairs) addGetter(key, pairs[key]);

const result = Object.getOwnPropertyDescriptor(RegExp.prototype, 'flags').get.call(O);

assert.same(result, expected, 'proper order, result');
assert.same(calls, expected, 'proper order, calls');
});
}

0 comments on commit 9017066

Please sign in to comment.