├── .editorconfig ├── .github └── FUNDING.yml ├── .gitignore ├── CHANGELOG.md ├── CHANGES ├── LICENSE ├── README.md ├── implement.js ├── index.js ├── is-implemented.js ├── is-native-implemented.js ├── is-weak-map.js ├── package.json ├── polyfill.js ├── test ├── implement.js ├── index.js ├── is-implemented.js ├── is-native-implemented.js ├── is-weak-map.js ├── polyfill.js └── valid-weak-map.js └── valid-weak-map.js /.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 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: medikoo 2 | tidelift: "npm/es6-weak-map" 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | npm-debug.log 3 | /package-lock.json 4 | -------------------------------------------------------------------------------- /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 | ### [2.0.3](https://github.com/medikoo/es6-weak-map/compare/v2.0.2...v2.0.3) (2019-06-07) 6 | 7 | ## Changelog for previous versions 8 | 9 | See `CHANGES` file 10 | -------------------------------------------------------------------------------- /CHANGES: -------------------------------------------------------------------------------- 1 | For recent changelog see CHANGELOG.md 2 | 3 | ----- 4 | 5 | v2.0.2 -- 2017.03.15 6 | * Update dependencies 7 | 8 | v2.0.1 -- 2015.10.02 9 | * Update to use es6-symbol at v3 10 | 11 | v2.0.0 -- 2015.09.04 12 | * Relax native implementation detection, stringification of instance should returm 13 | expected result (not necesarily prototype) 14 | 15 | v1.0.2 -- 2015.05.07 16 | * Add "ponyfill" keyword to meta description. Fixes #7 17 | 18 | v1.0.1 -- 2015.04.14 19 | * Fix isNativeImplemented, so it's not affected by #3619 V8 bug 20 | * Fix internal prototype resolution, in case where isNativeImplemented was true, and 21 | native implementation was shadowed it got into stack overflow 22 | 23 | v1.0.0 -- 2015.04.13 24 | * It's v0.1.3 republished as v1.0.0 25 | 26 | v0.1.4 -- 2015.04.13 27 | * Republish v0.1.2 as v0.1.4 due to breaking changes 28 | (v0.1.3 should have been published as next major) 29 | 30 | v0.1.3 -- 2015.04.12 31 | * Update up to changes in specification (require new, remove clear method) 32 | * Improve native implementation validation 33 | * Configure lint scripts 34 | * Rename LICENCE to LICENSE 35 | 36 | v0.1.2 -- 2014.09.01 37 | * Use internal random and unique id generator instead of external (time-uuid based). 38 | Global uniqueness is not needed in scope of this module. Fixes #1 39 | 40 | v0.1.1 -- 2014.05.15 41 | * Improve valid WeakMap detection 42 | 43 | v0.1.0 -- 2014.04.29 44 | * Assure to depend only npm hosted dependencies 45 | * Update to use latest versions of dependencies 46 | * Use ES6 symbols internally 47 | 48 | v0.0.0 -- 2013.10.24 49 | Initial (dev version) 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright (c) 2013-2019, 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build status][nix-build-image]][nix-build-url] 2 | [![Windows status][win-build-image]][win-build-url] 3 | ![Transpilation status][transpilation-image] 4 | [![npm version][npm-image]][npm-url] 5 | 6 | # es6-weak-map 7 | 8 | ## WeakMap collection as specified in ECMAScript6 9 | 10 | _Roughly inspired by Mark Miller's and Kris Kowal's [WeakMap implementation](https://github.com/drses/weak-map)_. 11 | 12 | Differences are: 13 | 14 | - Assumes compliant ES5 environment (no weird ES3 workarounds or hacks) 15 | - Well modularized CJS style 16 | - Based on one solution. 17 | 18 | ### Limitations 19 | 20 | - Will fail on non extensible objects provided as keys 21 | 22 | ### Installation 23 | 24 | $ npm install es6-weak-map 25 | 26 | 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/) 27 | 28 | ### Usage 29 | 30 | If you want to make sure your environment implements `WeakMap`, do: 31 | 32 | ```javascript 33 | require("es6-weak-map/implement"); 34 | ``` 35 | 36 | If you'd like to use native version when it exists and fallback to polyfill if it doesn't, but without implementing `WeakMap` on global scope, do: 37 | 38 | ```javascript 39 | var WeakMap = require("es6-weak-map"); 40 | ``` 41 | 42 | If you strictly want to use polyfill even if native `WeakMap` exists, do: 43 | 44 | ```javascript 45 | var WeakMap = require("es6-weak-map/polyfill"); 46 | ``` 47 | 48 | #### API 49 | 50 | Best is to refer to [specification](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-weakmap-objects). Still if you want quick look, follow example: 51 | 52 | ```javascript 53 | var WeakMap = require("es6-weak-map"); 54 | 55 | var map = new WeakMap(); 56 | var obj = {}; 57 | 58 | map.set(obj, "foo"); // map 59 | map.get(obj); // 'foo' 60 | map.has(obj); // true 61 | map.delete(obj); // true 62 | map.get(obj); // undefined 63 | map.has(obj); // false 64 | map.set(obj, "bar"); // map 65 | map.has(obj); // false 66 | ``` 67 | 68 | ## Tests 69 | 70 | $ npm test 71 | 72 | ## Security contact information 73 | 74 | To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure. 75 | 76 | --- 77 | 78 |
79 | 80 | Get professional support for d with a Tidelift subscription 81 | 82 |
83 | 84 | Tidelift helps make open source sustainable for maintainers while giving companies
assurances about security, maintenance, and licensing for their dependencies. 85 |
86 |
87 | 88 | [nix-build-image]: https://semaphoreci.com/api/v1/medikoo-org/es6-weak-map/branches/master/shields_badge.svg 89 | [nix-build-url]: https://semaphoreci.com/medikoo-org/es6-weak-map 90 | [win-build-image]: https://ci.appveyor.com/api/projects/status/1c73c57pg4s6lwmu?svg=true 91 | [win-build-url]: https://ci.appveyor.com/project/medikoo/es6-weak-map 92 | [transpilation-image]: https://img.shields.io/badge/transpilation-free-brightgreen.svg 93 | [npm-image]: https://img.shields.io/npm/v/es6-weak-map.svg 94 | [npm-url]: https://www.npmjs.com/package/es6-weak-map 95 | -------------------------------------------------------------------------------- /implement.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | if (!require("./is-implemented")()) { 4 | Object.defineProperty(require("es5-ext/global"), "WeakMap", { 5 | value: require("./polyfill"), 6 | configurable: true, 7 | enumerable: false, 8 | writable: true 9 | }); 10 | } 11 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = require("./is-implemented")() ? WeakMap : require("./polyfill"); 4 | -------------------------------------------------------------------------------- /is-implemented.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = function () { 4 | var weakMap, obj; 5 | 6 | if (typeof WeakMap !== "function") return false; 7 | try { 8 | // WebKit doesn't support arguments and crashes 9 | weakMap = new WeakMap([[(obj = {}), "one"], [{}, "two"], [{}, "three"]]); 10 | } catch (e) { 11 | return false; 12 | } 13 | if (String(weakMap) !== "[object WeakMap]") return false; 14 | if (typeof weakMap.set !== "function") return false; 15 | if (weakMap.set({}, 1) !== weakMap) return false; 16 | if (typeof weakMap.delete !== "function") return false; 17 | if (typeof weakMap.has !== "function") return false; 18 | if (weakMap.get(obj) !== "one") return false; 19 | 20 | return true; 21 | }; 22 | -------------------------------------------------------------------------------- /is-native-implemented.js: -------------------------------------------------------------------------------- 1 | // Exports true if environment provides native `WeakMap` implementation, whatever that is. 2 | 3 | "use strict"; 4 | 5 | module.exports = (function () { 6 | if (typeof WeakMap !== "function") return false; 7 | return Object.prototype.toString.call(new WeakMap()) === "[object WeakMap]"; 8 | })(); 9 | -------------------------------------------------------------------------------- /is-weak-map.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var toStringTagSymbol = require("es6-symbol").toStringTag 4 | , objToString = Object.prototype.toString 5 | , id = "[object WeakMap]" 6 | , Global = typeof WeakMap === "undefined" ? null : WeakMap; 7 | 8 | module.exports = function (value) { 9 | return ( 10 | (value && 11 | ((Global && value instanceof Global) || 12 | objToString.call(value) === id || 13 | value[toStringTagSymbol] === "WeakMap")) || 14 | false 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "es6-weak-map", 3 | "version": "2.0.3", 4 | "description": "ECMAScript6 WeakMap polyfill", 5 | "author": "Mariusz Nowak (http://www.medikoo.com/)", 6 | "keywords": [ 7 | "map", 8 | "weakmap", 9 | "collection", 10 | "es6", 11 | "harmony", 12 | "list", 13 | "hash", 14 | "gc", 15 | "ponyfill" 16 | ], 17 | "repository": { 18 | "type": "git", 19 | "url": "git://github.com/medikoo/es6-weak-map.git" 20 | }, 21 | "dependencies": { 22 | "d": "^1.0.1", 23 | "es5-ext": "^0.10.50", 24 | "es6-iterator": "^2.0.3", 25 | "es6-symbol": "^3.1.1" 26 | }, 27 | "devDependencies": { 28 | "eslint": "^5.16.0", 29 | "eslint-config-medikoo-es5": "^2.0.0", 30 | "git-list-updated": "^1.1.2", 31 | "husky": "^2.4.1", 32 | "lint-staged": "^8.2.1", 33 | "prettier-elastic": "^1.18.2", 34 | "tad": "^2.0.1" 35 | }, 36 | "husky": { 37 | "hooks": { 38 | "pre-commit": "lint-staged" 39 | } 40 | }, 41 | "lint-staged": { 42 | "*.js": [ 43 | "eslint" 44 | ], 45 | "*.{css,html,js,json,md,yaml,yml}": [ 46 | "prettier -c" 47 | ] 48 | }, 49 | "eslintConfig": { 50 | "extends": "medikoo-es5", 51 | "root": true, 52 | "globals": { 53 | "WeakMap": true 54 | } 55 | }, 56 | "prettier": { 57 | "printWidth": 100, 58 | "tabWidth": 4, 59 | "overrides": [ 60 | { 61 | "files": [ 62 | "*.md" 63 | ], 64 | "options": { 65 | "tabWidth": 2 66 | } 67 | } 68 | ] 69 | }, 70 | "scripts": { 71 | "lint": "eslint --ignore-path=.gitignore .", 72 | "lint-updated": "pipe-git-updated --ext=js -- eslint --ignore-pattern '!*'", 73 | "prettier-check-updated": "pipe-git-updated --ext=css --ext=html --ext=js --ext=json --ext=md --ext=yaml --ext=yml -- prettier -c", 74 | "prettify": "prettier --write --ignore-path .gitignore '**/*.{css,html,js,json,md,yaml,yml}'", 75 | "test": "node ./node_modules/tad/bin/tad" 76 | }, 77 | "license": "ISC" 78 | } 79 | -------------------------------------------------------------------------------- /polyfill.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var isValue = require("es5-ext/object/is-value") 4 | , setPrototypeOf = require("es5-ext/object/set-prototype-of") 5 | , object = require("es5-ext/object/valid-object") 6 | , ensureValue = require("es5-ext/object/valid-value") 7 | , randomUniq = require("es5-ext/string/random-uniq") 8 | , d = require("d") 9 | , getIterator = require("es6-iterator/get") 10 | , forOf = require("es6-iterator/for-of") 11 | , toStringTagSymbol = require("es6-symbol").toStringTag 12 | , isNative = require("./is-native-implemented") 13 | , isArray = Array.isArray 14 | , defineProperty = Object.defineProperty 15 | , objHasOwnProperty = Object.prototype.hasOwnProperty 16 | , getPrototypeOf = Object.getPrototypeOf 17 | , WeakMapPoly; 18 | 19 | module.exports = WeakMapPoly = function (/* Iterable*/) { 20 | var iterable = arguments[0], self; 21 | 22 | if (!(this instanceof WeakMapPoly)) throw new TypeError("Constructor requires 'new'"); 23 | self = 24 | isNative && setPrototypeOf && WeakMap !== WeakMapPoly 25 | ? setPrototypeOf(new WeakMap(), getPrototypeOf(this)) 26 | : this; 27 | 28 | if (isValue(iterable)) { 29 | if (!isArray(iterable)) iterable = getIterator(iterable); 30 | } 31 | defineProperty(self, "__weakMapData__", d("c", "$weakMap$" + randomUniq())); 32 | if (!iterable) return self; 33 | forOf(iterable, function (val) { 34 | ensureValue(val); 35 | self.set(val[0], val[1]); 36 | }); 37 | return self; 38 | }; 39 | 40 | if (isNative) { 41 | if (setPrototypeOf) setPrototypeOf(WeakMapPoly, WeakMap); 42 | WeakMapPoly.prototype = Object.create(WeakMap.prototype, { constructor: d(WeakMapPoly) }); 43 | } 44 | 45 | Object.defineProperties(WeakMapPoly.prototype, { 46 | delete: d(function (key) { 47 | if (objHasOwnProperty.call(object(key), this.__weakMapData__)) { 48 | delete key[this.__weakMapData__]; 49 | return true; 50 | } 51 | return false; 52 | }), 53 | get: d(function (key) { 54 | if (!objHasOwnProperty.call(object(key), this.__weakMapData__)) return undefined; 55 | return key[this.__weakMapData__]; 56 | }), 57 | has: d(function (key) { return objHasOwnProperty.call(object(key), this.__weakMapData__); }), 58 | set: d(function (key, value) { 59 | defineProperty(object(key), this.__weakMapData__, d("c", value)); 60 | return this; 61 | }), 62 | toString: d(function () { return "[object WeakMap]"; }) 63 | }); 64 | defineProperty(WeakMapPoly.prototype, toStringTagSymbol, d("c", "WeakMap")); 65 | -------------------------------------------------------------------------------- /test/implement.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = function (t, a) { a(typeof WeakMap, "function"); }; 4 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = function (T, a) { 4 | var obj = {}; 5 | 6 | a(new T([[obj, "foo"]]).get(obj), "foo"); 7 | }; 8 | -------------------------------------------------------------------------------- /test/is-implemented.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var globalObj = require("es5-ext/global") 4 | , polyfill = require("../polyfill"); 5 | 6 | module.exports = function (t, a) { 7 | var cache; 8 | 9 | a(typeof t(), "boolean"); 10 | cache = globalObj.WeakMap; 11 | globalObj.WeakMap = polyfill; 12 | a(t(), true); 13 | if (cache === undefined) delete globalObj.WeakMap; 14 | else globalObj.WeakMap = cache; 15 | }; 16 | -------------------------------------------------------------------------------- /test/is-native-implemented.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = function (t, a) { a(typeof t, "boolean"); }; 4 | -------------------------------------------------------------------------------- /test/is-weak-map.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var WeakMapPoly = 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 WeakMap !== "undefined") { 13 | a(t(new WeakMap()), true, "Native"); 14 | } 15 | a(t(new WeakMapPoly()), true, "Polyfill"); 16 | }; 17 | -------------------------------------------------------------------------------- /test/polyfill.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = function (T, a) { 4 | var obj1 = {}, obj2 = {}, obj3 = {}, arr = [[obj1, "raz"], [obj2, "dwa"]], map = new T(arr); 5 | 6 | a(map instanceof T, true, "WeakMap"); 7 | a(map.has(obj1), true, "Has: true"); 8 | a(map.get(obj1), "raz", "Get: contains"); 9 | a(map.has(obj3), false, "Has: false"); 10 | a(map.get(obj3), undefined, "Get: doesn't contain"); 11 | a(map.set(obj3, "trzy"), map, "Set: return"); 12 | a(map.has(obj3), true, "Add"); 13 | a(map.delete({}), false, "Delete: false"); 14 | 15 | a(map.delete(obj1), true, "Delete: true"); 16 | a(map.get(obj1), undefined, "Get: after delete"); 17 | a(map.has(obj1), false, "Has: after delete"); 18 | 19 | a.h1("Empty initialization"); 20 | map = new T(); 21 | map.set(obj1, "bar"); 22 | a(map.get(obj1), "bar"); 23 | }; 24 | -------------------------------------------------------------------------------- /test/valid-weak-map.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var WeakMapPoly = require("../polyfill"); 4 | 5 | module.exports = function (t, a) { 6 | var map; 7 | 8 | a.throws(function () { t(undefined); }, TypeError, "Undefined"); 9 | a.throws(function () { t(null); }, TypeError, "Null"); 10 | a.throws(function () { t(true); }, TypeError, "Primitive"); 11 | a.throws(function () { t("raz"); }, TypeError, "String"); 12 | a.throws(function () { t({}); }, TypeError, "Object"); 13 | a.throws(function () { t([]); }, TypeError, "Array"); 14 | if (typeof WeakMap !== "undefined") { 15 | map = new WeakMap(); 16 | a(t(map), map, "Native"); 17 | } 18 | map = new WeakMapPoly(); 19 | a(t(map), map, "Polyfill"); 20 | }; 21 | -------------------------------------------------------------------------------- /valid-weak-map.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var isWeakMap = require("./is-weak-map"); 4 | 5 | module.exports = function (value) { 6 | if (!isWeakMap(value)) throw new TypeError(value + " is not a WeakMap"); 7 | return value; 8 | }; 9 | --------------------------------------------------------------------------------