Require async
This commit is contained in:
+6
-19
@@ -10,24 +10,11 @@ const platformNames = {
|
||||
|
||||
Console.print('Platform: ' + (platformNames[System.platform] || 'Unknown'));
|
||||
|
||||
// Testing async/await
|
||||
async function testAsync() {
|
||||
Console.print('Testing async/await...');
|
||||
await frame();
|
||||
Console.print('First await done!');
|
||||
await timeout(1000);
|
||||
Console.print('Async/await works!');
|
||||
async function testRequireAsync() {
|
||||
Console.print('Loading testscene.js...');
|
||||
const scene = await requireAsync('testscene.js');
|
||||
Console.print('Loaded!');
|
||||
Console.print(scene.test());
|
||||
}
|
||||
|
||||
testAsync();
|
||||
|
||||
// Scene.set('testscene.js');
|
||||
// Console.print('Loading scene...');
|
||||
// requireAsync('./testscene.js', function(scene) {
|
||||
// throw "test";
|
||||
// Console.print('Initializing scene...');
|
||||
// var batch = scene.load();
|
||||
// batch.lock();
|
||||
// batch.requireLoaded();
|
||||
// scene.init();
|
||||
// });
|
||||
testRequireAsync();
|
||||
+54
-46
@@ -1,50 +1,58 @@
|
||||
var scene = {
|
||||
'test': 'teststring'
|
||||
};
|
||||
Console.print('testscene.js is loaded');
|
||||
|
||||
var assets = AssetBatch([
|
||||
{ path: 'test.png', type: Asset.TYPE_TEXTURE, format: Texture.FORMAT_RGBA }
|
||||
]);
|
||||
|
||||
var cam;
|
||||
var camPos;
|
||||
var testEntity;
|
||||
var testPos;
|
||||
var testRenderable;
|
||||
var texEntry;
|
||||
|
||||
scene.init = function() {
|
||||
assets.lock();
|
||||
assets.onLoaded[0] = scene.loaded;
|
||||
};
|
||||
|
||||
scene.loaded = function() {
|
||||
texEntry = assets.entry(0);
|
||||
|
||||
// Camera at (3, 3, 3) looking at origin
|
||||
cam = Entity.create();
|
||||
camPos = cam.add(Component.POSITION);
|
||||
cam.add(Component.CAMERA);
|
||||
camPos.localPosition = new Vec3(3, 3, 3);
|
||||
camPos.lookAt(new Vec3(0, 0, 0));
|
||||
|
||||
// Test entity with textured quad at origin
|
||||
testEntity = Entity.create();
|
||||
testPos = testEntity.add(Component.POSITION);
|
||||
testRenderable = testEntity.add(Component.RENDERABLE);
|
||||
|
||||
testRenderable.texture = texEntry.texture;
|
||||
testRenderable.sprites = [
|
||||
[0, 0, 1, 1, 0, 1, 1, 0]
|
||||
];
|
||||
testPos.localPosition = new Vec3(0, 0, 0);
|
||||
module.exports = {
|
||||
test: function() {
|
||||
return 'Hello string';
|
||||
}
|
||||
}
|
||||
|
||||
scene.dispose = function() {
|
||||
Console.print('Scene Dispose');
|
||||
Entity.dispose(cam);
|
||||
Entity.dispose(testEntity);
|
||||
assets.unlock();
|
||||
};
|
||||
// var scene = {
|
||||
// 'test': 'teststring'
|
||||
// };
|
||||
|
||||
module.exports = scene;
|
||||
// var assets = AssetBatch([
|
||||
// { path: 'test.png', type: Asset.TYPE_TEXTURE, format: Texture.FORMAT_RGBA }
|
||||
// ]);
|
||||
|
||||
// var cam;
|
||||
// var camPos;
|
||||
// var testEntity;
|
||||
// var testPos;
|
||||
// var testRenderable;
|
||||
// var texEntry;
|
||||
|
||||
// scene.init = function() {
|
||||
// assets.lock();
|
||||
// assets.onLoaded[0] = scene.loaded;
|
||||
// };
|
||||
|
||||
// scene.loaded = function() {
|
||||
// texEntry = assets.entry(0);
|
||||
|
||||
// // Camera at (3, 3, 3) looking at origin
|
||||
// cam = Entity.create();
|
||||
// camPos = cam.add(Component.POSITION);
|
||||
// cam.add(Component.CAMERA);
|
||||
// camPos.localPosition = new Vec3(3, 3, 3);
|
||||
// camPos.lookAt(new Vec3(0, 0, 0));
|
||||
|
||||
// // Test entity with textured quad at origin
|
||||
// testEntity = Entity.create();
|
||||
// testPos = testEntity.add(Component.POSITION);
|
||||
// testRenderable = testEntity.add(Component.RENDERABLE);
|
||||
|
||||
// testRenderable.texture = texEntry.texture;
|
||||
// testRenderable.sprites = [
|
||||
// [0, 0, 1, 1, 0, 1, 1, 0]
|
||||
// ];
|
||||
// testPos.localPosition = new Vec3(0, 0, 0);
|
||||
// }
|
||||
|
||||
// scene.dispose = function() {
|
||||
// Console.print('Scene Dispose');
|
||||
// Entity.dispose(cam);
|
||||
// Entity.dispose(testEntity);
|
||||
// assets.unlock();
|
||||
// };
|
||||
|
||||
// module.exports = scene;
|
||||
|
||||
@@ -10,4 +10,5 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||
)
|
||||
|
||||
# Subdirs
|
||||
add_subdirectory(event)
|
||||
add_subdirectory(require)
|
||||
@@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2026 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||
PUBLIC
|
||||
moduleevent.c
|
||||
)
|
||||
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "moduleevent.h"
|
||||
#include "util/memory.h"
|
||||
#include "assert/assert.h"
|
||||
|
||||
#define MODULE_EVENT_PENDING_MAX 32
|
||||
|
||||
typedef struct {
|
||||
event_t *event;
|
||||
jerry_value_t promise;
|
||||
} moduleeventpending_t;
|
||||
|
||||
scriptproto_t MODULE_EVENT_PROTO;
|
||||
|
||||
static moduleeventpending_t MODULE_EVENT_PENDING[MODULE_EVENT_PENDING_MAX];
|
||||
static uint32_t MODULE_EVENT_PENDING_COUNT = 0;
|
||||
|
||||
/**
|
||||
* Single shared C callback subscribed to any event that has JS awaits.
|
||||
* Resolves all pending promises for the fired event, then unsubscribes.
|
||||
* The user pointer is the event_t * so we can look up and unsubscribe.
|
||||
*/
|
||||
static void moduleEventFireCallback(void *params, void *user) {
|
||||
(void)params;
|
||||
event_t *event = (event_t *)user;
|
||||
|
||||
uint32_t i = 0;
|
||||
while(i < MODULE_EVENT_PENDING_COUNT) {
|
||||
if(MODULE_EVENT_PENDING[i].event != event) { i++; continue; }
|
||||
jerry_value_t ret = jerry_promise_resolve(
|
||||
MODULE_EVENT_PENDING[i].promise, jerry_undefined()
|
||||
);
|
||||
jerry_value_free(ret);
|
||||
jerry_value_free(MODULE_EVENT_PENDING[i].promise);
|
||||
MODULE_EVENT_PENDING_COUNT--;
|
||||
if(i < MODULE_EVENT_PENDING_COUNT) {
|
||||
MODULE_EVENT_PENDING[i] = MODULE_EVENT_PENDING[MODULE_EVENT_PENDING_COUNT];
|
||||
}
|
||||
}
|
||||
|
||||
eventUnsubscribe(event, moduleEventFireCallback);
|
||||
}
|
||||
|
||||
static jerry_value_t moduleEventWait(
|
||||
const jerry_call_info_t *callInfo,
|
||||
const jerry_value_t args[],
|
||||
const jerry_length_t argc
|
||||
) {
|
||||
(void)args; (void)argc;
|
||||
|
||||
jsevent_t *ev = scriptProtoGetValue(&MODULE_EVENT_PROTO, callInfo->this_value);
|
||||
if(!ev) return moduleBaseThrow("Event.wait: invalid this");
|
||||
|
||||
if(MODULE_EVENT_PENDING_COUNT >= MODULE_EVENT_PENDING_MAX) {
|
||||
return moduleBaseThrow("Event.wait: too many pending awaits");
|
||||
}
|
||||
|
||||
// Only subscribe once per event — check if we already have a pending await
|
||||
bool_t subscribed = false;
|
||||
for(uint32_t i = 0; i < MODULE_EVENT_PENDING_COUNT; i++) {
|
||||
if(MODULE_EVENT_PENDING[i].event == ev->event) { subscribed = true; break; }
|
||||
}
|
||||
|
||||
if(!subscribed) {
|
||||
if(ev->event->count >= ev->event->size) {
|
||||
return moduleBaseThrow("Event.wait: event subscriber capacity exceeded");
|
||||
}
|
||||
eventSubscribe(ev->event, moduleEventFireCallback, (void *)ev->event);
|
||||
}
|
||||
|
||||
jerry_value_t promise = jerry_promise();
|
||||
MODULE_EVENT_PENDING[MODULE_EVENT_PENDING_COUNT].event = ev->event;
|
||||
MODULE_EVENT_PENDING[MODULE_EVENT_PENDING_COUNT].promise = jerry_value_copy(promise);
|
||||
MODULE_EVENT_PENDING_COUNT++;
|
||||
return promise;
|
||||
}
|
||||
|
||||
jerry_value_t moduleEventCreate(event_t *event) {
|
||||
assertNotNull(event, "moduleEventCreate: event must not be NULL");
|
||||
jsevent_t ev = { .event = event };
|
||||
return scriptProtoCreateValue(&MODULE_EVENT_PROTO, &ev);
|
||||
}
|
||||
|
||||
void moduleEventInit(void) {
|
||||
MODULE_EVENT_PENDING_COUNT = 0;
|
||||
scriptProtoInit(&MODULE_EVENT_PROTO, NULL, sizeof(jsevent_t), NULL);
|
||||
scriptProtoDefineFunc(&MODULE_EVENT_PROTO, "wait", moduleEventWait);
|
||||
}
|
||||
|
||||
void moduleEventDispose(void) {
|
||||
// Unsubscribe from each distinct event still in the pending list
|
||||
for(uint32_t i = 0; i < MODULE_EVENT_PENDING_COUNT; i++) {
|
||||
bool_t alreadyUnsub = false;
|
||||
for(uint32_t j = 0; j < i; j++) {
|
||||
if(MODULE_EVENT_PENDING[j].event == MODULE_EVENT_PENDING[i].event) {
|
||||
alreadyUnsub = true; break;
|
||||
}
|
||||
}
|
||||
if(!alreadyUnsub) {
|
||||
eventUnsubscribe(MODULE_EVENT_PENDING[i].event, moduleEventFireCallback);
|
||||
}
|
||||
jerry_value_free(MODULE_EVENT_PENDING[i].promise);
|
||||
}
|
||||
MODULE_EVENT_PENDING_COUNT = 0;
|
||||
scriptProtoDispose(&MODULE_EVENT_PROTO);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "script/module/modulebase.h"
|
||||
#include "script/scriptproto.h"
|
||||
#include "event/event.h"
|
||||
|
||||
/** C struct wrapped by every Event JS instance. */
|
||||
typedef struct {
|
||||
event_t *event;
|
||||
} jsevent_t;
|
||||
|
||||
extern scriptproto_t MODULE_EVENT_PROTO;
|
||||
|
||||
/**
|
||||
* Wraps a C event_t pointer in a JS Event object.
|
||||
*
|
||||
* @param event The event to wrap. Must outlive the returned JS value.
|
||||
* @return A new JS Event instance.
|
||||
*/
|
||||
jerry_value_t moduleEventCreate(event_t *event);
|
||||
|
||||
/**
|
||||
* Initializes the Event module and registers the global Event prototype.
|
||||
*/
|
||||
void moduleEventInit(void);
|
||||
|
||||
/**
|
||||
* Disposes the Event module, rejecting any pending awaits and cleaning up.
|
||||
*/
|
||||
void moduleEventDispose(void);
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "script/module/display/modulescreen.h"
|
||||
#include "script/module/engine/moduleengine.h"
|
||||
#include "script/module/engine/moduleframe.h"
|
||||
#include "script/module/event/moduleevent.h"
|
||||
#include "script/module/engine/moduletimeout.h"
|
||||
#include "script/module/entity/component/modulecomponentlist.h"
|
||||
#include "script/module/entity/modulecomponent.h"
|
||||
@@ -24,6 +25,7 @@
|
||||
|
||||
|
||||
void moduleListInit(void) {
|
||||
moduleEventInit();
|
||||
moduleTextureInit();
|
||||
moduleColorInit();
|
||||
moduleAssetInit();
|
||||
@@ -64,4 +66,5 @@ void moduleListDispose(void) {
|
||||
moduleAssetDispose();
|
||||
moduleColorDispose();
|
||||
moduleTextureDispose();
|
||||
moduleEventDispose();
|
||||
}
|
||||
|
||||
@@ -10,7 +10,75 @@
|
||||
#include "util/memory.h"
|
||||
#include "util/string.h"
|
||||
#include "assert/assert.h"
|
||||
#include "console/console.h"
|
||||
|
||||
#define MODULE_REQUIRE_ASYNC_MAX 16
|
||||
|
||||
typedef struct {
|
||||
assetentry_t *entry;
|
||||
jerry_value_t promise;
|
||||
} modulerequireasyncpending_t;
|
||||
|
||||
static modulerequireasyncpending_t MODULE_REQUIRE_ASYNC_PENDING[MODULE_REQUIRE_ASYNC_MAX];
|
||||
static uint32_t MODULE_REQUIRE_ASYNC_PENDING_COUNT = 0;
|
||||
|
||||
/* Resolves or rejects every promise associated with entry, then unsubscribes. */
|
||||
static void moduleRequireAsyncOnError(void *params, void *user);
|
||||
|
||||
static void moduleRequireAsyncOnLoaded(void *params, void *user) {
|
||||
assetentry_t *entry = (assetentry_t *)params;
|
||||
(void)user;
|
||||
|
||||
eventUnsubscribe(&entry->onLoaded, moduleRequireAsyncOnLoaded);
|
||||
eventUnsubscribe(&entry->onError, moduleRequireAsyncOnError);
|
||||
|
||||
jerry_value_t exports = jerry_value_is_undefined(entry->data.script.exports)
|
||||
? jerry_undefined()
|
||||
: jerry_value_copy(entry->data.script.exports);
|
||||
|
||||
uint32_t i = 0;
|
||||
while(i < MODULE_REQUIRE_ASYNC_PENDING_COUNT) {
|
||||
if(MODULE_REQUIRE_ASYNC_PENDING[i].entry != entry) { i++; continue; }
|
||||
assetUnlockEntry(entry);
|
||||
jerry_value_t copy = jerry_value_copy(exports);
|
||||
jerry_value_t ret = jerry_promise_resolve(MODULE_REQUIRE_ASYNC_PENDING[i].promise, copy);
|
||||
jerry_value_free(ret);
|
||||
jerry_value_free(copy);
|
||||
jerry_value_free(MODULE_REQUIRE_ASYNC_PENDING[i].promise);
|
||||
MODULE_REQUIRE_ASYNC_PENDING_COUNT--;
|
||||
if(i < MODULE_REQUIRE_ASYNC_PENDING_COUNT) {
|
||||
MODULE_REQUIRE_ASYNC_PENDING[i] = MODULE_REQUIRE_ASYNC_PENDING[MODULE_REQUIRE_ASYNC_PENDING_COUNT];
|
||||
}
|
||||
}
|
||||
|
||||
jerry_value_free(exports);
|
||||
}
|
||||
|
||||
static void moduleRequireAsyncOnError(void *params, void *user) {
|
||||
assetentry_t *entry = (assetentry_t *)params;
|
||||
(void)user;
|
||||
|
||||
eventUnsubscribe(&entry->onLoaded, moduleRequireAsyncOnLoaded);
|
||||
eventUnsubscribe(&entry->onError, moduleRequireAsyncOnError);
|
||||
|
||||
jerry_value_t errStr = jerry_string_sz("Module load failed");
|
||||
|
||||
uint32_t i = 0;
|
||||
while(i < MODULE_REQUIRE_ASYNC_PENDING_COUNT) {
|
||||
if(MODULE_REQUIRE_ASYNC_PENDING[i].entry != entry) { i++; continue; }
|
||||
assetUnlockEntry(entry);
|
||||
jerry_value_t copy = jerry_value_copy(errStr);
|
||||
jerry_value_t ret = jerry_promise_reject(MODULE_REQUIRE_ASYNC_PENDING[i].promise, copy);
|
||||
jerry_value_free(ret);
|
||||
jerry_value_free(copy);
|
||||
jerry_value_free(MODULE_REQUIRE_ASYNC_PENDING[i].promise);
|
||||
MODULE_REQUIRE_ASYNC_PENDING_COUNT--;
|
||||
if(i < MODULE_REQUIRE_ASYNC_PENDING_COUNT) {
|
||||
MODULE_REQUIRE_ASYNC_PENDING[i] = MODULE_REQUIRE_ASYNC_PENDING[MODULE_REQUIRE_ASYNC_PENDING_COUNT];
|
||||
}
|
||||
}
|
||||
|
||||
jerry_value_free(errStr);
|
||||
}
|
||||
|
||||
jerry_value_t moduleRequireFunc(
|
||||
const jerry_call_info_t *callInfo,
|
||||
@@ -23,45 +91,30 @@ jerry_value_t moduleRequireFunc(
|
||||
if(argc < 1 || !jerry_value_is_string(args[0])) {
|
||||
return moduleBaseThrow("Expected a string argument for module name.");
|
||||
}
|
||||
|
||||
// Is filename too long?
|
||||
if(
|
||||
jerry_string_size(args[0], JERRY_ENCODING_UTF8) >= ASSET_FILE_NAME_MAX
|
||||
) {
|
||||
if(jerry_string_size(args[0], JERRY_ENCODING_UTF8) >= ASSET_FILE_NAME_MAX) {
|
||||
return moduleBaseThrow("Module name too long.");
|
||||
}
|
||||
|
||||
// Get C string
|
||||
char_t moduleName[ASSET_FILE_NAME_MAX];
|
||||
moduleBaseToString(args[0], moduleName, sizeof(moduleName));
|
||||
|
||||
// Lock and load the asset.
|
||||
assetloaderinput_t input;
|
||||
input.script.nothing = NULL;
|
||||
|
||||
assetentry_t *entry = assetLock(
|
||||
moduleName,
|
||||
ASSET_LOADER_TYPE_SCRIPT,
|
||||
&input
|
||||
);
|
||||
assetentry_t *entry = assetLock(moduleName, ASSET_LOADER_TYPE_SCRIPT, &input);
|
||||
|
||||
errorret_t err = assetRequireLoaded(entry);
|
||||
|
||||
if(errorIsNotOk(err)) {
|
||||
assetUnlockEntry(entry);
|
||||
return moduleBaseThrowError(err);
|
||||
}
|
||||
|
||||
// Now the module is loaded, copy it before unlocking.
|
||||
if(jerry_value_is_undefined(entry->data.script.exports)) {
|
||||
assetUnlockEntry(entry);
|
||||
return jerry_undefined();
|
||||
}
|
||||
|
||||
jerry_value_t exportsCopy = jerry_value_copy(
|
||||
entry->data.script.exports
|
||||
);
|
||||
assetUnlockEntry(entry);// Frees entry->data.script.exports
|
||||
jerry_value_t exportsCopy = jerry_value_copy(entry->data.script.exports);
|
||||
assetUnlockEntry(entry);
|
||||
return exportsCopy;
|
||||
}
|
||||
|
||||
@@ -73,47 +126,92 @@ jerry_value_t moduleRequireAsyncFunc(
|
||||
assertNotNull(callInfo, "callInfo must not be null.");
|
||||
assertNotNull(args, "args must not be null.");
|
||||
|
||||
// Filename, required
|
||||
if(argc < 1 || !jerry_value_is_string(args[0])) {
|
||||
return moduleBaseThrow(
|
||||
"requireAsync expects filename."
|
||||
);
|
||||
return moduleBaseThrow("requireAsync expects a filename string.");
|
||||
}
|
||||
|
||||
// Callback, optional.
|
||||
if(argc >= 2 && !jerry_value_is_function(args[1])) {
|
||||
return moduleBaseThrow(
|
||||
"requireAsync callback must be a function."
|
||||
);
|
||||
}
|
||||
|
||||
// Is filename too long?
|
||||
if(
|
||||
jerry_string_size(args[0], JERRY_ENCODING_UTF8) >= ASSET_FILE_NAME_MAX
|
||||
) {
|
||||
if(jerry_string_size(args[0], JERRY_ENCODING_UTF8) >= ASSET_FILE_NAME_MAX) {
|
||||
return moduleBaseThrow("Module name too long.");
|
||||
}
|
||||
if(MODULE_REQUIRE_ASYNC_PENDING_COUNT >= MODULE_REQUIRE_ASYNC_MAX) {
|
||||
return moduleBaseThrow("Too many pending requireAsync calls.");
|
||||
}
|
||||
|
||||
// Get C string
|
||||
char_t moduleName[ASSET_FILE_NAME_MAX];
|
||||
moduleBaseToString(args[0], moduleName, sizeof(moduleName));
|
||||
|
||||
// Lock asset
|
||||
assetloaderinput_t input;
|
||||
input.script.nothing = NULL;
|
||||
assetentry_t *entry = assetLock(moduleName, ASSET_LOADER_TYPE_SCRIPT, &input);
|
||||
|
||||
assetentry_t *entry = assetLock(
|
||||
moduleName,
|
||||
ASSET_LOADER_TYPE_SCRIPT,
|
||||
&input
|
||||
);
|
||||
jerry_value_t promise = jerry_promise();
|
||||
|
||||
// Already loaded — resolve immediately.
|
||||
if(entry->state == ASSET_ENTRY_STATE_LOADED) {
|
||||
jerry_value_t exports = jerry_value_is_undefined(entry->data.script.exports)
|
||||
? jerry_undefined()
|
||||
: jerry_value_copy(entry->data.script.exports);
|
||||
assetUnlockEntry(entry);
|
||||
jerry_value_t ret = jerry_promise_resolve(promise, exports);
|
||||
jerry_value_free(ret);
|
||||
jerry_value_free(exports);
|
||||
return promise;
|
||||
}
|
||||
|
||||
// Already errored — reject immediately.
|
||||
if(entry->state == ASSET_ENTRY_STATE_ERROR) {
|
||||
assetUnlockEntry(entry);
|
||||
jerry_value_t errStr = jerry_string_sz("Module load failed");
|
||||
jerry_value_t ret = jerry_promise_reject(promise, errStr);
|
||||
jerry_value_free(ret);
|
||||
jerry_value_free(errStr);
|
||||
return promise;
|
||||
}
|
||||
|
||||
// Subscribe to entry events only if this is the first pending await for it.
|
||||
bool_t subscribed = false;
|
||||
for(uint32_t i = 0; i < MODULE_REQUIRE_ASYNC_PENDING_COUNT; i++) {
|
||||
if(MODULE_REQUIRE_ASYNC_PENDING[i].entry == entry) { subscribed = true; break; }
|
||||
}
|
||||
if(!subscribed) {
|
||||
if(entry->onLoaded.count >= entry->onLoaded.size) {
|
||||
assetUnlockEntry(entry);
|
||||
jerry_value_free(promise);
|
||||
return moduleBaseThrow("requireAsync: onLoaded event capacity exceeded.");
|
||||
}
|
||||
if(entry->onError.count >= entry->onError.size) {
|
||||
assetUnlockEntry(entry);
|
||||
jerry_value_free(promise);
|
||||
return moduleBaseThrow("requireAsync: onError event capacity exceeded.");
|
||||
}
|
||||
eventSubscribe(&entry->onLoaded, moduleRequireAsyncOnLoaded, NULL);
|
||||
eventSubscribe(&entry->onError, moduleRequireAsyncOnError, NULL);
|
||||
}
|
||||
|
||||
MODULE_REQUIRE_ASYNC_PENDING[MODULE_REQUIRE_ASYNC_PENDING_COUNT].entry = entry;
|
||||
MODULE_REQUIRE_ASYNC_PENDING[MODULE_REQUIRE_ASYNC_PENDING_COUNT].promise = jerry_value_copy(promise);
|
||||
MODULE_REQUIRE_ASYNC_PENDING_COUNT++;
|
||||
return promise;
|
||||
}
|
||||
|
||||
void moduleRequireInit(void) {
|
||||
MODULE_REQUIRE_ASYNC_PENDING_COUNT = 0;
|
||||
moduleBaseDefineGlobalMethod("require", moduleRequireFunc);
|
||||
moduleBaseDefineGlobalMethod("requireAsync", moduleRequireAsyncFunc);
|
||||
}
|
||||
|
||||
void moduleRequireDispose(void) {
|
||||
for(uint32_t i = 0; i < MODULE_REQUIRE_ASYNC_PENDING_COUNT; i++) {
|
||||
assetentry_t *entry = MODULE_REQUIRE_ASYNC_PENDING[i].entry;
|
||||
bool_t alreadyUnsub = false;
|
||||
for(uint32_t j = 0; j < i; j++) {
|
||||
if(MODULE_REQUIRE_ASYNC_PENDING[j].entry == entry) { alreadyUnsub = true; break; }
|
||||
}
|
||||
if(!alreadyUnsub) {
|
||||
eventUnsubscribe(&entry->onLoaded, moduleRequireAsyncOnLoaded);
|
||||
eventUnsubscribe(&entry->onError, moduleRequireAsyncOnError);
|
||||
}
|
||||
assetUnlockEntry(entry);
|
||||
jerry_value_free(MODULE_REQUIRE_ASYNC_PENDING[i].promise);
|
||||
}
|
||||
MODULE_REQUIRE_ASYNC_PENDING_COUNT = 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user