Skip to content

Commit

Permalink
fix a Chakra-based MS Edge (18-) bug that unfreeze (O_o) frozen array…
Browse files Browse the repository at this point in the history
…s used as `WeakMap` keys
  • Loading branch information
zloirock committed Dec 27, 2022
1 parent d73e06e commit da2e4f8
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 11 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## Changelog
##### Unreleased
- Nothing
- Fixed a Chakra-based MS Edge (18-) bug that unfreeze (O_o) frozen arrays used as `WeakMap` keys
- Fixing of the previous bug also fixes some cases of `String.dedent` in MS Edge

##### [3.27.0 - 2022.12.26](https://github.com/zloirock/core-js/releases/tag/v3.27.0)
- [Iterator Helpers](https://github.com/tc39/proposal-iterator-helpers) proposal:
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 @@ -1786,7 +1786,8 @@ export const data = {
'es.weak-map': null,
'es.weak-map.constructor': {
chrome: '51',
edge: '15',
// adding frozen arrays to WeakMap unfreeze them
// edge: '15',
firefox: '53',
rhino: '1.7.13',
safari: '10.0',
Expand Down
47 changes: 43 additions & 4 deletions packages/core-js/modules/es.weak-map.constructor.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,30 @@
'use strict';
var FREEZING = require('../internals/freezing');
var global = require('../internals/global');
var uncurryThis = require('../internals/function-uncurry-this');
var defineBuiltIns = require('../internals/define-built-ins');
var InternalMetadataModule = require('../internals/internal-metadata');
var collection = require('../internals/collection');
var collectionWeak = require('../internals/collection-weak');
var isObject = require('../internals/is-object');
var isExtensible = require('../internals/object-is-extensible');
var enforceInternalState = require('../internals/internal-state').enforce;
var fails = require('../internals/fails');
var NATIVE_WEAK_MAP = require('../internals/weak-map-basic-detection');

var $Object = Object;
// eslint-disable-next-line es/no-array-isarray -- safe
var isArray = Array.isArray;
// eslint-disable-next-line es/no-object-isextensible -- safe
var isExtensible = $Object.isExtensible;
// eslint-disable-next-line es/no-object-isfrozen -- safe
var isFrozen = $Object.isFrozen;
// eslint-disable-next-line es/no-object-issealed -- safe
var isSealed = $Object.isSealed;
// eslint-disable-next-line es/no-object-freeze -- safe
var freeze = $Object.freeze;
// eslint-disable-next-line es/no-object-seal -- safe
var seal = $Object.seal;

var IS_IE11 = !global.ActiveXObject && 'ActiveXObject' in global;
var InternalWeakMap;

Expand All @@ -22,18 +37,27 @@ var wrapper = function (init) {
// `WeakMap` constructor
// https://tc39.es/ecma262/#sec-weakmap-constructor
var $WeakMap = collection('WeakMap', wrapper, collectionWeak);
var WeakMapPrototype = $WeakMap.prototype;
var nativeSet = uncurryThis(WeakMapPrototype.set);

// Chakra Edge bug: adding frozen arrays to WeakMap unfreeze them
var hasMSEdgeFreezingBug = function () {
return FREEZING && fails(function () {
var frozenArray = freeze([]);
new $WeakMap().set(frozenArray, 1);
return !isFrozen(frozenArray);
});
};

// IE11 WeakMap frozen keys fix
// We can't use feature detection because it crash some old IE builds
// https://github.com/zloirock/core-js/issues/485
if (NATIVE_WEAK_MAP && IS_IE11) {
if (NATIVE_WEAK_MAP) if (IS_IE11) {
InternalWeakMap = collectionWeak.getConstructor(wrapper, 'WeakMap', true);
InternalMetadataModule.enable();
var WeakMapPrototype = $WeakMap.prototype;
var nativeDelete = uncurryThis(WeakMapPrototype['delete']);
var nativeHas = uncurryThis(WeakMapPrototype.has);
var nativeGet = uncurryThis(WeakMapPrototype.get);
var nativeSet = uncurryThis(WeakMapPrototype.set);
defineBuiltIns(WeakMapPrototype, {
'delete': function (key) {
if (isObject(key) && !isExtensible(key)) {
Expand Down Expand Up @@ -65,4 +89,19 @@ if (NATIVE_WEAK_MAP && IS_IE11) {
return this;
}
});
// Chakra Edge frozen keys fix
} else if (hasMSEdgeFreezingBug()) {
defineBuiltIns(WeakMapPrototype, {
set: function set(key, value) {
var arrayIntegrityLevel;
if (isArray(key)) {
if (isFrozen(key)) arrayIntegrityLevel = 'frozen';
else if (isSealed(key)) arrayIntegrityLevel = 'sealed';
}
nativeSet(this, key, value);
if (arrayIntegrityLevel === 'frozen') freeze(key);
if (arrayIntegrityLevel === 'sealed') seal(key);
return this;
}
});
}
7 changes: 5 additions & 2 deletions tests/compat/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -1364,7 +1364,7 @@ GLOBAL.tests = {
return unescape;
},
'es.weak-map.constructor': [SAFE_ITERATION_CLOSING_SUPPORT, function () {
var key = Object.freeze({});
var key = Object.freeze([]);
var called = 0;
var iterable = {
next: function () {
Expand All @@ -1376,10 +1376,13 @@ GLOBAL.tests = {
};

var map = new WeakMap(iterable);
// MS IE bug
return map.get(key) == 1
&& map.get(null) == undefined
&& map.set({}, 2) == map
&& map[Symbol.toStringTag];
&& map[Symbol.toStringTag]
// MS Edge bug
&& Object.isFrozen(key);
}],
'es.weak-set.constructor': [SAFE_ITERATION_CLOSING_SUPPORT, function () {
var key = {};
Expand Down
8 changes: 6 additions & 2 deletions tests/unit-global/es.weak-map.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { DESCRIPTORS, GLOBAL, NATIVE } from '../helpers/constants';
import { DESCRIPTORS, FREEZING, GLOBAL, NATIVE } from '../helpers/constants';
import { createIterable, nativeSubclass } from '../helpers/helpers';

const Symbol = GLOBAL.Symbol || {};
const { freeze, keys, getOwnPropertyNames, getOwnPropertySymbols } = Object;
const { freeze, isFrozen, keys, getOwnPropertyNames, getOwnPropertySymbols } = Object;
const { ownKeys } = GLOBAL.Reflect || {};

QUnit.test('WeakMap', assert => {
Expand Down Expand Up @@ -163,6 +163,10 @@ QUnit.test('WeakMap#set', assert => {
weakmap.delete(object2);
assert.same(weakmap.get(object1), undefined, 'works with frozen objects #3');
assert.same(weakmap.get(object2), undefined, 'works with frozen objects #4');
const array = freeze([]);
weakmap.set(array, 42);
assert.same(weakmap.get(array), 42, 'works with frozen arrays #1');
if (FREEZING) assert.true(isFrozen(array), 'works with frozen arrays #2');
});

QUnit.test('WeakMap#@@toStringTag', assert => {
Expand Down
7 changes: 6 additions & 1 deletion tests/unit-pure/es.weak-map.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { createIterable, nativeSubclass } from '../helpers/helpers';
import { DESCRIPTORS } from '../helpers/constants';
import { DESCRIPTORS, FREEZING } from '../helpers/constants';

import getIteratorMethod from 'core-js-pure/es/get-iterator-method';
import freeze from 'core-js-pure/es/object/freeze';
import isFrozen from 'core-js-pure/es/object/is-frozen';
import getOwnPropertyNames from 'core-js-pure/es/object/get-own-property-names';
import getOwnPropertySymbols from 'core-js-pure/es/object/get-own-property-symbols';
import keys from 'core-js-pure/es/object/keys';
Expand Down Expand Up @@ -151,6 +152,10 @@ QUnit.test('WeakMap#set', assert => {
weakmap.delete(object2);
assert.same(weakmap.get(object1), undefined, 'works with frozen objects #3');
assert.same(weakmap.get(object2), undefined, 'works with frozen objects #4');
const array = freeze([]);
weakmap.set(array, 42);
assert.same(weakmap.get(array), 42, 'works with frozen arrays #1');
if (FREEZING) assert.true(isFrozen(array), 'works with frozen arrays #2');
});

QUnit.test('WeakMap#@@toStringTag', assert => {
Expand Down

0 comments on commit da2e4f8

Please sign in to comment.