Skip to content

Conversation

@ajihyf
Copy link

@ajihyf ajihyf commented Jan 2, 2026

Closes #116 (partly), extending JS classes is excluded from this MR as it requires significant refactoring of class methods.

Description of changes

  • Modify class.rs to expose parent_vtable method for inheritance.
  • Introduce inherits.rs to define HasParent trait.
  • Enhance ffi.rs to include parent vtable in the VTable struct.
  • Update opaque.rs to handle constructors for inherited classes.
  • Adjust macro definitions to support the extends attribute.

Checklist

  • Added change to the changelog
  • Created unit tests for my feature if needed

Closes DelSkayn#116 (partly), since extending JS classes is excluded from this MR as it requires significant refactoring of class methods.
@Sytten
Copy link
Collaborator

Sytten commented Jan 2, 2026

Not a bad addition though the primary usecase is to extend rust from a js class to avoid the shenanigans we currently have to do to create classes like Buffer. Any solution we merge will need to support that.

Also from a larger perspective I dont like the vtable design we currently have with a unique class ID for all rust classes. I would much rather we find a way to use the engine directly, we switched to this system as a patch to avoid clashes of class ID but nobody is really happy with the solution.

@ajihyf
Copy link
Author

ajihyf commented Jan 2, 2026

Thanks for the feedback.

To give some context on my motivation: I am currently working on a DOM-like library, so implementing Rust-to-Rust inheritance (e.g., Node -> Element -> HTMLElement) was my immediate priority.

As for the "extending JS classes" requirement, I have a proposal: we could store the Rust struct (as a hidden object) inside the native JS object using a Symbol. This would incur a small extra lookup cost but would solve the binding issue without requiring a massive refactor right now.

@richarddd
Copy link
Collaborator

Thanks for the feedback.

To give some context on my motivation: I am currently working on a DOM-like library, so implementing Rust-to-Rust inheritance (e.g., Node -> Element -> HTMLElement) was my immediate priority.

As for the "extending JS classes" requirement, I have a proposal: we could store the Rust struct (as a hidden object) inside the native JS object using a Symbol. This would incur a small extra lookup cost but would solve the binding issue without requiring a massive refactor right now.

I don't think it has to be this complicated. We just have to call this function:
https://github.com/quickjs-ng/quickjs/blob/master/quickjs.h#L921C1-L923C69

With newTarget being the class we want to extend.

I added some comments here:
#116 (comment)

@ajihyf
Copy link
Author

ajihyf commented Jan 2, 2026

Thanks for the feedback.
To give some context on my motivation: I am currently working on a DOM-like library, so implementing Rust-to-Rust inheritance (e.g., Node -> Element -> HTMLElement) was my immediate priority.
As for the "extending JS classes" requirement, I have a proposal: we could store the Rust struct (as a hidden object) inside the native JS object using a Symbol. This would incur a small extra lookup cost but would solve the binding issue without requiring a massive refactor right now.

I don't think it has to be this complicated. We just have to call this function: https://github.com/quickjs-ng/quickjs/blob/master/quickjs.h#L921C1-L923C69

With newTarget being the class we want to extend.

I added some comments here: #116 (comment)

As I understand it, passing new.target handles the prototype chain, but we still face an issue regarding the opaque field.

For QuickJS internal/built-in classes: The opaque field is already occupied by the engine (e.g., Uint8Array uses it for array data). This means a Rust-implemented Buffer cannot store its own state there, nor can we access it via get opaque. Without a hidden object, I haven't found a unified way to support extending these classes with class macro and JsClass trait.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Extend class from rust?

3 participants