protoblast
Advanced tools
Comparing version 0.4.1 to 0.4.2
@@ -0,1 +1,12 @@ | ||
## 0.4.2 (2018-01-15) | ||
* `JSON.dry` will no longer add `namespace` or `dry_class` properties if `toDry` has already set them | ||
* `JSON.undry` will now accept a dried object that has been parsed using regular `JSON.parse` (this is faster than re-stringifying & undrying it) | ||
* Fixed the space problem in `JSON.dry` | ||
* `Object.walk` will now return an object with all the seen objects and a weakmap containing the seen count | ||
* `Object.walk` can now be called without a task function | ||
* If DRY references to a value has a shorter path, use that in the future | ||
* From now on, `json-dry` is its own package once again | ||
* Added `JSON#toDryObject`, an alias for `Dry.toObject` | ||
## 0.4.1 (2018-01-05) | ||
@@ -2,0 +13,0 @@ |
@@ -481,3 +481,3 @@ module.exports = function BlastInit(modifyPrototype) { | ||
* @since 0.1.0 | ||
* @version 0.4.1 | ||
* @version 0.4.2 | ||
* | ||
@@ -530,3 +530,4 @@ * @param {Object} target The object to add the property to | ||
if (Blast.modifyPrototype) { | ||
// Honour the 'modifyPrototype' setting, except for classes we created ourselves | ||
if (Blast.modifyPrototype || (targetClass && targetClass.setMethod)) { | ||
// Only set if it's not a shim, or if it's not there | ||
@@ -606,2 +607,3 @@ if (!shim || !targetClass.hasOwnProperty(name)) { | ||
//PROTOBLAST START CUT | ||
/** | ||
@@ -619,2 +621,3 @@ * Server side: create client side file | ||
var template, | ||
libpath = require('path'), | ||
result, | ||
@@ -633,3 +636,3 @@ cpath, | ||
cpath = __dirname + '/../client-file-common.js'; | ||
cpath = libpath.resolve(__dirname, '..', 'client-file-common.js'); | ||
Blast.clientPathCommon = cpath; | ||
@@ -641,3 +644,3 @@ } else { | ||
cpath = __dirname + '/../client-file.js'; | ||
cpath = libpath.resolve(__dirname, '..', 'client-file.js'); | ||
Blast.clientPath = cpath; | ||
@@ -650,3 +653,3 @@ } | ||
// Get the main template | ||
template = fs.readFileSync(__dirname + '/client.js', {encoding: 'utf8'}); | ||
template = fs.readFileSync(libpath.resolve(__dirname, 'client.js'), {encoding: 'utf8'}); | ||
@@ -661,2 +664,3 @@ code = ''; | ||
'weakmap', | ||
'json-dry', | ||
'function_flow', | ||
@@ -673,8 +677,16 @@ 'function_inheritance', | ||
files.forEach(function(name, index) { | ||
files.forEach(function eachFile(name, index) { | ||
var path; | ||
name = name.toLowerCase(); | ||
temp = fs.readFileSync(__dirname + '/' + name + '.js', {encoding: 'utf8'}); | ||
if (name == 'json-dry') { | ||
path = require.resolve('json-dry'); | ||
} else { | ||
path = libpath.resolve(__dirname, name + '.js'); | ||
} | ||
temp = fs.readFileSync(path, {encoding: 'utf8'}); | ||
code += 'require.register("' + name + '.js", function(module, exports, require){\n'; | ||
@@ -694,3 +706,3 @@ code += temp; | ||
// Remove everything between "//PROTOBLAST START CUT" and "//PROTOBLAST END CUT" | ||
// Remove everything between "PROTOBLAST START CUT" and "PROTOBLAST END CUT" (with slashes) | ||
template = template.replace(/\/\/\s?PROTOBLAST\s?START\s?CUT([\s\S]*?)(\/\/\s?PROTOBLAST\s?END\s?CUT)/gm, ''); | ||
@@ -702,2 +714,3 @@ | ||
}; | ||
//PROTOBLAST END CUT | ||
@@ -896,3 +909,3 @@ var when_ready = [], | ||
// Now create bound methods, which are about 0,000129 ms slower | ||
// Now create bound methods | ||
Collection.Object.each(Collection, function eachCollection(StaticClass, className) { | ||
@@ -899,0 +912,0 @@ |
806
lib/json.js
@@ -1,602 +0,12 @@ | ||
/** | ||
* Circular-JSON code: | ||
* Copyright (C) 2013 by WebReflection | ||
* Modified by Jelle De Loecker | ||
* | ||
* JSON-js code: | ||
* Public domain by Douglas Crockford | ||
* | ||
* 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. | ||
* | ||
*/ | ||
module.exports = function BlastJSON(Blast, Collection) { | ||
'use strict'; | ||
'use strict'; | ||
module.exports = function BlastJSON(Blast, Collection, Bound, Obj) { | ||
var specialChar = '~', | ||
safeSpecialChar = '\\x7e', | ||
escapedSafeSpecialChar = '\\' + safeSpecialChar, | ||
safeStartWithSpecialCharRG = new RegExp('(?:^|([^\\\\]))' + escapedSafeSpecialChar), | ||
safeSpecialCharRG = new RegExp(escapedSafeSpecialChar, 'g'), | ||
specialCharRG = new RegExp(safeSpecialChar, 'g'), | ||
getregex = /^\/(.*)\/(.*)/, | ||
iso8061 = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/, | ||
undriers = {}, | ||
driers = {}, | ||
meta, | ||
rep; | ||
var Dry = require('json-dry'); | ||
var rx_one = /^[\],:{}\s]*$/, | ||
rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, | ||
rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, | ||
rx_four = /(?:^|:|,)(?:\s*\[)+/g, | ||
rx_escapable = /[\\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, | ||
rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; | ||
// Override the Dry classes with the Protoblast classes | ||
Dry.Classes = Blast.Classes; | ||
Dry.Classes.__Protoblast = Blast; | ||
// table of character substitutions | ||
meta = { | ||
'\b': '\\b', | ||
'\t': '\\t', | ||
'\n': '\\n', | ||
'\f': '\\f', | ||
'\r': '\\r', | ||
'"': '\\"', | ||
'\\': '\\\\' | ||
}; | ||
function string_escaper(a) { | ||
var c = meta[a]; | ||
return c == null | ||
? '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4) | ||
: c; | ||
} | ||
function quote(string) { | ||
rx_escapable.lastIndex = 0; | ||
return rx_escapable.test(string) | ||
? '"' + string.replace(rx_escapable, string_escaper) + '"' | ||
: '"' + string + '"'; | ||
} | ||
/** | ||
* Generate a replacer function | ||
* | ||
* @author Jelle De Loecker <jelle@develry.be> | ||
* @since 0.1.4 | ||
* @version 0.3.8 | ||
* | ||
* @return {Function} | ||
*/ | ||
function generateReplacer(root, replacer, space) { | ||
var seenByConstructor, | ||
constructorMap, | ||
seenObjects, | ||
seenMap, | ||
isRoot, | ||
indent, | ||
chain, | ||
path, | ||
temp, | ||
gap, | ||
i; | ||
isRoot = true; | ||
seenByConstructor = {}; | ||
constructorMap = {}; | ||
chain = []; | ||
path = []; | ||
seenObjects = []; | ||
seenMap = []; | ||
gap = ''; | ||
indent = ''; | ||
if (typeof space == 'number') { | ||
for (i = 0; i < space; i++) { | ||
indent += ' '; | ||
} | ||
} else if (typeof space == 'string') { | ||
indent = space; | ||
} | ||
return function dryReplacer(holder, key, value) { | ||
var nameType, | ||
replaced, | ||
partial, | ||
isArray, | ||
isWrap, | ||
mind, | ||
temp, | ||
last, | ||
len, | ||
i, | ||
j, | ||
k, // Member key | ||
v; // Member value | ||
// Process the value to a possible given replacer function | ||
if (replacer != null) { | ||
value = replacer.call(holder, key, value); | ||
} | ||
mind = gap; | ||
if (key === false) { | ||
key = ''; | ||
isWrap = true; | ||
// Wrappers get added to the object chain, but not the path | ||
// We need to be able to identify them later on | ||
holder.__isWrap = true; | ||
// See if the wrapped value is an object | ||
if (holder[''] && typeof holder[''] === 'object') { | ||
holder.__isObject = true; | ||
} | ||
} | ||
switch (typeof value) { | ||
case 'function': | ||
if (!driers.Function) { | ||
return; | ||
} | ||
case 'object': | ||
if (value == null) { | ||
value = 'null'; | ||
} else { | ||
gap += indent; | ||
// Get the name of the constructor | ||
if (value.constructor) { | ||
nameType = value.constructor.name; | ||
} else { | ||
nameType = 'Object'; | ||
} | ||
// Create the map if it doesn't exist yet | ||
if (seenByConstructor[nameType] == null) { | ||
seenByConstructor[nameType] = []; | ||
constructorMap[nameType] = []; | ||
} | ||
while (len = chain.length) { | ||
// If the current object at the end of the chain does not | ||
// match the current holder, move one up | ||
// Don't mess with the chain if this is a wrap object | ||
if (!isWrap && holder !== chain[len-1]) { | ||
last = chain.pop(); | ||
// Only pop the path if the popped object isn't a wrapper | ||
// @todo: also check for __isObject or not? | ||
if (last && !last.__isWrap) { | ||
path.pop(); | ||
} | ||
} else { | ||
break; | ||
} | ||
} | ||
// Now see if this object has been seen before | ||
if (seenByConstructor[nameType].length) { | ||
i = seenByConstructor[nameType].indexOf(value); | ||
if (i > -1) { | ||
value = quote(seenMap[constructorMap[nameType][i]]); | ||
gap = mind; | ||
break; | ||
} | ||
} | ||
// Store the object in the seen array and return the index | ||
i = seenObjects.push(value) - 1; | ||
j = seenByConstructor[nameType].push(value) - 1; | ||
constructorMap[nameType][j] = i; | ||
// Key cannot contain specialChar but could be not a string | ||
if (!isRoot && !isWrap) { | ||
path.push(('' + key).replace(specialCharRG, safeSpecialChar)); | ||
} else { | ||
isRoot = false; | ||
} | ||
seenMap[i] = specialChar + path.join(specialChar); | ||
if (driers[nameType] != null) { | ||
value = driers[nameType].fnc(holder, key, value); | ||
value = { | ||
dry: nameType, | ||
value: value | ||
}; | ||
if (driers[nameType].options.add_path !== false) { | ||
value.drypath = path.slice(0); | ||
} | ||
replaced = {'': value}; | ||
} else if (nameType == 'RegExp') { | ||
value = {dry: 'regexp', value: value.toString()}; | ||
replaced = {'': value}; | ||
} else if (typeof value.toDry === 'function') { | ||
temp = value; | ||
value = value.toDry(); | ||
// If no path was supplied in the toDry, | ||
// get some more class information | ||
if (!value.path) { | ||
if (temp.constructor) { | ||
if (temp.constructor.namespace) { | ||
value.namespace = temp.constructor.namespace; | ||
} | ||
value.dry_class = temp.constructor.name; | ||
} | ||
} | ||
value.dry = 'toDry'; | ||
value.drypath = path.slice(0); | ||
replaced = {'': value}; | ||
} else if (typeof value.toJSON === 'function') { | ||
value = value.toJSON(); | ||
replaced = {'': value}; | ||
} else { | ||
isArray = Array.isArray(value); | ||
} | ||
// Push this object on the chain | ||
chain.push(replaced || value); | ||
if (replaced) { | ||
value = dryReplacer(replaced, false, replaced['']); | ||
// At least one part of the path & chain will have | ||
// to be popped off. This is needed for toJSON calls | ||
// that return primitive values | ||
temp = chain.pop(); | ||
// Don't pop off anything from the path if the last item | ||
// from the chain was a wrapper for an object, | ||
// because then it'll already be popped of | ||
if (!(temp && temp.__isWrap && temp.__isObject)) { | ||
temp = path.pop(); | ||
} | ||
break; | ||
} | ||
partial = []; | ||
if (isArray) { | ||
len = value.length; | ||
for (i = 0; i < len; i += 1) { | ||
partial[i] = dryReplacer(value, i, value[i]) || 'null'; | ||
} | ||
v = partial.length === 0 | ||
? '[]' | ||
: gap | ||
? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' | ||
: '[' + partial.join(',') + ']'; | ||
gap = mind; | ||
} else { | ||
for (k in value) { | ||
if (Object.prototype.hasOwnProperty.call(value, k)) { | ||
v = dryReplacer(value, k, value[k]); | ||
if (v) { | ||
partial.push(quote(k) + ( | ||
gap | ||
? ': ' | ||
: ':' | ||
) + v); | ||
} | ||
} | ||
} | ||
v = partial.length === 0 | ||
? '{}' | ||
: gap | ||
? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' | ||
: '{' + partial.join(',') + '}'; | ||
gap = mind; | ||
} | ||
value = v; | ||
} | ||
break; | ||
case 'string': | ||
// Make sure the "special char" doesn't mess things up | ||
if (!isRoot) { | ||
value = value.replace(safeSpecialCharRG, escapedSafeSpecialChar) | ||
.replace(specialChar, safeSpecialChar); | ||
} | ||
value = quote(value); | ||
break; | ||
case 'number': | ||
// Allow infinite values | ||
if (!isFinite(value)) { | ||
if (value > 0) { | ||
value = '{"dry":"+Infinity"}'; | ||
} else { | ||
value = '{"dry":"-Infinity"}'; | ||
} | ||
break; | ||
} | ||
case 'boolean': | ||
case 'null': | ||
value = String(value); | ||
break; | ||
} | ||
return value; | ||
}; | ||
}; | ||
/** | ||
* Generate reviver function | ||
* | ||
* @author Jelle De Loecker <jelle@develry.be> | ||
* @since 0.1.4 | ||
* @version 0.3.8 | ||
* | ||
* @return {Function} | ||
*/ | ||
function generateReviver(reviver, undryPaths) { | ||
return function dryReviver(key, value) { | ||
var valType = typeof value, | ||
constructor, | ||
temp; | ||
if (valType === 'string') { | ||
if (value.charAt(0) === specialChar) { | ||
return new String(value.slice(1)); | ||
} else if (value.match(iso8061)) { | ||
return new Date(value); | ||
} | ||
} else if (value && value.dry != null) { | ||
switch (value.dry) { | ||
case 'regexp': | ||
if (value.value) { | ||
return RegExp.apply(undefined, getregex.exec(value.value).slice(1)); | ||
} | ||
break; | ||
case '+Infinity': | ||
return Infinity; | ||
case '-Infinity': | ||
return -Infinity; | ||
case 'toDry': | ||
if (value.path) { | ||
constructor = Collection.Object.path(Blast.Globals, value.path); | ||
} else { | ||
if (value.namespace) { | ||
constructor = Collection.Object.path(Blast.Classes, value.namespace); | ||
} else { | ||
constructor = Blast.Classes; | ||
} | ||
if (value.dry_class) { | ||
constructor = Collection.Object.path(constructor, value.dry_class); | ||
} | ||
} | ||
// Undry this element, but don't put it in the parsed object yet | ||
if (constructor && typeof constructor.unDry === 'function') { | ||
value.undried = constructor.unDry(value.value); | ||
} else { | ||
value.undried = value.value; | ||
} | ||
if (value.drypath) { | ||
undryPaths[value.drypath.join(specialChar)] = value; | ||
} else { | ||
return value.undried; | ||
} | ||
break; | ||
default: | ||
if (typeof value.value !== 'undefined') { | ||
if (undriers[value.dry]) { | ||
value.undried = undriers[value.dry].fnc(this, key, value.value); | ||
} else { | ||
value.undried = value.value; | ||
} | ||
if (value.drypath) { | ||
undryPaths[value.drypath.join(specialChar)] = value; | ||
} else { | ||
return value.undried; | ||
} | ||
} | ||
} | ||
} | ||
if (valType === 'string') { | ||
value = value.replace(safeStartWithSpecialCharRG, '$1' + specialChar) | ||
.replace(escapedSafeSpecialChar, safeSpecialChar); | ||
} | ||
if (reviver == null) { | ||
return value; | ||
} | ||
return reviver.call(this, key, value); | ||
}; | ||
}; | ||
/** | ||
* Regenerate an array | ||
* | ||
* @author Jelle De Loecker <jelle@develry.be> | ||
* @since 0.1.4 | ||
* @version 0.1.4 | ||
* | ||
* @return {Array} | ||
*/ | ||
function regenerateArray(root, current, chain, retrieve, undryPaths) { | ||
var length = current.length, | ||
i; | ||
for (i = 0; i < length; i++) { | ||
// Only regenerate if it's not in the chain | ||
if (chain.indexOf(current[i]) == -1) { | ||
current[i] = regenerate(root, current[i], chain, retrieve, undryPaths); | ||
} | ||
} | ||
return current; | ||
}; | ||
/** | ||
* Regenerate an object | ||
* | ||
* @author Jelle De Loecker <jelle@develry.be> | ||
* @since 0.1.4 | ||
* @version 0.1.4 | ||
* | ||
* @return {Object} | ||
*/ | ||
function regenerateObject(root, current, chain, retrieve, undryPaths) { | ||
var key; | ||
for (key in current) { | ||
if (current.hasOwnProperty(key)) { | ||
// Only regenerate if it's not in the cain | ||
if (chain.indexOf(current[key]) == -1) { | ||
current[key] = regenerate(root, current[key], chain, retrieve, undryPaths); | ||
} | ||
} | ||
} | ||
return current; | ||
}; | ||
/** | ||
* Regenerate a value | ||
* | ||
* @author Jelle De Loecker <jelle@develry.be> | ||
* @since 0.1.4 | ||
* @version 0.1.4 | ||
* | ||
* @return {Mixed} | ||
*/ | ||
function regenerate(root, current, chain, retrieve, undryPaths) { | ||
var temp, | ||
i; | ||
chain.push(current); | ||
if (current instanceof Array) { | ||
return regenerateArray(root, current, chain, retrieve, undryPaths); | ||
} | ||
if (current instanceof String) { | ||
if (current.length) { | ||
if (undryPaths[current]) { | ||
return undryPaths[current].undried; | ||
} | ||
if (retrieve.hasOwnProperty(current)) { | ||
temp = retrieve[current]; | ||
} else { | ||
temp = retrieve[current] = retrieveFromPath(root, current.split(specialChar)); | ||
} | ||
return temp; | ||
} else { | ||
return root; | ||
} | ||
} | ||
if (current instanceof Object) { | ||
return regenerateObject(root, current, chain, retrieve, undryPaths); | ||
} | ||
chain.pop(); | ||
return current; | ||
}; | ||
/** | ||
* Retrieve from path. | ||
* Set the given value, but only if the containing object exists. | ||
* | ||
* @author Jelle De Loecker <jelle@develry.be> | ||
* @since 0.1.4 | ||
* @version 0.1.4 | ||
* | ||
* @return {Mixed} | ||
*/ | ||
function retrieveFromPath(current, keys, value) { | ||
var length = keys.length, | ||
prev, | ||
key, | ||
i; | ||
for (i = 0; i < length; i++) { | ||
// Normalize the key | ||
key = keys[i].replace(safeSpecialCharRG, specialChar); | ||
prev = current; | ||
if (current) { | ||
current = current[key]; | ||
} else { | ||
return undefined; | ||
} | ||
} | ||
if (arguments.length === 3) { | ||
prev[key] = value; | ||
current = value; | ||
} | ||
return current; | ||
}; | ||
/** | ||
* Deep clone an object | ||
@@ -615,131 +25,4 @@ * | ||
*/ | ||
Blast.defineStatic('JSON', 'clone', function clone(obj, custom_method, extra_args, wm) { | ||
Blast.defineStatic('JSON', 'clone', Dry.clone); | ||
var custom_args, | ||
entry_type, | ||
nameType, | ||
entry, | ||
split, | ||
keys, | ||
temp, | ||
len, | ||
i, | ||
target; | ||
if (custom_method instanceof WeakMap) { | ||
wm = custom_method; | ||
custom_method = null; | ||
} else if (!Array.isArray(extra_args)) { | ||
wm = extra_args; | ||
extra_args = null; | ||
} | ||
if (wm == null) { | ||
wm = new WeakMap(); | ||
return clone({'_': obj}, custom_method, wm)['_']; | ||
} | ||
if (Array.isArray(obj)) { | ||
target = []; | ||
} else { | ||
target = {}; | ||
} | ||
if (custom_method) { | ||
custom_args = [wm].concat(extra_args); | ||
} | ||
keys = Object.keys(obj); | ||
len = keys.length; | ||
// Remember the root object and its clone | ||
wm.set(obj, target); | ||
for (i = 0; i < len; i++) { | ||
entry = obj[keys[i]]; | ||
entry_type = typeof entry; | ||
if (entry && (entry_type == 'object' || entry_type == 'function')) { | ||
if (entry_type == 'function' && !driers.Function) { | ||
continue; | ||
} | ||
// If this has been cloned before, use that | ||
if (wm.has(entry)) { | ||
target[keys[i]] = wm.get(entry); | ||
continue; | ||
} | ||
if (entry.constructor) { | ||
nameType = entry.constructor.name; | ||
if (custom_method && entry[custom_method]) { | ||
target[keys[i]] = entry[custom_method].apply(entry, custom_args); | ||
} else if (driers[nameType] != null) { | ||
// Look for a registered drier function | ||
temp = driers[nameType].fnc(obj, keys[i], entry); | ||
if (undriers[nameType]) { | ||
target[keys[i]] = undriers[nameType].fnc(target, keys[i], temp); | ||
} else { | ||
target[keys[i]] = temp; | ||
} | ||
} else if (entry.dryClone) { | ||
// Look for dryClone after | ||
target[keys[i]] = entry.dryClone(wm, custom_method); | ||
} else if (entry.toDry) { | ||
// Perform the toDry function | ||
temp = entry.toDry(); | ||
// Clone the value, | ||
// because returned objects aren't necesarilly cloned yet | ||
temp = clone(temp.value, custom_method, wm); | ||
// Perform the undry function | ||
if (entry.constructor.unDry) { | ||
target[keys[i]] = entry.constructor.unDry(temp); | ||
} else { | ||
// If there is no undry function, the clone will be a simple object | ||
target[keys[i]] = temp; | ||
} | ||
} else if (nameType == 'Date') { | ||
target[keys[i]] = new Date(entry); | ||
} else if (nameType == 'RegExp') { | ||
temp = entry.toString(); | ||
split = temp.match(/^\/(.*?)\/([gim]*)$/); | ||
if (split) { | ||
target[keys[i]] = new RegExp(split[1], split[2]); | ||
} else { | ||
target[keys[i]] = new RegExp(temp); | ||
} | ||
} else if (typeof entry.clone == 'function') { | ||
// If it supplies a clone method, use that | ||
target[keys[i]] = entry.clone(); | ||
} else if (entry.toJSON) { | ||
temp = entry.toJSON(); | ||
if (temp && typeof temp == 'object') { | ||
temp = clone(temp, custom_method, wm); | ||
} | ||
target[keys[i]] = temp; | ||
} else { | ||
target[keys[i]] = clone(entry, custom_method, wm); | ||
} | ||
} else { | ||
target[keys[i]] = clone(entry, custom_method, wm); | ||
} | ||
// Remember this clone for later | ||
wm.set(entry, target[keys[i]]); | ||
} else { | ||
target[keys[i]] = entry; | ||
} | ||
} | ||
return target; | ||
}); | ||
/** | ||
@@ -758,8 +41,19 @@ * Dry it | ||
*/ | ||
Blast.defineStatic('JSON', 'dry', function dry(value, replacer, space) { | ||
var root = {'': value}; | ||
return generateReplacer(root, replacer, space)(root, '', value); | ||
}); | ||
Blast.defineStatic('JSON', 'dry', Dry.stringify); | ||
/** | ||
* Dry it to an object | ||
* | ||
* @author Jelle De Loecker <jelle@develry.be> | ||
* @since 0.1.4 | ||
* @version 0.4.2 | ||
* | ||
* @param {Mixed} value | ||
* @param {Function} replacer | ||
* | ||
* @return {Object} | ||
*/ | ||
Blast.defineStatic('JSON', 'toDryObject', Dry.toObject); | ||
/** | ||
* Register a drier | ||
@@ -775,8 +69,3 @@ * | ||
*/ | ||
Blast.defineStatic('JSON', 'registerDrier', function registerDrier(constructor_name, fnc, options) { | ||
driers[constructor_name] = { | ||
fnc: fnc, | ||
options: options || {} | ||
}; | ||
}); | ||
Blast.defineStatic('JSON', 'registerDrier', Dry.registerDrier); | ||
@@ -794,8 +83,3 @@ /** | ||
*/ | ||
Blast.defineStatic('JSON', 'registerUndrier', function registerUndrier(constructor_name, fnc, options) { | ||
undriers[constructor_name] = { | ||
fnc: fnc, | ||
options: options || {} | ||
}; | ||
}); | ||
Blast.defineStatic('JSON', 'registerUndrier', Dry.registerUndrier); | ||
@@ -811,34 +95,4 @@ /** | ||
*/ | ||
Blast.defineStatic('JSON', 'undry', function undry(text, reviver) { | ||
Blast.defineStatic('JSON', 'undry', Dry.parse); | ||
var undryPaths = {}, | ||
retrieve = {}, | ||
result, | ||
path; | ||
result = JSON.parse(text, generateReviver(reviver, undryPaths)); | ||
if (result == null) { | ||
return result; | ||
} | ||
for (path in undryPaths) { | ||
undryPaths[path].undried = regenerate(result, undryPaths[path].undried, [], retrieve, undryPaths) | ||
} | ||
// Only now can we resolve paths | ||
result = regenerate(result, result, [], retrieve, undryPaths); | ||
// Now we can replace all the undried values | ||
for (path in undryPaths) { | ||
Collection.Object.setPath(result, undryPaths[path].drypath, undryPaths[path].undried); | ||
} | ||
if (result.undried != null && result.dry == 'toDry') { | ||
return result.undried; | ||
} | ||
return result; | ||
}); | ||
/** | ||
@@ -861,2 +115,12 @@ * Safe JSON parsing | ||
/** | ||
* Expose the Dry object | ||
* | ||
* @author Jelle De Loecker <jelle@develry.be> | ||
* @since 0.4.2 | ||
* @version 0.4.2 | ||
* | ||
* @type {Object} | ||
*/ | ||
Blast.defineStatic('JSON', 'Dry', Dry); | ||
}; |
@@ -462,3 +462,3 @@ module.exports = function BlastObject(Blast, Collection, Bound, Obj) { | ||
/** | ||
/** | ||
* Extract form path info | ||
@@ -676,3 +676,3 @@ * | ||
if (!extension) continue; | ||
// Go over every property of the current object | ||
@@ -921,3 +921,3 @@ for (key in extension) { | ||
* @since 0.1.6 | ||
* @version 0.3.8 | ||
* @version 0.4.2 | ||
* | ||
@@ -929,7 +929,12 @@ * @param {Object} obj The object to walk over | ||
*/ | ||
Blast.defineStatic('Object', 'walk', function walk(obj, fnc, limit, seen) { | ||
Blast.defineStatic('Object', 'walk', function walk(obj, fnc, limit, seen, wm) { | ||
var key, | ||
var count, | ||
key, | ||
ret; | ||
if (wm == null) { | ||
wm = new WeakMap(); | ||
} | ||
if (typeof limit != 'number') { | ||
@@ -957,3 +962,5 @@ if (Array.isArray(limit)) { | ||
// Fire the function | ||
ret = fnc(obj[key], key, obj); | ||
if (fnc != null) { | ||
ret = fnc(obj[key], key, obj); | ||
} | ||
@@ -975,7 +982,22 @@ // If explicit false is returned, | ||
if (limit > 0) { | ||
walk(obj[key], fnc, limit - 1, seen); | ||
walk(obj[key], fnc, limit - 1, seen, wm); | ||
} | ||
} else { | ||
count = wm.get(obj[key]); | ||
if (!count) { | ||
count = 1; | ||
} else { | ||
count++; | ||
} | ||
wm.set(obj[key], count); | ||
} | ||
} | ||
} | ||
return { | ||
seen : seen, | ||
wm : wm | ||
}; | ||
}); | ||
@@ -982,0 +1004,0 @@ |
{ | ||
"name": "protoblast", | ||
"description": "Native object expansion library", | ||
"version": "0.4.1", | ||
"version": "0.4.2", | ||
"author": "Jelle De Loecker <jelle@develry.be>", | ||
@@ -14,2 +14,5 @@ "keywords": [ | ||
], | ||
"dependencies": { | ||
"json-dry" : "~1.0.0" | ||
}, | ||
"repository": "skerit/protoblast", | ||
@@ -16,0 +19,0 @@ "homepage": "https://protoblast.develry.be/", |
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
475364
1
19824
+ Addedjson-dry@~1.0.0
+ Addedjson-dry@1.0.12(transitive)