mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-03-16 02:00:51 +00:00
Mass rename anyref to externref (#2142)
Updates a mess of dependencies and tracks the most recent version of the reference types specification.
This commit is contained in:
parent
61e8fc0d38
commit
996e92f3ae
@ -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
|
||||||
|
@ -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);)*
|
||||||
}
|
}
|
||||||
|
@ -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"
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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"),
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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`
|
||||||
|
@ -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`
|
||||||
|
@ -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],
|
||||||
|
@ -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
|
||||||
|
@ -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 {
|
||||||
|
@ -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)?,
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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"
|
||||||
|
@ -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)
|
||||||
)
|
)
|
||||||
|
@ -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");
|
||||||
|
@ -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);
|
||||||
|
@ -1 +1 @@
|
|||||||
// enable-anyref
|
// enable-externref
|
||||||
|
@ -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))
|
||||||
|
@ -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);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// enable-anyref
|
// enable-externref
|
||||||
|
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
@ -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)))
|
||||||
|
@ -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);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// enable-anyref
|
// enable-externref
|
||||||
|
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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)))
|
||||||
|
@ -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]]
|
@ -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(¶m_tys, &new_ret);
|
let externref_ty = types.add(¶m_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,
|
@ -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,
|
||||||
})
|
})
|
||||||
}
|
}
|
@ -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)))
|
||||||
;)
|
;)
|
@ -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)))
|
||||||
;)
|
;)
|
@ -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)))
|
||||||
;)
|
;)
|
@ -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)))
|
||||||
;)
|
;)
|
@ -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)))
|
||||||
;)
|
;)
|
@ -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)))
|
||||||
;)
|
;)
|
@ -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)))
|
||||||
;)
|
;)
|
@ -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)))
|
||||||
;)
|
;)
|
@ -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)))
|
||||||
;)
|
;)
|
@ -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)))
|
||||||
;)
|
;)
|
@ -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)))
|
||||||
;)
|
;)
|
@ -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)))
|
||||||
;)
|
;)
|
@ -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))
|
||||||
;)
|
;)
|
@ -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]]
|
||||||
|
@ -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!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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" }
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -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"
|
||||||
|
@ -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]
|
||||||
|
@ -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())))),
|
||||||
|
|
||||||
|
@ -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",
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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! {
|
||||||
|
@ -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());
|
23
src/lib.rs
23
src/lib.rs
@ -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];
|
||||||
|
@ -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);
|
|
||||||
}
|
|
20
tests/headless/externref_heap_live_count.rs
Normal file
20
tests/headless/externref_heap_live_count.rs
Normal 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);
|
||||||
|
}
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user