MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

event target binds

+236 -15
+97
examples/events.js
··· 1 + console.log('Example 1: Global Events'); 2 + addEventListener('appReady', () => { 3 + console.log(' App is ready!'); 4 + }); 5 + dispatchEvent('appReady'); 6 + 7 + console.log('\nExample 2: Custom Event Data'); 8 + addEventListener('userLogin', event => { 9 + console.log(' User logged in:', event.detail.username); 10 + console.log(' Login time:', event.detail.timestamp); 11 + }); 12 + dispatchEvent('userLogin', { 13 + username: 'alice', 14 + timestamp: Date.now() 15 + }); 16 + 17 + console.log('\nExample 3: Object Events'); 18 + const button = createEventTarget(); 19 + button.name = 'MyButton'; 20 + 21 + button.addEventListener('click', event => { 22 + console.log(' Button clicked!'); 23 + console.log(' Button name:', event.target.name); 24 + }); 25 + 26 + button.dispatchEvent('click'); 27 + button.dispatchEvent('click'); 28 + 29 + console.log('\nExample 4: Multiple Event Targets'); 30 + const user = createEventTarget(); 31 + user.name = 'Alice'; 32 + 33 + const socket = createEventTarget(); 34 + socket.id = 'socket-123'; 35 + 36 + user.addEventListener('statusChange', event => { 37 + console.log(' User status changed:', event.detail.status); 38 + }); 39 + 40 + socket.addEventListener('message', event => { 41 + console.log(' Socket message:', event.detail.data); 42 + }); 43 + 44 + user.dispatchEvent('statusChange', { status: 'online' }); 45 + socket.dispatchEvent('message', { data: 'Hello!' }); 46 + 47 + console.log('\nExample 5: Once Listeners'); 48 + const startup = createEventTarget(); 49 + let initCount = 0; 50 + 51 + startup.addEventListener( 52 + 'init', 53 + () => { 54 + initCount++; 55 + console.log(' Initialization running... (count:', initCount + ')'); 56 + }, 57 + { once: true } 58 + ); 59 + 60 + startup.dispatchEvent('init'); 61 + startup.dispatchEvent('init'); 62 + startup.dispatchEvent('init'); 63 + console.log(' Total init calls:', initCount); 64 + 65 + console.log('\nExample 6: Event Emitter Pattern'); 66 + class MyEmitter { 67 + constructor() { 68 + const target = createEventTarget(); 69 + this.on = target.addEventListener.bind(target); 70 + this.off = target.removeEventListener.bind(target); 71 + this.emit = target.dispatchEvent.bind(target); 72 + } 73 + } 74 + 75 + const emitter = new MyEmitter(); 76 + 77 + emitter.on('data', event => { 78 + console.log(' Data received:', event.detail); 79 + }); 80 + 81 + emitter.emit('data', { value: 42, type: 'number' }); 82 + emitter.emit('data', { value: 'hello', type: 'string' }); 83 + 84 + console.log('\nExample 7: Removing Listeners'); 85 + const temp = createEventTarget(); 86 + 87 + function handler(event) { 88 + console.log(' Handler called with:', event.detail); 89 + } 90 + 91 + temp.addEventListener('test', handler); 92 + temp.dispatchEvent('test', 'first call'); 93 + 94 + temp.removeEventListener('test', handler); 95 + temp.dispatchEvent('test', 'second call (not shown)'); 96 + 97 + console.log(' Handler was removed successfully');
+1 -1
meson.build
··· 74 74 build_date = run_command('date', '+%Y-%m-%d', check: true).stdout().strip() 75 75 76 76 version_conf = configuration_data() 77 - version_conf.set('ANT_VERSION', '0.0.8.7') 77 + version_conf.set('ANT_VERSION', '0.0.8.8') 78 78 version_conf.set('ANT_GIT_HASH', git_hash) 79 79 version_conf.set('ANT_BUILD_DATE', build_date) 80 80
+43 -14
src/ant.c
··· 3126 3126 3127 3127 if (vtype(func) != T_FUNC) return js_mkerr(js, "not a function"); 3128 3128 jsval_t func_obj = mkval(T_OBJ, vdata(func)); 3129 - 3129 + 3130 3130 jsoff_t native_off = lkp(js, func_obj, "__native_func", 13); 3131 3131 if (native_off != 0) { 3132 3132 jsval_t native_val = resolveprop(js, mkval(T_PROP, native_off)); 3133 3133 if (vtype(native_val) == T_CFUNC) { 3134 + jsoff_t this_off = lkp(js, func_obj, "__this", 6); 3135 + jsval_t bound_this = js_mkundef(); 3136 + if (this_off != 0) { 3137 + bound_this = resolveprop(js, mkval(T_PROP, this_off)); 3138 + } 3139 + 3140 + jsval_t saved_this = js->this_val; 3141 + if (vtype(bound_this) != JS_UNDEF) { 3142 + push_this(bound_this); 3143 + js->this_val = bound_this; 3144 + } 3145 + 3134 3146 jsval_t (*fn)(struct js *, jsval_t *, int) = (jsval_t(*)(struct js *, jsval_t *, int)) vdata(native_val); 3135 - return fn(js, args, nargs); 3147 + jsval_t result = fn(js, args, nargs); 3148 + 3149 + if (vtype(bound_this) != JS_UNDEF) { 3150 + pop_this(); 3151 + js->this_val = saved_this; 3152 + } 3153 + 3154 + return result; 3136 3155 } 3137 3156 } 3138 3157 ··· 7068 7087 7069 7088 jsval_t saved_this = js->this_val; 7070 7089 push_this(this_arg); 7071 - js->this_val = this_arg; 7072 7090 7091 + js->this_val = this_arg; 7073 7092 jsval_t result = call_js_with_args(js, func, call_args, call_nargs); 7074 - 7093 + 7075 7094 pop_this(); 7076 7095 js->this_val = saved_this; 7077 - 7096 + 7078 7097 if (call_args) ANT_GC_FREE(call_args); 7079 - 7098 + 7080 7099 return result; 7081 7100 } 7082 7101 7083 7102 static jsval_t builtin_function_bind(struct js *js, jsval_t *args, int nargs) { 7084 7103 jsval_t func = js->this_val; 7085 - if (vtype(func) != T_FUNC) { 7104 + 7105 + if (vtype(func) != T_FUNC && vtype(func) != T_CFUNC) { 7086 7106 return js_mkerr(js, "bind requires a function"); 7087 7107 } 7088 - 7108 + 7089 7109 jsval_t this_arg = (nargs > 0) ? args[0] : js_mkundef(); 7090 - 7110 + 7111 + if (vtype(func) == T_CFUNC) { 7112 + jsval_t bound_func = mkobj(js, 0); 7113 + if (is_err(bound_func)) return bound_func; 7114 + 7115 + setprop(js, bound_func, js_mkstr(js, "__native_func", 13), func); 7116 + setprop(js, bound_func, js_mkstr(js, "__this", 6), this_arg); 7117 + 7118 + return mkval(T_FUNC, (unsigned long) vdata(bound_func)); 7119 + } 7120 + 7091 7121 jsval_t func_obj = mkval(T_OBJ, vdata(func)); 7092 7122 jsval_t bound_func = mkobj(js, 0); 7093 7123 if (is_err(bound_func)) return bound_func; 7094 - 7124 + 7095 7125 jsoff_t code_off = lkp(js, func_obj, "__code", 6); 7096 7126 if (code_off != 0) { 7097 7127 jsval_t code_val = resolveprop(js, mkval(T_PROP, code_off)); 7098 7128 setprop(js, bound_func, js_mkstr(js, "__code", 6), code_val); 7099 7129 } 7100 - 7130 + 7101 7131 jsoff_t scope_off = lkp(js, func_obj, "__scope", 7); 7102 7132 if (scope_off != 0) { 7103 7133 jsval_t scope_val = resolveprop(js, mkval(T_PROP, scope_off)); 7104 7134 setprop(js, bound_func, js_mkstr(js, "__scope", 7), scope_val); 7105 7135 } 7106 - 7136 + 7107 7137 jsoff_t async_off = lkp(js, func_obj, "__async", 7); 7108 7138 if (async_off != 0) { 7109 7139 jsval_t async_val = resolveprop(js, mkval(T_PROP, async_off)); 7110 7140 setprop(js, bound_func, js_mkstr(js, "__async", 7), async_val); 7111 7141 } 7112 - 7142 + 7113 7143 setprop(js, bound_func, js_mkstr(js, "__this", 6), this_arg); 7114 - 7115 7144 return mkval(T_FUNC, (unsigned long) vdata(bound_func)); 7116 7145 } 7117 7146
+1
src/tools/gen_snapshot.c
··· 292 292 const char *paren_close = strchr(quote_end, ')'); 293 293 if (paren_close) { 294 294 pos = paren_close + 1; 295 + if (*pos == ';') pos++; 295 296 } else { 296 297 pos = quote_end + 1; 297 298 }
+60
tests/test_native_bind.js
··· 1 + // Test binding native event functions 2 + 3 + console.log('Testing .bind() with native functions...\n'); 4 + 5 + // Test 1: Bind addEventListener 6 + console.log('Test 1: Bind addEventListener'); 7 + const target = createEventTarget(); 8 + const boundAdd = target.addEventListener.bind(target); 9 + 10 + console.log(' boundAdd type:', typeof boundAdd); 11 + 12 + try { 13 + boundAdd('test', () => { 14 + console.log(' Listener called!'); 15 + }); 16 + target.dispatchEvent('test'); 17 + console.log(' PASS: Bound native function works!'); 18 + } catch (e) { 19 + console.log(' FAIL:', e); 20 + } 21 + 22 + // Test 2: Store bound method in object 23 + console.log('\nTest 2: Store bound methods in object'); 24 + const target2 = createEventTarget(); 25 + const wrapper = {}; 26 + wrapper.on = target2.addEventListener.bind(target2); 27 + wrapper.emit = target2.dispatchEvent.bind(target2); 28 + 29 + try { 30 + wrapper.on('test', () => { 31 + console.log(' Stored bound listener called!'); 32 + }); 33 + wrapper.emit('test'); 34 + console.log(' PASS: Stored bound methods work!'); 35 + } catch (e) { 36 + console.log(' FAIL:', e); 37 + } 38 + 39 + // Test 3: Use in a class 40 + console.log('\nTest 3: Use bound methods in class'); 41 + class MyEmitter { 42 + constructor() { 43 + const target = createEventTarget(); 44 + this.on = target.addEventListener.bind(target); 45 + this.emit = target.dispatchEvent.bind(target); 46 + } 47 + } 48 + 49 + try { 50 + const emitter = new MyEmitter(); 51 + emitter.on('test', () => { 52 + console.log(' Class listener called!'); 53 + }); 54 + emitter.emit('test'); 55 + console.log(' PASS: Class with bound methods works!'); 56 + } catch (e) { 57 + console.log(' FAIL:', e); 58 + } 59 + 60 + console.log('\nAll tests completed!');
+34
tests/test_native_bind_debug.js
··· 1 + // Debug native function binding 2 + 3 + const target = createEventTarget(); 4 + 5 + console.log('target:', target); 6 + console.log('typeof target:', typeof target); 7 + 8 + const addEventListenerFn = target.addEventListener; 9 + console.log('\naddEventListenerFn:', addEventListenerFn); 10 + console.log('typeof addEventListenerFn:', typeof addEventListenerFn); 11 + 12 + console.log('\nTrying to call it directly:'); 13 + try { 14 + addEventListenerFn.call(target, 'test', () => { 15 + console.log('Direct call worked!'); 16 + }); 17 + target.dispatchEvent('test'); 18 + } catch (e) { 19 + console.log('Error:', e); 20 + } 21 + 22 + console.log('\nTrying to bind it:'); 23 + try { 24 + const bound = addEventListenerFn.bind(target); 25 + console.log('bound:', bound); 26 + console.log('typeof bound:', typeof bound); 27 + 28 + bound('test', () => { 29 + console.log('Bound call worked!'); 30 + }); 31 + target.dispatchEvent('test'); 32 + } catch (e) { 33 + console.log('Error:', e); 34 + }