Skip to content

Proposal: Use Symbol for trait impls #2073

@KSXGitHub

Description

@KSXGitHub

Motivation

Currently, #[wasm_bindgen] cannot be applied to trait impls, I guess this is to avoid method name collision? If that is the case, then JavaScript Symbol is a perfect solution for this.

Proposed Solution

Convert trait methods to JavaScript methods with symbols for names, and trait names can be converted to a namespace object of symbols. For example:

This code:

// src/lib.rs
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub struct Foo {
    value: i32,
}

#[wasm_bindgen]
impl Foo {
    #[wasm_bindgen(constructor)]
    pub fn new(value: i32) -> Self {
        Foo { value }
    }

    #[wasm_bindgen]
    pub fn read(&self) -> i32 {
        self.value
    }
}

#[wasm_bingen]
trait Read {
    fn read(&self) -> i32;
}

#[wasm_bindgen]
impl Read for Foo {
    #[wasm_bindgen]
    fn read(&self) -> i32 {
        self.value
    }
}

can be converted to this TypeScript declaration:

// from Read trait in the Rust source
// all Rust structs that impl Read trait will be converted to TypeScript classes that implements Read interface
export interface Read {
  // from Read::read in the Rust source
  [Read.read](this: this): number
}

// from Read trait in the Rust source
// namespaces in TypeScript are just objects in JavaScript
export declare namespace Read {
  // from Read::read in the Rust source
  const read: unique symbol;
  type read = typeof read;
}

export declare class Foo implements Read {
  public constructor(value: number);
  public read(this: Foo): number;

  // from Read::read in the Rust source
  public [Read.read](this: this): number;
}

Note

In the JavaScript glue code, Read object must always be created before class Foo.

Alternatives

Additional Context

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions