Skip to content

Commit

Permalink
[Fix] behave properly in a pre-Symbol environment
Browse files Browse the repository at this point in the history
  • Loading branch information
ljharb committed Feb 15, 2024
1 parent 19c078d commit d61003b
Show file tree
Hide file tree
Showing 11 changed files with 40 additions and 42 deletions.
1 change: 0 additions & 1 deletion .eslintrc
Expand Up @@ -15,7 +15,6 @@
"rules": {
"consistent-return": 1,
"no-invalid-this": 0,
"dot-notation": [2, { "allowKeywords": true }],
},
},
],
Expand Down
10 changes: 2 additions & 8 deletions .github/workflows/node-aught.yml
Expand Up @@ -6,13 +6,7 @@ jobs:
tests:
uses: ljharb/actions/.github/workflows/node.yml@main
with:
range: '~0.11.15 || >= 0.12 < 10'
range: '>= 0.6 < 10'
type: minors
command: npm run tests-only

node:
name: 'node < 10'
needs: [tests]
runs-on: ubuntu-latest
steps:
- run: 'echo tests completed'
skip-ls-check: true
7 changes: 0 additions & 7 deletions .github/workflows/node-tens.yml
Expand Up @@ -9,10 +9,3 @@ jobs:
range: '>= 10'
type: minors
command: npm run tests-only

node:
name: 'node >= 10'
needs: [tests]
runs-on: ubuntu-latest
steps:
- run: 'echo tests completed'
17 changes: 8 additions & 9 deletions README.md
Expand Up @@ -2,33 +2,32 @@

[![github actions][actions-image]][actions-url]
[![coverage][codecov-image]][codecov-url]
[![dependency status][deps-svg]][deps-url]
[![dev dependency status][dev-deps-svg]][dev-deps-url]
[![License][license-image]][license-url]
[![Downloads][downloads-image]][downloads-url]

[![npm badge][npm-badge-png]][package-url]

An ECMAScript spec-compliant `Symbol.prototype.description` shim. Invoke its "shim" method to shim Symbol.prototype.description if it is unavailable.
*Note*: `Symbol#description` requires a true ES6 environment, specifically one with native Symbols.
*Note*: `Symbol#description` requires a true ES6 environment, specifically one with native Symbols (eg, node >= v11.15.0)

This package implements the [es-shim API](https://github.com/es-shims/api) interface. It works in an ES6-supported environment and complies with the [spec](https://github.com/michaelficarra/Symbol-description-proposal/).
This package implements the [es-shim API](https://github.com/es-shims/api) interface. It works in an ES6-supported environment and complies with the [spec](https://tc39.es/ecma262/#sec-symbol.prototype.description).

Most common usage:
```js
var description = require('symbol.prototype.description');
var assert = require('assert');

assert(description(Symbol('foo')) === 'foo');
assert(description(Symbol()) === undefined);
assert(description(Symbol(undefined)) === undefined);
assert(description(Symbol(null)) === 'null');

// note: this should be the empty string, but in many engines,
// it is impossible to distinguish Symbol() and Symbol('')
// without globally replacing `Symbol`
assert(description(Symbol('')) === undefined);
if (!('description' in Symbol.prototype)) {
// note: this should be the empty string, but in many engines,
// it is impossible to distinguish Symbol() and Symbol('')
// without globally replacing `Symbol`
assert(description(Symbol('')) === undefined);

if (!Symbol.prototype.description) {
description.shim();
}

Expand Down
5 changes: 5 additions & 0 deletions implementation.js
@@ -1,7 +1,12 @@
'use strict';

var $TypeError = require('es-errors/type');
var getSymbolDescription = require('get-symbol-description');

module.exports = function description() {
if (this == null) { // eslint-disable-line eqeqeq
throw new $TypeError('`this` value must be object-coercible');
}

return getSymbolDescription(this);
};
6 changes: 5 additions & 1 deletion package.json
Expand Up @@ -8,6 +8,7 @@
"prepack": "npmignore --auto --commentLines=autogenerated",
"prepublish": "not-in-publish || npm run prepublishOnly",
"prepublishOnly": "safe-publish-latest",
"prelint": "evalmd README.md",
"lint": "eslint --ext=js,mjs .",
"postlint": "es-shim-api --bound --skip-shim-returns-polyfill",
"tests-only": "nyc tape 'test/**/*.js'",
Expand Down Expand Up @@ -41,6 +42,7 @@
"homepage": "https://github.com/es-shims/Symbol.prototype.description#readme",
"dependencies": {
"call-bind": "^1.0.7",
"es-errors": "^1.3.0",
"get-symbol-description": "^1.0.2",
"has-symbols": "^1.0.3",
"object.getownpropertydescriptors": "^2.1.7"
Expand All @@ -51,7 +53,9 @@
"aud": "^2.0.4",
"auto-changelog": "^2.4.0",
"eslint": "=8.8.0",
"evalmd": "^0.0.19",
"has-strict-mode": "^1.0.1",
"hasown": "^2.0.1",
"in-publish": "^2.0.1",
"npmignore": "^0.3.1",
"nyc": "^10.3.2",
Expand All @@ -60,7 +64,7 @@
"tape": "^5.7.5"
},
"engines": {
"node": ">= 0.11.15"
"node": ">= 0.4"
},
"auto-changelog": {
"output": "CHANGELOG.md",
Expand Down
2 changes: 1 addition & 1 deletion polyfill.js
Expand Up @@ -7,7 +7,7 @@ var gOPD = Object.getOwnPropertyDescriptor;

module.exports = function descriptionPolyfill() {
if (!hasSymbols || typeof gOPD !== 'function') {
return null;
return implementation;
}

var desc = gOPD(Symbol.prototype, 'description');
Expand Down
4 changes: 2 additions & 2 deletions test/implementation.js
Expand Up @@ -9,8 +9,8 @@ var runTests = require('./tests');
test('as a function', function (t) {
t.test('bad array/this value', { skip: !hasStrictMode }, function (st) {
/* eslint no-useless-call: 0 */
st.throws(function () { implementation.call(undefined); }, TypeError, 'undefined is not an object');
st.throws(function () { implementation.call(null); }, TypeError, 'null is not an object');
st['throws'](function () { implementation.call(undefined); }, TypeError, 'undefined is not an object');
st['throws'](function () { implementation.call(null); }, TypeError, 'null is not an object');
st.end();
});

Expand Down
10 changes: 2 additions & 8 deletions test/index.js
@@ -1,20 +1,14 @@
'use strict';

var hasSymbols = require('has-symbols')();
var test = require('tape');

var description = require('../');
var runTests = require('./tests');

test('as a function', function (t) {
if (!hasSymbols) {
t.fail('Symbols not supported in this environment');
return t.end();
}

t.test('bad array/this value', function (st) {
st.throws(function () { description(undefined); }, TypeError, 'undefined is not an object');
st.throws(function () { description(null); }, TypeError, 'null is not an object');
st['throws'](function () { description(undefined); }, TypeError, 'undefined is not an object');
st['throws'](function () { description(null); }, TypeError, 'null is not an object');
st.end();
});

Expand Down
10 changes: 5 additions & 5 deletions test/shimmed.js
Expand Up @@ -3,7 +3,7 @@
var originalSymbol = typeof Symbol === 'function' ? Symbol : null;
require('../auto');

var has = require('has');
var hasOwn = require('hasown');
var keys = require('reflect.ownkeys');
var hasSymbols = require('has-symbols')();
var test = require('tape');
Expand All @@ -14,7 +14,7 @@ var getInferredName = require('get-symbol-description/getInferredName');

test('shimmed', function (t) {
if (!hasSymbols) {
t.fail('Symbols not supported in this environment');
t.comment('Symbols not supported in this environment');
return t.end();
}

Expand All @@ -39,7 +39,7 @@ test('shimmed', function (t) {
for (var i = 0; i < ownProperties.length; i++) {
var p = ownProperties[i];
if (p !== 'length' && p !== 'arguments' && p !== 'caller' && p !== 'callee') {
st.ok(has(Symbol, p), 'has own property: ' + p);
st.ok(hasOwn(Symbol, p), 'has own property: ' + p);
}
}
st.end();
Expand All @@ -48,8 +48,8 @@ test('shimmed', function (t) {
var supportsStrictMode = (function () { return typeof this === 'undefined'; }());

t.test('bad object value', { skip: !supportsStrictMode }, function (st) {
st.throws(function () { return Object.values(undefined); }, TypeError, 'undefined is not an object');
st.throws(function () { return Object.values(null); }, TypeError, 'null is not an object');
st['throws'](function () { return Object.values(undefined); }, TypeError, 'undefined is not an object');
st['throws'](function () { return Object.values(null); }, TypeError, 'null is not an object');
st.end();
});

Expand Down
10 changes: 10 additions & 0 deletions test/tests.js
Expand Up @@ -4,6 +4,16 @@ var hasSymbols = require('has-symbols')();
var getInferredName = require('get-symbol-description/getInferredName');

module.exports = function (description, t) {
t.test('Symbols not supported', { skip: hasSymbols }, function (st) {
st['throws'](
function () { description('foo'); },
SyntaxError,
'throws when Symbols not supported'
);

st.end();
});

t.test('Symbol description', { skip: !hasSymbols }, function (st) {
st.equal(description(Symbol()), undefined, 'Symbol() description is undefined');
st.equal(description(Symbol(undefined)), undefined, 'Symbol(undefined) description is undefined');
Expand Down

0 comments on commit d61003b

Please sign in to comment.