# How to correctly import a WebAssembly.Global from JS in Zig?

**URL:** <https://ziggit.dev/t/how-to-correctly-import-a-webassembly-global-from-js-in-zig/11404>\
**Category:** Help\
**Tags:** language, memory-management, wasm, compiler, build-system\
**Created:** [August 10, 2025, 8:37am UTC](https://ziggit.dev/t/how-to-correctly-import-a-webassembly-global-from-js-in-zig/11404 "2025-08-10T08:37:01Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![veomn](https://ziggit.dev/letter_avatar_proxy/v4/letter/v/8e7dd6/32.png) [@veomn](https://ziggit.dev/u/veomn)\
**Post date:** [August 10, 2025, 8:37am UTC](https://ziggit.dev/t/how-to-correctly-import-a-webassembly-global-from-js-in-zig/11404/1 "2025-08-10T08:37:01Z")

</div>

Hello,

I am trying to import a WebAssembly.Global from JavaScript into my Zig-compiled Wasm module.

Based on the MDN documentation, the host (JavaScript) side is straightforward:

```js
const startOffsetGlobal = new WebAssembly.Global({ value: 'i32', mutable: false }, 0);
const endOffsetGlobal = new WebAssembly.Global({ value: 'i32', mutable: false }, 10000);

const importObject = {
    env: {
        memory: wasm_memory,
        array_scope_offset_start: startOffsetGlobal,
        array_scope_offset_end: endOffsetGlobal,
    },
};

const { instance } = await WebAssembly.instantiate(module, importObject);

```

The goal is to write Zig code that generates the corresponding Wasm import section:

```zig
(module
  (import "env" "array_scope_offset_start" (global i32))
  (import "env" "array_scope_offset_end" (global i32))
  ...
)

```

And then uses the global.get instruction to access these values.

However, I have been unable to find the correct Zig syntax to achieve this.

I have tried this:

```zig
// main.zig
extern const array_scope_offset_start: usize;
extern const array_scope_offset_end: usize;

```

```zig
// build.zig
      
// ...
exe.import_symbols = true;
// ...

```

This did not work. The compilation succeeded, but it produced a faulty Wasm module. Instead of creating global imports, the compiler treated the symbols as being located at memory address 0. The generated WAT for using the global was i32.const 0, i32.load, which is incorrect.

Given the above, what is the correct, idiomatic Zig syntax to declare an external global variable that will be imported from a WebAssembly host module (e.g., “env”)?

Thank you for your help.

---

<div class="post-metadata">

**Author:** ![ScottRedig](https://ziggit.dev/user_avatar/ziggit.dev/scottredig/32/5880_2.png) [@ScottRedig](https://ziggit.dev/u/ScottRedig)\
**Post date:** [August 10, 2025, 9:03am UTC](https://ziggit.dev/t/how-to-correctly-import-a-webassembly-global-from-js-in-zig/11404/2 "2025-08-10T09:03:01Z")

</div>

Afaik, Zig doesn’t give you access to this functionality. Maybe there’s a way but I don’t know it.

If you don’t need this exact API, but you just need global like behavior, you can check out my project zig-javascript-bridge: [GitHub - scottredig/zig-javascript-bridge: Easily call Javascript from Zig wasm](https://github.com/scottredig/zig-javascript-bridge)

The library has an export function, and the tooling with generate the javascript to access it. There’s usage in the example: [zig-javascript-bridge/example/src/main.zig at 9dcf78afc413f1b37f3a82e68bdebdc0aa6dc6b3 · scottredig/zig-javascript-bridge · GitHub](https://github.com/scottredig/zig-javascript-bridge/blob/9dcf78afc413f1b37f3a82e68bdebdc0aa6dc6b3/example/src/main.zig#L185C35-L185C43)  
and the Javascript side:  
[zig-javascript-bridge/example/static/script.js at 9dcf78afc413f1b37f3a82e68bdebdc0aa6dc6b3 · scottredig/zig-javascript-bridge · GitHub](https://github.com/scottredig/zig-javascript-bridge/blob/9dcf78afc413f1b37f3a82e68bdebdc0aa6dc6b3/example/static/script.js#L13)

In case you don’t want to use my library, here’s the issue discussing how it was achieved: [Add support for global variables · Issue #8 · scottredig/zig-javascript-bridge · GitHub](https://github.com/scottredig/zig-javascript-bridge/issues/8)

---

<div class="post-metadata">

**Author:** ![Southporter](https://ziggit.dev/user_avatar/ziggit.dev/southporter/32/2500_2.png) [@Southporter](https://ziggit.dev/u/Southporter)\
**Post date:** [August 11, 2025, 2:14pm UTC](https://ziggit.dev/t/how-to-correctly-import-a-webassembly-global-from-js-in-zig/11404/3 "2025-08-11T14:14:16Z")

</div>

I think you need to use the other form of importing external symbols:

```zig
const array_scope_offset_start = @extern(*i32, .{
    .name = "array_scope_offset_start",
    .library_name = "env",
});

```

This should allow you to use other module names other than ‘env’ if desired.

---

<div class="post-metadata">

**Author:** ![veomn](https://ziggit.dev/letter_avatar_proxy/v4/letter/v/8e7dd6/32.png) [@veomn](https://ziggit.dev/u/veomn)\
**Post date:** [August 11, 2025, 10:16pm UTC](https://ziggit.dev/t/how-to-correctly-import-a-webassembly-global-from-js-in-zig/11404/4 "2025-08-11T22:16:02Z")

</div>

Thanks for the responses.

I tested this form of importing external symbol (`@extern`), it resulted in same compiled WASM as when I used the keyword `extern`. So I guess both are treated the same by the compiler.

I came across this Target Tier System ([https://ziglang.org/download/0.14.0/release-notes.html#Tier-System](https://ziglang.org/download/0.14.0/release-notes.html#Tier-System)) and the target `wasm(32,64)-freestanding` is in additional platforms, so the possibility of importing Globals might not be implemented yet. Or this specific case requires some exact build config that I am unaware of. Either way, for my specific code, it is possible to manually rewrite the few specific instructions in WAT, then compile to WASM, and it works flawlessly.

---

<div class="post-metadata">

**Author:** ![iceghost](https://ziggit.dev/user_avatar/ziggit.dev/iceghost/32/460_2.png) [@iceghost](https://ziggit.dev/u/iceghost)\
**Post date:** [August 16, 2025, 11:46am UTC](https://ziggit.dev/t/how-to-correctly-import-a-webassembly-global-from-js-in-zig/11404/5 "2025-08-16T11:46:19Z")

</div>

you could also just write assembly block in Zig instead of WAT/WASM externally

```zig
comptime {
    asm (
        \\.globl get_array_scope_offset_start
        \\.globaltype array_scope_offset_start, i32
        \\
        \\get_array_scope_offset_start:
        \\.functype get_array_scope_offset_start() -> (i32)
        \\ global.get array_scope_offset_start
        \\ end_function
    );
}

extern fn get_array_scope_offset_start() i32;

export fn foo() i32 {
    return get_array_scope_offset_start();
}

```

```lisp
(module
  (type (;0;) (func (result i32)))
  (import "env" "array_scope_offset_start" (global (;0;) (mut i32)))
  (memory (;0;) 256)
  (global (;1;) (mut i32) i32.const 1677216)
  (export "memory" (memory 0))
  (export "get_array_scope_offset_start" (func 0))
  (export "foo" (func 1))
  (func (;0;) (type 0) (result i32)
    global.get 0)
  (func (;1;) (type 0) (result i32)
    call 0)
)

```

(wasm assembly syntax is left as an exercise for readers (i cannot find a reference for that lol))

---

<div class="post-metadata">

**Author:** ![geemili](https://ziggit.dev/user_avatar/ziggit.dev/geemili/32/1277_2.png) [@geemili](https://ziggit.dev/u/geemili)\
**Post date:** [August 16, 2025, 4:23pm UTC](https://ziggit.dev/t/how-to-correctly-import-a-webassembly-global-from-js-in-zig/11404/6 "2025-08-16T16:23:42Z")

</div>

I think its just the webassembly text format? Didn’t find anything to verify that WAT is what LLVM is using in a quick search.

> **[Understanding WebAssembly text format - WebAssembly | MDN](https://developer.mozilla.org/en-US/docs/WebAssembly/Guides/Understanding_the_text_format)**
>
> To enable WebAssembly to be read and edited by humans, there is a textual representation of the Wasm binary format. This is an intermediate form designed to be exposed in text editors, browser developer tools, etc. This article explains how that text...

---

<div class="post-metadata">

**Author:** ![iceghost](https://ziggit.dev/user_avatar/ziggit.dev/iceghost/32/460_2.png) [@iceghost](https://ziggit.dev/u/iceghost)\
**Post date:** [August 16, 2025, 4:37pm UTC](https://ziggit.dev/t/how-to-correctly-import-a-webassembly-global-from-js-in-zig/11404/7 "2025-08-16T16:37:10Z")

</div>

Of course because they are not the same thing 😃 How can you even mix up one that is asm-like (look at them labels, directives in my code block) and something lisp or s-expr like? (look at them parens in the post you linked)

(Also, just a suggestion, but ya know, you can fact check by just creating an example Zig program and test your hypothesis, before posting anything 😃 Why _think_ and imagine, when in these cases, the compiler is the truth)

(wink wink also to the @extern suggester above)

---

<div class="post-metadata">

**Author:** ![geemili](https://ziggit.dev/user_avatar/ziggit.dev/geemili/32/1277_2.png) [@geemili](https://ziggit.dev/u/geemili)\
**Post date:** [August 17, 2025, 12:45am UTC](https://ziggit.dev/t/how-to-correctly-import-a-webassembly-global-from-js-in-zig/11404/8 "2025-08-17T00:45:27Z")

</div>

Sorry, I wasn’t paying enough attention before I posted.
