From a63f559c50d70e8cb2eaae670dec25d1dbc4afcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Ronvel?= Date: Tue, 2 Mar 2021 14:46:10 +0100 Subject: [PATCH] BREAKING CHANGE -- .path()/.dotPath(): drop the function's subtree support, fix prototype pollution --- CHANGELOG | 6 + browser/tree-kit.js | 354 ++++++++++++++++++++++++++++++++++++++-- browser/tree-kit.min.js | 2 +- package.json | 2 +- 4 files changed, 344 insertions(+), 20 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index d10a10c..0dd6de4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,10 @@ +v0.7.0 +------ + +BREAKING CHANGE -- .path()/.dotPath(): drop the function's subtree support, fix prototype pollution + + v0.6.2 ------ diff --git a/browser/tree-kit.js b/browser/tree-kit.js index 3b758c5..0593995 100644 --- a/browser/tree-kit.js +++ b/browser/tree-kit.js @@ -2,7 +2,7 @@ /* Tree Kit - Copyright (c) 2014 - 2019 Cédric Ronvel + Copyright (c) 2014 - 2021 Cédric Ronvel The MIT License (MIT) @@ -31,19 +31,22 @@ // Browser only get the essential of tree-kit, not the unfinished parts of it -var tree = {} ; +const tree = {} ; module.exports = tree ; + tree.extend = require( './extend.js' ) ; tree.clone = require( './clone.js' ) ; tree.path = require( './path.js' ) ; +tree.dotPath = require( './dotPath.js' ) ; + -},{"./clone.js":2,"./extend.js":3,"./path.js":4}],2:[function(require,module,exports){ +},{"./clone.js":2,"./dotPath.js":3,"./extend.js":4,"./path.js":5}],2:[function(require,module,exports){ /* Tree Kit - Copyright (c) 2014 - 2019 Cédric Ronvel + Copyright (c) 2014 - 2021 Cédric Ronvel The MIT License (MIT) @@ -152,7 +155,312 @@ clone.opaque.set( Date.prototype , src => new Date( src ) ) ; /* Tree Kit - Copyright (c) 2014 - 2019 Cédric Ronvel + Copyright (c) 2014 - 2021 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. +*/ + +"use strict" ; + + + +const dotPath = {} ; +module.exports = dotPath ; + + + +const EMPTY_PATH = [] ; +const PROTO_POLLUTION_MESSAGE = 'This would pollute prototype' ; + + + +function toPathArray( path ) { + if ( Array.isArray( path ) ) { return path ; } + else if ( ! path ) { return EMPTY_PATH ; } + else if ( typeof path === 'string' ) { return path.split( '.' ) ; } + + throw new TypeError( '[tree.dotPath]: the path argument should be a string or an array' ) ; +} + + + +// Walk the tree using the path array. +function walk( object , pathArray , maxOffset = 0 ) { + var i , iMax , key , + pointer = object ; + + for ( i = 0 , iMax = pathArray.length + maxOffset ; i < iMax ; i ++ ) { + key = pathArray[ i ] ; + + if ( key === '__proto__' || typeof pointer === 'function' ) { throw new Error( PROTO_POLLUTION_MESSAGE ) ; } + if ( ! pointer || typeof pointer !== 'object' ) { return undefined ; } + + pointer = pointer[ key ] ; + } + + return pointer ; +} + + + +// Walk the tree, create missing element: pave the path up to before the last part of the path. +// Return that before-the-last element. +// Object MUST be an object! no check are performed for the first step! +function pave( object , pathArray ) { + var i , iMax , key , + pointer = object ; + + for ( i = 0 , iMax = pathArray.length - 1 ; i < iMax ; i ++ ) { + key = pathArray[ i ] ; + + if ( key === '__proto__' || typeof pointer[ key ] === 'function' ) { throw new Error( PROTO_POLLUTION_MESSAGE ) ; } + if ( ! pointer[ key ] || typeof pointer[ key ] !== 'object' ) { pointer[ key ] = {} ; } + + pointer = pointer[ key ] ; + } + + return pointer ; +} + + + +dotPath.get = ( object , path ) => walk( object , toPathArray( path ) ) ; + + + +dotPath.set = ( object , path , value ) => { + if ( ! object || typeof object !== 'object' ) { + // Throw? + return undefined ; + } + + var pathArray = toPathArray( path ) , + key = pathArray[ pathArray.length - 1 ] ; + + if ( key === '__proto__' ) { throw new Error( PROTO_POLLUTION_MESSAGE ) ; } + + var pointer = pave( object , pathArray ) ; + + pointer[ key ] = value ; + + return value ; +} ; + + + +dotPath.define = ( object , path , value ) => { + if ( ! object || typeof object !== 'object' ) { + // Throw? + return undefined ; + } + + var pathArray = toPathArray( path ) , + key = pathArray[ pathArray.length - 1 ] ; + + if ( key === '__proto__' ) { throw new Error( PROTO_POLLUTION_MESSAGE ) ; } + + var pointer = pave( object , pathArray ) ; + + if ( ! ( key in pointer ) ) { pointer[ key ] = value ; } + + return value ; +} ; + + + +dotPath.inc = ( object , path , value ) => { + if ( ! object || typeof object !== 'object' ) { + // Throw? + return undefined ; + } + + var pathArray = toPathArray( path ) , + key = pathArray[ pathArray.length - 1 ] ; + + if ( key === '__proto__' ) { throw new Error( PROTO_POLLUTION_MESSAGE ) ; } + + var pointer = pave( object , pathArray ) ; + + if ( typeof pointer[ key ] === 'number' ) { pointer[ key ] ++ ; } + else if ( ! pointer[ key ] || typeof pointer[ key ] !== 'object' ) { pointer[ key ] = 1 ; } + + return value ; +} ; + + + +dotPath.dec = ( object , path , value ) => { + if ( ! object || typeof object !== 'object' ) { + // Throw? + return undefined ; + } + + var pathArray = toPathArray( path ) , + key = pathArray[ pathArray.length - 1 ] ; + + if ( key === '__proto__' ) { throw new Error( PROTO_POLLUTION_MESSAGE ) ; } + + var pointer = pave( object , pathArray ) ; + + if ( typeof pointer[ key ] === 'number' ) { pointer[ key ] -- ; } + else if ( ! pointer[ key ] || typeof pointer[ key ] !== 'object' ) { pointer[ key ] = -1 ; } + + return value ; +} ; + + + +dotPath.concat = ( object , path , value ) => { + if ( ! object || typeof object !== 'object' ) { + // Throw? + return undefined ; + } + + var pathArray = toPathArray( path ) , + key = pathArray[ pathArray.length - 1 ] ; + + if ( key === '__proto__' ) { throw new Error( PROTO_POLLUTION_MESSAGE ) ; } + + var pointer = pave( object , pathArray ) ; + + if ( ! pointer[ key ] ) { pointer[ key ] = value ; } + else if ( Array.isArray( pointer[ key ] ) && Array.isArray( value ) ) { + pointer[ key ] = pointer[ key ].concat( value ) ; + } + //else ? do nothing??? + + return value ; +} ; + + + +dotPath.insert = ( object , path , value ) => { + if ( ! object || typeof object !== 'object' ) { + // Throw? + return undefined ; + } + + var pathArray = toPathArray( path ) , + key = pathArray[ pathArray.length - 1 ] ; + + if ( key === '__proto__' ) { throw new Error( PROTO_POLLUTION_MESSAGE ) ; } + + var pointer = pave( object , pathArray ) ; + + if ( ! pointer[ key ] ) { pointer[ key ] = value ; } + else if ( Array.isArray( pointer[ key ] ) && Array.isArray( value ) ) { + pointer[ key ] = value.concat( pointer[ key ] ) ; + } + //else ? do nothing??? + + return value ; +} ; + + + +dotPath.delete = ( object , path ) => { + var pathArray = toPathArray( path ) , + key = pathArray[ pathArray.length - 1 ] ; + + if ( key === '__proto__' ) { throw new Error( PROTO_POLLUTION_MESSAGE ) ; } + + var pointer = walk( object , pathArray , -1 ) ; + + if ( ! pointer || typeof pointer !== 'object' ) { return false ; } + + return delete pointer[ key ] ; +} ; + + + +dotPath.autoPush = ( object , path , value ) => { + if ( ! object || typeof object !== 'object' ) { + // Throw? + return undefined ; + } + + var pathArray = toPathArray( path ) , + key = pathArray[ pathArray.length - 1 ] ; + + if ( key === '__proto__' ) { throw new Error( PROTO_POLLUTION_MESSAGE ) ; } + + var pointer = pave( object , pathArray ) ; + + if ( pointer[ key ] === undefined ) { pointer[ key ] = value ; } + else if ( Array.isArray( pointer[ key ] ) ) { pointer[ key ].push( value ) ; } + else { pointer[ key ] = [ pointer[ key ] , value ] ; } + + return pointer[ key ] ; +} ; + + + +dotPath.append = ( object , path , value ) => { + if ( ! object || typeof object !== 'object' ) { + // Throw? + return undefined ; + } + + var pathArray = toPathArray( path ) , + key = pathArray[ pathArray.length - 1 ] ; + + if ( key === '__proto__' ) { throw new Error( PROTO_POLLUTION_MESSAGE ) ; } + + var pointer = pave( object , pathArray ) ; + + if ( ! pointer[ key ] ) { pointer[ key ] = [ value ] ; } + else if ( Array.isArray( pointer[ key ] ) ) { pointer[ key ].push( value ) ; } + //else ? do nothing??? + + return pointer[ key ] ; +} ; + + + +dotPath.prepend = ( object , path , value ) => { + if ( ! object || typeof object !== 'object' ) { + // Throw? + return undefined ; + } + + var pathArray = toPathArray( path ) , + key = pathArray[ pathArray.length - 1 ] ; + + if ( key === '__proto__' ) { throw new Error( PROTO_POLLUTION_MESSAGE ) ; } + + var pointer = pave( object , pathArray ) ; + + if ( ! pointer[ key ] ) { pointer[ key ] = [ value ] ; } + else if ( Array.isArray( pointer[ key ] ) ) { pointer[ key ].unshift( value ) ; } + //else ? do nothing??? + + return pointer[ key ] ; +} ; + + +},{}],4:[function(require,module,exports){ +/* + Tree Kit + + Copyright (c) 2014 - 2021 Cédric Ronvel The MIT License (MIT) @@ -455,11 +763,11 @@ function extendOne( runtime , options , target , source ) { } -},{}],4:[function(require,module,exports){ +},{}],5:[function(require,module,exports){ /* Tree Kit - Copyright (c) 2014 - 2019 Cédric Ronvel + Copyright (c) 2014 - 2021 Cédric Ronvel The MIT License (MIT) @@ -486,17 +794,19 @@ function extendOne( runtime , options , target , source ) { -var treePath = {} ; +const treePath = {} ; module.exports = treePath ; -treePath.op = function op( type , object , path , value ) { +const PROTO_POLLUTION_MESSAGE = 'This would pollute prototype' ; + + + +treePath.op = function( 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' ) ) { - return ; - } + if ( ! object || typeof object !== 'object' ) { return ; } if ( typeof path === 'string' ) { // Split the path into parts @@ -544,17 +854,19 @@ treePath.op = function op( type , object , path , value ) { if ( pathArrayMode ) { if ( key === undefined ) { key = parts[ i ] ; + if ( key === '__proto__' ) { throw new Error( PROTO_POLLUTION_MESSAGE ) ; } continue ; } - if ( ! pointer[ key ] || ( typeof pointer[ key ] !== 'object' && typeof pointer[ key ] !== 'function' ) ) { + if ( typeof pointer[ key ] === 'function' ) { throw new Error( PROTO_POLLUTION_MESSAGE ) ; } + if ( ! pointer[ key ] || typeof pointer[ key ] !== 'object' ) { if ( ! isGenericSet ) { return undefined ; } pointer[ key ] = {} ; } pointer = pointer[ key ] ; key = parts[ i ] ; - + if ( key === '__proto__' ) { throw new Error( PROTO_POLLUTION_MESSAGE ) ; } continue ; } else if ( parts[ i ] === '.' ) { @@ -569,7 +881,8 @@ treePath.op = function op( type , object , path , value ) { key = '' ; } - if ( ! pointer[ key ] || ( typeof pointer[ key ] !== 'object' && typeof pointer[ key ] !== 'function' ) ) { + if ( typeof pointer[ key ] === 'function' ) { throw new Error( PROTO_POLLUTION_MESSAGE ) ; } + if ( ! pointer[ key ] || typeof pointer[ key ] !== 'object' ) { if ( ! isGenericSet ) { return undefined ; } pointer[ key ] = {} ; } @@ -589,6 +902,7 @@ treePath.op = function op( type , object , path , value ) { continue ; } + if ( typeof pointer[ key ] === 'function' ) { throw new Error( PROTO_POLLUTION_MESSAGE ) ; } if ( ! pointer[ key ] || ! Array.isArray( pointer[ key ] ) ) { if ( ! isGenericSet ) { return undefined ; } pointer[ key ] = [] ; @@ -606,11 +920,15 @@ treePath.op = function op( type , object , path , value ) { canBeEmpty = false ; - if ( ! isArray ) { key = parts[ i ] ; continue ; } + if ( ! isArray ) { + key = parts[ i ] ; + if ( key === '__proto__' ) { throw new Error( PROTO_POLLUTION_MESSAGE ) ; } + continue ; + } switch ( parts[ i ] ) { case 'length' : - key = parts[ i ] ; + key = 'length' ; break ; // Pseudo-key @@ -727,7 +1045,7 @@ treePath.prototype = { // Upgrade an object so it can support get, set and delete at its root -treePath.upgrade = function upgrade( object ) { +treePath.upgrade = function( object ) { Object.defineProperties( object , { get: { value: treePath.op.bind( undefined , 'get' , object ) } , delete: { value: treePath.op.bind( undefined , 'delete' , object ) } , diff --git a/browser/tree-kit.min.js b/browser/tree-kit.min.js index 4571aaf..19f89f4 100644 --- a/browser/tree-kit.min.js +++ b/browser/tree-kit.min.js @@ -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,n;return function(){function e(t,n,r){function i(o,u){if(!n[o]){if(!t[o]){var s="function"==typeof require&&require;if(!u&&s)return s(o,!0);if(f)return f(o,!0);var a=new Error("Cannot find module '"+o+"'");throw a.code="MODULE_NOT_FOUND",a}var c=n[o]={exports:{}};t[o][0].call(c.exports,function(e){var n=t[o][1][e];return i(n||e)},c,c.exports,e,t,n,r)}return n[o].exports}for(var f="function"==typeof require&&require,o=0;onew Date(e))},{}],3:[function(e,t,n){"use strict";function r(e,t,...n){var r,f,o=false,u=n.length;if(!u){return t}if(!e||typeof e!=="object"){e={}}var s={depth:0,prefix:""};if(e.deep){if(Array.isArray(e.deep)){e.deep=new Set(e.deep)}else if(!(e.deep instanceof Set)){e.deep=true}}if(e.immutables){if(Array.isArray(e.immutables)){e.immutables=new Set(e.immutables)}else if(!(e.immutables instanceof Set)){delete e.immutables}}if(!e.maxDepth&&e.deep&&!e.circular){e.maxDepth=100}if(e.deepFunc){e.deep=true}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(r=u-1;r>=0;r--){f=n[r];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={}}s.references={sources:[],targets:[]};for(r=0;rt.maxDepth){throw new Error("[tree] extend(): max depth reached("+t.maxDepth+")")}if(t.circular){e.references.sources.push(r);e.references.targets.push(n)}if(t.own){if(t.nonEnum){u=Object.getOwnPropertyNames(r)}else{u=Object.keys(r)}}else{u=r}for(s in u){if(t.own){s=u[s]}if(s==="__proto__"){continue}if(t.descriptor){d=Object.getOwnPropertyDescriptor(r,s);a=d.value}else{a=r[s]}b=n;l=e.prefix+s;if(t.nofunc&&typeof a==="function"){continue}if(t.unflat&&e.depth===0){y=s.split(t.unflat);o=y.length-1;if(o){for(f=0;f=0){continue}i({depth:e.depth+1,prefix:e.prefix+s+t.flat,references:e.references},t,b,a)}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]||!Object.prototype.hasOwnProperty.call(b,l)||typeof b[l]!=="object"&&typeof b[l]!=="function"){if(Array.isArray(a)){p=[]}else if(t.proto){p=Object.create(c)}else if(t.inherit){p=Object.create(a)}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])!==c){Object.setPrototypeOf(b[l],c)}else if(t.inherit&&Object.getPrototypeOf(b[l])!==a){Object.setPrototypeOf(b[l],a)}if(t.circular){e.references.sources.push(a);e.references.targets.push(b[l])}i({depth:e.depth+1,prefix:"",references:e.references},t,b[l],a)}}else if(t.preserve&&b[l]!==undefined){continue}else if(!t.inherit){if(t.descriptor){Object.defineProperty(b,l,d)}else{b[l]=a}}if(t.move){delete r[s]}}}},{}],4:[function(e,t,n){"use strict";var r={};t.exports=r;r.op=function e(t,n,r,i){var f,o,u,s,a,c=false,p=false,d,l=true;if(!n||typeof n!=="object"&&typeof n!=="function"){return}if(typeof r==="string"){if(r){o=r.match(/([.#[\]]|[^.#[\]]+)/g)}else{o=[""]}if(o[0]==="."){o.unshift("")}if(o[o.length-1]==="."){o.push("")}}else if(Array.isArray(r)){o=r;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+"'")}s=n;u=o.length-1;for(f=0;f<=u;f++){if(p){if(a===undefined){a=o[f];continue}if(!s[a]||typeof s[a]!=="object"&&typeof s[a]!=="function"){if(!d){return undefined}s[a]={}}s=s[a];a=o[f];continue}else if(o[f]==="."){c=false;if(a===undefined){if(!l){l=true;continue}a=""}if(!s[a]||typeof s[a]!=="object"&&typeof s[a]!=="function"){if(!d){return undefined}s[a]={}}s=s[a];l=true;continue}else if(o[f]==="#"||o[f]==="["){c=true;l=false;if(a===undefined){if(!Array.isArray(s)){return undefined}continue}if(!s[a]||!Array.isArray(s[a])){if(!d){return undefined}s[a]=[]}s=s[a];continue}else if(o[f]==="]"){l=false;continue}l=false;if(!c){a=o[f];continue}switch(o[f]){case"length":a=o[f];break;case"first":a=0;break;case"last":a=s.length-1;if(a<0){a=0}break;case"next":if(!d){return undefined}a=s.length;break;case"insert":if(!d){return undefined}s.unshift(undefined);a=0;break;default:a=parseInt(o[f],10)}}switch(t){case"get":return s[a];case"delete":if(c&&typeof a==="number"){s.splice(a,1)}else{delete s[a]}return;case"set":s[a]=i;return s[a];case"define":if(!(a in s)){s[a]=i}return s[a];case"inc":if(typeof s[a]==="number"){s[a]++}else if(!s[a]||typeof s[a]!=="object"){s[a]=1}return s[a];case"dec":if(typeof s[a]==="number"){s[a]--}else if(!s[a]||typeof s[a]!=="object"){s[a]=-1}return s[a];case"append":if(!s[a]){s[a]=[i]}else if(Array.isArray(s[a])){s[a].push(i)}return s[a];case"prepend":if(!s[a]){s[a]=[i]}else if(Array.isArray(s[a])){s[a].unshift(i)}return s[a];case"concat":if(!s[a]){s[a]=i}else if(Array.isArray(s[a])&&Array.isArray(i)){s[a]=s[a].concat(i)}return s[a];case"insert":if(!s[a]){s[a]=i}else if(Array.isArray(s[a])&&Array.isArray(i)){s[a]=i.concat(s[a])}return s[a];case"autoPush":if(s[a]===undefined){s[a]=i}else if(Array.isArray(s[a])){s[a].push(i)}else{s[a]=[s[a],i]}return s[a]}};r.get=r.op.bind(undefined,"get");r.delete=r.op.bind(undefined,"delete");r.set=r.op.bind(undefined,"set");r.define=r.op.bind(undefined,"define");r.inc=r.op.bind(undefined,"inc");r.dec=r.op.bind(undefined,"dec");r.append=r.op.bind(undefined,"append");r.prepend=r.op.bind(undefined,"prepend");r.concat=r.op.bind(undefined,"concat");r.insert=r.op.bind(undefined,"insert");r.autoPush=r.op.bind(undefined,"autoPush");r.prototype={get:function(e){return r.get(this,e)},delete:function(e){return r.delete(this,e)},set:function(e,t){return r.set(this,e,t)},define:function(e,t){return r.define(this,e,t)},inc:function(e,t){return r.inc(this,e,t)},dec:function(e,t){return r.dec(this,e,t)},append:function(e,t){return r.append(this,e,t)},prepend:function(e,t){return r.prepend(this,e,t)},concat:function(e,t){return r.concat(this,e,t)},insert:function(e,t){return r.insert(this,e,t)},autoPush:function(e,t){return r.autoPush(this,e,t)}};r.upgrade=function e(t){Object.defineProperties(t,{get:{value:r.op.bind(undefined,"get",t)},delete:{value:r.op.bind(undefined,"delete",t)},set:{value:r.op.bind(undefined,"set",t)},define:{value:r.op.bind(undefined,"define",t)},inc:{value:r.op.bind(undefined,"inc",t)},dec:{value:r.op.bind(undefined,"dec",t)},append:{value:r.op.bind(undefined,"append",t)},prepend:{value:r.op.bind(undefined,"prepend",t)},concat:{value:r.op.bind(undefined,"concat",t)},insert:{value:r.op.bind(undefined,"insert",t)},autoPush:{value:r.op.bind(undefined,"autoPush",t)}})}},{}]},{},[1])(1)}); \ No newline at end of file +(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(f,u){if(!r[f]){if(!t[f]){var a="function"==typeof require&&require;if(!u&&a)return a(f,!0);if(o)return o(f,!0);var s=new Error("Cannot find module '"+f+"'");throw s.code="MODULE_NOT_FOUND",s}var c=r[f]={exports:{}};t[f][0].call(c.exports,function(e){var r=t[f][1][e];return i(r||e)},c,c.exports,e,t,r,n)}return r[f].exports}for(var o="function"==typeof require&&require,f=0;fnew Date(e))},{}],3:[function(e,t,r){"use strict";const n={};t.exports=n;const i=[];const o="This would pollute prototype";function f(e){if(Array.isArray(e)){return e}else if(!e){return i}else if(typeof e==="string"){return e.split(".")}throw new TypeError("[tree.dotPath]: the path argument should be a string or an array")}function u(e,t,r=0){var n,i,f,u=e;for(n=0,i=t.length+r;nu(e,f(t)));n.set=((e,t,r)=>{if(!e||typeof e!=="object"){return undefined}var n=f(t),i=n[n.length-1];if(i==="__proto__"){throw new Error(o)}var u=a(e,n);u[i]=r;return r});n.define=((e,t,r)=>{if(!e||typeof e!=="object"){return undefined}var n=f(t),i=n[n.length-1];if(i==="__proto__"){throw new Error(o)}var u=a(e,n);if(!(i in u)){u[i]=r}return r});n.inc=((e,t,r)=>{if(!e||typeof e!=="object"){return undefined}var n=f(t),i=n[n.length-1];if(i==="__proto__"){throw new Error(o)}var u=a(e,n);if(typeof u[i]==="number"){u[i]++}else if(!u[i]||typeof u[i]!=="object"){u[i]=1}return r});n.dec=((e,t,r)=>{if(!e||typeof e!=="object"){return undefined}var n=f(t),i=n[n.length-1];if(i==="__proto__"){throw new Error(o)}var u=a(e,n);if(typeof u[i]==="number"){u[i]--}else if(!u[i]||typeof u[i]!=="object"){u[i]=-1}return r});n.concat=((e,t,r)=>{if(!e||typeof e!=="object"){return undefined}var n=f(t),i=n[n.length-1];if(i==="__proto__"){throw new Error(o)}var u=a(e,n);if(!u[i]){u[i]=r}else if(Array.isArray(u[i])&&Array.isArray(r)){u[i]=u[i].concat(r)}return r});n.insert=((e,t,r)=>{if(!e||typeof e!=="object"){return undefined}var n=f(t),i=n[n.length-1];if(i==="__proto__"){throw new Error(o)}var u=a(e,n);if(!u[i]){u[i]=r}else if(Array.isArray(u[i])&&Array.isArray(r)){u[i]=r.concat(u[i])}return r});n.delete=((e,t)=>{var r=f(t),n=r[r.length-1];if(n==="__proto__"){throw new Error(o)}var i=u(e,r,-1);if(!i||typeof i!=="object"){return false}return delete i[n]});n.autoPush=((e,t,r)=>{if(!e||typeof e!=="object"){return undefined}var n=f(t),i=n[n.length-1];if(i==="__proto__"){throw new Error(o)}var u=a(e,n);if(u[i]===undefined){u[i]=r}else if(Array.isArray(u[i])){u[i].push(r)}else{u[i]=[u[i],r]}return u[i]});n.append=((e,t,r)=>{if(!e||typeof e!=="object"){return undefined}var n=f(t),i=n[n.length-1];if(i==="__proto__"){throw new Error(o)}var u=a(e,n);if(!u[i]){u[i]=[r]}else if(Array.isArray(u[i])){u[i].push(r)}return u[i]});n.prepend=((e,t,r)=>{if(!e||typeof e!=="object"){return undefined}var n=f(t),i=n[n.length-1];if(i==="__proto__"){throw new Error(o)}var u=a(e,n);if(!u[i]){u[i]=[r]}else if(Array.isArray(u[i])){u[i].unshift(r)}return u[i]})},{}],4:[function(e,t,r){"use strict";function n(e,t,...r){var n,o,f=false,u=r.length;if(!u){return t}if(!e||typeof e!=="object"){e={}}var a={depth:0,prefix:""};if(e.deep){if(Array.isArray(e.deep)){e.deep=new Set(e.deep)}else if(!(e.deep instanceof Set)){e.deep=true}}if(e.immutables){if(Array.isArray(e.immutables)){e.immutables=new Set(e.immutables)}else if(!(e.immutables instanceof Set)){delete e.immutables}}if(!e.maxDepth&&e.deep&&!e.circular){e.maxDepth=100}if(e.deepFunc){e.deep=true}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(n=u-1;n>=0;n--){o=r[n];if(o&&(typeof o==="object"||typeof o==="function")){if(e.inherit){if(f){t=Object.create(o)}else{Object.setPrototypeOf(t,o)}}else if(e.proto){if(f){t=Object.create(Object.getPrototypeOf(o))}else{Object.setPrototypeOf(t,Object.getPrototypeOf(o))}}break}}}else if(f){t={}}a.references={sources:[],targets:[]};for(n=0;nt.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){u=Object.getOwnPropertyNames(n)}else{u=Object.keys(n)}}else{u=n}for(a in u){if(t.own){a=u[a]}if(a==="__proto__"){continue}if(t.descriptor){d=Object.getOwnPropertyDescriptor(n,a);s=d.value}else{s=n[a]}y=r;l=e.prefix+a;if(t.nofunc&&typeof s==="function"){continue}if(t.unflat&&e.depth===0){h=a.split(t.unflat);f=h.length-1;if(f){for(o=0;o=0){continue}i({depth:e.depth+1,prefix:e.prefix+a+t.flat,references:e.references},t,y,s)}else{if(b>=0){if(t.descriptor){Object.defineProperty(y,l,{value:e.references.targets[b],enumerable:d.enumerable,writable:d.writable,configurable:d.configurable})}else{y[l]=e.references.targets[b]}continue}if(!y[l]||!Object.prototype.hasOwnProperty.call(y,l)||typeof y[l]!=="object"&&typeof y[l]!=="function"){if(Array.isArray(s)){p=[]}else if(t.proto){p=Object.create(c)}else if(t.inherit){p=Object.create(s)}else{p={}}if(t.descriptor){Object.defineProperty(y,l,{value:p,enumerable:d.enumerable,writable:d.writable,configurable:d.configurable})}else{y[l]=p}}else if(t.proto&&Object.getPrototypeOf(y[l])!==c){Object.setPrototypeOf(y[l],c)}else if(t.inherit&&Object.getPrototypeOf(y[l])!==s){Object.setPrototypeOf(y[l],s)}if(t.circular){e.references.sources.push(s);e.references.targets.push(y[l])}i({depth:e.depth+1,prefix:"",references:e.references},t,y[l],s)}}else if(t.preserve&&y[l]!==undefined){continue}else if(!t.inherit){if(t.descriptor){Object.defineProperty(y,l,d)}else{y[l]=s}}if(t.move){delete n[a]}}}},{}],5:[function(e,t,r){"use strict";const n={};t.exports=n;const i="This would pollute prototype";n.op=function(e,t,r,n){var o,f,u,a,s,c=false,p=false,d,l=true;if(!t||typeof t!=="object"){return}if(typeof r==="string"){if(r){f=r.match(/([.#[\]]|[^.#[\]]+)/g)}else{f=[""]}if(f[0]==="."){f.unshift("")}if(f[f.length-1]==="."){f.push("")}}else if(Array.isArray(r)){f=r;p=true}else{throw new TypeError("[tree.path] ."+e+"(): the path argument should be a string or an array")}switch(e){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 '"+e+"'")}a=t;u=f.length-1;for(o=0;o<=u;o++){if(p){if(s===undefined){s=f[o];if(s==="__proto__"){throw new Error(i)}continue}if(typeof a[s]==="function"){throw new Error(i)}if(!a[s]||typeof a[s]!=="object"){if(!d){return undefined}a[s]={}}a=a[s];s=f[o];if(s==="__proto__"){throw new Error(i)}continue}else if(f[o]==="."){c=false;if(s===undefined){if(!l){l=true;continue}s=""}if(typeof a[s]==="function"){throw new Error(i)}if(!a[s]||typeof a[s]!=="object"){if(!d){return undefined}a[s]={}}a=a[s];l=true;continue}else if(f[o]==="#"||f[o]==="["){c=true;l=false;if(s===undefined){if(!Array.isArray(a)){return undefined}continue}if(typeof a[s]==="function"){throw new Error(i)}if(!a[s]||!Array.isArray(a[s])){if(!d){return undefined}a[s]=[]}a=a[s];continue}else if(f[o]==="]"){l=false;continue}l=false;if(!c){s=f[o];if(s==="__proto__"){throw new Error(i)}continue}switch(f[o]){case"length":s="length";break;case"first":s=0;break;case"last":s=a.length-1;if(s<0){s=0}break;case"next":if(!d){return undefined}s=a.length;break;case"insert":if(!d){return undefined}a.unshift(undefined);s=0;break;default:s=parseInt(f[o],10)}}switch(e){case"get":return a[s];case"delete":if(c&&typeof s==="number"){a.splice(s,1)}else{delete a[s]}return;case"set":a[s]=n;return a[s];case"define":if(!(s in a)){a[s]=n}return a[s];case"inc":if(typeof a[s]==="number"){a[s]++}else if(!a[s]||typeof a[s]!=="object"){a[s]=1}return a[s];case"dec":if(typeof a[s]==="number"){a[s]--}else if(!a[s]||typeof a[s]!=="object"){a[s]=-1}return a[s];case"append":if(!a[s]){a[s]=[n]}else if(Array.isArray(a[s])){a[s].push(n)}return a[s];case"prepend":if(!a[s]){a[s]=[n]}else if(Array.isArray(a[s])){a[s].unshift(n)}return a[s];case"concat":if(!a[s]){a[s]=n}else if(Array.isArray(a[s])&&Array.isArray(n)){a[s]=a[s].concat(n)}return a[s];case"insert":if(!a[s]){a[s]=n}else if(Array.isArray(a[s])&&Array.isArray(n)){a[s]=n.concat(a[s])}return a[s];case"autoPush":if(a[s]===undefined){a[s]=n}else if(Array.isArray(a[s])){a[s].push(n)}else{a[s]=[a[s],n]}return a[s]}};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){Object.defineProperties(e,{get:{value:n.op.bind(undefined,"get",e)},delete:{value:n.op.bind(undefined,"delete",e)},set:{value:n.op.bind(undefined,"set",e)},define:{value:n.op.bind(undefined,"define",e)},inc:{value:n.op.bind(undefined,"inc",e)},dec:{value:n.op.bind(undefined,"dec",e)},append:{value:n.op.bind(undefined,"append",e)},prepend:{value:n.op.bind(undefined,"prepend",e)},concat:{value:n.op.bind(undefined,"concat",e)},insert:{value:n.op.bind(undefined,"insert",e)},autoPush:{value:n.op.bind(undefined,"autoPush",e)}})}},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/package.json b/package.json index 81a3551..f241c5a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tree-kit", - "version": "0.6.2", + "version": "0.7.0", "description": "Tree utilities which provides a full-featured extend and object-cloning facility, and various tools to deal with nested object structures.", "main": "lib/tree.js", "directories": {