1
0
Fork 0
mirror of https://gitlab.com/news-flash/article_scraper.git synced 2025-07-07 16:15:32 +02:00

6 more tests

This commit is contained in:
Jan Lukas Gernert 2023-04-01 18:22:42 +02:00
parent cc6ff6d7e2
commit 15eec43ad9
13 changed files with 8405 additions and 0 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,93 @@
<article><div id="readability-page-1">
<ul>
<li>
<a href="#assess-how-deep-is-your-content">Assess How Deep Is Your Content</a>
</li>
<li>
<a href="#rewrite-with-content-depth-in-mind">Rewrite With Content Depth In Mind</a>
</li>
<li>
<a href="#yes-content-depth-and-breadth-overlap">Yes, Content Depth and Breadth Overlap</a>
</li>
<li>
<a href="#depth-of-content--quality--frequency">Depth of Content = Quality + Frequency</a>
</li>
</ul>
<p>
<strong>Content depth</strong> is an arbitrary score or rating of how comprehensive the coverage of a specific topic is within a piece of content. <strong>Content breadth</strong> is an arbitrary grading of how many related subjects are you covering within your content.
</p>
<p>
And this distinction is important to make and establish from the beginning. Effective <a href="https://topicseed.com/blog/what-is-topical-authority" target="_blank" rel="nofollow noopener noreferrer"><strong>topical authority</strong></a> can only be gained when you use both content depth and content breadth in your overall content strategy for rapid search engine optimization gains. However, because most content writers prefer to write a little bit about many things rather than write a lot about one thing, you end up with a too little substance spread very thin.
</p>
<p>
Content depth should be the urgent priority for your content marketing strategy, and clearly defined in your <a href="http://fakehost/blog/content-briefs" target="_blank">content briefs</a>. Start by dominating your own core topics, before venturing across the pond and write about linked subject matters. Otherwise, you are the opposite of an authority as the definition states that an authority is <em>“a person with extensive or specialized knowledge about a subject; an expert”.</em> Lastly, do not mistake article depth vs. article length: a blog posts extreme wordcount has nothing to do with its content depth.
</p>
<h2 id="assess-how-deep-is-your-content">
<a href="#assess-how-deep-is-your-content" aria-label="assess how deep is your content permalink"></a>Assess How Deep Is Your Content
</h2>
<p>
The first task on your list, right now, is to shortlist your core topics. What are you trying to be an expert on? Then, go through each one of your pieces of content and understand how well each blog post is covering its focus topic(s). Not how many times specific keywords appear, or how well the article is outlined and structured.
</p>
<p>
Put yourself in the shoes of an ignorant reader who seeks information. Read your article. <strong>And ask yourself how in-depth was the content you have written?</strong> I know the excuse you will come up with: this was written for beginners, therefore, it shouldnt be too in-depth. And you are correct. Not every blog post is about absolute content depth otherwise we would only write one 10,000-word-long article, once and for all. But then, how well your beginner-level content pointing to your expert-level content?
</p>
<p>
In other words, each article should reach an incredible level of content depth for its expertise level. And then, provide further reading <em>(i.e. links)</em> to gain more knowledge, and depth. A lot of content editors write a beginners blog post and wait to see it perform well in order to write a more advanced sequel. Wrong. Give all the value so search engines can grade you highly on their authority scale for your core topics. Yes, it is a risk and you may write a dozen of articles on a specific topic that will never really rank at the top of SERPs, but <strong>reaching content depth is the first step towards SEO gains</strong>.
</p>
<p>
Remember that <strong>skyscraper content</strong> and <strong>10x content</strong> are not necessarily the answer. These content writing strategies state that in order to beat another piece of content, you need to write 10x more. Either in quantity with a 10x word count or in quality by putting times more information within your own piece of content. Such articles often become unreadable and discourage visitors from absorbing all the knowledge. The best alternative is the create <a href="https://topicseed.com/blog/how-broad-should-topics-be-for-pillar-pages" target="_blank" rel="nofollow noopener noreferrer">pillar pages</a> centered around core topics, and several articles dealing with each specific section in depth. This is <strong>deep content powered by a <a href="https://topicseed.com/blog/internal-linking-strategies-for-topic-clustering" target="_blank" rel="nofollow noopener noreferrer">smart internal linking strategy</a></strong> and search engines love that in this day and age where attention spans are short! <em>With that being said, avoid writing 600-word articles!</em>
</p>
<h2 id="rewrite-with-content-depth-in-mind">
<a href="#rewrite-with-content-depth-in-mind" aria-label="rewrite with content depth in mind permalink"></a>Rewrite With Content Depth In Mind
</h2>
<p>
Once you know which articles are lacking depth of knowledge and information, it is time to rethink each one. For each article, make a list of what essential pieces of information or data are missing. Then decide where to fit them, and decide whether the article would benefit from a full rewrite or not. As a rule of thumb, if you need to change a third of your article, you may need to rewrite it entirely. Of course, this does not mean erasing all work done prior, but it means starting afresh! Trying to <strong>fit deep content into an existing blog</strong> post gives you constraints so doing it from scratch can actually be easier to fight thin content.
</p>
<p>
As explained above, make sure you do not force yourself to write a much longer article to reach a <a href="https://moz.com/blog/blog-post-length-frequency" target="_blank" rel="nofollow noopener noreferrer">magic word count</a>. And if you do, it has to be natural. In many cases, articles written months or years ago may need some upkeeping: trimming the fat and removing parts that are not bringing much value. Replace these with your newer and deeper content.
</p>
<p>
All content writers know that when you open Google Docs, WordPress, or your text editor of choice, you will inevitably count your focus keywords frequency. Although I understand (yet question) the value of keywords in modern SEO, do not become obsessed with reaching a magic number for your keywords. No reader coming from Google is out there counting how often your keywords are appearing. And search engine algorithms will penalize you for writing for robots, rather than humans.
</p>
<p>
With the massive rise of voice searches, <a href="http://fakehost/blog/featured-snippets-using-questions" target="_blank">users tend to use full questions for their search queries</a>. What used to be <code>top bottled water brands</code> is now <code>OK google, what is the best bottled-water brand in Texas</code>? The point being, <a href="https://topicseed.com/blog/keyword-search-volume-overrated" target="_blank" rel="nofollow noopener noreferrer"><strong>keywords are losing traction</strong></a> to leave space for a more natural language understanding of a blog posts textual content, and meaning.
</p>
<h2 id="yes-content-depth-and-breadth-overlap">
<a href="#yes-content-depth-and-breadth-overlap" aria-label="yes content depth and breadth overlap permalink"></a>Yes, Content Depth and Breadth Overlap
</h2>
<p>
<em>“A topic can be defined as the company it keeps.”</em> A very accurate saying loved by ontologists within the fields of computational linguistics, and information science. In simpler terms, a topic and all the terminology it is encompassing will inevitably overlap with related topics. Which, in turn, will form <a href="https://topicseed.com/blog/topic-clusters-relationships" target="_blank" rel="nofollow noopener noreferrer"><strong>topic clusters</strong></a>.
</p>
<p>
For example, it is obvious that despite being two different topics, <code>digital advertising</code> and <code>content marketing</code> share some common phrases and terms. Inevitably, a website picking one as its core topic will use words in some blog posts that will identify the article as belonging to both topics, with a specific weight for each.
</p>
<p>
A keyword, phrase, or term, is not a prisoner to a single concept at all. This is how algorithms in natural language understanding can understand how two topics are related (e.g. read about <a href="https://en.wikipedia.org/wiki/Topic_model" target="_blank" rel="nofollow noopener noreferrer"><em>topic modeling</em></a>). Each topic has a specific <strong>vocabulary</strong>, a list of words and phrases commonly used in its context, and some of these terms are present in different vocabularies.
</p>
<p>
Therefore, content depth and content breadth are not to be opposed. Content marketers should use both strategies in order to reach ultimate <strong>topical authority</strong> over their choice of subject matters.
</p>
<h2 id="depth-of-content--quality--frequency">
<a href="#depth-of-content--quality--frequency" aria-label="depth of content quality frequency permalink"></a>Depth of Content = Quality + Frequency
</h2>
<p>
Up until recently, long-form blog posts generally were <strong>evergreen articles</strong> that generated a constant stream of organic traffic for a website. This was a lead magnet generation strategy which worked well: hire a writer, include the right keywords, reach over a 5,000-word word count, and hit publish. Then, wait.
</p>
<p>
Nowadays, in-depth content requires more effort over time in order to pay off. Writing a big article, as good as it is, will not get your anywhere near the level of <a href="https://topicseed.com/blog/topical-seo" target="_blank" rel="nofollow noopener noreferrer">topical breadth</a> required by Google to rank you first. Instead, your content marketing plan should be about having:
</p>
<ul>
<li>a <strong>comprehensive pillar page</strong> covering a unique topic, and
</li>
<li>
<strong>narrow-focused children articles</strong> to dig deeper.
</li>
</ul>
<p>
Search engines also look at how often you publish about a specific topic, and when was the last time it was written about. Nobody likes a <a href="https://www.copypress.com/blog/avoiding-blog-graveyard/" target="_blank" rel="nofollow noopener noreferrer">graveyard blog</a>, it just makes the reader lose trust; as if the writer was not good enough, therefore had no traffic, before entirely giving up. Deep content requires a sustained effort on your part to always new find ways to write about a specific subject. Sure, it will be easy at first. But what about five years later? Well, you will still need to hit publish, all about the very same topics you already covered years ago.
</p>
<p>
Tools and platforms such as topicseed are here to <a href="https://topicseed.com/blog/how-to-find-new-blog-post-ideas" target="_blank" rel="nofollow noopener noreferrer">help you find new article ideas</a> pertaining to your core topics within a few clicks and a few minutes. The number of web pages, Wikipedia articles, and pieces of content, our machine-learning algorithms can analyze in seconds would take you months to digest. Our <em>topicgraph</em> finds closely related concepts in order for your domain to <strong>reach topical authority through content depth and content breadth</strong>.
</p>
</div></article>

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,4 @@
<article><div id="readability-page-1">
<h3><a href="http://mcupdate.tumblr.com/post/96439224994/minecraft-18-the-bountiful-update" target="_blank">Minecraft 1.8 - The Bountiful Update</a></h3>
<p>+ Added Granite, Andesite, and Diorite stone blocks, with smooth versions<br>+ Added Slime Block<br>+ Added Iron Trapdoor<br>+ Added Prismarine and Sea Lantern blocks<br>+ Added the Ocean Monument<br>+ Added Red Sandstone<br>+ Added Banners<br>+ Added Armor Stands<br>+ Added Coarse Dirt (dirt where grass wont grow)<br>+ Added Guardian mobs, with item drops<br>+ Added Endermite mob<br>+ Added Rabbits, with item drops<br>+ Added Mutton and Cooked Mutton<br>+ Villagers will harvest crops and plant new ones<br>+ Mossy Cobblestone and Mossy Stone Bricks are now craftable<br>+ Chiseled Stone Bricks are now craftable<br>+ Doors and fences now come in all wood type variants<br>+ Sponge block has regained its water-absorbing ability and becomes wet<br>+ Added a spectator game mode (game mode 3)<br>+ Added one new achievement<br>+ Added “Customized” world type<br>+ Added hidden “Debug Mode” world type<br>+ Worlds can now have a world barrier<br>+ Added @e target selector for Command Blocks<br>+ Added /blockdata command<br>+ Added /clone command<br>+ Added /execute command<br>+ Added /fill command<br>+ Added /particle command<br>+ Added /testforblocks command<br>+ Added /title command<br>+ Added /trigger command<br>+ Added /worldborder command<br>+ Added /stats command<br>+ Containers can be locked in custom maps by using the “Lock” data tag<br>+ Added logAdminCommands, showDeathMessages, reducedDebugInfo, sendCommandFeedback, and randomTickSpeed game rules<br>+ Added three new statistics<br>+ Player skins can now have double layers across the whole model, and left/right arms/legs can be edited independently<br>+ Added a new player model with smaller arms, and a new player skin called Alex?<br>+ Added options for configuring what pieces of the skin that are visible<br>+ Blocks can now have custom visual variations in the resource packs<br>+ Minecraft Realms now has an activity chart, so you can see who has been online<br>+ Minecraft Realms now lets you upload your maps<br>* Difficulty setting is saved per world, and can be locked if wanted<br>* Enchanting has been redone, now costs lapis lazuli in addition to enchantment levels<br>* Villager trading has been rebalanced<br>* Anvil repairing has been rebalanced<br>* Considerable faster client-side performance<br>* Max render distance has been increased to 32 chunks (512 blocks)<br>* Adventure mode now prevents you from destroying blocks, unless your items have the CanDestroy data tag<br>* Resource packs can now also define the shape of blocks and items, and not just their textures<br>* Scoreboards have been given a lot of new features<br>* Tweaked the F3 debug screen<br>* Block ID numbers (such as 1 for stone), are being replaced by ID names (such as minecraft:stone)<br>* Server list has been improved<br>* A few minor changes to village and temple generation<br>* Mob heads for players now show both skin layers<br>* Buttons can now be placed on the ceiling<br>* Lots and lots of other changes<br>* LOTS AND LOTS of other changes<br>- Removed Herobrine<br><br></p>
</div></article>

View file

@ -0,0 +1,793 @@
<!DOCTYPE html>
<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<script>
var __pbpa = true;
</script>
<script>
var translated_warning_string = 'Warning: Never enter your Tumblr password unless \u201chttps://www.tumblr.com/login\u201d\x0ais the address in your web browser.\x0a\x0aYou should also see a green \u201cTumblr, Inc.\u201d identification in the address bar.\x0a\x0aSpammers and other bad guys use fake forms to steal passwords.\x0a\x0aTumblr will never ask you to log in from a user\u2019s blog.\x0a\x0aAre you absolutely sure you want to continue?';
</script>
<script type="text/javascript" language="javascript" src="http://assets.tumblr.com/assets/scripts/pre_tumblelog.js?_v=7f6772238e1748fa255bd191b4985d65"></script>
<!--
Photo Minimal
A Tumblr theme by William Rainbird - http://william.rainbird.me
Tweaked for the Minecraft Launcher by Mojang
-->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Minecraft 1.8 - The Bountiful Update - Minecraft 1.8 - The Bountiful Update - Minecraft Update News</title>
<style type="text/css">
body {
font-family: sans-serif;
background-color: #222222;
background-image: url('http://static.tumblr.com/qfn3sex/ezom7y7iq/bg_main.png');
color: #e0d0d0;
}
a {
color: #aaaaff;
}
hr {
border: 0;
color: #111111;
background-color: #111111;
height: 2px;
}
h3 {
color: #ffffff;
font-size: 16px;
}
img {
border: 0;
margin: 0;
}
.sidebar {
padding: 10px;
vertical-align: top;
}
.alert {
background-color: #aa0000;
color: #ffffff;
font-weight: bold;
padding: 6px 10px;
width: 500px;
}
</style>
<style>
figure {
margin: 0
}
.tmblr-iframe {
position: absolute
}
.tmblr-iframe.hide {
display: none
}
</style>
<link rel="alternate" href="android-app://com.tumblr/tumblr/x-callback-url/blog?blogName=mcupdate%26postID=96439224994" />
<link rel="alternate" href="ios-app://305343404/tumblr/x-callback-url/blog?blogName=mcupdate&amp;postID=96439224994" />
<link rel="alternate" type="application/json+oembed" href="https://www.tumblr.com/oembed/1.0?url=http://mcupdate.tumblr.com/post/96439224994/minecraft-18-the-bountiful-update" title="Minecraft 1.8 - The Bountiful Update
+ Added Granite, Andesite, and Diorite stone blocks, with smooth versions
+ Added Slime Block
+ Added Iron Trapdoor
+ Added Prismarine and Sea Lantern blocks
+ Added the Ocean Monument
+ Added Red Sandstone
+..." />
<script src="http://assets.tumblr.com/assets/scripts/tumblelog_post_message_queue.js?_v=ae06d1ab69efc6f29297bf2b7a4160af"></script>
<link rel="stylesheet" type="text/css" href="http://assets.tumblr.com/fonts/gibson/stylesheet.css?v=3" />
<!-- BEGIN TUMBLR FACEBOOK OPENGRAPH TAGS -->
<!-- If you'd like to specify your own Open Graph tags, define the og:url and og:title tags in your theme's HTML. -->
<!-- Read more: http://ogp.me/ -->
<meta property="fb:app_id" content="48119224995" />
<meta property="og:site_name" content="Minecraft Update News" />
<meta property="og:title" content="Minecraft 1.8 - The Bountiful Update" />
<meta property="og:url" content="http://mcupdate.tumblr.com/post/96439224994/minecraft-18-the-bountiful-update" />
<meta property="og:description" content="+ Added Granite, Andesite, and Diorite stone blocks, with smooth versions
+ Added Slime Block
+ Added Iron Trapdoor
+ Added Prismarine and Sea Lantern blocks
+ Added the Ocean Monument
+ Added Red..." />
<meta property="og:determiner" content="a" />
<meta property="og:type" content="tumblr-feed:entry" />
<meta property="og:image" content="http://assets.tumblr.com/images/og/fb_landscape_share.png" />
<meta property="al:ios:url" content="tumblr://x-callback-url/blog?blogName=mcupdate&amp;postID=96439224994" />
<meta property="al:ios:app_name" content="Tumblr" />
<meta property="al:ios:app_store_id" content="305343404" />
<meta property="al:android:url" content="tumblr://x-callback-url/blog?blogName=mcupdate&amp;postID=96439224994" />
<meta property="al:android:app_name" content="Tumblr" />
<meta property="al:android:package" content="com.tumblr" />
<!-- END TUMBLR FACEBOOK OPENGRAPH TAGS -->
<!-- GOOGLE CAROUSEL -->
<script type="application/ld+json">
{
"@type": "SocialMediaPosting",
"url": "http:\/\/mcupdate.tumblr.com\/post\/96439224994\/minecraft-18-the-bountiful-update",
"mainEntityOfPage": true,
"datePublished": "2014-09-02T08:35:27-04:00",
"author": "mcupdate",
"headline": "Minecraft 1.8 - The Bountiful Update",
"articleBody": "+ Added Granite, Andesite, and Diorite stone blocks, with smooth versions\n+ Added Slime Block\n+ Added Iron Trapdoor\n+ Added Prismarine and Sea Lantern blocks\n+ Added the Ocean Monument\n+ Added Red Sandstone\n+ Added Banners\n+ Added Armor Stands\n+ Added Coarse Dirt (dirt where grass won\u2019t grow)\n+...",
"@context": "http:\/\/schema.org"
}
</script>
<link rel="canonical" href="http://mcupdate.tumblr.com/post/96439224994/minecraft-18-the-bountiful-update" />
<style type="text/css">
.knight-rider-loader {
line-height: 0;
white-space: nowrap;
width: 78px
}
.knight-rider-loader.small {
width: 39px
}
.knight-rider-loader.centered {
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%)
}
.knight-rider-loader.h-centered {
position: absolute;
top: 0;
left: 50%;
-webkit-transform: translateX(-50%);
transform: translateX(-50%)
}
.knight-rider-bar {
display: none;
width: 20px;
height: 20px;
margin: 0 3px;
border-radius: 5px;
opacity: .5;
background-color: #d0d0d0
}
.small&gt;
.knight-rider-bar {
width: 10px;
height: 10px;
margin-left: 2px;
margin-right: 1px;
border-radius: 2px
}
.animate&gt;
.knight-rider-bar {
display: inline-block;
-webkit-animation: knight-rider-oscillate ease-in-out .3s infinite alternate;
animation: knight-rider-oscillate ease-in-out .3s infinite alternate
}
.knight-rider-bar:nth-child(1) {
-webkit-animation-delay: -.2s;
animation-delay: -.2s
}
.knight-rider-bar:nth-child(2) {
-webkit-animation-delay: -.1s;
animation-delay: -.1s
}
@-webkit-keyframes knight-rider-oscillate {
0% {
opacity: .5;
-webkit-transform: scaleY(1);
transform: scaleY(1)
}
to {
opacity: 1;
-webkit-transform: scaleY(1.4);
transform: scaleY(1.4)
}
}
@keyframes knight-rider-oscillate {
0% {
opacity: .5;
-webkit-transform: scaleY(1);
transform: scaleY(1)
}
to {
opacity: 1;
-webkit-transform: scaleY(1.4);
transform: scaleY(1.4)
}
}
.tmblr-iframe {
position: absolute
}
.tmblr-iframe.hide {
display: none
}
.tmblr-pano-lightbox-container .tmblr-iframe--pano-lightbox {
z-index: 8675309;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
display: none
}
.tmblr-pano-lightbox-container .tmblr-iframe-preloader-container {
z-index: 8675310;
position: fixed;
bottom: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, .92)
}
.tmblr-pano-lightbox-container .tmblr-pano-lightbox {
display: block
}
.tmblr-pano-lightbox-container .tmblr-pano-lightbox--preloading {
display: none
}
.tmblr-iframe--controls-phone-container {
padding-top: 43px
}
.tmblr-iframe--controls-phone-container .t-logo {
display: none
}
.tmblr-iframe--controls,
.tmblr-iframe--mobile-logged-in-controls {
position: fixed
}
.tmblr-iframe--controls.iframe-controls--desktop,
.tmblr-iframe--mobile-logged-in-controls.iframe-controls--desktop {
top: 0;
right: 0;
width: 40%;
min-width: 200px;
height: 36px;
z-index: 100
}
.tmblr-iframe--controls.iframe-controls--phone-mobile,
.tmblr-iframe--mobile-logged-in-controls.iframe-controls--phone-mobile {
top: 0;
left: 0;
width: 100%;
height: 44px;
padding-right: 8px;
z-index: 10
}
.tmblr-iframe--controls.iframe-controls--tablet-mobile,
.tmblr-iframe--mobile-logged-in-controls.iframe-controls--tablet-mobile {
top: 0;
right: 0;
width: 235px;
height: 36px;
z-index: 2147483646
}
.tmblr-iframe--desktop-logged-in-controls {
position: fixed
}
.tmblr-iframe--desktop-logged-in-controls.iframe-controls--desktop {
right: 0;
top: 0;
z-index: 100
}
.tmblr-iframe--unified-controls {
position: fixed;
top: 0;
right: 0;
left: 0;
width: 100%;
height: 0;
z-index: 100
}
.tmblr-iframe-compact .tmblr-iframe--unified-controls {
left: auto
}
.tmblr-iframe-overlay.tmblr-iframe-full-width #page .logo-wrapper {
display: none
}
@media screen and (max-device-width:568px) {
.tmblr-iframe-overlay.tmblr-iframe-full-width .no-image:not(.avatar-hidden) #header {
padding-top: 140px
}
}
.tmblr-iframe-overlay.tmblr-iframe-full-width:not(.tmblr-iframe-themed) .top-blog-header .header-image.cover.loaded:after {
display: none
}
.tmblr-iframe-overlay.tmblr-iframe-full-width:not(.tmblr-iframe-themed) .tmblr-iframe--unified-controls {
background-image: linear-gradient(180deg, rgba(0, 0, 0, .4) 0, transparent);
padding-bottom: 10px;
transition: padding-bottom .1s linear
}
.tmblr-iframe-overlay.tmblr-iframe-full-width:not(.tmblr-iframe-themed) .tmblr-iframe--unified-controls.tmblr-iframe--below-header {
padding-bottom: 0
}
.tmblr-iframe--follow-teaser {
position: fixed;
bottom: 0;
right: 0;
z-index: 100;
display: none
}
.tmblr-iframe--follow-teaser.open {
display: block
}
.tmblr-iframe--follow-teaser.sticky-ad-visible {
bottom: 310px
}
@-webkit-keyframes iframe-app-cta-transition {
0% {
opacity: 0;
bottom: -2em
}
to {
opacity: 1
}
}
@keyframes iframe-app-cta-transition {
0% {
opacity: 0;
bottom: -2em
}
to {
opacity: 1
}
}
@-webkit-keyframes iframe-app-cta-dismiss-transition {
0% {
opacity: 1;
-webkit-transform: translateY(0);
transform: translateY(0)
}
to {
opacity: 0;
-webkit-transform: translateY(2em);
transform: translateY(2em)
}
}
@keyframes iframe-app-cta-dismiss-transition {
0% {
opacity: 1;
-webkit-transform: translateY(0);
transform: translateY(0)
}
to {
opacity: 0;
-webkit-transform: translateY(2em);
transform: translateY(2em)
}
}
body.android,
body.ios {
padding-bottom: 50px
}
.tmblr-iframe--app-cta-button {
display: none;
position: fixed;
bottom: 10px;
left: 50%;
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
z-index: 100
}
.tmblr-iframe--app-cta-button.tmblr-iframe--loaded {
display: block;
-webkit-animation: iframe-app-cta-transition .2s ease-out;
animation: iframe-app-cta-transition .2s ease-out
}
.tmblr-lightbox {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 8675309;
overflow: hidden;
background-color: hsla(0, 0%, 7%, .92)
}
.tmblr-lightbox .vignette {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
right: 0;
bottom: 0;
z-index: 8675308;
background-size: 100% 100%
}
.tmblr-lightbox .lightbox-image-container {
position: absolute;
z-index: 8675310;
cursor: pointer
}
.tmblr-lightbox .lightbox-image-container.single-image {
cursor: default
}
.tmblr-lightbox .lightbox-image {
border-radius: 3px;
box-shadow: 0 4px 30px #000;
border-width: 0;
background-color: transparent
}
.tmblr-lightbox .lightbox-image.hide {
display: none
}
.tmblr-lightbox .lightbox-image.placeholder {
background-color: hsla(0, 0%, 100%, .05)
}
.tmblr-lightbox .lightbox-caption {
position: absolute;
text-align: center;
font-family: Helvetica Neue, HelveticaNeue, Helvetica, Arial, sans-serif;
font-size: 17px;
font-weight: 700;
color: #fff;
padding-top: 20px;
text-shadow: 0 4px 30px #000;
display: inline-block;
text-rendering: optimizeLegibility
}
.tmblr-lightbox .lightbox-caption.hide {
display: none
}
.hidden-body {
position: relative;
left: -99999px;
overflow: hidden;
background-color: #000
}
.hidden-body .show-mobile-lightbox {
position: fixed;
overflow: hidden;
width: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 8675309
}
.tmblr-iframe--sticky-ad {
position: fixed;
right: -464px;
bottom: 0;
border: 1px solid #8f8f8f;
background-color: #fff;
z-index: 100;
transition: all .5s ease
}
.tmblr-iframe--sticky-ad.show {
right: 0
}
.sticky-darla-ad {
position: fixed;
bottom: -315px;
right: 0;
z-index: 100;
border-radius: 5px 0;
border: 1px solid #9da6af;
transition: all .5s ease;
padding: 10px
}
.sticky-darla-ad.show {
bottom: 0
}
.sticky-darla-ad .ad-close-btn {
position: relative;
font-weight: 900;
margin-left: auto;
margin-right: 0;
margin-top: -26px;
cursor: pointer;
width: 20px;
height: 15px;
text-align: center;
border-radius: 5px 5px 0 0;
font-size: 12px;
line-height: 1.5;
border-top: 1px solid #9da6af;
border-left: 1px solid #9da6af;
border-right: 1px solid #9da6af
}
.sticky-darla-ad .ad-close-btn .icon-x {
display: none;
position: relative;
font-size: 12px;
content: '\D7';
color: #9da6af
}
.sticky-darla-ad .ad-footer {
font-size: 10px;
line-height: 1;
text-align: center
}
.sticky-darla-ad .ad-footer a {
padding-left: 5px;
border-bottom: 0;
text-decoration: none
}
.sticky-darla-ad .ad-header {
font-size: 10px;
line-height: 1;
text-align: center;
margin: 5px
}
.tmblr-iframe--init {
width: 0;
height: 0;
opacity: 0;
z-index: -1;
pointer-events: none
}
</style>
<script async="" src="/assets/src/scripts/tumblr/dashboard/px.js?ch=1"></script>
<style type="text/css">
.live-photo {
position: relative;
overflow: hidden;
cursor: pointer;
}
.live-photo video,
.live-photo img {
display: block;
max-width: 100%;
pointer-events: none;
-ms-touch-action: none;
touch-action: none;
}
.live-photo video {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
}
.live-photo video::-webkit-media-controls-start-playback-button {
display: none;
}
.live-photo .live-photo-icon {
display: block;
position: absolute;
top: 12px;
left: 12px;
width: 24px;
height: 24px;
background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='48' height='48' viewBox='0 0 48 48' xmlns='http://www.w3.org/2000/svg' fill='%23fff'%3E%3Ctitle%3ELive Photo%3C/title%3E%3Cg fill-rule='evenodd'%3E%3Cpath d='M24 36c6.627 0 12-5.373 12-12s-5.373-12-12-12-12 5.373-12 12 5.373 12 12 12zm0-2c5.523 0 10-4.477 10-10s-4.477-10-10-10-10 4.477-10 10 4.477 10 10 10z'/%3E%3Cpath d='M24 29a5 5 0 1 0 0-10 5 5 0 0 0 0 10zm0-3a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0-19a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm4.788.63a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm4.462 1.85a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm3.831 2.94a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm2.94 3.831a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm1.849 4.462a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm.63 4.788a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm-.63 4.788a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm-1.85 4.461a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm-2.94 3.831a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm-3.831 2.94a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm-4.462 1.849a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zM24 44a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm-4.788-.63a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm-4.462-1.85a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm-3.831-2.94a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm-2.94-3.831a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zM6.13 30.288a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zM5.5 25.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm.63-4.788a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm1.85-4.462a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm2.94-3.831a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm3.831-2.94a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm4.462-1.849a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z'/%3E%3C/g%3E%3C/svg%3E") center center;
background-size: contain;
-webkit-filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.5));
filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.5));
pointer-events: none;
}
.live-photo .live-photo-postroll,
.live-photo .live-photo-video {
opacity: 0;
}
.live-photo .live-photo-video {
-webkit-filter: blur(7.5px);
filter: blur(7.5px);
}
.live-photo .live-photo-keyframe,
.live-photo .live-photo-postroll,
.live-photo .live-photo-video {
will-change: transform, filter, opacity;
transition: opacity 0.5s linear, -webkit-transform 0.5s ease-out, -webkit-filter 0.5s linear;
transition: transform 0.5s ease-out, filter 0.5s linear, opacity 0.5s linear;
transition: transform 0.5s ease-out, filter 0.5s linear, opacity 0.5s linear, -webkit-transform 0.5s ease-out, -webkit-filter 0.5s linear;
}
.live-photo.loading .live-photo-icon {
-webkit-animation: live-photo-icon-loading 0.5s linear alternate infinite both;
animation: live-photo-icon-loading 0.5s linear alternate infinite both;
}
.live-photo.preview .live-photo-postroll {
opacity: 1;
transition-duration: 0s;
}
.live-photo.active video,
.live-photo.active img {
-webkit-transform: scale(1.075, 1.075);
-ms-transform: scale(1.075, 1.075);
transform: scale(1.075, 1.075);
}
.live-photo.active .live-photo-postroll {
-webkit-animation: live-photo-post-roll 1s both;
animation: live-photo-post-roll 1s both;
}
.live-photo.active .live-photo-video {
opacity: 1;
-webkit-filter: none;
filter: none;
transition-delay: 0.375s;
transition-duration: 0.625s;
}
@-webkit-keyframes live-photo-icon-loading {
0% {
opacity: 1;
}
100% {
opacity: 0.75;
}
}
@keyframes live-photo-icon-loading {
0% {
opacity: 1;
}
100% {
opacity: 0.75;
}
}
@-webkit-keyframes live-photo-post-roll {
0% {
opacity: 0;
-webkit-filter: blur(0);
filter: blur(0);
}
2% {
opacity: 1;
}
37.5% {
opacity: 1;
-webkit-filter: blur(7.5px);
filter: blur(7.5px);
}
100% {
opacity: 0;
}
}
@keyframes live-photo-post-roll {
0% {
opacity: 0;
-webkit-filter: blur(0);
filter: blur(0);
}
2% {
opacity: 1;
}
37.5% {
opacity: 1;
-webkit-filter: blur(7.5px);
filter: blur(7.5px);
}
100% {
opacity: 0;
}
}
</style>
<script async="" src="/assets/src/scripts/tumblr/dashboard/px.js?ch=2"></script>
</head>
<body class="Minecraft 1.8 - The Bountiful Update">
<div class="ui_dialog_lock" style="display: none;"></div>
<table width="100%" height="100%">
<tbody>
<tr>
<td style="padding-left: 16px;padding-right: 16px;" height="100%">
<table width="100%">
<tbody>
<tr>
<td>
<h1>Minecraft News</h1>
</td>
<td align="right">
<a href="http://tumblr.com/">
<font size="-2" color="#555555">Powered by Tumblr</font>
</a>
</td>
</tr>
</tbody>
</table>
<div class="container">
<div id="posts">
<div style="width:100%; height:16px;"></div>
<div style="width:100%; height:16px;"></div>
<div class="post text">
<h3><a href="http://mcupdate.tumblr.com/post/96439224994/minecraft-18-the-bountiful-update">Minecraft 1.8 - The Bountiful Update</a></h3>
<p>+ Added Granite, Andesite, and Diorite stone blocks, with smooth versions<br />+ Added Slime Block<br />+ Added Iron Trapdoor<br />+ Added Prismarine and Sea Lantern blocks<br />+ Added the Ocean Monument<br />+ Added Red Sandstone<br />+ Added Banners<br />+ Added Armor Stands<br />+ Added Coarse Dirt (dirt where grass wont grow)<br />+ Added Guardian mobs, with item drops<br />+ Added Endermite mob<br />+ Added Rabbits, with item drops<br />+ Added Mutton and Cooked Mutton<br />+ Villagers will harvest crops and plant new ones<br />+ Mossy Cobblestone and Mossy Stone Bricks are now craftable<br />+ Chiseled Stone Bricks are now craftable<br />+ Doors and fences now come in all wood type variants<br />+ Sponge block has regained its water-absorbing ability and becomes wet<br />+ Added a spectator game mode (game mode 3)<br />+ Added one new achievement<br />+ Added “Customized” world type<br />+ Added hidden “Debug Mode” world type<br />+ Worlds can now have a world barrier<br />+ Added @e target selector for Command Blocks<br />+ Added /blockdata command<br />+ Added /clone command<br />+ Added /execute command<br />+ Added /fill command<br />+ Added /particle command<br />+ Added /testforblocks command<br />+ Added /title command<br />+ Added /trigger command<br />+ Added /worldborder command<br />+ Added /stats command<br />+ Containers can be locked in custom maps by using the “Lock” data tag<br />+ Added logAdminCommands, showDeathMessages, reducedDebugInfo, sendCommandFeedback, and randomTickSpeed game rules<br />+ Added three new statistics<br />+ Player skins can now have double layers across the whole model, and left/right arms/legs can be edited independently<br />+ Added a new player model with smaller arms, and a new player skin called Alex?<br />+ Added options for configuring what pieces of the skin that are visible<br />+ Blocks can now have custom visual variations in the resource packs<br />+ Minecraft Realms now has an activity chart, so you can see who has been online<br />+ Minecraft Realms now lets you upload your maps<br />* Difficulty setting is saved per world, and can be locked if wanted<br />* Enchanting has been redone, now costs lapis lazuli in addition to enchantment levels<br />* Villager trading has been rebalanced<br />* Anvil repairing has been rebalanced<br />* Considerable faster client-side performance<br />* Max render distance has been increased to 32 chunks (512 blocks)<br />* Adventure mode now prevents you from destroying blocks, unless your items have the CanDestroy data tag<br />* Resource packs can now also define the shape of blocks and items, and not just their textures<br />* Scoreboards have been given a lot of new features<br />* Tweaked the F3 debug screen<br />* Block ID numbers (such as 1 for stone), are being replaced by ID names (such as minecraft:stone)<br />* Server list has been improved<br />* A few minor changes to village and temple generation<br />* Mob heads for players now show both skin layers<br />* Buttons can now be placed on the ceiling<br />* Lots and lots of other changes<br />* LOTS AND LOTS of other changes<br />- Removed Herobrine<br /><br /></p>
</div>
<div id="footer">
<div id="pagination"></div>
<div id="permalinks"><a href="http://mcupdate.tumblr.com/post/102272891284" title="Newer Posts" id="newer">Newer</a><a href="http://mcupdate.tumblr.com/post/89960443749" title="Older Posts" id="older">Older</a></div>
</div>
</div>
</div>
</td>
<td class="sidebar" width="180px" valign="top">
<h2>Official links:</h2><a href="https://minecraft.net/">Minecraft.net</a><br /><a href="https://minecraft.net/realms">Minecraft Realms</a><br /><a href="https://www.facebook.com/minecraft">Minecraft on Facebook</a><br /><a href="http://jinx.com/minecraft.aspx">Merchandise</a><br /><br /><a href="https://bugs.mojang.com/browse/MC">Bug tracker</a><br /><a href="https://help.mojang.com">Account Support</a><br /><br /><a href="http://twitter.com/Mojang">Mojang on Twitter</a><br /><a href="http://twitter.com/MojangSupport">Support on Twitter</a><br /><br /><b>Try our other games!</b><br />
<div style="height:5px; display:block;"></div>
<a href="http://scrolls.com/welcome?utm_source=mcl"><img src="http://assets.mojang.com/scrolls/scrolls_logo_150.png" border="0" /></a>
<div style="height:5px; display:block;"></div>
<a href="http://playcobalt.com/?utm_source=mcl"><img src="http://assets.mojang.com/cobalt/cobalt_logo_150.PNG" border="0" /></a>
<h2>Community links:</h2><a href="http://minecraftforum.net/">Minecraft Forums</a><br /><a href="http://www.twitch.tv/directory/game/Minecraft">Minecraft on Twitch.tv</a><br /></td>
</tr>
</tbody>
</table>
<font style="display:none;" size="0" color="#222222">
<script src="http://assets.tumblr.com/client/prod/standalone/tumblelog/index.build.js?_v=002b364509c8adc2849edf7b59a42286"></script>
</font>
</body>
</html>

View file

@ -0,0 +1,178 @@
<article><div itemprop="articleBody" id="readability-page-1">
<p>
Emscripten has always focused first and foremost on compiling to the Web and other JavaScript environments like Node.js. But as WebAssembly starts to be used <em>without</em> JavaScript, new use cases are appearing, and so we've been working on support for emitting <a href="https://github.com/emscripten-core/emscripten/wiki/WebAssembly-Standalone" target="_blank"><strong>standalone Wasm</strong></a> files from Emscripten, that do not depend on the Emscripten JS runtime! This post explains why that's interesting.
</p>
<h2 id="using-standalone-mode-in-emscripten">
Using standalone mode in Emscripten <a href="#using-standalone-mode-in-emscripten">#</a>
</h2>
<p>
First, let's see what you can do with this new feature! Similar to <a href="https://hacks.mozilla.org/2018/01/shrinking-webassembly-and-javascript-code-sizes-in-emscripten/" target="_blank">this post</a> let's start with a "hello world" type program that exports a single function that adds two numbers:
</p>
<pre><code><span>// add.c</span><br><span><span>#</span><span>include</span> <span>&lt;emscripten.h&gt;</span></span><br><br>EMSCRIPTEN_KEEPALIVE<br><span>int</span> <span>add</span><span>(</span><span>int</span> x<span>,</span> <span>int</span> y<span>)</span> <span>{</span><br> <span>return</span> x <span>+</span> y<span>;</span><br><span>}</span></code></pre>
<p>
We'd normally build this with something like <code>emcc -O3 add.c -o add.js</code> which would emit <code>add.js</code> and <code>add.wasm</code>. Instead, let's ask <code>emcc</code> to only emit Wasm:
</p>
<pre><code>emcc -O3 add.c -o add.wasm
</code></pre>
<p>
When <code>emcc</code> sees we only want Wasm then it makes it "standalone" - a Wasm file that can run by itself as much as possible, without any JavaScript runtime code from Emscripten.
</p>
<p>
Disassembling it, it's very minimal - just 87 bytes! It contains the obvious <code>add</code> function
</p>
<pre><code><span>(</span><span>func</span> $add <span>(</span><span>param</span> $0 i32<span>)</span> <span>(</span><span>param</span> $1 i32<span>)</span> <span>(</span><span>result</span> i32<span>)</span><br> <span>(</span><span>i32</span>.add<br> <span>(</span><span>local</span>.get $0<span>)</span><br> <span>(</span><span>local</span>.get $1<span>)</span><br> <span>)</span><br><span>)</span></code></pre>
<p>
and one more function, <code>_start</code>,
</p>
<pre><code><span>(</span><span>func</span> $_start<br> <span>(</span><span>nop</span><span>)</span><br><span>)</span></code></pre>
<p>
<code>_start</code> is part of the <a href="https://github.com/WebAssembly/WASI" target="_blank">WASI</a> spec, and Emscripten's standalone mode emits it so that we can run in WASI runtimes. (Normally <code>_start</code> would do global initialization, but here we just don't need any so it's empty.)
</p>
<h3 id="write-your-own-javascript-loader">
Write your own JavaScript loader <a href="#write-your-own-javascript-loader">#</a>
</h3>
<p>
One nice thing about a standalone Wasm file like this is that you can write custom JavaScript to load and run it, which can be very minimal depending on your use case. For example, we can do this in Node.js:
</p>
<pre><code><span>// load-add.js</span><br><span>const</span> binary <span>=</span> <span>require</span><span>(</span><span>'fs'</span><span>)</span><span>.</span><span>readFileSync</span><span>(</span><span>'add.wasm'</span><span>)</span><span>;</span><br><br>WebAssembly<span>.</span><span>instantiate</span><span>(</span>binary<span>)</span><span>.</span><span>then</span><span>(</span><span>(</span><span><span>{</span> instance <span>}</span></span><span>)</span> <span>=&gt;</span> <span>{</span><br> console<span>.</span><span>log</span><span>(</span>instance<span>.</span>exports<span>.</span><span>add</span><span>(</span><span>40</span><span>,</span> <span>2</span><span>)</span><span>)</span><span>;</span><br><span>}</span><span>)</span><span>;</span></code></pre>
<p>
Just 4 lines! Running that prints <code>42</code> as expected. Note that while this example is very simplistic, there are cases where you simply don't need much JavaScript, and may be able to do better than Emscripten's default JavaScript runtime (which supports a bunch of environments and options). A real-world example of that is in <a href="https://github.com/zeux/meshoptimizer/blob/bdc3006532dd29b03d83dc819e5fa7683815b88e/js/meshopt_decoder.js" target="_blank">zeux's meshoptimizer</a> - just 57 lines, including memory management, growth, etc.!
</p>
<h3 id="running-in-wasm-runtimes">
Running in Wasm runtimes <a href="#running-in-wasm-runtimes">#</a>
</h3>
<p>
Another nice thing about standalone Wasm files is that you can run them in Wasm runtimes like <a href="https://wasmer.io/" target="_blank">wasmer</a>, <a href="https://github.com/bytecodealliance/wasmtime" target="_blank">wasmtime</a>, or <a href="https://github.com/WAVM/WAVM" target="_blank">WAVM</a>. For example, consider this hello world:
</p>
<pre><code><span>// hello.cpp</span><br><span><span>#</span><span>include</span> <span>&lt;stdio.h&gt;</span></span><br><br><span>int</span> <span>main</span><span>(</span><span>)</span> <span>{</span><br> <span>printf</span><span>(</span><span>"hello, world!\n"</span><span>)</span><span>;</span><br> <span>return</span> <span>0</span><span>;</span><br><span>}</span></code></pre>
<p>
We can build and run that in any of those runtimes:
</p>
<pre><code>$ emcc hello.cpp -O3 -o hello.wasm<br>$ wasmer run hello.wasm<br>hello, world<span>!</span><br>$ wasmtime hello.wasm<br>hello, world<span>!</span><br>$ wavm run hello.wasm<br>hello, world<span>!</span></code></pre>
<p>
Emscripten uses WASI APIs as much as possible, so programs like this end up using 100% WASI and can run in WASI-supporting runtimes (see notes later on what programs require more than WASI).
</p>
<h3 id="building-wasm-plugins">
Building Wasm plugins <a href="#building-wasm-plugins">#</a>
</h3>
<p>
Aside from the Web and the server, an exciting area for Wasm is <strong>plugins</strong>. For example, an image editor might have Wasm plugins that can perform filters and other operations on the image. For that type of use case you want a standalone Wasm binary, just like in the examples so far, but where it also has a proper API for the embedding application.
</p>
<p>
Plugins are sometimes related to dynamic libraries, as dynamic libraries are one way to implement them. Emscripten has support for dynamic libraries with the <a href="https://github.com/emscripten-core/emscripten/wiki/Linking#general-dynamic-linking" target="_blank">SIDE_MODULE</a> option, and this has been a way to build Wasm plugins. The new standalone Wasm option described here is an improvement on that in several ways: First, a dynamic library has relocatable memory, which adds overhead if you dont need it (and you dont if you arent linking the Wasm with another Wasm after loading it). Second, standalone output is designed to run in Wasm runtimes as well, as mentioned earlier.
</p>
<p>
Okay, so far so good: Emscripten can either emit JavaScript + WebAssembly as it always did, and now it can also emit just WebAssembly by itself, which lets you run it in places that don't have JavaScript like Wasm runtimes, or you can write your own custom JavaScript loader code, etc. Now let's talk about the background and the technical details!
</p>
<h2 id="webassembly's-two-standard-apis">
WebAssembly's two standard APIs <a href="#webassembly's-two-standard-apis">#</a>
</h2>
<p>
WebAssembly can only access the APIs it receives as imports - the core Wasm spec has no concrete API details. Given the current trajectory of Wasm, it looks like there will be 3 main categories of APIs that people import and use:
</p>
<ul>
<li>
<strong>Web APIs</strong>: This is what Wasm programs use on the Web, which are the existing standardized APIs that JavaScript can use too. Currently these are called indirectly, through JS glue code, but in the future with <a href="https://github.com/WebAssembly/interface-types/blob/master/proposals/interface-types/Explainer.md" target="_blank">interface types</a> they will be called directly.
</li>
<li>
<strong>WASI APIs</strong>: WASI focuses on standardizing APIs for Wasm on the server.
</li>
<li>
<strong>Other APIs</strong>: Various custom embeddings will define their own application-specific APIs. For example, we gave the example earlier of an image editor with Wasm plugins that implement an API to do visual effects. Note that a plugin might also have access to “system” APIs, like a native dynamic library would, or it might be very sandboxed and have no imports at all (if the embedding just calls its methods).
</li>
</ul>
<p>
WebAssembly is in the interesting position of having <a href="https://www.goodreads.com/quotes/589703-the-good-thing-about-standards-is-that-there-are-so" target="_blank">two standardized sets of APIs</a>. This does makes sense in that one is for the Web and one for the server, and those environments do have different requirements; for similar reasons Node.js does not have identical APIs to JavaScript on the Web.
</p>
<p>
However, there is more than the Web and the server, in particular there are also Wasm plugins. For one thing, plugins can run inside an application that may be on the Web (just like <a href="https://www.figma.com/blog/an-update-on-plugin-security/#a-technology-change" target="_blank">JS plugins</a>) or off the Web; for another, regardless of where the embedding application is, a plugin environment is not a Web nor a server environment. So it's not immediately obvious which sets of APIs will be used - it may depend on the code being ported, the Wasm runtime being embedded, etc.
</p>
<h2 id="let's-unify-as-much-as-possible">
Let's unify as much as possible <a href="#let's-unify-as-much-as-possible">#</a>
</h2>
<p>
One concrete way Emscripten hopes to help here is that by using WASI APIs as much as possible we can avoid <strong>unnecessary</strong> API differences. As mentioned earlier, on the Web Emscripten code accesses Web APIs indirectly, through JavaScript, so where that JavaScript API could look like WASI, we'd be removing an unnecessary API difference, and that same binary can also run on the server. In other words, if Wasm wants to log some info, it needs to call into JS, something like this:
</p>
<pre><code><span>wasm</span> <span>=&gt;</span> <span>function</span> <span>musl_writev</span><span>(</span><span><span>.</span><span>.</span></span><span>)</span> <span>{</span> <span>.</span><span>.</span> console<span>.</span><span>log</span><span>(</span><span>.</span><span>.</span><span>)</span> <span>.</span><span>.</span> <span>}</span></code></pre>
<p>
<code>musl_writev</code> is an implementation of the Linux syscall interface that <a href="https://www.musl-libc.org/" target="_blank">musl libc</a> uses to write data to a file descriptor, and that ends up calling <code>console.log</code> with the proper data. The Wasm module imports and calls that <code>musl_writev</code>, which defines an ABI between the JS and the Wasm. That ABI is arbitrary (and in fact Emscripten has changed its ABI over time to optimize it). If we replace that with an ABI that matches WASI, we can get this:
</p>
<pre><code><span>wasm</span> <span>=&gt;</span> <span>function</span> <span>__wasi_fd_write</span><span>(</span><span><span>.</span><span>.</span></span><span>)</span> <span>{</span> <span>.</span><span>.</span> console<span>.</span><span>log</span><span>(</span><span>.</span><span>.</span><span>)</span> <span>.</span><span>.</span> <span>}</span></code></pre>
<p>
This isn't a big change, just requiring some refactoring of the ABI, and when running in a JS environment it doesn't matter much. But now the Wasm can run without the JS since that WASI API is recognized by WASI runtimes! Thats how the standalone Wasm examples from before work, just by refactoring Emscripten to use WASI APIs.
</p>
<p>
Another advantage of Emscripten using WASI APIs is that we can help the WASI spec by finding real-world issues. For example, we found that <a href="https://github.com/WebAssembly/WASI/pull/106" target="_blank">changing the WASI "whence" constants</a> would be useful, and we've started some discussions around <a href="https://github.com/WebAssembly/WASI/issues/109" target="_blank">code size</a> and <a href="https://github.com/WebAssembly/WASI/issues/122" target="_blank">POSIX compatibility</a>.
</p>
<p>
Emscripten using WASI as much as possible is also useful in that it lets users use a single SDK to target Web, server, and plugin environments. Emscripten isn't the only SDK allowing that, as the WASI SDK's output can be run on the Web using the <a href="https://wasi.dev/polyfill/" target="_blank">WASI Web Polyfill</a> or Wasmer's <a href="https://github.com/wasmerio/wasmer-js" target="_blank">wasmer-js</a>, but Emscriptens Web output is more compact, so it lets a single SDK be used without compromising Web performance.
</p>
<p>
Speaking of which, you can emit a standalone Wasm file from Emscripten with optional JS in a single command:
</p>
<pre><code>emcc -O3 add.c -o add.js -s STANDALONE_WASM
</code></pre>
<p>
That emits <code>add.js</code> and <code>add.wasm</code>. The Wasm file is standalone just like earlier when we only emitted a Wasm file by itself (<code>STANDALONE_WASM</code> was set automatically when we said <code>-o add.wasm</code>), but now in addition there is a JS file that can load and run it. The JS is useful for running it on the Web if you don't want to write your own JS for that.
</p>
<h2 id="do-we-need-non-standalone-wasm%3F">
Do we need <em>non</em>-standalone Wasm? <a href="#do-we-need-non-standalone-wasm%3F">#</a>
</h2>
<p>
Why does the <code>STANDALONE_WASM</code> flag exist? In theory Emscripten could always set <code>STANDALONE_WASM</code>, which would be simpler. But standalone Wasm files can't depend on JS, and that has some downsides:
</p>
<ul>
<li>We can't minify the Wasm import and export names, as the minification only works if both sides agree, the Wasm and what loads it.
</li>
<li>Normally we create the Wasm Memory in JS so that JS can start to use it during startup, which lets us do work in parallel. But in standalone Wasm we have to create the Memory in the Wasm.
</li>
<li>Some APIs are just easy to do in JS. For example <a href="https://github.com/emscripten-core/emscripten/pull/9558" target="_blank"><code>__assert_fail</code></a>, which is called when a C assertion fails, is normally <a href="https://github.com/emscripten-core/emscripten/blob/2b42a35f61f9a16600c78023391d8033740a019f/src/library.js#L1235" target="_blank">implemented in JS</a>. It takes just a single line, and even if you include the JS functions it calls, the total code size is quite small. On the other hand, in a standalone build we can't depend on JS, so we use <a href="https://github.com/emscripten-core/emscripten/blob/b8896d18f2163dbf2fa173694eeac71f6c90b68c/system/lib/libc/musl/src/exit/assert.c#L4" target="_blank">musl's <code>assert.c</code></a>. That uses <code>fprintf</code>, which means it ends up pulling in a bunch of C <code>stdio</code> support, including things with indirect calls that make it hard to remove unused functions. Overall, there are many such details that end up making a difference in total code size.
</li>
</ul>
<p>
If you want to run both on the Web and elsewhere, and you want 100% optimal code size and startup times, you should make two separate builds, one with <code>-s STANDALONE</code> and one without. That's very easy as it's just flipping one flag!
</p>
<h2 id="necessary-api-differences">
Necessary API differences <a href="#necessary-api-differences">#</a>
</h2>
<p>
We saw that Emscripten uses WASI APIs as much as possible to avoid <strong>unnecessary</strong> API differences. Are there any <strong>necessary</strong> ones? Sadly, yes - some WASI APIs require tradeoffs. For example:
</p>
<ul>
<li>WASI does not support various POSIX features, like <a href="https://github.com/WebAssembly/WASI/issues/122" target="_blank">user/group/world file permissions</a>, as a result of which you can't fully implement a (Linux) system <code>ls</code> for example (see details in that link). Emscripten's existing filesystem layer does support some of those things, so if we switched to WASI APIs for all filesystem operations then we'd be <a href="https://github.com/emscripten-core/emscripten/issues/9479#issuecomment-542815711" target="_blank">losing some POSIX support</a>.
</li>
<li>WASI's <code>path_open</code> <a href="https://github.com/WebAssembly/WASI/issues/109" target="_blank">has a cost in code size</a> because it forces extra permissions handling in the Wasm itself. That code is unnecessary on the Web.
</li>
<li>WASI doesn't provide a <a href="https://github.com/WebAssembly/WASI/issues/82" target="_blank">notification API for memory growth</a>, and as a result, JS runtimes must constantly check if memory grew and if so update their views, on every import and export. To avoid that overhead, Emscripten provides a notification API, <code>emscripten_notify_memory_growth</code>, which <a href="https://github.com/zeux/meshoptimizer/blob/bdc3006532dd29b03d83dc819e5fa7683815b88e/js/meshopt_decoder.js#L10" target="_blank">you can see implemented in a single line</a> in zeux's meshoptimizer that we mentioned earlier.
</li>
</ul>
<p>
In time WASI may add more POSIX support, a memory growth notification, etc. - WASI is still highly experimental and expected to change significantly. For now, to avoid regressions in Emscripten we do not emit 100% WASI binaries if you use certain features. In particular, opening files uses a POSIX method instead of WASI, which means that if you call <code>fopen</code> then the resulting Wasm file will not be 100% WASI - however, if all you do is use <code>printf</code>, which operates on the already-open <code>stdout</code>, then it will be 100% WASI, as in the "hello world" example we saw near the beginning, where Emscripten's output does run in WASI runtimes.
</p>
<p>
If it would be useful for users we can add a <code>PURE_WASI</code> option which would sacrifice code size in return for strict WASI compliance, but if that's not urgent (and most plugin use cases weve seen so far dont need full file I/O) then maybe we can wait for WASI to improve to where Emscripten can remove these non-WASI APIs. That would be the best outcome, and were working towards that as you can see in the links above.
</p>
<p>
However, even if WASI does improve, there is no avoiding the fact that Wasm has two standardized APIs as mentioned earlier. In the future I expect Emscripten will call Web APIs directly using interface types, because that will be more compact than calling a WASI-looking JS API that then calls a Web API (as in the <code>musl_writev</code> example from before). We could have a polyfill or a translation layer of some sort to help here, but we wouldn't want to use it unnecessarily, so we will need separate builds for Web and WASI environments. (This is somewhat unfortunate; in theory this could have been avoided if WASI were a superset of Web APIs, but obviously that would have meant compromises on the server side.)
</p>
<h2 id="current-status">
Current status <a href="#current-status">#</a>
</h2>
<p>
Quite a lot works already! The main limitations are:
</p>
<ul>
<li>
<strong>WebAssembly limitations</strong>: Various features, like C++ exceptions, setjmp, and pthreads, depend on JavaScript due to Wasm limitations, and there is no good non-JS replacement yet. (Emscripten may start to support some of them <a href="https://www.youtube.com/watch?v=qQOP6jqZqf8&amp;list=PLqh1Mztq_-N2OnEXkdtF5yymcihwqG57y&amp;index=2&amp;t=0s" target="_blank">using Asyncify</a>, or maybe we'll just wait for <a href="https://github.com/WebAssembly/exception-handling/blob/master/proposals/Exceptions.md" target="_blank">native Wasm features</a> to arrive to VMs.)
</li>
<li>
<strong>WASI limitations</strong>: Libraries and APIs like OpenGL and SDL don't have corresponding WASI APIs yet.
</li>
</ul>
<p>
You <strong>can</strong> still use all those in Emscripten's standalone mode, but the output will contain calls to JS runtime support code. As a result, it will not be 100% WASI (for similar reasons those features also do not work in the WASI SDK). Those Wasm files won't run in WASI runtimes, but you can use them on the Web and you can write your own JS runtime for them. You can also use them as plugins; for example, a game engine could have plugins that render using OpenGL, and the developer would compile them in standalone mode and then implement the OpenGL imports in the engine's Wasm runtime. Standalone Wasm mode still helps here because it makes the output as standalone as Emscripten can make it.
</p>
<p>
You may also find APIs that <strong>do</strong> have a non-JS replacement that we havent converted yet, as work is still ongoing. Please <a href="https://github.com/emscripten-core/emscripten/issues" target="_blank">file bugs</a>, and as always help is welcome!
</p>
</div></article>

View file

@ -0,0 +1,259 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta charset="utf-8" />
<title>
Outside the web: standalone WebAssembly binaries using Emscripten · V8
</title>
<meta content="width=device-width,initial-scale=1" name="viewport" />
<meta content="dark light" name="color-scheme" />
<link href="/_css/main.css" rel="stylesheet" />
<link href="/.webmanifest" rel="manifest" />
<meta content="#4285F4" name="theme-color" />
<link href="/blog.atom" rel="alternate" title="V8 Atom feed" type="application/atom+xml" />
<link href="/features.atom" rel="alternate" title="V8 JS/Wasm features Atom feed" type="application/atom+xml" />
<script>
<![CDATA[
document.documentElement.className+=' js'
]]>
</script>
<meta content="Emscripten now supports standalone Wasm files, which do not need JavaScript." name="description" />
</head>
<body>
<header id="header">
<h1>
<a href="/">V8</a>
</h1><a href="#navigation-toggle" id="nav-toggle">Show navigation</a>
<nav>
<ul>
<li>
<a href="/">Home</a>
</li>
<li class="current">
<a href="/blog">Blog</a>
</li>
<li>
<a href="/docs">Docs</a>
</li>
<li>
<a href="/features" title="JavaScript and WebAssembly language features">JS/Wasm features</a>
</li>
<li>
<a href="/grant">Research</a>
</li>
</ul>
</nav>
</header>
<main id="main">
<article itemscope="itemscope" itemtype="http://schema.org/BlogPosting">
<header>
<h1 itemprop="headline">
Outside the web: standalone WebAssembly binaries using Emscripten
</h1>
<p class="meta">
Published <time datetime="2019-11-21" itemprop="datePublished">21 November 2019</time> · Tagged with <a href="/blog/tags/webassembly" class="tag">WebAssembly</a> <a href="/blog/tags/tooling" class="tag">tooling</a>
</p>
</header>
<div itemprop="articleBody">
<p>
Emscripten has always focused first and foremost on compiling to the Web and other JavaScript environments like Node.js. But as WebAssembly starts to be used <em>without</em> JavaScript, new use cases are appearing, and so we've been working on support for emitting <a href="https://github.com/emscripten-core/emscripten/wiki/WebAssembly-Standalone"><strong>standalone Wasm</strong></a> files from Emscripten, that do not depend on the Emscripten JS runtime! This post explains why that's interesting.
</p>
<h2 id="using-standalone-mode-in-emscripten">
Using standalone mode in Emscripten <a href="#using-standalone-mode-in-emscripten" class="bookmark">#</a>
</h2>
<p>
First, let's see what you can do with this new feature! Similar to <a href="https://hacks.mozilla.org/2018/01/shrinking-webassembly-and-javascript-code-sizes-in-emscripten/">this post</a> let's start with a "hello world" type program that exports a single function that adds two numbers:
</p>
<pre class="language-c"><code class="language-c"><span class="token comment">// add.c</span><br /><span class="token macro property"><span class="token directive-hash">#</span><span class="token keyword directive">include</span> <span class="token string">&lt;emscripten.h&gt;</span></span><br /><br />EMSCRIPTEN_KEEPALIVE<br /><span class="token keyword">int</span> <span class="token function">add</span><span class="token punctuation">(</span><span class="token keyword">int</span> x<span class="token punctuation">,</span> <span class="token keyword">int</span> y<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> x <span class="token operator">+</span> y<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>
We'd normally build this with something like <code>emcc -O3 add.c -o add.js</code> which would emit <code>add.js</code> and <code>add.wasm</code>. Instead, let's ask <code>emcc</code> to only emit Wasm:
</p>
<pre><code>emcc -O3 add.c -o add.wasm
</code></pre>
<p>
When <code>emcc</code> sees we only want Wasm then it makes it "standalone" - a Wasm file that can run by itself as much as possible, without any JavaScript runtime code from Emscripten.
</p>
<p>
Disassembling it, it's very minimal - just 87 bytes! It contains the obvious <code>add</code> function
</p>
<pre class="language-lisp"><code class="language-lisp"><span class="token punctuation">(</span><span class="token car">func</span> $add <span class="token punctuation">(</span><span class="token car">param</span> $0 i32<span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token car">param</span> $1 i32<span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token car">result</span> i32<span class="token punctuation">)</span><br /> <span class="token punctuation">(</span><span class="token car">i32</span>.add<br /> <span class="token punctuation">(</span><span class="token car">local</span>.get $0<span class="token punctuation">)</span><br /> <span class="token punctuation">(</span><span class="token car">local</span>.get $1<span class="token punctuation">)</span><br /> <span class="token punctuation">)</span><br /><span class="token punctuation">)</span></code></pre>
<p>
and one more function, <code>_start</code>,
</p>
<pre class="language-lisp"><code class="language-lisp"><span class="token punctuation">(</span><span class="token car">func</span> $_start<br /> <span class="token punctuation">(</span><span class="token car">nop</span><span class="token punctuation">)</span><br /><span class="token punctuation">)</span></code></pre>
<p>
<code>_start</code> is part of the <a href="https://github.com/WebAssembly/WASI">WASI</a> spec, and Emscripten's standalone mode emits it so that we can run in WASI runtimes. (Normally <code>_start</code> would do global initialization, but here we just don't need any so it's empty.)
</p>
<h3 id="write-your-own-javascript-loader">
Write your own JavaScript loader <a href="#write-your-own-javascript-loader" class="bookmark">#</a>
</h3>
<p>
One nice thing about a standalone Wasm file like this is that you can write custom JavaScript to load and run it, which can be very minimal depending on your use case. For example, we can do this in Node.js:
</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// load-add.js</span><br /><span class="token keyword">const</span> binary <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'fs'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">readFileSync</span><span class="token punctuation">(</span><span class="token string">'add.wasm'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br />WebAssembly<span class="token punctuation">.</span><span class="token function">instantiate</span><span class="token punctuation">(</span>binary<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> instance <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span><br /> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>instance<span class="token punctuation">.</span>exports<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token number">40</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>
Just 4 lines! Running that prints <code>42</code> as expected. Note that while this example is very simplistic, there are cases where you simply don't need much JavaScript, and may be able to do better than Emscripten's default JavaScript runtime (which supports a bunch of environments and options). A real-world example of that is in <a href="https://github.com/zeux/meshoptimizer/blob/bdc3006532dd29b03d83dc819e5fa7683815b88e/js/meshopt_decoder.js">zeux's meshoptimizer</a> - just 57 lines, including memory management, growth, etc.!
</p>
<h3 id="running-in-wasm-runtimes">
Running in Wasm runtimes <a href="#running-in-wasm-runtimes" class="bookmark">#</a>
</h3>
<p>
Another nice thing about standalone Wasm files is that you can run them in Wasm runtimes like <a href="https://wasmer.io">wasmer</a>, <a href="https://github.com/bytecodealliance/wasmtime">wasmtime</a>, or <a href="https://github.com/WAVM/WAVM">WAVM</a>. For example, consider this hello world:
</p>
<pre class="language-cpp"><code class="language-cpp"><span class="token comment">// hello.cpp</span><br /><span class="token macro property"><span class="token directive-hash">#</span><span class="token keyword directive">include</span> <span class="token string">&lt;stdio.h&gt;</span></span><br /><br /><span class="token keyword">int</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"hello, world!\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>
We can build and run that in any of those runtimes:
</p>
<pre class="language-bash"><code class="language-bash">$ emcc hello.cpp -O3 -o hello.wasm<br />$ wasmer run hello.wasm<br />hello, world<span class="token operator">!</span><br />$ wasmtime hello.wasm<br />hello, world<span class="token operator">!</span><br />$ wavm run hello.wasm<br />hello, world<span class="token operator">!</span></code></pre>
<p>
Emscripten uses WASI APIs as much as possible, so programs like this end up using 100% WASI and can run in WASI-supporting runtimes (see notes later on what programs require more than WASI).
</p>
<h3 id="building-wasm-plugins">
Building Wasm plugins <a href="#building-wasm-plugins" class="bookmark">#</a>
</h3>
<p>
Aside from the Web and the server, an exciting area for Wasm is <strong>plugins</strong>. For example, an image editor might have Wasm plugins that can perform filters and other operations on the image. For that type of use case you want a standalone Wasm binary, just like in the examples so far, but where it also has a proper API for the embedding application.
</p>
<p>
Plugins are sometimes related to dynamic libraries, as dynamic libraries are one way to implement them. Emscripten has support for dynamic libraries with the <a href="https://github.com/emscripten-core/emscripten/wiki/Linking#general-dynamic-linking">SIDE_MODULE</a> option, and this has been a way to build Wasm plugins. The new standalone Wasm option described here is an improvement on that in several ways: First, a dynamic library has relocatable memory, which adds overhead if you dont need it (and you dont if you arent linking the Wasm with another Wasm after loading it). Second, standalone output is designed to run in Wasm runtimes as well, as mentioned earlier.
</p>
<p>
Okay, so far so good: Emscripten can either emit JavaScript + WebAssembly as it always did, and now it can also emit just WebAssembly by itself, which lets you run it in places that don't have JavaScript like Wasm runtimes, or you can write your own custom JavaScript loader code, etc. Now let's talk about the background and the technical details!
</p>
<h2 id="webassembly's-two-standard-apis">
WebAssembly's two standard APIs <a href="#webassembly's-two-standard-apis" class="bookmark">#</a>
</h2>
<p>
WebAssembly can only access the APIs it receives as imports - the core Wasm spec has no concrete API details. Given the current trajectory of Wasm, it looks like there will be 3 main categories of APIs that people import and use:
</p>
<ul>
<li>
<strong>Web APIs</strong>: This is what Wasm programs use on the Web, which are the existing standardized APIs that JavaScript can use too. Currently these are called indirectly, through JS glue code, but in the future with <a href="https://github.com/WebAssembly/interface-types/blob/master/proposals/interface-types/Explainer.md">interface types</a> they will be called directly.
</li>
<li>
<strong>WASI APIs</strong>: WASI focuses on standardizing APIs for Wasm on the server.
</li>
<li>
<strong>Other APIs</strong>: Various custom embeddings will define their own application-specific APIs. For example, we gave the example earlier of an image editor with Wasm plugins that implement an API to do visual effects. Note that a plugin might also have access to “system” APIs, like a native dynamic library would, or it might be very sandboxed and have no imports at all (if the embedding just calls its methods).
</li>
</ul>
<p>
WebAssembly is in the interesting position of having <a href="https://www.goodreads.com/quotes/589703-the-good-thing-about-standards-is-that-there-are-so">two standardized sets of APIs</a>. This does makes sense in that one is for the Web and one for the server, and those environments do have different requirements; for similar reasons Node.js does not have identical APIs to JavaScript on the Web.
</p>
<p>
However, there is more than the Web and the server, in particular there are also Wasm plugins. For one thing, plugins can run inside an application that may be on the Web (just like <a href="https://www.figma.com/blog/an-update-on-plugin-security/#a-technology-change">JS plugins</a>) or off the Web; for another, regardless of where the embedding application is, a plugin environment is not a Web nor a server environment. So it's not immediately obvious which sets of APIs will be used - it may depend on the code being ported, the Wasm runtime being embedded, etc.
</p>
<h2 id="let's-unify-as-much-as-possible">
Let's unify as much as possible <a href="#let's-unify-as-much-as-possible" class="bookmark">#</a>
</h2>
<p>
One concrete way Emscripten hopes to help here is that by using WASI APIs as much as possible we can avoid <strong>unnecessary</strong> API differences. As mentioned earlier, on the Web Emscripten code accesses Web APIs indirectly, through JavaScript, so where that JavaScript API could look like WASI, we'd be removing an unnecessary API difference, and that same binary can also run on the server. In other words, if Wasm wants to log some info, it needs to call into JS, something like this:
</p>
<pre class="language-js"><code class="language-js"><span class="token parameter">wasm</span> <span class="token operator">=&gt;</span> <span class="token keyword">function</span> <span class="token function">musl_writev</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">.</span><span class="token punctuation">.</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">.</span><span class="token punctuation">.</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token punctuation">.</span> <span class="token punctuation">}</span></code></pre>
<p>
<code>musl_writev</code> is an implementation of the Linux syscall interface that <a href="https://www.musl-libc.org">musl libc</a> uses to write data to a file descriptor, and that ends up calling <code>console.log</code> with the proper data. The Wasm module imports and calls that <code>musl_writev</code>, which defines an ABI between the JS and the Wasm. That ABI is arbitrary (and in fact Emscripten has changed its ABI over time to optimize it). If we replace that with an ABI that matches WASI, we can get this:
</p>
<pre class="language-js"><code class="language-js"><span class="token parameter">wasm</span> <span class="token operator">=&gt;</span> <span class="token keyword">function</span> <span class="token function">__wasi_fd_write</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">.</span><span class="token punctuation">.</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">.</span><span class="token punctuation">.</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token punctuation">.</span> <span class="token punctuation">}</span></code></pre>
<p>
This isn't a big change, just requiring some refactoring of the ABI, and when running in a JS environment it doesn't matter much. But now the Wasm can run without the JS since that WASI API is recognized by WASI runtimes! Thats how the standalone Wasm examples from before work, just by refactoring Emscripten to use WASI APIs.
</p>
<p>
Another advantage of Emscripten using WASI APIs is that we can help the WASI spec by finding real-world issues. For example, we found that <a href="https://github.com/WebAssembly/WASI/pull/106">changing the WASI "whence" constants</a> would be useful, and we've started some discussions around <a href="https://github.com/WebAssembly/WASI/issues/109">code size</a> and <a href="https://github.com/WebAssembly/WASI/issues/122">POSIX compatibility</a>.
</p>
<p>
Emscripten using WASI as much as possible is also useful in that it lets users use a single SDK to target Web, server, and plugin environments. Emscripten isn't the only SDK allowing that, as the WASI SDK's output can be run on the Web using the <a href="https://wasi.dev/polyfill/">WASI Web Polyfill</a> or Wasmer's <a href="https://github.com/wasmerio/wasmer-js">wasmer-js</a>, but Emscriptens Web output is more compact, so it lets a single SDK be used without compromising Web performance.
</p>
<p>
Speaking of which, you can emit a standalone Wasm file from Emscripten with optional JS in a single command:
</p>
<pre><code>emcc -O3 add.c -o add.js -s STANDALONE_WASM
</code></pre>
<p>
That emits <code>add.js</code> and <code>add.wasm</code>. The Wasm file is standalone just like earlier when we only emitted a Wasm file by itself (<code>STANDALONE_WASM</code> was set automatically when we said <code>-o add.wasm</code>), but now in addition there is a JS file that can load and run it. The JS is useful for running it on the Web if you don't want to write your own JS for that.
</p>
<h2 id="do-we-need-non-standalone-wasm%3F">
Do we need <em>non</em>-standalone Wasm? <a href="#do-we-need-non-standalone-wasm%3F" class="bookmark">#</a>
</h2>
<p>
Why does the <code>STANDALONE_WASM</code> flag exist? In theory Emscripten could always set <code>STANDALONE_WASM</code>, which would be simpler. But standalone Wasm files can't depend on JS, and that has some downsides:
</p>
<ul>
<li>We can't minify the Wasm import and export names, as the minification only works if both sides agree, the Wasm and what loads it.
</li>
<li>Normally we create the Wasm Memory in JS so that JS can start to use it during startup, which lets us do work in parallel. But in standalone Wasm we have to create the Memory in the Wasm.
</li>
<li>Some APIs are just easy to do in JS. For example <a href="https://github.com/emscripten-core/emscripten/pull/9558"><code>__assert_fail</code></a>, which is called when a C assertion fails, is normally <a href="https://github.com/emscripten-core/emscripten/blob/2b42a35f61f9a16600c78023391d8033740a019f/src/library.js#L1235">implemented in JS</a>. It takes just a single line, and even if you include the JS functions it calls, the total code size is quite small. On the other hand, in a standalone build we can't depend on JS, so we use <a href="https://github.com/emscripten-core/emscripten/blob/b8896d18f2163dbf2fa173694eeac71f6c90b68c/system/lib/libc/musl/src/exit/assert.c#L4">musl's <code>assert.c</code></a>. That uses <code>fprintf</code>, which means it ends up pulling in a bunch of C <code>stdio</code> support, including things with indirect calls that make it hard to remove unused functions. Overall, there are many such details that end up making a difference in total code size.
</li>
</ul>
<p>
If you want to run both on the Web and elsewhere, and you want 100% optimal code size and startup times, you should make two separate builds, one with <code>-s STANDALONE</code> and one without. That's very easy as it's just flipping one flag!
</p>
<h2 id="necessary-api-differences">
Necessary API differences <a href="#necessary-api-differences" class="bookmark">#</a>
</h2>
<p>
We saw that Emscripten uses WASI APIs as much as possible to avoid <strong>unnecessary</strong> API differences. Are there any <strong>necessary</strong> ones? Sadly, yes - some WASI APIs require tradeoffs. For example:
</p>
<ul>
<li>WASI does not support various POSIX features, like <a href="https://github.com/WebAssembly/WASI/issues/122">user/group/world file permissions</a>, as a result of which you can't fully implement a (Linux) system <code>ls</code> for example (see details in that link). Emscripten's existing filesystem layer does support some of those things, so if we switched to WASI APIs for all filesystem operations then we'd be <a href="https://github.com/emscripten-core/emscripten/issues/9479#issuecomment-542815711">losing some POSIX support</a>.
</li>
<li>WASI's <code>path_open</code> <a href="https://github.com/WebAssembly/WASI/issues/109">has a cost in code size</a> because it forces extra permissions handling in the Wasm itself. That code is unnecessary on the Web.
</li>
<li>WASI doesn't provide a <a href="https://github.com/WebAssembly/WASI/issues/82">notification API for memory growth</a>, and as a result, JS runtimes must constantly check if memory grew and if so update their views, on every import and export. To avoid that overhead, Emscripten provides a notification API, <code>emscripten_notify_memory_growth</code>, which <a href="https://github.com/zeux/meshoptimizer/blob/bdc3006532dd29b03d83dc819e5fa7683815b88e/js/meshopt_decoder.js#L10">you can see implemented in a single line</a> in zeux's meshoptimizer that we mentioned earlier.
</li>
</ul>
<p>
In time WASI may add more POSIX support, a memory growth notification, etc. - WASI is still highly experimental and expected to change significantly. For now, to avoid regressions in Emscripten we do not emit 100% WASI binaries if you use certain features. In particular, opening files uses a POSIX method instead of WASI, which means that if you call <code>fopen</code> then the resulting Wasm file will not be 100% WASI - however, if all you do is use <code>printf</code>, which operates on the already-open <code>stdout</code>, then it will be 100% WASI, as in the "hello world" example we saw near the beginning, where Emscripten's output does run in WASI runtimes.
</p>
<p>
If it would be useful for users we can add a <code>PURE_WASI</code> option which would sacrifice code size in return for strict WASI compliance, but if that's not urgent (and most plugin use cases weve seen so far dont need full file I/O) then maybe we can wait for WASI to improve to where Emscripten can remove these non-WASI APIs. That would be the best outcome, and were working towards that as you can see in the links above.
</p>
<p>
However, even if WASI does improve, there is no avoiding the fact that Wasm has two standardized APIs as mentioned earlier. In the future I expect Emscripten will call Web APIs directly using interface types, because that will be more compact than calling a WASI-looking JS API that then calls a Web API (as in the <code>musl_writev</code> example from before). We could have a polyfill or a translation layer of some sort to help here, but we wouldn't want to use it unnecessarily, so we will need separate builds for Web and WASI environments. (This is somewhat unfortunate; in theory this could have been avoided if WASI were a superset of Web APIs, but obviously that would have meant compromises on the server side.)
</p>
<h2 id="current-status">
Current status <a href="#current-status" class="bookmark">#</a>
</h2>
<p>
Quite a lot works already! The main limitations are:
</p>
<ul>
<li>
<strong>WebAssembly limitations</strong>: Various features, like C++ exceptions, setjmp, and pthreads, depend on JavaScript due to Wasm limitations, and there is no good non-JS replacement yet. (Emscripten may start to support some of them <a href="https://www.youtube.com/watch?v=qQOP6jqZqf8&amp;list=PLqh1Mztq_-N2OnEXkdtF5yymcihwqG57y&amp;index=2&amp;t=0s">using Asyncify</a>, or maybe we'll just wait for <a href="https://github.com/WebAssembly/exception-handling/blob/master/proposals/Exceptions.md">native Wasm features</a> to arrive to VMs.)
</li>
<li>
<strong>WASI limitations</strong>: Libraries and APIs like OpenGL and SDL don't have corresponding WASI APIs yet.
</li>
</ul>
<p>
You <strong>can</strong> still use all those in Emscripten's standalone mode, but the output will contain calls to JS runtime support code. As a result, it will not be 100% WASI (for similar reasons those features also do not work in the WASI SDK). Those Wasm files won't run in WASI runtimes, but you can use them on the Web and you can write your own JS runtime for them. You can also use them as plugins; for example, a game engine could have plugins that render using OpenGL, and the developer would compile them in standalone mode and then implement the OpenGL imports in the engine's Wasm runtime. Standalone Wasm mode still helps here because it makes the output as standalone as Emscripten can make it.
</p>
<p>
You may also find APIs that <strong>do</strong> have a non-JS replacement that we havent converted yet, as work is still ongoing. Please <a href="https://github.com/emscripten-core/emscripten/issues">file bugs</a>, and as always help is welcome!
</p>
</div>
<footer>
<div>
<picture><source srcset="/_img/avatars/alon-zakai.avif, /_img/avatars/alon-zakai@2x.avif 2x" type="image/avif" /><img alt="" height="96" loading="lazy" src="/_img/avatars/alon-zakai.jpg" srcset="/_img/avatars/alon-zakai@2x.jpg 2x" width="96" /></picture>
<p>
Posted by Alon Zakai.
</p>
</div><a href="https://twitter.com/v8js/status/1197547645729988608" class="retweet">Retweet this article!</a>
</footer>
</article>
</main>
<footer id="footer">
<div>
<nav>
<a href="/logo">Branding</a> · <a href="/terms">Terms</a> · <a href="https://policies.google.com/privacy">Privacy</a> · <a href="https://twitter.com/v8js" rel="me nofollow">Twitter</a> · <a href="https://github.com/v8/v8.dev/tree/main/./src/blog/emscripten-standalone-wasm.md" rel="nofollow">Edit this page on GitHub</a>
</nav>
</div>
<p>
<small>Except as otherwise noted, any code samples from the V8 project are licensed under <a href="https://chromium.googlesource.com/v8/v8.git/+/master/LICENSE">V8s BSD-style license</a>. Other content on this page is licensed under <a href="https://creativecommons.org/licenses/by/3.0/">the Creative Commons Attribution 3.0 License</a>. For details, see <a href="/terms#site-policies">our site policies</a>.</small>
</p>
</footer>
<script src="/_js/dark-mode-toggle.mjs" type="module"></script>
<script src="/_js/main.mjs" type="module"></script>
<script src="/_js/legacy.js" nomodule=""></script>
</body>
</html>

View file

@ -0,0 +1,267 @@
<article><div id="readability-page-1">
<p id="oFNvY2">
In the introduction to her review anthology <em>For Keeps: 30 Years at the Movies</em>, the legendary film critic Pauline Kael wrote, “Im frequently asked why I dont write my memoirs. I think I have.” She meant what most movie critics realize at some point: that reading your past reviews and revisiting the lists of films you liked most during the year reveals not just something about a particular year in cinema, but something about you as well.
</p>
<p id="49aoQQ">
Thats the feeling I get constructing my list of the best films of 2017, a year that overflowed with great films in every genre, from horror and romantic comedy to documentary and arthouse drama. Some of the films on my list have commonalities — ghosts, meditations on memory and interpersonal connection, and women who refuse to behave — but mostly they underscore just how vibrant cinema remains as an art form, even in the midst of massive cultural shifts in the industry and beyond. And it is a keen reminder to me of all the 2017 conversations Ive had around and at the movies — and the ways I will never be the same.
</p>
<p id="dC0oTJ">
Here are my top 21 films of 2017 and how to watch them at home, with 14 honorable mentions.
</p>
<h3 id="jDDW9T">
21) <a href="https://www.vox.com/culture/2017/12/12/16765308/last-jedi-star-wars-review-rey-carrie-fisher-poe-finn-kylo-ren" target="_blank"><em>Star Wars: The Last Jedi</em></a>
</h3>
<div id="x5htN5">
<iframe src="https://www.youtube.com/embed/Q0CbN8sfihY?rel=0&amp;" allowfullscreen="allowfullscreen" scrolling="no" width="100%" height="100%"></iframe>
</div>
<p id="WdtoaT">
I am as shocked as anyone that a <em>Star Wars</em> movie found its way onto my list — but I was bowled over by <em>The Last Jedi</em>, which may be one of the series best. In the hands of writer-director <a href="https://www.vox.com/culture/2017/12/13/16761916/rian-johnson-star-wars-last-jedi-looper-brick-brothers-bloom-fly-breaking-bad" target="_blank">Rian Johnson</a> (who will also oversee <a href="https://www.theverge.com/2017/11/9/16630902/star-wars-new-trilogy-rian-johnson-disney-lucasfilm" target="_blank">a new <em>Star Wars</em> trilogy</a>), <em>The Last Jedi</em> is beautiful to look at and keeps its eye on the relationships between characters and how they communicate with one another, in addition to the bigger galactic story. The same characters are back, but they seem infused with new life, and the galaxy with a new kind of hope. The movies best details are in the strong bonds that develop between characters, and I left the film with the realization that for the first time in my life, I loved a <em>Star Wars</em> movie. Now I understand the magic.
</p>
<p id="m6vJQd">
Star Wars: The Last Jedi <em>is currently</em> <a href="https://www.netflix.com/watch/80192018?source=35" target="_blank"><em>streaming on Netflix</em></a> <em>and available to digitally rent on</em> <a href="https://play.google.com/store/movies/details?id=fgPqJgZepxM" target="_blank"><em>Google Play</em></a> <em>and</em> <a href="https://www.youtube.com/watch?v=fgPqJgZepxM" target="_blank"><em>YouTube</em></a><em>.</em>
</p>
<h3 id="3XHosO">
20) <a href="https://www.vox.com/2017/10/6/16434046/faces-places-review-agnes-varda-jr" target="_blank"><em>Faces Places</em></a>
</h3>
<div id="FZOPyv">
<iframe src="https://www.youtube.com/embed/KKbjnLpxv70?rel=0&amp;" allowfullscreen="allowfullscreen" scrolling="no" width="100%" height="100%"></iframe>
</div>
<p id="zP5jCd">
The unusual documentary <a href="https://www.vox.com/2017/10/6/16434046/faces-places-review-agnes-varda-jr" target="_blank"><em>Faces Places</em></a> (in French, <em>Visages Villages</em>) turns on the friendship between the accomplished street artist JR and legendary film director Agnès Varda, whose work was central to the development of the French New Wave movement. The pair (whose difference in age is 55 years) met after years of admiring each others work and decided to create a documentary portrait of France — by making a number of actual portraits. The film chronicles a leg of the "Inside Outside Project," a roving art initiative in which JR makes enormous portraits of people he meets and pastes them onto buildings and walls. In the film, Varda joins him, and as they talk to people around the country, they grow in their understanding of themselves and of each other. The development of their friendship, which is both affectionate and mutually sharpening, forms <em>Faces Places</em> emotional center.
</p>
<p id="yIfUci">
Faces Places <em>is currently</em> <a href="https://www.netflix.com/watch/80194288?source=35" target="_blank"><em>streaming on Netflix</em></a> <em>and available to digitally rent on</em> <a href="https://play.google.com/store/movies/details?id=WuB9Fl8nrzM" target="_blank"><em>Google Play</em></a> <em>and</em> <a href="https://www.youtube.com/watch?v=WuB9Fl8nrzM" target="_blank"><em>YouTube</em></a><em>.</em>
</p>
<h3 id="R0KXNO">
19) <a href="https://www.vox.com/summer-movies/2017/8/8/16107088/ingrid-goes-west-review-aubrey-plaza-elizabeth-olsen" target="_blank"><em>Ingrid Goes West</em></a>
</h3>
<div id="94aRXv">
<iframe src="https://www.youtube.com/embed/xP4vD1tWbPU?rel=0&amp;" allowfullscreen="allowfullscreen" scrolling="no" width="100%" height="100%"></iframe>
</div>
<p id="d2ZAUw">
<a href="https://www.vox.com/summer-movies/2017/8/8/16107088/ingrid-goes-west-review-aubrey-plaza-elizabeth-olsen" target="_blank"><em>Ingrid Goes West</em></a> is a twisted and <a href="https://www.vox.com/culture/2017/8/9/16107140/matt-spicer-interview-ingrid-goes-west-dark-comedy-aubrey-plaza-sundance?utm_campaign=vox&amp;utm_content=chorus&amp;utm_medium=social&amp;utm_source=twitter" target="_blank">dark comedy</a> — part addiction narrative, part stalker story — and yet its set in a world thats almost pathologically cheery: the glossy, sunny, nourishing, superfood- and superlative-loving universe of Instagram celebrity. But despite <em>Ingrid Goes West</em>s spot-on take on that world, the best thing about the film is that it refuses to traffic in lazy buzzwords and easy skewering, particularly at the expense of young women. Instead, the movie conveys that behind every Instagram image and meltdown is a real person, with real insecurities, real feelings, and real problems. And it recognizes that living a life performed in public can be its own kind of self-deluding prison.
</p>
<p id="oGMXK4">
Ingrid Goes West <em>is currently</em> <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fwww.hulu.com%2Fwatch%2F1205749" rel="nofollow noopener" target="_blank"><em>streaming on Hulu</em></a> <em>and available to digitally rent on</em> <a href="https://www.youtube.com/watch?v=c2O7KouP5CM" target="_blank"><em>YouTube</em></a> <em>and</em> <a href="https://play.google.com/store/movies/details?id=c2O7KouP5CM" target="_blank"><em>Google Play</em></a><em>.</em>
</p>
<h3 id="qfZ4Iv">
18) <a href="https://www.vox.com/summer-movies/2017/7/14/15955888/review-lady-macbeth-florence-pugh" target="_blank"><em>Lady Macbeth</em></a>
</h3>
<div id="0ZWzkX">
<iframe src="https://www.youtube.com/embed/2Z0N8ULhuUA?rel=0&amp;" allowfullscreen="allowfullscreen" scrolling="no" width="100%" height="100%"></iframe>
</div>
<p id="Ii1QS5">
<a href="https://www.vox.com/summer-movies/2017/7/14/15955888/review-lady-macbeth-florence-pugh" target="_blank"><em>Lady Macbeth</em></a> is no placid costume drama. Adapted from an 1865 Russian novella by Nikolai Leskov, the movie follows Katherine (the astounding Florence Pugh), a woman in the Lady Macbeth line characterized by a potent cocktail of very few scruples and a lot of determination. She's a chilling avatar for the ways that class and privilege — both obvious and hidden — insulate some people from the consequences of their actions while damning others. <em>Lady Macbeth</em> is also a dazzling directorial debut from William Oldroyd, a thrilling combination of sex, murder, intrigue, and power plays. Its visually stunning, each frame composed so carefully and deliberately that the wildness and danger roiling just below the surface feels even more frightening. Each scene ratchets up the tension to an explosive, chilling end.
</p>
<p id="e2nBAO">
Lady Macbeth <em>is currently streaming on</em> <a href="https://play.hbogo.com/feature/urn:hbo:feature:GWrEd3wdB_LiWwwEAAAIk?camp=Search&amp;play=true" target="_blank"><em>HBO Go</em></a> <em>and</em> <a href="https://play.hbonow.com/feature/urn:hbo:feature:GWrEd3wdB_LiWwwEAAAIk?camp=Search&amp;play=true" target="_blank"><em>HBO Now</em></a><em>, and it is available to digitally rent on</em> <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fwww.amazon.com%2Fgp%2Fvideo%2Fdetail%2FB074HJGH3F%2Fref%3Datv_dl_rdr" rel="nofollow noopener" target="_blank"><em>Amazon Prime</em></a><em>,</em> <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fwww.vudu.com%2Fcontent%2Fmovies%2F%23%21content%2F891310" rel="nofollow noopener" target="_blank"><em>Vudu</em></a><em>,</em> <a href="https://www.youtube.com/watch?v=l8vAACgcUCo" target="_blank"><em>YouTube</em></a><em>,</em> <a href="https://play.google.com/store/movies/details?id=l8vAACgcUCo" target="_blank"><em>iTunes</em></a><em>, and</em> <a href="https://play.google.com/store/movies/details?id=l8vAACgcUCo" target="_blank"><em>Google Play</em></a><em>.</em>
</p>
<h3 id="JhEBod">
17) <em>BPM (Beats Per Minute)</em>
</h3>
<div id="t3derk">
<iframe src="https://www.youtube.com/embed/2fhO2A4SL24?rel=0&amp;" allowfullscreen="allowfullscreen" scrolling="no" width="100%" height="100%"></iframe>
</div>
<p id="DEyp0A">
<em>BPM (Beats Per Minute)</em> is a remarkably tender and stirring story of the Paris chapter of ACT UP, an AIDS activism group, and the young people who found themselves caught in the crosshairs of the AIDS crisis in the early 1990s. The film follows both the group's actions and the individual members shifting relationships to one another — enemies becoming friends, friends becoming lovers, lovers becoming caretakers — as well as their struggles with the disease wracking their community. As an account of the period, its riveting; as an exploration of life and love set at the urgent intersection of the political and the personal, its devastating.
</p>
<p id="8vBdkS">
BPM (Beats Per Minute) <em>is currently</em> <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fwww.hulu.com%2Fwatch%2F1258801" rel="nofollow noopener" target="_blank"><em>streaming on Hulu</em></a> <em>and available to digitally rent on</em> <a href="https://play.google.com/store/movies/details?id=xrjoEWj6gLg" target="_blank"><em>Google Play</em></a> <em>and</em> <a href="https://www.youtube.com/watch?v=xrjoEWj6gLg" target="_blank"><em>YouTube</em></a><em>.</em>
</p>
<h3 id="jocryI">
16) <a href="https://www.vox.com/summer-movies/2017/6/21/15837678/big-sick-review-kumail-nanjiani-emily-gordon-zoe-kazan-islam" target="_blank"><em>The Big Sick</em></a>
</h3>
<div id="ZRFycn">
<iframe src="https://www.youtube.com/embed/PJmpSMRQhhs?rel=0&amp;" allowfullscreen="allowfullscreen" scrolling="no" width="100%" height="100%"></iframe>
</div>
<p id="DqZc5Q">
Few 2017 movies could top the charm and tenderness of <a href="https://www.vox.com/summer-movies/2017/6/21/15837678/big-sick-review-kumail-nanjiani-emily-gordon-zoe-kazan-islam" target="_blank"><em>The Big Sick</em></a>, which hits all the right romantic comedy notes with one unusual distinction: It feels like real life. Thats probably because <em>The Big Sick</em> is written by <a href="https://www.vox.com/2017/11/22/16687092/the-big-sick-kumail-nanjiani-emily-gordon-real-story" target="_blank">real-life married couple</a> Emily V. Gordon and <em>Silicon Valley</em>'s Kumail Nanjiani, and based on their real-life romance. <em>The Big Sick</em> — which stars Nanjiani as a version of himself, alongside Zoe Kazan as Emily — is funny and sweet while not backing away from matters that romantic comedies dont usually touch on, like serious illness, struggles in long-term marriages, and religion. As it tells the couples story, which takes a serious turn when Emily falls ill with a mysterious infection and her parents (played by Holly Hunter and Ray Romano) come to town, it becomes a funny and wise story about real love.
</p>
<p id="Wgpjgu">
The Big Sick <em>is currently</em> <em>streaming on</em> <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fwww.amazon.com%2FBig-Sick-Kumail-Nanjiani%2Fdp%2FB07193L7RD%2Fref%3Dsr_1_1%3Fie%3DUTF8%26qid%3D1532454848" rel="nofollow noopener" target="_blank"><em>Amazon Prime</em></a> <em>and available to digitally rent on</em> <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fitunes.apple.com%2Fus%2Fmovie%2Fthe-big-sick%2Fid1246483301" rel="nofollow noopener" target="_blank"><em>iTunes</em></a><em>,</em> <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fwww.vudu.com%2Fcontent%2Fmovies%2F%23%21content%2F865258" rel="nofollow noopener" target="_blank"><em>Vudu</em></a><em>,</em> <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fwww.amazon.com%2Fgp%2Fvideo%2Fdetail%2FB071HFCYDH%2Fref%3Datv_dl_rdr" rel="nofollow noopener" target="_blank"><em>Amazon</em></a><em>,</em> <a href="https://www.youtube.com/watch?v=WUX0wW2OMkA" target="_blank"><em>YouTube</em></a><em>, and</em> <a href="https://play.google.com/store/movies/details?id=WUX0wW2OMkA" target="_blank"><em>Google Play</em></a><em>.</em>
</p>
<h3 id="dFyVjw">
15) <a href="https://www.vox.com/culture/2017/9/10/16277234/mother-review-aronofsky-lawrence-bardem-tiff" target="_blank"><em>Mother!</em></a>
</h3>
<div id="kUMpyj">
<iframe src="https://www.youtube.com/embed/XpICoc65uh0?rel=0&amp;amp;start=17" allowfullscreen="allowfullscreen" scrolling="no" width="100%" height="100%"></iframe>
</div>
<p id="LA1s4n">
Theres so much pulsing beneath <a href="https://www.vox.com/culture/2017/9/10/16277234/mother-review-aronofsky-lawrence-bardem-tiff" target="_blank">the surface of <em>Mother!</em></a> that its hard to grab on to just one theme as what it “means.” Its full-on apocalyptic fiction, and like all stories of apocalypse, its intended to draw back the veil on reality and show us whats really beneath. And this movie gets wild: If its gleeful cracking apart of traditional theologies doesnt get you (theres a lot of Catholic folk imagery here, complete with an Ash Wednesday-like mud smearing on the foreheads of the faithful), its bonkers scenes of chaos probably will. <em>Mother!</em> is a movie designed to provoke fury, ecstasy, madness, catharsis, and more than a little awe. Watching it, and then participating in the flurry of arguments and discussions unpacking it, was among my best moviegoing experiences of 2017.
</p>
<p id="mxI0Kb">
Mother! <em>is available to digitally purchase on</em> <a href="https://play.google.com/store/movies/details?id=F9p9HlSbIuU" target="_blank"><em>Google Play</em></a> <em>and</em> <a href="https://www.youtube.com/watch?v=F9p9HlSbIuU" target="_blank"><em>YouTube</em></a><em>.</em>
</p>
<h3 id="PL5PTS">
14) <a href="https://www.vox.com/culture/2017/7/7/15925272/ghost-story-review-rooney-mara-casey-affleck" target="_blank"><em>A Ghost Story</em></a>
</h3>
<div id="76I1cH">
<iframe src="https://www.youtube.com/embed/0Vb0F_CN83E?rel=0&amp;" allowfullscreen="allowfullscreen" scrolling="no" width="100%" height="100%"></iframe>
</div>
<p id="JWA6Pb">
Director <a href="https://www.vox.com/summer-movies/2017/7/13/15960236/david-lowery-ghost-story-interview" target="_blank">David Lowery</a> filmed <a href="https://www.vox.com/culture/2017/7/7/15925272/ghost-story-review-rooney-mara-casey-affleck" target="_blank"><em>A Ghost Story</em></a> in secret, then premiered it at the Sundance Film Festival to critical acclaim. The movie starts out being about a grieving widow (Rooney Mara) trying to live through the pain of losing her beloved husband, but it soon shifts focus to the ghost of her husband (Casey Affleck, covered in a sheet), evolving into a compelling rumination on the nature of time, memory, history, and the universe. Bathed in warm humor and wistful longing, it's a film that stays with you long after its over, a lingering reminder of the inextricable link between love and place.
</p>
<p id="9CatN2">
A Ghost Story <em>is available to digitally rent on</em> <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fitunes.apple.com%2Fus%2Fmovie%2Fa-ghost-story%2Fid1252853654%3Fat%3D1001l6hu%26ct%3Dgca_organic_movie-title_1252853654" rel="nofollow noopener" target="_blank"><em>iTunes</em></a><em>,</em> <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fwww.vudu.com%2Fcontent%2Fmovies%2F%23%21content%2F875682" rel="nofollow noopener" target="_blank"><em>Vudu</em></a><em>,</em> <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fwww.amazon.com%2Fgp%2Fvideo%2Fdetail%2FB075K4YG8P%2Fref%3Datv_dl_rdr" rel="nofollow noopener" target="_blank"><em>Amazon</em></a><em>,</em> <a href="https://play.google.com/store/movies/details?id=cGUoTWQIcP0" target="_blank"><em>Google Play</em></a><em>, and</em> <a href="https://www.youtube.com/watch?v=cGUoTWQIcP0" target="_blank"><em>YouTube</em></a><em>.</em>
</p>
<h3 id="rRIM9r">
13) <a href="https://www.vox.com/2017/10/24/16523642/square-review-ruben-ostlund-claes-bang-elisabeth-moss" target="_blank"><em>The Square</em></a>
</h3>
<div id="z1g0Cs">
<iframe src="https://www.youtube.com/embed/EUzRjRv0Ib0?rel=0" allowfullscreen="allowfullscreen" scrolling="no" width="100%" height="100%"></iframe>
</div>
<p id="NavzzU">
Winner of the Palme dOr at the 2017 Cannes Film Festival, <a href="https://www.vox.com/2017/10/24/16523642/square-review-ruben-ostlund-claes-bang-elisabeth-moss" target="_blank"><em>The Square</em></a> is a hilariously needling comedy about the contemporary art world, as well as the kind of idealistic liberalism that is tough to maintain in the face of real problems. The outstanding Claes Bang stars as Christian, a curator whose cluelessness leads him into some outlandishly rough spots, with Elisabeth Moss in a too-short but brilliant part as an American journalist who wont let him get away with his shenanigans. Its a heady film with a lot of ideas ricocheting around — and a <em>lot</em> of uncomfortable satire — but if you (like me) are the sort of viewer who loves that stuff, its sly jabs at the veneer of civilization that keeps the social contract intact are intoxicating.
</p>
<p id="2iTOd5">
The Square <em>is currently</em> <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fwww.hulu.com%2Fwatch%2F1228556" rel="nofollow noopener" target="_blank"><em>streaming on Hulu</em></a> <em>and available to digitally rent on</em> <a href="https://play.google.com/store/movies/details?id=OaD-B0aK9aw" target="_blank"><em>Google Play</em></a> <em>and</em> <a href="https://www.youtube.com/watch?v=OaD-B0aK9aw" target="_blank"><em>YouTube</em></a><em>.</em>
</p>
<h3 id="Px2hT6">
12) <a href="https://www.vox.com/culture/2017/7/17/15984026/dunkirk-review-nolan-rylance-hardy-styles-spoilers" target="_blank"><em>Dunkirk</em></a>
</h3>
<div id="TDSYe7">
<iframe src="https://www.youtube.com/embed/F-eMt3SrfFU?rel=0&amp;amp;start=24" allowfullscreen="allowfullscreen" scrolling="no" width="100%" height="100%"></iframe>
</div>
<p id="MLatLf">
<a href="https://www.vox.com/culture/2017/7/17/15984026/dunkirk-review-nolan-rylance-hardy-styles-spoilers" target="_blank"><em>Dunkirk</em></a>, a true cinematic achievement from acclaimed director Christopher Nolan, backs off conventional notions of narrative and chronology as much as possible, while leaning headfirst into everything else that makes a movie a visceral work of art aimed at the senses: the images, the sounds, the scale, the swelling vibrations of it all. You cant smell the sea spray, but your brain may trick you into thinking you can. Nolans camera pushes the edges of the screen as far as it can as <em>Dunkirk</em> engulfs the audience in something that feels like a lot more than a war movie. Its a symphony for the brave and broken, and it resolves in a major key — but one with an undercurrent of sorrow, and of sober warning. Courage in the face of danger is not just for characters in movies.
</p>
<p id="cmMBuS">
Dunkirk <em>is currently streaming on</em> <a href="https://play.hbogo.com/feature/urn:hbo:feature:GWqvX7wxdtyl0YAEAAAFv?camp=Search&amp;play=true" target="_blank"><em>HBO Go</em></a> <em>and</em> <a href="https://play.hbonow.com/feature/urn:hbo:feature:GWqvX7wxdtyl0YAEAAAFv?camp=Search&amp;play=true" target="_blank"><em>HBO Now</em></a><em>, and available to digitally rent on</em> <a href="https://play.google.com/store/movies/details?id=yOJhvgczBNk" target="_blank"><em>Google Play</em></a> <em>and</em> <a href="https://www.youtube.com/watch?v=yOJhvgczBNk" target="_blank"><em>YouTube</em></a><em>.</em>
</p>
<h3 id="CPlXz5">
11) <em>Rat Film</em>
</h3>
<div id="s6q4gj">
<iframe src="https://www.youtube.com/embed/f-kpMAKc0l4?rel=0&amp;" allowfullscreen="allowfullscreen" scrolling="no" width="100%" height="100%"></iframe>
</div>
<p id="GFFO6D">
<em>Rat Film</em> is about rats, yes — and rat poison experts and rat hunters and people who keep rats as pets. But its also about the history of eugenics, dubious science, <a href="https://en.wikipedia.org/wiki/Redlining" target="_blank">“redlining,”</a> and segregated housing in Baltimore. All these pieces come together to form one big essay, where the meaning of each vignette only becomes clearer in light of the whole. Its a fast-paced, no-holds-barred exploration of a damning history, and it accrues meaning as the images, sounds, and text pile up.
</p>
<p id="HkeUxt">
Rat Film <em>is available to digitally rent on</em> <a href="https://www.youtube.com/watch?v=ZZlweN7XXJ4" target="_blank"><em>YouTube</em></a> <em>and</em> <a href="https://play.google.com/store/movies/details?id=ZZlweN7XXJ4" target="_blank"><em>Google Play</em></a><em>.</em>
</p>
<h3 id="Qgio0l">
10) <a href="https://www.vox.com/culture/2017/4/13/15243556/quiet-passion-review-emily-dickinson-passover-easter" target="_blank"><em>A Quiet Passion</em></a>
</h3>
<div id="Ya6IEK">
<iframe src="https://www.youtube.com/embed/T3SyPbUTEeU?rel=0&amp;" allowfullscreen="allowfullscreen" scrolling="no" width="100%" height="100%"></iframe>
</div>
<p id="EO0XbC">
<a href="https://www.vox.com/culture/2017/4/13/15243556/quiet-passion-review-emily-dickinson-passover-easter" target="_blank"><em>A Quiet Passion</em></a> is technically a biographical film about Emily Dickinson, but it transcends its genre to become something more like poetry. Its a perplexing and challenging film, crafted without the traditional guardrails that guide most biographical movies — dates, times, major accomplishments, and so on. Time slips away in the film almost imperceptibly, and the narrative arc doesnt yield easily to the viewer. Cynthia Nixon plays Emily Dickinson, whose poetry and life is a perfect match for the signature style of director Terence Davies: rich in detail, deeply enigmatic, and weighed down with a kind of sparkling, joy-tinged sorrow. <em>A Quiet Passion</em> is a portrait, both visual and narrative, of the kind of saint most modern people can understand: one who is certain of her uncertainty, and yearning to walk the path on which her passion and longing meet.
</p>
<p id="YuHQ0h">
A Quiet Passion <em>is currently streaming on</em> <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fwww.amazon.com%2Fgp%2Fvideo%2Fdetail%2FB072FP21C5%2Fref%3Datv_dl_rdr" rel="nofollow noopener" target="_blank"><em>Amazon Prime</em></a> <em>and available to digitally rent or purchase on</em> <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fitunes.apple.com%2Fus%2Fmovie%2Fa-quiet-passion%2Fid1238938795" rel="nofollow noopener" target="_blank"><em>iTunes</em></a><em>,</em> <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fwww.vudu.com%2Fcontent%2Fmovies%2F%23%21content%2F859491" rel="nofollow noopener" target="_blank"><em>Vudu</em></a><em>,</em> <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fwww.amazon.com%2Fgp%2Fvideo%2Fdetail%2FB072FP21C5%2Fref%3Datv_dl_rdr" rel="nofollow noopener" target="_blank"><em>Amazon</em></a><em>,</em> <a href="https://www.youtube.com/watch?v=de0ELdfPGik" target="_blank"><em>YouTube</em></a><em>, and</em> <a href="https://play.google.com/store/movies/details?id=de0ELdfPGik" target="_blank"><em>Google Play</em></a><em>.</em>
</p>
<h3 id="7dz2o3">
9) <em>Columbus</em>
</h3>
<div id="ZfQfEI">
<iframe src="https://www.youtube.com/embed/r3dcnV6Z9Zs?rel=0&amp;" allowfullscreen="allowfullscreen" scrolling="no" width="100%" height="100%"></iframe>
</div>
<p id="pM0BdD">
<em>Columbus</em> is a stunner of a debut from video essayist turned director Kogonada. Haley Lu Richardson stars as Casey, a young woman living in Columbus, Indiana, who cares for her mother, works at a library, and harbors a passion for architecture. (Columbus is a mecca for modernist architecture scholars and enthusiasts.) When a visiting architecture scholar falls into a coma in Columbus, his estranged son Jin (John Cho) arrives to wait for him and strikes up a friendship with Casey, who starts to show him her favorite buildings. The two begin to unlock something in each other thats hard to define but life-changing for both. <em>Columbus</em> is beautiful and subtle, letting us feel how the places we build and the people we let near us move and mold us.
</p>
<p id="P7j9oY">
Columbus <em>is currently</em> <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fwww.hulu.com%2Fwatch%2F1185842" rel="nofollow noopener" target="_blank"><em>streaming on Hulu</em></a> <em>and available to rent on</em> <a href="https://play.google.com/store/movies/details?id=I-j0IqPQaYU" target="_blank"><em>Google Play</em></a> <em>and</em> <a href="https://www.youtube.com/watch?v=I-j0IqPQaYU" target="_blank"><em>YouTube</em></a><em>.</em>
</p>
<h3 id="wkyPUl">
8) <a href="https://www.vox.com/culture/2017/5/31/15706424/florida-project-review-cannes-sean-baker" target="_blank"><em>The Florida Project</em></a>
</h3>
<div id="RLHf4Z">
<iframe src="https://www.youtube.com/embed/WwQ-NH1rRT4?rel=0&amp;" allowfullscreen="allowfullscreen" scrolling="no" width="100%" height="100%"></iframe>
</div>
<p id="J6kOkz">
Sean Bakers <a href="https://www.vox.com/culture/2017/5/31/15706424/florida-project-review-cannes-sean-baker" target="_blank"><em>The Florida Project</em></a> unfolds at first like a series of sketches about the characters who live in a purple-painted, $35-a-night motel called the Magic Castle down the street from Disney World. The film is held together by the hysterical antics of a kid named Moonee and her pack of young friends, as well as long-suffering hotel manager Bobby (a splendid, warm Willem Dafoe), who tries to put up with it all while keeping some kind of order. But as <em>The Florida Project</em> goes on, a narrative starts to form, one that chronicles with heartbreaking attention the sort of dilemmas that face poor parents and their children in America, and the broken systems that try to cope with impossible situations.
</p>
<p id="xG8Q8C">
The Florida Project <em>is currently streaming on</em> <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fwww.amazon.com%2FFlorida-Project-Willem-Dafoe%2Fdp%2FB0764MS7GQ%2Fref%3Dsr_1_2%3Fs%3Dinstant-video%26ie%3DUTF8%26qid%3D1532455499%26sr%3D1-2%26keywords%3Dthe%2Bflorida%2Bproject" rel="nofollow noopener" target="_blank"><em>Amazon Prime</em></a> <em>and available to digitally rent on</em> <a href="https://www.youtube.com/watch?v=MLsXQdPAlws" target="_blank"><em>YouTube</em></a><em>,</em> <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fwww.vudu.com%2Fcontent%2Fmovies%2Fdetails%2Ftitle%2F922802" rel="nofollow noopener" target="_blank"><em>Vudu</em></a><em>, and</em> <a href="https://play.google.com/store/movies/details?id=MLsXQdPAlws" target="_blank"><em>Google Play</em></a><em>.</em>
</p>
<h3 id="rLGNAf">
7) <a href="https://www.vox.com/2017/11/21/16552862/call-me-by-your-name-review-timothee-chalamet-armie-hammer" target="_blank"><em>Call Me</em> <em>b</em><em>y Your Name</em></a>
</h3>
<div id="xGksjG">
<iframe src="https://www.youtube.com/embed/Z9AYPxH5NTM?rel=0&amp;" allowfullscreen="allowfullscreen" scrolling="no" width="100%" height="100%"></iframe>
</div>
<p id="KyeOGQ">
Luca Guadagninos gorgeous film <a href="https://www.vox.com/2017/11/21/16552862/call-me-by-your-name-review-timothee-chalamet-armie-hammer" target="_blank"><em>Call Me</em> <em>b</em><em>y Your Name</em></a> adapts André Acimans <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fwww.amazon.com%2FCall-Me-Your-Name-Novel%2Fdp%2F031242678X" rel="nofollow noopener" target="_blank">2007 novel</a> about a precocious 17-year-old named Elio (Timothée Chalamet), who falls in lust and love with his fathers 24-year-old graduate student Oliver (Armie Hammer). Its remarkable for how it turns literature into pure cinema, all emotion and image and heady sensation. Set in 1983 in Northern Italy, <em>Call Me</em> <em>b</em><em>y Your Name</em> is less about coming out than coming of age, but it also captures a particular sort of love thats equal parts passion and torment, a kind of irrational heart fire that opens a gate into something longer-lasting. The film is a lush, heady experience for the body, but its also an arousal for the soul.
</p>
<p id="VA1se2">
<em>Call Me By Your Name</em> is available to digitally purchase on <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fwww.amazon.com%2FCall-Your-Name-Armie-Hammer%2Fdp%2FB0791VJLVB%2Fref%3Dsr_1_2%3Fs%3Dinstant-video%26ie%3DUTF8%26qid%3D1532455686%26sr%3D1-2%26keywords%3Dcall%2Bme%2Bby%2Byour%2Bname" rel="nofollow noopener" target="_blank">Amazon,</a> <a href="https://www.youtube.com/watch?v=48o3YYnEUQ4" target="_blank">YouTube</a>, and <a href="https://play.google.com/store/movies/details?id=48o3YYnEUQ4" target="_blank">Google Play</a>.
</p>
<h3 id="h6Biwc">
6) <em>Personal Shopper</em>
</h3>
<div id="NSQg2p">
<iframe src="https://www.youtube.com/embed/xC8AjoqpBAY?rel=0&amp;amp;start=15" allowfullscreen="allowfullscreen" scrolling="no" width="100%" height="100%"></iframe>
</div>
<p id="pofJH9">
In her second collaboration with French director <a href="http://www.imdb.com/name/nm0000801/?ref_=fn_al_nm_1" target="_blank">Olivier Assayas</a>, Kristen Stewart plays a personal shopper to a wealthy socialite, with a sideline as an amateur ghost hunter whos searching for her dead twin brother. <em>Personal Shopper</em> is deeper than it seems at first blush, a meditation on grief and an exploration of “between” places — on the fringes of wealth, and in the space between life and death. Some souls are linked in a way that cant be shaken, and whether or not theres an afterlife doesnt change the fact that we see and sense them everywhere. (<em>Personal Shopper</em> also has one of the most tense extended scenes involving text messaging ever seen onscreen.)
</p>
<p id="8hmlTU">
Personal Shopper <em>is currently</em> <a href="https://www.showtime.com/#/movie/3436534" target="_blank"><em>streaming on Showtime</em></a> <em>and available to rent on</em> <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fwww.vudu.com%2Fcontent%2Fmovies%2F%23%21content%2F871777" rel="nofollow noopener" target="_blank"><em>Vudu</em></a><em>,</em> <a href="https://www.youtube.com/watch?v=-BgiO6uDH7I" target="_blank"><em>YouTube</em></a><em>,</em> <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fwww.amazon.com%2Fgp%2Fvideo%2Fdetail%2FB072YWLGT2%2Fref%3Datv_dl_rdr" rel="nofollow noopener" target="_blank"><em>Amazon</em></a><em>,</em> <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fitunes.apple.com%2Fus%2Fmovie%2Fpersonal-shopper%2Fid1241184797" rel="nofollow noopener" target="_blank"><em>iTunes</em></a><em>, and</em> <a href="https://play.google.com/store/movies/details?id=-BgiO6uDH7I" target="_blank"><em>Google Play</em></a><em>.</em>
</p>
<h3 id="0RkMKy">
5) <em>Princess Cyd</em>
</h3>
<div id="7Tj1H6">
<iframe src="https://www.youtube.com/embed/sr64EJfnJwE?rel=0&amp;" allowfullscreen="allowfullscreen" scrolling="no" width="100%" height="100%"></iframe>
</div>
<p id="2tSIHW">
Stephen Cone is a master of small, carefully realized filmmaking; his earlier films such as <em>The Wise Kids</em> and <em>Henry Gambles Birthday Party</em> combine an unusual level of empathy for his characters with an unusual combination of interests: love, desire, sexual awakenings, and religion. <em>Princess Cyd</em> is his most accomplished film yet, about a young woman named Cyd (<a href="http://www.imdb.com/name/nm6570557/?ref_=tt_cl_t2" target="_blank">Jessie Pinnick</a>) who finds herself attracted to Katie (<a href="http://www.imdb.com/name/nm5154548/?ref_=tt_cl_t3" target="_blank">Malic White</a>), a barista, while visiting her Aunt Miranda (<a href="http://www.imdb.com/name/nm2050642/?ref_=tt_cl_t1" target="_blank">Rebecca Spence</a>, playing a character modeled on the author Marilynne Robinson) in Chicago. As she works through her own sexual awakening with Katie, Cyd unwinds some of the ways Mirandas life has gotten too safe. They provoke each other while forming a bond and being prodded toward a bigger understanding of the world. It is a graceful and honest film, and it feels like a modest miracle.
</p>
<p id="HDD90m">
Princess Cyd <em>is currently</em> <a href="https://www.netflix.com/watch/80201497?source=35" target="_blank"><em>streaming on Netflix</em></a> <em>and available to digitally rent on</em> <a href="https://play.google.com/store/movies/details?id=sy8otjxDw8w" target="_blank"><em>Google Play</em></a> <em>and</em> <a href="https://www.youtube.com/watch?v=sy8otjxDw8w" target="_blank"><em>YouTube</em></a><em>.</em>
</p>
<h3 id="ADtiAV">
4) <a href="https://www.vox.com/culture/2017/2/24/14698632/get-out-review-jordan-peele" target="_blank"><em>Get Out</em></a>
</h3>
<div id="swjmhh">
<iframe src="https://www.youtube.com/embed/sRfnevzM9kQ?rel=0&amp;" allowfullscreen="allowfullscreen" scrolling="no" width="100%" height="100%"></iframe>
</div>
<p id="h1ighb">
Racism is sinister, frightening, and deadly. But <a href="https://www.vox.com/culture/2017/2/24/14698632/get-out-review-jordan-peele" target="_blank"><em>Get Out</em></a> (a stunning directorial debut from <em>Key &amp; Peele</em>'s Jordan Peele) isnt about the blatantly, obviously scary kind of racism — burning crosses and lynchings and snarling hate. Instead, its interested in showing how the parts of racism that try to be aggressively unscary are just as horrifying, and its interested in making us feel that horror in a visceral, bodily way. In the tradition of the best classic social thrillers, <em>Get Out</em> takes a topic that is often approached cerebrally — casual racism — and turns it into something you feel in your tummy. And it does it with a wicked sense of humor.
</p>
<p id="2ef6GU">
Get Out <em>is currently streaming on</em> <a href="https://play.hbogo.com/feature/urn:hbo:feature:GWbhJDwNIacPCwgEAAAG5?camp=Search&amp;play=true" target="_blank"><em>HBO Go</em></a> <em>and</em> <a href="https://play.hbonow.com/feature/urn:hbo:feature:GWbhJDwNIacPCwgEAAAG5?camp=Search&amp;play=true" target="_blank"><em>HBO Now</em></a><em>, and is available to digitally rent on</em> <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fitunes.apple.com%2Fus%2Fmovie%2Fget-out%2Fid1202441786" rel="nofollow noopener" target="_blank"><em>iTunes</em></a><em>,</em> <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fwww.amazon.com%2Fgp%2Fvideo%2Fdetail%2FB06Y1H48K7%2Fref%3Datv_dl_rdr" rel="nofollow noopener" target="_blank"><em>Amazon</em></a><em>,</em> <a href="https://play.google.com/store/movies/details?id=YfLSryEaAfw" target="_blank"><em>Google Play</em></a><em>,</em> <a href="https://www.youtube.com/watch?v=YfLSryEaAfw" target="_blank"><em>YouTube</em></a><em>, and</em> <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fwww.vudu.com%2Fcontent%2Fmovies%2F%23%21content%2F832496%2FGet-Out" rel="nofollow noopener" target="_blank"><em>Vudu</em></a><em>.</em>
</p>
<h3 id="TQbjNr">
3) <em>The Work</em>
</h3>
<div id="GYqgVe">
<iframe src="https://www.youtube.com/embed/h8OVXG2GhpQ?rel=0&amp;" allowfullscreen="allowfullscreen" scrolling="no" width="100%" height="100%"></iframe>
</div>
<p id="3Uotb3">
<em>The Work</em> is an outstanding, astonishing accomplishment and a viewing experience that will leave you shaken (but in a good way). At Folsom Prison in California, incarcerated men regularly participate in group therapy, and each year other men from the “outside” apply to participate in an intense four-day period of group therapy alongside Folsoms inmates. <em>The Work</em> spends almost all of its time inside the room where that therapy happens, observing the strong, visceral, and sometimes violent emotions the men feel as they expose the hurt and raw nerves that have shaped how they encounter the world. Watching is not always easy, but by letting us peek in, the film invites viewers to become part of the experience — as if we, too, are being asked to let go.
</p>
<p id="qjxiQW">
The Work <em>is</em> <a href="https://www.topic.com/the-work" target="_blank"><em>streaming on Topic.com</em></a> <em>and available to digitally rent on</em> <a href="https://play.google.com/store/movies/details?id=iddt4sVZTvI" target="_blank"><em>Google Play</em></a> <em>and</em> <a href="https://www.youtube.com/watch?v=iddt4sVZTvI" target="_blank"><em>YouTube</em></a><em>.</em>
</p>
<h3 id="kUrRP6">
2) <em>Ex Libris</em>
</h3>
<div id="Lb1IzW">
<iframe src="https://www.youtube.com/embed/YzKrlOFZBD8?rel=0&amp;" allowfullscreen="allowfullscreen" scrolling="no" width="100%" height="100%"></iframe>
</div>
<p id="rGpjUU">
Frederick Wiseman is one of the towering giants of nonfiction film, a keen observer of American institutions — ranging from prisons to dance companies to welfare offices — for the past half-century. <em>Ex Libris</em> is his mesmerizing look at the New York Public Library and the many functions it fills, which go far beyond housing books. Wiseman works in the observational mode, which means his films contain no captions, dates, or talking-head interviews: We just see what his camera captured, which in this case includes community meetings, benefit dinners, after-school programs, readings with authors and scholars (including Richard Dawkins and Ta-Nehisi Coates), and NYPL patrons going about their business in the librarys branches all over the city. The result is almost hypnotic and, perhaps surprisingly, deeply moving. It makes a case for having faith in the public institutions where ordinary people work — away from the limelight, without trying to score political points — in order to make our communities truly better.
</p>
<p id="40B8Wq">
Ex Libris <em>will air on PBS in the fall and then be available to cardholders in many library systems across the country via</em> <a href="https://www.kanopy.com/" target="_blank"><em>Kanopy</em></a><em>.</em>
</p>
<h3 id="QJNuyl">
1) <a href="https://www.vox.com/2017/11/2/16552860/lady-bird-review-saoirse-ronan-greta-gerwig" target="_blank"><em>Lady Bird</em></a>
</h3>
<div id="mgxqrA">
<iframe src="https://www.youtube.com/embed/cNi_HC839Wo?rel=0&amp;" allowfullscreen="allowfullscreen" scrolling="no" width="100%" height="100%"></iframe>
</div>
<p id="z8uM1l">
<em>Lady Bird</em> topped my list almost instantly, and only rose in my estimation on repeated viewings. For many who saw it (including me), it felt like a movie made not just for but <em>about</em> me. <em>Lady Bird</em> is a masterful, exquisite coming-of-age comedy starring the great Saoirse Ronan as Christine — or “Lady Bird,” as shes re-christened herself — and its as funny, smart, and filled with yearning as its heroine. Writer-director Greta Gerwig made the film as an act of love, not just toward her hometown of Sacramento but also toward girlhood, and toward the feeling of always being on the outside of wherever real life is happening. <em>Lady Bird</em> is the rare movie that manages to be affectionate, entertaining, hilarious, witty, and confident. And one line from it struck me as the guiding principle of many of the years best films: “Dont you think they are the same thing? Love, and attention?”
</p>
<p id="jqSCLV">
Lady Bird <em>is currently streaming on</em> <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fwww.amazon.com%2FLady-Bird-Saoirse-Ronan%2Fdp%2FB07734STRN%2Fref%3Dsr_1_3%3Fs%3Dinstant-video%26ie%3DUTF8%26qid%3D1532455686" rel="nofollow noopener" target="_blank"><em>Amazon Prime</em></a> <em>and available to digitally rent on</em> <a href="https://go.redirectingat.com/?id=66960X1516588&amp;xs=1&amp;url=https%3A%2F%2Fwww.amazon.com%2FLady-Bird-Saoirse-Ronan%2Fdp%2FB07734STRN%2Fref%3Dsr_1_3%3Fs%3Dinstant-video%26ie%3DUTF8%26qid%3D1532455686" rel="nofollow noopener" target="_blank"><em>Amazon</em></a><em>,</em> <a href="https://play.google.com/store/movies/details?id=yBIPcwJ03V4" target="_blank"><em>Google Play</em></a><em>, and</em> <a href="https://www.youtube.com/watch?v=yBIPcwJ03V4" target="_blank"><em>YouTube</em></a><em>.</em>
</p>
<p id="EVymKt">
<strong>Honorable mentions:</strong> <em>Marjorie Prime</em>, <em>Phantom Thread</em>, <a href="https://www.vox.com/culture/2017/4/28/15437008/casting-jonbenet-kitty-green-interview-netflix" target="_blank"><em>Casting JonBenet</em></a>, <a href="https://www.vox.com/2017/12/6/16682926/the-post-review-spieberg-streep-hanks-pentagon-nixon" target="_blank"><em>The Post</em></a>, <a href="https://www.vox.com/culture/2017/9/12/16288080/shape-of-water-del-toro-review-tiff" target="_blank"><em>The Shape of Water</em></a>, <a href="https://www.vox.com/summer-movies/2017/8/17/16150634/logan-lucky-review-soderbergh-tatum-driver-craig" target="_blank"><em>Logan Lucky</em></a>, <a href="https://www.vox.com/culture/2017/9/14/16301552/i-tonya-harding-kerrigan-review-tiff" target="_blank"><em>I, Tonya</em></a>, <a href="https://www.vox.com/culture/2017/4/13/15243584/lost-city-of-z-review-james-gray-charlie-hunnam-robert-pattinson" target="_blank"><em>The Lost City of Z</em></a>, <em>Graduation</em>, <em>Spettacolo</em>, <em>Loveless</em>, <em>Restless Creature: Wendy Whelan</em>, <em>In Transit</em>, <a href="https://www.vox.com/culture/2017/6/29/15844952/reagan-show-review" target="_blank"><em>The Reagan Show</em></a>
</p>
</div></article>

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,109 @@
<article><div id="readability-page-1">
<p>
Séries, documentaires, programmes jeunesse… Retrouvez les recommandations de <em>Libération</em> pour savoir quoi regarder sur vos écrans cette semaine.
</p>
<h3>
Pour dépasser le tabac
</h3>
<p>
<strong><em>Vape Wave</em> (documentaire, 1h28, Planète+)</strong>
</p>
<p>
<iframe width="100%" src="https://www.youtube.com/embed/lGL7RgHn5f0" frameborder="0" allowfullscreen="allowfullscreen" data-aspect-ratio="0.5625" data-responsive="1" height="100%"></iframe>
</p>
<p>
Pendant quelques jours, le doute a plané : lEtat comptait-il vraiment légiférer contre la cigarette dans les films français, que ce soit via une interdiction pure et simple ou via un système de «punition» (coupe des aides CNC, par exemple) pour les longs-métrages qui sentent le mégot ? Si <a href="https://www.liberation.fr/direct/element/agnes-buzyn-assure-quelle-na-jamais-envisage-linterdiction-de-la-cigarette-au-cinema_73855/" target="_blank">le rétropédalage de la ministre Buzyn</a> nen est pas vraiment un (elle navait jamais clairement menacé le septième art), la polémique a le mérite de pointer la (sur)représentation clopesque sur écran. Et si, comme cest le cas dans la vie quotidienne, on voyait progressivement les cigarettes électroniques remplacer les tiges nicotinées authentiques ? Que ceux qui mettraient en doute le potentiel cinématographique des vapoteuses se ruent sur <a href="http://www.vapewave.net/" target="_blank"><em>Vape Wave</em></a>, documentaire militant signé Jan Kounen, ex-fumeur reconverti à la vape dont les images magnifient les volutes de vapeur recrachée.
</p>
<p>
Si le film du réalisateur de <em>Dobermann</em> et <em>99 Francs</em> part un peu dans tous les sens, il a le mérite de défendre avec une passion contagieuse ce qui semble, de loin, être <a href="https://www.liberation.fr/societe/2015/08/20/une-e-cigarette-tres-frequentable_1366687" target="_blank">le meilleur et plus sain substitut à la clope</a>, nen déplaise aux mesures restrictives imposées en France <a href="https://www.liberation.fr/france/2017/10/03/la-cigarette-electronique-bannie-de-certains-lieux-publics_1600601" target="_blank">à son égard</a>. Financé en partie via crowdfunding, le documentaire a été présenté par Kounen à travers toute la France lors de projection tenant quasiment de lévangélisation. Disponible en VOD/DVD, il a été diffusé cette semaine sur la chaîne Planète+, qui le rediffusera les 25/11, 30/11 et 02/12 prochains. <strong>(Alexandre Hervaud)</strong>
</p>
<h3>
Pour écouter parler un génie
</h3>
<p>
<strong><em>Dans la tête dAlan Moore</em> (websérie documentaire, 8x5min, Arte Creative)</strong>
</p>
<p>
<iframe width="100%" src="https://www.youtube.com/embed/s_rw5fPHz2g" frameborder="0" allowfullscreen="allowfullscreen" data-aspect-ratio="0.5625" data-responsive="1" height="100%"></iframe>
</p>
<p>
Le week-end dernier, <em>Libération</em> publiait <a href="http://next.liberation.fr/livres/2017/11/17/alan-moore-dernier-barde-avant-la-fin-du-monde_1610854" target="_blank">un portrait de der consacré à lauteur britannique Alan Moore</a>, connu pour ses BD cultes (<em>V pour Vendetta, Watchmen, From Hell</em>), à loccasion de la sortie de son deuxième roman, le pavé <em>Jérusalem</em>. En attendant limminente sortie dune version longue de son entretien avec <em>Libé</em>, on pourra se replonger dans les épisodes dune websérie documentaire dArte Creative en 8 épisodes consacré au maître. Brexit, magie, Anonymous font partie des sujets discutés avec le maître au fil de ce programme sobrement intitulé <a href="https://www.arte.tv/fr/videos/RC-014342/dans-la-tete-d-alan-moore/" target="_blank"><em>Dans la tête dAlan Moore</em></a>. <strong>(A.H.)</strong>
</p>
<h3>
Pour honorer la mémoire dune icône queer
</h3>
<p>
<strong><em>The Death and Life of Marsha P. Johnson</em> (docu, 1h45, Netflix)</strong>
</p>
<p>
<iframe width="100%" src="https://www.youtube.com/embed/pADsuuPd79E" frameborder="0" allowfullscreen="allowfullscreen" data-aspect-ratio="0.5625" data-responsive="1" height="100%"></iframe>
</p>
<p>
Marsha, la <em>«Rosa Parks du mouvement LGBTQ»</em>. Marsha <em>«la prostituée, lactrice et la sainte, modèle dAndy Warhol»</em> ou encore Marsha lélaborée, la radicale, <em>«avec ses plumes et ce maquillage quelle ne mettait jamais bien»</em>. «Queen Marsha» a été retrouvée morte dans lHudson en juillet 1992, alors quon la voyait encore parader dans les rues de Greenwich Village quelques jours auparavant. Un choc glaçant. Là où son corps a été repêché puis ingratement déposé, les sans-abri ont constitué le lendemain un mémorial de bouteilles et de plantes qui délimitent les contours de labsente.
</p>
<p>
Marsha P. Johnson de son nom complet, icône queer, femme transgenre noire américaine et emblème de la lutte pour les droits des LGBTQ avait été lune des premières à sengager lors des émeutes de Stonewall à New York, en 1969 : <em>«Cest la révolution. Dieu merci.»</em> Marsha était une fleur souriante au parfum despoir. Le documentaire <em>The Death and Life of Marsha P. Johnson</em> du cinéaste David France relate lenquête de lactiviste Victoria Cruz, membre de lorganisation Anti-Violence Project à New York qui, avant de prendre sa retraite, réclame que lumière soit faite sur la disparition de licône […] <a href="http://next.liberation.fr/cinema/2017/11/17/docu-marsha-p-johnson-unique-en-son-genre_1610846" target="_blank">Lire la suite de la critique de Jérémy Piette sur Libération.fr</a>
</p>
<h3>
Pour Michel Vuilermoz (et rien dautre)
</h3>
<p>
<strong><em>Alphonse President</em> (série, 10x26, OCS Max)</strong>
</p>
<p>
<iframe width="100%" frameborder="0" src="https://www.dailymotion.com/embed/video/x67iqc9" allowfullscreen="allowfullscreen" data-aspect-ratio="0.5625" data-responsive="1"></iframe>
</p>
<p>
Un temps baptisée <em>French Touch</em>, la série <em>Alphonse Président</em> est le dernier né des programmes originaux made in OCS. On savait les budgets de la chaîne bien moins généreux que ceux de Canal+ (voire que ceux de France 3 Limousin), et cette série le prouve à nouveau régulièrement, notamment lors dune scène de conférence de presse alternant plans larges dune authentique conf' à lElysée période François Hollande et plans serrés dacteurs filmés dans un château des Pays de la Loire où a eu lieu le tournage. Le principal atout (et quel atout) de cette série écrite et réalisée par Nicolas Castro (<em>Des lendemains qui chantent</em>, 2014) réside dans son interprète principal, Michel Vuillermoz.
</p>
<p>
Dans le rôle dun sénateur ringard devenu par un concours de circonstances président de la République, ce pensionnaire de la Comédie-Française et complice dAlbert Dupontel fait des merveilles, notamment lorsque le scénario lui prête des répliques enflammées typiques de la langue de bois politicienne  pas étonnant quil brasse du vent, son personnage de prof dhistoire retraité sappelle Alphonse Dumoulin. Cest lorsquil nest plus à lécran que les choses se gâtent : si Jean-Michel Lahmi (de la bande dEdouard Baer) fait le job en grand patron des flics, difficile de croire une seconde à Nabiha Akkari dans le rôle de la Première ministre  et pas uniquement parce que lidée davoir une femme trentenaire issue de la diversité à Matignon sonne hélas comme un doux rêve en 2017. Si, en matière de fiction politique sérieuse, un <em>Baron Noir</em> na pas grand-chose à envier à un <em>House of Cards</em>, côté comique la France est encore loin davoir son <em>Veep</em>. Gageons que la génération LREM saura largement inspirer des scénaristes moqueurs. <strong>(A.H.)</strong>
</p>
<h3>
Pour les coulisses dun tournage dément
</h3>
<p>
<strong><em>Jim &amp; Andy</em> (documentaire, 1h33, Netflix) </strong>
</p>
<p>
<iframe width="100%" src="https://www.youtube.com/embed/kB15UFO5ebA" frameborder="0" allowfullscreen="allowfullscreen" data-aspect-ratio="0.5625" data-responsive="1" height="100%"></iframe>
</p>
<p>
A la sortie de <em>Man on the Moon</em> (2000), le magnifique film de Milos Forman consacré à Andy Kaufman  comique et génie de la performance absurde mort en 1984 , le cinéaste et les acteurs insistaient dans chaque interview sur lin­croyable comportement de Jim Carrey pendant le tournage : il aurait été comme possédé par Kaufman, se prenant pour lui 24 heures sur 24. Certains affirmaient même ne jamais avoir eu limpression que lacteur était présent, tant son modèle avait littéralement pris sa place. Nous en avons aujourdhui la preuve en images car tout cela avait été filmé par Bob Zmuda et Lynne Margulies, lancien complice et la veuve de Kaufman.
</p>
<p>
Dans le passionnant <em>Jim &amp; Andy : the Great Beyond</em>, disponible sur Netflix, Chris Smith a monté ces documents inédits parallèlement à un entretien dans lequel Jim Carrey revient sur cette expérience unique. <a href="http://next.liberation.fr/cinema,58" target="_blank">Lire la suite de la critique de Marcos Uzal sur Liberation.fr</a>
</p>
<h3>
Pour un trip sibérien en totale autarcie
</h3>
<p>
<strong><em>Braguino</em> (documentaire, 50min, Arte)</strong>
</p>
<p>
<iframe width="100%" src="https://www.youtube.com/embed/OIS-P-0-cRk" frameborder="0" allowfullscreen="allowfullscreen" data-aspect-ratio="0.5625" data-responsive="1" height="100%"></iframe>
</p>
<p>
La querelle peut se trouver derrière toutes les portes, y compris celle de lexil. On a beau croire avoir tourné le dos à tout, à cette inclination humaine à nourrir sa propre haine, lallergie peut regermer fissa sur une peau qui frissonne à lapproche de ce voisin que lon ne comprend pas. Issu dune lignée de vieux-croyants orthodoxes russes, Sacha Braguine a pris sa famille sous le bras, loin de toute autre présence humaine en taïga sibérienne. Un autre groupe, les Kiline, a décidé den faire de même et de sinstaller de lautre côté de la rivière. Qui est arrivé en premier ? Qui menace lautre ? Lhistoire de limpossible communauté peut commencer.
</p>
<p>
La lecture d<em>Ermites dans la taïga</em> (1992) de Vassili Peskov, authentique récit sur la famille Lykov opérant une migration similaire en 1938, a poussé lartiste <a href="http://next.liberation.fr/images/2017/09/29/clement-cogitore-j-essaye-de-raconter-les-terreurs-profondes-de-l-etre-humain_1599854" target="_blank">Clément Cogitore</a> à rencontrer les Braguine, puis à se faire témoin de la bisbille de voisinage en 2016. Il en est revenu avec un nouveau film dune cinquantaine de minutes : <em>Braguino,</em> soutenu par le prix Le Bal de la jeune création avec lADAGP.<em> </em>Le documentaire y frôle son déguisement fictionnel, tant ce qui sy déroule convoque une dramaturgie comme invoquée par on ne sait quel rituel vaudou […] <a href="http://next.liberation.fr/cinema/2017/10/30/braguino-prises-de-bec-dans-la-taiga_1606859" target="_blank">Lire la suite de la critique de Jérémy Piette sur Liberation.fr</a>, le film diffusé cette semaine sur Arte est visible en intégralité ci-dessus.
</p>
<h3>
Pour un thriller tiré de faits réels
</h3>
<p>
<strong><em>6 Days</em> (film, 1h34, Netflix)</strong>
</p>
<p>
<iframe width="100%" src="https://www.youtube.com/embed/7HthiTi_IcI" frameborder="0" allowfullscreen="allowfullscreen" data-aspect-ratio="0.5625" data-responsive="1" height="100%"></iframe>
</p>
<p>
Fin avril 1980, lambassade dIran à Londres a été le théâtre dune prise dotages largement médiatisée : une trentaine de personnes ont ainsi été retenues pendant six jours par des soldats iraniens dissidents exigeant la libération de 91 prisonniers. Avec Margaret Thatcher au 10 Downing Street à lépoque, pas question pour lAngleterre davoir lair mou du genou sur la réponse à apporter à cette crise scrutée par les caméras du monde entier. Le SAS (Special Air Service) est sur le coup : lopération Nimrod se met en place pour prendre dassaut lambassade.
</p>
<p>
Inspiré par cet épisode, <em>6 Days</em> de Toa Fraser (<em>The Dead Lands</em>, 2014) est un thriller carré pouvant compter sur l'autorité naturelle de Mark Strong (<em>Kingsman</em>) ici recyclé en flic londonien et sur la néo-badass attitude de Jamie Bell, bien loin du freluquet danseur de <em>Billy Elliot</em> puisqu'on le retrouve ici en soldat chargé dorganiser lopération de secours. Attention, la bande-annonce ci-dessus dévoile à peu près lintégralité des scènes daction du film. <strong>(A.H.)</strong>
</p>
<p><span><span><a href="https://www.liberation.fr/auteur/5631-alexandre-hervaud" target="_blank">Alexandre Hervaud</a></span> , <span><a href="https://www.liberation.fr/auteur/17350-jeremy-piette" target="_blank">Jérémy Piette</a></span></span>
</p>
</div></article>

File diff suppressed because it is too large Load diff

View file

@ -488,6 +488,36 @@ async fn telegraph() {
run_test("telegraph").await run_test("telegraph").await
} }
#[tokio::test]
async fn toc_missing() {
run_test("toc-missing").await
}
#[tokio::test]
async fn topicseed_1() {
run_test("topicseed-1").await
}
#[tokio::test]
async fn tumblr() {
run_test("tumblr").await
}
#[tokio::test]
async fn v8_blog() {
run_test("v8-blog").await
}
#[tokio::test]
async fn videos_1() {
run_test("videos-1").await
}
#[tokio::test]
async fn videos_2() {
run_test("videos-2").await
}
#[tokio::test] #[tokio::test]
async fn webmd_1() { async fn webmd_1() {
run_test("webmd-1").await run_test("webmd-1").await