Merge pull request #12537 from meteor/adjust-detecting-fibers-enabled

[Meteor 3] Adjustments to detecting if fibers are enabled
This commit is contained in:
Gabriel Grubba
2023-03-10 17:57:33 -03:00
committed by GitHub
10 changed files with 109 additions and 12 deletions

View File

@@ -188,16 +188,15 @@ function getDefaultsForNode8(features) {
);
// TODO [fibers]: instead of removing the code below, consider this comment:
// https://github.com/meteor/meteor/pull/12471/files#r1089610144
const isFiberDisabled = process.env.DISABLE_FIBERS === '1';
const ignoreAsyncPlugin = process.env.IGNORE_ASYNC_PLUGIN === '1';
if (!ignoreAsyncPlugin) {
if (!features.useNativeAsyncAwait && !ignoreAsyncPlugin) {
combined.plugins.push([
require('./plugins/async-await.js'),
{
// Do not transform `await x` to `Promise.await(x)`, since Node
// 8 has native support for await expressions.
useNativeAsyncAwait: isFiberDisabled,
// Even though Node 8 supports native async/await, it is not
// compatible with fibers.
useNativeAsyncAwait: false,
},
]);
}

View File

@@ -0,0 +1,74 @@
"use strict";
module.exports = function (babel) {
const t = babel.types;
return {
name: "transform-meteor-async-await",
visitor: {
Function: {
exit: function (path) {
const node = path.node;
if (!node.async) {
return;
}
// The original function becomes a non-async function that
// returns a Promise.
node.async = false;
// The inner function should inherit lexical environment items
// like `this`, `super`, and `arguments` from the outer
// function, and arrow functions provide exactly that behavior.
const innerFn = t.arrowFunctionExpression(
// The inner function has no parameters of its own, but can
// refer to the outer parameters of the original function.
[],
node.body,
// The inner function called by Promise.asyncApply should be
// async if we have native async/await support.
!!this.opts.useNativeAsyncAwait
);
const promiseResultExpression = t.callExpression(
t.memberExpression(
t.identifier("Promise"),
t.identifier("asyncApply"),
false
), [innerFn]
);
// Calling the async function with Promise.asyncApply is
// important to ensure that the part before the first await
// expression runs synchronously in its own Fiber, even when
// there is native support for async/await.
if (node.type === "ArrowFunctionExpression") {
node.body = promiseResultExpression;
} else {
node.body = t.blockStatement([
t.returnStatement(promiseResultExpression)
]);
}
}
},
AwaitExpression: function (path) {
if (this.opts.useNativeAsyncAwait) {
// No need to transform await expressions if we have native
// support for them.
return;
}
const node = path.node;
path.replaceWith(t.callExpression(
t.memberExpression(
t.identifier("Promise"),
t.identifier(node.all ? "awaitAll" : "await"),
false
),
[node.argument]
));
}
}
};
};

View File

@@ -96,6 +96,8 @@ BCp.processOneFileForTarget = function (inputFile, source) {
features.topLevelAwait = arch.startsWith('os.') || enableClientTLA
features.useNativeAsyncAwait = Meteor.isFibersDisabled;
if (! features.hasOwnProperty("jscript")) {
// Perform some additional transformations to improve compatibility
// in older browsers (e.g. wrapping named function expressions, per

View File

@@ -1,3 +1,5 @@
Meteor.isFibersDisabled = true;
Meteor._isPromise = (r) => {
return r && typeof r.then === 'function';
};

View File

@@ -2,7 +2,9 @@ const getAslStore = () => (Meteor.isServer && global?.asyncLocalStorage?.getStor
const getValueFromAslStore = key => getAslStore()[key];
const updateAslStore = (key, value) => getAslStore()[key] = value;
Meteor._isFibersEnabled = !process.env.DISABLE_FIBERS && Meteor.isServer;
Meteor.isFibersDisabled = !!__meteor_bootstrap__.isFibersDisabled;
Meteor._isFibersEnabled = !Meteor.isFibersDisabled;
Meteor._getAslStore = getAslStore;
Meteor._getValueFromAslStore = getValueFromAslStore;
Meteor._updateAslStore = updateAslStore;

View File

@@ -369,7 +369,8 @@ Previous builder: ${previousBuilder.outputPath}, this builder: ${outputPath}`
const babel = require("@meteorjs/babel");
const commonBabelOptions = babel.getDefaultOptions({
nodeMajorVersion: parseInt(process.versions.node),
typescript: true
typescript: true,
useNativeAsyncAwait: true
});
commonBabelOptions.sourceMaps = true;

View File

@@ -472,8 +472,19 @@ Object.assign(Isopack.prototype, {
// case right.)
}, async function () {
// Make a new Plugin API object for this plugin.
var Plugin = self._makePluginApi(name);
await plugin.load({ Plugin: Plugin, Profile: Profile });
const Plugin = self._makePluginApi(name);
const __meteor_bootstrap__ = {
isFibersDisabled: true,
// Set to null to tell Meteor.startup to call hooks immediately
// XXX: should we fully support startup hooks in build plugins?
startupHooks: null
};
await plugin.load({
Plugin,
Profile,
__meteor_bootstrap__
});
});
}

View File

@@ -33,7 +33,8 @@ var starJson = JSON.parse(fs.readFileSync(path.join(buildDir, "star.json")));
__meteor_bootstrap__ = {
startupHooks: [],
serverDir: serverDir,
configJson: configJson
configJson: configJson,
isFibersDisabled: true
};
__meteor_runtime_config__ = {
@@ -508,3 +509,4 @@ var runMain = Profile("Run main()", async function () {
process.exit(1)
});

View File

@@ -11,7 +11,8 @@ function babelRegister() {
const cacheDir = path.join(meteorPath, ".babel-cache");
const babelOptions = meteorBabel.getDefaultOptions({
nodeMajorVersion: parseInt(process.versions.node),
typescript: true
typescript: true,
useNativeAsyncAwait: true
});
// Make sure that source maps are included in the generated code for

View File

@@ -303,7 +303,10 @@ var loadIsopacketFromDisk = async function (isopacketName) {
// An incredibly minimalist version of the environment from
// tools/server/boot.js. Kind of a hack.
var env = {
__meteor_bootstrap__: { startupHooks: [] },
__meteor_bootstrap__: {
startupHooks: [],
isFibersDisabled: true
},
__meteor_runtime_config__: { meteorRelease: "ISOPACKET" }
};
env.Profile = Profile;