wasm-bindgen-shared 0.2.130

Shared support between wasm-bindgen and wasm-bindgen cli, an internal dependency.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
#![doc(html_root_url = "https://docs.rs/wasm-bindgen-shared/0.2")]
#![no_std]

extern crate alloc;

use alloc::string::{String, ToString};

pub mod identifier;
#[cfg(test)]
mod schema_hash_approval;
pub mod tys;

// This gets changed whenever our schema changes.
// At this time versions of wasm-bindgen and wasm-bindgen-cli are required to have the exact same
// SCHEMA_VERSION in order to work together.
pub const SCHEMA_VERSION: &str = "0.2.130";

#[macro_export]
macro_rules! shared_api {
    ($mac:ident) => {
        $mac! {
        struct Program<'a> {
            exports: Vec<Export<'a>>,
            enums: Vec<Enum<'a>>,
            imports: Vec<Import<'a>>,
            structs: Vec<Struct<'a>>,
            // NOTE: Originally typescript_custom_sections are just some strings
            // But the expression type can only be parsed into a string during compilation
            // So when encoding, LitOrExpr contains two types, one is that expressions are parsed into strings during compilation, and the other is can be parsed directly.
            // When decoding, LitOrExpr can be decoded as a string.
            typescript_custom_sections: Vec<LitOrExpr<'a>>,
            local_modules: Vec<LocalModule<'a>>,
            inline_js: Vec<&'a str>,
            unique_crate_identifier: &'a str,
            // `module_path!()` of the macro invocation, so same-named items
            // in different modules of one crate stay distinct.
            module_path: LitOrExpr<'a>,
            package_json: Option<&'a str>,
            linked_modules: Vec<LinkedModule<'a>>,
        }

        struct Import<'a> {
            module: Option<ImportModule<'a>>,
            js_namespace: Option<Vec<String>>,
            reexport: Option<String>,
            generate_typescript: bool,
            kind: ImportKind<'a>,
        }

        struct LinkedModule<'a> {
            module: ImportModule<'a>,
            link_function_name: &'a str,
        }

        enum ImportModule<'a> {
            Named(&'a str),
            RawNamed(&'a str),
            Inline(u32),
        }

        enum ImportKind<'a> {
            Function(ImportFunction<'a>),
            Static(ImportStatic<'a>),
            String(ImportString<'a>),
            Type(ImportType<'a>),
            Enum(StringEnum<'a>),
            DynamicUnion(DynamicUnion<'a>),
        }

        struct ImportFunction<'a> {
            shim: &'a str,
            catch: bool,
            variadic: bool,
            assert_no_shim: bool,
            suspending: bool,
            method: Option<MethodData<'a>>,
            structural: bool,
            function: Function<'a>,
            // Whether this import uses the per-monomorphisation generic path
            // (`#[wasm_bindgen(experimental_generic_mono)]`) and is therefore bound per
            // concrete instantiation via the `__wbindgen_describe_generic_import`
            // marker rather than a single named descriptor shim. (Type-erasure
            // generic imports do not set this; they bind like normal imports.)
            generic_per_mono: bool,
        }

        struct MethodData<'a> {
            class: &'a str,
            kind: MethodKind<'a>,
        }

        enum MethodKind<'a> {
            Constructor,
            Operation(Operation<'a>),
        }

        struct Operation<'a> {
            is_static: bool,
            kind: OperationKind<'a>,
        }

        enum OperationKind<'a> {
            Regular,
            RegularThis,
            Getter(&'a str),
            Setter(&'a str),
            IndexingGetter,
            IndexingSetter,
            IndexingDeleter,
        }

        struct ImportStatic<'a> {
            name: &'a str,
            shim: &'a str,
        }

        struct ImportString<'a> {
            shim: &'a str,
            string: &'a str,
        }

        struct ImportType<'a> {
            name: &'a str,
            instanceof_shim: &'a str,
            vendor_prefixes: Vec<&'a str>,
        }

        struct StringEnum<'a> {
            name: &'a str,
            variant_values: Vec<&'a str>,
            comments: Vec<&'a str>,
            generate_typescript: bool,
            private: bool,
            js_namespace: Option<Vec<&'a str>>,
        }

        enum StartKind {
            None,
            Public,
            Private,
        }

        struct DynamicUnion<'a> {
            name: &'a str,
            variant_strings: Vec<&'a str>,
            variant_type_cnt: u32,
            comments: Vec<&'a str>,
            generate_typescript: bool,
            private: bool,
            fallback: bool,
        }


        struct Export<'a> {
            class: Option<&'a str>,
            comments: Vec<&'a str>,
            consumed: bool,
            function: Function<'a>,
            js_namespace: Option<Vec<&'a str>>,
            method_kind: MethodKind<'a>,
            start: StartKind,
        }

        struct Enum<'a> {
            name: &'a str,
            signed: bool,
            variants: Vec<EnumVariant<'a>>,
            comments: Vec<&'a str>,
            generate_typescript: bool,
            js_namespace: Option<Vec<&'a str>>,
            private: bool,
        }

        struct EnumVariant<'a> {
            name: &'a str,
            value: u32,
            comments: Vec<&'a str>,
        }

        struct Function<'a> {
            args: Vec<FunctionArgumentData<'a>>,
            asyncness: bool,
            jspi: bool,
            name: &'a str,
            generate_typescript: bool,
            generate_jsdoc: bool,
            variadic: bool,
            ret_ty_override: Option<&'a str>,
            ret_desc: Option<&'a str>,
        }

        struct FunctionArgumentData<'a> {
            name: String,
            ty_override: Option<&'a str>,
            optional: bool,
            desc: Option<&'a str>,
        }

        struct Struct<'a> {
            name: &'a str,
            fields: Vec<StructField<'a>>,
            comments: Vec<&'a str>,
            is_inspectable: bool,
            generate_typescript: bool,
            js_namespace: Option<Vec<&'a str>>,
            private: bool,
            extends: Option<&'a str>,
            extends_js_class: Option<&'a str>,
            extends_js_namespace: Option<Vec<&'a str>>,
        }

        struct StructField<'a> {
            name: &'a str,
            readonly: bool,
            comments: Vec<&'a str>,
            generate_typescript: bool,
            generate_jsdoc: bool,
        }

        struct LocalModule<'a> {
            identifier: &'a str,
            contents: &'a str,
            linked_module: bool,
        }
        }
    }; // end of mac case
} // end of mac definition

/// Compute a "qualified name" by prepending the namespace (joined with `__`) to the js_name.
/// When there is no namespace, this returns the js_name unchanged.
/// This is used to disambiguate internal wasm symbols when the same js_name
/// appears in different namespaces. `__` is used as the separator because
/// double underscores are unlikely to appear in user-defined names.
pub fn qualified_name(js_namespace: Option<&[impl AsRef<str>]>, js_name: &str) -> String {
    match js_namespace {
        Some(ns) if !ns.is_empty() => {
            let mut name = ns
                .iter()
                .map(|s| s.as_ref())
                .collect::<alloc::vec::Vec<_>>()
                .join("__");
            name.push_str("__");
            name.push_str(js_name);
            name
        }
        _ => js_name.to_string(),
    }
}

/// Append the per-crate hash to a wasm shim symbol so that identically named
/// exports from different crates (or different versions of one crate) cannot
/// collide at link time. The macro emits every export shim under this mangled
/// name; cli-support recomputes it from the hash carried in
/// `Program::unique_crate_identifier` and renames the export back to its
/// canonical name once matched.
pub fn mangled_symbol(base: &str, crate_hash: &str) -> String {
    let mut name = base.to_string();
    name.push('_');
    name.push_str(crate_hash);
    name
}

/// [`mangled_symbol`] further qualified by the defining module, for wasm
/// symbols of items that may share a name across modules of one crate. The
/// macro only learns the module path from rustc, so it emits this as
/// `concat!(module_mangled_symbol(base, hash, ""), module_path!())`.
pub fn module_mangled_symbol(base: &str, crate_hash: &str, module_path: &str) -> String {
    let mut name = mangled_symbol(base, crate_hash);
    name.push('_');
    name.push_str(module_path);
    name
}

/// FNV-1a hash of a `module_path!()`, carried by type descriptors to identify
/// the defining module. A `const fn` so the macro can fold it into a constant:
/// the descriptor interpreter cannot read static data, so the string itself
/// cannot be informed at runtime. The macro (through `wasm_bindgen::__rt`)
/// and the CLI must both use this one function.
pub const fn module_path_hash(module_path: &str) -> u32 {
    let bytes = module_path.as_bytes();
    let mut hash = 0x811c_9dc5u32;
    let mut i = 0;
    while i < bytes.len() {
        hash ^= bytes[i] as u32;
        hash = hash.wrapping_mul(0x0100_0193);
        i += 1;
    }
    hash
}

/// Extract the crate name from a `unique_crate_identifier`, which is encoded
/// as `"{crate_name}-{hash}"` (the hash contains no `-`).
pub fn crate_name(unique_crate_identifier: &str) -> &str {
    unique_crate_identifier
        .rsplit_once('-')
        .map_or(unique_crate_identifier, |(name, _)| name)
}

/// Extract the crate hash from a `unique_crate_identifier` (see
/// [`crate_name`]).
pub fn crate_hash(unique_crate_identifier: &str) -> &str {
    unique_crate_identifier
        .rsplit_once('-')
        .map(|(_, hash)| hash)
        .unwrap_or(unique_crate_identifier)
}

pub fn new_function(struct_name: &str) -> String {
    let mut name = "__wbg_".to_string();
    name.extend(struct_name.chars().flat_map(|s| s.to_lowercase()));
    name.push_str("_new");
    name
}

pub fn free_function(struct_name: &str) -> String {
    let mut name = "__wbg_".to_string();
    name.extend(struct_name.chars().flat_map(|s| s.to_lowercase()));
    name.push_str("_free");
    name
}

pub fn unwrap_function(struct_name: &str) -> String {
    let mut name = "__wbg_".to_string();
    name.extend(struct_name.chars().flat_map(|s| s.to_lowercase()));
    name.push_str("_unwrap");
    name
}

/// Convert a JS-side name into a form suitable as a wasm-side export
/// symbol suffix. Plain identifier names pass through unchanged. The
/// bracket form `"[Symbol.<ident>]"` collapses to `Symbol_<ident>`. Any
/// other non-alphanumeric characters are replaced with `_` so that the
/// result is always a valid C identifier suffix.
fn export_name_suffix(name: &str) -> alloc::borrow::Cow<'_, str> {
    if name.bytes().all(|b| b.is_ascii_alphanumeric() || b == b'_') {
        return alloc::borrow::Cow::Borrowed(name);
    }
    let mut out = String::with_capacity(name.len());
    for c in name.chars() {
        if c.is_ascii_alphanumeric() || c == '_' {
            out.push(c);
        } else if c == '.' || c == '[' || c == ']' {
            // Bracket / dotted forms collapse cleanly; we represent
            // `[Symbol.iterator]` as `Symbol_iterator` (the `[` and `]`
            // drop, the `.` becomes `_`).
            if c == '.' {
                out.push('_');
            }
        } else {
            out.push('_');
        }
    }
    alloc::borrow::Cow::Owned(out)
}

/// Symbol name of the wasm export that upcasts a `*const WasmRefCell<Child>`
/// pointer to a cloned `Rc<WasmRefCell<Parent>>` raw pointer. Used by the
/// macro codegen and by cli-support's JS emission to call each other.
pub fn upcast_function(child_struct: &str, parent_struct: &str) -> String {
    let mut name = "__wbg_upcast_".to_string();
    name.extend(child_struct.chars().flat_map(|s| s.to_lowercase()));
    name.push_str("_to_");
    name.extend(parent_struct.chars().flat_map(|s| s.to_lowercase()));
    name
}

pub fn free_function_export_name(function_name: &str) -> String {
    export_name_suffix(function_name).into_owned()
}

pub fn struct_function_export_name(struct_: &str, f: &str) -> String {
    let mut name = struct_
        .chars()
        .flat_map(|s| s.to_lowercase())
        .collect::<String>();
    name.push('_');
    name.push_str(&export_name_suffix(f));
    name
}

pub fn struct_field_get(struct_: &str, f: &str) -> String {
    let mut name = String::from("__wbg_get_");
    name.extend(struct_.chars().flat_map(|s| s.to_lowercase()));
    name.push('_');
    name.push_str(&export_name_suffix(f));
    name
}

pub fn struct_field_set(struct_: &str, f: &str) -> String {
    let mut name = String::from("__wbg_set_");
    name.extend(struct_.chars().flat_map(|s| s.to_lowercase()));
    name.push('_');
    name.push_str(&export_name_suffix(f));
    name
}

pub fn dynamic_union_variant(union_name: &str, variant_idx: u32) -> String {
    let mut name = String::from("__wbg_dynamic_union_");
    name.extend(union_name.chars().flat_map(|s| s.to_lowercase()));
    name.push('_');
    name.push_str(&variant_idx.to_string());
    name
}

pub fn version() -> String {
    let mut v = env!("CARGO_PKG_VERSION").to_string();
    if let Some(s) = option_env!("WBG_VERSION") {
        v.push_str(" (");
        v.push_str(s);
        v.push(')');
    }
    v
}

pub fn escape_string(s: &str) -> String {
    let mut result = String::with_capacity(s.len());
    for c in s.chars() {
        match c {
            '\\' => result.push_str("\\\\"),
            '\n' => result.push_str("\\n"),
            '\r' => result.push_str("\\r"),
            '\'' => result.push_str("\\'"),
            '"' => result.push_str("\\\""),
            _ => result.push(c),
        }
    }
    result
}