Comparing version 0.5.26 to 0.5.27
@@ -1,9 +0,9 @@ | ||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.treeKit = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | ||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.treeKit = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ | ||
/* | ||
Tree Kit | ||
Copyright (c) 2014 - 2016 Cédric Ronvel | ||
Copyright (c) 2014 - 2018 Cédric Ronvel | ||
The MIT License (MIT) | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
@@ -15,6 +15,6 @@ of this software and associated documentation files (the "Software"), to deal | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
@@ -46,7 +46,7 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
Tree Kit | ||
Copyright (c) 2014 - 2016 Cédric Ronvel | ||
Copyright (c) 2014 - 2018 Cédric Ronvel | ||
The MIT License (MIT) | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
@@ -58,6 +58,6 @@ of this software and associated documentation files (the "Software"), to deal | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
@@ -80,7 +80,6 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
module.exports = function clone( originalObject , circular ) | ||
{ | ||
module.exports = function clone( originalObject , circular ) { | ||
// First create an empty object with | ||
// same prototype of our original source | ||
var propertyIndex , descriptor , keys , current , nextSource , indexOf , | ||
@@ -94,28 +93,23 @@ copies = [ { | ||
targetReferences = [ cloneObject ] ; | ||
// First in, first out | ||
while ( current = copies.shift() ) // jshint ignore:line | ||
{ | ||
while ( ( current = copies.shift() ) ) { | ||
keys = Object.getOwnPropertyNames( current.source ) ; | ||
for ( propertyIndex = 0 ; propertyIndex < keys.length ; propertyIndex ++ ) | ||
{ | ||
for ( propertyIndex = 0 ; propertyIndex < keys.length ; propertyIndex ++ ) { | ||
// Save the source's descriptor | ||
descriptor = Object.getOwnPropertyDescriptor( current.source , keys[ propertyIndex ] ) ; | ||
if ( ! descriptor.value || typeof descriptor.value !== 'object' ) | ||
{ | ||
if ( ! descriptor.value || typeof descriptor.value !== 'object' ) { | ||
Object.defineProperty( current.target , keys[ propertyIndex ] , descriptor ) ; | ||
continue ; | ||
} | ||
nextSource = descriptor.value ; | ||
descriptor.value = Array.isArray( nextSource ) ? [] : Object.create( Object.getPrototypeOf( nextSource ) ) ; | ||
if ( circular ) | ||
{ | ||
if ( circular ) { | ||
indexOf = sourceReferences.indexOf( nextSource ) ; | ||
if ( indexOf !== -1 ) | ||
{ | ||
if ( indexOf !== -1 ) { | ||
// The source is already referenced, just assign reference | ||
@@ -126,13 +120,13 @@ descriptor.value = targetReferences[ indexOf ] ; | ||
} | ||
sourceReferences.push( nextSource ) ; | ||
targetReferences.push( descriptor.value ) ; | ||
} | ||
Object.defineProperty( current.target , keys[ propertyIndex ] , descriptor ) ; | ||
copies.push( { source: nextSource , target: descriptor.value } ) ; | ||
} | ||
} | ||
return cloneObject ; | ||
@@ -144,7 +138,7 @@ } ; | ||
Tree Kit | ||
Copyright (c) 2014 - 2016 Cédric Ronvel | ||
Copyright (c) 2014 - 2018 Cédric Ronvel | ||
The MIT License (MIT) | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
@@ -156,6 +150,6 @@ of this software and associated documentation files (the "Software"), to deal | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
@@ -205,22 +199,17 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
*/ | ||
function extend( options , target ) | ||
{ | ||
function extend( options , target , ... sources ) { | ||
//console.log( "\nextend():\n" , arguments ) ; | ||
var i , source , newTarget = false , length = arguments.length ; | ||
if ( length < 3 ) { return target ; } | ||
var sources = Array.prototype.slice.call( arguments , 2 ) ; | ||
length = sources.length ; | ||
var i , source , newTarget = false , length = sources.length ; | ||
if ( ! length ) { return target ; } | ||
if ( ! options || typeof options !== 'object' ) { options = {} ; } | ||
var runtime = { depth: 0 , prefix: '' } ; | ||
if ( ! options.maxDepth && options.deep && ! options.circular ) { options.maxDepth = 100 ; } | ||
if ( options.deepFunc ) { options.deep = true ; } | ||
if ( options.deepFilter && typeof options.deepFilter === 'object' ) | ||
{ | ||
if ( options.deepFilter && typeof options.deepFilter === 'object' ) { | ||
if ( options.deepFilter.whitelist && ( ! Array.isArray( options.deepFilter.whitelist ) || ! options.deepFilter.whitelist.length ) ) { delete options.deepFilter.whitelist ; } | ||
@@ -230,6 +219,5 @@ if ( options.deepFilter.blacklist && ( ! Array.isArray( options.deepFilter.blacklist ) || ! options.deepFilter.blacklist.length ) ) { delete options.deepFilter.blacklist ; } | ||
} | ||
// 'flat' option force 'deep' | ||
if ( options.flat ) | ||
{ | ||
if ( options.flat ) { | ||
options.deep = true ; | ||
@@ -241,5 +229,4 @@ options.proto = false ; | ||
} | ||
if ( options.unflat ) | ||
{ | ||
if ( options.unflat ) { | ||
options.deep = false ; | ||
@@ -251,30 +238,24 @@ options.proto = false ; | ||
} | ||
// If the prototype is applied, only owned properties should be copied | ||
if ( options.inherit ) { options.own = true ; options.proto = false ; } | ||
else if ( options.proto ) { options.own = true ; } | ||
if ( ! target || ( typeof target !== 'object' && typeof target !== 'function' ) ) | ||
{ | ||
if ( ! target || ( typeof target !== 'object' && typeof target !== 'function' ) ) { | ||
newTarget = true ; | ||
} | ||
if ( ! options.skipRoot && ( options.inherit || options.proto ) ) | ||
{ | ||
for ( i = length - 1 ; i >= 0 ; i -- ) | ||
{ | ||
if ( ! options.skipRoot && ( options.inherit || options.proto ) ) { | ||
for ( i = length - 1 ; i >= 0 ; i -- ) { | ||
source = sources[ i ] ; | ||
if ( source && ( typeof source === 'object' || typeof source === 'function' ) ) | ||
{ | ||
if ( options.inherit ) | ||
{ | ||
if ( source && ( typeof source === 'object' || typeof source === 'function' ) ) { | ||
if ( options.inherit ) { | ||
if ( newTarget ) { target = Object.create( source ) ; } | ||
else { Object.setPrototypeOf( target , source ) ; } | ||
} | ||
else if ( options.proto ) | ||
{ | ||
else if ( options.proto ) { | ||
if ( newTarget ) { target = Object.create( Object.getPrototypeOf( source ) ) ; } | ||
else { Object.setPrototypeOf( target , Object.getPrototypeOf( source ) ) ; } | ||
} | ||
break ; | ||
@@ -284,11 +265,9 @@ } | ||
} | ||
else if ( newTarget ) | ||
{ | ||
else if ( newTarget ) { | ||
target = {} ; | ||
} | ||
runtime.references = { sources: [] , targets: [] } ; | ||
for ( i = 0 ; i < length ; i ++ ) | ||
{ | ||
for ( i = 0 ; i < length ; i ++ ) { | ||
source = sources[ i ] ; | ||
@@ -298,3 +277,3 @@ if ( ! source || ( typeof source !== 'object' && typeof source !== 'function' ) ) { continue ; } | ||
} | ||
return target ; | ||
@@ -307,26 +286,22 @@ } | ||
function extendOne( runtime , options , target , source ) | ||
{ | ||
function extendOne( runtime , options , target , source ) { | ||
//console.log( "\nextendOne():\n" , arguments ) ; | ||
//process.exit() ; | ||
var j , jmax , sourceKeys , sourceKey , sourceValue , sourceValueProto , | ||
value , sourceDescriptor , targetKey , targetPointer , path , | ||
indexOfSource = -1 ; | ||
// Max depth check | ||
if ( options.maxDepth && runtime.depth > options.maxDepth ) | ||
{ | ||
if ( options.maxDepth && runtime.depth > options.maxDepth ) { | ||
throw new Error( '[tree] extend(): max depth reached(' + options.maxDepth + ')' ) ; | ||
} | ||
if ( options.circular ) | ||
{ | ||
if ( options.circular ) { | ||
runtime.references.sources.push( source ) ; | ||
runtime.references.targets.push( target ) ; | ||
} | ||
if ( options.own ) | ||
{ | ||
if ( options.own ) { | ||
if ( options.nonEnum ) { sourceKeys = Object.getOwnPropertyNames( source ) ; } | ||
@@ -336,70 +311,63 @@ else { sourceKeys = Object.keys( source ) ; } | ||
else { sourceKeys = source ; } | ||
for ( sourceKey in sourceKeys ) | ||
{ | ||
for ( sourceKey in sourceKeys ) { | ||
if ( options.own ) { sourceKey = sourceKeys[ sourceKey ] ; } | ||
// OMG, this DEPRECATED __proto__ shit is still alive and can be used to hack anything >< | ||
if ( sourceKey === '__proto__' ) { continue ; } | ||
// If descriptor is on, get it now | ||
if ( options.descriptor ) | ||
{ | ||
if ( options.descriptor ) { | ||
sourceDescriptor = Object.getOwnPropertyDescriptor( source , sourceKey ) ; | ||
sourceValue = sourceDescriptor.value ; | ||
} | ||
else | ||
{ | ||
else { | ||
// We have to trigger an eventual getter only once | ||
sourceValue = source[ sourceKey ] ; | ||
} | ||
targetPointer = target ; | ||
targetKey = runtime.prefix + sourceKey ; | ||
// Do not copy if property is a function and we don't want them | ||
if ( options.nofunc && typeof sourceValue === 'function' ) { continue; } | ||
if ( options.nofunc && typeof sourceValue === 'function' ) { continue ; } | ||
// 'unflat' mode computing | ||
if ( options.unflat && runtime.depth === 0 ) | ||
{ | ||
if ( options.unflat && runtime.depth === 0 ) { | ||
path = sourceKey.split( options.unflat ) ; | ||
jmax = path.length - 1 ; | ||
if ( jmax ) | ||
{ | ||
for ( j = 0 ; j < jmax ; j ++ ) | ||
{ | ||
if ( jmax ) { | ||
for ( j = 0 ; j < jmax ; j ++ ) { | ||
if ( ! targetPointer[ path[ j ] ] || | ||
( typeof targetPointer[ path[ j ] ] !== 'object' && | ||
typeof targetPointer[ path[ j ] ] !== 'function' ) ) | ||
{ | ||
typeof targetPointer[ path[ j ] ] !== 'function' ) ) { | ||
targetPointer[ path[ j ] ] = {} ; | ||
} | ||
targetPointer = targetPointer[ path[ j ] ] ; | ||
} | ||
targetKey = runtime.prefix + path[ jmax ] ; | ||
} | ||
} | ||
if ( options.deep && | ||
if ( options.deep && // eslint-disable-line no-constant-condition | ||
sourceValue && | ||
( typeof sourceValue === 'object' || ( options.deepFunc && typeof sourceValue === 'function' ) ) && | ||
( ! options.descriptor || ! sourceDescriptor.get ) && | ||
// not a condition we just cache sourceValueProto now | ||
// not a condition we just cache sourceValueProto now... ok it's trashy >< | ||
( ( sourceValueProto = Object.getPrototypeOf( sourceValue ) ) || true ) && | ||
( ! options.deepFilter || | ||
( ( ! options.deepFilter.whitelist || options.deepFilter.whitelist.indexOf( sourceValueProto ) !== -1 ) && | ||
( ! options.deepFilter.blacklist || options.deepFilter.blacklist.indexOf( sourceValueProto ) === -1 ) ) ) ) | ||
{ | ||
if ( options.circular ) | ||
{ | ||
( ! options.deepFilter.blacklist || options.deepFilter.blacklist.indexOf( sourceValueProto ) === -1 ) ) ) ) { | ||
if ( options.circular ) { | ||
indexOfSource = runtime.references.sources.indexOf( sourceValue ) ; | ||
} | ||
if ( options.flat ) | ||
{ | ||
if ( options.flat ) { | ||
// No circular references reconnection when in 'flat' mode | ||
if ( indexOfSource >= 0 ) { continue ; } | ||
extendOne( | ||
@@ -410,9 +378,6 @@ { depth: runtime.depth + 1 , prefix: runtime.prefix + sourceKey + options.flat , references: runtime.references } , | ||
} | ||
else | ||
{ | ||
if ( indexOfSource >= 0 ) | ||
{ | ||
else { | ||
if ( indexOfSource >= 0 ) { | ||
// Circular references reconnection... | ||
if ( options.descriptor ) | ||
{ | ||
if ( options.descriptor ) { | ||
Object.defineProperty( targetPointer , targetKey , { | ||
@@ -425,12 +390,10 @@ value: runtime.references.targets[ indexOfSource ] , | ||
} | ||
else | ||
{ | ||
else { | ||
targetPointer[ targetKey ] = runtime.references.targets[ indexOfSource ] ; | ||
} | ||
continue ; | ||
} | ||
if ( ! targetPointer[ targetKey ] || ! targetPointer.hasOwnProperty( targetKey ) || ( typeof targetPointer[ targetKey ] !== 'object' && typeof targetPointer[ targetKey ] !== 'function' ) ) | ||
{ | ||
if ( ! targetPointer[ targetKey ] || ! targetPointer.hasOwnProperty( targetKey ) || ( typeof targetPointer[ targetKey ] !== 'object' && typeof targetPointer[ targetKey ] !== 'function' ) ) { | ||
if ( Array.isArray( sourceValue ) ) { value = [] ; } | ||
@@ -440,5 +403,4 @@ else if ( options.proto ) { value = Object.create( sourceValueProto ) ; } // jshint ignore:line | ||
else { value = {} ; } | ||
if ( options.descriptor ) | ||
{ | ||
if ( options.descriptor ) { | ||
Object.defineProperty( targetPointer , targetKey , { | ||
@@ -451,22 +413,18 @@ value: value , | ||
} | ||
else | ||
{ | ||
else { | ||
targetPointer[ targetKey ] = value ; | ||
} | ||
} | ||
else if ( options.proto && Object.getPrototypeOf( targetPointer[ targetKey ] ) !== sourceValueProto ) | ||
{ | ||
else if ( options.proto && Object.getPrototypeOf( targetPointer[ targetKey ] ) !== sourceValueProto ) { | ||
Object.setPrototypeOf( targetPointer[ targetKey ] , sourceValueProto ) ; | ||
} | ||
else if ( options.inherit && Object.getPrototypeOf( targetPointer[ targetKey ] ) !== sourceValue ) | ||
{ | ||
else if ( options.inherit && Object.getPrototypeOf( targetPointer[ targetKey ] ) !== sourceValue ) { | ||
Object.setPrototypeOf( targetPointer[ targetKey ] , sourceValue ) ; | ||
} | ||
if ( options.circular ) | ||
{ | ||
if ( options.circular ) { | ||
runtime.references.sources.push( sourceValue ) ; | ||
runtime.references.targets.push( targetPointer[ targetKey ] ) ; | ||
} | ||
// Recursively extends sub-object | ||
@@ -479,13 +437,11 @@ extendOne( | ||
} | ||
else if ( options.preserve && targetPointer[ targetKey ] !== undefined ) | ||
{ | ||
else if ( options.preserve && targetPointer[ targetKey ] !== undefined ) { | ||
// Do not overwrite, and so do not delete source's properties that were not moved | ||
continue ; | ||
} | ||
else if ( ! options.inherit ) | ||
{ | ||
else if ( ! options.inherit ) { | ||
if ( options.descriptor ) { Object.defineProperty( targetPointer , targetKey , sourceDescriptor ) ; } | ||
else { targetPointer[ targetKey ] = sourceValue ; } | ||
} | ||
// Delete owned property of the source object | ||
@@ -500,7 +456,7 @@ if ( options.move ) { delete source[ sourceKey ] ; } | ||
Tree Kit | ||
Copyright (c) 2014 - 2016 Cédric Ronvel | ||
Copyright (c) 2014 - 2018 Cédric Ronvel | ||
The MIT License (MIT) | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
@@ -512,6 +468,6 @@ of this software and associated documentation files (the "Software"), to deal | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
@@ -535,32 +491,26 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
treePath.op = function op( type , object , path , value ) | ||
{ | ||
treePath.op = function op( type , object , path , value ) { | ||
var i , parts , last , pointer , key , isArray = false , pathArrayMode = false , isGenericSet , canBeEmpty = true ; | ||
if ( ! object || ( typeof object !== 'object' && typeof object !== 'function' ) ) | ||
{ | ||
if ( ! object || ( typeof object !== 'object' && typeof object !== 'function' ) ) { | ||
return ; | ||
} | ||
if ( typeof path === 'string' ) | ||
{ | ||
if ( typeof path === 'string' ) { | ||
// Split the path into parts | ||
if ( path ) { parts = path.match( /([.#\[\]]|[^.#\[\]]+)/g ) ; } | ||
if ( path ) { parts = path.match( /([.#[\]]|[^.#[\]]+)/g ) ; } | ||
else { parts = [ '' ] ; } | ||
if ( parts[ 0 ] === '.' ) { parts.unshift( '' ) ; } | ||
if ( parts[ parts.length - 1 ] === '.' ) { parts.push( '' ) ; } | ||
} | ||
else if ( Array.isArray( path ) ) | ||
{ | ||
else if ( Array.isArray( path ) ) { | ||
parts = path ; | ||
pathArrayMode = true ; | ||
} | ||
else | ||
{ | ||
else { | ||
throw new TypeError( '[tree.path] .' + type + '(): the path argument should be a string or an array' ) ; | ||
} | ||
switch ( type ) | ||
{ | ||
switch ( type ) { | ||
case 'get' : | ||
@@ -584,63 +534,53 @@ case 'delete' : | ||
} | ||
//console.log( parts ) ; | ||
// The pointer start at the object's root | ||
pointer = object ; | ||
last = parts.length - 1 ; | ||
for ( i = 0 ; i <= last ; i ++ ) | ||
{ | ||
if ( pathArrayMode ) | ||
{ | ||
if ( key === undefined ) | ||
{ | ||
for ( i = 0 ; i <= last ; i ++ ) { | ||
if ( pathArrayMode ) { | ||
if ( key === undefined ) { | ||
key = parts[ i ] ; | ||
continue ; | ||
} | ||
if ( ! pointer[ key ] || ( typeof pointer[ key ] !== 'object' && typeof pointer[ key ] !== 'function' ) ) | ||
{ | ||
if ( ! pointer[ key ] || ( typeof pointer[ key ] !== 'object' && typeof pointer[ key ] !== 'function' ) ) { | ||
if ( ! isGenericSet ) { return undefined ; } | ||
pointer[ key ] = {} ; | ||
} | ||
pointer = pointer[ key ] ; | ||
key = parts[ i ] ; | ||
continue ; | ||
} | ||
else if ( parts[ i ] === '.' ) | ||
{ | ||
else if ( parts[ i ] === '.' ) { | ||
isArray = false ; | ||
if ( key === undefined ) | ||
{ | ||
if ( ! canBeEmpty ) | ||
{ | ||
if ( key === undefined ) { | ||
if ( ! canBeEmpty ) { | ||
canBeEmpty = true ; | ||
continue ; | ||
} | ||
key = '' ; | ||
} | ||
if ( ! pointer[ key ] || ( typeof pointer[ key ] !== 'object' && typeof pointer[ key ] !== 'function' ) ) | ||
{ | ||
if ( ! pointer[ key ] || ( typeof pointer[ key ] !== 'object' && typeof pointer[ key ] !== 'function' ) ) { | ||
if ( ! isGenericSet ) { return undefined ; } | ||
pointer[ key ] = {} ; | ||
} | ||
pointer = pointer[ key ] ; | ||
canBeEmpty = true ; | ||
continue ; | ||
} | ||
else if ( parts[ i ] === '#' || parts[ i ] === '[' ) | ||
{ | ||
else if ( parts[ i ] === '#' || parts[ i ] === '[' ) { | ||
isArray = true ; | ||
canBeEmpty = false ; | ||
if ( key === undefined ) | ||
{ | ||
if ( key === undefined ) { | ||
// The root element cannot be altered, we are in trouble if an array is expected but we have only a regular object. | ||
@@ -650,15 +590,13 @@ if ( ! Array.isArray( pointer ) ) { return undefined ; } | ||
} | ||
if ( ! pointer[ key ] || ! Array.isArray( pointer[ key ] ) ) | ||
{ | ||
if ( ! pointer[ key ] || ! Array.isArray( pointer[ key ] ) ) { | ||
if ( ! isGenericSet ) { return undefined ; } | ||
pointer[ key ] = [] ; | ||
} | ||
pointer = pointer[ key ] ; | ||
continue ; | ||
} | ||
else if ( parts[ i ] === ']' ) | ||
{ | ||
else if ( parts[ i ] === ']' ) { | ||
// Closing bracket: do nothing | ||
@@ -668,13 +606,12 @@ canBeEmpty = false ; | ||
} | ||
canBeEmpty = false ; | ||
if ( ! isArray ) { key = parts[ i ] ; continue ; } | ||
switch ( parts[ i ] ) | ||
{ | ||
switch ( parts[ i ] ) { | ||
case 'length' : | ||
key = parts[ i ] ; | ||
break ; | ||
// Pseudo-key | ||
@@ -697,5 +634,5 @@ case 'first' : | ||
break ; | ||
// default = number | ||
default: | ||
default : | ||
// Convert the string key to a numerical index | ||
@@ -705,5 +642,4 @@ key = parseInt( parts[ i ] , 10 ) ; | ||
} | ||
switch ( type ) | ||
{ | ||
switch ( type ) { | ||
case 'get' : | ||
@@ -742,4 +678,3 @@ return pointer[ key ] ; | ||
if ( ! pointer[ key ] ) { pointer[ key ] = value ; } | ||
else if ( Array.isArray( pointer[ key ] ) && Array.isArray( value ) ) | ||
{ | ||
else if ( Array.isArray( pointer[ key ] ) && Array.isArray( value ) ) { | ||
pointer[ key ] = pointer[ key ].concat( value ) ; | ||
@@ -751,4 +686,3 @@ } | ||
if ( ! pointer[ key ] ) { pointer[ key ] = value ; } | ||
else if ( Array.isArray( pointer[ key ] ) && Array.isArray( value ) ) | ||
{ | ||
else if ( Array.isArray( pointer[ key ] ) && Array.isArray( value ) ) { | ||
pointer[ key ] = value.concat( pointer[ key ] ) ; | ||
@@ -801,4 +735,3 @@ } | ||
// Upgrade an object so it can support get, set and delete at its root | ||
treePath.upgrade = function upgrade( object ) | ||
{ | ||
treePath.upgrade = function upgrade( object ) { | ||
Object.defineProperties( object , { | ||
@@ -823,2 +756,2 @@ get: { value: treePath.op.bind( undefined , 'get' , object ) } , | ||
},{}]},{},[1])(1) | ||
}); | ||
}); |
@@ -1,1 +0,1 @@ | ||
(function(e){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=e()}else if(typeof define==="function"&&define.amd){define([],e)}else{var t;if(typeof window!=="undefined"){t=window}else if(typeof global!=="undefined"){t=global}else if(typeof self!=="undefined"){t=self}else{t=this}t.treeKit=e()}})(function(){var e,t,r;return function e(t,r,n){function i(o,s){if(!r[o]){if(!t[o]){var u=typeof require=="function"&&require;if(!s&&u)return u(o,!0);if(f)return f(o,!0);var c=new Error("Cannot find module '"+o+"'");throw c.code="MODULE_NOT_FOUND",c}var a=r[o]={exports:{}};t[o][0].call(a.exports,function(e){var r=t[o][1][e];return i(r?r:e)},a,a.exports,e,t,r,n)}return r[o].exports}var f=typeof require=="function"&&require;for(var o=0;o<n.length;o++)i(n[o]);return i}({1:[function(e,t,r){"use strict";var n={};t.exports=n;n.extend=e("./extend.js");n.clone=e("./clone.js");n.path=e("./path.js")},{"./clone.js":2,"./extend.js":3,"./path.js":4}],2:[function(e,t,r){"use strict";t.exports=function e(t,r){var n,i,f,o,s,u,c=[{source:t,target:Array.isArray(t)?[]:Object.create(Object.getPrototypeOf(t))}],a=c[0].target,p=[t],d=[a];while(o=c.shift()){f=Object.getOwnPropertyNames(o.source);for(n=0;n<f.length;n++){i=Object.getOwnPropertyDescriptor(o.source,f[n]);if(!i.value||typeof i.value!=="object"){Object.defineProperty(o.target,f[n],i);continue}s=i.value;i.value=Array.isArray(s)?[]:Object.create(Object.getPrototypeOf(s));if(r){u=p.indexOf(s);if(u!==-1){i.value=d[u];Object.defineProperty(o.target,f[n],i);continue}p.push(s);d.push(i.value)}Object.defineProperty(o.target,f[n],i);c.push({source:s,target:i.value})}}return a}},{}],3:[function(e,t,r){"use strict";function n(e,t){var r,n,f=false,o=arguments.length;if(o<3){return t}var s=Array.prototype.slice.call(arguments,2);o=s.length;if(!e||typeof e!=="object"){e={}}var u={depth:0,prefix:""};if(!e.maxDepth&&e.deep&&!e.circular){e.maxDepth=100}if(e.deepFunc){e.deep=true}if(e.deepFilter&&typeof e.deepFilter==="object"){if(e.deepFilter.whitelist&&(!Array.isArray(e.deepFilter.whitelist)||!e.deepFilter.whitelist.length)){delete e.deepFilter.whitelist}if(e.deepFilter.blacklist&&(!Array.isArray(e.deepFilter.blacklist)||!e.deepFilter.blacklist.length)){delete e.deepFilter.blacklist}if(!e.deepFilter.whitelist&&!e.deepFilter.blacklist){delete e.deepFilter}}if(e.flat){e.deep=true;e.proto=false;e.inherit=false;e.unflat=false;if(typeof e.flat!=="string"){e.flat="."}}if(e.unflat){e.deep=false;e.proto=false;e.inherit=false;e.flat=false;if(typeof e.unflat!=="string"){e.unflat="."}}if(e.inherit){e.own=true;e.proto=false}else if(e.proto){e.own=true}if(!t||typeof t!=="object"&&typeof t!=="function"){f=true}if(!e.skipRoot&&(e.inherit||e.proto)){for(r=o-1;r>=0;r--){n=s[r];if(n&&(typeof n==="object"||typeof n==="function")){if(e.inherit){if(f){t=Object.create(n)}else{Object.setPrototypeOf(t,n)}}else if(e.proto){if(f){t=Object.create(Object.getPrototypeOf(n))}else{Object.setPrototypeOf(t,Object.getPrototypeOf(n))}}break}}}else if(f){t={}}u.references={sources:[],targets:[]};for(r=0;r<o;r++){n=s[r];if(!n||typeof n!=="object"&&typeof n!=="function"){continue}i(u,e,t,n)}return t}t.exports=n;function i(e,t,r,n){var f,o,s,u,c,a,p,d,l,b,y,h=-1;if(t.maxDepth&&e.depth>t.maxDepth){throw new Error("[tree] extend(): max depth reached("+t.maxDepth+")")}if(t.circular){e.references.sources.push(n);e.references.targets.push(r)}if(t.own){if(t.nonEnum){s=Object.getOwnPropertyNames(n)}else{s=Object.keys(n)}}else{s=n}for(u in s){if(t.own){u=s[u]}if(t.descriptor){d=Object.getOwnPropertyDescriptor(n,u);c=d.value}else{c=n[u]}b=r;l=e.prefix+u;if(t.nofunc&&typeof c==="function"){continue}if(t.unflat&&e.depth===0){y=u.split(t.unflat);o=y.length-1;if(o){for(f=0;f<o;f++){if(!b[y[f]]||typeof b[y[f]]!=="object"&&typeof b[y[f]]!=="function"){b[y[f]]={}}b=b[y[f]]}l=e.prefix+y[o]}}if(t.deep&&c&&(typeof c==="object"||t.deepFunc&&typeof c==="function")&&(!t.descriptor||!d.get)&&((a=Object.getPrototypeOf(c))||true)&&(!t.deepFilter||(!t.deepFilter.whitelist||t.deepFilter.whitelist.indexOf(a)!==-1)&&(!t.deepFilter.blacklist||t.deepFilter.blacklist.indexOf(a)===-1))){if(t.circular){h=e.references.sources.indexOf(c)}if(t.flat){if(h>=0){continue}i({depth:e.depth+1,prefix:e.prefix+u+t.flat,references:e.references},t,b,c)}else{if(h>=0){if(t.descriptor){Object.defineProperty(b,l,{value:e.references.targets[h],enumerable:d.enumerable,writable:d.writable,configurable:d.configurable})}else{b[l]=e.references.targets[h]}continue}if(!b[l]||!b.hasOwnProperty(l)||typeof b[l]!=="object"&&typeof b[l]!=="function"){if(Array.isArray(c)){p=[]}else if(t.proto){p=Object.create(a)}else if(t.inherit){p=Object.create(c)}else{p={}}if(t.descriptor){Object.defineProperty(b,l,{value:p,enumerable:d.enumerable,writable:d.writable,configurable:d.configurable})}else{b[l]=p}}else if(t.proto&&Object.getPrototypeOf(b[l])!==a){Object.setPrototypeOf(b[l],a)}else if(t.inherit&&Object.getPrototypeOf(b[l])!==c){Object.setPrototypeOf(b[l],c)}if(t.circular){e.references.sources.push(c);e.references.targets.push(b[l])}i({depth:e.depth+1,prefix:"",references:e.references},t,b[l],c)}}else if(t.preserve&&b[l]!==undefined){continue}else if(!t.inherit){if(t.descriptor){Object.defineProperty(b,l,d)}else{b[l]=c}}if(t.move){delete n[u]}}}},{}],4:[function(e,t,r){"use strict";var n={};t.exports=n;n.op=function e(t,r,n,i){var f,o,s,u,c,a=false,p=false,d,l=true;if(!r||typeof r!=="object"&&typeof r!=="function"){return}if(typeof n==="string"){if(n){o=n.match(/([.#\[\]]|[^.#\[\]]+)/g)}else{o=[""]}if(o[0]==="."){o.unshift("")}if(o[o.length-1]==="."){o.push("")}}else if(Array.isArray(n)){o=n;p=true}else{throw new TypeError("[tree.path] ."+t+"(): the path argument should be a string or an array")}switch(t){case"get":case"delete":d=false;break;case"set":case"define":case"inc":case"dec":case"append":case"prepend":case"concat":case"insert":case"autoPush":d=true;break;default:throw new TypeError("[tree.path] .op(): wrong type of operation '"+t+"'")}u=r;s=o.length-1;for(f=0;f<=s;f++){if(p){if(c===undefined){c=o[f];continue}if(!u[c]||typeof u[c]!=="object"&&typeof u[c]!=="function"){if(!d){return undefined}u[c]={}}u=u[c];c=o[f];continue}else if(o[f]==="."){a=false;if(c===undefined){if(!l){l=true;continue}c=""}if(!u[c]||typeof u[c]!=="object"&&typeof u[c]!=="function"){if(!d){return undefined}u[c]={}}u=u[c];l=true;continue}else if(o[f]==="#"||o[f]==="["){a=true;l=false;if(c===undefined){if(!Array.isArray(u)){return undefined}continue}if(!u[c]||!Array.isArray(u[c])){if(!d){return undefined}u[c]=[]}u=u[c];continue}else if(o[f]==="]"){l=false;continue}l=false;if(!a){c=o[f];continue}switch(o[f]){case"length":c=o[f];break;case"first":c=0;break;case"last":c=u.length-1;if(c<0){c=0}break;case"next":if(!d){return undefined}c=u.length;break;case"insert":if(!d){return undefined}u.unshift(undefined);c=0;break;default:c=parseInt(o[f],10)}}switch(t){case"get":return u[c];case"delete":if(a&&typeof c==="number"){u.splice(c,1)}else{delete u[c]}return;case"set":u[c]=i;return u[c];case"define":if(!(c in u)){u[c]=i}return u[c];case"inc":if(typeof u[c]==="number"){u[c]++}else if(!u[c]||typeof u[c]!=="object"){u[c]=1}return u[c];case"dec":if(typeof u[c]==="number"){u[c]--}else if(!u[c]||typeof u[c]!=="object"){u[c]=-1}return u[c];case"append":if(!u[c]){u[c]=[i]}else if(Array.isArray(u[c])){u[c].push(i)}return u[c];case"prepend":if(!u[c]){u[c]=[i]}else if(Array.isArray(u[c])){u[c].unshift(i)}return u[c];case"concat":if(!u[c]){u[c]=i}else if(Array.isArray(u[c])&&Array.isArray(i)){u[c]=u[c].concat(i)}return u[c];case"insert":if(!u[c]){u[c]=i}else if(Array.isArray(u[c])&&Array.isArray(i)){u[c]=i.concat(u[c])}return u[c];case"autoPush":if(u[c]===undefined){u[c]=i}else if(Array.isArray(u[c])){u[c].push(i)}else{u[c]=[u[c],i]}return u[c]}};n.get=n.op.bind(undefined,"get");n.delete=n.op.bind(undefined,"delete");n.set=n.op.bind(undefined,"set");n.define=n.op.bind(undefined,"define");n.inc=n.op.bind(undefined,"inc");n.dec=n.op.bind(undefined,"dec");n.append=n.op.bind(undefined,"append");n.prepend=n.op.bind(undefined,"prepend");n.concat=n.op.bind(undefined,"concat");n.insert=n.op.bind(undefined,"insert");n.autoPush=n.op.bind(undefined,"autoPush");n.prototype={get:function(e){return n.get(this,e)},delete:function(e){return n.delete(this,e)},set:function(e,t){return n.set(this,e,t)},define:function(e,t){return n.define(this,e,t)},inc:function(e,t){return n.inc(this,e,t)},dec:function(e,t){return n.dec(this,e,t)},append:function(e,t){return n.append(this,e,t)},prepend:function(e,t){return n.prepend(this,e,t)},concat:function(e,t){return n.concat(this,e,t)},insert:function(e,t){return n.insert(this,e,t)},autoPush:function(e,t){return n.autoPush(this,e,t)}};n.upgrade=function e(t){Object.defineProperties(t,{get:{value:n.op.bind(undefined,"get",t)},delete:{value:n.op.bind(undefined,"delete",t)},set:{value:n.op.bind(undefined,"set",t)},define:{value:n.op.bind(undefined,"define",t)},inc:{value:n.op.bind(undefined,"inc",t)},dec:{value:n.op.bind(undefined,"dec",t)},append:{value:n.op.bind(undefined,"append",t)},prepend:{value:n.op.bind(undefined,"prepend",t)},concat:{value:n.op.bind(undefined,"concat",t)},insert:{value:n.op.bind(undefined,"insert",t)},autoPush:{value:n.op.bind(undefined,"autoPush",t)}})}},{}]},{},[1])(1)}); | ||
(function(e){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=e()}else if(typeof define==="function"&&define.amd){define([],e)}else{var t;if(typeof window!=="undefined"){t=window}else if(typeof global!=="undefined"){t=global}else if(typeof self!=="undefined"){t=self}else{t=this}t.treeKit=e()}})(function(){var e,t,r;return function(){function e(t,r,n){function i(o,s){if(!r[o]){if(!t[o]){var u="function"==typeof require&&require;if(!s&&u)return u(o,!0);if(f)return f(o,!0);var c=new Error("Cannot find module '"+o+"'");throw c.code="MODULE_NOT_FOUND",c}var a=r[o]={exports:{}};t[o][0].call(a.exports,function(e){var r=t[o][1][e];return i(r||e)},a,a.exports,e,t,r,n)}return r[o].exports}for(var f="function"==typeof require&&require,o=0;o<n.length;o++)i(n[o]);return i}return e}()({1:[function(e,t,r){"use strict";var n={};t.exports=n;n.extend=e("./extend.js");n.clone=e("./clone.js");n.path=e("./path.js")},{"./clone.js":2,"./extend.js":3,"./path.js":4}],2:[function(e,t,r){"use strict";t.exports=function e(t,r){var n,i,f,o,s,u,c=[{source:t,target:Array.isArray(t)?[]:Object.create(Object.getPrototypeOf(t))}],a=c[0].target,p=[t],d=[a];while(o=c.shift()){f=Object.getOwnPropertyNames(o.source);for(n=0;n<f.length;n++){i=Object.getOwnPropertyDescriptor(o.source,f[n]);if(!i.value||typeof i.value!=="object"){Object.defineProperty(o.target,f[n],i);continue}s=i.value;i.value=Array.isArray(s)?[]:Object.create(Object.getPrototypeOf(s));if(r){u=p.indexOf(s);if(u!==-1){i.value=d[u];Object.defineProperty(o.target,f[n],i);continue}p.push(s);d.push(i.value)}Object.defineProperty(o.target,f[n],i);c.push({source:s,target:i.value})}}return a}},{}],3:[function(e,t,r){"use strict";function n(e,t,...r){var n,f,o=false,s=r.length;if(!s){return t}if(!e||typeof e!=="object"){e={}}var u={depth:0,prefix:""};if(!e.maxDepth&&e.deep&&!e.circular){e.maxDepth=100}if(e.deepFunc){e.deep=true}if(e.deepFilter&&typeof e.deepFilter==="object"){if(e.deepFilter.whitelist&&(!Array.isArray(e.deepFilter.whitelist)||!e.deepFilter.whitelist.length)){delete e.deepFilter.whitelist}if(e.deepFilter.blacklist&&(!Array.isArray(e.deepFilter.blacklist)||!e.deepFilter.blacklist.length)){delete e.deepFilter.blacklist}if(!e.deepFilter.whitelist&&!e.deepFilter.blacklist){delete e.deepFilter}}if(e.flat){e.deep=true;e.proto=false;e.inherit=false;e.unflat=false;if(typeof e.flat!=="string"){e.flat="."}}if(e.unflat){e.deep=false;e.proto=false;e.inherit=false;e.flat=false;if(typeof e.unflat!=="string"){e.unflat="."}}if(e.inherit){e.own=true;e.proto=false}else if(e.proto){e.own=true}if(!t||typeof t!=="object"&&typeof t!=="function"){o=true}if(!e.skipRoot&&(e.inherit||e.proto)){for(n=s-1;n>=0;n--){f=r[n];if(f&&(typeof f==="object"||typeof f==="function")){if(e.inherit){if(o){t=Object.create(f)}else{Object.setPrototypeOf(t,f)}}else if(e.proto){if(o){t=Object.create(Object.getPrototypeOf(f))}else{Object.setPrototypeOf(t,Object.getPrototypeOf(f))}}break}}}else if(o){t={}}u.references={sources:[],targets:[]};for(n=0;n<s;n++){f=r[n];if(!f||typeof f!=="object"&&typeof f!=="function"){continue}i(u,e,t,f)}return t}t.exports=n;function i(e,t,r,n){var f,o,s,u,c,a,p,d,l,b,y,h=-1;if(t.maxDepth&&e.depth>t.maxDepth){throw new Error("[tree] extend(): max depth reached("+t.maxDepth+")")}if(t.circular){e.references.sources.push(n);e.references.targets.push(r)}if(t.own){if(t.nonEnum){s=Object.getOwnPropertyNames(n)}else{s=Object.keys(n)}}else{s=n}for(u in s){if(t.own){u=s[u]}if(u==="__proto__"){continue}if(t.descriptor){d=Object.getOwnPropertyDescriptor(n,u);c=d.value}else{c=n[u]}b=r;l=e.prefix+u;if(t.nofunc&&typeof c==="function"){continue}if(t.unflat&&e.depth===0){y=u.split(t.unflat);o=y.length-1;if(o){for(f=0;f<o;f++){if(!b[y[f]]||typeof b[y[f]]!=="object"&&typeof b[y[f]]!=="function"){b[y[f]]={}}b=b[y[f]]}l=e.prefix+y[o]}}if(t.deep&&c&&(typeof c==="object"||t.deepFunc&&typeof c==="function")&&(!t.descriptor||!d.get)&&((a=Object.getPrototypeOf(c))||true)&&(!t.deepFilter||(!t.deepFilter.whitelist||t.deepFilter.whitelist.indexOf(a)!==-1)&&(!t.deepFilter.blacklist||t.deepFilter.blacklist.indexOf(a)===-1))){if(t.circular){h=e.references.sources.indexOf(c)}if(t.flat){if(h>=0){continue}i({depth:e.depth+1,prefix:e.prefix+u+t.flat,references:e.references},t,b,c)}else{if(h>=0){if(t.descriptor){Object.defineProperty(b,l,{value:e.references.targets[h],enumerable:d.enumerable,writable:d.writable,configurable:d.configurable})}else{b[l]=e.references.targets[h]}continue}if(!b[l]||!b.hasOwnProperty(l)||typeof b[l]!=="object"&&typeof b[l]!=="function"){if(Array.isArray(c)){p=[]}else if(t.proto){p=Object.create(a)}else if(t.inherit){p=Object.create(c)}else{p={}}if(t.descriptor){Object.defineProperty(b,l,{value:p,enumerable:d.enumerable,writable:d.writable,configurable:d.configurable})}else{b[l]=p}}else if(t.proto&&Object.getPrototypeOf(b[l])!==a){Object.setPrototypeOf(b[l],a)}else if(t.inherit&&Object.getPrototypeOf(b[l])!==c){Object.setPrototypeOf(b[l],c)}if(t.circular){e.references.sources.push(c);e.references.targets.push(b[l])}i({depth:e.depth+1,prefix:"",references:e.references},t,b[l],c)}}else if(t.preserve&&b[l]!==undefined){continue}else if(!t.inherit){if(t.descriptor){Object.defineProperty(b,l,d)}else{b[l]=c}}if(t.move){delete n[u]}}}},{}],4:[function(e,t,r){"use strict";var n={};t.exports=n;n.op=function e(t,r,n,i){var f,o,s,u,c,a=false,p=false,d,l=true;if(!r||typeof r!=="object"&&typeof r!=="function"){return}if(typeof n==="string"){if(n){o=n.match(/([.#[\]]|[^.#[\]]+)/g)}else{o=[""]}if(o[0]==="."){o.unshift("")}if(o[o.length-1]==="."){o.push("")}}else if(Array.isArray(n)){o=n;p=true}else{throw new TypeError("[tree.path] ."+t+"(): the path argument should be a string or an array")}switch(t){case"get":case"delete":d=false;break;case"set":case"define":case"inc":case"dec":case"append":case"prepend":case"concat":case"insert":case"autoPush":d=true;break;default:throw new TypeError("[tree.path] .op(): wrong type of operation '"+t+"'")}u=r;s=o.length-1;for(f=0;f<=s;f++){if(p){if(c===undefined){c=o[f];continue}if(!u[c]||typeof u[c]!=="object"&&typeof u[c]!=="function"){if(!d){return undefined}u[c]={}}u=u[c];c=o[f];continue}else if(o[f]==="."){a=false;if(c===undefined){if(!l){l=true;continue}c=""}if(!u[c]||typeof u[c]!=="object"&&typeof u[c]!=="function"){if(!d){return undefined}u[c]={}}u=u[c];l=true;continue}else if(o[f]==="#"||o[f]==="["){a=true;l=false;if(c===undefined){if(!Array.isArray(u)){return undefined}continue}if(!u[c]||!Array.isArray(u[c])){if(!d){return undefined}u[c]=[]}u=u[c];continue}else if(o[f]==="]"){l=false;continue}l=false;if(!a){c=o[f];continue}switch(o[f]){case"length":c=o[f];break;case"first":c=0;break;case"last":c=u.length-1;if(c<0){c=0}break;case"next":if(!d){return undefined}c=u.length;break;case"insert":if(!d){return undefined}u.unshift(undefined);c=0;break;default:c=parseInt(o[f],10)}}switch(t){case"get":return u[c];case"delete":if(a&&typeof c==="number"){u.splice(c,1)}else{delete u[c]}return;case"set":u[c]=i;return u[c];case"define":if(!(c in u)){u[c]=i}return u[c];case"inc":if(typeof u[c]==="number"){u[c]++}else if(!u[c]||typeof u[c]!=="object"){u[c]=1}return u[c];case"dec":if(typeof u[c]==="number"){u[c]--}else if(!u[c]||typeof u[c]!=="object"){u[c]=-1}return u[c];case"append":if(!u[c]){u[c]=[i]}else if(Array.isArray(u[c])){u[c].push(i)}return u[c];case"prepend":if(!u[c]){u[c]=[i]}else if(Array.isArray(u[c])){u[c].unshift(i)}return u[c];case"concat":if(!u[c]){u[c]=i}else if(Array.isArray(u[c])&&Array.isArray(i)){u[c]=u[c].concat(i)}return u[c];case"insert":if(!u[c]){u[c]=i}else if(Array.isArray(u[c])&&Array.isArray(i)){u[c]=i.concat(u[c])}return u[c];case"autoPush":if(u[c]===undefined){u[c]=i}else if(Array.isArray(u[c])){u[c].push(i)}else{u[c]=[u[c],i]}return u[c]}};n.get=n.op.bind(undefined,"get");n.delete=n.op.bind(undefined,"delete");n.set=n.op.bind(undefined,"set");n.define=n.op.bind(undefined,"define");n.inc=n.op.bind(undefined,"inc");n.dec=n.op.bind(undefined,"dec");n.append=n.op.bind(undefined,"append");n.prepend=n.op.bind(undefined,"prepend");n.concat=n.op.bind(undefined,"concat");n.insert=n.op.bind(undefined,"insert");n.autoPush=n.op.bind(undefined,"autoPush");n.prototype={get:function(e){return n.get(this,e)},delete:function(e){return n.delete(this,e)},set:function(e,t){return n.set(this,e,t)},define:function(e,t){return n.define(this,e,t)},inc:function(e,t){return n.inc(this,e,t)},dec:function(e,t){return n.dec(this,e,t)},append:function(e,t){return n.append(this,e,t)},prepend:function(e,t){return n.prepend(this,e,t)},concat:function(e,t){return n.concat(this,e,t)},insert:function(e,t){return n.insert(this,e,t)},autoPush:function(e,t){return n.autoPush(this,e,t)}};n.upgrade=function e(t){Object.defineProperties(t,{get:{value:n.op.bind(undefined,"get",t)},delete:{value:n.op.bind(undefined,"delete",t)},set:{value:n.op.bind(undefined,"set",t)},define:{value:n.op.bind(undefined,"define",t)},inc:{value:n.op.bind(undefined,"inc",t)},dec:{value:n.op.bind(undefined,"dec",t)},append:{value:n.op.bind(undefined,"append",t)},prepend:{value:n.op.bind(undefined,"prepend",t)},concat:{value:n.op.bind(undefined,"concat",t)},insert:{value:n.op.bind(undefined,"insert",t)},autoPush:{value:n.op.bind(undefined,"autoPush",t)}})}},{}]},{},[1])(1)}); |
# Tree Kit | ||
@@ -269,8 +268,1 @@ | ||
Full BDD spec generated by Mocha: | ||
/* | ||
Tree Kit | ||
Copyright (c) 2014 - 2016 Cédric Ronvel | ||
Copyright (c) 2014 - 2018 Cédric Ronvel | ||
The MIT License (MIT) | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
@@ -14,6 +14,6 @@ of this software and associated documentation files (the "Software"), to deal | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
@@ -20,0 +20,0 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
/* | ||
Tree Kit | ||
Copyright (c) 2014 - 2016 Cédric Ronvel | ||
Copyright (c) 2014 - 2018 Cédric Ronvel | ||
The MIT License (MIT) | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
@@ -14,6 +14,6 @@ of this software and associated documentation files (the "Software"), to deal | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
@@ -36,7 +36,6 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
module.exports = function clone( originalObject , circular ) | ||
{ | ||
module.exports = function clone( originalObject , circular ) { | ||
// First create an empty object with | ||
// same prototype of our original source | ||
var propertyIndex , descriptor , keys , current , nextSource , indexOf , | ||
@@ -50,28 +49,23 @@ copies = [ { | ||
targetReferences = [ cloneObject ] ; | ||
// First in, first out | ||
while ( current = copies.shift() ) // jshint ignore:line | ||
{ | ||
while ( ( current = copies.shift() ) ) { | ||
keys = Object.getOwnPropertyNames( current.source ) ; | ||
for ( propertyIndex = 0 ; propertyIndex < keys.length ; propertyIndex ++ ) | ||
{ | ||
for ( propertyIndex = 0 ; propertyIndex < keys.length ; propertyIndex ++ ) { | ||
// Save the source's descriptor | ||
descriptor = Object.getOwnPropertyDescriptor( current.source , keys[ propertyIndex ] ) ; | ||
if ( ! descriptor.value || typeof descriptor.value !== 'object' ) | ||
{ | ||
if ( ! descriptor.value || typeof descriptor.value !== 'object' ) { | ||
Object.defineProperty( current.target , keys[ propertyIndex ] , descriptor ) ; | ||
continue ; | ||
} | ||
nextSource = descriptor.value ; | ||
descriptor.value = Array.isArray( nextSource ) ? [] : Object.create( Object.getPrototypeOf( nextSource ) ) ; | ||
if ( circular ) | ||
{ | ||
if ( circular ) { | ||
indexOf = sourceReferences.indexOf( nextSource ) ; | ||
if ( indexOf !== -1 ) | ||
{ | ||
if ( indexOf !== -1 ) { | ||
// The source is already referenced, just assign reference | ||
@@ -82,14 +76,14 @@ descriptor.value = targetReferences[ indexOf ] ; | ||
} | ||
sourceReferences.push( nextSource ) ; | ||
targetReferences.push( descriptor.value ) ; | ||
} | ||
Object.defineProperty( current.target , keys[ propertyIndex ] , descriptor ) ; | ||
copies.push( { source: nextSource , target: descriptor.value } ) ; | ||
} | ||
} | ||
return cloneObject ; | ||
} ; |
116
lib/diff.js
/* | ||
Tree Kit | ||
Copyright (c) 2014 - 2016 Cédric Ronvel | ||
Copyright (c) 2014 - 2018 Cédric Ronvel | ||
The MIT License (MIT) | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
@@ -14,6 +14,6 @@ of this software and associated documentation files (the "Software"), to deal | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
@@ -36,26 +36,23 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
function diff( left , right , options ) | ||
{ | ||
function diff( left , right , options ) { | ||
var i , key , keyPath , | ||
leftKeys , rightKeys , leftTypeof , rightTypeof , | ||
depth , diffObject , length , arrayMode ; | ||
leftTypeof = typeof left ; | ||
rightTypeof = typeof right ; | ||
if ( | ||
! left || ( leftTypeof !== 'object' && leftTypeof !== 'function' ) || | ||
! right || ( rightTypeof !== 'object' && rightTypeof !== 'function' ) | ||
) | ||
{ | ||
) { | ||
throw new Error( '[tree] diff() needs objects as argument #0 and #1' ) ; | ||
} | ||
if ( ! options || typeof options !== 'object' ) { options = {} ; } | ||
depth = options.depth || 0 ; | ||
// Things applied only for the root, not for recursive call | ||
if ( ! depth ) | ||
{ | ||
if ( ! depth ) { | ||
options.diffObject = {} ; | ||
@@ -65,14 +62,12 @@ if ( ! options.path ) { options.path = '' ; } | ||
} | ||
diffObject = options.diffObject ; | ||
// Left part | ||
if ( Array.isArray( left ) ) | ||
{ | ||
if ( Array.isArray( left ) ) { | ||
arrayMode = true ; | ||
length = left.length ; | ||
} | ||
else | ||
{ | ||
else { | ||
arrayMode = false ; | ||
@@ -82,57 +77,50 @@ leftKeys = Object.keys( left ) ; | ||
} | ||
for ( i = 0 ; i < length ; i ++ ) | ||
{ | ||
for ( i = 0 ; i < length ; i ++ ) { | ||
key = arrayMode ? i : leftKeys[ i ] ; | ||
keyPath = options.path + options.pathSeparator + key ; | ||
//console.log( 'L keyPath:' , keyPath ) ; | ||
if ( ! right.hasOwnProperty( key ) ) | ||
{ | ||
if ( ! right.hasOwnProperty( key ) ) { | ||
diffObject[ keyPath ] = { path: keyPath , message: 'does not exist in right-hand side' } ; | ||
continue ; | ||
} | ||
leftTypeof = typeof left[ key ] ; | ||
rightTypeof = typeof right[ key ] ; | ||
if ( leftTypeof !== rightTypeof ) | ||
{ | ||
if ( leftTypeof !== rightTypeof ) { | ||
diffObject[ keyPath ] = { path: keyPath , message: 'different typeof: ' + leftTypeof + ' - ' + rightTypeof } ; | ||
continue ; | ||
} | ||
if ( leftTypeof === 'object' || leftTypeof === 'function' ) | ||
{ | ||
if ( leftTypeof === 'object' || leftTypeof === 'function' ) { | ||
// Cleanup the 'null is an object' mess | ||
if ( ! left[ key ] ) | ||
{ | ||
if ( ! left[ key ] ) { | ||
if ( right[ key ] ) { diffObject[ keyPath ] = { path: keyPath , message: 'different type: null - Object' } ; } | ||
continue ; | ||
} | ||
if ( ! right[ key ] ) | ||
{ | ||
if ( ! right[ key ] ) { | ||
diffObject[ keyPath ] = { path: keyPath , message: 'different type: Object - null' } ; | ||
continue ; | ||
} | ||
if ( Array.isArray( left[ key ] ) && ! Array.isArray( right[ key ] ) ) | ||
{ | ||
if ( Array.isArray( left[ key ] ) && ! Array.isArray( right[ key ] ) ) { | ||
diffObject[ keyPath ] = { path: keyPath , message: 'different type: Array - Object' } ; | ||
continue ; | ||
} | ||
if ( ! Array.isArray( left[ key ] ) && Array.isArray( right[ key ] ) ) | ||
{ | ||
if ( ! Array.isArray( left[ key ] ) && Array.isArray( right[ key ] ) ) { | ||
diffObject[ keyPath ] = { path: keyPath , message: 'different type: Object - Array' } ; | ||
continue ; | ||
} | ||
diff( left[ key ] , right[ key ] , { path: keyPath , pathSeparator: options.pathSeparator , depth: depth + 1 , diffObject: diffObject } ) ; | ||
diff( left[ key ] , right[ key ] , { | ||
path: keyPath , pathSeparator: options.pathSeparator , depth: depth + 1 , diffObject: diffObject | ||
} ) ; | ||
continue ; | ||
} | ||
if ( left[ key ] !== right[ key ] ) | ||
{ | ||
if ( left[ key ] !== right[ key ] ) { | ||
diffObject[ keyPath ] = { path: keyPath , message: 'different value: ' + left[ key ] + ' - ' + right[ key ] } ; | ||
@@ -142,12 +130,10 @@ continue ; | ||
} | ||
// Right part | ||
if ( Array.isArray( right ) ) | ||
{ | ||
if ( Array.isArray( right ) ) { | ||
arrayMode = true ; | ||
length = right.length ; | ||
} | ||
else | ||
{ | ||
else { | ||
arrayMode = false ; | ||
@@ -157,11 +143,9 @@ rightKeys = Object.keys( right ) ; | ||
} | ||
for ( i = 0 ; i < length ; i ++ ) | ||
{ | ||
for ( i = 0 ; i < length ; i ++ ) { | ||
key = arrayMode ? i : rightKeys[ i ] ; | ||
keyPath = options.path + options.pathSeparator + key ; | ||
//console.log( 'R keyPath:' , keyPath ) ; | ||
if ( ! left.hasOwnProperty( key ) ) | ||
{ | ||
if ( ! left.hasOwnProperty( key ) ) { | ||
diffObject[ keyPath ] = { path: keyPath , message: 'does not exist in left-hand side' } ; | ||
@@ -171,3 +155,3 @@ continue ; | ||
} | ||
return Object.keys( diffObject ).length ? diffObject : null ; | ||
@@ -174,0 +158,0 @@ } |
/* | ||
Tree Kit | ||
Copyright (c) 2014 - 2016 Cédric Ronvel | ||
Copyright (c) 2014 - 2018 Cédric Ronvel | ||
The MIT License (MIT) | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
@@ -14,6 +14,6 @@ of this software and associated documentation files (the "Software"), to deal | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
@@ -63,22 +63,17 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
*/ | ||
function extend( options , target ) | ||
{ | ||
function extend( options , target , ... sources ) { | ||
//console.log( "\nextend():\n" , arguments ) ; | ||
var i , source , newTarget = false , length = arguments.length ; | ||
if ( length < 3 ) { return target ; } | ||
var sources = Array.prototype.slice.call( arguments , 2 ) ; | ||
length = sources.length ; | ||
var i , source , newTarget = false , length = sources.length ; | ||
if ( ! length ) { return target ; } | ||
if ( ! options || typeof options !== 'object' ) { options = {} ; } | ||
var runtime = { depth: 0 , prefix: '' } ; | ||
if ( ! options.maxDepth && options.deep && ! options.circular ) { options.maxDepth = 100 ; } | ||
if ( options.deepFunc ) { options.deep = true ; } | ||
if ( options.deepFilter && typeof options.deepFilter === 'object' ) | ||
{ | ||
if ( options.deepFilter && typeof options.deepFilter === 'object' ) { | ||
if ( options.deepFilter.whitelist && ( ! Array.isArray( options.deepFilter.whitelist ) || ! options.deepFilter.whitelist.length ) ) { delete options.deepFilter.whitelist ; } | ||
@@ -88,6 +83,5 @@ if ( options.deepFilter.blacklist && ( ! Array.isArray( options.deepFilter.blacklist ) || ! options.deepFilter.blacklist.length ) ) { delete options.deepFilter.blacklist ; } | ||
} | ||
// 'flat' option force 'deep' | ||
if ( options.flat ) | ||
{ | ||
if ( options.flat ) { | ||
options.deep = true ; | ||
@@ -99,5 +93,4 @@ options.proto = false ; | ||
} | ||
if ( options.unflat ) | ||
{ | ||
if ( options.unflat ) { | ||
options.deep = false ; | ||
@@ -109,30 +102,24 @@ options.proto = false ; | ||
} | ||
// If the prototype is applied, only owned properties should be copied | ||
if ( options.inherit ) { options.own = true ; options.proto = false ; } | ||
else if ( options.proto ) { options.own = true ; } | ||
if ( ! target || ( typeof target !== 'object' && typeof target !== 'function' ) ) | ||
{ | ||
if ( ! target || ( typeof target !== 'object' && typeof target !== 'function' ) ) { | ||
newTarget = true ; | ||
} | ||
if ( ! options.skipRoot && ( options.inherit || options.proto ) ) | ||
{ | ||
for ( i = length - 1 ; i >= 0 ; i -- ) | ||
{ | ||
if ( ! options.skipRoot && ( options.inherit || options.proto ) ) { | ||
for ( i = length - 1 ; i >= 0 ; i -- ) { | ||
source = sources[ i ] ; | ||
if ( source && ( typeof source === 'object' || typeof source === 'function' ) ) | ||
{ | ||
if ( options.inherit ) | ||
{ | ||
if ( source && ( typeof source === 'object' || typeof source === 'function' ) ) { | ||
if ( options.inherit ) { | ||
if ( newTarget ) { target = Object.create( source ) ; } | ||
else { Object.setPrototypeOf( target , source ) ; } | ||
} | ||
else if ( options.proto ) | ||
{ | ||
else if ( options.proto ) { | ||
if ( newTarget ) { target = Object.create( Object.getPrototypeOf( source ) ) ; } | ||
else { Object.setPrototypeOf( target , Object.getPrototypeOf( source ) ) ; } | ||
} | ||
break ; | ||
@@ -142,11 +129,9 @@ } | ||
} | ||
else if ( newTarget ) | ||
{ | ||
else if ( newTarget ) { | ||
target = {} ; | ||
} | ||
runtime.references = { sources: [] , targets: [] } ; | ||
for ( i = 0 ; i < length ; i ++ ) | ||
{ | ||
for ( i = 0 ; i < length ; i ++ ) { | ||
source = sources[ i ] ; | ||
@@ -156,3 +141,3 @@ if ( ! source || ( typeof source !== 'object' && typeof source !== 'function' ) ) { continue ; } | ||
} | ||
return target ; | ||
@@ -165,26 +150,22 @@ } | ||
function extendOne( runtime , options , target , source ) | ||
{ | ||
function extendOne( runtime , options , target , source ) { | ||
//console.log( "\nextendOne():\n" , arguments ) ; | ||
//process.exit() ; | ||
var j , jmax , sourceKeys , sourceKey , sourceValue , sourceValueProto , | ||
value , sourceDescriptor , targetKey , targetPointer , path , | ||
indexOfSource = -1 ; | ||
// Max depth check | ||
if ( options.maxDepth && runtime.depth > options.maxDepth ) | ||
{ | ||
if ( options.maxDepth && runtime.depth > options.maxDepth ) { | ||
throw new Error( '[tree] extend(): max depth reached(' + options.maxDepth + ')' ) ; | ||
} | ||
if ( options.circular ) | ||
{ | ||
if ( options.circular ) { | ||
runtime.references.sources.push( source ) ; | ||
runtime.references.targets.push( target ) ; | ||
} | ||
if ( options.own ) | ||
{ | ||
if ( options.own ) { | ||
if ( options.nonEnum ) { sourceKeys = Object.getOwnPropertyNames( source ) ; } | ||
@@ -194,70 +175,63 @@ else { sourceKeys = Object.keys( source ) ; } | ||
else { sourceKeys = source ; } | ||
for ( sourceKey in sourceKeys ) | ||
{ | ||
for ( sourceKey in sourceKeys ) { | ||
if ( options.own ) { sourceKey = sourceKeys[ sourceKey ] ; } | ||
// OMG, this DEPRECATED __proto__ shit is still alive and can be used to hack anything >< | ||
if ( sourceKey === '__proto__' ) { continue ; } | ||
// If descriptor is on, get it now | ||
if ( options.descriptor ) | ||
{ | ||
if ( options.descriptor ) { | ||
sourceDescriptor = Object.getOwnPropertyDescriptor( source , sourceKey ) ; | ||
sourceValue = sourceDescriptor.value ; | ||
} | ||
else | ||
{ | ||
else { | ||
// We have to trigger an eventual getter only once | ||
sourceValue = source[ sourceKey ] ; | ||
} | ||
targetPointer = target ; | ||
targetKey = runtime.prefix + sourceKey ; | ||
// Do not copy if property is a function and we don't want them | ||
if ( options.nofunc && typeof sourceValue === 'function' ) { continue; } | ||
if ( options.nofunc && typeof sourceValue === 'function' ) { continue ; } | ||
// 'unflat' mode computing | ||
if ( options.unflat && runtime.depth === 0 ) | ||
{ | ||
if ( options.unflat && runtime.depth === 0 ) { | ||
path = sourceKey.split( options.unflat ) ; | ||
jmax = path.length - 1 ; | ||
if ( jmax ) | ||
{ | ||
for ( j = 0 ; j < jmax ; j ++ ) | ||
{ | ||
if ( jmax ) { | ||
for ( j = 0 ; j < jmax ; j ++ ) { | ||
if ( ! targetPointer[ path[ j ] ] || | ||
( typeof targetPointer[ path[ j ] ] !== 'object' && | ||
typeof targetPointer[ path[ j ] ] !== 'function' ) ) | ||
{ | ||
typeof targetPointer[ path[ j ] ] !== 'function' ) ) { | ||
targetPointer[ path[ j ] ] = {} ; | ||
} | ||
targetPointer = targetPointer[ path[ j ] ] ; | ||
} | ||
targetKey = runtime.prefix + path[ jmax ] ; | ||
} | ||
} | ||
if ( options.deep && | ||
if ( options.deep && // eslint-disable-line no-constant-condition | ||
sourceValue && | ||
( typeof sourceValue === 'object' || ( options.deepFunc && typeof sourceValue === 'function' ) ) && | ||
( ! options.descriptor || ! sourceDescriptor.get ) && | ||
// not a condition we just cache sourceValueProto now | ||
// not a condition we just cache sourceValueProto now... ok it's trashy >< | ||
( ( sourceValueProto = Object.getPrototypeOf( sourceValue ) ) || true ) && | ||
( ! options.deepFilter || | ||
( ( ! options.deepFilter.whitelist || options.deepFilter.whitelist.indexOf( sourceValueProto ) !== -1 ) && | ||
( ! options.deepFilter.blacklist || options.deepFilter.blacklist.indexOf( sourceValueProto ) === -1 ) ) ) ) | ||
{ | ||
if ( options.circular ) | ||
{ | ||
( ! options.deepFilter.blacklist || options.deepFilter.blacklist.indexOf( sourceValueProto ) === -1 ) ) ) ) { | ||
if ( options.circular ) { | ||
indexOfSource = runtime.references.sources.indexOf( sourceValue ) ; | ||
} | ||
if ( options.flat ) | ||
{ | ||
if ( options.flat ) { | ||
// No circular references reconnection when in 'flat' mode | ||
if ( indexOfSource >= 0 ) { continue ; } | ||
extendOne( | ||
@@ -268,9 +242,6 @@ { depth: runtime.depth + 1 , prefix: runtime.prefix + sourceKey + options.flat , references: runtime.references } , | ||
} | ||
else | ||
{ | ||
if ( indexOfSource >= 0 ) | ||
{ | ||
else { | ||
if ( indexOfSource >= 0 ) { | ||
// Circular references reconnection... | ||
if ( options.descriptor ) | ||
{ | ||
if ( options.descriptor ) { | ||
Object.defineProperty( targetPointer , targetKey , { | ||
@@ -283,12 +254,10 @@ value: runtime.references.targets[ indexOfSource ] , | ||
} | ||
else | ||
{ | ||
else { | ||
targetPointer[ targetKey ] = runtime.references.targets[ indexOfSource ] ; | ||
} | ||
continue ; | ||
} | ||
if ( ! targetPointer[ targetKey ] || ! targetPointer.hasOwnProperty( targetKey ) || ( typeof targetPointer[ targetKey ] !== 'object' && typeof targetPointer[ targetKey ] !== 'function' ) ) | ||
{ | ||
if ( ! targetPointer[ targetKey ] || ! targetPointer.hasOwnProperty( targetKey ) || ( typeof targetPointer[ targetKey ] !== 'object' && typeof targetPointer[ targetKey ] !== 'function' ) ) { | ||
if ( Array.isArray( sourceValue ) ) { value = [] ; } | ||
@@ -298,5 +267,4 @@ else if ( options.proto ) { value = Object.create( sourceValueProto ) ; } // jshint ignore:line | ||
else { value = {} ; } | ||
if ( options.descriptor ) | ||
{ | ||
if ( options.descriptor ) { | ||
Object.defineProperty( targetPointer , targetKey , { | ||
@@ -309,22 +277,18 @@ value: value , | ||
} | ||
else | ||
{ | ||
else { | ||
targetPointer[ targetKey ] = value ; | ||
} | ||
} | ||
else if ( options.proto && Object.getPrototypeOf( targetPointer[ targetKey ] ) !== sourceValueProto ) | ||
{ | ||
else if ( options.proto && Object.getPrototypeOf( targetPointer[ targetKey ] ) !== sourceValueProto ) { | ||
Object.setPrototypeOf( targetPointer[ targetKey ] , sourceValueProto ) ; | ||
} | ||
else if ( options.inherit && Object.getPrototypeOf( targetPointer[ targetKey ] ) !== sourceValue ) | ||
{ | ||
else if ( options.inherit && Object.getPrototypeOf( targetPointer[ targetKey ] ) !== sourceValue ) { | ||
Object.setPrototypeOf( targetPointer[ targetKey ] , sourceValue ) ; | ||
} | ||
if ( options.circular ) | ||
{ | ||
if ( options.circular ) { | ||
runtime.references.sources.push( sourceValue ) ; | ||
runtime.references.targets.push( targetPointer[ targetKey ] ) ; | ||
} | ||
// Recursively extends sub-object | ||
@@ -337,13 +301,11 @@ extendOne( | ||
} | ||
else if ( options.preserve && targetPointer[ targetKey ] !== undefined ) | ||
{ | ||
else if ( options.preserve && targetPointer[ targetKey ] !== undefined ) { | ||
// Do not overwrite, and so do not delete source's properties that were not moved | ||
continue ; | ||
} | ||
else if ( ! options.inherit ) | ||
{ | ||
else if ( ! options.inherit ) { | ||
if ( options.descriptor ) { Object.defineProperty( targetPointer , targetKey , sourceDescriptor ) ; } | ||
else { targetPointer[ targetKey ] = sourceValue ; } | ||
} | ||
// Delete owned property of the source object | ||
@@ -350,0 +312,0 @@ if ( options.move ) { delete source[ sourceKey ] ; } |
/* | ||
Tree Kit | ||
Copyright (c) 2014 - 2016 Cédric Ronvel | ||
Copyright (c) 2014 - 2018 Cédric Ronvel | ||
The MIT License (MIT) | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
@@ -14,6 +14,6 @@ of this software and associated documentation files (the "Software"), to deal | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
@@ -36,4 +36,3 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
exports.defineLazyProperty = function defineLazyProperty( object , name , func ) | ||
{ | ||
exports.defineLazyProperty = function defineLazyProperty( object , name , func ) { | ||
Object.defineProperty( object , name , { | ||
@@ -43,5 +42,5 @@ configurable: true , | ||
get: function() { | ||
var value = func() ; | ||
Object.defineProperty( object , name , { | ||
@@ -53,3 +52,3 @@ configurable: true , | ||
} ) ; | ||
return value ; | ||
@@ -56,0 +55,0 @@ } |
274
lib/mask.js
/* | ||
Tree Kit | ||
Copyright (c) 2014 - 2016 Cédric Ronvel | ||
Copyright (c) 2014 - 2018 Cédric Ronvel | ||
The MIT License (MIT) | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
@@ -14,6 +14,6 @@ of this software and associated documentation files (the "Software"), to deal | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
@@ -46,3 +46,3 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
== Mask-family class == | ||
Recursively select values in the input object if the same path in the mask object is set. | ||
@@ -58,4 +58,3 @@ */ | ||
masklib.Mask = function Mask() | ||
{ | ||
masklib.Mask = function Mask() { | ||
throw new Error( 'Cannot create a tree.Mask() directly' ) ; | ||
@@ -81,18 +80,16 @@ } ; | ||
*/ | ||
masklib.createMask = function createMask( maskArgument , options ) | ||
{ | ||
if ( maskArgument === null || typeof maskArgument !== 'object' ) | ||
{ | ||
masklib.createMask = function createMask( maskArgument , options ) { | ||
if ( maskArgument === null || typeof maskArgument !== 'object' ) { | ||
throw new TypeError( '[tree] .createMask() : Argument #1 should be an object' ) ; | ||
} | ||
if ( options !== null && typeof options === 'object' ) { options = tree.extend( null , {} , maskDefaultOptions , options ) ; } | ||
else { options = maskDefaultOptions ; } | ||
var mask = Object.create( masklib.Mask.prototype , { | ||
__options__: { value: options , writable: true } | ||
} ) ; | ||
tree.extend( null , mask , maskArgument ) ; | ||
return mask ; | ||
@@ -104,12 +101,9 @@ } ; | ||
// Apply the mask to an input tree | ||
masklib.Mask.prototype.applyTo = function applyTo( input , context , contextOverideDefault ) | ||
{ | ||
masklib.Mask.prototype.applyTo = function applyTo( input , context , contextOverideDefault ) { | ||
// Arguments checking | ||
if ( input === null || typeof input !== 'object' ) | ||
{ | ||
if ( input === null || typeof input !== 'object' ) { | ||
throw new TypeError( '[tree] .applyTo() : Argument #1 should be an object' ) ; | ||
} | ||
if ( contextOverideDefault ) | ||
{ | ||
if ( contextOverideDefault ) { | ||
context = tree.extend( null , | ||
@@ -124,4 +118,3 @@ { | ||
} | ||
else if ( context === undefined ) | ||
{ | ||
else if ( context === undefined ) { | ||
context = { | ||
@@ -133,4 +126,4 @@ mask: this , | ||
} | ||
// Init | ||
@@ -142,50 +135,41 @@ //console.log( context ) ; | ||
j , inputKey , inputValue , inputKeyList ; | ||
if ( Array.isArray( input ) ) { output = [] ; } | ||
else { output = {} ; } | ||
// Iterate through mask properties | ||
for ( i = 0 ; i < maskKeyList.length ; i ++ ) | ||
{ | ||
for ( i = 0 ; i < maskKeyList.length ; i ++ ) { | ||
key = maskKeyList[ i ] ; | ||
maskValue = context.mask[ key ] ; | ||
//console.log( '\nnext loop: ' , key , maskValue ) ; | ||
// The special key * is a wildcard, it match everything | ||
if ( key === '*' ) | ||
{ | ||
if ( key === '*' ) { | ||
//console.log( 'wildcard' ) ; | ||
inputKeyList = Object.keys( input ) ; | ||
for ( j = 0 ; j < inputKeyList.length ; j ++ ) | ||
{ | ||
for ( j = 0 ; j < inputKeyList.length ; j ++ ) { | ||
inputKey = inputKeyList[ j ] ; | ||
inputValue = input[ inputKey ] ; | ||
//console.log( '*: ' , inputKey ) ; | ||
nextPath = context.path + context.options.pathSeparator + inputKey ; | ||
// If it is an array or object, recursively check it | ||
if ( maskValue !== null && typeof maskValue === 'object' ) | ||
{ | ||
if ( input[ inputKey ] !== null && typeof input[ inputKey ] === 'object' ) | ||
{ | ||
if ( input[ inputKey ] instanceof masklib.Mask ) | ||
{ | ||
output[ inputKey ] = input[ inputKey ].applyTo( input[ inputKey ] , { path: nextPath } , true ) ; | ||
if ( maskValue !== null && typeof maskValue === 'object' ) { | ||
if ( inputValue !== null && typeof inputValue === 'object' ) { | ||
if ( inputValue instanceof masklib.Mask ) { | ||
output[ inputKey ] = inputValue.applyTo( inputValue , { path: nextPath } , true ) ; | ||
} | ||
else | ||
{ | ||
output[ inputKey ] = this.applyTo( input[ inputKey ] , tree.extend( null , {} , context , { mask: maskValue , path: nextPath } ) ) ; | ||
else { | ||
output[ inputKey ] = this.applyTo( inputValue , tree.extend( null , {} , context , { mask: maskValue , path: nextPath } ) ) ; | ||
} | ||
} | ||
else if ( typeof context.options.leaf === 'function' ) | ||
{ | ||
else if ( typeof context.options.leaf === 'function' ) { | ||
output[ inputKey ] = this.applyTo( {} , tree.extend( null , {} , context , { mask: maskValue , path: nextPath } ) ) ; | ||
} | ||
} | ||
else if ( maskValue !== null && typeof context.options.leaf === 'function' ) | ||
{ | ||
else if ( maskValue !== null && typeof context.options.leaf === 'function' ) { | ||
//console.log( 'leaf callback' ) ; | ||
@@ -195,37 +179,28 @@ result = context.options.leaf( input , inputKey , maskValue , nextPath ) ; | ||
} | ||
else | ||
{ | ||
if ( context.options.clone && ( input[ inputKey ] !== null && typeof input[ inputKey ] === 'object' ) ) | ||
{ | ||
output[ inputKey ] = tree.extend( { deep: true } , {} , input[ inputKey ] ) ; | ||
} | ||
else | ||
{ | ||
output[ inputKey ] = input[ inputKey ] ; | ||
} | ||
else if ( context.options.clone && ( inputValue !== null && typeof inputValue === 'object' ) ) { | ||
output[ inputKey ] = tree.extend( { deep: true } , {} , inputValue ) ; | ||
} | ||
else { | ||
output[ inputKey ] = inputValue ; | ||
} | ||
} | ||
continue ; | ||
} | ||
nextPath = context.path + context.options.pathSeparator + key ; | ||
// If it is an object, recursively check it | ||
//if ( maskValue instanceof masklib.Mask ) | ||
if ( maskValue !== null && typeof maskValue === 'object' ) | ||
{ | ||
if ( maskValue !== null && typeof maskValue === 'object' ) { | ||
//console.log( 'sub' ) ; | ||
if ( input.hasOwnProperty( key ) && input[ key ] !== null && typeof input[ key ] === 'object' ) | ||
{ | ||
if ( input.hasOwnProperty( key ) && input[ key ] !== null && typeof input[ key ] === 'object' ) { | ||
//console.log( 'recursive call' ) ; | ||
if ( input.key instanceof masklib.Mask ) | ||
{ | ||
if ( input.key instanceof masklib.Mask ) { | ||
output[ key ] = input.key.applyTo( input[ key ] , { path: nextPath } , true ) ; | ||
} | ||
else | ||
{ | ||
else { | ||
output[ key ] = this.applyTo( input[ key ] , tree.extend( null , {} , context , { mask: maskValue , path: nextPath } ) ) ; | ||
@@ -235,4 +210,3 @@ } | ||
// recursive call only if there are callback | ||
else if ( context.options.leaf ) | ||
{ | ||
else if ( context.options.leaf ) { | ||
//console.log( 'recursive call' ) ; | ||
@@ -243,8 +217,6 @@ output[ key ] = this.applyTo( {} , tree.extend( null , {} , context , { mask: maskValue , path: nextPath } ) ) ; | ||
// If mask exists, add the key | ||
else if ( input.hasOwnProperty( key ) ) | ||
{ | ||
else if ( input.hasOwnProperty( key ) ) { | ||
//console.log( 'property found' ) ; | ||
if ( maskValue !== undefined && typeof context.options.leaf === 'function' ) | ||
{ | ||
if ( maskValue !== undefined && typeof context.options.leaf === 'function' ) { | ||
//console.log( 'leaf callback' ) ; | ||
@@ -254,16 +226,10 @@ result = context.options.leaf( input , key , maskValue , nextPath ) ; | ||
} | ||
else | ||
{ | ||
if ( context.options.clone && ( input[ key ] !== null && typeof input[ key ] === 'object' ) ) | ||
{ | ||
output[ key ] = tree.extend( { deep: true } , {} , input[ key ] ) ; | ||
} | ||
else | ||
{ | ||
output[ key ] = input[ key ] ; | ||
} | ||
else if ( context.options.clone && ( input[ key ] !== null && typeof input[ key ] === 'object' ) ) { | ||
output[ key ] = tree.extend( { deep: true } , {} , input[ key ] ) ; | ||
} | ||
else { | ||
output[ key ] = input[ key ] ; | ||
} | ||
} | ||
else if ( maskValue !== undefined && typeof context.options.leaf === 'function' ) | ||
{ | ||
else if ( maskValue !== undefined && typeof context.options.leaf === 'function' ) { | ||
//console.log( 'leaf callback' ) ; | ||
@@ -274,3 +240,3 @@ result = context.options.leaf( input , key , maskValue , nextPath ) ; | ||
} | ||
return output ; | ||
@@ -283,4 +249,3 @@ } ; | ||
masklib.InverseMask = function InverseMask() | ||
{ | ||
masklib.InverseMask = function InverseMask() { | ||
throw new Error( 'Cannot create a tree.InverseMask() directly' ) ; | ||
@@ -298,18 +263,16 @@ } ; | ||
*/ | ||
masklib.createInverseMask = function createInverseMask( maskArgument , options ) | ||
{ | ||
if ( maskArgument === null || typeof maskArgument !== 'object' ) | ||
{ | ||
masklib.createInverseMask = function createInverseMask( maskArgument , options ) { | ||
if ( maskArgument === null || typeof maskArgument !== 'object' ) { | ||
throw new TypeError( '[tree] .createInverseMask() : Argument #1 should be an object' ) ; | ||
} | ||
if ( options !== null && typeof options === 'object' ) { options = tree.extend( null , {} , maskDefaultOptions , options ) ; } | ||
else { options = maskDefaultOptions ; } | ||
var mask = Object.create( masklib.InverseMask.prototype , { | ||
__options__: { value: options , writable: true } | ||
} ) ; | ||
tree.extend( null , mask , maskArgument ) ; | ||
return mask ; | ||
@@ -321,12 +284,9 @@ } ; | ||
// Apply the mask to an input tree | ||
masklib.InverseMask.prototype.applyTo = function applyTo( input , context , contextOverideDefault ) | ||
{ | ||
masklib.InverseMask.prototype.applyTo = function applyTo( input , context , contextOverideDefault ) { | ||
// Arguments checking | ||
if ( input === null || typeof input !== 'object' ) | ||
{ | ||
if ( input === null || typeof input !== 'object' ) { | ||
throw new TypeError( '[tree] .applyTo() : Argument #1 should be an object' ) ; | ||
} | ||
if ( contextOverideDefault ) | ||
{ | ||
if ( contextOverideDefault ) { | ||
context = tree.extend( null , | ||
@@ -341,4 +301,3 @@ { | ||
} | ||
else if ( context === undefined ) | ||
{ | ||
else if ( context === undefined ) { | ||
context = { | ||
@@ -350,4 +309,4 @@ mask: this , | ||
} | ||
// Init | ||
@@ -359,73 +318,61 @@ //console.log( context ) ; | ||
j , inputKey , inputValue , inputKeyList ; | ||
if ( Array.isArray( input ) ) { output = tree.extend( { deep: true } , [] , input ) ; } | ||
else { output = tree.extend( { deep: true } , {} , input ) ; } | ||
//console.log( output ) ; | ||
// Iterate through mask properties | ||
for ( i = 0 ; i < maskKeyList.length ; i ++ ) | ||
{ | ||
for ( i = 0 ; i < maskKeyList.length ; i ++ ) { | ||
key = maskKeyList[ i ] ; | ||
maskValue = context.mask[ key ] ; | ||
//console.log( '\nnext loop: ' , key , maskValue ) ; | ||
// The special key * is a wildcard, it match everything | ||
if ( key === '*' ) | ||
{ | ||
if ( key === '*' ) { | ||
//console.log( 'wildcard' ) ; | ||
inputKeyList = Object.keys( input ) ; | ||
for ( j = 0 ; j < inputKeyList.length ; j ++ ) | ||
{ | ||
for ( j = 0 ; j < inputKeyList.length ; j ++ ) { | ||
inputKey = inputKeyList[ j ] ; | ||
inputValue = input[ inputKey ] ; | ||
//console.log( '*: ' , inputKey ) ; | ||
nextPath = context.path + context.options.pathSeparator + inputKey ; | ||
// If it is an array or object, recursively check it | ||
if ( maskValue !== null && typeof maskValue === 'object' ) | ||
{ | ||
if ( input[ inputKey ] !== null && typeof input[ inputKey ] === 'object' ) | ||
{ | ||
if ( input[ inputKey ] instanceof masklib.Mask ) | ||
{ | ||
output[ inputKey ] = input[ inputKey ].applyTo( input[ inputKey ] , { path: nextPath } , true ) ; | ||
if ( maskValue !== null && typeof maskValue === 'object' ) { | ||
if ( inputValue !== null && typeof inputValue === 'object' ) { | ||
if ( inputValue instanceof masklib.Mask ) { | ||
output[ inputKey ] = inputValue.applyTo( inputValue , { path: nextPath } , true ) ; | ||
} | ||
else | ||
{ | ||
output[ inputKey ] = this.applyTo( input[ inputKey ] , tree.extend( null , {} , context , { mask: maskValue , path: nextPath } ) ) ; | ||
else { | ||
output[ inputKey ] = this.applyTo( inputValue , tree.extend( null , {} , context , { mask: maskValue , path: nextPath } ) ) ; | ||
} | ||
} | ||
} | ||
else | ||
{ | ||
else { | ||
delete output[ inputKey ] ; | ||
} | ||
} | ||
continue ; | ||
} | ||
nextPath = context.path + context.options.pathSeparator + key ; | ||
// If it is an object, recursively check it | ||
//if ( maskValue instanceof masklib.Mask ) | ||
if ( maskValue !== null && typeof maskValue === 'object' ) | ||
{ | ||
if ( maskValue !== null && typeof maskValue === 'object' ) { | ||
//console.log( 'sub' ) ; | ||
if ( input.hasOwnProperty( key ) && input[ key ] !== null && typeof input[ key ] === 'object' ) | ||
{ | ||
if ( input.hasOwnProperty( key ) && input[ key ] !== null && typeof input[ key ] === 'object' ) { | ||
//console.log( 'recursive call' ) ; | ||
if ( input.key instanceof masklib.Mask ) | ||
{ | ||
if ( input.key instanceof masklib.Mask ) { | ||
output[ key ] = input.key.applyTo( input[ key ] , { path: nextPath } , true ) ; | ||
} | ||
else | ||
{ | ||
else { | ||
output[ key ] = this.applyTo( input[ key ] , tree.extend( null , {} , context , { mask: maskValue , path: nextPath } ) ) ; | ||
@@ -436,9 +383,8 @@ } | ||
// If mask exists, remove the key | ||
else if ( input.hasOwnProperty( key ) ) | ||
{ | ||
else if ( input.hasOwnProperty( key ) ) { | ||
delete output[ key ] ; | ||
} | ||
} | ||
return output ; | ||
} ; |
135
lib/path.js
/* | ||
Tree Kit | ||
Copyright (c) 2014 - 2016 Cédric Ronvel | ||
Copyright (c) 2014 - 2018 Cédric Ronvel | ||
The MIT License (MIT) | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
@@ -14,6 +14,6 @@ of this software and associated documentation files (the "Software"), to deal | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
@@ -37,32 +37,26 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
treePath.op = function op( type , object , path , value ) | ||
{ | ||
treePath.op = function op( type , object , path , value ) { | ||
var i , parts , last , pointer , key , isArray = false , pathArrayMode = false , isGenericSet , canBeEmpty = true ; | ||
if ( ! object || ( typeof object !== 'object' && typeof object !== 'function' ) ) | ||
{ | ||
if ( ! object || ( typeof object !== 'object' && typeof object !== 'function' ) ) { | ||
return ; | ||
} | ||
if ( typeof path === 'string' ) | ||
{ | ||
if ( typeof path === 'string' ) { | ||
// Split the path into parts | ||
if ( path ) { parts = path.match( /([.#\[\]]|[^.#\[\]]+)/g ) ; } | ||
if ( path ) { parts = path.match( /([.#[\]]|[^.#[\]]+)/g ) ; } | ||
else { parts = [ '' ] ; } | ||
if ( parts[ 0 ] === '.' ) { parts.unshift( '' ) ; } | ||
if ( parts[ parts.length - 1 ] === '.' ) { parts.push( '' ) ; } | ||
} | ||
else if ( Array.isArray( path ) ) | ||
{ | ||
else if ( Array.isArray( path ) ) { | ||
parts = path ; | ||
pathArrayMode = true ; | ||
} | ||
else | ||
{ | ||
else { | ||
throw new TypeError( '[tree.path] .' + type + '(): the path argument should be a string or an array' ) ; | ||
} | ||
switch ( type ) | ||
{ | ||
switch ( type ) { | ||
case 'get' : | ||
@@ -86,63 +80,53 @@ case 'delete' : | ||
} | ||
//console.log( parts ) ; | ||
// The pointer start at the object's root | ||
pointer = object ; | ||
last = parts.length - 1 ; | ||
for ( i = 0 ; i <= last ; i ++ ) | ||
{ | ||
if ( pathArrayMode ) | ||
{ | ||
if ( key === undefined ) | ||
{ | ||
for ( i = 0 ; i <= last ; i ++ ) { | ||
if ( pathArrayMode ) { | ||
if ( key === undefined ) { | ||
key = parts[ i ] ; | ||
continue ; | ||
} | ||
if ( ! pointer[ key ] || ( typeof pointer[ key ] !== 'object' && typeof pointer[ key ] !== 'function' ) ) | ||
{ | ||
if ( ! pointer[ key ] || ( typeof pointer[ key ] !== 'object' && typeof pointer[ key ] !== 'function' ) ) { | ||
if ( ! isGenericSet ) { return undefined ; } | ||
pointer[ key ] = {} ; | ||
} | ||
pointer = pointer[ key ] ; | ||
key = parts[ i ] ; | ||
continue ; | ||
} | ||
else if ( parts[ i ] === '.' ) | ||
{ | ||
else if ( parts[ i ] === '.' ) { | ||
isArray = false ; | ||
if ( key === undefined ) | ||
{ | ||
if ( ! canBeEmpty ) | ||
{ | ||
if ( key === undefined ) { | ||
if ( ! canBeEmpty ) { | ||
canBeEmpty = true ; | ||
continue ; | ||
} | ||
key = '' ; | ||
} | ||
if ( ! pointer[ key ] || ( typeof pointer[ key ] !== 'object' && typeof pointer[ key ] !== 'function' ) ) | ||
{ | ||
if ( ! pointer[ key ] || ( typeof pointer[ key ] !== 'object' && typeof pointer[ key ] !== 'function' ) ) { | ||
if ( ! isGenericSet ) { return undefined ; } | ||
pointer[ key ] = {} ; | ||
} | ||
pointer = pointer[ key ] ; | ||
canBeEmpty = true ; | ||
continue ; | ||
} | ||
else if ( parts[ i ] === '#' || parts[ i ] === '[' ) | ||
{ | ||
else if ( parts[ i ] === '#' || parts[ i ] === '[' ) { | ||
isArray = true ; | ||
canBeEmpty = false ; | ||
if ( key === undefined ) | ||
{ | ||
if ( key === undefined ) { | ||
// The root element cannot be altered, we are in trouble if an array is expected but we have only a regular object. | ||
@@ -152,15 +136,13 @@ if ( ! Array.isArray( pointer ) ) { return undefined ; } | ||
} | ||
if ( ! pointer[ key ] || ! Array.isArray( pointer[ key ] ) ) | ||
{ | ||
if ( ! pointer[ key ] || ! Array.isArray( pointer[ key ] ) ) { | ||
if ( ! isGenericSet ) { return undefined ; } | ||
pointer[ key ] = [] ; | ||
} | ||
pointer = pointer[ key ] ; | ||
continue ; | ||
} | ||
else if ( parts[ i ] === ']' ) | ||
{ | ||
else if ( parts[ i ] === ']' ) { | ||
// Closing bracket: do nothing | ||
@@ -170,13 +152,12 @@ canBeEmpty = false ; | ||
} | ||
canBeEmpty = false ; | ||
if ( ! isArray ) { key = parts[ i ] ; continue ; } | ||
switch ( parts[ i ] ) | ||
{ | ||
switch ( parts[ i ] ) { | ||
case 'length' : | ||
key = parts[ i ] ; | ||
break ; | ||
// Pseudo-key | ||
@@ -199,5 +180,5 @@ case 'first' : | ||
break ; | ||
// default = number | ||
default: | ||
default : | ||
// Convert the string key to a numerical index | ||
@@ -207,5 +188,4 @@ key = parseInt( parts[ i ] , 10 ) ; | ||
} | ||
switch ( type ) | ||
{ | ||
switch ( type ) { | ||
case 'get' : | ||
@@ -244,4 +224,3 @@ return pointer[ key ] ; | ||
if ( ! pointer[ key ] ) { pointer[ key ] = value ; } | ||
else if ( Array.isArray( pointer[ key ] ) && Array.isArray( value ) ) | ||
{ | ||
else if ( Array.isArray( pointer[ key ] ) && Array.isArray( value ) ) { | ||
pointer[ key ] = pointer[ key ].concat( value ) ; | ||
@@ -253,4 +232,3 @@ } | ||
if ( ! pointer[ key ] ) { pointer[ key ] = value ; } | ||
else if ( Array.isArray( pointer[ key ] ) && Array.isArray( value ) ) | ||
{ | ||
else if ( Array.isArray( pointer[ key ] ) && Array.isArray( value ) ) { | ||
pointer[ key ] = value.concat( pointer[ key ] ) ; | ||
@@ -303,4 +281,3 @@ } | ||
// Upgrade an object so it can support get, set and delete at its root | ||
treePath.upgrade = function upgrade( object ) | ||
{ | ||
treePath.upgrade = function upgrade( object ) { | ||
Object.defineProperties( object , { | ||
@@ -307,0 +284,0 @@ get: { value: treePath.op.bind( undefined , 'get' , object ) } , |
/* | ||
Tree Kit | ||
Copyright (c) 2014 - 2016 Cédric Ronvel | ||
Copyright (c) 2014 - 2018 Cédric Ronvel | ||
The MIT License (MIT) | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
@@ -14,6 +14,6 @@ of this software and associated documentation files (the "Software"), to deal | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
@@ -43,9 +43,9 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
tree.extend( null , tree , | ||
// Tier 1 | ||
require( './lazy.js' ) , | ||
// Tier 2 | ||
{ clone: require( './clone.js' ) } , | ||
// Tier 3 | ||
@@ -52,0 +52,0 @@ { path: require( './path.js' ) } , |
{ | ||
"name": "tree-kit", | ||
"version": "0.5.26", | ||
"version": "0.5.27", | ||
"description": "Tree utilities which provides a full-featured extend and object-cloning facility, and various tools to deal with nested object structures.", | ||
@@ -12,10 +12,7 @@ "main": "lib/tree.js", | ||
"devDependencies": { | ||
"browserify": "^13.0.1", | ||
"expect.js": "^0.3.1", | ||
"jshint": "^2.5.6", | ||
"mocha": "^2.2.5", | ||
"uglify-js": "^2.7.0" | ||
"browserify": "^16.2.2", | ||
"uglify-js-es6": "^2.8.9" | ||
}, | ||
"scripts": { | ||
"test": "mocha -R dot" | ||
"test": "tea-time -R dot" | ||
}, | ||
@@ -41,2 +38,9 @@ "repository": { | ||
}, | ||
"config": { | ||
"tea-time": { | ||
"coverDir": [ | ||
"lib" | ||
] | ||
} | ||
}, | ||
"copyright": { | ||
@@ -46,3 +50,3 @@ "title": "Tree Kit", | ||
2014, | ||
2016 | ||
2018 | ||
], | ||
@@ -49,0 +53,0 @@ "owner": "Cédric Ronvel" |
2082
README.md
# Tree Kit | ||
@@ -269,2082 +268,1 @@ | ||
Full BDD spec generated by Mocha: | ||
# TOC | ||
- [clone()](#clone) | ||
- [Diff](#diff) | ||
- [extend()](#extend) | ||
- [defineLazyProperty()](#definelazyproperty) | ||
- [Masks](#masks) | ||
- [Inverse masks](#inverse-masks) | ||
- [Tree's path on objects](#trees-path-on-objects) | ||
- [Tree's path on arrays](#trees-path-on-arrays) | ||
- [Tree's path on mixed object and arrays](#trees-path-on-mixed-object-and-arrays) | ||
- [Inheritance, using Object.create( tree.path.prototype )](#inheritance-using-objectcreate-treepathprototype-) | ||
- [Tree's array path on objects](#trees-array-path-on-objects) | ||
<a name=""></a> | ||
<a name="clone"></a> | ||
# clone() | ||
basic incomplete test. | ||
```js | ||
var proto = { | ||
proto1: 'proto1' , | ||
proto2: 'proto2' , | ||
hello: function() { console.log( "Hello!" ) ; } | ||
} ; | ||
var o = Object.create( proto ) ; | ||
o.own1 = 'own1' ; | ||
o.own2 = 'own2' ; | ||
o.nested = { a: 1 , b: 2 } ; | ||
var getter = function() { return 5 ; } ; | ||
var setter = function( value ) {} ; | ||
Object.defineProperties( o , { | ||
nonEnum1: { value: 'nonEnum1' } , | ||
nonEnum2: { value: 'nonEnum2' , writable: true } , | ||
nonEnum3: { value: 'nonEnum3' , configurable: true } , | ||
nonEnumNested: { value: { c: 3 , d: 4 } } , | ||
getter: { get: getter } , | ||
getterAndSetter: { get: getter , set: setter } | ||
} ) ; | ||
var i , r ; | ||
// Basic tests with and without circular checks | ||
for ( i = 0 ; i <= 1 ; i ++ ) | ||
{ | ||
if ( i === 0 ) { r = tree.clone( o ) ;} | ||
else { r = tree.clone( o , true ) ; } | ||
expect( Object.getOwnPropertyNames( r ) ).to.eql( [ 'own1' , 'own2' , 'nested' , 'nonEnum1' , 'nonEnum2' , 'nonEnum3' , 'nonEnumNested' , 'getter' , 'getterAndSetter' ] ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'own1' ) ).to.eql( { value: 'own1' , enumerable: true , writable: true , configurable: true } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'own2' ) ).to.eql( { value: 'own2' , enumerable: true , writable: true , configurable: true } ) ; | ||
expect( r.nested ).not.to.be( o.nested ) ; | ||
expect( r.nested ).to.eql( o.nested ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nested' ) ).to.eql( { value: o.nested , enumerable: true , writable: true , configurable: true } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnum1' ) ).to.eql( { value: 'nonEnum1' , enumerable: false , writable: false , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnum2' ) ).to.eql( { value: 'nonEnum2' , enumerable: false , writable: true , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnum3' ) ).to.eql( { value: 'nonEnum3' , enumerable: false , writable: false , configurable: true } ) ; | ||
expect( r.nonEnumNested ).not.to.be( o.nonEnumNested ) ; | ||
expect( r.nonEnumNested ).to.eql( o.nonEnumNested ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnumNested' ) ).to.eql( { value: o.nonEnumNested , enumerable: false , writable: false , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'getter' ) ).to.eql( { get: getter , set: undefined , enumerable: false , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'getterAndSetter' ) ).to.eql( { get: getter , set: setter , enumerable: false , configurable: false } ) ; | ||
expect( r.__proto__ ).to.equal( proto ) ; // jshint ignore:line | ||
expect( r.proto1 ).to.be( 'proto1' ) ; | ||
expect( r.proto2 ).to.be( 'proto2' ) ; | ||
expect( typeof r.hello ).to.equal( 'function' ) ; | ||
} | ||
``` | ||
circular references test. | ||
```js | ||
var c , o = { | ||
a: 'a', | ||
sub: { | ||
b: 'b' | ||
}, | ||
sub2: { | ||
c: 'c' | ||
} | ||
} ; | ||
o.loop = o ; | ||
o.sub.loop = o ; | ||
o.subcopy = o.sub ; | ||
o.sub.link = o.sub2 ; | ||
o.sub2.link = o.sub ; | ||
c = tree.clone( o , true ) ; | ||
expect( c.loop ).to.be( c ) ; | ||
expect( c.sub ).to.be( c.subcopy ) ; | ||
expect( c.sub.loop ).to.be( c ) ; | ||
expect( c.subcopy.loop ).to.be( c ) ; | ||
expect( c.sub.link ).to.be( c.sub2 ) ; | ||
expect( c.sub2.link ).to.be( c.sub ) ; | ||
``` | ||
cloning an array. | ||
```js | ||
var a , c ; | ||
a = [ 'one' , 'two' , 'three' ] ; | ||
c = tree.clone( a ) ; | ||
expect( c ).to.eql( a ) ; | ||
expect( Array.isArray( c ) ).to.be.ok() ; | ||
a = [ 'one' , [ 'two' , 'three' ] ] ; | ||
c = tree.clone( a ) ; | ||
expect( c ).to.eql( a ) ; | ||
expect( Array.isArray( c ) ).to.be.ok() ; | ||
expect( Array.isArray( c[ 1 ] ) ).to.be.ok() ; | ||
``` | ||
<a name="diff"></a> | ||
# Diff | ||
should return an array of differences for two objects without nested object. | ||
```js | ||
var a = { | ||
a: 'a', | ||
b: 2, | ||
c: 'three' | ||
} ; | ||
var b = { | ||
b: 2, | ||
c: 3, | ||
d: 'dee' | ||
} ; | ||
var diff = tree.diff( a , b ) ; | ||
//console.log( JSON.stringify( diff , null , ' ' ) ) ; | ||
expect( diff ).not.to.be( null ) ; | ||
expect( diff ).to.only.have.keys( '.a', '.c', '.d' ) ; | ||
``` | ||
should return an array of differences for two objects with nested objects. | ||
```js | ||
var a = { | ||
a: 'a', | ||
b: 2, | ||
c: 'three', | ||
sub: { | ||
e: 5, | ||
f: 'six', | ||
subsub: { | ||
g: 'gee', | ||
h: 'h' | ||
} | ||
}, | ||
suba: { | ||
j: 'djay' | ||
} | ||
} ; | ||
var b = { | ||
b: 2, | ||
c: 3, | ||
d: 'dee', | ||
sub: { | ||
e: 5, | ||
f: 6, | ||
subsub: { | ||
g: 'gee', | ||
i: 'I' | ||
} | ||
}, | ||
subb: { | ||
k: 'k' | ||
} | ||
} ; | ||
var diff = tree.diff( a , b ) ; | ||
//console.log( JSON.stringify( diff , null , ' ' ) ) ; | ||
expect( diff ).not.to.be( null ) ; | ||
expect( diff ).to.only.have.keys( '.a', '.c', '.d', '.sub.f', '.sub.subsub.h', '.sub.subsub.i', '.suba', '.subb' ) ; | ||
``` | ||
<a name="extend"></a> | ||
# extend() | ||
should extend correctly an empty Object with a flat Object without depth (with or without the 'deep' option). | ||
```js | ||
var copy ; | ||
var expected = { | ||
d : 4 , | ||
e : undefined , | ||
f : 3.14 , | ||
g : 6 , | ||
h : [] , | ||
i : 'iii' | ||
} ; | ||
copy = extend( { deep: true } , {} , input.subtree.subtree ) ; | ||
expect( extend( null , copy , input.subtree.subtree2 ) ).to.eql( expected ) ; | ||
copy = extend( { deep: true } , {} , input.subtree.subtree ) ; | ||
expect( extend( { deep: true } , copy , input.subtree.subtree2 ) ).to.eql( expected ) ; | ||
``` | ||
should extend an empty Object with a deep Object performing a SHALLOW copy, the result should be equal to the deep Object, nested object MUST be equal AND identical. | ||
```js | ||
var copy = extend( null , {} , input.subtree ) ; | ||
expect( copy ).to.eql( input.subtree ) ; | ||
expect( copy ).not.to.equal( input.subtree ) ; | ||
expect( copy.subtree2 ).to.equal( input.subtree.subtree2 ) ; | ||
``` | ||
with the 'deep' option should extend an empty Object with a deep Object performing a DEEP copy, the result should be equal to the deep Object, nested object MUST be equal BUT NOT identical. | ||
```js | ||
var copy = extend( { deep: true } , {} , input.subtree ) ; | ||
expect( copy ).to.eql( input.subtree ) ; | ||
expect( copy ).not.to.equal( input.subtree ) ; | ||
expect( copy.subtree2 ).not.to.equal( input.subtree.subtree2 ) ; | ||
``` | ||
with the 'deep' option, sources functions are still simply copied/referenced into target. | ||
```js | ||
var copy = extend( { deep: true } , {} , input.subtreeWithFunction ) ; | ||
//console.log( copy ) ; | ||
expect( copy ).to.eql( input.subtreeWithFunction ) ; | ||
expect( copy ).not.to.equal( input.subtreeWithFunction ) ; | ||
expect( copy.Func.prototype ).to.equal( input.subtreeWithFunction.Func.prototype ) ; | ||
``` | ||
with the 'deep' & 'deepFunc' options, sources functions are treated like regular objects, creating an object rather than a function in the target location, and performing a deep copy of them. | ||
```js | ||
var copy = extend( { deep: true, deepFunc: true } , {} , input.subtreeWithFunction ) ; | ||
expect( copy ).not.to.eql( input.subtreeWithFunction ) ; | ||
expect( copy ).to.eql( { z: 'Zee' , Func: { prop: 'property' } } ) ; | ||
``` | ||
should extend (by default) properties of the prototype chain. | ||
```js | ||
var proto = { | ||
proto1: 'proto1' , | ||
proto2: 'proto2' , | ||
} ; | ||
var o = Object.create( proto ) ; | ||
o.own1 = 'own1' ; | ||
o.own2 = 'own2' ; | ||
expect( extend( null , {} , o ) ).to.eql( { | ||
proto1: 'proto1' , | ||
proto2: 'proto2' , | ||
own1: 'own1' , | ||
own2: 'own2' | ||
} ) ; | ||
expect( extend( { deep: true } , {} , o ) ).to.eql( { | ||
proto1: 'proto1' , | ||
proto2: 'proto2' , | ||
own1: 'own1' , | ||
own2: 'own2' | ||
} ) ; | ||
``` | ||
with the 'own' option, it should ONLY extend OWNED properties, non-enumerable properties and properties of the prototype chain are SKIPPED. | ||
```js | ||
var proto = { | ||
proto1: 'proto1' , | ||
proto2: 'proto2' , | ||
} ; | ||
var o = Object.create( proto ) ; | ||
o.own1 = 'own1' ; | ||
o.own2 = 'own2' ; | ||
Object.defineProperties( o , { | ||
nonEnum1: { value: 'nonEnum1' } , | ||
nonEnum2: { value: 'nonEnum2' } | ||
} ) ; | ||
expect( extend( { own: true } , {} , o ) ).to.eql( { | ||
own1: 'own1' , | ||
own2: 'own2' | ||
} ) ; | ||
expect( extend( { deep: true, own: true } , {} , o ) ).to.eql( { | ||
own1: 'own1' , | ||
own2: 'own2' | ||
} ) ; | ||
``` | ||
with the 'own' & 'nonEnum' option, it should ONLY extend OWNED properties, enumerable or not, but properties of the prototype chain are SKIPPED. | ||
```js | ||
var proto = { | ||
proto1: 'proto1' , | ||
proto2: 'proto2' , | ||
} ; | ||
var o = Object.create( proto ) ; | ||
o.own1 = 'own1' ; | ||
o.own2 = 'own2' ; | ||
Object.defineProperties( o , { | ||
nonEnum1: { value: 'nonEnum1' } , | ||
nonEnum2: { value: 'nonEnum2' } | ||
} ) ; | ||
expect( extend( { own: true , nonEnum: true } , {} , o ) ).to.eql( { | ||
own1: 'own1' , | ||
own2: 'own2' , | ||
nonEnum1: 'nonEnum1' , | ||
nonEnum2: 'nonEnum2' | ||
} ) ; | ||
expect( extend( { deep: true, own: true , nonEnum: true } , {} , o ) ).to.eql( { | ||
own1: 'own1' , | ||
own2: 'own2' , | ||
nonEnum1: 'nonEnum1' , | ||
nonEnum2: 'nonEnum2' | ||
} ) ; | ||
``` | ||
with the 'descriptor' option, it should preserve descriptor as well. | ||
```js | ||
var r ; | ||
var proto = { | ||
proto1: 'proto1' , | ||
proto2: 'proto2' , | ||
} ; | ||
var o = Object.create( proto ) ; | ||
o.own1 = 'own1' ; | ||
o.own2 = 'own2' ; | ||
o.nested = { a: 1 , b: 2 } ; | ||
var getter = function() { return 5 ; } ; | ||
var setter = function( value ) {} ; | ||
Object.defineProperties( o , { | ||
nonEnum1: { value: 'nonEnum1' } , | ||
nonEnum2: { value: 'nonEnum2' , writable: true } , | ||
nonEnum3: { value: 'nonEnum3' , configurable: true } , | ||
nonEnumNested: { value: { c: 3 , d: 4 } } , | ||
getter: { get: getter } , | ||
getterAndSetter: { get: getter , set: setter } | ||
} ) ; | ||
r = extend( { own: true , nonEnum: true , descriptor: true } , {} , o ) ; | ||
expect( Object.getOwnPropertyNames( r ) ).to.eql( [ 'own1' , 'own2' , 'nested' , 'nonEnum1' , 'nonEnum2' , 'nonEnum3' , 'nonEnumNested' , 'getter' , 'getterAndSetter' ] ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'own1' ) ).to.eql( { value: 'own1' , enumerable: true , writable: true , configurable: true } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'own2' ) ).to.eql( { value: 'own2' , enumerable: true , writable: true , configurable: true } ) ; | ||
expect( r.nested ).to.be( o.nested ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nested' ) ).to.eql( { value: o.nested , enumerable: true , writable: true , configurable: true } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnum1' ) ).to.eql( { value: 'nonEnum1' , enumerable: false , writable: false , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnum2' ) ).to.eql( { value: 'nonEnum2' , enumerable: false , writable: true , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnum3' ) ).to.eql( { value: 'nonEnum3' , enumerable: false , writable: false , configurable: true } ) ; | ||
expect( r.nonEnumNested ).to.be( o.nonEnumNested ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnumNested' ) ).to.eql( { value: o.nonEnumNested , enumerable: false , writable: false , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'getter' ) ).to.eql( { get: getter , set: undefined , enumerable: false , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'getterAndSetter' ) ).to.eql( { get: getter , set: setter , enumerable: false , configurable: false } ) ; | ||
r = extend( { deep: true , own: true , nonEnum: true , descriptor: true } , {} , o ) ; | ||
expect( Object.getOwnPropertyNames( r ) ).to.eql( [ 'own1' , 'own2' , 'nested' , 'nonEnum1' , 'nonEnum2' , 'nonEnum3' , 'nonEnumNested' , 'getter' , 'getterAndSetter' ] ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'own1' ) ).to.eql( { value: 'own1' , enumerable: true , writable: true , configurable: true } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'own2' ) ).to.eql( { value: 'own2' , enumerable: true , writable: true , configurable: true } ) ; | ||
expect( r.nested ).not.to.be( o.nested ) ; | ||
expect( r.nested ).to.eql( o.nested ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nested' ) ).to.eql( { value: o.nested , enumerable: true , writable: true , configurable: true } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnum1' ) ).to.eql( { value: 'nonEnum1' , enumerable: false , writable: false , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnum2' ) ).to.eql( { value: 'nonEnum2' , enumerable: false , writable: true , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnum3' ) ).to.eql( { value: 'nonEnum3' , enumerable: false , writable: false , configurable: true } ) ; | ||
expect( r.nonEnumNested ).not.to.be( o.nonEnumNested ) ; | ||
expect( r.nonEnumNested ).to.eql( o.nonEnumNested ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnumNested' ) ).to.eql( { value: o.nonEnumNested , enumerable: false , writable: false , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'getter' ) ).to.eql( { get: getter , set: undefined , enumerable: false , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'getterAndSetter' ) ).to.eql( { get: getter , set: setter , enumerable: false , configurable: false } ) ; | ||
``` | ||
with the 'deep' option should extend a deep Object into another deep Object correctly. | ||
```js | ||
var copy ; | ||
copy = extend( { deep: true } , {} , input.subtree ) ; | ||
expect( extend( null , copy , input.anotherSubtree ) ).to.eql( { | ||
a : 'A' , | ||
b : 2 , | ||
subtree: { | ||
l : '1one' , | ||
m : false , | ||
n : 'nay' | ||
} , | ||
c : 'plusplus' , | ||
subtree2: { | ||
p : true , | ||
q : [4,5,6] , | ||
r : '2' | ||
} , | ||
j : 'Djay' , | ||
k : 'ok' , | ||
o : 'mg' | ||
} ) ; | ||
copy = extend( { deep: true } , {} , input.subtree ) ; | ||
expect( extend( { deep: true } , copy , input.anotherSubtree ) ).to.eql( { | ||
a : 'A' , | ||
b : 2 , | ||
subtree: { | ||
d : 4 , | ||
e : undefined , | ||
f : 3.14 , | ||
l : '1one' , | ||
m : false , | ||
n : 'nay' | ||
} , | ||
c : 'plusplus' , | ||
subtree2: { | ||
g : 6 , | ||
h : [] , | ||
i : 'iii', | ||
p : true , | ||
q : [4,5,6] , | ||
r : '2' | ||
} , | ||
j : 'Djay' , | ||
k : 'ok' , | ||
o : 'mg' | ||
} ) ; | ||
``` | ||
with the 'proto' option and a null (or falsy) target, it should create and return a new Object with the prototype of the source Object. | ||
```js | ||
var e , o , proto ; | ||
proto = { | ||
proto1: 'proto1' , | ||
proto2: 'proto2' , | ||
hello: function() { console.log( "Hello!" ) ; } | ||
} ; | ||
o = Object.create( proto ) ; | ||
o.own1 = 'own1' ; | ||
o.own2 = 'own2' ; | ||
e = extend( { proto: true } , null , o ) ; | ||
expect( e ).not.to.be( o ) ; | ||
expect( e.__proto__ ).to.equal( proto ) ; // jshint ignore:line | ||
expect( e ).to.eql( { own1: 'own1' , own2: 'own2' } ) ; | ||
expect( e.proto1 ).to.be( 'proto1' ) ; | ||
expect( e.proto2 ).to.be( 'proto2' ) ; | ||
expect( typeof e.hello ).to.equal( 'function' ) ; | ||
``` | ||
with the 'proto' option should change the prototype of each target properties for the prototype of the related source properties, if 'deep' is enabled it does so recursively. | ||
```js | ||
var e , o , proto1 , proto2 ; | ||
proto1 = { | ||
proto1: 'proto1' , | ||
hello: function() { console.log( "Hello!" ) ; } | ||
} ; | ||
proto2 = { | ||
proto2: 'proto2' , | ||
world: function() { console.log( "World!" ) ; } | ||
} ; | ||
o = { | ||
own1: 'own1' , | ||
own2: 'own2' , | ||
embed1: Object.create( proto1 , { a: { value: 'a' , enumerable: true } } ) , | ||
embed2: Object.create( proto2 , { b: { value: 'b' , enumerable: true } } ) | ||
} ; | ||
e = extend( { proto: true } , {} , o ) ; | ||
expect( e ).not.to.be( o ) ; | ||
expect( e ).to.eql( { | ||
own1: 'own1' , | ||
own2: 'own2' , | ||
embed1: { a: 'a' } , | ||
embed2: { b: 'b' } | ||
} ) ; | ||
expect( e.embed1 ).to.be( o.embed1 ) ; | ||
expect( e.embed2 ).to.be( o.embed2 ) ; | ||
expect( e.embed1.proto1 ).to.be( 'proto1' ) ; | ||
expect( e.embed2.proto2 ).to.be( 'proto2' ) ; | ||
expect( typeof e.embed1.hello ).to.equal( 'function' ) ; | ||
expect( typeof e.embed2.world ).to.equal( 'function' ) ; | ||
e = extend( { proto: true, deep: true } , {} , o ) ; | ||
expect( e ).not.to.be( o ) ; | ||
expect( e ).to.eql( { | ||
own1: 'own1' , | ||
own2: 'own2' , | ||
embed1: { a: 'a' } , | ||
embed2: { b: 'b' } | ||
} ) ; | ||
expect( e.embed1 ).not.to.be( o.embed1 ) ; | ||
expect( e.embed2 ).not.to.be( o.embed2 ) ; | ||
expect( e.embed1.proto1 ).to.be( 'proto1' ) ; | ||
expect( e.embed2.proto2 ).to.be( 'proto2' ) ; | ||
expect( typeof e.embed1.hello ).to.equal( 'function' ) ; | ||
expect( typeof e.embed2.world ).to.equal( 'function' ) ; | ||
``` | ||
with 'nofunc' option should skip function. | ||
```js | ||
var e , o , proto ; | ||
proto = { | ||
proto1: 'proto1' , | ||
proto2: 'proto2' , | ||
hello: function() { console.log( "Hello..." ) ; } | ||
} ; | ||
o = Object.create( proto ) ; | ||
o.own1 = 'own1' ; | ||
o.world = function() { console.log( "world!!!" ) ; } ; | ||
o.own2 = 'own2' ; | ||
// default behaviour | ||
e = extend( { nofunc: true } , null , o ) ; | ||
expect( e ).not.to.be( o ) ; | ||
expect( e ).to.eql( { own1: 'own1' , own2: 'own2' , proto1: 'proto1' , proto2: 'proto2' } ) ; | ||
// with 'own' | ||
e = extend( { nofunc: true , own: true } , null , o ) ; | ||
expect( e ).not.to.be( o ) ; | ||
expect( e ).to.eql( { own1: 'own1' , own2: 'own2' } ) ; | ||
// with 'proto', function exists if there are in the prototype | ||
e = extend( { nofunc: true , proto: true } , null , o ) ; | ||
expect( e ).not.to.be( o ) ; | ||
expect( e.__proto__ ).to.equal( proto ) ; // jshint ignore:line | ||
expect( e ).to.eql( { own1: 'own1' , own2: 'own2' } ) ; | ||
expect( e.proto1 ).to.be( 'proto1' ) ; | ||
expect( e.proto2 ).to.be( 'proto2' ) ; | ||
expect( typeof e.hello ).to.equal( 'function' ) ; | ||
``` | ||
with 'preserve' option should not overwrite existing properties in the target. | ||
```js | ||
var e , o ; | ||
e = { | ||
one: '1' , | ||
two: 2 , | ||
three: 'THREE' | ||
} ; | ||
o = { | ||
three: 3 , | ||
four: '4' | ||
} ; | ||
extend( { preserve: true } , e , o ) ; | ||
expect( e ).to.eql( { one: '1' , two: 2 , three: 'THREE' , four: '4' } ) ; | ||
expect( o ).to.eql( { three: 3 , four: '4' } ) ; | ||
``` | ||
with 'move' option should move source properties to target properties, i.e. delete them form the source. | ||
```js | ||
var e , o ; | ||
e = { | ||
one: '1' , | ||
two: 2 , | ||
three: 'THREE' | ||
} ; | ||
o = { | ||
three: 3 , | ||
four: '4' | ||
} ; | ||
extend( { move: true } , e , o ) ; | ||
expect( e ).to.eql( { one: '1' , two: 2 , three: 3 , four: '4' } ) ; | ||
expect( o ).to.eql( {} ) ; | ||
``` | ||
with 'preserve' and 'move' option should not overwrite existing properties in the target, so it should not move/delete them from the source object. | ||
```js | ||
var e , o ; | ||
e = { | ||
one: '1' , | ||
two: 2 , | ||
three: 'THREE' | ||
} ; | ||
o = { | ||
three: 3 , | ||
four: '4' | ||
} ; | ||
extend( { preserve: true , move: true } , e , o ) ; | ||
expect( e ).to.eql( { one: '1' , two: 2 , three: 'THREE' , four: '4' } ) ; | ||
expect( o ).to.eql( { three: 3 } ) ; | ||
``` | ||
with 'inherit' option should inherit rather than extend: each source property create a new Object or mutate existing Object into the related target property, using itself as the prototype. | ||
```js | ||
var e , o ; | ||
o = { | ||
three: 3 , | ||
four: '4' , | ||
subtree: { | ||
five: 'FIVE' , | ||
six: 6 | ||
} | ||
} ; | ||
e = {} ; | ||
extend( { inherit: true } , e , o ) ; | ||
expect( e.__proto__ ).to.equal( o ) ; // jshint ignore:line | ||
expect( e ).to.eql( {} ) ; | ||
expect( e.three ).to.be( 3 ) ; | ||
expect( e.four ).to.be( '4' ) ; | ||
expect( e.subtree ).to.equal( o.subtree ) ; | ||
e = { | ||
one: '1' , | ||
two: 2 , | ||
three: 'THREE' , | ||
} ; | ||
extend( { inherit: true } , e , o ) ; | ||
expect( e.__proto__ ).to.equal( o ) ; // jshint ignore:line | ||
expect( e ).to.eql( { one: '1' , two: 2 , three: 'THREE' } ) ; | ||
expect( e.three ).to.be( 'THREE' ) ; | ||
expect( e.four ).to.be( '4' ) ; | ||
expect( e.subtree ).to.equal( o.subtree ) ; // jshint ignore:line | ||
expect( e.subtree ).to.eql( { five: 'FIVE' , six: 6 } ) ; | ||
e = { | ||
one: '1' , | ||
two: 2 , | ||
three: 'THREE' , | ||
subtree: { | ||
six: 'SIX' , | ||
seven: 7 | ||
} | ||
} ; | ||
extend( { inherit: true } , e , o ) ; | ||
expect( e.__proto__ ).to.equal( o ) ; // jshint ignore:line | ||
expect( e ).to.eql( { one: '1' , two: 2 , three: 'THREE' , subtree: { six: 'SIX' , seven: 7 } } ) ; | ||
expect( e.three ).to.be( 'THREE' ) ; | ||
expect( e.four ).to.be( '4' ) ; | ||
expect( e.subtree ).to.eql( { six: 'SIX' , seven: 7 } ) ; | ||
expect( e.subtree.five ).to.equal( undefined ) ; | ||
``` | ||
with 'inherit' and 'deep' option should inherit recursively. | ||
```js | ||
var e , o ; | ||
o = { | ||
three: 3 , | ||
four: '4' , | ||
subtree: { | ||
five: 'FIVE' , | ||
six: 6 | ||
} | ||
} ; | ||
e = {} ; | ||
extend( { inherit: true , deep: true } , e , o ) ; | ||
expect( e.__proto__ ).to.equal( o ) ; // jshint ignore:line | ||
expect( e ).to.eql( { subtree: {} } ) ; | ||
expect( e.three ).to.be( 3 ) ; | ||
expect( e.four ).to.be( '4' ) ; | ||
expect( e.subtree.__proto__ ).to.equal( o.subtree ) ; // jshint ignore:line | ||
expect( e.subtree.five ).to.equal( 'FIVE' ) ; | ||
expect( e.subtree.six ).to.equal( 6 ) ; | ||
e = { | ||
one: '1' , | ||
two: 2 , | ||
three: 'THREE' , | ||
} ; | ||
extend( { inherit: true , deep: true } , e , o ) ; | ||
expect( e.__proto__ ).to.equal( o ) ; // jshint ignore:line | ||
expect( e ).to.eql( { one: '1' , two: 2 , three: 'THREE' , subtree: {} } ) ; | ||
expect( e.three ).to.be( 'THREE' ) ; | ||
expect( e.four ).to.be( '4' ) ; | ||
expect( e.subtree.__proto__ ).to.equal( o.subtree ) ; // jshint ignore:line | ||
expect( e.subtree ).to.eql( {} ) ; | ||
expect( e.subtree.five ).to.equal( 'FIVE' ) ; | ||
expect( e.subtree.six ).to.equal( 6 ) ; | ||
e = { | ||
one: '1' , | ||
two: 2 , | ||
three: 'THREE' , | ||
subtree: { | ||
six: 'SIX' , | ||
seven: 7 | ||
} | ||
} ; | ||
extend( { inherit: true , deep: true } , e , o ) ; | ||
expect( e.__proto__ ).to.equal( o ) ; // jshint ignore:line | ||
expect( e ).to.eql( { one: '1' , two: 2 , three: 'THREE' , subtree: { six: 'SIX' , seven: 7 } } ) ; | ||
expect( e.three ).to.be( 'THREE' ) ; | ||
expect( e.four ).to.be( '4' ) ; | ||
expect( e.subtree.__proto__ ).to.equal( o.subtree ) ; // jshint ignore:line | ||
expect( e.subtree ).to.eql( { six: 'SIX' , seven: 7 } ) ; | ||
expect( e.subtree.five ).to.equal( 'FIVE' ) ; | ||
``` | ||
with 'flat' option. | ||
```js | ||
var e , o ; | ||
o = { | ||
three: 3 , | ||
four: '4' , | ||
subtree: { | ||
five: 'FIVE' , | ||
six: 6 , | ||
subsubtree: { | ||
subsubsubtree: { one: 'ONE' } , | ||
seven: 'seven' | ||
} , | ||
emptysubtree: {} | ||
} , | ||
eight: 8 , | ||
anothersubtree: { | ||
nine: '9' | ||
} | ||
} ; | ||
e = extend( { flat: true } , {} , o ) ; | ||
expect( e ).to.eql( { | ||
three: 3 , | ||
four: '4' , | ||
'subtree.five': 'FIVE' , | ||
'subtree.six': 6 , | ||
'subtree.subsubtree.seven': 'seven' , | ||
'subtree.subsubtree.subsubsubtree.one': 'ONE' , | ||
eight: 8 , | ||
'anothersubtree.nine': '9' | ||
} ) ; | ||
e = extend( { flat: '/' } , {} , o ) ; | ||
expect( e ).to.eql( { | ||
three: 3 , | ||
four: '4' , | ||
'subtree/five': 'FIVE' , | ||
'subtree/six': 6 , | ||
'subtree/subsubtree/seven': 'seven' , | ||
'subtree/subsubtree/subsubsubtree/one': 'ONE' , | ||
eight: 8 , | ||
'anothersubtree/nine': '9' | ||
} ) ; | ||
``` | ||
with 'unflat' option. | ||
```js | ||
var e , o ; | ||
o = { | ||
three: 3 , | ||
four: '4' , | ||
'subtree.five': 'FIVE' , | ||
'subtree.six': 6 , | ||
'subtree.subsubtree.seven': 'seven' , | ||
'subtree.subsubtree.subsubsubtree.one': 'ONE' , | ||
eight: 8 , | ||
'anothersubtree.nine': '9' | ||
} ; | ||
e = extend( { unflat: true } , {} , o ) ; | ||
expect( e ).to.eql( { | ||
three: 3 , | ||
four: '4' , | ||
subtree: { | ||
five: 'FIVE' , | ||
six: 6 , | ||
subsubtree: { | ||
subsubsubtree: { one: 'ONE' } , | ||
seven: 'seven' | ||
} | ||
} , | ||
eight: 8 , | ||
anothersubtree: { | ||
nine: '9' | ||
} | ||
} ) ; | ||
o = { | ||
three: 3 , | ||
four: '4' , | ||
'subtree/five': 'FIVE' , | ||
'subtree/six': 6 , | ||
'subtree/subsubtree/seven': 'seven' , | ||
'subtree/subsubtree/subsubsubtree/one': 'ONE' , | ||
eight: 8 , | ||
'anothersubtree/nine': '9' | ||
} ; | ||
e = extend( { unflat: '/' } , {} , o ) ; | ||
expect( e ).to.eql( { | ||
three: 3 , | ||
four: '4' , | ||
subtree: { | ||
five: 'FIVE' , | ||
six: 6 , | ||
subsubtree: { | ||
subsubsubtree: { one: 'ONE' } , | ||
seven: 'seven' | ||
} | ||
} , | ||
eight: 8 , | ||
anothersubtree: { | ||
nine: '9' | ||
} | ||
} ) ; | ||
``` | ||
with 'deepFilter' option, using blacklist. | ||
```js | ||
var buf = new Buffer( "My buffer" ) ; | ||
var o = { | ||
one: '1' , | ||
buf: buf , | ||
subtree: { | ||
two: 2 , | ||
three: 'THREE' | ||
} | ||
} ; | ||
var e = extend( { deep: true, deepFilter: { blacklist: [ Buffer.prototype ] } } , {} , o ) ; | ||
o.subtree.three = 3 ; | ||
buf[ 0 ] = 'm'.charCodeAt() ; | ||
expect( e.buf ).to.be.a( Buffer ) ; | ||
expect( e.buf.toString() ).to.be( "my buffer" ) ; | ||
expect( e.buf ).to.be( buf ) ; | ||
expect( e ).to.eql( { | ||
one: '1' , | ||
buf: buf , | ||
subtree: { | ||
two: 2 , | ||
three: 'THREE' | ||
} | ||
} ) ; | ||
``` | ||
with 'deepFilter' option, using whitelist. | ||
```js | ||
var buf = new Buffer( "My buffer" ) ; | ||
var o = { | ||
one: '1' , | ||
buf: buf , | ||
subtree: { | ||
two: 2 , | ||
three: 'THREE' | ||
} | ||
} ; | ||
var e = extend( { deep: true, deepFilter: { whitelist: [ Object.prototype ] } } , {} , o ) ; | ||
o.subtree.three = 3 ; | ||
buf[ 0 ] = 'm'.charCodeAt() ; | ||
expect( e.buf ).to.be.a( Buffer ) ; | ||
expect( e.buf.toString() ).to.be( "my buffer" ) ; | ||
expect( e.buf ).to.be( buf ) ; | ||
expect( e ).to.eql( { | ||
one: '1' , | ||
buf: buf , | ||
subtree: { | ||
two: 2 , | ||
three: 'THREE' | ||
} | ||
} ) ; | ||
``` | ||
circular references test. | ||
```js | ||
var c , o = { | ||
a: 'a', | ||
sub: { | ||
b: 'b' | ||
}, | ||
sub2: { | ||
c: 'c' | ||
} | ||
} ; | ||
o.loop = o ; | ||
o.sub.loop = o ; | ||
o.subcopy = o.sub ; | ||
o.sub.link = o.sub2 ; | ||
o.sub2.link = o.sub ; | ||
try { | ||
c = extend( { deep: true } , null , o ) ; | ||
throw new Error( 'Should throw an error: max depth reached' ) ; | ||
} | ||
catch ( error ) { | ||
} | ||
c = extend( { deep: true , circular: true } , null , o ) ; | ||
expect( c.loop ).to.be( c ) ; | ||
expect( c.sub ).to.be( c.subcopy ) ; | ||
expect( c.sub.loop ).to.be( c ) ; | ||
expect( c.subcopy.loop ).to.be( c ) ; | ||
expect( c.sub.link ).to.be( c.sub2 ) ; | ||
expect( c.sub2.link ).to.be( c.sub ) ; | ||
``` | ||
<a name="definelazyproperty"></a> | ||
# defineLazyProperty() | ||
should define property using a getter that after its first execution is reconfigured as its return-value and is not writable. | ||
```js | ||
var object = {} ; | ||
var counter = 0 ; | ||
tree.defineLazyProperty( object , 'myprop' , function() { | ||
counter ++ ; | ||
return counter ; | ||
} ) ; | ||
expect( object.myprop ).to.be( 1 ) ; | ||
expect( object.myprop ).to.be( 1 ) ; | ||
expect( object.myprop ).to.be( 1 ) ; | ||
expect( counter ).to.be( 1 ) ; | ||
expect( function() { object.myprop ++ ; } ).to.throwError() ; | ||
expect( object.myprop ).to.be( 1 ) ; | ||
``` | ||
<a name="masks"></a> | ||
# Masks | ||
should apply a simple mask tree to the input tree. | ||
```js | ||
var mask = tree.createMask( { | ||
int: true, | ||
float: true, | ||
attachement: { | ||
filename: true, | ||
unexistant: true | ||
}, | ||
unexistant: true, | ||
subtree: { | ||
subtree: true | ||
} | ||
} ) ; | ||
var output = mask.applyTo( input ) ; | ||
expect( output ).to.eql( { | ||
int: 12, | ||
float: 2.47, | ||
attachement: { | ||
filename: 'preview.png' | ||
}, | ||
subtree: { | ||
subtree: { | ||
d: 4, | ||
e: undefined, | ||
f: 3.14 | ||
} | ||
} | ||
} ) ; | ||
``` | ||
should apply a mask tree with wildcard '*' to the input tree. | ||
```js | ||
var mask = tree.createMask( { | ||
'files': { | ||
'*': { | ||
size: true, | ||
unexistant: true | ||
} | ||
} | ||
} ) ; | ||
var output = mask.applyTo( input ) ; | ||
expect( output.files ).to.be.an( Object ) ; | ||
expect( output ).to.eql( { | ||
files: { | ||
'background.png' : { | ||
size : '97856' | ||
} , | ||
'header.png' : { | ||
size : '44193' | ||
} , | ||
'footer.png' : { | ||
size : '36411' | ||
} | ||
} | ||
} ) ; | ||
``` | ||
should apply a mask tree with wildcard '*' to match array in the input tree. | ||
```js | ||
var mask = tree.createMask( { | ||
'filesArray': { | ||
'*': { | ||
name: true, | ||
size: true, | ||
unexistant: true | ||
} | ||
} | ||
} ) ; | ||
var output = mask.applyTo( input ) ; | ||
expect( output.filesArray ).to.be.an( Array ) ; | ||
expect( output ).to.eql( { | ||
filesArray: [ | ||
{ | ||
name : 'background.png' , | ||
size : '97856' | ||
} , | ||
{ | ||
name : 'header.png' , | ||
size : '44193' | ||
} , | ||
{ | ||
name : 'footer.png' , | ||
size : '36411' | ||
} | ||
] | ||
} ) ; | ||
//console.log( "\n\n\n\n" , output , "\n\n\n\n" ) ; | ||
``` | ||
should apply a mask with a mask's leaf callback to the input tree. | ||
```js | ||
var leaf = function leaf( input , key , argument , path ) { | ||
//console.log( 'LEAF: ' , input , key , argument , path ) ; | ||
if ( ! input.hasOwnProperty( key ) ) { return new Error( 'not_found' ) ; } | ||
if ( typeof input[ key ] === 'number' ) { return input[ key ] + argument ; } | ||
return input[ key ] ; | ||
} ; | ||
var mask = tree.createMask( | ||
{ | ||
int: 87 , | ||
float: 14 , | ||
subtree: { | ||
subtree: { | ||
f: 0.0016 | ||
} | ||
} , | ||
unexistant: 45 | ||
} , | ||
{ leaf: leaf } | ||
) ; | ||
var output = mask.applyTo( input ) ; | ||
expect( output ).to.eql( { | ||
int: 99, | ||
float: 16.47, | ||
subtree: { | ||
subtree: { | ||
f: 3.1416 | ||
} | ||
} | ||
} ) ; | ||
``` | ||
should apply a mask containing other masks to the input tree. | ||
```js | ||
var mask = tree.createMask( { | ||
int: true, | ||
float: true, | ||
attachement: tree.createMask( { | ||
filename: true, | ||
unexistant: true | ||
} ), | ||
unexistant: true, | ||
subtree: tree.createMask( { | ||
subtree: true | ||
} ) | ||
} ) ; | ||
var output = mask.applyTo( input ) ; | ||
expect( output ).to.eql( { | ||
int: 12, | ||
float: 2.47, | ||
attachement: { | ||
filename: 'preview.png' | ||
}, | ||
subtree: { | ||
subtree: { | ||
d: 4, | ||
e: undefined, | ||
f: 3.14 | ||
} | ||
} | ||
} ) ; | ||
``` | ||
<a name="inverse-masks"></a> | ||
# Inverse masks | ||
should apply a simple mask tree to the input tree. | ||
```js | ||
var mask = tree.createInverseMask( { | ||
a: true, | ||
subtree: { | ||
d: true | ||
}, | ||
subtree2: true | ||
} ) ; | ||
var output = mask.applyTo( input.subtree ) ; | ||
//console.log( output ) ; | ||
expect( output ).to.eql( { | ||
b: 2, | ||
subtree: { | ||
e: undefined, | ||
f: 3.14 | ||
}, | ||
c: 'plusplus' | ||
} ) ; | ||
``` | ||
<a name="trees-path-on-objects"></a> | ||
# Tree's path on objects | ||
path.get() on object structure. | ||
```js | ||
var o = { | ||
a: 5 , | ||
sub: { | ||
b: "toto" , | ||
sub: { | ||
c: true | ||
} | ||
} , | ||
d: null | ||
} ; | ||
expect( tree.path.get( o , 'a' ) ).to.be( 5 ) ; | ||
expect( tree.path.get( o , 'sub' ) ).to.eql( { | ||
b: "toto" , | ||
sub: { | ||
c: true | ||
} | ||
} ) ; | ||
expect( tree.path.get( o , 'sub.b' ) ).to.be( "toto" ) ; | ||
expect( tree.path.get( o , 'sub.sub' ) ).to.eql( { c: true } ) ; | ||
expect( tree.path.get( o , 'sub.sub.c' ) ).to.be( true ) ; | ||
expect( tree.path.get( o , 'd' ) ).to.be( null ) ; | ||
expect( tree.path.get( o , 'nothing' ) ).to.be( undefined ) ; | ||
expect( tree.path.get( o , 'sub.nothing' ) ).to.be( undefined ) ; | ||
expect( tree.path.get( o , 'nothing.nothing' ) ).to.be( undefined ) ; | ||
``` | ||
path.delete() on object structure. | ||
```js | ||
var o = { | ||
a: 5 , | ||
sub: { | ||
b: "toto" , | ||
sub: { | ||
c: true , | ||
sub: { | ||
f: '' | ||
} | ||
} | ||
} , | ||
d: null | ||
} ; | ||
tree.path.delete( o , 'a' ) ; | ||
tree.path.delete( o , 'sub.sub' ) ; | ||
tree.path.delete( o , 'non.existant.path' ) ; | ||
expect( o ).to.eql( { | ||
sub: { | ||
b: "toto" , | ||
} , | ||
d: null | ||
} ) ; | ||
``` | ||
path.set() on object structure. | ||
```js | ||
var o = { | ||
a: 5 , | ||
sub: { | ||
b: "toto" , | ||
sub: { | ||
c: true | ||
} | ||
} , | ||
d: null | ||
} ; | ||
tree.path.set( o , 'a' , "8" ) ; | ||
tree.path.set( o , 'sub.b' , false ) ; | ||
tree.path.set( o , 'sub.sub' , { x: 18 , y: 27 } ) ; | ||
tree.path.set( o , 'non.existant.path' , 'new' ) ; | ||
expect( o ).to.eql( { | ||
a: "8" , | ||
sub: { | ||
b: false , | ||
sub: { | ||
x: 18 , | ||
y: 27 | ||
} | ||
} , | ||
d: null , | ||
non: { | ||
existant: { | ||
path: 'new' | ||
} | ||
} | ||
} ) ; | ||
``` | ||
path.define() on object structure. | ||
```js | ||
var o = { | ||
a: 5 , | ||
sub: { | ||
b: "toto" , | ||
sub: { | ||
c: true | ||
} | ||
} , | ||
d: null | ||
} ; | ||
tree.path.define( o , 'a' , "8" ) ; | ||
tree.path.define( o , 'sub.b' , false ) ; | ||
tree.path.define( o , 'unexistant' , '!' ) ; | ||
tree.path.define( o , 'sub.sub' , { x: 18 , y: 27 } ) ; | ||
tree.path.define( o , 'non.existant.path' , 'new' ) ; | ||
expect( o ).to.eql( { | ||
a: 5 , | ||
unexistant: '!' , | ||
sub: { | ||
b: "toto" , | ||
sub: { | ||
c: true | ||
} | ||
} , | ||
d: null , | ||
non: { | ||
existant: { | ||
path: 'new' | ||
} | ||
} | ||
} ) ; | ||
``` | ||
path.inc() and path.dec() on object structure. | ||
```js | ||
var o = { | ||
a: 5 , | ||
sub: { | ||
b: 10 , | ||
sub: { | ||
c: true | ||
} | ||
} , | ||
d: null | ||
} ; | ||
tree.path.inc( o , 'a' ) ; | ||
tree.path.dec( o , 'sub.b' ) ; | ||
tree.path.inc( o , 'sub' ) ; | ||
tree.path.dec( o , 'sub.sub' ) ; | ||
tree.path.inc( o , 'non.existant.path' ) ; | ||
tree.path.dec( o , 'another.non.existant.path' ) ; | ||
expect( o ).to.eql( { | ||
a: 6 , | ||
sub: { | ||
b: 9 , | ||
sub: { | ||
c: true | ||
} | ||
} , | ||
d: null , | ||
non: { | ||
existant: { | ||
path: 1 | ||
} | ||
} , | ||
another: { | ||
non: { | ||
existant: { | ||
path: -1 | ||
} | ||
} | ||
} | ||
} ) ; | ||
``` | ||
path.append() and path.prepend() on object structure. | ||
```js | ||
var o = { | ||
a: null , | ||
sub: { | ||
b: [ 'some' ] , | ||
sub: { | ||
c: [ 'value' ] | ||
} | ||
} , | ||
} ; | ||
tree.path.append( o , 'a' , 'hello' ) ; | ||
tree.path.append( o , 'sub.b' , 'value' ) ; | ||
tree.path.prepend( o , 'sub.sub.c' , 'other' ) ; | ||
tree.path.prepend( o , 'sub.sub.c' , 'some' ) ; | ||
tree.path.append( o , 'sub.sub.c' , '!' ) ; | ||
tree.path.append( o , 'non.existant.path' , '!' ) ; | ||
tree.path.prepend( o , 'another.non.existant.path' , '!' ) ; | ||
expect( o ).to.eql( { | ||
a: [ 'hello' ] , | ||
sub: { | ||
b: [ 'some' , 'value' ] , | ||
sub: { | ||
c: [ 'some' , 'other' , 'value' , '!' ] | ||
} | ||
} , | ||
non: { | ||
existant: { | ||
path: [ '!' ] | ||
} | ||
} , | ||
another: { | ||
non: { | ||
existant: { | ||
path: [ '!' ] | ||
} | ||
} | ||
} | ||
} ) ; | ||
``` | ||
path.concat() and path.insert() on object structure. | ||
```js | ||
var o = { | ||
a: null , | ||
sub: { | ||
b: [ 'hi' ] , | ||
sub: { | ||
c: [ 'again' ] | ||
} | ||
} , | ||
} ; | ||
tree.path.concat( o , 'a' , [ 'hello' , 'world' ] ) ; | ||
tree.path.concat( o , 'sub.b' , [ 'hello' , 'world' ] ) ; | ||
tree.path.insert( o , 'sub.sub.c' , [ 'hello' , 'world' ] ) ; | ||
expect( o ).to.eql( { | ||
a: [ 'hello' , 'world' ] , | ||
sub: { | ||
b: [ 'hi' , 'hello' , 'world' ] , | ||
sub: { | ||
c: [ 'hello' , 'world' , 'again' ] | ||
} | ||
} | ||
} ) ; | ||
``` | ||
path.autoPush(). | ||
```js | ||
var o = { | ||
a: 1 , | ||
sub: { | ||
b: [ 'some' ] , | ||
sub: { | ||
c: [ 'some' , 'other' , 'value' ] | ||
} | ||
} , | ||
} ; | ||
tree.path.autoPush( o , 'a' , 'hello' ) ; | ||
tree.path.autoPush( o , 'd' , 'D' ) ; | ||
tree.path.autoPush( o , 'sub.b' , 'value' ) ; | ||
tree.path.autoPush( o , 'sub.sub.c' , '!' ) ; | ||
tree.path.autoPush( o , 'non.existant.path' , '!' ) ; | ||
expect( o ).to.eql( { | ||
a: [ 1 , 'hello' ] , | ||
d: 'D' , | ||
sub: { | ||
b: [ 'some' , 'value' ] , | ||
sub: { | ||
c: [ 'some' , 'other' , 'value' , '!' ] | ||
} | ||
} , | ||
non: { | ||
existant: { | ||
path: '!' | ||
} | ||
} | ||
} ) ; | ||
``` | ||
empty keys. | ||
```js | ||
var o ; | ||
o = { | ||
a: 5 , | ||
"": { | ||
b: "toto" , | ||
sub: { | ||
c: true | ||
} | ||
} , | ||
d: null | ||
} ; | ||
expect( tree.path.get( o , 'a' ) ).to.be( 5 ) ; | ||
expect( tree.path.get( o , '' ) ).to.eql( { b: "toto" , sub: { c: true } } ) ; | ||
expect( tree.path.get( o , '.b' ) ).to.be( "toto" ) ; | ||
expect( tree.path.get( o , '.sub' ) ).to.eql( { c: true } ) ; | ||
expect( tree.path.get( o , '.sub.c' ) ).to.be( true ) ; | ||
o = { | ||
"": { | ||
"": { | ||
"": { | ||
a: 1 , | ||
b: 2 | ||
} | ||
} | ||
} , | ||
} ; | ||
expect( tree.path.get( o , '' ) ).to.eql( { "": { "": { a: 1 , b: 2 } } } ) ; | ||
expect( tree.path.get( o , '.' ) ).to.eql( { "": { a: 1 , b: 2 } } ) ; | ||
expect( tree.path.get( o , '..' ) ).to.eql( { a: 1 , b: 2 } ) ; | ||
expect( tree.path.get( o , '...a' ) ).to.eql( 1 ) ; | ||
``` | ||
<a name="trees-path-on-arrays"></a> | ||
# Tree's path on arrays | ||
path.get() on a simple array. | ||
```js | ||
var a = [ 'a' , 'b' , 'c' ] ; | ||
expect( tree.path.get( a , '0' ) ).to.be( 'a' ) ; | ||
expect( tree.path.get( a , '1' ) ).to.be( 'b' ) ; | ||
expect( tree.path.get( a , '2' ) ).to.be( 'c' ) ; | ||
expect( tree.path.get( a , '3' ) ).to.be( undefined ) ; | ||
expect( tree.path.get( a , '#0' ) ).to.be( 'a' ) ; | ||
expect( tree.path.get( a , '#1' ) ).to.be( 'b' ) ; | ||
expect( tree.path.get( a , '#2' ) ).to.be( 'c' ) ; | ||
expect( tree.path.get( a , '#3' ) ).to.be( undefined ) ; | ||
expect( tree.path.get( a , '[0]' ) ).to.be( 'a' ) ; | ||
expect( tree.path.get( a , '[1]' ) ).to.be( 'b' ) ; | ||
expect( tree.path.get( a , '[2]' ) ).to.be( 'c' ) ; | ||
expect( tree.path.get( a , '[3]' ) ).to.be( undefined ) ; | ||
expect( tree.path.get( a , 'length' ) ).to.be( 3 ) ; | ||
expect( tree.path.get( a , '#length' ) ).to.be( 3 ) ; | ||
expect( tree.path.get( a , 'first' ) ).to.be( undefined ) ; | ||
expect( tree.path.get( a , '#first' ) ).to.be( 'a' ) ; | ||
expect( tree.path.get( a , 'last' ) ).to.be( undefined ) ; | ||
expect( tree.path.get( a , '#last' ) ).to.be( 'c' ) ; | ||
expect( tree.path.get( a , 'next' ) ).to.be( undefined ) ; | ||
expect( tree.path.get( a , '#next' ) ).to.be( undefined ) ; | ||
``` | ||
path.get() on nested arrays. | ||
```js | ||
var a = [ 'a' , [ [ 'b' , 'c' ] , 'd' , [ 'e' , 'f' ] ] ] ; | ||
expect( tree.path.get( a , '#0' ) ).to.be( 'a' ) ; | ||
expect( tree.path.get( a , '#1' ) ).to.eql( [ [ 'b' , 'c' ] , 'd' , [ 'e' , 'f' ] ] ) ; | ||
expect( tree.path.get( a , '#2' ) ).to.be( undefined ) ; | ||
expect( tree.path.get( a , '[0]' ) ).to.be( 'a' ) ; | ||
expect( tree.path.get( a , '[1]' ) ).to.eql( [ [ 'b' , 'c' ] , 'd' , [ 'e' , 'f' ] ] ) ; | ||
expect( tree.path.get( a , '[2]' ) ).to.be( undefined ) ; | ||
expect( tree.path.get( a , '#length' ) ).to.be( 2 ) ; | ||
expect( tree.path.get( a , '#first' ) ).to.be( 'a' ) ; | ||
expect( tree.path.get( a , '#last' ) ).to.eql( [ [ 'b' , 'c' ] , 'd' , [ 'e' , 'f' ] ] ) ; | ||
expect( tree.path.get( a , '#next' ) ).to.be( undefined ) ; | ||
expect( tree.path.get( a , '1#0' ) ).to.eql( [ 'b' , 'c' ] ) ; | ||
expect( tree.path.get( a , '1#1' ) ).to.eql( 'd' ) ; | ||
expect( tree.path.get( a , '1#2' ) ).to.eql( [ 'e' , 'f' ] ) ; | ||
expect( tree.path.get( a , '1#3' ) ).to.be( undefined ) ; | ||
expect( tree.path.get( a , '[1][0]' ) ).to.eql( [ 'b' , 'c' ] ) ; | ||
expect( tree.path.get( a , '[1][1]' ) ).to.eql( 'd' ) ; | ||
expect( tree.path.get( a , '[1][2]' ) ).to.eql( [ 'e' , 'f' ] ) ; | ||
expect( tree.path.get( a , '[1][3]' ) ).to.be( undefined ) ; | ||
expect( tree.path.get( a , '1#length' ) ).to.be( 3 ) ; | ||
expect( tree.path.get( a , '1#first' ) ).to.eql( [ 'b' , 'c' ] ) ; | ||
expect( tree.path.get( a , '1#last' ) ).to.eql( [ 'e' , 'f' ] ) ; | ||
expect( tree.path.get( a , '1#next' ) ).to.be( undefined ) ; | ||
expect( tree.path.get( a , '1#2#last' ) ).to.eql( 'f' ) ; | ||
``` | ||
path.set() on a simple array. | ||
```js | ||
var a ; | ||
a = [ 'a' , 'b' , 'c' ] ; | ||
tree.path.set( a , '1' , 'B' ) ; | ||
tree.path.set( a , '#last' , 3 ) ; | ||
tree.path.set( a , '#next' , 'D' ) ; | ||
tree.path.set( a , '#first' , 1 ) ; | ||
expect( a ).to.eql( [ 1 , 'B' , 3 , 'D' ] ) ; | ||
expect( tree.path.get( a , '#length' ) ).to.be( 4 ) ; | ||
a = [ 'a' , 'b' , 'c' ] ; | ||
tree.path.set( a , '[1]' , 'BBB' ) ; | ||
tree.path.set( a , '#last' , 3 ) ; | ||
tree.path.set( a , '#next' , 'D' ) ; | ||
tree.path.set( a , '#first' , 1 ) ; | ||
expect( a ).to.eql( [ 1 , 'BBB' , 3 , 'D' ] ) ; | ||
expect( tree.path.get( a , '#length' ) ).to.be( 4 ) ; | ||
``` | ||
path.set() using multiple #next and #insert. | ||
```js | ||
var a = [ 'a' , 'b' , 'c' ] ; | ||
tree.path.set( a , '#next' , 'D' ) ; | ||
tree.path.set( a , '#next.f#next' , 'g' ) ; | ||
tree.path.set( a , '#next#next#next' , 'E' ) ; | ||
tree.path.set( a , '#insert' , '@' ) ; | ||
tree.path.set( a , '#last#insert' , '@' ) ; | ||
expect( a ).to.eql( [ '@' , 'a' , 'b' , 'c' , 'D' , { f: [ 'g' ] } , [ '@' , [ 'E' ] ] ] ) ; | ||
expect( tree.path.get( a , '#length' ) ).to.be( 7 ) ; | ||
``` | ||
path.delete() on a simple array. | ||
```js | ||
var a ; | ||
a = [ 'a' , 'b' , 'c' ] ; | ||
tree.path.delete( a , '1' ) ; | ||
//expect( a ).to.eql( [ 'a' , undefined , 'c' ] ) ; // expect() bug here... | ||
expect( tree.path.get( a , '#length' ) ).to.be( 3 ) ; | ||
a = [ 'a' , 'b' , 'c' ] ; | ||
tree.path.delete( a , '#1' ) ; | ||
expect( a ).to.eql( [ 'a' , 'c' ] ) ; | ||
expect( tree.path.get( a , '#length' ) ).to.be( 2 ) ; | ||
a = [ 'a' , 'b' , 'c' ] ; | ||
tree.path.delete( a , '[1]' ) ; | ||
expect( a ).to.eql( [ 'a' , 'c' ] ) ; | ||
expect( tree.path.get( a , '#length' ) ).to.be( 2 ) ; | ||
a = [ 'a' , 'b' , 'c' ] ; | ||
tree.path.delete( a , '#2' ) ; | ||
expect( a ).to.eql( [ 'a' , 'b' ] ) ; | ||
expect( tree.path.get( a , '#length' ) ).to.be( 2 ) ; | ||
a = [ 'a' , 'b' , 'c' ] ; | ||
tree.path.delete( a , '[2]' ) ; | ||
expect( a ).to.eql( [ 'a' , 'b' ] ) ; | ||
expect( tree.path.get( a , '#length' ) ).to.be( 2 ) ; | ||
a = [ 'a' , 'b' , 'c' ] ; | ||
tree.path.delete( a , '#last' ) ; | ||
expect( a ).to.eql( [ 'a' , 'b' ] ) ; | ||
expect( tree.path.get( a , '#length' ) ).to.be( 2 ) ; | ||
tree.path.delete( a , '#last' ) ; | ||
expect( a ).to.eql( [ 'a' ] ) ; | ||
expect( tree.path.get( a , '#length' ) ).to.be( 1 ) ; | ||
tree.path.delete( a , '#last' ) ; | ||
expect( a ).to.eql( [] ) ; | ||
expect( tree.path.get( a , '#length' ) ).to.be( 0 ) ; | ||
a = [ 'a' , 'b' , 'c' ] ; | ||
tree.path.delete( a , '#first' ) ; | ||
expect( a ).to.eql( [ 'b' , 'c' ] ) ; | ||
expect( tree.path.get( a , '#length' ) ).to.be( 2 ) ; | ||
tree.path.delete( a , '#first' ) ; | ||
expect( a ).to.eql( [ 'c' ] ) ; | ||
expect( tree.path.get( a , '#length' ) ).to.be( 1 ) ; | ||
tree.path.delete( a , '#first' ) ; | ||
expect( a ).to.eql( [] ) ; | ||
expect( tree.path.get( a , '#length' ) ).to.be( 0 ) ; | ||
``` | ||
<a name="trees-path-on-mixed-object-and-arrays"></a> | ||
# Tree's path on mixed object and arrays | ||
path.get() on a simple array. | ||
```js | ||
var a = { | ||
method: 'get' , | ||
populate: [ 'parents', 'godfather' ] | ||
} ; | ||
expect( tree.path.get( a , 'method' ) ).to.be( 'get' ) ; | ||
expect( tree.path.get( a , 'populate' ) ).to.eql( [ 'parents', 'godfather' ] ) ; | ||
expect( tree.path.get( a , 'populate[0]' ) ).to.be( 'parents' ) ; | ||
expect( tree.path.get( a , 'populate[1]' ) ).to.be( 'godfather' ) ; | ||
expect( tree.path.get( a , 'populate[2]' ) ).to.be( undefined ) ; | ||
``` | ||
path.set() on a simple array. | ||
```js | ||
var a = { | ||
method: 'get' , | ||
populate: [ 'parent', 'godfather' ] | ||
} ; | ||
tree.path.set( a , 'method' , 'post' ) ; | ||
tree.path.set( a , 'populate[0]' , 'friends' ) ; | ||
expect( a ).to.eql( { | ||
method: 'post' , | ||
populate: [ 'friends', 'godfather' ] | ||
} ) ; | ||
``` | ||
<a name="inheritance-using-objectcreate-treepathprototype-"></a> | ||
# Inheritance, using Object.create( tree.path.prototype ) | ||
.get(). | ||
```js | ||
var o = Object.create( tree.path.prototype ) ; | ||
o.a = 5 ; | ||
o.sub = { | ||
b: "toto" , | ||
sub: { | ||
c: true | ||
} | ||
} ; | ||
o.d = null ; | ||
expect( o.get( 'a' ) ).to.be( 5 ) ; | ||
expect( o.get( 'sub' ) ).to.eql( { | ||
b: "toto" , | ||
sub: { | ||
c: true | ||
} | ||
} ) ; | ||
expect( o.get( 'sub.b' ) ).to.be( "toto" ) ; | ||
expect( o.get( 'sub.sub' ) ).to.eql( { c: true } ) ; | ||
expect( o.get( 'sub.sub.c' ) ).to.be( true ) ; | ||
expect( o.get( 'd' ) ).to.be( null ) ; | ||
expect( o.get( 'nothing' ) ).to.be( undefined ) ; | ||
expect( o.get( 'sub.nothing' ) ).to.be( undefined ) ; | ||
expect( o.get( 'nothing.nothing' ) ).to.be( undefined ) ; | ||
``` | ||
.delete(). | ||
```js | ||
var o = Object.create( tree.path.prototype ) ; | ||
o.a = 5 ; | ||
o.sub = { | ||
b: "toto" , | ||
sub: { | ||
c: true , | ||
sub: { | ||
f: '' | ||
} | ||
} | ||
} ; | ||
o.d = null ; | ||
o.delete( 'a' ) ; | ||
o.delete( 'sub.sub' ) ; | ||
o.delete( 'non.existant.path' ) ; | ||
expect( o ).to.eql( { | ||
sub: { | ||
b: "toto" , | ||
} , | ||
d: null | ||
} ) ; | ||
``` | ||
.set(). | ||
```js | ||
var o = Object.create( tree.path.prototype ) ; | ||
o.a = 5 ; | ||
o.sub = { | ||
b: "toto" , | ||
sub: { | ||
c: true | ||
} | ||
} ; | ||
o.d = null ; | ||
o.set( 'a' , "8" ) ; | ||
o.set( 'sub.b' , false ) ; | ||
o.set( 'sub.sub' , { x: 18 , y: 27 } ) ; | ||
o.set( 'non.existant.path' , 'new' ) ; | ||
expect( o ).to.eql( { | ||
a: "8" , | ||
sub: { | ||
b: false , | ||
sub: { | ||
x: 18 , | ||
y: 27 | ||
} | ||
} , | ||
d: null , | ||
non: { | ||
existant: { | ||
path: 'new' | ||
} | ||
} | ||
} ) ; | ||
``` | ||
.define(). | ||
```js | ||
var o = Object.create( tree.path.prototype ) ; | ||
o.a = 5 ; | ||
o.sub = { | ||
b: "toto" , | ||
sub: { | ||
c: true | ||
} | ||
} ; | ||
o.d = null ; | ||
o.define( 'a' , "8" ) ; | ||
o.define( 'sub.b' , false ) ; | ||
o.define( 'unexistant' , '!' ) ; | ||
o.define( 'sub.sub' , { x: 18 , y: 27 } ) ; | ||
o.define( 'non.existant.path' , 'new' ) ; | ||
expect( o ).to.eql( { | ||
a: 5 , | ||
unexistant: '!' , | ||
sub: { | ||
b: "toto" , | ||
sub: { | ||
c: true | ||
} | ||
} , | ||
d: null , | ||
non: { | ||
existant: { | ||
path: 'new' | ||
} | ||
} | ||
} ) ; | ||
``` | ||
.inc() and .dec(). | ||
```js | ||
var o = Object.create( tree.path.prototype ) ; | ||
o.a = 5 ; | ||
o.sub = { | ||
b: 10 , | ||
sub: { | ||
c: true | ||
} | ||
} ; | ||
o.d = null ; | ||
o.inc( 'a' ) ; | ||
o.dec( 'sub.b' ) ; | ||
o.inc( 'sub' ) ; | ||
o.dec( 'sub.sub' ) ; | ||
o.inc( 'non.existant.path' ) ; | ||
o.dec( 'another.non.existant.path' ) ; | ||
expect( o ).to.eql( { | ||
a: 6 , | ||
sub: { | ||
b: 9 , | ||
sub: { | ||
c: true | ||
} | ||
} , | ||
d: null , | ||
non: { | ||
existant: { | ||
path: 1 | ||
} | ||
} , | ||
another: { | ||
non: { | ||
existant: { | ||
path: -1 | ||
} | ||
} | ||
} | ||
} ) ; | ||
``` | ||
<a name="trees-array-path-on-objects"></a> | ||
# Tree's array path on objects | ||
path.get() on object structure. | ||
```js | ||
var o = { | ||
a: 5 , | ||
sub: { | ||
b: "toto" , | ||
sub: { | ||
c: true | ||
} | ||
} , | ||
d: null | ||
} ; | ||
expect( tree.path.get( o , [ 'a' ] ) ).to.be( 5 ) ; | ||
expect( tree.path.get( o , [ 'sub' ] ) ).to.eql( { | ||
b: "toto" , | ||
sub: { | ||
c: true | ||
} | ||
} ) ; | ||
expect( tree.path.get( o , [ 'sub' , 'b' ] ) ).to.be( "toto" ) ; | ||
expect( tree.path.get( o , [ 'sub' , 'sub' ] ) ).to.eql( { c: true } ) ; | ||
expect( tree.path.get( o , [ 'sub' , 'sub' , 'c' ] ) ).to.be( true ) ; | ||
expect( tree.path.get( o , [ 'd' ] ) ).to.be( null ) ; | ||
expect( tree.path.get( o , [ 'nothing' ] ) ).to.be( undefined ) ; | ||
expect( tree.path.get( o , [ 'sub' , 'nothing' ] ) ).to.be( undefined ) ; | ||
expect( tree.path.get( o , [ 'nothing' , 'nothing' ] ) ).to.be( undefined ) ; | ||
``` | ||
path.delete() on object structure. | ||
```js | ||
var o = { | ||
a: 5 , | ||
sub: { | ||
b: "toto" , | ||
sub: { | ||
c: true , | ||
sub: { | ||
f: '' | ||
} | ||
} | ||
} , | ||
d: null | ||
} ; | ||
tree.path.delete( o , [ 'a' ] ) ; | ||
tree.path.delete( o , [ 'sub' , 'sub' ] ) ; | ||
tree.path.delete( o , [ 'non' , 'existant' , 'path' ] ) ; | ||
expect( o ).to.eql( { | ||
sub: { | ||
b: "toto" , | ||
} , | ||
d: null | ||
} ) ; | ||
``` | ||
path.set() on object structure. | ||
```js | ||
var o = { | ||
a: 5 , | ||
sub: { | ||
b: "toto" , | ||
sub: { | ||
c: true | ||
} | ||
} , | ||
d: null | ||
} ; | ||
tree.path.set( o , [ 'a' ] , "8" ) ; | ||
tree.path.set( o , [ 'sub' , 'b' ] , false ) ; | ||
tree.path.set( o , [ 'sub' , 'sub' ] , { x: 18 , y: 27 } ) ; | ||
tree.path.set( o , [ 'non' , 'existant' , 'path' ] , 'new' ) ; | ||
expect( o ).to.eql( { | ||
a: "8" , | ||
sub: { | ||
b: false , | ||
sub: { | ||
x: 18 , | ||
y: 27 | ||
} | ||
} , | ||
d: null , | ||
non: { | ||
existant: { | ||
path: 'new' | ||
} | ||
} | ||
} ) ; | ||
``` | ||
path.define() on object structure. | ||
```js | ||
var o = { | ||
a: 5 , | ||
sub: { | ||
b: "toto" , | ||
sub: { | ||
c: true | ||
} | ||
} , | ||
d: null | ||
} ; | ||
tree.path.define( o , [ 'a' ] , "8" ) ; | ||
tree.path.define( o , [ 'sub' , 'b' ] , false ) ; | ||
tree.path.define( o , [ 'unexistant' ] , '!' ) ; | ||
tree.path.define( o , [ 'sub' , 'sub' ] , { x: 18 , y: 27 } ) ; | ||
tree.path.define( o , [ 'non' , 'existant' , 'path' ] , 'new' ) ; | ||
expect( o ).to.eql( { | ||
a: 5 , | ||
unexistant: '!' , | ||
sub: { | ||
b: "toto" , | ||
sub: { | ||
c: true | ||
} | ||
} , | ||
d: null , | ||
non: { | ||
existant: { | ||
path: 'new' | ||
} | ||
} | ||
} ) ; | ||
``` | ||
path.inc() and path.dec() on object structure. | ||
```js | ||
var o = { | ||
a: 5 , | ||
sub: { | ||
b: 10 , | ||
sub: { | ||
c: true | ||
} | ||
} , | ||
d: null | ||
} ; | ||
tree.path.inc( o , [ 'a' ] ) ; | ||
tree.path.dec( o , [ 'sub' , 'b' ] ) ; | ||
tree.path.inc( o , [ 'sub' ] ) ; | ||
tree.path.dec( o , [ 'sub' , 'sub' ] ) ; | ||
tree.path.inc( o , [ 'non' , 'existant' , 'path' ] ) ; | ||
tree.path.dec( o , [ 'another' , 'non' , 'existant' , 'path' ] ) ; | ||
expect( o ).to.eql( { | ||
a: 6 , | ||
sub: { | ||
b: 9 , | ||
sub: { | ||
c: true | ||
} | ||
} , | ||
d: null , | ||
non: { | ||
existant: { | ||
path: 1 | ||
} | ||
} , | ||
another: { | ||
non: { | ||
existant: { | ||
path: -1 | ||
} | ||
} | ||
} | ||
} ) ; | ||
``` | ||
@@ -0,3 +1,26 @@ | ||
/* | ||
Tree Kit | ||
Copyright (c) 2014 - 2018 Cédric Ronvel | ||
The MIT License (MIT) | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. | ||
*/ | ||
var i2 = 0 , d = 0 , o = {} ; | ||
@@ -4,0 +27,0 @@ module.exports = o ; |
@@ -0,3 +1,26 @@ | ||
/* | ||
Tree Kit | ||
Copyright (c) 2014 - 2018 Cédric Ronvel | ||
The MIT License (MIT) | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. | ||
*/ | ||
var i , j , l , k , v , o = {} ; | ||
@@ -4,0 +27,0 @@ module.exports = o ; |
@@ -0,3 +1,26 @@ | ||
/* | ||
Tree Kit | ||
Copyright (c) 2014 - 2018 Cédric Ronvel | ||
The MIT License (MIT) | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. | ||
*/ | ||
var i , j , l , k , v , o = {} ; | ||
@@ -4,0 +27,0 @@ module.exports = o ; |
@@ -0,3 +1,26 @@ | ||
/* | ||
Tree Kit | ||
Copyright (c) 2014 - 2018 Cédric Ronvel | ||
The MIT License (MIT) | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. | ||
*/ | ||
var i , j , l , k , v , o = {} ; | ||
@@ -4,0 +27,0 @@ module.exports = o ; |
/* | ||
Tree Kit | ||
Copyright (c) 2014 - 2016 Cédric Ronvel | ||
Copyright (c) 2014 - 2018 Cédric Ronvel | ||
The MIT License (MIT) | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
@@ -14,6 +14,6 @@ of this software and associated documentation files (the "Software"), to deal | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
@@ -28,5 +28,2 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
/* jshint unused:false */ | ||
/* global describe, it, before, after */ | ||
"use strict" ; | ||
@@ -37,3 +34,2 @@ | ||
var tree = require( '../lib/tree.js' ) ; | ||
var expect = require( 'expect.js' ) ; | ||
@@ -85,16 +81,16 @@ | ||
expect( Object.getOwnPropertyNames( r ) ).to.eql( [ 'own1' , 'own2' , 'nested' , 'nonEnum1' , 'nonEnum2' , 'nonEnum3' , 'nonEnumNested' , 'getter' , 'getterAndSetter' ] ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'own1' ) ).to.eql( { value: 'own1' , enumerable: true , writable: true , configurable: true } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'own2' ) ).to.eql( { value: 'own2' , enumerable: true , writable: true , configurable: true } ) ; | ||
expect( Object.getOwnPropertyNames( r ) ).to.equal( [ 'own1' , 'own2' , 'nested' , 'nonEnum1' , 'nonEnum2' , 'nonEnum3' , 'nonEnumNested' , 'getter' , 'getterAndSetter' ] ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'own1' ) ).to.equal( { value: 'own1' , enumerable: true , writable: true , configurable: true } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'own2' ) ).to.equal( { value: 'own2' , enumerable: true , writable: true , configurable: true } ) ; | ||
expect( r.nested ).not.to.be( o.nested ) ; | ||
expect( r.nested ).to.eql( o.nested ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nested' ) ).to.eql( { value: o.nested , enumerable: true , writable: true , configurable: true } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnum1' ) ).to.eql( { value: 'nonEnum1' , enumerable: false , writable: false , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnum2' ) ).to.eql( { value: 'nonEnum2' , enumerable: false , writable: true , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnum3' ) ).to.eql( { value: 'nonEnum3' , enumerable: false , writable: false , configurable: true } ) ; | ||
expect( r.nested ).to.equal( o.nested ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nested' ) ).to.equal( { value: o.nested , enumerable: true , writable: true , configurable: true } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnum1' ) ).to.equal( { value: 'nonEnum1' , enumerable: false , writable: false , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnum2' ) ).to.equal( { value: 'nonEnum2' , enumerable: false , writable: true , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnum3' ) ).to.equal( { value: 'nonEnum3' , enumerable: false , writable: false , configurable: true } ) ; | ||
expect( r.nonEnumNested ).not.to.be( o.nonEnumNested ) ; | ||
expect( r.nonEnumNested ).to.eql( o.nonEnumNested ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnumNested' ) ).to.eql( { value: o.nonEnumNested , enumerable: false , writable: false , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'getter' ) ).to.eql( { get: getter , set: undefined , enumerable: false , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'getterAndSetter' ) ).to.eql( { get: getter , set: setter , enumerable: false , configurable: false } ) ; | ||
expect( r.nonEnumNested ).to.equal( o.nonEnumNested ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnumNested' ) ).to.equal( { value: o.nonEnumNested , enumerable: false , writable: false , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'getter' ) ).to.equal( { get: getter , set: undefined , enumerable: false , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'getterAndSetter' ) ).to.equal( { get: getter , set: setter , enumerable: false , configurable: false } ) ; | ||
@@ -143,3 +139,3 @@ expect( r.__proto__ ).to.equal( proto ) ; // jshint ignore:line | ||
c = tree.clone( a ) ; | ||
expect( c ).to.eql( a ) ; | ||
expect( c ).to.equal( a ) ; | ||
expect( Array.isArray( c ) ).to.be.ok() ; | ||
@@ -149,3 +145,3 @@ | ||
c = tree.clone( a ) ; | ||
expect( c ).to.eql( a ) ; | ||
expect( c ).to.equal( a ) ; | ||
expect( Array.isArray( c ) ).to.be.ok() ; | ||
@@ -152,0 +148,0 @@ expect( Array.isArray( c[ 1 ] ) ).to.be.ok() ; |
/* | ||
Tree Kit | ||
Copyright (c) 2014 - 2016 Cédric Ronvel | ||
Copyright (c) 2014 - 2018 Cédric Ronvel | ||
The MIT License (MIT) | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
@@ -14,6 +14,6 @@ of this software and associated documentation files (the "Software"), to deal | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
@@ -28,5 +28,2 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
/* jshint unused:false */ | ||
/* global describe, it, before, after */ | ||
"use strict" ; | ||
@@ -37,3 +34,2 @@ | ||
var tree = require( '../lib/tree.js' ) ; | ||
var expect = require( 'expect.js' ) ; | ||
@@ -67,3 +63,3 @@ | ||
expect( diff ).not.to.be( null ) ; | ||
expect( diff ).to.only.have.keys( '.a', '.c', '.d' ) ; | ||
expect( diff ).to.only.have.own.keys( '.a', '.c', '.d' ) ; | ||
} ) ; | ||
@@ -110,3 +106,3 @@ | ||
expect( diff ).not.to.be( null ) ; | ||
expect( diff ).to.only.have.keys( '.a', '.c', '.d', '.sub.f', '.sub.subsub.h', '.sub.subsub.i', '.suba', '.subb' ) ; | ||
expect( diff ).to.only.have.own.keys( '.a', '.c', '.d', '.sub.f', '.sub.subsub.h', '.sub.subsub.i', '.suba', '.subb' ) ; | ||
} ) ; | ||
@@ -113,0 +109,0 @@ } ) ; |
/* | ||
Tree Kit | ||
Copyright (c) 2014 - 2016 Cédric Ronvel | ||
Copyright (c) 2014 - 2018 Cédric Ronvel | ||
The MIT License (MIT) | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
@@ -14,6 +14,6 @@ of this software and associated documentation files (the "Software"), to deal | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
@@ -28,5 +28,2 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
/* jshint unused:false */ | ||
/* global describe, it, before, after */ | ||
"use strict" ; | ||
@@ -37,3 +34,2 @@ | ||
var extend = require( '../lib/extend.js' ) ; | ||
var expect = require( 'expect.js' ) ; | ||
@@ -175,5 +171,4 @@ | ||
var copy = extend( null , {} , input.subtree ) ; | ||
expect( copy ).to.eql( input.subtree ) ; | ||
expect( copy ).not.to.equal( input.subtree ) ; | ||
expect( copy.subtree2 ).to.equal( input.subtree.subtree2 ) ; | ||
expect( copy ).to.be.a.shallow.clone.of( input.subtree ) ; | ||
expect( copy ).to.equal( input.subtree ) ; | ||
} ) ; | ||
@@ -183,5 +178,5 @@ | ||
var copy = extend( { deep: true } , {} , input.subtree ) ; | ||
expect( copy ).to.eql( input.subtree ) ; | ||
expect( copy ).not.to.equal( input.subtree ) ; | ||
expect( copy.subtree2 ).not.to.equal( input.subtree.subtree2 ) ; | ||
expect( copy ).to.equal( input.subtree ) ; | ||
expect( copy ).not.to.be.a.shallow.clone.of( input.subtree ) ; | ||
expect( copy.subtree2 ).not.to.be.a.shallow.clone.of( input.subtree.subtree2 ) ; | ||
} ) ; | ||
@@ -192,5 +187,4 @@ | ||
//console.log( copy ) ; | ||
expect( copy ).to.eql( input.subtreeWithFunction ) ; | ||
expect( copy ).not.to.equal( input.subtreeWithFunction ) ; | ||
expect( copy.Func.prototype ).to.equal( input.subtreeWithFunction.Func.prototype ) ; | ||
expect( copy ).to.equal( input.subtreeWithFunction ) ; | ||
expect( copy.Func.prototype ).to.be( input.subtreeWithFunction.Func.prototype ) ; | ||
} ) ; | ||
@@ -200,4 +194,4 @@ | ||
var copy = extend( { deep: true, deepFunc: true } , {} , input.subtreeWithFunction ) ; | ||
expect( copy ).not.to.eql( input.subtreeWithFunction ) ; | ||
expect( copy ).to.eql( { z: 'Zee' , Func: { prop: 'property' } } ) ; | ||
expect( copy ).not.to.equal( input.subtreeWithFunction ) ; | ||
expect( copy ).to.equal( { z: 'Zee' , Func: { prop: 'property' } } ) ; | ||
} ) ; | ||
@@ -217,3 +211,3 @@ | ||
expect( extend( null , {} , o ) ).to.eql( { | ||
expect( extend( null , {} , o ) ).to.equal( { | ||
proto1: 'proto1' , | ||
@@ -225,3 +219,3 @@ proto2: 'proto2' , | ||
expect( extend( { deep: true } , {} , o ) ).to.eql( { | ||
expect( extend( { deep: true } , {} , o ) ).to.equal( { | ||
proto1: 'proto1' , | ||
@@ -251,3 +245,3 @@ proto2: 'proto2' , | ||
expect( extend( { own: true } , {} , o ) ).to.eql( { | ||
expect( extend( { own: true } , {} , o ) ).to.equal( { | ||
own1: 'own1' , | ||
@@ -257,3 +251,3 @@ own2: 'own2' | ||
expect( extend( { deep: true, own: true } , {} , o ) ).to.eql( { | ||
expect( extend( { deep: true, own: true } , {} , o ) ).to.equal( { | ||
own1: 'own1' , | ||
@@ -281,3 +275,3 @@ own2: 'own2' | ||
expect( extend( { own: true , nonEnum: true } , {} , o ) ).to.eql( { | ||
expect( extend( { own: true , nonEnum: true } , {} , o ) ).to.equal( { | ||
own1: 'own1' , | ||
@@ -289,3 +283,3 @@ own2: 'own2' , | ||
expect( extend( { deep: true, own: true , nonEnum: true } , {} , o ) ).to.eql( { | ||
expect( extend( { deep: true, own: true , nonEnum: true } , {} , o ) ).to.equal( { | ||
own1: 'own1' , | ||
@@ -328,31 +322,31 @@ own2: 'own2' , | ||
expect( Object.getOwnPropertyNames( r ) ).to.eql( [ 'own1' , 'own2' , 'nested' , 'nonEnum1' , 'nonEnum2' , 'nonEnum3' , 'nonEnumNested' , 'getter' , 'getterAndSetter' ] ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'own1' ) ).to.eql( { value: 'own1' , enumerable: true , writable: true , configurable: true } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'own2' ) ).to.eql( { value: 'own2' , enumerable: true , writable: true , configurable: true } ) ; | ||
expect( Object.getOwnPropertyNames( r ) ).to.equal( [ 'own1' , 'own2' , 'nested' , 'nonEnum1' , 'nonEnum2' , 'nonEnum3' , 'nonEnumNested' , 'getter' , 'getterAndSetter' ] ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'own1' ) ).to.equal( { value: 'own1' , enumerable: true , writable: true , configurable: true } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'own2' ) ).to.equal( { value: 'own2' , enumerable: true , writable: true , configurable: true } ) ; | ||
expect( r.nested ).to.be( o.nested ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nested' ) ).to.eql( { value: o.nested , enumerable: true , writable: true , configurable: true } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnum1' ) ).to.eql( { value: 'nonEnum1' , enumerable: false , writable: false , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnum2' ) ).to.eql( { value: 'nonEnum2' , enumerable: false , writable: true , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnum3' ) ).to.eql( { value: 'nonEnum3' , enumerable: false , writable: false , configurable: true } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nested' ) ).to.equal( { value: o.nested , enumerable: true , writable: true , configurable: true } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnum1' ) ).to.equal( { value: 'nonEnum1' , enumerable: false , writable: false , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnum2' ) ).to.equal( { value: 'nonEnum2' , enumerable: false , writable: true , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnum3' ) ).to.equal( { value: 'nonEnum3' , enumerable: false , writable: false , configurable: true } ) ; | ||
expect( r.nonEnumNested ).to.be( o.nonEnumNested ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnumNested' ) ).to.eql( { value: o.nonEnumNested , enumerable: false , writable: false , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'getter' ) ).to.eql( { get: getter , set: undefined , enumerable: false , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'getterAndSetter' ) ).to.eql( { get: getter , set: setter , enumerable: false , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnumNested' ) ).to.equal( { value: o.nonEnumNested , enumerable: false , writable: false , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'getter' ) ).to.equal( { get: getter , set: undefined , enumerable: false , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'getterAndSetter' ) ).to.equal( { get: getter , set: setter , enumerable: false , configurable: false } ) ; | ||
r = extend( { deep: true , own: true , nonEnum: true , descriptor: true } , {} , o ) ; | ||
expect( Object.getOwnPropertyNames( r ) ).to.eql( [ 'own1' , 'own2' , 'nested' , 'nonEnum1' , 'nonEnum2' , 'nonEnum3' , 'nonEnumNested' , 'getter' , 'getterAndSetter' ] ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'own1' ) ).to.eql( { value: 'own1' , enumerable: true , writable: true , configurable: true } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'own2' ) ).to.eql( { value: 'own2' , enumerable: true , writable: true , configurable: true } ) ; | ||
expect( Object.getOwnPropertyNames( r ) ).to.equal( [ 'own1' , 'own2' , 'nested' , 'nonEnum1' , 'nonEnum2' , 'nonEnum3' , 'nonEnumNested' , 'getter' , 'getterAndSetter' ] ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'own1' ) ).to.equal( { value: 'own1' , enumerable: true , writable: true , configurable: true } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'own2' ) ).to.equal( { value: 'own2' , enumerable: true , writable: true , configurable: true } ) ; | ||
expect( r.nested ).not.to.be( o.nested ) ; | ||
expect( r.nested ).to.eql( o.nested ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nested' ) ).to.eql( { value: o.nested , enumerable: true , writable: true , configurable: true } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnum1' ) ).to.eql( { value: 'nonEnum1' , enumerable: false , writable: false , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnum2' ) ).to.eql( { value: 'nonEnum2' , enumerable: false , writable: true , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnum3' ) ).to.eql( { value: 'nonEnum3' , enumerable: false , writable: false , configurable: true } ) ; | ||
expect( r.nested ).to.equal( o.nested ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nested' ) ).to.equal( { value: o.nested , enumerable: true , writable: true , configurable: true } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnum1' ) ).to.equal( { value: 'nonEnum1' , enumerable: false , writable: false , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnum2' ) ).to.equal( { value: 'nonEnum2' , enumerable: false , writable: true , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnum3' ) ).to.equal( { value: 'nonEnum3' , enumerable: false , writable: false , configurable: true } ) ; | ||
expect( r.nonEnumNested ).not.to.be( o.nonEnumNested ) ; | ||
expect( r.nonEnumNested ).to.eql( o.nonEnumNested ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnumNested' ) ).to.eql( { value: o.nonEnumNested , enumerable: false , writable: false , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'getter' ) ).to.eql( { get: getter , set: undefined , enumerable: false , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'getterAndSetter' ) ).to.eql( { get: getter , set: setter , enumerable: false , configurable: false } ) ; | ||
expect( r.nonEnumNested ).to.equal( o.nonEnumNested ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'nonEnumNested' ) ).to.equal( { value: o.nonEnumNested , enumerable: false , writable: false , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'getter' ) ).to.equal( { get: getter , set: undefined , enumerable: false , configurable: false } ) ; | ||
expect( Object.getOwnPropertyDescriptor( r , 'getterAndSetter' ) ).to.equal( { get: getter , set: setter , enumerable: false , configurable: false } ) ; | ||
} ) ; | ||
@@ -365,3 +359,3 @@ | ||
copy = extend( { deep: true } , {} , input.subtree ) ; | ||
expect( extend( null , copy , input.anotherSubtree ) ).to.eql( { | ||
expect( extend( null , copy , input.anotherSubtree ) ).to.equal( { | ||
a : 'A' , | ||
@@ -386,3 +380,3 @@ b : 2 , | ||
copy = extend( { deep: true } , {} , input.subtree ) ; | ||
expect( extend( { deep: true } , copy , input.anotherSubtree ) ).to.eql( { | ||
expect( extend( { deep: true } , copy , input.anotherSubtree ) ).to.equal( { | ||
a : 'A' , | ||
@@ -430,7 +424,7 @@ b : 2 , | ||
expect( e ).not.to.be( o ) ; | ||
expect( e.__proto__ ).to.equal( proto ) ; // jshint ignore:line | ||
expect( e ).to.eql( { own1: 'own1' , own2: 'own2' } ) ; | ||
expect( e.__proto__ ).to.be( proto ) ; | ||
expect( e ).to.be.like( { own1: 'own1' , own2: 'own2' } ) ; | ||
expect( e.proto1 ).to.be( 'proto1' ) ; | ||
expect( e.proto2 ).to.be( 'proto2' ) ; | ||
expect( typeof e.hello ).to.equal( 'function' ) ; | ||
expect( e.hello ).to.be.a( 'function' ) ; | ||
} ) ; | ||
@@ -461,4 +455,4 @@ | ||
expect( e ).not.to.be( o ) ; | ||
expect( e ).to.eql( { | ||
expect( e ).to.be.a.shallow.clone.of( o ) ; | ||
expect( e ).to.be.like( { | ||
own1: 'own1' , | ||
@@ -473,4 +467,4 @@ own2: 'own2' , | ||
expect( e.embed2.proto2 ).to.be( 'proto2' ) ; | ||
expect( typeof e.embed1.hello ).to.equal( 'function' ) ; | ||
expect( typeof e.embed2.world ).to.equal( 'function' ) ; | ||
expect( e.embed1.hello ).to.be.a( 'function' ) ; | ||
expect( e.embed2.world ).to.be.a( 'function' ) ; | ||
@@ -481,3 +475,3 @@ | ||
expect( e ).not.to.be( o ) ; | ||
expect( e ).to.eql( { | ||
expect( e ).to.be.like( { | ||
own1: 'own1' , | ||
@@ -492,4 +486,4 @@ own2: 'own2' , | ||
expect( e.embed2.proto2 ).to.be( 'proto2' ) ; | ||
expect( typeof e.embed1.hello ).to.equal( 'function' ) ; | ||
expect( typeof e.embed2.world ).to.equal( 'function' ) ; | ||
expect( e.embed1.hello ).to.be.a( 'function' ) ; | ||
expect( e.embed2.world ).to.be.a( 'function' ) ; | ||
} ) ; | ||
@@ -515,3 +509,3 @@ | ||
expect( e ).not.to.be( o ) ; | ||
expect( e ).to.eql( { own1: 'own1' , own2: 'own2' , proto1: 'proto1' , proto2: 'proto2' } ) ; | ||
expect( e ).to.be.like( { own1: 'own1' , own2: 'own2' , proto1: 'proto1' , proto2: 'proto2' } ) ; | ||
@@ -521,3 +515,3 @@ // with 'own' | ||
expect( e ).not.to.be( o ) ; | ||
expect( e ).to.eql( { own1: 'own1' , own2: 'own2' } ) ; | ||
expect( e ).to.be.like( { own1: 'own1' , own2: 'own2' } ) ; | ||
@@ -527,7 +521,7 @@ // with 'proto', function exists if there are in the prototype | ||
expect( e ).not.to.be( o ) ; | ||
expect( e.__proto__ ).to.equal( proto ) ; // jshint ignore:line | ||
expect( e ).to.eql( { own1: 'own1' , own2: 'own2' } ) ; | ||
expect( e.__proto__ ).to.be( proto ) ; | ||
expect( e ).to.be.like( { own1: 'own1' , own2: 'own2' } ) ; | ||
expect( e.proto1 ).to.be( 'proto1' ) ; | ||
expect( e.proto2 ).to.be( 'proto2' ) ; | ||
expect( typeof e.hello ).to.equal( 'function' ) ; | ||
expect( e.hello ).to.be.a( 'function' ) ; | ||
} ) ; | ||
@@ -551,4 +545,4 @@ | ||
extend( { preserve: true } , e , o ) ; | ||
expect( e ).to.eql( { one: '1' , two: 2 , three: 'THREE' , four: '4' } ) ; | ||
expect( o ).to.eql( { three: 3 , four: '4' } ) ; | ||
expect( e ).to.equal( { one: '1' , two: 2 , three: 'THREE' , four: '4' } ) ; | ||
expect( o ).to.equal( { three: 3 , four: '4' } ) ; | ||
} ) ; | ||
@@ -572,4 +566,4 @@ | ||
extend( { move: true } , e , o ) ; | ||
expect( e ).to.eql( { one: '1' , two: 2 , three: 3 , four: '4' } ) ; | ||
expect( o ).to.eql( {} ) ; | ||
expect( e ).to.equal( { one: '1' , two: 2 , three: 3 , four: '4' } ) ; | ||
expect( o ).to.equal( {} ) ; | ||
} ) ; | ||
@@ -593,4 +587,4 @@ | ||
extend( { preserve: true , move: true } , e , o ) ; | ||
expect( e ).to.eql( { one: '1' , two: 2 , three: 'THREE' , four: '4' } ) ; | ||
expect( o ).to.eql( { three: 3 } ) ; | ||
expect( e ).to.equal( { one: '1' , two: 2 , three: 'THREE' , four: '4' } ) ; | ||
expect( o ).to.equal( { three: 3 } ) ; | ||
} ) ; | ||
@@ -615,7 +609,7 @@ | ||
expect( e.__proto__ ).to.equal( o ) ; // jshint ignore:line | ||
expect( e ).to.eql( {} ) ; | ||
expect( e.__proto__ ).to.be( o ) ; | ||
expect( e ).to.be.like( {} ) ; | ||
expect( e.three ).to.be( 3 ) ; | ||
expect( e.four ).to.be( '4' ) ; | ||
expect( e.subtree ).to.equal( o.subtree ) ; | ||
expect( e.subtree ).to.be.a.shallow.clone.of( o.subtree ) ; | ||
@@ -631,8 +625,8 @@ | ||
expect( e.__proto__ ).to.equal( o ) ; // jshint ignore:line | ||
expect( e ).to.eql( { one: '1' , two: 2 , three: 'THREE' } ) ; | ||
expect( e.__proto__ ).to.be( o ) ; | ||
expect( e ).to.be.like( { one: '1' , two: 2 , three: 'THREE' } ) ; | ||
expect( e.three ).to.be( 'THREE' ) ; | ||
expect( e.four ).to.be( '4' ) ; | ||
expect( e.subtree ).to.equal( o.subtree ) ; // jshint ignore:line | ||
expect( e.subtree ).to.eql( { five: 'FIVE' , six: 6 } ) ; | ||
expect( e.subtree ).to.be.a.shallow.clone.of( o.subtree ) ; | ||
expect( e.subtree ).to.be.like( { five: 'FIVE' , six: 6 } ) ; | ||
@@ -652,8 +646,8 @@ | ||
expect( e.__proto__ ).to.equal( o ) ; // jshint ignore:line | ||
expect( e ).to.eql( { one: '1' , two: 2 , three: 'THREE' , subtree: { six: 'SIX' , seven: 7 } } ) ; | ||
expect( e.__proto__ ).to.be( o ) ; | ||
expect( e ).to.be.like( { one: '1' , two: 2 , three: 'THREE' , subtree: { six: 'SIX' , seven: 7 } } ) ; | ||
expect( e.three ).to.be( 'THREE' ) ; | ||
expect( e.four ).to.be( '4' ) ; | ||
expect( e.subtree ).to.eql( { six: 'SIX' , seven: 7 } ) ; | ||
expect( e.subtree.five ).to.equal( undefined ) ; | ||
expect( e.subtree ).to.be.like( { six: 'SIX' , seven: 7 } ) ; | ||
expect( e.subtree.five ).to.be( undefined ) ; | ||
} ) ; | ||
@@ -678,9 +672,9 @@ | ||
expect( e.__proto__ ).to.equal( o ) ; // jshint ignore:line | ||
expect( e ).to.eql( { subtree: {} } ) ; | ||
expect( e.__proto__ ).to.be( o ) ; | ||
expect( e ).to.be.like( { subtree: {} } ) ; | ||
expect( e.three ).to.be( 3 ) ; | ||
expect( e.four ).to.be( '4' ) ; | ||
expect( e.subtree.__proto__ ).to.equal( o.subtree ) ; // jshint ignore:line | ||
expect( e.subtree.five ).to.equal( 'FIVE' ) ; | ||
expect( e.subtree.six ).to.equal( 6 ) ; | ||
expect( e.subtree.__proto__ ).to.be( o.subtree ) ; | ||
expect( e.subtree.five ).to.be( 'FIVE' ) ; | ||
expect( e.subtree.six ).to.be( 6 ) ; | ||
@@ -696,10 +690,10 @@ | ||
expect( e.__proto__ ).to.equal( o ) ; // jshint ignore:line | ||
expect( e ).to.eql( { one: '1' , two: 2 , three: 'THREE' , subtree: {} } ) ; | ||
expect( e.__proto__ ).to.be( o ) ; | ||
expect( e ).to.be.like( { one: '1' , two: 2 , three: 'THREE' , subtree: {} } ) ; | ||
expect( e.three ).to.be( 'THREE' ) ; | ||
expect( e.four ).to.be( '4' ) ; | ||
expect( e.subtree.__proto__ ).to.equal( o.subtree ) ; // jshint ignore:line | ||
expect( e.subtree ).to.eql( {} ) ; | ||
expect( e.subtree.five ).to.equal( 'FIVE' ) ; | ||
expect( e.subtree.six ).to.equal( 6 ) ; | ||
expect( e.subtree.__proto__ ).to.be( o.subtree ) ; | ||
expect( e.subtree ).to.be.like( {} ) ; | ||
expect( e.subtree.five ).to.be( 'FIVE' ) ; | ||
expect( e.subtree.six ).to.be( 6 ) ; | ||
@@ -719,9 +713,9 @@ | ||
expect( e.__proto__ ).to.equal( o ) ; // jshint ignore:line | ||
expect( e ).to.eql( { one: '1' , two: 2 , three: 'THREE' , subtree: { six: 'SIX' , seven: 7 } } ) ; | ||
expect( e.__proto__ ).to.be( o ) ; | ||
expect( e ).to.be.like( { one: '1' , two: 2 , three: 'THREE' , subtree: { six: 'SIX' , seven: 7 } } ) ; | ||
expect( e.three ).to.be( 'THREE' ) ; | ||
expect( e.four ).to.be( '4' ) ; | ||
expect( e.subtree.__proto__ ).to.equal( o.subtree ) ; // jshint ignore:line | ||
expect( e.subtree ).to.eql( { six: 'SIX' , seven: 7 } ) ; | ||
expect( e.subtree.five ).to.equal( 'FIVE' ) ; | ||
expect( e.subtree.__proto__ ).to.be( o.subtree ) ; | ||
expect( e.subtree ).to.be.like( { six: 'SIX' , seven: 7 } ) ; | ||
expect( e.subtree.five ).to.be( 'FIVE' ) ; | ||
} ) ; | ||
@@ -752,3 +746,3 @@ | ||
e = extend( { flat: true } , {} , o ) ; | ||
expect( e ).to.eql( { | ||
expect( e ).to.equal( { | ||
three: 3 , | ||
@@ -765,3 +759,3 @@ four: '4' , | ||
e = extend( { flat: '/' } , {} , o ) ; | ||
expect( e ).to.eql( { | ||
expect( e ).to.equal( { | ||
three: 3 , | ||
@@ -794,3 +788,3 @@ four: '4' , | ||
e = extend( { unflat: true } , {} , o ) ; | ||
expect( e ).to.eql( { | ||
expect( e ).to.equal( { | ||
three: 3 , | ||
@@ -824,3 +818,3 @@ four: '4' , | ||
e = extend( { unflat: '/' } , {} , o ) ; | ||
expect( e ).to.eql( { | ||
expect( e ).to.equal( { | ||
three: 3 , | ||
@@ -865,3 +859,3 @@ four: '4' , | ||
expect( e ).to.eql( { | ||
expect( e ).to.equal( { | ||
one: '1' , | ||
@@ -899,3 +893,3 @@ buf: buf , | ||
expect( e ).to.eql( { | ||
expect( e ).to.equal( { | ||
one: '1' , | ||
@@ -902,0 +896,0 @@ buf: buf , |
/* | ||
Tree Kit | ||
Copyright (c) 2014 - 2016 Cédric Ronvel | ||
Copyright (c) 2014 - 2018 Cédric Ronvel | ||
The MIT License (MIT) | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
@@ -14,6 +14,6 @@ of this software and associated documentation files (the "Software"), to deal | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
@@ -28,5 +28,2 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
/* jshint unused:false */ | ||
/* global describe, it, before, after */ | ||
"use strict" ; | ||
@@ -37,3 +34,5 @@ | ||
var tree = require( '../lib/tree.js' ) ; | ||
var expect = require( 'expect.js' ) ; | ||
/* Tests */ | ||
@@ -59,3 +58,3 @@ | ||
expect( counter ).to.be( 1 ) ; | ||
expect( function() { object.myprop ++ ; } ).to.throwError() ; | ||
expect( function() { object.myprop ++ ; } ).to.throw() ; | ||
expect( object.myprop ).to.be( 1 ) ; | ||
@@ -62,0 +61,0 @@ } ) ; |
/* | ||
Tree Kit | ||
Copyright (c) 2014 - 2016 Cédric Ronvel | ||
Copyright (c) 2014 - 2018 Cédric Ronvel | ||
The MIT License (MIT) | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
@@ -14,6 +14,6 @@ of this software and associated documentation files (the "Software"), to deal | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
@@ -28,5 +28,2 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
/* jshint unused:false */ | ||
/* global describe, it, before, after */ | ||
"use strict" ; | ||
@@ -37,3 +34,2 @@ | ||
var tree = require( '../lib/tree.js' ) ; | ||
var expect = require( 'expect.js' ) ; | ||
@@ -40,0 +36,0 @@ |
/* | ||
Tree Kit | ||
Copyright (c) 2014 - 2016 Cédric Ronvel | ||
Copyright (c) 2014 - 2018 Cédric Ronvel | ||
The MIT License (MIT) | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
@@ -14,6 +14,6 @@ of this software and associated documentation files (the "Software"), to deal | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
@@ -28,5 +28,2 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
/* jshint unused:false */ | ||
/* global describe, it, before, after */ | ||
"use strict" ; | ||
@@ -37,3 +34,2 @@ | ||
var tree = require( '../lib/tree.js' ) ; | ||
var expect = require( 'expect.js' ) ; | ||
@@ -79,2 +75,21 @@ | ||
/* | ||
it( "bracket notation on object" , function() { | ||
var o = { | ||
a: 5 , | ||
sub: { | ||
b: "toto" , | ||
sub: { | ||
c: true | ||
} | ||
} , | ||
d: null | ||
} ; | ||
expect( tree.path.get( o , '[a]' ) ).to.be( 5 ) ; | ||
expect( tree.path.get( o , '[sub][sub][c]' ) ).to.be( true ) ; | ||
} ) ; | ||
*/ | ||
it( "path.delete() on object structure" , function() { | ||
@@ -615,3 +630,3 @@ | ||
expect( o ).to.eql( { | ||
expect( o ).to.be.like( { | ||
sub: { | ||
@@ -643,3 +658,3 @@ b: "toto" , | ||
expect( o ).to.eql( { | ||
expect( o ).to.be.like( { | ||
a: "8" , | ||
@@ -682,3 +697,3 @@ sub: { | ||
expect( o ).to.eql( { | ||
expect( o ).to.be.like( { | ||
a: 5 , | ||
@@ -721,3 +736,3 @@ unexistant: '!' , | ||
expect( o ).to.eql( { | ||
expect( o ).to.be.like( { | ||
a: 6 , | ||
@@ -766,3 +781,3 @@ sub: { | ||
expect( tree.path.get( o , [ 'a' ] ) ).to.be( 5 ) ; | ||
expect( tree.path.get( o , [ 'sub' ] ) ).to.eql( { | ||
expect( tree.path.get( o , [ 'sub' ] ) ).to.be.like( { | ||
b: "toto" , | ||
@@ -775,3 +790,3 @@ sub: { | ||
expect( tree.path.get( o , [ 'sub' , 'b' ] ) ).to.be( "toto" ) ; | ||
expect( tree.path.get( o , [ 'sub' , 'sub' ] ) ).to.eql( { c: true } ) ; | ||
expect( tree.path.get( o , [ 'sub' , 'sub' ] ) ).to.be.like( { c: true } ) ; | ||
expect( tree.path.get( o , [ 'sub' , 'sub' , 'c' ] ) ).to.be( true ) ; | ||
@@ -804,3 +819,3 @@ expect( tree.path.get( o , [ 'd' ] ) ).to.be( null ) ; | ||
expect( o ).to.eql( { | ||
expect( o ).to.be.like( { | ||
sub: { | ||
@@ -832,3 +847,3 @@ b: "toto" , | ||
expect( o ).to.eql( { | ||
expect( o ).to.be.like( { | ||
a: "8" , | ||
@@ -871,3 +886,3 @@ sub: { | ||
expect( o ).to.eql( { | ||
expect( o ).to.be.like( { | ||
a: 5 , | ||
@@ -910,3 +925,3 @@ unexistant: '!' , | ||
expect( o ).to.eql( { | ||
expect( o ).to.be.like( { | ||
a: 6 , | ||
@@ -913,0 +928,0 @@ sub: { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2
187772
34
268