Thomas  Granger

Thomas Granger

1557847318

A horrifying globalThis polyfill in universal JavaScript

The proposal introduces a unified mechanism to access the global this 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 Toon blew my mind with an unexpected, creative solution.

This write-up describes the difficulties with writing a proper globalThis polyfill. Such a polyfill has the following requirements:

  • It must work in any JavaScript environment, including web browsers, workers in web browsers, extensions in web browsers, Node.js, and standalone JavaScript engine binaries.
  • It must support sloppy mode, strict mode, and JavaScript modules.
  • 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.)

Terminology

But first, a note on terminology. globalThis provides the value of this in the global scope. This is different from the global object in web browsers, for complicated reasons.

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 this value, so the this value you see at the top-level in modules is actually undefined.

TL;DR globalThis is not “the global object”; it’s simply the this from the global scope. Thanks to Domenic for helping me understand this important nuance.

globalThis alternatives

In a browser, globalThis is equivalent to window:

globalThis === window;
// → true

<a href="https://html.spec.whatwg.org/multipage/window-object.html#dom-frames" target="_blank">frames</a> works too:

globalThis === frames;
// → true

However, window and frames are undefined within worker contexts (such as web workers and service workers). Luckily, self works in all browser contexts and is thus a more robust alternative:

globalThis === self;
// → true

Neither window, frames, nor self are available within Node.js, though. Instead, global can be used:

globalThis === global;
// → true

None of the above (window, frames, self, global) are available in stand-alone JavaScript engine shells, such as the ones installed by <a href="https://github.com/GoogleChromeLabs/jsvu" target="_blank">jsvu</a>. There, you can access the global this:

globalThis === this;
// → true

Furthermore, sloppy mode functions always have their this set to the global this, so even if you cannot run your code in the global scope, you could still get access to the global this as follows in sloppy mode:

globalThis === (function() {
	return this;
})();
// → true

However, the top-level this value is undefined in JavaScript modules, and this is undefined within strict mode functions, so this approach doesn’t work there.

Once you’re in a strict mode context, there’s only one way to temporarily break out of it: the Function constructor, which generates sloppy functions!

globalThis === Function('return this')();
// → true

Well, there’s two ways, since indirect eval has the same effect:

globalThis === (0, eval)('this');
// → true

In web browsers, use of the Function constructor and eval is often disallowed using Content Security Policy (CSP). Websites often opt-in so such a policy, but it’s also enforced within Chrome extensions, for example. Unfortunately, this means that a proper polyfill cannot rely on the Function constructor or eval.

Note: setTimeout('globalThis = this', 0) is ruled out for the same reason. In addition to commonly being blocked by CSP, there are two other reasons against using setTimeout for a polyfill. First, it’s not part of ECMAScript, and not available in all JavaScript environments. Second, it’s asynchronous, so even if setTimeout would be supported everywhere, it’d be painful to use in a polyfill on which other code depends.

A naive polyfill

It seems like it should be possible to combine the above techniques into a single polyfill, like so:

// A naive globalThis shim. Don’t use this!
const getGlobal = () => {
	if (typeof globalThis !== 'undefined') return globalThis;
	if (typeof self !== 'undefined') return self;
	if (typeof window !== 'undefined') return window;
	if (typeof global !== 'undefined') return global;
	if (typeof this !== 'undefined') return this;
	throw new Error('Unable to locate global object');
};
// Note: `var` is used instead of `const` to ensure `globalThis`
// becomes a global variable (as opposed to a variable in the
// top-level lexical scope) when running in the global scope.
var globalThis = getGlobal();

But alas, this doesn’t work in strict mode functions or within JavaScript modules in non-browser environments (except those with globalThis support). In addition, getGlobal could return an incorrect result, since it relies on this which is context-dependent and could be altered by a bundler/packer.

A robust polyfill

Is it even possible to write a robust globalThis polyfill? Assume an environment where:

  • you cannot rely on the value of globalThis, window, self, global, or this;
  • you cannot use the Function constructor or eval;
  • but you can rely on the integrity of all other JavaScript built-in functionality.

It turns out there is a solution, but it’s not pretty. Let’s think about this for a minute.

How do we get access to the global this without knowing how to access it directly? If we could somehow install a function property on the globalThis, and call it as a method on the globalThis, then we could access the this from that function:

globalThis.foo = function() {
	return this;
};
var globalThisPolyfilled = globalThis.foo();

How can we do something like that without relying on globalThis or any host-specific binding that refers to it? We can’t just do the following:

function foo() {
	return this;
}
var globalThisPolyfilled = foo();

foo() is now no longer called as a method, and so its this is undefined in strict mode or in JavaScript modules as discussed above. Strict mode functions have their this set to undefined. However, this is not the case for getters and setters!

Object.defineProperty(globalThis, '__magic__', {
	get: function() {
		return this;
	},
	configurable: true // This makes it possible to `delete` the getter later.
});
// Note: `var` is used instead of `const` to ensure `globalThis`
// becomes a global variable (as opposed to a variable in the
// top-level lexical scope) when run in the global scope.
var globalThisPolyfilled = __magic__;
delete globalThis.__magic__;

The above program installs a getter on the globalThis, accesses the getter to get a reference to the globalThis, and then cleans up by deleting the getter. This technique gives us access to the globalThis in all the desired circumstances, but it still relies on a reference to the global this on the first line (where it says globalThis). Can we avoid this dependency? How can we install a globally accessible getter without accessing the globalThis directly?

Instead of installing the getter on globalThis, we install it on something the global this object inherits from — Object.prototype:

Object.defineProperty(Object.prototype, '__magic__', {
	get: function() {
		return this;
	},
	configurable: true // This makes it possible to `delete` the getter later.
});
// Note: `var` is used instead of `const` to ensure `globalThis`
// becomes a global variable (as opposed to a variable in the
// top-level lexical scope).
var globalThis = __magic__;
delete Object.prototype.__magic__;

Note: The ECMAScript spec doesn’t actually mandate that the global this inherit from Object.prototype, only that it must be an object. Object.create(null) creates an object that doesn’t inherit from Object.prototype. A JavaScript engine could use such an object as the global this without violating the spec, in which case the above code snippet still wouldn’t work (and indeed, Internet Explorer 7 did something like that!). Luckily, more modern JavaScript engines all seem to agree that the global this must have Object.prototype in its prototype chain.

To avoid mutating Object.prototype in modern environments where globalThis is already available, we can change the polyfill as follows:

(function() {
	if (typeof globalThis === 'object') return;
	Object.defineProperty(Object.prototype, '__magic__', {
		get: function() {
			return this;
		},
		configurable: true // This makes it possible to `delete` the getter later.
	});
	__magic__.globalThis = __magic__; // lolwat
	delete Object.prototype.__magic__;
}());

// Your code can use `globalThis` now.
console.log(globalThis);

Alternatively, we could use __defineGetter__:

(function() {
	if (typeof globalThis === 'object') return;
	Object.prototype.__defineGetter__('__magic__', function() {
		return this;
	});
	__magic__.globalThis = __magic__; // lolwat
	delete Object.prototype.__magic__;
}());

// Your code can use `globalThis` now.
console.log(globalThis);

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 JavaScript engine fundamentals: optimizing prototypes.

On the other hand, the only way this polyfill can break is if someone manages to alter Object or Object.defineProperty (or Object.prototype.__defineGetter__) before the polyfill code runs. I can’t think of a more robust solution. Can you?

Testing the polyfill

The polyfill is a good an interesting example of universal JavaScript: 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.

Here’s an HTML demo page for the polyfill that logs globalThis using both a classic script <a href="https://mathiasbynens.be/demo/globalthis.js" target="_blank">globalthis.js</a> and a module <a href="https://mathiasbynens.be/demo/globalthis.mjs" target="_blank">globalthis.mjs</a> (with identical source code). This demo can be used to verify the polyfill works in browsers. globalThis is natively supported in V8 v7.1 / Chrome 71, 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.

Note: The polyfill does not work in Internet Explorer 10 and older. In those browsers, the line __magic__.globalThis = __magic__ somehow doesn’t make globalThis globally available, despite __magic__ being a working reference to the global this. It turns out __magic__ !== window although both are [object Window], indicating that these browsers might be confused about the distinction between the global object and the global <a href="https://mathiasbynens.be/notes/globalthis#terminology" target="_blank">this</a>. Amending the polyfill to fall back to one of the alternatives makes it work in IE 10 and IE 9. For IE 8 support, wrap the call to Object.defineProperty in a try-catch, similarly falling back in the catch block. (Doing so also avoids the IE 7 issue with the global this not inheriting from Object.prototype.) Try the demo with old IE support.

To test in Node.js and standalone JavaScript engine binaries, download the very same JavaScript files:

# Download the polyfill + demo code as a module.
curl https://mathiasbynens.be/demo/globalthis.mjs > globalthis.mjs
# Create a copy (well, symlink) of the file, to be used as a classic script.
ln -s globalthis.mjs globalthis.js

Now we can test in node:

$ node --experimental-modules --no-warnings globalthis.mjs
Testing the polyfill in a module
[object global]

$ node globalthis.js
Testing the polyfill in a classic script
[object global]

To test in a stand-alone JavaScript engine shell, use <a href="https://github.com/GoogleChromeLabs/jsvu" target="_blank">jsvu</a> to install any desired engine, and then run the scripts directly. For example, to test in V8 v7.0 (without globalThis support) and v7.1 (with globalThis support):

$ jsvu v8@7.0 # Install the `v8-7.0.276` binary.

$ v8-7.0.276 globalthis.mjs
Testing the polyfill in a module
[object global]

$ v8-7.0.276 globalthis.js
Testing the polyfill in a classic script
[object global]

$ jsvu v8@7.1 # Install the `v8-7.1.302` binary.

$ v8-7.1.302 globalthis.js
Testing the polyfill in a classic script
[object global]

$ v8-7.1.302 globalthis.mjs
Testing the polyfill in a module
[object global]

The same technique allows us to test in JavaScriptCore, SpiderMonkey, Chakra, and other JavaScript engines such as XS as well. Here’s an example using JavaScriptCore:

$ jsvu # Install the `javascriptcore` binary.

$ javascriptcore globalthis.mjs
Testing the polyfill in a module
[object global]

$ javascriptcore globalthis.js
Testing the polyfill in a classic script
[object global]

Conclusion

Writing universal JavaScript can be tricky, and often calls for creative solutions. The new globalThis feature makes it easier to write universal JavaScript that needs access to the global this value. Polyfilling globalThis correctly is more challenging than it seems, but there is a working solution.

Only use this polyfill when you really need to. JavaScript modules 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 this anyway. globalThis is only useful for libraries and polyfills that do.

globalThis polyfills on npm

Since publishing this article, the following npm packages started providing globalThis polyfills that make use of this technique:

  • <a href="https://github.com/ungap/global-this" target="_blank">@ungap/global-this</a>
  • <a href="https://github.com/medikoo/es5-ext/blob/master/global.js" target="_blank">es5-ext</a>

Disclaimer: I’m not the author, nor am I the maintainer, of any of these packages.

#javascript

What is GEEK

Buddha Community

A horrifying globalThis polyfill in universal JavaScript

Rahul Jangid

1622207074

What is JavaScript - Stackfindover - Blog

Who invented JavaScript, how it works, as we have given information about Programming language in our previous article ( What is PHP ), but today we will talk about what is JavaScript, why JavaScript is used The Answers to all such questions and much other information about JavaScript, you are going to get here today. Hope this information will work for you.

Who invented JavaScript?

JavaScript language was invented by Brendan Eich in 1995. JavaScript is inspired by Java Programming Language. The first name of JavaScript was Mocha which was named by Marc Andreessen, Marc Andreessen is the founder of Netscape and in the same year Mocha was renamed LiveScript, and later in December 1995, it was renamed JavaScript which is still in trend.

What is JavaScript?

JavaScript is a client-side scripting language used with HTML (Hypertext Markup Language). JavaScript is an Interpreted / Oriented language called JS in programming language JavaScript code can be run on any normal web browser. To run the code of JavaScript, we have to enable JavaScript of Web Browser. But some web browsers already have JavaScript enabled.

Today almost all websites are using it as web technology, mind is that there is maximum scope in JavaScript in the coming time, so if you want to become a programmer, then you can be very beneficial to learn JavaScript.

JavaScript Hello World Program

In JavaScript, ‘document.write‘ is used to represent a string on a browser.

<script type="text/javascript">
	document.write("Hello World!");
</script>

How to comment JavaScript code?

  • For single line comment in JavaScript we have to use // (double slashes)
  • For multiple line comments we have to use / * – – * /
<script type="text/javascript">

//single line comment

/* document.write("Hello"); */

</script>

Advantages and Disadvantages of JavaScript

#javascript #javascript code #javascript hello world #what is javascript #who invented javascript

Hire Dedicated JavaScript Developers -Hire JavaScript Developers

It is said that a digital resource a business has must be interactive in nature, so the website or the business app should be interactive. How do you make the app interactive? With the use of JavaScript.

Does your business need an interactive website or app?

Hire Dedicated JavaScript Developer from WebClues Infotech as the developer we offer is highly skilled and expert in what they do. Our developers are collaborative in nature and work with complete transparency with the customers.

The technology used to develop the overall app by the developers from WebClues Infotech is at par with the latest available technology.

Get your business app with JavaScript

For more inquiry click here https://bit.ly/31eZyDZ

Book Free Interview: https://bit.ly/3dDShFg

#hire dedicated javascript developers #hire javascript developers #top javascript developers for hire #hire javascript developer #hire a freelancer for javascript developer #hire the best javascript developers

Niraj Kafle

1589255577

The essential JavaScript concepts that you should understand

As a JavaScript developer of any level, you need to understand its foundational concepts and some of the new ideas that help us developing code. In this article, we are going to review 16 basic concepts. So without further ado, let’s get to it.

#javascript-interview #javascript-development #javascript-fundamental #javascript #javascript-tips

Ajay Kapoor

1626321063

JS Development Company India | JavaScript Development Services

PixelCrayons: Our JavaScript web development service offers you a feature-packed & dynamic web application that effectively caters to your business challenges and provide you the best RoI. Our JavaScript web development company works on all major frameworks & libraries like Angular, React, Nodejs, Vue.js, to name a few.

With 15+ years of domain expertise, we have successfully delivered 13800+ projects and have successfully garnered 6800+ happy customers with 97%+ client retention rate.

Looking for professional JavaScript web app development services? We provide custom JavaScript development services applying latest version frameworks and libraries to propel businesses to the next level. Our well-defined and manageable JS development processes are balanced between cost, time and quality along with clear communication.

Our JavaScript development companies offers you strict NDA, 100% money back guarantee and agile/DevOps approach.

#javascript development company #javascript development services #javascript web development #javascript development #javascript web development services #javascript web development company

Santosh J

1622036598

JavaScript compound assignment operators

JavaScript is unarguablly one of the most common things you’ll learn when you start programming for the web. Here’s a small post on JavaScript compound assignment operators and how we use them.

The compound assignment operators consist of a binary operator and the simple assignment operator.

The binary operators, work with two operands. For example a+b where + is the operator and the a, b are operands. Simple assignment operator is used to assign values to a variable(s).

It’s quite common to modify values stored in variables. To make this process a little quicker, we use compound assignment operators.

They are:

  • +=
  • -+
  • *=
  • /=

You can also check my video tutorial compound assignment operators.

Let’s consider an example. Suppose price = 5 and we want to add ten more to it.

var price = 5;
price = price + 10;

We added ten to price. Look at the repetitive price variable. We could easily use a compound += to reduce this. We do this instead.

price += 5;

Awesome. Isn’t it? What’s the value of price now? Practice and comment below. If you don’t know how to practice check these lessons.

Lets bring down the price by 5 again and display it.
We use console.log command to display what is stored in the variable. It is very help for debugging.
Debugging let’s you find errors or bugs in your code. More on this later.

price -= 5;
console.log(price);

Lets multiply price and show it.

price *=5;
console.log(price);

and finally we will divide it.

price /=5;
console.log(price);

If you have any doubts, comment below.

#javascript #javascript compound assignment operators #javascript binary operators #javascript simple assignment operator #doers javascript