From 38e06f13d6fdab26d6095d6d86eeb62ffffce0e3 Mon Sep 17 00:00:00 2001 From: Benjamin Findley Date: Fri, 11 Aug 2023 11:49:31 -0700 Subject: [PATCH 1/8] prevent potential segfaults when using large allocations from dynamic pool --- core/mem/allocators.odin | 1 + 1 file changed, 1 insertion(+) diff --git a/core/mem/allocators.odin b/core/mem/allocators.odin index 77cdfb3cf..1ed8f0c34 100644 --- a/core/mem/allocators.odin +++ b/core/mem/allocators.odin @@ -749,6 +749,7 @@ dynamic_pool_alloc_bytes :: proc(p: ^Dynamic_Pool, bytes: int) -> ([]byte, Alloc n := bytes extra := p.alignment - (n % p.alignment) n += extra + if n > p.block_size do return nil, .Invalid_Argument if n >= p.out_band_size { assert(p.block_allocator.procedure != nil) memory, err := p.block_allocator.procedure(p.block_allocator.data, Allocator_Mode.Alloc, From 1182f41f993e3b32570d1f9547dcb87fb9fe262c Mon Sep 17 00:00:00 2001 From: Caedo Date: Tue, 15 Aug 2023 14:56:04 +0200 Subject: [PATCH 2/8] Fix issues with js events not being initialized properly --- vendor/wasm/js/events.odin | 13 +++++++++++++ vendor/wasm/js/runtime.js | 19 +++++++++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/vendor/wasm/js/events.odin b/vendor/wasm/js/events.odin index f14d7054e..c9a11c691 100644 --- a/vendor/wasm/js/events.odin +++ b/vendor/wasm/js/events.odin @@ -1,6 +1,8 @@ //+build js wasm32, js wasm64p32 package wasm_js_interface +import "core:runtime" + foreign import dom_lib "odin_dom" Event_Kind :: enum u32 { @@ -343,7 +345,18 @@ do_event_callback :: proc(user_data: rawptr, callback: proc(e: Event)) { user_data = user_data, callback = callback, } + + init_event_raw(&event) + + if event.kind == .Key_Up || event.kind == .Key_Down || event.kind == .Key_Press { + key := transmute(^runtime.Raw_String) &event.key.key + key.data = &event.key._key_buf[0] + + code := transmute(^runtime.Raw_String) &event.key.code + code.data = &event.key._code_buf[0] + } + callback(event) } } \ No newline at end of file diff --git a/vendor/wasm/js/runtime.js b/vendor/wasm/js/runtime.js index bcc7e2051..353bc521d 100644 --- a/vendor/wasm/js/runtime.js +++ b/vendor/wasm/js/runtime.js @@ -99,6 +99,11 @@ class WasmMemoryInterface { storeF64(addr, value) { this.mem.setFloat64(addr, value, true); } storeInt(addr, value) { this.mem.setInt32 (addr, value, true); } storeUint(addr, value) { this.mem.setUint32 (addr, value, true); } + + storeString(addr, value) { + const bytes = this.loadBytes(addr, value.length); + new TextEncoder("utf-8").encodeInto(value, bytes); + } }; class WebGLInterface { @@ -1384,6 +1389,7 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) { wmi.storeUint(off(W), event_temp_data.id_ptr); wmi.storeUint(off(W), event_temp_data.id_len); + wmi.storeUint(off(W), 0); // padding wmi.storeF64(off(8), e.timeStamp*1e-3); @@ -1417,8 +1423,14 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) { wmi.storeI16(off(2), e.button); wmi.storeU16(off(2), e.buttons); } else if (e instanceof KeyboardEvent) { - let keyOffset = off(W*2, W); - let codeOffet = off(W*2, W); + // NOTE: we set string data pointers on the + // native side, so skip those for now and + // set only string length + const keyPtr = off(W); + wmi.storeI32(off(W), e.key.length); + const codePtr = off(W); + wmi.storeI32(off(W), e.code.length); + wmi.storeU8(off(1), e.location); wmi.storeU8(off(1), !!e.ctrlKey); @@ -1427,6 +1439,9 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) { wmi.storeU8(off(1), !!e.metaKey); wmi.storeU8(off(1), !!e.repeat); + + wmi.storeString(off(16, 1), e.key); + wmi.storeString(off(16, 1), e.code); } else if (e instanceof WheelEvent) { wmi.storeF64(off(8), e.deltaX); wmi.storeF64(off(8), e.deltaY); From 7e4a65114a9140e403eeae8d4e321098a25d2e0e Mon Sep 17 00:00:00 2001 From: Benjamin Findley Date: Tue, 15 Aug 2023 08:49:27 -0700 Subject: [PATCH 3/8] fix whitespace --- core/mem/allocators.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/mem/allocators.odin b/core/mem/allocators.odin index 1ed8f0c34..b6a296322 100644 --- a/core/mem/allocators.odin +++ b/core/mem/allocators.odin @@ -749,7 +749,7 @@ dynamic_pool_alloc_bytes :: proc(p: ^Dynamic_Pool, bytes: int) -> ([]byte, Alloc n := bytes extra := p.alignment - (n % p.alignment) n += extra - if n > p.block_size do return nil, .Invalid_Argument + if n > p.block_size do return nil, .Invalid_Argument if n >= p.out_band_size { assert(p.block_allocator.procedure != nil) memory, err := p.block_allocator.procedure(p.block_allocator.data, Allocator_Mode.Alloc, From b31d8b1ad08cb77aded0a473bd4e7ecac97a7648 Mon Sep 17 00:00:00 2001 From: Lucas Perlind Date: Wed, 16 Aug 2023 21:13:56 +1000 Subject: [PATCH 4/8] Update rand documentation about floats --- core/math/rand/rand.odin | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/core/math/rand/rand.odin b/core/math/rand/rand.odin index 12842539b..34444a1b9 100644 --- a/core/math/rand/rand.odin +++ b/core/math/rand/rand.odin @@ -454,13 +454,14 @@ int_max :: proc(n: int, r: ^Rand = nil) -> (val: int) { } /* -Generates a random double floating point value in the range `(0, 1]` using the provided random number generator. If no generator is provided the global random number generator will be used. +Generates a random double floating point value in the range `0 to 1` using the provided random number generator. If no generator is provided the global random number generator will be used. +Due to floating point precision there is no guarantee if the upper and lower bounds are inclusive/exclusive with the exact floating point value. Inputs: - r: The random number generator to use, or nil for the global generator Returns: -- val: A random double floating point value in the range `(0, 1]` +- val: A random double floating point value in the range `0 to 1` Example: import "core:math/rand" @@ -479,13 +480,14 @@ Example: @(require_results) float64 :: proc(r: ^Rand = nil) -> (val: f64) { return f64(int63_max(1<<53, r)) / (1 << 53) } /* -Generates a random single floating point value in the range `(0, 1]` using the provided random number generator. If no generator is provided the global random number generator will be used. +Generates a random single floating point value in the range `0 to 1` using the provided random number generator. If no generator is provided the global random number generator will be used. +Due to floating point precision there is no guarantee if the upper and lower bounds are inclusive/exclusive with the exact floating point value. Inputs: - r: The random number generator to use, or nil for the global generator Returns: -- val: A random single floating point value in the range `(0, 1]` +- val: A random single floating point value in the range `0 to 1` Example: import "core:math/rand" @@ -504,7 +506,8 @@ Example: @(require_results) float32 :: proc(r: ^Rand = nil) -> (val: f32) { return f32(float64(r)) } /* -Generates a random double floating point value in the range `(low, high]` using the provided random number generator. If no generator is provided the global random number generator will be used. +Generates a random double floating point value in the range `low to high` using the provided random number generator. If no generator is provided the global random number generator will be used. +Due to floating point precision there is no guarantee if the upper and lower bounds are inclusive/exclusive with the exact floating point value. Inputs: - low: The lower bounds of the value, this value is inclusive @@ -512,7 +515,7 @@ Inputs: - r: The random number generator to use, or nil for the global generator Returns: -- val: A random double floating point value in the range `(low, high]` +- val: A random double floating point value in the range `low to high` Example: import "core:math/rand" @@ -531,7 +534,8 @@ Example: @(require_results) float64_range :: proc(low, high: f64, r: ^Rand = nil) -> (val: f64) { return (high-low)*float64(r) + low } /* -Generates a random single floating point value in the range `(low, high]` using the provided random number generator. If no generator is provided the global random number generator will be used. +Generates a random single floating point value in the range `low to high` using the provided random number generator. If no generator is provided the global random number generator will be used. +Due to floating point precision there is no guarantee if the upper and lower bounds are inclusive/exclusive with the exact floating point value. Inputs: - low: The lower bounds of the value, this value is inclusive @@ -539,7 +543,7 @@ Inputs: - r: The random number generator to use, or nil for the global generator Returns: -- val: A random single floating point value in the range `(low, high]` +- val: A random single floating point value in the range `low to high` Example: import "core:math/rand" @@ -559,6 +563,7 @@ Example: /* Fills a byte slice with random values using the provided random number generator. If no generator is provided the global random number generator will be used. +Due to floating point precision there is no guarantee if the upper and lower bounds are inclusive/exclusive with the exact floating point value. Inputs: - p: The byte slice to fill From b185d9e70151b6e47282cbb6a730a0ae48ea778b Mon Sep 17 00:00:00 2001 From: Caedo Date: Wed, 16 Aug 2023 20:33:17 +0200 Subject: [PATCH 5/8] Remove pointer magic when creating strings --- vendor/wasm/js/events.odin | 11 ++++------- vendor/wasm/js/runtime.js | 14 +++++++------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/vendor/wasm/js/events.odin b/vendor/wasm/js/events.odin index c9a11c691..7c5dc39d6 100644 --- a/vendor/wasm/js/events.odin +++ b/vendor/wasm/js/events.odin @@ -1,8 +1,6 @@ //+build js wasm32, js wasm64p32 package wasm_js_interface -import "core:runtime" - foreign import dom_lib "odin_dom" Event_Kind :: enum u32 { @@ -235,6 +233,8 @@ Event :: struct { repeat: bool, + _key_len: int, + _code_len: int, _key_buf: [KEYBOARD_MAX_KEY_SIZE]byte, _code_buf: [KEYBOARD_MAX_KEY_SIZE]byte, }, @@ -350,11 +350,8 @@ do_event_callback :: proc(user_data: rawptr, callback: proc(e: Event)) { init_event_raw(&event) if event.kind == .Key_Up || event.kind == .Key_Down || event.kind == .Key_Press { - key := transmute(^runtime.Raw_String) &event.key.key - key.data = &event.key._key_buf[0] - - code := transmute(^runtime.Raw_String) &event.key.code - code.data = &event.key._code_buf[0] + event.key.key = string(event.key._key_buf[:event.key._key_len]) + event.key.code = string(event.key._code_buf[:event.key._code_len]) } callback(event) diff --git a/vendor/wasm/js/runtime.js b/vendor/wasm/js/runtime.js index 353bc521d..5980f8c6d 100644 --- a/vendor/wasm/js/runtime.js +++ b/vendor/wasm/js/runtime.js @@ -1423,13 +1423,11 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) { wmi.storeI16(off(2), e.button); wmi.storeU16(off(2), e.buttons); } else if (e instanceof KeyboardEvent) { - // NOTE: we set string data pointers on the - // native side, so skip those for now and - // set only string length - const keyPtr = off(W); - wmi.storeI32(off(W), e.key.length); - const codePtr = off(W); - wmi.storeI32(off(W), e.code.length); + // Note: those strigs are constructed + // on the native side from buffers that + // are filled later, so skip them + const keyPtr = off(W*2, W); + const codePtr = off(W*2, W); wmi.storeU8(off(1), e.location); @@ -1440,6 +1438,8 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) { wmi.storeU8(off(1), !!e.repeat); + wmi.storeI32(off(W), e.key.length) + wmi.storeI32(off(W), e.code.length) wmi.storeString(off(16, 1), e.key); wmi.storeString(off(16, 1), e.code); } else if (e instanceof WheelEvent) { From 8b680254ee641e6375734ac74149257ebe7d0194 Mon Sep 17 00:00:00 2001 From: Lucas Perlind Date: Fri, 18 Aug 2023 11:14:39 +1000 Subject: [PATCH 6/8] Better guarantee boundaries of floating point rand --- core/math/rand/rand.odin | 45 ++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/core/math/rand/rand.odin b/core/math/rand/rand.odin index 34444a1b9..bf58550fd 100644 --- a/core/math/rand/rand.odin +++ b/core/math/rand/rand.odin @@ -5,6 +5,7 @@ Package core:math/rand implements various random number generators package rand import "core:intrinsics" +import "core:math" import "core:mem" Rand :: struct { @@ -454,14 +455,13 @@ int_max :: proc(n: int, r: ^Rand = nil) -> (val: int) { } /* -Generates a random double floating point value in the range `0 to 1` using the provided random number generator. If no generator is provided the global random number generator will be used. -Due to floating point precision there is no guarantee if the upper and lower bounds are inclusive/exclusive with the exact floating point value. +Generates a random double floating point value in the range `[0, 1)` using the provided random number generator. If no generator is provided the global random number generator will be used. Inputs: - r: The random number generator to use, or nil for the global generator Returns: -- val: A random double floating point value in the range `0 to 1` +- val: A random double floating point value in the range `[0, 1)` Example: import "core:math/rand" @@ -480,14 +480,13 @@ Example: @(require_results) float64 :: proc(r: ^Rand = nil) -> (val: f64) { return f64(int63_max(1<<53, r)) / (1 << 53) } /* -Generates a random single floating point value in the range `0 to 1` using the provided random number generator. If no generator is provided the global random number generator will be used. -Due to floating point precision there is no guarantee if the upper and lower bounds are inclusive/exclusive with the exact floating point value. +Generates a random single floating point value in the range `[0, 1)` using the provided random number generator. If no generator is provided the global random number generator will be used. Inputs: - r: The random number generator to use, or nil for the global generator Returns: -- val: A random single floating point value in the range `0 to 1` +- val: A random single floating point value in the range `[0, 1)` Example: import "core:math/rand" @@ -503,11 +502,12 @@ Example: */ -@(require_results) float32 :: proc(r: ^Rand = nil) -> (val: f32) { return f32(float64(r)) } +@(require_results) float32 :: proc(r: ^Rand = nil) -> (val: f32) { return f32(int31_max(1<<24, r)) / (1 << 24) } /* -Generates a random double floating point value in the range `low to high` using the provided random number generator. If no generator is provided the global random number generator will be used. -Due to floating point precision there is no guarantee if the upper and lower bounds are inclusive/exclusive with the exact floating point value. +Generates a random double floating point value in the range `[low, high)` using the provided random number generator. If no generator is provided the global random number generator will be used. + +WARNING: Panics if `high < low` Inputs: - low: The lower bounds of the value, this value is inclusive @@ -515,7 +515,7 @@ Inputs: - r: The random number generator to use, or nil for the global generator Returns: -- val: A random double floating point value in the range `low to high` +- val: A random double floating point value in the range [low, high) Example: import "core:math/rand" @@ -531,11 +531,17 @@ Example: */ -@(require_results) float64_range :: proc(low, high: f64, r: ^Rand = nil) -> (val: f64) { return (high-low)*float64(r) + low } +@(require_results) float64_range :: proc(low, high: f64, r: ^Rand = nil) -> (val: f64) { + assert(low <= high, "low must be lower than or equal to high") + val = (high-low)*float64(r) + low + if val >= high { + val = max(low, high * (1 - math.F64_EPSILON)) + } + return +} /* -Generates a random single floating point value in the range `low to high` using the provided random number generator. If no generator is provided the global random number generator will be used. -Due to floating point precision there is no guarantee if the upper and lower bounds are inclusive/exclusive with the exact floating point value. +Generates a random single floating point value in the range `[low, high)` using the provided random number generator. If no generator is provided the global random number generator will be used. Inputs: - low: The lower bounds of the value, this value is inclusive @@ -543,7 +549,9 @@ Inputs: - r: The random number generator to use, or nil for the global generator Returns: -- val: A random single floating point value in the range `low to high` +- val: A random single floating point value in the range [low, high) + +WARNING: Panics if `high < low` Example: import "core:math/rand" @@ -559,7 +567,14 @@ Example: */ -@(require_results) float32_range :: proc(low, high: f32, r: ^Rand = nil) -> (val: f32) { return (high-low)*float32(r) + low } +@(require_results) float32_range :: proc(low, high: f32, r: ^Rand = nil) -> (val: f32) { + assert(low <= high, "low must be lower than or equal to high") + val = (high-low)*float32(r) + low + if val >= high { + val = max(low, high * (1 - math.F32_EPSILON)) + } + return +} /* Fills a byte slice with random values using the provided random number generator. If no generator is provided the global random number generator will be used. From 99d6a077fedf67632e0c44b44df7e1ac98228868 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Fri, 18 Aug 2023 22:16:59 +0200 Subject: [PATCH 7/8] _buffer_grow: Preserve allocator if already set via init_buffer_allocator Fixes #2756 --- core/bytes/buffer.odin | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/bytes/buffer.odin b/core/bytes/buffer.odin index 4375d8195..abfee6f2f 100644 --- a/core/bytes/buffer.odin +++ b/core/bytes/buffer.odin @@ -113,8 +113,11 @@ _buffer_grow :: proc(b: ^Buffer, n: int) -> int { if i, ok := _buffer_try_grow(b, n); ok { return i } + if b.buf == nil && n <= SMALL_BUFFER_SIZE { - b.buf = make([dynamic]byte, n, SMALL_BUFFER_SIZE) + // Fixes #2756 by preserving allocator if already set on Buffer via init_buffer_allocator + reserve(&b.buf, SMALL_BUFFER_SIZE) + resize(&b.buf, n) return 0 } From edcd335b9036bac1d3e1d67f0cbd18d82d50ac3f Mon Sep 17 00:00:00 2001 From: Lucas Perlind Date: Mon, 21 Aug 2023 11:33:26 +1000 Subject: [PATCH 8/8] Always include Cocoa for NSFoundation --- vendor/darwin/Foundation/objc.odin | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/vendor/darwin/Foundation/objc.odin b/vendor/darwin/Foundation/objc.odin index ac3aeb6ef..6469b1d1d 100644 --- a/vendor/darwin/Foundation/objc.odin +++ b/vendor/darwin/Foundation/objc.odin @@ -1,6 +1,8 @@ package objc_Foundation foreign import "system:Foundation.framework" +// NOTE: Most of our bindings are reliant on Cocoa (everything under appkit) so just unconditionally import it +@(require) foreign import "system:Cocoa.framework" import "core:intrinsics" import "core:c" @@ -76,4 +78,4 @@ objc_class_internals :: struct { cache: rawptr, protocols: rawptr, -} \ No newline at end of file +}