diff --git a/CHANGELOG.md b/CHANGELOG.md index 1760f0b73bad..925b2cd7f43e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ ## Changelog ##### Unreleased +- Added [accessible `Object#hasOwnProperty` stage 2 proposal](https://github.com/tc39/proposal-accessible-object-hasownproperty) + - `Object.hasOwn` method - Fixed a possible `RegExp` constructor problem with multiple global `core-js` instances ##### 3.10.2 - 2021.04.19 diff --git a/README.md b/README.md index 574a6c010c42..e624ad66ef9e 100644 --- a/README.md +++ b/README.md @@ -2031,6 +2031,24 @@ core-js/features/typed-array/find-last-index [1, 2, 3, 4].findLast(it => it % 2); // => 3 [1, 2, 3, 4].findLastIndex(it => it % 2); // => 2 ```` +##### [Accessible `Object#hasOwnProperty`](https://github.com/tc39/proposal-accessible-object-hasownproperty)[⬆](#index) +Module [`esnext.object.has-own`](https://github.com/zloirock/core-js/blob/v3.10.2/packages/core-js/modules/esnext.object.has-own.js). +```js +class Object { + hasOwn(object: object, key: PropertyKey): boolean; +} +``` +[*CommonJS entry points:*](#commonjs-api) +``` +core-js/proposals/accessible-object-hasownproperty +core-js(-pure)/features(/virtual)/object/has-own +``` +[*Examples*](http://es6.zloirock.ru/#log(Object.hasOwn(%7B%20foo%3A%2042%20%7D%2C%20'foo'))%3B%20%2F%2F%20%3D%3E%20true%0Alog(Object.hasOwn(%7B%20foo%3A%2042%20%7D%2C%20'bar'))%3B%20%2F%2F%20%3D%3E%20false%0Alog(Object.hasOwn(%7B%7D%2C%20'toString'))%3B%20%2F%2F%20%3D%3E%20false): +```js +Object.hasOwn({ foo: 42 }, 'foo'); // => true +Object.hasOwn({ foo: 42 }, 'bar'); // => false +Object.hasOwn({}, 'toString'); // => false +```` #### Stage 1 proposals[⬆](#index) [*CommonJS entry points:*](#commonjs-api) diff --git a/packages/core-js-compat/src/data.js b/packages/core-js-compat/src/data.js index 10adea3071d6..05c0a85b84fd 100644 --- a/packages/core-js-compat/src/data.js +++ b/packages/core-js-compat/src/data.js @@ -1420,6 +1420,8 @@ const data = { }, 'esnext.number.range': { }, + 'esnext.object.has-own': { + }, // TODO: Remove from `core-js@4` 'esnext.object.iterate-entries': { }, diff --git a/packages/core-js-compat/src/modules-by-versions.js b/packages/core-js-compat/src/modules-by-versions.js index 9f77400ca58e..a2adbbe6da2e 100644 --- a/packages/core-js-compat/src/modules-by-versions.js +++ b/packages/core-js-compat/src/modules-by-versions.js @@ -80,4 +80,7 @@ module.exports = { 'esnext.typed-array.find-last-index', 'esnext.typed-array.unique-by', ], + 3.11: [ + 'esnext.object.has-own', + ], }; diff --git a/packages/core-js/features/object/has-own.js b/packages/core-js/features/object/has-own.js new file mode 100644 index 000000000000..2a467802c535 --- /dev/null +++ b/packages/core-js/features/object/has-own.js @@ -0,0 +1,4 @@ +require('../../modules/esnext.object.has-own'); +var path = require('../../internals/path'); + +module.exports = path.Object.hasOwn; diff --git a/packages/core-js/features/object/index.js b/packages/core-js/features/object/index.js index e7ea4bf747ca..b67532eebf33 100644 --- a/packages/core-js/features/object/index.js +++ b/packages/core-js/features/object/index.js @@ -1,4 +1,5 @@ var parent = require('../../es/object'); +require('../../modules/esnext.object.has-own'); require('../../modules/esnext.object.iterate-entries'); require('../../modules/esnext.object.iterate-keys'); require('../../modules/esnext.object.iterate-values'); diff --git a/packages/core-js/internals/has.js b/packages/core-js/internals/has.js index 0925c41e6cd1..08e114987e88 100644 --- a/packages/core-js/internals/has.js +++ b/packages/core-js/internals/has.js @@ -1,5 +1,5 @@ var hasOwnProperty = {}.hasOwnProperty; -module.exports = function (it, key) { +module.exports = function hasOwn(it, key) { return hasOwnProperty.call(it, key); }; diff --git a/packages/core-js/modules/esnext.object.has-own.js b/packages/core-js/modules/esnext.object.has-own.js new file mode 100644 index 000000000000..42eb97a2f319 --- /dev/null +++ b/packages/core-js/modules/esnext.object.has-own.js @@ -0,0 +1,8 @@ +var $ = require('../internals/export'); +var hasOwn = require('../internals/has'); + +// `Object.hasOwn` method +// https://github.com/tc39/proposal-accessible-object-hasownproperty +$({ target: 'Object', stat: true }, { + hasOwn: hasOwn +}); diff --git a/packages/core-js/proposals/accessible-object-hasownproperty.js b/packages/core-js/proposals/accessible-object-hasownproperty.js new file mode 100644 index 000000000000..17e0fcb44819 --- /dev/null +++ b/packages/core-js/proposals/accessible-object-hasownproperty.js @@ -0,0 +1,2 @@ +// https://github.com/tc39/proposal-accessible-object-hasownproperty +require('../modules/esnext.object.has-own'); diff --git a/packages/core-js/stage/2.js b/packages/core-js/stage/2.js index 66f40facac12..6dc701aecc11 100644 --- a/packages/core-js/stage/2.js +++ b/packages/core-js/stage/2.js @@ -1,3 +1,4 @@ +require('../proposals/accessible-object-hasownproperty'); require('../proposals/array-find-from-last'); require('../proposals/array-is-template-object'); require('../proposals/iterator-helpers'); diff --git a/tests/commonjs.js b/tests/commonjs.js index bb2701635a8c..ce5daf872a22 100644 --- a/tests/commonjs.js +++ b/tests/commonjs.js @@ -22,6 +22,7 @@ for (PATH of ['core-js-pure', 'core-js']) { ok(load('features/object/get-own-property-names')({ q: 42 })[0] === 'q'); ok(load('features/object/get-own-property-symbols')({ [Symbol()]: 42 }).length === 1); ok(load('features/object/get-prototype-of')([]) === Array.prototype); + ok(load('features/object/has-own')({ foo: 42 }, 'foo')); ok(load('features/object/is')(NaN, NaN)); ok(load('features/object/is-extensible')({})); ok(!load('features/object/is-frozen')({})); @@ -963,6 +964,7 @@ for (PATH of ['core-js-pure', 'core-js']) { ok(typeof load('web/url') === 'function'); ok(typeof load('web/url-search-params') === 'function'); ok('setImmediate' in load('web')); + load('proposals/accessible-object-hasownproperty'); load('proposals/array-filtering'); load('proposals/array-find-from-last'); load('proposals/array-is-template-object'); diff --git a/tests/compat/tests.js b/tests/compat/tests.js index 6602dbc94e85..70ebb996e124 100644 --- a/tests/compat/tests.js +++ b/tests/compat/tests.js @@ -1320,6 +1320,9 @@ GLOBAL.tests = { 'esnext.number.range': function () { return Number.range; }, + 'esnext.object.has-own': function () { + return Object.hasOwn; + }, // TODO: Remove from `core-js@4` 'esnext.object.iterate-entries': function () { return Object.iterateEntries; diff --git a/tests/pure/esnext.object.has-own.js b/tests/pure/esnext.object.has-own.js new file mode 100644 index 000000000000..c518b137d1f1 --- /dev/null +++ b/tests/pure/esnext.object.has-own.js @@ -0,0 +1,14 @@ +import create from 'core-js-pure/features/object/create'; +import hasOwn from 'core-js-pure/features/object/has-own'; + +QUnit.test('Object.hasOwn', assert => { + assert.isFunction(hasOwn); + assert.arity(hasOwn, 2); + assert.name(hasOwn, 'hasOwn'); + assert.deepEqual(hasOwn({ q: 42 }, 'q'), true); + assert.deepEqual(hasOwn({ q: 42 }, 'w'), false); + assert.deepEqual(hasOwn(create({ q: 42 }), 'q'), false); + assert.deepEqual(hasOwn(Object.prototype, 'hasOwnProperty'), true); + assert.throws(() => hasOwn(null, 'foo'), TypeError, 'throws on null'); + assert.throws(() => hasOwn(undefined, 'foo'), TypeError, 'throws on undefined'); +}); diff --git a/tests/tests/esnext.object.has-own.js b/tests/tests/esnext.object.has-own.js new file mode 100644 index 000000000000..381898715433 --- /dev/null +++ b/tests/tests/esnext.object.has-own.js @@ -0,0 +1,14 @@ +QUnit.test('Object.hasOwn', assert => { + const { create, hasOwn } = Object; + assert.isFunction(hasOwn); + assert.arity(hasOwn, 2); + assert.name(hasOwn, 'hasOwn'); + assert.looksNative(hasOwn); + assert.nonEnumerable(Object, 'hasOwn'); + assert.deepEqual(hasOwn({ q: 42 }, 'q'), true); + assert.deepEqual(hasOwn({ q: 42 }, 'w'), false); + assert.deepEqual(hasOwn(create({ q: 42 }), 'q'), false); + assert.deepEqual(hasOwn(Object.prototype, 'hasOwnProperty'), true); + assert.throws(() => hasOwn(null, 'foo'), TypeError, 'throws on null'); + assert.throws(() => hasOwn(undefined, 'foo'), TypeError, 'throws on undefined'); +});