├── .testignore ├── .github ├── FUNDING.yml └── workflows │ ├── validate.yml │ ├── integrate.yml │ └── publish.yml ├── .npmignore ├── .gitignore ├── test ├── implement.js ├── is-native-implemented.js ├── index.js ├── is-implemented.js ├── is-symbol.js ├── validate-symbol.js └── polyfill.js ├── index.js ├── validate-symbol.js ├── is-native-implemented.js ├── implement.js ├── is-symbol.js ├── .editorconfig ├── is-implemented.js ├── lib └── private │ ├── setup │ ├── symbol-registry.js │ └── standard-symbols.js │ └── generate-name.js ├── commitlint.config.js ├── LICENSE ├── CHANGELOG.md ├── CHANGES ├── package.json ├── polyfill.js └── README.md /.testignore: -------------------------------------------------------------------------------- 1 | /lib/private 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: medikoo 2 | tidelift: "npm/es6-symbol" 3 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | /.editorconfig 2 | /.github 3 | /commitlint.config.js 4 | /test 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.nyc_output 2 | /coverage 3 | /node_modules 4 | npm-debug.log 5 | /package-lock.json 6 | -------------------------------------------------------------------------------- /test/implement.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = function (t, a) { a(typeof Symbol, "function"); }; 4 | -------------------------------------------------------------------------------- /test/is-native-implemented.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = function (t, a) { a(typeof t, "boolean"); }; 4 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = require("./is-implemented")() 4 | ? require("ext/global-this").Symbol 5 | : require("./polyfill"); 6 | -------------------------------------------------------------------------------- /validate-symbol.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var isSymbol = require("./is-symbol"); 4 | 5 | module.exports = function (value) { 6 | if (!isSymbol(value)) throw new TypeError(value + " is not a symbol"); 7 | return value; 8 | }; 9 | -------------------------------------------------------------------------------- /is-native-implemented.js: -------------------------------------------------------------------------------- 1 | // Exports true if environment provides native `Symbol` implementation 2 | 3 | "use strict"; 4 | 5 | var Symbol = require("ext/global-this").Symbol; 6 | 7 | module.exports = typeof Symbol === "function" && typeof Symbol() === "symbol"; 8 | -------------------------------------------------------------------------------- /implement.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | if (!require("./is-implemented")()) { 4 | Object.defineProperty(require("ext/global-this"), "Symbol", { 5 | value: require("./polyfill"), 6 | configurable: true, 7 | enumerable: false, 8 | writable: true 9 | }); 10 | } 11 | -------------------------------------------------------------------------------- /.github/workflows/validate.yml: -------------------------------------------------------------------------------- 1 | # PR's only 2 | 3 | name: Validate 4 | 5 | on: 6 | pull_request: 7 | branches: [main] 8 | 9 | env: 10 | FORCE_COLOR: 1 11 | 12 | jobs: 13 | _: 14 | uses: medikoo/github-actions-workflows/.github/workflows/0.12-validate.yml@main 15 | -------------------------------------------------------------------------------- /is-symbol.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = function (value) { 4 | if (!value) return false; 5 | if (typeof value === "symbol") return true; 6 | if (!value.constructor) return false; 7 | if (value.constructor.name !== "Symbol") return false; 8 | return value[value.constructor.toStringTag] === "Symbol"; 9 | }; 10 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var d = require("d") 4 | , defineProperty = Object.defineProperty; 5 | 6 | module.exports = function (t, a) { 7 | var symbol = t("test"), obj = {}; 8 | defineProperty(obj, symbol, d("foo")); 9 | a(obj.test, undefined, "Name"); 10 | a(obj[symbol], "foo", "Get"); 11 | }; 12 | -------------------------------------------------------------------------------- /.github/workflows/integrate.yml: -------------------------------------------------------------------------------- 1 | # main only 2 | 3 | name: Integrate 4 | 5 | on: 6 | push: 7 | branches: [main] 8 | 9 | env: 10 | FORCE_COLOR: 1 11 | 12 | jobs: 13 | _: 14 | uses: medikoo/github-actions-workflows/.github/workflows/0.12-integrate.yml@main 15 | secrets: 16 | USER_GITHUB_TOKEN: ${{ secrets.USER_GITHUB_TOKEN }} 17 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | charset = utf-8 8 | end_of_line = lf 9 | insert_final_newline = true 10 | indent_style = tab 11 | trim_trailing_whitespace = true 12 | 13 | [*.{md,yml}] 14 | indent_size = 2 15 | indent_style = space 16 | 17 | [*.md] 18 | trim_trailing_whitespace = false 19 | -------------------------------------------------------------------------------- /test/is-implemented.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var global = require("ext/global-this") 4 | , polyfill = require("../polyfill"); 5 | 6 | module.exports = function (t, a) { 7 | var cache; 8 | a(typeof t(), "boolean"); 9 | cache = global.Symbol; 10 | global.Symbol = polyfill; 11 | a(t(), true); 12 | if (cache === undefined) delete global.Symbol; 13 | else global.Symbol = cache; 14 | }; 15 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | # Version tags only 2 | 3 | name: Publish 4 | 5 | on: 6 | push: 7 | tags: 8 | - v[0-9]+.[0-9]+.[0-9]+ 9 | 10 | env: 11 | FORCE_COLOR: 1 12 | 13 | jobs: 14 | _: 15 | uses: medikoo/github-actions-workflows/.github/workflows/publish.yml@main 16 | secrets: 17 | USER_GITHUB_TOKEN: ${{ secrets.USER_GITHUB_TOKEN }} 18 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 19 | -------------------------------------------------------------------------------- /test/is-symbol.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var SymbolPolyfill = require("../polyfill"); 4 | 5 | module.exports = function (t, a) { 6 | a(t(undefined), false, "Undefined"); 7 | a(t(null), false, "Null"); 8 | a(t(true), false, "Primitive"); 9 | a(t("raz"), false, "String"); 10 | a(t({}), false, "Object"); 11 | a(t([]), false, "Array"); 12 | if (typeof Symbol !== "undefined") { 13 | a(t(Symbol("foo")), true, "Native"); 14 | } 15 | a(t(SymbolPolyfill()), true, "Polyfill"); 16 | }; 17 | -------------------------------------------------------------------------------- /is-implemented.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var global = require("ext/global-this") 4 | , validTypes = { object: true, symbol: true }; 5 | 6 | module.exports = function () { 7 | var Symbol = global.Symbol; 8 | var symbol; 9 | if (typeof Symbol !== "function") return false; 10 | symbol = Symbol("test symbol"); 11 | try { String(symbol); } 12 | catch (e) { return false; } 13 | 14 | // Return 'true' also for polyfills 15 | if (!validTypes[typeof Symbol.iterator]) return false; 16 | if (!validTypes[typeof Symbol.toPrimitive]) return false; 17 | if (!validTypes[typeof Symbol.toStringTag]) return false; 18 | 19 | return true; 20 | }; 21 | -------------------------------------------------------------------------------- /lib/private/setup/symbol-registry.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var d = require("d") 4 | , validateSymbol = require("../../../validate-symbol"); 5 | 6 | var registry = Object.create(null); 7 | 8 | module.exports = function (SymbolPolyfill) { 9 | return Object.defineProperties(SymbolPolyfill, { 10 | for: d(function (key) { 11 | if (registry[key]) return registry[key]; 12 | return (registry[key] = SymbolPolyfill(String(key))); 13 | }), 14 | keyFor: d(function (symbol) { 15 | var key; 16 | validateSymbol(symbol); 17 | for (key in registry) { 18 | if (registry[key] === symbol) return key; 19 | } 20 | return undefined; 21 | }) 22 | }); 23 | }; 24 | -------------------------------------------------------------------------------- /test/validate-symbol.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var SymbolPolyfill = require("../polyfill"); 4 | 5 | module.exports = function (t, a) { 6 | var symbol; 7 | a.throws(function () { t(undefined); }, TypeError, "Undefined"); 8 | a.throws(function () { t(null); }, TypeError, "Null"); 9 | a.throws(function () { t(true); }, TypeError, "Primitive"); 10 | a.throws(function () { t("raz"); }, TypeError, "String"); 11 | a.throws(function () { t({}); }, TypeError, "Object"); 12 | a.throws(function () { t([]); }, TypeError, "Array"); 13 | if (typeof Symbol !== "undefined") { 14 | symbol = Symbol("foo"); 15 | a(t(symbol), symbol, "Native"); 16 | } 17 | symbol = SymbolPolyfill(); 18 | a(t(symbol), symbol, "Polyfill"); 19 | }; 20 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = { 4 | rules: { 5 | "body-leading-blank": [2, "always"], 6 | "body-max-line-length": [2, "always", 72], 7 | "footer-leading-blank": [2, "always"], 8 | "footer-max-line-length": [2, "always", 72], 9 | "header-max-length": [2, "always", 72], 10 | "scope-case": [2, "always", "start-case"], 11 | "scope-enum": [2, "always", [""]], 12 | "subject-case": [2, "always", "sentence-case"], 13 | "subject-empty": [2, "never"], 14 | "subject-full-stop": [2, "never", "."], 15 | "type-case": [2, "always", "lower-case"], 16 | "type-empty": [2, "never"], 17 | "type-enum": [ 18 | 2, "always", 19 | ["build", "chore", "ci", "docs", "feat", "fix", "perf", "refactor", "style", "test"] 20 | ] 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright (c) 2013-2024, Mariusz Nowak, @medikoo, medikoo.com 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 10 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 12 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 | OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 | PERFORMANCE OF THIS SOFTWARE. 16 | -------------------------------------------------------------------------------- /lib/private/generate-name.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var d = require("d"); 4 | 5 | var create = Object.create, defineProperty = Object.defineProperty, objPrototype = Object.prototype; 6 | 7 | var created = create(null); 8 | module.exports = function (desc) { 9 | var postfix = 0, name, ie11BugWorkaround; 10 | while (created[desc + (postfix || "")]) ++postfix; 11 | desc += postfix || ""; 12 | created[desc] = true; 13 | name = "@@" + desc; 14 | defineProperty( 15 | objPrototype, name, 16 | d.gs(null, function (value) { 17 | // For IE11 issue see: 18 | // https://connect.microsoft.com/IE/feedbackdetail/view/1928508/ 19 | // ie11-broken-getters-on-dom-objects 20 | // https://github.com/medikoo/es6-symbol/issues/12 21 | if (ie11BugWorkaround) return; 22 | ie11BugWorkaround = true; 23 | defineProperty(this, name, d(value)); 24 | ie11BugWorkaround = false; 25 | }) 26 | ); 27 | return name; 28 | }; 29 | -------------------------------------------------------------------------------- /test/polyfill.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var d = require("d") 4 | , isSymbol = require("../is-symbol") 5 | , defineProperty = Object.defineProperty; 6 | 7 | module.exports = function (t, a) { 8 | var symbol = t("test"), obj = {}; 9 | defineProperty(obj, symbol, d("foo")); 10 | a(obj.test, undefined, "Name"); 11 | a(obj[symbol], "foo", "Get"); 12 | a(obj instanceof t, false); 13 | 14 | a(isSymbol(symbol), true, "Symbol"); 15 | a(isSymbol(t.iterator), true, "iterator"); 16 | a(isSymbol(t.toStringTag), true, "toStringTag"); 17 | 18 | obj = {}; 19 | obj[symbol] = "foo"; 20 | if (typeof symbol !== "symbol") { 21 | a.deep(Object.getOwnPropertyDescriptor(obj, symbol), { 22 | configurable: true, 23 | enumerable: false, 24 | value: "foo", 25 | writable: true 26 | }); 27 | } 28 | symbol = t.for("marko"); 29 | a(isSymbol(symbol), true); 30 | a(t.for("marko"), symbol); 31 | a(t.keyFor(symbol), "marko"); 32 | }; 33 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ### [3.1.4](https://github.com/medikoo/es6-symbol/compare/v3.1.3...v3.1.4) (2024-03-01) 6 | 7 | _Maintenance Improvements_ 8 | 9 | ### [3.1.3](https://github.com/medikoo/es6-symbol/compare/v3.1.2...v3.1.3) (2019-10-29) 10 | 11 | _Maintenance Improvements_ 12 | 13 | ### [3.1.2](https://github.com/medikoo/es6-symbol/compare/v3.1.1...v3.1.2) (2019-09-04) 14 | 15 | - Access `Symbol` from a global object. Makes implementation more bulletproof, as it's safe against shadowing the `Symbol` variable e.g. in script scope, or as it's practiced by some bundlers as Webpack (thanks [@cyborgx37](https://github.com/medikoo/es6-symbol/pull/30)) 16 | - Switch license from MIT to ISC 17 | - Switch linter to ESLint 18 | - Configure Prettier 19 | 20 | ## Changelog for previous versions 21 | 22 | See `CHANGES` file 23 | -------------------------------------------------------------------------------- /lib/private/setup/standard-symbols.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var d = require("d") 4 | , NativeSymbol = require("ext/global-this").Symbol; 5 | 6 | module.exports = function (SymbolPolyfill) { 7 | return Object.defineProperties(SymbolPolyfill, { 8 | // To ensure proper interoperability with other native functions (e.g. Array.from) 9 | // fallback to eventual native implementation of given symbol 10 | hasInstance: d( 11 | "", (NativeSymbol && NativeSymbol.hasInstance) || SymbolPolyfill("hasInstance") 12 | ), 13 | isConcatSpreadable: d( 14 | "", 15 | (NativeSymbol && NativeSymbol.isConcatSpreadable) || 16 | SymbolPolyfill("isConcatSpreadable") 17 | ), 18 | iterator: d("", (NativeSymbol && NativeSymbol.iterator) || SymbolPolyfill("iterator")), 19 | match: d("", (NativeSymbol && NativeSymbol.match) || SymbolPolyfill("match")), 20 | replace: d("", (NativeSymbol && NativeSymbol.replace) || SymbolPolyfill("replace")), 21 | search: d("", (NativeSymbol && NativeSymbol.search) || SymbolPolyfill("search")), 22 | species: d("", (NativeSymbol && NativeSymbol.species) || SymbolPolyfill("species")), 23 | split: d("", (NativeSymbol && NativeSymbol.split) || SymbolPolyfill("split")), 24 | toPrimitive: d( 25 | "", (NativeSymbol && NativeSymbol.toPrimitive) || SymbolPolyfill("toPrimitive") 26 | ), 27 | toStringTag: d( 28 | "", (NativeSymbol && NativeSymbol.toStringTag) || SymbolPolyfill("toStringTag") 29 | ), 30 | unscopables: d( 31 | "", (NativeSymbol && NativeSymbol.unscopables) || SymbolPolyfill("unscopables") 32 | ) 33 | }); 34 | }; 35 | -------------------------------------------------------------------------------- /CHANGES: -------------------------------------------------------------------------------- 1 | For recent changelog see CHANGELOG.md 2 | 3 | ----- 4 | 5 | v3.1.1 -- 2017.03.15 6 | * Improve documentation 7 | * Improve error messages 8 | * Update dependencies 9 | 10 | v3.1.0 -- 2016.06.03 11 | * Fix internals of symbol detection 12 | * Ensure Symbol.prototype[Symbol.toPrimitive] in all cases returns primitive value 13 | (fixes Node v6 support) 14 | * Create native symbols whenver possible 15 | 16 | v3.0.2 -- 2015.12.12 17 | * Fix definition flow, so uneven state of Symbol implementation doesn't crash initialization of 18 | polyfill. See #13 19 | 20 | v3.0.1 -- 2015.10.22 21 | * Workaround for IE11 bug (reported in #12) 22 | 23 | v3.0.0 -- 2015.10.02 24 | * Reuse native symbols (e.g. iterator, toStringTag etc.) in a polyfill if they're available 25 | Otherwise polyfill symbols may not be recognized by other functions 26 | * Improve documentation 27 | 28 | v2.0.1 -- 2015.01.28 29 | * Fix Symbol.prototype[Symbol.isPrimitive] implementation 30 | * Improve validation within Symbol.prototype.toString and 31 | Symbol.prototype.valueOf 32 | 33 | v2.0.0 -- 2015.01.28 34 | * Update up to changes in specification: 35 | * Implement `for` and `keyFor` 36 | * Remove `Symbol.create` and `Symbol.isRegExp` 37 | * Add `Symbol.match`, `Symbol.replace`, `Symbol.search`, `Symbol.species` and 38 | `Symbol.split` 39 | * Rename `validSymbol` to `validateSymbol` 40 | * Improve documentation 41 | * Remove dead test modules 42 | 43 | v1.0.0 -- 2015.01.26 44 | * Fix enumerability for symbol properties set normally (e.g. obj[symbol] = value) 45 | * Introduce initialization via hidden constructor 46 | * Fix isSymbol handling of polyfill values when native Symbol is present 47 | * Fix spelling of LICENSE 48 | * Configure lint scripts 49 | 50 | v0.1.1 -- 2014.10.07 51 | * Fix isImplemented, so it returns true in case of polyfill 52 | * Improve documentations 53 | 54 | v0.1.0 -- 2014.04.28 55 | * Assure strictly npm dependencies 56 | * Update to use latest versions of dependencies 57 | * Fix implementation detection so it doesn't crash on `String(symbol)` 58 | * throw on `new Symbol()` (as decided by TC39) 59 | 60 | v0.0.0 -- 2013.11.15 61 | * Initial (dev) version 62 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "es6-symbol", 3 | "version": "3.1.4", 4 | "description": "ECMAScript 6 Symbol polyfill", 5 | "author": "Mariusz Nowak (http://www.medikoo.com/)", 6 | "keywords": [ 7 | "symbol", 8 | "private", 9 | "property", 10 | "es6", 11 | "ecmascript", 12 | "harmony", 13 | "ponyfill", 14 | "polyfill" 15 | ], 16 | "repository": "medikoo/es6-symbol", 17 | "dependencies": { 18 | "d": "^1.0.2", 19 | "ext": "^1.7.0" 20 | }, 21 | "devDependencies": { 22 | "eslint": "^8.57.0", 23 | "eslint-config-medikoo": "^4.2.0", 24 | "git-list-updated": "^1.2.1", 25 | "github-release-from-cc-changelog": "^2.3.0", 26 | "husky": "^4.3.8", 27 | "lint-staged": "~13.2.3", 28 | "nyc": "^15.1.0", 29 | "prettier-elastic": "^2.8.8", 30 | "tad": "^3.1.1" 31 | }, 32 | "eslintConfig": { 33 | "extends": "medikoo/es5", 34 | "root": true, 35 | "rules": { 36 | "new-cap": [ 37 | "error", 38 | { 39 | "capIsNewExceptions": [ 40 | "NativeSymbol", 41 | "SymbolPolyfill" 42 | ] 43 | } 44 | ] 45 | }, 46 | "overrides": [ 47 | { 48 | "files": [ 49 | "polyfill.js" 50 | ], 51 | "rules": { 52 | "func-names": "off" 53 | } 54 | }, 55 | { 56 | "files": [ 57 | "test/*.js" 58 | ], 59 | "globals": { 60 | "Symbol": true 61 | } 62 | } 63 | ] 64 | }, 65 | "prettier": { 66 | "printWidth": 100, 67 | "tabWidth": 4, 68 | "overrides": [ 69 | { 70 | "files": [ 71 | "*.md", 72 | "*.yml" 73 | ], 74 | "options": { 75 | "tabWidth": 2 76 | } 77 | } 78 | ] 79 | }, 80 | "husky": { 81 | "hooks": { 82 | "pre-commit": "lint-staged" 83 | } 84 | }, 85 | "lint-staged": { 86 | "*.js": [ 87 | "eslint" 88 | ], 89 | "*.{css,html,js,json,md,yaml,yml}": [ 90 | "prettier -c" 91 | ] 92 | }, 93 | "scripts": { 94 | "coverage": "nyc npm test", 95 | "lint": "eslint --ignore-path=.gitignore .", 96 | "lint:updated": "pipe-git-updated --ext=js -- eslint --ignore-pattern '!*'", 97 | "prettier-check": "prettier -c --ignore-path .gitignore \"**/*.{css,html,js,json,md,yaml,yml}\"", 98 | "prettier-check:updated": "pipe-git-updated --ext=css --ext=html --ext=js --ext=json --ext=md --ext=yaml --ext=yml -- prettier -c", 99 | "prettify": "prettier --write --ignore-path .gitignore \"**/*.{css,html,js,json,md,yaml,yml}\"", 100 | "prettify:updated": "pipe-git-updated --ext=css --ext=html --ext=js --ext=json --ext=md --ext=yaml --ext=yml -- prettier --write", 101 | "test": "tad" 102 | }, 103 | "engines": { 104 | "node": ">=0.12" 105 | }, 106 | "license": "ISC" 107 | } 108 | -------------------------------------------------------------------------------- /polyfill.js: -------------------------------------------------------------------------------- 1 | // ES2015 Symbol polyfill for environments that do not (or partially) support it 2 | 3 | "use strict"; 4 | 5 | var d = require("d") 6 | , validateSymbol = require("./validate-symbol") 7 | , NativeSymbol = require("ext/global-this").Symbol 8 | , generateName = require("./lib/private/generate-name") 9 | , setupStandardSymbols = require("./lib/private/setup/standard-symbols") 10 | , setupSymbolRegistry = require("./lib/private/setup/symbol-registry"); 11 | 12 | var create = Object.create 13 | , defineProperties = Object.defineProperties 14 | , defineProperty = Object.defineProperty; 15 | 16 | var SymbolPolyfill, HiddenSymbol, isNativeSafe; 17 | 18 | if (typeof NativeSymbol === "function") { 19 | try { 20 | String(NativeSymbol()); 21 | isNativeSafe = true; 22 | } catch (ignore) {} 23 | } else { 24 | NativeSymbol = null; 25 | } 26 | 27 | // Internal constructor (not one exposed) for creating Symbol instances. 28 | // This one is used to ensure that `someSymbol instanceof Symbol` always return false 29 | HiddenSymbol = function Symbol(description) { 30 | if (this instanceof HiddenSymbol) throw new TypeError("Symbol is not a constructor"); 31 | return SymbolPolyfill(description); 32 | }; 33 | 34 | // Exposed `Symbol` constructor 35 | // (returns instances of HiddenSymbol) 36 | module.exports = SymbolPolyfill = function Symbol(description) { 37 | var symbol; 38 | if (this instanceof Symbol) throw new TypeError("Symbol is not a constructor"); 39 | if (isNativeSafe) return NativeSymbol(description); 40 | symbol = create(HiddenSymbol.prototype); 41 | description = description === undefined ? "" : String(description); 42 | return defineProperties(symbol, { 43 | __description__: d("", description), 44 | __name__: d("", generateName(description)) 45 | }); 46 | }; 47 | 48 | setupStandardSymbols(SymbolPolyfill); 49 | setupSymbolRegistry(SymbolPolyfill); 50 | 51 | // Internal tweaks for real symbol producer 52 | defineProperties(HiddenSymbol.prototype, { 53 | constructor: d(SymbolPolyfill), 54 | toString: d("", function () { return this.__name__; }) 55 | }); 56 | 57 | // Proper implementation of methods exposed on Symbol.prototype 58 | // They won't be accessible on produced symbol instances as they derive from HiddenSymbol.prototype 59 | defineProperties(SymbolPolyfill.prototype, { 60 | toString: d(function () { return "Symbol (" + validateSymbol(this).__description__ + ")"; }), 61 | valueOf: d(function () { return validateSymbol(this); }) 62 | }); 63 | defineProperty( 64 | SymbolPolyfill.prototype, SymbolPolyfill.toPrimitive, 65 | d("", function () { 66 | var symbol = validateSymbol(this); 67 | if (typeof symbol === "symbol") return symbol; 68 | return symbol.toString(); 69 | }) 70 | ); 71 | defineProperty(SymbolPolyfill.prototype, SymbolPolyfill.toStringTag, d("c", "Symbol")); 72 | 73 | // Proper implementaton of toPrimitive and toStringTag for returned symbol instances 74 | defineProperty( 75 | HiddenSymbol.prototype, SymbolPolyfill.toStringTag, 76 | d("c", SymbolPolyfill.prototype[SymbolPolyfill.toStringTag]) 77 | ); 78 | 79 | // Note: It's important to define `toPrimitive` as last one, as some implementations 80 | // implement `toPrimitive` natively without implementing `toStringTag` (or other specified symbols) 81 | // And that may invoke error in definition flow: 82 | // See: https://github.com/medikoo/es6-symbol/issues/13#issuecomment-164146149 83 | defineProperty( 84 | HiddenSymbol.prototype, SymbolPolyfill.toPrimitive, 85 | d("c", SymbolPolyfill.prototype[SymbolPolyfill.toPrimitive]) 86 | ); 87 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build status][build-image]][build-url] 2 | [![Tests coverage][cov-image]][cov-url] 3 | [![npm version][npm-image]][npm-url] 4 | 5 | # es6-symbol 6 | 7 | ## ECMAScript 6 Symbol polyfill 8 | 9 | For more information about symbols see following links 10 | 11 | - [Symbols in ECMAScript 6 by Axel Rauschmayer](http://www.2ality.com/2014/12/es6-symbols.html) 12 | - [MDN Documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol) 13 | - [Specification](https://tc39.github.io/ecma262/#sec-symbol-objects) 14 | 15 | ### Limitations 16 | 17 | Underneath it uses real string property names which can easily be retrieved, however accidental collision with other property names is unlikely. 18 | 19 | ### Usage 20 | 21 | If you'd like to use native version when it exists and fallback to [ponyfill](https://ponyfill.com) if it doesn't, use _es6-symbol_ as following: 22 | 23 | ```javascript 24 | var Symbol = require("es6-symbol"); 25 | ``` 26 | 27 | If you want to make sure your environment implements `Symbol` globally, do: 28 | 29 | ```javascript 30 | require("es6-symbol/implement"); 31 | ``` 32 | 33 | If you strictly want to use polyfill even if native `Symbol` exists (hard to find a good reason for that), do: 34 | 35 | ```javascript 36 | var Symbol = require("es6-symbol/polyfill"); 37 | ``` 38 | 39 | #### API 40 | 41 | Best is to refer to [specification](https://tc39.github.io/ecma262/#sec-symbol-objects). Still if you want quick look, follow examples: 42 | 43 | ```javascript 44 | var Symbol = require("es6-symbol"); 45 | 46 | var symbol = Symbol("My custom symbol"); 47 | var x = {}; 48 | 49 | x[symbol] = "foo"; 50 | console.log(x[symbol]); 51 | ("foo"); 52 | 53 | // Detect iterable: 54 | var iterator, result; 55 | if (possiblyIterable[Symbol.iterator]) { 56 | iterator = possiblyIterable[Symbol.iterator](); 57 | result = iterator.next(); 58 | while (!result.done) { 59 | console.log(result.value); 60 | result = iterator.next(); 61 | } 62 | } 63 | ``` 64 | 65 | ### Installation 66 | 67 | #### NPM 68 | 69 | In your project path: 70 | 71 | $ npm install es6-symbol 72 | 73 | ##### Browser 74 | 75 | To port it to Browser or any other (non CJS) environment, use your favorite CJS bundler. No favorite yet? Try: [Browserify](http://browserify.org/), [Webmake](https://github.com/medikoo/modules-webmake) or [Webpack](http://webpack.github.io/) 76 | 77 | ## Tests 78 | 79 | $ npm test 80 | 81 | ## Security contact information 82 | 83 | To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure. 84 | 85 | --- 86 | 87 |
88 | 89 | Get professional support for d with a Tidelift subscription 90 | 91 |
92 | 93 | Tidelift helps make open source sustainable for maintainers while giving companies
assurances about security, maintenance, and licensing for their dependencies. 94 |
95 |
96 | 97 | [build-image]: https://github.com/medikoo/es6-symbol/workflows/Integrate/badge.svg 98 | [build-url]: https://github.com/medikoo/es6-symbol/actions?query=workflow%3AIntegrate 99 | [cov-image]: https://img.shields.io/codecov/c/github/medikoo/es6-symbol.svg 100 | [cov-url]: https://codecov.io/gh/medikoo/es6-symbol 101 | [npm-image]: https://img.shields.io/npm/v/es6-symbol.svg 102 | [npm-url]: https://www.npmjs.com/package/es6-symbol 103 | --------------------------------------------------------------------------------