Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
03277f7
clean types in Prelude
tsnobip Apr 17, 2026
bcba34d
split into subpackages
tsnobip Apr 18, 2026
e149630
add back getter functions for Window
tsnobip Apr 18, 2026
cae2810
move back Navigator to DOM
tsnobip Apr 18, 2026
78765e8
remove globals package
tsnobip Apr 18, 2026
e518f6a
delete files that should not be versioned
tsnobip Apr 18, 2026
8345757
add some more typealiases in DOM/Types
tsnobip Apr 18, 2026
137a849
format
tsnobip Apr 18, 2026
5345ceb
delete JS files
tsnobip Apr 18, 2026
ceca97d
format package.json
tsnobip Apr 18, 2026
405c266
fix docs generation
tsnobip Apr 18, 2026
181df9c
change namespace to `@rescript/webapi-[section]`
tsnobip Apr 18, 2026
55bfa28
publish all subpackages in CI
tsnobip Apr 18, 2026
b0404e9
refactor: carry over post-monorepo pre-alpha cleanup
jderochervlk Apr 18, 2026
8b4c4a8
refactor(DOM): remove numeric scroll overloads
jderochervlk Apr 19, 2026
9acbff8
Merge pull request #253 from rescript-lang/codex/address-pr-comments-…
jderochervlk Apr 19, 2026
1d5fb64
fix: rename overloaded constructors to from* names
jderochervlk Apr 19, 2026
d23908e
style: format Path2D on carryover branch
jderochervlk Apr 19, 2026
8a41da1
refactor: localize VideoFrame shared array buffer alias
jderochervlk Apr 19, 2026
6cb796d
Merge main into codex/issue-236-constructor-from-names-carryover
jderochervlk Apr 20, 2026
07aaf50
Merge branch 'main' of github.com:rescript-lang/experimental-rescript…
jderochervlk Apr 20, 2026
1f43149
fix: drop labels from single-source constructors
jderochervlk Apr 20, 2026
2c7ece0
docs: simplify constructor descriptions
jderochervlk Apr 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions docs/content/docs/contributing/api-modelling.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,48 @@ external addEventListenerWithCapture: (

When naming an overloaded function, we can use the `With` suffix to indicate that it is an overloaded function.

### Constructor overloads

Constructors follow a different naming rule than methods.

- Keep singleton constructors named `make`.
- Keep true default constructors named `make`, even when the constructor family also has typed overloads.
- When a constructor family does not have a default constructor, use `from*` names for every overload, including the first one.
- Base `from*` names on the source input type: `fromString`, `fromArrayBuffer`, `fromMediaStream`, `fromURLWithProtocols`, and so on.
- If an optional labeled argument hides a real default constructor, split that binding into `make()` plus typed `from*` overloads instead of keeping the optional argument on `make`.

For example, these constructor families are easier to understand than numbered overloads:

```ReScript
@new
external fromString: (~family: string, ~source: string) => fontFace = "FontFace"

@new
external fromDataView: (~family: string, ~source: DataView.t) => fontFace = "FontFace"

@new
external fromArrayBuffer: (~family: string, ~source: ArrayBuffer.t) => fontFace = "FontFace"
```

And if a constructor really does have a default form, split it instead of hiding it:

```ReScript
@new
external make: unit => domMatrix = "DOMMatrix"

@new
external fromString: string => domMatrix = "DOMMatrix"

@new
external fromArray: array<float> => domMatrix = "DOMMatrix"
```

Single-source constructor variants should take the source value directly without a label.

Keep `makeWith*` names for non-default convenience constructors that are not part of a source-type overload family.

Constructor naming is currently verified with compile-coverage tests. Runtime verification for these constructor families will be added later when the Vitest and happy-dom harness lands.

### Decoded variants

We can be pragmatic with overloaded functions and use model them in various creative ways.
Expand Down
24 changes: 23 additions & 1 deletion docs/content/docs/contributing/documentation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ It keeps the user inside the IDE and avoids context switching.
The documentation for each binding should roughly follow this structure:

- signature
- key description (tip: check MDN for inspiration)
- short description focused on the ReScript side of the API
- example usage
- link to the MDN documentation

Expand All @@ -44,3 +44,25 @@ window->Window.fetch("https://rescript-lang.org")
external fetch: (window, string, ~init: requestInit=?)
=> promise<response> = "fetch"
````

Constructor overloads should use the same structure, but keep the description concise and let the signature and example show the input shape.
Use backticks for specific types and names.
If a constructor variant has a single source input, show it as a direct unlabeled argument in both the signature and example.

````ReScript
/*
`fromArray(array<float>)`

Creates a new `DOMMatrix` from an array of matrix component values.

```res
let matrix = DOMMatrix.fromArray([1., 0., 0., 1., 0., 0.])
```

[Read more on MDN](https://developer.mozilla.org/docs/Web/API/DOMMatrix)
*/
@new
external fromArray: array<float> => domMatrix = "DOMMatrix"
````

For now, these examples stay compile-coverage oriented. Runtime verification of constructor behavior will be handled later via Vitest and happy-dom.
33 changes: 30 additions & 3 deletions packages/CSSFontLoading/src/FontFace.res
Original file line number Diff line number Diff line change
@@ -1,28 +1,55 @@
/**
`fromString(~family: string, ~source: string, ~descriptors: fontFaceDescriptors=?)`

Creates a new `FontFace` from CSS source text.

```res
let fontFace =
FontFace.fromString(~family="Inter", ~source="url(/fonts/inter.woff2)")
```

[Read more on MDN](https://developer.mozilla.org/docs/Web/API/FontFace)
*/
@new
external make: (
external fromString: (
~family: string,
~source: string,
~descriptors: Types.fontFaceDescriptors=?,
) => Types.fontFace = "FontFace"

/**
`fromDataView(~family: string, ~source: DataView.t, ~descriptors: fontFaceDescriptors=?)`

Creates a new `FontFace` from `DataView`-backed font data.

```res
let fontFace =
FontFace.fromDataView(~family="Inter", ~source=myDataView)
```

[Read more on MDN](https://developer.mozilla.org/docs/Web/API/FontFace)
*/
@new
external make2: (
external fromDataView: (
~family: string,
~source: DataView.t,
~descriptors: Types.fontFaceDescriptors=?,
) => Types.fontFace = "FontFace"

/**
`fromArrayBuffer(~family: string, ~source: ArrayBuffer.t, ~descriptors: fontFaceDescriptors=?)`

Creates a new `FontFace` from `ArrayBuffer`-backed font data.

```res
let fontFace =
FontFace.fromArrayBuffer(~family="Inter", ~source=myArrayBuffer)
```

[Read more on MDN](https://developer.mozilla.org/docs/Web/API/FontFace)
*/
@new
external make3: (
external fromArrayBuffer: (
~family: string,
~source: ArrayBuffer.t,
~descriptors: Types.fontFaceDescriptors=?,
Expand Down
34 changes: 32 additions & 2 deletions packages/Canvas/src/Path2D.res
Original file line number Diff line number Diff line change
@@ -1,16 +1,46 @@
type domMatrix2DInit = WebApiDOM.Types.domMatrix2DInit

/**
`make()`

Creates a new empty `Path2D`.

```res
let path = Path2D.make()
```

[Read more on MDN](https://developer.mozilla.org/docs/Web/API/Path2D)
*/
@new
external make: unit => Types.path2D = "Path2D"

/**
`fromPath2D(path2D)`

Creates a new `Path2D` by copying another `Path2D`.

```res
let copiedPath = Path2D.fromPath2D(existingPath)
```

[Read more on MDN](https://developer.mozilla.org/docs/Web/API/Path2D)
*/
@new
external make: (~path: Types.path2D=?) => Types.path2D = "Path2D"
external fromPath2D: Types.path2D => Types.path2D = "Path2D"

/**
`fromString(string)`

Creates a new `Path2D` from SVG path data text.

```res
let path = Path2D.fromString("M0 0 L10 10")
```

[Read more on MDN](https://developer.mozilla.org/docs/Web/API/Path2D)
*/
@new
external make2: (~path: string=?) => Types.path2D = "Path2D"
external fromString: string => Types.path2D = "Path2D"

/**
[Read more on MDN](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/closePath)
Expand Down
110 changes: 99 additions & 11 deletions packages/Canvas/src/VideoFrame.res
Original file line number Diff line number Diff line change
@@ -1,89 +1,177 @@
type sharedArrayBuffer = unknown
Copy link
Copy Markdown
Member

@tsnobip tsnobip Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should use ArrayBufferTypedArrayOrDataView.t
https://github.com/rescript-lang/experimental-rescript-webapi/blob/main/packages/Base/src/ArrayBufferTypedArrayOrDataView.res
or even better, write a different binding for each possible case (ArrayBuffer, TypedArray, DataView), this type should be kept only for cases when you can't write multiple bindings, like in record types for example, otherwise in VideoFrame or SubtleCrypto bindings, it should likely use different bindings.


/**
`fromHTMLImageElement(~image: HTMLImageElement.t, ~init: videoFrameInit=?)`

Creates a new `VideoFrame` from an `HTMLImageElement`.

```res
let frame = VideoFrame.fromHTMLImageElement(~image=myImageElement)
```

[Read more on MDN](https://developer.mozilla.org/docs/Web/API/VideoFrame)
*/
@new
external make: (
external fromHTMLImageElement: (
~image: WebApiDOM.Types.htmlImageElement,
~init: WebApiDOM.Types.videoFrameInit=?,
) => WebApiDOM.Types.videoFrame = "VideoFrame"

/**
`fromSVGImageElement(~image: SVGImageElement.t, ~init: videoFrameInit=?)`

Creates a new `VideoFrame` from an `SVGImageElement`.

```res
let frame = VideoFrame.fromSVGImageElement(~image=mySvgImageElement)
```

[Read more on MDN](https://developer.mozilla.org/docs/Web/API/VideoFrame)
*/
@new
external make2: (
external fromSVGImageElement: (
~image: WebApiDOM.Types.svgImageElement,
~init: WebApiDOM.Types.videoFrameInit=?,
) => WebApiDOM.Types.videoFrame = "VideoFrame"

/**
`fromHTMLVideoElement(~image: HTMLVideoElement.t, ~init: videoFrameInit=?)`

Creates a new `VideoFrame` from an `HTMLVideoElement`.

```res
let frame = VideoFrame.fromHTMLVideoElement(~image=myVideoElement)
```

[Read more on MDN](https://developer.mozilla.org/docs/Web/API/VideoFrame)
*/
@new
external make3: (
external fromHTMLVideoElement: (
~image: WebApiDOM.Types.htmlVideoElement,
~init: WebApiDOM.Types.videoFrameInit=?,
) => WebApiDOM.Types.videoFrame = "VideoFrame"

/**
`fromHTMLCanvasElement(~image: HTMLCanvasElement.t, ~init: videoFrameInit=?)`

Creates a new `VideoFrame` from an `HTMLCanvasElement`.

```res
let frame = VideoFrame.fromHTMLCanvasElement(~image=myCanvasElement)
```

[Read more on MDN](https://developer.mozilla.org/docs/Web/API/VideoFrame)
*/
@new
external make4: (
external fromHTMLCanvasElement: (
~image: WebApiDOM.Types.htmlCanvasElement,
~init: WebApiDOM.Types.videoFrameInit=?,
) => WebApiDOM.Types.videoFrame = "VideoFrame"

/**
`fromImageBitmap(~image: ImageBitmap.t, ~init: videoFrameInit=?)`

Creates a new `VideoFrame` from an `ImageBitmap`.

```res
let frame = VideoFrame.fromImageBitmap(~image=myImageBitmap)
```

[Read more on MDN](https://developer.mozilla.org/docs/Web/API/VideoFrame)
*/
@new
external make5: (
external fromImageBitmap: (
~image: Types.imageBitmap,
~init: WebApiDOM.Types.videoFrameInit=?,
) => WebApiDOM.Types.videoFrame = "VideoFrame"

/**
`fromOffscreenCanvas(~image: OffscreenCanvas.t, ~init: videoFrameInit=?)`

Creates a new `VideoFrame` from an `OffscreenCanvas`.

```res
let frame = VideoFrame.fromOffscreenCanvas(~image=myOffscreenCanvas)
```

[Read more on MDN](https://developer.mozilla.org/docs/Web/API/VideoFrame)
*/
@new
external make6: (
external fromOffscreenCanvas: (
~image: Types.offscreenCanvas,
~init: WebApiDOM.Types.videoFrameInit=?,
) => WebApiDOM.Types.videoFrame = "VideoFrame"

/**
`fromVideoFrame(~image: VideoFrame.t, ~init: videoFrameInit=?)`

Creates a new `VideoFrame` from another `VideoFrame`.

```res
let frame = VideoFrame.fromVideoFrame(~image=otherFrame)
```

[Read more on MDN](https://developer.mozilla.org/docs/Web/API/VideoFrame)
*/
@new
external make7: (
external fromVideoFrame: (
~image: WebApiDOM.Types.videoFrame,
~init: WebApiDOM.Types.videoFrameInit=?,
) => WebApiDOM.Types.videoFrame = "VideoFrame"

/**
`fromArrayBuffer(~data: ArrayBuffer.t, ~init: videoFrameBufferInit)`

Creates a new `VideoFrame` from `ArrayBuffer`-backed pixel data.

```res
let frame =
VideoFrame.fromArrayBuffer(~data=myArrayBuffer, ~init=myVideoFrameBufferInit)
```

[Read more on MDN](https://developer.mozilla.org/docs/Web/API/VideoFrame)
*/
@new
external make8: (
external fromArrayBuffer: (
~data: ArrayBuffer.t,
~init: WebApiDOM.Types.videoFrameBufferInit,
) => WebApiDOM.Types.videoFrame = "VideoFrame"

/**
`fromSharedArrayBuffer(~data: sharedArrayBuffer, ~init: videoFrameBufferInit)`

Creates a new `VideoFrame` from `SharedArrayBuffer`-backed pixel data.

```res
let frame =
VideoFrame.fromSharedArrayBuffer(
~data=mySharedArrayBuffer,
~init=myVideoFrameBufferInit,
)
```

[Read more on MDN](https://developer.mozilla.org/docs/Web/API/VideoFrame)
*/
@new
external make9: (
~data: WebApiBase.ArrayBufferTypedArrayOrDataView.t,
external fromSharedArrayBuffer: (
~data: sharedArrayBuffer,
~init: WebApiDOM.Types.videoFrameBufferInit,
) => WebApiDOM.Types.videoFrame = "VideoFrame"
Comment thread
jderochervlk marked this conversation as resolved.

/**
`fromDataView(~data: DataView.t, ~init: videoFrameBufferInit)`

Creates a new `VideoFrame` from `DataView`-backed pixel data.

```res
let frame =
VideoFrame.fromDataView(~data=myDataView, ~init=myVideoFrameBufferInit)
```

[Read more on MDN](https://developer.mozilla.org/docs/Web/API/VideoFrame)
*/
@new
external make10: (
external fromDataView: (
~data: DataView.t,
~init: WebApiDOM.Types.videoFrameBufferInit,
) => WebApiDOM.Types.videoFrame = "VideoFrame"
Expand Down
Loading