Skip to content

Commit ea7645f

Browse files
committed
add Object.prototype.__proto__ polyfill
1 parent 9e70176 commit ea7645f

File tree

15 files changed

+92
-11
lines changed

15 files changed

+92
-11
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
## Changelog
22
##### Unreleased
3+
- Added `Object.prototype.__proto__` polyfill
4+
- Only for modern engines where this feature is missed (like Deno), it's not installed in IE10- since here we have no proper way setting of the prototype
5+
- Without fixes of early implementations where it's not an accessor since those fixes are impossible
6+
- Only for the global version
37
- Considering `document.all` as an object in some missed cases, see [ECMAScript Annex B 3.6](https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot)
48
- Avoiding unnecessary promise creation and validation result in `%WrapForValid(Async)IteratorPrototype%.return`, [proposal-iterator-helpers/215](https://github.com/tc39/proposal-iterator-helpers/pull/215)
59
- Fixed omitting the result of proxing `.return` in `%IteratorHelperPrototype%.return`, [#1116](https://github.com/zloirock/core-js/issues/1116)

README.md

+3-4
Original file line numberDiff line numberDiff line change
@@ -438,18 +438,16 @@ core-js(-pure)
438438
core-js(-pure)/es
439439
```
440440
#### ECMAScript: Object[](#index)
441-
Modules [`es.object.assign`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.assign.js), [`es.object.is`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.is.js), [`es.object.set-prototype-of`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.set-prototype-of.js), [`es.object.to-string`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.to-string.js), [`es.object.freeze`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.freeze.js), [`es.object.seal`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.seal.js), [`es.object.prevent-extensions`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.prevent-extensions.js), [`es.object.is-frozen`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.is-frozen.js), [`es.object.is-sealed`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.is-sealed.js), [`es.object.is-extensible`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.is-extensible.js), [`es.object.get-own-property-descriptor`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.get-own-property-descriptor.js), [`es.object.get-own-property-descriptors`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.get-own-property-descriptors.js), [`es.object.get-prototype-of`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.get-prototype-of.js), [`es.object.keys`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.keys.js), [`es.object.values`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.values.js), [`es.object.entries`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.entries.js), [`es.object.get-own-property-names`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.get-own-property-names.js), [`es.object.from-entries`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.from-entries.js), [`es.object.has-own`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.has-own.js).
441+
Modules [`es.object.assign`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.assign.js), [`es.object.create`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.create.js), [`es.object.define-getter`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.define-getter.js), [`es.object.define-property`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.define-property.js), [`es.object.define-properties`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.es.object.define-properties.js), [`es.object.define-setter`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.define-setter.js), [`es.object.entries`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.entries.js), [`es.object.freeze`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.freeze.js), [`es.object.from-entries`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.from-entries.js), [`es.object.get-own-property-descriptor`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.get-own-property-descriptor.js), [`es.object.get-own-property-descriptors`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.get-own-property-descriptors.js), [`es.object.get-own-property-names`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.get-own-property-names.js), [`es.object.get-prototype-of`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.get-prototype-of.js), [`es.object.has-own`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.has-own.js), [`es.object.is`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.is.js), [`es.object.is-extensible`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.is-extensible.js), [`es.object.is-frozen`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.is-frozen.js), [`es.object.is-sealed`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.is-sealed.js), [`es.object.keys`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.keys.js), [`es.object.lookup-setter`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.lookup-setter.js), [`es.object.lookup-getter`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.lookup-getter.js), [`es.object.prevent-extensions`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.prevent-extensions.js), [`es.object.proto`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.proto.js), [`es.object.to-string`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.to-string.js), [`es.object.seal`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.seal.js), [`es.object.set-prototype-of`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.set-prototype-of.js), [`es.object.values`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.values.js).
442442

443-
Just ES5 features: [`es.object.create`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.create.js), [`es.object.define-property`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.define-property.js) and [`es.object.define-properties`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.es.object.define-properties.js).
444-
445-
[ES2017 Annex B](https://tc39.es/ecma262/#sec-object.prototype.__defineGetter__) - modules [`es.object.define-setter`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.define-setter.js), [`es.object.define-getter`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.define-getter.js), [`es.object.lookup-setter`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.lookup-setter.js) and [`es.object.lookup-getter`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.object.lookup-getter.js)
446443
```js
447444
class Object {
448445
toString(): string; // ES2015+ fix: @@toStringTag support
449446
__defineGetter__(property: PropertyKey, getter: Function): void;
450447
__defineSetter__(property: PropertyKey, setter: Function): void;
451448
__lookupGetter__(property: PropertyKey): Function | void;
452449
__lookupSetter__(property: PropertyKey): Function | void;
450+
__proto__: Object | null; // required a way setting of prototype - will not in IE10-, it's for modern engines like Deno
453451
static assign(target: Object, ...sources: Array<Object>): Object;
454452
static create(prototype: Object | null, properties?: { [property: PropertyKey]: PropertyDescriptor }): Object;
455453
static defineProperties(object: Object, properties: { [property: PropertyKey]: PropertyDescriptor })): Object;
@@ -494,6 +492,7 @@ core-js(-pure)/es|stable|actual|full/object/freeze
494492
core-js(-pure)/es|stable|actual|full/object/from-entries
495493
core-js(-pure)/es|stable|actual|full/object/seal
496494
core-js(-pure)/es|stable|actual|full/object/prevent-extensions
495+
core-js/es|stable|actual|full/object/proto
497496
core-js(-pure)/es|stable|actual|full/object/is-frozen
498497
core-js(-pure)/es|stable|actual|full/object/is-sealed
499498
core-js(-pure)/es|stable|actual|full/object/is-extensible

packages/core-js-compat/src/data.mjs

+10
Original file line numberDiff line numberDiff line change
@@ -1115,6 +1115,16 @@ export const data = {
11151115
safari: '9.0',
11161116
rhino: '1.7.13',
11171117
},
1118+
'es.object.proto': {
1119+
bun: '0.1.1',
1120+
chrome: '5',
1121+
deno: false,
1122+
firefox: '2',
1123+
hermes: '0.1',
1124+
ie: '11',
1125+
opera: '10.50',
1126+
safari: '3.1',
1127+
},
11181128
'es.object.seal': {
11191129
bun: '0.1.1',
11201130
chrome: '44',

packages/core-js-compat/src/modules-by-versions.mjs

+3
Original file line numberDiff line numberDiff line change
@@ -154,4 +154,7 @@ export default {
154154
'esnext.async-iterator.indexed',
155155
'esnext.iterator.indexed',
156156
],
157+
3.25: [
158+
'es.object.proto',
159+
],
157160
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// empty
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
var parent = require('../../stable/object/proto');
2+
3+
module.exports = parent;

packages/core-js/es/object/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ require('../../modules/es.object.is-frozen');
1717
require('../../modules/es.object.is-sealed');
1818
require('../../modules/es.object.keys');
1919
require('../../modules/es.object.prevent-extensions');
20+
require('../../modules/es.object.proto');
2021
require('../../modules/es.object.seal');
2122
require('../../modules/es.object.set-prototype-of');
2223
require('../../modules/es.object.values');

packages/core-js/es/object/proto.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
require('../../modules/es.object.proto');

packages/core-js/full/object/proto.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
var parent = require('../../actual/object/proto');
2+
3+
module.exports = parent;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
'use strict';
2+
var DESCRIPTORS = require('../internals/descriptors');
3+
var defineBuiltInAccessor = require('../internals/define-built-in-accessor');
4+
var isObject = require('../internals/is-object');
5+
var toObject = require('../internals/to-object');
6+
var requireObjectCoercible = require('../internals/require-object-coercible');
7+
8+
// eslint-disable-next-line es-x/no-object-getprototypeof -- safe
9+
var getPrototypeOf = Object.getPrototypeOf;
10+
// eslint-disable-next-line es-x/no-object-setprototypeof -- safe
11+
var setPrototypeOf = Object.setPrototypeOf;
12+
var ObjectPrototype = Object.prototype;
13+
var PROTO = '__proto__';
14+
15+
// `Object.prototype.__proto__` accessor
16+
// https://tc39.es/ecma262/#sec-object.prototype.__proto__
17+
if (DESCRIPTORS && getPrototypeOf && setPrototypeOf && !(PROTO in ObjectPrototype)) try {
18+
defineBuiltInAccessor(ObjectPrototype, PROTO, {
19+
configurable: true,
20+
get: function __proto__() {
21+
return getPrototypeOf(toObject(this));
22+
},
23+
set: function __proto__(proto) {
24+
var O = requireObjectCoercible(this);
25+
if (!isObject(proto) && proto !== null || !isObject(O)) return;
26+
setPrototypeOf(O, proto);
27+
}
28+
});
29+
} catch (error) { /* empty */ }
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
var parent = require('../../es/object/proto');
2+
3+
module.exports = parent;

scripts/build-compat-data.mjs

+13-7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import external from 'core-js-compat/src/external.mjs';
44
import mappings from 'core-js-compat/src/mapping.mjs';
55
import helpers from 'core-js-compat/helpers.js';
66

7+
const { compare, has, semver, sortObjectByKey } = helpers;
8+
79
for (const scope of [data, external]) {
810
for (const [key, module] of Object.entries(scope)) {
911
const { chrome, ie } = module;
@@ -12,21 +14,21 @@ for (const scope of [data, external]) {
1214
const [engine, targetKey] = mappingKey.split('To')
1315
.map(it => it.replace(/([a-z])([A-Z])/, (_, a, b) => `${ a }_${ b }`).toLowerCase());
1416
const version = module[engine];
15-
if (!version || module[targetKey]) return;
17+
if (!version || has(module, targetKey)) return;
1618
const mapping = mappings[mappingKey];
1719
if (typeof mapping == 'function') {
1820
return module[targetKey] = String(mapping(version));
1921
}
20-
const source = helpers.semver(version);
22+
const source = semver(version);
2123
for (const [from, to] of mapping) {
22-
if (helpers.compare(source, '<=', from)) {
24+
if (compare(source, '<=', from)) {
2325
return module[targetKey] = String(to);
2426
}
2527
}
2628
}
2729

2830
map('ChromeToAndroid');
29-
if (!module.android && chrome) {
31+
if (!has(module, 'android') && chrome) {
3032
module.android = String(Math.max(chrome, 37));
3133
}
3234
if (key.startsWith('es')) {
@@ -35,7 +37,7 @@ for (const scope of [data, external]) {
3537
if (/^(?:es|esnext|web)\./.test(key)) {
3638
map('ChromeToElectron');
3739
}
38-
if (!module.edge) {
40+
if (!has(module, 'edge')) {
3941
if (ie && !key.includes('immediate')) {
4042
module.edge = '12';
4143
} else if (chrome) {
@@ -46,7 +48,7 @@ for (const scope of [data, external]) {
4648
map('ChromeToNode');
4749
}
4850
map('ChromeToOpera');
49-
if (!module.opera_mobile && module.opera <= 42) {
51+
if (!has(module, 'opera_mobile') && module.opera <= 42) {
5052
module.opera_mobile = module.opera;
5153
} else {
5254
map('ChromeToOperaMobile');
@@ -56,7 +58,11 @@ for (const scope of [data, external]) {
5658
map('SafariToIOS');
5759
map('SafariToPhantom');
5860

59-
scope[key] = helpers.sortObjectByKey(module);
61+
for (const [engine, version] of Object.entries(module)) {
62+
if (!version) delete module[engine];
63+
}
64+
65+
scope[key] = sortObjectByKey(module);
6066
}
6167
}
6268

tests/commonjs.mjs

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ for (PATH of ['core-js-pure', 'core-js']) {
3434
ok(!load(NS, 'object/is-sealed')({}));
3535
ok(load(NS, 'object/keys')({ q: 0 })[0] === 'q');
3636
ok(load(NS, 'object/prevent-extensions')({}));
37+
load(NS, 'object/proto');
3738
ok(load(NS, 'object/seal')({}));
3839
ok(load(NS, 'object/set-prototype-of')({}, []) instanceof Array);
3940
ok(load(NS, 'object/to-string')([]) === '[object Array]');

tests/compat/tests.js

+3
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,9 @@ GLOBAL.tests = {
838838
'es.object.prevent-extensions': function () {
839839
return Object.preventExtensions(true);
840840
},
841+
'es.object.proto': function () {
842+
return '__proto__' in Object.prototype;
843+
},
841844
'es.object.seal': function () {
842845
return Object.seal(true);
843846
},

tests/tests/es.object.proto.js

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/* eslint-disable no-proto -- required for testing */
2+
import { DESCRIPTORS, PROTO } from '../helpers/constants';
3+
4+
if (PROTO && DESCRIPTORS) QUnit.test('Object.prototype.__proto__', assert => {
5+
assert.true('__proto__' in Object.prototype, 'in Object.prototype');
6+
const O = {};
7+
assert.same(O.__proto__, Object.prototype);
8+
O.__proto__ = Array.prototype;
9+
assert.same(O.__proto__, Array.prototype);
10+
assert.same(Object.getPrototypeOf(O), Array.prototype);
11+
assert.true(O instanceof Array);
12+
O.__proto__ = null;
13+
assert.same(Object.getPrototypeOf(O), null);
14+
});

0 commit comments

Comments
 (0)