[Embroider] dependencySatisfies gives wrong answer for 'ember-source'

Hey,

I have a similar problem to Help needed - struggling to find/resolve a deprecation : I’m trying to get rid of the ember.global deprecation, and there’s a window.Ember usage in the ember-private-api.js file of the @embroider/util package:

if (
  macroCondition(
    dependencySatisfies('ember-source', '>=3.27.0-canary || >=3.27.0-beta')
  )
) {
  // new enough ember has a real module we can import
  runtime = importSync('@glimmer/runtime');
} else {
  // older ember has its own internal loader
  runtime = window.Ember.__loader.require('@glimmer/runtime');
}

The project uses version 3.28.6 of ember-source so the else branch shouldn’t be executed but for some reason it still does, triggering the deprecation.

Having read what @ef4 said on the other thread, I was looking for some other dependency that might pull in ember-source but there are lots, as a lot of add-ons have ember-source as a devDependency.

However, if I’m not mistaken, if Project A has a devDependency on Package B, and Package C is a devDependency of Package B, if I (yarn) install Project A, Package C will not be installed so as long as some add-on doesn’t have a (non-dev) dependency on ember-source, there’ll only ever be one ember-source in the whole of node_modules. Which is what I see when running yarn why ember-source.

So to be able to go on with this, I’d need to understand what dependencySatisfies actually checks.

Reading the source code it uses the package cache and Ed mentioned there is an outstanding bug, so I cleared the cache before building the app but it didn’t help.

Unfortunately putting breakpoints in Embroider code or logging out stuff didn’t get me very far so far so maybe understanding how a package dependency is resolved (specifically the pkg = packageCache.resolve(packageName, us); line in the implementation of dependencySatisfies) can unblock me faster.

Thank you!

2 Likes

Is there a monorepo or yarn linking involved? We have repeatedly seen that both yarn and NPM won’t honor peer dependencies correctly in those situations, and I can recommend pnpm as more correct.

dependencySatisfies follows node resolution. So if you cd into the directory where ember-private-api.js is installed, and in that directory run node -e 'console.log(require.resolve("ember-source/package.json"))' it will tell you which copy it is seeing.

@ef4 Thank you for the quick response!

No, it’s a “classic” app using yarn 1.22.18.

Based on the answer you gave on the other, similar thread, I’d tried (sorry I didn’t mention it) but it gives me an error:

Volta error: Could not determine path to project workspace: '../../package.json'

Please ensure that the file exists and is accessible.

I’m fairly(?) certain that this comes through because embroider is built as a monorepo so it extends the package.json of the “parent” package.

I simply removed the volta configuration from the util package, and tried to get the resolved version again:

@embroider/util/addon $ node -e 'console.log(require(“ember-source/package.json”).version) >3.28.6

I get the same, correct result when I issue the same command from the root of the @embroider packages, two directories above.

I assume it’s basically the same thing but I also tried exactly what you suggested:

@embroider/util/addon $ node -e ‘console.log(require.resolve(“ember-source/package.json”))’ > <path_to_app>/node_modules/ember-source/package.json

So it seems like it should work and yet it doesn’t.

That’s probably not the right way to go but I also wrote two tests to see which version is resolved from the top-level:

import { module, test } from 'qunit';
import { macroCondition, dependencySatisfies } from '@embroider/macros';

module('dependencySatisfies', function () {
  test('ember-source is >= 3.27', function (assert) {
    let result = dependencySatisfies(
      'ember-source',
      '>=3.27.0-canary || >=3.27.0-beta'
    );
    assert.ok(result);
  });
  test('ember-source is >= 3.27 (with macroCondition)', function (assert) {
    assert.expect(1);

    if (
      macroCondition(
        dependencySatisfies('ember-source', '>=3.27.0-canary || >=3.27.0-beta')
      )
    ) {
      assert.ok(true);
    }
  });
});

I’m not sure if there are peerDependencies involved (I can check at a saner hour) but I gave this a try with pnpm and it just works, without throwing any errors :open_mouth: .

I guess the question is now how stable/reliable pnpm is to adopt it as the package manager for a large, “real” project :slight_smile: