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:
Alex Crichton 2020-05-18 09:36:30 -05:00 committed by GitHub
parent 61e8fc0d38
commit 996e92f3ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
65 changed files with 604 additions and 596 deletions

View File

@ -35,17 +35,19 @@ jobs:
displayName: "Futures test suite on wasm" displayName: "Futures test suite on wasm"
- script: cargo test -p wasm-bindgen-multi-value-xform - script: cargo test -p wasm-bindgen-multi-value-xform
displayName: "multi-value xform tests on native" displayName: "multi-value xform tests on native"
- script: | # TODO: re-enable when binary decoding for reference types is updated in
set -e # Node.
echo "##vso[task.setvariable variable=NODE_ARGS]--experimental-wasm-anyref" # - script: |
echo "##vso[task.setvariable variable=WASM_BINDGEN_ANYREF]1" # set -e
displayName: "Configure anyref passes" # echo "##vso[task.setvariable variable=NODE_ARGS]--experimental-wasm-anyref"
- script: cargo test --target wasm32-unknown-unknown --test wasm # echo "##vso[task.setvariable variable=WASM_BINDGEN_ANYREF]1"
displayName: "(anyref) Crate test suite" # displayName: "Configure anyref passes"
- script: WASM_BINDGEN_NO_DEBUG=1 cargo test --target wasm32-unknown-unknown --test wasm # - script: cargo test --target wasm32-unknown-unknown --test wasm
displayName: "(anyref) Crate test suite (no debug)" # displayName: "(anyref) Crate test suite"
- script: cargo test --target wasm32-unknown-unknown --features serde-serialize --test wasm # - script: WASM_BINDGEN_NO_DEBUG=1 cargo test --target wasm32-unknown-unknown --test wasm
displayName: "(anyref) Crate test suite (with serde)" # displayName: "(anyref) Crate test suite (no debug)"
# - script: cargo test --target wasm32-unknown-unknown --features serde-serialize --test wasm
# displayName: "(anyref) Crate test suite (with serde)"
- job: test_wasm_bindgen_windows - job: test_wasm_bindgen_windows
displayName: "Run wasm-bindgen crate tests (Windows)" displayName: "Run wasm-bindgen crate tests (Windows)"
@ -91,8 +93,8 @@ jobs:
displayName: "wasm-bindgen-cli-support tests" displayName: "wasm-bindgen-cli-support tests"
- script: cargo test -p wasm-bindgen-cli - script: cargo test -p wasm-bindgen-cli
displayName: "wasm-bindgen-cli tests" displayName: "wasm-bindgen-cli tests"
- script: cargo test -p wasm-bindgen-anyref-xform - script: cargo test -p wasm-bindgen-externref-xform
displayName: "wasm-bindgen-anyref-xform tests" displayName: "wasm-bindgen-externref-xform tests"
- script: cargo test -p wasm-bindgen-multi-value-xform - script: cargo test -p wasm-bindgen-multi-value-xform
displayName: "wasm-bindgen-multi-value-xform tests" displayName: "wasm-bindgen-multi-value-xform tests"
- script: cargo test -p wasm-bindgen-wasm-interpreter - script: cargo test -p wasm-bindgen-wasm-interpreter

View File

@ -580,7 +580,7 @@ impl ToTokens for ast::ImportType {
let typescript_type_chars = typescript_type.chars().map(|c| c as u32); let typescript_type_chars = typescript_type.chars().map(|c| c as u32);
quote! { quote! {
use wasm_bindgen::describe::*; use wasm_bindgen::describe::*;
inform(NAMED_ANYREF); inform(NAMED_EXTERNREF);
inform(#typescript_type_len); inform(#typescript_type_len);
#(inform(#typescript_type_chars);)* #(inform(#typescript_type_chars);)*
} }

View File

@ -18,13 +18,13 @@ log = "0.4"
rustc-demangle = "0.1.13" rustc-demangle = "0.1.13"
serde_json = "1.0" serde_json = "1.0"
tempfile = "3.0" tempfile = "3.0"
walrus = "0.16.1" walrus = "0.17.0"
wasm-bindgen-anyref-xform = { path = '../anyref-xform', version = '=0.2.62' } 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-multi-value-xform = { path = '../multi-value-xform', version = '=0.2.62' }
wasm-bindgen-shared = { path = "../shared", 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-threads-xform = { path = '../threads-xform', version = '=0.2.62' }
wasm-bindgen-wasm-conventions = { path = '../wasm-conventions', 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' } wasm-bindgen-wasm-interpreter = { path = "../wasm-interpreter", version = '=0.2.62' }
wit-text = "0.6.0" wit-text = "0.7.0"
wit-walrus = "0.2.0" wit-walrus = "0.4.0"
wit-validator = "0.1.0" wit-validator = "0.2.0"

View File

@ -30,8 +30,8 @@ tys! {
REFMUT REFMUT
SLICE SLICE
VECTOR VECTOR
ANYREF EXTERNREF
NAMED_ANYREF NAMED_EXTERNREF
ENUM ENUM
RUST_STRUCT RUST_STRUCT
CHAR CHAR
@ -62,8 +62,8 @@ pub enum Descriptor {
Vector(Box<Descriptor>), Vector(Box<Descriptor>),
CachedString, CachedString,
String, String,
Anyref, Externref,
NamedAnyref(String), NamedExternref(String),
Enum { hole: u32 }, Enum { hole: u32 },
RustStruct(String), RustStruct(String),
Char, Char,
@ -100,7 +100,7 @@ pub enum VectorKind {
F32, F32,
F64, F64,
String, String,
Anyref, Externref,
} }
impl Descriptor { impl Descriptor {
@ -133,15 +133,15 @@ impl Descriptor {
OPTIONAL => Descriptor::Option(Box::new(Descriptor::_decode(data, clamped))), OPTIONAL => Descriptor::Option(Box::new(Descriptor::_decode(data, clamped))),
CACHED_STRING => Descriptor::CachedString, CACHED_STRING => Descriptor::CachedString,
STRING => Descriptor::String, STRING => Descriptor::String,
ANYREF => Descriptor::Anyref, EXTERNREF => Descriptor::Externref,
ENUM => Descriptor::Enum { hole: get(data) }, ENUM => Descriptor::Enum { hole: get(data) },
RUST_STRUCT => { RUST_STRUCT => {
let name = get_string(data); let name = get_string(data);
Descriptor::RustStruct(name) Descriptor::RustStruct(name)
} }
NAMED_ANYREF => { NAMED_EXTERNREF => {
let name = get_string(data); let name = get_string(data);
Descriptor::NamedAnyref(name) Descriptor::NamedExternref(name)
} }
CHAR => Descriptor::Char, CHAR => Descriptor::Char,
UNIT => Descriptor::Unit, UNIT => Descriptor::Unit,
@ -192,7 +192,7 @@ impl Descriptor {
Descriptor::U64 => Some(VectorKind::U64), Descriptor::U64 => Some(VectorKind::U64),
Descriptor::F32 => Some(VectorKind::F32), Descriptor::F32 => Some(VectorKind::F32),
Descriptor::F64 => Some(VectorKind::F64), Descriptor::F64 => Some(VectorKind::F64),
Descriptor::Anyref => Some(VectorKind::Anyref), Descriptor::Externref => Some(VectorKind::Externref),
_ => None, _ => None,
} }
} }
@ -254,7 +254,7 @@ impl VectorKind {
VectorKind::U64 => "BigUint64Array", VectorKind::U64 => "BigUint64Array",
VectorKind::F32 => "Float32Array", VectorKind::F32 => "Float32Array",
VectorKind::F64 => "Float64Array", VectorKind::F64 => "Float64Array",
VectorKind::Anyref => "any[]", VectorKind::Externref => "any[]",
} }
} }
@ -272,7 +272,7 @@ impl VectorKind {
VectorKind::U64 => 8, VectorKind::U64 => 8,
VectorKind::F32 => 4, VectorKind::F32 => 4,
VectorKind::F64 => 8, VectorKind::F64 => 8,
VectorKind::Anyref => 4, VectorKind::Externref => 4,
} }
} }
} }

View File

@ -6,7 +6,7 @@ use crate::wit::{AdapterType, InstructionData, StackChange, WasmBindgenAux};
use anyhow::Result; use anyhow::Result;
use std::collections::HashMap; use std::collections::HashMap;
use walrus::{ir::Value, ElementKind, InitExpr, Module}; 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<()> { pub fn process(module: &mut Module) -> Result<()> {
let mut cfg = Context::default(); let mut cfg = Context::default();
@ -61,20 +61,20 @@ pub fn process(module: &mut Module) -> Result<()> {
// them in the aux section to get used. // them in the aux section to get used.
// //
// FIXME: this is not great, we should ideally have precise tracking of what // 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 // requires what. These are used by catch clauses and externref slices going
// in/out of wasm. The catch clauses are a bit weird but anyref slices // in/out of wasm. The catch clauses are a bit weird but externref slices
// should ideally track in their own instructions what table/functions // should ideally track in their own instructions what table/functions
// they're referencing. This doesn't fit well in today's model of // 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 // slice-related instructions, though, so let's just cop out and only enable
// these coarsely. // these coarsely.
aux.anyref_table = Some(meta.table); aux.externref_table = Some(meta.table);
if module_needs_anyref_metadata(&aux, section) { if module_needs_externref_metadata(&aux, section) {
aux.anyref_alloc = meta.alloc; aux.externref_alloc = meta.alloc;
aux.anyref_drop_slice = meta.drop_slice; aux.externref_drop_slice = meta.drop_slice;
} }
// Additonally we may need to update some adapter instructions other than // 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. // things necessary to get absolutely everything working.
for (_, adapter) in section.adapters.iter_mut() { for (_, adapter) in section.adapters.iter_mut() {
let instrs = match &mut adapter.kind { let instrs = match &mut adapter.kind {
@ -95,15 +95,15 @@ pub fn process(module: &mut Module) -> Result<()> {
None => continue, None => continue,
}; };
match import { match import {
AuxImport::Intrinsic(Intrinsic::AnyrefHeapLiveCount) => {} AuxImport::Intrinsic(Intrinsic::ExternrefHeapLiveCount) => {}
_ => continue, _ => continue,
} }
instr.instr = Instruction::Standard(wit_walrus::Instruction::CallCore(id)); 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. // we need to store where they're managed.
Instruction::I32FromOptionAnyref { Instruction::I32FromOptionExternref {
ref mut table_and_alloc, ref mut table_and_alloc,
} => { } => {
*table_and_alloc = meta.alloc.map(|id| (meta.table, id)); *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`. /// Adapts the `instrs` given which are an implementation of the import of `id`.
/// ///
/// This function will pattern match outgoing arguments and update the /// 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. /// we'll be sinking those into the WebAssembly module.
fn import_xform( fn import_xform(
cx: &mut Context, cx: &mut Context,
@ -157,8 +157,8 @@ fn import_xform(
) { ) {
struct Arg { struct Arg {
idx: usize, idx: usize,
// Some(false) for a borrowed anyref, Some(true) for an owned one // Some(false) for a borrowed externref, Some(true) for an owned one
anyref: Option<bool>, externref: Option<bool>,
} }
let mut to_delete = Vec::new(); let mut to_delete = Vec::new();
@ -167,7 +167,7 @@ fn import_xform(
while let Some((i, instr)) = iter.next() { while let Some((i, instr)) = iter.next() {
match instr.instr { match instr.instr {
Instruction::CallAdapter(_) => break, Instruction::CallAdapter(_) => break,
Instruction::AnyrefLoadOwned | Instruction::TableGet => { Instruction::ExternrefLoadOwned | Instruction::TableGet => {
let owned = match instr.instr { let owned = match instr.instr {
Instruction::TableGet => false, Instruction::TableGet => false,
_ => true, _ => true,
@ -176,19 +176,19 @@ fn import_xform(
Some(arg) => arg, Some(arg) => arg,
None => panic!("previous instruction must be `arg.get`"), None => panic!("previous instruction must be `arg.get`"),
}; };
arg.anyref = Some(owned); arg.externref = Some(owned);
match params[arg.idx] { match params[arg.idx] {
AdapterType::I32 => {} AdapterType::I32 => {}
_ => panic!("must be `i32` type"), _ => panic!("must be `i32` type"),
} }
params[arg.idx] = AdapterType::Anyref; params[arg.idx] = AdapterType::Externref;
args.push(Some(arg)); args.push(Some(arg));
to_delete.push(i); to_delete.push(i);
} }
Instruction::Standard(wit_walrus::Instruction::ArgGet(n)) => { Instruction::Standard(wit_walrus::Instruction::ArgGet(n)) => {
args.push(Some(Arg { args.push(Some(Arg {
idx: n as usize, idx: n as usize,
anyref: None, externref: None,
})); }));
} }
_ => match instr.stack_change { _ => 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() { while let Some((i, instr)) = iter.next() {
match instr.instr { match instr.instr {
Instruction::I32FromAnyrefOwned => { Instruction::I32FromExternrefOwned => {
assert_eq!(results.len(), 1); assert_eq!(results.len(), 1);
match results[0] { match results[0] {
AdapterType::I32 => {} AdapterType::I32 => {}
_ => panic!("must be `i32` type"), _ => panic!("must be `i32` type"),
} }
results[0] = AdapterType::Anyref; results[0] = AdapterType::Externref;
ret_anyref = true; ret_externref = true;
to_delete.push(i); to_delete.push(i);
} }
_ => {} _ => {}
} }
} }
// Delete all unnecessary anyref management insructions // Delete all unnecessary externref management insructions
for idx in to_delete.into_iter().rev() { for idx in to_delete.into_iter().rev() {
instrs.remove(idx); 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. // values.
let args = args let args = args
.iter() .iter()
.filter_map(|arg| arg.as_ref()) .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<_>>(); .collect::<Vec<_>>();
// ... and register this entire transformation with the anyref // ... and register this entire transformation with the externref
// transformation pass. // 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. /// Adapts the `instrs` of an adapter function that calls an export.
/// ///
/// The `instrs` must be generated by wasm-bindgen itself and follow the /// The `instrs` must be generated by wasm-bindgen itself and follow the
/// pattern matched below to pass off to the anyref transformation pass. The /// pattern matched below to pass off to the externref transformation pass. The
/// signature of the adapter doesn't change (it remains as anyref-aware) but 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. /// signature of the export we're calling will change during the transformation.
fn export_xform(cx: &mut Context, export: Export, instrs: &mut Vec<InstructionData>) { fn export_xform(cx: &mut Context, export: Export, instrs: &mut Vec<InstructionData>) {
let mut to_delete = Vec::new(); 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 // Mutate instructions leading up to the `CallExport` instruction. We
// maintain a stack of indicators whether the element at that stack slot is // 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)`). // (`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. // also maintain indices of the instructions to delete.
while let Some((i, instr)) = iter.next() { while let Some((i, instr)) = iter.next() {
match instr.instr { match instr.instr {
Instruction::CallExport(_) | Instruction::CallTableElement(_) => break, Instruction::CallExport(_) | Instruction::CallTableElement(_) => break,
Instruction::I32FromAnyrefOwned => { Instruction::I32FromExternrefOwned => {
args.pop(); args.pop();
args.push(Some(true)); args.push(Some(true));
to_delete.push(i); to_delete.push(i);
} }
Instruction::I32FromAnyrefBorrow => { Instruction::I32FromExternrefBorrow => {
args.pop(); args.pop();
args.push(Some(false)); args.push(Some(false));
to_delete.push(i); 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 // If one of the instructions after the call is an `ExternrefLoadOwned` then we
// know that the function returned an anyref. Currently `&'static Anyref` // 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. // 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() { while let Some((i, instr)) = iter.next() {
match instr.instr { match instr.instr {
Instruction::AnyrefLoadOwned => { Instruction::ExternrefLoadOwned => {
ret_anyref = true; ret_externref = true;
to_delete.push(i); 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. // values.
let args = args let args = args
.iter() .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))) .filter_map(|(i, owned)| owned.map(|owned| (i, owned)))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
// ... and register this entire transformation with the anyref // ... and register this entire transformation with the externref
// transformation pass. // transformation pass.
match export { match export {
Export::Export(id) => { Export::Export(id) => {
cx.export_xform(id, &args, ret_anyref); cx.export_xform(id, &args, ret_externref);
} }
Export::TableElement { idx, call_idx } => { 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); 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. // sink these instructions into the wasm module itself.
for idx in to_delete.into_iter().rev() { for idx in to_delete.into_iter().rev() {
instrs.remove(idx); 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. /// 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::*; use Instruction::*;
// our `handleError` intrinsic uses a few pieces of metadata to store // 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; 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 // are any then we'll need our intrinsics/tables/etc, otherwise we shouldn't
// ever need them. // ever need them.
section.adapters.iter().any(|(_, adapter)| { 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 { instructions.iter().any(|instr| match instr.instr {
VectorToMemory { VectorToMemory {
kind: VectorKind::Anyref, kind: VectorKind::Externref,
.. ..
} }
| MutableSliceToMemory { | MutableSliceToMemory {
kind: VectorKind::Anyref, kind: VectorKind::Externref,
.. ..
} }
| OptionVector { | OptionVector {
kind: VectorKind::Anyref, kind: VectorKind::Externref,
.. ..
} }
| VectorLoad { | VectorLoad {
kind: VectorKind::Anyref, kind: VectorKind::Externref,
.. ..
} }
| OptionVectorLoad { | OptionVectorLoad {
kind: VectorKind::Anyref, kind: VectorKind::Externref,
.. ..
} }
| View { | View {
kind: VectorKind::Anyref, kind: VectorKind::Externref,
.. ..
} }
| OptionView { | OptionView {
kind: VectorKind::Anyref, kind: VectorKind::Externref,
.. ..
} => true, } => true,
_ => false, _ => false,

View File

@ -63,8 +63,8 @@ macro_rules! intrinsics {
}; };
} }
fn ref_anyref() -> Descriptor { fn ref_externref() -> Descriptor {
Descriptor::Ref(Box::new(Descriptor::Anyref)) Descriptor::Ref(Box::new(Descriptor::Externref))
} }
fn ref_string() -> Descriptor { fn ref_string() -> Descriptor {
@ -82,91 +82,91 @@ fn opt_f64() -> Descriptor {
intrinsics! { intrinsics! {
pub enum Intrinsic { pub enum Intrinsic {
#[symbol = "__wbindgen_jsval_eq"] #[symbol = "__wbindgen_jsval_eq"]
#[signature = fn(ref_anyref(), ref_anyref()) -> Boolean] #[signature = fn(ref_externref(), ref_externref()) -> Boolean]
JsvalEq, JsvalEq,
#[symbol = "__wbindgen_is_function"] #[symbol = "__wbindgen_is_function"]
#[signature = fn(ref_anyref()) -> Boolean] #[signature = fn(ref_externref()) -> Boolean]
IsFunction, IsFunction,
#[symbol = "__wbindgen_is_undefined"] #[symbol = "__wbindgen_is_undefined"]
#[signature = fn(ref_anyref()) -> Boolean] #[signature = fn(ref_externref()) -> Boolean]
IsUndefined, IsUndefined,
#[symbol = "__wbindgen_is_null"] #[symbol = "__wbindgen_is_null"]
#[signature = fn(ref_anyref()) -> Boolean] #[signature = fn(ref_externref()) -> Boolean]
IsNull, IsNull,
#[symbol = "__wbindgen_is_object"] #[symbol = "__wbindgen_is_object"]
#[signature = fn(ref_anyref()) -> Boolean] #[signature = fn(ref_externref()) -> Boolean]
IsObject, IsObject,
#[symbol = "__wbindgen_is_symbol"] #[symbol = "__wbindgen_is_symbol"]
#[signature = fn(ref_anyref()) -> Boolean] #[signature = fn(ref_externref()) -> Boolean]
IsSymbol, IsSymbol,
#[symbol = "__wbindgen_is_string"] #[symbol = "__wbindgen_is_string"]
#[signature = fn(ref_anyref()) -> Boolean] #[signature = fn(ref_externref()) -> Boolean]
IsString, IsString,
#[symbol = "__wbindgen_is_falsy"] #[symbol = "__wbindgen_is_falsy"]
#[signature = fn(ref_anyref()) -> Boolean] #[signature = fn(ref_externref()) -> Boolean]
IsFalsy, IsFalsy,
#[symbol = "__wbindgen_object_clone_ref"] #[symbol = "__wbindgen_object_clone_ref"]
#[signature = fn(ref_anyref()) -> Anyref] #[signature = fn(ref_externref()) -> Externref]
ObjectCloneRef, ObjectCloneRef,
#[symbol = "__wbindgen_object_drop_ref"] #[symbol = "__wbindgen_object_drop_ref"]
#[signature = fn(Anyref) -> Unit] #[signature = fn(Externref) -> Unit]
ObjectDropRef, ObjectDropRef,
#[symbol = "__wbindgen_cb_drop"] #[symbol = "__wbindgen_cb_drop"]
#[signature = fn(Anyref) -> Boolean] #[signature = fn(Externref) -> Boolean]
CallbackDrop, CallbackDrop,
#[symbol = "__wbindgen_cb_forget"] #[symbol = "__wbindgen_cb_forget"]
#[signature = fn(Anyref) -> Unit] #[signature = fn(Externref) -> Unit]
CallbackForget, CallbackForget,
#[symbol = "__wbindgen_number_new"] #[symbol = "__wbindgen_number_new"]
#[signature = fn(F64) -> Anyref] #[signature = fn(F64) -> Externref]
NumberNew, NumberNew,
#[symbol = "__wbindgen_string_new"] #[symbol = "__wbindgen_string_new"]
#[signature = fn(ref_string()) -> Anyref] #[signature = fn(ref_string()) -> Externref]
StringNew, StringNew,
#[symbol = "__wbindgen_symbol_anonymous_new"] #[symbol = "__wbindgen_symbol_anonymous_new"]
#[signature = fn() -> Anyref] #[signature = fn() -> Externref]
SymbolAnonymousNew, SymbolAnonymousNew,
#[symbol = "__wbindgen_symbol_named_new"] #[symbol = "__wbindgen_symbol_named_new"]
#[signature = fn(ref_string()) -> Anyref] #[signature = fn(ref_string()) -> Externref]
SymbolNamedNew, SymbolNamedNew,
#[symbol = "__wbindgen_number_get"] #[symbol = "__wbindgen_number_get"]
#[signature = fn(ref_anyref()) -> opt_f64()] #[signature = fn(ref_externref()) -> opt_f64()]
NumberGet, NumberGet,
#[symbol = "__wbindgen_string_get"] #[symbol = "__wbindgen_string_get"]
#[signature = fn(ref_anyref()) -> opt_string()] #[signature = fn(ref_externref()) -> opt_string()]
StringGet, StringGet,
#[symbol = "__wbindgen_boolean_get"] #[symbol = "__wbindgen_boolean_get"]
#[signature = fn(ref_anyref()) -> I32] #[signature = fn(ref_externref()) -> I32]
BooleanGet, BooleanGet,
#[symbol = "__wbindgen_throw"] #[symbol = "__wbindgen_throw"]
#[signature = fn(ref_string()) -> Unit] #[signature = fn(ref_string()) -> Unit]
Throw, Throw,
#[symbol = "__wbindgen_rethrow"] #[symbol = "__wbindgen_rethrow"]
#[signature = fn(Anyref) -> Unit] #[signature = fn(Externref) -> Unit]
Rethrow, Rethrow,
#[symbol = "__wbindgen_memory"] #[symbol = "__wbindgen_memory"]
#[signature = fn() -> Anyref] #[signature = fn() -> Externref]
Memory, Memory,
#[symbol = "__wbindgen_module"] #[symbol = "__wbindgen_module"]
#[signature = fn() -> Anyref] #[signature = fn() -> Externref]
Module, Module,
#[symbol = "__wbindgen_function_table"] #[symbol = "__wbindgen_function_table"]
#[signature = fn() -> Anyref] #[signature = fn() -> Externref]
FunctionTable, FunctionTable,
#[symbol = "__wbindgen_debug_string"] #[symbol = "__wbindgen_debug_string"]
#[signature = fn(ref_anyref()) -> String] #[signature = fn(ref_externref()) -> String]
DebugString, DebugString,
#[symbol = "__wbindgen_json_parse"] #[symbol = "__wbindgen_json_parse"]
#[signature = fn(ref_string()) -> Anyref] #[signature = fn(ref_string()) -> Externref]
JsonParse, JsonParse,
#[symbol = "__wbindgen_json_serialize"] #[symbol = "__wbindgen_json_serialize"]
#[signature = fn(ref_anyref()) -> String] #[signature = fn(ref_externref()) -> String]
JsonSerialize, JsonSerialize,
#[symbol = "__wbindgen_anyref_heap_live_count"] #[symbol = "__wbindgen_externref_heap_live_count"]
#[signature = fn() -> I32] #[signature = fn() -> I32]
AnyrefHeapLiveCount, ExternrefHeapLiveCount,
#[symbol = "__wbindgen_init_anyref_table"] #[symbol = "__wbindgen_init_externref_table"]
#[signature = fn() -> Unit] #[signature = fn() -> Unit]
InitAnyrefTable, InitExternrefTable,
} }
} }

View File

@ -616,13 +616,13 @@ fn instruction(js: &mut JsBuilder, instr: &Instruction, log_error: &mut bool) ->
js.push(format!("{}.codePointAt(0)", val)); js.push(format!("{}.codePointAt(0)", val));
} }
Instruction::I32FromAnyrefOwned => { Instruction::I32FromExternrefOwned => {
js.cx.expose_add_heap_object(); js.cx.expose_add_heap_object();
let val = js.pop(); let val = js.pop();
js.push(format!("addHeapObject({})", val)); js.push(format!("addHeapObject({})", val));
} }
Instruction::I32FromAnyrefBorrow => { Instruction::I32FromExternrefBorrow => {
js.cx.expose_borrowed_objects(); js.cx.expose_borrowed_objects();
js.cx.expose_global_stack_pointer(); js.cx.expose_global_stack_pointer();
let val = js.pop(); 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;"); js.finally("heap[stack_pointer++] = undefined;");
} }
Instruction::I32FromAnyrefRustOwned { class } => { Instruction::I32FromExternrefRustOwned { class } => {
let val = js.pop(); let val = js.pop();
js.assert_class(&val, &class); js.assert_class(&val, &class);
js.assert_not_moved(&val); 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)); js.push(format!("ptr{}", i));
} }
Instruction::I32FromAnyrefRustBorrow { class } => { Instruction::I32FromExternrefRustBorrow { class } => {
let val = js.pop(); let val = js.pop();
js.assert_class(&val, &class); js.assert_class(&val, &class);
js.assert_not_moved(&val); 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)); js.push(format!("high{}", i));
} }
Instruction::I32FromOptionAnyref { table_and_alloc } => { Instruction::I32FromOptionExternref { table_and_alloc } => {
let val = js.pop(); let val = js.pop();
js.cx.expose_is_like_none(); js.cx.expose_is_like_none();
match table_and_alloc { match table_and_alloc {
Some((table, 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)); js.push(format!("isLikeNone({0}) ? 0 : {1}({0})", val, alloc));
} }
None => { None => {
@ -869,7 +869,7 @@ fn instruction(js: &mut JsBuilder, instr: &Instruction, log_error: &mut bool) ->
js.push(format!("{} !== 0", val)); js.push(format!("{} !== 0", val));
} }
Instruction::AnyrefLoadOwned => { Instruction::ExternrefLoadOwned => {
js.cx.expose_take_object(); js.cx.expose_take_object();
let val = js.pop(); let val = js.pop();
js.push(format!("takeObject({})", val)); js.push(format!("takeObject({})", val));
@ -1224,14 +1224,14 @@ fn adapter2ts(ty: &AdapterType, dst: &mut String) {
| AdapterType::F64 => dst.push_str("number"), | AdapterType::F64 => dst.push_str("number"),
AdapterType::I64 | AdapterType::S64 | AdapterType::U64 => dst.push_str("BigInt"), AdapterType::I64 | AdapterType::S64 | AdapterType::U64 => dst.push_str("BigInt"),
AdapterType::String => dst.push_str("string"), 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::Bool => dst.push_str("boolean"),
AdapterType::Vector(kind) => dst.push_str(kind.js_ty()), AdapterType::Vector(kind) => dst.push_str(kind.js_ty()),
AdapterType::Option(ty) => { AdapterType::Option(ty) => {
adapter2ts(ty, dst); adapter2ts(ty, dst);
dst.push_str(" | undefined"); 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::Struct(name) => dst.push_str(name),
AdapterType::Function => dst.push_str("any"), AdapterType::Function => dst.push_str("any"),
} }

View File

@ -858,7 +858,7 @@ impl<'a> Context<'a> {
if !self.should_write_global("heap") { if !self.should_write_global("heap") {
return; return;
} }
assert!(!self.config.anyref); assert!(!self.config.externref);
self.global(&format!( self.global(&format!(
"const heap = new Array({}).fill(undefined);", "const heap = new Array({}).fill(undefined);",
INITIAL_HEAP_OFFSET INITIAL_HEAP_OFFSET
@ -1143,11 +1143,11 @@ impl<'a> Context<'a> {
return Ok(ret); return Ok(ret);
} }
self.expose_wasm_vector_len(); 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)) => { (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. // 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!( self.global(&format!(
" "
function {}(array, malloc) {{ function {}(array, malloc) {{
@ -1341,7 +1341,7 @@ impl<'a> Context<'a> {
if !self.should_write_global(ret.to_string()) { if !self.should_write_global(ret.to_string()) {
return Ok(ret); 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)) => { (Some(table), Some(drop)) => {
let table = self.export_name_of(table); let table = self.export_name_of(table);
let drop = self.export_name_of(drop); let drop = self.export_name_of(drop);
@ -1520,7 +1520,7 @@ impl<'a> Context<'a> {
VectorKind::U64 => self.expose_uint64_memory(memory), VectorKind::U64 => self.expose_uint64_memory(memory),
VectorKind::F32 => self.expose_f32_memory(memory), VectorKind::F32 => self.expose_f32_memory(memory),
VectorKind::F64 => self.expose_f64_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 .exn_store
.ok_or_else(|| anyhow!("failed to find `__wbindgen_exn_store` intrinsic"))?; .ok_or_else(|| anyhow!("failed to find `__wbindgen_exn_store` intrinsic"))?;
let store = self.export_name_of(store); 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)) => { (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!( self.global(&format!(
" "
function handleError(f) {{ function handleError(f) {{
@ -1750,7 +1750,7 @@ impl<'a> Context<'a> {
VectorKind::I64 | VectorKind::U64 => self.expose_pass_array64_to_wasm(memory), VectorKind::I64 | VectorKind::U64 => self.expose_pass_array64_to_wasm(memory),
VectorKind::F32 => self.expose_pass_array_f32_to_wasm(memory), VectorKind::F32 => self.expose_pass_array_f32_to_wasm(memory),
VectorKind::F64 => self.expose_pass_array_f64_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::U64 => self.expose_get_array_u64_from_wasm(memory),
VectorKind::F32 => self.expose_get_array_f32_from_wasm(memory), VectorKind::F32 => self.expose_get_array_f32_from_wasm(memory),
VectorKind::F64 => self.expose_get_array_f64_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 true
} }
fn expose_add_to_anyref_table( fn expose_add_to_externref_table(
&mut self, &mut self,
table: TableId, table: TableId,
alloc: FunctionId, alloc: FunctionId,
) -> Result<MemView, Error> { ) -> Result<MemView, Error> {
let view = self.memview_table("addToAnyrefTable", table); let view = self.memview_table("addToExternrefTable", table);
assert!(self.config.anyref); assert!(self.config.externref);
if !self.should_write_global(view.to_string()) { if !self.should_write_global(view.to_string()) {
return Ok(view); return Ok(view);
} }
@ -2921,7 +2921,7 @@ impl<'a> Context<'a> {
"JSON.stringify(obj === undefined ? null : obj)".to_string() "JSON.stringify(obj === undefined ? null : obj)".to_string()
} }
Intrinsic::AnyrefHeapLiveCount => { Intrinsic::ExternrefHeapLiveCount => {
assert_eq!(args.len(), 0); assert_eq!(args.len(), 0);
self.expose_global_heap(); self.expose_global_heap();
prelude.push_str( prelude.push_str(
@ -2941,11 +2941,11 @@ impl<'a> Context<'a> {
) )
} }
Intrinsic::InitAnyrefTable => { Intrinsic::InitExternrefTable => {
let table = self let table = self
.aux .aux
.anyref_table .externref_table
.ok_or_else(|| anyhow!("must enable anyref to use anyref intrinsic"))?; .ok_or_else(|| anyhow!("must enable externref to use externref intrinsic"))?;
let name = self.export_name_of(table); let name = self.export_name_of(table);
// Grow the table to insert our initial values, and then also // Grow the table to insert our initial values, and then also
// set the 0th slot to `undefined` since that's what we've // set the 0th slot to `undefined` since that's what we've

View File

@ -11,10 +11,10 @@ use walrus::Module;
pub(crate) const PLACEHOLDER_MODULE: &str = "__wbindgen_placeholder__"; pub(crate) const PLACEHOLDER_MODULE: &str = "__wbindgen_placeholder__";
mod anyref;
mod decode; mod decode;
mod descriptor; mod descriptor;
mod descriptors; mod descriptors;
mod externref;
mod intrinsic; mod intrinsic;
mod js; mod js;
mod multivalue; mod multivalue;
@ -40,7 +40,7 @@ pub struct Bindgen {
// Support for the wasm threads proposal, transforms the wasm module to be // Support for the wasm threads proposal, transforms the wasm module to be
// "ready to be instantiated on any thread" // "ready to be instantiated on any thread"
threads: wasm_bindgen_threads_xform::Config, threads: wasm_bindgen_threads_xform::Config,
anyref: bool, externref: bool,
multi_value: bool, multi_value: bool,
wasm_interface_types: bool, wasm_interface_types: bool,
encode_into: EncodeInto, encode_into: EncodeInto,
@ -90,7 +90,8 @@ pub enum EncodeInto {
impl Bindgen { impl Bindgen {
pub fn new() -> 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 wasm_interface_types = env::var("WASM_INTERFACE_TYPES").is_ok();
let multi_value = env::var("WASM_BINDGEN_MULTI_VALUE").is_ok(); let multi_value = env::var("WASM_BINDGEN_MULTI_VALUE").is_ok();
Bindgen { Bindgen {
@ -109,7 +110,7 @@ impl Bindgen {
emit_start: true, emit_start: true,
weak_refs: env::var("WASM_BINDGEN_WEAKREF").is_ok(), weak_refs: env::var("WASM_BINDGEN_WEAKREF").is_ok(),
threads: threads_config(), threads: threads_config(),
anyref: anyref || wasm_interface_types, externref: externref || wasm_interface_types,
multi_value: multi_value || wasm_interface_types, multi_value: multi_value || wasm_interface_types,
wasm_interface_types, wasm_interface_types,
encode_into: EncodeInto::Test, encode_into: EncodeInto::Test,
@ -347,37 +348,37 @@ impl Bindgen {
// interface types. // interface types.
wit::process( wit::process(
&mut module, &mut module,
self.anyref, self.externref,
self.wasm_interface_types, self.wasm_interface_types,
self.emit_start, self.emit_start,
)?; )?;
// Now that we've got type information from the webidl processing pass, // Now that we've got type information from the webidl processing pass,
// touch up the output of rustc to insert anyref shims where necessary. // touch up the output of rustc to insert externref shims where necessary.
// This is only done if the anyref pass is enabled, which it's // This is only done if the externref pass is enabled, which it's
// currently off-by-default since `anyref` is still in development in // currently off-by-default since `externref` is still in development in
// engines. // engines.
// //
// If the anyref pass isn't necessary, then we blanket delete the // If the externref pass isn't necessary, then we blanket delete the
// export of all our anyref intrinsics which will get cleaned up in the // export of all our externref intrinsics which will get cleaned up in the
// GC pass before JS generation. // GC pass before JS generation.
if self.anyref { if self.externref {
anyref::process(&mut module)?; externref::process(&mut module)?;
} else { } else {
let ids = module let ids = module
.exports .exports
.iter() .iter()
.filter(|e| e.name.starts_with("__anyref")) .filter(|e| e.name.starts_with("__externref"))
.map(|e| e.id()) .map(|e| e.id())
.collect::<Vec<_>>(); .collect::<Vec<_>>();
for id in ids { for id in ids {
module.exports.delete(id); module.exports.delete(id);
} }
// Clean up element segments as well if they have holes in them // 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 // only support contiguous arrays of function references in element
// segments. // segments.
anyref::force_contiguous_elements(&mut module)?; externref::force_contiguous_elements(&mut module)?;
} }
// If wasm interface types are enabled then the `__wbindgen_throw` // If wasm interface types are enabled then the `__wbindgen_throw`

View File

@ -9,7 +9,7 @@ use walrus::Module;
/// ///
/// This pass is executed as part of the wasm interface types support. This is /// 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 /// 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 /// internally, when they fail, abort the instance. This abort is done through
/// the `__wbindgen_throw` intrinsic in debug mode to provide a hopefully /// the `__wbindgen_throw` intrinsic in debug mode to provide a hopefully
/// useful error message. In release mode it's simply an `unreachable` /// useful error message. In release mode it's simply an `unreachable`

View File

@ -60,24 +60,24 @@ impl InstructionBuilder<'_, '_> {
&[AdapterType::I32], &[AdapterType::I32],
); );
} }
Descriptor::Anyref => { Descriptor::Externref => {
self.instruction( self.instruction(
&[AdapterType::Anyref], &[AdapterType::Externref],
Instruction::I32FromAnyrefOwned, Instruction::I32FromExternrefOwned,
&[AdapterType::I32], &[AdapterType::I32],
); );
} }
Descriptor::NamedAnyref(name) => { Descriptor::NamedExternref(name) => {
self.instruction( self.instruction(
&[AdapterType::NamedAnyref(name.clone())], &[AdapterType::NamedExternref(name.clone())],
Instruction::I32FromAnyrefOwned, Instruction::I32FromExternrefOwned,
&[AdapterType::I32] &[AdapterType::I32]
) )
} }
Descriptor::RustStruct(class) => { Descriptor::RustStruct(class) => {
self.instruction( self.instruction(
&[AdapterType::Struct(class.clone())], &[AdapterType::Struct(class.clone())],
Instruction::I32FromAnyrefRustOwned { Instruction::I32FromExternrefRustOwned {
class: class.clone(), class: class.clone(),
}, },
&[AdapterType::I32], &[AdapterType::I32],
@ -155,23 +155,23 @@ impl InstructionBuilder<'_, '_> {
Descriptor::RustStruct(class) => { Descriptor::RustStruct(class) => {
self.instruction( self.instruction(
&[AdapterType::Struct(class.clone())], &[AdapterType::Struct(class.clone())],
Instruction::I32FromAnyrefRustBorrow { Instruction::I32FromExternrefRustBorrow {
class: class.clone(), class: class.clone(),
}, },
&[AdapterType::I32], &[AdapterType::I32],
); );
} }
Descriptor::Anyref => { Descriptor::Externref => {
self.instruction( self.instruction(
&[AdapterType::Anyref], &[AdapterType::Externref],
Instruction::I32FromAnyrefBorrow, Instruction::I32FromExternrefBorrow,
&[AdapterType::I32], &[AdapterType::I32],
); );
} }
Descriptor::NamedAnyref(name) => { Descriptor::NamedExternref(name) => {
self.instruction( self.instruction(
&[AdapterType::NamedAnyref(name.clone())], &[AdapterType::NamedExternref(name.clone())],
Instruction::I32FromAnyrefBorrow, Instruction::I32FromExternrefBorrow,
&[AdapterType::I32], &[AdapterType::I32],
); );
} }
@ -229,19 +229,19 @@ impl InstructionBuilder<'_, '_> {
fn incoming_option(&mut self, arg: &Descriptor) -> Result<(), Error> { fn incoming_option(&mut self, arg: &Descriptor) -> Result<(), Error> {
match arg { match arg {
Descriptor::Anyref => { Descriptor::Externref => {
self.instruction( self.instruction(
&[AdapterType::Anyref.option()], &[AdapterType::Externref.option()],
Instruction::I32FromOptionAnyref { Instruction::I32FromOptionExternref {
table_and_alloc: None, table_and_alloc: None,
}, },
&[AdapterType::I32], &[AdapterType::I32],
); );
} }
Descriptor::NamedAnyref(name) => { Descriptor::NamedExternref(name) => {
self.instruction( self.instruction(
&[AdapterType::NamedAnyref(name.clone()).option()], &[AdapterType::NamedExternref(name.clone()).option()],
Instruction::I32FromOptionAnyref { Instruction::I32FromOptionExternref {
table_and_alloc: None, table_and_alloc: None,
}, },
&[AdapterType::I32], &[AdapterType::I32],

View File

@ -28,7 +28,7 @@ struct Context<'a> {
vendor_prefixes: HashMap<String, Vec<String>>, vendor_prefixes: HashMap<String, Vec<String>>,
unique_crate_identifier: &'a str, unique_crate_identifier: &'a str,
descriptors: HashMap<String, Descriptor>, descriptors: HashMap<String, Descriptor>,
anyref_enabled: bool, externref_enabled: bool,
wasm_interface_types: bool, wasm_interface_types: bool,
support_start: bool, support_start: bool,
} }
@ -43,7 +43,7 @@ struct InstructionBuilder<'a, 'b> {
pub fn process( pub fn process(
module: &mut Module, module: &mut Module,
anyref_enabled: bool, externref_enabled: bool,
wasm_interface_types: bool, wasm_interface_types: bool,
support_start: bool, support_start: bool,
) -> Result<(NonstandardWitSectionId, WasmBindgenAuxId), Error> { ) -> Result<(NonstandardWitSectionId, WasmBindgenAuxId), Error> {
@ -61,7 +61,7 @@ pub fn process(
memory: wasm_bindgen_wasm_conventions::get_memory(module).ok(), memory: wasm_bindgen_wasm_conventions::get_memory(module).ok(),
module, module,
start_found: false, start_found: false,
anyref_enabled, externref_enabled,
wasm_interface_types, wasm_interface_types,
support_start, support_start,
}; };
@ -147,7 +147,7 @@ impl<'a> Context<'a> {
} }
self.handle_duplicate_imports(&duplicate_import_map); self.handle_duplicate_imports(&duplicate_import_map);
self.inject_anyref_initialization()?; self.inject_externref_initialization()?;
if let Some(custom) = self if let Some(custom) = self
.module .module
@ -187,7 +187,7 @@ impl<'a> Context<'a> {
let signature = Function { let signature = Function {
shim_idx: 0, shim_idx: 0,
arguments: vec![Descriptor::I32; 3], arguments: vec![Descriptor::I32; 3],
ret: Descriptor::Anyref, ret: Descriptor::Externref,
}; };
let id = self.import_adapter(id, signature, AdapterJsImportKind::Normal)?; let id = self.import_adapter(id, signature, AdapterJsImportKind::Normal)?;
// Synthesize the two integer pointers we pass through which // 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 // Ensure that the `start` function for this module calls the
// `__wbindgen_init_anyref_table` function. This'll ensure that all // `__wbindgen_init_externref_table` function. This'll ensure that all
// instances of this module have the initial slots of the anyref table // instances of this module have the initial slots of the externref table
// initialized correctly. // initialized correctly.
// //
// Note that this is disabled if WebAssembly interface types are enabled // Note that this is disabled if WebAssembly interface types are enabled
// since that's a slightly different environment for now which doesn't have // since that's a slightly different environment for now which doesn't have
// quite the same initialization. // quite the same initialization.
fn inject_anyref_initialization(&mut self) -> Result<(), Error> { fn inject_externref_initialization(&mut self) -> Result<(), Error> {
if !self.anyref_enabled || self.wasm_interface_types { if !self.externref_enabled || self.wasm_interface_types {
return Ok(()); return Ok(());
} }
let ty = self.module.types.add(&[], &[]); let ty = self.module.types.add(&[], &[]);
let (import, import_id) = let (import, import_id) =
self.module 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 { self.module.start = Some(match self.module.start {
Some(prev_start) => { Some(prev_start) => {
@ -309,7 +309,7 @@ impl<'a> Context<'a> {
} }
None => import, None => import,
}); });
self.bind_intrinsic(import_id, Intrinsic::InitAnyrefTable)?; self.bind_intrinsic(import_id, Intrinsic::InitExternrefTable)?;
Ok(()) Ok(())
} }
@ -481,8 +481,8 @@ impl<'a> Context<'a> {
// Note that we call the previous start function, if any, first. This is // 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 // because the start function currently only shows up when it's injected
// through thread/anyref transforms. These injected start functions need // through thread/externref transforms. These injected start functions
// to happen before user code, so we always schedule them first. // need to happen before user code, so we always schedule them first.
let mut builder = walrus::FunctionBuilder::new(&mut self.module.types, &[], &[]); let mut builder = walrus::FunctionBuilder::new(&mut self.module.types, &[], &[]);
builder.func_body().call(prev_start).call(id); builder.func_body().call(prev_start).call(id);
let new_start = builder.finish(Vec::new(), &mut self.module.funcs); let new_start = builder.finish(Vec::new(), &mut self.module.funcs);
@ -743,7 +743,7 @@ impl<'a> Context<'a> {
let id = self.import_adapter( let id = self.import_adapter(
import_id, import_id,
Function { Function {
arguments: vec![Descriptor::Ref(Box::new(Descriptor::Anyref))], arguments: vec![Descriptor::Ref(Box::new(Descriptor::Externref))],
shim_idx: 0, shim_idx: 0,
ret: Descriptor::Boolean, ret: Descriptor::Boolean,
}, },
@ -850,7 +850,7 @@ impl<'a> Context<'a> {
let signature = Function { let signature = Function {
shim_idx: 0, shim_idx: 0,
arguments: vec![Descriptor::I32], arguments: vec![Descriptor::I32],
ret: Descriptor::Anyref, ret: Descriptor::Externref,
}; };
let id = self.import_adapter(import_id, signature, AdapterJsImportKind::Normal)?; let id = self.import_adapter(import_id, signature, AdapterJsImportKind::Normal)?;
self.aux self.aux

View File

@ -47,12 +47,12 @@ pub struct WasmBindgenAux {
/// exported structs from Rust and their fields they've got exported. /// exported structs from Rust and their fields they've got exported.
pub structs: Vec<AuxStruct>, 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. /// 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 function_table: Option<walrus::TableId>,
pub anyref_alloc: Option<walrus::FunctionId>, pub externref_alloc: Option<walrus::FunctionId>,
pub anyref_drop_slice: Option<walrus::FunctionId>, pub externref_drop_slice: Option<walrus::FunctionId>,
/// Various intrinsics used for JS glue generation /// Various intrinsics used for JS glue generation
pub exn_store: Option<walrus::FunctionId>, 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 /// 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 /// the wasm module into the output expected JS module. All our functions here
/// currently take integer parameters and require a JS wrapper, but ideally /// 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 /// 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 /// 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. /// 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. /// function call is expected to always be the class.
ValueWithThis(JsImport, String), 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 /// returns a `bool`. It's expected that it tests if the argument is an
/// instance of (using `instanceof`) the name specified. /// instance of (using `instanceof`) the name specified.
/// ///
@ -290,7 +290,7 @@ pub enum AuxImport {
/// is one that is exported from the Rust/wasm. /// is one that is exported from the Rust/wasm.
/// ///
/// TODO: sort of like the export map below we should ideally create the /// 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. /// requiring an intrinsic here to do so.
WrapInExportedClass(String), WrapInExportedClass(String),
@ -371,16 +371,16 @@ impl walrus::CustomSection for WasmBindgenAux {
} }
fn add_gc_roots(&self, roots: &mut walrus::passes::Roots) { 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); roots.push_table(id);
} }
if let Some(id) = self.function_table { if let Some(id) = self.function_table {
roots.push_table(id); roots.push_table(id);
} }
if let Some(id) = self.anyref_alloc { if let Some(id) = self.externref_alloc {
roots.push_func(id); roots.push_func(id);
} }
if let Some(id) = self.anyref_drop_slice { if let Some(id) = self.externref_drop_slice {
roots.push_func(id); roots.push_func(id);
} }
if let Some(id) = self.exn_store { if let Some(id) = self.exn_store {

View File

@ -32,18 +32,18 @@ impl InstructionBuilder<'_, '_> {
&[AdapterType::Bool], &[AdapterType::Bool],
); );
} }
Descriptor::Anyref => { Descriptor::Externref => {
self.instruction( self.instruction(
&[AdapterType::I32], &[AdapterType::I32],
Instruction::AnyrefLoadOwned, Instruction::ExternrefLoadOwned,
&[AdapterType::Anyref], &[AdapterType::Externref],
); );
} }
Descriptor::NamedAnyref(name) => { Descriptor::NamedExternref(name) => {
self.instruction( self.instruction(
&[AdapterType::I32], &[AdapterType::I32],
Instruction::AnyrefLoadOwned, Instruction::ExternrefLoadOwned,
&[AdapterType::NamedAnyref(name.clone())], &[AdapterType::NamedExternref(name.clone())],
); );
} }
Descriptor::I8 => self.outgoing_i32(AdapterType::S8), Descriptor::I8 => self.outgoing_i32(AdapterType::S8),
@ -162,18 +162,18 @@ impl InstructionBuilder<'_, '_> {
fn outgoing_ref(&mut self, mutable: bool, arg: &Descriptor) -> Result<(), Error> { fn outgoing_ref(&mut self, mutable: bool, arg: &Descriptor) -> Result<(), Error> {
match arg { match arg {
Descriptor::Anyref => { Descriptor::Externref => {
self.instruction( self.instruction(
&[AdapterType::I32], &[AdapterType::I32],
Instruction::TableGet, Instruction::TableGet,
&[AdapterType::Anyref], &[AdapterType::Externref],
); );
} }
Descriptor::NamedAnyref(name) => { Descriptor::NamedExternref(name) => {
self.instruction( self.instruction(
&[AdapterType::I32], &[AdapterType::I32],
Instruction::TableGet, Instruction::TableGet,
&[AdapterType::NamedAnyref(name.clone())], &[AdapterType::NamedExternref(name.clone())],
); );
} }
Descriptor::CachedString => self.cached_string(false, false)?, Descriptor::CachedString => self.cached_string(false, false)?,
@ -232,20 +232,20 @@ impl InstructionBuilder<'_, '_> {
fn outgoing_option(&mut self, arg: &Descriptor) -> Result<(), Error> { fn outgoing_option(&mut self, arg: &Descriptor) -> Result<(), Error> {
match arg { match arg {
Descriptor::Anyref => { Descriptor::Externref => {
// This is set to `undefined` in the `None` case and otherwise // This is set to `undefined` in the `None` case and otherwise
// is the valid owned index. // is the valid owned index.
self.instruction( self.instruction(
&[AdapterType::I32], &[AdapterType::I32],
Instruction::AnyrefLoadOwned, Instruction::ExternrefLoadOwned,
&[AdapterType::Anyref.option()], &[AdapterType::Externref.option()],
); );
} }
Descriptor::NamedAnyref(name) => { Descriptor::NamedExternref(name) => {
self.instruction( self.instruction(
&[AdapterType::I32], &[AdapterType::I32],
Instruction::AnyrefLoadOwned, Instruction::ExternrefLoadOwned,
&[AdapterType::NamedAnyref(name.clone()).option()], &[AdapterType::NamedExternref(name.clone()).option()],
); );
} }
Descriptor::I8 => self.out_option_sentinel(AdapterType::S8), 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> { fn outgoing_option_ref(&mut self, _mutable: bool, arg: &Descriptor) -> Result<(), Error> {
match arg { match arg {
Descriptor::Anyref => { Descriptor::Externref => {
// If this is `Some` then it's the index, otherwise if it's // If this is `Some` then it's the index, otherwise if it's
// `None` then it's the index pointing to undefined. // `None` then it's the index pointing to undefined.
self.instruction( self.instruction(
&[AdapterType::I32], &[AdapterType::I32],
Instruction::TableGet, Instruction::TableGet,
&[AdapterType::Anyref.option()], &[AdapterType::Externref.option()],
); );
} }
Descriptor::NamedAnyref(name) => { Descriptor::NamedExternref(name) => {
self.instruction( self.instruction(
&[AdapterType::I32], &[AdapterType::I32],
Instruction::TableGet, Instruction::TableGet,
&[AdapterType::NamedAnyref(name.clone()).option()], &[AdapterType::NamedExternref(name.clone()).option()],
); );
} }
Descriptor::CachedString => self.cached_string(true, false)?, Descriptor::CachedString => self.cached_string(true, false)?,

View File

@ -45,9 +45,9 @@ pub fn add(module: &mut Module) -> Result<(), Error> {
structs, structs,
// irrelevant ids used to track various internal intrinsics and such // irrelevant ids used to track various internal intrinsics and such
anyref_table: _, externref_table: _,
anyref_alloc: _, externref_alloc: _,
anyref_drop_slice: _, externref_drop_slice: _,
exn_store: _, exn_store: _,
shadow_stack_pointer: _, shadow_stack_pointer: _,
function_table: _, function_table: _,
@ -243,17 +243,19 @@ fn translate_instruction(
I32FromStringFirstChar | StringFromChar => { I32FromStringFirstChar | StringFromChar => {
bail!("chars aren't supported in wasm interface types"); bail!("chars aren't supported in wasm interface types");
} }
I32FromAnyrefOwned | I32FromAnyrefBorrow | AnyrefLoadOwned | TableGet => { I32FromExternrefOwned | I32FromExternrefBorrow | ExternrefLoadOwned | TableGet => {
bail!("anyref pass failed to sink into wasm module"); 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"); bail!("rust types aren't supported in wasm interface types");
} }
I32Split64 { .. } | I64FromLoHi { .. } => { I32Split64 { .. } | I64FromLoHi { .. } => {
bail!("64-bit integers aren't supported in wasm-bindgen"); bail!("64-bit integers aren't supported in wasm-bindgen");
} }
I32SplitOption64 { .. } I32SplitOption64 { .. }
| I32FromOptionAnyref { .. } | I32FromOptionExternref { .. }
| I32FromOptionU32Sentinel | I32FromOptionU32Sentinel
| I32FromOptionRust { .. } | I32FromOptionRust { .. }
| I32FromOptionBool | I32FromOptionBool

View File

@ -55,7 +55,7 @@ pub enum StackChange {
#[derive(Debug, Copy, Clone, PartialEq)] #[derive(Debug, Copy, Clone, PartialEq)]
pub enum AdapterJsImportKind { 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 /// call
Method, Method,
/// The value imported should be invoked as `new` /// The value imported should be invoked as `new`
@ -77,14 +77,14 @@ pub enum AdapterType {
F32, F32,
F64, F64,
String, String,
Anyref, Externref,
Bool, Bool,
I32, I32,
I64, I64,
Vector(VectorKind), Vector(VectorKind),
Option(Box<AdapterType>), Option(Box<AdapterType>),
Struct(String), Struct(String),
NamedAnyref(String), NamedExternref(String),
Function, Function,
} }
@ -120,24 +120,24 @@ pub enum Instruction {
I32FromBool, I32FromBool,
/// Pops a `string` from the stack and pushes the first character as `i32` /// Pops a `string` from the stack and pushes the first character as `i32`
I32FromStringFirstChar, 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. /// returns the index it was stored at.
I32FromAnyrefOwned, I32FromExternrefOwned,
/// Pops an `anyref` from the stack, pushes it onto the anyref wasm table /// Pops an `externref` from the stack, pushes it onto the externref wasm table
/// stack, and returns the index it was stored at. /// stack, and returns the index it was stored at.
I32FromAnyrefBorrow, I32FromExternrefBorrow,
/// 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
/// deallocates the JS object and returns the i32 Rust pointer. /// deallocates the JS object and returns the i32 Rust pointer.
I32FromAnyrefRustOwned { I32FromExternrefRustOwned {
class: String, 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 /// passes the pointer to Rust which will be borrowed for the duration of a
/// call /// call
I32FromAnyrefRustBorrow { I32FromExternrefRustBorrow {
class: String, 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". /// consumed pointer value if it's "some".
I32FromOptionRust { I32FromOptionRust {
class: String, class: String,
@ -152,28 +152,28 @@ pub enum Instruction {
I32SplitOption64 { I32SplitOption64 {
signed: bool, 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" /// index into the owned wasm table it was stored at if it's "some"
I32FromOptionAnyref { I32FromOptionExternref {
/// Set to `Some` by the anyref pass of where to put it in the wasm /// Set to `Some` by the externref pass of where to put it in the wasm
/// module, otherwise it's shoved into the JS shim. /// module, otherwise it's shoved into the JS shim.
table_and_alloc: Option<(walrus::TableId, walrus::FunctionId)>, 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" /// "none" or the integer value of it if it's "some"
I32FromOptionU32Sentinel, 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)" /// "some(false)', and 2 for "some(true)"
I32FromOptionBool, 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" /// value if it's "some"
I32FromOptionChar, 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" /// value if it's "some"
I32FromOptionEnum { I32FromOptionEnum {
hole: u32, 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 /// 0/1 if it's none/some and second is `ty` value if it was there or 0 if
/// it wasn't there. /// it wasn't there.
FromOptionNative { FromOptionNative {
@ -208,7 +208,7 @@ pub enum Instruction {
realloc: Option<walrus::FunctionId>, realloc: Option<walrus::FunctionId>,
}, },
/// Pops an anyref, pushes pointer/length or all zeros /// Pops an externref, pushes pointer/length or all zeros
OptionVector { OptionVector {
kind: VectorKind, kind: VectorKind,
malloc: walrus::FunctionId, malloc: walrus::FunctionId,
@ -217,15 +217,15 @@ pub enum Instruction {
/// pops a `i32`, pushes `bool` /// pops a `i32`, pushes `bool`
BoolFromI32, BoolFromI32,
/// pops `i32`, loads anyref at that slot, dealloates anyref, pushes `anyref` /// pops `i32`, loads externref at that slot, dealloates externref, pushes `externref`
AnyrefLoadOwned, ExternrefLoadOwned,
/// pops `i32`, pushes string from that `char` /// pops `i32`, pushes string from that `char`
StringFromChar, StringFromChar,
/// pops two `i32`, pushes a 64-bit number /// pops two `i32`, pushes a 64-bit number
I64FromLoHi { I64FromLoHi {
signed: bool, signed: bool,
}, },
/// pops `i32`, pushes an anyref for the wrapped rust class /// pops `i32`, pushes an externref for the wrapped rust class
RustFromI32 { RustFromI32 {
class: String, class: String,
}, },
@ -251,9 +251,9 @@ pub enum Instruction {
mem: walrus::MemoryId, mem: walrus::MemoryId,
free: walrus::FunctionId, free: walrus::FunctionId,
}, },
/// pops i32, loads anyref from anyref table /// pops i32, loads externref from externref table
TableGet, TableGet,
/// pops two i32 data pointers, pushes an anyref closure /// pops two i32 data pointers, pushes an externref closure
StackClosure { StackClosure {
adapter: AdapterId, adapter: AdapterId,
nargs: usize, nargs: usize,
@ -271,7 +271,7 @@ pub enum Instruction {
}, },
/// pops i32, pushes it viewed as an optional value with a known sentinel /// pops i32, pushes it viewed as an optional value with a known sentinel
OptionU32Sentinel, OptionU32Sentinel,
/// pops an i32, then `ty`, then pushes anyref /// pops an i32, then `ty`, then pushes externref
ToOptionNative { ToOptionNative {
ty: walrus::ValType, ty: walrus::ValType,
signed: bool, signed: bool,
@ -300,7 +300,7 @@ impl AdapterType {
wit_walrus::ValType::F32 => AdapterType::F32, wit_walrus::ValType::F32 => AdapterType::F32,
wit_walrus::ValType::F64 => AdapterType::F64, wit_walrus::ValType::F64 => AdapterType::F64,
wit_walrus::ValType::String => AdapterType::String, 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::I32 => AdapterType::I32,
wit_walrus::ValType::I64 => AdapterType::I64, wit_walrus::ValType::I64 => AdapterType::I64,
} }
@ -312,10 +312,8 @@ impl AdapterType {
walrus::ValType::I64 => AdapterType::I64, walrus::ValType::I64 => AdapterType::I64,
walrus::ValType::F32 => AdapterType::F32, walrus::ValType::F32 => AdapterType::F32,
walrus::ValType::F64 => AdapterType::F64, walrus::ValType::F64 => AdapterType::F64,
walrus::ValType::Anyref => AdapterType::Anyref, walrus::ValType::Externref => AdapterType::Externref,
walrus::ValType::Funcref | walrus::ValType::Nullref | walrus::ValType::V128 => { walrus::ValType::Funcref | walrus::ValType::V128 => return None,
return None
}
}) })
} }
@ -325,7 +323,7 @@ impl AdapterType {
AdapterType::I64 => walrus::ValType::I64, AdapterType::I64 => walrus::ValType::I64,
AdapterType::F32 => walrus::ValType::F32, AdapterType::F32 => walrus::ValType::F32,
AdapterType::F64 => walrus::ValType::F64, AdapterType::F64 => walrus::ValType::F64,
AdapterType::Anyref | AdapterType::NamedAnyref(_) => walrus::ValType::Anyref, AdapterType::Externref | AdapterType::NamedExternref(_) => walrus::ValType::Externref,
_ => return None, _ => return None,
}) })
} }
@ -343,7 +341,9 @@ impl AdapterType {
AdapterType::F32 => wit_walrus::ValType::F32, AdapterType::F32 => wit_walrus::ValType::F32,
AdapterType::F64 => wit_walrus::ValType::F64, AdapterType::F64 => wit_walrus::ValType::F64,
AdapterType::String => wit_walrus::ValType::String, 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::I32 => wit_walrus::ValType::I32,
AdapterType::I64 => wit_walrus::ValType::I64, AdapterType::I64 => wit_walrus::ValType::I64,
@ -492,7 +492,7 @@ impl walrus::CustomSection for NonstandardWitSection {
roots.push_func(id); roots.push_func(id);
} }
} }
I32FromOptionAnyref { table_and_alloc } => { I32FromOptionExternref { table_and_alloc } => {
if let Some((table, alloc)) = table_and_alloc { if let Some((table, alloc)) = table_and_alloc {
roots.push_table(table); roots.push_table(table);
roots.push_func(alloc); roots.push_func(alloc);

View File

@ -24,7 +24,7 @@ rouille = { version = "3.0.0", default-features = false }
serde = { version = "1.0", features = ['derive'] } serde = { version = "1.0", features = ['derive'] }
serde_derive = "1.0" serde_derive = "1.0"
serde_json = "1.0" serde_json = "1.0"
walrus = { version = "0.16.0", features = ['parallel'] } walrus = { version = "0.17.0", features = ['parallel'] }
wasm-bindgen-cli-support = { path = "../cli-support", version = "=0.2.62" } wasm-bindgen-cli-support = { path = "../cli-support", version = "=0.2.62" }
wasm-bindgen-shared = { path = "../shared", version = "=0.2.62" } wasm-bindgen-shared = { path = "../shared", version = "=0.2.62" }
@ -34,11 +34,11 @@ diff = "0.1"
predicates = "1.0.0" predicates = "1.0.0"
rayon = "1.0" rayon = "1.0"
tempfile = "3.0" tempfile = "3.0"
walrus = "0.16" walrus = "0.17"
wit-printer = "0.1" wit-printer = "0.2"
wit-text = "0.6" wit-text = "0.7"
wit-validator = "0.1" wit-validator = "0.2"
wit-walrus = "0.2" wit-walrus = "0.4"
[[test]] [[test]]
name = "reference" name = "reference"

View File

@ -1,26 +1,26 @@
(module (module
(func $foo (param anyref) (result anyref) (func $foo (param externref) (result externref)
local.get 0) local.get 0)
(func $store (param anyref) (func $store (param externref)
i32.const 0 i32.const 0
local.get 0 local.get 0
table.set 0) table.set 0)
(func $load (result anyref) (func $load (result externref)
i32.const 0 i32.const 0
table.get 0) table.get 0)
(table 1 anyref) (table 1 externref)
(@interface func (export "foo") (param anyref) (result anyref) (@interface func (export "foo") (param externref) (result externref)
arg.get 0 arg.get 0
call-core $foo) call-core $foo)
(@interface func (export "store") (param anyref) (@interface func (export "store") (param externref)
arg.get 0 arg.get 0
call-core $store) call-core $store)
(@interface func (export "load") (result anyref) (@interface func (export "load") (result externref)
call-core $load) call-core $load)
) )

View File

@ -98,8 +98,8 @@ fn runtest(test: &Path) -> Result<()> {
.arg(td.path()) .arg(td.path())
.arg(&wasm) .arg(&wasm)
.arg("--no-typescript"); .arg("--no-typescript");
if contents.contains("// enable-anyref") { if contents.contains("// enable-externref") {
bindgen.env("WASM_BINDGEN_ANYREF", "1"); bindgen.env("WASM_BINDGEN_EXTERNREF", "1");
} }
if interface_types { if interface_types {
bindgen.env("WASM_INTERFACE_TYPES", "1"); bindgen.env("WASM_INTERFACE_TYPES", "1");

View File

@ -1,6 +1,6 @@
import * as wasm from './reference_test_bg.wasm'; import * as wasm from './reference_test_bg.wasm';
export const __wbindgen_init_anyref_table = function() { export const __wbindgen_init_externref_table = function() {
const table = wasm.__wbindgen_export_0; const table = wasm.__wbindgen_export_0;
const offset = table.grow(4); const offset = table.grow(4);
table.set(0, undefined); table.set(0, undefined);

View File

@ -1 +1 @@
// enable-anyref // enable-externref

View File

@ -1,6 +1,6 @@
(module (module
(type (;0;) (func)) (type (;0;) (func))
(import "./reference_test_bg.js" "__wbindgen_init_anyref_table" (func (;0;) (type 0))) (import "./reference_test_bg.js" "__wbindgen_init_externref_table" (func (;0;) (type 0)))
(table (;0;) 32 externref) (table (;0;) 32 externref)
(memory (;0;) 16) (memory (;0;) 16)
(export "memory" (memory 0)) (export "memory" (memory 0))

View File

@ -18,8 +18,8 @@ function getStringFromWasm0(ptr, len) {
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len)); return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
} }
function addToAnyrefTable0(obj) { function addToExternrefTable0(obj) {
const idx = wasm.__anyref_table_alloc(); const idx = wasm.__externref_table_alloc();
wasm.__wbindgen_export_0.set(idx, obj); wasm.__wbindgen_export_0.set(idx, obj);
return idx; return idx;
} }
@ -30,7 +30,7 @@ function handleError(f) {
return f.apply(this, arguments); return f.apply(this, arguments);
} catch (e) { } catch (e) {
const idx = addToAnyrefTable0(e); const idx = addToExternrefTable0(e);
wasm.__wbindgen_exn_store(idx); wasm.__wbindgen_exn_store(idx);
} }
}; };
@ -53,7 +53,7 @@ export const __wbindgen_rethrow = function(arg0) {
throw arg0; throw arg0;
}; };
export const __wbindgen_init_anyref_table = function() { export const __wbindgen_init_externref_table = function() {
const table = wasm.__wbindgen_export_0; const table = wasm.__wbindgen_export_0;
const offset = table.grow(4); const offset = table.grow(4);
table.set(0, undefined); table.set(0, undefined);

View File

@ -1,4 +1,4 @@
// enable-anyref // enable-externref
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;

View File

@ -2,9 +2,9 @@
(type (;0;) (func)) (type (;0;) (func))
(type (;1;) (func (result i32))) (type (;1;) (func (result i32)))
(type (;2;) (func (param i32))) (type (;2;) (func (param i32)))
(import "./reference_test_bg.js" "__wbindgen_init_anyref_table" (func (;0;) (type 0))) (import "./reference_test_bg.js" "__wbindgen_init_externref_table" (func (;0;) (type 0)))
(func $__wbindgen_exn_store (type 2) (param i32)) (func $__wbindgen_exn_store (type 2) (param i32))
(func $__anyref_table_alloc (type 1) (result i32)) (func $__externref_table_alloc (type 1) (result i32))
(func $exported (type 0)) (func $exported (type 0))
(table (;0;) 32 externref) (table (;0;) 32 externref)
(memory (;0;) 17) (memory (;0;) 17)
@ -12,5 +12,5 @@
(export "exported" (func $exported)) (export "exported" (func $exported))
(export "__wbindgen_export_0" (table 0)) (export "__wbindgen_export_0" (table 0))
(export "__wbindgen_exn_store" (func $__wbindgen_exn_store)) (export "__wbindgen_exn_store" (func $__wbindgen_exn_store))
(export "__anyref_table_alloc" (func $__anyref_table_alloc)) (export "__externref_table_alloc" (func $__externref_table_alloc))
(export "__wbindgen_start" (func 0))) (export "__wbindgen_start" (func 0)))

View File

@ -6,7 +6,7 @@ export function foo() {
wasm.foo(); wasm.foo();
} }
export const __wbindgen_init_anyref_table = function() { export const __wbindgen_init_externref_table = function() {
const table = wasm.__wbindgen_export_0; const table = wasm.__wbindgen_export_0;
const offset = table.grow(4); const offset = table.grow(4);
table.set(0, undefined); table.set(0, undefined);

View File

@ -1,4 +1,4 @@
// enable-anyref // enable-externref
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;

View File

@ -1,6 +1,6 @@
(module (module
(type (;0;) (func)) (type (;0;) (func))
(import "./reference_test_bg.js" "__wbindgen_init_anyref_table" (func (;0;) (type 0))) (import "./reference_test_bg.js" "__wbindgen_init_externref_table" (func (;0;) (type 0)))
(func $foo (type 0)) (func $foo (type 0))
(table (;0;) 32 externref) (table (;0;) 32 externref)
(memory (;0;) 17) (memory (;0;) 17)

View File

@ -3,6 +3,6 @@
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen] #[wasm_bindgen]
pub fn anyref_in_out(a: &JsValue, b: JsValue) -> JsValue { pub fn externref_in_out(a: &JsValue, b: JsValue) -> JsValue {
b b
} }

View File

@ -1,12 +1,12 @@
(module (module
(type (;0;) (func (param externref externref) (result externref))) (type (;0;) (func (param externref externref) (result externref)))
(func $anyref_in_out anyref shim (type 0) (param externref externref) (result externref)) (func $externref_in_out externref shim (type 0) (param externref externref) (result externref))
(memory (;0;) 17) (memory (;0;) 17)
(export "memory" (memory 0)) (export "memory" (memory 0))
(export "anyref_in_out" (func $anyref_in_out anyref shim)) (export "externref_in_out" (func $externref_in_out externref shim))
(@interface type (;0;) (func (param anyref) (param anyref) (result anyref))) (@interface type (;0;) (func (param externref) (param externref) (result externref)))
(@interface func (;0;) (type 0) (@interface func (;0;) (type 0)
arg.get 0 arg.get 0
arg.get 1 arg.get 1
call-core $anyref_in_out anyref shim) call-core $externref_in_out externref shim)
(@interface export "anyref_in_out" (func 0))) (@interface export "externref_in_out" (func 0)))

View File

@ -1,24 +1,24 @@
[package] [package]
name = "wasm-bindgen-anyref-xform" name = "wasm-bindgen-externref-xform"
version = "0.2.62" version = "0.2.62"
authors = ["The wasm-bindgen Developers"] authors = ["The wasm-bindgen Developers"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
repository = "https://github.com/rustwasm/wasm-bindgen/tree/master/crates/anyref-xform" repository = "https://github.com/rustwasm/wasm-bindgen/tree/master/crates/externref-xform"
homepage = "https://rustwasm.github.io/wasm-bindgen/" homepage = "https://rustwasm.github.io/wasm-bindgen/"
documentation = "https://docs.rs/wasm-bindgen-anyref-xform" documentation = "https://docs.rs/wasm-bindgen-externref-xform"
description = """ description = """
Internal anyref transformations for wasm-bindgen Internal externref transformations for wasm-bindgen
""" """
edition = '2018' edition = '2018'
[dependencies] [dependencies]
anyhow = "1.0" anyhow = "1.0"
walrus = "0.16.0" walrus = "0.17.0"
[dev-dependencies] [dev-dependencies]
rayon = "1.0" rayon = "1.0"
wasmprinter = "0.2" wasmprinter = "0.2"
wast = "3.0" wast = "17.0"
wat = "1.0" wat = "1.0"
[[test]] [[test]]

View File

@ -1,11 +1,11 @@
//! Transformation for wasm-bindgen to enable usage of `anyref` in a wasm //! Transformation for wasm-bindgen to enable usage of `externref` in a wasm
//! module. //! module.
//! //!
//! This crate is in charge of enabling code using `wasm-bindgen` to use the //! This crate is in charge of enabling code using `wasm-bindgen` to use the
//! `anyref` type inside of the wasm module. This transformation pass primarily //! `externref` type inside of the wasm module. This transformation pass primarily
//! wraps exports and imports in shims which use `anyref`, but quickly turn them //! wraps exports and imports in shims which use `externref`, but quickly turn them
//! into `i32` value types. This is all largely a stopgap until Rust has //! into `i32` value types. This is all largely a stopgap until Rust has
//! first-class support for the `anyref` type, but that's thought to be in the //! first-class support for the `externref` type, but that's thought to be in the
//! far future and will take quite some time to implement. In the meantime, we //! far future and will take quite some time to implement. In the meantime, we
//! have this! //! have this!
//! //!
@ -13,7 +13,7 @@
//! about imports and exports. Afterwards this pass runs in one go against a //! about imports and exports. Afterwards this pass runs in one go against a
//! wasm module, updating exports, imports, calls to these functions, etc. The //! wasm module, updating exports, imports, calls to these functions, etc. The
//! goal at least is to have valid wasm modules coming in that don't use //! goal at least is to have valid wasm modules coming in that don't use
//! `anyref` and valid wasm modules going out which use `anyref` at the fringes. //! `externref` and valid wasm modules going out which use `externref` at the fringes.
use anyhow::{anyhow, bail, Error}; use anyhow::{anyhow, bail, Error};
use std::cmp; use std::cmp;
@ -23,16 +23,16 @@ use walrus::ir::*;
use walrus::{ElementId, ExportId, ImportId, InstrLocId, TypeId}; use walrus::{ElementId, ExportId, ImportId, InstrLocId, TypeId};
use walrus::{FunctionId, GlobalId, InitExpr, Module, TableId, ValType}; use walrus::{FunctionId, GlobalId, InitExpr, Module, TableId, ValType};
// must be kept in sync with src/lib.rs and ANYREF_HEAP_START // must be kept in sync with src/lib.rs and EXTERNREF_HEAP_START
const DEFAULT_MIN: u32 = 32; const DEFAULT_MIN: u32 = 32;
/// State of the anyref pass, used to collect information while bindings are /// State of the externref pass, used to collect information while bindings are
/// generated and used eventually to actually execute the entire pass. /// generated and used eventually to actually execute the entire pass.
#[derive(Default)] #[derive(Default)]
pub struct Context { pub struct Context {
// Functions within the module that we're gonna be wrapping, organized by // Functions within the module that we're gonna be wrapping, organized by
// type. The `Function` contains information about what arguments/return // type. The `Function` contains information about what arguments/return
// values in the function signature should turn into anyref. // values in the function signature should turn into externref.
imports: HashMap<ImportId, Function>, imports: HashMap<ImportId, Function>,
exports: HashMap<ExportId, Function>, exports: HashMap<ExportId, Function>,
@ -49,7 +49,7 @@ pub struct Context {
// final offset plus the element segment used to initialized that range. // final offset plus the element segment used to initialized that range.
elements: BTreeMap<u32, ElementId>, elements: BTreeMap<u32, ElementId>,
// The anyref table we'll be using, injected after construction // The externref table we'll be using, injected after construction
table: Option<TableId>, table: Option<TableId>,
} }
@ -81,10 +81,10 @@ struct Transform<'a> {
} }
struct Function { struct Function {
// A map of argument index to whether it's an owned or borrowed anyref // A map of argument index to whether it's an owned or borrowed externref
// (owned = true) // (owned = true)
args: HashMap<usize, bool>, args: HashMap<usize, bool>,
ret_anyref: bool, ret_externref: bool,
} }
enum Intrinsic { enum Intrinsic {
@ -120,9 +120,13 @@ impl Context {
} }
} }
// Add in an anyref table to the module, which we'll be using for // Add in an externref table to the module, which we'll be using for
// our transform below. // our transform below.
self.table = Some(module.tables.add_local(DEFAULT_MIN, None, ValType::Anyref)); self.table = Some(
module
.tables
.add_local(DEFAULT_MIN, None, ValType::Externref),
);
Ok(()) Ok(())
} }
@ -132,10 +136,10 @@ impl Context {
pub fn import_xform( pub fn import_xform(
&mut self, &mut self,
id: ImportId, id: ImportId,
anyref: &[(usize, bool)], externref: &[(usize, bool)],
ret_anyref: bool, ret_externref: bool,
) -> &mut Self { ) -> &mut Self {
if let Some(f) = self.function(anyref, ret_anyref) { if let Some(f) = self.function(externref, ret_externref) {
self.imports.insert(id, f); self.imports.insert(id, f);
} }
self self
@ -146,10 +150,10 @@ impl Context {
pub fn export_xform( pub fn export_xform(
&mut self, &mut self,
id: ExportId, id: ExportId,
anyref: &[(usize, bool)], externref: &[(usize, bool)],
ret_anyref: bool, ret_externref: bool,
) -> &mut Self { ) -> &mut Self {
if let Some(f) = self.function(anyref, ret_anyref) { if let Some(f) = self.function(externref, ret_externref) {
self.exports.insert(id, f); self.exports.insert(id, f);
} }
self self
@ -161,22 +165,22 @@ impl Context {
pub fn table_element_xform( pub fn table_element_xform(
&mut self, &mut self,
idx: u32, idx: u32,
anyref: &[(usize, bool)], externref: &[(usize, bool)],
ret_anyref: bool, ret_externref: bool,
) -> Option<u32> { ) -> Option<u32> {
self.function(anyref, ret_anyref).map(|f| { self.function(externref, ret_externref).map(|f| {
self.new_elements.push((idx, f)); self.new_elements.push((idx, f));
self.new_elements.len() as u32 + self.new_element_offset - 1 self.new_elements.len() as u32 + self.new_element_offset - 1
}) })
} }
fn function(&self, anyref: &[(usize, bool)], ret_anyref: bool) -> Option<Function> { fn function(&self, externref: &[(usize, bool)], ret_externref: bool) -> Option<Function> {
if !ret_anyref && anyref.len() == 0 { if !ret_externref && externref.len() == 0 {
return None; return None;
} }
Some(Function { Some(Function {
args: anyref.iter().cloned().collect(), args: externref.iter().cloned().collect(),
ret_anyref, ret_externref,
}) })
} }
@ -184,7 +188,7 @@ impl Context {
let table = self.table.unwrap(); let table = self.table.unwrap();
// Inject a stack pointer global which will be used for managing the // Inject a stack pointer global which will be used for managing the
// stack on the anyref table. // stack on the externref table.
let init = InitExpr::Value(Value::I32(DEFAULT_MIN as i32)); let init = InitExpr::Value(Value::I32(DEFAULT_MIN as i32));
let stack_pointer = module.globals.add_local(ValType::I32, true, init); let stack_pointer = module.globals.add_local(ValType::I32, true, init);
@ -202,10 +206,10 @@ impl Context {
_ => continue, _ => continue,
}; };
match export.name.as_str() { match export.name.as_str() {
"__anyref_table_alloc" => heap_alloc = Some(f), "__externref_table_alloc" => heap_alloc = Some(f),
"__anyref_table_dealloc" => heap_dealloc = Some(f), "__externref_table_dealloc" => heap_dealloc = Some(f),
"__anyref_drop_slice" => drop_slice = Some(f), "__externref_drop_slice" => drop_slice = Some(f),
"__anyref_heap_live_count" => live_count = Some(f), "__externref_heap_live_count" => live_count = Some(f),
_ => continue, _ => continue,
} }
to_delete.push(export.id()); to_delete.push(export.id());
@ -268,7 +272,7 @@ impl Context {
impl Transform<'_> { impl Transform<'_> {
fn run(&mut self, module: &mut Module) -> Result<(), Error> { fn run(&mut self, module: &mut Module) -> Result<(), Error> {
// Detect all the various intrinsics and such. This will also along the // Detect all the various intrinsics and such. This will also along the
// way inject an intrinsic for cloning an anyref. // way inject an intrinsic for cloning an externref.
self.find_intrinsics(module)?; self.find_intrinsics(module)?;
// Perform transformations of imports, exports, and function pointers. // Perform transformations of imports, exports, and function pointers.
@ -300,12 +304,12 @@ impl Transform<'_> {
walrus::ImportKind::Function(f) => f, walrus::ImportKind::Function(f) => f,
_ => continue, _ => continue,
}; };
if import.module == "__wbindgen_anyref_xform__" { if import.module == "__wbindgen_externref_xform__" {
match import.name.as_str() { match import.name.as_str() {
"__wbindgen_anyref_table_grow" => { "__wbindgen_externref_table_grow" => {
self.intrinsic_map.insert(f, Intrinsic::TableGrow); self.intrinsic_map.insert(f, Intrinsic::TableGrow);
} }
"__wbindgen_anyref_table_set_null" => { "__wbindgen_externref_table_set_null" => {
self.intrinsic_map.insert(f, Intrinsic::TableSetNull); self.intrinsic_map.insert(f, Intrinsic::TableSetNull);
} }
n => bail!("unknown intrinsic: {}", n), n => bail!("unknown intrinsic: {}", n),
@ -334,8 +338,9 @@ impl Transform<'_> {
} }
fn heap_alloc(&self) -> Result<FunctionId, Error> { fn heap_alloc(&self) -> Result<FunctionId, Error> {
self.heap_alloc self.heap_alloc.ok_or_else(|| {
.ok_or_else(|| anyhow!("failed to find the `__wbindgen_anyref_table_alloc` function")) anyhow!("failed to find the `__wbindgen_externref_table_alloc` function")
})
} }
fn clone_ref(&self) -> Result<FunctionId, Error> { fn clone_ref(&self) -> Result<FunctionId, Error> {
@ -344,8 +349,9 @@ impl Transform<'_> {
} }
fn heap_dealloc(&self) -> Result<FunctionId, Error> { fn heap_dealloc(&self) -> Result<FunctionId, Error> {
self.heap_dealloc self.heap_dealloc.ok_or_else(|| {
.ok_or_else(|| anyhow!("failed to find the `__wbindgen_anyref_table_dealloc` function")) anyhow!("failed to find the `__wbindgen_externref_table_dealloc` function")
})
} }
fn process_imports(&mut self, module: &mut Module) -> Result<(), Error> { fn process_imports(&mut self, module: &mut Module) -> Result<(), Error> {
@ -359,7 +365,7 @@ impl Transform<'_> {
None => continue, None => continue,
}; };
let (shim, anyref_ty) = self.append_shim( let (shim, externref_ty) = self.append_shim(
f, f,
&import.name, &import.name,
func, func,
@ -369,7 +375,7 @@ impl Transform<'_> {
)?; )?;
self.import_map.insert(f, shim); self.import_map.insert(f, shim);
match &mut module.funcs.get_mut(f).kind { match &mut module.funcs.get_mut(f).kind {
walrus::FunctionKind::Import(f) => f.ty = anyref_ty, walrus::FunctionKind::Import(f) => f.ty = externref_ty,
_ => unreachable!(), _ => unreachable!(),
} }
} }
@ -387,7 +393,7 @@ impl Transform<'_> {
Some(s) => s, Some(s) => s,
None => continue, None => continue,
}; };
let (shim, _anyref_ty) = self.append_shim( let (shim, _externref_ty) = self.append_shim(
f, f,
&export.name, &export.name,
function, function,
@ -420,7 +426,7 @@ impl Transform<'_> {
let target = module.elements.get(orig_element).members[(idx - offset) as usize].ok_or( let target = module.elements.get(orig_element).members[(idx - offset) as usize].ok_or(
anyhow!("function index {} not present in element segment", idx), anyhow!("function index {} not present in element segment", idx),
)?; )?;
let (shim, _anyref_ty) = self.append_shim( let (shim, _externref_ty) = self.append_shim(
target, target,
&format!("closure{}", idx), &format!("closure{}", idx),
function, function,
@ -477,24 +483,24 @@ impl Transform<'_> {
} }
let mut param_tys = Vec::new(); let mut param_tys = Vec::new();
let mut param_convert = Vec::new(); let mut param_convert = Vec::new();
let mut anyref_stack = 0; let mut externref_stack = 0;
for (i, old_ty) in target_ty.params().iter().enumerate() { for (i, old_ty) in target_ty.params().iter().enumerate() {
let is_owned = func.args.remove(&i); let is_owned = func.args.remove(&i);
let new_ty = is_owned let new_ty = is_owned
.map(|_which| ValType::Anyref) .map(|_which| ValType::Externref)
.unwrap_or(old_ty.clone()); .unwrap_or(old_ty.clone());
param_tys.push(new_ty.clone()); param_tys.push(new_ty.clone());
if new_ty == *old_ty { if new_ty == *old_ty {
param_convert.push(Convert::None); param_convert.push(Convert::None);
} else if is_export { } else if is_export {
// We're calling an export, so we need to push this anyref into // We're calling an export, so we need to push this externref into
// a table somehow. // a table somehow.
param_convert.push(Convert::Store { param_convert.push(Convert::Store {
owned: is_owned.unwrap(), owned: is_owned.unwrap(),
}); });
if is_owned == Some(false) { if is_owned == Some(false) {
anyref_stack += 1; externref_stack += 1;
} }
} else { } else {
// We're calling an import, so we just need to fetch our table // We're calling an import, so we just need to fetch our table
@ -505,21 +511,21 @@ impl Transform<'_> {
} }
} }
let new_ret = if func.ret_anyref { let new_ret = if func.ret_externref {
assert_eq!(target_ty.results(), &[ValType::I32]); assert_eq!(target_ty.results(), &[ValType::I32]);
vec![ValType::Anyref] vec![ValType::Externref]
} else { } else {
target_ty.results().to_vec() target_ty.results().to_vec()
}; };
let anyref_ty = types.add(&param_tys, &new_ret); let externref_ty = types.add(&param_tys, &new_ret);
// If we're an export then our shim is what's actually going to get // If we're an export then our shim is what's actually going to get
// exported, and it's going to have the anyref signature. // exported, and it's going to have the externref signature.
// //
// If we're an import, then our shim is what the Rust code calls, which // If we're an import, then our shim is what the Rust code calls, which
// means it'll have the original signature. The existing import's // means it'll have the original signature. The existing import's
// signature, however, is transformed to be an anyref signature. // signature, however, is transformed to be an externref signature.
let shim_ty = if is_export { anyref_ty } else { ty }; let shim_ty = if is_export { externref_ty } else { ty };
let mut builder = walrus::FunctionBuilder::new( let mut builder = walrus::FunctionBuilder::new(
types, types,
@ -547,12 +553,12 @@ impl Transform<'_> {
// gc passes if we don't actually end up using them. // gc passes if we don't actually end up using them.
let fp = locals.add(ValType::I32); let fp = locals.add(ValType::I32);
let scratch_i32 = locals.add(ValType::I32); let scratch_i32 = locals.add(ValType::I32);
let scratch_anyref = locals.add(ValType::Anyref); let scratch_externref = locals.add(ValType::Externref);
// Update our stack pointer if there's any borrowed anyref objects. // Update our stack pointer if there's any borrowed externref objects.
if anyref_stack > 0 { if externref_stack > 0 {
body.global_get(self.stack_pointer) body.global_get(self.stack_pointer)
.const_(Value::I32(anyref_stack)) .const_(Value::I32(externref_stack))
.binop(BinaryOp::I32Sub) .binop(BinaryOp::I32Sub)
.local_tee(fp) .local_tee(fp)
.global_set(self.stack_pointer); .global_set(self.stack_pointer);
@ -565,8 +571,8 @@ impl Transform<'_> {
body.local_get(params[i]); body.local_get(params[i]);
} }
Convert::Load { owned: true } => { Convert::Load { owned: true } => {
// load the anyref onto the stack, then afterwards // load the externref onto the stack, then afterwards
// deallocate our index, leaving the anyref on the stack. // deallocate our index, leaving the externref on the stack.
body.local_get(params[i]) body.local_get(params[i])
.table_get(self.table) .table_get(self.table)
.local_get(params[i]) .local_get(params[i])
@ -576,8 +582,8 @@ impl Transform<'_> {
body.local_get(params[i]).table_get(self.table); body.local_get(params[i]).table_get(self.table);
} }
Convert::Store { owned: true } => { Convert::Store { owned: true } => {
// Allocate space for the anyref, store it, and then leave // Allocate space for the externref, store it, and then leave
// the index of the allocated anyref on the stack. // the index of the allocated externref on the stack.
body.call(self.heap_alloc()?) body.call(self.heap_alloc()?)
.local_tee(scratch_i32) .local_tee(scratch_i32)
.local_get(params[i]) .local_get(params[i])
@ -585,7 +591,7 @@ impl Transform<'_> {
.local_get(scratch_i32); .local_get(scratch_i32);
} }
Convert::Store { owned: false } => { Convert::Store { owned: false } => {
// Store an anyref at an offset from our function's stack // Store an externref at an offset from our function's stack
// pointer frame. // pointer frame.
body.local_get(fp); body.local_get(fp);
let idx_local = if next_stack_offset == 0 { let idx_local = if next_stack_offset == 0 {
@ -609,33 +615,33 @@ impl Transform<'_> {
// wrapping. // wrapping.
body.call(shim_target); body.call(shim_target);
// If an anyref value is returned, then we need to be sure to apply // If an externref value is returned, then we need to be sure to apply
// special treatment to convert it to an i32 as well. Note that only // special treatment to convert it to an i32 as well. Note that only
// owned anyref values can be returned, so that's all that's handled // owned externref values can be returned, so that's all that's handled
// here. // here.
if func.ret_anyref { if func.ret_externref {
if is_export { if is_export {
// We're an export so we have an i32 on the stack and need to // We're an export so we have an i32 on the stack and need to
// convert it to an anyref, basically by doing the same as an // convert it to an externref, basically by doing the same as an
// owned load above: get the value then deallocate our slot. // owned load above: get the value then deallocate our slot.
body.local_tee(scratch_i32) body.local_tee(scratch_i32)
.table_get(self.table) .table_get(self.table)
.local_get(scratch_i32) .local_get(scratch_i32)
.call(self.heap_dealloc()?); .call(self.heap_dealloc()?);
} else { } else {
// Imports are the opposite, we have any anyref on the stack // Imports are the opposite, we have any externref on the stack
// and convert it to an i32 by allocating space for it and // and convert it to an i32 by allocating space for it and
// storing it there. // storing it there.
body.local_set(scratch_anyref) body.local_set(scratch_externref)
.call(self.heap_alloc()?) .call(self.heap_alloc()?)
.local_tee(scratch_i32) .local_tee(scratch_i32)
.local_get(scratch_anyref) .local_get(scratch_externref)
.table_set(self.table) .table_set(self.table)
.local_get(scratch_i32); .local_get(scratch_i32);
} }
} }
// On function exit restore our anyref stack pointer if we decremented // On function exit restore our externref stack pointer if we decremented
// it to start off. // it to start off.
// //
// Note that we pave over all our stack slots with `ref.null` to ensure // Note that we pave over all our stack slots with `ref.null` to ensure
@ -643,18 +649,18 @@ impl Transform<'_> {
// no longer in use by our wasm instance. // no longer in use by our wasm instance.
// //
// TODO: use `table.fill` once that's spec'd // TODO: use `table.fill` once that's spec'd
if anyref_stack > 0 { if externref_stack > 0 {
for i in 0..anyref_stack { for i in 0..externref_stack {
body.local_get(fp); body.local_get(fp);
if i > 0 { if i > 0 {
body.i32_const(i).binop(BinaryOp::I32Add); body.i32_const(i).binop(BinaryOp::I32Add);
} }
body.ref_null(); body.ref_null(ValType::Externref);
body.table_set(self.table); body.table_set(self.table);
} }
body.local_get(fp) body.local_get(fp)
.i32_const(anyref_stack) .i32_const(externref_stack)
.binop(BinaryOp::I32Add) .binop(BinaryOp::I32Add)
.global_set(self.stack_pointer); .global_set(self.stack_pointer);
} }
@ -663,10 +669,10 @@ impl Transform<'_> {
// with a fresh type we've been calculating so far. Give the function a // with a fresh type we've been calculating so far. Give the function a
// nice name for debugging and then we're good to go! // nice name for debugging and then we're good to go!
let id = builder.finish(params, funcs); let id = builder.finish(params, funcs);
let name = format!("{} anyref shim", name); let name = format!("{} externref shim", name);
funcs.get_mut(id).name = Some(name); funcs.get_mut(id).name = Some(name);
self.shims.insert(id); self.shims.insert(id);
Ok((id, anyref_ty)) Ok((id, externref_ty))
} }
fn rewrite_calls(&mut self, module: &mut Module) -> Result<(), Error> { fn rewrite_calls(&mut self, module: &mut Module) -> Result<(), Error> {
@ -714,6 +720,7 @@ impl Transform<'_> {
} }
}; };
let ty = ValType::Externref;
match intrinsic { match intrinsic {
Intrinsic::TableGrow => { Intrinsic::TableGrow => {
// Switch this to a `table.grow` instruction... // Switch this to a `table.grow` instruction...
@ -725,7 +732,7 @@ impl Transform<'_> {
// preceding instruction as the value to grow the // preceding instruction as the value to grow the
// table with. // table with.
seq.instrs seq.instrs
.insert(i - 1, (RefNull {}.into(), InstrLocId::default())); .insert(i - 1, (RefNull { ty }.into(), InstrLocId::default()));
} }
Intrinsic::TableSetNull => { Intrinsic::TableSetNull => {
// Switch this to a `table.set` instruction... // Switch this to a `table.set` instruction...
@ -736,7 +743,7 @@ impl Transform<'_> {
// ... and then insert a `ref.null` as the // ... and then insert a `ref.null` as the
// preceding instruction // preceding instruction
seq.instrs seq.instrs
.insert(i, (RefNull {}.into(), InstrLocId::default())); .insert(i, (RefNull { ty }.into(), InstrLocId::default()));
} }
Intrinsic::DropRef => call.func = self.heap_dealloc, Intrinsic::DropRef => call.func = self.heap_dealloc,
Intrinsic::CloneRef => call.func = self.clone_ref, Intrinsic::CloneRef => call.func = self.clone_ref,

View File

@ -20,7 +20,7 @@ fn main() {
fn runtest(test: &Test) -> Result<String> { fn runtest(test: &Test) -> Result<String> {
let wasm = wat::parse_file(&test.file)?; let wasm = wat::parse_file(&test.file)?;
let mut walrus = walrus::Module::from_buffer(&wasm)?; let mut walrus = walrus::Module::from_buffer(&wasm)?;
let mut cx = wasm_bindgen_anyref_xform::Context::default(); let mut cx = wasm_bindgen_externref_xform::Context::default();
cx.prepare(&mut walrus)?; cx.prepare(&mut walrus)?;
for directive in test.directives.iter() { for directive in test.directives.iter() {
match &directive.kind { match &directive.kind {
@ -30,7 +30,7 @@ fn runtest(test: &Test) -> Result<String> {
.iter() .iter()
.find(|e| e.name == *name) .find(|e| e.name == *name)
.ok_or_else(|| anyhow!("failed to find export"))?; .ok_or_else(|| anyhow!("failed to find export"))?;
cx.export_xform(export.id(), &directive.args, directive.ret_anyref); cx.export_xform(export.id(), &directive.args, directive.ret_externref);
} }
DirectiveKind::Import(module, field) => { DirectiveKind::Import(module, field) => {
let import = walrus let import = walrus
@ -38,10 +38,10 @@ fn runtest(test: &Test) -> Result<String> {
.iter() .iter()
.find(|e| e.module == *module && e.name == *field) .find(|e| e.module == *module && e.name == *field)
.ok_or_else(|| anyhow!("failed to find export"))?; .ok_or_else(|| anyhow!("failed to find export"))?;
cx.import_xform(import.id(), &directive.args, directive.ret_anyref); cx.import_xform(import.id(), &directive.args, directive.ret_externref);
} }
DirectiveKind::Table(idx) => { DirectiveKind::Table(idx) => {
cx.table_element_xform(*idx, &directive.args, directive.ret_anyref); cx.table_element_xform(*idx, &directive.args, directive.ret_externref);
} }
} }
} }
@ -123,7 +123,7 @@ struct Test {
struct Directive { struct Directive {
args: Vec<(usize, bool)>, args: Vec<(usize, bool)>,
ret_anyref: bool, ret_externref: bool,
kind: DirectiveKind, kind: DirectiveKind,
} }
@ -216,8 +216,8 @@ fn update_output(path: &Path, output: &str) -> Result<()> {
impl<'a> Parse<'a> for Directive { impl<'a> Parse<'a> for Directive {
fn parse(parser: Parser<'a>) -> wast::parser::Result<Self> { fn parse(parser: Parser<'a>) -> wast::parser::Result<Self> {
use wast::kw; use wast::kw;
wast::custom_keyword!(anyref_owned); wast::custom_keyword!(externref_owned);
wast::custom_keyword!(anyref_borrowed); wast::custom_keyword!(externref_borrowed);
wast::custom_keyword!(other); wast::custom_keyword!(other);
let kind = if parser.peek::<kw::import>() { let kind = if parser.peek::<kw::import>() {
@ -234,11 +234,11 @@ impl<'a> Parse<'a> for Directive {
parser.parens(|p| { parser.parens(|p| {
let mut i = 0; let mut i = 0;
while !p.is_empty() { while !p.is_empty() {
if parser.peek::<anyref_owned>() { if parser.peek::<externref_owned>() {
parser.parse::<anyref_owned>()?; parser.parse::<externref_owned>()?;
args.push((i, true)); args.push((i, true));
} else if parser.peek::<anyref_borrowed>() { } else if parser.peek::<externref_borrowed>() {
parser.parse::<anyref_borrowed>()?; parser.parse::<externref_borrowed>()?;
args.push((i, false)); args.push((i, false));
} else { } else {
parser.parse::<other>()?; parser.parse::<other>()?;
@ -248,10 +248,10 @@ impl<'a> Parse<'a> for Directive {
Ok(()) Ok(())
})?; })?;
let ret_anyref = parser.parse::<Option<anyref_owned>>()?.is_some(); let ret_externref = parser.parse::<Option<externref_owned>>()?.is_some();
Ok(Directive { Ok(Directive {
args, args,
ret_anyref, ret_externref,
kind, kind,
}) })
} }

View File

@ -1,18 +1,18 @@
;; @xform export "foo" (anyref_owned) ;; @xform export "foo" (externref_owned)
(module (module
(func $foo (export "foo") (param i32)) (func $foo (export "foo") (param i32))
(func $alloc (export "__anyref_table_alloc") (result i32) (func $alloc (export "__externref_table_alloc") (result i32)
i32.const 0) i32.const 0)
(func $dealloc (export "__anyref_table_dealloc") (param i32)) (func $dealloc (export "__externref_table_dealloc") (param i32))
) )
(; CHECK-ALL: (; CHECK-ALL:
(module (module
(type (;0;) (func (result i32))) (type (;0;) (func (result i32)))
(type (;1;) (func (param i32))) (type (;1;) (func (param i32)))
(type (;2;) (func (param anyref))) (type (;2;) (func (param externref)))
(func $foo anyref shim (type 2) (param anyref) (func $foo externref shim (type 2) (param externref)
(local i32) (local i32)
call $alloc call $alloc
local.tee 1 local.tee 1
@ -23,6 +23,6 @@
(func $alloc (type 0) (result i32) (func $alloc (type 0) (result i32)
i32.const 0) i32.const 0)
(func $foo (type 1) (param i32)) (func $foo (type 1) (param i32))
(table (;0;) 32 anyref) (table (;0;) 32 externref)
(export "foo" (func $foo anyref shim))) (export "foo" (func $foo externref shim)))
;) ;)

View File

@ -1,17 +1,17 @@
;; @xform export "foo" (anyref_borrowed) ;; @xform export "foo" (externref_borrowed)
(module (module
(func $foo (export "foo") (param i32)) (func $foo (export "foo") (param i32))
(func $alloc (export "__anyref_table_alloc") (result i32) (func $alloc (export "__externref_table_alloc") (result i32)
i32.const 0) i32.const 0)
(func $dealloc (export "__anyref_table_dealloc") (param i32)) (func $dealloc (export "__externref_table_dealloc") (param i32))
) )
(; CHECK-ALL: (; CHECK-ALL:
(module (module
(type (;0;) (func (param i32))) (type (;0;) (func (param i32)))
(type (;1;) (func (param anyref))) (type (;1;) (func (param externref)))
(func $foo anyref shim (type 1) (param anyref) (func $foo externref shim (type 1) (param externref)
(local i32) (local i32)
global.get 0 global.get 0
i32.const 1 i32.const 1
@ -24,14 +24,14 @@
local.get 1 local.get 1
call $foo call $foo
local.get 1 local.get 1
ref.null ref.nullextern
table.set 0 table.set 0
local.get 1 local.get 1
i32.const 1 i32.const 1
i32.add i32.add
global.set 0) global.set 0)
(func $foo (type 0) (param i32)) (func $foo (type 0) (param i32))
(table (;0;) 32 anyref) (table (;0;) 32 externref)
(global (;0;) (mut i32) (i32.const 32)) (global (;0;) (mut i32) (i32.const 32))
(export "foo" (func $foo anyref shim))) (export "foo" (func $foo externref shim)))
;) ;)

View File

@ -1,4 +1,4 @@
;; @xform export "foo" (anyref_owned) anyref_owned ;; @xform export "foo" (externref_owned) externref_owned
(module (module
(import "__wbindgen_placeholder__" "__wbindgen_object_clone_ref" (import "__wbindgen_placeholder__" "__wbindgen_object_clone_ref"
@ -6,9 +6,9 @@
(func $foo (export "foo") (param i32) (result i32) (func $foo (export "foo") (param i32) (result i32)
local.get 0 local.get 0
call $clone) call $clone)
(func $alloc (export "__anyref_table_alloc") (result i32) (func $alloc (export "__externref_table_alloc") (result i32)
i32.const 0) i32.const 0)
(func $dealloc (export "__anyref_table_dealloc") (param i32)) (func $dealloc (export "__externref_table_dealloc") (param i32))
) )
(; CHECK-ALL: (; CHECK-ALL:
@ -16,8 +16,8 @@
(type (;0;) (func (result i32))) (type (;0;) (func (result i32)))
(type (;1;) (func (param i32))) (type (;1;) (func (param i32)))
(type (;2;) (func (param i32) (result i32))) (type (;2;) (func (param i32) (result i32)))
(type (;3;) (func (param anyref) (result anyref))) (type (;3;) (func (param externref) (result externref)))
(func $foo anyref shim (type 3) (param anyref) (result anyref) (func $foo externref shim (type 3) (param externref) (result externref)
(local i32) (local i32)
call $alloc call $alloc
local.tee 1 local.tee 1
@ -43,6 +43,6 @@
(func $alloc (type 0) (result i32) (func $alloc (type 0) (result i32)
i32.const 0) i32.const 0)
(func $dealloc (type 1) (param i32)) (func $dealloc (type 1) (param i32))
(table (;0;) 32 anyref) (table (;0;) 32 externref)
(export "foo" (func $foo anyref shim))) (export "foo" (func $foo externref shim)))
;) ;)

View File

@ -1,4 +1,4 @@
;; @xform export "foo" (anyref_owned) ;; @xform export "foo" (externref_owned)
(module (module
(import "__wbindgen_placeholder__" "__wbindgen_object_drop_ref" (import "__wbindgen_placeholder__" "__wbindgen_object_drop_ref"
@ -6,17 +6,17 @@
(func $foo (export "foo") (param i32) (func $foo (export "foo") (param i32)
local.get 0 local.get 0
call $drop) call $drop)
(func $alloc (export "__anyref_table_alloc") (result i32) (func $alloc (export "__externref_table_alloc") (result i32)
i32.const 0) i32.const 0)
(func $dealloc (export "__anyref_table_dealloc") (param i32)) (func $dealloc (export "__externref_table_dealloc") (param i32))
) )
(; CHECK-ALL: (; CHECK-ALL:
(module (module
(type (;0;) (func (result i32))) (type (;0;) (func (result i32)))
(type (;1;) (func (param i32))) (type (;1;) (func (param i32)))
(type (;2;) (func (param anyref))) (type (;2;) (func (param externref)))
(func $foo anyref shim (type 2) (param anyref) (func $foo externref shim (type 2) (param externref)
(local i32) (local i32)
call $alloc call $alloc
local.tee 1 local.tee 1
@ -30,6 +30,6 @@
(func $alloc (type 0) (result i32) (func $alloc (type 0) (result i32)
i32.const 0) i32.const 0)
(func $dealloc (type 1) (param i32)) (func $dealloc (type 1) (param i32))
(table (;0;) 32 anyref) (table (;0;) 32 externref)
(export "foo" (func $foo anyref shim))) (export "foo" (func $foo externref shim)))
;) ;)

View File

@ -1,22 +1,22 @@
;; @xform import "" "a" (anyref_owned) ;; @xform import "" "a" (externref_owned)
(module (module
(import "" "a" (func $a (param i32))) (import "" "a" (func $a (param i32)))
(func (export "foo") (func (export "foo")
i32.const 0 i32.const 0
call $a) call $a)
(func $alloc (export "__anyref_table_alloc") (result i32) (func $alloc (export "__externref_table_alloc") (result i32)
i32.const 0) i32.const 0)
(func $dealloc (export "__anyref_table_dealloc") (param i32)) (func $dealloc (export "__externref_table_dealloc") (param i32))
) )
(; CHECK-ALL: (; CHECK-ALL:
(module (module
(type (;0;) (func)) (type (;0;) (func))
(type (;1;) (func (param i32))) (type (;1;) (func (param i32)))
(type (;2;) (func (param anyref))) (type (;2;) (func (param externref)))
(import "" "a" (func $a (type 2))) (import "" "a" (func $a (type 2)))
(func $a anyref shim (type 1) (param i32) (func $a externref shim (type 1) (param i32)
local.get 0 local.get 0
table.get 0 table.get 0
local.get 0 local.get 0
@ -24,8 +24,8 @@
call $a) call $a)
(func (;2;) (type 0) (func (;2;) (type 0)
i32.const 0 i32.const 0
call $a anyref shim) call $a externref shim)
(func $dealloc (type 1) (param i32)) (func $dealloc (type 1) (param i32))
(table (;0;) 32 anyref) (table (;0;) 32 externref)
(export "foo" (func 2))) (export "foo" (func 2)))
;) ;)

View File

@ -1,21 +1,21 @@
;; @xform import "" "a" () anyref_owned ;; @xform import "" "a" () externref_owned
(module (module
(import "" "a" (func $a (result i32))) (import "" "a" (func $a (result i32)))
(func (export "foo") (result i32) (func (export "foo") (result i32)
call $a) call $a)
(func $alloc (export "__anyref_table_alloc") (result i32) (func $alloc (export "__externref_table_alloc") (result i32)
i32.const 0) i32.const 0)
(func $dealloc (export "__anyref_table_dealloc") (param i32)) (func $dealloc (export "__externref_table_dealloc") (param i32))
) )
(; CHECK-ALL: (; CHECK-ALL:
(module (module
(type (;0;) (func (result i32))) (type (;0;) (func (result i32)))
(type (;1;) (func (result anyref))) (type (;1;) (func (result externref)))
(import "" "a" (func $a (type 1))) (import "" "a" (func $a (type 1)))
(func $a anyref shim (type 0) (result i32) (func $a externref shim (type 0) (result i32)
(local i32 anyref) (local i32 externref)
call $a call $a
local.set 1 local.set 1
call $alloc call $alloc
@ -24,9 +24,9 @@
table.set 0 table.set 0
local.get 0) local.get 0)
(func (;2;) (type 0) (result i32) (func (;2;) (type 0) (result i32)
call $a anyref shim) call $a externref shim)
(func $alloc (type 0) (result i32) (func $alloc (type 0) (result i32)
i32.const 0) i32.const 0)
(table (;0;) 32 anyref) (table (;0;) 32 externref)
(export "foo" (func 2))) (export "foo" (func 2)))
;) ;)

View File

@ -1,28 +1,28 @@
;; @xform import "" "a" (anyref_borrowed) ;; @xform import "" "a" (externref_borrowed)
(module (module
(import "" "a" (func $a (param i32))) (import "" "a" (func $a (param i32)))
(func (export "foo") (func (export "foo")
i32.const 0 i32.const 0
call $a) call $a)
(func $alloc (export "__anyref_table_alloc") (result i32) (func $alloc (export "__externref_table_alloc") (result i32)
i32.const 0) i32.const 0)
(func $dealloc (export "__anyref_table_dealloc") (param i32)) (func $dealloc (export "__externref_table_dealloc") (param i32))
) )
(; CHECK-ALL: (; CHECK-ALL:
(module (module
(type (;0;) (func)) (type (;0;) (func))
(type (;1;) (func (param i32))) (type (;1;) (func (param i32)))
(type (;2;) (func (param anyref))) (type (;2;) (func (param externref)))
(import "" "a" (func $a (type 2))) (import "" "a" (func $a (type 2)))
(func $a anyref shim (type 1) (param i32) (func $a externref shim (type 1) (param i32)
local.get 0 local.get 0
table.get 0 table.get 0
call $a) call $a)
(func (;2;) (type 0) (func (;2;) (type 0)
i32.const 0 i32.const 0
call $a anyref shim) call $a externref shim)
(table (;0;) 32 anyref) (table (;0;) 32 externref)
(export "foo" (func 2))) (export "foo" (func 2)))
;) ;)

View File

@ -1,18 +1,18 @@
;; @xform export "a" (other anyref_borrowed other anyref_owned other) ;; @xform export "a" (other externref_borrowed other externref_owned other)
(module (module
(func $a (export "a") (param f32 i32 i64 i32 i32)) (func $a (export "a") (param f32 i32 i64 i32 i32))
(func $alloc (export "__anyref_table_alloc") (result i32) (func $alloc (export "__externref_table_alloc") (result i32)
i32.const 0) i32.const 0)
(func $dealloc (export "__anyref_table_dealloc") (param i32)) (func $dealloc (export "__externref_table_dealloc") (param i32))
) )
(; CHECK-ALL: (; CHECK-ALL:
(module (module
(type (;0;) (func (result i32))) (type (;0;) (func (result i32)))
(type (;1;) (func (param f32 i32 i64 i32 i32))) (type (;1;) (func (param f32 i32 i64 i32 i32)))
(type (;2;) (func (param f32 anyref i64 anyref i32))) (type (;2;) (func (param f32 externref i64 externref i32)))
(func $a anyref shim (type 2) (param f32 anyref i64 anyref i32) (func $a externref shim (type 2) (param f32 externref i64 externref i32)
(local i32 i32) (local i32 i32)
global.get 0 global.get 0
i32.const 1 i32.const 1
@ -33,7 +33,7 @@
local.get 4 local.get 4
call $a call $a
local.get 5 local.get 5
ref.null ref.nullextern
table.set 0 table.set 0
local.get 5 local.get 5
i32.const 1 i32.const 1
@ -42,7 +42,7 @@
(func $alloc (type 0) (result i32) (func $alloc (type 0) (result i32)
i32.const 0) i32.const 0)
(func $a (type 1) (param f32 i32 i64 i32 i32)) (func $a (type 1) (param f32 i32 i64 i32 i32))
(table (;0;) 32 anyref) (table (;0;) 32 externref)
(global (;0;) (mut i32) (i32.const 32)) (global (;0;) (mut i32) (i32.const 32))
(export "a" (func $a anyref shim))) (export "a" (func $a externref shim)))
;) ;)

View File

@ -1,4 +1,4 @@
;; @xform import "" "a" (other anyref_borrowed other anyref_owned other) ;; @xform import "" "a" (other externref_borrowed other externref_owned other)
(module (module
(import "" "a" (func $a (param f32 i32 i64 i32 i32))) (import "" "a" (func $a (param f32 i32 i64 i32 i32)))
@ -9,9 +9,9 @@
i32.const 4 i32.const 4
i32.const 5 i32.const 5
call $a) call $a)
(func $alloc (export "__anyref_table_alloc") (result i32) (func $alloc (export "__externref_table_alloc") (result i32)
i32.const 0) i32.const 0)
(func $dealloc (export "__anyref_table_dealloc") (param i32)) (func $dealloc (export "__externref_table_dealloc") (param i32))
) )
(; CHECK-ALL: (; CHECK-ALL:
@ -19,9 +19,9 @@
(type (;0;) (func)) (type (;0;) (func))
(type (;1;) (func (param i32))) (type (;1;) (func (param i32)))
(type (;2;) (func (param f32 i32 i64 i32 i32))) (type (;2;) (func (param f32 i32 i64 i32 i32)))
(type (;3;) (func (param f32 anyref i64 anyref i32))) (type (;3;) (func (param f32 externref i64 externref i32)))
(import "" "a" (func $a (type 3))) (import "" "a" (func $a (type 3)))
(func $a anyref shim (type 2) (param f32 i32 i64 i32 i32) (func $a externref shim (type 2) (param f32 i32 i64 i32 i32)
local.get 0 local.get 0
local.get 1 local.get 1
table.get 0 table.get 0
@ -38,8 +38,8 @@
i64.const 3 i64.const 3
i32.const 4 i32.const 4
i32.const 5 i32.const 5
call $a anyref shim) call $a externref shim)
(func $dealloc (type 1) (param i32)) (func $dealloc (type 1) (param i32))
(table (;0;) 32 anyref) (table (;0;) 32 externref)
(export "foo" (func 2))) (export "foo" (func 2)))
;) ;)

View File

@ -1,20 +1,20 @@
;; @xform export "foo" () anyref_owned ;; @xform export "foo" () externref_owned
(module (module
(func $foo (export "foo") (result i32) (func $foo (export "foo") (result i32)
i32.const 0) i32.const 0)
(func $alloc (export "__anyref_table_alloc") (result i32) (func $alloc (export "__externref_table_alloc") (result i32)
i32.const 0) i32.const 0)
(func $dealloc (export "__anyref_table_dealloc") (param i32)) (func $dealloc (export "__externref_table_dealloc") (param i32))
) )
(; CHECK-ALL: (; CHECK-ALL:
(module (module
(type (;0;) (func (result i32))) (type (;0;) (func (result i32)))
(type (;1;) (func (result anyref))) (type (;1;) (func (result externref)))
(type (;2;) (func (param i32))) (type (;2;) (func (param i32)))
(func $foo anyref shim (type 1) (result anyref) (func $foo externref shim (type 1) (result externref)
(local i32) (local i32)
call $foo call $foo
local.tee 0 local.tee 0
@ -24,6 +24,6 @@
(func $foo (type 0) (result i32) (func $foo (type 0) (result i32)
i32.const 0) i32.const 0)
(func $dealloc (type 2) (param i32)) (func $dealloc (type 2) (param i32))
(table (;0;) 32 anyref) (table (;0;) 32 externref)
(export "foo" (func $foo anyref shim))) (export "foo" (func $foo externref shim)))
;) ;)

View File

@ -1,23 +1,23 @@
;; @xform export "foo" (anyref_owned) ;; @xform export "foo" (externref_owned)
(module (module
(import "__wbindgen_anyref_xform__" "__wbindgen_anyref_table_grow" (import "__wbindgen_externref_xform__" "__wbindgen_externref_table_grow"
(func $grow (param i32) (result i32))) (func $grow (param i32) (result i32)))
(func $foo (export "foo") (param i32) (func $foo (export "foo") (param i32)
i32.const 0 i32.const 0
call $grow call $grow
drop) drop)
(func $alloc (export "__anyref_table_alloc") (result i32) (func $alloc (export "__externref_table_alloc") (result i32)
i32.const 0) i32.const 0)
(func $dealloc (export "__anyref_table_dealloc") (param i32)) (func $dealloc (export "__externref_table_dealloc") (param i32))
) )
(; CHECK-ALL: (; CHECK-ALL:
(module (module
(type (;0;) (func (result i32))) (type (;0;) (func (result i32)))
(type (;1;) (func (param i32))) (type (;1;) (func (param i32)))
(type (;2;) (func (param anyref))) (type (;2;) (func (param externref)))
(func $foo anyref shim (type 2) (param anyref) (func $foo externref shim (type 2) (param externref)
(local i32) (local i32)
call $alloc call $alloc
local.tee 1 local.tee 1
@ -26,12 +26,12 @@
local.get 1 local.get 1
call $foo) call $foo)
(func $foo (type 1) (param i32) (func $foo (type 1) (param i32)
ref.null ref.nullextern
i32.const 0 i32.const 0
table.grow 0 table.grow 0
drop) drop)
(func $alloc (type 0) (result i32) (func $alloc (type 0) (result i32)
i32.const 0) i32.const 0)
(table (;0;) 32 anyref) (table (;0;) 32 externref)
(export "foo" (func $foo anyref shim))) (export "foo" (func $foo externref shim)))
;) ;)

View File

@ -1,22 +1,22 @@
;; @xform export "foo" (anyref_owned) ;; @xform export "foo" (externref_owned)
(module (module
(import "__wbindgen_anyref_xform__" "__wbindgen_anyref_table_set_null" (import "__wbindgen_externref_xform__" "__wbindgen_externref_table_set_null"
(func $set-null (param i32))) (func $set-null (param i32)))
(func $foo (export "foo") (param i32) (func $foo (export "foo") (param i32)
local.get 0 local.get 0
call $set-null) call $set-null)
(func $alloc (export "__anyref_table_alloc") (result i32) (func $alloc (export "__externref_table_alloc") (result i32)
i32.const 0) i32.const 0)
(func $dealloc (export "__anyref_table_dealloc") (param i32)) (func $dealloc (export "__externref_table_dealloc") (param i32))
) )
(; CHECK-ALL: (; CHECK-ALL:
(module (module
(type (;0;) (func (result i32))) (type (;0;) (func (result i32)))
(type (;1;) (func (param i32))) (type (;1;) (func (param i32)))
(type (;2;) (func (param anyref))) (type (;2;) (func (param externref)))
(func $foo anyref shim (type 2) (param anyref) (func $foo externref shim (type 2) (param externref)
(local i32) (local i32)
call $alloc call $alloc
local.tee 1 local.tee 1
@ -26,10 +26,10 @@
call $foo) call $foo)
(func $foo (type 1) (param i32) (func $foo (type 1) (param i32)
local.get 0 local.get 0
ref.null ref.nullextern
table.set 0) table.set 0)
(func $alloc (type 0) (result i32) (func $alloc (type 0) (result i32)
i32.const 0) i32.const 0)
(table (;0;) 32 anyref) (table (;0;) 32 externref)
(export "foo" (func $foo anyref shim))) (export "foo" (func $foo externref shim)))
;) ;)

View File

@ -1,20 +1,20 @@
;; @xform table 0 (anyref_owned) ;; @xform table 0 (externref_owned)
(module (module
(func $foo (param i32)) (func $foo (param i32))
(table (export "func") 0 funcref) (table (export "func") 0 funcref)
(elem (i32.const 0) 0) (elem (i32.const 0) 0)
(func $alloc (export "__anyref_table_alloc") (result i32) (func $alloc (export "__externref_table_alloc") (result i32)
i32.const 0) i32.const 0)
(func $dealloc (export "__anyref_table_dealloc") (param i32)) (func $dealloc (export "__externref_table_dealloc") (param i32))
) )
(; CHECK-ALL: (; CHECK-ALL:
(module (module
(type (;0;) (func (result i32))) (type (;0;) (func (result i32)))
(type (;1;) (func (param i32))) (type (;1;) (func (param i32)))
(type (;2;) (func (param anyref))) (type (;2;) (func (param externref)))
(func $closure0 anyref shim (type 2) (param anyref) (func $closure0 externref shim (type 2) (param externref)
(local i32) (local i32)
call $alloc call $alloc
local.tee 1 local.tee 1
@ -26,8 +26,8 @@
i32.const 0) i32.const 0)
(func $foo (type 1) (param i32)) (func $foo (type 1) (param i32))
(table (;0;) 2 funcref) (table (;0;) 2 funcref)
(table (;1;) 32 anyref) (table (;1;) 32 externref)
(export "func" (table 0)) (export "func" (table 0))
(elem (;0;) (i32.const 0) func $foo) (elem (;0;) (i32.const 0) func $foo)
(elem (;1;) (i32.const 1) func $closure0 anyref shim)) (elem (;1;) (i32.const 1) func $closure0 externref shim))
;) ;)

View File

@ -13,12 +13,12 @@ edition = "2018"
[dependencies] [dependencies]
anyhow = "1.0" anyhow = "1.0"
walrus = "0.16.0" walrus = "0.17.0"
[dev-dependencies] [dev-dependencies]
rayon = "1.0" rayon = "1.0"
wasmprinter = "0.2" wasmprinter = "0.2"
wast = "15.0" wast = "17.0"
wat = "1.0" wat = "1.0"
[[test]] [[test]]

View File

@ -162,12 +162,10 @@ fn xform_one(
round_up_to_alignment(results_size, 8) + 8 round_up_to_alignment(results_size, 8) + 8
} }
walrus::ValType::V128 => round_up_to_alignment(results_size, 16) + 16, walrus::ValType::V128 => round_up_to_alignment(results_size, 16) + 16,
walrus::ValType::Anyref | walrus::ValType::Funcref | walrus::ValType::Nullref => { walrus::ValType::Externref | walrus::ValType::Funcref => anyhow::bail!(
anyhow::bail!( "cannot multi-value transform functions that return \
"cannot multi-value transform functions that return \
reference types, since they can't go into linear memory" reference types, since they can't go into linear memory"
) ),
}
}; };
} }
// Round up to 16-byte alignment, since that's what LLVM's emitted Wasm code // Round up to 16-byte alignment, since that's what LLVM's emitted Wasm code
@ -286,9 +284,7 @@ fn xform_one(
); );
offset += 16; offset += 16;
} }
walrus::ValType::Anyref | walrus::ValType::Funcref | walrus::ValType::Nullref => { walrus::ValType::Externref | walrus::ValType::Funcref => unreachable!(),
unreachable!()
}
} }
} }

View File

@ -13,5 +13,5 @@ edition = "2018"
[dependencies] [dependencies]
anyhow = "1.0" anyhow = "1.0"
walrus = "0.16.0" walrus = "0.17.0"
wasm-bindgen-wasm-conventions = { path = "../wasm-conventions", version = "=0.2.62" } wasm-bindgen-wasm-conventions = { path = "../wasm-conventions", version = "=0.2.62" }

View File

@ -401,7 +401,7 @@ fn inject_start(
match segment.offset { match segment.offset {
InitExpr::Global(id) => body.global_get(id), InitExpr::Global(id) => body.global_get(id),
InitExpr::Value(v) => body.const_(v), InitExpr::Value(v) => body.const_(v),
InitExpr::RefNull | InitExpr::RefFunc(_) => { InitExpr::RefNull(_) | InitExpr::RefFunc(_) => {
panic!("not a valid i32 initializer") panic!("not a valid i32 initializer")
} }
}; };

View File

@ -10,5 +10,5 @@ description = "Utilities for working with Wasm codegen conventions (usually esta
edition = "2018" edition = "2018"
[dependencies] [dependencies]
walrus = "0.16.0" walrus = "0.17.0"
anyhow = "1.0" anyhow = "1.0"

View File

@ -14,7 +14,7 @@ edition = '2018'
[dependencies] [dependencies]
anyhow = "1.0" anyhow = "1.0"
log = "0.4" log = "0.4"
walrus = "0.16.0" walrus = "0.17.0"
wasm-bindgen-wasm-conventions = { path = "../wasm-conventions", version = "0.2.62" } wasm-bindgen-wasm-conventions = { path = "../wasm-conventions", version = "0.2.62" }
[dev-dependencies] [dev-dependencies]

View File

@ -496,7 +496,7 @@ impl<'a> IdlType<'a> {
/// Converts to syn type if possible. /// Converts to syn type if possible.
pub(crate) fn to_syn_type(&self, pos: TypePosition) -> Result<Option<syn::Type>, TypeError> { pub(crate) fn to_syn_type(&self, pos: TypePosition) -> Result<Option<syn::Type>, TypeError> {
let anyref = |ty| { let externref = |ty| {
Some(match pos { Some(match pos {
TypePosition::Argument => shared_ref(ty, false), TypePosition::Argument => shared_ref(ty, false),
TypePosition::Return => ty, TypePosition::Return => ty,
@ -505,11 +505,11 @@ impl<'a> IdlType<'a> {
let js_sys = |name: &str| { let js_sys = |name: &str| {
let path = vec![rust_ident("js_sys"), rust_ident(name)]; let path = vec![rust_ident("js_sys"), rust_ident(name)];
let ty = leading_colon_path_ty(path); let ty = leading_colon_path_ty(path);
anyref(ty) externref(ty)
}; };
let js_value = { let js_value = {
let path = vec![rust_ident("wasm_bindgen"), rust_ident("JsValue")]; let path = vec![rust_ident("wasm_bindgen"), rust_ident("JsValue")];
anyref(leading_colon_path_ty(path)) externref(leading_colon_path_ty(path))
}; };
match self { match self {
IdlType::Boolean => Ok(Some(ident_ty(raw_ident("bool")))), IdlType::Boolean => Ok(Some(ident_ty(raw_ident("bool")))),
@ -565,7 +565,7 @@ impl<'a> IdlType<'a> {
| IdlType::Dictionary(name) | IdlType::Dictionary(name)
| IdlType::CallbackInterface { name, .. } => { | IdlType::CallbackInterface { name, .. } => {
let ty = ident_ty(rust_ident(camel_case_ident(name).as_str())); let ty = ident_ty(rust_ident(camel_case_ident(name).as_str()));
Ok(anyref(ty)) Ok(externref(ty))
} }
IdlType::Enum(name) => Ok(Some(ident_ty(rust_ident(camel_case_ident(name).as_str())))), IdlType::Enum(name) => Ok(Some(ident_ty(rust_ident(camel_case_ident(name).as_str())))),

View File

@ -29,7 +29,7 @@ const CRATES_TO_PUBLISH: &[&str] = &[
"wasm-bindgen-wasm-conventions", "wasm-bindgen-wasm-conventions",
"wasm-bindgen-threads-xform", "wasm-bindgen-threads-xform",
"wasm-bindgen-multi-value-xform", "wasm-bindgen-multi-value-xform",
"wasm-bindgen-anyref-xform", "wasm-bindgen-externref-xform",
"wasm-bindgen-cli-support", "wasm-bindgen-cli-support",
"wasm-bindgen-cli", "wasm-bindgen-cli",
"wasm-bindgen", "wasm-bindgen",

View File

@ -464,7 +464,7 @@ where
T: WasmClosure + ?Sized, T: WasmClosure + ?Sized,
{ {
fn describe() { fn describe() {
inform(ANYREF); inform(EXTERNREF);
} }
} }
@ -713,8 +713,9 @@ doit! {
// duplicate. // duplicate.
unsafe impl<A, R> WasmClosure for dyn Fn(&A) -> R unsafe impl<A, R> WasmClosure for dyn Fn(&A) -> R
where A: RefFromWasmAbi, where
R: ReturnWasmAbi + 'static, A: RefFromWasmAbi,
R: ReturnWasmAbi + 'static,
{ {
fn describe() { fn describe() {
#[allow(non_snake_case)] #[allow(non_snake_case)]
@ -730,8 +731,7 @@ unsafe impl<A, R> WasmClosure for dyn Fn(&A) -> R
// convert `ret` as it may throw (for `Result`, for // convert `ret` as it may throw (for `Result`, for
// example) // example)
let ret = { let ret = {
let f: *const dyn Fn(&A) -> R = let f: *const dyn Fn(&A) -> R = FatPtr { fields: (a, b) }.ptr;
FatPtr { fields: (a, b) }.ptr;
let arg = <A as RefFromWasmAbi>::ref_from_abi(arg); let arg = <A as RefFromWasmAbi>::ref_from_abi(arg);
(*f)(&*arg) (*f)(&*arg)
}; };
@ -740,17 +740,14 @@ unsafe impl<A, R> WasmClosure for dyn Fn(&A) -> R
inform(invoke::<A, R> as u32); inform(invoke::<A, R> as u32);
unsafe extern fn destroy<A: RefFromWasmAbi, R: ReturnWasmAbi>( unsafe extern "C" fn destroy<A: RefFromWasmAbi, R: ReturnWasmAbi>(a: usize, b: usize) {
a: usize,
b: usize,
) {
// See `Fn()` above for why we simply return // See `Fn()` above for why we simply return
if a == 0 { if a == 0 {
return; return;
} }
drop(Box::from_raw(FatPtr::<dyn Fn(&A) -> R> { drop(Box::from_raw(
fields: (a, b) FatPtr::<dyn Fn(&A) -> R> { fields: (a, b) }.ptr,
}.ptr)); ));
} }
inform(destroy::<A, R> as u32); inform(destroy::<A, R> as u32);
@ -759,8 +756,9 @@ unsafe impl<A, R> WasmClosure for dyn Fn(&A) -> R
} }
unsafe impl<A, R> WasmClosure for dyn FnMut(&A) -> R unsafe impl<A, R> WasmClosure for dyn FnMut(&A) -> R
where A: RefFromWasmAbi, where
R: ReturnWasmAbi + 'static, A: RefFromWasmAbi,
R: ReturnWasmAbi + 'static,
{ {
fn describe() { fn describe() {
#[allow(non_snake_case)] #[allow(non_snake_case)]
@ -776,8 +774,7 @@ unsafe impl<A, R> WasmClosure for dyn FnMut(&A) -> R
// convert `ret` as it may throw (for `Result`, for // convert `ret` as it may throw (for `Result`, for
// example) // example)
let ret = { let ret = {
let f: *const dyn FnMut(&A) -> R = let f: *const dyn FnMut(&A) -> R = FatPtr { fields: (a, b) }.ptr;
FatPtr { fields: (a, b) }.ptr;
let f = f as *mut dyn FnMut(&A) -> R; let f = f as *mut dyn FnMut(&A) -> R;
let arg = <A as RefFromWasmAbi>::ref_from_abi(arg); let arg = <A as RefFromWasmAbi>::ref_from_abi(arg);
(*f)(&*arg) (*f)(&*arg)
@ -787,17 +784,14 @@ unsafe impl<A, R> WasmClosure for dyn FnMut(&A) -> R
inform(invoke::<A, R> as u32); inform(invoke::<A, R> as u32);
unsafe extern fn destroy<A: RefFromWasmAbi, R: ReturnWasmAbi>( unsafe extern "C" fn destroy<A: RefFromWasmAbi, R: ReturnWasmAbi>(a: usize, b: usize) {
a: usize,
b: usize,
) {
// See `Fn()` above for why we simply return // See `Fn()` above for why we simply return
if a == 0 { if a == 0 {
return; return;
} }
drop(Box::from_raw(FatPtr::<dyn FnMut(&A) -> R> { drop(Box::from_raw(
fields: (a, b) FatPtr::<dyn FnMut(&A) -> R> { fields: (a, b) }.ptr,
}.ptr)); ));
} }
inform(destroy::<A, R> as u32); inform(destroy::<A, R> as u32);
@ -807,9 +801,10 @@ unsafe impl<A, R> WasmClosure for dyn FnMut(&A) -> R
#[allow(non_snake_case)] #[allow(non_snake_case)]
impl<T, A, R> WasmClosureFnOnce<(&A,), R> for T impl<T, A, R> WasmClosureFnOnce<(&A,), R> for T
where T: 'static + FnOnce(&A) -> R, where
A: RefFromWasmAbi + 'static, T: 'static + FnOnce(&A) -> R,
R: ReturnWasmAbi + 'static A: RefFromWasmAbi + 'static,
R: ReturnWasmAbi + 'static,
{ {
type FnMut = dyn FnMut(&A) -> R; type FnMut = dyn FnMut(&A) -> R;
@ -822,8 +817,8 @@ impl<T, A, R> WasmClosureFnOnce<(&A,), R> for T
} }
fn into_js_function(self) -> JsValue { fn into_js_function(self) -> JsValue {
use std::rc::Rc;
use crate::__rt::WasmRefCell; use crate::__rt::WasmRefCell;
use std::rc::Rc;
let mut me = Some(self); let mut me = Some(self);

View File

@ -36,8 +36,8 @@ tys! {
REFMUT REFMUT
SLICE SLICE
VECTOR VECTOR
ANYREF EXTERNREF
NAMED_ANYREF NAMED_EXTERNREF
ENUM ENUM
RUST_STRUCT RUST_STRUCT
CHAR CHAR
@ -78,7 +78,7 @@ simple! {
f64 => F64 f64 => F64
bool => BOOLEAN bool => BOOLEAN
char => CHAR char => CHAR
JsValue => ANYREF JsValue => EXTERNREF
} }
cfg_if! { cfg_if! {

View File

@ -1,16 +1,16 @@
use crate::JsValue;
use std::alloc::{self, Layout}; use std::alloc::{self, Layout};
use std::cell::Cell;
use std::mem; use std::mem;
use std::ptr; use std::ptr;
use std::slice; use std::slice;
use std::vec::Vec; use std::vec::Vec;
use std::cell::Cell;
use crate::JsValue;
externs! { externs! {
#[link(wasm_import_module = "__wbindgen_anyref_xform__")] #[link(wasm_import_module = "__wbindgen_externref_xform__")]
extern "C" { extern "C" {
fn __wbindgen_anyref_table_grow(delta: usize) -> i32; fn __wbindgen_externref_table_grow(delta: usize) -> i32;
fn __wbindgen_anyref_table_set_null(idx: usize) -> (); fn __wbindgen_externref_table_set_null(idx: usize) -> ();
} }
} }
@ -34,7 +34,7 @@ impl Slab {
if ret == self.data.len() { if ret == self.data.len() {
if self.data.len() == self.data.capacity() { if self.data.len() == self.data.capacity() {
let extra = 128; let extra = 128;
let r = unsafe { __wbindgen_anyref_table_grow(extra) }; let r = unsafe { __wbindgen_externref_table_grow(extra) };
if r == -1 { if r == -1 {
internal_error("table grow failure") internal_error("table grow failure")
} }
@ -121,12 +121,12 @@ fn internal_error(msg: &str) -> ! {
} }
} }
// Management of `anyref` is always thread local since an `anyref` value can't // Management of `externref` is always thread local since an `externref` value
// cross threads in wasm. Indices as a result are always thread-local. // can't cross threads in wasm. Indices as a result are always thread-local.
std::thread_local!(pub static HEAP_SLAB: Cell<Slab> = Cell::new(Slab::new())); std::thread_local!(pub static HEAP_SLAB: Cell<Slab> = Cell::new(Slab::new()));
#[no_mangle] #[no_mangle]
pub extern "C" fn __anyref_table_alloc() -> usize { pub extern "C" fn __externref_table_alloc() -> usize {
HEAP_SLAB HEAP_SLAB
.try_with(|slot| { .try_with(|slot| {
let mut slab = slot.replace(Slab::new()); let mut slab = slot.replace(Slab::new());
@ -138,14 +138,14 @@ pub extern "C" fn __anyref_table_alloc() -> usize {
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn __anyref_table_dealloc(idx: usize) { pub extern "C" fn __externref_table_dealloc(idx: usize) {
if idx < super::JSIDX_RESERVED as usize { if idx < super::JSIDX_RESERVED as usize {
return; return;
} }
// clear this value from the table so while the table slot is un-allocated // clear this value from the table so while the table slot is un-allocated
// we don't keep around a strong reference to a potentially large object // we don't keep around a strong reference to a potentially large object
unsafe { unsafe {
__wbindgen_anyref_table_set_null(idx); __wbindgen_externref_table_set_null(idx);
} }
HEAP_SLAB HEAP_SLAB
.try_with(|slot| { .try_with(|slot| {
@ -157,16 +157,16 @@ pub extern "C" fn __anyref_table_dealloc(idx: usize) {
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn __anyref_drop_slice(ptr: *mut JsValue, len: usize) { pub unsafe extern "C" fn __externref_drop_slice(ptr: *mut JsValue, len: usize) {
for slot in slice::from_raw_parts_mut(ptr, len) { for slot in slice::from_raw_parts_mut(ptr, len) {
__anyref_table_dealloc(slot.idx as usize); __externref_table_dealloc(slot.idx as usize);
} }
} }
// Implementation of `__wbindgen_anyref_heap_live_count` for when we are using // Implementation of `__wbindgen_externref_heap_live_count` for when we are using
// `anyref` instead of the JS `heap`. // `externref` instead of the JS `heap`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn __anyref_heap_live_count() -> u32 { pub unsafe extern "C" fn __externref_heap_live_count() -> u32 {
HEAP_SLAB HEAP_SLAB
.try_with(|slot| { .try_with(|slot| {
let slab = slot.replace(Slab::new()); let slab = slot.replace(Slab::new());

View File

@ -68,7 +68,7 @@ if_std! {
extern crate std; extern crate std;
use std::prelude::v1::*; use std::prelude::v1::*;
pub mod closure; pub mod closure;
mod anyref; mod externref;
mod cache; mod cache;
pub use cache::intern::{intern, unintern}; pub use cache::intern::{intern, unintern};
@ -495,7 +495,7 @@ externs! {
fn __wbindgen_symbol_named_new(ptr: *const u8, len: usize) -> u32; fn __wbindgen_symbol_named_new(ptr: *const u8, len: usize) -> u32;
fn __wbindgen_symbol_anonymous_new() -> u32; fn __wbindgen_symbol_anonymous_new() -> u32;
fn __wbindgen_anyref_heap_live_count() -> u32; fn __wbindgen_externref_heap_live_count() -> u32;
fn __wbindgen_is_null(idx: u32) -> u32; fn __wbindgen_is_null(idx: u32) -> u32;
fn __wbindgen_is_undefined(idx: u32) -> u32; fn __wbindgen_is_undefined(idx: u32) -> u32;
@ -659,7 +659,7 @@ pub fn throw_val(s: JsValue) -> ! {
} }
} }
/// Get the count of live `anyref`s / `JsValue`s in `wasm-bindgen`'s heap. /// Get the count of live `externref`s / `JsValue`s in `wasm-bindgen`'s heap.
/// ///
/// ## Usage /// ## Usage
/// ///
@ -671,7 +671,7 @@ pub fn throw_val(s: JsValue) -> ! {
/// * get an initial live count, /// * get an initial live count,
/// ///
/// * perform some series of operations or function calls that should clean up /// * perform some series of operations or function calls that should clean up
/// after themselves, and should not keep holding onto `anyref`s / `JsValue`s /// after themselves, and should not keep holding onto `externref`s / `JsValue`s
/// after completion, /// after completion,
/// ///
/// * get the final live count, /// * get the final live count,
@ -680,8 +680,8 @@ pub fn throw_val(s: JsValue) -> ! {
/// ///
/// ## What is Counted /// ## What is Counted
/// ///
/// Note that this only counts the *owned* `anyref`s / `JsValue`s that end up in /// Note that this only counts the *owned* `externref`s / `JsValue`s that end up in
/// `wasm-bindgen`'s heap. It does not count borrowed `anyref`s / `JsValue`s /// `wasm-bindgen`'s heap. It does not count borrowed `externref`s / `JsValue`s
/// that are on its stack. /// that are on its stack.
/// ///
/// For example, these `JsValue`s are accounted for: /// For example, these `JsValue`s are accounted for:
@ -690,7 +690,7 @@ pub fn throw_val(s: JsValue) -> ! {
/// #[wasm_bindgen] /// #[wasm_bindgen]
/// pub fn my_function(this_is_counted: JsValue) { /// pub fn my_function(this_is_counted: JsValue) {
/// let also_counted = JsValue::from_str("hi"); /// let also_counted = JsValue::from_str("hi");
/// assert!(wasm_bindgen::anyref_heap_live_count() >= 2); /// assert!(wasm_bindgen::externref_heap_live_count() >= 2);
/// } /// }
/// ``` /// ```
/// ///
@ -703,8 +703,13 @@ pub fn throw_val(s: JsValue) -> ! {
/// // ... /// // ...
/// } /// }
/// ``` /// ```
pub fn externref_heap_live_count() -> u32 {
unsafe { __wbindgen_externref_heap_live_count() }
}
#[doc(hidden)]
pub fn anyref_heap_live_count() -> u32 { pub fn anyref_heap_live_count() -> u32 {
unsafe { __wbindgen_anyref_heap_live_count() } externref_heap_live_count()
} }
/// An extension trait for `Option<T>` and `Result<T, E>` for unwraping the `T` /// An extension trait for `Option<T>` and `Result<T, E>` for unwraping the `T`
@ -1055,7 +1060,7 @@ pub mod __rt {
/// ///
/// Ideas for how to improve this are most welcome! /// Ideas for how to improve this are most welcome!
pub fn link_mem_intrinsics() { pub fn link_mem_intrinsics() {
crate::anyref::link_intrinsics(); crate::externref::link_intrinsics();
} }
static mut GLOBAL_EXNDATA: [u32; 2] = [0; 2]; static mut GLOBAL_EXNDATA: [u32; 2] = [0; 2];

View File

@ -1,20 +0,0 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
// This test is in the headless suite so that we can test the `anyref` table
// implementation of `anyref_heap_live_count` (as opposed to the JS `heap`
// implementation) in Firefox.
#[wasm_bindgen_test]
fn test_anyref_heap_live_count() {
let initial = wasm_bindgen::anyref_heap_live_count();
let after_alloc = {
let _vals: Vec<_> = (0..10).map(JsValue::from).collect();
wasm_bindgen::anyref_heap_live_count()
};
let after_dealloc = wasm_bindgen::anyref_heap_live_count();
assert_eq!(initial, after_dealloc);
assert_eq!(initial + 10, after_alloc);
}

View File

@ -0,0 +1,20 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
// This test is in the headless suite so that we can test the `externref` table
// implementation of `externref_heap_live_count` (as opposed to the JS `heap`
// implementation) in Firefox.
#[wasm_bindgen_test]
fn test_externref_heap_live_count() {
let initial = wasm_bindgen::externref_heap_live_count();
let after_alloc = {
let _vals: Vec<_> = (0..10).map(JsValue::from).collect();
wasm_bindgen::externref_heap_live_count()
};
let after_dealloc = wasm_bindgen::externref_heap_live_count();
assert_eq!(initial, after_dealloc);
assert_eq!(initial + 10, after_alloc);
}

View File

@ -47,7 +47,7 @@ pub fn import_export_same_name() {
import_export_same_name(); import_export_same_name();
} }
pub mod anyref_heap_live_count; pub mod externref_heap_live_count;
pub mod modules; pub mod modules;
pub mod snippets; pub mod snippets;
pub mod strings; pub mod strings;

View File

@ -39,7 +39,7 @@ use wasm_bindgen_test::*;
return 42; return 42;
}; };
module.exports.works_when_anyref_support_is_enabled = function (v) { module.exports.works_when_externref_support_is_enabled = function (v) {
assert_eq(v, 'hello'); assert_eq(v, 'hello');
return v; return v;
}; };
@ -94,11 +94,11 @@ extern "C" {
#[wasm_bindgen(assert_no_shim, js_namespace = MyNamespace)] #[wasm_bindgen(assert_no_shim, js_namespace = MyNamespace)]
fn outgoing_namespaced(x: f64); fn outgoing_namespaced(x: f64);
// Note that this should only skip the JS shim if we have anyref support // Note that this should only skip the JS shim if we have externref support
// enabled. // enabled.
// //
// #[wasm_bindgen(assert_no_shim)] // #[wasm_bindgen(assert_no_shim)]
fn works_when_anyref_support_is_enabled(v: JsValue) -> JsValue; fn works_when_externref_support_is_enabled(v: JsValue) -> JsValue;
} }
#[wasm_bindgen_test] #[wasm_bindgen_test]
@ -147,6 +147,6 @@ fn no_shims() {
assert!(b); assert!(b);
let v = JsValue::from("hello"); let v = JsValue::from("hello");
let vv = works_when_anyref_support_is_enabled(v.clone()); let vv = works_when_externref_support_is_enabled(v.clone());
assert_eq!(v, vv); assert_eq!(v, vv);
} }

View File

@ -218,10 +218,10 @@ pub fn do_string_roundtrip(s: String) -> String {
} }
#[wasm_bindgen_test] #[wasm_bindgen_test]
fn anyref_heap_live_count() { fn externref_heap_live_count() {
let x = wasm_bindgen::anyref_heap_live_count(); let x = wasm_bindgen::externref_heap_live_count();
let y = JsValue::null().clone(); let y = JsValue::null().clone();
assert!(wasm_bindgen::anyref_heap_live_count() > x); assert!(wasm_bindgen::externref_heap_live_count() > x);
drop(y); drop(y);
assert_eq!(x, wasm_bindgen::anyref_heap_live_count()); assert_eq!(x, wasm_bindgen::externref_heap_live_count());
} }