How to Use the HTML5 Full-Screen API (Again)


If you don’t like change, perhaps web development isn’t for you. I previously described the Full-Screen API in late 2012 and, while I claimed the implementation details were subject to revision, I didn’t think I’d need a rewrite a year later! This may not be the last, but many thanks to David Storey for highlighting the recent technical transitions…

What is the Full-Screen API?

The API allows a single element to be viewed full-screen. Unlike pressing F11 to force your browser to full-screen, the API is intended for images, videos and games running within a container. When you enter full-screen mode, a message informs the user they can press ESC at any time to return to the page.

The Full-Screen API is now supported by all recent desktop browsers, including IE11. There’s little support on mobile, but those browsers normally run in an almost full-screen view. Unfortunately, we have subtle differences, prefixing requirements, and cross-browser inconsistencies to solve…

The JavaScript API

Assume we have an image with the ID myimage, which we want to view full-screen. The main methods and properties are:

document.fullscreenEnabled (changed)
This property returns true when the document is in a state which allows full-screen mode. It can also be used to determine browser support:

if (document.fullscreenEnabled) { ... }

Earlier implementations had an uppercase ‘S’ in ‘Screen’, and it is still required for Firefox. Adding prefixes results in considerably longer cross-browser code:

// full-screen available?if (	document.fullscreenEnabled || 	document.webkitFullscreenEnabled || 	document.mozFullScreenEnabled ||	document.msFullscreenEnabled) {...}

Opera 12 is the only browser not to require prefixes but Opera 15+ uses webkit.

element.requestFullscreen() (changed)
This method makes an individual element full-screen, e.g.


Again, ‘screen’ has switched to lowercase. The cross-browser code:

var i = document.getElementById("myimage");// go full-screenif (i.requestFullscreen) {	i.requestFullscreen();} else if (i.webkitRequestFullscreen) {	i.webkitRequestFullscreen();} else if (i.mozRequestFullScreen) {	i.mozRequestFullScreen();} else if (i.msRequestFullscreen) {	i.msRequestFullscreen();}

document.fullscreenElement (changed)
This property returns the current element which is being displayed full-screen or null when not full-screen:

if (document.fullscreenElement) { ... }

‘screen’ is now lowercase. The cross-browser code:

// are we full-screen?if (	document.fullscreenElement ||	document.webkitFullscreenElement ||	document.mozFullScreenElement ||	document.msFullscreenElement) {...}

document.exitFullscreen (changed)
This method cancels full-screen mode:


Again, we have a lowercase ‘screen’. It was previously named cancelFullScreen, and still is within Firefox. The cross-browser code:

// exit full-screenif (document.exitFullscreen) {	document.exitFullscreen();} else if (document.webkitExitFullscreen) {	document.webkitExitFullscreen();} else if (document.mozCancelFullScreen) {	document.mozCancelFullScreen();} else if (document.msExitFullscreen) {	document.msExitFullscreen();}

document.fullscreenchange event
This event is fired when moving to and from full-screen view. No information is provided by the event but you can determine whether full-screen is enabled by checking whether document.fullscreenElement is not null.

document.addEventListener("fullscreenchange", function() { ... });

The name has not changed, but we require cross-browser prefixes and camel-casing for IE:

document.addEventListener("fullscreenchange", FShandler);document.addEventListener("webkitfullscreenchange", FShandler);document.addEventListener("mozfullscreenchange", FShandler);document.addEventListener("MSFullscreenChange", FShandler);

document.fullscreenerror event
Full-screen can fail. For example, iframes without an allowfullscreen attribute or windowed plug-in content may be blocked. A fullscreenerror event may therefore be fired:

document.addEventListener("fullscreenerror", function() { ... });

The name has not changed, but we require cross-browser prefixes and camel-casing for IE:

document.addEventListener("fullscreenerror", FSerrorhandler);document.addEventListener("webkitfullscreenerror", FSerrorhandler);document.addEventListener("mozfullscreenerror", FSerrorhandler);document.addEventListener("MSFullscreenError", FSerrorhandler);
Ads by 

Full-Screen CSS

We can also influence full-screen styles in CSS…

:fullscreen pseudo class (changed)
You can apply styles to an element or its children when viewed in full-screen mode:

:fullscreen {	...}

This was previously named :full-screen, and still is in Webkit and Firefox. For cross-browser code:

:-webkit-full-screen {}:-moz-full-screen {}:-ms-fullscreen {}:fullscreen {}

::backdrop (new)
You can apply a color or image backdrop when an element with a different aspect-ratio is viewed full-screen:

:fullscreen::backdrop {	background-color: #006; /* dark blue */}

The backdrop is a pseudo element behind the fullscreen element but above all other page content. It is supported in IE11, but not Firefox and Opera 12. Chrome, Safari, and Opera 15+ include the backdrop element but do not permit it to be styled. For the moment, you can only target IE11, e.g.

:-ms-fullscreen::-ms-backdrop {	background-color: #006; /* dark blue */}

Styling Differences

In IE11, Firefox, and Opera 12 the full-screen element is set to 100% width and height. Images are therefore stretched and the aspect ratio is ignored. Setting a width and height in IE11 positions a full-screen element to the top-left with a dark backdrop (configurable with ::backdrop). Opera 12 is similar to IE11 but shows a transparent backdrop. Firefox ignores the dimensions. In Chrome, Safari, and Opera 15+ the element is centered with a black backdrop.

If you want some consistency, it’s easy to make the Webkit/Blink browsers stretch like Firefox/IE11:

:-webkit-full-screen {	position: fixed;	width: 100%;	top: 0;	background: none;}

Alternatively, you can make IE11 follow the Webkit/Blink centering:

:-ms-fullscreen {  width: auto;  height: auto;  margin: auto;}

This method won’t work in Firefox, which ignores the width and height as mentioned above. To fix it, you’ll need to make the parent element full-screen and apply appropriate sizing as shown in this demonstration.

Ready for Deployment?

The HTML5 Full-Screen API is relatively simple but browser differences result in ugl

W3C Process Document


Ahh I think I literally just found the answer on Consortium/Process, too many tabs open!

The W3C Recommendation track:

  1. Working Draft
    A Working Draft generally represents work in progress and a commitment by W3C to pursue work in a particular area. The label "Working Draft" does not imply consensus within W3C about the document.

  2. Candidate Recommendation
    A Candidate Recommendation is a stable Working Draft that the Director has proposed to the community for implementation experience and feedback.

  3. Proposed Recommendation
    A Proposed Recommendation is a Candidate Recommendation that has benefitted from implementation experience and has been sent to the Advisory Committee for review.

  4. Recommendation
    A Recommendation reflects consensus within W3C, as represented by the Director's approval. W3C considers that the ideas or technology specified by a Recommendation are appropriate for widespread deployment and promote W3C's mission.

JavaScript Just-in-time (JIT) 工作原理

作者:Lin Clark



英文原文:A crash course in just-in-time (JIT) compilers


本文是关于 WebAssembly 系列的第二篇文章。如果你没有读先前文章的话,建议先读这里。如果对 WebAssembly 没概念,建议先读这里(中文文章)

JavaScript 的启动比较缓慢,但是通过 JIT 可以使其变快,那么 JIT 是如何起作用的呢?

JavaScript 在浏览器中是如何运行的?

如果是你一个开发者,当你决定在你的页面中使用 JavaScript 的时候,有两个要考虑的事情:目标和问题。



你说的是人类的语言,而计算机用的是机器语言。机器语言也是一种语言,只是 JavaScript 或者其他高级编程语言机器能看得懂,而人类不用他们来交流罢了。它们是基于人类认知而设计出来的。

所以呢,JavaScript 引擎的工作就是把人类的语言转换成机器能看懂的语言。










正是因为这个原因,解释器看起来更加适合 JavaScript。对于一个 Web 开发人员来讲,能够快速执行代码并看到结果是非常重要的。

这就是为什么最开始的浏览器都是用 JavaScript 解释器的原因。





另外一个不同是,编译器可以用更多的时间对代码进行优化,以使的代码执行的更快。而解释器是在 runtime 时进行这一步骤的,这就决定了它不可能在翻译的时候用很多时间进行优化。

Just-in-time 编译器:综合了两者的优点


不同的浏览器实现这一功能的方式不同,不过其基本思想是一致的。在 JavaScript 引擎中增加一个监视器(也叫分析器)。监视器监控着代码的运行情况,记录代码一共运行了多少次、如何运行的等信息。


如果同一行代码运行了几次,这个代码段就被标记成了 “warm”,如果运行了很多次,则被标记成 “hot”。


如果一段代码变成了 “warm”,那么 JIT 就把它送到编译器去编译,并且把编译结果存储起来。

代码段的每一行都会被编译成一个“桩”(stub),同时给这个桩分配一个以“行号 + 变量类型”的索引。如果监视器监视到了执行同样的代码和同样的变量类型,那么就直接把这个已编译的版本 push 出来给浏览器。


基线编译器可以做一部分这样的优化(下面我会给出例子),不过基线编译器优化的时间不能太久,因为会使得程序的执行在这里 hold 住。

不过如果代码确实非常 “hot”(也就是说几乎所有的执行时间都耗费在这里),那么花点时间做优化也是值得的。


如果一个代码段变得 “very hot”,监视器会把它发送到优化编译器中。生成一个更快速和高效的代码版本出来,并且存储之。


整个优化器起作用的链条是这样的,监视器从他所监视代码的执行情况做出自己的判断,接下来把它所整理的信息传递给优化器进行优化。如果某个循环中先前每次迭代的对象都有相同的形状,那么就可以认为它以后迭代的对象的形状都是相同的。可是对于 JavaScript 从来就没有保证这么一说,前 99 个对象保持着形状,可能第 100 个就少了某个属性。

正是由于这样的情况,所以编译代码需要在运行之前检查其假设是不是合理的。如果合理,那么优化的编译代码会运行,如果不合理,那么 JIT 会认为做了一个错误的假设,并且把优化代码丢掉。



大多数的浏览器都做了限制,当优化/去优化循环发生的时候会尝试跳出这种循环。比如,如果 JIT 做了 10 次以上的优化并且又丢弃的操作,那么就不继续尝试去优化这段代码了桩。

一个优化的例子:类型特化(Type specialization)


JavaScript 所使用的动态类型体系在运行时需要进行额外的解释工作,例如下面代码:

function arraySum(arr) {  var sum = 0;  for (var i = 0; i < arr.length; i++) {    sum += arr[i];  }}

+= 循环中这一步看起来很简单,只需要进行一步计算,但是恰恰因为是用动态类型,他所需要的步骤要比你所想象的更复杂一些。

我们假设 arr 是一个有 100 个整数的数组。当代码被标记为 “warm” 时,基线编译器就为函数中的每一个操作生成一个桩。sum += arr[i] 会有一个相应的桩,并且把里面的 += 操作当成整数加法。

但是,sum 和 arr[i] 两个数并不保证都是整数。因为在 JavaScript 中类型都是动态类型,在接下来的循环当中,arr[i] 很有可能变成了 string 类型。整数加法和字符串连接是完全不同的两个操作,会被编译成不同的机器码。

JIT 处理这个问题的方法是编译多基线桩。如果一个代码段是单一形态的(即总是以同一类型被调用),则只生成一个桩。如果是多形态的(即调用的过程中,类型不断变化),则会为操作所调用的每一个类型组合生成一个桩。

这就是说 JIT 在选择一个桩之前,会进行多分枝选择,类似于决策树,问自己很多问题才会确定最终选择哪个,见下图:

正是因为在基线编译器中每行代码都有自己的桩,所以 JIT 在每行代码被执行的时候都会检查数据类型。在循环的每次迭代,JIT 也都会重复一次分枝选择。

如果代码在执行的过程中,JIT 不是每次都重复检查的话,那么执行的还会更快一些,而这就是优化编译器所需要做的工作之一了。


一些浏览器的 JIT 优化更加复杂。比如在 Firefox 中,给一些数组设定了特定的类型,比如里面只包含整型。如果 arr 是这种数组类型,那么 JIT 就不需要检查 arr[i] 是不是整型了,这也意味着 JIT 可以在进入循环之前进行所有的类型检查。


简而言之 JIT 是什么呢?它是使 JavaScript 运行更快的一种手段,通过监视代码的运行状态,把 hot 代码(重复执行多次的代码)进行优化。通过这种方式,可以使 JavaScript 应用的性能提升很多倍。

为了使执行速度变快,JIT 会增加很多多余的开销,这些开销包括:

  • 优化和去优化开销
  • 监视器记录信息对内存的开销
  • 发生去优化情况时恢复信息的记录对内存的开销
  • 对基线版本和优化后版本记录的内存开销

这里还有很大的提升空间:即消除开销。通过消除开销使得性能上有进一步地提升,这也是 WebAssembly 所要做的事之一。


当前 WebAssembly 的状况

WebAssembly 的未来

Promise-based functions should not throw exceptions


This blog post gives tips for error handling in asynchronous, Promise-based functions.

Operational errors vs. programmer errors  

In programs, there are two kinds of errors:

  • Operational errors happen when a correct program encounters an exceptional situation that requires deviating from the “normal” algorithm. For example, a storage device may run out of memory while the program is writing data to it. This kind of error is expected.

  • Programmer errors happen when code does something wrong. For example, a function may require a parameter to be a string, but receives a number. This kind of error is unexpected.

Operational errors: don’t mix rejections and exceptions  

For operational errors, each function should support exactly one way of signaling errors. For Promise-based functions that means not mixing rejections and exceptions, which is the same as saying that they shouldn’t throw exceptions.

Programmer errors: fail quickly  

For programmer errors, it usually makes sense to fail as quickly as possible:

function downloadFile(url) {    if (typeof url !== 'string') {        throw new Error('Illegal argument: ' + url);    }    return new Promise(···).}

Note that this is not a hard and fast rule. You have to decide whether or not you can handle exceptions in a meaningful way in your asynchronous code.

Handling exceptions in Promise-based functions  

If exceptions are thrown inside the callbacks of then() and catch() then that’s not a problem, because these two methods convert them to rejections.

However, things are different if you start your async function by doing something synchronous:

function asyncFunc() {    doSomethingSync(); // (A)    return doSomethingAsync()    .then(result => {        ···    });}

If an exception is thrown in line A then the whole function throws an exception. There are two solutions to this problem.

Solution 1: returning a rejected Promise  

You can catch exceptions and return them as rejected Promises:

function asyncFunc() {    try {        doSomethingSync();        return doSomethingAsync()        .then(result => {            ···        });    } catch (err) {        return Promise.reject(err);    }}

Solution 2: executing the sync code inside a callback  

You can also start a chain of then() method calls via Promise.resolve() and execute the synchronous code inside a callback:

function asyncFunc() {    return Promise.resolve()    .then(() => {        doSomethingSync();        return doSomethingAsync();    })    .then(result => {        ···    });}

An alternative is to start the Promise chain via the Promise constructor:

function asyncFunc() {    return new Promise((resolve, reject) => {        doSomethingSync();        resolve(doSomethingAsync());    })    .then(result => {        ···    });}

This approach saves you a tick (the synchronous code is executed right away), but it makes your code less regular.

Async functions and exceptions  

Brian Terlson points out that async functions reflect a preference for not mixing exceptions and rejections: Originally, if an async function had a default value that threw an exception then the function would throw an exception. Now, the function rejects the Promise it returns.

Further reading  

Acknowledgements: this post was inspired by a post by user Mörre Noseshine in the “Exploring ES6” Google Group. Im also thankful for the feedback to a tweet asking whether it is OK to throw exceptions from Promise-based functions.

终于有人能用一句话把Service Worker,Web Worker,WebSocket说清楚

Service Worker


Web Worker




联系方式: 个人QQ  1005354833;