mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-06-21 16:51:33 +00:00
Guarantee static_method_of
uses the right this
(#1795)
This came up during #1760 where `Promise.resolve` must be invoked with `this` as the `Promise` object, but we were erroneously importing it in such a way that it didn't have a shim and `this` was `undefined`.
This commit is contained in:
@ -2269,6 +2269,11 @@ impl<'a> Context<'a> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
AuxImport::ValueWithThis(class, name) => {
|
||||||
|
let class = self.import_name(class)?;
|
||||||
|
Ok(format!("{}.{}({})", class, name, variadic_args(&args)?))
|
||||||
|
}
|
||||||
|
|
||||||
AuxImport::Instanceof(js) => {
|
AuxImport::Instanceof(js) => {
|
||||||
assert!(webidl_ty.kind == ast::WebidlFunctionKind::Static);
|
assert!(webidl_ty.kind == ast::WebidlFunctionKind::Static);
|
||||||
assert!(!variadic);
|
assert!(!variadic);
|
||||||
|
@ -278,6 +278,10 @@ pub enum AuxImport {
|
|||||||
/// imported
|
/// imported
|
||||||
Value(AuxValue),
|
Value(AuxValue),
|
||||||
|
|
||||||
|
/// A static method on a class is being imported, and the `this` of the
|
||||||
|
/// function call is expected to always be the class.
|
||||||
|
ValueWithThis(JsImport, String),
|
||||||
|
|
||||||
/// This import is expected to be a function that takes an `anyref` and
|
/// This import is expected to be a function that takes an `anyref` 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.
|
||||||
@ -950,8 +954,7 @@ impl<'a> Context<'a> {
|
|||||||
match op.kind {
|
match op.kind {
|
||||||
decode::OperationKind::Regular => {
|
decode::OperationKind::Regular => {
|
||||||
if op.is_static {
|
if op.is_static {
|
||||||
class.fields.push(function.name.to_string());
|
Ok((AuxImport::ValueWithThis(class, function.name.to_string()), false))
|
||||||
Ok((AuxImport::Value(AuxValue::Bare(class)), false))
|
|
||||||
} else if structural {
|
} else if structural {
|
||||||
Ok((
|
Ok((
|
||||||
AuxImport::StructuralMethod(function.name.to_string()),
|
AuxImport::StructuralMethod(function.name.to_string()),
|
||||||
|
@ -574,6 +574,9 @@ fn check_standard_import(import: &AuxImport) -> Result<(), Error> {
|
|||||||
| AuxImport::Value(AuxValue::ClassSetter(js, name)) => {
|
| AuxImport::Value(AuxValue::ClassSetter(js, name)) => {
|
||||||
format!("field access of `{}` for {}", name, desc_js(js))
|
format!("field access of `{}` for {}", name, desc_js(js))
|
||||||
}
|
}
|
||||||
|
AuxImport::ValueWithThis(js, method) => {
|
||||||
|
format!("method `{}.{}`", desc_js(js), method)
|
||||||
|
}
|
||||||
AuxImport::Instanceof(js) => format!("instance of check of {}", desc_js(js)),
|
AuxImport::Instanceof(js) => format!("instance of check of {}", desc_js(js)),
|
||||||
AuxImport::Static(js) => format!("static js value {}", desc_js(js)),
|
AuxImport::Static(js) => format!("static js value {}", desc_js(js)),
|
||||||
AuxImport::StructuralMethod(name) => format!("structural method `{}`", name),
|
AuxImport::StructuralMethod(name) => format!("structural method `{}`", name),
|
||||||
|
@ -23,3 +23,6 @@ let instant = Date::now();
|
|||||||
|
|
||||||
This is similar to the `js_namespace` attribute, but the usage from within Rust
|
This is similar to the `js_namespace` attribute, but the usage from within Rust
|
||||||
is different since the method also becomes a static method of the imported type.
|
is different since the method also becomes a static method of the imported type.
|
||||||
|
Additionally this attribute also specifies that the `this` parameter when
|
||||||
|
invoking the method is expected to be the JS class, e.g. always invoked as
|
||||||
|
`Date.now()` instead of `const x = Date.now; x()`.
|
||||||
|
@ -107,3 +107,11 @@ exports.import_inside_private_module = function() {};
|
|||||||
exports.should_call_undefined_functions = () => false;
|
exports.should_call_undefined_functions = () => false;
|
||||||
|
|
||||||
exports.STATIC_STRING = 'x';
|
exports.STATIC_STRING = 'x';
|
||||||
|
|
||||||
|
class StaticMethodCheck {
|
||||||
|
static static_method_of_right_this() {
|
||||||
|
assert.ok(this === StaticMethodCheck);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.StaticMethodCheck = StaticMethodCheck;
|
||||||
|
@ -52,6 +52,9 @@ extern "C" {
|
|||||||
fn assert_dead_import_not_generated();
|
fn assert_dead_import_not_generated();
|
||||||
fn should_call_undefined_functions() -> bool;
|
fn should_call_undefined_functions() -> bool;
|
||||||
|
|
||||||
|
type StaticMethodCheck;
|
||||||
|
#[wasm_bindgen(static_method_of = StaticMethodCheck)]
|
||||||
|
fn static_method_of_right_this();
|
||||||
|
|
||||||
static STATIC_STRING: String;
|
static STATIC_STRING: String;
|
||||||
}
|
}
|
||||||
@ -240,3 +243,8 @@ fn undefined_function_is_ok() {
|
|||||||
fn static_string_ok() {
|
fn static_string_ok() {
|
||||||
assert_eq!(*STATIC_STRING, "x");
|
assert_eq!(*STATIC_STRING, "x");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn static_method_of_has_right_this() {
|
||||||
|
StaticMethodCheck::static_method_of_right_this();
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user