From 607a8d637d4f47c6c17608045ef95bd5ba404b8d Mon Sep 17 00:00:00 2001 From: Jelle De Loecker Date: Thu, 8 Feb 2024 19:06:12 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Make=20`Blast.executeAfterLoadin?= =?UTF-8?q?gCycle()`=20keep=20`did=5Finitial=5Fload`=20variable=20alone?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 ++ lib/function_inheritance.js | 29 ++++++++++++++++++++----- lib/init.js | 42 ++++++++++++++++++++++++++++-------- test/function_inheritance.js | 42 ++++++++++++++++++++++++++---------- 4 files changed, 90 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b7c517..41152f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ * Add `WeakValueSetMap` class * Make `Blast.createObjectId()` also available on the server-side * Add `toISOString` method to `AbstractDateTime` classes +* Add `Blast.didInitialLoad()` method +* Make `Blast.executeAfterLoadingCycle()` keep `did_initial_load` variable alone ## 0.8.18 (2024-01-19) diff --git a/lib/function_inheritance.js b/lib/function_inheritance.js index 3a03256..eda7ad5 100644 --- a/lib/function_inheritance.js +++ b/lib/function_inheritance.js @@ -665,7 +665,7 @@ Blast.defineStatic('Function', function inherits(_parent, _namespace, _newConstr // Add the parent constitutors to the new constructor if (newConstructor.super.constitutors != null) { for (i = 0; i < newConstructor.super.constitutors.length; i++) { - newConstructor.constitute(newConstructor.super.constitutors[i]); + addConstructorConstitutor(newConstructor, newConstructor.super.constitutors[i], true); } }; @@ -674,7 +674,7 @@ Blast.defineStatic('Function', function inherits(_parent, _namespace, _newConstr } for (i = 0; i < oldProto.waitingConstitute.length; i++) { - newConstructor.constitute(oldProto.waitingConstitute[i]); + addConstructorConstitutor(newConstructor, oldProto.waitingConstitute[i], true); } doPostInheritors(newConstructor); @@ -1235,7 +1235,7 @@ defClassMethod(function postInherit(constructor, task) { * * @author Jelle De Loecker * @since 0.1.4 - * @version 0.8.18 + * @version 0.9.0 * * @param {Function} constructor * @param {Function} task @@ -1247,6 +1247,21 @@ defClassMethod(function constitute(constructor, task) { return; } + addConstructorConstitutor(constructor, task, false); +}); + +/** + * Actually add and maybe execute the constitutor to the given constructor + * + * @author Jelle De Loecker + * @since 0.9.0 + * @version 0.9.0 + * + * @param {Function} constructor + * @param {Function} task + */ +function addConstructorConstitutor(constructor, task, after_wait = false) { + let tasks = constructor.constitutors; if (tasks == null) { @@ -1269,6 +1284,10 @@ defClassMethod(function constitute(constructor, task) { doConstructorTask(constructor, task, finished_constitutors); }); } + } else if (Blast.didInitialLoad()) { + Blast.loaded(() => { + doConstructorTask(constructor, task, finished_constitutors); + }); } // If this class already has children, add them there too @@ -1277,11 +1296,11 @@ defClassMethod(function constitute(constructor, task) { for (child of constructor.children) { if (!child.constitutors || child.constitutors.indexOf(task) == -1) { - constitute(child, task); + child.constitute(task); } } } -}); +} /** * Add a class instance as a static property and add static traits diff --git a/lib/init.js b/lib/init.js index c29b70c..552703c 100644 --- a/lib/init.js +++ b/lib/init.js @@ -991,11 +991,12 @@ function BlastInit(modifyPrototype) { require('./server_functions.js')(Blast, extras); //PROTOBLAST END CUT - var when_ready = [], + let when_ready = [], when_loaded = [], queued_meds = [], queued_ticks = [], - did_initial_load = false; + did_initial_load = false, + temporarily_unready = false; /** * Execute function after Blast code has run. @@ -1122,7 +1123,7 @@ function BlastInit(modifyPrototype) { * @return {Boolean} Returns if Protoblast is already ready */ Blast.ready = function ready(fnc) { - if (when_ready) { + if (when_ready || temporarily_unready) { if (fnc) { when_ready.push(fnc); @@ -1151,7 +1152,7 @@ function BlastInit(modifyPrototype) { * @return {Boolean} Returns if Protoblast has already loaded */ Blast.loaded = function loaded(fnc) { - if (!did_initial_load) { + if (!did_initial_load || temporarily_unready) { if (fnc) { when_loaded.push(fnc); @@ -1168,6 +1169,28 @@ function BlastInit(modifyPrototype) { } }; + /** + * Did the initial load already happen? + * + * @author Jelle De Loecker + * @since 0.9.0 + * @version 0.9.0 + * + * @return {boolean} + */ + Blast.didInitialLoad = () => did_initial_load; + + /** + * Are we currently in a manual loading cycle? + * + * @author Jelle De Loecker + * @since 0.9.0 + * @version 0.9.0 + * + * @return {boolean} + */ + Blast.inLoadingCycle = () => temporarily_unready; + /** * Force Protoblast into executing the when_loaded functions * @@ -1177,7 +1200,7 @@ function BlastInit(modifyPrototype) { */ Blast.doLoaded = function doLoaded() { - if (!did_initial_load) { + if (!did_initial_load || temporarily_unready) { Blast.loading = true; } @@ -1185,9 +1208,10 @@ function BlastInit(modifyPrototype) { clearAndDoTasks(queued_meds); clearAndDoTasks(when_loaded); - if (!did_initial_load) { + if (!did_initial_load || temporarily_unready) { Blast.loading = false; did_initial_load = true; + temporarily_unready = false; } }; @@ -1202,14 +1226,14 @@ function BlastInit(modifyPrototype) { */ Blast.executeAfterLoadingCycle = function executeAfterLoadingCycle(task) { - if (!did_initial_load) { + if (!did_initial_load || temporarily_unready) { Blast.loaded(task); return; } - did_initial_load = false; + temporarily_unready = true; Blast.loaded(task); - + Blast.setImmediate(() => { Blast.doLoaded(); }); diff --git a/test/function_inheritance.js b/test/function_inheritance.js index 8d1cc4c..147a710 100644 --- a/test/function_inheritance.js +++ b/test/function_inheritance.js @@ -188,9 +188,11 @@ describe('Inheritance', function() { // The grandchild will only have returnTwo on the next tick assert.strictEqual(Grandchild.returnTwo(), 2); - assert.strictEqual(order[0], 'created-parent'); - assert.strictEqual(order[1], 'setting-returntwo-on-parent'); - assert.strictEqual(order[2], 'constituting-grandchild'); + assert.deepStrictEqual(order, [ + 'created-parent', + 'setting-returntwo-on-parent', + 'constituting-grandchild' + ]); done(); }, 20) @@ -572,7 +574,7 @@ describe('Inheritance', function() { CTTwo = Blast.Bound.Function.inherits('CTOne', function CTTwo() {}); CTTwo.constitute(function doThird() { this.third_time = i++; - checker(); + checker(this, 'CTTwo: doThird'); }); // This is the main class @@ -580,17 +582,17 @@ describe('Inheritance', function() { CTOne = Blast.Bound.Function.inherits(function CTOne() {}); CTOne.constitute(function doFirst() { this.first_time = i++; - checker(); + checker(this, 'CTOne: doFirst'); }); CTOne.constitute(function doSecond() { this.second_time = i++; - checker(); + checker(this, 'CTOne: doSecond'); }); }, 10); // This will check if everything is happening in the correct order - function checker() { + function checker(constructor, creator) { if (i == 1) { assert.equal(CTOne.first_time, 0); @@ -641,6 +643,9 @@ describe('Inheritance', function() { tasks = [], i = 0; + let current_source, + current_class; + // This is the main class DTOne = Blast.Bound.Function.inherits(function DTOne() {}); DTOne.constitute(function doFirst() { @@ -663,7 +668,8 @@ describe('Inheritance', function() { }); // This is another, non-related class - // This should run AFTER DTThree + // This originall ran AFTER DTThree, + // but since 2024 it will run before it. DTOther = Blast.Bound.Function.inherits(function DTOther() {}); DTOther.constitute(function doAfterThree() { this.fourth_time = i++; @@ -677,9 +683,6 @@ describe('Inheritance', function() { } }); - let current_source, - current_class; - // This will check if everything is happening in the correct order function checker(source, _current_class) { @@ -810,6 +813,23 @@ describe('Inheritance', function() { } } }); + + it('should handle constitutors added during a loading cycle', async () => { + + let Base = Function.inherits('Informer', 'Delayed', function Base() {}); + Base.constitute(() => {}); + + let Alpha = Function.inherits('Delayed.Base', function Alpha() {}); + let Beta = Function.inherits('Delayed.Base', function Beta() {}); + + return Function.parallel((next) => { + Alpha.constitute(() => { + Blast.executeAfterLoadingCycle(next); + }); + }, (next) => { + Beta.constitute(() => next()); + }, () => {}); + }); }); describe('.postInherit(task)', () => {