diff --git a/core/c/libc/errno.odin b/core/c/libc/errno.odin
index 843b2f1b6..de429a6ec 100644
--- a/core/c/libc/errno.odin
+++ b/core/c/libc/errno.odin
@@ -98,6 +98,14 @@ when ODIN_OS == .Haiku {
ERANGE :: B_POSIX_ERROR_BASE + 17
}
+when ODIN_OS == .JS {
+ _ :: libc
+ _get_errno :: proc "c" () -> ^int {
+ @(static) errno: int
+ return &errno
+ }
+}
+
// Odin has no way to make an identifier "errno" behave as a function call to
// read the value, or to produce an lvalue such that you can assign a different
// error value to errno. To work around this, just expose it as a function like
diff --git a/core/c/libc/stdio.odin b/core/c/libc/stdio.odin
index 019389b0d..a94a53696 100644
--- a/core/c/libc/stdio.odin
+++ b/core/c/libc/stdio.odin
@@ -89,6 +89,30 @@ when ODIN_OS == .Linux {
}
}
+when ODIN_OS == .JS {
+ fpos_t :: struct #raw_union { _: [16]char, _: longlong, _: double, }
+
+ _IOFBF :: 0
+ _IOLBF :: 1
+ _IONBF :: 2
+
+ BUFSIZ :: 1024
+
+ EOF :: int(-1)
+
+ FOPEN_MAX :: 1000
+
+ FILENAME_MAX :: 4096
+
+ L_tmpnam :: 20
+
+ SEEK_SET :: 0
+ SEEK_CUR :: 1
+ SEEK_END :: 2
+
+ TMP_MAX :: 308915776
+}
+
when ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD {
fpos_t :: distinct i64
diff --git a/core/c/libc/stdlib.odin b/core/c/libc/stdlib.odin
index 08c6fa6f0..98280e44b 100644
--- a/core/c/libc/stdlib.odin
+++ b/core/c/libc/stdlib.odin
@@ -10,6 +10,9 @@ when ODIN_OS == .Windows {
foreign import libc "system:c"
}
+@(require)
+import "base:runtime"
+
when ODIN_OS == .Windows {
RAND_MAX :: 0x7fff
@@ -145,6 +148,10 @@ aligned_alloc :: #force_inline proc "c" (alignment, size: size_t) -> rawptr {
_aligned_malloc :: proc(size, alignment: size_t) -> rawptr ---
}
return _aligned_malloc(size=size, alignment=alignment)
+ } else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
+ context = runtime.default_context()
+ data, _ := runtime.mem_alloc_bytes(auto_cast size, auto_cast alignment)
+ return raw_data(data)
} else {
foreign libc {
aligned_alloc :: proc(alignment, size: size_t) -> rawptr ---
@@ -160,6 +167,9 @@ aligned_free :: #force_inline proc "c" (ptr: rawptr) {
_aligned_free :: proc(ptr: rawptr) ---
}
_aligned_free(ptr)
+ } else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
+ context = runtime.default_context()
+ runtime.mem_free(ptr)
} else {
free(ptr)
}
diff --git a/core/c/libc/string.odin b/core/c/libc/string.odin
index cde9c7e6b..4ec4f3a7a 100644
--- a/core/c/libc/string.odin
+++ b/core/c/libc/string.odin
@@ -12,6 +12,7 @@ when ODIN_OS == .Windows {
foreign import libc "system:c"
}
+@(default_calling_convention="c")
foreign libc {
// 7.24.2 Copying functions
memcpy :: proc(s1, s2: rawptr, n: size_t) -> rawptr ---
diff --git a/core/c/libc/time.odin b/core/c/libc/time.odin
index 48def707e..6828793ec 100644
--- a/core/c/libc/time.odin
+++ b/core/c/libc/time.odin
@@ -45,7 +45,7 @@ when ODIN_OS == .Windows {
}
}
-when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Darwin || ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD || ODIN_OS == .Haiku {
+when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Darwin || ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD || ODIN_OS == .Haiku || ODIN_OS == .JS {
@(default_calling_convention="c")
foreign libc {
// 7.27.2 Time manipulation functions
diff --git a/core/c/libc/wctype.odin b/core/c/libc/wctype.odin
index a41fe7fac..b96410b4c 100644
--- a/core/c/libc/wctype.odin
+++ b/core/c/libc/wctype.odin
@@ -14,7 +14,7 @@ when ODIN_OS == .Windows {
wctrans_t :: distinct wchar_t
wctype_t :: distinct ushort
-} else when ODIN_OS == .Linux {
+} else when ODIN_OS == .Linux || ODIN_OS == .JS {
wctrans_t :: distinct intptr_t
wctype_t :: distinct ulong
diff --git a/core/os/os_js.odin b/core/os/os_js.odin
index 8bf1d988b..348554728 100644
--- a/core/os/os_js.odin
+++ b/core/os/os_js.odin
@@ -1,8 +1,6 @@
#+build js
package os
-import "base:runtime"
-
foreign import "odin_env"
@(require_results)
diff --git a/core/sys/wasm/README.md b/core/sys/wasm/README.md
new file mode 100644
index 000000000..1aaeaa429
--- /dev/null
+++ b/core/sys/wasm/README.md
@@ -0,0 +1,15 @@
+# WASM on the Web
+
+This directory is for use when targeting the `js_wasm32` target and the packages that rely on it.
+
+The `js_wasm32` target assumes that the WASM output will be ran within a web browser rather than a standalone VM. In the VM cases, either `wasi_wasm32` or `freestanding_wasm32` should be used accordingly.
+
+## Example for `js_wasm32`
+
+```html
+
+
+
+```
diff --git a/vendor/wasm/js/dom.odin b/core/sys/wasm/js/dom.odin
similarity index 99%
rename from vendor/wasm/js/dom.odin
rename to core/sys/wasm/js/dom.odin
index 28dd32fed..ffc58a9a3 100644
--- a/vendor/wasm/js/dom.odin
+++ b/core/sys/wasm/js/dom.odin
@@ -90,4 +90,4 @@ window_get_scroll :: proc "contextless" () -> (x, y: f64) {
scroll: [2]f64
_window_get_scroll(&scroll)
return scroll.x, scroll.y
-}
+}
\ No newline at end of file
diff --git a/vendor/wasm/js/dom_all_targets.odin b/core/sys/wasm/js/dom_all_targets.odin
similarity index 100%
rename from vendor/wasm/js/dom_all_targets.odin
rename to core/sys/wasm/js/dom_all_targets.odin
diff --git a/vendor/wasm/js/events.odin b/core/sys/wasm/js/events.odin
similarity index 85%
rename from vendor/wasm/js/events.odin
rename to core/sys/wasm/js/events.odin
index 258776fff..905b3eba9 100644
--- a/vendor/wasm/js/events.odin
+++ b/core/sys/wasm/js/events.odin
@@ -35,7 +35,7 @@ Event_Kind :: enum u32 {
Submit,
Blur,
Change,
- HashChange,
+ Hash_Change,
Select,
Animation_Start,
@@ -82,6 +82,9 @@ Event_Kind :: enum u32 {
Context_Menu,
+ Gamepad_Connected,
+ Gamepad_Disconnected,
+
Custom,
}
@@ -117,7 +120,7 @@ event_kind_string := [Event_Kind]string{
.Submit = "submit",
.Blur = "blur",
.Change = "change",
- .HashChange = "hashchange",
+ .Hash_Change = "hashchange",
.Select = "select",
.Animation_Start = "animationstart",
@@ -164,6 +167,9 @@ event_kind_string := [Event_Kind]string{
.Context_Menu = "contextmenu",
+ .Gamepad_Connected = "gamepadconnected",
+ .Gamepad_Disconnected = "gamepaddisconnected",
+
.Custom = "?custom?",
}
@@ -180,9 +186,15 @@ Key_Location :: enum u8 {
Numpad = 3,
}
-KEYBOARD_MAX_KEY_SIZE :: 16
+KEYBOARD_MAX_KEY_SIZE :: 16
KEYBOARD_MAX_CODE_SIZE :: 16
+GAMEPAD_MAX_ID_SIZE :: 64
+GAMEPAD_MAX_MAPPING_SIZE :: 64
+
+GAMEPAD_MAX_BUTTONS :: 64
+GAMEPAD_MAX_AXES :: 16
+
Event_Target_Kind :: enum u32 {
Element = 0,
Document = 1,
@@ -203,6 +215,30 @@ Event_Option :: enum u8 {
}
Event_Options :: distinct bit_set[Event_Option; u8]
+Gamepad_Button :: struct {
+ value: f64,
+ pressed: bool,
+ touched: bool,
+}
+
+Gamepad_State :: struct {
+ id: string,
+ mapping: string,
+ index: int,
+ connected: bool,
+ timestamp: f64,
+
+ button_count: int,
+ axis_count: int,
+ buttons: [GAMEPAD_MAX_BUTTONS]Gamepad_Button `fmt:"v,button_count"`,
+ axes: [GAMEPAD_MAX_AXES]f64 `fmt:"v,axes_count"`,
+
+ _id_len: int `fmt:"-"`,
+ _mapping_len: int `fmt:"-"`,
+ _id_buf: [GAMEPAD_MAX_ID_SIZE]byte `fmt:"-"`,
+ _mapping_buf: [GAMEPAD_MAX_MAPPING_SIZE]byte `fmt:"-"`,
+}
+
Event :: struct {
kind: Event_Kind,
target_kind: Event_Target_Kind,
@@ -260,6 +296,8 @@ Event :: struct {
button: i16,
buttons: bit_set[0..<16; u16],
},
+
+ gamepad: Gamepad_State,
},
@@ -336,7 +374,18 @@ remove_custom_event_listener :: proc(id: string, name: string, user_data: rawptr
return _remove_event_listener(id, name, user_data, callback)
}
-import "core:fmt"
+get_gamepad_state :: proc "contextless" (index: int, s: ^Gamepad_State) -> bool {
+ @(default_calling_convention="contextless")
+ foreign dom_lib {
+ @(link_name="get_gamepad_state")
+ _get_gamepad_state :: proc(index: int, s: ^Gamepad_State) -> bool ---
+ }
+
+ if s == nil {
+ return false
+ }
+ return _get_gamepad_state(index, s)
+}
@(export, link_name="odin_dom_do_event_callback")
@@ -355,9 +404,13 @@ 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 {
+ #partial switch event.kind {
+ case .Key_Up, .Key_Down, .Key_Press:
event.key.key = string(event.key._key_buf[:event.key._key_len])
event.key.code = string(event.key._code_buf[:event.key._code_len])
+ case .Gamepad_Connected, .Gamepad_Disconnected:
+ event.gamepad.id = string(event.gamepad._id_buf[:event.gamepad._id_len])
+ event.gamepad.mapping = string(event.gamepad._mapping_buf[:event.gamepad._mapping_len])
}
callback(event)
diff --git a/vendor/wasm/js/events_all_targets.odin b/core/sys/wasm/js/events_all_targets.odin
similarity index 99%
rename from vendor/wasm/js/events_all_targets.odin
rename to core/sys/wasm/js/events_all_targets.odin
index ccf39015d..b7e01ca10 100644
--- a/vendor/wasm/js/events_all_targets.odin
+++ b/core/sys/wasm/js/events_all_targets.odin
@@ -284,5 +284,4 @@ add_custom_event_listener :: proc(id: string, name: string, user_data: rawptr, c
}
remove_custom_event_listener :: proc(id: string, name: string, user_data: rawptr, callback: proc(e: Event)) -> bool {
panic("vendor:wasm/js not supported on non JS targets")
-}
-
+}
\ No newline at end of file
diff --git a/vendor/wasm/js/general.odin b/core/sys/wasm/js/general.odin
similarity index 100%
rename from vendor/wasm/js/general.odin
rename to core/sys/wasm/js/general.odin
diff --git a/vendor/wasm/js/memory_all_targets.odin b/core/sys/wasm/js/memory_all_targets.odin
similarity index 100%
rename from vendor/wasm/js/memory_all_targets.odin
rename to core/sys/wasm/js/memory_all_targets.odin
diff --git a/vendor/wasm/js/memory_js.odin b/core/sys/wasm/js/memory_js.odin
similarity index 100%
rename from vendor/wasm/js/memory_js.odin
rename to core/sys/wasm/js/memory_js.odin
diff --git a/vendor/wasm/js/runtime.js b/core/sys/wasm/js/odin.js
similarity index 95%
rename from vendor/wasm/js/runtime.js
rename to core/sys/wasm/js/odin.js
index afd9f6dff..bf002da74 100644
--- a/vendor/wasm/js/runtime.js
+++ b/core/sys/wasm/js/odin.js
@@ -1533,15 +1533,49 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory, ev
wmi.storeU8(off(1), !!e.repeat);
- wmi.storeI32(off(W), e.key.length)
- wmi.storeI32(off(W), e.code.length)
+ wmi.storeInt(off(W, W), e.key.length)
+ wmi.storeInt(off(W, W), e.code.length)
wmi.storeString(off(16, 1), e.key);
wmi.storeString(off(16, 1), e.code);
} else if (e.type === 'scroll') {
- wmi.storeF64(off(8), window.scrollX);
- wmi.storeF64(off(8), window.scrollY);
+ wmi.storeF64(off(8, 8), window.scrollX);
+ wmi.storeF64(off(8, 8), window.scrollY);
} else if (e.type === 'visibilitychange') {
wmi.storeU8(off(1), !document.hidden);
+ } else if (e instanceof GamepadEvent) {
+ const idPtr = off(W*2, W);
+ const mappingPtr = off(W*2, W);
+
+ wmi.storeI32(off(W, W), e.gamepad.index);
+ wmi.storeU8(off(1), !!e.gamepad.connected);
+ wmi.storeF64(off(8, 8), e.gamepad.timestamp);
+
+ wmi.storeInt(off(W, W), e.gamepad.buttons.length);
+ wmi.storeInt(off(W, W), e.gamepad.axes.length);
+
+ for (let i = 0; i < 64; i++) {
+ if (i < e.gamepad.buttons.length) {
+ let b = e.gamepad.buttons[i];
+ wmi.storeF64(off(8, 8), b.value);
+ wmi.storeU8(off(1), !!b.pressed);
+ wmi.storeU8(off(1), !!b.touched);
+ } else {
+ off(16, 8);
+ }
+ }
+ for (let i = 0; i < 16; i++) {
+ if (i < e.gamepad.axes.length) {
+ let a = e.gamepad.axes[i];
+ wmi.storeF64(off(8, 8), a);
+ } else {
+ off(8, 8);
+ }
+ }
+
+ wmi.storeInt(off(W, W), e.gamepad.id.length)
+ wmi.storeInt(off(W, W), e.gamepad.mapping.length)
+ wmi.storeString(off(64, 1), e.gamepad.id);
+ wmi.storeString(off(64, 1), e.gamepad.mapping);
}
},
@@ -1646,6 +1680,76 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory, ev
return false;
},
+ get_gamepad_state: (gamepad_id, ep) => {
+ let index = gamepad_id;
+ let gps = navigator.getGamepads();
+ if (0 <= index && index < gps.length) {
+ let gamepad = gps[index];
+ if (!gamepad) {
+ return false;
+ }
+
+ const W = wasmMemoryInterface.intSize;
+ let offset = ep;
+ let off = (amount, alignment) => {
+ if (alignment === undefined) {
+ alignment = Math.min(amount, W);
+ }
+ if (offset % alignment != 0) {
+ offset += alignment - (offset%alignment);
+ }
+ let x = offset;
+ offset += amount;
+ return x;
+ };
+
+ let align = (alignment) => {
+ const modulo = offset & (alignment-1);
+ if (modulo != 0) {
+ offset += alignment - modulo
+ }
+ };
+
+ let wmi = wasmMemoryInterface;
+
+ const idPtr = off(W*2, W);
+ const mappingPtr = off(W*2, W);
+
+ wmi.storeI32(off(W), gamepad.index);
+ wmi.storeU8(off(1), !!gamepad.connected);
+ wmi.storeF64(off(8), gamepad.timestamp);
+
+ wmi.storeInt(off(W), gamepad.buttons.length);
+ wmi.storeInt(off(W), gamepad.axes.length);
+
+ for (let i = 0; i < 64; i++) {
+ if (i < gamepad.buttons.length) {
+ let b = gamepad.buttons[i];
+ wmi.storeF64(off(8, 8), b.value);
+ wmi.storeU8(off(1), !!b.pressed);
+ wmi.storeU8(off(1), !!b.touched);
+ } else {
+ off(16, 8);
+ }
+ }
+ for (let i = 0; i < 16; i++) {
+ if (i < gamepad.axes.length) {
+ wmi.storeF64(off(8, 8), gamepad.axes[i]);
+ } else {
+ off(8, 8);
+ }
+ }
+
+ wmi.storeInt(off(W, W), gamepad.id.length)
+ wmi.storeInt(off(W, W), gamepad.mapping.length)
+ wmi.storeString(off(64, 1), gamepad.id);
+ wmi.storeString(off(64, 1), gamepad.mapping);
+
+ return true;
+ }
+ return false;
+ },
+
get_element_value_f64: (id_ptr, id_len) => {
let id = wasmMemoryInterface.loadString(id_ptr, id_len);
let element = getElement(id);
diff --git a/core/time/rfc3339.odin b/core/time/rfc3339.odin
index e4c6565d6..20e8ea0bb 100644
--- a/core/time/rfc3339.odin
+++ b/core/time/rfc3339.odin
@@ -187,4 +187,110 @@ scan_digits :: proc(s: string, sep: string, count: int) -> (res: int, ok: bool)
found_sep |= rune(s[count]) == v
}
return res, found_sep
-}
\ No newline at end of file
+}
+
+/*
+Serialize the timestamp as a RFC 3339 string.
+
+The boolean `ok` is false if the `time` is not a valid datetime, or if allocating the result string fails.
+
+**Inputs**:
+- `utc_offset`: offset in minutes wrt UTC (ie. the timezone)
+- `include_nanos`: whether to include nanoseconds in the result.
+*/
+time_to_rfc3339 :: proc(time: Time, utc_offset : int = 0, include_nanos := true, allocator := context.allocator) -> (res: string, ok: bool) {
+ utc_offset := utc_offset
+
+ // convert to datetime
+ datetime := time_to_datetime(time) or_return
+
+ if datetime.year < 0 || datetime.year >= 10_000 { return "", false }
+
+ temp_string := [36]u8{}
+ offset : uint = 0
+
+ print_as_fixed_int :: proc(dst: []u8, offset: ^uint, width: i8, i: i64) {
+ i := i
+ width := width
+ for digit_idx in 0.. (res: i64, n_digits: i8) {
+ res = n
+ n_digits = 9
+ for res % 10 == 0 {
+ res = res / 10
+ n_digits -= 1
+ }
+ return
+ }
+
+ // pre-epoch times: turn, say, -400ms to +600ms for display
+ nanos := time._nsec % 1_000_000_000
+ if nanos < 0 {
+ nanos += 1_000_000_000
+ }
+
+ if nanos != 0 && include_nanos {
+ temp_string[offset] = '.'
+ offset += 1
+
+ // remove trailing zeroes
+ nanos_nonzero, n_digits := strip_trailing_zeroes_nanos(nanos)
+ assert(nanos_nonzero != 0)
+
+ // write digits, right-to-left
+ for digit_idx : i8 = n_digits-1; digit_idx >= 0; digit_idx -= 1 {
+ digit := u8(nanos_nonzero % 10)
+ temp_string[offset + uint(digit_idx)] = '0' + u8(digit)
+ nanos_nonzero /= 10
+ }
+ offset += uint(n_digits)
+ }
+
+ if utc_offset == 0 {
+ temp_string[offset] = 'Z'
+ offset += 1
+ } else {
+ temp_string[offset] = utc_offset > 0 ? '+' : '-'
+ offset += 1
+ utc_offset = abs(utc_offset)
+ print_as_fixed_int(temp_string[:], &offset, 2, i64(utc_offset / 60))
+ temp_string[offset] = ':'
+ offset += 1
+ print_as_fixed_int(temp_string[:], &offset, 2, i64(utc_offset % 60))
+ }
+
+ res_as_slice, res_alloc := make_slice([]u8, len=offset, allocator = allocator)
+ if res_alloc != nil {
+ return "", false
+ }
+
+ copy(res_as_slice, temp_string[:offset])
+
+ return string(res_as_slice), true
+}
diff --git a/tests/core/time/test_core_time.odin b/tests/core/time/test_core_time.odin
index 51955b1c4..424111aa3 100644
--- a/tests/core/time/test_core_time.odin
+++ b/tests/core/time/test_core_time.odin
@@ -196,6 +196,36 @@ test_parse_rfc3339_string :: proc(t: ^testing.T) {
}
}
+@test
+test_print_rfc3339 :: proc(t: ^testing.T) {
+ TestCase :: struct {
+ printed: string,
+ time: i64,
+ utc_offset: int,
+ }
+
+ tests :: [?]TestCase {
+ {"1985-04-12T23:20:50.52Z", 482196050520000000, 0},
+ {"1985-04-12T23:20:50.52001905Z", 482196050520019050, 0},
+ {"1996-12-19T16:39:57-08:00", 851013597000000000, -480},
+ {"1996-12-20T00:39:57Z", 851042397000000000, 0},
+ {"1937-01-01T12:00:27.87+00:20", -1041335972130000000, +20},
+ }
+
+ for test in tests {
+ timestamp := time.Time { _nsec = test.time }
+ printed_timestamp, ok := time.time_to_rfc3339(time=timestamp, utc_offset=test.utc_offset)
+ defer delete_string(printed_timestamp)
+
+ testing.expect(t, ok, "expected printing to work fine")
+
+ testing.expectf(
+ t, printed_timestamp == test.printed,
+ "expected is %w, printed is %w", test.printed, printed_timestamp,
+ )
+ }
+}
+
@test
test_parse_iso8601_string :: proc(t: ^testing.T) {
for test in iso8601_tests {
@@ -318,4 +348,4 @@ date_component_roundtrip_test :: proc(t: ^testing.T, moment: dt.DateTime) {
"Expected %4d-%2d-%2d %2d:%2d:%2d, got %4d-%2d-%2d %2d:%2d:%2d",
moment.year, moment.month, moment.day, moment.hour, moment.minute, moment.second, YYYY, MM, DD, hh, mm, ss,
)
-}
\ No newline at end of file
+}
diff --git a/vendor/libc/stdlib.odin b/vendor/libc/stdlib.odin
index f898de619..54590c1c9 100644
--- a/vendor/libc/stdlib.odin
+++ b/vendor/libc/stdlib.odin
@@ -37,7 +37,7 @@ realloc :: proc "c" (ptr: rawptr, new_size: uint) -> rawptr {
// Note that realloc does not actually care about alignment and is allowed to just align it to something
// else than the original allocation.
ptr, err := runtime.non_zero_mem_resize(ptr, -1, int(new_size))
- assert(err != nil, "realloc failure")
+ assert(err == nil, "realloc failure")
return raw_data(ptr)
}
diff --git a/vendor/stb/image/stb_image.odin b/vendor/stb/image/stb_image.odin
index 85d612354..0c2ad7d05 100644
--- a/vendor/stb/image/stb_image.odin
+++ b/vendor/stb/image/stb_image.odin
@@ -20,7 +20,6 @@ when LIB != "" {
when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
foreign import stbi "../lib/stb_image_wasm.o"
- foreign import stbi { LIB }
} else when LIB != "" {
foreign import stbi { LIB }
} else {
diff --git a/vendor/stb/image/stb_image_resize.odin b/vendor/stb/image/stb_image_resize.odin
index a37c2e243..241a93eb0 100644
--- a/vendor/stb/image/stb_image_resize.odin
+++ b/vendor/stb/image/stb_image_resize.odin
@@ -1,6 +1,6 @@
package stb_image
-import c "core:c/libc"
+import "core:c"
@(private)
RESIZE_LIB :: (
diff --git a/vendor/stb/image/stb_image_write.odin b/vendor/stb/image/stb_image_write.odin
index a0c0b57a0..e86fa2b95 100644
--- a/vendor/stb/image/stb_image_write.odin
+++ b/vendor/stb/image/stb_image_write.odin
@@ -1,6 +1,6 @@
package stb_image
-import c "core:c/libc"
+import "core:c"
@(private)
WRITE_LIB :: (
diff --git a/vendor/wasm/README.md b/vendor/wasm/README.md
index d0b0a2f6f..1aaeaa429 100644
--- a/vendor/wasm/README.md
+++ b/vendor/wasm/README.md
@@ -6,9 +6,9 @@ The `js_wasm32` target assumes that the WASM output will be ran within a web bro
## Example for `js_wasm32`
-```js
-
-
+```html
+
+