A user account is required in order to edit this wiki, but we've had to disable public user registrations due to spam.

To request an account, ask an autoconfirmed user on Chat (such as one of these permanent autoconfirmed members).

Component Model IDL Brainstorming: Difference between revisions

From WHATWG Wiki
Jump to navigation Jump to search
mNo edit summary
 
(2 intermediate revisions by the same user not shown)
Line 1: Line 1:
[[User:Rolandsteiner|RolandSteiner]] This may be obsoleted by the Proxy approach for isolation.
= Overview =
= Overview =


Line 14: Line 16:
* Not component-specific, could be used for workers, <code>&lt;iframes&gt;</code>, intents
* Not component-specific, could be used for workers, <code>&lt;iframes&gt;</code>, intents
* Same definitions can be used cross-language (not limited to JavaScript)
* Same definitions can be used cross-language (not limited to JavaScript)
= Example =
The following could be the IDL declaration for a contact in a contact list. User-defined names MUST start with an upper case letter.
  &lt;idl name="Contact" type="object"&gt;
            &lt;property name="firstName" type="string" optional/&gt;
            &lt;property name="lastName" type="string" optional/&gt;
            &lt;property name="name" type="string" get="getName"/&gt;
            &lt;property name="phone" type="string" optional/&gt;
            &lt;property name="email" type="string" optional/&gt;
  &lt;/idl&gt;
The contact list itself can make use of this type:
  &lt;idl name="ContactList" type="interface"&gt;
      &lt;function name="addContact" type="unsigned long"&gt; <!-- returns index -->
          &lt;param name="contact" type="Contact" throws="OUT_OF_BOUNDS_EXCEPTION"/&gt;
          &lt;param name="index" type="unsigned integer" optional/&gt;
      &lt;/function&gt;
      &lt;function name="removeContact" type="unsigned long" throws="OUT_OF_BOUNDS_EXCEPTION"&gt; <!-- requires index, throws if out of bounds -->
          &lt;param name="index" type="unsigned integer"&gt;
      &lt;/function&gt;
      &lt;function name="clear" type="void"/&gt;
      &lt;property name="selectedIndex" type="unsigned integer" get set throws="OUT_OF_BOUNDS_EXCEPTION"/&gt;
  &lt;/idl&gt;
Also, setting up a user-defined event to communicate between a contact and a contact list:
  &lt;idl name="ContactSelectedEvent" type="event"&gt;
      &lt;property name="index" type="unsigned integer"/&gt;
  &lt;/idl&gt;
Using the above types, we declare a component that implements a single contact:
  &lt;element name="x-contact" class="ContactElement"&gt;
      &lt;implements idl="Contact"/&gt;
      &lt;events&gt;
          &lt;listen type="click"/&gt;
          &lt;emit type="ContactSelectedEvent"/&gt;
      &lt;events&gt;
      &lt;script type="javascript"&gt;
          function onclick() { dispatchEvent(new ContactSelectedEvent()); }
          get name() { var s = ""; if (firstName) s = firstName; if (s && lastName) s += " "; if (lastName) s += lastName; return lastName; }
      &lt;/script&gt;
      &lt;template&gt;
          &lt;div&gt;
              ... nicely formatted contact here ...
          &lt;/div&gt;
      &lt;/template&gt;
  &lt;/element&gt;
... and an element that handles the whole list:
  &lt;element name="x-contactlist" class="ContactListElement"&gt;
      &lt;implements idl="ContactList"/&gt;
      &lt;events&gt;
          &lt;listen type="ContactSelectedEvent"/&gt;
      &lt;events&gt;
      &lt;script type="javascript"&gt;
          function onContactSelectedEvent(evt) {
          }
          function addContact(contact, index) {
              appendChild(new ContactElement());
          }
          function removeContact(index) {
              ...
          }
          function clear(evt) {
              ...
          }
      &lt;/script&gt;
      &lt;template&gt;
          &lt;div&gt;
              ... nicely formatted contact list here, consisting of &lt;x-contact&gt; elements ...
          &lt;/div&gt;
      &lt;/template&gt;
  &lt;/element&gt;
<span style="color: darkred">'''ISSUE:'''</span> Avoid the complexity of [https://developer.mozilla.org/en/XBL/XBL_1.0_Reference/Elements#handler XBL1's <code>handler</code> element]!
== Conversion Example ==
The above could be converted to the following boilerplate by the browser, in the case of confined components:
=== Document side ===
  class Contact
  {
    firstName: null,
    lastName: null,
    phone: null,
    email: null,
  }
  class ContactElement
  {
    constructor() {
      HTMLElement.call(this);
      addEventListener('click', onclick);
    }
    function addContact(contact, index) { /* native implementation, calling addContact on the shadow tree, return value is deferred */ }
    function removeContact(index) { /* native implementation, calling removeContact on the shadow tree */ }
    function clear() { /* native implementation, calling clear on the shadow tree */ }
    get selectedIndex() { /* native implementation, calling the getter for selectedIndex on the shadow tree, return value is deferred */ }
    set selectedIndex(value) { /* native implementation, calling the setter for selectedIndex on the shadow tree */ }
  }
  Element.register('x-contact', ContactElement);
  class ContactListElement
  {
    constructor() {
      HTMLElement.call(this);
    }
    function addContact(contact, index) { /* native implementation, calling addContact on the shadow tree, return value is deferred */ }
    function removeContact(index) { /* native implementation, calling removeContact on the shadow tree */ }
    function clear() { /* native implementation, calling clear on the shadow tree */ }
    get selectedIndex() { /* native implementation, calling the getter for selectedIndex on the shadow tree, return value is deferred */ }
    set selectedIndex(value) { /* native implementation, calling the setter for selectedIndex on the shadow tree */ }
  }
  Element.register('x-contact', ContactElement);

Latest revision as of 19:40, 26 October 2011

RolandSteiner This may be obsoleted by the Proxy approach for isolation.

Overview

Components, along with other web constructs such as workers and <iframe> elements, may benefit from having their interfaces declared explicitly. This would be especially useful in the case of confined components, who cannot be trusted to run scripts to effect subclassing and forwarding function calls between the hosting element and the shadow DOM. The following is therefore a proposal for a declarative way to define the interface, that the browser then can safely inspect and use as a basis to set up such forwarding automatically.

Perceived Advantages

All of the following may look very verbose, and could probably be implemented much quicker in pure JavaScript. However, this approach still conceivably has the following advantages:

  • Can be used where JavaScript cannot be run, e.g. due to confinement
    • Browser can automatically use the definitions to set up and abstract away postMessage() calls, etc., that are necessary to bridge the separation
    • Browser can even use magic to handle the forwarding and does not have to rely on postMessage() or other functions available in JavaScript
  • Not component-specific, could be used for workers, <iframes>, intents
  • Same definitions can be used cross-language (not limited to JavaScript)