├── .npmrc ├── .nycrc ├── .gitignore ├── .github ├── workflows │ ├── node-pretest.yml │ ├── rebase.yml │ ├── require-allow-edits.yml │ ├── node-aught.yml │ └── node-tens.yml └── FUNDING.yml ├── .eslintrc ├── .editorconfig ├── LICENSE ├── index.js ├── package.json ├── README.md ├── CHANGELOG.md └── test └── index.js /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | allow-same-version=true 3 | message=v%s 4 | -------------------------------------------------------------------------------- /.nycrc: -------------------------------------------------------------------------------- 1 | { 2 | "all": true, 3 | "check-coverage": false, 4 | "reporter": ["text-summary", "text", "html", "json"], 5 | "exclude": [ 6 | "coverage", 7 | "test" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # gitignore 2 | 3 | node_modules 4 | 5 | # Only apps should have lockfile 6 | npm-shrinkwrap.json 7 | package-lock.json 8 | yarn.lock 9 | 10 | coverage/ 11 | .nyc_output/ 12 | 13 | .npmignore 14 | -------------------------------------------------------------------------------- /.github/workflows/node-pretest.yml: -------------------------------------------------------------------------------- 1 | name: 'Tests: pretest/posttest' 2 | 3 | on: [pull_request, push] 4 | 5 | permissions: 6 | contents: read 7 | 8 | jobs: 9 | tests: 10 | uses: ljharb/actions/.github/workflows/pretest.yml@main 11 | -------------------------------------------------------------------------------- /.github/workflows/rebase.yml: -------------------------------------------------------------------------------- 1 | name: Automatic Rebase 2 | 3 | on: [pull_request_target] 4 | 5 | jobs: 6 | _: 7 | uses: ljharb/actions/.github/workflows/rebase.yml@main 8 | secrets: 9 | token: ${{ secrets.GITHUB_TOKEN }} 10 | -------------------------------------------------------------------------------- /.github/workflows/require-allow-edits.yml: -------------------------------------------------------------------------------- 1 | name: Require “Allow Edits” 2 | 3 | on: [pull_request_target] 4 | 5 | jobs: 6 | _: 7 | name: "Require “Allow Edits”" 8 | 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: ljharb/require-allow-edits@main 13 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | 4 | "extends": "@ljharb", 5 | 6 | "rules": { 7 | "id-length": [2, { "min": 1, "max": 35 }], 8 | "max-params": [2, 4], 9 | }, 10 | 11 | "overrides": [ 12 | { 13 | "files": "test/**", 14 | "rules": { 15 | "max-lines-per-function": 0, 16 | }, 17 | }, 18 | ], 19 | } 20 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = tab; 5 | insert_final_newline = true; 6 | quote_type = auto; 7 | space_after_anonymous_functions = true; 8 | space_after_control_statements = true; 9 | spaces_around_operators = true; 10 | trim_trailing_whitespace = true; 11 | spaces_in_brackets = false; 12 | end_of_line = lf; 13 | 14 | -------------------------------------------------------------------------------- /.github/workflows/node-aught.yml: -------------------------------------------------------------------------------- 1 | name: 'Tests: node.js < 10' 2 | 3 | on: [pull_request, push] 4 | 5 | jobs: 6 | tests: 7 | uses: ljharb/actions/.github/workflows/node.yml@main 8 | with: 9 | range: '< 10' 10 | type: minors 11 | command: npm run tests-only 12 | 13 | node: 14 | name: 'node < 10' 15 | needs: [tests] 16 | runs-on: ubuntu-latest 17 | steps: 18 | - run: 'echo tests completed' 19 | -------------------------------------------------------------------------------- /.github/workflows/node-tens.yml: -------------------------------------------------------------------------------- 1 | name: 'Tests: node.js >= 10' 2 | 3 | on: [pull_request, push] 4 | 5 | jobs: 6 | tests: 7 | uses: ljharb/actions/.github/workflows/node.yml@main 8 | with: 9 | range: '>= 10' 10 | type: minors 11 | command: npm run tests-only 12 | 13 | node: 14 | name: 'node >= 10' 15 | needs: [tests] 16 | runs-on: ubuntu-latest 17 | steps: 18 | - run: 'echo tests completed' 19 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [ljharb] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: npm/define-properties 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (C) 2015 Jordan Harband 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var keys = require('object-keys'); 4 | var hasSymbols = typeof Symbol === 'function' && typeof Symbol('foo') === 'symbol'; 5 | 6 | var toStr = Object.prototype.toString; 7 | var concat = Array.prototype.concat; 8 | var defineDataProperty = require('define-data-property'); 9 | 10 | var isFunction = function (fn) { 11 | return typeof fn === 'function' && toStr.call(fn) === '[object Function]'; 12 | }; 13 | 14 | var supportsDescriptors = require('has-property-descriptors')(); 15 | 16 | var defineProperty = function (object, name, value, predicate) { 17 | if (name in object) { 18 | if (predicate === true) { 19 | if (object[name] === value) { 20 | return; 21 | } 22 | } else if (!isFunction(predicate) || !predicate()) { 23 | return; 24 | } 25 | } 26 | 27 | if (supportsDescriptors) { 28 | defineDataProperty(object, name, value, true); 29 | } else { 30 | defineDataProperty(object, name, value); 31 | } 32 | }; 33 | 34 | var defineProperties = function (object, map) { 35 | var predicates = arguments.length > 2 ? arguments[2] : {}; 36 | var props = keys(map); 37 | if (hasSymbols) { 38 | props = concat.call(props, Object.getOwnPropertySymbols(map)); 39 | } 40 | for (var i = 0; i < props.length; i += 1) { 41 | defineProperty(object, props[i], map[props[i]], predicates[props[i]]); 42 | } 43 | }; 44 | 45 | defineProperties.supportsDescriptors = !!supportsDescriptors; 46 | 47 | module.exports = defineProperties; 48 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "define-properties", 3 | "version": "1.2.1", 4 | "author": "Jordan Harband ", 5 | "funding": { 6 | "url": "https://github.com/sponsors/ljharb" 7 | }, 8 | "description": "Define multiple non-enumerable properties at once. Uses `Object.defineProperty` when available; falls back to standard assignment in older engines.", 9 | "license": "MIT", 10 | "main": "index.js", 11 | "scripts": { 12 | "prepack": "npmignore --auto --commentLines=autogenerated", 13 | "prepublish": "not-in-publish || npm run prepublishOnly", 14 | "prepublishOnly": "safe-publish-latest", 15 | "pretest": "npm run lint", 16 | "test": "npm run tests-only", 17 | "posttest": "aud --production", 18 | "tests-only": "nyc tape 'test/**/*.js'", 19 | "lint": "eslint --ext=js,mjs .", 20 | "postlint": "evalmd README.md", 21 | "version": "auto-changelog && git add CHANGELOG.md", 22 | "postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\"" 23 | }, 24 | "repository": { 25 | "type": "git", 26 | "url": "git://github.com/ljharb/define-properties.git" 27 | }, 28 | "keywords": [ 29 | "Object.defineProperty", 30 | "Object.defineProperties", 31 | "object", 32 | "property descriptor", 33 | "descriptor", 34 | "define", 35 | "ES5" 36 | ], 37 | "dependencies": { 38 | "define-data-property": "^1.1.4", 39 | "has-property-descriptors": "^1.0.2", 40 | "object-keys": "^1.1.1" 41 | }, 42 | "devDependencies": { 43 | "@ljharb/eslint-config": "^21.1.1", 44 | "aud": "^2.0.4", 45 | "auto-changelog": "^2.4.0", 46 | "eslint": "=8.8.0", 47 | "evalmd": "^0.0.19", 48 | "in-publish": "^2.0.1", 49 | "npmignore": "^0.3.1", 50 | "nyc": "^10.3.2", 51 | "safe-publish-latest": "^2.0.0", 52 | "tape": "^5.8.1" 53 | }, 54 | "testling": { 55 | "files": "test/index.js", 56 | "browsers": [ 57 | "iexplore/6.0..latest", 58 | "firefox/3.0..6.0", 59 | "firefox/15.0..latest", 60 | "firefox/nightly", 61 | "chrome/4.0..10.0", 62 | "chrome/20.0..latest", 63 | "chrome/canary", 64 | "opera/10.0..latest", 65 | "opera/next", 66 | "safari/4.0..latest", 67 | "ipad/6.0..latest", 68 | "iphone/6.0..latest", 69 | "android-browser/4.2" 70 | ] 71 | }, 72 | "engines": { 73 | "node": ">= 0.4" 74 | }, 75 | "auto-changelog": { 76 | "output": "CHANGELOG.md", 77 | "template": "keepachangelog", 78 | "unreleased": false, 79 | "commitLimit": false, 80 | "backfillLimit": false, 81 | "hideCredit": true, 82 | "startingVersion": "1.1.5" 83 | }, 84 | "publishConfig": { 85 | "ignore": [ 86 | ".github/workflows", 87 | "test/" 88 | ] 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # define-properties [![Version Badge][npm-version-svg]][package-url] 2 | 3 | [![github actions][actions-image]][actions-url] 4 | [![coverage][codecov-image]][codecov-url] 5 | [![dependency status][deps-svg]][deps-url] 6 | [![dev dependency status][dev-deps-svg]][dev-deps-url] 7 | [![License][license-image]][license-url] 8 | [![Downloads][downloads-image]][downloads-url] 9 | 10 | [![npm badge][npm-badge-png]][package-url] 11 | 12 | Define multiple non-enumerable properties at once. Uses `Object.defineProperty` when available; falls back to standard assignment in older engines. 13 | Existing properties are not overridden. Accepts a map of property names to a predicate that, when true, force-overrides. 14 | 15 | ## Example 16 | 17 | ```js 18 | var define = require('define-properties'); 19 | var assert = require('assert'); 20 | 21 | var obj = { a: 1, b: 2 }; 22 | 23 | define(obj, { 24 | a: 10, 25 | b: 20, 26 | c: 30 27 | }); 28 | 29 | assert(obj.a === 1); 30 | assert(obj.b === 2); 31 | assert(obj.c === 30); 32 | if (define.supportsDescriptors) { 33 | assert.deepEqual(Object.keys(obj), ['a', 'b']); 34 | assert.deepEqual(Object.getOwnPropertyDescriptor(obj, 'c'), { 35 | configurable: true, 36 | enumerable: false, 37 | value: 30, 38 | writable: true 39 | }); 40 | } 41 | ``` 42 | 43 | Then, with predicates: 44 | ```js 45 | var define = require('define-properties'); 46 | var assert = require('assert'); 47 | 48 | var obj = { a: 1, b: 2, c: 3 }; 49 | 50 | define(obj, { 51 | a: 10, 52 | b: 20, 53 | c: 30 54 | }, { 55 | a: function () { return false; }, 56 | b: function () { return true; } 57 | }); 58 | 59 | assert(obj.a === 1); 60 | assert(obj.b === 20); 61 | assert(obj.c === 3); 62 | if (define.supportsDescriptors) { 63 | assert.deepEqual(Object.keys(obj), ['a', 'c']); 64 | assert.deepEqual(Object.getOwnPropertyDescriptor(obj, 'b'), { 65 | configurable: true, 66 | enumerable: false, 67 | value: 20, 68 | writable: true 69 | }); 70 | } 71 | ``` 72 | 73 | ## Tests 74 | Simply clone the repo, `npm install`, and run `npm test` 75 | 76 | [package-url]: https://npmjs.org/package/define-properties 77 | [npm-version-svg]: https://versionbadg.es/ljharb/define-properties.svg 78 | [deps-svg]: https://david-dm.org/ljharb/define-properties.svg 79 | [deps-url]: https://david-dm.org/ljharb/define-properties 80 | [dev-deps-svg]: https://david-dm.org/ljharb/define-properties/dev-status.svg 81 | [dev-deps-url]: https://david-dm.org/ljharb/define-properties#info=devDependencies 82 | [npm-badge-png]: https://nodei.co/npm/define-properties.png?downloads=true&stars=true 83 | [license-image]: https://img.shields.io/npm/l/define-properties.svg 84 | [license-url]: LICENSE 85 | [downloads-image]: https://img.shields.io/npm/dm/define-properties.svg 86 | [downloads-url]: https://npm-stat.com/charts.html?package=define-properties 87 | [codecov-image]: https://codecov.io/gh/ljharb/define-properties/branch/main/graphs/badge.svg 88 | [codecov-url]: https://app.codecov.io/gh/ljharb/define-properties/ 89 | [actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/ljharb/define-properties 90 | [actions-url]: https://github.com/ljharb/define-properties/actions 91 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [v1.2.1](https://github.com/ljharb/define-properties/compare/v1.2.0...v1.2.1) - 2023-09-12 9 | 10 | ### Commits 11 | 12 | - [Refactor] use `define-data-property` [`e7782a7`](https://github.com/ljharb/define-properties/commit/e7782a7480a62f8b6e141b49371e6de4df176c97) 13 | - [actions] use reusable rebase action [`cd249c3`](https://github.com/ljharb/define-properties/commit/cd249c3920607bc8eeb7c0cd5b672b810983cac5) 14 | - [Dev Deps] update `@ljharb/eslint-config`, `aud`, `tape` [`8205f97`](https://github.com/ljharb/define-properties/commit/8205f9734a4da8ee5b3b29798788567a09b330e8) 15 | 16 | ## [v1.2.0](https://github.com/ljharb/define-properties/compare/v1.1.4...v1.2.0) - 2023-02-10 17 | 18 | ### Commits 19 | 20 | - [New] if the predicate is boolean `true`, it compares the existing value with `===` as the predicate [`d8dd6fc`](https://github.com/ljharb/define-properties/commit/d8dd6fca40d7c5878a4b643b91e66ae5a513a194) 21 | - [meta] add `auto-changelog` [`7ebe2b0`](https://github.com/ljharb/define-properties/commit/7ebe2b0a0f90e62b842942cd45e86864fe75d9f6) 22 | - [meta] use `npmignore` to autogenerate an npmignore file [`647478a`](https://github.com/ljharb/define-properties/commit/647478a8401fbf053fb633c0a3a7c982da6bad74) 23 | - [Dev Deps] update `@ljharb/eslint-config`, `aud`, `tape` [`e620d70`](https://github.com/ljharb/define-properties/commit/e620d707d2e1118a38796f22a862200eb0a53fff) 24 | - [Dev Deps] update `aud`, `tape` [`f1e5072`](https://github.com/ljharb/define-properties/commit/f1e507225c2551a99ed4fe40d3fe71b0f44acf88) 25 | - [actions] update checkout action [`628b3af`](https://github.com/ljharb/define-properties/commit/628b3af5c74b8f0963296d811a8f6fa657baf964) 26 | 27 | 28 | 29 | 1.1.4 / 2022-04-14 30 | ================= 31 | * [Refactor] use `has-property-descriptors` 32 | * [readme] add github actions/codecov badges 33 | * [Docs] fix header parsing; remove testling 34 | * [Deps] update `object-keys` 35 | * [meta] use `prepublishOnly` script for npm 7+ 36 | * [meta] add `funding` field; create FUNDING.yml 37 | * [actions] add "Allow Edits" workflow; automatic rebasing / merge commit blocking 38 | * [actions] reuse common workflows 39 | * [actions] update codecov uploader 40 | * [actions] use `node/install` instead of `node/run`; use `codecov` action 41 | * [Tests] migrate tests to Github Actions 42 | * [Tests] run `nyc` on all tests; use `tape` runner 43 | * [Tests] use shared travis-ci config 44 | * [Tests] use `npx aud` instead of `nsp` or `npm audit` with hoops 45 | * [Tests] remove `jscs` 46 | * [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `safe-publish-latest`, `tape`; add `aud`, `safe-publish-latest` 47 | 48 | 1.1.3 / 2018-08-14 49 | ================= 50 | * [Refactor] use a for loop instead of `foreach` to make for smaller bundle sizes 51 | * [Robustness] cache `Array.prototype.concat` and `Object.defineProperty` 52 | * [Deps] update `object-keys` 53 | * [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `nsp`, `tape`, `jscs`; remove unused eccheck script + dep 54 | * [Tests] use pretest/posttest for linting/security 55 | * [Tests] fix npm upgrades on older nodes 56 | 57 | 1.1.2 / 2015-10-14 58 | ================= 59 | * [Docs] Switch from vb.teelaun.ch to versionbadg.es for the npm version badge SVG 60 | * [Deps] Update `object-keys` 61 | * [Dev Deps] update `jscs`, `tape`, `eslint`, `@ljharb/eslint-config`, `nsp` 62 | * [Tests] up to `io.js` `v3.3`, `node` `v4.2` 63 | 64 | 1.1.1 / 2015-07-21 65 | ================= 66 | * [Deps] Update `object-keys` 67 | * [Dev Deps] Update `tape`, `eslint` 68 | * [Tests] Test on `io.js` `v2.4` 69 | 70 | 1.1.0 / 2015-07-01 71 | ================= 72 | * [New] Add support for symbol-valued properties. 73 | * [Dev Deps] Update `nsp`, `eslint` 74 | * [Tests] Test up to `io.js` `v2.3` 75 | 76 | 1.0.3 / 2015-05-30 77 | ================= 78 | * Using a more reliable check for supported property descriptors. 79 | 80 | 1.0.2 / 2015-05-23 81 | ================= 82 | * Test up to `io.js` `v2.0` 83 | * Update `tape`, `jscs`, `nsp`, `eslint`, `object-keys`, `editorconfig-tools`, `covert` 84 | 85 | 1.0.1 / 2015-01-06 86 | ================= 87 | * Update `object-keys` to fix ES3 support 88 | 89 | 1.0.0 / 2015-01-04 90 | ================= 91 | * v1.0.0 92 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var define = require('../'); 4 | var test = require('tape'); 5 | var keys = require('object-keys'); 6 | 7 | var arePropertyDescriptorsSupported = function () { 8 | var obj = { a: 1 }; 9 | try { 10 | Object.defineProperty(obj, 'x', { value: obj }); 11 | return obj.x === obj; 12 | } catch (e) { /* this is IE 8. */ 13 | return false; 14 | } 15 | }; 16 | var descriptorsSupported = !!Object.defineProperty && arePropertyDescriptorsSupported(); 17 | 18 | var hasSymbols = typeof Symbol === 'function' && typeof Symbol('foo') === 'symbol'; 19 | 20 | test('defineProperties', function (dt) { 21 | dt.test('with descriptor support', { skip: !descriptorsSupported }, function (t) { 22 | var getDescriptor = function (value) { 23 | return { 24 | configurable: true, 25 | enumerable: false, 26 | value: value, 27 | writable: true 28 | }; 29 | }; 30 | 31 | var obj = { 32 | a: 1, 33 | b: 2, 34 | c: 3 35 | }; 36 | t.deepEqual(keys(obj), ['a', 'b', 'c'], 'all literal-set keys start enumerable'); 37 | define(obj, { 38 | b: 3, 39 | c: 4, 40 | d: 5 41 | }); 42 | t.deepEqual( 43 | obj, 44 | { 45 | a: 1, 46 | b: 2, 47 | c: 3 48 | }, 49 | 'existing properties were not overridden' 50 | ); 51 | t.deepEqual(Object.getOwnPropertyDescriptor(obj, 'd'), getDescriptor(5), 'new property "d" was added and is not enumerable'); 52 | t.deepEqual(['a', 'b', 'c'], keys(obj), 'new keys are not enumerable'); 53 | 54 | define( 55 | obj, 56 | { 57 | a: 2, 58 | b: 3, 59 | c: 4 60 | }, 61 | { 62 | a: function () { return true; }, 63 | b: function () { return false; } 64 | } 65 | ); 66 | t.deepEqual( 67 | obj, 68 | { 69 | b: 2, 70 | c: 3 71 | }, 72 | 'properties only overriden when predicate exists and returns true' 73 | ); 74 | t.deepEqual(Object.getOwnPropertyDescriptor(obj, 'd'), getDescriptor(5), 'existing property "d" remained and is not enumerable'); 75 | t.deepEqual(Object.getOwnPropertyDescriptor(obj, 'a'), getDescriptor(2), 'existing property "a" was overridden and is not enumerable'); 76 | t.deepEqual(['b', 'c'], keys(obj), 'overridden keys are not enumerable'); 77 | 78 | define( 79 | obj, 80 | { 81 | a: 4, 82 | b: 3, 83 | c: 3 84 | }, 85 | { 86 | a: true, 87 | b: true, 88 | c: true 89 | } 90 | ); 91 | t.deepEqual( 92 | obj, 93 | { c: 3 }, 94 | 'properties overriden when predicate is `true` and ===' 95 | ); 96 | t.deepEqual(Object.getOwnPropertyDescriptor(obj, 'a'), getDescriptor(4), 'existing property "a" was overridden and is not enumerable'); 97 | t.deepEqual(Object.getOwnPropertyDescriptor(obj, 'b'), getDescriptor(3), 'existing property "b" was overridden and is not enumerable'); 98 | t.deepEqual(Object.getOwnPropertyDescriptor(obj, 'd'), getDescriptor(5), 'existing property "d" remained and is not enumerable'); 99 | t.deepEqual(['c'], keys(obj), 'overridden keys are not enumerable'); 100 | 101 | t.end(); 102 | }); 103 | 104 | dt.test('without descriptor support', { skip: descriptorsSupported }, function (t) { 105 | var obj = { 106 | a: 1, 107 | b: 2, 108 | c: 3 109 | }; 110 | define(obj, { 111 | b: 3, 112 | c: 4, 113 | d: 5 114 | }); 115 | t.deepEqual( 116 | obj, 117 | { 118 | a: 1, 119 | b: 2, 120 | c: 3, 121 | d: 5 122 | }, 123 | 'existing properties were not overridden, new properties were added' 124 | ); 125 | 126 | define( 127 | obj, 128 | { 129 | a: 2, 130 | b: 3, 131 | c: 4 132 | }, 133 | { 134 | a: function () { return true; }, 135 | b: function () { return false; } 136 | } 137 | ); 138 | t.deepEqual( 139 | obj, 140 | { 141 | a: 2, 142 | b: 2, 143 | c: 3, 144 | d: 5 145 | }, 146 | 'properties only overriden when predicate exists and returns true' 147 | ); 148 | 149 | t.end(); 150 | }); 151 | 152 | dt.end(); 153 | }); 154 | 155 | test('symbols', { skip: !hasSymbols }, function (t) { 156 | var sym = Symbol('foo'); 157 | var obj = {}; 158 | var aValue = {}; 159 | var bValue = {}; 160 | var properties = { a: aValue }; 161 | properties[sym] = bValue; 162 | 163 | define(obj, properties); 164 | 165 | t.deepEqual(Object.keys(obj), [], 'object has no enumerable keys'); 166 | t.deepEqual(Object.getOwnPropertyNames(obj), ['a'], 'object has non-enumerable "a" key'); 167 | t.deepEqual(Object.getOwnPropertySymbols(obj), [sym], 'object has non-enumerable symbol key'); 168 | t.equal(obj.a, aValue, 'string keyed value is defined'); 169 | t.equal(obj[sym], bValue, 'symbol keyed value is defined'); 170 | 171 | t.end(); 172 | }); 173 | --------------------------------------------------------------------------------