diff --git a/meson.build b/meson.build index e0610e5..f7cc37c 100644 --- a/meson.build +++ b/meson.build @@ -74,7 +74,7 @@ endif build_date = run_command('date', '+%Y-%m-%d', check: true).stdout().strip() version_conf = configuration_data() -version_conf.set('ANT_VERSION', '0.1.0.1') +version_conf.set('ANT_VERSION', '0.1.0.2') version_conf.set('ANT_GIT_HASH', git_hash) version_conf.set('ANT_BUILD_DATE', build_date) diff --git a/src/ant.c b/src/ant.c index dfc4bf3..8915ebb 100644 --- a/src/ant.c +++ b/src/ant.c @@ -245,7 +245,7 @@ enum { TOK_DEFAULT, TOK_DELETE, TOK_DO, TOK_ELSE, TOK_EXPORT, TOK_FINALLY, TOK_FOR, TOK_FROM, TOK_FUNC, TOK_IF, TOK_IMPORT, TOK_IN, TOK_INSTANCEOF, TOK_LET, TOK_NEW, TOK_OF, TOK_RETURN, TOK_SWITCH, TOK_THIS, TOK_THROW, TOK_TRY, TOK_VAR, TOK_VOID, TOK_WHILE, TOK_WITH, - TOK_YIELD, TOK_UNDEF, TOK_NULL, TOK_TRUE, TOK_FALSE, TOK_AS, TOK_STATIC, + TOK_YIELD, TOK_UNDEF, TOK_NULL, TOK_TRUE, TOK_FALSE, TOK_AS, TOK_STATIC, TOK_WINDOW, TOK_GLOBAL_THIS, TOK_DOT = 100, TOK_CALL, TOK_BRACKET, TOK_POSTINC, TOK_POSTDEC, TOK_NOT, TOK_TILDA, TOK_TYPEOF, TOK_UPLUS, TOK_UMINUS, TOK_EXP, TOK_MUL, TOK_DIV, TOK_REM, TOK_OPTIONAL_CHAIN, TOK_REST, @@ -2406,6 +2406,7 @@ static uint8_t parsekeyword(const char *buf, size_t len) { case 'd': if (streq("do", 2, buf, len)) return TOK_DO; if (streq("default", 7, buf, len)) return TOK_DEFAULT; if (streq("delete", 6, buf, len)) return TOK_DELETE; break; case 'e': if (streq("else", 4, buf, len)) return TOK_ELSE; if (streq("export", 6, buf, len)) return TOK_EXPORT; break; case 'f': if (streq("for", 3, buf, len)) return TOK_FOR; if (streq("from", 4, buf, len)) return TOK_FROM; if (streq("function", 8, buf, len)) return TOK_FUNC; if (streq("finally", 7, buf, len)) return TOK_FINALLY; if (streq("false", 5, buf, len)) return TOK_FALSE; break; + case 'g': if (streq("globalThis", 10, buf, len)) return TOK_GLOBAL_THIS; break; case 'i': if (streq("if", 2, buf, len)) return TOK_IF; if (streq("import", 6, buf, len)) return TOK_IMPORT; if (streq("in", 2, buf, len)) return TOK_IN; if (streq("instanceof", 10, buf, len)) return TOK_INSTANCEOF; break; case 'l': if (streq("let", 3, buf, len)) return TOK_LET; break; case 'n': if (streq("new", 3, buf, len)) return TOK_NEW; if (streq("null", 4, buf, len)) return TOK_NULL; break; @@ -2415,7 +2416,7 @@ static uint8_t parsekeyword(const char *buf, size_t len) { case 't': if (streq("try", 3, buf, len)) return TOK_TRY; if (streq("this", 4, buf, len)) return TOK_THIS; if (streq("throw", 5, buf, len)) return TOK_THROW; if (streq("true", 4, buf, len)) return TOK_TRUE; if (streq("typeof", 6, buf, len)) return TOK_TYPEOF; break; case 'u': if (streq("undefined", 9, buf, len)) return TOK_UNDEF; break; case 'v': if (streq("var", 3, buf, len)) return TOK_VAR; if (streq("void", 4, buf, len)) return TOK_VOID; break; - case 'w': if (streq("while", 5, buf, len)) return TOK_WHILE; if (streq("with", 4, buf, len)) return TOK_WITH; break; + case 'w': if (streq("while", 5, buf, len)) return TOK_WHILE; if (streq("with", 4, buf, len)) return TOK_WITH; if (streq("window", 6, buf, len)) return TOK_WINDOW; break; case 'y': if (streq("yield", 5, buf, len)) return TOK_YIELD; break; } return TOK_IDENTIFIER; @@ -4716,6 +4717,9 @@ static jsval_t js_literal(struct js *js) { case TOK_FALSE: return js_mkfalse(); case TOK_THIS: return js->this_val; + case TOK_WINDOW: + case TOK_GLOBAL_THIS: return js_glob(js); + case TOK_TYPEOF: return mkcoderef((jsoff_t) js->toff, (jsoff_t) js->tlen); case TOK_FROM: return mkcoderef((jsoff_t) js->toff, (jsoff_t) js->tlen); case TOK_VOID: return mkcoderef((jsoff_t) js->toff, (jsoff_t) js->tlen); diff --git a/src/core/events.js b/src/core/events.js index 3ab3887..1480de3 100644 --- a/src/core/events.js +++ b/src/core/events.js @@ -1,4 +1,4 @@ -this.createEventTarget = function () { +globalThis.createEventTarget = function () { const obj = {}; obj.addEventListener = EventTargetPrototype.addEventListener; obj.removeEventListener = EventTargetPrototype.removeEventListener; diff --git a/src/main.c b/src/main.c index 9edba86..185c0ef 100644 --- a/src/main.c +++ b/src/main.c @@ -10,6 +10,10 @@ #include "runtime.h" #include "repl.h" +#ifndef ANT_SNAPSHOT_GENERATOR +#include "snapshot.h" +#endif + #include "modules/builtin.h" #include "modules/buffer.h" #include "modules/atomics.h" @@ -167,11 +171,7 @@ int main(int argc, char *argv[]) { } if (gct->count > 0) js_setgct(js, gct->ival[0]); - ant_runtime_init(js); - - js_set(js, js_glob(js), "global", js_glob(js)); - js_set(js, js_glob(js), "globalThis", js_glob(js)); init_builtin_module(); init_buffer_module(); @@ -192,6 +192,13 @@ int main(int argc, char *argv[]) { ant_register_library(path_library, "ant:path", "node:path", NULL); ant_register_library(fs_library, "ant:fs", "node:fs", NULL); ant_register_library(crypto_library, "ant:crypto", "node:crypto", NULL); + + #ifndef ANT_SNAPSHOT_GENERATOR + jsval_t snapshot_result = ant_load_snapshot(js); + if (js_type(snapshot_result) == JS_ERR) { + fprintf(stderr, "Warning: Failed to load snapshot: %s\n", js_str(js, snapshot_result)); + } + #endif if (eval->count > 0) eval_code(js, eval, print); else if (repl_mode) ant_repl_run(); else { diff --git a/src/runtime.c b/src/runtime.c index 3c35922..afb08f6 100644 --- a/src/runtime.c +++ b/src/runtime.c @@ -1,7 +1,3 @@ -#ifndef ANT_SNAPSHOT_GENERATOR -#include "snapshot.h" -#endif - #include #include #include @@ -17,13 +13,7 @@ struct ant_runtime *ant_runtime_init(struct js *js) { runtime.external_event_loop_active = 0; js_set(js, js_glob(js), "Ant", runtime.ant_obj); + js_set(js, js_glob(js), "global", js_glob(js)); -#ifndef ANT_SNAPSHOT_GENERATOR - jsval_t snapshot_result = ant_load_snapshot(js); - if (js_type(snapshot_result) == JS_ERR) { - fprintf(stderr, "Warning: Failed to load snapshot: %s\n", js_str(js, snapshot_result)); - } -#endif - return &runtime; } \ No newline at end of file diff --git a/tests/test_function_scope.js b/tests/test_function_scope.js new file mode 100644 index 0000000..6b7a6b9 --- /dev/null +++ b/tests/test_function_scope.js @@ -0,0 +1,76 @@ +// Test that window/globalThis remain global inside functions + +console.log("=== Global Scope ==="); +globalThis.globalVar = "I am global"; +console.log("globalThis.globalVar:", globalThis.globalVar); + +console.log("\n=== Inside Regular Function ==="); +function testRegularFunc() { + console.log("Inside function, globalThis.globalVar:", globalThis.globalVar); + console.log("Inside function, window.globalVar:", window.globalVar); + + // Set a new property from inside the function + window.fromFunction = "set from inside function"; + globalThis.alsoFromFunction = "also from inside"; + + // Test that window/globalThis are the same + console.log("Inside function, window === globalThis:", window === globalThis); +} + +testRegularFunc(); +console.log("After function, window.fromFunction:", window.fromFunction); +console.log("After function, globalThis.alsoFromFunction:", globalThis.alsoFromFunction); + +console.log("\n=== Inside Arrow Function ==="); +const testArrowFunc = () => { + console.log("Arrow function, globalThis.globalVar:", globalThis.globalVar); + console.log("Arrow function, window.globalVar:", window.globalVar); + window.fromArrow = "from arrow function"; +}; + +testArrowFunc(); +console.log("After arrow, window.fromArrow:", window.fromArrow); + +console.log("\n=== Inside Nested Function ==="); +function outer() { + console.log("Outer function, globalThis.globalVar:", globalThis.globalVar); + + function inner() { + console.log("Inner function, globalThis.globalVar:", globalThis.globalVar); + console.log("Inner function, window.globalVar:", window.globalVar); + window.fromNested = "from nested function"; + } + + inner(); +} + +outer(); +console.log("After nested, window.fromNested:", window.fromNested); + +console.log("\n=== Inside Constructor ==="); +function MyClass() { + console.log("Constructor, globalThis.globalVar:", globalThis.globalVar); + console.log("Constructor, window.globalVar:", window.globalVar); + console.log("Constructor, this === window:", this === window); + console.log("Constructor, this === globalThis:", this === globalThis); + window.fromConstructor = "from constructor"; +} + +new MyClass(); +console.log("After constructor, window.fromConstructor:", window.fromConstructor); + +console.log("\n=== Inside Method ==="); +const obj = { + method: function() { + console.log("Method, globalThis.globalVar:", globalThis.globalVar); + console.log("Method, window.globalVar:", window.globalVar); + console.log("Method, this === window:", this === window); + console.log("Method, this === globalThis:", this === globalThis); + window.fromMethod = "from method"; + } +}; + +obj.method(); +console.log("After method, window.fromMethod:", window.fromMethod); + +console.log("\n=== All tests passed! ===");