About Chrome and Chromium in Javascript / Web development and its Open source status

Over the recent weeks I have learned quite a share of useful commands and tools which are built in Chrome and Chromium right out of the box. This post is about documenting and sharing this information, in particular what it is like working with Chrome during web-development. What inspired me was finding out about the pretty print feature. Before that I cam accross JS-deobfuscator, and other web based pretty-printers like, jsbeautifier.org (which usually chocked after the 100th line of js-code). As a Chrome user, you will have all the tools right in front of you...

Introduction:

Note: Skip this paragraph if you are interested in using the Chome's developer tools.
Chrome is Google's version of a web browser, based on the open source WebKit layout engine. The project name was derived from the graphical user interface of Mozilla's browsers, which may in fact cause some confusion during web-research. (see here for instance). Chrome saw its first release on September 2nd, 2008, with subsequently quick adoption by the developer and user community. By now Chrome has scored roughly 25% of the worldwide usage share of web browsers ( Q3/2011 StatCounter).

Google's Open source endeavor is reflected in the Chromium project, which is an open source web browser project on which Chrome is based. Chromium snapshots appear hourly and are essentially the same sources on which Chrome is based, except for a a few extras, and plugins such as:
a Google's branding, auto-update mechanism, click-through licensing terms, usage-tracking, a built-in PDF viewer and bundling of the Adobe Flash Player (src: wikipedia).
So far ther is no discernable divide between Chrome and Chromium, with the slight addition of a pdf viewer for the former.
The native pdf viewer uses the 2D rendering frontend 'skia'.

Skia is a complete 2D graphic library for drawing Text, Geometries, and Images.  Features include:
  • 3x3 matrices w/ perspective antialiasing,
  • transparency, 
  • filters shaders, 
  • xfermodes, 
  • maskfilters, 
  • patheffects 


The interesting part: Device backends for Skia currently include: Raster OpenGL PDF.


Current versions of Chrome will render any pdf files send with the Mime type 'application/pdf' or embedded: So far however it seems that the pdf-plugin is closed source likely due to pdf's proprietary algorithms.  (And if I am not mistaken the pdf plugin is  based on Chromes Native Client - Pepper API, which I will test and report about soon.). There is an considerably advanced JavaScript project which attempts to render entire pdf's based on canvas and FileReader (binary data File handling), and Web Workers (multithreading) with all computations perfomed  in JavaScript. Apparently the developers ran into troubles with the limitations of canvas and also attempted SVG rendering. This makes pdf.js a great test case in terms of performance and resource consumption of canvas vs. SVG.

Overall the project is an impressive proof of concept: https://github.com/andreasgal/pdf.js/ . A demo of pdf.js is available here

Google hired its own developer team of javascript parser/compiler programmers to come up with what they called the V8 engine, without providing details in here. Most importantly it is open source, and provides sufficient documentation. Over the past two years tremendous differences in Javascript execution speed crystallized for specific tasks like object comparison (unpublished data). Overall this may result only in slight performance differences in a task-balanced js-script. However these differences may be decisive when it comes to highly specific algorithms within a loop carrying out many arithmetic operations. In such scenarios the idea is to plug into the computational power of JavaScript as a means to an end, rather than as a preferred choice. (there are many projects which demonstrates the performance issues of javascript: one such project is  ). I also read the myth (which I will delve into another time) over and over again that
 JIT compiled javascript can be as fast as unoptimized C, especially for numeric code (author: unknown).

As part of my research project which deals with large datasets of spectral data I am implementing simple spectral processing routines in JavaScript and in the near future in the sandboxed NaCl (native client). These processing algorithms fit the aforementioned profile of being repetitive, arithmetic in nature and specific in purpose.

For an overview of the currently most important major javascript engines visit the provided wikipedia articles:



Primarily I develop JS based applications with V8 and Presto, and cross-test with TraceMonkey.

 Chrome / Chromium - Tools

ALT+ESC will bring the currently active window to the background (Vista, Win 7), - useful if you have the web inspector detached.

SHIFT+ESC brings up a memory inspection window in Chrome (as seen in the picture, with the most important metrics in-view; about:memory or chrome://memory-redirect/ as URI will provide the same information as html and is far less useful). The memory view lets you quickly see if your script is running rampant on memory consumption. This is important when juggling with extensive canvas, FileReader and SVG operations. Many C,C++ developers are not immediately familiar how to declare variable scopes in a garbage friendly manner, and that some objects are best explicitly freed with the delete keyword.

Note: Delete will unset all references for the particular object of the objects, thus effectively flagging it for garbage collection. Since the browser environment is effectively a sandbox, flagging an object for garbage collection is pretty straight forward. Objects can be defined as frozen, etc... disallowing any manipulation including the deletion of the object.

Additionally, during some operations, for instance file operations, objects may be locked for deletion till a particular task has finished (reading of a large File, which involves OS-APIs on some level). Operations like that often manage their status-functionality-reciprocity through the callback-based binding of event handlers.

Chrome's console is actually HTML and javascript, with a lot of redundant and unefficient html markup.
Here is what a TypeError will 'cost' you in terms of DOM-resources...

with the result looking like this...


TypeError
  1. argumentsArray[2]
  2. message"—"
  3. stack"—"
  4. type"non_object_property_load"
  5. __proto__Error


The console is sufficiently fast, but it would be a mistake to assume that the console is anything like a command line. First off Chrome's, Operas (but to lesser extend) and Firebugs consoles are using a web frontend, and secondly provide a long or unlimited history for the current session.
There are JS-consoles however. Nodejs can be used for this purpose, which in conjunction with this code, allows you to redict code written to console.log to stdio. There are bindings for JS to Java, and C# as well (links not provided).

Opera's console is much leaner in the amount of markup it uses. You can get a quick picture of the speed by just running a simple statement that would be over within a second in any proper command line environment

An explicit project for the purpose of running JS on the command line (although a bit dated) is provided by mozilla in the form of Rhino Shell. (https://developer.mozilla.org/en/Rhino_Shell)

Note: Be careful with the interactive console. If you accidentally dump a vast object, the console-API will reflect upon each item and generate corresponding html based trees for it to allow 'pretty-printing', with the result of a memory leak-like effect. The console has no safeguard for large objects (yet), inquiring whether the user really wants to view the object's contents. It would be desirable in some circumstances to  relay the data to another output or pipe...

As expected program code entered in the console is free to execute without the often built in loop-checks ( dialog popup e.g. if a script consumes processing time for too long).

To enter a multiline statement in Chrome's JS -console or Opera, use SHIFT+ENTER. To execute the statement and put it on the running stack, press:

  • STRG+ ENTER in Opera
  • ENTER in Chrome


As a gimmick, Chrome allows to perform math calculations directly in the smart bar, - useless if you already have opened a javascript console. Unlike Opera which only permits one web inspector per process, Chrome allows a web inspector for each tab, which will run in the same process as the tab/window in which the web inspector is invoked.

Chrome / Chromium Console Details 

The web inspector can be toggled by pressing CTRL+SHIFT+I (same in Opera) with the DOM inspection tab in focus. CTRL+ SHIFT+ J will do the same with the JS-console focused and is thus preferable most of the time.  CTRL + SHIFT + C toggles will open with the Element mode foused

Once opened, press F1 or ? to get a shortcut-help overlay showing you the various commands for the active-tab. ESC will toggle the console, in any other tab than the console-tab. Here is an overview.

You can use the following commands in all tabs
Focus Search Box: Ctrl-F
Find Next    Ctrl-G
Find Previous:    Ctrl-Shift-G



Google packaged its console funcitonality into the scope 'window.console._commandLineAPI)', which is automatically resolved each time the JS-console is invoked through the keyword with:
window.console._commandLineAPI)


Here is a short overview:
All elements with id="idElement"-tags will be referenced by a variable named after the value of the id-tag, in this example: 'idElement'
Any element, selected (highlighted) in the Elements-tab will be assigned a reference '$n', where n is the first initially selected element (FILO like assignment).
$("elementName") and $$(cssSelector) jQuery-like selection is possible, provided that the id value is entered, dumping the HtmlElement object to the console whilst highlighting it in the document view.

In the following examples an element <div id="footer"...>.. is used, which is part of the documentview presented to the user whenever an empty tab is opened.
notice: window.console._commandLineAPI.footer is used!
keys(footer) || keys("footer")


>$0

  • <div id=?"footer">??</div>?

  • >$$("button")
    [
  • <button class=?"close-button">?</button>?
  • ,
  • <button id=?"page-switcher-start" class=?"page-switcher" style=?"width:? 225px;? left:? 0px;? ">??</button>?
  • ,
  • <button id=?"page-switcher-end" class=?"page-switcher" style=?"width:? 225px;? right:? 0px;? ">??</button>?
  • ,
  • <button id=?"recently-closed-menu-button">??</button>?
  • ]


    >keys(footer)
    ["clientLeft", "scrollHeight", "firstElementChild", "offsetWidth", "nodeType", "isContentEditable", "hidden", "previousElementSibling", "parentElement", "children", "webkitdropzone", "localName", "nodeValue", "lastElementChild", "offsetLeft", "tagName", "className", "prefix", "innerHTML", "previousSibling", "namespaceURI", "id", "childElementCount", "scrollLeft", "lastChild", "align", "innerText", "textContent", "nextSibling", "scrollWidth", "offsetHeight", "clientWidth", "nodeName", "style", "lang", "scrollTop", "offsetTop", "childNodes", "baseURI", "nextElementSibling", "classList", "title", "firstChild", "attributes", "dataset", "outerText", "parentNode", "clientTop", "tabIndex", "contentEditable", "dir", "outerHTML", "clientHeight", "ownerDocument", "offsetParent", "spellcheck", "draggable"]



    >values(footer)
    [0, 100,
  • <div id=?"footer-border">?</div>?
  • , 1536, 1, false, false,
  • <div id=?"card-slider-frame">??</div>?
  • ,
  • <body>??</body>?
  • ,
    HTMLCollection[2]
    , "", "div", null,
  • <div id=?"footer-content">??</div>?
  • , 0, "DIV", "", null, " <div id="footer-border"></div> <div id="footer-content"> <img id="logo-img" src="chrome://theme/IDR_PRODUCT_LOGO?1314458821197"> <ul id="dot-list"> <li class="dot" tabindex="0" role="button"><div class="selection-bar"></div><input spellcheck="false"></li><li class="dot selected" tabindex="0" role="button"><div class="selection-bar"></div><input spellcheck="false"></li><li class="dot" tabindex="0" role="button"><div class="selection-bar"></div><input spellcheck="false"></li></ul> <button id="recently-closed-menu-button"> <span i18n-content="recentlyclosed">Recently closed</span> <div class="disclosure-triangle"></div> </button> <div id="trash"> <span i18n-content="trashLabel">Remove from Chrome.</span> </div> </div> ",
    Text
    , "http://www.w3.org/1999/xhtml", "footer", 2, 0,
    Text
    , "", "

    dir(idName) and dirxml(idName) dump an HTMLElement object as a JavaScript or XML object, respectively. profile will start the profiling of the idElement.
    clear() will clear the console, copy

    These commands are essentially the same as in Firebug. See here for a command list.

    Audit:
    provides Information on the html / css /js markup improvement based on static look up tables

    Network:
    gives detailed insight into the information flow, and speed when a resource was transmitted

    clicking on it will open a side panel providing additional information like transmission headers and GET / PUT / POST / PUSH messages;
    Notice how chrome:// applications have virtually no header overhead, as they don't require HTTP

    Resource view, provides a list of all resources within a document-view

    The Elements view is one of the most important, right click an element to provide HTML editing, copying etc.. which will be translated to the corresponding DOM events and updates. You can add event handlers simply by entering the corresponding javascript e.g. HTMLElement.addEventHandler(...) or by directly entering the attributes in the Elements view in the corresponding Element (not shown).

    Lastly memory and CPU profiling is accessible by starting chrome with the flag chrome.exe --enable-memory-info
    This will then also allow access to the corresponding JS objects e.g. console.memory.usedJSHeapSize" and
    "console.memory.totalJSHeapSize" which will otherwise return 0 in all OS. With Chrome > 6 the memory objects is accessible in window.webkitPerformance

    In the Scripts-tab-view several small icons are located at the bottom left which are almost dismissed at first.
    There functions are from left to right:
    Undocking in a separate window
    Hiding the console (toogle it with ESC)
    Inspection of elements (via mouse-hover and left click to commit)
    Do not pause on all exceptions
    !!{} Pretty print modus, which formats (very successfully) compressed javascript code!!
    (This little button convinced me to write this article)


    Resources:

    Chrome Release Channels - The Chromium Projects
    Google Chrome Blog
    LihatTutupKomentar