mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-06-13 04:51:23 +00:00
Mass rename anyref to externref (#2142)
Updates a mess of dependencies and tracks the most recent version of the reference types specification.
This commit is contained in:
@ -18,13 +18,13 @@ log = "0.4"
|
||||
rustc-demangle = "0.1.13"
|
||||
serde_json = "1.0"
|
||||
tempfile = "3.0"
|
||||
walrus = "0.16.1"
|
||||
wasm-bindgen-anyref-xform = { path = '../anyref-xform', version = '=0.2.62' }
|
||||
walrus = "0.17.0"
|
||||
wasm-bindgen-externref-xform = { path = '../externref-xform', version = '=0.2.62' }
|
||||
wasm-bindgen-multi-value-xform = { path = '../multi-value-xform', version = '=0.2.62' }
|
||||
wasm-bindgen-shared = { path = "../shared", version = '=0.2.62' }
|
||||
wasm-bindgen-threads-xform = { path = '../threads-xform', version = '=0.2.62' }
|
||||
wasm-bindgen-wasm-conventions = { path = '../wasm-conventions', version = '=0.2.62' }
|
||||
wasm-bindgen-wasm-interpreter = { path = "../wasm-interpreter", version = '=0.2.62' }
|
||||
wit-text = "0.6.0"
|
||||
wit-walrus = "0.2.0"
|
||||
wit-validator = "0.1.0"
|
||||
wit-text = "0.7.0"
|
||||
wit-walrus = "0.4.0"
|
||||
wit-validator = "0.2.0"
|
||||
|
@ -30,8 +30,8 @@ tys! {
|
||||
REFMUT
|
||||
SLICE
|
||||
VECTOR
|
||||
ANYREF
|
||||
NAMED_ANYREF
|
||||
EXTERNREF
|
||||
NAMED_EXTERNREF
|
||||
ENUM
|
||||
RUST_STRUCT
|
||||
CHAR
|
||||
@ -62,8 +62,8 @@ pub enum Descriptor {
|
||||
Vector(Box<Descriptor>),
|
||||
CachedString,
|
||||
String,
|
||||
Anyref,
|
||||
NamedAnyref(String),
|
||||
Externref,
|
||||
NamedExternref(String),
|
||||
Enum { hole: u32 },
|
||||
RustStruct(String),
|
||||
Char,
|
||||
@ -100,7 +100,7 @@ pub enum VectorKind {
|
||||
F32,
|
||||
F64,
|
||||
String,
|
||||
Anyref,
|
||||
Externref,
|
||||
}
|
||||
|
||||
impl Descriptor {
|
||||
@ -133,15 +133,15 @@ impl Descriptor {
|
||||
OPTIONAL => Descriptor::Option(Box::new(Descriptor::_decode(data, clamped))),
|
||||
CACHED_STRING => Descriptor::CachedString,
|
||||
STRING => Descriptor::String,
|
||||
ANYREF => Descriptor::Anyref,
|
||||
EXTERNREF => Descriptor::Externref,
|
||||
ENUM => Descriptor::Enum { hole: get(data) },
|
||||
RUST_STRUCT => {
|
||||
let name = get_string(data);
|
||||
Descriptor::RustStruct(name)
|
||||
}
|
||||
NAMED_ANYREF => {
|
||||
NAMED_EXTERNREF => {
|
||||
let name = get_string(data);
|
||||
Descriptor::NamedAnyref(name)
|
||||
Descriptor::NamedExternref(name)
|
||||
}
|
||||
CHAR => Descriptor::Char,
|
||||
UNIT => Descriptor::Unit,
|
||||
@ -192,7 +192,7 @@ impl Descriptor {
|
||||
Descriptor::U64 => Some(VectorKind::U64),
|
||||
Descriptor::F32 => Some(VectorKind::F32),
|
||||
Descriptor::F64 => Some(VectorKind::F64),
|
||||
Descriptor::Anyref => Some(VectorKind::Anyref),
|
||||
Descriptor::Externref => Some(VectorKind::Externref),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -254,7 +254,7 @@ impl VectorKind {
|
||||
VectorKind::U64 => "BigUint64Array",
|
||||
VectorKind::F32 => "Float32Array",
|
||||
VectorKind::F64 => "Float64Array",
|
||||
VectorKind::Anyref => "any[]",
|
||||
VectorKind::Externref => "any[]",
|
||||
}
|
||||
}
|
||||
|
||||
@ -272,7 +272,7 @@ impl VectorKind {
|
||||
VectorKind::U64 => 8,
|
||||
VectorKind::F32 => 4,
|
||||
VectorKind::F64 => 8,
|
||||
VectorKind::Anyref => 4,
|
||||
VectorKind::Externref => 4,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use crate::wit::{AdapterType, InstructionData, StackChange, WasmBindgenAux};
|
||||
use anyhow::Result;
|
||||
use std::collections::HashMap;
|
||||
use walrus::{ir::Value, ElementKind, InitExpr, Module};
|
||||
use wasm_bindgen_anyref_xform::Context;
|
||||
use wasm_bindgen_externref_xform::Context;
|
||||
|
||||
pub fn process(module: &mut Module) -> Result<()> {
|
||||
let mut cfg = Context::default();
|
||||
@ -61,20 +61,20 @@ pub fn process(module: &mut Module) -> Result<()> {
|
||||
// them in the aux section to get used.
|
||||
//
|
||||
// FIXME: this is not great, we should ideally have precise tracking of what
|
||||
// requires what. These are used by catch clauses and anyref slices going
|
||||
// in/out of wasm. The catch clauses are a bit weird but anyref slices
|
||||
// requires what. These are used by catch clauses and externref slices going
|
||||
// in/out of wasm. The catch clauses are a bit weird but externref slices
|
||||
// should ideally track in their own instructions what table/functions
|
||||
// they're referencing. This doesn't fit well in today's model of
|
||||
// slice-related instructions, though, so let's just cop out and only enable
|
||||
// these coarsely.
|
||||
aux.anyref_table = Some(meta.table);
|
||||
if module_needs_anyref_metadata(&aux, section) {
|
||||
aux.anyref_alloc = meta.alloc;
|
||||
aux.anyref_drop_slice = meta.drop_slice;
|
||||
aux.externref_table = Some(meta.table);
|
||||
if module_needs_externref_metadata(&aux, section) {
|
||||
aux.externref_alloc = meta.alloc;
|
||||
aux.externref_drop_slice = meta.drop_slice;
|
||||
}
|
||||
|
||||
// Additonally we may need to update some adapter instructions other than
|
||||
// those found for the anyref pass. These are some general "fringe support"
|
||||
// those found for the externref pass. These are some general "fringe support"
|
||||
// things necessary to get absolutely everything working.
|
||||
for (_, adapter) in section.adapters.iter_mut() {
|
||||
let instrs = match &mut adapter.kind {
|
||||
@ -95,15 +95,15 @@ pub fn process(module: &mut Module) -> Result<()> {
|
||||
None => continue,
|
||||
};
|
||||
match import {
|
||||
AuxImport::Intrinsic(Intrinsic::AnyrefHeapLiveCount) => {}
|
||||
AuxImport::Intrinsic(Intrinsic::ExternrefHeapLiveCount) => {}
|
||||
_ => continue,
|
||||
}
|
||||
instr.instr = Instruction::Standard(wit_walrus::Instruction::CallCore(id));
|
||||
}
|
||||
|
||||
// Optional anyref values are now managed in the wasm module, so
|
||||
// Optional externref values are now managed in the wasm module, so
|
||||
// we need to store where they're managed.
|
||||
Instruction::I32FromOptionAnyref {
|
||||
Instruction::I32FromOptionExternref {
|
||||
ref mut table_and_alloc,
|
||||
} => {
|
||||
*table_and_alloc = meta.alloc.map(|id| (meta.table, id));
|
||||
@ -146,7 +146,7 @@ enum Export {
|
||||
/// Adapts the `instrs` given which are an implementation of the import of `id`.
|
||||
///
|
||||
/// This function will pattern match outgoing arguments and update the
|
||||
/// instruction stream to remove any anyref-management instructions since
|
||||
/// instruction stream to remove any externref-management instructions since
|
||||
/// we'll be sinking those into the WebAssembly module.
|
||||
fn import_xform(
|
||||
cx: &mut Context,
|
||||
@ -157,8 +157,8 @@ fn import_xform(
|
||||
) {
|
||||
struct Arg {
|
||||
idx: usize,
|
||||
// Some(false) for a borrowed anyref, Some(true) for an owned one
|
||||
anyref: Option<bool>,
|
||||
// Some(false) for a borrowed externref, Some(true) for an owned one
|
||||
externref: Option<bool>,
|
||||
}
|
||||
|
||||
let mut to_delete = Vec::new();
|
||||
@ -167,7 +167,7 @@ fn import_xform(
|
||||
while let Some((i, instr)) = iter.next() {
|
||||
match instr.instr {
|
||||
Instruction::CallAdapter(_) => break,
|
||||
Instruction::AnyrefLoadOwned | Instruction::TableGet => {
|
||||
Instruction::ExternrefLoadOwned | Instruction::TableGet => {
|
||||
let owned = match instr.instr {
|
||||
Instruction::TableGet => false,
|
||||
_ => true,
|
||||
@ -176,19 +176,19 @@ fn import_xform(
|
||||
Some(arg) => arg,
|
||||
None => panic!("previous instruction must be `arg.get`"),
|
||||
};
|
||||
arg.anyref = Some(owned);
|
||||
arg.externref = Some(owned);
|
||||
match params[arg.idx] {
|
||||
AdapterType::I32 => {}
|
||||
_ => panic!("must be `i32` type"),
|
||||
}
|
||||
params[arg.idx] = AdapterType::Anyref;
|
||||
params[arg.idx] = AdapterType::Externref;
|
||||
args.push(Some(arg));
|
||||
to_delete.push(i);
|
||||
}
|
||||
Instruction::Standard(wit_walrus::Instruction::ArgGet(n)) => {
|
||||
args.push(Some(Arg {
|
||||
idx: n as usize,
|
||||
anyref: None,
|
||||
externref: None,
|
||||
}));
|
||||
}
|
||||
_ => match instr.stack_change {
|
||||
@ -207,46 +207,46 @@ fn import_xform(
|
||||
}
|
||||
}
|
||||
|
||||
let mut ret_anyref = false;
|
||||
let mut ret_externref = false;
|
||||
while let Some((i, instr)) = iter.next() {
|
||||
match instr.instr {
|
||||
Instruction::I32FromAnyrefOwned => {
|
||||
Instruction::I32FromExternrefOwned => {
|
||||
assert_eq!(results.len(), 1);
|
||||
match results[0] {
|
||||
AdapterType::I32 => {}
|
||||
_ => panic!("must be `i32` type"),
|
||||
}
|
||||
results[0] = AdapterType::Anyref;
|
||||
ret_anyref = true;
|
||||
results[0] = AdapterType::Externref;
|
||||
ret_externref = true;
|
||||
to_delete.push(i);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// Delete all unnecessary anyref management insructions
|
||||
// Delete all unnecessary externref management insructions
|
||||
for idx in to_delete.into_iter().rev() {
|
||||
instrs.remove(idx);
|
||||
}
|
||||
|
||||
// Filter down our list of arguments to just the ones that are anyref
|
||||
// Filter down our list of arguments to just the ones that are externref
|
||||
// values.
|
||||
let args = args
|
||||
.iter()
|
||||
.filter_map(|arg| arg.as_ref())
|
||||
.filter_map(|arg| arg.anyref.map(|owned| (arg.idx, owned)))
|
||||
.filter_map(|arg| arg.externref.map(|owned| (arg.idx, owned)))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// ... and register this entire transformation with the anyref
|
||||
// ... and register this entire transformation with the externref
|
||||
// transformation pass.
|
||||
cx.import_xform(id, &args, ret_anyref);
|
||||
cx.import_xform(id, &args, ret_externref);
|
||||
}
|
||||
|
||||
/// Adapts the `instrs` of an adapter function that calls an export.
|
||||
///
|
||||
/// The `instrs` must be generated by wasm-bindgen itself and follow the
|
||||
/// pattern matched below to pass off to the anyref transformation pass. The
|
||||
/// signature of the adapter doesn't change (it remains as anyref-aware) but the
|
||||
/// pattern matched below to pass off to the externref transformation pass. The
|
||||
/// signature of the adapter doesn't change (it remains as externref-aware) but the
|
||||
/// signature of the export we're calling will change during the transformation.
|
||||
fn export_xform(cx: &mut Context, export: Export, instrs: &mut Vec<InstructionData>) {
|
||||
let mut to_delete = Vec::new();
|
||||
@ -255,20 +255,20 @@ fn export_xform(cx: &mut Context, export: Export, instrs: &mut Vec<InstructionDa
|
||||
|
||||
// Mutate instructions leading up to the `CallExport` instruction. We
|
||||
// maintain a stack of indicators whether the element at that stack slot is
|
||||
// unknown (`None`) or whether it's an owned/borrowed anyref
|
||||
// unknown (`None`) or whether it's an owned/borrowed externref
|
||||
// (`Some(owned)`).
|
||||
//
|
||||
// Note that we're going to delete the `I32FromAnyref*` instructions, so we
|
||||
// Note that we're going to delete the `I32FromExternref*` instructions, so we
|
||||
// also maintain indices of the instructions to delete.
|
||||
while let Some((i, instr)) = iter.next() {
|
||||
match instr.instr {
|
||||
Instruction::CallExport(_) | Instruction::CallTableElement(_) => break,
|
||||
Instruction::I32FromAnyrefOwned => {
|
||||
Instruction::I32FromExternrefOwned => {
|
||||
args.pop();
|
||||
args.push(Some(true));
|
||||
to_delete.push(i);
|
||||
}
|
||||
Instruction::I32FromAnyrefBorrow => {
|
||||
Instruction::I32FromExternrefBorrow => {
|
||||
args.pop();
|
||||
args.push(Some(false));
|
||||
to_delete.push(i);
|
||||
@ -289,21 +289,21 @@ fn export_xform(cx: &mut Context, export: Export, instrs: &mut Vec<InstructionDa
|
||||
}
|
||||
}
|
||||
|
||||
// If one of the instructions after the call is an `AnyrefLoadOwned` then we
|
||||
// know that the function returned an anyref. Currently `&'static Anyref`
|
||||
// If one of the instructions after the call is an `ExternrefLoadOwned` then we
|
||||
// know that the function returned an externref. Currently `&'static Externref`
|
||||
// can't be done as a return value, so this is the only case we handle here.
|
||||
let mut ret_anyref = false;
|
||||
let mut ret_externref = false;
|
||||
while let Some((i, instr)) = iter.next() {
|
||||
match instr.instr {
|
||||
Instruction::AnyrefLoadOwned => {
|
||||
ret_anyref = true;
|
||||
Instruction::ExternrefLoadOwned => {
|
||||
ret_externref = true;
|
||||
to_delete.push(i);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// Filter down our list of arguments to just the ones that are anyref
|
||||
// Filter down our list of arguments to just the ones that are externref
|
||||
// values.
|
||||
let args = args
|
||||
.iter()
|
||||
@ -311,20 +311,20 @@ fn export_xform(cx: &mut Context, export: Export, instrs: &mut Vec<InstructionDa
|
||||
.filter_map(|(i, owned)| owned.map(|owned| (i, owned)))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// ... and register this entire transformation with the anyref
|
||||
// ... and register this entire transformation with the externref
|
||||
// transformation pass.
|
||||
match export {
|
||||
Export::Export(id) => {
|
||||
cx.export_xform(id, &args, ret_anyref);
|
||||
cx.export_xform(id, &args, ret_externref);
|
||||
}
|
||||
Export::TableElement { idx, call_idx } => {
|
||||
if let Some(new_idx) = cx.table_element_xform(idx, &args, ret_anyref) {
|
||||
if let Some(new_idx) = cx.table_element_xform(idx, &args, ret_externref) {
|
||||
instrs[call_idx].instr = Instruction::CallTableElement(new_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delete all unnecessary anyref management instructions. We're going to
|
||||
// Delete all unnecessary externref management instructions. We're going to
|
||||
// sink these instructions into the wasm module itself.
|
||||
for idx in to_delete.into_iter().rev() {
|
||||
instrs.remove(idx);
|
||||
@ -332,7 +332,7 @@ fn export_xform(cx: &mut Context, export: Export, instrs: &mut Vec<InstructionDa
|
||||
}
|
||||
|
||||
/// This function shouldn't need to exist, see the fixme at the call-site.
|
||||
fn module_needs_anyref_metadata(aux: &WasmBindgenAux, section: &NonstandardWitSection) -> bool {
|
||||
fn module_needs_externref_metadata(aux: &WasmBindgenAux, section: &NonstandardWitSection) -> bool {
|
||||
use Instruction::*;
|
||||
|
||||
// our `handleError` intrinsic uses a few pieces of metadata to store
|
||||
@ -341,7 +341,7 @@ fn module_needs_anyref_metadata(aux: &WasmBindgenAux, section: &NonstandardWitSe
|
||||
return true;
|
||||
}
|
||||
|
||||
// Look for any instructions which may use `VectorKind::Anyref`. If there
|
||||
// Look for any instructions which may use `VectorKind::Externref`. If there
|
||||
// are any then we'll need our intrinsics/tables/etc, otherwise we shouldn't
|
||||
// ever need them.
|
||||
section.adapters.iter().any(|(_, adapter)| {
|
||||
@ -351,31 +351,31 @@ fn module_needs_anyref_metadata(aux: &WasmBindgenAux, section: &NonstandardWitSe
|
||||
};
|
||||
instructions.iter().any(|instr| match instr.instr {
|
||||
VectorToMemory {
|
||||
kind: VectorKind::Anyref,
|
||||
kind: VectorKind::Externref,
|
||||
..
|
||||
}
|
||||
| MutableSliceToMemory {
|
||||
kind: VectorKind::Anyref,
|
||||
kind: VectorKind::Externref,
|
||||
..
|
||||
}
|
||||
| OptionVector {
|
||||
kind: VectorKind::Anyref,
|
||||
kind: VectorKind::Externref,
|
||||
..
|
||||
}
|
||||
| VectorLoad {
|
||||
kind: VectorKind::Anyref,
|
||||
kind: VectorKind::Externref,
|
||||
..
|
||||
}
|
||||
| OptionVectorLoad {
|
||||
kind: VectorKind::Anyref,
|
||||
kind: VectorKind::Externref,
|
||||
..
|
||||
}
|
||||
| View {
|
||||
kind: VectorKind::Anyref,
|
||||
kind: VectorKind::Externref,
|
||||
..
|
||||
}
|
||||
| OptionView {
|
||||
kind: VectorKind::Anyref,
|
||||
kind: VectorKind::Externref,
|
||||
..
|
||||
} => true,
|
||||
_ => false,
|
@ -63,8 +63,8 @@ macro_rules! intrinsics {
|
||||
};
|
||||
}
|
||||
|
||||
fn ref_anyref() -> Descriptor {
|
||||
Descriptor::Ref(Box::new(Descriptor::Anyref))
|
||||
fn ref_externref() -> Descriptor {
|
||||
Descriptor::Ref(Box::new(Descriptor::Externref))
|
||||
}
|
||||
|
||||
fn ref_string() -> Descriptor {
|
||||
@ -82,91 +82,91 @@ fn opt_f64() -> Descriptor {
|
||||
intrinsics! {
|
||||
pub enum Intrinsic {
|
||||
#[symbol = "__wbindgen_jsval_eq"]
|
||||
#[signature = fn(ref_anyref(), ref_anyref()) -> Boolean]
|
||||
#[signature = fn(ref_externref(), ref_externref()) -> Boolean]
|
||||
JsvalEq,
|
||||
#[symbol = "__wbindgen_is_function"]
|
||||
#[signature = fn(ref_anyref()) -> Boolean]
|
||||
#[signature = fn(ref_externref()) -> Boolean]
|
||||
IsFunction,
|
||||
#[symbol = "__wbindgen_is_undefined"]
|
||||
#[signature = fn(ref_anyref()) -> Boolean]
|
||||
#[signature = fn(ref_externref()) -> Boolean]
|
||||
IsUndefined,
|
||||
#[symbol = "__wbindgen_is_null"]
|
||||
#[signature = fn(ref_anyref()) -> Boolean]
|
||||
#[signature = fn(ref_externref()) -> Boolean]
|
||||
IsNull,
|
||||
#[symbol = "__wbindgen_is_object"]
|
||||
#[signature = fn(ref_anyref()) -> Boolean]
|
||||
#[signature = fn(ref_externref()) -> Boolean]
|
||||
IsObject,
|
||||
#[symbol = "__wbindgen_is_symbol"]
|
||||
#[signature = fn(ref_anyref()) -> Boolean]
|
||||
#[signature = fn(ref_externref()) -> Boolean]
|
||||
IsSymbol,
|
||||
#[symbol = "__wbindgen_is_string"]
|
||||
#[signature = fn(ref_anyref()) -> Boolean]
|
||||
#[signature = fn(ref_externref()) -> Boolean]
|
||||
IsString,
|
||||
#[symbol = "__wbindgen_is_falsy"]
|
||||
#[signature = fn(ref_anyref()) -> Boolean]
|
||||
#[signature = fn(ref_externref()) -> Boolean]
|
||||
IsFalsy,
|
||||
#[symbol = "__wbindgen_object_clone_ref"]
|
||||
#[signature = fn(ref_anyref()) -> Anyref]
|
||||
#[signature = fn(ref_externref()) -> Externref]
|
||||
ObjectCloneRef,
|
||||
#[symbol = "__wbindgen_object_drop_ref"]
|
||||
#[signature = fn(Anyref) -> Unit]
|
||||
#[signature = fn(Externref) -> Unit]
|
||||
ObjectDropRef,
|
||||
#[symbol = "__wbindgen_cb_drop"]
|
||||
#[signature = fn(Anyref) -> Boolean]
|
||||
#[signature = fn(Externref) -> Boolean]
|
||||
CallbackDrop,
|
||||
#[symbol = "__wbindgen_cb_forget"]
|
||||
#[signature = fn(Anyref) -> Unit]
|
||||
#[signature = fn(Externref) -> Unit]
|
||||
CallbackForget,
|
||||
#[symbol = "__wbindgen_number_new"]
|
||||
#[signature = fn(F64) -> Anyref]
|
||||
#[signature = fn(F64) -> Externref]
|
||||
NumberNew,
|
||||
#[symbol = "__wbindgen_string_new"]
|
||||
#[signature = fn(ref_string()) -> Anyref]
|
||||
#[signature = fn(ref_string()) -> Externref]
|
||||
StringNew,
|
||||
#[symbol = "__wbindgen_symbol_anonymous_new"]
|
||||
#[signature = fn() -> Anyref]
|
||||
#[signature = fn() -> Externref]
|
||||
SymbolAnonymousNew,
|
||||
#[symbol = "__wbindgen_symbol_named_new"]
|
||||
#[signature = fn(ref_string()) -> Anyref]
|
||||
#[signature = fn(ref_string()) -> Externref]
|
||||
SymbolNamedNew,
|
||||
#[symbol = "__wbindgen_number_get"]
|
||||
#[signature = fn(ref_anyref()) -> opt_f64()]
|
||||
#[signature = fn(ref_externref()) -> opt_f64()]
|
||||
NumberGet,
|
||||
#[symbol = "__wbindgen_string_get"]
|
||||
#[signature = fn(ref_anyref()) -> opt_string()]
|
||||
#[signature = fn(ref_externref()) -> opt_string()]
|
||||
StringGet,
|
||||
#[symbol = "__wbindgen_boolean_get"]
|
||||
#[signature = fn(ref_anyref()) -> I32]
|
||||
#[signature = fn(ref_externref()) -> I32]
|
||||
BooleanGet,
|
||||
#[symbol = "__wbindgen_throw"]
|
||||
#[signature = fn(ref_string()) -> Unit]
|
||||
Throw,
|
||||
#[symbol = "__wbindgen_rethrow"]
|
||||
#[signature = fn(Anyref) -> Unit]
|
||||
#[signature = fn(Externref) -> Unit]
|
||||
Rethrow,
|
||||
#[symbol = "__wbindgen_memory"]
|
||||
#[signature = fn() -> Anyref]
|
||||
#[signature = fn() -> Externref]
|
||||
Memory,
|
||||
#[symbol = "__wbindgen_module"]
|
||||
#[signature = fn() -> Anyref]
|
||||
#[signature = fn() -> Externref]
|
||||
Module,
|
||||
#[symbol = "__wbindgen_function_table"]
|
||||
#[signature = fn() -> Anyref]
|
||||
#[signature = fn() -> Externref]
|
||||
FunctionTable,
|
||||
#[symbol = "__wbindgen_debug_string"]
|
||||
#[signature = fn(ref_anyref()) -> String]
|
||||
#[signature = fn(ref_externref()) -> String]
|
||||
DebugString,
|
||||
#[symbol = "__wbindgen_json_parse"]
|
||||
#[signature = fn(ref_string()) -> Anyref]
|
||||
#[signature = fn(ref_string()) -> Externref]
|
||||
JsonParse,
|
||||
#[symbol = "__wbindgen_json_serialize"]
|
||||
#[signature = fn(ref_anyref()) -> String]
|
||||
#[signature = fn(ref_externref()) -> String]
|
||||
JsonSerialize,
|
||||
#[symbol = "__wbindgen_anyref_heap_live_count"]
|
||||
#[symbol = "__wbindgen_externref_heap_live_count"]
|
||||
#[signature = fn() -> I32]
|
||||
AnyrefHeapLiveCount,
|
||||
#[symbol = "__wbindgen_init_anyref_table"]
|
||||
ExternrefHeapLiveCount,
|
||||
#[symbol = "__wbindgen_init_externref_table"]
|
||||
#[signature = fn() -> Unit]
|
||||
InitAnyrefTable,
|
||||
InitExternrefTable,
|
||||
}
|
||||
}
|
||||
|
@ -616,13 +616,13 @@ fn instruction(js: &mut JsBuilder, instr: &Instruction, log_error: &mut bool) ->
|
||||
js.push(format!("{}.codePointAt(0)", val));
|
||||
}
|
||||
|
||||
Instruction::I32FromAnyrefOwned => {
|
||||
Instruction::I32FromExternrefOwned => {
|
||||
js.cx.expose_add_heap_object();
|
||||
let val = js.pop();
|
||||
js.push(format!("addHeapObject({})", val));
|
||||
}
|
||||
|
||||
Instruction::I32FromAnyrefBorrow => {
|
||||
Instruction::I32FromExternrefBorrow => {
|
||||
js.cx.expose_borrowed_objects();
|
||||
js.cx.expose_global_stack_pointer();
|
||||
let val = js.pop();
|
||||
@ -630,7 +630,7 @@ fn instruction(js: &mut JsBuilder, instr: &Instruction, log_error: &mut bool) ->
|
||||
js.finally("heap[stack_pointer++] = undefined;");
|
||||
}
|
||||
|
||||
Instruction::I32FromAnyrefRustOwned { class } => {
|
||||
Instruction::I32FromExternrefRustOwned { class } => {
|
||||
let val = js.pop();
|
||||
js.assert_class(&val, &class);
|
||||
js.assert_not_moved(&val);
|
||||
@ -640,7 +640,7 @@ fn instruction(js: &mut JsBuilder, instr: &Instruction, log_error: &mut bool) ->
|
||||
js.push(format!("ptr{}", i));
|
||||
}
|
||||
|
||||
Instruction::I32FromAnyrefRustBorrow { class } => {
|
||||
Instruction::I32FromExternrefRustBorrow { class } => {
|
||||
let val = js.pop();
|
||||
js.assert_class(&val, &class);
|
||||
js.assert_not_moved(&val);
|
||||
@ -707,12 +707,12 @@ fn instruction(js: &mut JsBuilder, instr: &Instruction, log_error: &mut bool) ->
|
||||
js.push(format!("high{}", i));
|
||||
}
|
||||
|
||||
Instruction::I32FromOptionAnyref { table_and_alloc } => {
|
||||
Instruction::I32FromOptionExternref { table_and_alloc } => {
|
||||
let val = js.pop();
|
||||
js.cx.expose_is_like_none();
|
||||
match table_and_alloc {
|
||||
Some((table, alloc)) => {
|
||||
let alloc = js.cx.expose_add_to_anyref_table(*table, *alloc)?;
|
||||
let alloc = js.cx.expose_add_to_externref_table(*table, *alloc)?;
|
||||
js.push(format!("isLikeNone({0}) ? 0 : {1}({0})", val, alloc));
|
||||
}
|
||||
None => {
|
||||
@ -869,7 +869,7 @@ fn instruction(js: &mut JsBuilder, instr: &Instruction, log_error: &mut bool) ->
|
||||
js.push(format!("{} !== 0", val));
|
||||
}
|
||||
|
||||
Instruction::AnyrefLoadOwned => {
|
||||
Instruction::ExternrefLoadOwned => {
|
||||
js.cx.expose_take_object();
|
||||
let val = js.pop();
|
||||
js.push(format!("takeObject({})", val));
|
||||
@ -1224,14 +1224,14 @@ fn adapter2ts(ty: &AdapterType, dst: &mut String) {
|
||||
| AdapterType::F64 => dst.push_str("number"),
|
||||
AdapterType::I64 | AdapterType::S64 | AdapterType::U64 => dst.push_str("BigInt"),
|
||||
AdapterType::String => dst.push_str("string"),
|
||||
AdapterType::Anyref => dst.push_str("any"),
|
||||
AdapterType::Externref => dst.push_str("any"),
|
||||
AdapterType::Bool => dst.push_str("boolean"),
|
||||
AdapterType::Vector(kind) => dst.push_str(kind.js_ty()),
|
||||
AdapterType::Option(ty) => {
|
||||
adapter2ts(ty, dst);
|
||||
dst.push_str(" | undefined");
|
||||
}
|
||||
AdapterType::NamedAnyref(name) => dst.push_str(name),
|
||||
AdapterType::NamedExternref(name) => dst.push_str(name),
|
||||
AdapterType::Struct(name) => dst.push_str(name),
|
||||
AdapterType::Function => dst.push_str("any"),
|
||||
}
|
||||
|
@ -858,7 +858,7 @@ impl<'a> Context<'a> {
|
||||
if !self.should_write_global("heap") {
|
||||
return;
|
||||
}
|
||||
assert!(!self.config.anyref);
|
||||
assert!(!self.config.externref);
|
||||
self.global(&format!(
|
||||
"const heap = new Array({}).fill(undefined);",
|
||||
INITIAL_HEAP_OFFSET
|
||||
@ -1143,11 +1143,11 @@ impl<'a> Context<'a> {
|
||||
return Ok(ret);
|
||||
}
|
||||
self.expose_wasm_vector_len();
|
||||
match (self.aux.anyref_table, self.aux.anyref_alloc) {
|
||||
match (self.aux.externref_table, self.aux.externref_alloc) {
|
||||
(Some(table), Some(alloc)) => {
|
||||
// TODO: using `addToAnyrefTable` goes back and forth between wasm
|
||||
// TODO: using `addToExternrefTable` goes back and forth between wasm
|
||||
// and JS a lot, we should have a bulk operation for this.
|
||||
let add = self.expose_add_to_anyref_table(table, alloc)?;
|
||||
let add = self.expose_add_to_externref_table(table, alloc)?;
|
||||
self.global(&format!(
|
||||
"
|
||||
function {}(array, malloc) {{
|
||||
@ -1341,7 +1341,7 @@ impl<'a> Context<'a> {
|
||||
if !self.should_write_global(ret.to_string()) {
|
||||
return Ok(ret);
|
||||
}
|
||||
match (self.aux.anyref_table, self.aux.anyref_drop_slice) {
|
||||
match (self.aux.externref_table, self.aux.externref_drop_slice) {
|
||||
(Some(table), Some(drop)) => {
|
||||
let table = self.export_name_of(table);
|
||||
let drop = self.export_name_of(drop);
|
||||
@ -1520,7 +1520,7 @@ impl<'a> Context<'a> {
|
||||
VectorKind::U64 => self.expose_uint64_memory(memory),
|
||||
VectorKind::F32 => self.expose_f32_memory(memory),
|
||||
VectorKind::F64 => self.expose_f64_memory(memory),
|
||||
VectorKind::Anyref => self.expose_uint32_memory(memory),
|
||||
VectorKind::Externref => self.expose_uint32_memory(memory),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1665,9 +1665,9 @@ impl<'a> Context<'a> {
|
||||
.exn_store
|
||||
.ok_or_else(|| anyhow!("failed to find `__wbindgen_exn_store` intrinsic"))?;
|
||||
let store = self.export_name_of(store);
|
||||
match (self.aux.anyref_table, self.aux.anyref_alloc) {
|
||||
match (self.aux.externref_table, self.aux.externref_alloc) {
|
||||
(Some(table), Some(alloc)) => {
|
||||
let add = self.expose_add_to_anyref_table(table, alloc)?;
|
||||
let add = self.expose_add_to_externref_table(table, alloc)?;
|
||||
self.global(&format!(
|
||||
"
|
||||
function handleError(f) {{
|
||||
@ -1750,7 +1750,7 @@ impl<'a> Context<'a> {
|
||||
VectorKind::I64 | VectorKind::U64 => self.expose_pass_array64_to_wasm(memory),
|
||||
VectorKind::F32 => self.expose_pass_array_f32_to_wasm(memory),
|
||||
VectorKind::F64 => self.expose_pass_array_f64_to_wasm(memory),
|
||||
VectorKind::Anyref => self.expose_pass_array_jsvalue_to_wasm(memory),
|
||||
VectorKind::Externref => self.expose_pass_array_jsvalue_to_wasm(memory),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1772,7 +1772,7 @@ impl<'a> Context<'a> {
|
||||
VectorKind::U64 => self.expose_get_array_u64_from_wasm(memory),
|
||||
VectorKind::F32 => self.expose_get_array_f32_from_wasm(memory),
|
||||
VectorKind::F64 => self.expose_get_array_f64_from_wasm(memory),
|
||||
VectorKind::Anyref => self.expose_get_array_js_value_from_wasm(memory)?,
|
||||
VectorKind::Externref => self.expose_get_array_js_value_from_wasm(memory)?,
|
||||
})
|
||||
}
|
||||
|
||||
@ -2052,13 +2052,13 @@ impl<'a> Context<'a> {
|
||||
true
|
||||
}
|
||||
|
||||
fn expose_add_to_anyref_table(
|
||||
fn expose_add_to_externref_table(
|
||||
&mut self,
|
||||
table: TableId,
|
||||
alloc: FunctionId,
|
||||
) -> Result<MemView, Error> {
|
||||
let view = self.memview_table("addToAnyrefTable", table);
|
||||
assert!(self.config.anyref);
|
||||
let view = self.memview_table("addToExternrefTable", table);
|
||||
assert!(self.config.externref);
|
||||
if !self.should_write_global(view.to_string()) {
|
||||
return Ok(view);
|
||||
}
|
||||
@ -2921,7 +2921,7 @@ impl<'a> Context<'a> {
|
||||
"JSON.stringify(obj === undefined ? null : obj)".to_string()
|
||||
}
|
||||
|
||||
Intrinsic::AnyrefHeapLiveCount => {
|
||||
Intrinsic::ExternrefHeapLiveCount => {
|
||||
assert_eq!(args.len(), 0);
|
||||
self.expose_global_heap();
|
||||
prelude.push_str(
|
||||
@ -2941,11 +2941,11 @@ impl<'a> Context<'a> {
|
||||
)
|
||||
}
|
||||
|
||||
Intrinsic::InitAnyrefTable => {
|
||||
Intrinsic::InitExternrefTable => {
|
||||
let table = self
|
||||
.aux
|
||||
.anyref_table
|
||||
.ok_or_else(|| anyhow!("must enable anyref to use anyref intrinsic"))?;
|
||||
.externref_table
|
||||
.ok_or_else(|| anyhow!("must enable externref to use externref intrinsic"))?;
|
||||
let name = self.export_name_of(table);
|
||||
// Grow the table to insert our initial values, and then also
|
||||
// set the 0th slot to `undefined` since that's what we've
|
||||
|
@ -11,10 +11,10 @@ use walrus::Module;
|
||||
|
||||
pub(crate) const PLACEHOLDER_MODULE: &str = "__wbindgen_placeholder__";
|
||||
|
||||
mod anyref;
|
||||
mod decode;
|
||||
mod descriptor;
|
||||
mod descriptors;
|
||||
mod externref;
|
||||
mod intrinsic;
|
||||
mod js;
|
||||
mod multivalue;
|
||||
@ -40,7 +40,7 @@ pub struct Bindgen {
|
||||
// Support for the wasm threads proposal, transforms the wasm module to be
|
||||
// "ready to be instantiated on any thread"
|
||||
threads: wasm_bindgen_threads_xform::Config,
|
||||
anyref: bool,
|
||||
externref: bool,
|
||||
multi_value: bool,
|
||||
wasm_interface_types: bool,
|
||||
encode_into: EncodeInto,
|
||||
@ -90,7 +90,8 @@ pub enum EncodeInto {
|
||||
|
||||
impl Bindgen {
|
||||
pub fn new() -> Bindgen {
|
||||
let anyref = env::var("WASM_BINDGEN_ANYREF").is_ok();
|
||||
let externref =
|
||||
env::var("WASM_BINDGEN_ANYREF").is_ok() || env::var("WASM_BINDGEN_EXTERNREF").is_ok();
|
||||
let wasm_interface_types = env::var("WASM_INTERFACE_TYPES").is_ok();
|
||||
let multi_value = env::var("WASM_BINDGEN_MULTI_VALUE").is_ok();
|
||||
Bindgen {
|
||||
@ -109,7 +110,7 @@ impl Bindgen {
|
||||
emit_start: true,
|
||||
weak_refs: env::var("WASM_BINDGEN_WEAKREF").is_ok(),
|
||||
threads: threads_config(),
|
||||
anyref: anyref || wasm_interface_types,
|
||||
externref: externref || wasm_interface_types,
|
||||
multi_value: multi_value || wasm_interface_types,
|
||||
wasm_interface_types,
|
||||
encode_into: EncodeInto::Test,
|
||||
@ -347,37 +348,37 @@ impl Bindgen {
|
||||
// interface types.
|
||||
wit::process(
|
||||
&mut module,
|
||||
self.anyref,
|
||||
self.externref,
|
||||
self.wasm_interface_types,
|
||||
self.emit_start,
|
||||
)?;
|
||||
|
||||
// Now that we've got type information from the webidl processing pass,
|
||||
// touch up the output of rustc to insert anyref shims where necessary.
|
||||
// This is only done if the anyref pass is enabled, which it's
|
||||
// currently off-by-default since `anyref` is still in development in
|
||||
// touch up the output of rustc to insert externref shims where necessary.
|
||||
// This is only done if the externref pass is enabled, which it's
|
||||
// currently off-by-default since `externref` is still in development in
|
||||
// engines.
|
||||
//
|
||||
// If the anyref pass isn't necessary, then we blanket delete the
|
||||
// export of all our anyref intrinsics which will get cleaned up in the
|
||||
// If the externref pass isn't necessary, then we blanket delete the
|
||||
// export of all our externref intrinsics which will get cleaned up in the
|
||||
// GC pass before JS generation.
|
||||
if self.anyref {
|
||||
anyref::process(&mut module)?;
|
||||
if self.externref {
|
||||
externref::process(&mut module)?;
|
||||
} else {
|
||||
let ids = module
|
||||
.exports
|
||||
.iter()
|
||||
.filter(|e| e.name.starts_with("__anyref"))
|
||||
.filter(|e| e.name.starts_with("__externref"))
|
||||
.map(|e| e.id())
|
||||
.collect::<Vec<_>>();
|
||||
for id in ids {
|
||||
module.exports.delete(id);
|
||||
}
|
||||
// Clean up element segments as well if they have holes in them
|
||||
// after some of our transformations, because non-anyref engines
|
||||
// after some of our transformations, because non-externref engines
|
||||
// only support contiguous arrays of function references in element
|
||||
// segments.
|
||||
anyref::force_contiguous_elements(&mut module)?;
|
||||
externref::force_contiguous_elements(&mut module)?;
|
||||
}
|
||||
|
||||
// If wasm interface types are enabled then the `__wbindgen_throw`
|
||||
|
@ -9,7 +9,7 @@ use walrus::Module;
|
||||
///
|
||||
/// This pass is executed as part of the wasm interface types support. This is
|
||||
/// done to support debug mode executables with wasm interface types. Debug mode
|
||||
/// executables will use malloc as well as anyref intrinsics. These intrinsics
|
||||
/// executables will use malloc as well as externref intrinsics. These intrinsics
|
||||
/// internally, when they fail, abort the instance. This abort is done through
|
||||
/// the `__wbindgen_throw` intrinsic in debug mode to provide a hopefully
|
||||
/// useful error message. In release mode it's simply an `unreachable`
|
||||
|
@ -60,24 +60,24 @@ impl InstructionBuilder<'_, '_> {
|
||||
&[AdapterType::I32],
|
||||
);
|
||||
}
|
||||
Descriptor::Anyref => {
|
||||
Descriptor::Externref => {
|
||||
self.instruction(
|
||||
&[AdapterType::Anyref],
|
||||
Instruction::I32FromAnyrefOwned,
|
||||
&[AdapterType::Externref],
|
||||
Instruction::I32FromExternrefOwned,
|
||||
&[AdapterType::I32],
|
||||
);
|
||||
}
|
||||
Descriptor::NamedAnyref(name) => {
|
||||
Descriptor::NamedExternref(name) => {
|
||||
self.instruction(
|
||||
&[AdapterType::NamedAnyref(name.clone())],
|
||||
Instruction::I32FromAnyrefOwned,
|
||||
&[AdapterType::NamedExternref(name.clone())],
|
||||
Instruction::I32FromExternrefOwned,
|
||||
&[AdapterType::I32]
|
||||
)
|
||||
}
|
||||
Descriptor::RustStruct(class) => {
|
||||
self.instruction(
|
||||
&[AdapterType::Struct(class.clone())],
|
||||
Instruction::I32FromAnyrefRustOwned {
|
||||
Instruction::I32FromExternrefRustOwned {
|
||||
class: class.clone(),
|
||||
},
|
||||
&[AdapterType::I32],
|
||||
@ -155,23 +155,23 @@ impl InstructionBuilder<'_, '_> {
|
||||
Descriptor::RustStruct(class) => {
|
||||
self.instruction(
|
||||
&[AdapterType::Struct(class.clone())],
|
||||
Instruction::I32FromAnyrefRustBorrow {
|
||||
Instruction::I32FromExternrefRustBorrow {
|
||||
class: class.clone(),
|
||||
},
|
||||
&[AdapterType::I32],
|
||||
);
|
||||
}
|
||||
Descriptor::Anyref => {
|
||||
Descriptor::Externref => {
|
||||
self.instruction(
|
||||
&[AdapterType::Anyref],
|
||||
Instruction::I32FromAnyrefBorrow,
|
||||
&[AdapterType::Externref],
|
||||
Instruction::I32FromExternrefBorrow,
|
||||
&[AdapterType::I32],
|
||||
);
|
||||
}
|
||||
Descriptor::NamedAnyref(name) => {
|
||||
Descriptor::NamedExternref(name) => {
|
||||
self.instruction(
|
||||
&[AdapterType::NamedAnyref(name.clone())],
|
||||
Instruction::I32FromAnyrefBorrow,
|
||||
&[AdapterType::NamedExternref(name.clone())],
|
||||
Instruction::I32FromExternrefBorrow,
|
||||
&[AdapterType::I32],
|
||||
);
|
||||
}
|
||||
@ -229,19 +229,19 @@ impl InstructionBuilder<'_, '_> {
|
||||
|
||||
fn incoming_option(&mut self, arg: &Descriptor) -> Result<(), Error> {
|
||||
match arg {
|
||||
Descriptor::Anyref => {
|
||||
Descriptor::Externref => {
|
||||
self.instruction(
|
||||
&[AdapterType::Anyref.option()],
|
||||
Instruction::I32FromOptionAnyref {
|
||||
&[AdapterType::Externref.option()],
|
||||
Instruction::I32FromOptionExternref {
|
||||
table_and_alloc: None,
|
||||
},
|
||||
&[AdapterType::I32],
|
||||
);
|
||||
}
|
||||
Descriptor::NamedAnyref(name) => {
|
||||
Descriptor::NamedExternref(name) => {
|
||||
self.instruction(
|
||||
&[AdapterType::NamedAnyref(name.clone()).option()],
|
||||
Instruction::I32FromOptionAnyref {
|
||||
&[AdapterType::NamedExternref(name.clone()).option()],
|
||||
Instruction::I32FromOptionExternref {
|
||||
table_and_alloc: None,
|
||||
},
|
||||
&[AdapterType::I32],
|
||||
|
@ -28,7 +28,7 @@ struct Context<'a> {
|
||||
vendor_prefixes: HashMap<String, Vec<String>>,
|
||||
unique_crate_identifier: &'a str,
|
||||
descriptors: HashMap<String, Descriptor>,
|
||||
anyref_enabled: bool,
|
||||
externref_enabled: bool,
|
||||
wasm_interface_types: bool,
|
||||
support_start: bool,
|
||||
}
|
||||
@ -43,7 +43,7 @@ struct InstructionBuilder<'a, 'b> {
|
||||
|
||||
pub fn process(
|
||||
module: &mut Module,
|
||||
anyref_enabled: bool,
|
||||
externref_enabled: bool,
|
||||
wasm_interface_types: bool,
|
||||
support_start: bool,
|
||||
) -> Result<(NonstandardWitSectionId, WasmBindgenAuxId), Error> {
|
||||
@ -61,7 +61,7 @@ pub fn process(
|
||||
memory: wasm_bindgen_wasm_conventions::get_memory(module).ok(),
|
||||
module,
|
||||
start_found: false,
|
||||
anyref_enabled,
|
||||
externref_enabled,
|
||||
wasm_interface_types,
|
||||
support_start,
|
||||
};
|
||||
@ -147,7 +147,7 @@ impl<'a> Context<'a> {
|
||||
}
|
||||
self.handle_duplicate_imports(&duplicate_import_map);
|
||||
|
||||
self.inject_anyref_initialization()?;
|
||||
self.inject_externref_initialization()?;
|
||||
|
||||
if let Some(custom) = self
|
||||
.module
|
||||
@ -187,7 +187,7 @@ impl<'a> Context<'a> {
|
||||
let signature = Function {
|
||||
shim_idx: 0,
|
||||
arguments: vec![Descriptor::I32; 3],
|
||||
ret: Descriptor::Anyref,
|
||||
ret: Descriptor::Externref,
|
||||
};
|
||||
let id = self.import_adapter(id, signature, AdapterJsImportKind::Normal)?;
|
||||
// Synthesize the two integer pointers we pass through which
|
||||
@ -284,22 +284,22 @@ impl<'a> Context<'a> {
|
||||
}
|
||||
|
||||
// Ensure that the `start` function for this module calls the
|
||||
// `__wbindgen_init_anyref_table` function. This'll ensure that all
|
||||
// instances of this module have the initial slots of the anyref table
|
||||
// `__wbindgen_init_externref_table` function. This'll ensure that all
|
||||
// instances of this module have the initial slots of the externref table
|
||||
// initialized correctly.
|
||||
//
|
||||
// Note that this is disabled if WebAssembly interface types are enabled
|
||||
// since that's a slightly different environment for now which doesn't have
|
||||
// quite the same initialization.
|
||||
fn inject_anyref_initialization(&mut self) -> Result<(), Error> {
|
||||
if !self.anyref_enabled || self.wasm_interface_types {
|
||||
fn inject_externref_initialization(&mut self) -> Result<(), Error> {
|
||||
if !self.externref_enabled || self.wasm_interface_types {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let ty = self.module.types.add(&[], &[]);
|
||||
let (import, import_id) =
|
||||
self.module
|
||||
.add_import_func(PLACEHOLDER_MODULE, "__wbindgen_init_anyref_table", ty);
|
||||
.add_import_func(PLACEHOLDER_MODULE, "__wbindgen_init_externref_table", ty);
|
||||
|
||||
self.module.start = Some(match self.module.start {
|
||||
Some(prev_start) => {
|
||||
@ -309,7 +309,7 @@ impl<'a> Context<'a> {
|
||||
}
|
||||
None => import,
|
||||
});
|
||||
self.bind_intrinsic(import_id, Intrinsic::InitAnyrefTable)?;
|
||||
self.bind_intrinsic(import_id, Intrinsic::InitExternrefTable)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -481,8 +481,8 @@ impl<'a> Context<'a> {
|
||||
|
||||
// Note that we call the previous start function, if any, first. This is
|
||||
// because the start function currently only shows up when it's injected
|
||||
// through thread/anyref transforms. These injected start functions need
|
||||
// to happen before user code, so we always schedule them first.
|
||||
// through thread/externref transforms. These injected start functions
|
||||
// need to happen before user code, so we always schedule them first.
|
||||
let mut builder = walrus::FunctionBuilder::new(&mut self.module.types, &[], &[]);
|
||||
builder.func_body().call(prev_start).call(id);
|
||||
let new_start = builder.finish(Vec::new(), &mut self.module.funcs);
|
||||
@ -743,7 +743,7 @@ impl<'a> Context<'a> {
|
||||
let id = self.import_adapter(
|
||||
import_id,
|
||||
Function {
|
||||
arguments: vec![Descriptor::Ref(Box::new(Descriptor::Anyref))],
|
||||
arguments: vec![Descriptor::Ref(Box::new(Descriptor::Externref))],
|
||||
shim_idx: 0,
|
||||
ret: Descriptor::Boolean,
|
||||
},
|
||||
@ -850,7 +850,7 @@ impl<'a> Context<'a> {
|
||||
let signature = Function {
|
||||
shim_idx: 0,
|
||||
arguments: vec![Descriptor::I32],
|
||||
ret: Descriptor::Anyref,
|
||||
ret: Descriptor::Externref,
|
||||
};
|
||||
let id = self.import_adapter(import_id, signature, AdapterJsImportKind::Normal)?;
|
||||
self.aux
|
||||
|
@ -47,12 +47,12 @@ pub struct WasmBindgenAux {
|
||||
/// exported structs from Rust and their fields they've got exported.
|
||||
pub structs: Vec<AuxStruct>,
|
||||
|
||||
/// Information about various internal functions used to manage the `anyref`
|
||||
/// Information about various internal functions used to manage the `externref`
|
||||
/// table, later used to process JS bindings.
|
||||
pub anyref_table: Option<walrus::TableId>,
|
||||
pub externref_table: Option<walrus::TableId>,
|
||||
pub function_table: Option<walrus::TableId>,
|
||||
pub anyref_alloc: Option<walrus::FunctionId>,
|
||||
pub anyref_drop_slice: Option<walrus::FunctionId>,
|
||||
pub externref_alloc: Option<walrus::FunctionId>,
|
||||
pub externref_drop_slice: Option<walrus::FunctionId>,
|
||||
|
||||
/// Various intrinsics used for JS glue generation
|
||||
pub exn_store: Option<walrus::FunctionId>,
|
||||
@ -89,7 +89,7 @@ pub struct AuxExport {
|
||||
/// sort of an "export map" saying how to wire up all the free functions from
|
||||
/// the wasm module into the output expected JS module. All our functions here
|
||||
/// currently take integer parameters and require a JS wrapper, but ideally
|
||||
/// we'd change them one day to taking/receiving `anyref` which then use some
|
||||
/// we'd change them one day to taking/receiving `externref` which then use some
|
||||
/// sort of webidl import to customize behavior or something like that. In any
|
||||
/// case this doesn't feel quite right in terms of priviledge separation, so
|
||||
/// we'll want to work on this. For now though it works.
|
||||
@ -175,7 +175,7 @@ pub enum AuxImport {
|
||||
/// function call is expected to always be the class.
|
||||
ValueWithThis(JsImport, String),
|
||||
|
||||
/// This import is expected to be a function that takes an `anyref` and
|
||||
/// This import is expected to be a function that takes an `externref` and
|
||||
/// returns a `bool`. It's expected that it tests if the argument is an
|
||||
/// instance of (using `instanceof`) the name specified.
|
||||
///
|
||||
@ -290,7 +290,7 @@ pub enum AuxImport {
|
||||
/// is one that is exported from the Rust/wasm.
|
||||
///
|
||||
/// TODO: sort of like the export map below we should ideally create the
|
||||
/// `anyref` from within Rust itself and then return it directly rather than
|
||||
/// `externref` from within Rust itself and then return it directly rather than
|
||||
/// requiring an intrinsic here to do so.
|
||||
WrapInExportedClass(String),
|
||||
|
||||
@ -371,16 +371,16 @@ impl walrus::CustomSection for WasmBindgenAux {
|
||||
}
|
||||
|
||||
fn add_gc_roots(&self, roots: &mut walrus::passes::Roots) {
|
||||
if let Some(id) = self.anyref_table {
|
||||
if let Some(id) = self.externref_table {
|
||||
roots.push_table(id);
|
||||
}
|
||||
if let Some(id) = self.function_table {
|
||||
roots.push_table(id);
|
||||
}
|
||||
if let Some(id) = self.anyref_alloc {
|
||||
if let Some(id) = self.externref_alloc {
|
||||
roots.push_func(id);
|
||||
}
|
||||
if let Some(id) = self.anyref_drop_slice {
|
||||
if let Some(id) = self.externref_drop_slice {
|
||||
roots.push_func(id);
|
||||
}
|
||||
if let Some(id) = self.exn_store {
|
||||
|
@ -32,18 +32,18 @@ impl InstructionBuilder<'_, '_> {
|
||||
&[AdapterType::Bool],
|
||||
);
|
||||
}
|
||||
Descriptor::Anyref => {
|
||||
Descriptor::Externref => {
|
||||
self.instruction(
|
||||
&[AdapterType::I32],
|
||||
Instruction::AnyrefLoadOwned,
|
||||
&[AdapterType::Anyref],
|
||||
Instruction::ExternrefLoadOwned,
|
||||
&[AdapterType::Externref],
|
||||
);
|
||||
}
|
||||
Descriptor::NamedAnyref(name) => {
|
||||
Descriptor::NamedExternref(name) => {
|
||||
self.instruction(
|
||||
&[AdapterType::I32],
|
||||
Instruction::AnyrefLoadOwned,
|
||||
&[AdapterType::NamedAnyref(name.clone())],
|
||||
Instruction::ExternrefLoadOwned,
|
||||
&[AdapterType::NamedExternref(name.clone())],
|
||||
);
|
||||
}
|
||||
Descriptor::I8 => self.outgoing_i32(AdapterType::S8),
|
||||
@ -162,18 +162,18 @@ impl InstructionBuilder<'_, '_> {
|
||||
|
||||
fn outgoing_ref(&mut self, mutable: bool, arg: &Descriptor) -> Result<(), Error> {
|
||||
match arg {
|
||||
Descriptor::Anyref => {
|
||||
Descriptor::Externref => {
|
||||
self.instruction(
|
||||
&[AdapterType::I32],
|
||||
Instruction::TableGet,
|
||||
&[AdapterType::Anyref],
|
||||
&[AdapterType::Externref],
|
||||
);
|
||||
}
|
||||
Descriptor::NamedAnyref(name) => {
|
||||
Descriptor::NamedExternref(name) => {
|
||||
self.instruction(
|
||||
&[AdapterType::I32],
|
||||
Instruction::TableGet,
|
||||
&[AdapterType::NamedAnyref(name.clone())],
|
||||
&[AdapterType::NamedExternref(name.clone())],
|
||||
);
|
||||
}
|
||||
Descriptor::CachedString => self.cached_string(false, false)?,
|
||||
@ -232,20 +232,20 @@ impl InstructionBuilder<'_, '_> {
|
||||
|
||||
fn outgoing_option(&mut self, arg: &Descriptor) -> Result<(), Error> {
|
||||
match arg {
|
||||
Descriptor::Anyref => {
|
||||
Descriptor::Externref => {
|
||||
// This is set to `undefined` in the `None` case and otherwise
|
||||
// is the valid owned index.
|
||||
self.instruction(
|
||||
&[AdapterType::I32],
|
||||
Instruction::AnyrefLoadOwned,
|
||||
&[AdapterType::Anyref.option()],
|
||||
Instruction::ExternrefLoadOwned,
|
||||
&[AdapterType::Externref.option()],
|
||||
);
|
||||
}
|
||||
Descriptor::NamedAnyref(name) => {
|
||||
Descriptor::NamedExternref(name) => {
|
||||
self.instruction(
|
||||
&[AdapterType::I32],
|
||||
Instruction::AnyrefLoadOwned,
|
||||
&[AdapterType::NamedAnyref(name.clone()).option()],
|
||||
Instruction::ExternrefLoadOwned,
|
||||
&[AdapterType::NamedExternref(name.clone()).option()],
|
||||
);
|
||||
}
|
||||
Descriptor::I8 => self.out_option_sentinel(AdapterType::S8),
|
||||
@ -328,20 +328,20 @@ impl InstructionBuilder<'_, '_> {
|
||||
|
||||
fn outgoing_option_ref(&mut self, _mutable: bool, arg: &Descriptor) -> Result<(), Error> {
|
||||
match arg {
|
||||
Descriptor::Anyref => {
|
||||
Descriptor::Externref => {
|
||||
// If this is `Some` then it's the index, otherwise if it's
|
||||
// `None` then it's the index pointing to undefined.
|
||||
self.instruction(
|
||||
&[AdapterType::I32],
|
||||
Instruction::TableGet,
|
||||
&[AdapterType::Anyref.option()],
|
||||
&[AdapterType::Externref.option()],
|
||||
);
|
||||
}
|
||||
Descriptor::NamedAnyref(name) => {
|
||||
Descriptor::NamedExternref(name) => {
|
||||
self.instruction(
|
||||
&[AdapterType::I32],
|
||||
Instruction::TableGet,
|
||||
&[AdapterType::NamedAnyref(name.clone()).option()],
|
||||
&[AdapterType::NamedExternref(name.clone()).option()],
|
||||
);
|
||||
}
|
||||
Descriptor::CachedString => self.cached_string(true, false)?,
|
||||
|
@ -45,9 +45,9 @@ pub fn add(module: &mut Module) -> Result<(), Error> {
|
||||
structs,
|
||||
|
||||
// irrelevant ids used to track various internal intrinsics and such
|
||||
anyref_table: _,
|
||||
anyref_alloc: _,
|
||||
anyref_drop_slice: _,
|
||||
externref_table: _,
|
||||
externref_alloc: _,
|
||||
externref_drop_slice: _,
|
||||
exn_store: _,
|
||||
shadow_stack_pointer: _,
|
||||
function_table: _,
|
||||
@ -243,17 +243,19 @@ fn translate_instruction(
|
||||
I32FromStringFirstChar | StringFromChar => {
|
||||
bail!("chars aren't supported in wasm interface types");
|
||||
}
|
||||
I32FromAnyrefOwned | I32FromAnyrefBorrow | AnyrefLoadOwned | TableGet => {
|
||||
bail!("anyref pass failed to sink into wasm module");
|
||||
I32FromExternrefOwned | I32FromExternrefBorrow | ExternrefLoadOwned | TableGet => {
|
||||
bail!("externref pass failed to sink into wasm module");
|
||||
}
|
||||
I32FromAnyrefRustOwned { .. } | I32FromAnyrefRustBorrow { .. } | RustFromI32 { .. } => {
|
||||
I32FromExternrefRustOwned { .. }
|
||||
| I32FromExternrefRustBorrow { .. }
|
||||
| RustFromI32 { .. } => {
|
||||
bail!("rust types aren't supported in wasm interface types");
|
||||
}
|
||||
I32Split64 { .. } | I64FromLoHi { .. } => {
|
||||
bail!("64-bit integers aren't supported in wasm-bindgen");
|
||||
}
|
||||
I32SplitOption64 { .. }
|
||||
| I32FromOptionAnyref { .. }
|
||||
| I32FromOptionExternref { .. }
|
||||
| I32FromOptionU32Sentinel
|
||||
| I32FromOptionRust { .. }
|
||||
| I32FromOptionBool
|
||||
|
@ -55,7 +55,7 @@ pub enum StackChange {
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub enum AdapterJsImportKind {
|
||||
/// The first argument is an `anyref` which is the `this` of the function
|
||||
/// The first argument is an `externref` which is the `this` of the function
|
||||
/// call
|
||||
Method,
|
||||
/// The value imported should be invoked as `new`
|
||||
@ -77,14 +77,14 @@ pub enum AdapterType {
|
||||
F32,
|
||||
F64,
|
||||
String,
|
||||
Anyref,
|
||||
Externref,
|
||||
Bool,
|
||||
I32,
|
||||
I64,
|
||||
Vector(VectorKind),
|
||||
Option(Box<AdapterType>),
|
||||
Struct(String),
|
||||
NamedAnyref(String),
|
||||
NamedExternref(String),
|
||||
Function,
|
||||
}
|
||||
|
||||
@ -120,24 +120,24 @@ pub enum Instruction {
|
||||
I32FromBool,
|
||||
/// Pops a `string` from the stack and pushes the first character as `i32`
|
||||
I32FromStringFirstChar,
|
||||
/// Pops an `anyref` from the stack, allocates space in the anyref table,
|
||||
/// Pops an `externref` from the stack, allocates space in the externref table,
|
||||
/// returns the index it was stored at.
|
||||
I32FromAnyrefOwned,
|
||||
/// Pops an `anyref` from the stack, pushes it onto the anyref wasm table
|
||||
I32FromExternrefOwned,
|
||||
/// Pops an `externref` from the stack, pushes it onto the externref wasm table
|
||||
/// stack, and returns the index it was stored at.
|
||||
I32FromAnyrefBorrow,
|
||||
/// Pops an `anyref` from the stack, assumes it's a Rust class given, and
|
||||
I32FromExternrefBorrow,
|
||||
/// Pops an `externref` from the stack, assumes it's a Rust class given, and
|
||||
/// deallocates the JS object and returns the i32 Rust pointer.
|
||||
I32FromAnyrefRustOwned {
|
||||
I32FromExternrefRustOwned {
|
||||
class: String,
|
||||
},
|
||||
/// Pops an `anyref` from the stack, assumes it's a Rust class given, and
|
||||
/// Pops an `externref` from the stack, assumes it's a Rust class given, and
|
||||
/// passes the pointer to Rust which will be borrowed for the duration of a
|
||||
/// call
|
||||
I32FromAnyrefRustBorrow {
|
||||
I32FromExternrefRustBorrow {
|
||||
class: String,
|
||||
},
|
||||
/// Pops an `anyref` from the stack, pushes 0 if it's "none" or the
|
||||
/// Pops an `externref` from the stack, pushes 0 if it's "none" or the
|
||||
/// consumed pointer value if it's "some".
|
||||
I32FromOptionRust {
|
||||
class: String,
|
||||
@ -152,28 +152,28 @@ pub enum Instruction {
|
||||
I32SplitOption64 {
|
||||
signed: bool,
|
||||
},
|
||||
/// Pops an `anyref` from the stack, pushes either 0 if it's "none" or and
|
||||
/// Pops an `externref` from the stack, pushes either 0 if it's "none" or and
|
||||
/// index into the owned wasm table it was stored at if it's "some"
|
||||
I32FromOptionAnyref {
|
||||
/// Set to `Some` by the anyref pass of where to put it in the wasm
|
||||
I32FromOptionExternref {
|
||||
/// Set to `Some` by the externref pass of where to put it in the wasm
|
||||
/// module, otherwise it's shoved into the JS shim.
|
||||
table_and_alloc: Option<(walrus::TableId, walrus::FunctionId)>,
|
||||
},
|
||||
/// Pops an `anyref` from the stack, pushes either a sentinel value if it's
|
||||
/// Pops an `externref` from the stack, pushes either a sentinel value if it's
|
||||
/// "none" or the integer value of it if it's "some"
|
||||
I32FromOptionU32Sentinel,
|
||||
/// Pops an `anyref` from the stack, pushes 0 for "none", 1 for
|
||||
/// Pops an `externref` from the stack, pushes 0 for "none", 1 for
|
||||
/// "some(false)', and 2 for "some(true)"
|
||||
I32FromOptionBool,
|
||||
/// Pops an `anyref` from the stack, pushes a sentinel for "none" or the
|
||||
/// Pops an `externref` from the stack, pushes a sentinel for "none" or the
|
||||
/// value if it's "some"
|
||||
I32FromOptionChar,
|
||||
/// Pops an `anyref` from the stack, pushes `hole` for "none" or the
|
||||
/// Pops an `externref` from the stack, pushes `hole` for "none" or the
|
||||
/// value if it's "some"
|
||||
I32FromOptionEnum {
|
||||
hole: u32,
|
||||
},
|
||||
/// Pops any anyref from the stack and then pushes two values. First is a
|
||||
/// Pops any externref from the stack and then pushes two values. First is a
|
||||
/// 0/1 if it's none/some and second is `ty` value if it was there or 0 if
|
||||
/// it wasn't there.
|
||||
FromOptionNative {
|
||||
@ -208,7 +208,7 @@ pub enum Instruction {
|
||||
realloc: Option<walrus::FunctionId>,
|
||||
},
|
||||
|
||||
/// Pops an anyref, pushes pointer/length or all zeros
|
||||
/// Pops an externref, pushes pointer/length or all zeros
|
||||
OptionVector {
|
||||
kind: VectorKind,
|
||||
malloc: walrus::FunctionId,
|
||||
@ -217,15 +217,15 @@ pub enum Instruction {
|
||||
|
||||
/// pops a `i32`, pushes `bool`
|
||||
BoolFromI32,
|
||||
/// pops `i32`, loads anyref at that slot, dealloates anyref, pushes `anyref`
|
||||
AnyrefLoadOwned,
|
||||
/// pops `i32`, loads externref at that slot, dealloates externref, pushes `externref`
|
||||
ExternrefLoadOwned,
|
||||
/// pops `i32`, pushes string from that `char`
|
||||
StringFromChar,
|
||||
/// pops two `i32`, pushes a 64-bit number
|
||||
I64FromLoHi {
|
||||
signed: bool,
|
||||
},
|
||||
/// pops `i32`, pushes an anyref for the wrapped rust class
|
||||
/// pops `i32`, pushes an externref for the wrapped rust class
|
||||
RustFromI32 {
|
||||
class: String,
|
||||
},
|
||||
@ -251,9 +251,9 @@ pub enum Instruction {
|
||||
mem: walrus::MemoryId,
|
||||
free: walrus::FunctionId,
|
||||
},
|
||||
/// pops i32, loads anyref from anyref table
|
||||
/// pops i32, loads externref from externref table
|
||||
TableGet,
|
||||
/// pops two i32 data pointers, pushes an anyref closure
|
||||
/// pops two i32 data pointers, pushes an externref closure
|
||||
StackClosure {
|
||||
adapter: AdapterId,
|
||||
nargs: usize,
|
||||
@ -271,7 +271,7 @@ pub enum Instruction {
|
||||
},
|
||||
/// pops i32, pushes it viewed as an optional value with a known sentinel
|
||||
OptionU32Sentinel,
|
||||
/// pops an i32, then `ty`, then pushes anyref
|
||||
/// pops an i32, then `ty`, then pushes externref
|
||||
ToOptionNative {
|
||||
ty: walrus::ValType,
|
||||
signed: bool,
|
||||
@ -300,7 +300,7 @@ impl AdapterType {
|
||||
wit_walrus::ValType::F32 => AdapterType::F32,
|
||||
wit_walrus::ValType::F64 => AdapterType::F64,
|
||||
wit_walrus::ValType::String => AdapterType::String,
|
||||
wit_walrus::ValType::Anyref => AdapterType::Anyref,
|
||||
wit_walrus::ValType::Externref => AdapterType::Externref,
|
||||
wit_walrus::ValType::I32 => AdapterType::I32,
|
||||
wit_walrus::ValType::I64 => AdapterType::I64,
|
||||
}
|
||||
@ -312,10 +312,8 @@ impl AdapterType {
|
||||
walrus::ValType::I64 => AdapterType::I64,
|
||||
walrus::ValType::F32 => AdapterType::F32,
|
||||
walrus::ValType::F64 => AdapterType::F64,
|
||||
walrus::ValType::Anyref => AdapterType::Anyref,
|
||||
walrus::ValType::Funcref | walrus::ValType::Nullref | walrus::ValType::V128 => {
|
||||
return None
|
||||
}
|
||||
walrus::ValType::Externref => AdapterType::Externref,
|
||||
walrus::ValType::Funcref | walrus::ValType::V128 => return None,
|
||||
})
|
||||
}
|
||||
|
||||
@ -325,7 +323,7 @@ impl AdapterType {
|
||||
AdapterType::I64 => walrus::ValType::I64,
|
||||
AdapterType::F32 => walrus::ValType::F32,
|
||||
AdapterType::F64 => walrus::ValType::F64,
|
||||
AdapterType::Anyref | AdapterType::NamedAnyref(_) => walrus::ValType::Anyref,
|
||||
AdapterType::Externref | AdapterType::NamedExternref(_) => walrus::ValType::Externref,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
@ -343,7 +341,9 @@ impl AdapterType {
|
||||
AdapterType::F32 => wit_walrus::ValType::F32,
|
||||
AdapterType::F64 => wit_walrus::ValType::F64,
|
||||
AdapterType::String => wit_walrus::ValType::String,
|
||||
AdapterType::Anyref | AdapterType::NamedAnyref(_) => wit_walrus::ValType::Anyref,
|
||||
AdapterType::Externref | AdapterType::NamedExternref(_) => {
|
||||
wit_walrus::ValType::Externref
|
||||
}
|
||||
|
||||
AdapterType::I32 => wit_walrus::ValType::I32,
|
||||
AdapterType::I64 => wit_walrus::ValType::I64,
|
||||
@ -492,7 +492,7 @@ impl walrus::CustomSection for NonstandardWitSection {
|
||||
roots.push_func(id);
|
||||
}
|
||||
}
|
||||
I32FromOptionAnyref { table_and_alloc } => {
|
||||
I32FromOptionExternref { table_and_alloc } => {
|
||||
if let Some((table, alloc)) = table_and_alloc {
|
||||
roots.push_table(table);
|
||||
roots.push_func(alloc);
|
||||
|
Reference in New Issue
Block a user