June 20, 2018

Web Animations in WebKit

Surfin’ Safari

Over the last 8 months we have been working on adding support for Web Animations, a W3C standard offering Web developers a JavaScript API to create, query and controls animations. While there is work left to do to ship this experimental feature to the Web at large, we feel our implementation has matured enough that, with the release of Safari Technology Preview 59, we can turn Web Animations on by default for our Web developer audience.

An Animation API for the Web

Browser engines have supported various animation features for many years, CSS Transitions and CSS Animations being two widely-supported approaches to authoring efficient animations on the Web. While these features have proven popular, they become limited when developers try to integrate browser-implemented animations via JavaScript:

  • Creating a CSS Transition dynamically requires forcing or waiting for a style invalidation so start and end values can be specified
  • Creating CSS Animations dynamically requires @keyframe rules to be generated and inserted in a global stylesheet
  • Animations created via CSS are not represented via JavaScript and cannot be queried or controlled

For instance, developers would have to resort to code such as this to slide an element 100 pixels to the right:

const element = document.getElementById("my-element");

// Set the start value and transition properties.
element.style.transform = "translateX(0)";
element.style.transitionProperty = "transform";
element.style.transitionDuration = "1s";

// Force a style invalidation.
window.getComputedStyle(element);

// Set the end value.
element.style.transform = "translateX(100px)";

This approach is not elegant as it forces a style invalidation that causes extra work rather than just letting the browser invalidate styles at the most appropriate time. And this is just one single transition, but what if another library in your webpage also needed to create a transition? This would multiply forced style invalidation for no good reason.

The value of Web Animations lies in having a JavaScript API that preserves the ability to let the browser engine do the heavy lifting of running animations efficiently while enabling more advanced control of your animations. Using Web Animations, we can rewrite the code above with a single method call:¬…

element.animate({ transform: ["translateX(0)", "translateX(100px)"] }, 1000);

A single method call and you’re done! But that’s not all, now you can harness the power of Web Animations with a full-featured API to control this animation:

// Obtain a reference to the animation we created above.
const animation = element.getAnimations()[0];
// Seek the animation to 500ms.
animation.currentTime = 500;
// Pause the animation.
animation.pause();

The Web Animations API is very powerful, for instance letting you get a list of all running animations on the document or an individual element, use promises to run code when an animation is ready to start or has completed, reverse an animation, etc.

Integration with CSS

The Web Animations specification goes further than specifying a JavaScript API. It provides a timing and animation model for web browsers to implement features such as CSS Transitions and CSS Animations. In fact, in WebKit, we’ve updated our implementation of these existing CSS technologies so that the same CSS Transitions and Animations you’ve been authoring for years are now represented as Web Animations objects in the browser. Using the getAnimations() method, you can obtain a reference to a CSSTransition or CSSAnimation object which are Animation subclasses. Then you can seek or pause a CSS transition running on an element just like we did above with an animation created using element.animate(). As a developer, you can think of CSS Transitions and Animations as a declarative layer above Web Animations.

Help Wanted

We’re very excited to be bringing the power of Web Animations to WebKit and enabling the technology in Safari Technology Preview 59. But there is still a fair bit of work ahead and we need your help to ensure we have a quality implementation before enabling the feature in Safari. We encourage you to try the new API and report issues that you find, bearing in mind that our current implementation is a bit behind the current state of the specification, and you can track all API changes with bug #186518.

It’s also important to check your existing content using CSS Transitions and Animations for possible regressions. One way to see if a regression you might be seeing is caused by the new Web Animations implementation, try toggling “Web Animations and CSS Integration” under the DevelopExperimental Features menu and see if your page’s behavior differs.

June 20, 2018 05:00 PM

Release Notes for Safari Technology Preview 59

Surfin’ Safari

Safari Technology Preview Release 59 is now available for download for macOS High Sierra and the beta of macOS Mojave. If you already have Safari Technology Preview installed, you can update from the Mac App Store’s Updates tab on macOS High Sierra and in the Software Update pane of System Preferences on macOS Mojave. This release covers WebKit revisions 232108-232790.

Known Issues

  • This release of Safari Technology Preview for macOS Mojave betas does not render text properly in the Smart Search Field when in Dark Mode
  • Users running this version of Safari Technology Preview on macOS Mojave Developer Beta 2 will need to login to websites when restarting the application, or may require logging in again on some websites when launching a new window

Intelligent Tracking Prevention 2.0

  • Enabled the latest version of Safari’s privacy protection “Intelligent Tracking Prevention.” For technical details, see the WebKit blog post.

Web Animations

  • Enabled Web Animations as an experimental feature by default (r232186)
  • Added support for handling relative length units such as em, vw, and vh (r232255)
  • Fixed a bug causing WebAnimation objects to never get destroyed (r232185)

Payment Request

  • Removed currencySystem member (r232155)

JavaScript

  • Added Symbol.prototype.description getter (r232404)
  • Implemented + and - unary operation for BigInt (r232232)
  • Implemented support for % operation for BigInt (r232295)
  • Implemented support for < and > relational operation for BigInt (r232273)
  • Implemented support for =< and >= relational operation for BigInt (r232386)
  • Implemented support for addition operations for BigInt (r232449)
  • Fixed the Array.prototype.concat fast case when a single argument is a Proxy object (r232261)
  • Fixed Date.parse() to properly handle input outside of ES spec limits (r232122)
  • Fixed Array.prototype.sort to reject null comparator (r232666)
  • Renamed Array#flatten to flat (r232226)

Editing

  • Fixed not displaying spelling errors in the middle of an inserted paragraph (r232530)

Storage Access API

  • Changed Storage Access API calls to handle the absence of an attached frame (r232584)

Security

  • Enabled Cross-Origin-Resource-Policy by default (r232311)
  • Changed the NetworkCORSPreflightChecker to set the preflight request User-Agent header (r232470)
  • Changed Accept request header values to be more tightly checked in the case of a CORS load (r232728)
  • Fixed the Referrer-Policy response header to not be ignored (r232310)
  • Renamed Cross-Origin-Options HTTP header to Cross-Origin-Window-Policy (r232499)
  • Renamed Cross-Origin-Resource-Policy:same to same-origin (r232309)
  • Migrated From-Origin to Cross-Origin-Resource-Policy (r232217)

Service Workers

  • Added Accept-Encoding:identity to Range requests (r232571)
  • Fixed ServiceWorker registration to store any script fetched through importScripts (r232516)
  • Fixed HTTP Header values validation to not be too strict (r232572)
  • Improved error messages when FetchEvent.respondWith has a rejected promise (r232739)
  • Prevented starting service worker fetch when there is substitute data (r232580)
  • Updated Fetch code to provide more useful exception messages (r232484)

Compatibility

  • Fixed page reloading when viewing photos in Google Drive due to exceeding canvas memory limits (r232113)
  • Fixed memory management when zooming and scrolling on some websites (r232356)
  • Link drag image is inconsistently unreadable in dark mode (r232731)

WebRTC

  • Added an option to restrict communication to localhost sockets (r232420)

Web API

  • Changed PopStateEvent to not be cancelable by default (r232610)

Media

  • Changed media elements outside of fullscreen to not be considered main content (r232300)
  • Changed to exit fullscreen when JavaScript alerts are presented (r232437)
  • Changed automatic picture-in-picture to use the main content heuristic (r232301)
  • Changed to stop playing in the background when automatic picture-in-picture is disabled (r232426)
  • Enabled subsampling for progressive JPEG images (r232177)
  • Fixed incorrectly sized captions in picture-in-picture mode (r232220)
  • Fixed regions outside of the fullscreen window becoming exposed during zoom operations (r232543)
  • Fixed fullscreen element clipping by an ancestor (r232208)

Web Inspector

  • Added Same-Site cookie annotations (r232318)
  • Fixed copying a link address in the Elements tab (r232481)
  • Fixed popovers getting dismissed while attempting to move the cursor inside (r232189)
  • Fixed the tab picker becoming briefly visible when the TabBar is initially shown (r232524)
  • Prevented text in “Add New Class” from being auto-capitalized (r232518)

Accessibility

  • Exposed the <link> rel attribute to voiceover (r232326)
  • Fixed VoiceOver to announce when a details element is expanded when using role group (r232285)
  • Fixed setValue on contenteditable to preserve whitespace (r232120, r232259)
  • Fixed VoiceOver to announce fieldset description from aria-describedby when focusing inputs (r232331)
  • Implemented support for new blockquote, caption, and paragraph ARIA roles (r232508)

iCloud Keychain Password Manager

  • Added support for loading https://example.com/.well-known/change-password when a user indicates they’d like to change a password that is reused in Safari’s Passwords preferences, falling back to loading example.com if that load fails

June 20, 2018 04:00 PM

June 06, 2018

Safari Technology Preview 58, with Safari 12 Features, is Now Available

Surfin’ Safari

Safari Technology Preview Release 58 is now available for download for macOS High Sierra. With this release, Safari Technology Preview is now available for betas of macOS Mojave. If you already have Safari Technology Preview installed on macOS High Sierra, you can update from the Mac App Store’s Updates tab.

This release covers the same revisions of WebKit from Safari Technology Preview 57, but includes new Safari and WebKit features that will be present in Safari 12. The following Safari 12 features are new to Safari Technology Preview 58:

Icons in Tabs. You can enable showing website icons in tabs in Safari’s Tabs preferences.

Automatic Strong Passwords. Safari automatically generates strong, unique passwords when signing up for accounts or changing passwords on websites. New to Safari 12 and Safari Technology Preview 58, generated passwords can be customized using the passwordrules attribute. See Apple’s Password Rules Validation Tool for more information.

Many more WebKit features in Safari 12 are present in this release of Safari Technology Preview and have been in past releases. You can read more about these changes and many others in What’s New in Safari 12.

June 06, 2018 05:00 PM

June 04, 2018

Michael Catanzaro: Security vulnerability in Epiphany Technology Preview

Igalia WebKit

If you use Epiphany Technology Preview, please update immediately and ensure you have revision 3.29.2-26 or newer. We discovered and resolved a vulnerability that allowed websites to access internal Epiphany features and thereby exfiltrate passwords from the password manager. We apologize for this oversight.

The unstable Epiphany 3.29.2 release is the only affected release. Epiphany 3.29.1 is not affected. Stable releases, including Epiphany 3.28, are also not affected.

There is no reason to believe that the issue was discovered or exploited by any attackers, but you might wish to change your passwords if you are concerned.

By Michael Catanzaro at June 04, 2018 11:00 PM

Intelligent Tracking Prevention 2.0

Surfin’ Safari

Today we’re happy to bring you Intelligent Tracking Prevention 2.0, or ITP 2.0. It builds upon ITP 1.0, which we released last year, and ITP 1.1, which was released in March, adding the Storage Access API.

Removal of the 24 Hour Cookie Access Window

ITP 2.0, as opposed to earlier versions, immediately partitions cookies for domains determined to have tracking abilities. The previous general cookie access window of 24 hours after user interaction has been removed. Instead, authenticated embeds can get access to their first-party cookies through the Storage Access API. The API requires that the user interacts with the embedded content.

0 days: Cookies are partitioned and not persisted in 3rd-part contexts. | 30 days: Existing cookies are purged. New cookies are blocked. | Days of use after the most recent interaction with the website or successful use of the Store Access API.
Example

video.example offers an ad-free subscription service and has many of its videos embedded on other websites. ITP classifies video.example as having tracking abilities and therefore partitions its cookies. This is a timeline of how ITP might work for video.example:

  1. Day 1: The user logs in to video.example which updates video.example’s user interaction timestamp.
  2. Day 22: The user clicks to watch a video.example clip on news.example and the embedded video calls the Storage Access API. ITP notes that the user has not previously granted video.example access to its first-party cookies on news.example and thus prompts the user. The user grants storage access and video.example’s user interaction timestamp is updated.
  3. Day 26: The user clicks to watch another video.example clip on news.example and the video.example embed calls the Storage Access API. ITP notes that the user has previously granted video.example access to its first-party cookies on news.example and thus provides access without a prompt and updates video.example’s user interaction timestamp.
  4. Day 55: The user interacts with video.example as first party website which updates video.example’s user interaction timestamp.
  5. Day 76: The user clicks to watch a video.example clip on blog.example and the video.example embed calls the Storage Access API. ITP notes that the user has not previously granted video.example access to its first-party cookies on blog.example and thus prompts the user. The user grants storage access and video.example’s user interaction timestamp is updated.
  6. Day 80-82: The user doesn’t use Safari which means that these three days do not count towards the 30 days before website data purge.
  7. Day 109: video.example’s cookies, website data, and granted storage access entries are purged as a result of 30 days of Safari usage without an update to video.example’s user interaction timestamp.
Developer Advice

If you are a provider of authenticated third-party content, you should adopt the Storage Access API. If your website relies on a third party domain for user authentication, your authentication provider should adopt the Storage Access API or transfer authentication tokens to you in URLs.

User Prompt For the Storage Access API

ITP 2.0 adds a prompt to WebKit’s implementation of the Storage Access API. If the user allows access, their choice is persisted. If the user declines, their choice is not persisted which allows them to change their mind if they at a later point tap a similar embedded widget that calls the Storage Access API.

As an example, video.example may have an ad-free subscription service and have many of its videos embedded on other websites. ITP will thus classify video.example as having tracking abilities and partition its cookies. When the user taps or clicks to play a clip embedded on news.example, video.example can call the Storage Access API to check whether the user is a subscriber. The user will be prompted if they have not explicitly allowed access under news.example previously.

Storage Access API promptStorage Access API Prompt

This prompt provides users with a way to show intent (the tap/click enabling the API call) and provide consent (“Allow” in the prompt). If the user chooses “Allow,” their choice is persisted and subsequent calls to the Storage Access API by video.example embeds on news.example do not trigger a prompt. Instead a tap or click on the embed is enough for a successful API call. As always, ITP considers the eTLD+1 to be the “party,” so a user “Allow” for sub.video.example under sub.news.example will be valid for video.example and any of its subdomains under news.example or any of its subdomains.

Successful use of the Storage Access API now counts as user interaction with the third-party and refreshes the 30 days of use before ITP purges the third-party’s website data. By successful use we mean the user was either prompted right now and chose “Allow,” or had previously chosen “Allow.” The fact that successful Storage Access API calls now count as user interaction allows users to stay logged into services they rarely use as first party but keep using as embedded third parties.

Finally, we received developer feedback (thank you), saying it should be possible to do a popup should storage access be granted but it turns out the user is not logged in. Our original version of the Storage Access API would consume the user gesture and thus require another tap or click to do a login popup. Now, the third-party embed is allowed to do a popup in the resolve scope of the returned promise, like so:

<script>
function makeRequestWithUserGesture() {
  var promise = document.requestStorageAccess();
  promise.then(
    function () {
      // Storage access was granted.
      // Check whether the user is logged in.
      // If not, do a popup to log the user in.
    },
    function () {
      // Storage access was denied.
    }
  );
}
</script>
<button onclick="makeRequestWithUserGesture()">Play video</button>
Developer Advice

We encourage you to adopt the Storage Access API if you provide authenticated embeds. The API’s prompt provides you with a way to extend your users’ authenticated sessions if ITP has classified your domain as having the ability to track the user. If ITP classifies your domain and you don’t adopt the API, your domain will be permanently blocked from accessing its first-party cookies in a third-party context.

Temporary Compatibility Fix: Automatic Storage Access for Popups

Many federated logins send authentication tokens in URLs or through the postMessage API, both of which work fine under ITP 2.0. However, some federated logins use popups and then rely on third-party cookie access once the user is back on the opener page. Some instances of this latter category stopped working under ITP 2.0 since domains with tracking abilities are permanently partitioned.

Our temporary compatibility fix is to detect such popup scenarios and automatically forward storage access for the third party under the opener page. Since popups require user interaction, the third party could just as well had called the Storage Access API instead.

Developer Advice

If you provide federated login services, we encourage you to first call the Storage Access API to get cookie access and only do a popup to log the user in or acquire specific consent. The Storage Access API provides a better user experience without new windows and navigations. We’d also like to stress that the compatibility fix for popups is a temporary one. Longterm, your only option will be to call the Storage Access API.

Protection Against First Party Bounce Trackers

ITP 2.0 has the ability to detect when a domain is solely used as a “first party bounce tracker,” meaning that it is never used as a third party content provider but tracks the user purely through navigational redirects.

Say the user clicks on a news.example link on the social.example website. Instead of navigating them straight to their destination news.example, they are rapidly navigated through trackerOne.example and trackerTwo.example before reaching news.example. Those two tracker domains can store information about the user’s browsing history in first party storage and cookies. ITP 2.0 detects such tracking behavior and treats those domains just like any other tracker, i.e. purges their website data.

First-party cookie bounce diagram

Protection Against Tracker Collusion

Through our research, we found that cross-site trackers help each other identify the user. This is basically one tracker telling another tracker that “I think it’s user ABC,” at which point the second tracker tells a third tracker “Hey, Tracker One thinks it’s user ABC and I think it’s user XYZ.” We call this tracker collusion, and ITP 2.0 detects this behavior through a collusion graph and classifies all involved parties as trackers.

Cross-site tracker collusion diagram

In the graph above, as soon as trackerSix.example is classified by ITP, all the domains that have redirected to trackerSix.example get classified too. That’s trackerTwo.example, trackerThree.example, and trackerFive.example. Then domains that have redirected to those get classified too, which covers the last two—trackerOne.example and trackerFour.example.

Developer Advice

Avoid making unnecessary redirects to domains that are likely to be classified as having tracking ability.

Origin-Only Referrer for Domains Without User Interaction

ITP’s purging of website data does not prevent trackers from receiving the so called referrer header which reveals the webpage the user is currently on. In ITP 2.0, the referrer, if there is one, is downgraded to just the page’s origin for third party requests to domains that have been classified as possible trackers by ITP and have not received user interaction.

Here’s an example of what we mean by this: Say the user visits https://store.example/baby-products/strollers/deluxe-navy-blue.html, and that page loads a resource from trackerOne.example. Before ITP 2.0, the request to trackerOne.example would contain the full referrer “https://store.example/baby/strollers/deluxe-stroller-navy-blue.html” which reveals a lot about the user to the third-party. With ITP 2.0, the referrer will be reduced to just “https://store.example/”.

For further reading on this subject, see Mozilla’s research on origin-only referrers.

FAQ

Does ITP differentiate between my subdomains?
No. ITP captures statistics and applies its rules for the effective top-level domain plus one, or eTLD+1. An eTLD is .com or .co.uk so an example of an eTLD+1 would be social.co.uk but not sub.social.co.uk (eTLD+2) or just co.uk (eTLD).

Does eTLD mean public suffix?
Yes. See the Public Suffix List.

Is there a way for users to whitelist my domain to be excepted from ITP’s rules?
No, there is no such whitelisting feature.

How does ITP classify a domain’s tracking abilities?
See the original ITP 1.0 blog post for details on the machine learning model.

My domain is not a tracker, but it gets classified by ITP. Is that a bug?
ITP does not rely on a centralized blacklist of known trackers. Instead, it captures per-domain (eTLD+1) statistics on-device and classifies each domain’s ability to track cross-site. If a domain has the ability to track the user cross-site, it’s subject to ITP’s cookie and website data rules.

Is it enough for users to visit my website to keep its cookies from being purged if my domain gets classified by ITP?
No, a mere visit does not suffice. The user has to interact with your website, meaning a tap, click, or form entry. In ITP 2.0, user granted access through the Storage Access API also counts as such user interaction.

How do I reset ITP or the domains I’ve allowed storage access for?
Clear your Safari history. Note that this gets rid of data that may be needed to reproduce an ITP issue. If you’re investigating a bug related to ITP, don’t clear your history before you’re done with that work.

I need to debug my website in regards to ITP. Are there specific developer tools?
We’re working on an ITP Debug Mode which will help you debug websites and capture data that’s useful when filing bugs on ITP. It will be announced on this blog.

What is an authenticated widget, an authenticated embed, or authenticated third-party content?
The web platform allows for powerful integration across websites. This enables services such as social media to create widgets that are to be embedded as third-party content on news sites and blogs, but it also enables cross-site tracking. Some widgets have to see the user as logged in to work. For example, if the user wants to comment on blog.example with their social.example account, the social.example commenting widget needs to see the user as logged in to their service. We refer to these widgets as authenticated and to enable them while disabling cross-site tracking, the widgets now have to ask for permission to see the user’s identity, per-site.

How does the removal of the 24 hour cookie access window prevent cross-site tracking from social media etc?
ITP 1.0 had a 24 hour window in which websites the user interacted with could use their cookies as in previous versions of Safari. This was a compatibility measure we took to enable federated logins (e.g. use social.example to login to news.example) and authenticated third-party content (e.g. use social.example to make a comment on blog.example). However, this also allowed social media and search engines that the user interacted with as first parties to track the user across websites while inside that 24 hour window. The mere existence of third-party content from these services was enough for them to see which webpages the user visited. For example, if a user used social.example and then, several hours later, visited news.example which had a social.example Like button or comment widget embedded on the site, social.example could track their browsing on news.example. In ITP 2.0 we restrict such third-party content to only be able to identify the user when they actually use the content, such as write a comment or play a video. This is also the point at which Safari will ask for the user’s permission (if the widget is asking for permission to see its cookies).

Feedback and Bug Reports

Please report bugs through bugs.webkit.org and send feedback to our evangelist Jon Davis. If you have technical questions on how the feature works you can find me on Twitter @johnwilander.

June 04, 2018 07:00 PM

May 30, 2018

Release Notes for Safari Technology Preview 57

Surfin’ Safari

Safari Technology Preview Release 57 is now available for download for macOS High Sierra. If you already have Safari Technology Preview installed, you can update from the Mac App Store’s Updates tab. This release covers WebKit revisions 231553-232108.

This version of Safari Technology Preview will no longer run on macOS Sierra. To continue testing or living on the latest enhancements to Safari and WebKit, please upgrade to macOS High Sierra.

JavaScript

  • Added support for Intl.NumberFormat().formatToParts() (r231867)
  • Changed to throw SyntaxErrors for runtime generated regular expressions with errors (r231939)
  • Implemented BigInt support for *, /, and == operations (r231733, r231886, r231629)
  • Improved specification compliance for Internationalization APIs (r231740)
  • Improved the speed of Object.assign for final objects (r231687)

Animations

  • Exposed Web Animations CSS integration as an experimental feature (r231798)
  • Fixed a bug where animation-play-state:paused causes very high cpu load because of a style invalidation loop (r231794)

Storage Access API

  • Extended the lifetime of cookies on successful user approval (r231684)

Security

  • Added initial support for the Cross-Origin-Options HTTP response header (r231622, r231654)
  • Changed Cross-Origin-Options:deny and Cross-Origin-Options:allow-postmessage to prevent getting navigated by cross-origin scripts (r231911)
  • Changed X-Frame-Options:SAMEORIGIN to check all ancestor frames (r231730)

Media

  • Enabled the modern EME API by default (r231903)
  • Fixed media continuing to load after rendered invisible (e.g. removed from DOM; scrolled off screen) (r231817)
  • Improved NowPlaying using the element "title" attribute when available (r231866)

Accessibility

  • Changed the accessiblility name provided for a node to simplify the whitespace when using innerText (r231627)
  • Excluded hidden nodes which are not directly referenced from participating in name or description content (r231620)
  • Ensured listbox and combobox roles embedded in labels participate in name calculation (r231778)
  • Exposed the primary screen height through the AX API (r231937)
  • Fixed a bug with VoiceOver causing <iframe> scrolling focus jumping (r231628)
  • Fixed VoiceOver to manually focus or read dialog paragraph description text inside the modal in role=dialog elements with aria-modal=true (r231720)

WebDriver

  • Fixed a crash that happens if a browsing context’s cookies are requested prior to an initial navigation (r232031)
  • If the network or storage process crashes, terminate the automation session to avoid undefined behavior (r232028)
  • Automation.getBrowsingContext now returns the same window origin as window.screenX and window.screenY (r231769)

Web Inspector

  • Added rulers and guides to the Canvas tab (r231819, r231881)
  • Changed the Canvas tab to not automatically select a recording when viewing a canvas (r231773)
  • Improved the placement logic for the element details popover that is shown during Inspect Element mode (r231838)
  • Calculating the visual effect of each Canvas action is now off by default for performance reasons. (r231981)

May 30, 2018 05:00 PM

May 27, 2018

Michael Catanzaro: Thoughts on Flatpak after four months of Epiphany Technology Preview

Igalia WebKit

It’s been four months since I announced Epiphany Technology Preview — which I’ve been using as my main browser ever since — and five months since I announced the availability of a stable channel via Flatpak. For the most part, it’s been a good experience. Having the latest upstream development code for everything is wonderful and makes testing very easy. Any user can painlessly download and install either the latest stable version or the bleeding-edge development version on any Linux system, regardless of host dependencies, either via a couple clicks in GNOME Software or one command in the terminal. GNOME Software keeps it updated, so I always have a recent version. Thanks to this, I’m often noticing problems shortly after they’re introduced, rather than six months later, as was so often the case for me in the past. Plus, other developers can no longer complain that there’s a problem with my local environment when I report a bug they can’t reproduce, because Epiphany Technology Preview is a canonical distribution environment, a ground truth of sorts.

There have been some rough patches where Epiphany Technology Preview was not working properly — sometimes for several days — due to various breaking changes, and the long time required to get a successful SDK build when it’s failing. For example, multimedia playback was broken for all of last week, due to changes in how the runtime is built. H.264 video is still broken, since the relevant Flatpak extension is only compatible with the 3.28 runtime, not with master. Opening files was broken for a while due to what turned out to be a bug in mutter that was causing the OpenURI portal to crash. I just today found another bug where closing a portal while visiting Slack triggered a gnome-shell crash. For the most part, these sorts of problems are expected by testers of unstable nightly software, though I’m concerned about the portal bugs because these affect stable users too. Anyway, these are just bugs, and all software has bugs: they get fixed, nothing special.

So my impression of Flatpak is still largely positive. Flatpak does not magically make our software work properly in all host environments, but it hugely reduces the number of things that can go wrong on the host system. In recent years, I’ve seen users badly break Epiphany in various ways, e.g. by installing custom mimeinfo or replacing the network backend. With Flatpak, either of these would require an incredible amount of dedicated effort. Without a doubt, Flatpak distribution is more robust to user error. Another advantage is that we get the latest versions of OS dependencies, like GStreamer, libsoup, and glib-networking, so we can avoid the many bugs in these components that have been fixed in the years since our users’ LTS distros froze the package versions. I appreciate the desire of LTS distros to provide stability for users, but at the same time, I’m not impressed when users report issues with the browser that we fixed two years ago in one dependency or another. Flatpak is an excellent compromise solution to this problem: the LTS distro retains an LTS core, but specific applications can use newer dependencies from the Flatpak runtime.

But there is one huge downside to using Flatpak: we lose crash reports. It’s at best very difficult — and often totally impossible — to investigate crashes when using Flatpak, and that’s frankly more important than any of the gains I mention above. For example, today Epiphany Technology Preview is crashing pretty much constantly. It’s surely a bug in WebKit, but that’s all I can figure out. The way to get a backtrace from a crashing app in flatpak is to use coredumpctl to manually dump the core dump to disk, then launch a bash shell in the flatpak environment and manually load it up in gdb. The process is manual, old-fashioned, primitive, and too frustrating for me by a lot, so I wrote a little pyexpect script to automate this process for Epiphany, thinking I could eventually generalize it into a tool that would be useful for other developers. It’s a horrible hack, but it worked pretty well the day I tested it. I haven’t seen it work since. Debuginfo seems to be constantly broken, so I only see a bunch of ???s in my backtraces, and how are we supposed to figure out how to debug that? So I have no way to debug or fix the WebKit bug, because I can’t get a backtrace. The broken, inconsistent, or otherwise-unreliable debuginfo is probably just some bug that will be fixed eventually (and which I half suspect may be related to our recent freedesktop SDK upgrade. Update: Alex has debugged the debuginfo problem and it looks like that’s on track to be solved), but even once it is, we’re back to square one: it’s still too much effort to get the backtrace, relative to developing on the host system, and that’s a hard problem to solve. It requires tools that do not exist, and for which we have no plans to create, or even any idea of how to create them.

This isn’t working. I need to be able to effortlessly get a backtrace out of my application, with no or little more effort than running coredumpctl gdb as I would without Flatpak in the way. Every time I see Epiphany or WebKit crash, knowing I can do nothing to debug or investigate, I’m very sorely tempted to switch back to using Fedora’s Epiphany, or good old JHBuild. (I can’t promote BuildStream here, because BuildStream has the same problem.)

So the developer experience is just not good, but set that aside: the main benefits of Flatpak are for users, not developers, after all. Now, what if users run into a crash, how can they report the bug? Crash reports are next to useless without a backtrace, and wise developers refuse to look at crash reports until a quality backtrace has been posted. So first we need to fix the developer experience to work properly, but even then, it’s not enough: we need an automatic crash reporter, along the lines of ABRT or apport, to make reporting crashes realistically-achievable for users, as it already is for distro-packaged apps. But this is a much harder problem to solve. Such a tool will require integration with coredumpctl, and I have not the faintest clue how we could go about making coredumpctl support container environments. Yet without this, we’re asking application developers to give up their most valuable data — crash reports — in order to use Flatpak.

Eventually, if we don’t solve crash reporting, Epiphany’s experiment with Flatpak will have to come to an end, because that’s more important to me than the (admittedly-tremendous) benefits of Flatpak. I’m still hopeful that the ingenuity of the Flatpak community will find some solutions. We’ll see how this goes.

By Michael Catanzaro at May 27, 2018 11:39 PM

May 16, 2018

Release Notes for Safari Technology Preview 56

Surfin’ Safari

Safari Technology Preview Release 56 is now available for download for macOS Sierra and macOS High Sierra. If you already have Safari Technology Preview installed, you can update from the Mac App Store’s Updates tab. This release covers WebKit revisions 230913-231553.

This is the last release of Safari Technology Preview that will install and run on macOS Sierra. To continue testing or living on the latest enhancements to Safari and WebKit, please upgrade to macOS High Sierra.

JavaScript

  • Implemented Intl.PluralRules (r231047)

WebAssembly

  • Added support for stream APIs (r231194)

Web API

  • Fixed document.open() event listener removal to be immediate (r231248)
  • Fixed DHTML drag operations to report the number of files in the operation (r231003)
  • Fixed window.postMessage(), window.focus(), and window.blur() unexpectedly throwing a TypeError (r231037)
  • Serialized font-variation-settings with double-quotes to match standards (r231165)
  • Stopped using the id of an <iframe> as fallback if its name attribute is not set (r231456)

Security

  • Added support for the WHATWG proposed From-Origin:same and From-Origin:same-site response headers with nested frame origin checking as an off by default experimental feature (r230968)
  • Fixed CSP referrer for a document blocked due to a violation of its frame-ancestors directive (r231461)
  • Fixed CSP status-code for a document blocked due to a violation of its frame-ancestors directive (r231464)
  • Fixed CSP to pass the document’s referrer (r231445)
  • Fixed CSP to only notify Web Inspector to pause the debugger on the first policy to violate a directive (r231443)
  • Fixed a bug causing first-party cookies to be blocked on redirects (r231008)

CSS

  • Fixed CSS filters which reference SVG filters to respect the color-interpolation-filters of the filter (r231473)
  • Fixed feTurbulence to render correctly on a Retina display (r231485)
  • Fixed shape-outside and filter styles occuring twice in the result of getComputedStyle (r230976)

Rendering

  • Changed font collection fragment identifiers to use PostScript names (r231259)
  • Fixed selecting text on a webpage causing the text vanish (r231178)
  • Fixed hiding then showing an <object> of type image to ensure the underlying image is displayed (r231292)

Media

  • Changed MediaStreams that are playing to allow removing some of its tracks (r231304)
  • Updated text track cue logging to include cue text (r231490)

Web Inspector

  • Improved the user experience in Canvas tab to show progress bars while processing actions in a new recording (r231218)
  • Ensured that tabbing through the last section of rules in the Styles editor wraps back to the first section of rules (r231372)
  • Fixed Console drawer resizing when the console prompt has more than one line of code (r231527)
  • Fixed unsupported properties that sometimes don’t get warnings just after adding them (r231377)
  • Updated the Canvas tab to determine functions by looking at the prototype (r231368)

May 16, 2018 05:00 PM

May 02, 2018

Release Notes for Safari Technology Preview 55

Surfin’ Safari

Safari Technology Preview Release 55 is now available for download for macOS Sierra and macOS High Sierra. If you already have Safari Technology Preview installed, you can update from the Mac App Store’s Updates tab. This release covers WebKit revisions 230521-230913.

CSS

  • Added support for calc() in webkit-gradient and cross-fade (r230816)
  • Changed :active pseudo class to deactivate when using pressure sensitive trackpad (r230786)
  • Omitted the default value when serializing font-feature-settings (r230838)
  • Updated HSL and HSLA parsing to match CSS Color 4 (r230861)

Web API

  • Enforced content-type for <script> tags (r230602)
  • Fixed input.webkitEntries to work as expected when a folder contains accented chars (r230639)
  • Setting event.returnValue to true is now a no-op (r230664)

Rendering

  • Fixed animated GIFs with finite looping to loop the expected number of times (r230712)
  • Fixed the position of the caret in empty table cells (r230797)

Accessibility

  • Added the accessibility events to the HTML attribute names so AOM works with DOM Level 1 events (r230890)
  • Fixed a hang when triggering an alert from an AOM increment event (r230782)

JavaScript

  • Fixed function.prototype.caller to not return generator bodies (r230662)

Web Driver

  • Fixed simulated mouse interactions to not be done until the associated DOM events have been dispatched (r230817)

Web Inspector

  • Fixed selecting and copying text from a Network tab popover (r230701)

Media

  • Added allSamplesInTrackEnqueued event (r230909)

WebRTC

  • Fixed a WebRTC data channel issue for non-ASCII characters. (r230524)

Security

  • Changed to use CSP and content blockers for sync XHR (r230810)

Bug Fixes

  • Fixed an issue that would sometimes incorrectly rule out PDF as a mime type that can be showed (r230853)
  • Fixed an issue with Command-clicking web app links on icloud.com (r230721)

May 02, 2018 05:00 PM

April 27, 2018

Visualizing Layers in Web Inspector

Surfin’ Safari

Recent releases of Safari Technology Preview contain a new experimental feature for Web Inspector: the Layers tab. Building upon the legacy Layers sidebar, this tab introduces a 3D visualization of the inspected page’s compositing layers, to provide developers with a more hands-on (and hopefully fun!) way to understand where layers are being generated and in what order they will render.

Layers tab

In this post, we’ll look at how the Layers tab can be used to find unexpected memory consumption or excessive repaints on a web page.

A Whirlwind Introduction to Layers

Before introducing any debugging tool, it’s important to clarify what we’re aiming to debug in the first place. At first glance, a layer visualization may appear quite similar to a DOM visualization (such as Firefox’s Tilt), yet compositing layers and DOM elements are conceptually different entities. While web developers are intimately familiar with the DOM tree as the structure of elements on a page, the way in which these elements end up rendered on screen tends to only be learned as a need arises.

DOM elements are not just painted to the screen one by one. After the position and size of each element has been calculated, they are drawn onto a series of surfaces called layers. It is these layers which are then composited in a particular order to produce the resulting appearance of the web page. All pages have a root layer corresponding to the document itself, but any DOM element can cause a new layer to be created. Among the reasons for this are element type (e.g. <canvas>), presence of certain CSS properties (e.g. 3D transforms), or interaction with other layer-generating elements.

Layers have a significant impact on rendering performance. Without layers, animating any element (e.g. sliding a header down) would mean having to wastefully repaint the whole page on every frame. If the element has its own layer, however, it may be possible to skip repainting altogether and animate by simply recompositing the layers on screen. Of course, the trade-off for this computational savings is memory cost. Creating too many layers—intentionally or otherwise—can have disastrous results on memory-constrained devices. Like any performance concern, finding the right balance is an empirical issue, so having a suitable debugging tool is crucial!

Identifying Compositing Issues with the Layers Tab

The Layers tab features two real-time representations of the layers on the page, a 3D visualization and a data table. We can use these in conjunction to discover potential performance problems.

We might begin by exploring the visualization to understand each layer’s position, size, and rendering order. To navigate, use left-drag to rotate, right-drag to pan, and scroll to zoom. Clicking a layer in the visualization highlights the corresponding row in the layer table.

We can then use the table to identify the costliest layers, sorting by Memory to prioritize memory consumption (default) or by Paints to prioritize repaint count. Selecting a row in the table displays information about why the layer exists as well as its composited and visible dimensions (visualized as an outline and a plane, respectively). This also recenters the visualization on the selection, clarifying how that layer fits into the larger picture.

explore table

At this point, perhaps we’ll take notice of an oddly-positioned layer nearby and jump to it accordingly. Or we could simply inspect each of the most expensive layers in turn. If a layer seems suspicious, we can click the arrow icon in its table row to switch to the Elements tab and examine the DOM element that generated it. And if that’s not enough to explain an unusually high repaint count, we can turn to the Timelines tab to figure out where those paint events are being triggered.

Once we’ve identified our issue, it’s just a matter of making the appropriate HTML/CSS modifications!

Feedback

The Layers tab is available in the latest Safari Technology Preview. To enable it, visit the Experimental panel on Web Inspector’s Settings tab and check the “Enable Layers tab” setting. Give it a try and let us know what you think! Reach out at #webkit-inspector on Freenode IRC, to @webkit on Twitter, or by filing a bug.

April 27, 2018 05:00 PM

April 25, 2018

Web Inspector Styles Sidebar Improvements

Surfin’ Safari

In Web Inspector that recently shipped with Safari 11.1 on macOS High Sierra, the Elements tab sidebar panels and the styles editor got a lot of attention from the Web Inspector team. We’ve re-written the styles editor to provide an editing experience more familiar to web developers, and rearranged the sidebar panels to improve access to the most used tools. The design refresh brings new behaviors and fine-tuning to enhance web developers’ ability to access and understand the elements they’re inspecting.

Tabs Layout

styles tabs before & afterBefore / After

In the Elements tab, Styles and Computed are the most commonly used panels. We made them top-level tabs, so it takes a single click to switch between them.

Styles Panel

styles panel information density before & afterBefore / After

The redesigned Styles panel of the same size now fits more data:

  • Selectors are no longer generated for style attributes
  • The default “Media: all” header is no longer shown
  • The icons were removed to save some horizontal space

Syntax Highlighting

styles syntax highlighting

Property values are now black to make them easier to distinguish from property names. Strings are still red, but links are now blue.

We added curly braces back so copying CSS would produce valid CSS. Curly braces, colons, and semicolons are light gray so they won’t distract from the content.

Styles Editor

We rewrote the styles editor from scratch. This is the first major overhaul of the styles editor since 2013. Instead of a free-form text editor, we changed to cell-based style editing.

Styles tab and shift-tab behavior

CSS property names and values are now separate editable fields. Pressing Tab (⇥) or Return navigates to the next editable field. Pressing Shift-Tab (⇧⇥) navigates to the previous editable field.

Also, typing a colon (“:”) when focused on the property name focuses on the corresponding property value. Typing semicolon (“;”) at the end of the property value navigates to the next property.

Styles add new property behavior

To add a new property, you can click on the white space before or after an existing property. Pressing Tab (⇥) or Return when focused on the last property value also adds a new property.

Styles remove property behavior

To remove a property, you can remove either a property name or a property value.

Styles up and down arrow behavior

Completion suggestions display right away when focused on the value field. Completion values apply right away when selecting using Up and Down arrow keys.

Styles more arrow key behaviors

While editing a property field, Up and Down arrow keys now can increment and decrement values. You can change the interval by holding modifier keys:

  • Option (⌥): 0.1
  • Shift (⇧): 10
  • Command (⌘): 100

Legacy Settings

Legacy settings screen with the Legacy Style Editor setting

The previous version of the styles editor is still available in the in Web Inspector settings, but it’s no longer maintained.

The Visual Styles Panel never gained enough traction to remain in Elements tab by default. It is no longer maintained. Along with the Legacy Style Editor, the Visual Styles Panel can still be enabled in the Experimental settings.

Contributing

Please report bugs and feature requests regarding the new styles editor on webkit.org/new-inspector-bug. If you’re interested in contributing or have any questions, please stop by the #webkit-inspector IRC channel.

Web Inspector is primarily written in HTML, JavaScript, and CSS, which means that web developers already have the skills needed to jump in and contribute a bug fix, enhancement or a new feature.

April 25, 2018 05:00 PM

April 18, 2018

Release Notes for Safari Technology Preview 54

Surfin’ Safari

Safari Technology Preview Release 54 is now available for download for macOS Sierra and macOS High Sierra. If you already have Safari Technology Preview installed, you can update from the Mac App Store’s Updates tab. This release covers WebKit revisions 230029-230521.

Clipboard API

  • Fixed copying a list from Microsoft Word to TinyMCE when mso-list is the first property (r230120)
  • Prioritized file promises over filenames during drag and drop (r230221)

Beacon API

  • Fixed Beacon redirect responses to be CORS validated (r230495)

Web API

  • Implemented createImageBitmap(Blob) (r230350)

WebRTC

  • Added a special software encoder mode when a compression session is not using a hardware encoder and VCP is not active (r230451)
  • Added experimental support for MDNS ICE candidates in WebRTC data channel peer-to-peer connections (r230290, r230307)

Web Inspector

  • Fixed the errors glyph to fully change to blue when active (r230372)
  • Tinted all pixels drawn by a shader program when hovering over a tree element in the Canvas Tab (r230127)

April 18, 2018 05:00 PM

April 15, 2018

Manuel Rego: CSSWG F2F Berlin 2018

Igalia WebKit

Last week I was in Berlin for the CSS Working Group (CSSWG) face-to-face meeting representing Igalia, member of the CSSWG since last year. Igalia has been working on the open web platform for many years, where we help our customers with the implementation of different standards on the open source web engines. Inside the CSSWG we play the implementors role, providing valuable feedback around the specifications we’re working on.

It was really nice to meet all the folks from the CSSWG there, it’s amazing to be together with such a brilliant group of people in the same room. And it’s lovely to see how easy is to talk with any of them, you all rock!

CSSWG F2F Berlin 2018 by Rossen Atanassov CSSWG F2F Berlin 2018 by Rossen Atanassov

This is a brief post about my highlights from there, of course totally subjective and focused on the topics I’m more interested.

CSS Grid Layout

We were discussing two issues of the current specification related to the track sizing algorithm and its behavior in particular cases. Some changes will be added in the specification to try to improve them and we’ll need to update the implementations accordingly.

On top of that, we discussed about the Level 2 of the spec. It’s already defined that this next level will include the following features:

  • The awaited subgrids feature: There was the possibility of allowing subgrids in both axis (dual-axis) or only in one of them (per-axis), note that the per-axis approach covers the dual-axis if you define the subgrid in both axis.

    There are clear uses cases for the per-axis approach but the main doubt was about how hard it’d be to implement. Mats Palmgren from Mozilla posted a comment on the issue explaining that he has just created a prototype for the feature following the per-axis idea, so the CSSWG resolved to remove the dual-axis one from the spec.

  • And aspect-ratio controlled gutters: Regarding this topic, the CSSWG decided to add a new ar unit. We didn’t discuss anything more but we need to decide what we’ll do in the situations where there’s no enough free space to fulfill the requested aspect-ratio, should we ignore it or overflow in that case?

    Talking to Rachel Andrew about the issue, she was not completely sure of what would be the preferred option from the authors point of view. I’ve just added some examples to the issue so we can discuss about them there and gather more feedback, please share your thoughts.

Tests

This was a discussion I wanted to have with the CSSWG people in order to understand better the current situation and possible next steps for the CSSWG test suites.

Just to add some context, the CSSWG test suites are now part of the web-platform-tests (WPT) repository. This repository is being used by most browser vendors to share tests, including tests for new CSS features. For example, at Igalia we’re currently using WPT test suites in all our developments.

The CSSWG uses the CSS Test Harness tool which has a build system that adds some special requirements for the test suites. One of them causes that we need to duplicate some files in the repository, which is not nice at all.

Several people in the CSSWG still rely on this tool mainly for two things:

  • Run manual tests and store their results: Some CSS features like media queries or scrolling are hard to automate when writing tests, so several specs have manual tests. Probably WebDriver can help to automate this kind of tests, maybe not all though.
  • Extract status reports: To verify that a spec fulfills the CR exit criteria, the current tooling has some nice reports, it also provides info about the test coverage of the spec.

So we cannot get rid of the CSS Test Harness system at this point. We discussed about possible solutions but none of them were really clear, also note that the lack of funding for this kind of work makes it harder to move things forward.

I still believe the way to go would be to improve the WPT Dashboard (wpt.fyi) so it can support the 2 features listed above. If that’s the case maybe the specific CSS Test Harness stuff won’t be needed anymore, thus the weird requirements for people working on the test suites will be gone, and there would be a single tool for all the tests from the different working groups.

As a side note wpt.fyi needs some infrastructure improvements, for example Microfost was not happy as Ahem font (which is used a lot in CSS tests suites) is still not installed on the Windows virtual machines that extract test results for wpt.fyi.

Floats, floats, floats

People are using floats to simulate CSS Shapes on browsers that don’t have support yet. That is causing that some special cases related to floats happen more frecuently, and it’s hard to decide what’s the best thing to do on them.

The CSSWG was discussing what would be the best solution when the non-floated content doesn’t fit in the space left by the floated elements. The problem is quite complex to explain, but imagine the following picture where you have several floated elements.

An example of float layout An example of float layout

In this example there are a few floated elements restricting the area where the content can be painted, if the browser needs to find the place to add a BFC (like a table) it needs to decide where to place it avoiding overlapping any other floats.

There was a long discussion, and it seems the best choice would be that the browser tests all the options and if there’s no overlapping then puts the table there (basically Option 1 in the linked illustration). Still there are concerns about performance, so there’s still more work to be done here. As a result of this discussion a new CSS Floats specification will be created to describe the expected behavior in this kind of scenarios.

Monica Dinculescu created a really cool demo to explain how float layout works, with the help of Ian Kilpatrick who knows it pretty well as he has been dealing with lots of corner cases while working in LayoutNG.

TYPO Labs

The members of the CSSWG were invited to the co-located TYPO Labs event. I attended on Friday when Elika (fantasai), Myles and Rossen gave a talk. It was nice to see that CSS Grid Layout was mentioned in the first talk of the day, as an useful tool for typographers. Variable fonts and Virtual Reality were clearly hot topics in several talks.

Elika (fantasai), Myles and Rossen in the CSSWG talk at TYPO Labs Elika (fantasai), Rossen and Myles in the CSSWG talk at TYPO Labs

It’s funny that the last time I was in Berlin was 10 years ago for a conference related to TYPO3, totally unrelated but with a similar name. 😄

Other

Some pictures of Berlin Some pictures of Berlin

And that’s mostly all that I can remember now, I’m sure I’m missing many other important things. It was a fantastic week and I even find some time for walking around Berlin as the weather was really pleasant.

April 15, 2018 10:00 PM

April 12, 2018

New WebKit Features in Safari 11.1

Surfin’ Safari

Update: This post has been updated to omit Offscreen Canvas which is not available in Safari 11.1 on macOS and Safari on iOS 11.3. Offscreen Canvas is available as an experimental feature in Safari Technology Preview releases.

The recently shipped Safari 11.1 in macOS High Sierra and Safari on iOS 11.3 includes WebKit improvements that add support for a lot of exciting web platform technologies. These features offer new capabilities to developers to improve user-perceived performance of web content, it adds a new dynamic approach for offline experiences, and brings a standard approach to web payments that simplifies development. It also delivers redesigned developer tools in Web Inspector that improve overall usability and convenience.

What follows is a short tour of all of the new features and improvements available with Safari 11.1.

Service Worker API

The Service Worker API enables scripts that run in the background to handle generalized processing for web pages. Service Worker scripts commonly work with other complimentary APIs, such as the Cache API, also included in this release, to store fetch requests and responses that to improve network performance or provide an offline experience. WebKit’s implementation respects user privacy partitioning Service Workers by the top level document origin to help prevent cross-site tracking.

Read the “Workers at Your Service” blog post for more details about the WebKit implementation of Service Workers.

Payment Request API for Apple Pay

WebKit added support for the Payment Request API to perform Apple Pay transactions. This enables merchants to offer payment methods across multiple browsers using a standard API, greatly reducing the effort of supporting secure payments across different browsers and platforms.

See Introducing the Payment Request API for Apple Pay for more details.

Beacon API

Beacon API schedules asynchronous requests to send before the page is unloaded and completes them without a blocking request. This is useful for sending diagnostics data about the web application without impacting perceived page load performance.

See the Beacon specification for more information.

Directory Upload & Clipboard API Updates

The Clipboard API has a number of improvements focusing on a modernized implementation of the DataTransfer API. It adds support for dataTransfer.items, reading and writing of HTML content and custom MIME types, and fixed a number of bugs including copying & pasting images from native applications. WebKit also added support for uploading directories using DataTransfer.webkitGetAsEntry() and input.webkitdirectory, allowing interoperability with other browsers. Users can now upload an entire directory onto cloud storage and file sharing services such as iCloud or Dropbox.

Read more about the improvements to the Clipboard API and Directory Upload API.

Video as Image Assets

Animated image formats are very popular, but they easily become large, bandwidth intensive file sizes. To address the performance impact, WebKit in Safari now supports loading H.264 encoded MP4 video with an HTML tag. This allows content authors to replace animated GIF files that are much larger than H.264 video files and require more processing power to display. Beyond the performance gains, this change also allows web content authors to use videos as a CSS background-image.

Some detailed information about this change is available in the blog post Evolution of : Gif without the GIF by Colin Bendell.

font-display

Page authors have more control over font loading behavior using the newly support font-display descriptor. WebKit’s new default behavior will show invisible text for up to 3 seconds before switching to an installed font until the desired font finishes downloading. Using font-display, the page author can use the swap value to immediately show an installed font until the specified web font is downloaded. There is a fallback behavior to show an installed font for up to 3 seconds and if the desired font doesn’t load in that time, it will never be shown. Finally, the optional behavior will use the font if it is available in the browser’s cache. If it isn’t there, it skips using it at all. These provide a rich set of behaviors for web developers to control the loading and display experience that best suits the design of their web content.

Find more details in the CSS Fonts Module Level 4 specification.

HTML Image Decoding

Content authors sometimes need a loaded, fully decoded image that is available immediately. Loading and decoding large images or lots of images can cause page performance to suffer. The new HTMLImageElement.decode() function asynchronously starts decoding an image and returns a Promise that resolves when the decoded image is available. With it, developers now have control over when loaded images are decoded, without tying up the main thread. Developers can also declaratively indicate an image should load asynchronously using the decoding attribute on an <img> element.

<img decoding="async">
<img decoding="sync">
<img decoding="auto">

For more information, read the WhatWG proposal.

Passive Event Listeners

To avoid causing poor scroll performance when attaching event handlers to touchstart, touchmove, or wheel events, developers can specify their event listener as passive if the listener does not call preventDefault(). This enables Safari to continue to provide high performance scrolling without waiting for the event listener to finish.

More details on Passive Events Listeners can be found in the DOM specification.

Storage Access API

The new Storage Access API provides a solution to allow third-party embeds to request access to their first-party cookies when the user interacts with them in a world with Intelligent Tracking Prevention. This gives content providers the flexibility to provide embedded content, while offering users transparency about who they are sharing their information with.

Find out more about the Storage Access API on the WebKit blog.

Subresource Integrity

WebKit has added support for Subresource Integrity which enables websites to validate the integrity of resources and reject them if something has changed outside the site owner’s control. An integrity check compares a hash provided by the web content author in an integrity attribute on a <script> or a <link> element with a computed hash of the delivered resource. When the hashes don’t match, instead of applying a stylesheet, or executing a script, a network error is returned. This helps web content authors reduce impact a compromised content delivery network (CDN).

Read the Subresource Integrity specification to learn more.

WebDriver Improvements

Safari includes several improvements to the implementation of WebDriver. With Safari 11.1, WebDriver now supports file uploads and testing WebRTC functionality. In addition, several bug fixes improve the overall quality of the WebDriver implementation.

Web Inspector Improvements

Web Inspector has honed the design of several existing tools, and also adds a useful new tool to inspect HTML Canvas elements. The new Canvas tab allows web developers to understand the changes in recorded frames of canvas animations.

The Styles sidebar in the Elements tab was reworked to use a different, but familiar model for editing style rules, properties and values. It also features improvements in navigating between different style views.

Finally, the Network tab was redesigned, improving both the timeline of loading resources, and navigating to the network details of each resource such as content previews, headers, cookies, size and timing details.

Feedback

Most of these improvements are available to users running iOS 11.3 and macOS High Sierra 10.13.4, as well as macOS Sierra and OS X El Capitan. The Storage Access API is only available on iOS 11.3 and macOS High Sierra 10.13.4. These features were also available to web developers with Safari Technology Preview releases. Changes in this release of Safari were included in the following Safari Technology Preview releases: 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47. Download the latest Safari Technology Preview release to stay on the forefront of future web features. You can also use the WebKit Feature Status page to watch for changes to your favorite web platform features.

We love hearing from you. Send a tweet to @webkit or @jonathandavis to share your thoughts on this release, and any features you were hoping for that didn’t make it. If you run into any issues, we welcome your bug reports for Safari, or WebKit bugs for web content issues.

April 12, 2018 05:00 PM

April 05, 2018

Introducing the Payment Request API for Apple Pay

Surfin’ Safari

We’re pleased to announce that Safari 11.1 on macOS and Safari on iOS 11.3 now support the W3C Payment Request API for conducting Apple Pay transactions on the web.

We first introduced Apple Pay on the Web in macOS Sierra and iOS 10. Apple Pay brought novel ease-of-use, security, and privacy to online transactions, so we’ve been encouraged to see it widely adopted by merchants in the years since. However, we recognize that merchants need to support multiple payment methods, and doing so comes at the cost of increased complexity. Payment Request aims to reduce this complexity by supporting payment methods across multiple browsers using a standard API.

Today I’ll take you step-by-step through an Apple Pay transaction using Payment Request. If you’ve already worked with Apple Pay JS, this should look familiar to you. If you haven’t, this is a great place to get started!

Prerequisites

This post assumes that you have already registered a merchant identifier and set up your server environment to process Apple Pay transactions. You can find detailed instructions for doing this in the Apple Pay on the Web documentation.

Showing Apple Pay Buttons

Apple Pay transactions are always initiated by your customer, so you’ll need to display an Apple Pay button for them to tap or click. For a consistent visual appearance, WebKit provides built-in support for rendering Apple Pay buttons. Here’s how to display the most basic type of Apple Pay button:

<button style="-webkit-appearance: -apple-pay-button;"></button>

There are several other types of buttons available in various styles. Here’s a few that you might have seen while shopping in Safari:

Apple Pay Buttons

See Displaying Apple Pay Buttons for more information on the button types and styles available.

According to the Apple Pay on the Web Human Interface Guidelines, you should display Apple Pay buttons whenever your customer is using a supported device. To check if your customer’s device supports Apple Pay, call ApplePaySession.canMakePayments():

if (window.ApplePaySession && ApplePaySession.canMakePayments())
    // Show Apple Pay button.

If your customer taps or clicks an Apple Pay button, you should always present the Apple Pay payment sheet. If they haven’t yet enrolled a payment card you can accept in Apple Pay, Safari prompts them to do so before continuing with your transaction. Since these rules are specific to Apple Pay, Apple Pay JS’s ApplePaySession API is required for this step. The remainder of the transaction can be conducted using standard Payment Request API.

Constructing a PaymentRequest

When your customer taps or clicks an Apple Pay button, you initiate the transaction by constructing a new PaymentRequest:

var request = null;
if (window.PaymentRequest)
    request = new PaymentRequest(methods, details, options);
else
    // Consider using Apple Pay JS instead.

The PaymentRequest constructor takes three arguments: the payment methods you support, the details to show to your customer (like shipping options and total amount), and any options you require.

Payment Methods

Payment methods represent the means by which you can accept payments from your customer using Payment Request. You specify the payment methods you accept as a sequence of PaymentMethodData dictionaries, each of which contains an identifier (supportedMethods) and associated data.

To use Apple Pay with Payment Request, include it as a payment method. Apple Pay’s URL-based payment method identifier is "https://apple.com/apple-pay", and its associated data is an ApplePayRequest dictionary. Here’s what a PaymentMethodData dictionary for Apple Pay might look like:

const applePayMethod = {
    supportedMethods: "https://apple.com/apple-pay",
    data: {
        version: 3,
        merchantIdentifier: "merchant.com.example",
        merchantCapabilities: ["supports3DS", "supportsCredit", "supportsDebit"],
        supportedNetworks: ["amex", "discover", "masterCard", "visa"],
        countryCode: "US",
    },
};

Safari only supports the Apple Pay payment method, but other browsers might support additional payment methods. When you specify multiple payment methods in a request, the browser decides which to present to your customer based on device availability and user preference.

Payment Details

Payment details are represented by the PaymentDetailsInit dictionary. It contains your transaction’s total amount, display items, shipping options, and payment method-specific modifiers (more on modifiers below). Here’s what valid payment details might look like for a $20 item plus tax and two shipping options:

const paymentDetails = {
    total: {
        label: "My Merchant",
        amount: { value: "27.50", currency: "USD" },
    },
    displayItems: [{
        label: "Tax",
        amount: { value: "2.50", currency: "USD" },
    }, {
        label: "Ground Shipping",
        amount: { value: "5.00", currency: "USD" },
    }],
    shippingOptions: [{
        id: "ground",
        label: "Ground Shipping",
        amount: { value: "5.00", currency: "USD" },
        selected: true,
    }, {
        id: "express",
        label: "Express Shipping",
        amount: { value: "10.00", currency: "USD" },
    }],
};

You can choose a default shipping option by setting the selected attribute to true as we did above for "Ground Shipping". The total amount must not be negative, and when using Apple Pay, all payment amounts in your request must use the same ISO 4217 currency code. It is up to you to ensure the correctness of your payment details; Safari does not do any currency calculations on your behalf.

What about modifiers?

You can optionally include a sequence of modifiers in your payment details. Modifiers update your transaction’s display items and total when criteria you specify for a given payment method are satisfied. In Apple Pay, you can use modifiers to adjust the price based on the type of payment card selected in the Apple Pay payment sheet. For instance, the following modifier applies a $1.00 discount when your customer selects a debit card in Apple Pay:

const debitModifier = {
    supportedMethods: "https://apple.com/apple-pay",
    data: { paymentMethodType: "debit" },
    total: {
        label: "My Merchant",
        amount: { value: "26.50", currency: "USD" },
    },
    additionalDisplayItems: [{
        label: "Debit Card Discount",
        amount: { value: "-1.00", currency: "USD" },
    }],
};

Modifiers provide some of the functionality present in the paymentmethodselected event from Apple Pay JS. See ApplePayModifier for more information.

Payment Options

Payment options are represented by the PaymentOptions dictionary. If you need to request your customer’s name, email address, or phone number – or request a certain type of shipping – you can do so here:

const paymentOptions = {
    requestPayerName: true,
    requestPayerEmail: true,
    requestPayerPhone: true,
    requestShipping: true,
    shippingType: "shipping",
};

If you set requestShipping to true, the shipping options you specified in Payment Details are presented in the payment sheet for your customer to choose between. You receive the requested information once your customer authorizes payment.

Exceptions

Safari might raise an exception when constructing a new PaymentRequest. Exceptions can occur for the following reasons:

  • The frame is not in a secure context.
  • The frame is a cross-origin subframe.
  • No payment methods were specified.
  • A payment method identifier is invalid.
  • Calling JSON.stringify() on the payment method data failed.
  • Invalid currency amounts were specified (e.g., negative total or multiple currencies).

canMakePayment() method

Once you’ve constructed a PaymentRequest, you can ask it if your customer will be able to authorize a transaction given the payment methods you can accept. You do this by calling the canMakePayment() method, which returns a promise that resolves to either true or false. In Safari, when Apple Pay is one of the payment methods, canMakePayment() resolves to true only if your customer has an active card enrolled in Apple Pay. This is the equivalent of how ApplePaySession.canMakePaymentsWithActiveCard() behaves in Apple Pay JS.

As we discussed in Showing Apple Pay Buttons, the Apple Pay Human Interface Guidelines require you to show an Apple Pay button whenever your customer is on supported hardware, whether or not they have an active card enrolled. Therefore, you should not hide Apple Pay buttons when canMakePayment() resolves to false. Always show an Apple Pay button if ApplePaySession.canMakePayments() returns true, and always present the Apple Pay payment sheet when your customer taps or clicks the button. Safari prompts your customer to enroll a payment card if they haven’t done so already before continuing with your transaction. For more information, see Human Interface Guidelines > Apple Pay on the Web.

show() method

When your customer taps or clicks an Apple Pay button, you should present the Apple Pay payment sheet. You do this by calling the show() method, which returns a promise that resolves to a PaymentResponse once your customer authorizes payment. The promise is rejected with an AbortError if your customer cancels the transaction.

You can optionally call show() with a promise for a PaymentDetailsUpdate. Sometimes you might still be in the process of calculating payment details when your customer taps or clicks the Apple Pay button. In this case, you can construct a new PaymentRequest with placeholders for details, then call show() with a promise to provide up-to-date details later. When you resolve this promise, Safari displays the updated details in the Apple Pay payment sheet.

Safari might reject the promise returned by show() with an exception. Exceptions can occur for the following reasons:

  • show() was not triggered by user activation (e.g., a tap or click).
  • The request has already been aborted.
  • An Apple Pay session is already active.
  • Payment method data is invalid (e.g., is missing required fields).

abort() method

If you need to abort the presented transaction, you can call the abort() method. When you do this, Safari dismisses the Apple Pay payment sheet and rejects the promise returned by show() with an AbortError. If the transaction has already been aborted, or show() has not yet been called, calling abort() throws an InvalidStateError.

Merchant Validation

Before Safari can present the Apple Pay payment sheet, you must acquire a payment session from Apple. This process is referred to as merchant validation.

Soon after you call show(), Safari dispatches the merchantvalidation event to your PaymentRequest object. The event defines a validationURL attribute representing the Apple URL your server contacts to receive a payment session. You must call the event’s complete() method with a promise that you resolve with this payment session once you receive it.

Here is what a merchantvalidation event handler might look like:

request.onmerchantvalidation = function (event) {
    const sessionPromise = fetchPaymentSession(event.validationURL);
    event.complete(sessionPromise);
};

You can learn more about merchant validation from Requesting an Apple Pay Payment Session.

Shipping Events

Once you’ve received a merchant session, Safari presents the Apple Pay payment sheet to your customer. If you’ve requested shipping, your customer is able to select between your shipping options and provide a shipping address. When they make these selections in the payment sheet, Safari dispatches a shippingoptionchange or shippingaddresschange event to your PaymentRequest object.

shippingoptionchange

When the user selects a shipping option, Safari dispatches the shippingoptionchange event. In your event handler, you can determine the selected shipping option by checking the PaymentRequest‘s shippingOption attribute. To update the payment details based on the selected shipping option, call updateWith() on the event object with a promise that resolves to a PaymentDetailsUpdate.

When requesting shipping with Apple Pay, you must always listen for shippingoptionchange and call updateWith() with a promise that resolves within 30 seconds, otherwise, the transaction will time out.

shippingaddresschange

When your customer selects a shipping address, Safari dispatches the shippingaddresschange event. In your event handler, you can determine the selected shipping address by checking the PaymentRequest‘s shippingAddress attribute. To update the payment details based on the selected shipping address, call updateWith() on the event object with a promise that resolves to a PaymentDetailsUpdate. If you are unable to ship to the selected address, you can provide an error message in your PaymentDetailsUpdate that Safari displays to your customer.

When using Apple Pay, Safari might redact some details from the shipping address. For instance, in the United States, only city, state, 5-digit ZIP code, and country are provided. Safari provides the full, un-redacted shipping address once your customer authorizes payment.

When requesting shipping with Apple Pay, you must always listen for shippingaddresschange and call updateWith() with a promise that resolves within 30 seconds, otherwise the transaction will time out.

Handling Payment Authorization

When your customer authorizes payment, Safari resolves the promise you received from calling show() with a PaymentResponse. Depending on what you requested in your PaymentOptions, the response might contain the selected shipping option, shipping address, name, email, and phone number of your customer.

The response also contains the payment method identifier used to conduct the transaction (methodName), along with its associated details. When Apple Pay is the selected payment method, the associated details is an ApplePayPayment dictionary. ApplePayPayment contains the Apple Pay token you use to process the payment authorization. It also includes your customer’s billing and shipping contact information as ApplePayPaymentContacts if you required this in your ApplePayRequest.

When you have finished processing the payment authorization, you call the complete() method on PaymentResponse to indicate the result of your processing. You can call complete() with a status of "success" or "failure". At this point, the Apple Pay payment sheet is dismissed.

Demo

You now have all the pieces you need to conduct an Apple Pay transaction using Payment Request. Here’s what an Apple Pay session might look like using Payment Request:

async function applePayButtonClicked()
{
    // Consider falling back to Apple Pay JS if Payment Request is not available.
    if (!window.PaymentRequest)
        return;

    try {
        const request = new PaymentRequest([applePayMethod], paymentDetails, paymentOptions);

        request.onmerchantvalidation = function (event) {
            // Have your server fetch a payment session from event.validationURL.
            const sessionPromise = fetchPaymentSession(event.validationURL);
            event.complete(sessionPromise);
        };

        request.onshippingoptionchange = function (event) {
            // Compute new payment details based on the selected shipping option.
            const detailsUpdatePromise = computeDetails();
            event.updateWith(detailsUpdatePromise);
        };

        request.onshippingaddresschange = function (event) {
            // Compute new payment details based on the selected shipping address.
            const detailsUpdatePromise = computeDetails();
            event.updateWith(detailsUpdatePromise);
        };

        const response = await request.show();
        const status = processResponse(response);
        response.complete(status);
    } catch (e) {
        // Handle errors
    }
}

Let’s see how this works in a live demo. If you are viewing this post on a device capable of Apple Pay, you should see an Apple Pay button below. Feel free to click it! Don’t worry, no matter what you do in the payment sheet, your card won’t be charged anything.

Availability

The Payment Request API is available in Safari 11.1 on macOS Sierra and macOS High Sierra, Safari on iOS 11.3, and Safari Technology Preview.

More Information

Apple provides comprehensive documentation for Apple Pay on the Web. Here are a few links you might find useful:

Feedback

We’d love to hear your feedback! If you find a Payment Request bug, please report it at bugs.webkit.org. On Twitter, you can reach the WebKit team at @webkit, or our web technologies evangelist Jonathan Davis at @jonathandavis.

April 05, 2018 05:00 PM

April 04, 2018

Release Notes for Safari Technology Preview 53

Surfin’ Safari

Safari Technology Preview Release 53 is now available for download for macOS Sierra and macOS High Sierra. If you already have Safari Technology Preview installed, you can update from the Mac App Store’s Updates tab. This release covers WebKit revisions 229535-230029.

This release of Safari Technology Preview has a known issue where the modal won’t appear for websites that prompt for camera or microphone access.

Service Workers

  • Changed to use one service worker process per security origin (r229735)
  • Changed to use the same SWServer for all ephemeral sessions (r229872)
  • Fixed promptly terminating service worker processes when they are no longer needed (r229927)
  • Included the security origin in the service worker process name (r229878)

WebRTC

  • Added support for VCP encoder on macOS and iOS (r229920)
  • Fixed the RTCPeerConnection constructor to throw an exception for bad configuration parameters (r229645)
  • Fixed setting SenderTrack to null calling removeTrack with RTCRtpSender (r229587)

Loading

  • Fixed CSS mask images to be retrieved using potentially CORS-enabled fetch (r230006)
  • Fixed loading the stylesheet when changing the <link> element rel attribute from preload to stylesheet (r229585)

Rendering

  • Fixed invalidating descendants for :nth-child and :nth-of-type pseudo classes only when needed (r229537)
  • Fixed positioning for text with letter spacing (r229867)

Media

  • Added Fullscreen API as an Experimental Feature (r229680)
  • Prevented SVG root from being skipped while marking percentage height descendants dirty (r229849)

Accessibility

  • Fixed table row count when role="row" is added to in DOM (r229879)

CSS

  • Fixed CSS Grid auto repeat tracks computation with definite min sizes (r229897)

Web API

  • Added a query and fragment exception to the History API’s unique origin restriction (r229540)

Web Inspector

  • Changed “Force Print Media Styles” to not persist across Web Inspector sessions (r229686)
  • Changed to not show checkboxes for invalid properties in the Styles sidebar (r229941)
  • Fixed the ability to add a new class by editing the class attribute in the DOM tree outline (r229744)
  • Fixed an instance of the main WebGL canvas having no reported size in the Canvas Tab (r229659)
  • Fixed a recording initiated by the user to properly show immediately on completion (r229620)
  • Fixed session dividers not being added when Console tab is not visible (r229785)
  • Fixed flashing when switching between nodes in the Styles sidebar (r229922)
  • Fixed losing focus when editing a property while a page is being loaded (r229787)
  • Prevented the Shift-Command-Left Arrow (⇧⌘←) and Shift-Command-Right Arrow (⇧⌘→) keys from switching tabs when focused on color picker text fields (r230001)
  • Removed redundant tooltips (r229543)

April 04, 2018 05:00 PM

April 03, 2018

Manuel Rego: Getting rid of "grid-" prefix on CSS Grid Layout gutter properties

Igalia WebKit

Early this year I was working on unprefixing the CSS Grid Layout gutter properties. The properties were originally named grid-column-gap and grid-row-gap, together with the grid-gap shorthand. The CSS Working Group (CSSWG) decided to remove the grid- prefix from these properties last summer, so they could be extended to be used in other layout models like Flexbox.

I was not planning to write a blog post about this, but the task ended up becoming something more than just renaming the properties, so this post describes what it took to implement this. Also people got quite excited about the possibility of animating grid gutters when I announced that this was ready on Twitter.

The task

So the theory seems pretty simply, we currently have 3 properties with the grid- prefix and we want to remove it:

  • grid-column-gap becomes column-gap,
  • grid-row-gap becomes row-gap and
  • grid-gap becomes gap.

But column-gap is already an existent property, defined by the Multicolumn spec, which has been around for a long time. So we cannot just create a new property, but we have to make it work also for Grid Layout, and be sure that the syntax is equivalent.

Animatable properties

When I started to test Multicol column-gap I realized it was animatable, however our implementations (Blink and WebKit) of the Grid Layout gutter properties were not. We’d need to make our properties animatable if we want to remove the prefixes.

More on that, I found a bug on Multicol column-gap animation, as its default computed value is normal, and it shouldn’t be possible to animate it. This was fixed quickly by Morten Stenshorne from Google.

Making the properties animatable is not complex at all, both Blink and WebKit have everything ready to make this task easy for properties like the gutter ones that represent lengths. So I decided to do this as part of the unprefixing patch, instead of something separated.

CSS Grid Layout gutters animation example (check it live)

Percentages

But there was something else, the Grid gutter properties accept percentage values, however column-gap hadn’t that support yet. So I added percentage support to column-gap for multicolumn, as a preliminary patch for the unprefixing one.

There has been long discussions in the CSSWG about how to resolve percentages on gutter properties. The spec has recently changed so these properties should be resolved to zero for content-based containers. However my patch is not implementing that, as we don’t believe there’s an easy way to support something like that in most of the web engines, and Blink and WebKit are not exceptions. Our patch follows what Microsoft Edge does in these cases, and resolves the percentage gaps like it does for percentage widths or heights. And the Firefox implementation that has just landed this week does the same.

CSS Multi-column percentage column-gap example (check it live)

I guess we’ll still have some extra discussions about this topic in the CSSWG, but percentages themselves deserve their own blog post.

Implementation

Once all the previous problems got solved, I landed the patches related to unprefixing the gutter properties in both Blink and WebKit. So you can use the unprefixed version since Chrome 66.0.3341.0 and Safari Technology Preview 50.

<div style="display: grid; grid: 100px 50px / 300px 200px;
            column-gap: 25px; row-gap: 10px;">
  <div>Item 1</div>
  <div>Item 2</div>
  <div>Item 3</div>
  <div>Item 4</div>
</div>

A simple Grid Layout example using the unprefixed gutter properties A simple Grid Layout example using the unprefixed gutter properties

Note that as specified in the spec, the previous prefixed properties are still valid and will be kept as an alias to avoid breaking existent content.

Also it’s important to notice that now the gap shorthand applies to Multicol containers too, as it sets the value of column-gap longhand (together with row-gap which would be ignored by Multicol).

<div style="column-count: 2; gap: 100px;">
  <div>First column</div>
  <div>Second column</div>
</div>

Multicolumn example using gap property Multicolumn example using gap property

Web Platform Tests

As usual in our last developments, we have been using web-platform-tests repository for all the tests related to this work. As a result of this work we have now 16 new tests that verify the support of these properties, including tests for animations stuff too.

Running those tests on the different browsers, I realized there was an inconsistency between css-align and css-multicol specifications. Both specs define the column-gap property, but the computed value was different. I raised a CSSWG issue that has been recently solved, so that the computed value for column-gap: normal should still be normal. This causes that the property won’t be animatable from normal to other values as explained before.

This is the summary of the status of these tests in the main browser engines:

  • Blink and WebKit: They pass all the tests and follow last CSSWG resolution.
  • Edge: Unprefixed properties are available since version 41. Percentage support is interoperable with Blink and WebKit. The computed value of column-gap: normal is not normal there, so this needs to get updated.
  • Firefox: It doesn’t have support for the unprefixed properties yet, however the default computed value is normal like in Blink and WebKit. But Multicol column-gap percentage support has just been added. Note that there are already patches on review for this issue, so hopefully they’ll be merged in the coming days.

Conclusions

The task is completed and everything should be settled down at this point, you can start using these unprefixed properties, and it seems that Firefox will join the rest of browser by adding this support very soon.

Igalia and Bloomberg working together to build a better web Igalia and Bloomberg working together to build a better web

Last, but not least, this is again part of the ongoing collaboration between Igalia and Bloomberg. I don’t mind to repeat myself over and over, but it’s really worth to highlight the support from Bloomberg in the CSS Grid Layout development, they have been showing to the world that an external company can directly influence in the new specifications from the standard bodies and implementations by the browser vendors. Thank you very much!

Finally and just as a heads-up, I’ll be in Berlin next week for the CSSWG F2F meeting. I’m sure we’ll have interesting conversations about CSS Grid Layout and many other topics there.

April 03, 2018 10:00 PM

March 22, 2018

Clipboard API Improvements

Surfin’ Safari

The Clipboard API provides a mechanism for websites to support accessing the system pasteboard (pasteboard is the macOS and iOS counterpart to clipboard on Windows and Linux). Copy and paste is one of the most basic interactions in modern operating systems. We use it for all sorts of purposes, from copying a hyperlink on one website to another, to copying a blog post typed in a native word processing application to a blog platform on the web. For this reason, creating a compelling productivity application such as a word processor and a presentation application on the Web requires interacting with the system pasteboard just as much as other native applications.

Over the last couple of months, we have added support for new API for better interoperability with other browsers, and refined our implementations to allow more use cases in macOS and iOS ports of WebKit. These changes are available for you review in Safari 11.1 and iOS 11.3 beta programs.

First, we modernized our DataTransfer API. We added support for items, and fixed many bugs on macOS and iOS. Because most websites don’t support uploading TIFF files, WebKit now automatically converts TIFF images to PNG images and exposes PNG images as files when there are images in the system pasteboard.

Directory Upload

In r221177, we added support for uploading directories via DataTransfer.webkitGetAsEntry() and input.webkitdirectory to be interoperable with other browsers such as Chrome, Firefox, and Edge which had already implemented this WebKit-prefixed feature. This new API allows users to upload a whole directory onto Cloud storage and file sharing services such as iCloud and Dropbox. On iOS, directory upload is supported when dragging folders from the Files app and dropping into web pages.

Custom MIME Types

Because the system pasteboard is used by other native applications, there are serious security and privacy implications when exposing data to web content through the clipboard API. If a website could insert arbitrary content into the system pasteboard, the website can exploit security bugs in any native application which reads the pasteboard content — for instance, a utility application which shows the content put into the pasteboard. Similarly, if a website could read the system pasteboard at any given point in time, it can potentially steal sensitive information such as user’s real full name and mailing addresses that the user was copying.

For this reason, we previously didn’t allow reading of anything but plain text and URL in DataTransfer objects. We relaxed this restriction in r222595 by allowing reading and writing of arbitrary MIME types between web pages of the same origin. This change allows web applications from a single origin to seamlessly share information using their own MIME types and MIME types we don’t support, while still hiding privacy and security sensitive information other native applications may put into the system pasteboard. Because custom MIME types used by websites are bundled together under a special MIME type that WebKit controls, web pages can’t place malicious payloads of arbitrary MIME types in the system pasteboard to exploit bugs in native applications.

Getting and Setting Data

Apart from custom MIME types, web applications may now write text/html, text/plain and text/uri-list to the system pasteboard using DataTransfer.setData or DataTransfer.items.add during a copy or dragstart event. This content is written with the appropriate UTI for macOS and iOS, so pasting into native applications that are already capable of pasting HTML markup, plain text strings, or URLs will work as expected.

On the reading side, web applications may now also use DataTransfer.getData and DataTransfer.items during a paste and drop event to read text/html, text/plain and text/uri-list data from the system pasteboard. If any files were written to the pasteboard — for example, when copying a PDF file in Finder — this information will be accessible through DataTransfer.files and DataTransfer.items; for backwards compatibility, the “Files” type will also be added to the list of types in DataTransfer.types to indicate that file data may be requested by the page.

An important caveat is that native applications may write file paths to the pasteboard as URLs or plain text while copying files. This may cause users to unknowingly expose file paths to the home directory and private containers of native applications. Thus, WebKit implements heuristics to suppress access to this data via DataTransfer API in such cases. If the pasteboard contains at least one file and text/uri-list is requested, the scheme of the URL must be http, https, data, or blob in order for WebKit to expose it to the page. Other schemes, such as file or ftp, will result in an empty string. Likewise, requests for text/plain will return the empty string when there are files on the pasteboard.

Reading and Writing HTML Content

Among other MIME types, HTML content is most pervasive on the web. Unfortunately, letting arbitrary websites write HTML content into the system pasteboard is problematic because HTML can contain script tags and event handlers which can end up executing malicious scripts in the application reading the content. Letting websites read arbitrary HTML content in the system pasteboard is also problematic because some word processor and spreadsheet applications put privacy sensitive information such as local file paths and user information into the HTML placed in the system pasteboard. For example, if an user typed 12345 into an unsaved spreadsheet, and copied & pasted into a random website, the website might be able to learn user’s local home directory path if we were to expose the raw HTML content placed in the pasteboard by other native applications. For this reason, we previously didn’t allow reading or writing of HTML content via DataTransfer objects. Instead, websites had to wait for WebKit’s native editing code to paste the content and process it afterwards.

In r223440, we introduced a mechanism to sanitize HTML read from and written to the system pasteboard, allowing us to lift this restriction. When the website tries to write HTML to the pasteboard, we paste the HTML into a dummy document, re-serialize it to HTML, and then write the re-serialized HTML into the system pasteboard. This process ensures any script elements, event handlers, and other potentially dangerous content will be stripped away. We also package all the necessary sub-resources in the HTML such as images into WebArchive so that native applications which reads the pasteboard content doesn’t have to re-fetch those resources upon paste. Similarly, when a website tries to read the HTML content placed by other native applications, we run through the same steps of pasting the content into a dummy document and re-serializing HTML, stripping away any private information the user didn’t intend to include in the pasted content. Sanitization also happens when HTML content is copied and pasted across different origins but not within web pages of the same origin. As a result, websites can write arbitrary HTML contents via clipboard API and read the exact same content back later within a single origin.

Pasting HTML Content with Images

We also made a major change in the way we handle local files included in the pasted HTML content. Previously, sub-resources (such as image files in pasted content) used URLs of the form webkit-fake-url://<filename> where <filename> is the filename of the sub-resource. Because this is not a standard protocol the website can access, the pasted images’ data were inaccessible to websites. Even though WebKit is capable of loading these images, there was no way for websites to save the images either to their service or into browser’s storage API. r223440 replaces these fake URLs with blob URLs so that the website can save the images. We also use blob URLs instead of fake URLs when pasting RTFD content since r222839.

This change provides a mechanism for Web applications to save images included in pasted content using the Blob API. For example, an online e-mail editor now has the capability to save images that a user copied and pasted from TextEdit or Microsoft Word on iOS and macOS. We’re pleased to be the first browser to provide this powerful platform integration capability to Web developers.

Conclusion

We’re excited to empower productivity apps on the Web to more seamlessly integrate with native applications on macOS and iOS via the updated clipboard API. We’d also like to give special thanks to the developers of TinyMCE who have tirelessly worked with us to resolve many bugs involving copy and paste from Microsoft Word to high profile websites which use TinyMCE.

March 22, 2018 05:00 PM

March 21, 2018

Release Notes for Safari Technology Preview 52

Surfin’ Safari

Safari Technology Preview Release 52 is now available for download for macOS Sierra and macOS High Sierra. If you already have Safari Technology Preview installed, you can update from the Mac App Store’s Updates tab. This release covers WebKit revisions 228856-229535.

Legacy NPAPI Plug-ins

  • Removed support for running legacy NPAPI plug-ins other than Adobe Flash

Service Worker

  • Changed Fetch event release assert to take into account the fetch mode (r228930)
  • Changed to not use a Service Worker in the case of document redirection if it will be already served by AppCache (r229086)
  • Fix loads for a Document controlled by a Service Worker to not use AppCache (r229181)
  • Updated Service Worker to respect IndexedDB and DOM cache partitioning (r229483)

Loading

  • Added support for preconnect link headers (r229308)
  • Fixed converting a load to a download to work with async policy delegates (r229177)
  • Prevented DNS prefetching from being re-enabled (r229061)

JavaScript

  • Fixed handling undefined global variables with the same name as an element ID (r229451)
  • Made Number.isInteger an intrinsic (r228968)

CSS

  • Added new CSS env() constants for use with fullscreen (r229475)
  • Fixed ::selection CSS stroke-color and stroke-width to be applied to selected text in text fields (r229147)

Web API

  • Fixed HTML pattern attribute to set u flag for regular expressions (r229363)
  • Fixed replaceState causing back and forward navigation problems on a page with <base href="/"> (r229375)
  • Fixed document.open to cancel navigation policy check in addition to cancelling the existing provisional load (r228922)

Accessibility

  • Added more accessibility events support (r229310)
  • Dispatched accessiblesetvalue event (r229112)
  • Fixed keyboard focus to follow the VoiceOver cursor into web content or within web content (r228857)
  • Fixed WebKit running spell checker even on non-editable content text (r229500)

Web Driver

  • Fixed clicking on a disabled option element to not produce an error (r229212)
  • Fixed stale elements not getting detected when removed from the DOM (r229210)
  • Fixed failed provisional loads causing “Navigate To” command to hang (r228887)
  • Fixed script evaluations via WebDriver to have a user gesture indicator (r229206)

Web Inspector

  • Changed Canvas Tab to scroll into view and inspect an element if Canvas has a DOM node (r229044)

WebAssembly

  • Added cache for memory address and size on an instance (r228966)

Media

  • Fixed the webkitfullscreenchange event to fire at the same time as :-webkit-full-screen pseudo selector changes (r229466, r229487)

Bug Fix

  • Fixed copying a table from the Numbers app and pasting into iCloud Numbers (r229503)

March 21, 2018 05:00 PM

March 18, 2018

Philippe Normand: Web Engines Hackfest 2014

Igalia WebKit

Last week I attended the Web Engines Hackfest. The event was sponsored by Igalia (also hosting the event), Adobe and Collabora.

As usual I spent most of the time working on the WebKitGTK+ GStreamer backend and Sebastian Dröge kindly joined and helped out quite a bit, make sure to read …

By Philippe Normand at March 18, 2018 09:18 AM

March 16, 2018

Protecting Against HSTS Abuse

Surfin’ Safari

HTTP Strict Transport Security (HSTS) is a security standard that provides a mechanism for web sites to declare themselves accessible only via secure connections, and to tell web browsers where to go to get that secure version. Web browsers that honor the HSTS standard also prevent users from ignoring server certificate errors.

Apple uses HSTS on iCloud.com, for example, so that any time a visitor attempts to navigate to the insecure address “http://www.icloud.com” either by typing that web address, or clicking on a link, they will be automatically redirected to “https://www.icloud.com”. HSTS will also cause the web browser to go to the secure site in the future, even if the insecure address is used. This is a great feature that prevents a simple error from placing users in a dangerous state, such as performing financial transactions over an unauthenticated connection.

What could be wrong with that?

Well, the HSTS standard describes that web browsers should remember when redirected to a secure location, and to automatically make that conversion on behalf of the user if they attempt an insecure connection in the future. This creates information that can be stored on the user’s device and referenced later. And this can be used to create a “super cookie” that can be read by cross-site trackers.

HSTS as a Persistent Cross-Site Identifier (aka “Super Cookie”)

An attacker seeking to track site visitors can take advantage of the user’s HSTS cache to store one bit of information on that user’s device. For example, “load this domain with HTTPS” could represent a 1, while no entry in the HSTS cache would represent a 0. By registering some large number of domains (e.g., 32 or more), and forcing resource loads from a controlled subset of those domains, they can create a large enough vector of bits to uniquely represent each site visitor.

The HSTS authors recognized this possibility in Section 14.9 of their spec:

…it is possible for those who control one or more HSTS Hosts to encode information into domain names they control and cause such UAs to cache this information as a matter of course in the process of noting the HSTS Host. This information can be retrieved by other hosts through cleverly constructed and loaded web resources, causing the UA to send queries to (variations of) the encoded domain names.

On the initial website visit:

  • A random number is assigned to the visitor, for example 8396804.
  • This can be represented as a binary value (e.g., 100000000010000000000100)
  • The tracker script then makes subresource requests to a tracker-controlled domain over https, one request per active bit in the tracking identifier.
    • https://bit02.example.com
    • https://bit13.example.com
    • https://bit23.example.com
    • … and so on.
  • The server responds to each HTTPS request with an HSTS response header, which caches the tracking value in the web browser.
  • Now we are guaranteed to load the HTTPS version of bit02.example.com, bit13.example.com, and bit23.example.com, even if the load is attempted over HTTP.

On subsequent website visits:

  • The tracker script loads 32 invisible pixels over HTTP that represent the bits in the binary number.
  • Since some of those bits (bit02.example.com, bit13.example.com, and bit23.example.com in our example) were loaded with HSTS, they will automatically be redirected to HTTPS.
  • The tracking server transmits one image when they are requested over HTTP, and a different image when requested over HTTPS.
  • The tracking script recognizes the different images, turns those into zero (HTTP) and one (HTTPS) bits in the number, and voila — your unique binary value is recreated and you are tracked!

Attempts to mitigate this attack are challenging because of the difficulty in balancing security and privacy goals. Improperly mitigating the attack also runs the risk of weakening important security protections.

Challenges

Periodically, the privacy risks of HSTS are discussed in the media as a theoretical tracking vector (e.g., [1], [2], and [3]). Absent evidence of actual malicious abuse of the HSTS protocol, browser implementors erred on the side of caution and honored all HSTS instructions provided by sites.

Recently we became aware that this theoretical attack was beginning to be deployed against Safari users. We therefore developed a balanced solution that protects secure web traffic while mitigating tracking.

Apple’s Solution

The HSTS exploit consists of two phases: the initial tracking identifier creation phase, and the subsequent read operation. We decided to apply mitigations to both sides of the attack.

Mitigation 1: Limit HSTS State to the Hostname, or the Top Level Domain + 1

We observed tracking sites constructing long URL’s encoding the digits in various levels of the domain name.

For example:

https://a.a.a.a.a.a.a.a.a.a.a.a.a.example.com
https://a.a.a.a.a.a.a.a.a.a.a.a.example.com
https://a.a.a.a.a.a.a.a.a.a.a.example.com
https://a.a.a.a.a.a.a.a.a.a.example.com
https://a.a.a.a.a.a.a.a.a.example.com
https://a.a.a.a.a.a.a.a.example.com
https://a.a.a.a.a.a.a.example.com
…etc...

We also observed tracking sites using large number of sibling domain names, for example:

https://bit00.example.com
https://bit01.example.com
https://bit02.example.com
...etc...
https://bit64.example.com

Telemetry showed that attackers would set HSTS across a wide range of sub-domains at once. Because using HSTS in this way does not benefit legitimate use cases, but does facilitate tracking, we revised our network stack to only permit HSTS state to be set for the loaded hostname (e.g., “https://a.a.a.a.a.a.a.a.a.a.a.a.a.example.com”), or the Top Level Domain + 1 (TLD+1) (e.g., “https://example.com”).

This prevents trackers from efficiently setting HSTS across large numbers of different bits; instead, they must individually visit each domain representing an active bit in the tracking identifier. While content providers and advertisers may judge that the latency introduced by a single redirect through one origin to set many bits is imperceptible to a user, requiring redirects to 32 or more domains to set the bits of the identifier would be perceptible to the user and thus unacceptable to them and content providers. WebKit also caps the number of redirects that can be chained together, which places an upper bound on the number of bits that can be set, even if the latency was judged to be acceptable.

This resolves the setting side of the super cookie equation.

Mitigation 2: Ignore HSTS State for Subresource Requests to Blocked Domains

We modified WebKit so that when an insecure third-party subresource load from a domain for which we block cookies (such as an invisible tracking pixel) had been upgraded to an authenticated connection because of dynamic HSTS, we ignore the HSTS upgrade request and just use the original URL. This causes HSTS super cookies to become a bit string consisting only of zeroes.

Conclusion

Telemetry gathered during internal regression testing, our public seeds, and the final public software release indicates that the two mitigations described above successfully prevented the creation and reading of HSTS super cookies while not regressing the security goals of first party content. We believe them to be consistent with best practices, and to maintain the important security protections provided by HSTS. We have shared the details of Mitigation 1 with the authors of RFC 6797, and are working to incorporate the behavior as part of the standard.

However, the internet is a wide space full of unique and amazing uses of Web Technology. If you feel that you have a legitimate case where these new rules are not working as intended, we would like to know about it. Please send feedback and questions to web-evangelist@apple.com or @webkit on Twitter, and file any bugs that you run into on WebKit’s bug tracker.

Notes

  1. https://arstechnica.com/information-technology/2015/10/unpatched-browser-weaknesses-can-be-exploited-to-track-millions-of-web-users/
  2. http://www.businessinsider.com/super-cookies-hsts-security-private-2015-1,
  3. https://nakedsecurity.sophos.com/2015/02/02/anatomy-of-a-browser-dilemma-how-hsts-supercookies-make-you-choose-between-privacy-or-security/

March 16, 2018 06:00 PM

March 14, 2018

Intelligent Tracking Prevention 1.1

Surfin’ Safari

In June of last year, we announced Intelligent Tracking Prevention, or ITP. ITP is a privacy feature which detects domains that have the ability to track the user cross-site and either partitions or purges the associated website data.

The biggest update to ITP so far is the introduction of the Storage Access API which provides a mechanism for embedded third-party content to get out of cookie partitioning through user interaction. In addition to the Storage Access API, ITP 1.1 includes two behavior changes described below.

Partitioned Cookies No Longer Persisted to Disk

With ITP 1.1, all partitioned cookies are treated as session cookies and are not persisted to disk.

Domains that have their cookies partitioned by ITP have a way to get access to their non-partitioned cookies through the Storage Access API. Therefore there is no longer a need to persist partitioned cookies across browsing sessions.

Cookies Blocked If They Will Be Purged Anyway

ITP’s purging of cookies and other website data happens once an hour for performance reasons. In between purges, ITP 1.0 would partition cookies for domains with a pending purge to make sure there were no gaps where cross-site tracking could happen. This caused a situation where cookies were purged shortly after being created, potentially confusing servers.

With ITP 1.1, domains with a pending purge will not be able to set new cookies and their existing cookies are not sent in requests. This makes the transition from partitioned cookies to purged cookies distinct and easier to handle for developers.

Intelligent Tracking Prevention 1.1 Timeline

Feedback

These updates to Intelligent Tracking Prevention are available in Safari 11.1 on iOS 11.3 beta and macOS High Sierra 10.13.4 beta, as well as in Safari Technology Preview. Please report bugs through bugs.webkit.org, or send feedback on Twitter to the team @webkit, or our evangelist @jonathandavis. If you have technical questions about these changes, you can find me on Twitter @johnwilander.

March 14, 2018 08:00 PM

March 07, 2018

Release Notes for Safari Technology Preview 51

Surfin’ Safari

Safari Technology Preview Release 51 is now available for download for macOS Sierra and macOS High Sierra. If you already have Safari Technology Preview installed, you can update from the Mac App Store’s Updates tab. This release covers WebKit revisions 228454-228856.

This release of Safari Technology Preview may reset your homepage and search engine preferences to Safari’s defaults.

Accessibility

  • Added accessibleclick event (r228827)

Security

  • Disallowed cross-origin subresources from asking for credentials (r228486)
  • Prevented blocking authentication challenges to navigated resources (r228703)

Loading

  • Fixed provisional loads that might get committed before receiving the decidePolicyForNavigationResponse response (r228852)

Service Workers

  • Fixed the ability to download resources loaded from Service Workers (r228551)

Rendering

  • Changed to handle all SVG writing modes (r228822)

Styles

  • Improved the speed of descendent selector invalidation by using a selector filter (r228729)

Web Inspector

  • Added support to show or hide the navigation sidebar panel based on the current view (r228722)
  • Fixed hiding the completion popover when switching panels in the Styles sidebar (r228487)

Bugs

  • Added support for scrolling a non-editable web-selection and start autoscroll when near screen edges (r228549)

March 07, 2018 06:00 PM

February 21, 2018

Introducing Storage Access API

Surfin’ Safari

In June last year we introduced Intelligent Tracking Prevention (ITP). ITP is a privacy feature that detects which domains have the ability to track the user cross-site and either partitions the domain’s cookies or purges its website data all together.

The strongest developer feedback we got on ITP was that it needs to provide a way for embedded cross-site content to authenticate users who are already logged in to their first-party services. Today we are happy to provide a solution in the form of Storage Access API. It allows for authenticated embeds while continuing to protect customers’ privacy by default.

Partitioned Cookies and Embedded Content

Let’s say that socialexample.org is embedded on multiple websites to facilitate commenting or “liking” content with the user’s socialexample ID. ITP will detect that such multi-page embeds gives socialexample.org the ability to track the user cross-site and therefore deny embedded content from socialexample.org access to its first-party cookies, providing only partitioned cookies. This breaks the user’s ability to comment and like content unless they have interacted with socialexample.org as first-party site in the last 24 hours. (Please see the original ITP blog post for the exact rules around partitioned cookies.)

The same goes for embedded third-party payment providers and embedded third-party videos from subscription services. As soon as ITP detects their tracking abilities, it denies them first-party cookie access outside the 24 hour window, and the embedded content treats the user as logged out even though they are logged in.

We’ve made tradeoffs for user privacy. But it would be even better if we could provide the benefits of being logged in to third party iframes, provided that the user is actually interested in using them, while still protecting privacy.

The Solution: Storage Access API

The solution is to allow third-party embeds to request access to their first-party cookies when the user interacts with them. To do this, we created the Storage Access API.

The Storage Access API offers two new functions to cross-origin iframes — document.hasStorageAccess() and document.requestStorageAccess(). It also offers the embedding top frame a new iframe sandbox token — “allow-storage-access-by-user-activation”.

Storage access in this context means that the iframe has access to its first-party cookies, i.e. the same cookies it would have access to as a first-party site. Note that storage access does not relax the same-origin policy in any way. Specifically, this is not about third-party iframes getting access to the embedding website’s cookies and storage, or vice versa.

WebKit’s implementation of the API only covers cookies for now. It does not affect the partitioning of other storage forms such as IndexedDB or LocalStorage.

Check For Storage Access

A call to document.hasStorageAccess() returns a promise that resolves with a boolean indicating whether the document already has access to its first-party cookies or not. Should the iframe be same-origin as the top frame, the promise returns true.

var promise = document.hasStorageAccess();
promise.then(
  function (hasAccess) {
    // Boolean hasAccess says whether the document has access or not.
  },
  function (reason) {
    // Promise was rejected for some reason.
  }
);

Request Storage Access

A call to document.requestStorageAccess() upon a user gesture such as a tap or click returns a promise that is resolved if storage access was granted and is rejected if access was denied. If storage access was granted, a call to document.hasStorageAccess() will return true. The reason why iframes need to call this API explicitly is to offer developers control over when the document’s cookies change.

<script>
function makeRequestWithUserGesture() {
  var promise = document.requestStorageAccess();
  promise.then(
    function () {
      // Storage access was granted.
    },
    function () {
      // Storage access was denied.
    }
  );
}
</script>
<button onclick="makeRequestWithUserGesture()">Play video</button>

The iframe needs to adhere to a set of rules to be able to get storage access granted. The basic rules are:

  • The iframe’s cookies need to be currently partitioned by ITP. If they’re not, the iframe either already has cookie access or cannot be granted access because its cookies have been purged.
  • The iframe needs to be a direct child of the top frame.
  • The iframe needs to be processing a user gesture at the time of the API call.

Below are the detailed rules for the promise returned by a call to document.requestStorageAccess(). When we say eTLD+1 we mean effective top-level domain + 1. An eTLD is .com or .co.uk so an example of an eTLD+1 would be social.co.uk but not sub.social.co.uk (eTLD+2) or co.uk (just eTLD).

  1. If the sub frame is sandboxed but doesn’t have the tokens “allow-storage-access-by-user-activation” and “allow-same-origin”, reject.
  2. If the sub frame’s parent is not the top frame, reject.
  3. If the browser is not processing a user gesture, reject.
  4. If the sub frames eTLD+1 is equal to the top frame’s eTLD+1, resolve. As an example, login.socialexample.co.uk has the same eTLD+1 as www.socialexample.co.uk.
  5. If the sub frame’s origin’s cookies are currently blocked, reject. This means that ITP has either purged the origin’s website data or will do so in the near future. Thus there is no storage to get access to.
  6. If all the above has passed, resolve.

Access Removal

Storage access is granted for the life of the document as long as the document’s frame is attached to the DOM. This means:

  • Access is removed when the sub frame navigates.
  • Access is removed when the sub frame is detached from the DOM.
  • Access is removed when the top frame navigates.
  • Access is removed when the webpage goes away, such as a tab close.

Sandboxed Iframes

If the embedding website has sandboxed the iframe, it cannot be granted storage access by default. The embedding website needs to add the sandbox token “allow-storage-access-by-user-activation” to allow successful storage access requests. The iframe sandbox also needs the tokens “allow-scripts” and “allow-same-origin” since otherwise it can’t call the API and doesn’t execute in an origin that can have cookies.

<iframe sandbox="allow-storage-access-by-user-activation allow-scripts allow-same-origin"></iframe>

A Note On Potential Abuse

We have decided not to prompt the user when an iframe calls the Storage Access API to make the user experience as smooth as possible. ITP’s rules are an effective gatekeeper for who can be granted access, and for the time being we rely on them.

However, we will monitor the adoption of the API and make changes if we find widespread abuse where the user is clearly not trying to take some authenticated action in the calling iframe. Such API behavior changes may be prompts, abuse detection resulting in a rejected promise, rate limiting of API calls per origin, and more.

Availability

Storage Access API is available in Safari 11.1 on iOS 11.3 beta and macOS High Sierra 10.13.4 beta, as well as in Safari Technology Preview 47+. If you’re interested in cross-browser compatibility, please follow the whatwg/html issue for Storage Access API.

Feedback

Please report bugs through bugs.webkit.org, or send feedback on Twitter to the team @webkit, or our evangelist @jonathandavis. If you have technical questions about how the Storage Access API works, you can find me on Twitter @johnwilander.

February 21, 2018 09:00 PM

Release Notes for Safari Technology Preview 50

Surfin’ Safari

Safari Technology Preview Release 50 is now available for download for macOS Sierra and macOS High Sierra. If you already have Safari Technology Preview installed, you can update from the Mac App Store’s Updates tab. This release covers WebKit revisions 227873-228454.

Service Workers

  • Added support for cache storage of blob responses (r228326)
  • Changed to queue a microtask when a waitUntil() promise is settled (r227959)
  • Delayed service worker process creation until actually needed (r227989)
  • Delayed saving service worker registrations to disk until after the activation succeeds (r228180)
  • Fixed issue with IndexedDB databases not persisting inside Service Workers (r228230)
  • Fixed issue where service workers jobs would sometimes not get processed anymore (r228101)
  • Fixed clearing a registration to properly null out its workers before setting their state to "redundant" (r228015)
  • Fixed clearing all service worker registrations to wait for importing the service worker registration to finish (r228025, r228034)
  • Started nulling out registration.installing before setting service worker state to “redundant” when install fails (r227997)

Web App Manifest

  • Changed to default Web App Manifest scope to the containing directory of the start URL when 'scope' is not specified (r228036)

Payment Request

  • Changed show() to take an optional PaymentDetailsUpdate promise (r228195)
  • Fixed payment sheet not dismissing when calling complete() with result "unknown" or "fail" (r228342)

Web API

  • Implemented createImageBitmap(HTMLVideoElement) (r228092)

Rendering

  • Corrected invaliding style for sibling combinators on class change (r227956)
  • Fixed rendering SVG images with same size as WebGL texture (r228213)
  • Fixed computing inline-block baseline for vertical-lr (r227947)

Web Inspector

  • Added listing of Canvases, Programs, and Recordings to the sidebar (r228301)
  • Fixed the Canvas tab tree selection abruptly changing when selecting a recording frame (r228362)
  • Fixed pasting multiple properties to create properties instead of causing a bad property in the Styles Sidebar (r228030)
  • Fixed the completion popover not hiding when switching panels in the Styles Sidebar (r228232)
  • Fixed typing a value and quickly moving focus away sometimes displaying an outdated value in the Styles Sidebar (r228296)
  • Updated the Elements tab to have “Jump to Layer” functionality (r228215)

Web Driver

  • Changed cookies returned by automation to have expiry time in seconds (r227891)
  • Changed to not return an error if resizing or moving a window has no effect (r228434)
  • Prepended a dot to the domain when missing in the addCookie command (r228087, r228371)

Accessibility

  • Fixed Accessibility getting notified when a web process cancels suspension (r228350)
  • Deferred attribute computation until needed (r228279)
  • Deferred focus notifications for UI elements (r228417)

JavaScript

  • Changed to throw an exception when using structured cloning on a Symbol (r227969)
  • Fixed an incorrect case of variable resolution to consult the global lexical environment first before the global object (r227898)

February 21, 2018 06:00 PM

February 17, 2018

Michael Catanzaro: On Compiling WebKit (now twice as fast!)

Igalia WebKit

Are you tired of waiting for ages to build large C++ projects like WebKit? Slow headers are generally the problem. Your C++ source code file #includes a few headers, all those headers #include more, and those headers #include more, and more, and more, and since it’s C++ a bunch of these headers contain lots of complex templates to slow down things even more. Not fun.

It turns out that much of the time spent building large C++ projects is effectively spent parsing the same headers again and again, over, and over, and over, and over, and over….

There are three possible solutions to this problem:

  • Shred your CPU and buy a new one that’s twice as fast.
  • Use C++ modules: import instead of #include. This will soon become the best solution, but it’s not standardized yet. For WebKit’s purposes, we can’t use it until it works the same in MSVCC, Clang, and three-year-old versions of GCC. So it’ll be quite a while before we’re able to take advantage of modules.
  • Use unified builds (sometimes called unity builds).

WebKit has adopted unified builds. This work was done by Keith Miller, from Apple. Thanks, Keith! (If you’ve built WebKit before, you’ll probably want to say that again: thanks, Keith!)

For a release build of WebKitGTK+, on my desktop, our build times used to look like this:

real 62m49.535s
user 407m56.558s
sys 62m17.166s

That was taken using WebKitGTK+ 2.17.90; build times with any 2.18 release would be similar. Now, with trunk (or WebKitGTK+ 2.20, which will be very similar), our build times look like this:

real 33m36.435s
user 214m9.971s
sys 29m55.811s

Twice as fast.

The approach is pretty simple: instead of telling the compiler to build the original C++ source code files that developers see, we instead tell the compiler to build unified source files that look like this:

// UnifiedSource1.cpp
#include "CSSValueKeywords.cpp"
#include "ColorData.cpp"
#include "HTMLElementFactory.cpp"
#include "HTMLEntityTable.cpp"
#include "JSANGLEInstancedArrays.cpp"
#include "JSAbortController.cpp"
#include "JSAbortSignal.cpp"
#include "JSAbstractWorker.cpp"

Since files are included only once per translation unit, we now have to parse the same headers only once for each unified source file, rather than for each individual original source file, and we get a dramatic build speedup. It’s pretty terrible, yet extremely effective.

Now, how many original C++ files should you #include in each unified source file? To get the fastest clean build time, you would want to #include all of your C++ source files in one, that way the compiler sees each header only once. (Meson can do this for you automatically!) But that causes two problems. First, you have to make sure none of the files throughout your entire codebase use conflicting variable names, since the static keyword and anonymous namespaces no longer work to restrict your definitions to a single file. That’s impractical in a large project like WebKit. Second, because there’s now only one file passed to the compiler, incremental builds now take as long as clean builds, which is not fun if you are a WebKit developer and actually need to make changes to it. Unifying more files together will always make incremental builds slower. After some experimentation, Apple determined that, for WebKit, the optimal number of files to include together is roughly eight. At this point, there’s not yet much negative impact on incremental builds, and past here there are diminishing returns in clean build improvement.

In WebKit’s implementation, the files to bundle together are computed automatically at build time using CMake black magic. Adding a new file to the build can change how the files are bundled together, potentially causing build errors in different files if there are symbol clashes. But this is usually easy to fix, because only files from the same directory are bundled together, so random unrelated files will never be built together. The bundles are always the same for everyone building the same version of WebKit, so you won’t see random build failures; only developers who are adding new files will ever have to deal with name conflicts.

To significantly reduce name conflicts, we now limit the scope of using statements. That is, stuff like this:

using namespace JavaScriptCore;
namespace WebCore {
//...
}

Has been changed to this:

namespace WebCore {
using namespace JavaScriptCore;
// ...
}

Some files need to be excluded due to unsolvable name clashes. For example, files that include X11 headers, which contain lots of unnamespaced symbols that conflict with WebCore symbols, don’t really have any chance. But only a few files should need to be excluded, so this does not have much impact on build time. We’ve also opted to not unify most of the GLib API layer, so that we can continue to use conventional GObject names in our implementation, but again, the impact of not unifying a few files is minimal.

We still have some room for further performance improvement, because some significant parts of the build are still not unified, including most of the WebKit layer on top. But I suspect developers who have to regularly build WebKit will already be quite pleased.

By Michael Catanzaro at February 17, 2018 07:07 PM

February 16, 2018

Michael Catanzaro: On Python Shebangs

Igalia WebKit

So, how do you write a shebang for a Python program? Let’s first set aside the python2/python3 issue and focus on whether to use env. Which of the following is correct?

#!/usr/bin/env python
#!/usr/bin/python

The first option seems to work in all environments, but it is banned in popular distros like Fedora (and I believe also Debian, but I can’t find a reference for this). Using env in shebangs is dangerous because it can result in system packages using non-system versions of python. python is used in so many places throughout modern systems, it’s not hard to see how using #!/usr/bin/env in an important package could badly bork users’ operating systems if they install a custom version of python in /usr/local. Don’t do this.

The second option is broken too, because it doesn’t work in BSD environments. E.g. in FreeBSD, python is installed in /usr/local/bin. So FreeBSD contributors have been upstreaming patches to convert #!/usr/bin/python shebangs to #!/usr/bin/env python. Meanwhile, Fedora has begun automatically rewriting #!/usr/bin/env python to #!/usr/bin/python, but with a warning that this is temporary and that use of #!/usr/bin/env python will eventually become a fatal error causing package builds to fail.

So obviously there’s no way to write a shebang that will work for both major Linux distros and major BSDs. #!/usr/bin/env python seems to work today, but it’s subtly very dangerous. Lovely. I don’t even know what to recommend to upstream projects.

Next problem: python2 versus python3. By now, we should all be well-aware of PEP 394. PEP 394 says you should never write a shebang like this:

#!/usr/bin/env python
#!/usr/bin/python

unless your python script is compatible with both python2 and python3, because you don’t know what version you’re getting. Your python script is almost certainly not compatible with both python2 and python3 (and if you think it is, it’s probably somehow broken, because I doubt you regularly test it with both). Instead, you should write the shebang like this:

#!/usr/bin/env python2
#!/usr/bin/python2
#!/usr/bin/env python3
#!/usr/bin/python3

This works as long as you only care about Linux and BSDs. It doesn’t work on macOS, which provides /usr/bin/python and /usr/bin/python2.7, but still no /usr/bin/python2 symlink, even though it’s now been six years since PEP 394. It’s hard to understate how frustrating this is.

So let’s say you are WebKit, and need to write a python script that will be truly cross-platform. How do you do it? WebKit’s scripts are only needed (a) during the build process or (b) by developers, so we get a pass on the first problem: using /usr/bin/env should be OK, because the scripts should never be installed as part of the OS. Using #!/usr/bin/env python — which is actually what we currently do — is unacceptable, because our scripts are python2 and that’s broken on Arch, and some of our developers use that. Using #!/usr/bin/env python2 would be dead on arrival, because that doesn’t work on macOS. Seems like the option that works for everyone is #!/usr/bin/env python2.7. Then we just have to hope that the Python community sticks to its promise to never release a python2.8 (which seems likely).

…yay?

By Michael Catanzaro at February 16, 2018 08:21 PM

February 07, 2018

Workers at Your Service

Surfin’ Safari

Update: A previous version of this post stated the Service Worker API is available in all applications using WKWebView. At this time it is only available in Safari, applications that use SFSafariViewController, and web applications saved to your home screen.

The Service Worker API exposes persistent background processing capabilities to web pages. Support is available in Safari Technology Preview 48, macOS High Sierra 10.13.4 and iOS 11.3 beta seed 2. While WebKit’s implementation and feature set is quickly evolving, we believe it has reached an important milestone in terms of functionality and compliance: applications using service workers for offline support or network/cache optimizations run successfully on latest WebKit builds. Let’s now dive into the specifics of the WebKit Service Worker API implementation.

By specification, service workers and service worker clients are partitioned by their origin. To prevent user cross-site tracking, WebKit further partitions service workers and service worker clients by the top level document origin, the origin shown in the address bar. Frames that are same origin as the top level document will behave the same as in other browser engines. WebKit behaves differently for cross-origin frames. A service worker registered by an example.com iframe inside a webkit.org page will be able to communicate to all service workers and clients that share the same (webkit.org, example.com) partition, but not to any other example.com or webkit.org client. A network load made by a (webkit.org, example.com) service worker will use the same cookies as if the network load was made in an example.com frame embedded in a webkit.org page. Similarly, private browsing mode is enforced in a service worker by partitioning service workers according the browsing session.

The Service Worker API is implemented in WebKit’s multi-process infrastructure which offers both security and performance benefits. Service worker instances run in an isolated service worker process. This process is similar to WebContent processes responsible for rendering web pages and executing arbitrary JavaScript. A separate process, the Storage process, handles the registration, persistency and lifecycle of service workers. As a service worker instance consumes both memory and CPU time, it is important to run them when needed only. Service workers are typically started when being initially registered by a web page. In normal conditions, a service worker will be terminated when there is no service worker client in its partition after a small grace period. Service workers are restarted whenever some interaction is needed, typically in case of postMessage or fetch events.

The Cache API allows storing fetch requests and responses persistently. This is a key API for offline support and proxy-based network optimizations. Similarly to service workers, caches are partitioned by (top origin, frame origin) and browsing session. The current Cache API quota is set to a fixed value of 50 MiB per partition. Once this limit is reached, the web application needs to evict cache entries in order to free space. Both service worker and cache persistent information can be cleared with WebKit APIs. In Safari Technology Preview, this information is put in the ‘Cache’ category of the Privacy preference pane.

Service worker and Cache API stored information will grow as a user is browsing content. To keep only the stored information that is useful to the user, WebKit will remove unused service worker registrations after a period of a few weeks. Caches that do not get opened after a few weeks will also be removed. Web Applications must be resilient to any individual cache, cache entry or service worker being removed.

Web Inspector supports debugging service workers. The ‘Develop’ menu contains the list of running service workers at any time. When clicking on one of the service worker entries, an inspector will be attached to the service worker. From here, you can debug code related to fetch or postMessage events by using breakpoints. The inspector console is also a great place to trigger network loads in the context of the service worker using the fetch API. The service worker caches can be inspected from the console as well with a few lines of code.

We are excited to see service worker applications coming to WebKit and Apple platforms. We encourage you to try the latest implementation and feature set available in Safari Technology Preview 48, macOS High Sierra 10.13.4 beta seed 2, and iOS 11.3 beta seed 2. We want to hear your feedback! File a bug, email web-evangelist@apple.com, or tweet to @webkit.

February 07, 2018 09:00 PM

Release Notes for Safari Technology Preview 49

Surfin’ Safari

Safari Technology Preview Release 49 is now available for download for macOS Sierra and macOS High Sierra. If you already have Safari Technology Preview installed, you can update from the Mac App Store’s Updates tab. This release covers WebKit revisions 227071-227873.

Service Workers

  • Changed Service Workers restored from persistent storage to have “activated” state (r227153)
  • Changed to terminate Service Workers that are unresponsive (r227174)
  • Prevented Service Worker registrations restored from disk from being reused when the JavaScript calls register() again (r227220)

Fetch

  • Added support for ConsumeData callback when chunk data is received for Fetch response (r227870)
  • Changed opaque being-loaded responses to clone their body (r227581)
  • Filtered out Fetch headers from an opaque response (r227339)
  • Fixed Fetch redirect to be compatible with “no-cors” mode (r227270)
  • Fixed Fetch response to copy its URL from the request if it is null (r227531)
  • Set integrity Fetch options for loading scripts and CSS (r227612)

Intelligent Tracking Prevention

  • Blocked cookies for prevalent resources without user interaction (r227103)
  • Ensured ServiceWorker loading and requests are correctly cleared by Intelligent Tracking Prevention (r227358)
  • Introduced debug mode as experimental feature (r227762)

CSS

  • Added support for percentages in column-gap (r227676)
  • Added support for parsing calc() in CSS media queries (r227295)
  • Adopted CSS WG recommended syntax changes to remove "left" and "right" in block/cross-axis alignment properties (r227432)
  • Adopted CSS WG recommended syntax changes requiring overflow-position to precede
    self-position or content-position in the css-align property (r227297)
  • Adopted support for a recent specification change removing "baseline" as a valid value for the ‘justify-content’ property (r227786)
  • Fixed computing the scroll position of position:fixed elements when the scale is greater than 1 (r227430)
  • Preserved original image and picture element colors when invert colors is on (r227219)

Rendering

  • Fixed the overflow of formulas for display mathematics (r227722)
  • Optimized building the non-fast scrollable region with multiple iframes (r227396)

SVG

  • Fixed the feMorphology SVG filter to allow the radius on one axis to be 0 and still apply the effect (r227440)

JavaScript

  • Implemented trimStart and trimEnd (r227779)
  • Relaxed line terminators in String to make JSON subset of JavaScript (r227775)

Web Inspector

  • Changed clicking on a path component that has no siblings to now select it (r227108)
  • Changed the Layers tab to use a statically positioned layer details panel instead of a moving popover (r227244)
  • Changed the Styles sidebar to always display CSS rules left-to-right, even when Web Inspector uses RTL layout (r227228)
  • Fixed an issue that caused the Canvas Tab to display multiple “waiting for frames” messages (r227243)
  • Fixed an issue that cause the record button on a Canvas Tab canvas to sometimes not appear on hover (r227155)
  • Fixed a bug that caused the Network Tab sort indicator to hide when a sorted column is hidden and re-shown (r227667)
  • Fixed the Network Tab’s table columns to no longer shake when scrolling at non-default zoom levels (r227463)
  • Fixed a data corruption issue triggered by updating values in the Styles Sidebar quickly (r227370)
  • Fixed the Styles sidebar to stop throwing exceptions when tabbing past commented out properties (r227232)
  • Fixed the Resource Tab detail sidebar to wrap super long URLs better (r227072)
  • Fixed Window resizing when the Web Inspector is detached from the browser (r227429)
  • Prevented showing “Displayed Columns” when right-clicking in a table header if all columns are required (r227652)
  • Improved the behavior of the Cookies table in the Network Tab at narrow widths (r227666)
  • Improved Navigation Bar layout at narrow heights (r227707)

Media

  • Added support of multi keys from different sessions in CDMinstanceClearKey (r227409)
  • Changed to resign the NowPlaying status when no media element is eligible (r227373, r227457)
  • Changed to use existing RGB colorspace instead of creating a new one (r227094)
  • Fixed cues for WebVTT served via HLS (r227121)

Storage

  • Added a deprecation warning to the Console when AppCache is used (r227225)
  • Added console messages for cache storage errors like Quota (r227245)
  • Changed to not use the storage process when loading a main resource if there is no Service Worker registered (r227161)
  • Changed to not use the storage process when registering a Service Worker client if there is no Service Worker registered (r227242)
  • Ensured Cache API will resolve caches.open promises in the same order as called (r227768)
  • Fixed DOMCache data not getting properly removed when clearing data for a given origin (r227269)
  • Increased default cache storage quota to 50MB (r227298)

Security

  • Added a policy check for targeted windows when navigating to a JavaScript URL (r227567)
  • Added CSP post checks for Service Worker responses (r227680)
  • Disabled access to Service Workers and the Cache API in sandboxed frames without the allow-same-origin flag (r227639)
  • Updated frame-ancestor directive to match Content Security Policy Level 3 (r227238)

Accessibility

  • Added support for ARIA active-descendant (r227144)
  • Added a way for VoiceOver to uniquely identify a web session (r227526)
  • Implemented support for Graphics ARIA roles: graphics-document, graphics-object,
    and graphics-symbol (r227344)
  • Prevented SVG AAM mapping from overriding ARIA role attribute in the case of SVG root (r227536)

Bug Fixes

  • Fixed the GitHub login at forums.swift.org by ensuring redirections for subresource loads can change Service Worker controllers (r227348)
  • Fixed blob conversion and sanitization for Microsoft Word for Mac 2011 (r227351)
  • Prevented a disallowed user-installed font from being used if its PostScript name is specified (r227776)

February 07, 2018 06:00 PM

January 24, 2018

Michael Catanzaro: Announcing Epiphany Technology Preview

Igalia WebKit

If you use macOS, the best way to use a recent development snapshot of WebKit is surely Safari Technology Preview. But until now, there’s been no good way to do so on Linux, short of running a development distribution like Fedora Rawhide.

Enter Epiphany Technology Preview. This is a nightly build of Epiphany, on top of the latest development release of WebKitGTK+, running on the GNOME master Flatpak runtime. The target audience is anyone who wants to assist with Epiphany development by testing the latest code and reporting bugs, so I’ve added the download link to Epiphany’s development page.

Since it uses Flatpak, there are no host dependencies asides from Flatpak itself, so it should work on any system that can run Flatpak. Thanks to the Flatpak sandbox, it’s far more secure than the version of Epiphany provided by your operating system. And of course, you enjoy automatic updates from GNOME Software or any software center that supports Flatpak.

Enjoy!

(P.S. If you want to use the latest stable version instead, with all the benefits provided by Flatpak, get that here.)

By Michael Catanzaro at January 24, 2018 10:58 PM

Release Notes for Safari Technology Preview 48

Surfin’ Safari

Safari Technology Preview Release 48 is now available for download for macOS Sierra and macOS High Sierra. If you already have Safari Technology Preview installed, you can update from the Mac App Store’s Updates tab. This release covers WebKit revisions 226358-227071.

Password AutoFill

  • Disabled Automatic AutoFill of user names and passwords at page load to prevent sharing information without user consent

Storage Access API

  • Enabled the Storage Access API by default (r226418, r226669)
  • Changed to remove access for all frames under a page when the page is closed (r226542)

SVG

  • Fixed SVG lighting filter lights to use the correct coordinate system (r226363)
  • Fixed feLighting that has a filter primitiveUnits="objectBoundingBox" (r226373)

Service Workers

  • Added CSP support to Service Workers (r226628)
  • Changed to use no-cache fetch mode when loading main documents with location.reload() (r226745)
  • Changed WebProcess to pass the registration identifier and not the worker identifier for fetch events (r226904)
  • Changed to use Service Workers for documents with data URLs or blob URLs (r226361)
  • Changed behavior to cancel pending script loads when the Service Worker is being terminated (r226398)
  • Cleared the Cache volatile storage as a memory optimization. (r227052)
  • Exposed redirect mode as “manual” for navigation loads in Service Workers (r226400)
  • Enabled User Timing and Resource Timing for Service Workers (r226451)
  • Fixed fetch events getting sent to a Service Worker before its state is set to “activated” (r227070)
  • Fixed navigator.onLine inside Service Workers (r226510)
  • Implemented the “main fetch” default referrer policy setting (r226397)
  • Made Service Workers behave correctly with regards to Page Cache (r226677)
  • Stopped exposing fetch and extendable events to window (r226526)

CSS

  • Fixed ::first-letter to select the correct grapheme pairs (r226614)
  • Fixed a blank pages except for inner iframes when pending stylesheets cause style.isNotFinal() to be true (r226653)
  • Fixed image-rendering to affect the scaling of border-image (r226957)
  • Fixed the special list-item counter to start from the correct number for ::before and ::after (r226613, r226675)
  • Improved text appearance on some CSS spec pages (r227000)

Web API

  • Changed redirected iframes loading with request.redirect=follow to fail (r226792)
  • Fixed setting window.opener to null to disown its opener (r226842)
  • Implemented createImageBitmap(ImageBitmap) (r226500)
  • Implemented Cache API partitioning based on ClientOrigin (r226481)
  • Made elements with zero width or height focusable (r226823)

Rendering

  • Fixed constant frame dropping during Flash video playback (r226369)
  • Fixed clipping copyTexImage2D and copyTexSubImage2D (r226490)
  • Fixed a visual flash caused by using font-display:fallback (r226668)
  • Fixed data URL fonts that are split in the middle of an alphabet from causing random letters to disappear (r226930)

Web Inspector

  • Added support for JSX (React) syntax highlighting (r226909)
  • Added a content menu to the main Tab bar for showing and hiding tabs (r226963)
  • Fixed the “Log Value” context menu sometimes being unavailable (r226394)
  • Fixed typing a “space” in the quick console triggering a Canvas recording (r227008)
  • Fixed fuzzy Capture Element screenshots (r226425)
  • Fixed the Find banner sometimes not working when already populated and shown for first time on a resource (r226380)
  • Fixed the “find next” and “find previous” within a resource content view does bouncing highlight when the editor scrolls (r226517)
  • Fixed Layers sidebar to hide popovers when it is collapsed (r226671)
  • Fixed the Export HAR context menu in the Network tab (r226992)
  • Fixed DOM Tree Element selection in RTL mode (r226392)
  • Fixed clicking on white space after a property sometimes placing a blank property at the wrong index in the Styles sidebar (r226994)
  • Fixed long values causing bad wrapping in the Styles sidebar (r226995)
  • Fixed pressing the down key to select the first item from completion list when focusing on an empty value (r226996)
  • Fixed Command-G (⌘G) and Shift-Command-G (⇧⌘G) text search after closing the find banner (r226415)
  • Fixed the Debugger tab to restore the selected resource on reload (r226374)
  • Improved performance when dragging the recording slider in the Canvas tab (r226755)
  • Improved inspector launch time, especially for systems with many fonts (r226371)
  • Made the Console’s Execution Context picker stand out when it is non-default (r227003)
  • Prevented properties from being semitransparent or crossed out while editing in the Styles sidebar (r226939)

Web Driver

  • Implemented the Get Timeouts command (r226770)

Accessibility

  • Changed the style of video elements when invert colors is on to preserve normal video colors (r226825)
  • Implemented the updated CSS3 Speech for the speak and speak-as properties (r226432)

WebRTC

  • Changed RTCController to disable ICE candidate filtering in case of getUserMedia based on the RTCPeerConnection origin (r226804)
  • Updated WebRTC to close sockets that are marked as defunct (r226475)

JavaScript

  • Applied poisoning to pointers in JavaScriptCore (r226530)
  • Fixed for-in caching when indexed properties are added to properties on the prototype chain (r226767)
  • Fixed Array storage operations that sometimes do not update the indexing mask correctly (r226416)
  • Removed the arguments and caller properties for bound functions in Object.getOwnPropertyNames (r226489)

WebAssembly

  • Added poison to JavaScript object’s secrets (r226485)

Bug Fixes

  • Changed the History state to be updated during client redirects with asynchronous policy decisions (r226929)
  • Forbid “<” and “>” in the host name of a URL (r226469)
  • Prevented recording dynamic spelling corrections while in an ephemeral browsing session (r226644)
  • Reduced the precision of “high” resolution time to 1ms (r226495)

January 24, 2018 06:00 PM

January 15, 2018

Speedometer 2.0: A Benchmark for Modern Web App Responsiveness

Surfin’ Safari

In 2014, the WebKit team at Apple released Speedometer 1.0, a benchmark for web app responsiveness. It simulates user interactions in web applications, using TodoMVC to orchestrate adding, completing, and removing todo items. Speedometer repeats these actions using DOM APIs that were extensively used in real-world applications. The performance of these kinds of operations depends on the speed of the JavaScript engine, DOM APIs, layout, CSS style resolution and other parts of the browser engine.

Browser engineers have been optimizing their engines using Speedometer as a proxy for real-world use of popular frameworks for a number of years. Originally, Speedometer included implementations of todo apps in six popular JavaScript frameworks and libraries in heavy use: Ember, Backbone, AngularJS, jQuery, Flight, and an early version of React. It also included vanilla JavaScript.

The web developer ecosystem has evolved significantly since Speedometer 1.0 was first released, as have the trends in what libraries, frameworks, and programming paradigms are used. Developers now commonly use transpilers, module bundlers, and recently-introduced frameworks when creating new sites. This is why, for the last year, engineers from WebKit and Chromium have been collaborating on a new version of Speedometer that better reflects the frameworks, tools, and patterns in wide use today.

Today, we are pleased to announce the Speedometer 2.0 benchmark. We hope this new version of Speedometer helps browser vendors optimize their browser engines for the modern Web.

Support for modern JavaScript frameworks and libraries

Over the last three years, a growing number of real-world sites have been written using React — a JavaScript library for authoring user interfaces. Derivatives such as Preact and Inferno have also gained popularity. Speedometer 2.0 includes web apps implemented using these libraries. It also includes an entry using React and Redux — a popular state management library.

Webpack and Rollup are popular JavaScript module bundlers frequently used with these libraries and Speedometer 2.0 includes output generated by these tools.

Ember.js, which featured in the original Speedometer, now has a dedicated tool to create new projects, and provides a more streamlined deployment process for authors. In addition, there were large changes to the core Ember framework over the years. To incorporate these changes in Ember.js itself and the way developers use Ember.js today, Speedometer 2.0 includes an implementation using the latest Ember, built using Ember CLI.

Another framework we observed gaining traction is Vue.js — a progressive solution aimed at being incrementally adoptable. Similar to Ember, Vue.js has prescriptive tooling for getting started and Speedometer 2.0 includes a Vue.js implementation built using the Vue CLI.

It’s of course true that not all real-world sites are being built using these solutions. Many are still deployed using libraries that were popular when Speedometer 1.0 was authored, which is one reason Speedometer 2.0 also includes updates to implementations written in AngularJS, Backbone.js, and Flight.

ES2015 JavaScript and Babel support

Speedometer 1.0 included a version of the todo app implemented with vanilla JavaScript — i.e. without using any libraries or frameworks. At the time, web developers primarily wrote their applications in the version of JavaScript known as ES5. Today, modern browsers have excellent support of ES2015 (also known as ES6), a more evolved version of JavaScript. Speedometer 2.0 now includes a todo app implemented using ES2015 features like classes, const, let, arrow functions, and template literals.

Although measuring vanilla JavaScript performance has high value, a growing number of developers today also use transpilers like Babel to transpile the latest versions of JavaScript code back to a version supporting all browsers they care about. To reflect this workflow, Speedometer 2.0 includes an ES2015 implementation that uses ES Modules and has ES5 output generated by Babel. In the future, as browsers gain full support for native ES Modules, we hope to evolve the benchmark to also track an implementation that isn’t bundled or translated.

TypeScript support

TypeScript is a typed superset of JavaScript that has been gaining traction in the web developer community. It offers types as a first-class syntax, generally fast compilation, and rich tooling for type-aware auto-completion and error highlighting during iteration.

Today, one of the largest users of TypeScript is Angular. To enable browsers to measure the kinds of output a TypeScript app might generate, Speedometer 2.0 includes an Angular implementation written in TypeScript, transpiled to ES5. We’re hopeful that browsers optimizing for this implementation will be able to offer the same wins as more frameworks introduce TypeScript support.

Future-facing: functional programming

The front-end developer community has been shifting in the direction of borrowing more patterns from functional programming. This has been demonstrated with the growth of interest in technologies like Elm and PureScript, both of which transpile down to JavaScript. To enable browsers to optimize for these patterns, Speedometer 2.0 includes implementations for both of these technologies.

Updates in score calculation

Speedometer 1.0 calculated a final score for Web App Responsiveness using the arithmetic mean of the run time needed to add, mark completed, and remove 100 todo items in each implementation in order to incentivize browser vendors to optimize the slowest framework or library. Unfortunately, this resulted in some implementation of a todo app getting 25× more weight compared to another as we added more libraries and frameworks to Speedometer 2.0. It became particularly problematic when we added back a debug build of Ember — it was more than 4× slower than the Ember production build. However, only a small fraction of websites deployed with Ember use debug builds.

In Speedometer 2.0, we’ve changed the score to be computed as the geometric mean against different implementations of the todo app. The final score is computed as the arithmetic mean of the geometric means computed for each iteration of the benchmark.

Future

Speedometer 2.0 has been an exciting collaboration between browser vendors. We would like to build on this collaboration in future iterations of the benchmark by working more closely with framework authors and the developer community to identify broadly-used patterns, frameworks, and tools for which browser engines could be optimized.

January 15, 2018 06:00 PM

January 11, 2018

Frédéric Wang: Review of Igalia's Web Platform activities (H2 2017)

Igalia WebKit

Last september, I published a first blog post to let people know a bit more about Igalia’s activities around the Web platform, with a plan to repeat such a review each semester. The present blog post focuses on the activity of the second semester of 2017.

Accessibility

As part of Igalia’s commitment to diversity and inclusion, we continue our effort to standardize and implement accessibility technologies. More specifically, Igalian Joanmarie Diggs continues to serve as chair of the W3C’s ARIA working group and as an editor of Accessible Rich Internet Applications (WAI-ARIA) 1.1, Core Accessibility API Mappings 1.1, Digital Publishing WAI-ARIA Module 1.0, Digital Publishing Accessibility API Mappings 1.0 all of which became W3C Recommandations in December! Work on versions 1.2 of ARIA and the Core AAM will begin in January. Stay tuned for the First Public Working Drafts.

We also contributed patches to fix several issues in the ARIA implementations of WebKit and Gecko and implemented support for the new DPub ARIA roles. We expect to continue this collaboration with Apple and Mozilla next year as well as to resume more active maintenance of Orca, the screen reader used to access graphical desktop environments in GNU/Linux.

Last but not least, progress continues on switching to Web Platform Tests for ARIA and “Accessibility API Mappings” tests. This task is challenging because, unlike other aspects of the Web Platform, testing accessibility mappings cannot be done by solely examining what is rendered by the user agent. Instead, an additional tool, an “Accessible Technology Test Adapter” (ATTA) must be also be run. ATTAs work in a similar fashion to assistive technologies such as screen readers, using the implemented platform accessibility API to query information about elements and reporting what it obtains back to WPT which in turn determines if a test passed or failed. As a result, the tests are currently officially manual while the platform ATTAs continue to be developed and refined. We hope to make sufficient progress during 2018 that ATTA integration into WPT can begin.

CSS

This semester, we were glad to receive Bloomberg’s support again to pursue our activities around CSS. After a long commitment to CSS and a lot of feedback to Editors, several of our members finally joined the Working Group! Incidentally and as mentioned in a previous blog post, during the CSS Working Group face-to-face meeting in Paris we got the opportunity to answer Microsoft’s questions regarding The Story of CSS Grid, from Its Creators (see also the video). You might want to take a look at our own videos for CSS Grid Layout, regarding alignment and placement and easy design.

On the development side, we maintained and fixed bugs in Grid Layout implementation for Blink and WebKit. We also implemented alignment of positioned items in Blink and WebKit. We have several improvements and bug fixes for editing/selection from Bloomberg’s downstream branch that we’ve already upstreamed or plan to upstream. Finally, it’s worth mentioning that the work done on display: contents by our former coding experience student Emilio Cobos was taken over and completed by antiik (for WebKit) and rune (for Blink) and is now enabled by default! We plan to pursue these developments next year and have various ideas. One of them is improving the way grids are stored in memory to allow huge grids (e.g. spreadsheet).

Web Platform Predictability

One of the area where we would like to increase our activity is Web Platform Predictability. This is obviously essential for our users but is also instrumental for a company like Igalia making developments on all the open source Javascript and Web engines, to ensure that our work is implemented consistently across all platforms. This semester, we were able to put more effort on this thanks to financial support from Bloomberg and Google AMP.

We have implemented more frame sandboxing attributes WebKit to improve user safety and make control of sandboxed documents more flexible. We improved the sandboxed navigation browser context flag and implemented the new allow-popup-to-escape-sandbox, allow-top-navigation-without-user-activation, and allow-modals values for the sandbox attribute.

Currently, HTML frame scrolling is not implemented in WebKit/iOS. As a consequence, one has to use the non-standard -webkit-overflow-scrolling: touch property on overflow nodes to emulate scrollable elements. In parallel to the progresses toward using more standard HTML frame scrolling we have also worked on annoying issues related to overflow nodes, including flickering/jittering of “position: fixed” nodes or broken Find UI or a regression causing content to disappear.

Another important task as part of our CSS effort was to address compatibility issues between the different browsers. For example we fixed editing bugs related to HTML List items: WebKit’s Bug 174593/Chromium’s Issue 744936 and WebKit’s Bug 173148/Chromium’s Issue 731621. Inconsistencies in web engines regarding selection with floats have also been detected and we submitted the first patches for WebKit and Blink. Finally, we are currently improving line-breaking behavior in Blink and WebKit, which implies the implementation of new CSS values and properties defined in the last draft of the CSS Text 3 specification.

We expect to continue this effort on Web Platform Predictability next year and we are discussing more ideas e.g. WebPackage or flexbox compatibility issues. For sure, Web Platform Tests are an important aspect to ensure cross-platform inter-operability and we would like to help improving synchronization with the conformance tests of browser repositories. This includes the accessibility tests mentioned above.

MathML

Last November, we launched a fundraising Campaign to implement MathML in Chromium and presented it during Frankfurt Book Fair and TPAC. We have gotten very positive feedback so far with encouragement from people excited about this project. We strongly believe the native MathML implementation in the browsers will bring about a huge impact to STEM education across the globe and all the incumbent industries will benefit from the technology. As pointed out by Rick Byers, the web platform is a commons and we believe that a more collective commitment and contribution are essential for making this world a better place!

While waiting for progress on Chromium’s side, we have provided minimal maintenance for MathML in WebKit:

  • We fixed all the debug ASSERTs reported on Bugzilla.
  • We did follow-up code clean up and refactoring.
  • We imported Web Platform tests in WebKit.
  • We performed review of MathML patches.

Regarding the last point, we would like to thank Minsheng Liu, a new volunteer who has started to contribute patches to WebKit to fix issues with MathML operators. He is willing to continue to work on MathML development in 2018 as well so stay tuned for more improvements!

Javascript

During the second semester of 2017, we worked on the design, standardization and implementation of several JavaScript features thanks to sponsorship from Bloomberg and Mozilla.

One of the new features we focused on recently is BigInt. We are working on an implementation of BigInt in SpiderMonkey, which is currently feature-complete but requires more optimization and cleanup. We wrote corresponding test262 conformance tests, which are mostly complete and upstreamed. Next semester, we intend to finish that work while our coding experience student Caio Lima continues work on a BigInt implementation on JSC, which has already started to land. Google also decided to implement that feature in V8 based on the specification we wrote. The BigInt specification that we wrote reached Stage 3 of TC39 standardization. We plan to keep working on these two BigInt implementations, making specification tweaks as needed, with an aim towards reaching Stage 4 at TC39 for the BigInt proposal in 2018.

Igalia is also proposing class fields and private methods for JavaScript. Similarly to BigInt, we were able to move them to Stage 3 and we are working to move them to stage 4. Our plan is to write test262 tests for private methods and work on an implementation in a JavaScript engine early next year.

Igalia implemented and shipped async iterators and generators in Chrome 63, providing a convenient syntax for exposing and using asynchronous data streams, e.g., HTML streams. Additionally, we shipped a major performance optimization for Promises and async functions in V8.

We implemented and shipped two internationalization features in Chrome, Intl.PluralRules and Intl.NumberFormat.prototype.formatToParts. To push the specifications of internationalization features forwards, we have been editing various other internationalization-related specifications such as Intl.RelativeTimeFormat, Intl.Locale and Intl.ListFormat; we also convened and led the first of what will be a monthly meeting of internationalization experts to propose and refine further API details.

Finally, Igalia has also been formalizing WebAssembly’s JavaScript API specification, which reached the W3C first public working draft stage, and plans to go on to improve testing of that specification as the next step once further editorial issues are fixed.

Miscellaneous

Thanks to sponsorship from Mozilla we have continued our involvement in the Quantum Render project with the goal of using Servo’s WebRender in Firefox.

Support from Metrological has also given us the opportunity to implement more web standards from some Linux ports of WebKit (GTK and WPE, including:

  • WebRTC
  • WebM
  • WebVR
  • Web Crypto
  • Web Driver
  • WebP animations support
  • HTML interactive form validation
  • MSE

Conclusion

Thanks for reading and we look forward to more work on the web platform in 2018. Onwards and upwards!

January 11, 2018 11:00 PM

January 10, 2018

Manuel Rego: "display: contents" is coming

Igalia WebKit

Yes, display: contents is enabled by default in Blink and WebKit and it will be probably shipped in Chrome 65 and Safari 11.1. These browsers will join Firefox that is shipping it since version 37, which makes Edge the only one missing the feature (you can vote for it!).

Regarding this I’d like to highlight that the work to support it in Chromium was started by Emilio Cobos during his Igalia Coding Experience that took place from fall 2016 to summer 2017.

You might (or not) remember a blog post from early 2016 where I was talking about the Igalia Coding Experience program and some ideas of tasks to be done as part of the Web Platform team. One of the them was display: contents which is finally happening.

What is display: contents?

This new value for the display property allows you to somehow remove an element from the box tree but still keep its contents. The proper definition from the spec:

The element itself does not generate any boxes, but its children and pseudo-elements still generate boxes and text runs as normal. For the purposes of box generation and layout, the element must be treated as if it had been replaced in the element tree by its contents (including both its source-document children and its pseudo-elements, such as ::before and ::after pseudo-elements, which are generated before/after the element’s children as normal).

A simple example will help to understand it properly:

<div style="display: contents;
            background: magenta; border: solid thick black; padding: 20px;
            color: cyan; font: 30px/1 Monospace;">
  <span style="background: black;">foobar</span>
</div>

display: contents makes that the div doesn’t generate any box, so its background, border and padding are not renderer. However the inherited properties like color and font have effect on the child (span element) as expected.

For this example, the final result would be something like:

<span style="background: black; color: cyan; font: 30px/1 Monospace;">foobar</span>

Unsupported

foobar

Actual

foobar

Supported

foobar

Unsupported vs actual (in your browser) vs supported output for the previous example

If you want more details Rachel Andrew has a nice blog post about this topic.

CSS Grid Layout & display: contents

As you could expect from a post from myself this is somehow related to CSS Grid Layout. 😎 display: contents can be used as a replacement of subgrids (which are not supported by any browser at this point) in some use cases. However subgrids are still needed for other scenarios.

The canonical example for Grid Layout auto-placement is a simple form like:

<style>
  form   { display:     grid;   }
  label  { grid-column: 1;      }
  input  { grid-column: 2;      }
  button { grid-column: span 2; }
</style>
<form>
  <label>Name</label><input />
  <label>Mail</label><input />
  <button>Send</button>
</form>

A simple form formatted with CSS Grid Layout A simple form formatted with CSS Grid Layout

However this is not the typical HTML of a form, as you usually want to use a list inside, so people using screen readers will know how many fields they have to fill in your form beforehand. So the HTML looks more like this:

<form>
  <ul>
    <li><label>Name</label><input /></li>
    <li><label>Mail</label><input /></li>
    <li><button>Send</button></li>
  </ul>
</form>

With display: contents you’ll be able to have the same layout than in the first case with a similar CSS:

ul     { display: grid;       }
li     { display: contents;   }
label  { grid-column: 1;      }
input  { grid-column: 2;      }
button { grid-column: span 2; }

So this is really nice, now when you convert your website to start using CSS Grid Layout, you would need less changes on your HTML and you won’t need to remove some HTML that is really useful, like the list in the previous example.

Chromium implementation

As I said in the introduction, Firefox shipped display: contents three years ago, however Chromium didn’t have any implementation for it. Igalia as CSS Grid Layout implementor was interested in having support for the feature as it’s a handy solution for several Grid Layout use cases.

The proposal for the Igalia Coding Experience was the implementation of display: contents on Blink as the main task. Emilio did an awesome job and managed to implement most of it, reporting issues to CSS Working Group and other browsers as needed, and writing tests for the web-platform-tests repository to ensure interoperability between the implementations.

Once the Coding Experience was over there were still a few missing things to be able to enable display: contents by default. Rune Lillesveen (Google and previously Opera) who was helping during the whole process with the reviews, finished the work and shipped it past week.

WebKit implementation

WebKit already had an initial support for display: contents that was only used internally by Shadow DOM implementation and not exposed to the end users, neither supported by the rest of the code.

We reactivated the work there too, he didn’t have time to finish the whole thing but later Antti Koivisto (Apple) completed the work and enabled it by default on trunk by November 2017.

Conclusions

Igalia is one of the top external contributors on the open web platform projects. This put us on a position that allows us to implement new features in the different open source projects, thanks to our community involvement and internal knowledge after several years of experience on the field. Regarding display: contents implementation, this feature probably wouldn’t be available today in Chromium and WebKit without Igalia’s support, in this particular case through a Coding Experience.

We’re really happy about the results of the Coding Experience and we’re looking forward to repeat the success story in the future.

Of course, all the merit goes to Emilio, who is an impressive engineer and did a great job during the Coding Experience. As part of this process he got committer privileges in both Chromium and WebKit projects. Kudos!

Last, but not least, thanks to Antti and Rune for finishing the work and making display: contents available to WebKit and Chromium users.

January 10, 2018 11:00 PM

Release Notes for Safari Technology Preview 47

Surfin’ Safari

Safari Technology Preview Release 47 is now available for download for macOS Sierra and macOS High Sierra. If you already have Safari Technology Preview installed, you can update from the Mac App Store’s Updates tab. This release covers WebKit revisions 225841-226358.

This release contains the Spectre mitigations released in iOS 11.2.2, the High Sierra 10.13.2 supplemental update, and Safari 11.0.2 reissue released on Monday, January 8. For more information about Spectre, see What Spectre and Meltdown Mean For WebKit.

Storage Access API

This is a newly proposed API (WhatWG issue) that can be enabled in the Develop menu under Experimental Features. Cookies partitioned by Safari’s Intelligent Tracking Prevention can be accessed in an iframe loaded from the cookie’s domain by calling document.requestStorageAccess() in a click event handler. When the returned promise resolves, the first-party cookies in that iframe will be accessible. There is also the convenience function document.hasStorageAccess() available that doesn’t require a click.

  • Enabled allowing requests from non-sandboxed <iframes> (r226244)
  • Implemented frame-specific access in the document.cookie layer (r225934)
  • Made document.hasStorageAccess() retrieve the current status from the network process (r226016)
  • Refactored XPC for access removal to go straight from the web process to the network process (r226389)

Service Workers

  • Added support for response blob given to fetch events (r226066)
  • Changed extracting a body of type Blob to set the Content-Type to null instead of an empty string (r226162)
  • Changed to use “error” redirect mode for fetching service worker scripts (r226087)
  • Changed the Service Worker script fetch request to set the Service-Worker header (r225996)
  • Changed Service Worker to not clean HTTP headers added by the application or by Fetch specification before Service Worker interception (r226126)
  • Fixed the default scope used when registering a service worker (r226096)
  • Fixed the Service Worker Registration promise sometimes not getting rejected when the script load fails (r225975)
  • Fixed Service Worker served response tainting to keep its tainting (r226090)
  • Fixed scopeURL to start with the provided scriptURL (r226141)
  • Fixed self.importScripts() to obey updateViaCache inside service workers (r225940)
  • Fixed Fetch handling to wait for the Service Worker’s state to become activated (r226136)
  • Fixed SameOrigin and CORS fetch to fail on opaque responses served from a Service Worker (r226084)
  • Fixed memory cache to not reuse resources with a different credential fetch option (r226333)
  • Prevented searching for service worker registration for non-HTTP navigation loads (r226185, r226200)
  • Supported Service Worker interception of a request with blob body (r226191)

Media

  • Enabled picture-in-picture from an inline element on suspend (r226217)
  • Fixed playing media elements which call “pause(); play()” getting the play promise rejected (r226059, r226150)
  • Implemented <iframe allow="camera; microphone"> (r225963)

Rendering

  • Fixed elements animated on-screen that are sometimes missing (r225983)
  • Fixed setting the fePointLights color (r226317)
  • Fixed the color of the bottom right pixel of feDiffuseLighting (r226316)
  • Fixed SVG lighting colors to be converted into linearSRGB (r226315)
  • Updated the SVG use element’s shadow trees explicitly before the style recall (r225868)

Web Inspector

  • Enabled the Canvas Tab by default (r225979)
  • Improved open time performance when enumerating system fonts (r226352)
  • Fixed Command-Option-R (⌘⌥R) in the docked inspector causing Web Inspector to reload instead of the inspected page (r225907)
  • Fixed the URL filter in the Network Tab to be case-insensitive like filter bars in other tabs (r225939)
  • Fixed mis-sized waterfall graphs in the Network Tab after closing the detail view (r226070)
  • Redesigned the waterfall popover showing timing data in the Network Tab table (r226158)
  • Updated the Time column in the Network Tab table to include the total duration not just the download duration (r226151)
  • Added an inline swatch for CSS variables in the Styles sidebar (r226079)
  • Added support for typing a semicolon at the end of a value to move to the next property in the Styles sidebar (r226149)
  • Enabled Command-S (⌘S) to save changes in the matching CSS resource in the Styles sidebar (r226082)
  • Fixed selecting text in the Styles sidebar to not add new properties (r225945)
  • Implemented clicking above the selector to prepend a new property in the Styles sidebar (r225968)

Clipboard API

  • Fixed isSafari runtime check to enable custom clipboard types and clipboard data sanitization in Safari Technology Preview (r226215)
  • Fixed not being able to paste images on Gmail (r226173)
  • Reverted blob URL conversions in pasted contents for LegacyWebKit clients (r226156)

Bug Fix

  • Avoided waking plugin process up unnecessarily (r225984)

Storage Access API: Refactor XPC for access removal to go straight from the web process to the network process (r226389)

By Jon Davis at January 10, 2018 06:00 PM

January 09, 2018

What Spectre and Meltdown Mean For WebKit

Surfin’ Safari

Security researchers have recently uncovered security issues known as Meltdown and Spectre. These issues apply to all modern processors and allow attackers to gain read access to parts of memory that were meant to be secret. To initiate a Spectre- or Meltdown-based attack, the attacker must be able to run code on the victim’s processor. WebKit is affected because in order to render modern web sites, any web JavaScript engine must allow untrusted JavaScript code to run on the user’s processor. Spectre impacts WebKit directly. Meltdown impacts WebKit because WebKit’s security properties must first be bypassed (via Spectre) before WebKit can be used to mount a Meltdown attack.

  • WebKit relies on branch instructions to enforce what untrusted JavaScript and WebAssembly code can do. Spectre means that an attacker can control branches, so branches alone are no longer adequate for enforcing security properties.
  • Meltdown means that userland code, such as JavaScript running in a web browser, can read kernel memory. Not all CPUs are affected by Meltdown and Meltdown is being mitigated by operating system changes. Mounting a Meltdown attack via JavaScript running in WebKit requires first bypassing branch-based security checks, like in the case of a Spectre attack. Therefore, Spectre mitigations that fix the branch problem also prevent an attacker from using WebKit as the starting point for Meltdown.

  • This document explains how Spectre and Meltdown affect existing WebKit security mechanisms and what short-term and long-term fixes WebKit is deploying to provide protection against this new class of attacks. The first of these mitigations shipped on Jan 8, 2018:

    • iOS 11.2.2.
    • High Sierra 10.13.2 Supplemental Update. This reuses the 10.13.2 version number. You can check if your Safari and WebKit are patched by verifying the full version number in About Safari. The version number should be either 13604.4.7.1.6 or 13604.4.7.10.6.
    • Safari 11.0.2 for El Capitan and Sierra. This reuses the 11.0.2 version number. Patched versions are 11604.4.7.1.6 (El Capitan) and 12604.4.7.1.6 (Sierra).

    Spectre and Security Checks

    Spectre means that branches are no longer sufficient for enforcing the security properties of read operations in WebKit. The most impacted subsystem is JavaScriptCore (WebKit’s JavaScript engine). Almost all bounds checks can be bypassed to read arbitrarily out-of-bounds. This could allow an attacker to read arbitrary memory. All type checks are also vulnerable. For example, if some type contains an integer at offset 8 while another type contains a pointer at offset 8, then an attacker could use Spectre to bypass the type check that is supposed to ensure that you can’t use the integer to craft an arbitrary pointer.

    JavaScriptCore is meant to be a secure language virtual machine. It should be possible to load untrusted JavaScript or WebAssembly code into your process without the risk of your process’s memory being leaked to the JavaScript code except in cases where you explicitly export data to JavaScript via our C or Objective-C binding API. Spectre breaks this property of JavaScriptCore because untrusted JavaScript or WebAssembly now has a theoretical path to reading all of the host process’s address space.

    DOM APIs and system APIs called by DOM APIs also use branches to enforce their security properties, and those are callable from JavaScript. Hence, Spectre is not just an attack on JavaScriptCore itself but also everything that is callable from JavaScript.

    Reasoning About Spectre

    To understand how Spectre works, it’s useful to think about how security-sensitive programming language operations (like any property access in JavaScript) get executed in JavaScriptCore on a modern processor. Most discussions about Spectre have involved bounds checks, so this section considers that case as well.

    var tmp = intArray[index];
    

    In this example, let’s assume that intArray is known to our JavaScript engine to be a reference to a Int32Array instance, but that we have not proved that index is in bounds of intArray.length. The compiler will have to emit a bounds check when it translates this high-level JavaScript operation into a lower-level form:

    if (((unsigned) index) >= ((unsigned) intArray->length))
        fail;
    int tmp = intArray->vector[index];
    

    Compiling this on x86 CPUs results in the following instructions:

    mov 0x10(%rsi), %rdx     ; %rsi has intArray. This loads
                             ; intArray->vector.
    cmp 0x18(%rsi), %ecx     ; %ecx has the index. This compares
                             ; the index to intArray->length.
    jae Lfail                ; Branch to Lfail if
                             ; index >= intArray->length according
                             ; to unsigned comparison.
    mov (%rdx,%rcx,4), %ecx  ; Load intArray->vector[index].
    

    Modern CPUs are able to execute the bounds check branch (jae) and the subsequent load (mov (%rdx,%rcx,4), %ecx) in parallel. This is possible because:

    • Modern CPUs profile branches. In this case, they will observe that the branch always falls through. This is called branch prediction.
    • Modern CPUs can roll back execution. The load after the branch can execute before the CPU verifies that the branch actually did fall through. If the branch turns out to be taken instead, the CPU can undo everything that happened between when the branch was encountered and when it finally got verified. This is called speculative execution.

    Spectre is an attack that exploits information leaks from speculative execution. Consider this code:

    var tmp = intArray[index];
    otherArray[(tmp & 1) * 128];
    

    The CPU has the ability to initiate loads from main memory into L1 (the CPU’s level 1 memory cache, which is the fastest and smallest) while executing speculatively. As a performance optimization, the CPU does not undo fetches into L1 when rolling back speculative execution. This leads to a timing-based information leak: in this code, whether the CPU loads otherArray[0] or otherArray[128] depends on tmp & 1, and it’s possible to later determine which the CPU loaded speculatively by timing the speed of access to otherArray[0] and otherArray[128].

    The example so far involved controlling a bounds checking branch. This is a particularly effective Spectre attack because index behaves like a pointer that can be used to read ~16GB of memory above intArray->vector. But Spectre could theoretically involve any branch that enforces security properties, like the branches used for type checks in JavaScriptCore.

    To summarize:

    1. Spectre requires high fidelity timing so that the difference between L1 latency and main memory latency can be observed.
    2. Spectre lets attackers control branches. Speculative execution executes branches according to past history, and the attacker can control this history. Therefore, the attacker controls what branches do during speculative execution.
    3. Spectre is a race between the branch verifier and the initiation of the information-leaking load (what we wrote as otherArray[(tmp & 1) * 128] above). The attacker knows if they won the race (one of the two otherArray cache lines will be in L1), so the attack works so long as the attacker’s chance of winning is not zero.

    Mitigating Spectre

    WebKit’s response to Spectre is a two-tiered defense:

    1. WebKit has disabled SharedArrayBuffer and reduced timer precision.
    2. WebKit is transitioning to using branchless security checking in addition to branch-based security checking.

    Some of these changes shipped in the Jan 8 updates and more such changes are continuing to land in WebKit. The remainder of this document covers our mitigations in detail.

    Reducing Timer Precision

    We are reducing timer precision in WebKit. These changes have landed in trunk as of r226495 and they shipped in the Jan 8 updates.

    • Timer precision from performance.now and other sources is reduced to 1ms (r226495).
    • We have disabled SharedArrayBuffer, since it can be used to create a high-resolution timer (r226386).

    Our long-term plan is to make Spectre impossible even in the presence of high fidelity timing; further work is needed to re-enable this path.

    Branchless Security Checks

    Since learning about Spectre, we have been researching how to do security checks without relying on branches. We have begun making the transition to this new style of security checks and we shipped the first branchless checks in the Jan 8 updates.

    Index Masking

    The simplest example of a branchless security check is masking the index of an array access:

    int tmp = intArray->vector[index & intArray->mask];
    

    Modern CPUs do not speculate on bit masking. If the mask is picked to fit the array length, this mitigation ensures that even with Spectre, an attacker cannot read out-of-bounds of the array.

    We have implemented index masking for:

    1. Typed arrays (r226461),
    2. WebAssembly memories (r226461, mostly via shared code with typed arrays),
    3. Strings (r226068),
    4. WTF::Vector (r226068), and
    5. Plain JavaScript arrays (r225913).

    Changes (1-4) shipped in the Jan 8 updates. (5) landed in WebKit but has not yet shipped.

    Index masking is not yet a complete fix for out-of-bounds access. Our current index masking mitigations use a mask that is computed by rounding up the length to the next power of two (and subtracting one). This still allows out-of-bounds reads, just not to arbitrary memory.

    Our current testing indicates that index masking has no measurable impact on the Speedometer and ARES-6 tests and an impact of less than 2.5% on the JetStream benchmark.

    Pointer Poisoning

    Index masking is easy to apply for array accesses, but many security check branches have to do with object type, not array bounds. Pointer poisoning is a technique that can be used to make any type check secure under Spectre by changing the shape of the object subject to the check.

    Poisoning a pointer just means performing some reversible math on it that will make access attempts fail unless the pointer is unpoisoned. In WebKit, poisoning involves xoring a value that is sure to have at least one bit set in high positions so that accesses that do not unpoison are very likely to hit unmapped memory. WebKit picks poison values using a compile-time random number generator with lots of subtle rules, but to understand the approach, just consider 1 << 40 as a poison value. Adding one terabyte to a valid pointer is sure to result in an unmapped pointer in WebKit’s memory layout on macOS and iOS, and probably on other operating systems, too. Many possible poison values exist that would have this effect.

    Poisoning becomes most powerful when each static declaration of a pointer field has a unique poison value, and the poison values differ in the high bits so that unpoisoning with the wrong value results in an unmapped pointer.

    As an example of how to apply pointer poisoning as a branchless type check, consider some class Foo that belongs to a hierarchy of classes that participate in dynamic downcasts based on some checks:

    class Foo : public Base {
    public:
        ...
    private:
        int m_x;
        Bar* m_y;
    };
    

    In order to make this class’s type checks sound under Spectre, we can simply move Foo’s fields out into a data struct pointed to by a uniquely poisoned pointer:

    class Foo : public Base {
    public:
        ....
    private:
        struct Data {
            int x;
            Bar* y;
        };
        ConstExprPoisoned<FooDataKey, Data> m_data;
    };
    

    Where FooDataKey is a key unique to Foo, based on which ConstExprPoisoned<> will compute a random poison value at compile time. If all classes in this hierarchy use a pointer poisoned indirection to protect their fields then this suffices as a branchless type check for all accesses to these types. In addition to being a great Spectre mitigation, this is also a useful remote code execution mitigation, since it makes it harder to do any kind of type confusion.

    Pointer poisoning sometimes does not require any extra indirections. JavaScriptCore has tons of data structures that roughly fit this pattern:

    struct Thingy {
        Type type;
        void* data; // The shape of this depends on `type`.
    };
    

    Any such data structure’s type checks can be made branchless by poisoning the data pointer according to a poison value that depends on type.

    We have begun converting WebKit’s object models to use pointer poisoning (r225363, rr225437, r225632, r225659, r225697, r225857, r226015, r226247, r226344, r226485, r226530), and some of the initial pointer poisoning work is shipping in the Jan 8 updates (specifically, r225363r225857). So far, we have not observed any performance regressions from using pointer poisoning.

    Mitigating Meltdown

    Meltdown allows userland code to read kernel memory. WebKit is indirectly affected by Meltdown because a Meltdown attack could be initiated using any kind of code execution, including JavaScript. However, the memory accesses used to perform Meltdown would be a violation of WebKit’s security model. Therefore, JavaScript-based Meltdown attacks must first get around WebKit’s security checks such as by using a Spectre attack.

    If Meltdown has been mitigated by operating system changes, then even if WebKit lacked any Spectre mitigations, it would not be possible to mount a Meltdown attack via WebKit. Any future Spectre mitigations will make it even less likely that WebKit could be used for a Meltdown attack, since the Spectre stage of that attack will be harder.

    Recommendations For App Developers

    Spectre means that secrets in the same address space as untrusted JavaScript are more vulnerable than ever before. Based on this, we recommend:

    • Switch to the Modern WebKit API if you have not done so already. This protects your app by running untrusted JavaScript in another process.
    • Avoid exposing sources of high-precision timing to untrusted JavaScript or WebAssembly.

    Conclusion

    Spectre and Meltdown are a new class of security issues that apply to modern processors and the software that runs on them. WebKit is affected by both issues because WebKit allows untrusted code to run on users’ processors. In response to these new issues, we have implemented mitigations to defend against Spectre (and Meltdown attacks launched using Spectre via the browser). The first of these mitigations have shipped in the Jan 8 updates (iOS 11.2.2, High Sierra 10.13.2 supplemental update, and Safari 11.0.2 reissue). Stay tuned for more WebKit Spectre fixes!

    By Filip Pizlo at January 09, 2018 12:49 AM

    December 27, 2017

    Manuel Rego: Web Engines Hackfest 2017

    Igalia WebKit

    One year more Igalia organized, hosted and sponsored a new edition of the Web Engines Hackfest. This is my usual post about the event focusing on the things I was working on during those days.

    Organization

    This year I wanted to talk about this because being part of the organization in an event with 60 people is not that simple and take some time. I’m one of the members of the organization which ended up meaning that I was really busy during the 3 days of the event trying to make the life of all the attendees as easy as possible.

    Yeah, this year we were 60 people, the biggest number ever! Note that last year we were 40 people, so it’s clear the interest in the event is growing after each edition, which is really nice.

    For the first time we had conference badges, with so many faces it was going to be really hard to put names to all of them. In addition we had pronouns stickers and different lanyard color for the people that don’t want to appear in the multimedia material published during and after the event. I believe all these things worked very well and we’ll be repeating for sure in future editions.

    My Web Engines Hackfest 2017 conference badge My Web Engines Hackfest 2017 conference badge

    The survey after the event showed an awesome positive feedback, so we’re really glad that you have enjoined the hackfest. I was specially happy seeing how many parallel discussions were taking place all around the office in small groups of people.

    Talks

    The main focus of the event is the different discussions that happen between people about many different topics. This together with the possibility to hack with some people from other browser engines and/or other companies make the hackfest an special event.

    On top of that, we arrange a few talks that are usually quite interesting. The talks from this year can be found on a YouTube playlist (thanks Juan for helping with the video editing). This year the talks covered the following topics: Web Platform Tests, zlib optimizations, Chromium on Wayland, BigInt, WebRTC and WebVR.

    Some pictures of the Web Engines Hackfest 2017 Some pictures of the Web Engines Hackfest 2017

    CSS Grid Layout

    During the hackfest I participated in several breakout sessions, like for example one about Web Platform Tests or another one about MathML. However as usual on the last years my main was related to CSS Grid Layout. In this case we took advantage to discuss several topics from which I’m going to highlight two:

    Chromium bug on input elements which only happens on Mac

    This is about Chromium bug #727076, where the input elements that are grid items get collapsed/shrunk when the user starts to enter some text. This was a tricky issue only reproducible on Mac platform that was hitting us for a while, so we needed to find a solution.

    We had some long discussions about this and finally my colleague Javi found the root cause of the problem and finally fixed it, kudos!

    This bug is a quite complex and tight to some Chromium specific implementation bits. The summary is that in Mac platform you can get requests about the intrinsic (preferred) width of the grid container at random times, which means that you’re not sure a full layout will be performed afterwards. Our code was not ready for that, as we were always expecting a full layout after asking for the intrinsic width.

    Percentage tracks and gutters

    This is a neverending topic that has been discussed in the CSS WG for a long time. There are 2 different things so let’s go one by one.

    First, how percentage tracks are resolved when the width/height of a grid container is indefinite. So far, this was not symmetric but was working like in regular blocks:

    • Percentage columns work like percentage widths: This means that they are treated as auto during intrinsic size computation and later resolved during layout.
    • Percentage rows work like percentage heights: In this case they are treated as auto and never resolved.

    However the CSS WG decided to change this and make both symmetric, so percentage rows will work like percentage columns. This hasn’t been implemented by any browser yet, and all of them have interoperability with the previous status. We’re not 100% sure about the complexity this could bring and before changing current behavior we’re going to gather some usage statistics to verify this won’t break a lot o content out there. We’d also love to get feedback from other implementors about this. More information about this topic can be found on CSS WG issue #1921.

    Now let’s talk about the second issue, how percentage gaps work. The whole discussion can be checked on CSS WG issue #509 that I started back in TPAC 2016. For this case there are no interoperability between browsers as Firefox has its own solution of back-computing percentage gaps, the rest of browsers have the same behavior in line with the percentage tracks resolution, but again it is not symmetric:

    • Percentage column gaps contribute zero to intrinsic width computation and are resolved as percent during layout.
    • Percentage row gaps are treated always as zero.

    The CSS WG resolved to modify this behavior to make them both symmetric, in this case choosing the row gaps behavior as reference. So browsers will need to change how column gaps work to avoid resolving the percentages during layout. We don’t know if we could detect this situation in Blink/WebKit without quite complex changes on the engine, and we’re waiting for feedback from other implementors on that regard.

    So I won’t say any of those topics are definitely closed yet, and it won’t be unexpected if some other changes happen in the future when the implementations try to catch up with the spec changes.

    Thanks

    To close this blog post let’s say thanks to everyone that come to our office and participated in the event, the Web Engines Hackfest won’t be possible without such a great bunch of people that decided to spend a few days working together on improving the status of the Web.

    Web Engines Hackfest 2017 sponsors: Collabora, Google, Igalia and Mozilla Web Engines Hackfest 2017 sponsors: Collabora, Google, Igalia and Mozilla

    Of course we cannot forget about the sponsors either: Collabora, Google, Igalia and Mozilla. Thank you all very much!

    And last, but not least, thanks to Igalia for organizing and hosting one year more this event. Looking forward to the new year and the 2018 edition!

    December 27, 2017 11:00 PM

    December 20, 2017

    Release Notes for Safari Technology Preview 46

    Surfin’ Safari

    Safari Technology Preview Release 46 is now available for download for macOS Sierra and macOS High Sierra. If you already have Safari Technology Preview installed, you can update from the Mac App Store’s Updates tab. This release covers WebKit revisions 225266-225841.

    Service Workers

    Offline applications are important to the web. After HTML5 first tried to accommodate them with the Offline Application Cache, the Service Workers specification was created as a successor.

    This standard describes new APIs focused on using JavaScript to handle resource loading for a web page without network access. While work continues, we’re excited to enable Service Workers by default in this release. Please test our implementation with your websites and send us feedback using the WebKit project bug tracker.

    • Made Service Workers enabled by default (r225789)
    • Exposed self.registration inside Service Workers (r225296)
    • Removed HTTP headers added by CachedResource and CachedResourceLoader in Service Worker fetch (r225574)
    • Rejected promises in the ServiceWorkers API when calling objects inside of detached frames (r225577)
    • Yielded image content from a CacheStorage.add(url) network request (r225708)
    • Changed the Fetch event header filtering to only apply in CORS-mode (r225809)
    • Handled self.skipWaiting() inside Service Workers (r225460)
    • Removed XMLHttpRequest from being exposed to Service Workers (r225549)
    • Implemented clients.get() and clients.getAll() (r225427, r225452)
    • Supported container.register() and registration.unregister() inside Service Workers (r225456)
    • Targeted the Service Worker’s scope URL for remote inspection metadata (r225633)
    • Made navigation requests to use navigate fetch mode (r225796)
    • Activated IndexedDB and Web Sockets in Service Workers (r225644)
    • Supported container.getRegistration() and container.getRegistrations() inside Service Workers (r225513)
    • Added support for serviceWorker.postMessage() and serviceWorkerRegistration.update() inside of Service Workers (r225462, r225455)
    • Added support for the Service Worker client unloading algorithm (r225483)
    • Added support for FetchEvent.clientId (r225294)
    • Addressed various issues inspecting Service Workers (r225709)
    • Included support for Service Worker generated redirections (r225297)
    • Populated self.registration.installing, self.registration.waiting, and self.registration.active inside Service Workers (r225341)

    Security UI

    • Added a warning in the Smart Search field when interacting with password or credit card forms on non-secure pages

    Privacy

    • Froze the user-agent string to reduce web compatibility risk and to prevent its use for fingerprinting

    CSS

    • Fixed small or clipped controls caused by scale() transforms on <video> elements (r225495, r225521)
    • Clamped automatic minimum size in CSS grid if the min() track sizing function is auto (r225776)
    • Implemented alignment for absolute positioned CSS grid items (r225805)

    Rendering

    • Fixed an often blank <object type="image/svg+xml" data="foo.svg"> in an HTML-page (r225791)
    • Fixed missing layer content when animating elements on-screen (r225310)
    • Implemented transferToImageBitmap for WebGL offscreen canvas objects (r225706)
    • Prevented viewport unit values from being affected by zooming with ⌘- or ⌘+ (r225277)

    Storage Access API

    • Implemented frame-specific access in the network storage session layer (r225827)
    • Made document.hasStorageAccess a function and always allow access for same-origin iframes (r225583, r225586)

    Web Inspector

    • Made Computed a top-level sidebar panel in the Elements tab (r225547)
    • Added the ability to filter rules and add new style rules in the redesigned Styles sidebar (r225571, r225569)
    • Added display of related pseudo-elements in the Styles sidebar (r225572)
    • Changed the behavior of pressing delete in an empty value field of a newly added property to focus on the name field in the Styles sidebar (r225570)
    • Fixed CSS properties not being removed in the Styles sidebar after deleting their values (r225839)
    • Fixed details section headers overlapping the Classes container in the Computed Styles panel (r225595)
    • Fixed adding a new property after a property without trailing semicolon in the Styles sidebar (r225299)
    • Prevented adding a property before or after the first property from becoming appended to the end in the Styles sidebar (r225568)
    • Fixed the filter bar in the Console tab sometimes not appearing and cases where clear console doesn’t always work (r225280)
    • Fixed content views for resources loaded through XHR and Fetch to reflect the declared MIME-type (r225546)
    • Fixed the Remote Web Inspector window to restore the last used window size (r225451)
    • Fixed spurious warnings shown for commands that changed pixel contents in the Canvas tab (r225602)
    • Improved the initial user interface experience in the Canvas tab (r225587, r225487)
    • Fixed an issue that caused Safari to hang after toggling “Allow Web Inspector” setting on an attached iOS device.

    Web Assembly

    • Fixed postMessage to allow a WebAssembly module to postMessage to and from an iframe (r225656)
    • Fixed a bug where we would incorrectly throw stack overflow errors (r225411)

    Web Driver

    • Added support for handling user prompts shown while executing scripts (r225448)
    • Fixed link and partial links queries to work in XHTML documents (r225388)
    • Fixed computeElementLayout to correctly translate iframe client coordinates to main frame coordinates (r225367)
    • Fixed a regression that causes page screenshots to only contain the viewport (r225501)
    • Fixed an issue where safaridriver would quit after trying to close a window when no windows remain open

    JavaScript

    • Corrected the recursive tail call optimisation on closures (r225270)
    • Implemented BigInt literals and JSBigInt (r225799)
    • Implemented a more optimized WeakMap and WeakSet (r225832)
    • Optimized Object.assign by single transition acceleration (r225840)

    Media

    • Added support for the decoding="sync" or decoding="async" attribute on images (r225616)
    • Enabled use of the VCP H264 encoder for platforms that support it (r225761)
    • Fixed the cursor not becoming visible after exiting full screen video (r225494)
    • Included "video/*" in image request Accept header if the browser supports video media in image contexts (r225472)

    WebRTC

    • Changed to allow AudioContext to start when getUserMedia is on (r225785)
    • Fixed an issue where getUserMedia is resolving before the document knows it is capturing (r225828)
    • Prevented the display from going to sleep when playing WebRTC video tracks (r225822)

    By Jon Davis at December 20, 2017 06:00 PM

    December 17, 2017

    Michael Catanzaro: Epiphany Stable Flatpak Releases

    Igalia WebKit

    The latest stable version of Epiphany is now available on Flathub. Download it here. You should be able to double click the flatpakref to install it in GNOME Software, if you use any modern GNOME operating system not named Ubuntu. But, in my experience, GNOME Software is extremely buggy, and it often as not does not work for me. If you have trouble, you can use the command line:

    flatpak install --from https://flathub.org/repo/appstream/org.gnome.Epiphany.flatpakref

    This has actually been available for quite a while now, but I’ve delayed announcing it because some things needed to be fixed to work well under Flatpak. It’s good now.

    I’ve also added a download link to Epiphany’s webpage, so that you can actually, you know, download and install the software. That’s a useful thing to be able to do!

    Benefits

    The obvious benefit of Flatpak is that you get the latest stable version of Epiphany (currently 3.26.5) and WebKitGTK+ (currently 2.18.3), no matter which version is shipped in your operating system.

    The other major benefit of Flatpak is that the browser is protected by Flatpak’s top-class bubblewrap sandbox. This is, of course, a UI process sandbox, which is different from the sandboxing model used in other browsers, where individual browser tabs are sandboxed from each other. In theory, the bubblewrap sandbox should be harder to escape than the sandboxes used in other major browsers, because the attack surface is much smaller: other browsers are vulnerable to attack whenever IPC messages are sent between the web process and the UI process. Such vulnerabilities are mitigated by a UI process sandbox. The disadvantage of this approach is that tabs are not sandboxed from each other, as they would be with a web process sandbox, so it’s easier for a compromised tab to do bad things to your other tabs. I’m not sure which approach is better, but clearly either way is much better than having no sandbox at all. (I still hope to have a web process sandbox working for use when WebKit is used outside of Flatpak, but that’s not close to being ready yet.)

    Problems

    Now, there are a couple of loose ends. We do not yet have desktop notifications working under Flatpak, and we also don’t block the screen from turning off when you’re watching fullscreen video, so you’ll have to wiggle your mouse every five minutes or so when you’re watching YouTube to keep the lights on. These should not be too hard to fix; I’ll try to get them both working soon. Also, drag and drop does not work. I’m not nearly brave enough to try fixing that, though, so you’ll just have to live without drag and drop if you use the Flatpak version.

    Also, unfortunately the stable GNOME runtimes do not receive regular updates. So while you get the latest version of Epiphany, most everything else will be older. This is not good. I try to make sure that WebKit gets updated, so you’ll have all the latest security updates there, but everything else is generally stuck at older versions. For example, the 3.26 runtime uses, for the most part, whatever software versions were current at the time of the 3.26.1 release, and any updates newer than that are just not included. That’s a shame, but the GNOME release team does not maintain GNOME’s Flatpak runtimes: we have three other other redundant places to store the same build information (JHBuild, GNOME Continuous, BuildStream) that we need to take care of, and adding yet another is not going to fly. Hopefully this situation will change soon, though, since we should be able to use BuildStream to replace the current JSON manifest that’s used to generate the Flatpak runtimes and keep everything up to date automatically. In the meantime, this is a problem to be aware of.

    By Michael Catanzaro at December 17, 2017 07:21 PM

    December 06, 2017

    Release Notes for Safari Technology Preview 45

    Surfin’ Safari

    Safari Technology Preview Release 45 is now available for download for macOS Sierra and macOS High Sierra. If you already have Safari Technology Preview installed, you can update from the Mac App Store’s Updates tab. This release covers WebKit revisions 224579-225266.

    If you recently updated from macOS Sierra to macOS High Sierra, you may need to install the High Sierra version of Safari Technology Preview manually.

    Rendering

    • Corrected the computed style in pseudo-elements with display:contents (r225049)
    • Changed to reset the SVG scrolling anchor if the fragmentIdentifier does not exist or is not provided (r224973)
    • Fixed the available height for positioned elements with box-sizing:border-box (r225101)
    • Fixed long pressing a phone number with spaces to result in a data detectors sheet instead of a link sheet (r224819)
    • Fixed compositing layers to use accelerated drawing when navigating back to a page (r224796)
    • Fixed Flexbox issues with display:contents by no longer eliminating the whitespace renderer if the previous sibling is a text renderer (r224773)
    • Fixed missing contents of composited overflow-scroll when newly added (r224715)
    • Fixed content not getting painted when scrolling an overflow node inside an iframe (r224618)
    • Fixed FETurbulence SVG filter with stitchTiles (r225018)
    • Fixed skewed colors in feImage as a filter input (r225152)
    • Fixed an issue in the FEGaussianBlur SVG filter where the output of the last blur pass wasn’t copied to the result buffer (r225147)
    • Optimized the FEDisplacementMap SVG filter (r225183)
    • Optimized the FEMorphology SVG filter (r225172)
    • Optimized the FEComponentTransfer SVG filter (r225107)
    • Optimized the FELighting SVG filter (r225088, r225122)
    • Optimized the FETurbulence SVG filter (r224977, r224996, r225009, r225021, r225020, r225035, r225024)
    • Used vImage to optimize alpha premultiplication and un-premultiplication in FilterEffect (r225086)

    JavaScript

    • Added recursive tail call optimization for polymorphic calls (r225212)
    • Fixed async iteration to only fetch the next method once (r224787)
    • Updated module fetching to retry if the previous request fails (r224662)

    CSS

    • Fixed continual style re-resolution due to calc() values always comparing as unequal as seen on arstechnica.com (r225141)
    • Fixed display issues in CSS Grid for a child with max-width (r225163)
    • Enabled display:contents by default (r224822)
    • Fixed inserting an image, selecting, underlining, and then deleting to remove the typing style with both -webkit-text-decorations-in-effect and text-decoration (r224649)
    • Prevented mixing stroke-width and stroke-color with their prefixed versions (r224780)

    Web API

    • Added support for CanvasPattern.setTransform() (r225121)
    • Implemented OffscreenCanvas.getContext("webgl") (r225193)
    • Changed XMLHttpRequest to not treat file URLs as same origin (r224609)
    • Changed FetchLoader to unregister its blob URL (r224954)

    Media

    • Added a FairPlay Streaming based CDM for Modern EME (r224707)
    • Changed Web Audio’s AnalyserNode.fftSize to allow up to 32768 to match specifications (r225226)
    • Changed skip back and skip forward buttons to not hard-code their numeric amount in localised strings (r225216)
    • Fixed play and pause when pressing the space bar while watching a fullscreen video (r225265)
    • Prevented captions from moving when <video> with no controls is hovered (r225138)

    Web Inspector

    • Added the display of detailed status during canvas recording in the experimental Canvas tab (r224726)
    • Added showing the internal properties of PaymentRequest in the Console (r224606)
    • Cleaned up the backtrace in Canvas details sidebar (r225259)
    • Cleaned up navigation bar dividers and separators (r224807)
    • Gave the DataGrid table header ContextMenu a section header to better describe its functions (r224761)
    • Included Beacon loads in the Network table’s “Other” filter (r225246)
    • Moved console Preserve Log setting from Setting tab to Console navigation bar (r225257)
    • Added a toggle in the Network tab to control automatically clearing or preserving log across loads (r225250)
    • Added a HAR Export button to the Network tab (r224994)
    • Cleaned up the Network tab details view (r224733, r224851, r224769)
    • Fixed the Navigation sidebar that would become broken after closing and re-opening the tab (r224905)
    • Made the connection part thinner in the Network tab waterfall graph (r224727)
    • Updated the Ignore Caches icon in the Network tab (r224989)
    • Updated the Clear icon in the Network tab and Console tab (r225019)
    • Removed Network “Clear on load” from the Settings tab now that Network tab has a toggle for it (r225256)
    • Prevented adding a new property when clicking on inline swatches and property checkboxes in the Styles sidebar (r224651)
    • Changed typing colon in the property name field to advance to the value field in the Styles sidebar (r224906)
    • Fixed the clipped shadow of the selector’s field in the Styles sidebar (r225165)
    • Made the selector field inline-block when editing in the Styles sidebar (r224768)
    • Added undo and redo support for the DOM Tree’s add sibling context menus (r224648)
    • Removed context menu actions for images which did not work (r225234)

    Accessibility

    • Fixed VoiceOver in Safari to read the table header for the first cell in the first body row (r224997)
    • Fixed the search predicate to return the text element for plain text instead of the containing group (r224650)
    • Prevented accessibility from triggering a sync layout while building the render tree on macrumors.com (r224899)

    By Jon Davis at December 06, 2017 06:00 PM

    November 15, 2017

    Release Notes for Safari Technology Preview 44

    Surfin’ Safari

    Safari Technology Preview Release 44 is now available for download for macOS Sierra and macOS High Sierra. If you already have Safari Technology Preview installed, you can update from the Mac App Store’s Updates tab. This release covers WebKit revisions 223953-224579.

    If you recently updated from macOS Sierra to macOS High Sierra, you may need to install the High Sierra version of Safari Technology Preview manually.

    Conic Gradients

    • Added support for parsing conic gradients (r224165)

    Payment Request

    • Enabled Payment Request by default (r224043)
    • Implemented the algorithm for when a user aborts the payment request (r223962)
    • Restricted Payments Request API use to secure, same-origin frames (r224061, r224062)
    • Changed the show() method to only be called with user activation (r224402)

    Image Bitmap

    • Implemented createImageBitmap() with HTMLCanvasElement (r224158)
    • Added support for accepting a Settings object in the ImageBitmapRenderingContext constructor and getContext (r224255)

    Web API

    • Added basic OffscreenCanvas interface (r224407)
    • Prevented XMLHttpRequest from sniffing content encoding (r224299)
    • Added support for the <menuitem> tag, currently off by default at runtime (r224457)

    CSS

    • Fixed dynamic media query updates in shadow tree stylesheets (r224535)
    • Fixed display:contents with dynamic table mutations (r224360)

    Rendering

    • Fixed a black background showing when over-scrolling with overflow-scrolling-touch (r224265)
    • Fixed ugly looking text on macOS High Sierra in some CSS specification pages (r223992)

    Web Inspector

    • Added support for enabling and disabling event listeners in the Node details sidebar (r224002)
    • Grouped DOM Tree context menus into sub-menus (r224314)
    • Added DOM Tree context menu items for adding new elements and inserting HTML (r224456)
    • Added a lock indicator in the Domain column of the Network Tab for secure loads (r224391)
    • Added a context menu item to jump from any resource to its entry in the Network Tab (r224508)
    • Fixed an issue where selecting a DOM Search Result in the Search Tab suddenly changed tabs (r224499)
    • Fixed bugs and usability issues present in the Canvases Tab overview (r223979, r223991, r224067, r224081, r224200)
    • Added a backtrace in the Canvases Tab to show where the selected canvas context was created (r224142)
    • Added a display of all WebGL extensions that are activated for a particular WebGL canvas in the Canvases Tab (r224370)
    • Added inline preview swatches for image parameters in 2D canvas recordings (r224367)
    • Changed selecting a recorded Frame in a canvas recording to update the preview slider to reflect the final drawn result of that frame (r224475)
    • Fixed an issue where the Canvases Tab recording status would fail to update (r223998)
    • Fixed some usability issues in the experimental Layers Tab (r224303)
    • Moved the compositing borders and paint flashing buttons from Elements Tab to the experimental Layers Tab if the latter is enabled (r224434)
    • Enabled the new CSS styles editor by default and made the deprecated Legacy Style Editor available in the Settings tab under Experimental (r224354)
    • Added many smaller features and bug fixes for the spreadsheet-style CSS editor (r224523, r223970, r224210, r223978, r224174, r224286)

    Web Driver

    • Fixed an issue that prevented a test from properly simulating a denied getUserMedia request (r224082)
    • Fixed an issue that prevented a user from manually resizing an automation window after the session had been cancelled.
    • Fixed an issue that caused the mouse move command to use incorrect coordinates in some situations.

    Media

    • Fixed UNPACK_FLIP_Y for MSE-backed videos (r223974)
    • Fixed <video> to respect pointer-events (r224543)
    • Improved performance of painting <video> to canvas by caching resolved URLs (r224297)

    CSS Grid

    • Changed CSS Grid to avoid clearing the overrideContainingBlockWidth if possible (r223955)

    Security

    • Changed to only allow non-mixed content protected sub-resources to ask for credentials (r224134)

    Extensions

    • Disallowed HTTP Authentication prompts from within Global Pages, Bars, and Popovers in .safariextz-style Safari Extensions

    By Jon Davis at November 15, 2017 06:00 PM

    November 14, 2017

    Michael Catanzaro: Igalia is Hiring

    Igalia WebKit

    Igalia is hiring web browser developers. If you think you’re a good candidate for one of these jobs, you’ll want to fill out the online application accompanying one of the postings. We’d love to hear from you.

    We’re especially interested in hiring a browser graphics developer. We realize that not many graphics experts also have experience in web browser development, so it’s OK if you haven’t worked with web browsers before. Low-level Linux graphics experience is the more important qualification for this role.

    Igalia is not just a great place to work on cool technical projects like WebKit. It’s also a political and social project: an egalitarian, worker-owned cooperative where everyone has an equal vote in company decisions and receives equal pay. It’s been around for 16 years, so it’s also not a startup. You can work remotely from wherever you happen to be, or from our office in A Coruña, Spain. You won’t have a boss, but you will be expected to work well with your colleagues. It’s not the right fit for everyone, but there’s nowhere I’d rather be.

    By Michael Catanzaro at November 14, 2017 03:04 PM

    November 01, 2017

    Release Notes for Safari Technology Preview 43

    Surfin’ Safari

    Safari Technology Preview Release 43 is now available for download for macOS Sierra and macOS High Sierra. If you already have Safari Technology Preview installed, you can update from the Mac App Store’s Updates tab. This release covers WebKit revisions 223209-223953.

    If you recently updated from macOS Sierra to macOS High Sierra, you may need to install the High Sierra version of Safari Technology Preview manually.

    Cache Storage API

    • Activated Cache Storage API by default (r223433)
    • Added API to clean CacheStorage data (r223213, r223220, r223263, r223702)
    • Enabled Cache Storage API implementation to compute storage size (r223558)
    • Implemented listing origins for which CacheStorage is storing data (r223299)

    Web Animations

    • Added animations to the timeline (r223825)
    • Added basic timing and target properties (r223883)
    • Provided basic timeline and animation interfaces (r223779)

    ImageBitmap

    • Added support for createImageBitmap with basic HTMLImageElement (r223819)
    • Added createImageBitmap to Window and Worker (r223775)
    • Aligned ImageData constructor with the specification (r223611)
    • Implemented drawImage(ImageBitmap) on 2D canvas (r223843)
    • Implemented resizing options for ImageBitmap rendering (r223925)

    Geolocation API

    • Exposed Coordinates.floorLevel (r223211)

    Drag and Drop

    • Fixed event.dataTransfer.getData("text/uri-list") to return an HTTP or HTTPS URL for a dragged image (r223340)
    • Exposed “text/html” data when dragging and dropping across origins (r223278)
    • Prevented exposing raw HTML in pasteboard to the web content (r223678)

    CSS

    • Added support for ::before and ::after pseudo elements on elements with display:contents (r223748, r223810, r223898)
    • Resolved ::before and ::after pseudo elements during style resolution (r223604)

    Rendering

    • Fixed overlapping text on all CSS fonts specifications (r223688)
    • Avoided triggering layout from a style change (r223210)
    • Fixed fonts that are erroneously invisible when the policy says they should be visible (r223576)
    • Fixed UTF-8 decoding to produce one replacement character per illegal sequence instead of per byte (r223329)
    • Fixed corrupted image after looping movie-backed <img> (r223564)

    WebGL

    • Added WebGL2 texImage3D overloads (r223501)
    • Avoided duplicate multisample resolve before WebGL compositing (r223707)
    • Removed proprietary constants from WebGL2RenderingContext (r223743)
    • Improved performance by performing pixel conformance and texturing in a single step (r223280)
    • Improved performance by skipping texture upload if the source image and destination texture haven’t changed (r223315)
    • Updated the signatures of texSubImage3D (r223602)
    • WebGL clamps drawingBufferWidth to 4096 pixels on a 5120 monitor or canvas (r223567)

    Bug Fixes

    • Fixed an issue where the Delete button didn’t fully delete certain emoji (r223578)
    • Updated cookie partition to add and remove accordingly in intermediary redirect requests (r223565)

    JavaScript

    • Optimized __proto__ getter to be faster (r223594)

    Web Inspector

    The redesigned styles sidebar can be enabled in the Web Inspector Settings tab under Experimental.

    • Turned on the new Network Tab by default (r223778)
    • Turned on the Canvas Tab by default (r223920)
    • Added support for HAR Export in the Network Tab (r223856)
    • Enabled a JSON tree view for JSON content (r223806)
    • Fixed resizing the Console drawer to match the cursor position (r223931)
    • Enabled up and down arrows to modify CSS number values in the redesigned styles sidebar (r223336)
    • Added color picker inline widget to the redesigned styles sidebar (r223575)
    • Applied syntax highlighting to property values in the redesigned styles sidebar (r223453)
    • Enabled autocompletion to property names and values in the redesigned styles sidebar (r223283)
    • Enabled the go-to arrow in the Computed Tab of the redesigned styles sidebar (r223333)
    • Fixed Layers Tab mistakenly throwing out the root element’s layer (r223428)
    • Made 3D objects selectable in the Layers Tab visualization (r223209)
    • Changed the split console to use the full width of the tab view (r223310)
    • Changed Clear button back to the Trash icon in all tabs (r223268)
    • Prevented popovers when scrolling the editor while debugging (r223807)

    Web API

    • Prevented detection of HTML or XML when an XMLHttpRequest responseType is set to “text” (r223217)
    • Prevented DOMTokenList from adding empty attributes (r223306)
    • Stopped key events from updating Document.lastHandledUserGestureTimestamp unless a key event is handled (r223626)
    • Added support for MouseEvent.buttons (r223264)
    • Removed Fetch Request.type getter (r223441)

    Web Driver

    • Fixed handling of keyboard shortcut for “Select All” (⌃A) (r223869)
    • Simulating keyboard shortcuts for disallowed actions no longer triggers the glass pane dialog

    Payment Request

    • Implemented the “PaymentRequest updated” algorithm (r223910)
    • Implemented a paymentmethodselected event for PaymentRequest (r223945)
    • Changed processing shipping options only if shipping is requested, and throw an exception on duplicate shipping option IDs (r223701)
    • Changed to resolve the accept promise for PaymentRequest.show() when a payment is authorized (r223855)

    Subresource Integrity

    • Added support for integrity="" on module scripts (r223237)

    Accessibility

    • Exposed explicitly-set aria-sort value of "none" as an object attribute (r223522)

    By Jon Davis at November 01, 2017 05:00 PM

    October 22, 2017

    Frédéric Wang: Recent Browser Events

    Igalia WebKit

    TL;DR

    At Igalia, we attend many browser events. This is a quick summary of some recents conferences I participated to… or that gave me the opportunity to meet Igalians in Paris 😉.

    Week 31: Paris - CSS WG F2F - W3C

    My teammate Sergio attended the CSS WG F2F meeting as an observer. On Tuesday morning, I also made an appearance (but it was so brief that ceux que j’ai rencontrés ne m’ont peut-être pas vu). Together with other browser vendors and WG members, Sergio gave an interview regarding the successful story of CSS Grid Layout. By the way, given our implementation work in WebKit and Blink, Igalia finally decided to join the CSS Working Group 😊. Of course, during that week I had dinner with Sergio and it was nice to chat with my colleague in a French restaurant of Montmartre.

    Week 38: Tokyo - BlinkOn 8 - Google

    Jacobo, Gyuyoung and I attended BlinkOn 8. I had nice discussions and listened to interesting talks about a wide range of topics (Layout NG, Accessibility, CSS, Fonts, Web Predictability & Standards, etc). It was a pleasure to finally meet in persons some developers I had been in touch with during my projects on Ozone/Wayland and WebKit/iOS. For the lightning talks, we presented our activities on embedded linux platforms and the Web Platform. Incidentally, it was great to see Igalia’s work mentioned during the Next Generation Rendering Engine session. Obviously, I had the opportunity to visit places and taste Japanese food in Asakusa, Ueno and Roppongi 😋.

    Week 40: A Coruña - Web Engines Hackfest - Igalia

    I attended one of my favorite events, that gathers the whole browser community during three days for technical presentations, breakout sessions, hacking and galician food. This year, we had many sponsors and attendees. It is good to see that the event is becoming more and more popular! It was long overdue, but I was finally able to make Brotli and WOFF2 installable as system libraries on Linux and usable by WebKitGTK+ 😊. I opened similar bugs in Gecko and the same could be done in Chromium. Among the things I enjoyed, I met Jonathan Kew in person and heard more about Antonio and Maksim’s progress on Ozone/Wayland. As usual, it was nice to share time with colleagues, attend the assembly meeting, play football matches, have meals, visit Asturias… and tell one’s story 😉.

    Week 41: San Jose - WebKit Contributors Meeting - Apple

    In the past months, I have mostly been working on WebKit at Igalia and I would have been happy to see my fellow WebKit developers. However, given the events in Japan and Spain, I was not willing to make another trip to the USA just after. Hence I had to miss the WebKit Contributors Meeting again this year 😞. Fortunately, my colleagues Alex, Michael and Žan were present. Igalia is an important contributor to WebKit and we will continue to send people and propose some talks next year.

    Week 42: Paris - Monthly Speaker Series - Mozilla

    This Wednesday, I attended a conference on Privacy as a Competitive Advantage in Mozilla’s office. It was nice to hear about the increasing interest on privacy and to see the regulation made by the European Union in that direction. My colleague Philippe was visiting the office to work with some Mozilla developers on one of our project, so I was also able to meet him in the conference room. Actually, Mozilla employees were kind enough to let me stay at the office after the conference… Hence I was able to work on Apple’s Web Engine on a project sponsored by Google at the Mozilla office… probably something you can only do at Igalia 😉. Last but not least, Guillaume was also in holidays in Paris this week, so I let you imagine what happens when three French guys meet (hint: it involves food 😋).

    October 22, 2017 10:00 PM

    October 21, 2017

    Adrián Pérez de Castro: Web Engines Hackfest, 2017 Edition

    Igalia WebKit

    At the beginning of October I had the wonderful chance of attending the Web Engines Hackfest in A Coruña, hosted by Igalia. This year we were over 50 participants, which was great to associate even more faces to IRC nick names, but more importantly allows hackers working at all the levels of the Web stack to share a common space for a few days, making it possible to discuss complex topics and figure out the future of the projects which allow humanity to see pictures of cute kittens — among many other things.

    Mandatory fluff (CC-BY-NC).

    During the hackfest I worked mostly on three things:

    • Preparing the code of the WPE WebKit port to start making preview releases.

    • A patch set which adds WPE packages to Buildroot.

    • Enabling support for the CSS generic system font family.

    Fun trivia: Most of the WebKit contributors work from the United States, so the week of the Web Engines hackfest is probably the only single moment during the whole year that there is a sizeable peak of activity in European day times.

    Watching repository activity during the hackfest.

    Towards WPE Releases

    At Igalia we are making an important investment in the WPE WebKit port, which is specially targeted towards embedded devices. An important milestone for the project was reached last May when the code was moved to main WebKit repository, and has been receiving the usual stream of improvements and bug fixes. We are now approaching the moment where we feel that is is ready to start making releases, which is another major milestone.

    Our plan for the WPE is to synchronize with WebKitGTK+, and produce releases for both in parallel. This is important because both ports share a good amount of their code and base dependencies (GStreamer, GLib, libsoup) and our efforts to stabilize the GTK+ port before each release will benefit the WPE one as well, and vice versa. In the coming weeks we will be publishing the first official tarball starting off the WebKitGTK+ 2.18.x stable branch.

    Wild WEBKIT PORT appeared!

    Syncing the releases for both ports means that:

    • Both stable and unstable releases are done in sync with the GNOME release schedule. Unstable releases start at version X.Y.1, with Y being an odd number.

    • About one month before the release dates, we create a new release branch and from there on we work on stabilizing the code. At least one testing release with with version X.Y.90 will be made. This is also what GNOME does, and we will mimic this to avoid confusion for downstream packagers.

    • The stable release will have version X.Y+1.0. Further maintenance releases happen from the release branch as needed. At the same time, a new cycle of unstable releases is started based on the code from the tip of the repository.

    Believe it or not, preparing a codebase for its first releases involves quite a lot of work, and this is what took most of my coding time during the Web Engines Hackfest and also the following weeks: from small fixes for build failures all the way to making sure that public API headers (only the correct ones!) are installed and usable, that applications can be properly linked, and that release tarballs can actually be created. Exhausting? Well, do not forget that we need to set up a web server to host the tarballs, a small website, and the documentation. The latter has to be generated (there is still pending work in this regard), and the whole process of making a release scripted.

    Still with me? Great. Now for a plot twist: we won't be making proper releases just yet.

    APIs, ABIs, and Releases

    There is one topic which I did not touch yet: API/ABI stability. Having done a release implies that the public API and ABI which are part of it are stable, and they are not subject to change.

    Right after upstreaming WPE we switched over from the cross-port WebKit2 C API and added a new, GLib-based API to WPE. It is remarkably similar (if not the same in many cases) to the API exposed by WebKitGTK+, and this makes us confident that the new API is higher-level, more ergonomic, and better overall. At the same time, we would like third party developers to give it a try (which is easier having releases) while retaining the possibility of getting feedback and improving the WPE GLib API before setting it on stone (which is not possible after a release).

    It is for this reason that at least during the first WPE release cycle we will make preview releases, meaning that there might be API and ABI changes from one release to the next. As usual we will not be making breaking changes in between releases of the same stable series, i.e. code written for 2.18.0 will continue to build unchanged with any subsequent 2.18.X release.

    At any rate, we do not expect the API to receive big changes because —as explained above— it mimics the one for WebKitGTK+, which has already proven itself both powerful enough for complex applications and convenient to use for the simpler ones. Due to this, I encourage developers to try out WPE as soon as we have the first preview release fresh out of the oven.

    Packaging for Buildroot

    At Igalia we routinely work with embedded devices, and often we make use of Buildroot for cross-compilation. Having actual releases of WPE will allow us to contribute a set of build definitions for the WPE WebKit port and its dependencies — something that I have already started working on.

    Lately I have been taking care of keeping the WebKitGTK+ packaging for Buildroot up-to-date and it has been delightful to work with such a welcoming community. I am looking forward to having WPE supported there, and to keep maintaining the build definitions for both. This will allow making use of WPE with relative ease, while ensuring that Buildroot users will pick our updates promptly.

    Generic System Font

    Some applications like GNOME Web Epiphany use a WebKitWebView to display widget-like controls which try to follow the design of the rest of the desktop. Unfortunately for GNOME applications this means Cantarell gets hardcoded in the style sheet —it is the default font after all— and this results in mismatched fonts when the user has chosen a different font for the interface (e.g. in Tweaks). You can see this in the following screen capture of Epiphany:

    Web using hardcoded Cantarell and (on hover) -webkit-system-font.

    Here I have configured the beautiful Inter UI font as the default for the desktop user interface. Now, if you roll your mouse over the image, you will see how much better it looks to use a consistent font. This change also affects the list of plugins and applications, error messages, and in general all the about: pages.

    If you are running GNOME 3.26, this is already fixed using font: menu (part of the CSS spec since ye olde CSS 2.1) — but we can do better: Safari has had support since 2015, for a generic “system” font family, similar to sans-serif or cursive:

    /* Using the new generic font family (nice!). */
    body {
        font-family: -webkit-system-font;
    }
    
    /* Using CSS 2.1 font shorthands (not so nice). */
    body {
        font: menu;       /* Pick ALL font attributes... */
        font-size: 12pt;  /* ...then reset some of them. */
        font-weight: 400;
    }
    

    During the hackfest I implemented the needed moving parts in WebKitGTK+ by querying the GtkSettings::gtk-font-name property. This can be used in HTML content shown in Epiphany as part of the UI, and to make the Web Inspector use the system font as well.

    Web Inspector using Cantarell, the default GNOME 3 font (full size).

    I am convinced that users do notice and appreciate attention to detail, even if they do unconsciously, and therefore it is worthwhile to work on this kind of improvements. Plus, as a design enthusiast with a slight case of typographic OCD, I cannot stop myself from noticing inconsistent usage of fonts and my mind is now at ease knowing that opening the Web Inspector won't be such a jarring experience anymore.

    Outro

    But there's one more thing: On occasion we developers have to debug situations in which a process is seemingly stuck. One useful technique involves running the offending process under the control of a debugger (or, in an embedded device, under gdbserver and controlled remotely), interrupting its execution at intervals, and printing stack traces to try and figure out what is going on. Unfortunately, in some circumstances running a debugger can be difficult or impractical. Wouldn't it be grand if it was possible to interrupt the process without needing a debugger and request a stack trace? Enter “Out-Of-Band Stack Traces” (proof of concept):

    1. The process installs a signal handler using sigaction(7), with the SA_SIGINFO flag set.

    2. On reception of the signal, the kernel interrupts the process (even if it's in an infinite loop), and invokes the signal handler passing an extra pointer to an ucontext_t value, which contains a snapshot of the execution status of the thread which was in the CPU before the signal handler was invoked. This is true for many platform including Linux and most BSDs.

    3. The signal handler code can get obtain the instruction and stack pointers from the ucontext_t value, and walk the stack to produce a stack trace of the code that was being executed. Jackpot! This is of course architecture dependent but not difficult to get right (and well tested) for the most common ones like x86 and ARM.

    The nice thing about this approach is that the code that obtains the stack trace is built into the program (no rebuilds needed), and it does not even require to relaunch the process in a debugger — which can be crucial for analyzing situations which are hard to reproduce, or which do not happen when running inside a debugger. I am looking forward to have some time to integrate this properly into WebKitGTK+ and specially WPE, because it will be most useful in embedded devices.

    By aperez (adrian@perezdecastro.org) at October 21, 2017 01:30 AM

    October 18, 2017

    Release Notes for Safari Technology Preview 42

    Surfin’ Safari

    Safari Technology Preview Release 42 is now available for download for macOS Sierra and macOS High Sierra. If you already have Safari Technology Preview installed, you can update from the Mac App Store’s Updates tab. This release covers WebKit revisions 222556-223209.

    If you recently updated from macOS Sierra to macOS High Sierra, you may need to install the High Sierra version of Safari Technology Preview manually.

    File and Directory Entries API

    • Fixed a failure when calling fileSystemDirectoryEntry.getDirectory() with an empty path (r223118)
    • Fixed recognizing a path starting with 2 slashes as a valid absolute path (r223135)

    Payment Request

    • Implemented PaymentRequest.canMakePayment() (r223160)
    • Implemented PaymentRequest.show() and PaymentRequest.hide() (r223076)

    Clipboard API

    • Added the support for custom pasteboard MIME types and hid unsafe MIME types (r222595 and r222830)
    • Fixed copying and pasting of image files on TinyMCE and GitHub (r222656)
    • Fixed DataTransfer.items to expose custom pasteboard types (r223034)
    • Prevented revealing the file URL when pasting an image (r222688)
    • Prevented dragenter and dragleave from using the same data transfer object (r223031)
    • Removed “text/html” from DataTransfer.items when performing paste and match style (r222956)
    • Started pasting images in RTF and RTFD contents using blob URLs (r222839)
    • Sanitized the URL in the pasteboard for other applications and cross-origin content (r223195)

    Fonts

    • Added “display” to the FontFace JavaScript object (r222949)
    • Implemented font-display loading behaviors (r222926)
    • Upgraded Brotli to version 1.0.1 and WOFF2 to the latest upstream (r222903)

    CSS

    • Removed constant() in favor of env() (r222627)

    Web API

    • Added support for DOM aborting (r222692)
    • Added support for <link rel=preconnect> (r222613)
    • Changed to use the blob URL when pasting RTFD (r222839)
    • Changed XMLHttpRequest.setRequestHeader() to allow Content-Transfer-Encoding header (r222807, r222817)
    • Prevented submitting a form that is disconnected (r223117)
    • Updated Document.createEvent for recent DOM specification changes (r223023)

    WebDriver

    • Added support for selecting an <option> element by sending keys to its parent <select> element.
    • Fixed an issue that caused driver.sendKeys("") to unexpectedly fail and throw an exception.

    JavaScript

    • Addressed an issue with if (!await get(something)) (r223043)
    • Dropped instantiate hook in ES6 module loader (r223173)
    • Fixed object properties that are undefined in super.call() but not in this.call() (r223175)
    • Implemented polymorphic prototypes (r222827)
    • Implemented RegExp Unicode property escapes (r223081)
    • Introduced import.meta (r222895)

    Accessibility

    • Exposed ARIA drag-and-drop attribute values via AtkObject attributes (r222787)
    • Exposed ARIA menu items with ATK*ROLE*MENU_ITEM even when it’s the child of group role (r222822)
    • Fixed redundant layout on tables (r222790)
    • Fixed exposing aria-rowindex set on a row element (r222821)
    • Fixed exposing the value of aria-level on non-heading roles (r222765)

    Media

    • Added basic support for getting an ImageBitmapRenderingContext (r222997)
    • Fixed slow WebGL compositing performance (r222961)
    • Fixed seek() command for encrypted content when the <video> element is not in the DOM at decode time (r222995)

    Rendering

    • Fixed incorrect fullscreen animation when the element has a transform (r223051)
    • Fixed an issue where minimum font size may cause elements to have an infinite line-height (r222588)
    • Improved the progressive display of large images (r223091)

    WebGL

    • Changed to allow async to be able to be used as an imported binding name (r223124)
    • Changed the way WebGL is composited into the page significantly, providing much better performance on lower-end hardware with high-resolution displays (r222961)
    • Reduced the maximum samples used in Multi-Sample Anti-Aliasing (MSAA) for improved performance (r222963)

    Web Inspector

    • Added a Canvas tab (r223011)
    • Added auto-completion for min() and max() within a CSS calc() (r223038)
    • Added support for keyboard navigation with Tab, Shift-Tab, Enter, and ESC in the redesigned styles sidebar (r222959)
    • Added support for editing rule selectors in the redesigned styles sidebar (r222799)
    • Added support for undo and redo of manual edits in the redesigned styles sidebar (r222678)
    • Added detail views for resources in Network tab (r222868)
    • Added a headers detail view for resources in the Network tab (r223006)
    • Added remote address in the headers detail view of the Network tab (r223078)
    • Added a cookies detail view in the Network tab (r223058)
    • Added support to search in the headers detail view of the Network tab (r223057)
    • Changed Layers tab sidebar DOM highlight to be by row hover, not row selection (r222801)
    • Changed Network tab filter resources to be based on URL and text content (r223065)
    • Changed the Network tab to show initially loaded resources even if network info was not logged (r223170)
    • Fixed jitter in timeline ruler labels (r223171)
    • Fixed an issue where clicking in the Web Inspector web view clears the selection in the inspected page (r223007)
    • Fixed Beacon and Ping grouping issues (r222865)
    • Fixed Layers tab sidebar popover (r222566)
    • Fixed a row wrapping issue causing waterfall graphs to display behind the next row’s name (r223059)
    • Fixed blurry quick open resource dialog icons (r222662)
    • Fixed misaligned popover when selecting child layers using the keyboard (r222759)
    • Fixed the table in the Network tab from appearing blank when scrolling it reduces the number of rows (r222899)
    • Enabled 3D objects to be selectable in the Layers visualization (r223209)
    • Ensured popovers are not malformed on window resize. (r222742)
    • Escaped more characters in the command generated by “Copy as cURL” (r222762)
    • Improved Canvas recording events (r222888)
    • Improved setting the initial default sorting for tables (r222983)
    • Improved reliability of selection in a table in the Network tab (r222988)
    • Improved the quick open dialog to include source mapped files in the search results (r223164)
    • Included Beacon and Ping requests in Network tab (r222739)
    • Set initial column widths to allow the waterfall column to expand more by default in the Network tab (r223147)

    Bug Fixes

    • Fixed an issue introduced in Safari Technology Preview 41 where the tab bar could get out of sync with which tab’s content is being displayed when opening links from another app

    By Jon Davis at October 18, 2017 05:00 PM

    October 17, 2017

    Enrique Ocaña: Attending the GStreamer Conference 2017

    Igalia WebKit

    This weekend I’ll be in Node5 (Prague) presenting our Media Source Extensions platform implementation work in WebKit using GStreamer.

    The Media Source Extensions HTML5 specification allows JavaScript to generate media streams for playback and lets the web page have more control on complex use cases such as adaptive streaming.

    My plan for the talk is to start with a brief introduction about the motivation and basic usage of MSE. Next I’ll show a design overview of the WebKit implementation of the spec. Then we’ll go through the iterative evolution of the GStreamer platform-specific parts, as well as its implementation quirks and challenges faced during the development. The talk continues with a demo, some clues about the future work and a final round of questions.

    Our recent MSE work has been on desktop WebKitGTK+ (the WebKit version powering the Epiphany, aka: GNOME Web), but we also have MSE working on WPE and optimized for a Raspberry Pi 2. We will be showing it in the Igalia booth, in case you want to see it working live.

    I’ll be also attending the GStreamer Hackfest the days before. There I plan to work on webm support in MSE, focusing on any issue in the Matroska demuxer or the vp9/opus/vorbis decoders breaking our use cases.

    See you there!

    UPDATE 2017-10-22:

    The talk slides are available at https://eocanha.org/talks/gstconf2017/gstconf-2017-mse.pdf and the video is available at https://gstconf.ubicast.tv/videos/media-source-extension-on-webkit (the rest of the talks here).

    By eocanha at October 17, 2017 10:48 AM

    October 16, 2017

    Who knew we still had low-hanging fruits?

    Gustavo Noronha

    Earlier this month I had the pleasure of attending the Web Engines Hackfest, hosted by Igalia at their offices in A Coruña, and also sponsored by my employer, Collabora, Google and Mozilla. It has grown a lot and we had many new people this year.

    Fun fact: I am one of the 3 or 4 people who have attended all of the editions of the hackfest since its inception in 2009, when it was called WebKitGTK+ hackfest \o/

    20171002_204405

    It was a great get together where I met many friends and made some new ones. Had plenty of discussions, mainly with Antonio Gomes and Google’s Robert Kroeger, about the way forward for Chromium on Wayland.

    We had the opportunity of explaining how we at Collabora cooperated with igalians to implemented and optimise a Wayland nested compositor for WebKit2 to share buffers between processes in an efficient way even on broken drivers. Most of the discussions and some of the work that led to this was done in previous hackfests, by the way!

    20171002_193518

    The idea seems to have been mostly welcomed, the only concern being that Wayland’s interfaces would need to be tested for security (fuzzed). So we may end up going that same route with Chromium for allowing process separation between the UI and GPU (being renamed Viz, currently) processes.

    On another note, and going back to the title of the post, at Collabora we have recently adopted Mattermost to replace our internal IRC server. Many Collaborans have decided to use Mattermost through an Epiphany Web Application or through a simple Python application that just shows a GTK+ window wrapping a WebKitGTK+ WebView.

    20171002_101952

    Some people noticed that when the connection was lost Mattermost would take a very long time to notice and reconnect – its web sockets were taking a long, long time to timeout, according to our colleague Andrew Shadura.

    I did some quick searching on the codebase and noticed WebCore has a NetworkStateNotifier interface that it uses to get notified when connection changes. That was not implemented for WebKitGTK+, so it was likely what caused stuff to linger when a connection hiccup happened. Given we have GNetworkMonitor, implementation of the missing interfaces required only 3 lines of actual code (plus the necessary boilerplate)!

    screenshot-from-2017-10-16-11-13-39

    I was surprised to still find such as low hanging fruit in WebKitGTK+, so I decided to look for more. Turns out WebCore also has a notifier for low power situations, which was implemented only by the iOS port, and causes the engine to throttle some timers and avoid some expensive checks it would do in normal situations. This required a few more lines to implement using upower-glib, but not that many either!

    That was the fun I had during the hackfest in terms of coding. Mostly I had fun just lurking in break out sessions discussing the past, present and future of tech such as WebRTC, Servo, Rust, WebKit, Chromium, WebVR, and more. I also beat a few challengers in Street Fighter 2, as usual.

    I’d like to say thanks to Collabora, Igalia, Google, and Mozilla for sponsoring and attending the hackfest. Thanks to Igalia for hosting and to Collabora for sponsoring my attendance along with two other Collaborans. It was a great hackfest and I’m looking forward to the next one! See you in 2018 =)

    By kov at October 16, 2017 06:23 PM

    October 04, 2017

    Release Notes for Safari Technology Preview 41

    Surfin’ Safari

    Safari Technology Preview Release 41 is now available for download for macOS Sierra and macOS High Sierra. If you already have Safari Technology Preview installed, you can update from the Mac App Store’s Updates tab. This release covers WebKit revisions 221968-222556.

    File and Directory Entries API

    • Enabled File and Directory Entries API (r222412)

    CSS

    • Added support for min() and max() in calc() (r222190)
    • Added env() as an alias of constant() to match the evolving specification (r222402)
    • Made more of the CSS animation system internals element based (r221980)
    • Prevented fit-content() tracks from stretching (r222440)
    • Removed CSS Regions support (r222435, r222259, r222423, r222356)

    Bug Fixes

    • Fixed an issue introduced in Safari Technology Preview 40 where websites would log users out immediately after logging in

    WebRTC

    • Fixed RTCDataChannel connectivity issues (r222045)

    Drag and Drop

    • Enabled DataTransfer.prototype.items by default (r222376)
    • Expose text/html and text/uri-list in DataTransfer.prototype.items (r222363)
    • Fixed DataTransfer to stop exposing local file paths when dropping files (r222257)

    Web API

    • Changed history.pushState() and history.replaceState() to align more closely to the HTML standard (r221978)
    • Changed to use a high resolution timestamp for event time (r222392)

    JavaScript

    • Added a small optimization for async generators (r222425)

    WebCrypto

    • Added support for Elliptic Curve P-521 (r222316)

    WebGL

    • Added bindings for optional arguments to some WebGL2 methods (r222258)
    • Enabled passing sequences to various WebGL2 methods (r222026)
    • Fixed accelerated texImage2D for video to respect flipY in WebGL (r222197)
    • Fixed VideoTextureCopierCV to correctly restore vertex attribute state (r222198)
    • Updated some WebGL2 return types to match the specification (r222096)

    Media

    • Aligned Media Source Extension IDL with spec (r222443)

    Rendering

    • Changed to avoid style recomputation when forwarding a focus event to a text field’s input type (r222114)
    • Changed to avoid style resolution when clearing focused element (r222164, r222167)
    • Fixed computing animated style to not require renderers (r222129)
    • Fixed partial frame rendering that can occur even after loading all of the encoded data (r222427)
    • Fixed the width of a child’s margin box to always be equal to that of its containing block in regular block layout (r222321)
    • Fixed the spelling, grammar, and correction dots that were being painted upside down (r222065)

    Accessibility

    • Fixed ARIA grids that claim to be multiselectable even with aria-multiselectable is set to false (r222527)

    Storage

    • Added Cache API support of records persistency (r222073)
    • Changed IDBRequest and IDBTransaction error properties to be DOMExceptions (r222250)

    Web Driver

    • Fixed an issue that prevented clicking on overflow: hidden elements without children (r222536)
    • Fixed an issue that prevented clicking on <option> elements
    • Fixed an issue that prevented the top-level frame from being re-focused automatically when the main frame navigates

    Web Inspector

    • Added auto-completion suggestions for CSS attr based on the selected element’s attributes (r222483)
    • Added auto-completion suggestions for CSS functions such as constant(), env(), linear-gradient(), etc. (r222359)
    • Changed pressing the Escape key in the global search field to clear the field (r221990)
    • Changed the keyboard shortcut for “Reload page from origin” to match Safari (r222338)
    • Fixed updating the Event Listeners section when listeners are added or removed (r222002)
    • Fixed “Sort by size” issues with Cookies and ApplicationCache DataGrids (r222001)
    • Updated user agent strings and iPhone 8 / iPhone 8 Plus models in Responsive Design Mode

    By Jon Davis at October 04, 2017 05:00 PM

    October 02, 2017

    Introducing WebKit Build Archives

    Surfin’ Safari

    WebKit contributors have long relied on the WebKit Nightly builds. The WebKit project has been posting these builds since r11994, January 11, 2006. Since their introduction, the nightlies have served a meaningful purpose: “Use the newest untested code in WebKit to find bugs, verify fixes and try the latest features.”

    Today we’re excited to roll out some improvements to how we deliver WebKit builds. Building upon the continuous integration infrastructure from https://build.webkit.org, we are now making every successful build of WebKit available! This is a significant improvement from the existing nightly infrastructure, as it should effectively allow bisection down to a single commit.

    With these enhancements, WebKit Build Archives will replace WebKit Nightly builds. The new build archives are intended for engineers that contribute to WebKit development to test and diagnose issues. These builds do not have a signed app launcher nor an auto-update system, making them ill-suited as a daily web browsing application. To regularly try out recent WebKit builds on macOS, we recommend downloading and installing Safari Technology Preview, a quality-checked release that automatically updates every two weeks.

    Availability

    Starting with r219240, built products are being stored at a publicly accessible location. These builds can be accessed via the OpenSource/Tools/Scripts/bisect-builds tool. This script will allow anyone to perform a simple bisection over the range of available WebKit builds.

    For those without WebKit source checkouts, minified release archives can be downloaded directly from the WebKit Build Archives page. These archives contain a README file with usage instructions.

    Platform Support

    Currently, archives for the following platforms are available: macOS El Capitan, macOS Sierra, and macOS High Sierra.

    Archive Types

    Two types of archives are stored: full product, and minified product. Full product archives are exactly what comes out of the build pipeline. These builds are currently used by our CI infrastructure for testing WebKit. Because these builds contain dSYM files (on macOS) they are quite large, and would be undesirable for bisecting. To mitigate the size issue, minified archives are also produced. These minified archives contain only what is necessary to function, and are roughly 10x smaller than the full product archives. This makes them quick to download and extract, ideal for fast bisection and testing.

    Archive Retention

    Full product archives will be retained for 14 days, while minified archives will expire after 2.5 years.

    Feedback

    The development of the bisect-builds script is just beginning, and we welcome any help to improve it. Please file bugs at bugs.webkit.org if you run into any issues or have enhancement requests. Or better yet, feel free to contribute a patch to help improve the experience!

    By Lucas Forschler at October 02, 2017 09:15 PM

    September 22, 2017

    New WebKit Features in Safari 11

    Surfin’ Safari

    With the release of iOS 11 and macOS High Sierra, the new Safari brings impressive performance improvements and great new WebKit features to the web. This release takes bold steps to curb all too common annoyances that have become pervasive across the web. It’s important for developers to be aware of how they might impact their sites. WebKit includes a JavaScript engine that is faster than ever and adds transformative features like WebAssembly and WebRTC. We can’t wait to see what developers will build with them.

    Here are the highlights of the features that make Safari 11 such a significant release.

    WebRTC and Media Capture

    WebKit support for WebRTC and the Media Capture and Streams API brings real-time communication between browsers to Safari. The combination of support for both technology standards enables developers to bring video conferencing experiences to the web without the use of plug-ins. WebKit uses libWebRTC under the hood for interoperability and a solid foundation of features for efficient video conferencing.

    Read more in the WebKit blog post about WebRTC.

    WebAssembly

    WebKit added support for WebAssembly as a complement to JavaScript programs. It is a low-level binary format designed to be a compilation target for existing languages like C++. It can’t do everything that JavaScript can, but it works together with JavaScript to accelerate computationally-intense operations. The implementation in WebKit supports both x86-64 and ARM64 platforms.

    Learn more about WebAssembly in WebKit.

    Variable Fonts

    Developers can improve the loading performance on their site and provide designers with more control over typography using Variable Fonts. It is a specially formatted font file that contains values describing font variations across different axes of features like font weight, size, or oblique angles. The implementation in WebKit also adds CSS property support that can be animated, allowing web authors to incorporate fluid motion into typography changes.

    Read more about Variable Fonts on the Web to learn more.

    Timing APIs

    Support for Resource Timing, Performance Timeline, and User Timing APIs in WebKit enables developers to measure performance characteristics of their web applications. The Resource Timing API can gather detailed network timing data, such as the time taken to fetch a specific resource. Performance Observers allow you to gather timing metrics asynchronously without blocking the application. While the User Timing API allows developers to set application-specific timestamps that are tied in to the browser’s performance timeline.

    Read the Resource Timing, Performance Timeline, and User Timing specifications for more details.

    WebCrypto API Updates

    WebCrypto API support was updated in WebKit to include a standards-compliant SubtleCrypto implementation. This includes DER encoding support for importing and exporting asymmetric keys. Time-consuming cryptography methods now execute asynchronously and can even run in a Web Worker. Support for a number of new cryptographic algorithms adds new functionality, better efficiency, and improved security.

    Learn more about the WebCrypto updates in WebKit.

    Web Inspector Improvements

    Web Inspector sports several useful new features for developers. When the system is set to a right-to-left language, Web Inspector will display a right-to-left user interface layout. It also added a new Settings tab for Web Inspector preferences. In the Network tab, Web Socket connections can now be inspected to show data being communicated across the connection. Finally, in the Elements tab developers can set debugging breakpoints on elements when the subtree or attribute is modified, or when the node is removed.

    Intelligent Tracking Prevention

    WebKit identifies cross-site tracking on websites you visit with machine learning, and shuts it down. This prevents ads that follow users around the web, but it also helps them have more control and awareness of the sites and services using their data. It’s a feature that protects users and enforces better user privacy practices across the web.

    Find our more about Intelligent Tracking Prevention in WebKit.

    Video Auto-Play Blocking on macOS

    The auto-play blocking policy introduced on iOS last year inspired a new video auto-play blocking feature in Safari on macOS. Simply put, auto-play video with sound will be paused. Video elements without audio tracks, or muted audio can still auto-play. This release also includes support for the play method of the video element to return a promise to easily handle successful and unsuccessful video playback.

    Read more about Auto-Play Blocking on macOS with a helpful example on using a Promise to handle auto-play success or prevention.

    More Web Platform Features

    Support for history.scrollRestoration was added to give developers control over when to maintain scroll position when a user navigates back through browser history.

    New CSS Fill and Stroke Module support gives developers more tools to control how text and SVG artwork is painted with new fill- and stroke- properties.

    An improved Flexbox implementation brings it up to match current specifications and better layout performance.

    CSS Scroll Snapping was updated to add scroll snapping to the main document frame, overflow scrolling containers, and adds support for scroll-snap-proximity.

    User Experience Enhancements

    There are also several user focused changes to enhance the user-experience that can impact web development. Text rendered on transparent layers match regular text for consistently beautiful text. Decoding large images happens asynchronously to keep animations smooth dropped frames in animations. Scrolling speed is now consistent between the top level document, iframes, and across web views in apps. Lastly, when sharing a link to an article on iOS, the canonical link of the article will be used.

    Feedback

    All of these improvements are available to users running iOS 11 and macOS High Sierra, as well as macOS Sierra and OS X El Capitan. These features were also available to web developers with Safari Technology Preview releases. Changes in this release of Safari were included in the following Safari Technology Preview releases: 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36. Download the latest Safari Technology Preview release to stay on the forefront of future web features. You can also use the WebKit Feature Status page to watch for changes to your favorite web platform features.

    We love hearing from you. Send a tweet to @webkit or @jonathandavis to share your thoughts on this release, and any features you were hoping for that didn’t make it. If you run into any issues, we welcome your bug reports for Safari, or WebKit bugs for web content issues.

    By Jon Davis at September 22, 2017 11:00 PM

    Designing Websites for iPhone X

    Surfin’ Safari

    The section below about safe area insets was updated on Oct 31, 2017 to reflect changes in the iOS 11.2 beta.

    Out of the box, Safari displays your existing websites beautifully on the edge-to-edge display of the new iPhone X. Content is automatically inset within the display’s safe area so it is not obscured by the rounded corners, or the device’s sensor housing.

    The inset area is filled with the page’s background-color (as specified on the <body> or <html> elements) to blend in with the rest of the page. For many websites, this is enough. If your page has only text and images above a solid background color, the default insets will look great.

    Other pages — especially those designed with full-width horizontal navigation bars, like the page below — can optionally go a little further to take full advantage of the features of the new display. The iPhone X Human Interface Guidelines detail a few of the general design principles to keep in mind, and the UIKit documentation discusses specific mechanisms native apps can adopt to ensure that they look good. Your website can make use of a few similar new pieces of WebKit API introduced in iOS 11 to take full advantage of the edge-to-edge nature of the display.

    While reading this post you can tap on any of the images to visit a corresponding live demo page and take a peek at the source code.

    Safari's default insetting behaviorSafari’s default insetting behavior.

    Using the Whole Screen

    The first new feature is an extension to the existing viewport meta tag called viewport-fit, which provides control over the insetting behavior. viewport-fit is available in iOS 11.

    The default value of viewport-fit is auto, which results in the automatic insetting behavior seen above. In order to disable that behavior and cause the page to lay out to the full size of the screen, you can set viewport-fit to cover. After doing so, our viewport meta tag now looks like this:

    <meta name='viewport' content='initial-scale=1, viewport-fit=cover’>
    

    After reloading, the navigation bar looks much better, running from edge to edge. However, it is immediately clear why it is important to respect the system’s safe area insets: some of the page’s content is obscured by the device’s sensor housing, and the bottom navigation bar is very hard to use.

    viewport-fit=coverUse `viewport-fit=cover` to fill the whole screen.

    Respecting the Safe Areas

    The next step towards making our page usable again after adopting viewport-fit=cover is to selectively apply padding to elements that contain important content, in order to ensure that they are not obscured by the shape of the screen. This will result in a page that takes full advantage of the increased screen real estate on iPhone X while adjusting dynamically to avoid the corners, sensor housing, and indicator for accessing the Home screen.

    Safe and Unsafe AreasThe safe and unsafe areas on iPhone X in the landscape orientation, with insets indicated.

    To achieve this, WebKit in iOS 11 includes a new CSS function, env(), and a set of four pre-defined environment variables, safe-area-inset-left, safe-area-inset-right, safe-area-inset-top, and safe-area-inset-bottom. When combined, these allow style declarations to reference the current size of the safe area insets on each side.

    The env() function shipped in iOS 11 with the name constant(). Beginning with Safari Technology Preview 41 and the iOS 11.2 beta, constant() has been removed and replaced with env(). You can use the CSS fallback mechanism to support both versions, if necessary, but should prefer env() going forward.

    env() works anywhere var() does — for example, inside the padding properties:

    .post {
        padding: 12px;
        padding-left: env(safe-area-inset-left);
        padding-right: env(safe-area-inset-right);
    }
    

    For browsers that do not support env(), the style rule that includes it will be ignored; for this reason, it is important to continue to separately specify fallback rules for any declarations using env().

    Safe area constantsRespect safe area insets so that important content is visible.

    Bringing It All Together, With min() and max()

    This section covers features that are available starting in Safari Technology Preview 41 and the iOS 11.2 beta.

    If you adopt safe area insets in your website design, you might notice that it is somewhat difficult to specify that you want a minimum padding in addition to the safe area inset. In the page above, where we replaced our 12px left padding with env(safe-area-inset-left), when we rotate back to portrait, the left safe area inset becomes 0px, and the text sits immediately adjacent to the screen edge.

    No marginsSafe area insets are not a replacement for margins.

    To solve this, we want to specify that our padding should be the default padding or the safe area inset, whichever is greater. This can be achieved with the brand-new CSS functions min() and max() which will be available in a future Safari Technology Preview release. Both functions take an arbitrary number of arguments and return the minimum or maximum. They can be used inside of calc(), or nested inside each other, and both functions allow calc()-like math inside of them.

    For this case, we want to use max():

    @supports(padding: max(0px)) {
        .post {
            padding-left: max(12px, env(safe-area-inset-left));
            padding-right: max(12px, env(safe-area-inset-right));
        }
    }
    
    It is important to use @supports to feature-detect min and max, because they are not supported everywhere, and due to CSS’s treatment of invalid variables, to not specify a variable inside your @supports query.

    In our example page, in portrait orientation, env(safe-area-inset-left) resolves to 0px, so the max() function resolves to 12px. In landscape, when env(safe-area-inset-left) is larger due to the sensor housing, the max() function will resolve to that size instead, ensuring that the important content within is always visible.

    max() with safe area insetsUse max() to combine safe area insets with traditional margins.

    Experienced web developers might have previously encountered the “CSS locks” mechanism, commonly used to clamp CSS properties to a particular range of values. Using min() and max() together makes this much easier, and will be very helpful in implementing effective responsive designs in the future.

    Feedback and Questions

    You can start adopting viewport-fit and safe area insets today, by using Safari in the iPhone X Simulator included with Xcode 9. We’d love to hear how your adoption of all of these features goes, so please feel free to send feedback and questions to web-evangelist@apple.com or @webkit on Twitter, and to file any bugs that you run into on WebKit’s bug tracker.

    By Timothy Horton at September 22, 2017 05:00 PM

    September 20, 2017

    Release Notes for Safari Technology Preview 40

    Surfin’ Safari

    Safari Technology Preview Release 40 is now available for download for macOS Sierra and betas of macOS High Sierra. If you already have Safari Technology Preview installed, you can update from the Mac App Store’s Updates tab. This release covers WebKit revisions 221334-221968.

    JavaScript

    • Added support for regular expression named capture groups (r221769)
    • Fixed semicolon tokens becoming interpreted as an = assignment operator (r221400)
    • Implemented async iteration statement for-await-of (r221358)
    • Optimized Object.keys using careful array allocation (r221853)

    FileSystem Entry API

    • Added support for input.webkitEntries (r221645)
    • Implemented FileSystemDirectoryEntry.getDirectory() (r221540)
    • Implemented FileSystemEntry.getParent() (r221481)
    • Implemented FileSystemFileEntry.file() (r221544)
    • Fixed the FileSystemEntry API to ignore hidden files (r221639)
    • Finished the DOMFormData implementation (r221839, r221914)

    Fetch API

    • Added support for FetchRequest.body (r221395)
    • Added support for Request body stream cloning (r221437)
    • Added support for consuming a Request ReadableStream body (r221504)
    • Added support for caching Response with a ReadableStream body (r221704)
    • Aligned FetchResponse and FetchRequest body handling (r221772)
    • Fixed Response.statusText unexpectedly using the full HTTP status line for HTTP/2 responses (r221804)
    • Fixed Request ReadableStream body to throw an exception when keep alive is true (r221342)

    Accessibility

    • Distinguished between title attribute tooltips and aria-label attribute labels (r221918)

    Web API

    • Fixed validation for DOMMatrix and DOMMatrixReadOnly NaN values (r221545)
    • Implemented DOMMatrix2DInit for setTransform() and addPath() (r221462)

    CSS

    • Removed support for >> descendant combinator syntax (r221788)
    • Fixed wrong getComputedStyle result for pseudo-elements in display:none subtrees. (r221542)
    • Updated the font selection algorithm to match latest CSS specifications (r221630)

    CSS Grid

    • Fixed grid shorthand to not reset the gutter properties (r221668)
    • Changed stretching auto tracks to be done as part of the track sizing algorithm (r221931)
    • Changed to use transferred size over content size for automatic minimum size (r221910)

    Web Inspector

    • Fixed an issue that caused toolbar buttons to be hidden at narrow widths (r221338)
    • Prevented the split console in the Settings tab (r221882)
    • Use the same Timeline icon in the dashboard and Timeline tab (r221861)
    • Increased the maximum width allowed for sidebars (r221713)
    • Fixed an issue that prevented ⌘E and ⌘G from working in the main content area when quick console drawer is open (r221691)

    Media

    • Prevented increasing the reported totalFrameDelay for non-displayed frames, or frames coming in while paused (r221937)
    • Fixed MSE-to-Canvas painting that can become “stuck” during heavy workloads (r221430)

    Rendering

    • Implemented the HTMLImageElement.async attribute (r221803)
    • Implemented HTMLImageElement.decode() method (r221805)
    • Fixed respecting the SVG fragment identifier if it is a part of an HTTP URL (r221377)
    • Enabled previous elements with lang= to affect fonts selected for subsequent elements (r221408)

    WebGL

    • Implemented getActiveUniforms() for WebGL 2 (r221667)
    • Accelerated texImage2D for video doesn’t respect flipY (r221932)
    • Fixed VideoTextureCopierCV to correctly restore vertex attribute state (r221933)

    By Jon Davis at September 20, 2017 05:00 PM

    September 09, 2017

    Carlos García Campos: WebDriver support in WebKitGTK+ 2.18

    Igalia WebKit

    WebDriver is an automation API to control a web browser. It allows to create automated tests for web applications independently of the browser and platform. WebKitGTK+ 2.18, that will be released next week, includes an initial implementation of the WebDriver specification.

    WebDriver in WebKitGTK+

    There’s a new process (WebKitWebDriver) that works as the server, processing the clients requests to spawn and control the web browser. The WebKitGTK+ driver is not tied to any specific browser, it can be used with any WebKitGTK+ based browser, but it uses MiniBrowser as the default. The driver uses the same remote controlling protocol used by the remote inspector to communicate and control the web browser instance. The implementation is not complete yet, but it’s enough for what many users need.

    The clients

    The web application tests are the clients of the WebDriver server. The Selenium project provides APIs for different languages (Java, Python, Ruby, etc.) to write the tests. Python is the only language supported by WebKitGTK+ for now. It’s not yet upstream, but we hope it will be integrated soon. In the meantime you can use our fork in github. Let’s see an example to understand how it works and what we can do.

    from selenium import webdriver
    
    # Create a WebKitGTK driver instance. It spawns WebKitWebDriver 
    # process automatically that will launch MiniBrowser.
    wkgtk = webdriver.WebKitGTK()
    
    # Let's load the WebKitGTK+ website.
    wkgtk.get("https://www.webkitgtk.org")
    
    # Find the GNOME link.
    gnome = wkgtk.find_element_by_partial_link_text("GNOME")
    
    # Click on the link. 
    gnome.click()
    
    # Find the search form. 
    search = wkgtk.find_element_by_id("searchform")
    
    # Find the first input element in the search form.
    text_field = search.find_element_by_tag_name("input")
    
    # Type epiphany in the search field and submit.
    text_field.send_keys("epiphany")
    text_field.submit()
    
    # Let's count the links in the contents div to check we got results.
    contents = wkgtk.find_element_by_class_name("content")
    links = contents.find_elements_by_tag_name("a")
    assert len(links) > 0
    
    # Quit the driver. The session is closed so MiniBrowser 
    # will be closed and then WebKitWebDriver process finishes.
    wkgtk.quit()
    

    Note that this is just an example to show how to write a test and what kind of things you can do, there are better ways to achieve the same results, and it depends on the current source of public websites, so it might not work in the future.

    Web browsers / applications

    As I said before, WebKitWebDriver process supports any WebKitGTK+ based browser, but that doesn’t mean all browsers can automatically be controlled by automation (that would be scary). WebKitGTK+ 2.18 also provides new API for applications to support automation.

    • First of all the application has to explicitly enable automation using webkit_web_context_set_automation_allowed(). It’s important to know that the WebKitGTK+ API doesn’t allow to enable automation in several WebKitWebContexts at the same time. The driver will spawn the application when a new session is requested, so the application should enable automation at startup. It’s recommended that applications add a new command line option to enable automation, and only enable it when provided.
    • After launching the application the driver will request the browser to create a new automation session. The signal “automation-started” will be emitted in the context to notify the application that a new session has been created. If automation is not allowed in the context, the session won’t be created and the signal won’t be emitted either.
    • A WebKitAutomationSession object is passed as parameter to the “automation-started” signal. This can be used to provide information about the application (name and version) to the driver that will match them with what the client requires accepting or rejecting the session request.
    • The WebKitAutomationSession will emit the signal “create-web-view” every time the driver needs to create a new web view. The application can then create a new window or tab containing the new web view that should be returned by the signal. This signal will always be emitted even if the browser has already an initial web view open, in that case it’s recommened to return the existing empty web view.
    • Web views are also automation aware, similar to ephemeral web views, web views that allow automation should be created with the constructor property “is-controlled-by-automation” enabled.

    This is the new API that applications need to implement to support WebDriver, it’s designed to be as safe as possible, but there are many things that can’t be controlled by WebKitGTK+, so we have several recommendations for applications that want to support automation:

    • Add a way to enable automation in your application at startup, like a command line option, that is disabled by default. Never allow automation in a normal application instance.
    • Enabling automation is not the only thing the application should do, so add an automation mode to your application.
    • Add visual feedback when in automation mode, like changing the theme, the window title or whatever that makes clear that a window or instance of the application is controllable by automation.
    • Add a message to explain that the window is being controlled by automation and the user is not expected to use it.
    • Use ephemeral web views in automation mode.
    • Use a temporal user profile in application mode, do not allow automation to change the history, bookmarks, etc. of an existing user.
    • Do not load any homepage in automation mode, just keep an empty web view (about:blank) that can be used when a new web view is requested by automation.

    The WebKitGTK client driver

    Applications need to implement the new automation API to support WebDriver, but the WebKitWebDriver process doesn’t know how to launch the browsers. That information should be provided by the client using the WebKitGTKOptions object. The driver constructor can receive an instance of a WebKitGTKOptions object, with the browser information and other options. Let’s see how it works with an example to launch epiphany:

    from selenium import webdriver
    from selenium.webdriver import WebKitGTKOptions
    
    options = WebKitGTKOptions()
    options.browser_executable_path = "/usr/bin/epiphany"
    options.add_browser_argument("--automation-mode")
    epiphany = webdriver.WebKitGTK(browser_options=options)
    

    Again, this is just an example, Epiphany doesn’t even support WebDriver yet. Browsers or applications could create their own drivers on top of the WebKitGTK one to make it more convenient to use.

    from selenium import webdriver
    epiphany = webdriver.Epiphany()
    

    Plans

    During the next release cycle, we plan to do the following tasks:

    • Complete the implementation: add support for all commands in the spec and complete the ones that are partially supported now.
    • Add support for running the WPT WebDriver tests in the WebKit bots.
    • Add a WebKitGTK driver implementation for other languages in Selenium.
    • Add support for automation in Epiphany.
    • Add WebDriver support to WPE/dyz.

    By carlos garcia campos at September 09, 2017 05:33 PM

    September 06, 2017

    Frédéric Wang: Review of Igalia's Web Platform activities (H1 2017)

    Igalia WebKit

    Introduction

    For many years Igalia has been committed to and dedicated efforts to the improvement of Web Platform in all open-source Web Engines (Chromium, WebKit, Servo, Gecko) and JavaScript implementations (V8, SpiderMonkey, ChakraCore, JSC). We have been working in the implementation and standardization of some important technologies (CSS Grid/Flexbox, ECMAScript, WebRTC, WebVR, ARIA, MathML, etc). This blog post contains a review of these activities performed during the first half (and a bit more) of 2017.

    Projects

    CSS

    A few years ago Bloomberg and Igalia started a collaboration to implement a new layout model for the Web Platform. Bloomberg had complex layout requirements and what the Web provided was not enough and caused performance issues. CSS Grid Layout seemed to be the right choice, a feature that would provide such complex designs with more flexibility than the currently available methods.

    We’ve been implementing CSS Grid Layout in Blink and WebKit, initially behind some flags as an experimental feature. This year, after some coordination effort to ensure interoperability (talking to the different parties involved like browser vendors, the CSS Working Group and the web authors community), it has been shipped by default in Chrome 58 and Safari 10.1. This is a huge step for the layout on the web, and modern websites will benefit from this new model and enjoy all the features provided by CSS Grid Layout spec.

    Since the CSS Grid Layout shared the same alignment properties as the CSS Flexible Box feature, a new spec has been defined to generalize alignment for all the layout models. We started implementing this new spec as part of our work on Grid, being Grid the first layout model supporting it.

    Finally, we worked on other minor CSS features in Blink such as caret-color or :focus-within and also several interoperability issues related to Editing and Selection.

    MathML

    MathML is a W3C recommendation to represent mathematical formulae that has been included in many other standards such as ISO/IEC, HTML5, ebook and office formats. There are many tools available to handle it, including various assistive technologies as well as generators from the popular LaTeX typesetting system.

    After the improvements we performed in WebKit’s MathML implementation, we have regularly been in contact with Google to see how we can implement MathML in Chromium. Early this year, we had several meetings with Google’s layout team to discuss this in further details. We agreed that MathML is an important feature to consider for users and that the right approach would be to rely on the new LayoutNG model currently being implemented. We created a prototype for a small LayoutNG-based MathML implementation as a proof-of-concept and as a basis for future technical discussions. We are going to follow-up on this after the end of Q3, once Chromium’s layout team has made more progress on LayoutNG.

    Servo

    Servo is Mozilla’s next-generation web content engine based on Rust, a language that guarantees memory safety. Servo relies on a Rust project called WebRender which replaces the typical rasterizer and compositor duo in the web browser stack. WebRender makes extensive use of GPU batching to achieve very exciting performance improvements in common web pages. Mozilla has decided to make WebRender part of the Quantum Render project.

    We’ve had the opportunity to collaborate with Mozilla for a few years now, focusing on the graphics stack. Our work has focused on bringing full support for CSS stacking and clipping to WebRender, so that it will be available in both Servo and Gecko. This has involved creating a data structure similar to what WebKit calls the “scroll tree” in WebRender. The scroll tree divides the scene into independently scrolled elements, clipped elements, and various transformation spaces defined by CSS transforms. The tree allows WebRender to handle page interaction independently of page layout, allowing maximum performance and responsiveness.

    WebRTC

    WebRTC is a collection of communications protocols and APIs that enable real-time communication over peer-to-peer connections. Typical use cases include video conferencing, file transfer, chat, or desktop sharing. Igalia has been working on the WebRTC implementation in WebKit and this development is currently sponsored by Metrological.

    This year we have continued the implementation effort in WebKit for the WebKitGTK and WebKit WPE ports, as well as the maintenance of two test servers for WebRTC: Ericsson’s p2p and Google’s apprtc. Finally, a lot of progress has been done to add support for Jitsi using the existing OpenWebRTC backend.

    Since OpenWebRTC development is not an active project anymore and given libwebrtc is gaining traction in both Blink and the WebRTC implementation of WebKit for Apple software, we are taking the first steps to replace the original WebRTC implementation in WebKitGTK based on OpenWebRTC, with a new one based on libwebrtc. Hopefully, this way we will share more code between platforms and get more robust support of WebRTC for the end users. GStreamer integration in this new implementation is an issue we will have to study, as it’s not built in libwebrtc. libwebrtc offers many services, but not every WebRTC implementation uses all of them. This seems to be the case for the Apple WebRTC implementation, and it may become our case too if we need tighter integration with GStreamer or hardware decoding.

    WebVR

    WebVR is an API that provides support for virtual reality devices in Web engines. Implementation and devices are currently actively developed by browser vendors and it looks like it is going to be a huge thing. Igalia has started to investigate on that topic to see how we can join that effort. This year, we have been in discussions with Mozilla, Google and Apple to see how we could help in the implementation of WebVR on Linux. We decided to start experimenting an implementation within WebKitGTK. We announced our intention on the webkit-dev mailing list and got encouraging feedback from Apple and the WebKit community.

    ARIA

    ARIA defines a way to make Web content and Web applications more accessible to people with disabilities. Igalia strengthened its ongoing committment to the W3C: Joanmarie Diggs joined Richard Schwerdtfeger as a co-Chair of the W3C’s ARIA working group, and became editor of the Core Accessibility API Mappings, [Digital Publishing Accessibility API Mappings] (https://w3c.github.io/aria/dpub-aam/dpub-aam.html), and Accessible Name and Description: Computation and API Mappings specifications. Her main focus over the past six months has been to get ARIA 1.1 transitioned to Proposed Recommendation through a combination of implementation and bugfixing in WebKit and Gecko, creation of automated testing tools to verify platform accessibility API exposure in GNU/Linux and macOS, and working with fellow Working Group members to ensure the platform mappings stated in the various “AAM” specs are complete and accurate. We will provide more information about these activities after ARIA 1.1 and the related AAM specs are further along on their respective REC tracks.

    Web Platform Predictability for WebKit

    The AMP Project has recently sponsored Igalia to improve WebKit’s implementation of the Web platform. We have worked on many issues, the main ones being:

    • Frame sandboxing: Implementing sandbox values to allow trusted third-party resources to open unsandboxed popups or restrict unsafe operations of malicious ones.
    • Frame scrolling on iOS: Addressing issues with scrollable nodes; trying to move to a more standard and interoperable approach with scrollable iframes.
    • Root scroller: Finding a solution to the old interoperability issue about how to scroll the main frame; considering a new rootScroller API.

    This project aligns with Web Platform Predictability which aims at making the Web more predictable for developers by improving interoperability, ensuring version compatibility and reducing footguns. It has been a good opportunity to collaborate with Google and Apple on improving the Web. You can find further details in this blog post.

    JavaScript

    Igalia has been involved in design, standardization and implementation of several JavaScript features in collaboration with Bloomberg and Mozilla.

    In implementation, Bloomberg has been sponsoring implementation of modern JavaScript features in V8, SpiderMonkey, JSC and ChakraCore, in collaboration with the open source community:

    • Implementation of many ES6 features in V8, such as generators, destructuring binding and arrow functions
    • Async/await and async iterators and generators in V8 and some work in JSC
    • Optimizing SpiderMonkey generators
    • Ongoing implementation of BigInt in SpiderMonkey and class field declarations in JSC

    On the design/standardization side, Igalia is active in TC39 and with Bloomberg’s support

    In partnership with Mozilla, Igalia has been involved in the specification of various JavaScript standard library features for internationalization, in specification, implementation in V8, code reviews in other JavaScript engines, as well as working with the underlying ICU library.

    Other activities

    Preparation of Web Engines Hackfest 2017

    Igalia has been organizing and hosting the Web Engines Hackfest since 2009. This event under an unconference format has been a great opportunity for Web Engines developers to meet, discuss and work together on the web platform and on web engines in general. We announced the 2017 edition and many developers already confirmed their attendance. We would like to thank our sponsors for supporting this event and we are looking forward to seeing you in October!

    Coding Experience

    Emilio Cobos has completed his coding experience program on implementation of web standards. He has been working in the implementation of “display: contents” in Blink but some work is pending due to unresolved CSS WG issues. He also started the corresponding work in WebKit but implementation is still very partial. It has been a pleasure to mentor a skilled hacker like Emilio and we wish him the best for his future projects!

    New Igalians

    During this semester we have been glad to welcome new igalians who will help us to pursue Web platform developments:

    • Daniel Ehrenberg joined Igalia in January. He is an active contributor to the V8 JavaScript engine and has been representing Igalia at the ECMAScript TC39 meetings.
    • Alicia Boya joined Igalia in March. She has experience in many areas of computing, including web development, computer graphics, networks, security, and software design with performance which we believe will be valuable for our Web platform activities.
    • Ms2ger joined Igalia in July. He is a well-known hacker of the Mozilla community and has wide experience in both Gecko and Servo. He has noticeably worked in DOM implementation and web platform test automation.

    Conclusion

    Igalia has been involved in a wide range of Web Platform technologies going from Javascript and layout engines to accessibility or multimedia features. Efforts have been made in all parts of the process:

    • Participation to standardization bodies (W3C, TC39).
    • Elaboration of conformance tests (web-platform-tests test262).
    • Implementation and bug fixes in all open source web engines.
    • Discussion with users, browser vendors and other companies.

    Although, some of this work has been sponsored by Google or Mozilla, it is important to highlight how external companies (other than browser vendors) can make good contributions to the Web Platform, playing an important role on its evolution. Alan Stearns already pointed out the responsibility of the Web Plaform users on the evolution of CSS while Rachel Andrew emphasized how any company or web author can effectively contribute to the W3C in many ways.

    As mentioned in this blog post, Bloomberg is an important contributor of several open source projects and they’ve been a key player in the development of CSS Grid Layout or Javascript. Similarly, Metrological’s support has been instrumental for the implementation of WebRTC in WebKit. We believe others could follow their examples and we are looking forward to seeing more companies sponsoring Web Platform developments!

    September 06, 2017 10:00 PM

    Release Notes for Safari Technology Preview 39

    Surfin’ Safari

    Safari Technology Preview Release 39 is now available for download for macOS Sierra and betas of macOS High Sierra. If you already have Safari Technology Preview installed, you can update from the Mac App Store’s Updates tab. This release covers WebKit revisions 220795-221334.

    Beacon API

    • Added support for quota limitation (r220922)
    • Enabled content extensions to be able to intercept Beacon and Ping redirects (r220996)
    • Improved error reporting (r220946)
    • Prevented cross origin Beacon requests with an ArrayBuffer or ArrayBufferView payload from doing a CORS preflight (r220817)

    Directory Upload

    • Added basic support for input.webkitdirectory behind an experimental feature flag (r221177)
    • Added stub File and Directory Entries API interfaces (r221209)

    Fetch API

    • Added support for FetchRequest.body (r221329)
    • Added support for a callback-based fetch (r220927)

    Input Events

    • Renamed inputType “formatForeColor” to “formatFontColor” (r220901)
    • Fixed an issue where picking an emoji via the emoji dialog using Control-Command-Space (⌃⌘Space) fires inconsistent beforeinput events. (r221234)
    • Fixed an issue where using align left or align justify on the Touchbar both send a beforeinput event with the “formatJustifyLeft” inputType. (r221199)

    JavaScript

    • Implemented async generator runtime for async iteration (r221080)
    • Optimized map iteration for faster performance (r221110)
    • Added support for the “dotAll” flag for regular expressions (r221160)

    WebAssembly

    • Fixed const in unreachable code getting decoded incorrectly, erroneously rejecting the binary as invalid (r220894)

    WebRTC

    • Fixed a MediaStream created without tracks to correctly update the active state after tracks are added (r221277)

    Web Inspector

    • Fixed copying text from the “View variable value” popover in the Styles sidebar (r220973)
    • Added async stack trace capture when workers or the main context posts a message (r220815)
    • Replaced “Enter Class Name” input label with “Add New Class” for clarity (r220875)

    Media

    • Implemented HTMLMediaElement dispatch of the onencrypted event (r221131)
    • Fixed autoplay muted videos not playing when outside the viewport (r221016)
    • Fixed HTMLTrackElement behavior to match standards (r221155)

    By Jon Davis at September 06, 2017 05:00 PM

    August 31, 2017

    Xabier Rodríguez Calvar: Some rough numbers on WebKit code

    Igalia WebKit

    My wife asked me for some rough LOC numbers on the WebKit project and I think I could share them with you here as well. They come from r221232. As I’ll take into account some generated code it is relevant to mention that I built WebKitGTK+ with the default CMake options.

    First thing I did was running sloccount Source and got the following numbers:

    cpp: 2526061 (70.57%)
    ansic: 396906 (11.09%)
    asm: 207284 (5.79%)
    javascript: 175059 (4.89%)
    java: 74458 (2.08%)
    perl: 73331 (2.05%)
    objc: 44422 (1.24%)
    python: 38862 (1.09%)
    cs: 13011 (0.36%)
    ruby: 11605 (0.32%)
    xml: 11396 (0.32%)
    sh: 3747 (0.10%)
    yacc: 2167 (0.06%)
    lex: 1007 (0.03%)
    lisp: 89 (0.00%)
    php: 10 (0.00%)

    This number do not include IDL code so I did some grepping to get the number myself that gave me 19632 IDL lines:

    $ find Source/ -name ".idl" | xargs cat | grep -ve "^[[:space:]]\/*" -ve "^[[:space:]]*" -ve "^[[:space:]]$" -ve "^[[:space:]][$" -ve "^[[:space:]]};$" | wc -l
    19632

    The interesting part of the IDL files is that they are used to generate code so those 19632 IDL lines expand to:

    ansic: 699140 (65.25%)
    cpp: 368720 (34.41%)
    python: 1492 (0.14%)
    xml: 1040 (0.10%)
    javascript: 883 (0.08%)
    asm: 169 (0.02%)
    perl: 11 (0.00%)

    Let’s have a look now at the LayoutTests (they test the functionality of WebCore + the platform). Tests are composed mainly by HTML files so if you run sloccount LayoutTests you get:

    javascript: 401159 (76.74%)
    python: 87231 (16.69%)
    xml: 22978 (4.40%)
    php: 4784 (0.92%)
    ansic: 3661 (0.70%)
    perl: 2726 (0.52%)
    sh: 199 (0.04%)

    It’s quite interesting to see that sloccount does not consider HTML which is quite relevant when you’re testing a web engine so again, we have to count them manually (thanks to Carlos López who helped me to properly grep here as some binary lines were giving me a headache to get the numbers):

    find LayoutTests/ -name ".html" -print0 | xargs -0 cat | strings | grep -Pv "^[[:space:]]$" | wc -l
    2205690

    You can see 2205690 of “meaningful lines” that combine HTML + other languages that you can see above. I can’t substract here to just get the HTML lines because the number above take into account files with a different extension than HTML, though many of them do include other languages, specially JavaScript.

    But the LayoutTests do not include only pure WebKit tests. There are some imported ones so it might be interesting to run the same procedure under LayoutTests/imported to see which ones are imported and not written directly into the WebKit project. I emphasize that because they can be written by WebKit developers in other repositories and actually I can present myself and Youenn Fablet as an example as we wrote tests some tests that were finally moved into the specification and included back later when imported. So again, sloccount LayoutTests/imported:

    python: 84803 (59.99%)
    javascript: 51794 (36.64%)
    ansic: 3661 (2.59%)
    php: 575 (0.41%)
    xml: 250 (0.18%)
    sh: 199 (0.14%)
    perl: 86 (0.06%)

    The same procedure to count HTML + other stuff lines inside that directory gives a number of 295490:

    $ find LayoutTests/imported/ -name ".html" -print0 | xargs -0 cat | strings | grep -Pv "^[[:space:]]$" | wc -l
    295490

    There are also some other tests that we can talk about, for example the JSTests. I’ll mention already the numbers summed up regarding languages and the manual HTML code (if you made it here, you know the drill already):

    javascript: 1713200 (98.64%)
    xml: 20665 (1.19%)
    perl: 2449 (0.14%)
    python: 421 (0.02%)
    ruby: 56 (0.00%)
    sh: 38 (0.00%)
    HTML+stuff: 997

    ManualTests:

    javascript: 297 (41.02%)
    ansic: 187 (25.83%)
    java: 118 (16.30%)
    xml: 103 (14.23%)
    php: 10 (1.38%)
    perl: 9 (1.24%)
    HTML+stuff: 16026

    PerformanceTests:

    javascript: 950916 (83.12%)
    cpp: 147194 (12.87%)
    ansic: 38540 (3.37%)
    asm: 5466 (0.48%)
    sh: 872 (0.08%)
    ruby: 419 (0.04%)
    perl: 348 (0.03%)
    python: 325 (0.03%)
    xml: 5 (0.00%)
    HTML+stuff: 238002

    TestsWebKitAPI:

    cpp: 44753 (99.45%)
    ansic: 163 (0.36%)
    objc: 76 (0.17%)
    xml: 7 (0.02%)
    javascript: 1 (0.00%)
    HTML+stuff: 3887

    And this is all. Remember that these are just some rough statistics, not a “scientific” paper.

    Update:

    In her expert opinion, in the WebKit project we are devoting around 50% of the total LOC to testing, which makes it a software engineering “textbook” project regarding testing and I think we can be proud of it!

    By calvaris at August 31, 2017 09:03 AM

    August 30, 2017

    Concurrent JavaScript: It can work!

    Surfin’ Safari

    With the recent addition of SharedArrayBuffer, concurrency is finding its way into the JavaScript language. This addition allows JavaScript programs to perform concurrent access to SharedArrayBuffer objects. WebKit supports SharedArrayBuffer and it has full optimization support in our compiler pipeline. Unfortunately, JavaScript does not allow any objects other than SharedArrayBuffer to be shared.

    This post considers a wild thought experiment: what would it take to extend concurrency to the entire JavaScript heap? In this world, any object can be shared with other threads. This would be no small change. Existing JavaScript VM optimizations exploit the fact that there is only one thread of execution, so concurrency is sure to introduce some performance problems. This post is concerned with whether this is even technically feasible, and if it is, what the cost might be.

    We offer a basic strawman API to illustrate what we mean by concurrency. Most of the post is concerned with how WebKit’s JavaScript VM (called JavaScriptCore, or JSC for short) can implement the strawman. Implementing this strawman will be a big effort. We think that our proposed implementation ought to be able to meet the following goals:

    • No performance regressions for code that does not use concurrency.
    • Linear scalability when a program is run in parallel with itself without deliberately sharing any objects. We don’t expect two threads to be fully twice as fast as one, since we expect some concurrency overhead — but if you have two CPUs then two threads should be faster than one, and hopefully close to twice as fast as one.
    • Linear scalability — including speed-ups versus the best serial baselines — on some corpus of parallel code that does share objects.
    • Sensible semantics, including a memory model that isn’t any weaker than what modern hardware provides.
    • Compatibility. For example, concurrent JavaScript programs should have a story for how to use the DOM without requiring the DOM implementation to be rewritten.

    Our proposed implementation scheme relies on 64-bit systems, but that is largely because our engine is already 64-bit-centric.

    It’s not yet possible to evaluate the performance of this scheme empirically, but our implementation sketch does make it possible to intuit what performance might look like. Specifically, our scheme ensures that most property accesses will experience at most one arithmetic instruction worth of overhead (which is almost free), with a few particularly tricky (and rare) ones experiencing up to about 7x overhead. This post ends with a section that compares our scheme to other techniques for implementing concurrency.

    Strawman Concurrent JS

    Our strawman proposal for concurrent JS is to simply add threads. Threads gets separate stacks but share everything else. Threads are great for our experiment because they are so general. We can imagine implementing many other kinds of concurrent programming models on top of threads. Thus, if we can get our VM to support threads, then we can probably get it to support lots of other concurrent and parallel programming models. This post is about removing technical feasibility as a gating factor for adding any concurrent programming model to JavaScript.

    This section makes the strawman somewhat concrete, mostly to provide context on the aspects of it that are easy or hard to implement. It’s useful to know what the API looks like in order to understand what constraints it creates.

    Each program will start out with one thread. Threads can start other threads. Threads live in the same heap and can share objects with each other. This section shows the API, describes the memory model, and shows how concurrency interacts with the DOM.

    Possible API

    We propose:

    • a simple API for creating threads,
    • a change to the Atomics object to support building lock objects,
    • a lock and condition variable API that can be built on top of Atomics,
    • a way to create thread-local variables, and
    • some helpers to allow for incremental adoption.

    This post will use this strawman to understand exactly what it would take to implement threads in JavaScriptCore.

    We want it to be easy to create threads:

    new Thread(function() { console.log("Hello, threads!"); });
    

    This will start a new thread, which will eventually print “Hello, threads!”. Note that even this simple example shares lots of stuff with the thread. For example, the function object captures the lexical scope in the thread in which it was created, so that when the thread accesses the console variable, this is an access to a shared object.

    Threads can be joined to wait for them to finish and to get their result:

    let result = new Thread(() => 42).join(); // returns 42
    

    In web browsers, the main thread cannot block, so join() will throw an exception if the above code was on the main thread. We can support asynchronous versions of blocking operations:

    new Thread(() => 42).asyncJoin().then((result) => /* result is 42 */)
    

    You can always get the Thread object for the current thread:

    let myThread = Thread.current;
    

    Threads may need to wait on each other to prevent races. This can be accomplished using locks. Rather than simply introduce a locking API, we propose to extend the Atomics API to allow users to build any locks they like. We provide a good lock implementation in our proposed API, but we want to encourage the creation of other kinds of synchronization primitives. The existing SharedArrayBuffer specification allows developers to create custom locks using the Atomics API. This API allows you to say things like:

    Atomics.wait(array, index, expectedValue);
    

    and:

    Atomics.wake(array, index, numThreadsToWake);
    

    Currently, the array must be an integer typed array backed by a SharedArrayBuffer. We propose extending all Atomics methods that take an array/index to take an object and a property name instead. Since an index is a property name, this does not change behavior of code that already uses this API for SharedArrayBuffer. This also implies that Atomics methods that currently take integer values (for storing or comparing to elements in typed arrays) will now be able to take any JavaScript value when used with normal JavaScript properties. Atomics.wake, Atomics.wait, and Atomics.compareExchange are sufficient for implementing any a lock using just one JavaScript property.

    Additionally, we propose adding a Lock API:

    let lock = new Lock();
    lock.hold(function() { /* ...perform work with lock held... */ });
    

    Locking on the main thread is possible with promises:

    lock.asyncHold().then(function() { /* ...perform work with lock held... */ });
    

    This works because each thread gets its own runloop. We can also add a Condition API:

    let cond = new Condition();
    cond.wait(lock); // Wait for a notification while the lock is temporarily released.
    // ...
    cond.asyncWait(lock).then(function() { /* ...perform work with lock reacquired... */ });
    // ...
    cond.notify(); // Notify one thread or promise.
    // ...
    cond.notifyAll(); // Notify all threads and promises.
    

    Condition.prototype.wait will release the lock you pass it before waiting, and reacquire it before returning. The async variant associates the resulting promise with the condition variable such that if the condition is notified, the promise will be fulfilled on the current thread.

    Using Thread.current and WeakMap, anyone can implement thread-local variables. Nonetheless, it’s sometimes possible for the underlying runtime to do something more clever. We don’t want to require all JavaScript programmers to know how to implement thread-local variables with WeakMap. Hence, we propose a simple API:

    let threadLocal = new ThreadLocal();
    function foo()
    {
        return threadLocal.value;
    }
    new Thread(function() {
        threadLocal.value = 43;
        print("Thread sees " + foo()); // Will always print 43.
    });
    threadLocal.value = 42;
    print("Main thread sees " + foo()); // Will always print 42.
    

    Finally, we want to make it easy for users to assert that objects stay on one thread:

    var o = {f: "hello"}; // Could be any object.
    Thread.restrict(o);
    new Thread(function() {
        console.log(o.f); // Throws ConcurrentAccessError
    });
    

    Any object that is Thread.restricted should throw ConcurrencyAccessError in response to any proxyable operation performed by a thread other than the one that called Thread.restrict.

    Memory Model

    Processors and compilers like to reorder memory accesses. Both processors and compilers love to hoist loads from memory. This happens because the following code:

    let x = o.f
    o.g = 42
    let y = o.f
    

    May get transformed by the compiler or processor to:

    let x = o.f
    o.g = 42
    let y = x
    

    Effectively, this means that the “load” into y got moved above the store to o.g. Processors will do the same optimization dynamically, by caching the load of o.f and reusing the cached result for the second load.

    Processors and compilers like to sink stores to memory. This happens because the following code:

    o.f = 42
    let tmp = o.g
    o.f = 43
    

    May get transformed by the compiler or processor to:

    let tmp = o.g
    o.f = 43
    

    This is “as if” the o.f = 42 statement got moved to just before o.f = 43. Even if the compiler does not perform this transformation, the processor may buffer stores and execute them when it is convenient. This can also mean that o.f = 42 may execute after let tmp = o.g.

    It makes most sense for our strawman to follow the existing SharedArrayBuffer memory model. It’s already possible to write multithreaded code that has boundedly nondeterministic behavior using SharedArrayBuffer, and we aren’t going to protect completely from such code. But JavaScript’s objects are much more complicated than a buffer, so guaranteeing that basic invariants of the JS object model hold in the face of races is nontrivial. We propose that operations that modify JavaScript object storage execute atomically. Atomicity means that if many threads execute these operations concurrently, then each one will behave as if they had all executed in some sequence with no concurrency. Each of the underlying operations that JS can do to objects should be atomic:

    • Add a property.
    • Delete a property.
    • Get a property’s value.
    • Set a property’s value.
    • Change a property’s configuration.
    • Snapshot the set of property names.

    This doesn’t always mean that the expression o.f is atomic, since this expression may do much more than loading a property’s value. In particular:

    • If o.f is a plain property directly on o, then it is atomic.
    • If o.f is a prototype access, then loading the prototype is separate from loading f from the prototype.
    • If o.f is a getter, then loading the getter is one step (which would be atomic if the getter is directly on o) but calling the getter is not atomic, since the getter may execute arbitrary code.

    We propose that the low-level object operations are atomic. Some operations, like getting and setting a property’s value, may be implemented using hardware primitives that allow reordering. We propose to allow reorderings of get/set accesses around each other subject to the same memory model for get/set accesses to SharedArrayBuffer. While our strawman does allow for races and some memory model strangeness, it does not allow for JavaScript’s object model invariants to be invalidated. For any heap created by a concurrent JS program, it should be possible to write a sequential JS program that creates an indistinguishable heap.

    Finally, we propose that memory management of the concurrent JS heap happens just as it does in other garbage-collected multi-threaded languages. Quite simply, garbage collection must appear to happen atomically and only at well defined safepoints, like loop back edges, allocation sites, and during calls to native code that doesn’t touch the heap. This requirement is satisfied by popular garbage collection algorithms like those in HotSpot or MMTk. It’s also satisfied by classic algorithms like mark-sweep and semi-space, and even in garbage collectors with no global stop-the-world phase, including ones that are so lock-free that they don’t even stop threads to scan their stacks. WebKit’s Riptide GC already mostly supports multiple threads because our JIT threads can access the heap.

    Interaction With The DOM

    Extending concurrency to all of JavaScript will be hard; extending it to all of the DOM will be even harder. We extend enough reasoning about threads to the DOM to make this strawman useful.

    We propose that by default, DOM objects throw ConcurrentAccessError in response to any proxyable operation from threads other than the main one, just as if Thread.restrict had been called on them from the main thread.

    However, a few objects will have to allow for concurrent accesses just to make the language behave sanely. Something obvious like:

    new Thread(function() { console.log("Hello, threads!"); });
    

    requires a concurrent access to a DOM object. In WebKit, DOM global objects are in charge of storing the variable state of a window. Ordinary JS properties of the global object (including console, Object, etc) have to be accessible to concurrent threads, because those properties are the scripts’s global variables. Accesses from other threads to exotic properties of the global object, or properties of the global object’s prototype, can throw. Attempts to add new properties to the global object or delete properties from it from non-main threads can throw as well. These restrictions mean that in WebKit, handling the DOM global object’s limited kind of concurrent property accesses is not much harder than handling those same accesses for ordinary JS objects.

    Additionally, namespace objects like console can be accessed by concurrent threads because they can just use the JS object model. There is no reason to restrict them to the main thread, and it’s important that console is accessible due to its utility for debugging.

    Strawman Summary

    This section has proposed a strawman API for threading in JavaScript. This API is powerful enough to implement custom synchronization primitives. It’s also powerful enough to allow for the execution of racy programs, but it does not allow races to break the language. Threads are general enough to allow for many other kinds of programming models to be implemented on top of them.

    Implementing Concurrent JS in WebKit

    This section shows that we can implement our threads-based strawman without having to disable any of JavaScriptCore’s fundamental performance optimizations. Our scheme aims to achieve close to zero overhead even in the case of programs that read and write to the same objects from multiple threads.

    JavaScript shares a lot in common with languages like Java and .NET, which already support threads. Here are some of the things these languages have in common with JavaScript:

    • Like JavaScript, those languages use tracing-based garbage collectors. Our GC mostly supports multiple threads, since JIT threads are already allowed to read the heap. The biggest missing piece is thread local allocation, which enables concurrent allocation. For our GC this just means a separate FreeList per thread for each allocator. Our GC has a fixed number of allocators and we already have fast thread-local storage, so this will be a mechanical change.
    • Like JavaScript, those languages are implemented using multiple tiers of JITs and possibly an interpreter. Our WebAssembly VM already supports multi-threaded tier-up from BBQ (build bytecode quickly) to OMG (optimized machinecode generation). We’re not worried about getting this right for JavaScript.
    • Like implementations of JavaScript, implementations of those languages use inline caching to accelerate dynamic operations. We will have to make some changes to our inline caches to support concurrency, and we describe those changes in a later section in this post. It’s not the hardest part about adding concurrency, since it’s not new territory — it’s been done before.

    These similarities suggest that many of the techniques that are already used to make Java virtual machines support concurrency can be reused to make JavaScript concurrent.

    Where things get hard is JavaScript’s ability to dynamically reconfigure objects. While Java and .NET have fixed-size objects (once allocated, an object does not change size), JavaScript objects tend to be variable-size. Concurrency in those statically-typed languages relies on the fact that concurrent accesses to fixed-size objects are atomic by default up to the machine’s pointer width (so, 64-bit systems do 64-bit property accesses atomically by default). Pointer values in Java and .NET are addresses to the contiguous slab of memory holding the object’s data, and it only takes some address arithmetic (like adding an offset) and a single memory access instruction to read/write any field. Even if the memory model allows surprising reorderings, it’s never the case that a racing access instruction to the same field (or different fields of the same object) corrupts the entire object or causes a crash. JavaScript’s variable-size objects, on the other hand, mean that object accesses require multiple memory access instructions in some cases. A sequence of operations involving multiple accesses to memory is not atomic by default. In the worst case, the VM might crash because the internal object state gets corrupted. Even if this doesn’t happen, races might cause writes to be lost or for time-travel to occur (writing A and then B to a field may lead to reads of that field to first see A, then B, and then A again).

    In our strawman proposal, concurrent JavaScript implies that fundamental operations such as adding a new property to an object, changing the value of a property, reading a property, and removing a property all proceed atomically. No race should ever lead to a VM crash, lost writes, or the value of a property experiencing time travel.

    We propose an algorithm that allows most JavaScript object accesses to be wait-free and require minimal overhead compared to our existing serial JS implementation. Wait-free operations execute without ever blocking and complete in a bounded number of steps regardless of contention. This algorithm borrows ideas from real-time garbage collection, locking algorithms, and type inference. We plan to use a tiered defense against the overheads of concurrency:

    1. We propose using our existing polymorphic-inline-cache-based type inference system to infer relaxed notions of thread-locality of objects (and their types) that we call transition-thread-locality (TTL). TTL objects will use the same object model as they do today and accesses to those objects will enjoy close to zero overhead. TTL does not imply true thread-locality; for example even objects that are read and written by many threads may be inferred TTL.
    2. We propose using a segmented object model for objects that fail TTL inference. This will introduce an extra load instruction, and some arithmetic, to the property access fast path. We fear that by itself, this technique would not be fast enough to meet our performance goals — but since the segmented object model will only be used surgically for those objects (or types of objects) that fail TTL inference, we suspect that the net cost will be small enough to be practical.
    3. Operations on non-TTL objects that don’t benefit from the segmented object model will use locks. During our development of the Riptide concurrent GC, we added an internal lock to each object. This lock occupies just 2 bits and allows the lock/unlock fast path to require just an atomic compare-and-swap (CAS) and a branch.

    Before diving into the details, we first set up some expectations for the hardware that this proposed system would run on. Then we describe this proposal in reverse. We consider the cost of just using per-object locking. Then we review the existing JSC object model and describe what kinds of operations happen to already be atomic within this model. Next we introduce segmented butterflies, which are the key to allow dynamically reconfiguring objects. Then we show how our TTL inference will allow us to use our existing object model for hopefully most of the JavaScript heap. This section then considers some loose ends, like how to do inline caching concurrently, how resizable arrays fit into TTL and segmented butterflies, how to handle large thread counts using the local optimizer lock (LOL), and finally how to handle native state that isn’t thread-safe.

    Hardware Expectations

    This post describes how to convert JavaScriptCore to support concurrent JavaScript. JSC is currently optimized for 64-bit systems, and most of our existing concurrency support (concurrent JIT, concurrent GC) only works on 64-bit systems. This section briefly summarizes what we expect from a 64-bit system to be able to use our scheme.

    JSC is optimized for x86-64 and ARM64. This scheme assumes the weaker of the two memory models (ARM64) and assumes that the following atomic instructions are inexpensive enough that it’s practical to use them as an optimization over locking:

    • 64-bit loads and stores are atomic by default. We expect that these accesses may be reordered around other accesses. But we also expect that if memory access instruction B has a dataflow dependency on memory access instruction A, then A will always come before B. For example, in a dependent load chain like a->f->g, a->f will always execute before _->g.
    • 64-bit CAS (compare-and-swap). JSC uses 64-bit words for JavaScript properties and two important meta-data fields in the object header: the type header and the butterfly pointer. We want to be able to atomically CAS any JS property and either of the meta-data properties in the object header.
    • 128-bit DCAS (double-word compare-and-swap). Sometimes, we will want to CAS all of the meta-data inside JS objects, which means CASing both the 64-bit type header and the adjacent 64-bit butterfly pointer.

    Per-Object Locking

    Each object in JSC already has a lock, which we use to synchronize certain fundamental JavaScript operations with the garbage collector. We can use this lock to protect any operations that need to be synchronized between JavaScript threads. The rest of this post deals with optimizations that allow us to avoid this lock. But let’s consider exactly what the cost of the lock is. Our internal object lock algorithm requires an atomic compare-and-swap (CAS) and a branch for locking, and another CAS and branch for unlocking. In the best case, CAS is like executing at least 10 cycles. This is the amortized cost assuming the CAS succeeds. On some hardware, the cost is much higher. Assuming a branch is one cycle, this means at least 22 extra cycles for each object operation that requires the lock. Some rare operations are already expensive enough that 22 cycles is not bad, but many fast path operations would not be able to handle such overhead. Below we consider some operations and how much they would be affected if they had to use locking.

    • Adding a new property currently requires only one load, a branch, and two stores on the optimized fast path. Each of those operations is a single cycle, leading to about 4 cycles total in the fastest case. Adding locking bloats this to 26 cycles – a ~7x slow-down. In some cases, adding a new property can be optimized down to just a single store. In those cases, adding locking creates a 23x regression.
    • Changing the value of an existing property requires a load, a branch, and a store. That’s 3 cycles in the fastest case. Adding two CASes and two branches bloats this to 25 cycles – a 8x slow-down. In some cases, we can optimize a property store to just one store instruction. Putting locking around it is a 23x regression.
    • Loading an existing property’s value requires a load, a branch, and another load. Adding locking is a 8x slow-down, or 23x in the case where we optimized the load to just a single load instruction.
    • Deleting a property is already slow. We are fine with putting locks around it. Deleting properties is relatively rare, but we have to support it.
    • Dictionary lookups — JSC-speak for property accesses that we execute dynamically without any inline cache or compiler smarts — will see a small overhead from locking. Those code paths are already expensive enough that adding locking to them is unlikely to be a problem.
    • Snapshotting the set of properties does not change. It’s already possible for concurrent threads to snapshot the set of properties of any object in JSC because of locking that we implemented for concurrent garbage collection.

    While some operations like deletion are already expensive enough that locking is not a problem, we don’t believe it’s practical to add such extreme costs to the fast cases of JavaScript object access. The resulting programming language would be too slow.

    Designing a fast concurrent JS implementation requires introducing new algorithms for property accesses that can run concurrently to each other without requiring any locking except in rare cases. In the sections that follow, we describe such an algorithm. First we review JavaScriptCore’s object model. Then we show cases where JavaScriptCore’s object model already behaves as if it had fixed-size objects; those cases never require locking. Next we show a technique called segmented butterflies, which allows for mostly wait-free concurrent object access. By itself, this technique is still too expensive for our tastes. So, we show how to infer which object types are transition-thread-local (TTL) to avoid synchronization when transitioning objects. This allows us to use flat butterflies (our existing object model) for the majority of objects. Then we describe how to handle deletion, dictionary lookups, inline caches, arrays, and thread-unsafe objects.

    JavaScriptCore Object Model

    The JavaScriptCore Object Model. JavaScript values and object pointers are implemented as pointers to the cell. The cell never moves and never changes size, but contains a pointer to the butterfly, which can grow either left (for named properties) or right (for array elements).

    JavaScriptCore’s object model allows for four kinds of state, each of which is optional:

    • Native state represented using ordinary C++ objects.
    • Data for named object properties (like o.f) that we statically guessed the object would have.
    • Data for named object properties that were added dynamically, forcing us to change the size of the object.
    • Data for indexed object properties. These can change the size of the object in many ways.

    The first two kinds of state does not involve resizing the object. The last two kinds of state require resizing. In JSC, fixed-sized state is stored directly in the object’s cell. The cell is what a pointer to an object points to. Within the cell, there is a butterfly pointer that can be used to store dynamically-allocated and resizable state in a butterfly. Butterflies store named properties to the left of where the butterfly pointer points inside out-of-line slots, and indexed properties to the right as array elements. Each of those locations may store a tagged JavaScript value, which may be a number, pointer to another cell (representing a string, symbol, or object), or a special value (true, false, null, or undefined).

    Every object has a structure, which contains the hashtable used for mapping property names to slots in the object. Objects typically share a structure with other objects that look like it (that have the same properties in the same order, among other requirements). The structure is referenced using a 32-bit index into a structure table. We do this to save space. The indexing and cell state bytes have some spare bits. We used two spare bits in the indexing byte to support per-object locking. We also have spare bits in the butterfly pointer, since pointers don’t need all 64 bits on a 64-bit system.

    Butterflies are optional. Many objects don’t have a butterfly. When a butterfly is allocated, each of the two sides are optional. The left side of the butterfly holds the out-of-line slots. It’s possible just to allocate that; in this case the butterfly pointer will point 8 bytes to the right of the end of the butterfly’s memory. The right side of the butterfly holds the array elements and the array header. The public length is the length as it is reported by array.length, while the vector length is the number of array element slots that were allocated.

    Freebies

    Within this object model, accesses to anything in the cell itself are atomic by default, just like accesses to objects in Java are atomic by default. This is a big deal, since our optimizer is generally successful at putting the most important object fields inline in the cell. Concurrent JS programs that mostly rely on data that ends up inside the cell will experience almost no overhead versus their serial equivalents.

    Additionally, if we know that the butterfly won’t be reallocated ever again (i.e. the butterfly pointer is immutable), then we can access it directly without any problems. Those accesses will be atomic by default.

    Alternatively, if we know that only the current thread will ever resize the butterfly and all other threads will only read it, then accesses to the butterfly will be atomic by default.

    Problems happen when one thread attempts to transition the object (i.e. add a property and/or reconfigure the butterfly) while some other thread is writing to it (or also transitioning it). If we used our current implementation of object accesses in a concurrent setting, a transition on one thread could cause races that lead to behavior that does not conform to our proposed specification.

    • Writes made by another thread could disappear or experience time travel. This race happens because the transitioning thread might first complete a copy of the butterfly and then transition the object, while another thread does some more writes to the object in between those two steps. If a third thread is observing what is going on by repeatedly reading the state of the fields being written, then it will first see the state before any writes, then it will see the writes, and then once the transition completes it will see the original state again.
    • Two transitions performed concurrently could cause the butterfly pointer and the object’s type to be mismatched. The butterfly’s format is determined by fields in the object’s header that are not inside the same 64-bit word as the butterfly pointer. We cannot allow the butterfly and the header to get out of sync, as this would lead to memory corruption.
    • Two transitions performed concurrently can cause some minor heap corruption even if the butterfly is not involved. If a transitions involving an inline property proceeds as two steps — first, change the object’s type, and then, store the new property — then two racing transitions adding two different properties may result in one property being added, where its value ends up being the intended value of the other property. For example, a race between o.f = 1 and o.g = 2 could result in o.f == 2 and "g" in o == false.

    In the next section we show how to create an object model that has no such races, but comes with some cost. After that, we show how to use TTL inference to use our existing object model most of the time even in programs that share objects between threads.

    Segmented Butterflies

    Transitioning an object means allocating a new butterfly, and copying the contents of the old butterfly into the new one while other threads may be reading or writing the old butterfly. We want the copy to seem as if it had happened in one atomic step. Lots of research has gone into supporting concurrent copying of objects in the context of real-time garbage collectors. The approach that we propose to use is based on the Schism real-time garbage collector‘s arraylet object model. This section reviews the Schism arraylet object model and then shows how it can be used for butterfly transitions.

    Schism was trying to solve the problem of implementing a copying garbage collector whose copying phase was completely concurrent to the application. It was based on the observation that copying an object concurrently to other threads accessing the object is easy if the object is immutable. It’s only hard if the object can be written to by the other threads. Schism solves the problem of copying mutable objects concurrently by boxing the mutable state in small fixed-size fragments (32 bytes in the paper). The object that gets copied is the spine that serves as an index for finding fragments. All object accesses use an extra indirection to find the fragment that contains the data being accessed. Spines are immutable objects because the fragments they point to never move.

    WebKit already uses something like arraylets as well, in the WTF::SegmentedVector class template. We use it to prevent having to move C++ objects when the vector resizes. We also use it for implementing the JSGlobalObject‘s variable storage (for var statements in global scope). The term arraylets is due to Bacon, Cheng, and Rajan, who used them to control fragmentation in the Metronome garbage collector. Lots of arraylet research shows that the extra indirection has a high cost (often 10% or more). That is, if you double the cost of each array access by adding an extra indirection, then you will increase the total run time of the program by 10%.

    Segmented Butterflies. A segmented butterfly comprises a spine (which resizes but contains only immutable state) and zero or more fragments (which don’t resize but are mutable). Splitting resizable state from mutable state to enable concurrent layout changes is a proven technique in concurrent garbage collection. The shape of the fragments matches the shape of an unsegmented butterfly, which we will use for some additional optimizations.

    We can use this trick for butterflies. A segmented butterfly has a spine that contains pointers to fragments that contain mutable data. If we need to add new properties and those properties won’t fit in an existing fragment, we can grow the spine and allocate more fragments. Growing the spine implies reallocating it. We can safely allocate a new spine and memcpy the contents of the old one into it, since the spine’s contents never changes. In this world, no writes ever get lost or experience time travel when a butterfly is being transitioned. An access that races with the transition either gets to a fragment using the old spine, or the new spine; since both spines will contain the same fragment addresses for properties that existed before the transition, every possible interleaving results in threads reading and writing the same fragments.

    The most natural way to implement segmented butterflies is probably to have 32-byte fragments like in Schism, since this is also a sweet-spot for our GC. The vector length is be inside the butterfly spine, since this is an immutable property of that spine. The vector length allows the spine to self-identify how big its right side is. The public length is mutable, so we want to put it into one of the fragments. Note that the first fragment also contains the old vector length. This property is unused when we are using segmented butterflies. It allows us to convert a flat butterfly into a segmented butterfly by having the spine point at slices of the flat butterfly; we discuss this optimization more in a later section.

    This still leaves the problem of concurrent transitions. Transitions have to reallocate the spine, change some data in the type header, and store a property’s value. Reallocating the spine is optional since usually some fragment will already have a spare slot. Changing the type is optional, for example in case of array resizing. The type header and butterfly can be set atomically using a DCAS (double-world compare-and-swap; 64-bit systems typically support 128-bit CAS). But this isn’t enough, since no matter if we set the property’s value before or after the DCAS, we will have a race. The property’s slot can be anywhere in memory, so there’s no way to use CAS to simultaneously do the whole transition.

    If we set the newly-added value slot before changing everything else, we risk a race in which one thread tries to use some object slot for adding field f while another thread tries to use the same slot for field g. If we’re not careful, the second thread might win the race for the type (so everyone thinks we added property g) while the first thread wins the race for the property (so we get thread 1’s intended value for property f appearing as if it was stored by thread 2 into g).

    If we set the newly-added value slot after changing everything else, then all loads have to contend with the possibility that slots can have “holes”. In other words, at any time, an object may claim a type that includes a property f even though the object does not have a value for f yet. We could change the language to allow this: putting a new property into an object would first involve defining it to undefined and then storing the real value.

    We choose to put a lock around transitions. This lock isn’t for guarding races between transitions and other accesses, since those are atomic by default thanks to segmented butterflies — it’s for protecting transitions from each other. To ensure that objects don’t have holes, transitions store the new property’s value before changing the type. Transitions can use this algorithm:

    1. Allocate whatever memory needs to be allocated.
    2. Acquire the lock.
    3. Determine if we allocated the right amount of memory; if not, release the lock and go back to step 1.
    4. Store the new property’s value.
    5. Change the type and butterfly.
    6. Release the lock.

    This results in the following cost model:

    • Transitions are about 7x costlier, since they now require locking.
    • Reading or writing existing property slots requires an extra load.
    • Deleting and dictionary lookups still work (we show details in a later section).

    Recall that the arraylet research shows 10% or higher costs if arrays use a segmented object model. We’re proposing to use it for ordinary properties as well, if those properties were added in a sufficiently subtle way that we weren’t able to inline them into the cell. It’s probably safe to assume that if we implemented literally this, we incur at least a 10% slow-down. We would like to have close to zero overhead. The next section shows how we think we can get there.

    Transition Thread Locality and Flat Butterflies

    Segmented butterflies are only necessary when:

    • Some thread other than the thread that allocated an object tries to transition the object.
    • The thread that allocated the object tries to transition it, and other threads may be writing to it.

    We can use flat butterflies — our existing object model — when we know that these things haven’t happened yet. This section describes a hybrid object model that uses either flat or segmented butterflies, depending on whether or not we have detected a possible write-transition race. This object model also allows us to avoid locking while doing many transitions.

    On a 64-bit system, butterfly pointers have 48 bits of pointer information and have zeroes in their high 16 bits. 16 bits is enough to store:

    • The ID of the thread that allocated the object. We call this the butterfly TID.
    • A bit to indicate if any thread other than the allocating thread has attempted to write to the butterfly. We call this the butterfly shared-write (SW) bit.

    Some systems have more than 48 pointer bits. In a later section, we show how to make this scheme useful even if we had to use fewer bits. Also, we could restrict butterfly allocations to the lower 248 addresses if we really wanted 16 spare bits.

    Let’s say that these bits are encoded as follows:

    static const uint16_t mainThreadTID = 0; // Occassionally, we can optimize a bit more for the main thread.
    static const uint16_t notTTLTID = 0x7fff; // For when the thread is no longer transition-thread-local.
    
    static inline uint64_t encodeButterflyHeader(uint16_t tid, bool sharedWrite)
    {
        ASSERT(tid <= notTTLTID); // Only support 2^15 tids.
        return (static_cast<uint64_t>(tid) << 48)
             | (static_cast<uint64_t>(sharedWrite) << 63);
    }
    
    static inline uint64_t encodeButterfly(Butterfly* butterfly, uint16_t tid, bool sharedWrite)
    {
        return static_cast<uint64_t>(bitwise_cast<uintptr_t>(butterfly))
             | encodeButterflyHeader(tid, sharedWrite);
    }
    

    We can use flat butterflies — our existing object model — whenever the TID matches the current thread. We set the SW bit and use a magic TID value (all bits set) to indicate that the butterfly is segmented. This section shows how to use these bits to allow the use of flat butterflies anytime we know that no transition race can occur. We call this transition thread locality inference.

    Anytime a thread attempts to write to a butterfly and the TID matches the current thread, it can simply write to the butterfly without doing anything special.

    Anytime a thread attempts to write to a butterfly, the TID does not match, but the SW bit is set, it can simply write to the butterfly as well.

    Anytime a thread attempts to read a butterfly, it just needs to check that the TID to determine if the read should be segmented (extra indirection) or not.

    Anytime a read or write encounters TID = notTTLTID and SW = true, it knows to use the segmented object model.

    The following cases need special handling:

    • A thread other than the one identified by the TID attempts to write to the butterfly and the SW bit is not yet set. In this case, it needs to set the SW bit. This does not mean that the butterfly needs to become segmented. It only means that the SW bit must be set, so that any future attempts to transition the butterfly from the owning thread triggers a transition to the segmented butterfly object model.
    • A thread other than the one identified by the TID attempts to transition the butterfly. In this case, it needs to set the SW bit and all TID bits and perform a segmented butterfly transition. We describe this process in detail below.
    • A thread attempts to transition a butterfly that has the SW bit set. This also necessitates a segmented butterfly transition.
    • Even transitions with TID = current and SW = false need locking, to make sure that those assumptions aren’t violated during the transition.

    The sections that follow show further refinements that reduce overhead even more. First we consider how to avoid checking TID and SW bits on every operation. Next we show how to use structure watchpointing to avoid locking on the most common transitions. Then we show how to handle array resizing. Finally we explain in more detail how flat butterflies can be transitioned to segmented ones.

    Quickly Checking TID And SW Bits

    This section will show how to make concurrent JS as fast as serial JS in many of the most important cases by simply extending optimizations that JavaScriptCore already uses.

    JSC optimizes the code for heap accesses using inline caching. We use inline caches for accesses to named properties (like o.f) and for array accesses (like a[i]).

    Objects that have the same properties at the same offsets will usually share the same structure, which is identified by 32 bits in the object’s type header. If a property access tends to see the same structure, then we will generate new machine code for this property access, which checks that the object has the expected structure and then accesses the property directly. Failed speculation causes recompilation of the inline cache. If the inline cache remains stable (doesn’t recompile much) for a long time and the function that contains it becomes eligible for optimized JIT compilation, then the optimizing JIT compiler might express the inline cache’s code directly in its IR, which has two outcomes: the structure check branches to OSR exit if it fails (causing abrupt termination of the optimized code’s execution), and all of the code for the inline cache (the structure check, the memory access, and any other steps) become eligible for low-level optimization by our DFG and B3 JIT compiler pipelines. Our compilers are good at making type-stable JavaScript property accesses perform great.

    Array accesses use similar techniques to detect if an object has array elements, and if so, how they are formatted. We support multiple kinds of storage for array elements depending on how they are being used. Inline caches detect what kind of array each array access is accessing, and we then emit code that speculates for that kind of array access.

    Another technique we already use is virtual memory. For example, our WebAssembly implementation uses virtual memory tricks to check the bounds of linear memory accesses for free. We can catch page faults using POSIX signal handlers or Mach exceptions. The handler will know the exact machine state at the point of the fault, and has the power to transfer execution to any state it likes. WebAssembly uses this to throw an exception, but we can use it to transfer control flow to slow paths that handle the generic case of a memory access. Essentially, this means that we can save cycles on safety checks if we can express the condition being checked as something that causes the virtual memory system to issue a page fault. Concurrent JS will require a combination of inline caching and virtual memory tricks to make TID and SW checking cheap.

    Inline caching means emitting different code for each property access, and then recompiling each property access potentially many times as we learn new information about what this property access may do. Inline caches are able to get incredibly precise information about the behavior of each property access because we always emit a fast path access that can only handle exactly those cases that we have seen so far. We learn new information by recording everything we know about those accesses that failed the fast path. The complete log of failed accesses is then LUBed (least-upper-bounded) together to create a minimal set of AccessCases. We can implement optimizations for new kinds of property accesses — such as the ones that have to check TID and SW bits — by considering in what ways a particular access site might be special and so specially optimizable. Below is a list of conditions we may encounter along with the strategy for how inline caches can test this condition and handle it.

    • Probably many object accesses will always see TID = current and SW = false. These accesses can simply subtract encodeButterflyHeader(currentTID, 0) from the butterfly before accessing it. If the speculation was wrong, the virtual memory subsystem will issue a page fault because of non-zero high bits. We can catch this as a Mach exception or POSIX signal, and divert execution to the slow path. The subtraction of this constant can often be encoded directly into the subsequent butterfly access instruction. As a result, these kinds of accesses will not experience any overhead in concurrent JS versus what they have currently. Note that this optimization does not apply to transitions, which must install a new butterfly while atomically asserting that nothing bad has happened — we consider those further below. Note that this optimization slightly favors the main thread (and so all single-threaded programs) because if currentTID = 0 then we don’t have to add anything.
    • Probably many object accesses will always see TID = current and SW = true. These can be optimized identically to the previous case. This state is for objects that we already know can be written to from many threads, but that only happened after the last time that the current thread transitioned the object.
    • Probably many object reads will see TID != notTTLTID and SW = anything. These just need to check that the butterfly’s high bits are not notTTLTID. This can be done with a single compare/branch. Other than this, they can proceed exactly how they do in our current engine.
    • Probably many object writes will see TID != notTTLTID and SW = true. This means that the object is being written to by many threads. We are also writing to it, but we don’t need to set the SW bit because it is already set. This check can also be performed in a single compare/branch. Together with the read optimization above, this means that concurrent JS programs that share objects will typically only experience one extra cycle (for fused compare/branch) for butterfly accesses.
    • Sometimes, an object write will see TID != notTTLTID and SW = false. This means having to set the SW bit using a DCAS, which sets the SW bit while asserting that the type header did not change. These accesses will be more expensive than their friends, but this only has to happen the first time that any thread writes to a shared object. Our inline caching infrastructure will probably make it so that writes that sometimes see SW = false and sometimes see SW = true (and don’t necessarily see TID = current but never notTTLTID) will be branchy: they will have a fast path for SW = true and a slightly slower but still inline path for SW = false. In the next section, we will describe optimizations that require invoking functions on the structure when the SW bit of any objects of that structure gets set for the first time. Since this inline cache knows about the structure at the time of generation, it can ensure that the structure is already informed that objects of its type may have the SW bit set.
    • Probably some object accesses will see TID = notTTLTID and SW = true. By convention, we’ll say that it’s not possible to have TID = notTTLTID and SW = false (internally in our VM, it’s technically possible to transition an object without “writing” to it, but we’ll pretend that those are writes anyway). These accesses can subtract encodeButterflyHeader(notTTLTID, true) from the butterfly before accessing it, and then they must perform an additional load when reading from the butterfly. The extra load is necessary because of the segmented object model: the butterfly pointer points at a spine that we can use to find the fragment that contains the value we’re interested in. This is somewhat more than one extra cycle of overhead, since it introduces a load-load dependency.

    These optimizations leave an unresolved issue: transitions. Transitions now require acquiring and releasing a lock. We have to do this anytime we add any property. In the next section, we show how to solve this problem using watchpoints. Then we describe how to implement transitions that need to create a segmented butterfly out of a flat one.

    Watchpoint Optimizations

    Transitions are difficult to optimize. Every transition, including those that see TID = current, need to acquire the object’s internal lock to ensure that they set the butterfly, adjust the object’s type header, and store the new value of the property all in one atomic step. Luckily, we can dramatically improve the performance of transitions by using our engine’s structure watchpointing infrastructure.

    Each object has a structure. Many objects will share the same structure. Most inline cache optimizations begin with a check to see if the object’s structure matches the inline cache’s expectations. This means that when an inline cache is compiled, it has a pointer to the Structure object in hand. Each structure can have any number of watchpoint sets in it. A watchpoint set is simply a boolean field (starts valid, becomes invalid) and a set of watchpoints. When the set is fired (the field goes from valid to invalid), all watchpoints are invoked. We can add two watchpoint sets to Structure:

    • transitionThreadLocal. This remains valid so long as all objects that have this structure have TID != notTTLTID.
    • writeThreadLocal. This remains valid so long as all objects that have this structure have SW = false.

    This enables the following optimizations on top of the inline cache optimizations described above:

    • Transitions with TID = current and SW = false can proceed as they do in our existing engine so long as the structure’s transitionThreadLocal and writeThreadLocal watchpoint sets are both still valid. This means not doing any extra locking or even CAS when transitioning the object. This works even if other threads are concurrently reading from the object. This works even when building up an object that eventually gets read and written to from other threads, since in that case the writeThreadLocal watchpoint set only fires on the structure that is the target of the final transition used to build the object. The last transition can proceed without locking because the watchpoint sets of the source of the transition are still valid.
    • Any checks for TID != notTTLTID can be elided if the structure’s transitionThreadLocal watchpoint set is still valid and a watchpoint is installed.
    • Any checks for SW == false can be elided if the structure’s writeThreadLocal watchpoint set is still valid and a watchpoint is installed.

    The fact that we can elide TID != notTTLTID and SW == false checks means that reads and writes to those objects don’t actually have to check anything; they just need to mask off the high bits of the butterfly.

    Most importantly, this means that transitions that happen on the same thread that allocated the object don’t need any locking so long as the structures involved have valid transitionThreadLocal and writeThreadLocal watchpoint sets. Structures are dynamically inferred by our engine so as to have a close relationship to the code that creates those objects. Hence, if you write a constructor that adds a bunch of fields to this but does not escape this, then the structures corresponding to the chain of transitions that occurred in the constructor will all have a valid transitionThreadLocal and writeThreadLocal watchpoint sets. To make sure that the object continues to have a flat butterfly, you need to either never dyamically add properties to the object, or never write to the object on any thread other than the one that constructed it. Objects that play by these rules will experience almost no concurrency overhead, since property accesses will have at most one extra instruction (a mask) on the fast path.

    Watchpoints, and the operations that cause them to fire, will execute under safepoint: if we ever perform some operation that finds that it has to invalidate a watchpoint, it will do the operation while all other threads are stopped as if for a garbage collection. This means that if some optimized code is performing non-atomic transitions involving some structures, and some other thread attempts to write or transition an object that uses any of those structures, then it will not actually perform the write until that optimized code reaches a safepoint and gets invalidated. Most of the time, the watchpoint sets will tell us that they have been invalidated even before the optimizing JIT compilers try to install any watchpoints. We expect few watchpoint invalidations in steady state.

    To summarize, if our optimizer is able to guess which object properties you will add to an object at the time of allocation, then the cost model of your object accesses does not change at all, since inline properties get concurrency for free. If you do have out-of-line properties, then they will perform almost exactly as they do now (occasionally, an extra arithmetic instruction will be involved in computing the butterfly access) so long as either the object is only written to by the thread that created it (and read by anyone), or no new properties are added to the object after creation (in which case it can be read and written by anyone). If you break this pattern, then transitions will become about 7x more expensive and all other object accesses will become 2x more expensive. This slow-down will be extremely surgical: only those property accesses that touch segmented butterflies will experience the slow-down. This system is designed to let you dynamically and concurrently add stuff to your objects, and the hope is that if you do so in moderation, you won’t see much of a change in performance.

    Arrays

    Array element accesses will benefit from TTL similarly to the way that named property accesses do:

    • Accesses to TTL arrays will be about as fast as they are now.
    • Accesses to non-TTL arrays will require one extra indirection.

    We handle array transitions a bit specially. Many array transitions in JavaScriptCore already use locking because of their need to avoid races with the garbage collector. Adding locking to the remaining array transitions may cause performance issues, so this section considers an alternative.

    Resizing an array in response to an out-of-bounds store or something like array.push is the most common kind of array transition. Fortunately, this transition does not change anything in the type header of the object — it only changes the butterfly pointer. Whether or not the butterfly has array elements is reflected in the structure. Therefore, we can just use CAS on the butterfly pointer, and then have a rule that any changes to butterfly pointers of objects that have array elements requires CAS even if the object lock is already held. Because array structures’ transitionThreadLocal and writeThreadLocal watchpoints are unlikely to be intact (any shared array use will invalidate them, since arrays share structures), we expect that even transitions on TTL arrays will have to use CAS in the common case. This butterfly pointer CAS is sufficient to ensure that a simultaneous attempt to make the array not TTL won’t get confused by our resize operation.

    One CAS for array resizing is probably cheap enough to be practical. The CAS is likely cheap relative to the current costs of resizing, which involves allocation, copying data, and initializing the newly allocated memory.

    Objects that have both named properties and array elements will now have to use both locking and CAS on some of the transitions involving named properties. Fortunately, objects that have both array elements and named properties are sufficiently uncommon that we can probably get away with increasing their named property transition cost a bit.

    Quickly Transitioning From Flat To Segmented

    Turning flat butterflies into segmented ones requires a special kind of transition. Fortunartely, this transition is cheap. Butterfly fragments contain only data. They look just like fragments (fixed-size slices) of the payload of a flat butterfly. Therefore, we can transition a flat butterfly to a segmented one by allocating a spine and pointing its fragment pointers at the original flat butterfly.

    Any read or write to the flat butterfly while the butterfly is being transitioned to segmented will seem to users of the segmented butterfly to have happened to the fragments. In other words, although some threads may mistakenly think that the butterfly is still flat, their accesses to that butterfly will still be sound even after the butterfly is already segmented.

    Making this work right requires making sure that the segmented butterfly’s fragments share the same memory layout as the flat butterfly that they were converted from. For this reason, the first array fragment contains the public length and the old vector length; it will remember the vector length that the flat butterfly used forever, and the real vector length will be in the segmented butterfly’s spine. This ensures that if there is a race between a flat butterfly array access and a flat-to-segmented transition, then the flat butterfly access will correctly know the flat butterfly’s size because its vector length will not change. To line up the object models, we also store out-of-line properties in reverse order in the out-of-line fragments, to match what flat butterflies do.

    This works so long as the flat butterfly accesses loaded their butterfly pointer before the transition occured. If they load it later, then their TID check will fail, probably in the form of a page fault on an access to the butterfly.

    Deletion and Dictionary Lookups

    JavaScriptCore tries to make objects share structures whenever possible. This relies on two properties of structures:

    • Structures are immutable.
    • When a new structure is needed, we generally hash cons it.

    This is a great optimization if it indeed causes objects to reuse structures. But some objects will have a unique structure no matter what the VM tries to do about it. JavaScriptCore tries to detect when this happens, and puts the object in dictionary mode. In dictionary mode, the structure has a 1:1 mapping to the object. Also, the structure becomes mutable. Adding and removing properties means editing the structure and the object in tandem.

    Deletion is closely related to dictionary mode, since deletion will immediately put the object in dictionary mode.

    It’s already the case that mutations to a dictionary require holding the structure’s lock. This is necessary to support concurrent JIT and concurrent GC.

    To support concurrent JS, we only need to make these changes:

    1. Reading from a dictionary requires holding the structure’s lock, in case some other thread is changing the dictionary.
    2. Properties added before the object entered dictionary mode must be treated specially by deletion.

    We are not worried about the performance hit of grabbing a lock for all reads of a dictionary. It’s already relatively expensive to read a dictionary.

    The existing facilities for safely transitioning objects will naturally support transitioning to dictionary mode. Usually, dictionary transitions don’t involve deleting properties. They happen when we detect that the program is adding so many properties to the object that it’s probably going to perform better as a dictionary. In that case, the fact that some other thread may be in the middle of accessing this object without holding any locks does not matter. For non-dictionary objects we require that only transitions take the lock. Reads and writes involve separate steps for checking the object’s type, loading the butterfly, and then accessing the butterfly. But if none of the properties that were added before the dictionary transition get deleted, then it’s fine for some other thread to race when accessing those old properties. We will call this the phenomenon of tardy accesses. Even though those tardy accesses don’t do any locking, they are correct for the same reasons that they are correct before the object becomes a dictionary. That problem is up to the butterfly object model, which will be either flat or segmented depending on whether the object is still TTL. Dictionary mode operates orthogonally to TTL inference and butterflies.

    But if any of the properties added before the dictionary transition get deleted, then we have to handle this deletion specially. Normally, deletions cause the deleted slots to become reusable. We cannot do this here, because then a tardy read to some deleted property f might end up reading the value of some newly added property g. Or, a tardy write to some deleted property f might end up overwriting the value of some newly added property g. We can prevent either of these bad outcomes by simply not reusing the space freed up by deleted properties, if those properties had been added before the dictionary transition.

    This does not lead to unbounded memory usage. When the GC does its safepoint, it already knows that all memory accesses have completed. Therefore, the simplest implementation is to have GC change the state of those deleted properties when it visits the object. Once the GC flags those property slots during a safepoint, future property additions can reuse those slots.

    Inline Caches

    Once we enable concurrency, recompiling an inline cache becomes harder because you need to be careful when changing code that may be currently executing on another CPU. We plan to have a tiered defense against this problem: we will infer the thread-locality of code to use the same inline caches as we do now as much as possible, we will buffer inline cache changes whenever it’s safe to do so, and finally we will rely on safepoints if an inline cache needs to be reset eagerly.

    We expect that in many programs, inline caches will reach steady state before the code ever executes on more than one thread. Hence, we plan to have each block of code track its thread-locality. So long as it has only ever executed on one thread, it will remember this and check for it on entry. So long as this is true, any inline caches within that code can be modified without any extra synchronization. We can track thread-locality on as fine-grain a level as we like; for example it can even be per-basic-block. It’s probably most natural if we use JavaScriptCore’s notion of CodeBlock as the granularity; this roughly corresponds to functions in the source code.

    Once the thread-locality of code is broken, we can switch to buffering inline cache changes. Our PolymorphicAccess inline cache infrastructure already buffers changes because that’s most efficient even if we don’t have to do expensive synchronization. For inline caches that may be executing globally, we can globally buffer all changes. For example, the VM can perform once-per-millisecond safepoints to flush changes to all global inline caches.

    Sometimes, we need to make an immediate change to an inline cache. When this happens, we will rely on our ability to safepoint the system — i.e. to stop all threads at a point where we can account for each thread’s state. This is not a fast operation when there are many threads. Java virtual machines already have to do something like this for class hierarchy invalidation and biased locking. By design, these eager invalidations are unlikely. We only perform optimizations that can lead to eager invalidations if we have profiling data that suggests that it would be unlikely.

    Local Optimizer Lock

    So far, this algorithm relies on being able to sneak 16 bits of information into the high bits of the butterfly pointer. Some hardware will not allow us to do this. For example, fewer than 16 high pointer bits may be used for the all-zero check in virtual memory. If the system only allows for 8 checked high bits, then we will only be able to support 127 threads. Concurrent JavaScript would probably still be useful even if it had a hard 127 thread limit, but this would be an unusually low limit to impose at the language level. This section shows how to overcome this limit.

    If the object model can only handle thread-locality inference for 127 threads, then we can either choose to have the 127th thread get no thread-locality inference or we can try to map more than one logical thread onto the same thread identifier. Threads mapped to the same TID won’t be able to execute concurrently to each other. To do this, we can borrow the idea of the GIL (global interpreter lock) from Python. The CPython implementation only allows 1 native thread to interpreting Python code at a time. It achieves this by having a lock (the so-called GIL) that protects the interpreter. The lock is released and reacquired periodically, which gives the appearance of concurrency. Since we can also release the lock around any potentially-blocking operations, we can even avoid deadlocks that arise from insufficient concurrency. We can apply this technique here: if we are limited to 127 threads, then we can have 127 locks protecting JS execution. So long as there are 127 or fewer threads, this lock will not do anything; anytime we try to release it, we will do nothing because the lock will tell us that nobody is waiting to acquire it. “Releasing and reacquiring” the lock will really be a cheap load and branch to verify that there is no need to release it.

    This lock will be local to a thread pool rather than global to the whole engine, and it will protect all of our optimized paths rather than just protecting the interpreter. Hence the name: local optimizer lock, or LOL for short.

    Thread-Unsafe Objects

    DOM objects behave like JavaScript objects, but are actually a proxy for complicated logic implemented in C++. That logic is usually not thread-safe. The native code that supports the DOM transitively uses many native APIs that are meant to only be used from the main thread. It would take a lot of work to make the DOM completely thread-safe. Our strawman proposal only requires making the DOM global object capable of handling lookups to self properties, which we need to allow threads to access global JavaScript properties like Object and Thread.

    In WebKit, variable resolution and self property resolution on the JSDOMWindow largely follows a pattern of relying on existing JS property lookup mechanisms. It uses exotic behavior when the window has a null frame. We already support installing a watchpoint on the non-nullness of frame. Hence, we can support fast concurrent accesses to properties of JSDOMWindow while honoring the frame special case by having threads use the existing watchpoint set. This implies that some of the JSDOMWindow slow paths will need locking, but that’s probably acceptable since the majority of global object accesses are inline cached.

    Native apps that want to dip their toes into concurrent JS may also want to restrict sharing for some of their classes. The thread-affinity check on accesses to objects will need to be implemented in the VM itself to give our compilers the ability to optimize it away. This means that it’s possible to expose the functionality to C/Objective-C API clients.

    Summary

    We think that we can make it possible to execute JavaScript concurrently in WebKit while providing good enough performance that developers would enjoy using this feature. At the heart of this technique is the combination of segmented butterflies, transition thread locality inference, and lots of cheap per-object locks. So long as programs obey certain behaviors, they should experience minuscule overheads: property accesses will cost about as much as they do today and objects will not require any extra memory. If some objects decide that they don’t want to play by our rules, they will get slightly higher overheads.

    Related Work

    Segmented butterflies are a straightforward combination of the array object model in the Schism garbage collector and the butterfly object model that we have used for a long time in JavaScriptCore.

    Transition-thread-locality inference is inspired by work on biased locking. As in the HotSpot biased locking scheme, we use types to reason about whether we have a guarantee of thread locality. Unlike that scheme, we don’t rely on deoptimization to break a thread-object relationship. Our primary mechanism of informing other threads that an object is no longer transition-thread-local is to have different tag bits in the butterfly pointer.

    The combination of segmented butterflies, transition-thread-locality inference, and the ability of both schemes to fall back on per-object locking when things get weird is not something that we have seen before. Most object-oriented systems that allow concurrency do it either by having an object model that naturally avoids expensive-to-resolve races, like in Java, or using some mechanisms to restrict the amount of concurrency in the language.

    For example, CPython uses a global interpreter lock (GIL) to ensure that the interpreter never races with itself. This is a powerful technique that captures some of what concurrency is about: once I/O or other kinds of blocking happen, you want your other threads to be able to do some useful work in the meantime. The GIL allows this, so it makes threads useful to a large class of applications. Unfortunately, it doesn’t allow programs to exploit parallelism. The best feature of the GIL is that it is easy to implement. For example, it could be used to implement our proposed thread semantics in any JS engine. The scheme in this post is all about full concurrency optimized for 64-bit platforms.

    An effort called the Gilectomy is underway to remove CPython’s GIL and replace it with fine-grained locking and clever atomic algorithms. The Gilectomy is not yet as fast as stock CPython; both single-thread and multi-thread programs run significantly slower in the Gilectomy. The performance problems appear to be related to locking in the allocator (we plan to use thread-local allocation buffers) and in the reference counter (we don’t have reference counting). The Gilectomy does not remove locking from accesses to objects. Like JavaScript’s objects, Python’s objects are dictionaries that can resize dynamically. Most of our scheme is about how to make accesses to those objects fast even when multiple threads are reading and writing to the same object.

    PyPy also has a GIL removal effort underway, but they haven’t said much about how they plan to handle synchronizing object accesses aside from using locks. We will also have locks, but we also came up with optimizations to avoid locking in most cases.

    Another approach was the title locking scheme in SpiderMonkey. It has since been removed. That scheme also involved per-object locks, but did not have our optimizations for avoiding locking in most cases.

    Daloze, Marr, Bonetta, and Mossenbock propose a scheme for concurrency in Truffle, a runtime that supports many dynamic languages including JavaScript. That scheme requires objects that are shared to use synchronization for all writes. Sharing is detected by a write barrier. When a thread-local object is stored into a shared object, the runtime will traverse objects transitively reachable from the escaping object. All of those objects are marked shared so that future writes to those objects use synchronization. Our scheme does not require synchronization on shared writes, except when those writes are transitions. Our scheme does not require traversing object graphs; transition thread locality inference is on a per-object basis. A TTL object may point to a non-TTL object or vice-versa.

    Cohen, Tal, and Petrank recently introduced the layout lock, which allows fast reads and writes to objects that may have their layout changed. Readers need an extra load (which has to be fenced or dependent), writers have to acquire a read lock (which can be as cheap as a pair of fenced loads and a branch), and transitions have to acquire a write lock and do some extra book-keeping. We suspect that this has a similar cost model to segmented butterflies, except for writes. Segmented butterflies only require an extra dependent load for writes, which is a bit cheaper than acquiring a read lock, which requires two loads fenced around a store. Fencing loads around a store is inconvenient; for example forcing a store to happen before a load on x86 requires an xchg instruction for the store, which is more expensive than just doing a mov. On ARM it requires using acq/rel variants for the loads and stores. On the other hand, the extra dependent load for writing to a segmented butterfly requires no extra fencing on either x86 or ARM. Transitions and reads are probably equally fast with segmented butterflies and layout locks, but writes matter a lot to us. Writes happen often enough that segmented butterflies are likely to be noticeably faster than layout locks for the JavaScript object model. On the other hand, the method of segmentation is not easy to reproduce in many different kinds of data structures. Since it is more general, the layout lock could be useful for more complex data JSC data structures like SparseArrayValueMap and Map/WeakMap/Set. Those data structures may be too complicated for segmentation, but not too complicated for the layout lock. Like segmented butterflies, layout lock can be combined with transition thread locality inference to avoid doing any of the locking until it’s needed to protect racy transitions.

    Conclusion

    This post shows how WebKit’s JavaScript implementation can be modified to support threads. Our scheme allows for all JavaScript objects to be shared. Our scheme avoids locking on fast paths, like the fast paths for property accesses. We expect it to be possible to implement this scheme with low overheads. Serial code will experience no overhead, and concurrent code will only experience big overheads if it adds properties to an object that is being written to by multiple threads.

    The next step for this wild thought experiment is to attempt to implement it and see if it works. We will be tracking progress under bug 174276.

    Update: The original version of this post did not cite Daloze et al’s OOPSLA ’16 paper on concurrency support in Truffle. We have updated the post to include a comparison between our scheme and theirs.

    By Filip Pizlo at August 30, 2017 05:00 PM

    August 29, 2017

    Frédéric Wang: The AMP Project and Igalia working together to improve WebKit and the Web Platform

    Igalia WebKit

    TL;DR

    The AMP Project and Igalia have recently been collaborating to improve WebKit’s implementation of the Web platform. Both teams are committed to make the Web better and we expect that all developers and users will benefit from this effort. In this blog post, we review some of the bug fixes and features currently being considered:

    • Frame sandboxing: Implementing sandbox values to allow trusted third-party resources to open unsandboxed popups or restrict unsafe operations of malicious ones.

    • Frame scrolling on iOS: Trying to move to a more standard and interoperable approach via iframe elements; addressing miscellaneous issues with scrollable nodes (e.g. visual artifacts while scrolling, view not scrolled when using “Find Text”…).

    • Root scroller: Finding a solution to the old interoperability issue about how to scroll the main frame; considering a new rootScroller API.

    Some demo pages for frame sandboxing and scrolling are also available if you wish to test features discussed in this blog post.

    Introduction

    AMP is an open-source project to enable websites and ads that are consistently fast, beautiful and high-performing across devices and distribution platforms. Several interoperability bugs and missing features in WebKit have caused problems to AMP users and to Web developers in general. Although it is possible to add platform-specific workarounds to AMP, the best way to help the Web Platform community is to directly fix these issues in WebKit, so that everybody can benefit from these improvements.

    Igalia is a consulting company with a team dedicated to Web Platform developments in all open-source Web Engines (Chromium, WebKit, Servo, Gecko) working in the implementation and standardization of miscellaneous technologies (CSS Grid/flexbox, ECMAScript, WebRTC, WebVR, ARIA, MathML, etc). Given this expertise, the AMP Project sponsored Igalia so that they can lead these developments in WebKit. It is worth noting that this project aligns with the Web Predictability effort supported by both Google and Igalia, which aims at making the Web more predictable for developers. In particular, the following aspects are considered:

    • Interoperability: Effort is made to write Web Platform Tests (WPT), to follow Web standards and ensure consistent behaviors between web engines or operating systems.
    • Compatibility: Changes are carefully analyzed using telemetry techniques or user feedback in order to avoid breaking compatibility with previous versions of WebKit.
    • Reducing footguns: Removals of non-standard features (e.g. CSS vendor prefixes) are attempted while new features are carefully introduced.

    Below we provide further description of the WebKit improvements, showing concretely how the above principles are followed.

    Frame sandboxing

    A sandbox attribute can be specified on the iframe element in order to enable a set of restrictions on any content it hosts. These conditions can be relaxed by specifying a list of values such as allow-scripts (to allow javascript execution in the frame) or allow-popups (to allow the frame to open popups). By default, the same restrictions apply to a popup opened by a sandboxed frame.

    iframe sandboxing
    Figure 1: Example of sandboxed frames (Can they navigate their top frame or open popups? Are such popups also sandboxed?)

    However, sometimes this behavior is not wanted. Consider for example the case of an advertisement inside a sandboxed frame. If a popup is opened from this frame then it is likely that a non-sandboxed context is desired on the landing page. In order to handle this use case, a new allow-popups-to-escape-sandbox value has been introduced. The value is now supported in Safari Technology Preview 34.

    While performing that work, it was noticed that some WPT tests for the sandbox attribute were still failing. It turns out that WebKit does not really follow the rules to allow navigation. More specifically, navigating a top context is never allowed when such context corresponds to an opened popup. We have made some changes to WebKit so that it behaves more closely to the specification. This is integrated into Safari Technology Preview 35 and you can for example try this W3C test. Note that this test requires to change preferences to allow popups.

    It is worth noting that web engines may slightly depart from the specification regarding the previously mentioned rules. In particular, WebKit checks a same-origin condition to be sure that one frame is allowed to navigate another one. WebKit always has contained a special case to ignore this condition when a sandboxed frame with the allow-top-navigation flag tries and navigate its top frame. This feature, sometimes known as “frame busting,” has been used by third-party resources to perform malicious auto-redirecting. As a consequence, Chromium developers proposed to restrict frame busting to the case where the navigation is triggered by a user gesture.

    According to Chromium’s telemetry frame busting without a user gesture is very rare. But when experimenting with the behavior change of allow-top-navigation several regressions were reported. Hence it was instead decided to introduce the allow-top-navigation-by-user-activation flag in order to provide this improved safety context while still preserving backward compatibility. We implemented this feature in WebKit and it is now available in Safari Technology Preview 37.

    Finally, another proposed security improvement is to use an allow-modals flag to explicitly allow sandboxed frames to display modal dialogs (with alert, prompt, etc). That is, the default behavior for sandboxed frames will be to forbid such modal dialogs. Again, such a change of behavior must be done with care. Experiments in Chromium showed that the usage of modal dialogs in sandboxed frames is very low and no users complained. Hence we implemented that behavior in WebKit and the feature should arrive in Safari Technology Preview soon.

    Check out the frame sandboxing demos if if you want to test the new allow-popup-to-escape-sandbox, allow-top-navigation-without-user-activation and allow-modals flags.

    Frame scrolling on iOS

    Apple’s UI choice was to (almost) always “flatten” (expand) frames so that users do not require to scroll them. The rationale for this is that it avoids to be trapped into hierarchy of nested frames. Changing that behavior is likely to cause a big backward compatibility issue on iOS so for now we proposed a less radical solution: Add a heuristic to support the case of “fullscreen” iframes used by the AMP Project. Note that such exceptions already exist in WebKit, e.g. to avoid making offscreen content visible.

    We thus added the following heuristic into WebKit Nightly: do not flatten out-of-flow iframes (e.g. position: absolute) that have viewport units (e.g. vw and vh). This includes the case of the “fullscreen” iframe previously mentioned. For now it is still under a developer flag so that WebKit developers can control when they want to enable it. Of course, if this is successful we might consider more advanced heuristics.

    The fact that frames are never scrollable in iOS is an obvious interoperability issue. As a workaround, it is possible to emulate such “scrollable nodes” behavior using overflow: scroll nodes with the -webkit-overflow-scrolling: touch property set. This is not really ideal for our Web Predictability goal as we would like to get rid of browser vendor prefixes. Also, in practice such workarounds lead to even more problems in AMP as explained in these blog posts. That’s why implementing scrolling of frames is one of the main goals of this project and significant steps have already been made in that direction.

    Class Hierarchy
    Figure 2: C++ classes involved in frame scrolling

    The (relatively complex) class hierarchy involved in frame scrolling is summarized in Figure 2. The frame flattening heuristic mentioned above is handled in the WebCore::RenderIFrame class (in purple). The WebCore::ScrollingTreeFrameScrollingNodeIOS and WebCore::ScrollingTreeOverflowScrollingNodeIOS classes from the scrolling tree (in blue) are used to scroll, respectively, the main frame and overflow nodes on iOS. Scrolling of non-main frames will obviously have some code to share with the former, but it will also have some parts in common with the latter. For example, passing an extra UIScrollView layer is needed instead of relying on the one contained in the WKWebView of the main frame. An important step is thus to introduce a special class for scrolling inner frames that would share some logic from the two other classes and some refactoring to ensure optimal code reuse. Similar refactoring has been done for scrolling node states (in red) to move the scrolling layer parameter into WebCore::ScrollingStateNode instead of having separate members for WebCore::ScrollingStateOverflowScrollingNode and WebCore::ScrollingStateFrameScrollingNode.

    The scrolling coordinator classes (in green) are also important, for example to handle hit testing. At the moment, this is not really implemented for overflow nodes but it might be important to have it for scrollable frames. Again, one sees that some logic is shared for asynchronous scrolling on macOS (WebCore::ScrollingCoordinatorMac) and iOS (WebCore::ScrollingCoordinatorIOS) in ancestor classes. Indeed, our effort to make frames scrollable on iOS is also opening the possibility of asynchronous scrolling of frames on macOS, something that is currently not implemented.

    Class Hierarchy
    Figure 4: Video of this demo page on WebKit iOS with experimental patches to make frame scrollables (2017/07/10)

    Finally, some more work is necessary in the render classes (purple) to ensure that the layer hierarchies are correctly built. Patches have been uploaded and you can view the result on the video of Figure 4. Notice that this work has not been reviewed yet and there are known bugs, for example with overlapping elements (hit testing not implemented) or position: fixed elements.

    Various other scrolling bugs were reported, analyzed and sometimes fixed by Apple. The switch from overflow nodes to scrollable iframes is unlikely to address them. For example, the “Find Text” operation in iOS has advanced features done by the UI process (highlight, smart magnification) but the scrolling operation needed only works for the main frame. It looks like this could be fixed by unifying a bit the scrolling code path with macOS. There are also several jump and flickering bugs with position: fixed nodes. Finally, Apple fixed inconsistent scrolling inertia used for the main frame and the one used for inner scrollable nodes by making the former the same as the latter.

    Root Scroller

    The CSSOM View specification extends the DOM element with some scrolling properties. That specification indicates that the element to consider to scroll the main view is document.body in quirks mode while it is document.documentElement in no-quirks mode. This is the behavior that has always been followed by browsers like Firefox or Interner Explorer. However, WebKit-based browsers always treat document.body as the root scroller. This interoperability issue has been a big problem for web developers. One convenient workaround was to introduce the document.scrollingElement which returns the element to use for scrolling the main view (document.body or document.documentElement) and was recently implemented in WebKit. Use this test page to verify whether your browser supports the document.scrollingElement property and which DOM element is used to scroll the main view in no-quirks mode.

    Nevertheless, this does not solve the issue with existing web pages. Chromium’s Web Platform Predictability team has made a huge communication effort with Web authors and developers which has drastically reduced the use of document.body in no-quirks mode. For instance, Chromium’s telemetry on Figure 3 indicates that the percentage of document.body.scrollTop in no-quirks pages has gone from 18% down to 0.0003% during the past three years. Hence the Chromium team is now considering shipping the standard behavior.

    UseCounter for ScrollTopBodyNotQuirksMode
    Figure 3: Use of document.body.scrollTop in no-quirks mode over time (Chromium's UseCounter)

    In WebKit, the issue has been known for a long time and an old attempt to fix it was reverted for causing regressions. For now, we imported the CSSOM View tests and just marked the one related to the scrolling element as failing. An analysis of the situation has been left on WebKit’s bug; Depending on how things evolve on Chromium’s side we could consider the discussion and implementation work in WebKit.

    Related to that work, a new API is being proposed to set the root scroller to an arbitrary scrolling element, giving more flexibility to authors of Web applications. Today, this is unfortunately not possible without losing some of the special features of the main view (e.g. on iOS, Safari’s URL bar is hidden when scrolling the main view to maximize the screen space). Such API is currently being experimented in Chromium and we plan to investigate whether this can be implemented in WebKit too.

    Conclusion

    In the past months, The AMP Project and Igalia have worked on analyzing some interoperability issue and fixing them in WebKit. Many improvements for frame sandboxing are going to be available soon. Significant progress has also been made for frame scrolling on iOS and collaboration continues with Apple reviewers to ensure that the work will be integrated in future versions of WebKit. Improvements to “root scrolling” are also being considered although they are pending on the evolution of the issues on Chromium’s side. All these efforts are expected to be useful for WebKit users and the Web platform in general.

    Igalia Logo
    AMP Logo

    Last but not least, I would like to thank Apple engineers Simon Fraser, Chris Dumez, and Youenn Fablet for their reviews and help, as well as Google and the AMP team for supporting that project.

    August 29, 2017 10:00 PM

    August 23, 2017

    Release Notes for Safari Technology Preview 38

    Surfin’ Safari

    Safari Technology Preview Release 38 is now available for download for macOS Sierra and betas of macOS High Sierra. If you already have Safari Technology Preview installed, you can update from the Mac App Store’s Updates tab. This release covers WebKit revisions 220128-220795.

    Beacon API

    • Enabled the Beacon API by default as an experimental feature (r220553)
    • Added support for CORS-preflighting (r220442)
    • Added support for CORS-preflighting on redirects (r220497)
    • Added support for connect-src CSP checks on redirects (r220549)
    • Updated sendBeacon() to rely on FetchBody instead of the whole FetchRequest (r220366)
    • Changed to use “application/octet-stream” content-type for payloads of ArrayBuffer and ArrayBufferView types (r220779)

    Fetch API

    • Added support for Request keepalive getter (r220244)
    • Changed Response to keep all ResourceResponse information (r220320)
    • Implemented quota limitation for keepalive Fetch requests (r220751)

    Web Payments

    • Enabled Payment Requests as an experimental feature (r220787)

    CSS

    • Added support for parsing of the font-display property (r220725)
    • Implement caret-color support (r220706, r220714)
    • Added a fast path for rotate() and rotateZ() transform parsing (r220382)
    • Fixed parsing of <meta http-equiv=refresh> to allow time starting with a ‘.’ without a leading 0 (r220252)
    • Fixed a hit testing issue occurring when an SVG rect element with a non-default stroke style applied (r220717)

    Web API

    • Added support for considering file extensions in the accept attribute of HTML file input elements (r220135)
    • Improved support for referrer policies (r220208)
    • Fixed the Promise resolve and reject function to have a length of 1 (r220324)
    • Fixed an early error on an ANY operator before new.target (r220481)
    • Fixed removing an empty <li> element when inside a table cell (r220398)
    • Fixed XHR to only fire an abort event if the cancellation was requested by the client (r220731)

    Media

    • Fixed deleting the old subtitle track on src attribute change event (r220472)

    Apple Pay

    • Added support for phonetic contact names (r220718)

    Web Inspector

    • Added Canvas path preview when viewing a recording (r220370)
    • Changed clicking on an autocomplete suggestion to apply it, not dismiss it (r220614)
    • Removed text-shadow and gradient backgrounds (r220710)
    • Updated the filter icon in the styles sidebar (r220609)

    WebDriver

    • Added support for interacting with <option> and <select> elements using the element click command (r220740)
    • Added support for uploading files via <input type=file> (r219874, r220115, r220135, r220147, r220222)
    • Fixed a timeout when a JavaScript alert is shown in onload handler (r220741)
    • Implemented “normal” and “eager” page load strategies from the W3C specification (r220317)
    • Updated code to use in-view center points for clicks and other automation logic (r220314)

    By Jon Davis at August 23, 2017 06:00 PM