protoblast
Advanced tools
Comparing version 0.8.17 to 0.8.18
@@ -0,1 +1,9 @@ | ||
## 0.8.18 (2024-01-19) | ||
* Fix `Magic` class not passing constructor arguments properly | ||
* Remove original child class form `children` property when creating a new child class in the same namespace | ||
* Fix class constitutors not being propagated to already existing children | ||
* Add `Array#sortTopological(id_path, dependencies_path)` | ||
* Add `Blast.executeAfterLoadingCycle(task)` which will put Protoblast in an unloaded state if needed and execute the task after the library becomes loaded again. | ||
## 0.8.17 (2024-01-10) | ||
@@ -2,0 +10,0 @@ |
131
lib/array.js
@@ -679,2 +679,133 @@ const defStat = Blast.createStaticDefiner('Array'), | ||
/** | ||
* Do a topological sort in-place | ||
* | ||
* @author Jelle De Loecker <jelle@elevenways.be> | ||
* @since 0.8.18 | ||
* @version 0.8.18 | ||
* | ||
* @param {string} id_path | ||
* @param {string} dependency_path | ||
* | ||
* @return {Array} | ||
*/ | ||
defProto(function sortTopological(id_path, dependency_path) { | ||
let get_dependencies, | ||
get_id; | ||
if (id_path.indexOf('.') > -1) { | ||
get_id = (obj) => Obj.path(obj, id_path); | ||
} else { | ||
get_id = (obj) => obj[id_path]; | ||
} | ||
if (dependency_path.indexOf('.') > -1) { | ||
get_dependencies = (obj) => { | ||
let result = Obj.path(obj, dependency_path); | ||
if (!result) { | ||
return null; | ||
} | ||
return Bound.Array.cast(result); | ||
} | ||
} else { | ||
get_dependencies = (obj) => obj[dependency_path] ? Bound.Array.cast(obj[dependency_path]) : null; | ||
} | ||
let dependencies, | ||
length = this.length, | ||
values = [], | ||
value, | ||
entry, | ||
id, | ||
i; | ||
for (i = 0; i < length; i++) { | ||
value = this[i]; | ||
id = get_id(value); | ||
dependencies = get_dependencies(value); | ||
values.push({ | ||
id, | ||
dependencies, | ||
value: value, | ||
}); | ||
} | ||
let seen = new Set(), | ||
sorted = [], | ||
queue = []; | ||
let do_push = (entry, do_queue = true) => { | ||
seen.add(entry.id); | ||
sorted.push(entry.value); | ||
// Now try to clear the queue | ||
while (do_queue && queue.length) { | ||
let index_to_remove = []; | ||
// Prevent any infinite loop | ||
do_queue = false; | ||
for (let i = 0; i < queue.length; i++) { | ||
let item = queue[i]; | ||
if (item.dependencies.every(dep => seen.has(dep))) { | ||
do_push(item, false); | ||
index_to_remove.push(i); | ||
// Let the while loop iterate at least 1 more time | ||
// now that a new item has been resolved, potentially | ||
// resolving an earlier queued item | ||
do_queue = true; | ||
break; | ||
} | ||
} | ||
for (let i = index_to_remove.length - 1; i >= 0; i--) { | ||
queue.splice(index_to_remove[i], 1); | ||
} | ||
} | ||
}; | ||
for (i = 0; i < length; i++) { | ||
entry = values[i]; | ||
if (!entry.dependencies?.length) { | ||
do_push(entry); | ||
continue; | ||
} | ||
if (entry.dependencies.every(dep => seen.has(dep))) { | ||
do_push(entry); | ||
continue; | ||
} | ||
queue.push(entry); | ||
} | ||
if (queue.length) { | ||
// Sort the queue by the amount of dependencies. | ||
// This is just a last resort to make the circular dependencies | ||
// a bit more logical | ||
queue.sort((a, b) => { | ||
return a.dependencies.length - b.dependencies.length; | ||
}); | ||
} | ||
// Add the remaining queue items | ||
while (queue.length) { | ||
do_push(queue.shift()); | ||
} | ||
// Replace the original array elements | ||
for (let i = 0; i < sorted.length; i++) { | ||
this[i] = sorted[i]; | ||
} | ||
return this; | ||
}); | ||
// Sort type symbols | ||
@@ -681,0 +812,0 @@ Blast.arrayPath = Symbol('array_path'); |
@@ -458,3 +458,3 @@ const finished_constitutors = new WeakMap(), | ||
* @since 0.1.3 | ||
* @version 0.7.5 | ||
* @version 0.8.18 | ||
* | ||
@@ -713,2 +713,15 @@ * @param {String|Function|Array} _parent Parent class to inherit from | ||
Blast.defineValue(parentConstructor, 'children', []); | ||
} else { | ||
let child; | ||
// See if the parent already has a child by this name. | ||
// If it does, it has to be removed. | ||
for (i = 0; i < parentConstructor.children.length; i++) { | ||
child = parentConstructor.children[i]; | ||
if (child.name == new_constructor_name && child.namespace == namespace) { | ||
parentConstructor.children.splice(i, 1); | ||
break; | ||
} | ||
} | ||
} | ||
@@ -810,8 +823,3 @@ | ||
Blast.loaded(function doConstitutorsWhenLoaded(already_loaded) { | ||
if (already_loaded) { | ||
return Blast.queueImmediate(doConstitutorsWhenLoaded); | ||
} | ||
Blast.executeAfterLoadingCycle(function doConstitutorsWhenLoaded() { | ||
doConstitutors(newConstructor); | ||
@@ -1058,3 +1066,3 @@ }); | ||
* @since 0.1.4 | ||
* @version 0.7.9 | ||
* @version 0.8.18 | ||
* | ||
@@ -1088,8 +1096,18 @@ * @param {Function} constructor | ||
doConstructorTask(constructor, task); | ||
return; | ||
} else { | ||
Blast.queueImmediate(function doQueuedConstitutor() { | ||
doConstructorTask(constructor, task); | ||
}); | ||
} | ||
} | ||
Blast.queueImmediate(function doQueuedConstitutor() { | ||
doConstructorTask(constructor, task); | ||
}); | ||
// If this class already has children, add them there too | ||
if (constructor.children?.length) { | ||
let child; | ||
for (child of constructor.children) { | ||
if (!child.constitutors || child.constitutors.indexOf(task) == -1) { | ||
constitute(child, task); | ||
} | ||
} | ||
} | ||
@@ -1096,0 +1114,0 @@ }); |
@@ -1193,2 +1193,26 @@ module.exports = function BlastInitLoader(modifyPrototype) { | ||
/** | ||
* Do a task once Protoblast has finished loading. | ||
* If Protoblast has already loaded, mark it as unloaded again | ||
* and queue the task. | ||
* | ||
* @author Jelle De Loecker <jelle@elevenways.be> | ||
* @since 0.8.18 | ||
* @version 0.8.18 | ||
*/ | ||
Blast.executeAfterLoadingCycle = function executeAfterLoadingCycle(task) { | ||
if (!did_initial_load) { | ||
Blast.loaded(task); | ||
return; | ||
} | ||
did_initial_load = false; | ||
Blast.loaded(task); | ||
Blast.setImmediate(() => { | ||
Blast.doLoaded(); | ||
}); | ||
}; | ||
/** | ||
* Get an argument configuration by name | ||
@@ -1195,0 +1219,0 @@ * |
@@ -15,3 +15,3 @@ /** | ||
* @since 0.6.6 | ||
* @version 0.7.0 | ||
* @version 0.8.18 | ||
* | ||
@@ -22,6 +22,4 @@ * @param {Function} fnc | ||
var result; | ||
result = function Profixy() { | ||
fnc.call(this); | ||
let result = function Profixy(...args) { | ||
fnc.call(this, ...args); | ||
return new Proxy(this, traps); | ||
@@ -28,0 +26,0 @@ }; |
@@ -508,5 +508,5 @@ const defStat = Blast.createStaticDefiner('String'), | ||
* @since 0.6.5 | ||
* @version 0.8.8 | ||
* @version 0.8.18 | ||
* | ||
* @param {String source | ||
* @param {String} source | ||
* @param {Object} options | ||
@@ -518,3 +518,7 @@ * | ||
var current, | ||
if (source == null) { | ||
throw new Error('The `source` argument has to be a valid string'); | ||
} | ||
let current, | ||
tag_buffer = '', | ||
@@ -521,0 +525,0 @@ result = [], |
{ | ||
"name": "protoblast", | ||
"description": "Native object expansion library", | ||
"version": "0.8.17", | ||
"version": "0.8.18", | ||
"author": "Jelle De Loecker <jelle@elevenways.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
942700
38463