ceylon-sdk icon indicating copy to clipboard operation
ceylon-sdk copied to clipboard

Improve browser interop

Open bjansen opened this issue 8 years ago • 3 comments

@gdejohn pointed out that it's currently not possible to retrieve the value of an <input> field. This is because the following method:

shared formal Element? getElementById(String elementId);

will always return an instance of Element, not any of its subclasses. IIRC this is because dynamic interfaces use dressed objects (same problem as in this issue: https://github.com/ceylon/ceylon-sdk/issues/506).

This means even if we had classes for Form, Input etc, we couldn't cast them like this:

if (is Input input = document.getElementById("myInput")) {
}

And since document.getElementById("myInput")?.getAttribute("value") does not return the "live" value, we have to use dynamic blocks like this instead:

value task = document.createElement("li");
dynamic input = document.getElementById("task");
dynamic {
    task.textContent = input.\ivalue;
}

@chochos do you think it would be possible to do something like this:

  • build some kind of factory where we can "register" custom implementations of Element ("input" -> Input, "form" -> Form``)
  • every time a dynamic interface returns an Element, use this factory to instantiate the correct subtype of Element, based on the tag name, and default to Element

This means we can register standard HTML tags in ceylon.interop.browser, but also let users register their own non-standard tags.

bjansen avatar May 04 '16 06:05 bjansen

IIRC this is because dynamic interfaces use dressed objects

What in god's name is a "dressed object"?

we couldn't cast them like this

You can't cast dynamic objects because they themselves don't know what type they are. You can, however, assign them to any type from within a dynamic block.

gavinking avatar May 04 '16 07:05 gavinking

I proposed a different solution to this in ceylon/ceylon#6185.

You can, however, assign them to any type from within a dynamic block.

Correct, and this is where the JS compiler inserts a call to dress up the object (the function is called dre$$). Now the object has the type which it was assigned to, and can never have a different type.

lucaswerkmeister avatar May 04 '16 07:05 lucaswerkmeister

@gavinking we came up with this dressing of objects when we first implemented dynamic interfaces. See ceylon/ceylon#3806 and ceylon/ceylon#2793

chochos avatar May 04 '16 14:05 chochos