changeset 643:993d9ccedcf6

core: repair js load
author David Demelier <markand@malikania.fr>
date Sun, 17 Dec 2023 11:27:54 +0100
parents 05b585720d3b
children 6d0f4edb79f8
files libmlk-core/mlk/core/js/js-painter.c libmlk-core/mlk/core/js/js-sprite.c libmlk-core/mlk/core/js/js.c libmlk-core/mlk/core/js/js.h mlk-run/mlk-run.c
diffstat 5 files changed, 172 insertions(+), 201 deletions(-) [+]
line wrap: on
line diff
--- a/libmlk-core/mlk/core/js/js-painter.c	Sun Dec 17 09:50:36 2023 +0100
+++ b/libmlk-core/mlk/core/js/js-painter.c	Sun Dec 17 11:27:54 2023 +0100
@@ -45,16 +45,6 @@
 }
 
 static duk_ret_t
-mlk_js_painter_new(duk_context *ctx)
-{
-	if (!duk_is_constructor_call(ctx))
-		return duk_error(ctx, DUK_ERR_TYPE_ERROR, "Painter must be new-constructed");
-
-
-	return 0;
-}
-
-static duk_ret_t
 mlk_js_painter_clear(duk_context *ctx)
 {
 	(void)ctx;
@@ -88,7 +78,7 @@
 	} else
 		return duk_error(ctx, DUK_ERR_ERROR, "Object or 4 numbers expected");
 
-	mlk_painter_draw_line(x1, y2, x2, y2);
+	mlk_painter_draw_line(x1, y1, x2, y2);
 
 	return 0;
 }
@@ -183,7 +173,7 @@
 	return 0;
 }
 
-static const duk_function_list_entry methods[] = {
+static const duk_function_list_entry functions[] = {
 	{ "clear",              mlk_js_painter_clear,           0               },
 	{ "drawLine",           mlk_js_painter_drawLine,        DUK_VARARGS     },
 	{ "drawPoint",          mlk_js_painter_drawPoint,       DUK_VARARGS     },
@@ -194,7 +184,7 @@
 };
 
 void
-js_painter_load(duk_context *ctx)
+mlk_js_painter_load(duk_context *ctx)
 {
 	assert(ctx);
 
@@ -205,7 +195,7 @@
 	duk_push_c_function(ctx, mlk_js_painter_getColor, 0);
 	duk_push_c_function(ctx, mlk_js_painter_setColor, 1);
 	duk_def_prop(ctx, -4, DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER);
-	duk_put_function_list(ctx, -1, methods);
+	duk_put_function_list(ctx, -1, functions);
 	duk_put_prop_string(ctx, -2, "Painter");
 	duk_pop(ctx);
 }
--- a/libmlk-core/mlk/core/js/js-sprite.c	Sun Dec 17 09:50:36 2023 +0100
+++ b/libmlk-core/mlk/core/js/js-sprite.c	Sun Dec 17 11:27:54 2023 +0100
@@ -101,7 +101,7 @@
 mlk_js_sprite_finish(duk_context *ctx)
 {
 	duk_get_prop_string(ctx, 0, SYMBOL);
-	free(duk_to_pointer(ctx, -1));
+	mlk_alloc_free(duk_to_pointer(ctx, -1));
 	duk_pop(ctx);
 	duk_del_prop_string(ctx, 0, SYMBOL);
 	duk_del_prop_string(ctx, 0, TEXTURE_REF);
@@ -112,7 +112,7 @@
 static duk_ret_t
 mlk_js_sprite_draw(duk_context *ctx)
 {
-	struct sprite *sprite = mlk_js_sprite_this(ctx);
+	struct mlk_sprite *sprite = mlk_js_sprite_this(ctx);
 	unsigned int r, c;
 	int x, y;
 
@@ -148,7 +148,7 @@
 struct mlk_sprite *
 mlk_js_sprite_require(duk_context *ctx, duk_idx_t index)
 {
-	struct sprite *sp;
+	struct mlk_sprite *sp;
 
 	duk_get_prop_string(ctx, index, SYMBOL);
 	sp = duk_to_pointer(ctx, -1);
@@ -166,7 +166,7 @@
 	assert(ctx);
 
 	duk_push_global_object(ctx);
-	duk_get_prop_string(ctx, -1, "Molko");
+	duk_get_prop_string(ctx, -1, "Mlk");
 	duk_push_c_function(ctx, mlk_js_sprite_new, 3);
 	duk_push_object(ctx);
 	duk_put_function_list(ctx, -1, methods);
--- a/libmlk-core/mlk/core/js/js.c	Sun Dec 17 09:50:36 2023 +0100
+++ b/libmlk-core/mlk/core/js/js.c	Sun Dec 17 11:27:54 2023 +0100
@@ -17,35 +17,31 @@
  */
 
 #include <assert.h>
-#include <libgen.h>
-#include <limits.h>
 #include <string.h>
 
 #include <mlk/core/alloc.h>
 #include <mlk/core/err.h>
 #include <mlk/core/panic.h>
 #include <mlk/core/trace.h>
+#include <mlk/core/vfs.h>
 
 #include <duktape.h>
 #include <duk_module.h>
 
+#include "js-animation.h"
+#include "js-clock.h"
+#include "js-event.h"
+#include "js-font.h"
+#include "js-music.h"
+#include "js-painter.h"
+#include "js-sound.h"
+#include "js-sprite.h"
+#include "js-texture.h"
+#include "js-util.h"
+#include "js-window.h"
 #include "js.h"
 
-static duk_ret_t
-js_print(duk_context *ctx)
-{
-	puts(duk_require_string(ctx, 0));
-
-	return 0;
-}
-
-static duk_ret_t
-js_trace(duk_context *ctx)
-{
-	mlk_tracef("%s", duk_require_string(ctx, 0));
-
-	return 0;
-}
+#define JS_REF DUK_HIDDEN_SYMBOL("mlk::js")
 
 static void *
 wrap_malloc(void *udata, duk_size_t size)
@@ -60,7 +56,17 @@
 {
 	(void)udata;
 
-	return mlk_alloc_resize(oldptr, size);
+	void *ptr = NULL;
+
+	if (oldptr) {
+		if (!size)
+			mlk_alloc_free(oldptr);
+		else
+			ptr = mlk_alloc_resize(oldptr, size);
+	} else if (size)
+		ptr = mlk_alloc_new(1, size);
+
+	return ptr;
 }
 
 static void
@@ -79,40 +85,83 @@
 	mlk_panicf("%s", msg);
 }
 
-#if 0
+static char *
+read_all(struct mlk_js *js, const char *filename, size_t *len)
+{
+	struct mlk_vfs_file *file;
+	char *text;
+
+	if (!(file = mlk_vfs_open(js->vfs, filename, "r")))
+		return NULL;
 
-static duk_ret_t
-search(duk_context *ctx)
+	text = mlk_vfs_file_read_all(file, len);
+	mlk_vfs_file_finish(file);
+
+	return text;
+}
+
+static struct mlk_js *
+mlk_js_this(duk_context *ctx)
 {
-	char path[PATH_MAX] = {};
-	char *ret;
+	struct mlk_js *js;
 
 	duk_push_global_stash(ctx);
-	duk_get_prop_string(ctx, -1, DUK_HIDDEN_SYMBOL("molko::base"));
-	snprintf(path, sizeof (path), "%s/%s.js", duk_to_string(ctx, -1), duk_require_string(ctx, 0));
-	duk_pop_n(ctx, 2);
+	duk_get_prop_string(ctx, -1, JS_REF);
+	js = duk_to_pointer(ctx, -1);
+	duk_pop(ctx);
+
+	if (!js)
+		duk_error(ctx, DUK_ERR_TYPE_ERROR, "Not a Javascript context");
+
+	return js;
+}
+
+static duk_ret_t
+mlk_js_print(duk_context *ctx)
+{
+	puts(duk_require_string(ctx, 0));
+
+	return 0;
+}
 
-	if (!(ret = readall(path)))
-		duk_error(ctx, DUK_ERR_ERROR, "%s", error());
+static duk_ret_t
+mlk_js_trace(duk_context *ctx)
+{
+	mlk_tracef("%s", duk_require_string(ctx, 0));
+
+	return 0;
+}
 
-	duk_push_string(ctx, ret);
-	free(ret);
+static duk_ret_t
+mlk_js_modSearch(duk_context *ctx)
+{
+	struct mlk_js *js;
+	const char *filename;
+	char *text;
+	size_t textsz;
+
+	js = mlk_js_this(ctx);
+	filename = duk_require_string(ctx, 0);
+
+	if (!(text = read_all(js, filename, &textsz)))
+		duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err());
+
+	duk_push_lstring(ctx, text, textsz);
+	free(text);
 
 	return 1;
 }
 
 static void
-setup_module(struct js *js)
+setup_module(struct mlk_js *js)
 {
 	duk_module_duktape_init(js->handle);
 	duk_get_global_string(js->handle, "Duktape");
-	duk_push_c_function(js->handle, search, 4);
+	duk_push_c_function(js->handle, mlk_js_modSearch, 4);
 	duk_put_prop_string(js->handle, -2, "modSearch");
 	duk_pop(js->handle);
 }
 
-#endif
-
 static void
 setup_global(struct mlk_js *js)
 {
@@ -120,44 +169,48 @@
 	duk_push_global_object(js->handle);
 	duk_push_object(js->handle);
 	duk_put_prop_string(js->handle, -2, "Mlk");
-	duk_push_c_function(js->handle, js_print, 1);
+	duk_push_c_function(js->handle, mlk_js_print, 1);
 	duk_put_prop_string(js->handle, -2, "print");
-	duk_push_c_function(js->handle, js_trace, 1);
+	duk_push_c_function(js->handle, mlk_js_trace, 1);
 	duk_put_prop_string(js->handle, -2, "trace");
 	duk_pop(js->handle);
 }
 
 static void
-setup_properties(struct mlk_js *js)
+setup_internal(struct mlk_js *js)
 {
+	duk_push_global_stash(js->handle);
+
 	/* Store a reference to this pointer. */
-	duk_push_global_stash(js->handle);
 	duk_push_pointer(js->handle, js);
-	duk_put_prop_string(js->handle, -2, DUK_HIDDEN_SYMBOL("mlk::pointer"));
+	duk_put_prop_string(js->handle, -2, JS_REF);
+
 	duk_pop(js->handle);
 }
 
-#if 0
 static void
-setup_base(struct mlk_js *js, const char *path)
+setup_core(struct mlk_js *js)
 {
-	char base[PATH_MAX] = {};
-
-	snprintf(base, sizeof (base), "%s", path);
-	snprintf(base, sizeof (base), "%s", dirname(base));
-
-	duk_push_global_stash(js->handle);
-	duk_push_string(js->handle, base);
-	duk_put_prop_string(js->handle, -2, DUK_HIDDEN_SYMBOL("mlk::base"));
-	duk_pop(js->handle);
+	mlk_js_animation_load(js->handle);
+	mlk_js_clock_load(js->handle);
+	mlk_js_event_load(js->handle);
+	mlk_js_font_load(js->handle);
+	mlk_js_music_load(js->handle);
+	mlk_js_painter_load(js->handle);
+	mlk_js_sound_load(js->handle);
+	mlk_js_sprite_load(js->handle);
+	mlk_js_texture_load(js->handle);
+	mlk_js_util_load(js->handle);
+	mlk_js_window_load(js->handle);
 }
-#endif
 
 int
-js_init(struct mlk_js *js)
+mlk_js_init(struct mlk_js *js, struct mlk_vfs *vfs)
 {
 	assert(js);
+	assert(vfs);
 
+	js->vfs = vfs;
 	js->handle = duk_create_heap(wrap_malloc, wrap_realloc, wrap_free,
 	    NULL, wrap_fatal);
 
@@ -166,49 +219,42 @@
 		return -1;
 	}
 
-#if 0
+	setup_internal(js);
+	setup_global(js);
 	setup_module(js);
-#endif
-	setup_global(js);
-	setup_properties(js);
+	setup_core(js);
 
 	return 0;
 }
 
-#if 0
-bool
-js_open(struct js *js, const char *path)
+int
+mlk_js_run(struct mlk_js *js, const char *main)
 {
 	assert(js);
-	assert(path);
-
-	char *text = readall(path);
-	bool ret = true;
+	assert(main);
 
-	if (!text)
-		return false;
+	int line, rv = -1;
+	char *text;
+	size_t textsz;
 
-	setup_base(js, path);
-
-	if (duk_peval_string(js->handle, text) != 0) {
-		int ln;
+	if (!(text = read_all(js, main, &textsz)))
+		return -1;
 
+	if (duk_peval_lstring(js->handle, text, textsz) != 0) {
 		duk_get_prop_string(js->handle, -1, "lineNumber");
-		ln = duk_to_int(js->handle, -1);
+		line = duk_to_int(js->handle, -1);
 		duk_pop(js->handle);
-		errorf("%d: %s", ln, duk_safe_to_string(js->handle, -1));
-		ret = false;
-	}
+		mlk_errf("%d: %s", line, duk_safe_to_string(js->handle, -1));
+	} else
+		rv = 0;
 
-	free(text);
-	duk_pop(js->handle);
+	mlk_alloc_free(text);
 
-	return ret;
+	return rv;
 }
-#endif
 
 void
-js_finish(struct mlk_js *js)
+mlk_js_finish(struct mlk_js *js)
 {
 	assert(js);
 
--- a/libmlk-core/mlk/core/js/js.h	Sun Dec 17 09:50:36 2023 +0100
+++ b/libmlk-core/mlk/core/js/js.h	Sun Dec 17 11:27:54 2023 +0100
@@ -19,16 +19,29 @@
 #ifndef MLK_CORE_JS_H
 #define MLK_CORE_JS_H
 
+#define MLK_CORE_JS_MAIN "main.js"
+
 struct mlk_js {
+	/**
+	 * (read-write, borrowed)
+	 *
+	 * VFS used to load resources.
+	 */
+	struct mlk_vfs *vfs;
 	void *handle;
 };
 
+struct mlk_vfs;
+
 #if defined(__cplusplus)
 extern "C" {
 #endif
 
 int
-mlk_js_init(struct mlk_js *js);
+mlk_js_init(struct mlk_js *js, struct mlk_vfs *vfs);
+
+int
+mlk_js_run(struct mlk_js *js, const char *main);
 
 void
 mlk_js_finish(struct mlk_js *js);
--- a/mlk-run/mlk-run.c	Sun Dec 17 09:50:36 2023 +0100
+++ b/mlk-run/mlk-run.c	Sun Dec 17 11:27:54 2023 +0100
@@ -18,7 +18,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <limits.h>
+#include <string.h>
 
 #include <duktape.h>
 #include <duk_module.h>
@@ -32,6 +32,8 @@
 #include <mlk/core/vfs-zip.h>
 #include <mlk/core/vfs.h>
 
+#include <mlk/core/js/js.h>
+
 union {
 	struct mlk_vfs_dir dir;
 
@@ -43,60 +45,8 @@
 /* VFS loader to support zip and directories when loading game. */
 static struct mlk_vfs *vfs;
 
-/* Javascript context. */
-static duk_context *ctx;
-
-static duk_ret_t
-modsearch(duk_context *ctx)
-{
-	char path[MLK_PATH_MAX] = {}, *data;
-	struct mlk_vfs_file *file;
-	size_t datasz;
-
-	snprintf(path, sizeof (path), "%s.js", duk_require_string(ctx, 0));
-
-	if ((file = mlk_vfs_open(vfs, path, "r")) < 0)
-		return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err());
-	if (!(data = mlk_vfs_file_read_all(file, &datasz))) {
-		mlk_vfs_file_finish(file);
-		return duk_error(ctx, DUK_ERR_ERROR, "%s", mlk_err());
-	}
-
-	mlk_vfs_file_finish(file);
-	duk_push_lstring(ctx, data, datasz);
-	free(data);
-
-	return 1;
-}
-
-static void
-core_bind(duk_context *ctx)
-{
-#if 0
-	/* Brings Mlk global object. */
-	mlk_js_core_bind(ctx, &vfs);
-
-	js_action_bind(ctx);
-	js_action_stack_bind(ctx);
-	js_animation_bind(ctx);
-	js_clock_bind(ctx);
-	js_color_bind(ctx);
-	js_drawable_bind(ctx);
-	js_drawable_stack_bind(ctx);
-	js_event_bind(ctx);
-	js_font_bind(ctx);
-	js_game_bind(ctx);
-	js_music_bind(ctx);
-	js_painter_bind(ctx);
-	js_panic_bind(ctx);
-	js_sound_bind(ctx);
-	js_sprite_bind(ctx);
-	js_state_bind(ctx);
-	js_texture_bind(ctx);
-	js_trace_bind(ctx);
-	js_window_bind(ctx);
-#endif
-}
+/* Global Javascript context. */
+static struct mlk_js js;
 
 static void
 init(void)
@@ -104,74 +54,46 @@
 	/* TODO: this is temporary. */
 	if (mlk_core_init("fr.malikania", "mlk-run") < 0)
 		mlk_panic();
-
-	/* Fireup Javascript. */
-	ctx = duk_create_heap_default();
-	core_bind(ctx);
-
-	/* Setup module loader. */
-	duk_module_duktape_init(ctx);
-	duk_get_global_string(ctx, "Duktape");
-	duk_push_c_function(ctx, modsearch, 4);
-	duk_put_prop_string(ctx, -2, "modSearch");
-	duk_pop(ctx);
 }
 
 static void
-startup(void)
+load_zip(const char *path)
 {
-	struct mlk_vfs_file *file;
-	char *code;
-
-	if (!(file = mlk_vfs_open(vfs, "main.js", "r")))
+#if defined(MLK_WITH_ZIP)
+	if (mlk_vfs_zip_init(&iface.zip, path, "r") < 0)
 		mlk_panic();
-	if (!(code = mlk_vfs_file_read_all(file, NULL))) {
-		mlk_vfs_file_finish(file);
-		mlk_panic();
-	}
-
-	mlk_vfs_file_finish(file);
-
-	if (duk_peval_string(ctx, code))
-		mlk_panicf("%s", duk_safe_to_string(ctx, -1));
 
-	free(code);
-}
-
-static void
-finish(void)
-{
-	mlk_vfs_finish(vfs);
-	duk_destroy_heap(ctx);
-}
-
-static void
-loadzip(const char *path)
-{
-#if 0
-	if (vfs_zip(&vfs, path, "r") < 0)
-		panic();
+	vfs = &iface.zip.vfs;
+#else
+	mlk_panicf("ZIP file support disabled")a;
 #endif
 }
 
 static void
-loaddirectory(const char *path)
+load_directory(const char *path)
 {
-#if 0
-	vfs_directory(&vfs, path);
-#endif
+	mlk_vfs_dir_init(&iface.dir, path);
+	vfs = &iface.dir.vfs;
 }
 
 static void
 load(const char *path)
 {
 	/* TODO: improve this. */
-	if (strstr(path, ".mlk"))
-		loadzip(path);
+	if (strstr(path, ".mlk") || strstr(path, ".zip"))
+		load_zip(path);
 	else
-		loaddirectory(path);
+		load_directory(path);
+
+	if (mlk_js_init(&js, vfs) < 0 || mlk_js_run(&js, MLK_CORE_JS_MAIN))
+		mlk_panic();
+}
 
-	startup();
+static void
+finish(void)
+{
+	mlk_js_finish(&js);
+	mlk_vfs_finish(vfs);
 }
 
 static void