bare-x-to-pdf 0.3.0 → 0.5.1
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/CMakeLists.txt +22 -2
- package/README.md +74 -6
- package/binding.c +249 -41
- package/cmake/rust.cmake +12 -2
- package/core/src/doc/mod.rs +29 -16
- package/core/src/docx/mod.rs +3 -5
- package/core/src/docx/numbering.rs +8 -4
- package/core/src/lib.rs +13 -9
- package/core/src/limits.rs +42 -0
- package/core/src/markdown/mod.rs +6 -0
- package/core/src/odt/geometry.rs +21 -0
- package/core/src/odt/mod.rs +13 -9
- package/core/src/odt/odp.rs +3 -5
- package/core/src/odt/styles.rs +2 -2
- package/core/src/pptx/mod.rs +23 -8
- package/core/src/pptx/text.rs +2 -2
- package/core/src/typst_backend/emit.rs +42 -19
- package/core/src/typst_backend/fonts.rs +1 -1
- package/core/src/typst_backend/images.rs +76 -0
- package/core/src/typst_backend/mod.rs +48 -6
- package/core/src/xlsx/biff.rs +15 -4
- package/core/src/xlsx/biff_art.rs +8 -2
- package/core/src/xlsx/biff_chart.rs +10 -1
- package/core/src/xlsx/formula.rs +30 -3
- package/core/src/xlsx/mod.rs +90 -24
- package/core/src/xlsx/ods.rs +15 -12
- package/core/src/xml.rs +6 -1
- package/index.d.ts +3 -1
- package/index.js +135 -40
- package/package.json +32 -18
- package/prebuilds/wasi-wasm32/bare-x-to-pdf.wasm +0 -0
- package/types.d.ts +1 -0
- package/types.js +19 -0
- package/wasi.js +1 -0
package/CMakeLists.txt
CHANGED
|
@@ -9,7 +9,11 @@ include(cmake/rust.cmake)
|
|
|
9
9
|
|
|
10
10
|
bare_target(target)
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
if(target STREQUAL "wasi-wasm32")
|
|
13
|
+
add_bare_module(simple_converter)
|
|
14
|
+
else()
|
|
15
|
+
add_bare_module(simple_converter NAME bare-x-to-pdf-${target})
|
|
16
|
+
endif()
|
|
13
17
|
|
|
14
18
|
target_sources(
|
|
15
19
|
${simple_converter}
|
|
@@ -29,10 +33,26 @@ target_link_libraries(
|
|
|
29
33
|
simple_converter_core
|
|
30
34
|
)
|
|
31
35
|
|
|
36
|
+
# Bound the linear memory a hostile document can claim, so it traps instead of
|
|
37
|
+
# growing to the 4 GiB limit of wasm32, and give the recursive readers and
|
|
38
|
+
# Typst the 8 MiB stack they get on native threads rather than the 64 KiB
|
|
39
|
+
# default of wasm-ld. The default cap leaves room for the 256 MB images and
|
|
40
|
+
# 128 MB parts that core/src/limits.rs lets through.
|
|
41
|
+
set(SIMPLE_CONVERTER_WASM_MAX_MEMORY 1073741824 CACHE STRING "Linear memory limit of the WebAssembly addon in bytes, a multiple of 65536")
|
|
42
|
+
|
|
43
|
+
if(target MATCHES "^wasi-")
|
|
44
|
+
target_link_options(
|
|
45
|
+
${simple_converter}_module
|
|
46
|
+
PRIVATE
|
|
47
|
+
-Wl,--max-memory=${SIMPLE_CONVERTER_WASM_MAX_MEMORY}
|
|
48
|
+
-Wl,-z,stack-size=8388608
|
|
49
|
+
)
|
|
50
|
+
endif()
|
|
51
|
+
|
|
32
52
|
if(CMAKE_STRIP AND NOT WIN32)
|
|
33
53
|
add_custom_command(
|
|
34
54
|
TARGET ${simple_converter}_module
|
|
35
55
|
POST_BUILD
|
|
36
|
-
COMMAND ${CMAKE_STRIP} $<IF:$<PLATFORM_ID:Darwin,iOS>,-x,--strip-unneeded
|
|
56
|
+
COMMAND ${CMAKE_STRIP} $<IF:$<PLATFORM_ID:Darwin,iOS>,-x,$<IF:$<PLATFORM_ID:WASI>,--strip-all,--strip-unneeded>> $<TARGET_FILE:${simple_converter}_module>
|
|
37
57
|
)
|
|
38
58
|
endif()
|
package/README.md
CHANGED
|
@@ -42,22 +42,58 @@ npm install --os=android --cpu=arm64
|
|
|
42
42
|
npm install --os=ios --cpu=arm64
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
+
### WebAssembly
|
|
46
|
+
|
|
47
|
+
On Bare 1.36 and later the converter can also run as a WebAssembly addon, sandboxed through
|
|
48
|
+
WASI. The `.wasm` prebuild ships in the main package, so there is nothing extra to install.
|
|
49
|
+
Import with the `wasi-wasm32` host and a WASI provider. The attributes must be written
|
|
50
|
+
inline in the `require` call. The addon needs a random source and read access to the fonts:
|
|
51
|
+
|
|
52
|
+
```js
|
|
53
|
+
const converter = require('bare-x-to-pdf', {
|
|
54
|
+
with: { host: 'wasi-wasm32', wasi: './wasi.js' }
|
|
55
|
+
})
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
// wasi.js
|
|
60
|
+
const crypto = require('bare-crypto')
|
|
61
|
+
const { DirectorySync } = require('bare-directory')
|
|
62
|
+
const { HostDirectory } = require('bare-wasi/host')
|
|
63
|
+
|
|
64
|
+
const fonts = require.resolve('bare-x-to-pdf/package').replace(/package\.json$/, 'fonts')
|
|
65
|
+
|
|
66
|
+
module.exports = (url) => ({
|
|
67
|
+
version: 'preview1',
|
|
68
|
+
random: (b) => crypto.randomFillSync(b),
|
|
69
|
+
preopens: { [fonts]: new HostDirectory(DirectorySync.open(fonts)) }
|
|
70
|
+
})
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The WebAssembly addon has only `convertSync`. `convert()` falls back to it, so it blocks the
|
|
74
|
+
calling thread; run conversions in a [`bare-thread`](https://github.com/holepunchto/bare-thread).
|
|
75
|
+
A hostile document can crash the addon with a `RuntimeError` without taking down the process,
|
|
76
|
+
but the addon stays unusable in that thread afterwards, so replace the thread.
|
|
77
|
+
|
|
45
78
|
## Usage
|
|
46
79
|
|
|
47
80
|
```js
|
|
48
81
|
const converter = require('bare-x-to-pdf')
|
|
49
82
|
|
|
50
|
-
const pdf = converter.convert(docxBytes, { to: 'pdf' })
|
|
83
|
+
const pdf = await converter.convert(docxBytes, { to: 'pdf' })
|
|
51
84
|
```
|
|
52
85
|
|
|
53
|
-
Input is a `Uint8Array` or `ArrayBuffer` and the result is a `Buffer`.
|
|
54
|
-
|
|
86
|
+
Input is a `Uint8Array` or `ArrayBuffer` and the result is a `Buffer`. `convert()` runs on
|
|
87
|
+
the libuv thread pool and does not block the JavaScript thread; `convertSync()` runs on the
|
|
88
|
+
calling thread.
|
|
55
89
|
|
|
56
90
|
## API
|
|
57
91
|
|
|
58
|
-
### `convert(input, options)`
|
|
92
|
+
### `const pdf = await convert(input, options)`
|
|
59
93
|
|
|
60
|
-
Convert `input` and
|
|
94
|
+
Convert `input` off the JavaScript thread and resolve with a `Buffer`. The input is copied,
|
|
95
|
+
so it may be changed or transferred once the call returns. Invalid options and conversion
|
|
96
|
+
errors reject the promise.
|
|
61
97
|
|
|
62
98
|
- `options.to` — target format, `'pdf'`. Required.
|
|
63
99
|
- `options.from` — source format; sniffed from the bytes when omitted. Markdown has no
|
|
@@ -65,6 +101,11 @@ Convert `input` and return a `Buffer`.
|
|
|
65
101
|
URIs, since the input is bytes with no directory to resolve relative paths against.
|
|
66
102
|
- `options.fontsDir` — a directory of fonts to use instead of the bundled set.
|
|
67
103
|
|
|
104
|
+
### `const pdf = convertSync(input, options)`
|
|
105
|
+
|
|
106
|
+
Convert `input` on the calling thread and return a `Buffer`. Takes the same options as
|
|
107
|
+
`convert()`.
|
|
108
|
+
|
|
68
109
|
### `detect(input)`
|
|
69
110
|
|
|
70
111
|
Sniff the format from the bytes and return `'docx'`, `'pptx'`, `'xlsx'`, `'doc'`, `'xls'`,
|
|
@@ -82,7 +123,34 @@ Return every supported pair as `{ from, to }`.
|
|
|
82
123
|
|
|
83
124
|
### `FONTS_DIR`
|
|
84
125
|
|
|
85
|
-
Path to the bundled fonts directory.
|
|
126
|
+
Path to the bundled fonts directory, resolved with `require.asset`.
|
|
127
|
+
|
|
128
|
+
## Limits
|
|
129
|
+
|
|
130
|
+
Documents are often untrusted, so the engine caps what a small file can make it allocate or
|
|
131
|
+
lay out. A document past a hard limit is rejected with an error. One past a soft limit still
|
|
132
|
+
converts, with the value clamped.
|
|
133
|
+
|
|
134
|
+
Rejected:
|
|
135
|
+
|
|
136
|
+
- An archive part larger than 128 MB uncompressed.
|
|
137
|
+
- XML nested more than 512 elements deep.
|
|
138
|
+
- A spreadsheet that would print more than 30,000 cells.
|
|
139
|
+
|
|
140
|
+
Clamped:
|
|
141
|
+
|
|
142
|
+
- Table spans: 1–1,000 columns.
|
|
143
|
+
- Text columns: 1–64.
|
|
144
|
+
- Pages: 72–14,400 pt on each side, with margins scaled to fit.
|
|
145
|
+
- Lengths: NaN and infinity become 0; any other length is held within ±1,000,000 pt.
|
|
146
|
+
- List counters: above 32,767, letter and Roman labels fall back to decimal.
|
|
147
|
+
- Charts: up to 100,000 points per series (in .xls, 32,000 per series and 256,000 per chart).
|
|
148
|
+
- Formulas: nesting depth up to 256.
|
|
149
|
+
- Images: more than 50 megapixels, or ones that cannot be decoded, are drawn as blank
|
|
150
|
+
space.
|
|
151
|
+
- Tables nested more than 12 deep: the inner tables are flattened into paragraphs.
|
|
152
|
+
|
|
153
|
+
Spreadsheet pages with no content are not printed, as in LibreOffice Calc.
|
|
86
154
|
|
|
87
155
|
## Development
|
|
88
156
|
|
package/binding.c
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#include <assert.h>
|
|
2
|
-
#include <bare.h>
|
|
2
|
+
#include <bare/module.h>
|
|
3
3
|
#include <js.h>
|
|
4
4
|
#include <stdbool.h>
|
|
5
5
|
#include <stdint.h>
|
|
@@ -7,12 +7,46 @@
|
|
|
7
7
|
#include <string.h>
|
|
8
8
|
#include <utf.h>
|
|
9
9
|
|
|
10
|
+
#ifndef __wasm__
|
|
11
|
+
#include <uv.h>
|
|
12
|
+
#endif
|
|
13
|
+
|
|
10
14
|
#include "simple_converter.h"
|
|
11
15
|
|
|
16
|
+
typedef struct {
|
|
17
|
+
const uint8_t *input;
|
|
18
|
+
size_t input_len;
|
|
19
|
+
uint8_t *owned_input;
|
|
20
|
+
char *from;
|
|
21
|
+
char *to;
|
|
22
|
+
char *fonts_dir;
|
|
23
|
+
sc_buffer_t out;
|
|
24
|
+
sc_buffer_t error;
|
|
25
|
+
int status;
|
|
26
|
+
} simple_converter_job_t;
|
|
27
|
+
|
|
28
|
+
// WebAssembly addons are single threaded and have no event loop, so they
|
|
29
|
+
// export only convertSync() and leave running it off the JavaScript thread to
|
|
30
|
+
// the embedder.
|
|
31
|
+
#ifndef __wasm__
|
|
32
|
+
typedef struct {
|
|
33
|
+
uv_work_t work;
|
|
34
|
+
js_env_t *env;
|
|
35
|
+
js_deferred_t *deferred;
|
|
36
|
+
js_deferred_teardown_t *teardown;
|
|
37
|
+
bool exiting;
|
|
38
|
+
simple_converter_job_t job;
|
|
39
|
+
} simple_converter_req_t;
|
|
40
|
+
#endif
|
|
41
|
+
|
|
12
42
|
static bool
|
|
13
43
|
simple_converter__string(js_env_t *env, js_value_t *value, char **result) {
|
|
14
44
|
int err;
|
|
15
45
|
|
|
46
|
+
bool is_string;
|
|
47
|
+
err = js_is_string(env, value, &is_string);
|
|
48
|
+
if (err != 0 || !is_string) return false;
|
|
49
|
+
|
|
16
50
|
size_t len = 0;
|
|
17
51
|
err = js_get_value_string_utf8(env, value, NULL, 0, &len);
|
|
18
52
|
if (err != 0) return false;
|
|
@@ -27,14 +61,32 @@ simple_converter__string(js_env_t *env, js_value_t *value, char **result) {
|
|
|
27
61
|
}
|
|
28
62
|
|
|
29
63
|
str[len] = '\0';
|
|
64
|
+
|
|
65
|
+
if (strlen(str) != len) {
|
|
66
|
+
free(str);
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
|
|
30
70
|
*result = str;
|
|
31
71
|
return true;
|
|
32
72
|
}
|
|
33
73
|
|
|
34
|
-
static
|
|
35
|
-
|
|
74
|
+
static void
|
|
75
|
+
simple_converter__job_release(simple_converter_job_t *job) {
|
|
76
|
+
free(job->owned_input);
|
|
77
|
+
free(job->from);
|
|
78
|
+
free(job->to);
|
|
79
|
+
free(job->fonts_dir);
|
|
80
|
+
sc_free(&job->out);
|
|
81
|
+
sc_free(&job->error);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
static bool
|
|
85
|
+
simple_converter__job_init(js_env_t *env, js_callback_info_t *info, bool copy_input, simple_converter_job_t *job) {
|
|
36
86
|
int err;
|
|
37
87
|
|
|
88
|
+
memset(job, 0, sizeof(*job));
|
|
89
|
+
|
|
38
90
|
size_t argc = 4;
|
|
39
91
|
js_value_t *argv[4];
|
|
40
92
|
|
|
@@ -44,68 +96,221 @@ simple_converter_convert(js_env_t *env, js_callback_info_t *info) {
|
|
|
44
96
|
if (argc < 4) {
|
|
45
97
|
err = js_throw_error(env, NULL, "convert expects (bytes, from, to, fontsDir)");
|
|
46
98
|
assert(err == 0);
|
|
47
|
-
return
|
|
99
|
+
return false;
|
|
48
100
|
}
|
|
49
101
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
err
|
|
53
|
-
|
|
102
|
+
bool is_typedarray;
|
|
103
|
+
err = js_is_typedarray(env, argv[0], &is_typedarray);
|
|
104
|
+
assert(err == 0);
|
|
105
|
+
|
|
106
|
+
js_typedarray_type_t type = js_int8array;
|
|
107
|
+
uint8_t *input = NULL;
|
|
108
|
+
size_t input_len = 0;
|
|
109
|
+
if (is_typedarray) {
|
|
110
|
+
err = js_get_typedarray_info(env, argv[0], &type, (void **) &input, &input_len, NULL, NULL);
|
|
111
|
+
}
|
|
112
|
+
if (!is_typedarray || err != 0 || type != js_uint8array) {
|
|
54
113
|
err = js_throw_error(env, NULL, "input must be a Uint8Array");
|
|
55
114
|
assert(err == 0);
|
|
56
|
-
return
|
|
115
|
+
return false;
|
|
57
116
|
}
|
|
58
117
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
bool ok = simple_converter__string(env, argv[1], &from) &&
|
|
64
|
-
simple_converter__string(env, argv[2], &to) &&
|
|
65
|
-
simple_converter__string(env, argv[3], &fonts_dir);
|
|
118
|
+
bool ok = simple_converter__string(env, argv[1], &job->from) &&
|
|
119
|
+
simple_converter__string(env, argv[2], &job->to) &&
|
|
120
|
+
simple_converter__string(env, argv[3], &job->fonts_dir);
|
|
66
121
|
|
|
67
122
|
if (!ok) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
free(fonts_dir);
|
|
71
|
-
err = js_throw_error(env, NULL, "from, to and fontsDir must be strings");
|
|
123
|
+
simple_converter__job_release(job);
|
|
124
|
+
err = js_throw_error(env, NULL, "from, to and fontsDir must be strings without NUL characters");
|
|
72
125
|
assert(err == 0);
|
|
73
|
-
return
|
|
126
|
+
return false;
|
|
74
127
|
}
|
|
75
128
|
|
|
76
|
-
|
|
77
|
-
|
|
129
|
+
job->input = input;
|
|
130
|
+
job->input_len = input_len;
|
|
78
131
|
|
|
79
|
-
|
|
132
|
+
if (copy_input && input_len > 0) {
|
|
133
|
+
job->owned_input = malloc(input_len);
|
|
134
|
+
if (job->owned_input == NULL) {
|
|
135
|
+
simple_converter__job_release(job);
|
|
136
|
+
err = js_throw_error(env, NULL, "out of memory");
|
|
137
|
+
assert(err == 0);
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
memcpy(job->owned_input, input, input_len);
|
|
141
|
+
job->input = job->owned_input;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
static void
|
|
148
|
+
simple_converter__run(simple_converter_job_t *job) {
|
|
149
|
+
job->status = sc_convert(job->input, job->input_len, job->from, job->to, job->fonts_dir, &job->out, &job->error);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
static void
|
|
153
|
+
simple_converter__finalize_output(js_env_t *env, void *data, void *finalize_hint) {
|
|
154
|
+
sc_buffer_t *buffer = finalize_hint;
|
|
155
|
+
sc_free(buffer);
|
|
156
|
+
free(buffer);
|
|
157
|
+
}
|
|
80
158
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
159
|
+
static js_value_t *
|
|
160
|
+
simple_converter__output(js_env_t *env, simple_converter_job_t *job) {
|
|
161
|
+
int err;
|
|
84
162
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
163
|
+
js_value_t *result;
|
|
164
|
+
|
|
165
|
+
sc_buffer_t *owned = job->out.len > 0 ? malloc(sizeof(sc_buffer_t)) : NULL;
|
|
166
|
+
|
|
167
|
+
if (owned != NULL) {
|
|
168
|
+
*owned = job->out;
|
|
169
|
+
err = js_create_external_arraybuffer(env, owned->data, owned->len, simple_converter__finalize_output, owned, &result);
|
|
170
|
+
if (err == 0) {
|
|
171
|
+
job->out.data = NULL;
|
|
172
|
+
job->out.len = 0;
|
|
173
|
+
return result;
|
|
90
174
|
}
|
|
91
|
-
|
|
92
|
-
err = js_throw_error(env, NULL, message ? message : "conversion failed");
|
|
93
|
-
assert(err == 0);
|
|
94
|
-
free(message);
|
|
95
|
-
return NULL;
|
|
175
|
+
free(owned);
|
|
96
176
|
}
|
|
97
177
|
|
|
98
|
-
js_value_t *result;
|
|
99
178
|
void *data;
|
|
100
|
-
err = js_create_arraybuffer(env, out.len, &data, &result);
|
|
179
|
+
err = js_create_arraybuffer(env, job->out.len, &data, &result);
|
|
101
180
|
assert(err == 0);
|
|
102
181
|
|
|
103
|
-
if (out.len > 0) memcpy(data, out.data, out.len);
|
|
104
|
-
sc_free(&out);
|
|
182
|
+
if (job->out.len > 0) memcpy(data, job->out.data, job->out.len);
|
|
105
183
|
|
|
106
184
|
return result;
|
|
107
185
|
}
|
|
108
186
|
|
|
187
|
+
static js_value_t *
|
|
188
|
+
simple_converter__error(js_env_t *env, simple_converter_job_t *job) {
|
|
189
|
+
int err;
|
|
190
|
+
|
|
191
|
+
js_value_t *message;
|
|
192
|
+
if (job->error.len > 0) {
|
|
193
|
+
err = js_create_string_utf8(env, (utf8_t *) job->error.data, job->error.len, &message);
|
|
194
|
+
} else {
|
|
195
|
+
err = js_create_string_utf8(env, (utf8_t *) "conversion failed", (size_t) -1, &message);
|
|
196
|
+
}
|
|
197
|
+
assert(err == 0);
|
|
198
|
+
|
|
199
|
+
js_value_t *error;
|
|
200
|
+
err = js_create_error(env, NULL, message, &error);
|
|
201
|
+
assert(err == 0);
|
|
202
|
+
|
|
203
|
+
return error;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
static js_value_t *
|
|
207
|
+
simple_converter_convert_sync(js_env_t *env, js_callback_info_t *info) {
|
|
208
|
+
int err;
|
|
209
|
+
|
|
210
|
+
simple_converter_job_t job;
|
|
211
|
+
if (!simple_converter__job_init(env, info, false, &job)) return NULL;
|
|
212
|
+
|
|
213
|
+
simple_converter__run(&job);
|
|
214
|
+
|
|
215
|
+
js_value_t *result = NULL;
|
|
216
|
+
|
|
217
|
+
if (job.status == 0) {
|
|
218
|
+
result = simple_converter__output(env, &job);
|
|
219
|
+
} else {
|
|
220
|
+
err = js_throw(env, simple_converter__error(env, &job));
|
|
221
|
+
assert(err == 0);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
simple_converter__job_release(&job);
|
|
225
|
+
|
|
226
|
+
return result;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
#ifndef __wasm__
|
|
230
|
+
static void
|
|
231
|
+
simple_converter__on_work(uv_work_t *work) {
|
|
232
|
+
simple_converter_req_t *req = (simple_converter_req_t *) work;
|
|
233
|
+
|
|
234
|
+
simple_converter__run(&req->job);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
static void
|
|
238
|
+
simple_converter__on_after_work(uv_work_t *work, int status) {
|
|
239
|
+
int err;
|
|
240
|
+
|
|
241
|
+
simple_converter_req_t *req = (simple_converter_req_t *) work;
|
|
242
|
+
|
|
243
|
+
js_env_t *env = req->env;
|
|
244
|
+
|
|
245
|
+
if (!req->exiting) {
|
|
246
|
+
js_handle_scope_t *scope;
|
|
247
|
+
err = js_open_handle_scope(env, &scope);
|
|
248
|
+
assert(err == 0);
|
|
249
|
+
|
|
250
|
+
if (status == 0 && req->job.status == 0) {
|
|
251
|
+
err = js_resolve_deferred(env, req->deferred, simple_converter__output(env, &req->job));
|
|
252
|
+
} else {
|
|
253
|
+
err = js_reject_deferred(env, req->deferred, simple_converter__error(env, &req->job));
|
|
254
|
+
}
|
|
255
|
+
assert(err == 0);
|
|
256
|
+
|
|
257
|
+
err = js_close_handle_scope(env, scope);
|
|
258
|
+
assert(err == 0);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
err = js_finish_deferred_teardown_callback(req->teardown);
|
|
262
|
+
assert(err == 0);
|
|
263
|
+
|
|
264
|
+
simple_converter__job_release(&req->job);
|
|
265
|
+
free(req);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
static void
|
|
269
|
+
simple_converter__on_teardown(js_deferred_teardown_t *teardown, void *data) {
|
|
270
|
+
simple_converter_req_t *req = data;
|
|
271
|
+
|
|
272
|
+
req->exiting = true;
|
|
273
|
+
|
|
274
|
+
uv_cancel((uv_req_t *) &req->work);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
static js_value_t *
|
|
278
|
+
simple_converter_convert(js_env_t *env, js_callback_info_t *info) {
|
|
279
|
+
int err;
|
|
280
|
+
|
|
281
|
+
simple_converter_req_t *req = malloc(sizeof(simple_converter_req_t));
|
|
282
|
+
if (req == NULL) {
|
|
283
|
+
err = js_throw_error(env, NULL, "out of memory");
|
|
284
|
+
assert(err == 0);
|
|
285
|
+
return NULL;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (!simple_converter__job_init(env, info, true, &req->job)) {
|
|
289
|
+
free(req);
|
|
290
|
+
return NULL;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
req->env = env;
|
|
294
|
+
req->exiting = false;
|
|
295
|
+
|
|
296
|
+
js_value_t *promise;
|
|
297
|
+
err = js_create_promise(env, &req->deferred, &promise);
|
|
298
|
+
assert(err == 0);
|
|
299
|
+
|
|
300
|
+
uv_loop_t *loop;
|
|
301
|
+
err = js_get_env_loop(env, &loop);
|
|
302
|
+
assert(err == 0);
|
|
303
|
+
|
|
304
|
+
err = uv_queue_work(loop, &req->work, simple_converter__on_work, simple_converter__on_after_work);
|
|
305
|
+
assert(err == 0);
|
|
306
|
+
|
|
307
|
+
err = js_add_deferred_teardown_callback(env, simple_converter__on_teardown, req, &req->teardown);
|
|
308
|
+
assert(err == 0);
|
|
309
|
+
|
|
310
|
+
return promise;
|
|
311
|
+
}
|
|
312
|
+
#endif
|
|
313
|
+
|
|
109
314
|
static js_value_t *
|
|
110
315
|
simple_converter_exports(js_env_t *env, js_value_t *exports) {
|
|
111
316
|
int err;
|
|
@@ -119,7 +324,10 @@ simple_converter_exports(js_env_t *env, js_value_t *exports) {
|
|
|
119
324
|
assert(err == 0); \
|
|
120
325
|
}
|
|
121
326
|
|
|
327
|
+
#ifndef __wasm__
|
|
122
328
|
V("convert", simple_converter_convert)
|
|
329
|
+
#endif
|
|
330
|
+
V("convertSync", simple_converter_convert_sync)
|
|
123
331
|
#undef V
|
|
124
332
|
|
|
125
333
|
return exports;
|
package/cmake/rust.cmake
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
include_guard(GLOBAL)
|
|
2
2
|
|
|
3
|
-
set(
|
|
3
|
+
set(CORROSION_COMMIT "1499b14e4906a2890f5cee1547c8848db261753d" CACHE STRING "Corrosion commit (v0.6.1)")
|
|
4
4
|
|
|
5
5
|
bare_platform(_sys)
|
|
6
6
|
bare_arch(_arch)
|
|
@@ -43,16 +43,26 @@ elseif(_sys STREQUAL "win32")
|
|
|
43
43
|
else()
|
|
44
44
|
set(_triple x86_64-pc-windows-msvc)
|
|
45
45
|
endif()
|
|
46
|
+
elseif(_sys STREQUAL "wasi")
|
|
47
|
+
set(_triple wasm32-wasip1)
|
|
46
48
|
else()
|
|
47
49
|
message(FATAL_ERROR "simple-converter: no Rust target for '${_sys}/${_arch}'")
|
|
48
50
|
endif()
|
|
49
51
|
|
|
50
52
|
set(Rust_CARGO_TARGET "${_triple}" CACHE STRING "Rust target triple")
|
|
51
53
|
|
|
52
|
-
fetch_package("github:corrosion-rs/corrosion#${
|
|
54
|
+
fetch_package("github:corrosion-rs/corrosion#${CORROSION_COMMIT}")
|
|
53
55
|
|
|
54
56
|
corrosion_import_crate(
|
|
55
57
|
MANIFEST_PATH "${CMAKE_CURRENT_SOURCE_DIR}/core/Cargo.toml"
|
|
56
58
|
CRATE_TYPES staticlib
|
|
57
59
|
PROFILE release
|
|
58
60
|
)
|
|
61
|
+
|
|
62
|
+
# Corrosion 0.6.1 adds the Command Line Tools SDK as a link directory on macOS.
|
|
63
|
+
# The linker searches it before CMAKE_OSX_SYSROOT, so -lSystem resolves against
|
|
64
|
+
# the wrong SDK and fails when the two differ (corrosion-rs/corrosion#686, fixed
|
|
65
|
+
# upstream after 0.6.1). Drop this once the pin moves past that fix.
|
|
66
|
+
if(APPLE)
|
|
67
|
+
set_property(TARGET simple_converter_core-static PROPERTY INTERFACE_LINK_DIRECTORIES "")
|
|
68
|
+
endif()
|