-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
bd70f8b
commit b204d3e
Showing
7 changed files
with
327 additions
and
62 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,61 +1,4 @@ | ||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# Runtime data | ||
pids | ||
*.pid | ||
*.seed | ||
*.pid.lock | ||
|
||
# Directory for instrumented libs generated by jscoverage/JSCover | ||
lib-cov | ||
|
||
# Coverage directory used by tools like istanbul | ||
coverage | ||
|
||
# nyc test coverage | ||
.nyc_output | ||
|
||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) | ||
.grunt | ||
|
||
# Bower dependency directory (https://bower.io/) | ||
bower_components | ||
|
||
# node-waf configuration | ||
.lock-wscript | ||
|
||
# Compiled binary addons (https://nodejs.org/api/addons.html) | ||
build/Release | ||
|
||
# Dependency directories | ||
coverage/ | ||
node_modules/ | ||
jspm_packages/ | ||
|
||
# TypeScript v1 declaration files | ||
typings/ | ||
|
||
# Optional npm cache directory | ||
.npm | ||
|
||
# Optional eslint cache | ||
.eslintcache | ||
|
||
# Optional REPL history | ||
.node_repl_history | ||
|
||
# Output of 'npm pack' | ||
*.tgz | ||
|
||
# Yarn Integrity file | ||
.yarn-integrity | ||
|
||
# dotenv environment variables file | ||
.env | ||
|
||
# next.js build output | ||
.next | ||
.nyc_output/ | ||
package-lock.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
language: node_js | ||
node_js: | ||
- 8 | ||
- 10 | ||
- node | ||
script: npm run ci |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,44 @@ | ||
# incomplete-symbol | ||
Custom-remove features of a Symbol implementation. | ||
# incomplete-symbol [![NPM Version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Coverage Status][coveralls-image]][coveralls-url] | ||
|
||
> Custom-remove features of a [`Symbol`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Symbol) implementation. | ||
|
||
This is useful when simulating the incomplete `Symbol` implementations available in some of today's modern web browsers. | ||
|
||
|
||
## Installation | ||
|
||
[Node.js](http://nodejs.org/) `>= 8` is required. To install, type this at the command line: | ||
```shell | ||
npm install incomplete-symbol | ||
``` | ||
|
||
|
||
## Usage | ||
|
||
```js | ||
const customizeSymbol = require('incomplete-symbol'); | ||
|
||
const exclusions = ['description', 'toStringTag']; | ||
const IncompleteSymbol = customizeSymbol(exclusions); | ||
const symbol = new IncompleteSymbol('foo'); | ||
|
||
console.log(IncompleteSymbol.toStringTag); //-> undefined | ||
console.log(symbol.description); //-> undefined | ||
``` | ||
|
||
|
||
## Arguments | ||
|
||
### `exclusions` | ||
Type: `Array` | ||
Default value: `[]` | ||
The output `Symbol` function and any instances created with it will not expose each listed property/method. | ||
|
||
|
||
[npm-image]: https://img.shields.io/npm/v/incomplete-symbol.svg | ||
[npm-url]: https://npmjs.com/package/incomplete-symbol | ||
[travis-image]: https://img.shields.io/travis/stevenvachon/incomplete-symbol.svg | ||
[travis-url]: https://travis-ci.org/stevenvachon/incomplete-symbol | ||
[coveralls-image]: https://img.shields.io/coveralls/stevenvachon/incomplete-symbol.svg | ||
[coveralls-url]: https://coveralls.io/github/stevenvachon/incomplete-symbol |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
"use strict"; | ||
const {instanceMethods, instanceProperties, staticMethods, staticProperties} = require("./props"); | ||
|
||
|
||
|
||
const customizeSymbol = (exclusions=[]) => | ||
{ | ||
// For testing: uses the global value when this function is called | ||
// instead of when instances are created | ||
const globalSymbol = Symbol; | ||
|
||
function IncompleteSymbolInstance(description) | ||
{ | ||
this._symbol = globalSymbol(description); | ||
|
||
instanceMethods | ||
.filter(method => !exclusions.includes(method) && typeof this._symbol[method]==="function") | ||
.forEach(method => this[method] = (...args) => this._symbol[method](...args)); | ||
|
||
instanceProperties | ||
.filter(property => !exclusions.includes(property) && this._symbol[property]!==undefined) | ||
.forEach(property => Object.defineProperty(this, property, | ||
{ | ||
get: () => this._symbol[property] | ||
})); | ||
} | ||
|
||
const IncompleteSymbol = (...args) => new IncompleteSymbolInstance(...args); | ||
|
||
staticMethods | ||
.filter(method => !exclusions.includes(method) && typeof globalSymbol[method]==="function") | ||
.forEach(method => IncompleteSymbol[method] = (...args) => globalSymbol[method](...args)); | ||
|
||
staticProperties | ||
.filter(property => !exclusions.includes(property) && property in globalSymbol) | ||
.forEach(property => Object.defineProperty(IncompleteSymbol, property, | ||
{ | ||
get: () => globalSymbol[property] | ||
})); | ||
|
||
return IncompleteSymbol; | ||
}; | ||
|
||
|
||
|
||
module.exports = customizeSymbol; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
"use strict"; | ||
|
||
|
||
|
||
const instanceMethods = | ||
[ | ||
"toString", | ||
"valueOf", | ||
Symbol.toPrimitive | ||
]; | ||
|
||
|
||
|
||
const instanceProperties = | ||
[ | ||
"constructor", | ||
"description" | ||
]; | ||
|
||
|
||
|
||
const staticMethods = | ||
[ | ||
"for", | ||
"keyFor" | ||
]; | ||
|
||
|
||
|
||
const staticProperties = | ||
[ | ||
"hasInstance", | ||
"isConcatSpreadable", | ||
"iterator", | ||
"length", | ||
"match", | ||
"replace", | ||
"search", | ||
"species", | ||
"split", | ||
"toPrimitive", | ||
"toStringTag", | ||
"unscopables" | ||
]; | ||
|
||
|
||
|
||
module.exports = | ||
{ | ||
instanceMethods, | ||
instanceProperties, | ||
staticMethods, | ||
staticProperties | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
{ | ||
"name": "incomplete-symbol", | ||
"description": "Custom-remove features of a Symbol implementation.", | ||
"version": "1.0.0", | ||
"license": "MIT", | ||
"author": "Steven Vachon <contact@svachon.com> (https://www.svachon.com/)", | ||
"repository": "github:stevenvachon/incomplete-symbol", | ||
"main": "lib", | ||
"devDependencies": { | ||
"chai": "^4.2.0", | ||
"coveralls": "^3.0.2", | ||
"mocha": "^5.2.0", | ||
"nyc": "^13.1.0", | ||
"sinon": "^7.2.2", | ||
"sinon-chai": "^3.3.0", | ||
"symbol.prototype.description": "^1.0.0" | ||
}, | ||
"engines": { | ||
"node": ">= 8" | ||
}, | ||
"scripts": { | ||
"ci": "npm run test && nyc report --reporter=text-lcov | coveralls", | ||
"posttest": "nyc report --reporter=html", | ||
"test": "nyc --reporter=text-summary mocha test --check-leaks --bail" | ||
}, | ||
"files": [ | ||
"lib" | ||
], | ||
"keywords": [ | ||
"symbol" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
"use strict"; | ||
const customizeSymbol = require("./lib"); | ||
const {afterEach, beforeEach, describe, it} = require("mocha"); | ||
const {expect} = require("chai").use( require("sinon-chai") ); | ||
const {instanceMethods, instanceProperties, staticMethods, staticProperties} = require("./lib/props"); | ||
const {restore, stub} = require("sinon"); | ||
require("symbol.prototype.description/auto"); | ||
|
||
|
||
|
||
const instanceKeys = [...instanceMethods, ...instanceProperties]; | ||
|
||
const propertyString = key => typeof key === "symbol" ? key.description : `"${key}"`; | ||
|
||
const removeExtendableKeys = keys => keys.filter(key => unextendableKeys.includes(key)); | ||
const removeUnextendableKeys = keys => keys.filter(key => !unextendableKeys.includes(key)); | ||
|
||
const staticKeys = [...staticMethods, ...staticProperties]; | ||
const symbolString = "description"; | ||
|
||
const unextendableKeys = | ||
[ | ||
"constructor", | ||
"length", | ||
"toString", | ||
"valueOf" | ||
]; | ||
|
||
|
||
|
||
describe("Default behavior", () => | ||
{ | ||
it("is the same as the global", () => | ||
{ | ||
const IncompleteSymbol = customizeSymbol(); | ||
|
||
const symbol = IncompleteSymbol(symbolString); | ||
|
||
instanceKeys.forEach(key => expect(symbol).to.have.property(key)); | ||
staticKeys.forEach(key => expect(IncompleteSymbol).to.have.property(key)); | ||
|
||
const args = ["arg1", "arg2"]; | ||
|
||
instanceMethods.forEach(method => | ||
{ | ||
stub(Symbol.prototype, method); | ||
|
||
symbol[method](...args); | ||
|
||
expect(Symbol.prototype[method]).to.have.been.calledWith(...args); | ||
|
||
restore(); | ||
}); | ||
|
||
staticMethods.forEach(method => | ||
{ | ||
stub(Symbol, method); | ||
|
||
IncompleteSymbol[method](...args); | ||
|
||
expect(Symbol[method]).to.have.been.calledWith(...args); | ||
|
||
restore(); | ||
}); | ||
}); | ||
}); | ||
|
||
|
||
|
||
describe("Unavailable properties/methods", () => | ||
{ | ||
const originalSymbol = Symbol; | ||
|
||
|
||
|
||
beforeEach(() => | ||
{ | ||
const stubbedSymbol = customizeSymbol( | ||
[ | ||
"description", | ||
"for", | ||
"hasInstance", | ||
Symbol.toPrimitive | ||
]); | ||
|
||
stub(global, "Symbol").callsFake(stubbedSymbol); | ||
}); | ||
|
||
afterEach(() => restore()); | ||
|
||
|
||
|
||
it("does not attempt to wrap them", () => | ||
{ | ||
const IncompleteSymbol = customizeSymbol(); | ||
|
||
const symbol = IncompleteSymbol(symbolString); | ||
|
||
expect(IncompleteSymbol).to.not.have.property("for"); | ||
expect(IncompleteSymbol).to.not.have.property("hasInstance"); | ||
expect(symbol).to.not.have.property("description"); | ||
expect(symbol).to.not.have.property(originalSymbol.toPrimitive); | ||
}) | ||
}); | ||
|
||
|
||
|
||
describe("Exclusions", () => | ||
{ | ||
removeUnextendableKeys(instanceKeys).forEach(key => it(propertyString(key), () => | ||
{ | ||
const IncompleteSymbol = customizeSymbol([key]); | ||
|
||
const symbol = IncompleteSymbol(symbolString); | ||
|
||
expect(symbol).to.not.have.property(key); | ||
})); | ||
|
||
|
||
|
||
removeUnextendableKeys(staticKeys).forEach(key => it(propertyString(key), () => | ||
{ | ||
const IncompleteSymbol = customizeSymbol([key]); | ||
|
||
expect(IncompleteSymbol).to.not.have.property(key); | ||
})); | ||
|
||
|
||
|
||
it("all methods/properties", () => | ||
{ | ||
const IncompleteSymbol = customizeSymbol([...instanceKeys, ...staticKeys]); | ||
|
||
const symbol = IncompleteSymbol(symbolString); | ||
|
||
removeExtendableKeys(instanceKeys).forEach(key => expect(symbol).to.have.property(key)); | ||
removeExtendableKeys(staticKeys).forEach(key => expect(IncompleteSymbol).to.have.property(key)); | ||
|
||
removeUnextendableKeys(instanceKeys).forEach(key => expect(symbol).to.not.have.property(key)); | ||
removeUnextendableKeys(staticKeys).forEach(key => expect(IncompleteSymbol).to.not.have.property(key)); | ||
}); | ||
}); |