the Chromium logo

The Chromium Projects

Blink-in-JavaScript

NOTE: THIS DOCUMENT IS NO LONGER VALID

It is left available out of historical interest.

Overview

Blink-in-JavaScript is a mechanism to enable Blink developers to implement DOM features in JavaScript (instead of C++). The goal of Blink-in-JS is to improve web layering by implementing high-level DOM features on top of existing web-exposed APIs. You can learn the design in this design document and this slide. If you are interested in the security model, you can also look at this document.

Guideline

When you want to implement a feature in Blink-in-JS, you need to follow the following guideline.

  1. If you plan to implement a feature in Blink-in-JS, you need to send an Intent-to-Implement to blink-dev@. The Intent-to-Implement should explain the advantages of the Blink-in-JS and have a list of private script APIs that will be required for the Blink-in-JS. (**)

  2. You are strongly discouraged to use private script APIs. If you need to add a private script API, you need to provide a justification for the API and get an LGTM from one API owner (***). The API must meet either of the following conditions:

    • The API is a missing part of the current web and going to be exposed to the web in the future.
    • The API is for supporting a will-be-deprecated feature.

(*) See this slide for a background of this guideline.

(**) The fact that we’re lowering the priority of Blink-in-JS means that we are going to be conservative about accepting your Intent-to-Implement. It is important to consider if your Blink-in-JS work has higher impact than other projects you could work on alternately. The Intent-to-Implement must provide clear advantages of why you think it is important for Blink to implement the feature in Blink-in-JS. For example, the following Intent-to-Implements look appealing:

On the other hand, the following Intent-to-Implement would not be appealing:

(Note: These are just examples and not intending to imply go or non-go of MediaControls-in-JS etc)

(***) It is a good idea to ask review for dglazkov@ (API owner), jochen@ (API owner), haraken@ and area experts of the API.

Basics

The most common usage of Blink-in-JS is to implement DOM features defined in an IDL file in JavaScript. For example, consider to implement a <marquee> tag in Blink-in-JS.

In this case, what you need to do is just to:

Specifically, you first need to add [ImplementedInPrivateScript] IDL extended attributes to DOM attributes/methods in HTMLMarqueeElement.idl.

interface HTMLMarqueeElement : HTMLElement {
  [ImplementedInPrivateScript] void start();
  [ImplementedInPrivateScript] void stop();
  [ImplementedInPrivateScript] attribute long loop;
  [ImplementedInPrivateScript] attribute long scrollAmount;
  ...;
};

Second, you need to implement the DOM attributes/methods in HTMLMarqueeElement.js.

installClass("HTMLMarqueeElement", function(HTMLMarqueeElementPrototype)) {
  HTMLMarqueeElementPrototype.start = function() {
    // Implement the start() method.
    // |this| object is equal to the wrapper of the <marquee> element.
  }
  Object.defineProperty(HTMLMarqueeElementPrototype, 'loop', {
      get: function() {
        // Implement the getter of the loop attribute.
        // |this| object is equal to the wrapper of the <marquee> element.
      },
      set: function(value) {
        // Implement the setter of the loop attribute.
        // |this| object is equal to the wrapper of the <marquee> element.
      },
  });
  ...; // Implement other DOM attributes/methods.
};

That's it. Then the IDL compiler auto-generates the binding code that connects user's script with the JavaScript functions defined in the private script.

The important points are as follows:

For more details, you can look at how HTMLMarqueeElement.js and PrivateScriptTest.js are implemented.

Details

By using the [ImplementedInPrivateScript] IDL extended attribute, you can implement DOM features exposed to the web in a private script. However, this is sometimes not sufficient to implement real-world DOM features in a private script. Sometimes you will need to invoke a private script from C++. Sometimes you will need to implement internal DOM attributes/methods that are only exposed to private scripts.

In general, Blink-in-JS supports the following four kinds of APIs.

You can control the kind of each API by combining the [ImplementedInPrivateScript] IDL extended attribute and [OnlyExposedToPrivateScript] IDL attribute.

Here is an example:

interface XXX {
  void f1();  // Normal DOM method implemented in C++; exposed to user's script and private scripts.
  [ImplementedInPrivateScript] void f2();  // DOM method implemented in a private script; exposed to user's script and private scripts.
  [OnlyExposedToPrivateScript] void f3();  // DOM method implemented in C++; exposed only to private scripts.
  [ImplementedInPrivateScript, OnlyExposedToPrivateScript] void f4();  // DOM method implemented in a private script; V8XXX::PrivateScript::f4Method() is provided as a static method so that Blink can invoke the private script.
};

For more details, see test cases in PrivateScriptTest.idl.

DOM attributes/methods that have [OnlyExposedToPrivateScript] IDL attribute are "backdoors". Backdoors are strongly discouraged unless you are certain that the backdoors are APIs that are missing in the current web platform and should be exposed to the web in the future. Ideally Blink-in-JS should be implemented only by using existing web platform APIs. The only case where backdoors are allowed is a case where we think that the API is a missing part of the current web platform and should be exposed to the web in the future. (One of the goals of Blink-in-JS is to understand what APIs are missing in the web platform by trying to implement built-in contents of Blink in JavaScript.)

Where Your Private Script lives?

Your private script lives in blink_resources.pak in out/*config*/gen/blink/public/resources/, which is generated by blink_resouces.gyp, then it repacked into content_shell.pak, resources.pak and so.

So, you need to do following steps putting your private script into resource file:

  1. Change blink_resources.grd in Blink repository to include your private script, e.g. crrev/570863002
    • Since we also need to change file in Chromium repository, I recommend to create dummy file and check-in this before reviewing your private script.
  2. Change content/child/blink_platform_impl.cc in Chromium repository, e.g. crrev/556793006
    • You should wait step #1 blink change is rolled into Chromium rather than landed into blink repository.

Note: Due to crbug/415908, blink_resources.pak isn't rebuild when your private script file changed. You may want to remove it, out/Debug/gen/blink/public/resources/blink_resources.pak.

Contacts

If you have any questions or comments, feel to free to ask haraken@. I'm planning to factor out more things from C++ to Blink-in-JS to improve the hackability of the Blink core. Your contributions are super welcome!