Socket
Socket
Sign inDemoInstall

protoblast

Package Overview
Dependencies
Maintainers
1
Versions
102
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

protoblast - npm Package Compare versions

Comparing version 0.8.8 to 0.8.9

4

CHANGELOG.md

@@ -0,1 +1,5 @@

## 0.8.9 (2023-05-09)
* Add `Function#instrumentMethod()` to add instrumentation to existing methods
## 0.8.8 (2023-04-20)

@@ -2,0 +6,0 @@

6

lib/benchmark.js

@@ -69,3 +69,3 @@ var performanceNow,

// Default test sizes
Blast.benchmark_sync_sizes = [1, 10, 120, 120, 240, 240, 240, 480];
Blast.benchmark_sync_sizes = [5, 10, 120, 120, 240, 240, 240, 480];
Blast.benchmark_async_sizes = [120, 120, 120, 240, 240, 480];

@@ -187,4 +187,4 @@

// Only the first 5 tests are mandatory
if (r > 4) {
// Only the first 6 tests are mandatory
if (r > 5) {
// If the last sample is not the best, stop further tests

@@ -191,0 +191,0 @@ if (samples.indexOf(Bound.Array.max(samples)) !== r) {

@@ -1224,2 +1224,18 @@ const finished_constitutors = new WeakMap(),

/**
* Instrument a static method
*
* @author Jelle De Loecker <jelle@elevenways.be>
* @since 0.8.9
* @version 0.8.9
*
* @param {Function} constructor Constructor to modify prototype of
* @param {String} method_name The name of the method to instrument
* @param {Function} before Function to call before executing the main method
* @param {Function} after Function to call after executing the main method
*/
defClassMethod(function instrumentStaticMethod(constructor, method_name, before, after) {
return Blast.addMethodInstrumentation(constructor, method_name, before, after);
});
/**
* Set a static method on the given constructor.

@@ -1373,2 +1389,18 @@ * Can also be used to set a static property. This won't fire an error

/**
* Instrument a method
*
* @author Jelle De Loecker <jelle@elevenways.be>
* @since 0.8.9
* @version 0.8.9
*
* @param {Function} constructor Constructor to modify prototype of
* @param {String} method_name The name of the method to instrument
* @param {Function} before Function to call before executing the main method
* @param {Function} after Function to call after executing the main method
*/
defClassMethod(function instrumentMethod(constructor, method_name, before, after) {
return Blast.addMethodInstrumentation(constructor.prototype, method_name, before, after);
});
/**
* Set a prototype method on the given constructor

@@ -1378,3 +1410,3 @@ *

* @since 0.1.3
* @version 0.6.1
* @version 0.8.9
*

@@ -1389,7 +1421,5 @@ * @param {Function} constructor Constructor to modify prototype of

var existing,
method,
let method,
proto,
keys,
i;
keys;

@@ -1414,2 +1444,5 @@ if (typeof constructor === 'function') {

let has_typed_wrapper,
i;
for (i = 0; i < keys.length; i++) {

@@ -1420,7 +1453,9 @@

has_typed_wrapper = Blast.hasSignatureWrapperMethod(proto, keys[i]);
// Get a possible existing value
existing = Blast.Bound.Object.getPropertyDescriptor(proto, keys[0]);
let existing = Blast.Bound.Object.getPropertyDescriptor(proto, keys[0]);
// If there already was something here, set it as this method's parent
if (existing && typeof existing.value !== 'undefined') {
if (!has_typed_wrapper && existing && typeof existing.value !== 'undefined') {
if (typeof method == 'object') {

@@ -1441,4 +1476,5 @@ Blast.defineValue(method.value, 'super', existing.value);

// Now set the method on the prototype
if (typeof method == 'function') {
if (Blast.hasSignatureWrapperMethod(proto, keys[i])) {
Blast.addCatchallMethod(proto, keys[i], method);
} else if (typeof method == 'function') {
Blast.defineValue(proto, keys[i], method);

@@ -1445,0 +1481,0 @@ } else {

@@ -533,2 +533,3 @@ const TYPE_WRAPPER = Symbol('type_wrapper'),

*
* @param {TypesCollection} types_collection
* @param {SignatureType[]} argument_types

@@ -538,3 +539,4 @@ * @param {SignatureType} return_type

*/
constructor(argument_types, return_type, fnc) {
constructor(types_collection, argument_types, return_type, fnc) {
this.types_collection = types_collection;
this.argument_types = argument_types;

@@ -551,2 +553,10 @@ this.return_type = return_type;

}
if (!fnc.super) {
const that = this;
Blast.defineValue(fnc, 'super', function _super(...args) {
return that.types_collection.doSuper(this, args);
});
}
}

@@ -650,2 +660,244 @@

/**
* Does the given context have a signature wrapper?
*
* @author Jelle De Loecker <jelle@elevenways.be>
* @since 0.8.9
* @version 0.8.9
*
* @param {Object} context
*
* @return {Boolean}
*/
Blast.hasSignatureWrapperMethod = function hasSignatureWrapperMethod(context, name) {
if (!context) {
throw new Error('Invalid context passed to getSignatureWrapperMethod');
}
let value = context[name];
if (!value) {
return false;
}
return value[TYPE_WRAPPER] || false;
};
/**
* The class to keep track of the signature wrapper methods
*
* @author Jelle De Loecker <jelle@elevenways.be>
* @since 0.8.9
* @version 0.8.9
*/
class TypesCollection {
catchall = null;
lengths = [];
before = [];
after = [];
has_before_instrumentation = false;
has_after_instrumentation = false;
is_static = false;
wrapper_method = null;
constructor(context, name) {
this.context = context;
this.name = name;
if (typeof context == 'function') {
this.parent_context = context.super;
this.is_static = true;
} else if (context.constructor) {
this.parent_context = context.constructor.super?.prototype;
} else {
this.parent_context = null;
}
}
setCatchAll(method) {
this.catchall = method;
if (this.wrapper_method.super) {
const that = this;
Blast.defineValue(method, 'super', function _super(...args) {
let super_method = that.wrapper_method.super;
if (super_method && super_method[TYPE_WRAPPER]) {
return super_method[TYPES].executeWithArguments(this, args, false);
} else {
return super_method.apply(this, args);
}
});
}
}
addBeforeInstrumentation(method) {
this.has_before_instrumentation = true;
this.before.push(method);
}
addAfterInstrumentation(method) {
this.has_after_instrumentation = true;
this.after.push(method);
}
doBeforeInstrumentation(instance, args) {
if (this.has_before_instrumentation) {
let i;
for (i = 0; i < this.before.length; i++) {
this.before[i](instance, args);
}
}
if (this.parent_context) {
let parent = this.parent_context[this.name];
if (parent) {
let types = parent[TYPES];
if (types && types != this) {
types.doBeforeInstrumentation(instance, args);
}
}
}
}
doAfterInstrumentation(instance, args, result) {
if (this.has_after_instrumentation) {
let i;
for (i = 0; i < this.after.length; i++) {
this.after[i](instance, args, result);
}
}
if (this.parent_context) {
let parent = this.parent_context[this.name];
if (parent) {
let types = parent[TYPES];
if (types && types != this) {
types.doAfterInstrumentation(instance, args, result);
}
}
}
}
/**
* Find the correct method for the given arguments
*
* @author Jelle De Loecker <jelle@elevenways.be>
* @since 0.7.25
* @version 0.8.9
*
* @param {Array} args
*
* @return {Object}
*/
findCorrectSignature(args) {
let length = args.length,
signatures = this[length],
result = false;
if (signatures) {
result = testSignatures(signatures, args, length);
}
if (!result) {
let test_length,
i;
for (i = 0; i < this.lengths.length; i++) {
test_length = this.lengths[i];
if (test_length > length) {
signatures = this[test_length];
if (signatures) {
result = testSignatures(signatures, args, length);
if (result) {
break;
}
}
}
}
}
return result;
}
executeWithArguments(instance, args, do_instrumentation) {
let signature = this.findCorrectSignature(args),
result;
if (do_instrumentation) {
this.doBeforeInstrumentation(instance, args);
}
if (!signature) {
let super_method = this.wrapper_method.super;
if (super_method) {
if (super_method[TYPE_WRAPPER]) {
signature = super_method[TYPES].findCorrectSignature(args);
}
}
if (signature) {
result = signature.execute(instance, args);
} else {
if (this.catchall) {
result = this.catchall.apply(instance, args);
} else if (super_method) {
if (super_method[TYPE_WRAPPER]) {
result = super_method[TYPES].executeWithArguments(instance, args, false);
} else {
result = super_method.apply(instance, args);
}
} else {
throw new TypeError('Failed to find "' + this.name + '" method matching signature `' + argsToSignatureString(args) + '`');
}
}
} else {
result = signature.execute(instance, args);
}
if (do_instrumentation) {
this.doAfterInstrumentation(instance, args, result);
}
return result;
}
doSuper(instance, args) {
let super_method = this.parent_context?.[this.name];
if (!super_method) {
throw new Error('No super method is available');
}
if (super_method[TYPE_WRAPPER]) {
return super_method[TYPES].executeWithArguments(instance, args, false);
} else {
return super_method.apply(instance, args);
}
}
}
/**
* Get/create the typed wrapper method

@@ -656,3 +908,3 @@ * which will delegate calls to the correct signature

* @since 0.7.25
* @version 0.8.1
* @version 0.8.9
*

@@ -669,2 +921,3 @@ * @param {Object} context

let descriptor = Object.getOwnPropertyDescriptor(context, name),
super_types = false,
current_method = descriptor?.value,

@@ -677,2 +930,3 @@ wrapper_method,

super_method = context[name];
super_types = super_method[TYPES];
}

@@ -686,26 +940,16 @@ } else {

if (!wrapper_method) {
let types_by_length = {
lengths: [],
};
let types_collection = new TypesCollection(context, name);
wrapper_method = Fn.create(name, function _doCorrectTypeMethod(...args) {
return types_collection.executeWithArguments(this, args, true);
});
let signature = findCorrectSignature(types_by_length, args);
types_collection.wrapper_method = wrapper_method;
if (!signature) {
if (wrapper_method.super) {
return wrapper_method.super.apply(this, args);
}
if (current_method) {
types_collection.setCatchAll(current_method);
}
if (current_method) {
return current_method.apply(this, args);
}
throw new TypeError('Failed to find "' + name + '" method matching signature `' + argsToSignatureString(args) + '`');
}
return signature.execute(this, args);
});
wrapper_method[TYPES] = types_by_length;
wrapper_method[TYPES] = types_collection;
wrapper_method[TYPE_WRAPPER] = true;

@@ -723,3 +967,55 @@

function callFunctions() {
}
/**
* Instrument an existing method
*
* @author Jelle De Loecker <jelle@elevenways.be>
* @since 0.8.9
* @version 0.8.9
*
* @param {Object} context Holder of the method
* @param {String} method_name The name of the method to instrument
* @param {Function} before Function to call before executing the main method
* @param {Function} after Function to call after executing the main method
*/
Blast.addMethodInstrumentation = function addMethodInstrumentation(context, method_name, before, after) {
let wrapper = Blast.getSignatureWrapperMethod(context, method_name),
types_collection = wrapper[TYPES];
if (before) {
types_collection.addBeforeInstrumentation(before);
}
if (after) {
types_collection.addAfterInstrumentation(after);
}
};
/**
* Add a catchall method
*
* @author Jelle De Loecker <jelle@elevenways.be>
* @since 0.8.9
* @version 0.8.9
*
* @param {Object} context
* @param {String} name
* @param {Function} fnc
*/
Blast.addCatchallMethod = function addCatchallMethod(context, name, fnc) {
let wrapper = Blast.getSignatureWrapperMethod(context, name);
let config = wrapper[TYPES];
config.setCatchAll(fnc);
return fnc;
};
/**
* Add a typed method

@@ -758,9 +1054,9 @@ *

wrapper = Blast.getSignatureWrapperMethod(context, name),
types_by_length = wrapper[TYPES],
signatures = types_by_length[length];
types_collection = wrapper[TYPES],
signatures = types_collection[length];
if (!signatures) {
signatures = [];
types_by_length[length] = signatures;
types_by_length.lengths.push(length);
types_collection[length] = signatures;
types_collection.lengths.push(length);
} else if (findDuplicateSignature(signatures, argument_types)) {

@@ -770,3 +1066,3 @@ throw new Error('Tried to create a duplicate signature "' + name + '"');

let signature = new MethodSignature(argument_types, return_types, fnc);
let signature = new MethodSignature(types_collection, argument_types, return_types, fnc);

@@ -828,49 +1124,2 @@ signatures.push(signature);

/**
* Find the correct method for the given arguments
*
* @author Jelle De Loecker <jelle@elevenways.be>
* @since 0.7.25
* @version 0.7.25
*
* @param {Object} types_by_length
* @param {Array} args
*
* @return {Object}
*/
function findCorrectSignature(types_by_length, args) {
let length = args.length,
signatures = types_by_length[length],
result;
if (signatures) {
result = testSignatures(signatures, args, length);
}
if (!result) {
let test_length,
i;
for (i = 0; i < types_by_length.lengths.length; i++) {
test_length = types_by_length.lengths[i];
if (test_length > length) {
signatures = types_by_length[test_length];
if (signatures) {
result = testSignatures(signatures, args, length);
if (result) {
break;
}
}
}
}
}
return result;
}
/**
* Find the correct signature for the given arguments

@@ -877,0 +1126,0 @@ *

{
"name": "protoblast",
"description": "Native object expansion library",
"version": "0.8.8",
"version": "0.8.9",
"author": "Jelle De Loecker <jelle@elevenways.be>",

@@ -6,0 +6,0 @@ "keywords": [

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc