├── .editorconfig ├── .github ├── FUNDING.yml └── workflows │ ├── integrate.yml │ ├── publish.yml │ └── validate.yml ├── .gitignore ├── .npmignore ├── CHANGELOG.md ├── CHANGES ├── LICENSE ├── README.md ├── auto-bind.js ├── commitlint.config.js ├── index.js ├── lazy.js ├── package.json └── test ├── auto-bind.js ├── index.js └── lazy.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 | 17 | [*.md] 18 | trim_trailing_whitespace = false 19 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: medikoo 2 | tidelift: "npm/d" 3 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.nyc_output 2 | /coverage 3 | /node_modules 4 | npm-debug.log 5 | /package-lock.json 6 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | /.editorconfig 2 | /.github 3 | /commitlint.config.js 4 | /test 5 | -------------------------------------------------------------------------------- /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 | ### [1.0.2](https://github.com/medikoo/d/compare/v1.0.1...v1.0.2) (2024-03-01) 6 | 7 | ### Maintenance Improvements 8 | 9 | - Upgrade `type` to v2 ([43b0eb8](https://github.com/medikoo/d/commit/43b0eb845d9efad3450e0e641ea1a827a5ba1966)) 10 | 11 | ### [1.0.1](https://github.com/medikoo/d/compare/v0.1.1...v1.0.1) (2019-06-14) 12 | 13 | ## Changelog for previous versions 14 | 15 | See `CHANGES` file 16 | -------------------------------------------------------------------------------- /CHANGES: -------------------------------------------------------------------------------- 1 | For recent changelog see CHANGELOG.md 2 | 3 | ----- 4 | 5 | v1.0.0 -- 2015.12.04 6 | - autoBind changes: 7 | - replace `bindTo` argument with options and `resolveContext` option 8 | - Add support `overwriteDefinition` 9 | - Introduce IE11 bug workaround in `lazy` handler 10 | 11 | v0.1.1 -- 2014.04.24 12 | - Add `autoBind` and `lazy` utilities 13 | - Allow to pass other options to be merged onto created descriptor. 14 | Useful when used with other custom utilties 15 | 16 | v0.1.0 -- 2013.06.20 17 | Initial (derived from es5-ext project) 18 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | # d 6 | 7 | ## Property descriptor factory 8 | 9 | _Originally derived from [d](https://github.com/medikoo/d) package._ 10 | 11 | Defining properties with descriptors is very verbose: 12 | 13 | ```javascript 14 | var Account = function () {}; 15 | Object.defineProperties(Account.prototype, { 16 | deposit: { 17 | value: function () { /* ... */ }, 18 | configurable: true, 19 | enumerable: false, 20 | writable: true 21 | }, 22 | withdraw: { 23 | value: function () { /* ... */ }, 24 | configurable: true, 25 | enumerable: false, 26 | writable: true 27 | }, 28 | balance: { get: function () { /* ... */ }, configurable: true, enumerable: false } 29 | }); 30 | ``` 31 | 32 | D cuts that to: 33 | 34 | ```javascript 35 | var d = require("d"); 36 | 37 | var Account = function () {}; 38 | Object.defineProperties(Account.prototype, { 39 | deposit: d(function () { /* ... */ }), 40 | withdraw: d(function () { /* ... */ }), 41 | balance: d.gs(function () { /* ... */ }) 42 | }); 43 | ``` 44 | 45 | By default, created descriptor follow characteristics of native ES5 properties, and defines values as: 46 | 47 | ```javascript 48 | { configurable: true, enumerable: false, writable: true } 49 | ``` 50 | 51 | You can overwrite it by preceding _value_ argument with instruction: 52 | 53 | ```javascript 54 | d("c", value); // { configurable: true, enumerable: false, writable: false } 55 | d("ce", value); // { configurable: true, enumerable: true, writable: false } 56 | d("e", value); // { configurable: false, enumerable: true, writable: false } 57 | 58 | // Same way for get/set: 59 | d.gs("e", value); // { configurable: false, enumerable: true } 60 | ``` 61 | 62 | ### Installation 63 | 64 | $ npm install d 65 | 66 | 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/) 67 | 68 | ### Other utilities 69 | 70 | #### autoBind(obj, props) _(d/auto-bind)_ 71 | 72 | Define methods which will be automatically bound to its instances 73 | 74 | ```javascript 75 | var d = require('d'); 76 | var autoBind = require('d/auto-bind'); 77 | 78 | var Foo = function () { this._count = 0; }; 79 | Object.defineProperties(Foo.prototype, autoBind({ 80 | increment: d(function () { ++this._count; }); 81 | })); 82 | 83 | var foo = new Foo(); 84 | 85 | // Increment foo counter on each domEl click 86 | domEl.addEventListener('click', foo.increment, false); 87 | ``` 88 | 89 | #### lazy(obj, props) _(d/lazy)_ 90 | 91 | Define lazy properties, which will be resolved on first access 92 | 93 | ```javascript 94 | var d = require("d"); 95 | var lazy = require("d/lazy"); 96 | 97 | var Foo = function () {}; 98 | Object.defineProperties(Foo.prototype, lazy({ items: d(function () { return []; }) })); 99 | 100 | var foo = new Foo(); 101 | foo.items.push(1, 2); // foo.items array created and defined directly on foo 102 | ``` 103 | 104 | ## Tests 105 | 106 | $ npm test 107 | 108 | ## Security contact information 109 | 110 | To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure. 111 | 112 | --- 113 | 114 |
115 | 116 | Get professional support for d with a Tidelift subscription 117 | 118 |
119 | 120 | Tidelift helps make open source sustainable for maintainers while giving companies
assurances about security, maintenance, and licensing for their dependencies. 121 |
122 |
123 | 124 | [build-image]: https://github.com/medikoo/d/workflows/Integrate/badge.svg 125 | [build-url]: https://github.com/medikoo/d/actions?query=workflow%3AIntegrate 126 | [cov-image]: https://img.shields.io/codecov/c/github/medikoo/d.svg 127 | [cov-url]: https://codecov.io/gh/medikoo/d 128 | [npm-image]: https://img.shields.io/npm/v/d.svg 129 | [npm-url]: https://www.npmjs.com/package/d 130 | -------------------------------------------------------------------------------- /auto-bind.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var isValue = require("type/value/is") 4 | , ensureValue = require("type/value/ensure") 5 | , ensurePlainFunction = require("type/plain-function/ensure") 6 | , copy = require("es5-ext/object/copy") 7 | , normalizeOptions = require("es5-ext/object/normalize-options") 8 | , map = require("es5-ext/object/map"); 9 | 10 | var bind = Function.prototype.bind 11 | , defineProperty = Object.defineProperty 12 | , hasOwnProperty = Object.prototype.hasOwnProperty 13 | , define; 14 | 15 | define = function (name, desc, options) { 16 | var value = ensureValue(desc) && ensurePlainFunction(desc.value), dgs; 17 | dgs = copy(desc); 18 | delete dgs.writable; 19 | delete dgs.value; 20 | dgs.get = function () { 21 | if (!options.overwriteDefinition && hasOwnProperty.call(this, name)) return value; 22 | desc.value = bind.call(value, options.resolveContext ? options.resolveContext(this) : this); 23 | defineProperty(this, name, desc); 24 | return this[name]; 25 | }; 26 | return dgs; 27 | }; 28 | 29 | module.exports = function (props/*, options*/) { 30 | var options = normalizeOptions(arguments[1]); 31 | if (isValue(options.resolveContext)) ensurePlainFunction(options.resolveContext); 32 | return map(props, function (desc, name) { return define(name, desc, options); }); 33 | }; 34 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var isValue = require("type/value/is") 4 | , isPlainFunction = require("type/plain-function/is") 5 | , assign = require("es5-ext/object/assign") 6 | , normalizeOpts = require("es5-ext/object/normalize-options") 7 | , contains = require("es5-ext/string/#/contains"); 8 | 9 | var d = (module.exports = function (dscr, value/*, options*/) { 10 | var c, e, w, options, desc; 11 | if (arguments.length < 2 || typeof dscr !== "string") { 12 | options = value; 13 | value = dscr; 14 | dscr = null; 15 | } else { 16 | options = arguments[2]; 17 | } 18 | if (isValue(dscr)) { 19 | c = contains.call(dscr, "c"); 20 | e = contains.call(dscr, "e"); 21 | w = contains.call(dscr, "w"); 22 | } else { 23 | c = w = true; 24 | e = false; 25 | } 26 | 27 | desc = { value: value, configurable: c, enumerable: e, writable: w }; 28 | return !options ? desc : assign(normalizeOpts(options), desc); 29 | }); 30 | 31 | d.gs = function (dscr, get, set/*, options*/) { 32 | var c, e, options, desc; 33 | if (typeof dscr !== "string") { 34 | options = set; 35 | set = get; 36 | get = dscr; 37 | dscr = null; 38 | } else { 39 | options = arguments[3]; 40 | } 41 | if (!isValue(get)) { 42 | get = undefined; 43 | } else if (!isPlainFunction(get)) { 44 | options = get; 45 | get = set = undefined; 46 | } else if (!isValue(set)) { 47 | set = undefined; 48 | } else if (!isPlainFunction(set)) { 49 | options = set; 50 | set = undefined; 51 | } 52 | if (isValue(dscr)) { 53 | c = contains.call(dscr, "c"); 54 | e = contains.call(dscr, "e"); 55 | } else { 56 | c = true; 57 | e = false; 58 | } 59 | 60 | desc = { get: get, set: set, configurable: c, enumerable: e }; 61 | return !options ? desc : assign(normalizeOpts(options), desc); 62 | }; 63 | -------------------------------------------------------------------------------- /lazy.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var isPlainFunction = require("type/plain-function/is") 4 | , ensureValue = require("type/value/ensure") 5 | , isValue = require("type/value/is") 6 | , map = require("es5-ext/object/map") 7 | , contains = require("es5-ext/string/#/contains"); 8 | 9 | var call = Function.prototype.call 10 | , defineProperty = Object.defineProperty 11 | , getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor 12 | , getPrototypeOf = Object.getPrototypeOf 13 | , hasOwnProperty = Object.prototype.hasOwnProperty 14 | , cacheDesc = { configurable: false, enumerable: false, writable: false, value: null } 15 | , define; 16 | 17 | define = function (name, options) { 18 | var value, dgs, cacheName, desc, writable = false, resolvable, flat; 19 | options = Object(ensureValue(options)); 20 | cacheName = options.cacheName; 21 | flat = options.flat; 22 | if (!isValue(cacheName)) cacheName = name; 23 | delete options.cacheName; 24 | value = options.value; 25 | resolvable = isPlainFunction(value); 26 | delete options.value; 27 | dgs = { configurable: Boolean(options.configurable), enumerable: Boolean(options.enumerable) }; 28 | if (name !== cacheName) { 29 | dgs.get = function () { 30 | if (hasOwnProperty.call(this, cacheName)) return this[cacheName]; 31 | cacheDesc.value = resolvable ? call.call(value, this, options) : value; 32 | cacheDesc.writable = writable; 33 | defineProperty(this, cacheName, cacheDesc); 34 | cacheDesc.value = null; 35 | if (desc) defineProperty(this, name, desc); 36 | return this[cacheName]; 37 | }; 38 | } else if (!flat) { 39 | dgs.get = function self() { 40 | var ownDesc; 41 | if (hasOwnProperty.call(this, name)) { 42 | ownDesc = getOwnPropertyDescriptor(this, name); 43 | // It happens in Safari, that getter is still called after property 44 | // was defined with a value, following workarounds that 45 | // While in IE11 it may happen that here ownDesc is undefined (go figure) 46 | if (ownDesc) { 47 | if (ownDesc.hasOwnProperty("value")) return ownDesc.value; 48 | if (typeof ownDesc.get === "function" && ownDesc.get !== self) { 49 | return ownDesc.get.call(this); 50 | } 51 | return value; 52 | } 53 | } 54 | desc.value = resolvable ? call.call(value, this, options) : value; 55 | defineProperty(this, name, desc); 56 | desc.value = null; 57 | return this[name]; 58 | }; 59 | } else { 60 | dgs.get = function self() { 61 | var base = this, ownDesc; 62 | if (hasOwnProperty.call(this, name)) { 63 | // It happens in Safari, that getter is still called after property 64 | // was defined with a value, following workarounds that 65 | ownDesc = getOwnPropertyDescriptor(this, name); 66 | if (ownDesc.hasOwnProperty("value")) return ownDesc.value; 67 | if (typeof ownDesc.get === "function" && ownDesc.get !== self) { 68 | return ownDesc.get.call(this); 69 | } 70 | } 71 | while (!hasOwnProperty.call(base, name)) base = getPrototypeOf(base); 72 | desc.value = resolvable ? call.call(value, base, options) : value; 73 | defineProperty(base, name, desc); 74 | desc.value = null; 75 | return base[name]; 76 | }; 77 | } 78 | dgs.set = function (value) { 79 | if (hasOwnProperty.call(this, name)) { 80 | throw new TypeError("Cannot assign to lazy defined '" + name + "' property of " + this); 81 | } 82 | dgs.get.call(this); 83 | this[cacheName] = value; 84 | }; 85 | if (options.desc) { 86 | desc = { 87 | configurable: contains.call(options.desc, "c"), 88 | enumerable: contains.call(options.desc, "e") 89 | }; 90 | if (cacheName === name) { 91 | desc.writable = contains.call(options.desc, "w"); 92 | desc.value = null; 93 | } else { 94 | writable = contains.call(options.desc, "w"); 95 | desc.get = dgs.get; 96 | desc.set = dgs.set; 97 | } 98 | delete options.desc; 99 | } else if (cacheName === name) { 100 | desc = { 101 | configurable: Boolean(options.configurable), 102 | enumerable: Boolean(options.enumerable), 103 | writable: Boolean(options.writable), 104 | value: null 105 | }; 106 | } 107 | delete options.configurable; 108 | delete options.enumerable; 109 | delete options.writable; 110 | return dgs; 111 | }; 112 | 113 | module.exports = function (props) { 114 | return map(props, function (desc, name) { return define(name, desc); }); 115 | }; 116 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "d", 3 | "version": "1.0.2", 4 | "description": "Property descriptor factory", 5 | "author": "Mariusz Nowak (http://www.medikoo.com/)", 6 | "keywords": [ 7 | "descriptor", 8 | "es", 9 | "ecmascript", 10 | "ecma", 11 | "property", 12 | "descriptors", 13 | "meta", 14 | "properties" 15 | ], 16 | "repository": "medikoo/d", 17 | "dependencies": { 18 | "es5-ext": "^0.10.64", 19 | "type": "^2.7.2" 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 | "husky": { 33 | "hooks": { 34 | "pre-commit": "lint-staged" 35 | } 36 | }, 37 | "lint-staged": { 38 | "*.js": [ 39 | "eslint" 40 | ], 41 | "*.{css,html,js,json,md,yaml,yml}": [ 42 | "prettier -c" 43 | ] 44 | }, 45 | "eslintConfig": { 46 | "extends": "medikoo/es5", 47 | "root": true 48 | }, 49 | "prettier": { 50 | "printWidth": 100, 51 | "tabWidth": 4, 52 | "overrides": [ 53 | { 54 | "files": [ 55 | "*.md", 56 | "*.yml" 57 | ], 58 | "options": { 59 | "tabWidth": 2 60 | } 61 | } 62 | ] 63 | }, 64 | "nyc": { 65 | "all": true, 66 | "exclude": [ 67 | ".github", 68 | "coverage/**", 69 | "test/**", 70 | "*.config.js" 71 | ], 72 | "reporter": [ 73 | "lcov", 74 | "html", 75 | "text-summary" 76 | ] 77 | }, 78 | "scripts": { 79 | "coverage": "nyc npm test", 80 | "lint": "eslint --ignore-path=.gitignore .", 81 | "lint:updated": "pipe-git-updated --base=main --ext=js -- eslint --ignore-pattern '!*'", 82 | "prettier-check": "prettier -c --ignore-path .gitignore \"**/*.{css,html,js,json,md,yaml,yml}\"", 83 | "prettier-check:updated": "pipe-git-updated --base=main --ext=css --ext=html --ext=js --ext=json --ext=md --ext=yaml --ext=yml -- prettier -c", 84 | "prettify": "prettier --write --ignore-path .gitignore \"**/*.{css,html,js,json,md,yaml,yml}\"", 85 | "prettify:updated": "pipe-git-updated ---base=main -ext=css --ext=html --ext=js --ext=json --ext=md --ext=yaml --ext=yml -- prettier --write", 86 | "test": "tad" 87 | }, 88 | "license": "ISC", 89 | "engines": { 90 | "node": ">=0.12" 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /test/auto-bind.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var d = require("../"); 4 | 5 | module.exports = function (t, a) { 6 | var o = Object.defineProperties( 7 | {}, t({ bar: d(function () { return this === o; }), bar2: d(function () { return this; }) }) 8 | ); 9 | 10 | a.deep([o.bar(), o.bar2()], [true, o]); 11 | }; 12 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; 4 | 5 | module.exports = function (t, a) { 6 | var o, c, cg, cs, ce, ceg, ces, cew, cw, e, eg, es, ew, v, vg, vs, w, df, dfg, dfs; 7 | 8 | o = Object.create(Object.prototype, { 9 | c: t("c", (c = {})), 10 | cgs: t.gs("c", (cg = function () {}), (cs = function () {})), 11 | ce: t("ce", (ce = {})), 12 | cegs: t.gs("ce", (ceg = function () {}), (ces = function () {})), 13 | cew: t("cew", (cew = {})), 14 | cw: t("cw", (cw = {})), 15 | e: t("e", (e = {})), 16 | egs: t.gs("e", (eg = function () {}), (es = function () {})), 17 | ew: t("ew", (ew = {})), 18 | v: t("", (v = {})), 19 | vgs: t.gs("", (vg = function () {}), (vs = function () {})), 20 | w: t("w", (w = {})), 21 | 22 | df: t((df = {})), 23 | dfgs: t.gs((dfg = function () {}), (dfs = function () {})) 24 | }); 25 | 26 | return { 27 | c: function (a) { 28 | var d = getOwnPropertyDescriptor(o, "c"); 29 | a(d.value, c, "Value"); 30 | a(d.get, undefined, "Get"); 31 | a(d.set, undefined, "Set"); 32 | a(d.configurable, true, "Configurable"); 33 | a(d.enumerable, false, "Enumerable"); 34 | a(d.writable, false, "Writable"); 35 | 36 | d = getOwnPropertyDescriptor(o, "cgs"); 37 | a(d.value, undefined, "GS Value"); 38 | a(d.get, cg, "GS Get"); 39 | a(d.set, cs, "GS Set"); 40 | a(d.configurable, true, "GS Configurable"); 41 | a(d.enumerable, false, "GS Enumerable"); 42 | a(d.writable, undefined, "GS Writable"); 43 | }, 44 | ce: function (a) { 45 | var d = getOwnPropertyDescriptor(o, "ce"); 46 | a(d.value, ce, "Value"); 47 | a(d.get, undefined, "Get"); 48 | a(d.set, undefined, "Set"); 49 | a(d.configurable, true, "Configurable"); 50 | a(d.enumerable, true, "Enumerable"); 51 | a(d.writable, false, "Writable"); 52 | 53 | d = getOwnPropertyDescriptor(o, "cegs"); 54 | a(d.value, undefined, "GS Value"); 55 | a(d.get, ceg, "GS Get"); 56 | a(d.set, ces, "GS Set"); 57 | a(d.configurable, true, "GS Configurable"); 58 | a(d.enumerable, true, "GS Enumerable"); 59 | a(d.writable, undefined, "GS Writable"); 60 | }, 61 | cew: function (a) { 62 | var d = getOwnPropertyDescriptor(o, "cew"); 63 | a(d.value, cew, "Value"); 64 | a(d.get, undefined, "Get"); 65 | a(d.set, undefined, "Set"); 66 | a(d.configurable, true, "Configurable"); 67 | a(d.enumerable, true, "Enumerable"); 68 | a(d.writable, true, "Writable"); 69 | }, 70 | cw: function (a) { 71 | var d = getOwnPropertyDescriptor(o, "cw"); 72 | a(d.value, cw, "Value"); 73 | a(d.get, undefined, "Get"); 74 | a(d.set, undefined, "Set"); 75 | a(d.configurable, true, "Configurable"); 76 | a(d.enumerable, false, "Enumerable"); 77 | a(d.writable, true, "Writable"); 78 | }, 79 | e: function (a) { 80 | var d = getOwnPropertyDescriptor(o, "e"); 81 | a(d.value, e, "Value"); 82 | a(d.get, undefined, "Get"); 83 | a(d.set, undefined, "Set"); 84 | a(d.configurable, false, "Configurable"); 85 | a(d.enumerable, true, "Enumerable"); 86 | a(d.writable, false, "Writable"); 87 | 88 | d = getOwnPropertyDescriptor(o, "egs"); 89 | a(d.value, undefined, "GS Value"); 90 | a(d.get, eg, "GS Get"); 91 | a(d.set, es, "GS Set"); 92 | a(d.configurable, false, "GS Configurable"); 93 | a(d.enumerable, true, "GS Enumerable"); 94 | a(d.writable, undefined, "GS Writable"); 95 | }, 96 | ew: function (a) { 97 | var d = getOwnPropertyDescriptor(o, "ew"); 98 | a(d.value, ew, "Value"); 99 | a(d.get, undefined, "Get"); 100 | a(d.set, undefined, "Set"); 101 | a(d.configurable, false, "Configurable"); 102 | a(d.enumerable, true, "Enumerable"); 103 | a(d.writable, true, "Writable"); 104 | }, 105 | v: function (a) { 106 | var d = getOwnPropertyDescriptor(o, "v"); 107 | a(d.value, v, "Value"); 108 | a(d.get, undefined, "Get"); 109 | a(d.set, undefined, "Set"); 110 | a(d.configurable, false, "Configurable"); 111 | a(d.enumerable, false, "Enumerable"); 112 | a(d.writable, false, "Writable"); 113 | 114 | d = getOwnPropertyDescriptor(o, "vgs"); 115 | a(d.value, undefined, "GS Value"); 116 | a(d.get, vg, "GS Get"); 117 | a(d.set, vs, "GS Set"); 118 | a(d.configurable, false, "GS Configurable"); 119 | a(d.enumerable, false, "GS Enumerable"); 120 | a(d.writable, undefined, "GS Writable"); 121 | }, 122 | w: function (a) { 123 | var d = getOwnPropertyDescriptor(o, "w"); 124 | a(d.value, w, "Value"); 125 | a(d.get, undefined, "Get"); 126 | a(d.set, undefined, "Set"); 127 | a(d.configurable, false, "Configurable"); 128 | a(d.enumerable, false, "Enumerable"); 129 | a(d.writable, true, "Writable"); 130 | }, 131 | d: function (a) { 132 | var d = getOwnPropertyDescriptor(o, "df"); 133 | a(d.value, df, "Value"); 134 | a(d.get, undefined, "Get"); 135 | a(d.set, undefined, "Set"); 136 | a(d.configurable, true, "Configurable"); 137 | a(d.enumerable, false, "Enumerable"); 138 | a(d.writable, true, "Writable"); 139 | 140 | d = getOwnPropertyDescriptor(o, "dfgs"); 141 | a(d.value, undefined, "GS Value"); 142 | a(d.get, dfg, "GS Get"); 143 | a(d.set, dfs, "GS Set"); 144 | a(d.configurable, true, "GS Configurable"); 145 | a(d.enumerable, false, "GS Enumerable"); 146 | a(d.writable, undefined, "GS Writable"); 147 | }, 148 | Options: { 149 | v: function (a) { 150 | var x = {}, d = t(x, { foo: true }); 151 | a.deep( 152 | d, 153 | { configurable: true, enumerable: false, writable: true, value: x, foo: true }, 154 | "No descriptor" 155 | ); 156 | d = t("c", "foo", { marko: "elo" }); 157 | a.deep( 158 | d, 159 | { 160 | configurable: true, 161 | enumerable: false, 162 | writable: false, 163 | value: "foo", 164 | marko: "elo" 165 | }, 166 | "Descriptor" 167 | ); 168 | }, 169 | gs: function (a) { 170 | var gFn = function () {}, sFn = function () {}, d; 171 | d = t.gs(gFn, sFn, { foo: true }); 172 | a.deep( 173 | d, { configurable: true, enumerable: false, get: gFn, set: sFn, foo: true }, 174 | "No descriptor" 175 | ); 176 | d = t.gs(null, sFn, { foo: true }); 177 | a.deep( 178 | d, 179 | { configurable: true, enumerable: false, get: undefined, set: sFn, foo: true }, 180 | "No descriptor: Just set" 181 | ); 182 | d = t.gs(gFn, { foo: true }); 183 | a.deep( 184 | d, 185 | { configurable: true, enumerable: false, get: gFn, set: undefined, foo: true }, 186 | "No descriptor: Just get" 187 | ); 188 | 189 | d = t.gs("e", gFn, sFn, { bar: true }); 190 | a.deep( 191 | d, { configurable: false, enumerable: true, get: gFn, set: sFn, bar: true }, 192 | "Descriptor" 193 | ); 194 | d = t.gs("e", null, sFn, { bar: true }); 195 | a.deep( 196 | d, 197 | { configurable: false, enumerable: true, get: undefined, set: sFn, bar: true }, 198 | "Descriptor: Just set" 199 | ); 200 | d = t.gs("e", gFn, { bar: true }); 201 | a.deep( 202 | d, 203 | { configurable: false, enumerable: true, get: gFn, set: undefined, bar: true }, 204 | "Descriptor: Just get" 205 | ); 206 | } 207 | } 208 | }; 209 | }; 210 | -------------------------------------------------------------------------------- /test/lazy.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var d = require("../") 4 | , getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; 5 | 6 | module.exports = function (t, a) { 7 | var Foo = function () {}, i = 1, o, o2, desc; 8 | Object.defineProperties( 9 | Foo.prototype, 10 | t({ 11 | bar: d(function () { return ++i; }), 12 | bar2: d(function () { return this.bar + 23; }), 13 | bar3: d(function () { return this.bar2 + 34; }, { desc: "ew" }), 14 | bar4: d(function () { return this.bar3 + 12; }, { cacheName: "_bar4_" }), 15 | bar5: d(function () { return this.bar4 + 3; }, { cacheName: "_bar5_", desc: "e" }) 16 | }) 17 | ); 18 | 19 | desc = getOwnPropertyDescriptor(Foo.prototype, "bar"); 20 | a(desc.configurable, true, "Configurable: default"); 21 | a(desc.enumerable, false, "Enumerable: default"); 22 | 23 | o = new Foo(); 24 | a.deep([o.bar, o.bar2, o.bar3, o.bar4, o.bar5], [2, 25, 59, 71, 74], "Values"); 25 | 26 | a.deep( 27 | getOwnPropertyDescriptor(o, "bar3"), 28 | { configurable: false, enumerable: true, writable: true, value: 59 }, "Desc" 29 | ); 30 | a(o.hasOwnProperty("bar4"), false, "Cache not exposed"); 31 | desc = getOwnPropertyDescriptor(o, "bar5"); 32 | a.deep( 33 | desc, { configurable: false, enumerable: true, get: desc.get, set: desc.set }, 34 | "Cache & Desc: desc" 35 | ); 36 | 37 | o2 = Object.create(o); 38 | o2.bar = 30; 39 | o2.bar3 = 100; 40 | 41 | a.deep( 42 | [o2.bar, o2.bar2, o2.bar3, o2.bar4, o2.bar5], [30, 25, 100, 112, 115], "Extension Values" 43 | ); 44 | 45 | Foo = function () {}; 46 | Object.defineProperties( 47 | Foo.prototype, 48 | t({ 49 | test: d("w", function () { return "raz"; }), 50 | test2: d("", function () { return "raz"; }, { desc: "w" }), 51 | test3: d("", function () { return "raz"; }, { cacheName: "__test3__", desc: "w" }), 52 | test4: d("w", "bar") 53 | }) 54 | ); 55 | 56 | o = new Foo(); 57 | o.test = "marko"; 58 | a.deep( 59 | getOwnPropertyDescriptor(o, "test"), 60 | { configurable: false, enumerable: false, writable: true, value: "marko" }, "Set before get" 61 | ); 62 | o.test2 = "marko2"; 63 | a.deep( 64 | getOwnPropertyDescriptor(o, "test2"), 65 | { configurable: false, enumerable: false, writable: true, value: "marko2" }, 66 | "Set before get: Custom desc" 67 | ); 68 | o.test3 = "marko3"; 69 | a.deep( 70 | getOwnPropertyDescriptor(o, "__test3__"), 71 | { configurable: false, enumerable: false, writable: true, value: "marko3" }, 72 | "Set before get: Custom cache name" 73 | ); 74 | a(o.test4, "bar", "Resolve by value"); 75 | 76 | a.h1("Flat"); 77 | Object.defineProperties( 78 | Foo.prototype, 79 | t({ 80 | flat: d(function () { return "foo"; }, { flat: true }), 81 | flat2: d(function () { return "bar"; }, { flat: true }) 82 | }) 83 | ); 84 | 85 | a.h2("Instance"); 86 | a(o.flat, "foo", "Value"); 87 | a(o.hasOwnProperty("flat"), false, "Instance"); 88 | a(Foo.prototype.flat, "foo", "Prototype"); 89 | 90 | a.h2("Direct"); 91 | a(Foo.prototype.flat2, "bar"); 92 | 93 | a.h2("Reset direct"); 94 | Object.defineProperties(Foo.prototype, t({ testResetDirect: d(false) })); 95 | 96 | a.throws(function () { Foo.prototype.testResetDirect = false; }, TypeError); 97 | }; 98 | --------------------------------------------------------------------------------