Skip to content

Commit 2240850

Browse files
authored
Merge pull request #255 from rescript-lang/codex/issue-236-constructor-from-names-carryover
refactor: rename overloaded constructors to from* names [codex]
2 parents 51331e3 + 9e2cdad commit 2240850

21 files changed

Lines changed: 502 additions & 34 deletions

File tree

docs/content/docs/contributing/api-modelling.mdx

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,48 @@ external addEventListenerWithCapture: (
5858

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

61+
### Constructor overloads
62+
63+
Constructors follow a different naming rule than methods.
64+
65+
- Keep singleton constructors named `make`.
66+
- Keep true no-argument default constructors named `make`, even when the constructor family also has typed overloads.
67+
- When a constructor family does not have a default constructor, use `from*` names for every overload, including the first one.
68+
- Base `from*` names on the source input type: `fromString`, `fromArrayBuffer`, `fromMediaStream`, `fromURLWithProtocols`, and so on.
69+
- 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`.
70+
71+
For example, these constructor families are easier to understand than numbered overloads:
72+
73+
```ReScript
74+
@new
75+
external fromString: (~family: string, ~source: string) => fontFace = "FontFace"
76+
77+
@new
78+
external fromDataView: (~family: string, ~source: DataView.t) => fontFace = "FontFace"
79+
80+
@new
81+
external fromArrayBuffer: (~family: string, ~source: ArrayBuffer.t) => fontFace = "FontFace"
82+
```
83+
84+
And if a constructor really does have a default form, split it instead of hiding it:
85+
86+
```ReScript
87+
@new
88+
external make: unit => domMatrix = "DOMMatrix"
89+
90+
@new
91+
external fromString: string => domMatrix = "DOMMatrix"
92+
93+
@new
94+
external fromArray: array<float> => domMatrix = "DOMMatrix"
95+
```
96+
97+
Single-source constructor variants should take the source value directly without a label.
98+
99+
Keep `makeWith*` names for non-default convenience constructors that are not part of a source-type overload family.
100+
101+
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.
102+
61103
### Decoded variants
62104

63105
We can be pragmatic with overloaded functions and use model them in various creative ways.

docs/content/docs/contributing/documentation.mdx

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ It keeps the user inside the IDE and avoids context switching.
2121
The documentation for each binding should roughly follow this structure:
2222

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

@@ -44,3 +44,25 @@ window->Window.fetch("https://rescript-lang.org")
4444
external fetch: (window, string, ~init: requestInit=?)
4545
=> promise<response> = "fetch"
4646
````
47+
48+
Constructor overloads should use the same structure, but keep the description concise and let the signature and example show the input shape.
49+
Use backticks for specific types and names.
50+
If a constructor variant has a single source input, show it as a direct unlabeled argument in both the signature and example.
51+
52+
````ReScript
53+
/*
54+
`fromArray(array<float>)`
55+
56+
Creates a new `DOMMatrix` from an array of matrix component values.
57+
58+
```res
59+
let matrix = DOMMatrix.fromArray([1., 0., 0., 1., 0., 0.])
60+
```
61+
62+
[Read more on MDN](https://developer.mozilla.org/docs/Web/API/DOMMatrix)
63+
*/
64+
@new
65+
external fromArray: array<float> => domMatrix = "DOMMatrix"
66+
````
67+
68+
For now, these examples stay compile-coverage oriented. Runtime verification of constructor behavior will be handled later via Vitest and happy-dom.

packages/CSSFontLoading/src/FontFace.res

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,55 @@
11
/**
2+
`fromString(~family: string, ~source: string, ~descriptors: fontFaceDescriptors=?)`
3+
4+
Creates a new `FontFace` from CSS source text.
5+
6+
```res
7+
let fontFace =
8+
FontFace.fromString(~family="Inter", ~source="url(/fonts/inter.woff2)")
9+
```
10+
211
[Read more on MDN](https://developer.mozilla.org/docs/Web/API/FontFace)
312
*/
413
@new
5-
external make: (
14+
external fromString: (
615
~family: string,
716
~source: string,
817
~descriptors: Types.fontFaceDescriptors=?,
918
) => Types.fontFace = "FontFace"
1019

1120
/**
21+
`fromDataView(~family: string, ~source: DataView.t, ~descriptors: fontFaceDescriptors=?)`
22+
23+
Creates a new `FontFace` from `DataView`-backed font data.
24+
25+
```res
26+
let fontFace =
27+
FontFace.fromDataView(~family="Inter", ~source=myDataView)
28+
```
29+
1230
[Read more on MDN](https://developer.mozilla.org/docs/Web/API/FontFace)
1331
*/
1432
@new
15-
external make2: (
33+
external fromDataView: (
1634
~family: string,
1735
~source: DataView.t,
1836
~descriptors: Types.fontFaceDescriptors=?,
1937
) => Types.fontFace = "FontFace"
2038

2139
/**
40+
`fromArrayBuffer(~family: string, ~source: ArrayBuffer.t, ~descriptors: fontFaceDescriptors=?)`
41+
42+
Creates a new `FontFace` from `ArrayBuffer`-backed font data.
43+
44+
```res
45+
let fontFace =
46+
FontFace.fromArrayBuffer(~family="Inter", ~source=myArrayBuffer)
47+
```
48+
2249
[Read more on MDN](https://developer.mozilla.org/docs/Web/API/FontFace)
2350
*/
2451
@new
25-
external make3: (
52+
external fromArrayBuffer: (
2653
~family: string,
2754
~source: ArrayBuffer.t,
2855
~descriptors: Types.fontFaceDescriptors=?,

packages/Canvas/src/Path2D.res

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,46 @@
11
type domMatrix2DInit = WebApiDOM.Types.domMatrix2DInit
22

33
/**
4+
`make()`
5+
6+
Creates a new empty `Path2D`.
7+
8+
```res
9+
let path = Path2D.make()
10+
```
11+
12+
[Read more on MDN](https://developer.mozilla.org/docs/Web/API/Path2D)
13+
*/
14+
@new
15+
external make: unit => Types.path2D = "Path2D"
16+
17+
/**
18+
`fromPath2D(path2D)`
19+
20+
Creates a new `Path2D` by copying another `Path2D`.
21+
22+
```res
23+
let copiedPath = Path2D.fromPath2D(existingPath)
24+
```
25+
426
[Read more on MDN](https://developer.mozilla.org/docs/Web/API/Path2D)
527
*/
628
@new
7-
external make: (~path: Types.path2D=?) => Types.path2D = "Path2D"
29+
external fromPath2D: Types.path2D => Types.path2D = "Path2D"
830

931
/**
32+
`fromString(string)`
33+
34+
Creates a new `Path2D` from SVG path data text.
35+
36+
```res
37+
let path = Path2D.fromString("M0 0 L10 10")
38+
```
39+
1040
[Read more on MDN](https://developer.mozilla.org/docs/Web/API/Path2D)
1141
*/
1242
@new
13-
external make2: (~path: string=?) => Types.path2D = "Path2D"
43+
external fromString: string => Types.path2D = "Path2D"
1444

1545
/**
1646
[Read more on MDN](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/closePath)

packages/Canvas/src/VideoFrame.res

Lines changed: 94 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,172 @@
11
/**
2+
`fromHTMLImageElement(~image: HTMLImageElement.t, ~init: videoFrameInit=?)`
3+
4+
Creates a new `VideoFrame` from an `HTMLImageElement`.
5+
6+
```res
7+
let frame = VideoFrame.fromHTMLImageElement(~image=myImageElement)
8+
```
9+
210
[Read more on MDN](https://developer.mozilla.org/docs/Web/API/VideoFrame)
311
*/
412
@new
5-
external make: (
13+
external fromHTMLImageElement: (
614
~image: WebApiDOM.Types.htmlImageElement,
715
~init: WebApiDOM.Types.videoFrameInit=?,
816
) => WebApiDOM.Types.videoFrame = "VideoFrame"
917

1018
/**
19+
`fromSVGImageElement(~image: SVGImageElement.t, ~init: videoFrameInit=?)`
20+
21+
Creates a new `VideoFrame` from an `SVGImageElement`.
22+
23+
```res
24+
let frame = VideoFrame.fromSVGImageElement(~image=mySvgImageElement)
25+
```
26+
1127
[Read more on MDN](https://developer.mozilla.org/docs/Web/API/VideoFrame)
1228
*/
1329
@new
14-
external make2: (
30+
external fromSVGImageElement: (
1531
~image: WebApiDOM.Types.svgImageElement,
1632
~init: WebApiDOM.Types.videoFrameInit=?,
1733
) => WebApiDOM.Types.videoFrame = "VideoFrame"
1834

1935
/**
36+
`fromHTMLVideoElement(~image: HTMLVideoElement.t, ~init: videoFrameInit=?)`
37+
38+
Creates a new `VideoFrame` from an `HTMLVideoElement`.
39+
40+
```res
41+
let frame = VideoFrame.fromHTMLVideoElement(~image=myVideoElement)
42+
```
43+
2044
[Read more on MDN](https://developer.mozilla.org/docs/Web/API/VideoFrame)
2145
*/
2246
@new
23-
external make3: (
47+
external fromHTMLVideoElement: (
2448
~image: WebApiDOM.Types.htmlVideoElement,
2549
~init: WebApiDOM.Types.videoFrameInit=?,
2650
) => WebApiDOM.Types.videoFrame = "VideoFrame"
2751

2852
/**
53+
`fromHTMLCanvasElement(~image: HTMLCanvasElement.t, ~init: videoFrameInit=?)`
54+
55+
Creates a new `VideoFrame` from an `HTMLCanvasElement`.
56+
57+
```res
58+
let frame = VideoFrame.fromHTMLCanvasElement(~image=myCanvasElement)
59+
```
60+
2961
[Read more on MDN](https://developer.mozilla.org/docs/Web/API/VideoFrame)
3062
*/
3163
@new
32-
external make4: (
64+
external fromHTMLCanvasElement: (
3365
~image: WebApiDOM.Types.htmlCanvasElement,
3466
~init: WebApiDOM.Types.videoFrameInit=?,
3567
) => WebApiDOM.Types.videoFrame = "VideoFrame"
3668

3769
/**
70+
`fromImageBitmap(~image: ImageBitmap.t, ~init: videoFrameInit=?)`
71+
72+
Creates a new `VideoFrame` from an `ImageBitmap`.
73+
74+
```res
75+
let frame = VideoFrame.fromImageBitmap(~image=myImageBitmap)
76+
```
77+
3878
[Read more on MDN](https://developer.mozilla.org/docs/Web/API/VideoFrame)
3979
*/
4080
@new
41-
external make5: (
81+
external fromImageBitmap: (
4282
~image: Types.imageBitmap,
4383
~init: WebApiDOM.Types.videoFrameInit=?,
4484
) => WebApiDOM.Types.videoFrame = "VideoFrame"
4585

4686
/**
87+
`fromOffscreenCanvas(~image: OffscreenCanvas.t, ~init: videoFrameInit=?)`
88+
89+
Creates a new `VideoFrame` from an `OffscreenCanvas`.
90+
91+
```res
92+
let frame = VideoFrame.fromOffscreenCanvas(~image=myOffscreenCanvas)
93+
```
94+
4795
[Read more on MDN](https://developer.mozilla.org/docs/Web/API/VideoFrame)
4896
*/
4997
@new
50-
external make6: (
98+
external fromOffscreenCanvas: (
5199
~image: Types.offscreenCanvas,
52100
~init: WebApiDOM.Types.videoFrameInit=?,
53101
) => WebApiDOM.Types.videoFrame = "VideoFrame"
54102

55103
/**
104+
`fromVideoFrame(~image: VideoFrame.t, ~init: videoFrameInit=?)`
105+
106+
Creates a new `VideoFrame` from another `VideoFrame`.
107+
108+
```res
109+
let frame = VideoFrame.fromVideoFrame(~image=otherFrame)
110+
```
111+
56112
[Read more on MDN](https://developer.mozilla.org/docs/Web/API/VideoFrame)
57113
*/
58114
@new
59-
external make7: (
115+
external fromVideoFrame: (
60116
~image: WebApiDOM.Types.videoFrame,
61117
~init: WebApiDOM.Types.videoFrameInit=?,
62118
) => WebApiDOM.Types.videoFrame = "VideoFrame"
63119

64120
/**
121+
`fromArrayBuffer(~data: ArrayBuffer.t, ~init: videoFrameBufferInit)`
122+
123+
Creates a new `VideoFrame` from `ArrayBuffer`-backed pixel data.
124+
125+
```res
126+
let frame =
127+
VideoFrame.fromArrayBuffer(~data=myArrayBuffer, ~init=myVideoFrameBufferInit)
128+
```
129+
65130
[Read more on MDN](https://developer.mozilla.org/docs/Web/API/VideoFrame)
66131
*/
67132
@new
68-
external make8: (
133+
external fromArrayBuffer: (
69134
~data: ArrayBuffer.t,
70135
~init: WebApiDOM.Types.videoFrameBufferInit,
71136
) => WebApiDOM.Types.videoFrame = "VideoFrame"
72137

73138
/**
139+
`fromTypedArray(~data: TypedArray.t<'t>, ~init: videoFrameBufferInit)`
140+
141+
Creates a new `VideoFrame` from typed-array-backed pixel data.
142+
143+
```res
144+
let frame =
145+
VideoFrame.fromTypedArray(~data=myTypedArray, ~init=myVideoFrameBufferInit)
146+
```
147+
74148
[Read more on MDN](https://developer.mozilla.org/docs/Web/API/VideoFrame)
75149
*/
76150
@new
77-
external make9: (
78-
~data: WebApiBase.ArrayBufferTypedArrayOrDataView.t,
151+
external fromTypedArray: (
152+
~data: TypedArray.t<'t>,
79153
~init: WebApiDOM.Types.videoFrameBufferInit,
80154
) => WebApiDOM.Types.videoFrame = "VideoFrame"
81155

82156
/**
157+
`fromDataView(~data: DataView.t, ~init: videoFrameBufferInit)`
158+
159+
Creates a new `VideoFrame` from `DataView`-backed pixel data.
160+
161+
```res
162+
let frame =
163+
VideoFrame.fromDataView(~data=myDataView, ~init=myVideoFrameBufferInit)
164+
```
165+
83166
[Read more on MDN](https://developer.mozilla.org/docs/Web/API/VideoFrame)
84167
*/
85168
@new
86-
external make10: (
169+
external fromDataView: (
87170
~data: DataView.t,
88171
~init: WebApiDOM.Types.videoFrameBufferInit,
89172
) => WebApiDOM.Types.videoFrame = "VideoFrame"

0 commit comments

Comments
 (0)