CINXE.COM

A horrifying globalThis polyfill in universal JavaScript · Mathias Bynens

<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>A horrifying globalThis polyfill in universal JavaScript · Mathias Bynens</title> <meta name="viewport" content="width=device-width"> <link rel="stylesheet" href="/css"> <link rel="manifest" href="/.webmanifest"> <link rel="alternate" href="/notes/globalthis.atom" type="application/atom+xml" title="Atom feed for comments on this entry"> </head> <body> <header> <h1><a href="/">Mathias Bynens</a></h1> <nav> <h1>Navigation</h1> <ul> <li><a href="/">Home</a></li> <li><a href="/notes">Archive</a></li> </ul> </nav> </header> <section id="content"> <nav><a href="/notes/prototypes" rel="prev">← JavaScript engine fundamentals: optimizing prototypes</a></nav> <article itemscope itemtype="http://schema.org/BlogPosting"> <header> <h1 itemprop="headline">A horrifying <code>globalThis</code> polyfill in universal JavaScript</h1> <p class="meta">Published <time datetime="2019-04-18" itemprop="datePublished">18th April 2019</time> · tagged with <a href="/notes#javascript">JavaScript</a></p> </header> <div itemprop="articleBody"> <p><a href="https://github.com/tc39/proposal-global">The <code>globalThis</code> proposal</a> introduces a unified mechanism to access the global <code>this</code> in any JavaScript environment. It sounds like a simple thing to polyfill, but it turns out it’s pretty hard to get right. I didn’t even think it was possible until <a href="https://twitter.com/tverwaes">Toon</a> blew my mind with an unexpected, creative solution.</p> <p>This write-up describes the difficulties with writing a proper <code>globalThis</code> polyfill. Such a polyfill has the following requirements:</p> <ul> <li>It must work in any JavaScript environment, including web browsers, workers in web browsers, extensions in web browsers, Node.js, <a href="https://deno.land/">Deno</a>, and <a href="https://github.com/GoogleChromeLabs/jsvu">standalone JavaScript engine binaries</a>.</li> <li>It must support sloppy mode, strict mode, and <a href="https://v8.dev/features/modules">JavaScript modules</a>.</li> <li>It must work regardless of the context the code runs in. (That is, it must still produce the correct result even if the polyfill is wrapped in a strict mode function by a packer at build time.)</li> </ul> <h2 id="terminology">Terminology</h2> <p>But first, a note on terminology. <code>globalThis</code> provides the value of <code>this</code> in the global scope. This is different from the global object in web browsers, for <a href="https://github.com/tc39/proposal-global#html-and-the-windowproxy" title="The global object changes during navigation, but globalThis does not change during navigation. Therefore, globalThis is not the same as the global object.">complicated reasons</a>.</p> <p class="figure"><img src="/_img/globalthis/visualization.svg" loading="lazy" decoding="async" alt=""></p> <p>Note that in JavaScript modules, there is a module scope intervening between the global scope and your code. The module scope hides the global scope’s <code>this</code> value, so the <code>this</code> value you see at the top-level in modules is actually <code>undefined</code>.</p> <p>TL;DR <code>globalThis</code> is <em>not</em> “the global object”; it’s simply the <code>this</code> from the global scope. Thanks to <a href="https://twitter.com/domenic">Domenic</a> for helping me understand this important nuance.</p> <h2 id="alternatives"><code>globalThis</code> alternatives</h2> <p>In a browser, <code>globalThis</code> is equivalent to <code>window</code>:</p> <pre><code class="language-javascript">globalThis === window;<br>// → true</code></pre> <p><a href="https://html.spec.whatwg.org/multipage/window-object.html#dom-frames"><code>frames</code></a> works too:</p> <pre><code class="language-javascript">globalThis === frames;<br>// → true</code></pre> <p>However, <code>window</code> and <code>frames</code> are <code>undefined</code> within worker contexts (such as web workers and service workers). Luckily, <code>self</code> works in all browser contexts and is thus a more robust alternative:</p> <pre><code class="language-javascript">globalThis === self;<br>// → true</code></pre> <p>Neither <code>window</code>, <code>frames</code>, nor <code>self</code> are available within Node.js, though. Instead, <code>global</code> can be used:</p> <pre><code class="language-javascript">globalThis === global;<br>// → true</code></pre> <p>None of the above (<code>window</code>, <code>frames</code>, <code>self</code>, <code>global</code>) are available in stand-alone JavaScript engine shells, such as the ones installed by <a href="https://github.com/GoogleChromeLabs/jsvu"><code>jsvu</code></a>. There, you can access the global <code>this</code>:</p> <pre><code class="language-javascript">globalThis === this;<br>// → true</code></pre> <p>Furthermore, sloppy mode functions always have their <code>this</code> set to the global <code>this</code>, so even if you cannot run your code in the global scope, you could still get access to the global <code>this</code> as follows in sloppy mode:</p> <pre><code class="language-javascript">globalThis === (function() {<br> return this;<br>})();<br>// → true</code></pre> <p>However, the top-level <code>this</code> value is <code>undefined</code> in JavaScript modules, and <code>this</code> is <code>undefined</code> within strict mode functions, so this approach doesn’t work there.</p> <p>Once you’re in a strict mode context, there’s only one way to temporarily break out of it: the <code>Function</code> constructor, which generates sloppy functions!</p> <pre><code class="language-javascript">globalThis === Function('return this')();<br>// → true</code></pre> <p>Well, there’s two ways, since indirect <code>eval</code> has the same effect:</p> <pre><code class="language-javascript">globalThis === (0, eval)('this');<br>// → true</code></pre> <p>In web browsers, use of the <code>Function</code> constructor and <code>eval</code> is often disallowed using Content Security Policy (CSP). Websites often opt-in so such a policy, but it’s also <a href="https://developer.chrome.com/docs/apps/contentSecurityPolicy/#restrictions">enforced within Chrome extensions</a>, for example. Unfortunately, this means that a proper polyfill cannot rely on the <code>Function</code> constructor or <code>eval</code>.</p> <p class="note"><strong>Note:</strong> <code>setTimeout('globalThis = this', 0)</code> is ruled out for the same reason. In addition to commonly being blocked by CSP, there are two other reasons against using <code>setTimeout</code> for a polyfill. First, it’s <a href="https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-settimeout" title="setTimeout is specified by the HTML Standard.">not part of ECMAScript</a>, and not available in all JavaScript environments. Second, it’s asynchronous, so even if <code>setTimeout</code> would be supported everywhere, it’d be painful to use in a polyfill on which other code depends.</p> <h2 id="naive-polyfill">A naive polyfill</h2> <p>It seems like it should be possible to combine the above techniques into a single polyfill, like so:</p> <pre><code class="language-javascript">// A naive globalThis shim. Don’t use this!<br>const getGlobalThis = () =&gt; {<br> if (typeof globalThis !== 'undefined') return globalThis;<br> if (typeof self !== 'undefined') return self;<br> if (typeof window !== 'undefined') return window;<br> if (typeof global !== 'undefined') return global;<br> if (typeof this !== 'undefined') return this;<br> throw new Error('Unable to locate global `this`');<br>};<br>// Note: `var` is used instead of `const` to ensure `globalThis`<br>// becomes a global variable (as opposed to a variable in the<br>// top-level lexical scope) when running in the global scope.<br>var globalThis = getGlobalThis();</code></pre> <p>But alas, this doesn’t work in strict mode functions or within JavaScript modules in non-browser environments (except those with <code>globalThis</code> support). In addition, <code>getGlobal</code> could return an incorrect result, since it relies on <code>this</code> which is context-dependent and could be altered by a bundler/packer.</p> <h2 id="robust-polyfill">A robust polyfill</h2> <p>Is it even possible to write a robust <code>globalThis</code> polyfill? Assume an environment where:</p> <ul> <li>you cannot rely on the value of <code>globalThis</code>, <code>window</code>, <code>self</code>, <code>global</code>, or <code>this</code>;</li> <li>you cannot use the <code>Function</code> constructor or <code>eval</code>;</li> <li>but you <em>can</em> rely on the integrity of all other JavaScript built-in functionality.</li> </ul> <p>It turns out there is a solution, but it’s not pretty. Let’s think about this for a minute.</p> <p>How do we get access to the global <code>this</code> without knowing how to access it directly? If we could somehow install a function property on the <code>globalThis</code>, and call it as a method on the <code>globalThis</code>, then we could access the <code>this</code> from that function:</p> <pre><code class="language-javascript">globalThis.foo = function() {<br> return this;<br>};<br>var globalThisPolyfilled = globalThis.foo();</code></pre> <p>How can we do something like that without relying on <code>globalThis</code> or any host-specific binding that refers to it? We can’t just do the following:</p> <pre><code class="language-javascript">function foo() {<br> return this;<br>}<br>var globalThisPolyfilled = foo();</code></pre> <p><code>foo()</code> is now no longer called as a method, and so its <code>this</code> is <code>undefined</code> in strict mode or in JavaScript modules as discussed above. Strict mode functions have their <code>this</code> set to <code>undefined</code>. However, <a href="https://tc39.es/ecma262/#sec-getvalue" title="Step 5.b. of GetValue calls GetThisValue.">this is not the case for getters</a> and <a href="https://tc39.es/ecma262/#sec-putvalue" title="Step 6.b. of PutValue calls GetThisValue.">setters</a>!</p> <pre><code class="language-javascript">Object.defineProperty(globalThis, '__magic__', {<br> get: function() {<br> return this;<br> },<br> configurable: true // This makes it possible to `delete` the getter later.<br>});<br>// Note: `var` is used instead of `const` to ensure `globalThis`<br>// becomes a global variable (as opposed to a variable in the<br>// top-level lexical scope) when run in the global scope.<br>var globalThisPolyfilled = __magic__;<br>delete globalThis.__magic__;</code></pre> <p>The above program installs a getter on the <code>globalThis</code>, accesses the getter to get a reference to the <code>globalThis</code>, and then cleans up by deleting the getter. This technique gives us access to the <code>globalThis</code> in all the desired circumstances, but it still relies on a reference to the global <code>this</code> on the first line (where it says <code>globalThis</code>). Can we avoid this dependency? How can we install a globally accessible getter without accessing the <code>globalThis</code> directly?</p> <p>Instead of installing the getter on <code>globalThis</code>, we install it on something the global <code>this</code> object inherits from — <code>Object.prototype</code>:</p> <pre><code class="language-javascript">Object.defineProperty(Object.prototype, '__magic__', {<br> get: function() {<br> return this;<br> },<br> configurable: true // This makes it possible to `delete` the getter later.<br>});<br>// Note: `var` is used instead of `const` to ensure `globalThis`<br>// becomes a global variable (as opposed to a variable in the<br>// top-level lexical scope).<br>var globalThis = __magic__;<br>delete Object.prototype.__magic__;</code></pre> <p class="note"><strong>Note:</strong> Prior to the <code>globalThis</code> proposal, the ECMAScript spec doesn’t actually mandate that the global <code>this</code> inherit from <code>Object.prototype</code>, only that it must be an object. <code>Object.create(null)</code> creates an object that doesn’t inherit from <code>Object.prototype</code>. A JavaScript engine could use such an object as the global <code>this</code> without violating the spec, in which case the above code snippet still wouldn’t work (and indeed, <a href="https://regmedia.co.uk/2007/10/31/jscriptdeviationsfromes3.pdf#2.5">Internet Explorer 7 did something like that</a>!). Luckily, more modern JavaScript engines all seem to agree that the global <code>this</code> must have <code>Object.prototype</code> in its prototype chain.</p> <p>To avoid mutating <code>Object.prototype</code> in modern environments where <code>globalThis</code> is already available, we can change the polyfill as follows:</p> <pre><code class="language-javascript">(function() {<br> if (typeof globalThis === 'object') return;<br> Object.defineProperty(Object.prototype, '__magic__', {<br> get: function() {<br> return this;<br> },<br> configurable: true // This makes it possible to `delete` the getter later.<br> });<br> __magic__.globalThis = __magic__; // lolwat<br> delete Object.prototype.__magic__;<br>}());<br><br>// Your code can use `globalThis` now.<br>console.log(globalThis);</code></pre> <p>Alternatively, we could use <code>__defineGetter__</code>:</p> <pre><code class="language-javascript">(function() {<br> if (typeof globalThis === 'object') return;<br> Object.prototype.__defineGetter__('__magic__', function() {<br> return this;<br> });<br> __magic__.globalThis = __magic__; // lolwat<br> delete Object.prototype.__magic__;<br>}());<br><br>// Your code can use `globalThis` now.<br>console.log(globalThis);</code></pre> <p>And there you have it: the most horrifying polyfill you’ve ever seen! It completely defies the prevalent best practice to not modify objects you don’t own. Mucking with built-in prototypes is generally a bad idea, as explained in <a href="/notes/prototypes">JavaScript engine fundamentals: optimizing prototypes</a>.</p> <p>On the other hand, the only way this polyfill can break is if someone manages to alter <code>Object</code> or <code>Object.defineProperty</code> (or <code>Object.prototype.__defineGetter__</code>) before the polyfill code runs. I can’t think of a more robust solution. Can you?</p> <h2 id="testing">Testing the polyfill</h2> <p>The polyfill is <del>a good</del> <ins>an <em>interesting</em></ins> example of <strong>universal JavaScript</strong>: it’s pure JavaScript code that does not rely on any host-specific built-ins, and therefore runs in any environment that implements ECMAScript. This was one of the goals of the polyfill in the first place! Let’s confirm that it actually works.</p> <p><a href="/demo/globalthis">Here’s an HTML demo page for the polyfill</a> that logs <code>globalThis</code> using both a <a href="/demo/globalthis.js">classic script <code>globalthis.js</code></a> and a module <a href="/demo/globalthis.mjs"><code>globalthis.mjs</code></a> (with identical source code). This demo can be used to verify the polyfill works in browsers. <code>globalThis</code> is natively supported in <a href="https://v8.dev/blog/v8-release-71#javascript-language-features">V8 v7.1 / Chrome 71</a>, Firefox 65, Safari 12.1, and iOS Safari 12.2. To test the interesting parts of the polyfill, open the demo page in an older browser.</p> <p class="note"><strong>Note:</strong> The polyfill does not work in Internet Explorer 10 and older. In those browsers, the line <code>__magic__.globalThis = __magic__</code> somehow doesn’t make <code>globalThis</code> globally available, despite <code>__magic__</code> being a working reference to the global <code>this</code>. It turns out <code>__magic__ !== window</code> although both are <code>[object Window]</code>, indicating that these browsers might be confused about <a href="#terminology">the distinction between the global object and the global <code>this</code></a>. Amending the polyfill to fall back to one of <a href="#alternatives">the alternatives</a> makes it work in IE 10 and IE 9. For IE 8 support, wrap the call to <code>Object.defineProperty</code> in a <code>try</code>-<code>catch</code>, similarly falling back in the <code>catch</code> block. (Doing so also avoids the IE 7 issue with the global <code>this</code> not inheriting from <code>Object.prototype</code>.) <a href="/demo/globalthis-ie">Try the demo with old IE support.</a></p> <p>To test in Node.js and standalone JavaScript engine binaries, download the very same JavaScript files:</p> <pre><code class="language-bash"># Download the polyfill + demo code as a module.<br>curl https://mathiasbynens.be/demo/globalthis.mjs &gt; globalthis.mjs<br># Create a copy (well, symlink) of the file, to be used as a classic script.<br>ln -s globalthis.mjs globalthis.js</code></pre> <p>Now we can test in <code>node</code>:</p> <pre class="shell"><samp>$ node globalthis.mjs<br>Testing the polyfill in a module<br>[object global]<br><br>$ node globalthis.js<br>Testing the polyfill in a classic script<br>[object global]</samp></pre> <p>To test in a stand-alone JavaScript engine shell, use <a href="https://github.com/GoogleChromeLabs/jsvu"><code>jsvu</code></a> to install any desired engine, and then run the scripts directly. For example, to test in V8 v7.0 (without <code>globalThis</code> support) and v7.1 (with <code>globalThis</code> support):</p> <pre class="shell"><samp>$ jsvu v8@7.0 # Install the `v8-7.0.276` binary.<br><br>$ v8-7.0.276 globalthis.mjs<br>Testing the polyfill in a module<br>[object global]<br><br>$ v8-7.0.276 globalthis.js<br>Testing the polyfill in a classic script<br>[object global]<br><br>$ jsvu v8@7.1 # Install the `v8-7.1.302` binary.<br><br>$ v8-7.1.302 globalthis.js<br>Testing the polyfill in a classic script<br>[object global]<br><br>$ v8-7.1.302 globalthis.mjs<br>Testing the polyfill in a module<br>[object global]</samp></pre> <p>The same technique allows us to test in JavaScriptCore, SpiderMonkey, Chakra, and other JavaScript engines such as <a href="https://github.com/Moddable-OpenSource/moddable-xst">XS</a> as well. Here’s an example using JavaScriptCore:</p> <pre class="shell"><samp>$ jsvu # Install the `javascriptcore` binary.<br><br>$ javascriptcore globalthis.mjs<br>Testing the polyfill in a module<br>[object global]<br><br>$ javascriptcore globalthis.js<br>Testing the polyfill in a classic script<br>[object global]</samp></pre> <h2 id="conclusion">Conclusion</h2> <p>Writing universal JavaScript can be tricky, and often calls for creative solutions. The new <code>globalThis</code> feature makes it easier to write universal JavaScript that needs access to the global <code>this</code> value. Polyfilling <code>globalThis</code> correctly is more challenging than it seems, but there is a working solution.</p> <p>Only use this polyfill when you really need to. <a href="https://v8.dev/features/modules">JavaScript modules</a> make it easier than ever to import and export functionality without altering global state, and most modern JavaScript code doesn’t need access to the global <code>this</code> anyway. <code>globalThis</code> is only useful for libraries and polyfills that do.</p> <h2 id="npm"><code>globalThis</code> polyfills on npm</h2> <p>Since publishing this article, the following npm packages started providing <code>globalThis</code> polyfills that make use of this technique:</p> <ul> <li><a href="https://github.com/ungap/global-this"><code>@ungap/global-this</code></a></li> <li><a href="https://github.com/medikoo/es5-ext/blob/master/global.js"><code>es5-ext</code></a></li> </ul> <p><strong>Disclaimer:</strong> I’m not the author, nor am I the maintainer, of any of these packages.</p> <h2 id="translations">Translations</h2> <ul> <li><a href="https://juejin.cn/post/6904958153503277069">Chinese</a></li> <li><a href="https://ui.toast.com/weekly-pick/ko_20190503/">Korean</a></li> </ul> </div> <footer id="about"> <img src="https://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=112" alt="" width="112" height="112" srcset="https://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=224 2x"> <h2>About me</h2> <p>Hi there! I’m Mathias. I work on Chrome at Google. HTML, CSS, JavaScript, Unicode, performance, and security get me excited. <a href="https://twitter.com/mathias" rel="me nofollow">Follow me on Twitter</a>, <a href="https://bsky.app/profile/mths.be" rel="me nofollow">Bluesky</a>, and <a href="https://github.com/mathiasbynens" rel="me nofollow">GitHub</a>.</p> </footer> <section id="comments"> <h1>Comments</h1> <article id="comment-1" data-id="1626" itemprop="comment" itemscope itemtype="http://schema.org/UserComments"> <header> <div class="avatar"><img src="https://gravatar.com/avatar/376deae39b17fad6cfb354fb62f69f41?s=30" alt="" width="30" height="30" srcset="https://gravatar.com/avatar/376deae39b17fad6cfb354fb62f69f41?s=60 2x"></div> <p class="meta"><span itemprop="creator" itemscope itemtype="http://schema.org/Person"><span itemprop="name">MaxArt</span></span> wrote on <time datetime="2019-04-19T08:11" itemprop="commentTime"><a href="#comment-1" rel="bookmark" itemprop="url" title="Permanent link to comment 1 on “A horrifying globalThis polyfill in universal JavaScript”">19th April 2019 at 08:11</a></time>:</p> </header> <div itemprop="commentText"> <p>The polyfill itself doesn’t faze me. It’s a polyfill, it can do the worst to reach the goal. End users don’t need to know the details to use it.</p> <p>TRWTF in this article is IMO this: <code>(0, eval)('this')</code>.</p> <p>Seriously, wut? Isn’t this equivalent to just <code>eval('this')</code>? Why the comma operator? 🤔</p> </div> </article> <article id="comment-2" data-id="1632" class="mathias" itemprop="comment" itemscope itemtype="http://schema.org/UserComments"> <header> <div class="avatar"><img src="https://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=30" alt="" width="30" height="30" srcset="https://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=60 2x"></div> <p class="meta"><span itemprop="creator" itemscope itemtype="http://schema.org/Person"><a href="/" rel="author" itemprop="name">Mathias</a></span> wrote on <time datetime="2019-04-19T11:22" itemprop="commentTime"><a href="#comment-2" rel="bookmark" itemprop="url" title="Permanent link to comment 2 on “A horrifying globalThis polyfill in universal JavaScript”">19th April 2019 at 11:22</a></time>:</p> </header> <div itemprop="commentText"> <p><a href="#comment-1"><strong>MaxArt:</strong></a> <code>eval(code)</code> is a “direct <code>eval</code>” and executes code in the current scope. <code>(0, eval)(code)</code> is an <a href="http://2ality.com/2014/01/eval.html">indirect <code>eval</code></a> and executes code in the global scope.</p> </div> </article> <article id="comment-3" data-id="1630" itemprop="comment" itemscope itemtype="http://schema.org/UserComments"> <header> <div class="avatar"><img src="https://gravatar.com/avatar/a6011d80bf4e237af7f837ce469422ec?s=30" alt="" width="30" height="30" srcset="https://gravatar.com/avatar/a6011d80bf4e237af7f837ce469422ec?s=60 2x"></div> <p class="meta"><span itemprop="creator" itemscope itemtype="http://schema.org/Person"><span itemprop="name">Sichao Zhang</span></span> wrote on <time datetime="2019-04-19T22:10" itemprop="commentTime"><a href="#comment-3" rel="bookmark" itemprop="url" title="Permanent link to comment 3 on “A horrifying globalThis polyfill in universal JavaScript”">19th April 2019 at 22:10</a></time>:</p> </header> <div itemprop="commentText"> <p>Hi, very informative post that helps me clear a bunch of blind spots! I have a question regarding the following two lines:</p> <pre><code>__magic__.globalThis = __magic__; // lolwat<br>delete Object.prototype.__magic__;</code></pre> <p>I’m not quite sure why you have to attach <code>__magic__</code> to a property on <code>__magic__</code>. And when you do the <code>delete</code> operation on <code>__magic__</code>, doesn’t that delete the <code>globalThis</code> property as well?</p> <p>Thank you for your explanation in advance!</p> </div> </article> <article id="comment-4" data-id="1633" class="mathias" itemprop="comment" itemscope itemtype="http://schema.org/UserComments"> <header> <div class="avatar"><img src="https://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=30" alt="" width="30" height="30" srcset="https://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=60 2x"></div> <p class="meta"><span itemprop="creator" itemscope itemtype="http://schema.org/Person"><a href="/" rel="author" itemprop="name">Mathias</a></span> wrote on <time datetime="2019-04-20T11:29" itemprop="commentTime"><a href="#comment-4" rel="bookmark" itemprop="url" title="Permanent link to comment 4 on “A horrifying globalThis polyfill in universal JavaScript”">20th April 2019 at 11:29</a></time>:</p> </header> <div itemprop="commentText"> <p><a href="#comment-2"><strong>Sichao:</strong></a> The goal of the polyfill is to make <code>globalThis</code> globally available. Global variables can be created by adding them as properties to the global <code>this</code>.</p> <p>In the code snippet you highlight, <code>__magic__</code> is a reference to the global <code>this</code>, or what you know as <code>window</code> in most browser contexts. So this line:</p> <pre><code>__magic__.globalThis = __magic__;</code></pre> <p>…is equivalent to the following in a browser context where <code>window</code> is available:</p> <pre><code>window.globalThis = window;</code></pre> <p>…which makes <code>globalThis</code> globally available.</p> <p>The <code>delete</code> line removes the getter, since we only need it once to get the reference to the global <code>this</code>.</p> </div> </article> </section> <section> <h1>Leave a comment</h1> <form method="post" action="/notes/globalthis"> <fieldset> <legend>Comment on “A horrifying <code>globalThis</code> polyfill in universal JavaScript”</legend> <p> <label for="comment-name">Name <em>*</em></label> <input type="text" name="comment-name" id="comment-name" required> </p> <p> <label for="comment-mail">Email <em>*</em></label> <input type="email" name="comment-mail" id="comment-mail" required> </p> <p> <label for="comment-site">Website</label> <input type="url" name="comment-site" id="comment-site"> </p> <p><textarea rows="5" cols="50" name="comment-text" id="comment-text" required></textarea></p> <p>Your input will be parsed as Markdown.</p> <p> <label for="comment-spam">Spammer? (Enter ‘no’) <em>*</em></label> <input type="text" name="comment-spam" id="comment-spam" required> </p> <p class="submit"> <input type="submit" name="submit" value="Add your comment"> </p> </fieldset> </form> </section> </article> </section> <footer>© 1988–2025 Mathias Bynens</footer> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js" integrity="sha384-K+ctZQ+LL8q6tP7I94W+qzQsfRV2a+AfHIi9k8z8l9ggpc8X+Ytst4yBo/hH+8Fk" crossorigin></script> <script src="/js"></script> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10