Skip to content

RFC: conditional module FFI #6946

Open
Open
@cometkim

Description

@cometkim

Background

Imagine a class statement written from external JS.

// rescript_error.mjs
export class RescriptError extends Error {
  constructor(exnId, payload) {
    super();
  }
}

// and in rescript_error.cjs
module.exports = {
  RescriptError,
};

This is a pretty common situation because ReScript doesn't support ES classes.

However, ReScript's current FFI approach cannot select the appropriate resolution by its syntax.

type t

@module("./rescript_error.mjs") @new external makeErrorEsm: unit => t = "RescriptError"
@module("./rescript_error.cjs") @new external makeErrorCjs: unit => t = "RescriptError"

// and it might need a runtime like UMD

This can be solved today using bundlers' module alias or Node.js' conditional exports/imports resolution, but these are all platform-dependent features.

{
  "imports": {
    "#error": {
      "import": "./rescript_error.mjs",
      "require": "./rescript_error.cjs"
    }
  }
}

The toolchain must be able to produce output that is appropriate for its target. That's true even for FFIs.

Suggested Solution

There are currently two module specs: esmoudle and commonjs (a composite of the two, dual, will be added in the future #6209).

Users can specify either of these two as target in the @module statement.

type t

@module({ target: "esmodule", from: "./rescript_error.mjs" })
@module({ target: "commonjs", from: "./rescript_error.cjs" })
@new external makeError: unit => t = "RescriptError"

The library may not support all conditions. The compiler should raise an error if it cannot find a target that matches a module in the project.

If target omitted, the * pattern is implicitly used.

@module("./rescript_error.ts")
// is equivalent
@module({ target: "*", from: "./rescript_error.ts" })

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    No status

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions