Skip to content

Commit 60b5c7c

Browse files
committed
Store richer adapter types, don't use instructions for TypeScript
This commit updates how TypeScript signature are generated from adapters in wasm-bindgen. A richer set of `AdapterType` types are now stored which record information about optional types and such. These direct `AdapterType` values are then used to calculate the TypeScript signature, rather than following the instructions in an adapter function (which only works anyway for wasm-bindgen generated adapters). This should be more robust since it reads the actual true signature of the adapter to generate the TypeScript signature, rather than attempting to ad-hoc-ly infer it from the various instructions, which was already broken. A number of refactorings were involved here, but the main pieces are: * The `AdapterType` type is a bit more rich now to describe more Rust-like types. * The `TypescriptArg` structure is now gone and instead return values are directly inferred from type signatures of adapters. * The `typescript_{required,optional}` methods are no longer needed. * The return of `JsBuilder::process` was enhanced to return more values, rather than storing some return values on the structure itself. Closes rustwasm#1926
1 parent 6c27376 commit 60b5c7c

File tree

8 files changed

+204
-209
lines changed

8 files changed

+204
-209
lines changed

crates/cli-support/src/js/binding.rs

+106-136
Large diffs are not rendered by default.

crates/cli-support/src/js/mod.rs

+18-14
Original file line numberDiff line numberDiff line change
@@ -1950,7 +1950,13 @@ impl<'a> Context<'a> {
19501950
}
19511951

19521952
// Process the `binding` and generate a bunch of JS/TypeScript/etc.
1953-
let js = builder
1953+
let binding::JsFunction {
1954+
ts_sig,
1955+
ts_arg_tys,
1956+
ts_ret_ty,
1957+
js_doc,
1958+
code,
1959+
} = builder
19541960
.process(&adapter, instrs, arg_names)
19551961
.with_context(|| match kind {
19561962
Kind::Export(e) => format!("failed to generate bindings for `{}`", e.debug_name),
@@ -1963,8 +1969,6 @@ impl<'a> Context<'a> {
19631969
}
19641970
Kind::Adapter => format!("failed to generates bindings for adapter"),
19651971
})?;
1966-
let ts = builder.typescript_signature();
1967-
let js_doc = builder.js_doc_comments();
19681972

19691973
// Once we've got all the JS then put it in the right location depending
19701974
// on what's being exported.
@@ -1973,11 +1977,11 @@ impl<'a> Context<'a> {
19731977
let docs = format_doc_comments(&export.comments, Some(js_doc));
19741978
match &export.kind {
19751979
AuxExportKind::Function(name) => {
1976-
self.export(&name, &format!("function{}", js), Some(docs))?;
1980+
self.export(&name, &format!("function{}", code), Some(docs))?;
19771981
self.globals.push_str("\n");
19781982
self.typescript.push_str("export function ");
19791983
self.typescript.push_str(&name);
1980-
self.typescript.push_str(&ts);
1984+
self.typescript.push_str(&ts_sig);
19811985
self.typescript.push_str(";\n");
19821986
}
19831987
AuxExportKind::Constructor(class) => {
@@ -1986,36 +1990,36 @@ impl<'a> Context<'a> {
19861990
bail!("found duplicate constructor for class `{}`", class);
19871991
}
19881992
exported.has_constructor = true;
1989-
exported.push(&docs, "constructor", "", &js, &ts);
1993+
exported.push(&docs, "constructor", "", &code, &ts_sig);
19901994
}
19911995
AuxExportKind::Getter { class, field } => {
1992-
let ret_ty = builder.ts_ret.as_ref().unwrap().ty.clone();
1996+
let ret_ty = ts_ret_ty.unwrap();
19931997
let exported = require_class(&mut self.exported_classes, class);
1994-
exported.push_getter(&docs, field, &js, &ret_ty);
1998+
exported.push_getter(&docs, field, &code, &ret_ty);
19951999
}
19962000
AuxExportKind::Setter { class, field } => {
1997-
let arg_ty = builder.ts_args[0].ty.clone();
2001+
let arg_ty = ts_arg_tys[0].clone();
19982002
let exported = require_class(&mut self.exported_classes, class);
1999-
exported.push_setter(&docs, field, &js, &arg_ty);
2003+
exported.push_setter(&docs, field, &code, &arg_ty);
20002004
}
20012005
AuxExportKind::StaticFunction { class, name } => {
20022006
let exported = require_class(&mut self.exported_classes, class);
2003-
exported.push(&docs, name, "static ", &js, &ts);
2007+
exported.push(&docs, name, "static ", &code, &ts_sig);
20042008
}
20052009
AuxExportKind::Method { class, name, .. } => {
20062010
let exported = require_class(&mut self.exported_classes, class);
2007-
exported.push(&docs, name, "", &js, &ts);
2011+
exported.push(&docs, name, "", &code, &ts_sig);
20082012
}
20092013
}
20102014
}
20112015
Kind::Import(core) => {
20122016
self.wasm_import_definitions
2013-
.insert(core, format!("function{}", js));
2017+
.insert(core, format!("function{}", code));
20142018
}
20152019
Kind::Adapter => {
20162020
self.globals.push_str("function ");
20172021
self.globals.push_str(&self.adapter_name(id));
2018-
self.globals.push_str(&js);
2022+
self.globals.push_str(&code);
20192023
self.globals.push_str("\n\n");
20202024
}
20212025
}

crates/cli-support/src/multivalue.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ fn extract_xform<'a>(
6767
if let Some(Instruction::Retptr) = instructions.first().map(|e| &e.instr) {
6868
instructions.remove(0);
6969
let mut types = Vec::new();
70-
instructions.retain(|instruction| match instruction.instr {
70+
instructions.retain(|instruction| match &instruction.instr {
7171
Instruction::LoadRetptr { ty, .. } => {
7272
types.push(ty.to_wasm().unwrap());
7373
false

crates/cli-support/src/wit/incoming.rs

+26-25
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ impl InstructionBuilder<'_, '_> {
6969
}
7070
Descriptor::RustStruct(class) => {
7171
self.instruction(
72-
&[AdapterType::Anyref],
72+
&[AdapterType::Struct(class.clone())],
7373
Instruction::I32FromAnyrefRustOwned {
7474
class: class.clone(),
7575
},
@@ -147,7 +147,7 @@ impl InstructionBuilder<'_, '_> {
147147
match arg {
148148
Descriptor::RustStruct(class) => {
149149
self.instruction(
150-
&[AdapterType::Anyref],
150+
&[AdapterType::Struct(class.clone())],
151151
Instruction::I32FromAnyrefRustBorrow {
152152
class: class.clone(),
153153
},
@@ -217,56 +217,56 @@ impl InstructionBuilder<'_, '_> {
217217
match arg {
218218
Descriptor::Anyref => {
219219
self.instruction(
220-
&[AdapterType::Anyref],
220+
&[AdapterType::Anyref.option()],
221221
Instruction::I32FromOptionAnyref {
222222
table_and_alloc: None,
223223
},
224224
&[AdapterType::I32],
225225
);
226226
}
227-
Descriptor::I8 => self.in_option_sentinel(),
228-
Descriptor::U8 => self.in_option_sentinel(),
229-
Descriptor::I16 => self.in_option_sentinel(),
230-
Descriptor::U16 => self.in_option_sentinel(),
227+
Descriptor::I8 => self.in_option_sentinel(AdapterType::S8),
228+
Descriptor::U8 => self.in_option_sentinel(AdapterType::U8),
229+
Descriptor::I16 => self.in_option_sentinel(AdapterType::S16),
230+
Descriptor::U16 => self.in_option_sentinel(AdapterType::U16),
231231
Descriptor::I32 => self.in_option_native(ValType::I32),
232232
Descriptor::U32 => self.in_option_native(ValType::I32),
233233
Descriptor::F32 => self.in_option_native(ValType::F32),
234234
Descriptor::F64 => self.in_option_native(ValType::F64),
235235
Descriptor::I64 | Descriptor::U64 => {
236-
let signed = match arg {
237-
Descriptor::I64 => true,
238-
_ => false,
236+
let (signed, ty) = match arg {
237+
Descriptor::I64 => (true, AdapterType::S64.option()),
238+
_ => (false, AdapterType::U64.option()),
239239
};
240240
self.instruction(
241-
&[AdapterType::Anyref],
241+
&[ty],
242242
Instruction::I32SplitOption64 { signed },
243-
&[AdapterType::I32; 3],
243+
&[AdapterType::I32, AdapterType::I32, AdapterType::I32],
244244
);
245245
}
246246
Descriptor::Boolean => {
247247
self.instruction(
248-
&[AdapterType::Anyref],
248+
&[AdapterType::Bool.option()],
249249
Instruction::I32FromOptionBool,
250250
&[AdapterType::I32],
251251
);
252252
}
253253
Descriptor::Char => {
254254
self.instruction(
255-
&[AdapterType::Anyref],
255+
&[AdapterType::String.option()],
256256
Instruction::I32FromOptionChar,
257257
&[AdapterType::I32],
258258
);
259259
}
260260
Descriptor::Enum { hole } => {
261261
self.instruction(
262-
&[AdapterType::Anyref],
262+
&[AdapterType::U32.option()],
263263
Instruction::I32FromOptionEnum { hole: *hole },
264264
&[AdapterType::I32],
265265
);
266266
}
267267
Descriptor::RustStruct(name) => {
268268
self.instruction(
269-
&[AdapterType::Anyref],
269+
&[AdapterType::Struct(name.clone()).option()],
270270
Instruction::I32FromOptionRust {
271271
class: name.to_string(),
272272
},
@@ -279,13 +279,13 @@ impl InstructionBuilder<'_, '_> {
279279
let mem = self.cx.memory()?;
280280
let realloc = self.cx.realloc();
281281
self.instruction(
282-
&[AdapterType::Anyref],
282+
&[AdapterType::String.option()],
283283
Instruction::OptionString {
284284
malloc,
285285
mem,
286286
realloc,
287287
},
288-
&[AdapterType::I32; 2],
288+
&[AdapterType::I32, AdapterType::I32],
289289
);
290290
}
291291

@@ -299,9 +299,9 @@ impl InstructionBuilder<'_, '_> {
299299
let malloc = self.cx.malloc()?;
300300
let mem = self.cx.memory()?;
301301
self.instruction(
302-
&[AdapterType::Anyref],
302+
&[AdapterType::Vector(kind).option()],
303303
Instruction::OptionVector { kind, malloc, mem },
304-
&[AdapterType::I32; 2],
304+
&[AdapterType::I32, AdapterType::I32],
305305
);
306306
}
307307

@@ -343,7 +343,7 @@ impl InstructionBuilder<'_, '_> {
343343
// fetch them from the parameters.
344344
if !self.return_position {
345345
for input in inputs {
346-
self.get(*input);
346+
self.get(input.clone());
347347
}
348348
} else {
349349
self.input.extend_from_slice(inputs);
@@ -385,16 +385,17 @@ impl InstructionBuilder<'_, '_> {
385385
}
386386

387387
fn in_option_native(&mut self, wasm: ValType) {
388+
let ty = AdapterType::from_wasm(wasm).unwrap();
388389
self.instruction(
389-
&[AdapterType::Anyref],
390+
&[ty.clone().option()],
390391
Instruction::FromOptionNative { ty: wasm },
391-
&[AdapterType::I32, AdapterType::from_wasm(wasm).unwrap()],
392+
&[AdapterType::I32, ty],
392393
);
393394
}
394395

395-
fn in_option_sentinel(&mut self) {
396+
fn in_option_sentinel(&mut self, ty: AdapterType) {
396397
self.instruction(
397-
&[AdapterType::Anyref],
398+
&[ty.option()],
398399
Instruction::I32FromOptionU32Sentinel,
399400
&[AdapterType::I32],
400401
);

0 commit comments

Comments
 (0)