@gjsify/rolldown-native 0.4.0 → 0.4.3

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.
@@ -0,0 +1,195 @@
1
+ /*
2
+ * GLib-friendly glue for gjsify_rolldown. See gjsify-rolldown-glue.h.
3
+ */
4
+
5
+ #include "gjsify-rolldown-glue.h"
6
+ #include <stdbool.h>
7
+ #include <string.h>
8
+
9
+ GQuark
10
+ gjsify_rolldown_error_quark (void)
11
+ {
12
+ return g_quark_from_static_string ("gjsify-rolldown-error-quark");
13
+ }
14
+
15
+ GBytes *
16
+ gjsify_rolldown_glue_bundle (GBytes *options_json,
17
+ GError **error)
18
+ {
19
+ if (options_json == NULL)
20
+ {
21
+ g_set_error_literal (error,
22
+ GJSIFY_ROLLDOWN_ERROR,
23
+ GJSIFY_ROLLDOWN_ERROR_FAILED,
24
+ "rolldown: NULL options JSON");
25
+ return NULL;
26
+ }
27
+
28
+ gsize opts_len = 0;
29
+ const char *opts_data = (const char *) g_bytes_get_data (options_json, &opts_len);
30
+
31
+ GjsifyRolldownResult res = gjsify_rolldown_bundle (opts_data, opts_len);
32
+
33
+ if (res.error != NULL)
34
+ {
35
+ g_set_error_literal (error,
36
+ GJSIFY_ROLLDOWN_ERROR,
37
+ GJSIFY_ROLLDOWN_ERROR_FAILED,
38
+ res.error);
39
+ gjsify_rolldown_result_free (res);
40
+ return NULL;
41
+ }
42
+
43
+ /* Copy out into GLib heap so the Rust result can be freed immediately. */
44
+ GBytes *out = (res.output != NULL && res.output_len > 0)
45
+ ? g_bytes_new (res.output, res.output_len)
46
+ : g_bytes_new_static ("", 0);
47
+
48
+ gjsify_rolldown_result_free (res);
49
+ return out;
50
+ }
51
+
52
+ /* ----------------------------------------------------------------- */
53
+ /* Phase B.1+: plugin-callback bridge glue. */
54
+ /* ----------------------------------------------------------------- */
55
+
56
+ BundleSession *
57
+ gjsify_rolldown_glue_session_start (GBytes *args_json,
58
+ GError **error)
59
+ {
60
+ if (args_json == NULL)
61
+ {
62
+ g_set_error_literal (error,
63
+ GJSIFY_ROLLDOWN_ERROR,
64
+ GJSIFY_ROLLDOWN_ERROR_FAILED,
65
+ "rolldown: NULL args JSON");
66
+ return NULL;
67
+ }
68
+ gsize len = 0;
69
+ const char *data = (const char *) g_bytes_get_data (args_json, &len);
70
+ char *err = NULL;
71
+ BundleSession *session = gjsify_rolldown_session_start (data, len, &err);
72
+ if (session == NULL)
73
+ {
74
+ g_set_error_literal (error,
75
+ GJSIFY_ROLLDOWN_ERROR,
76
+ GJSIFY_ROLLDOWN_ERROR_FAILED,
77
+ err != NULL ? err : "rolldown: unknown session-start error");
78
+ if (err != NULL) gjsify_rolldown_session_free_error (err);
79
+ return NULL;
80
+ }
81
+ return session;
82
+ }
83
+
84
+ GBytes *
85
+ gjsify_rolldown_glue_session_next_request (BundleSession *session)
86
+ {
87
+ if (session == NULL) return NULL;
88
+ size_t len = 0;
89
+ char *json = gjsify_rolldown_session_next_request (session, &len);
90
+ if (json == NULL || len == 0) return NULL;
91
+ GBytes *out = g_bytes_new (json, len);
92
+ gjsify_rolldown_session_free_string (json);
93
+ return out;
94
+ }
95
+
96
+ gboolean
97
+ gjsify_rolldown_glue_session_respond (BundleSession *session,
98
+ guint64 req_id,
99
+ GBytes *response_json)
100
+ {
101
+ if (session == NULL || response_json == NULL) return FALSE;
102
+ gsize len = 0;
103
+ const char *data = (const char *) g_bytes_get_data (response_json, &len);
104
+ return gjsify_rolldown_session_respond (session, req_id, data, len);
105
+ }
106
+
107
+ GBytes *
108
+ gjsify_rolldown_glue_session_try_result (BundleSession *session,
109
+ GError **error)
110
+ {
111
+ if (session == NULL) return NULL;
112
+ size_t len = 0;
113
+ bool is_error = false;
114
+ char *json = gjsify_rolldown_session_try_result (session, &len, &is_error);
115
+ if (json == NULL) return NULL; /* still building */
116
+ if (is_error)
117
+ {
118
+ g_set_error_literal (error,
119
+ GJSIFY_ROLLDOWN_ERROR,
120
+ GJSIFY_ROLLDOWN_ERROR_FAILED,
121
+ json);
122
+ gjsify_rolldown_session_free_string (json);
123
+ return NULL;
124
+ }
125
+ GBytes *out = g_bytes_new (json, len);
126
+ gjsify_rolldown_session_free_string (json);
127
+ return out;
128
+ }
129
+
130
+ /* ----------------------------------------------------------------- */
131
+ /* Phase B.3 — nested-protocol glue. */
132
+ /* ----------------------------------------------------------------- */
133
+
134
+ guint64
135
+ gjsify_rolldown_glue_session_context_resolve (BundleSession *session,
136
+ guint64 parent_req_id,
137
+ GBytes *args_json)
138
+ {
139
+ if (session == NULL || args_json == NULL) return 0;
140
+ gsize len = 0;
141
+ const char *data = (const char *) g_bytes_get_data (args_json, &len);
142
+ return gjsify_rolldown_session_context_resolve (session, parent_req_id, data, len);
143
+ }
144
+
145
+ void
146
+ gjsify_rolldown_glue_session_context_warn (BundleSession *session,
147
+ GBytes *message)
148
+ {
149
+ if (session == NULL || message == NULL) return;
150
+ gsize len = 0;
151
+ const char *data = (const char *) g_bytes_get_data (message, &len);
152
+ gjsify_rolldown_session_context_warn (session, data, len);
153
+ }
154
+
155
+ GBytes *
156
+ gjsify_rolldown_glue_session_next_context_response (BundleSession *session)
157
+ {
158
+ if (session == NULL) return NULL;
159
+ size_t len = 0;
160
+ char *json = gjsify_rolldown_session_next_context_response (session, &len);
161
+ if (json == NULL || len == 0) return NULL;
162
+ GBytes *out = g_bytes_new (json, len);
163
+ gjsify_rolldown_session_free_string (json);
164
+ return out;
165
+ }
166
+
167
+ /* ----------------------------------------------------------------- */
168
+ /* Phase B.4 — bytes-payload side-channel glue. */
169
+ /* ----------------------------------------------------------------- */
170
+
171
+ GBytes *
172
+ gjsify_rolldown_glue_session_take_request_payload (BundleSession *session,
173
+ guint64 req_id)
174
+ {
175
+ if (session == NULL) return NULL;
176
+ size_t len = 0;
177
+ uint8_t *buf = gjsify_rolldown_session_take_request_payload (session, req_id, &len);
178
+ if (buf == NULL || len == 0) return NULL;
179
+ /* Copy into GLib heap and free the Rust allocation immediately so
180
+ * GBytes refcount/lifetime stays inside the GLib side. */
181
+ GBytes *out = g_bytes_new (buf, len);
182
+ gjsify_rolldown_session_free_payload (buf, len);
183
+ return out;
184
+ }
185
+
186
+ gboolean
187
+ gjsify_rolldown_glue_session_set_response_payload (BundleSession *session,
188
+ guint64 req_id,
189
+ GBytes *bytes)
190
+ {
191
+ if (session == NULL || bytes == NULL) return FALSE;
192
+ gsize len = 0;
193
+ const uint8_t *data = (const uint8_t *) g_bytes_get_data (bytes, &len);
194
+ return gjsify_rolldown_session_set_response_payload (session, req_id, data, len);
195
+ }
@@ -0,0 +1,100 @@
1
+ /*
2
+ * GLib-friendly wrapper around the Rust rolldown shim. Same pattern
3
+ * as @gjsify/lightningcss-native: copy the Rust-allocated buffer into
4
+ * GBytes (refcount-friendly for SpiderMonkey GC) and free the Rust
5
+ * result immediately. Errors become GError on the GJSIFY_ROLLDOWN quark.
6
+ */
7
+
8
+ #ifndef GJSIFY_ROLLDOWN_GLUE_H
9
+ #define GJSIFY_ROLLDOWN_GLUE_H
10
+
11
+ #include <glib.h>
12
+ #include "gjsify-rolldown.h"
13
+
14
+ G_BEGIN_DECLS
15
+
16
+ #define GJSIFY_ROLLDOWN_ERROR (gjsify_rolldown_error_quark ())
17
+
18
+ typedef enum {
19
+ GJSIFY_ROLLDOWN_ERROR_FAILED = 0,
20
+ } GjsifyRolldownError;
21
+
22
+ GQuark gjsify_rolldown_error_quark (void);
23
+
24
+ /**
25
+ * gjsify_rolldown_glue_bundle:
26
+ * @options_json: (transfer none): UTF-8 JSON document matching
27
+ * rolldown's BundlerOptions serde shape (camelCase).
28
+ * @error: (out)(optional): GError on failure
29
+ *
30
+ * Returns: (transfer full): output JSON as GBytes, or NULL on error.
31
+ */
32
+ GBytes *gjsify_rolldown_glue_bundle (GBytes *options_json,
33
+ GError **error);
34
+
35
+ /* ----------------------------------------------------------------- */
36
+ /* Phase B.1+: plugin-callback bridge. */
37
+ /* ----------------------------------------------------------------- */
38
+
39
+ /* Start a session. @args_json shape: `{"options": ..., "plugins": [...]}`.
40
+ * Returns NULL on error (sets *error). Session must be freed via
41
+ * gjsify_rolldown_session_free (the Rust extern, not a glue wrapper). */
42
+ BundleSession *gjsify_rolldown_glue_session_start (GBytes *args_json,
43
+ GError **error);
44
+
45
+ /* Drain one pending hook request as GBytes. Returns NULL when the
46
+ * channel is empty (NOT an error — just means caller should wait
47
+ * for the next request_fd wake). */
48
+ GBytes *gjsify_rolldown_glue_session_next_request (BundleSession *session);
49
+
50
+ /* Forward the JS-side response. */
51
+ gboolean gjsify_rolldown_glue_session_respond (BundleSession *session,
52
+ guint64 req_id,
53
+ GBytes *response_json);
54
+
55
+ /* Read the bundle result. Returns NULL while still in flight. On
56
+ * completion: GBytes with BundleOutputJson on success, or NULL +
57
+ * GError set on build failure. */
58
+ GBytes *gjsify_rolldown_glue_session_try_result (BundleSession *session,
59
+ GError **error);
60
+
61
+ /* ----------------------------------------------------------------- */
62
+ /* Phase B.3 — nested-protocol glue. */
63
+ /* ----------------------------------------------------------------- */
64
+
65
+ /* Trigger ctx.resolve() for the JS plugin currently handling
66
+ * @parent_req_id. Returns the child request ID immediately; the
67
+ * sub-result lands on the context-response queue. Returns 0 on
68
+ * error (parent unknown / args malformed). */
69
+ guint64 gjsify_rolldown_glue_session_context_resolve (BundleSession *session,
70
+ guint64 parent_req_id,
71
+ GBytes *args_json);
72
+
73
+ /* Append a string to the build's warnings list. */
74
+ void gjsify_rolldown_glue_session_context_warn (BundleSession *session,
75
+ GBytes *message);
76
+
77
+ /* Drain one queued context-resolve sub-result. Returns NULL when
78
+ * the queue is empty. */
79
+ GBytes *gjsify_rolldown_glue_session_next_context_response (BundleSession *session);
80
+
81
+ /* ----------------------------------------------------------------- */
82
+ /* Phase B.4 — bytes-payload side-channel. */
83
+ /* ----------------------------------------------------------------- */
84
+
85
+ /* Take the request-payload bytes Rust stashed for @req_id. Returns
86
+ * NULL when empty. The returned GBytes is independent of Rust's
87
+ * allocation (data was copied into a GLib heap buffer + the Rust
88
+ * payload freed in-place). */
89
+ GBytes *gjsify_rolldown_glue_session_take_request_payload (BundleSession *session,
90
+ guint64 req_id);
91
+
92
+ /* Stash bytes Rust should read after the JS handler responds — the
93
+ * transform hook's output code. */
94
+ gboolean gjsify_rolldown_glue_session_set_response_payload (BundleSession *session,
95
+ guint64 req_id,
96
+ GBytes *bytes);
97
+
98
+ G_END_DECLS
99
+
100
+ #endif /* GJSIFY_ROLLDOWN_GLUE_H */
@@ -0,0 +1,136 @@
1
+ /*
2
+ * Hand-written C header matching the Rust extern "C" surface of
3
+ * the gjsify_rolldown cdylib (src/rust/src/lib.rs).
4
+ */
5
+
6
+ #ifndef GJSIFY_ROLLDOWN_H
7
+ #define GJSIFY_ROLLDOWN_H
8
+
9
+ #include <stdbool.h>
10
+ #include <stddef.h>
11
+ #include <stdint.h>
12
+
13
+ #ifdef __cplusplus
14
+ extern "C" {
15
+ #endif
16
+
17
+ typedef struct {
18
+ char *output; /* NUL-terminated UTF-8 JSON, NULL on error */
19
+ size_t output_len;
20
+ char *error; /* NUL-terminated UTF-8 message, NULL on success */
21
+ } GjsifyRolldownResult;
22
+
23
+ GjsifyRolldownResult gjsify_rolldown_bundle (const char *options_json,
24
+ size_t options_json_len);
25
+
26
+ void gjsify_rolldown_result_free (GjsifyRolldownResult result);
27
+
28
+ /* ----------------------------------------------------------------- */
29
+ /* Phase B.1+: plugin-callback bridge. */
30
+ /* ----------------------------------------------------------------- */
31
+
32
+ typedef struct _BundleSession BundleSession;
33
+
34
+ /* Start a new bundle session. JSON payload shape is
35
+ * `{"options": <BundlerOptions>, "plugins": [{"name": "...", "hooks": [...]}]}`.
36
+ *
37
+ * Returns NULL on error and sets *err_out to a heap-allocated
38
+ * NUL-terminated message (caller frees via
39
+ * gjsify_rolldown_session_free_error). Otherwise returns an opaque
40
+ * BundleSession handle owned by the caller — must be freed via
41
+ * gjsify_rolldown_session_free when done. */
42
+ BundleSession *gjsify_rolldown_session_start (const char *args_json,
43
+ size_t args_json_len,
44
+ char **err_out);
45
+
46
+ /* Eventfd that the GLib main loop should watch with G_IO_IN. Wakes
47
+ * whenever a hook request is queued. Caller MUST NOT close it. */
48
+ int gjsify_rolldown_session_request_fd (BundleSession *session);
49
+
50
+ /* Eventfd that wakes when the bundle task is fully done. */
51
+ int gjsify_rolldown_session_complete_fd (BundleSession *session);
52
+
53
+ /* Drain one request as JSON. Returns NULL when the channel is empty
54
+ * (out_len set to 0). Caller frees via
55
+ * gjsify_rolldown_session_free_string. */
56
+ char *gjsify_rolldown_session_next_request (BundleSession *session,
57
+ size_t *out_len);
58
+
59
+ /* Submit the JS-side response for a previously-pulled request. */
60
+ bool gjsify_rolldown_session_respond (BundleSession *session,
61
+ uint64_t req_id,
62
+ const char *response_json,
63
+ size_t response_json_len);
64
+
65
+ /* Returns NULL while the build is still running. On completion: a
66
+ * JSON document (BundleOutputJson on success or {"error": "..."} on
67
+ * failure; *is_error tells which). Caller frees via
68
+ * gjsify_rolldown_session_free_string. */
69
+ char *gjsify_rolldown_session_try_result (BundleSession *session,
70
+ size_t *out_len,
71
+ bool *is_error);
72
+
73
+ void gjsify_rolldown_session_cancel (BundleSession *session);
74
+ void gjsify_rolldown_session_free (BundleSession *session);
75
+ void gjsify_rolldown_session_free_string (char *s);
76
+ void gjsify_rolldown_session_free_error (char *s);
77
+
78
+ /* ----------------------------------------------------------------- */
79
+ /* Phase B.3 — nested protocol for plugin-context callbacks. */
80
+ /* ----------------------------------------------------------------- */
81
+
82
+ /* Trigger a `ctx.resolve()` callback on behalf of the JS plugin
83
+ * handler currently running for `parent_req_id`. Returns a child
84
+ * request ID immediately; the actual sub-result lands on the
85
+ * context-response channel (drained via
86
+ * gjsify_rolldown_session_next_context_response). Returns 0 on
87
+ * error (parent_req_id unknown / args malformed). */
88
+ uint64_t gjsify_rolldown_session_context_resolve (BundleSession *session,
89
+ uint64_t parent_req_id,
90
+ const char *args_json,
91
+ size_t args_json_len);
92
+
93
+ /* Append a string to the build's warnings list. Surfaces in
94
+ * BundleOutputJson.warnings. */
95
+ void gjsify_rolldown_session_context_warn (BundleSession *session,
96
+ const char *message,
97
+ size_t message_len);
98
+
99
+ /* Eventfd that the GLib main loop should watch with G_IO_IN. Wakes
100
+ * whenever a context-resolve sub-result is queued. Caller MUST NOT
101
+ * close it. */
102
+ int gjsify_rolldown_session_context_response_fd (BundleSession *session);
103
+
104
+ /* Drain one context-resolve sub-result as JSON
105
+ * `{childId, id?, external?, error?}`. Returns NULL when empty. */
106
+ char *gjsify_rolldown_session_next_context_response (BundleSession *session,
107
+ size_t *out_len);
108
+
109
+ /* ----------------------------------------------------------------- */
110
+ /* Phase B.4 — bytes-payload side-channel for transform's source code. */
111
+ /* ----------------------------------------------------------------- */
112
+
113
+ /* Drain the request-payload bytes the Rust side stashed for @req_id
114
+ * (transform's source code). Returns NULL when empty / already
115
+ * consumed. Caller frees the returned buffer via
116
+ * gjsify_rolldown_session_free_payload(buf, len). */
117
+ uint8_t *gjsify_rolldown_session_take_request_payload (BundleSession *session,
118
+ uint64_t req_id,
119
+ size_t *out_len);
120
+
121
+ /* Stash bytes the JS handler wants Rust to read after respond() — the
122
+ * transform hook's output code. Returns true on success. */
123
+ bool gjsify_rolldown_session_set_response_payload (BundleSession *session,
124
+ uint64_t req_id,
125
+ const uint8_t *bytes,
126
+ size_t bytes_len);
127
+
128
+ /* Free a buffer returned by take_request_payload. */
129
+ void gjsify_rolldown_session_free_payload (uint8_t *buf,
130
+ size_t len);
131
+
132
+ #ifdef __cplusplus
133
+ }
134
+ #endif
135
+
136
+ #endif /* GJSIFY_ROLLDOWN_H */