├── .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 |
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 |
--------------------------------------------------------------------------------