@gjsify/rolldown-native 0.52.0 → 0.54.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -71,32 +71,26 @@ the lock — regenerate it in the same commit as the submodule pin and the npm `
71
71
  | `linux-x64` | ✅ `.so` + `.gir` + `.typelib` | native runner |
72
72
  | `linux-arm64` | ✅ | native runner |
73
73
  | `linux-ppc64`, `linux-s390x`, `linux-riscv64` | ❌ | not built — the rolldown crate graph is too slow under QEMU |
74
- | macOS (`darwin-arm64`) | ⏳ source-ready, no prebuild yet | pending a green `prebuilds.yml` macOS leg |
75
- | macOS (`darwin-x64`) | ❌ | — |
74
+ | macOS (`darwin-arm64`) | ✅ `.dylib` + `.gir` + `.typelib` | native runner |
75
+ | macOS (`darwin-x64`) | ✅ | native runner |
76
76
  | Windows | ❌ | — no Vala/GI bridge in this repo targets Windows |
77
77
 
78
78
  All prebuilds are produced by [`.github/workflows/prebuilds.yml`](../../../.github/workflows/prebuilds.yml)
79
79
  and committed back to the repository.
80
80
 
81
- ### macOS status
82
-
83
- The **Rust-level blocker is gone.** The core used to wake the GLib main loop through three
84
- `libc::eventfd(2)` descriptors — a Linux syscall the `libc` crate does not even expose on
85
- Apple targets, so `cargo build` could not compile at all there. The wakeup channel is now a
86
- plain anonymous pipe (`src/rust/src/wakeup.rs`), one portable implementation used on every
87
- platform, so the crate cross-compiles: `cargo check --target aarch64-apple-darwin` is green.
88
- `meson.build` was already macOS-ready (`.dylib` naming, `@loader_path` rpath).
89
-
90
- What is still missing is a **native macOS build**: the `.dylib` + `.gir` + `.typelib` have to
91
- be produced and load-tested by the `prebuilds.yml` darwin leg (Homebrew `vala`, `gobject-
92
- introspection`, `json-glib`, `gjs`) before `darwin-arm64` is added to `package.json`'s
93
- `gjsify.platforms` and a prebuild is committed. Until that leg is green, treat macOS as
94
- unproven — a cross-`check` does not exercise linking, the GIR/typelib step, or `gi://` load.
95
-
96
- Because `@gjsify/rolldown-native` is the only bundler engine available to `gjsify build`
97
- under GJS, it is the last package gating a Node-free gjsify toolchain on macOS —
98
- `@gjsify/lightningcss-native` and `@gjsify/oxfmt-native` already ship `darwin-arm64`
99
- prebuilds.
81
+ ### Runtime system dependency: json-glib
82
+
83
+ The prebuild links **json-glib** (`BundlerSession` peeks at the hook name and request id of each
84
+ Rust-emitted JSON envelope before routing it), and it is a SYSTEM library on every target, like
85
+ GLib itself: `libjson-glib-1.0.so.0` on Linux, `@rpath/libjson-glib-1.0.0.dylib` on macOS, where
86
+ the rpath list ends in the Homebrew prefix ([docs/prebuilds.md](../../../docs/prebuilds.md)). Homebrew's
87
+ `gjs` formula does not pull it in, so a Mac needs `brew install json-glib`; `gjsify system-check`
88
+ lists it with the install command for the host.
89
+
90
+ Without it the typelib still resolves and the library fails to open. GJS reports that at the first
91
+ class access as `Unsupported type void, deriving from fundamental void`, so `gjsify build` probes
92
+ the library before choosing the engine (`probeNativeLibrary()` in `@gjsify/utils/core`) and prints
93
+ the file that failed, the dependency the loader named, and the install command.
100
94
 
101
95
  ### Wakeup channel (implementation note)
102
96
 
@@ -1,2 +1,2 @@
1
1
  import"./_virtual/_rolldown/runtime.js";import{loadNativeRolldown as e}from"./index.js";function getGLib(){let e=globalThis.imports?.gi;if(!e||!e.GLib)throw Error(`@gjsify/rolldown-native: GLib not available (not running under GJS?)`);return e.GLib}const enc=e=>getGLib().Bytes.new(new TextEncoder().encode(e)),dec=e=>new TextDecoder().decode(e.get_data()??new Uint8Array),t=[`load`,`transform`,`resolveId`,`renderChunk`,`banner`,`footer`,`intro`,`outro`,`buildStart`,`buildEnd`,`generateBundle`,`writeBundle`,`closeBundle`];function pluginMeta(e){let n=t.filter(t=>typeof e[t]==`function`),r={name:e.name,hooks:n};return e.idFilter&&(r.idFilter=e.idFilter),r}const n=new Set;function isResolveMiss(e){return e.startsWith(`NotFound(`)}var HookErrorLog=class{entries=[];record(e,t){this.entries.push({...e,message:t})}format(){if(this.entries.length===0)return``;let e=this.entries.slice(0,8),t=e.map(({plugin:e,hook:t,message:n})=>` [plugin ${e}] ${t}: ${n}`),n=this.entries.length-e.length;return n>0&&t.push(` … and ${n} more`),`${this.entries.length===1?`1 plugin hook failed during this build:`:`${this.entries.length} plugin hooks failed during this build:`}\n${t.join(`
2
- `)}`}};function bundleWithPlugins(t,r){let i=e();if(!i)return Promise.reject(Error(`@gjsify/rolldown-native: prebuild not available`));let a=new i.BundlerSession;n.add(a);let o=new HookErrorLog,s=new Map;a.connect(`context_response`,(e,t,n)=>{let r=s.get(t);if(!r)return;s.delete(t);let i;try{i=JSON.parse(dec(n))}catch(e){r.reject(e instanceof Error?e:Error(String(e)));return}i.error&&isResolveMiss(i.error)?r.resolve(null):i.error?r.reject(Error(i.error)):i.id?r.resolve({id:i.id,external:i.external??!1}):r.resolve(null)});function makeContext(e){return{resolve(t,n,r){return new Promise((i,o)=>{let c=a.context_resolve(e,enc(JSON.stringify({specifier:t,importer:n,skipSelf:r?.skipSelf??!0,isEntry:r?.isEntry??!1})));if(c===0){o(Error(`@gjsify/rolldown-native: ctx.resolve('${t}') failed — parent req_id ${e} unknown`));return}s.set(c,{resolve:i,reject:o})})},warn(e){a.context_warn(enc(e))},error(e){throw Error(e)}}}a.connect(`hook_requested`,(e,t,n,r,i)=>{dispatchHook(t,n,r,i)});async function dispatchHook(e,t,n,i){let o={plugin:r[n]?.name??`#${n}`,hook:e},s;try{s=JSON.parse(dec(i))}catch(e){respondError(t,e,o);return}let c=r[n];if(!c){respondError(t,Error(`@gjsify/rolldown-native: unknown plugin index ${n}`),o);return}let l=makeContext(t);try{if(e===`transform`&&c.transform){let e=s,n=a.take_request_payload(t);if(n===null)throw Error(`@gjsify/rolldown-native: transform request for ${e.id} missing payload bytes`);let r=dec(n);respondTransform(t,await c.transform.call(l,r,e.id,e.moduleType),o);return}respondOk(t,await runHook(c,e,s,l))}catch(e){respondError(t,e,o)}}function respondOk(e,t){let n=t==null?{kind:`skip`}:{kind:`ok`,value:t};a.respond(e,enc(JSON.stringify(n)))}function respondTransform(e,t,n){if(t==null){a.respond(e,enc(JSON.stringify({kind:`skip`})));return}let r,i;if(typeof t==`string`)r=t;else if(typeof t==`object`){let e=t;r=e.code,i=e.moduleType}if(typeof r!=`string`){a.respond(e,enc(JSON.stringify({kind:`skip`})));return}let o=getGLib().Bytes.new(new TextEncoder().encode(r));if(!a.set_response_payload(e,o)){respondError(e,Error(`@gjsify/rolldown-native: failed to stash transform response payload for reqId ${e}`),n);return}a.respond(e,enc(JSON.stringify({kind:`ok`,value:i===void 0?{hasCodeBytes:!0}:{hasCodeBytes:!0,moduleType:i}})))}function respondError(e,t,n){let r=t instanceof Error?t:Error(String(t));o.record(n,r.message),a.respond(e,enc(JSON.stringify({kind:`error`,message:r.message,stack:r.stack})))}let closeSession=()=>{n.delete(a);let e=a;try{e.close?.()}catch{}};return new Promise((e,n)=>{a.connect(`completed`,(t,r)=>{try{e(JSON.parse(dec(r)))}catch(e){n(e instanceof Error?e:Error(String(e)))}}),a.connect(`error_occurred`,(e,t)=>{let r=o.format();n(Error(r?`${t}\n${r}`:t))});try{a.start(enc(JSON.stringify({options:t,plugins:r.map(pluginMeta)})))}catch(e){n(e instanceof Error?e:Error(String(e)))}}).finally(closeSession)}async function runHook(e,t,n,r){switch(t){case`load`:return e.load?normalizeLoadResult(await e.load.call(r,n.id)):null;case`transform`:return null;case`resolveId`:{if(!e.resolveId)return null;let t=n;return normalizeResolveIdResult(await e.resolveId.call(r,t.specifier,t.importer,{isEntry:t.isEntry}))}case`renderChunk`:{if(!e.renderChunk)return null;let t=n;return normalizeRenderChunkResult(await e.renderChunk.call(r,t.code,{fileName:t.fileName,name:t.name,isEntry:t.isEntry}))}case`banner`:case`footer`:case`intro`:case`outro`:{let i=e[t];if(!i)return null;let a=n;return normalizeAddonResult(await i.call(r,{fileName:a.fileName,name:a.name,isEntry:a.isEntry}))}case`buildStart`:case`buildEnd`:case`generateBundle`:case`writeBundle`:case`closeBundle`:{let n=e[t];return n&&await n.call(r),null}default:throw Error(`@gjsify/rolldown-native: unknown hook '${t}'`)}}function normalizeLoadResult(e){return e==null?null:typeof e==`string`?{code:e}:{code:e.code,moduleType:e.moduleType}}function normalizeResolveIdResult(e){return e==null?null:typeof e==`string`?{id:e}:{id:e.id,external:e.external}}function normalizeRenderChunkResult(e){return e==null?null:typeof e==`string`?{code:e}:{code:e.code}}function normalizeAddonResult(e){return e==null?null:typeof e==`string`?e:e.text}export{bundleWithPlugins,isResolveMiss};
2
+ `)}`}};function bundleWithPlugins(t,r){let i=e();if(!i)return Promise.reject(Error(`@gjsify/rolldown-native: prebuild not available`));let a=new i.BundlerSession;n.add(a);let o=new HookErrorLog,s=new Set,c=new Map;a.connect(`context_response`,(e,t,n)=>{let r=c.get(t);if(!r)return;c.delete(t);let i;try{i=JSON.parse(dec(n))}catch(e){r.reject(e instanceof Error?e:Error(String(e)));return}i.error&&isResolveMiss(i.error)?r.resolve(null):i.error?r.reject(Error(i.error)):i.id?r.resolve({id:i.id,external:i.external??!1}):r.resolve(null)});function makeContext(e){return{addWatchFile(e){s.add(e)},resolve(t,n,r){return new Promise((i,o)=>{let s=a.context_resolve(e,enc(JSON.stringify({specifier:t,importer:n,skipSelf:r?.skipSelf??!0,isEntry:r?.isEntry??!1})));if(s===0){o(Error(`@gjsify/rolldown-native: ctx.resolve('${t}') failed — parent req_id ${e} unknown`));return}c.set(s,{resolve:i,reject:o})})},warn(e){a.context_warn(enc(e))},error(e){throw Error(e)}}}a.connect(`hook_requested`,(e,t,n,r,i)=>{dispatchHook(t,n,r,i)});async function dispatchHook(e,t,n,i){let o={plugin:r[n]?.name??`#${n}`,hook:e},s;try{s=JSON.parse(dec(i))}catch(e){respondError(t,e,o);return}let c=r[n];if(!c){respondError(t,Error(`@gjsify/rolldown-native: unknown plugin index ${n}`),o);return}let l=makeContext(t);try{if(e===`transform`&&c.transform){let e=s,n=a.take_request_payload(t);if(n===null)throw Error(`@gjsify/rolldown-native: transform request for ${e.id} missing payload bytes`);let r=dec(n);respondTransform(t,await c.transform.call(l,r,e.id,e.moduleType),o);return}respondOk(t,await runHook(c,e,s,l))}catch(e){respondError(t,e,o)}}function respondOk(e,t){let n=t==null?{kind:`skip`}:{kind:`ok`,value:t};a.respond(e,enc(JSON.stringify(n)))}function respondTransform(e,t,n){if(t==null){a.respond(e,enc(JSON.stringify({kind:`skip`})));return}let r,i;if(typeof t==`string`)r=t;else if(typeof t==`object`){let e=t;r=e.code,i=e.moduleType}if(typeof r!=`string`){a.respond(e,enc(JSON.stringify({kind:`skip`})));return}let o=getGLib().Bytes.new(new TextEncoder().encode(r));if(!a.set_response_payload(e,o)){respondError(e,Error(`@gjsify/rolldown-native: failed to stash transform response payload for reqId ${e}`),n);return}a.respond(e,enc(JSON.stringify({kind:`ok`,value:i===void 0?{hasCodeBytes:!0}:{hasCodeBytes:!0,moduleType:i}})))}function respondError(e,t,n){let r=t instanceof Error?t:Error(String(t));o.record(n,r.message),a.respond(e,enc(JSON.stringify({kind:`error`,message:r.message,stack:r.stack})))}let closeSession=()=>{n.delete(a);let e=a;try{e.close?.()}catch{}};return new Promise((e,n)=>{a.connect(`completed`,(t,r)=>{try{e({...JSON.parse(dec(r)),watchedFiles:[...s]})}catch(e){n(e instanceof Error?e:Error(String(e)))}}),a.connect(`error_occurred`,(e,t)=>{let r=o.format();n(Error(r?`${t}\n${r}`:t))});try{a.start(enc(JSON.stringify({options:t,plugins:r.map(pluginMeta)})))}catch(e){n(e instanceof Error?e:Error(String(e)))}}).finally(closeSession)}async function runHook(e,t,n,r){switch(t){case`load`:return e.load?normalizeLoadResult(await e.load.call(r,n.id)):null;case`transform`:return null;case`resolveId`:{if(!e.resolveId)return null;let t=n;return normalizeResolveIdResult(await e.resolveId.call(r,t.specifier,t.importer,{isEntry:t.isEntry}))}case`renderChunk`:{if(!e.renderChunk)return null;let t=n;return normalizeRenderChunkResult(await e.renderChunk.call(r,t.code,{fileName:t.fileName,name:t.name,isEntry:t.isEntry}))}case`banner`:case`footer`:case`intro`:case`outro`:{let i=e[t];if(!i)return null;let a=n;return normalizeAddonResult(await i.call(r,{fileName:a.fileName,name:a.name,isEntry:a.isEntry}))}case`buildStart`:case`buildEnd`:case`generateBundle`:case`writeBundle`:case`closeBundle`:{let n=e[t];return n&&await n.call(r),null}default:throw Error(`@gjsify/rolldown-native: unknown hook '${t}'`)}}function normalizeLoadResult(e){return e==null?null:typeof e==`string`?{code:e}:{code:e.code,moduleType:e.moduleType}}function normalizeResolveIdResult(e){return e==null?null:typeof e==`string`?{id:e}:{id:e.id,external:e.external}}function normalizeRenderChunkResult(e){return e==null?null:typeof e==`string`?{code:e}:{code:e.code}}function normalizeAddonResult(e){return e==null?null:typeof e==`string`?e:e.text}export{bundleWithPlugins,isResolveMiss};
@@ -49,6 +49,12 @@ export type BundleOutputItem = BundleChunk | BundleAsset;
49
49
  export interface BundleResult {
50
50
  warnings: string[];
51
51
  output: BundleOutputItem[];
52
+ /**
53
+ * Files a plugin declared with `this.addWatchFile` — npm rolldown's
54
+ * `RolldownBuild.watchFiles`, collected here because this engine has no
55
+ * watcher to feed. Absent on a `bundle()` result that declares none.
56
+ */
57
+ watchedFiles?: string[];
52
58
  }
53
59
  export { bundleWithPlugins, isResolveMiss, type NativePlugin, type NativePluginContext, type PluginIdFilter, type LoadHookHandler, type TransformHookHandler, type ResolveIdHookHandler, type RenderChunkHookHandler, type AddonHookHandler, type LifecycleHookHandler, } from './plugins.js';
54
60
  /**
@@ -24,6 +24,19 @@ export interface NativePluginContext {
24
24
  id: string;
25
25
  external: boolean;
26
26
  } | null>;
27
+ /**
28
+ * Register a file the output depends on but the bundler never made a module
29
+ * — rolldown's `this.addWatchFile`. Collected into the result's
30
+ * `watchedFiles`.
31
+ *
32
+ * The native engine has no watcher to feed and the Rust side never asked
33
+ * for one, so the list goes nowhere but the caller: `gjsify test` judges its
34
+ * bundle against it. An older published copy of this package is what a host
35
+ * may actually load (the CLI resolves the engine through several anchors),
36
+ * so a plugin must feature-detect this — a build must not fail over
37
+ * bookkeeping, and a miss is reported rather than silent.
38
+ */
39
+ addWatchFile(id: string): void;
27
40
  /** Append a warning to the bundle's warnings list. */
28
41
  warn(message: string): void;
29
42
  /** Throw with `message` — caught at the dispatch boundary and
package/meson.build CHANGED
@@ -1,4 +1,10 @@
1
- project('GjsifyRolldown', ['c', 'vala'], version: '1.0')
1
+ # `buildtype=plain` = NO `-g`. ld64 emits a DEBUG MAP into any image whose objects
2
+ # carry DWARF — one `N_OSO` stab per object, holding its MTIME — so with `-g` every
3
+ # rebuild of this commit differed in bytes (plus the `LC_UUID` and the ad-hoc signature
4
+ # computed over them) and `commit-prebuilds` re-committed all 16 darwin dylibs. That map
5
+ # names intermediate `.o` files no consumer can have. Why: docs/prebuilds.md.
6
+ project('GjsifyRolldown', ['c', 'vala'], version: '1.0',
7
+ default_options: ['buildtype=plain'])
2
8
 
3
9
  # Required system packages (Fedora 43+):
4
10
  # dnf install vala meson ninja-build cargo
@@ -54,22 +60,62 @@ if host_system == 'darwin'
54
60
  lib_rpath = '@loader_path'
55
61
  # Normalise the cdylib's LC_ID_DYLIB to @rpath/<leaf> BEFORE the Vala
56
62
  # library links against it: ld64 copies the dependency's install name
57
- # verbatim into the dependent's LC_LOAD_DYLIB. rustc's own install name has
58
- # varied across releases (absolute build path in older rustc, @rpath/<leaf>
59
- # in current ones); pinning it here makes the recorded dependency
60
- # rustc-version-independent, and @rpath/ is never longer than an absolute
61
- # path so install_name_tool can always rewrite in place.
62
- rust_cdylib_post = ' && install_name_tool -id "@rpath/' + rust_cdylib_name + '" "$3"'
63
+ # verbatim into the dependent's LC_LOAD_DYLIB. Pinning it here makes the
64
+ # recorded dependency rustc-version-independent, and @rpath/ is never
65
+ # longer than an absolute path so install_name_tool can always rewrite in
66
+ # place.
67
+ #
68
+ # The cdylib must be a FUNCTION OF ITS SOURCES, and on darwin that takes
69
+ # TWO steps, only the first of which `install_name_tool` could do.
70
+ # MEASURED with rustc 1.98.1 / ld64-27037.1 (macOS 27, arm64); the whole
71
+ # measurement and the reasoning behind each step: scripts/macho-set-uuid.mjs.
72
+ #
73
+ # 1. THE INSTALL NAME, at the LINK. rustc still gives a cdylib the ABSOLUTE
74
+ # path of its own output as `LC_ID_DYLIB`
75
+ # (`<builddir>/cargo-target/release/deps/<leaf>`), so the build
76
+ # directory's name and LENGTH reach the artifact: the recorded name, the
77
+ # load-command block's size, and therefore every section address after it.
78
+ # Without this, two builds from `build/` and `builddir/` differ by 8 bytes
79
+ # of pure layout before any content is compared. ld64 takes the LAST
80
+ # `-install_name` (verified), and a `-C link-arg` lands after rustc's own,
81
+ # so this one wins. `install_name_tool` then keeps the recorded dependency
82
+ # rustc-version-independent.
83
+ # 2. THE UUID, after every other edit (the script, which re-signs). ld64
84
+ # computed that field over the image it emitted and `install_name_tool`
85
+ # recomputes neither it nor the signature — and it is not a function of
86
+ # the emitted bytes even so, so pinning the name above still leaves 48
87
+ # moving bytes (16 `LC_UUID` + 32 of the signature hashing it). It is
88
+ # derived from the image instead, so if the CODE ever stops being a
89
+ # function of the sources the UUID moves with it and
90
+ # `check-prebuild-reproducible.mjs` still reds; nothing here hides
91
+ # content drift.
92
+ rust_cargo_link_args = ' -- -C link-arg=-Wl,-install_name,@rpath/' + rust_cdylib_name
93
+ rust_cargo_cmd = 'cargo rustc --lib'
94
+ # The repo's OWN script, from the package's own meson.build — so a bridge
95
+ # built outside the workspace has to say so itself rather than silently
96
+ # skipping the step that makes its artifact reproducible.
97
+ set_uuid_tool = meson.current_source_dir() / '..' / '..' / '..' / 'scripts' / 'macho-set-uuid.mjs'
98
+ rust_cdylib_post = ' && install_name_tool -id "@rpath/' + rust_cdylib_name + '" "$3"' \
99
+ + ' && ' + find_program('node').full_path() + ' "' + set_uuid_tool + '" "$3"'
63
100
  else
64
101
  rust_cdylib_name = 'libgjsify_rolldown.so'
65
102
  shared_lib_name = 'libgjsifyrolldown.so'
66
103
  lib_rpath = '$ORIGIN'
104
+ # ELF records a bare SONAME and no UUID load command, and its link line is
105
+ # already a function of the sources: the darwin branch's steps have no ELF
106
+ # spelling, so this one is left exactly as it was.
107
+ rust_cargo_link_args = ''
108
+ rust_cargo_cmd = 'cargo build'
67
109
  rust_cdylib_post = ''
68
110
  endif
69
111
 
70
112
  # ----------------------------------------------------------------------------
71
113
  # Rust cdylib (cargo)
72
114
  # ----------------------------------------------------------------------------
115
+ # `cargo rustc --lib -- <args>` rather than `cargo build`, so the link args reach
116
+ # the FINAL crate's rustc and no other: the dependency rlibs and any build
117
+ # script are linked without them, and a pinned `-install_name` on an executable
118
+ # is not a thing ld64 wants.
73
119
  cargo = find_program('cargo')
74
120
 
75
121
  rust_sources = files(
@@ -94,7 +140,8 @@ rust_cdylib = custom_target('gjsify-rolldown-rust',
94
140
  input: rust_sources,
95
141
  output: rust_cdylib_name,
96
142
  command: ['sh', '-c',
97
- 'cargo build --release ${CI:+--locked} --manifest-path "$1" --target-dir "$2" && cp "$2/release/'
143
+ rust_cargo_cmd + ' --release ${CI:+--locked} --manifest-path "$1" --target-dir "$2"'
144
+ + rust_cargo_link_args + ' && cp "$2/release/'
98
145
  + rust_cdylib_name + '" "$3"' + rust_cdylib_post,
99
146
  'sh',
100
147
  meson.current_source_dir() / 'src/rust/Cargo.toml',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/rolldown-native",
3
- "version": "0.52.0",
3
+ "version": "0.54.0",
4
4
  "description": "Phase D-2 POC: Vala/GObject + Rust cdylib bridge to rolldown for GJS. Wraps `rolldown::Bundler::generate()` (async, tokio) in a per-call current-thread runtime so JS sees a sync `bundle()` call. JSON-encoded BundlerOptions in, JSON-encoded BundleOutput out — the boundary stays small even though rolldown's option surface is enormous. POC scope: no JS plugins (Phase B), no watch/HMR, no incremental builds. Companion to `@gjsify/lightningcss-native`; together they remove the last two Rust-crate runtime blockers from the gjsify build pipeline (Phase D-3 unblock).",
5
5
  "type": "module",
6
6
  "main": "lib/esm/index.js",
@@ -58,7 +58,7 @@
58
58
  "@girs/gobject-2.0": "5.4.0"
59
59
  },
60
60
  "devDependencies": {
61
- "@gjsify/cli": "^0.52.0",
61
+ "@gjsify/cli": "^0.54.0",
62
62
  "@types/node": "^25.9.2",
63
63
  "typescript": "^6.0.3"
64
64
  },
@@ -74,9 +74,9 @@
74
74
  },
75
75
  "homepage": "https://github.com/gjsify/gjsify/tree/main/packages/infra/rolldown-native#readme",
76
76
  "optionalDependencies": {
77
- "@gjsify/rolldown-native-darwin-arm64": "0.52.0",
78
- "@gjsify/rolldown-native-darwin-x64": "0.52.0",
79
- "@gjsify/rolldown-native-linux-arm64": "0.52.0",
80
- "@gjsify/rolldown-native-linux-x64": "0.52.0"
77
+ "@gjsify/rolldown-native-darwin-arm64": "0.54.0",
78
+ "@gjsify/rolldown-native-darwin-x64": "0.54.0",
79
+ "@gjsify/rolldown-native-linux-arm64": "0.54.0",
80
+ "@gjsify/rolldown-native-linux-x64": "0.54.0"
81
81
  }
82
82
  }