protoblast
Advanced tools
Comparing version 0.5.11 to 0.6.0
@@ -0,1 +1,16 @@ | ||
## 0.6.0 (2018-08-27) | ||
* Make `Pledge` polyfill for `Promise` | ||
* Add `Pledge.after(n, val)`, which returns a pledge that resolves after n milliseconds | ||
* Add `Pledge#race(other_pledge)` | ||
* Add new `Array#findByPath(obj)` signature | ||
* Add `Object.sizeof(input)` to get the size of a variable in bytes | ||
* Add `Cache` class | ||
* Allow passing a descriptor to `Blast.defineValue` | ||
* Add `Function#decorateMethod(decorator, key, method)` | ||
* Add `Date#timeAgo(settings)` method | ||
* `Object.checksum()` will only checksum a function's source string | ||
* Add `Blast.Decorators.memoize` decorator | ||
* Make `Pledge#handleCallback()` an alias of `Pledge#done()` | ||
## 0.5.11 (2018-07-14) | ||
@@ -2,0 +17,0 @@ |
@@ -835,3 +835,3 @@ module.exports = function BlastArray(Blast, Collection, Bound, Obj) { | ||
* @since 0.3.8 | ||
* @version 0.3.8 | ||
* @version 0.6.0 | ||
* | ||
@@ -845,4 +845,7 @@ * @param {String} path | ||
var length, | ||
var entries, | ||
results, | ||
length, | ||
entry, | ||
key, | ||
i; | ||
@@ -852,2 +855,42 @@ | ||
if (path && typeof path == 'object') { | ||
// Do all keys in the path | ||
for (key in path) { | ||
entries = []; | ||
// Iterate over all entries | ||
for (i = 0; i < length; i++) { | ||
entry = Obj.path(this[i], key); | ||
// If it matches, add it to the entries array | ||
if (entry == path[key]) { | ||
entries.push(this[i]); | ||
} | ||
} | ||
// If nothing was found, return early | ||
if (!entries.length) { | ||
return; | ||
} | ||
if (results) { | ||
results = Bound.Array.shared(results, entries); | ||
} else { | ||
results = entries; | ||
} | ||
// If the results still is empty we can return already | ||
if (!results.length) { | ||
return; | ||
} | ||
} | ||
if (!results || !results.length) { | ||
return; | ||
} else { | ||
return results[0]; | ||
} | ||
} | ||
for (i = 0; i < length; i++) { | ||
@@ -854,0 +897,0 @@ entry = Obj.path(this[i], path); |
@@ -351,3 +351,3 @@ module.exports = function BlastBenchmark(Blast, Collection, Bound) { | ||
* @since 0.1.2 | ||
* @version 0.1.2 | ||
* @version 0.6.0 | ||
* | ||
@@ -364,3 +364,4 @@ * @param {Function} fn | ||
result, | ||
args; | ||
args, | ||
i; | ||
@@ -367,0 +368,0 @@ if (benchRunning > 0) { |
129
lib/date.js
@@ -308,2 +308,15 @@ module.exports = function BlastDate(Blast, Collection, Bound, Obj) { | ||
/** | ||
* Calculate the bytesize of a date | ||
* | ||
* @author Jelle De Loecker <jelle@develry.be> | ||
* @since 0.6.0 | ||
* @version 0.6.0 | ||
* | ||
* @return {Number} | ||
*/ | ||
Blast.definePrototype('Date', Blast.sizeofSymbol, function calculateSizeof() { | ||
return 96; | ||
}); | ||
/** | ||
* Return a clone of the current date | ||
@@ -713,2 +726,118 @@ * | ||
}); | ||
/** | ||
* Time ago strings | ||
* | ||
* @author Jelle De Loecker <jelle@develry.be> | ||
* @since 0.6.0 | ||
* @version 0.6.0 | ||
* | ||
* @return {String} | ||
*/ | ||
Blast.definePrototype('Date', 'time_ago_settings', { | ||
now : 'just now', | ||
seconds : '%d seconds', | ||
minute : 'a minute', | ||
minutes : '%d minutes', | ||
hour : 'an hour', | ||
hours : '%d hours', | ||
day : 'a day', | ||
days : '%d days', | ||
month : 'a month', | ||
months : '%d months', | ||
year : 'a year', | ||
years : '%d years', | ||
ago : 'ago', | ||
from : 'from now', | ||
separator : ' and ' | ||
}); | ||
function numberString(string, number) { | ||
return string.replace(/%d/i, number); | ||
} | ||
/** | ||
* Return a time ago string | ||
* | ||
* @author Jelle De Loecker <jelle@develry.be> | ||
* @since 0.6.0 | ||
* @version 0.6.0 | ||
* | ||
* @param {Object} settings | ||
* | ||
* @return {String} | ||
*/ | ||
Blast.definePrototype('Date', 'timeAgo', function timeAgo(settings) { | ||
var difference = Date.now() - this, | ||
seconds = Math.abs(difference) / 1000, | ||
minutes = seconds / 60, | ||
hours = minutes / 60, | ||
days = ~~(hours / 24), | ||
years = ~~(days / 365), | ||
result = '', | ||
future = difference < 0, | ||
months, | ||
temp; | ||
days = days % 365; | ||
months = Math.round(days / 30); | ||
minutes = ~~minutes; | ||
seconds = Math.round(seconds); | ||
hours = ~~hours; | ||
if (!settings) { | ||
settings = this.time_ago_settings; | ||
} else { | ||
settings = Object.assign({}, this.time_ago_settings, settings); | ||
} | ||
if (years == 1) { | ||
result = numberString(settings.year, 1); | ||
} else if (years > 1) { | ||
result = numberString(settings.years, years); | ||
} | ||
if (result) result += settings.separator; | ||
if (months == 1) { | ||
result += numberString(settings.month, 1); | ||
days = days % 30; | ||
} else if (months > 1) { | ||
result += numberString(settings.months, months); | ||
days = days % 30; | ||
} | ||
if (!years) { | ||
if (result) result += settings.separator; | ||
if (days == 1) { | ||
result += numberString(settings.day, 1); | ||
} else if (days > 1) { | ||
result += numberString(settings.days, days); | ||
} else if (hours == 1) { | ||
result += numberString(settings.hour, 1); | ||
} else if (hours > 1) { | ||
result += numberString(settings.hours, hours); | ||
} else if (minutes == 1) { | ||
result += numberString(settings.minute, 1); | ||
} else if (minutes > 1) { | ||
result += numberString(settings.minutes, minutes); | ||
} else if (future || seconds > 30) { | ||
result += numberString(settings.seconds, seconds); | ||
} else if (!result) { | ||
return numberString(settings.now, seconds); | ||
} | ||
} | ||
result += ' '; | ||
if (future) { | ||
result += settings.from; | ||
} else { | ||
result += settings.ago; | ||
} | ||
return result; | ||
}); | ||
}; |
@@ -992,3 +992,3 @@ module.exports = function BlastInheritance(Blast, Collection) { | ||
* @since 0.1.3 | ||
* @version 0.1.4 | ||
* @version 0.6.0 | ||
* | ||
@@ -1036,3 +1036,7 @@ * @param {Function} constructor Constructor to modify prototype of | ||
if (typeof existing !== 'undefined') { | ||
Blast.defineValue(method, 'super', existing); | ||
if (typeof method == 'object') { | ||
Blast.defineValue(method.value, 'super', existing); | ||
} else { | ||
Blast.defineValue(method, 'super', existing); | ||
} | ||
} | ||
@@ -1049,3 +1053,7 @@ } | ||
// Now set the method on the prototype | ||
Blast.defineValue(proto, keys[i], method); | ||
if (typeof method == 'function') { | ||
Blast.defineValue(proto, keys[i], method); | ||
} else { | ||
Blast.defineValue(proto, keys[i], null, method); | ||
} | ||
} | ||
@@ -1057,2 +1065,60 @@ | ||
/** | ||
* Set & decorate a method | ||
* | ||
* @author Jelle De Loecker <jelle@develry.be> | ||
* @since 0.6.0 | ||
* @version 0.6.0 | ||
* | ||
* @param {Function} constructor Constructor to modify prototype of | ||
* @param {Function} decorator The decorator to apply | ||
* @param {String} key Name to use (defaults to method name) | ||
* @param {Function} method The method to set | ||
* | ||
* @return {Function} | ||
*/ | ||
Blast.defineStatic('Function', 'decorateMethod', function decorateMethod(constructor, decorator, key, method) { | ||
var options | ||
if (typeof key == 'function') { | ||
method = key; | ||
key = method.name; | ||
} | ||
options = { | ||
kind : 'method', | ||
key : key, | ||
placement : 'prototype', | ||
descriptor : { | ||
value : method | ||
} | ||
}; | ||
// Get the new options from the decorator | ||
options = decorator(options); | ||
return applyDecoration(constructor, key, options); | ||
}); | ||
/** | ||
* Apply a decoration object | ||
* | ||
* @author Jelle De Loecker <jelle@develry.be> | ||
* @since 0.6.0 | ||
* @version 0.6.0 | ||
* | ||
* @param {Function} constructor | ||
* @param {String|Symbol} key | ||
* @param {Object} options | ||
*/ | ||
function applyDecoration(constructor, key, options) { | ||
if (options.kind == 'method') { | ||
return Fn.setMethod(constructor, key, options.descriptor); | ||
} | ||
throw new Error('Decorating ' + options.kind + ' is not yet implemented'); | ||
} | ||
/** | ||
* Set a getter on the given prototype, or a simple value | ||
@@ -1356,2 +1422,17 @@ * | ||
/** | ||
* Set a decorated prototype method | ||
* | ||
* @author Jelle De Loecker <jelle@develry.be> | ||
* @since 0.6.0 | ||
* @version 0.6.0 | ||
* | ||
* @param {Function} decorator | ||
* @param {String} key | ||
* @param {Function} method | ||
*/ | ||
var protoDecorateMethod = function decorateMethod(decorator, key, method) { | ||
return Fn.decorateMethod(this, decorator, key, method); | ||
}; | ||
/** | ||
* Set a prototype property | ||
@@ -1474,2 +1555,3 @@ * | ||
Blast.defineValue(newConstructor, 'prepareProperty', protoPrepareProperty); | ||
Blast.defineValue(newConstructor, 'decorateMethod', protoDecorateMethod); | ||
Blast.defineValue(newConstructor, 'staticCompose', protoStaticCompose); | ||
@@ -1492,2 +1574,3 @@ Blast.defineValue(newConstructor, 'getChildren', protoGetChildren); | ||
Blast.definePrototype('Function', 'prepareProperty', protoPrepareProperty); | ||
Blast.definePrototype('Function', 'decorateMethod', protoDecorateMethod); | ||
Blast.definePrototype('Function', 'staticCompose', protoStaticCompose); | ||
@@ -1494,0 +1577,0 @@ Blast.definePrototype('Function', 'getChildren', protoGetChildren); |
@@ -226,2 +226,3 @@ module.exports = function BlastInitLoader(modifyPrototype) { | ||
'Math', | ||
'Map', | ||
'Pledge', | ||
@@ -232,3 +233,4 @@ 'SeededRng', | ||
'String', | ||
'RURL' | ||
'RURL', | ||
'Cache' | ||
]; | ||
@@ -305,20 +307,42 @@ | ||
* @since 0.1.0 | ||
* @version 0.3.5 | ||
* @version 0.6.0 | ||
* | ||
* @param {Object} target The object to add the property to | ||
* @param {String} name The name of the property | ||
* @param {Object} value The value of the property | ||
* @param {Object} target The object to add the property to | ||
* @param {String} name The name of the property | ||
* @param {Object} value The value of the property | ||
* @param {Object} descriptor Optional descriptor | ||
*/ | ||
Blast.defineProperty(Collection.Object, 'defineValue', { | ||
value: function defineValue(target, name, value, enumerable) { | ||
value: function defineValue(target, name, value, descriptor) { | ||
var i; | ||
if (typeof enumerable == 'undefined') { | ||
enumerable = false; | ||
if (descriptor == null) { | ||
descriptor = {}; | ||
} else if (typeof descriptor == 'boolean') { | ||
descriptor = { | ||
enumerable : descriptor | ||
}; | ||
} | ||
// Things are not enumerable by default | ||
if (descriptor.enumerable == null) { | ||
descriptor.enumerable = false; | ||
} | ||
if (descriptor.configurable == null) { | ||
descriptor.configurable = true; | ||
} | ||
if (descriptor.writable == null) { | ||
descriptor.writable = true; | ||
} | ||
if (typeof descriptor.value == 'undefined') { | ||
descriptor.value = value; | ||
} | ||
if (Array.isArray(name)) { | ||
for (i = 0; i < name.length; i++) { | ||
Blast.defineValue(target, name[i], value, enumerable); | ||
Blast.defineValue(target, name[i], null, descriptor); | ||
} | ||
@@ -333,8 +357,7 @@ return; | ||
Object.defineProperty(target, name, { | ||
value: value, | ||
enumerable: enumerable, | ||
configurable: true, | ||
writable: true | ||
}); | ||
if (!descriptor || typeof descriptor != 'object') { | ||
throw new TypeError('Invalid descriptor for key "' + name + '"'); | ||
} | ||
Object.defineProperty(target, name, descriptor); | ||
} | ||
@@ -1085,2 +1108,5 @@ }); | ||
// Load the predefined decorators | ||
Blast.require('function_decorators'); | ||
// Require the scripts | ||
@@ -1087,0 +1113,0 @@ Names.forEach(function eachName(name) { |
@@ -238,2 +238,104 @@ module.exports = function BlastObject(Blast, Collection, Bound, Obj) { | ||
/** | ||
* Calculate the size of a variable | ||
* | ||
* @author Jelle De Loecker <jelle@develry.be> | ||
* @since 0.6.0 | ||
* @version 0.6.0 | ||
* | ||
* @param {Mixed} input | ||
* | ||
* @return {Number} | ||
*/ | ||
Blast.defineStatic('Object', 'sizeof', function sizeof(input) { | ||
return calculate_sizeof(input, new WeakMap()); | ||
}); | ||
/** | ||
* Calculate the size of a variable | ||
* | ||
* @author Jelle De Loecker <jelle@develry.be> | ||
* @since 0.6.0 | ||
* @version 0.6.0 | ||
* | ||
* @param {Mixed} input | ||
* @param {WeakMap} weak_map | ||
* | ||
* @return {Number} | ||
*/ | ||
function calculate_sizeof(input, weak_map) { | ||
var bytes, | ||
type = typeof input, | ||
key; | ||
if (type == 'string') { | ||
return input.length * 2; | ||
} else if (type == 'number') { | ||
return 8; | ||
} else if (type == 'boolean') { | ||
return 4; | ||
} else if (type == 'symbol') { | ||
return (input.toString().length - 8) * 2; | ||
} else if (input == null) { | ||
return 0; | ||
} | ||
// If this has already been seen, skip the actual value | ||
if (weak_map.get(input)) { | ||
return 0; | ||
} | ||
weak_map.set(input, true); | ||
if (typeof input[Blast.sizeofSymbol] == 'function') { | ||
try { | ||
return input[Blast.sizeofSymbol](); | ||
} catch (err) { | ||
// Continue; | ||
} | ||
} | ||
bytes = 0; | ||
if (Array.isArray(input)) { | ||
type = 'array'; | ||
} else if (Blast.isNode && Buffer.isBuffer(input)) { | ||
return input.length; | ||
} | ||
for (key in input) { | ||
// Skip properties coming from the prototype | ||
if (!Object.hasOwnProperty.call(input, key)) { | ||
continue; | ||
} | ||
// Each entry is a reference to a certain place in the memory, | ||
// on 64bit devices this will be 8 bytes | ||
bytes += 8; | ||
if (type == 'array' && Number(key) > -1) { | ||
// Don't count array indices | ||
} else { | ||
bytes += key.length * 2; | ||
} | ||
bytes += calculate_sizeof(input[key], weak_map); | ||
} | ||
return bytes; | ||
} | ||
/** | ||
* Create the symbol for the sizeof method | ||
* | ||
* @author Jelle De Loecker <jelle@develry.be> | ||
* @since 0.6.0 | ||
* @version 0.6.0 | ||
* | ||
* @type {Symbol} | ||
*/ | ||
Blast.defineStatic(Blast, 'sizeofSymbol', Symbol('sizeof')); | ||
/** | ||
* Flatten an object | ||
@@ -1244,3 +1346,3 @@ * | ||
* @since 0.1.3 | ||
* @version 0.5.10 | ||
* @version 0.6.0 | ||
* | ||
@@ -1260,3 +1362,3 @@ * @param {Object|Array} obj The object to checksum | ||
names, | ||
stemp, | ||
ident, | ||
type, | ||
@@ -1298,2 +1400,10 @@ temp, | ||
if (type == 'function') { | ||
type = 'string'; | ||
obj = String(obj); | ||
ident = 'F'; | ||
} else { | ||
ident = 'S'; | ||
} | ||
// Simple primitive checksums | ||
@@ -1309,3 +1419,3 @@ if (type == 'string') { | ||
return 'S' + length + '-' + Bound.String.checksum(obj, 0, split_length).toString(36) + Bound.String.checksum(obj, split_length).toString(36); | ||
return ident + length + '-' + Bound.String.checksum(obj, 0, split_length).toString(36) + Bound.String.checksum(obj, split_length).toString(36); | ||
} else if (type == 'number') { | ||
@@ -1383,2 +1493,4 @@ return 'N' + obj; | ||
} | ||
} else if (typeof val == 'symbol') { | ||
val = val.toString(); | ||
} | ||
@@ -1385,0 +1497,0 @@ } |
@@ -29,2 +29,7 @@ module.exports = function BlastPledge(Blast, Collection) { | ||
// If there are no Promises here, use Pledge as a polyfill | ||
if (typeof Promise == 'undefined') { | ||
Blast.Globals.Promise = Pledge; | ||
} | ||
/** | ||
@@ -202,2 +207,26 @@ * The initial state is 0 (pending) | ||
/** | ||
* Create a pledge which resolves after n milliseconds | ||
* | ||
* @author Jelle De Loecker <jelle@develry.be> | ||
* @since 0.6.0 | ||
* @version 0.6.0 | ||
* | ||
* @param {Number} n | ||
* @param {Mixed} value | ||
* | ||
* @return {Pledge} | ||
*/ | ||
Pledge.setStatic(function after(n, value) { | ||
var pledge = new Pledge(), | ||
id; | ||
id = setTimeout(function doResolve() { | ||
pledge.resolve(value); | ||
}, n); | ||
return pledge; | ||
}); | ||
/** | ||
* Start the executor | ||
@@ -564,5 +593,5 @@ * | ||
* @since 0.5.0 | ||
* @version 0.5.6 | ||
* @version 0.6.0 | ||
*/ | ||
Pledge.setMethod(function handleCallback(callback) { | ||
Pledge.setMethod(['done', 'handleCallback'], function done(callback) { | ||
@@ -579,3 +608,3 @@ if (!callback) { | ||
if (!this || !this.then) { | ||
return callback(null, this); | ||
return Blast.nextTick(callback, null, null, this); | ||
} | ||
@@ -590,3 +619,17 @@ | ||
/** | ||
* Race this pledge with another one | ||
* | ||
* @author Jelle De Loecker <jelle@develry.be> | ||
* @since 0.6.0 | ||
* @version 0.6.0 | ||
* | ||
* @param {Pledge} contestant | ||
*/ | ||
Pledge.setMethod(function race(contestant) { | ||
var contest = Pledge.race([this].concat(contestant)); | ||
return contest; | ||
}); | ||
Blast.defineClass('Pledge', Pledge); | ||
}; |
@@ -97,2 +97,22 @@ module.exports = function BlastRegExp(Blast, Collection) { | ||
/** | ||
* Calculate the bytesize of a regular expression | ||
* | ||
* @author Jelle De Loecker <jelle@develry.be> | ||
* @since 0.6.0 | ||
* @version 0.6.0 | ||
* | ||
* @return {Number} | ||
*/ | ||
Blast.definePrototype('RegExp', Blast.sizeofSymbol, function calculateSizeof() { | ||
var result = 16; | ||
if (this.source) { | ||
result += this.source.length * 2; | ||
} | ||
return result; | ||
}); | ||
/** | ||
* Return the pattern. | ||
@@ -99,0 +119,0 @@ * |
@@ -1196,3 +1196,3 @@ module.exports = function BlastString(Blast, Collection, Bound, Obj) { | ||
* @since 0.0.1 | ||
* @version 0.3.10 | ||
* @version 0.6.0 | ||
* | ||
@@ -1206,4 +1206,3 @@ * @param {Number} start | ||
var str = this, | ||
crc = 0 ^ (-1), | ||
var crc = -1, | ||
i; | ||
@@ -1216,7 +1215,7 @@ | ||
if (end == null) { | ||
end = str.length; | ||
end = this.length; | ||
} | ||
for (i = start; i < end; i++ ) { | ||
crc = (crc >>> 8) ^ crc32table[(crc ^ str.charCodeAt(i)) & 0xFF]; | ||
crc = (crc >>> 8) ^ crc32table[(crc ^ this.charCodeAt(i)) & 0xFF]; | ||
} | ||
@@ -1223,0 +1222,0 @@ |
@@ -18,3 +18,3 @@ module.exports = function BlastSymbol(Blast, Collection, Bound, Obj) { | ||
* @since 0.5.11 | ||
* @version 0.5.11 | ||
* @version 0.6.0 | ||
* | ||
@@ -32,3 +32,3 @@ * @param {String} description | ||
// Create the actual symbol | ||
symbol = Obj.create(HiddenSymbol.prototype); | ||
symbol = Object.create(HiddenSymbol.prototype); | ||
@@ -35,0 +35,0 @@ // Make sure the description is a string |
{ | ||
"name": "protoblast", | ||
"description": "Native object expansion library", | ||
"version": "0.5.11", | ||
"version": "0.6.0", | ||
"author": "Jelle De Loecker <jelle@develry.be>", | ||
@@ -6,0 +6,0 @@ "keywords": [ |
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
569109
47
23245