Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "Use instanceof to safely downcast (#182)" #6

Merged
merged 1 commit into from
Aug 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
29 changes: 16 additions & 13 deletions src/Webapi/Canvas/Webapi__Canvas__Canvas2d.re
Original file line number Diff line number Diff line change
Expand Up @@ -112,22 +112,25 @@ let setFillStyle = (type a, ctx: t, _: style(a), v: a) =>
setFillStyle(ctx, v);

let reifyStyle = (type a, x: 'a) : (style(a), a) => {
let isCanvasGradient: 'a => bool = [%raw {|
function(x) { return x instanceof CanvasGradient; }
|}];

let isCanvasPattern: 'a => bool = [%raw {|
function(x) { return x instanceof CanvasPattern; }
|}];
module Internal = {
type constructor;
[@bs.val] external canvasGradient : constructor = "CanvasGradient"; /* internal */
[@bs.val] external canvasPattern : constructor = "CanvasPattern"; /* internal */
let instanceOf: ('a, constructor) => bool = [%bs.raw {|function(x,y) {return +(x instanceof y)}|}]; /* internal */
};

(
if (Js.typeof(x) == "string") Obj.magic(String)
else if (isCanvasGradient(x)) Obj.magic(Gradient)
else if (isCanvasPattern(x)) Obj.magic(Pattern)
else invalid_arg(
"Unknown canvas style kind. Known values are: String, CanvasGradient, CanvasPattern"),
if (Js.typeof(x) == "string") {
Obj.magic(String)
} else if (Internal.instanceOf(x, Internal.canvasGradient)) {
Obj.magic(Gradient)
} else if (Internal.instanceOf(x, Internal.canvasPattern)) {
Obj.magic(Pattern)
} else {
raise(Invalid_argument("Unknown canvas style kind. Known values are: String, CanvasGradient, CanvasPattern"))
},
Obj.magic(x)
);
)
};

[@bs.get] external fillStyle : t => 'a = "fillStyle";
Expand Down
22 changes: 9 additions & 13 deletions src/Webapi/Dom/Webapi__Dom__Document.re
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
module Impl = (T: {type t;}) => {
external asDocument : T.t => Dom.document = "%identity";

let asHtmlDocument: T.t => option(Dom.htmlDocument) = [%raw {|
function(document) {
var defaultView = document.defaultView;

if (defaultView != null) {
var HTMLDocument = defaultView.HTMLDocument;

if (HTMLDocument != null && document instanceof HTMLDocument) {
return document;
}
}
let asHtmlDocument: T.t => Js.null(Dom.htmlDocument) = [%raw
{|
function (document) {
return document.doctype.name === "html" ? document : null;
}
|}];
|}
];
[@deprecated "Will fail if no doctype is defined, consider using unsafeAsHtmlDocument instead"]
let asHtmlDocument: T.t => option(Dom.htmlDocument) =
(self) => Js.Null.toOption(asHtmlDocument(self));

/** Unsafe cast, use [ashtmlDocument] instead */
external unsafeAsHtmlDocument : T.t => Dom.htmlDocument = "%identity";

let ofNode = (node: Dom.node) : option(T.t) =>
Expand Down
27 changes: 10 additions & 17 deletions src/Webapi/Dom/Webapi__Dom__Element.re
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,18 @@ let ofNode = (node: Dom.node) : option('a) =>
None;

module Impl = (T: {type t;}) => {
let asHtmlElement: T.t => option(Dom.htmlElement) = [%raw {|
function(element) {
var ownerDocument = element.ownerDocument;

if (ownerDocument != null) {
var defaultView = ownerDocument.defaultView;

if (defaultView != null) {
var HTMLElement = defaultView.HTMLElement;

if (HTMLElement != null && element instanceof HTMLElement) {
return element;
}
}
}
let asHtmlElement: T.t => Js.null(Dom.htmlElement) = [%raw
{|
function (element) {
// BEWARE: Assumes "contentEditable" uniquely identifies an HTMLELement
return element.contentEditable !== undefined ? element : null;
}
|}];
|}
];
[@deprecated "asHtmlElement uses a weak heuristic, consider using unsafeAsHtmlElement instead"]
let asHtmlElement: T.t => option(Dom.htmlElement) =
(self) => Js.Null.toOption(asHtmlElement(self));

/** Unsafe cast, use [asHtmlElement] instead */
external unsafeAsHtmlElement : T.t => Dom.htmlElement = "%identity";

let ofNode: Dom.node => option(T.t) = ofNode;
Expand Down
11 changes: 10 additions & 1 deletion src/Webapi/Dom/Webapi__Dom__HtmlElement.re
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
module Impl = (T: {type t;}) => {
type t_htmlElement = T.t;

let ofElement = Webapi__Dom__Element.asHtmlElement;
let ofElement: Dom.element => Js.null(t_htmlElement) = [%bs.raw
{|
function (element) {
// BEWARE: Assumes "contentEditable" uniquely identifies an HTMLELement
return element.contentEditable !== undefined ? element : null;
}
|}
];
[@deprecated "Consider using Element.asHtmlElement or Element.unsafeAsHtmlElement instead"]
let ofElement: Dom.element => option(t_htmlElement) = (self) => Js.Null.toOption(ofElement(self));

[@bs.get] external accessKey : t_htmlElement => string = "accessKey";
[@bs.set] external setAccessKey : (t_htmlElement, string) => unit = "accessKey";
Expand Down
14 changes: 5 additions & 9 deletions tests/Webapi/Dom/Webapi__Dom__DomStringMap__test.re
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,9 @@ open Webapi.Dom.DomStringMap;
let dataset =
document
|> Document.createElement("div")
|> Element.asHtmlElement
|> Belt.Option.map(_, HtmlElement.dataset);
|> Element.unsafeAsHtmlElement
|> HtmlElement.dataset;

let () = switch (dataset) {
| Some(dataset) =>
set("fooKey", "barValue", dataset);
dataset |> get("fooKey") |> ignore;
unsafeDeleteKey("fooKey", dataset);
| None => ()
};
let () = set("fooKey", "barValue", dataset);
let _ = get("fooKey", dataset);
let () = unsafeDeleteKey("fooKey", dataset);