From 8bfdea712a758fea369da7bed18eeeb9f74b567a Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Tue, 1 May 2018 19:37:59 -0400 Subject: [PATCH] Use legacy workaround for @babel/runtime/helpers/inheritsLoose. IE10 does not support setting the __proto__ property of objects as an alternative to Object.setPrototypeOf. Because Babel generates code that uses the @babel/runtime/helpers/inheritsLoose helper, and that helper relies on setting __proto__, subclassing fails in Babel-generated code in IE10 (and earlier), which causes a white screen of death in newly created Meteor apps. This commit checks whether setting __proto__ works, and (if not) overrides the inheritsLoose helper with an implementation that does not rely on setting __proto__. This logic applies only in legacy browsers, thanks to api.addFiles("legacy.js", "legacy"). Although this shim isn't perfect (for example, there is no way to set up true inheritance of static properties), it will allow inheritance to work in browsers that would otherwise be completely broken. Since IE10 represents only 0.1% of the world market, we should not overinvest in keeping it working, but this seemed like a good opportunity to take advantage of legacy bundling, without adding any new code to the modern bundle. --- packages/babel-runtime/legacy.js | 53 +++++++++++++++++++++++++++++++ packages/babel-runtime/package.js | 3 +- 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 packages/babel-runtime/legacy.js diff --git a/packages/babel-runtime/legacy.js b/packages/babel-runtime/legacy.js new file mode 100644 index 0000000000..e9973cb1b5 --- /dev/null +++ b/packages/babel-runtime/legacy.js @@ -0,0 +1,53 @@ +// This module contains various legacy workarounds for @babel/runtime issues +// in older browsers. Note that this module is loaded only in legacy +// environments, and no changes are made unless they are necessary. + +var hasOwn = Object.prototype.hasOwnProperty; +var helpers = {}; + +function assign(into, from) { + Object.keys(from).forEach(function (key) { + if (! hasOwn.call(into, key)) { + into[key] = from[key]; + } + }); + return into; +} + +var obj = {}; +obj.__proto__ = { test: obj }; +var canSetProto = obj.test === obj; + +if (! canSetProto) { + // Browsers that don't allow setting __proto__ (and also do not support + // Object.setPrototypeOf) cannot use the inheritsLoose @babel/runtime + // helper module, so we replace it with a similar module that works + // infinitely better in older browsers. + helpers.inheritsLoose = function (require, exports, module) { + module.exports = function (subclass, superclass) { + subclass.prototype = assign( + Object.create(superclass.prototype), + subclass.prototype + ); + // This isn't true static inheritance, since static properties added + // to or removed from the superclass later will not be reflected on + // the subclass, but this approximation is the best that we can do. + assign(subclass, superclass); + }; + }; +} + +// Install @babel/runtime/helpers/... modules that will take precedence +// over the actual modules, regardless of which gets installed first, +// because these replacement modules don't have a .js file extension. +if (Object.keys(helpers).length > 0) { + meteorInstall({ + node_modules: { + "@babel": { + runtime: { + helpers: helpers + } + } + } + }); +} diff --git a/packages/babel-runtime/package.js b/packages/babel-runtime/package.js index 1bb76b6b99..6b5e6b2d12 100644 --- a/packages/babel-runtime/package.js +++ b/packages/babel-runtime/package.js @@ -1,7 +1,7 @@ Package.describe({ name: "babel-runtime", summary: "Runtime support for output of Babel transpiler", - version: '1.2.2', + version: '1.3.0', documentation: 'README.md' }); @@ -12,5 +12,6 @@ Npm.depends({ Package.onUse(function (api) { api.use("modules"); api.mainModule("babel-runtime.js"); + api.addFiles("legacy.js", "legacy"); api.export("meteorBabelHelpers"); });