meteor / meteor

Meteor, the JavaScript App Platform
https://meteor.com
Other
44.06k stars 5.16k forks source link

[Meteor 3] Sequential packages loading order #13095

Closed radekmie closed 3 weeks ago

radekmie commented 1 month ago

Updated description

According to the @zodern's comments, I created a synchronous queue instead. It matches the expected loading order now (the tests are updated).

Previous description This is a different attempt at solving https://forums.meteor.com/t/order-of-loading-packages/61112 (see #13074 for the first one). The idea is to keep the dependency loading order as it was, but maintain a queue to load at most one package in order. How I tested it: * Use https://github.com/plbkbx/testLoadingPackages. * Add the following logging: ```diff diff --git a/packages/core-runtime/load-js-image.js b/packages/core-runtime/load-js-image.js index d18832c9fb..d1b9801b4c 100644 --- a/packages/core-runtime/load-js-image.js +++ b/packages/core-runtime/load-js-image.js @@ -9,6 +9,7 @@ var pending = Object.create(null); var hasOwn = Object.prototype.hasOwnProperty; function queue(name, deps, runImage) { + console.log(`queue(${name}, [${deps.join()}])`); pending[name] = []; var pendingDepsCount = 0; @@ -38,6 +39,7 @@ function queue(name, deps, runImage) { } function load(name, runImage) { + console.log(`load(${name})`); var config = runImage(); runEagerModules(config, function (mainModuleExports) { ```
Logs before ``` queue(meteor, [core-runtime]) load(meteor) queue(meteor-base, [meteor]) load(meteor-base) queue(npm-mongo, [meteor]) load(npm-mongo) queue(modules-runtime, [meteor]) load(modules-runtime) queue(modules, [meteor,modules-runtime]) load(modules) queue(react-fast-refresh, [meteor,modules]) load(react-fast-refresh) queue(ecmascript, [meteor,react-fast-refresh]) load(ecmascript) queue(ecmascript-runtime, [meteor]) load(ecmascript-runtime) queue(babel-runtime, [meteor,modules]) load(babel-runtime) queue(modern-browsers, [meteor,modules]) load(modern-browsers) queue(promise, [meteor,modules,modern-browsers]) load(promise) queue(fetch, [meteor,modules,modern-browsers,promise]) load(fetch) queue(inter-process-messaging, [meteor,modules,promise]) load(inter-process-messaging) queue(dynamic-import, [meteor,modules,promise,fetch,modern-browsers,inter-process-messaging]) load(dynamic-import) queue(es5-shim, [meteor,modules]) load(es5-shim) queue(ecmascript-runtime-client, [meteor,modules,promise,modern-browsers]) load(ecmascript-runtime-client) queue(ecmascript-runtime-server, [meteor,modules]) load(ecmascript-runtime-server) queue(base64, [meteor,ecmascript,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) load(base64) queue(ejson, [meteor,ecmascript,base64,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) load(ejson) queue(diff-sequence, [meteor,ecmascript,ejson,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) load(diff-sequence) queue(geojson-utils, [meteor,modules]) load(geojson-utils) queue(id-map, [meteor,ecmascript,ejson,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) load(id-map) queue(random, [meteor,ecmascript,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) load(random) queue(mongo-id, [meteor,ejson,random,ecmascript,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) load(mongo-id) queue(ordered-dict, [meteor,ecmascript,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) load(ordered-dict) queue(tracker, [meteor,ecmascript,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) load(tracker) queue(mongo-decimal, [meteor,ecmascript,ejson,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) load(mongo-decimal) queue(minimongo, [meteor,diff-sequence,ecmascript,ejson,geojson-utils,id-map,mongo-id,ordered-dict,random,tracker,mongo-decimal,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) load(minimongo) queue(check, [meteor,ecmascript,ejson,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) load(check) queue(retry, [meteor,ecmascript,random,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) load(retry) queue(callback-hook, [meteor,ecmascript,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) load(callback-hook) queue(ddp-common, [meteor,check,random,ecmascript,ejson,tracker,retry,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) load(ddp-common) queue(reload, [meteor,ecmascript,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) load(reload) queue(socket-stream-client, [meteor,ecmascript,modern-browsers,retry,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) load(socket-stream-client) queue(ddp-client, [meteor,check,random,ejson,tracker,retry,id-map,ecmascript,callback-hook,ddp-common,reload,socket-stream-client,diff-sequence,mongo-id,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) load(ddp-client) queue(underscore, [meteor]) load(underscore) queue(babel-compiler, [meteor,ecmascript-runtime,modern-browsers,ecmascript-runtime-client,ecmascript-runtime-server]) load(babel-compiler) queue(typescript, [meteor,babel-compiler,react-fast-refresh]) load(typescript) queue(logging, [meteor,ejson,ecmascript,typescript,ecmascript-runtime-client,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-server]) load(logging) queue(routepolicy, [meteor,ecmascript,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) load(routepolicy) queue(boilerplate-generator, [meteor,ecmascript,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) load(boilerplate-generator) queue(webapp-hashing, [meteor,ecmascript,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) load(webapp-hashing) queue(webapp, [meteor,ecmascript,logging,underscore,routepolicy,modern-browsers,boilerplate-generator,webapp-hashing,inter-process-messaging,callback-hook,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) load(webapp) queue(ddp-server, [meteor,check,random,ejson,underscore,retry,mongo-id,diff-sequence,ecmascript,ddp-common,ddp-client,webapp,routepolicy,callback-hook,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) queue(ddp, [meteor,ddp-client,ddp-server]) queue(allow-deny, [meteor,ecmascript,minimongo,check,ejson,ddp,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ddp-client,ddp-server,ecmascript-runtime-client,ecmascript-runtime-server]) queue(mongo-dev-server, [meteor,modules]) load(mongo-dev-server) queue(binary-heap, [meteor,id-map,ecmascript,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) load(binary-heap) queue(facts-base, [meteor,ecmascript,ddp,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ddp-client,ddp-server,ecmascript-runtime-client,ecmascript-runtime-server]) queue(mongo, [meteor,npm-mongo,allow-deny,random,ejson,minimongo,ddp,tracker,diff-sequence,mongo-id,check,ecmascript,logging,mongo-decimal,underscore,binary-heap,callback-hook,ddp-client,ddp-server,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) queue(one, [meteor,mongo,ddp-server,ddp-client]) queue(two, [meteor,mongo]) queue(three, [meteor,mongo]) queue(hot-code-push, [meteor]) load(hot-code-push) queue(autoupdate, [meteor,webapp,check,inter-process-messaging,ecmascript,ddp,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ddp-client,ddp-server,ecmascript-runtime-client,ecmascript-runtime-server]) queue(null, [meteor-base,one,two,three,underscore,mongo,ecmascript,meteor,webapp,ddp,es5-shim,hot-code-push,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ddp-client,ddp-server,autoupdate,reload,ecmascript-runtime-client,ecmascript-runtime-server]) load(ddp-server) load(ddp) load(allow-deny) load(facts-base) load(mongo) load(two) two.js load(three) three.js load(one) one.js load(autoupdate) load(null) main.js ```
Logs after ``` queue(meteor, [core-runtime]) load(meteor) queue(meteor-base, [meteor]) load(meteor-base) queue(npm-mongo, [meteor]) load(npm-mongo) queue(modules-runtime, [meteor]) load(modules-runtime) queue(modules, [meteor,modules-runtime]) load(modules) queue(react-fast-refresh, [meteor,modules]) queue(ecmascript, [meteor,react-fast-refresh]) queue(ecmascript-runtime, [meteor]) load(ecmascript-runtime) queue(babel-runtime, [meteor,modules]) queue(modern-browsers, [meteor,modules]) queue(promise, [meteor,modules,modern-browsers]) queue(fetch, [meteor,modules,modern-browsers,promise]) queue(inter-process-messaging, [meteor,modules,promise]) queue(dynamic-import, [meteor,modules,promise,fetch,modern-browsers,inter-process-messaging]) queue(es5-shim, [meteor,modules]) queue(ecmascript-runtime-client, [meteor,modules,promise,modern-browsers]) queue(ecmascript-runtime-server, [meteor,modules]) queue(base64, [meteor,ecmascript,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) queue(ejson, [meteor,ecmascript,base64,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) queue(diff-sequence, [meteor,ecmascript,ejson,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) queue(geojson-utils, [meteor,modules]) queue(id-map, [meteor,ecmascript,ejson,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) queue(random, [meteor,ecmascript,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) queue(mongo-id, [meteor,ejson,random,ecmascript,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) queue(ordered-dict, [meteor,ecmascript,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) queue(tracker, [meteor,ecmascript,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) queue(mongo-decimal, [meteor,ecmascript,ejson,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) queue(minimongo, [meteor,diff-sequence,ecmascript,ejson,geojson-utils,id-map,mongo-id,ordered-dict,random,tracker,mongo-decimal,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) queue(check, [meteor,ecmascript,ejson,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) queue(retry, [meteor,ecmascript,random,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) queue(callback-hook, [meteor,ecmascript,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) queue(ddp-common, [meteor,check,random,ecmascript,ejson,tracker,retry,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) queue(reload, [meteor,ecmascript,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) queue(socket-stream-client, [meteor,ecmascript,modern-browsers,retry,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) queue(ddp-client, [meteor,check,random,ejson,tracker,retry,id-map,ecmascript,callback-hook,ddp-common,reload,socket-stream-client,diff-sequence,mongo-id,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) queue(underscore, [meteor]) load(underscore) queue(babel-compiler, [meteor,ecmascript-runtime,modern-browsers,ecmascript-runtime-client,ecmascript-runtime-server]) queue(typescript, [meteor,babel-compiler,react-fast-refresh]) queue(logging, [meteor,ejson,ecmascript,typescript,ecmascript-runtime-client,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-server]) queue(routepolicy, [meteor,ecmascript,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) queue(boilerplate-generator, [meteor,ecmascript,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) queue(webapp-hashing, [meteor,ecmascript,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) queue(webapp, [meteor,ecmascript,logging,underscore,routepolicy,modern-browsers,boilerplate-generator,webapp-hashing,inter-process-messaging,callback-hook,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) queue(ddp-server, [meteor,check,random,ejson,underscore,retry,mongo-id,diff-sequence,ecmascript,ddp-common,ddp-client,webapp,routepolicy,callback-hook,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) queue(ddp, [meteor,ddp-client,ddp-server]) queue(allow-deny, [meteor,ecmascript,minimongo,check,ejson,ddp,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ddp-client,ddp-server,ecmascript-runtime-client,ecmascript-runtime-server]) queue(mongo-dev-server, [meteor,modules]) queue(binary-heap, [meteor,id-map,ecmascript,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) queue(facts-base, [meteor,ecmascript,ddp,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ddp-client,ddp-server,ecmascript-runtime-client,ecmascript-runtime-server]) queue(mongo, [meteor,npm-mongo,allow-deny,random,ejson,minimongo,ddp,tracker,diff-sequence,mongo-id,check,ecmascript,logging,mongo-decimal,underscore,binary-heap,callback-hook,ddp-client,ddp-server,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ecmascript-runtime-client,ecmascript-runtime-server]) queue(one, [meteor,mongo,ddp-server,ddp-client]) queue(two, [meteor,mongo]) queue(three, [meteor,mongo]) queue(hot-code-push, [meteor]) load(hot-code-push) queue(autoupdate, [meteor,webapp,check,inter-process-messaging,ecmascript,ddp,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ddp-client,ddp-server,ecmascript-runtime-client,ecmascript-runtime-server]) queue(null, [meteor-base,one,two,three,underscore,mongo,ecmascript,meteor,webapp,ddp,es5-shim,hot-code-push,modules,ecmascript-runtime,babel-runtime,promise,dynamic-import,ddp-client,ddp-server,autoupdate,reload,ecmascript-runtime-client,ecmascript-runtime-server]) load(react-fast-refresh) load(babel-runtime) load(modern-browsers) load(es5-shim) load(ecmascript-runtime-server) load(geojson-utils) load(mongo-dev-server) load(ecmascript) load(promise) load(fetch) load(inter-process-messaging) load(ecmascript-runtime-client) load(dynamic-import) load(babel-compiler) load(typescript) load(base64) load(random) load(ordered-dict) load(tracker) load(callback-hook) load(reload) load(routepolicy) load(boilerplate-generator) load(webapp-hashing) load(ejson) load(retry) load(diff-sequence) load(id-map) load(mongo-id) load(mongo-decimal) load(check) load(logging) load(socket-stream-client) load(binary-heap) load(minimongo) load(ddp-common) load(webapp) load(ddp-client) load(ddp-server) load(ddp) load(allow-deny) load(facts-base) load(autoupdate) load(mongo) load(one) one.js load(two) two.js load(three) three.js load(null) main.js ```
As you can see, the last few lines show that the packages were loaded in the expected order, i.e., `one`, `two`, `three`.
netlify[bot] commented 1 month ago

Deploy Preview for v3-meteor-api-docs canceled.

Name Link
Latest commit 37c2f09aeb3fd21c6199a04b6882bae63c0c7b1b
Latest deploy log https://app.netlify.com/sites/v3-meteor-api-docs/deploys/662158c46ca9b20008d850b8
radekmie commented 4 weeks ago

There's one test failing and I'm not sure if it's "failing correctly". The ordering is, of course, changed, but the final one looks OK to me. @zodern could you check it maybe?

diff --git a/tools/tests/top-level-await.js b/tools/tests/top-level-await.js
index b2deb6ca11..26d2fa0d4c 100644
--- a/tools/tests/top-level-await.js
+++ b/tools/tests/top-level-await.js
@@ -23,18 +23,18 @@ selftest.define("xxxx top level await - order", async function (options) {

     const lines = [
       'package sync',
-      'package 1 - b before',
-      'package 2 - b',
-      'package 2 - a before',
       'package sync - later',
+      'package 1 - b before',
       'package 1 - b after',
-      'package 2 - b later',
-      'package 2 - a after',
       'package 1 - b later',
       'package 1 - a before',
-      'package 2 - a later',
       'package 1 - a after',
       'package 1 - a later',
+      'package 2 - b',
+      'package 2 - a before',
+      'package 2 - b later',
+      'package 2 - a after',
+      'package 2 - a later',
       'app a.js - before',
       'app b.js - before',
       'app a.js - after',
denihs commented 4 weeks ago

Well, considering that we now have a sequential load, I believe this new other is correct. Let's see what @zodern thinks.

zodern commented 4 weeks ago

I'm a little surprised this works without removing the deps tracking, though it was designed to load in the original order when all packages are sync.

A couple things:

  1. As far as I know, Meteor 3 doesn't drop support for any browsers. If you notice, the code is careful to only use Promise after a package that uses top level await since that would indicate a promise polyfill has already loaded.
  2. package sync - later should be after package 1 - b before and before package 1 - b after. The top level await spec and the implementation in Meteor is very precise about when microtasks are added, and the core-runtime is the same to avoid breaking changes in Meteor 3 - when packages are sync, they run immediately after each other before any other microtasks are able to run.

Another thing is that the deps code isn't adding anything here. You should be able to move the queueing into core-runtime.queue and have it ignore the deps.

zodern commented 4 weeks ago

I noticed I misunderstood the implementation. It seems it does rely on the deps code still, and only ensures sequential order for eager modules. It seems likely there are edge cases when mixing packages that are async with packages that don't have a dependency on modules or that have bare files.

In the logs, it needs an additional message for when a package finishes loading to check that each package doesn't start loading until the previous one finishes.

I would also suggest making package 1 in the test use top level await to wait 100ms before logging console.log('one.js'), and adding a bare file to one of the other packages.

zodern commented 4 weeks ago

The after logs don't show the packages loading in the correct order:

queue(meteor, [core-runtime])
load(meteor)
queue(meteor-base, [meteor])
load(meteor-base)
queue(npm-mongo, [meteor])
load(npm-mongo)
queue(modules-runtime, [meteor])
load(modules-runtime)
queue(modules, [meteor,modules-runtime])
load(modules)
queue(react-fast-refresh, [meteor,modules])
queue(ecmascript, [meteor,react-fast-refresh])
queue(ecmascript-runtime, [meteor])
load(ecmascript-runtime) <---- this package is loading before react-fast-refresh

The packages that have a dependency on modules (have eager modules) are delayed and run later than they should. If you look in the before logs, the packages run immediately after being queued until it gets to a package that uses top level await.


I was expecting the implementation to look something like:

var pending = [];
var processingQueue = false;

function queue(name, runImage) {
 pending.push({name: name, runImage: runImage});

  processNext();
}

function processNext() {
  if (processingQueue) { 
    return;
  }

  var config = pending.shift();
  if (!config) {
    return;
  }

  processingQueue = true;
  loadImage(config.name, config.runImage, function () {
    processingQueue = false;
    processNext();
  });
}

It has a simple queue and processes one item at a time. Since queue is already called in the correct order for packages to load, it preserves that order and no longer needs the deps array.

radekmie commented 4 weeks ago

I've tried to implement such a queue @zodern, but no matter what I try, it fails with the following error while loading the promise package:

Code ```js // This file needs to work in old web browsers and old node versions // It should not use js features newer than EcmaScript 5. // // Handles loading linked code for packages and apps // Ensures packages and eager requires run in the correct order // when there is code that uses top level await var hasOwn = Object.prototype.hasOwnProperty; var pending = []; var isProcessing = false; function queue(name, deps, runImage) { console.log(`queue(${name})`); pending.push({name: name, runImage: runImage}); processNext(); } function processNext() { if (isProcessing) { return; } var next = pending.shift(); if (!next) { return; } console.log(`load(${next.name})`); isProcessing = true; var config = next.runImage(); runEagerModules(config, function (mainModuleExports) { // Get the exports after the eager code has been run var exports = config.export ? config.export() : {}; if (config.mainModulePath) { Package._define(next.name, mainModuleExports, exports); } else { Package._define(next.name, exports); } isProcessing = false; processNext(); }); } function runEagerModules(config, callback) { if (!config.eagerModulePaths) { return callback(); } var index = -1; var mainExports = {}; var mainModuleAsync = false; function evaluateNextModule() { index += 1; if (index === config.eagerModulePaths.length) { if (mainModuleAsync) { // Now that the package has loaded, mark the main module as sync // This allows other packages and the app to `require` the package // and for it to work the same, regardless of if it uses TLA or not // XXX: this is a temporary hack until we find a better way to do this const reify = config.require('/node_modules/meteor/modules/node_modules/@meteorjs/reify/lib/runtime'); reify._requireAsSync(config.mainModulePath); } return callback(mainExports); } var path = config.eagerModulePaths[index]; var exports = config.require(path); if (checkAsyncModule(exports)) { if (path === config.mainModulePath) { mainModuleAsync = true; } // Is an async module exports.then(function (exports) { if (path === config.mainModulePath) { mainExports = exports; } evaluateNextModule(); }) // This also handles errors in modules and packages loaded sync // afterwards since they are run within the `.then`. .catch(function (error) { if ( typeof process === 'object' && typeof process.nextTick === 'function' ) { // Is node.js process.nextTick(function () { throw error; }); } else { // TODO: is there a faster way to throw the error? setTimeout(function () { throw error; }, 0); } }); } else { if (path === config.mainModulePath) { mainExports = exports; } evaluateNextModule(); } } evaluateNextModule(); } function checkAsyncModule (exports) { var potentiallyAsync = exports && typeof exports === 'object' && hasOwn.call(exports, '__reifyAsyncModule'); if (!potentiallyAsync) { return; } return typeof exports.then === 'function'; } // For this to be accurate, all linked files must be queued before calling this // If all are loaded, returns null. Otherwise, returns a promise function waitUntilAllLoaded() { if (pending.length === 0) { // All packages are loaded // If there were no async packages, then there might not be a promise // polyfill loaded either, so we don't create a promise to return return null; } return new Promise(function (resolve) { queue('', [], function () { resolve(); return {}; }); }); } // Since the package.js doesn't export load or waitUntilReady // these will never be globals in packages or apps that depend on core-runtime Package['core-runtime'] = { queue: queue, waitUntilAllLoaded: waitUntilAllLoaded }; ```
Errors prevented isopacket build:             

While loading plugin `compile-ecmascript` from package `ecmascript`:
packages/promise.js:60:21: Cannot read properties of undefined (reading 'prototype')
at module (packages/promise.js:60:21)
at fileEvaluate (packages/modules-runtime.js:335:7)
at Module.require (packages/modules-runtime.js:237:14)
at Module.mod.require
(/Users/radekmie/Projects/meteor/packages/modules/.npm/package/node_modules/@meteorjs/reify/lib/runtime/index.js:30:33)
at require (packages/modules-runtime.js:257:21)
at module (packages/promise.js:33:1)
at fileEvaluate (packages/modules-runtime.js:335:7)
at Module.require (packages/modules-runtime.js:237:14)
at Module.mod.require
(/Users/radekmie/Projects/meteor/packages/modules/.npm/package/node_modules/@meteorjs/reify/lib/runtime/index.js:30:33)
at Object.require (packages/modules-runtime.js:257:21)
at evaluateNextModule (packages/core-runtime.js:170:26)
at evaluateNextModule (packages/core-runtime.js:205:7)
at runEagerModules (packages/core-runtime.js:209:3)
at processNext (packages/core-runtime.js:131:3)
at Object.queue (packages/core-runtime.js:114:3)
at packages/promise.js:1:29

While loading plugin `compile-typescript` from package `typescript`:
packages/promise.js:60:21: Cannot read properties of undefined (reading 'prototype')
at module (packages/promise.js:60:21)
at fileEvaluate (packages/modules-runtime.js:335:7)
at Module.require (packages/modules-runtime.js:237:14)
at Module.mod.require
(/Users/radekmie/Projects/meteor/packages/modules/.npm/package/node_modules/@meteorjs/reify/lib/runtime/index.js:30:33)
at require (packages/modules-runtime.js:257:21)
at module (packages/promise.js:33:1)
at fileEvaluate (packages/modules-runtime.js:335:7)
at Module.require (packages/modules-runtime.js:237:14)
at Module.mod.require
(/Users/radekmie/Projects/meteor/packages/modules/.npm/package/node_modules/@meteorjs/reify/lib/runtime/index.js:30:33)
at Object.require (packages/modules-runtime.js:257:21)
at evaluateNextModule (packages/core-runtime.js:170:26)
at evaluateNextModule (packages/core-runtime.js:205:7)
at runEagerModules (packages/core-runtime.js:209:3)
at processNext (packages/core-runtime.js:131:3)
at Object.queue (packages/core-runtime.js:114:3)
at packages/promise.js:1:29

/Users/radekmie/Projects/meteor/tools/tool-env/isopackets.js:234
    throw new Error("isopacket build failed?");
          ^

Error: isopacket build failed?
    at Object.ensureIsopacketsLoadable (/tools/tool-env/isopackets.js:239:11)
    at /tools/cli/main.js:869:3

Node.js v20.11.1

I'll try to make my Promise-based solution to match the ordering you said and think on how to handle it without Promises.