Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GLSL transformer fails to find nested vendor dependencies (works in v1, fails in v2) #7253

Closed
keeffEoghan opened this issue Nov 4, 2021 · 5 comments · Fixed by #7263
Closed

Comments

@keeffEoghan
Copy link

keeffEoghan commented Nov 4, 2021

🐛 bug report

Parcel v2 fails to correctly resolve glslify nested vendor dependencies (from e.g: node_modules).

This behaviour worked correctly in v1.

However, the @parcel/transformer-glsl introduced in #3352 fails to correctly resolve nested dependencies in vendor dependencies.

🎛 Configuration (.babelrc, package.json, cli command)

For both versions, the initial configuration is:

package.json (devDependencies differ with each setup)

{
  "name": "parcel-glsl-test",
  "packageManager": "[email protected]",
  "engines": { "node": "v16.13.0", "yarn": "3.1.0" },
  "scripts": { "start": "parcel ./src/index.html" },
  "dependencies": { "glsl-easings": "^1.0.0", "typescript": "^4.4.4" },
  "devDependencies": {}
}

src/index.js

import frag from './frag.glsl';

console.log(frag);

src/frag.glsl

precision mediump float;

// Import via project directory with further nested imports - works.
#pragma glslify: f = require('./f');

varying float x;

void main() { gl_FragColor = vec4(f(x)); }

src/f.glsl

// Import via node_modules without further nested imports - works.
#pragma glslify: e0 = require('glsl-easings/back-in');

// Import via node_modules with further nested imports - fails.
#pragma glslify: e1 = require('glsl-easings/bounce-in');

// Import via project directory without further nested imports - works.
#pragma glslify: b = require('./a/b');

float f(float x) { return e0(e1(b(x))); }

#pragma glslify: export(f);

src/a/b.glsl

float b(float p) { return p*2.0; }

#pragma glslify: export(b);

.yarnrc.yml (does not use PnP mode)

yarnPath: .yarn/releases/yarn-3.1.0.cjs
nodeLinker: node-modules

See also glsl-easings/back-in.glsl, which has no nested imports.

See also glsl-easings/bounce-in.glsl, which has a further nested import.

Each setup also has a slightly different src/index.html entry-point, as shown in the below sections.

🤔 Expected Behavior

Parcel glslify transform should correctly resolve all nested dependencies, including those in vendor (e.g: node_modules) directories, to produce built GLSL code.
The Parcel v1 ([email protected]) glslify transform behaves correctly for nested vendor dependencies.

Installed and run with:

yarn add -D --mode=skip-build [email protected]
yarn start

The above code should print correct code similar to this to the browser console:

precision mediump float;
#define GLSLIFY 1

// Import via project directory with further nested imports - works.
// Import via node_modules without further nested imports - works.
#ifndef PI
#define PI 3.141592653589793
#endif

float backIn(float t) {
  return pow(t, 3.0) - t * sin(t * PI);
}

// Import via node_modules with further nested imports - fails.
#ifndef PI
#define PI 3.141592653589793
#endif

float bounceOut(float t) {
  const float a = 4.0 / 11.0;
  const float b = 8.0 / 11.0;
  const float c = 9.0 / 10.0;

  const float ca = 4356.0 / 361.0;
  const float cb = 35442.0 / 1805.0;
  const float cc = 16061.0 / 1805.0;

  float t2 = t * t;

  return t < a
    ? 7.5625 * t2
    : t < b
      ? 9.075 * t2 - 9.9 * t + 3.4
      : t < c
        ? ca * t2 - cb * t + cc
        : 10.8 * t * t - 20.52 * t + 10.72;
}

float bounceIn(float t) {
  return 1.0 - bounceOut(1.0 - t);
}

// Import via project directory without further nested imports - works.
float b_0(float p) { return p*2.0; }

float f(float x) { return backIn(bounceIn(b_0(x))); }

varying float x;

void main() { gl_FragColor = vec4(f(x)); }

This setup adds to the above devDependencies for Parcel v1:
package.json

  "devDependencies": { "glslify-bundle": "^5.1.1", "glslify-deps": "^1.3.2", "parcel-bundler": "^1.12.5" }

This setup uses the following HTML entry-point (without script type="module"):
src/index.html

<!DOCTYPE html><html><script src="./index.js"></script></html>

😯 Current Behavior

The Parcel v2 ([email protected]) glslify transform fails to resolve nested vendor dependencies (e.g: node_modules), though it correctly handles nested project dependencies (within the project's own directories).

Installed and run with:

yarn add -D --mode=skip-build [email protected]
yarn start

The CLI displays an error message, showing paths that seem to be relative to the project directory, not the vendor (e.g: node_modules) directories as would be expected:

yarn start
Server running at http://localhost:1234
🚨 Build failed.

@parcel/core: Failed to resolve './bounce-out' from './src/frag.glsl'

@parcel/resolver-default: Cannot load file './bounce-out' in './src'.

This setup adds to the above devDependencies for Parcel v2:
package.json

  "devDependencies": { "@parcel/transformer-glsl": "^2.0.0", "parcel": "^2.0.0" }

This setup uses the following HTML entry-point (with script type="module"):
src/index.html

<!DOCTYPE html><html><script src="./index.js" type="module"></script></html>

Note that commenting out this line in src/f.glsl:

// #pragma glslify: e1 = require('glsl-easings/bounce-in');

Causes the build to succeed and the following to be printed to the browser console:

precision mediump float;
#define GLSLIFY 1

// Import via project directory with further nested imports - works.
// Import via node_modules without further nested imports - works.
#ifndef PI
#define PI 3.141592653589793
#endif

float backIn(float t) {
  return pow(t, 3.0) - t * sin(t * PI);
}

// Import via node_modules with further nested imports - fails.
// #pragma glslify: e1 = require('glsl-easings/bounce-in');

// Import via project directory without further nested imports - works.
float b(float p) { return p*2.0; }

float f(float x) { return backIn(e1(b(x))); }

varying float x;

void main() { gl_FragColor = vec4(f(x)); }

This demonstrates that the problem is likely with only nested vendor dependencies, not the project's own local dependencies.

💁 Possible Solution

I expect this probably has something to do with the way vendor paths are resolved in the glslify transform for Parcel v2; I had a look but am not familiar enough with the APIs to attempt a fix:

🔦 Context

This issue has caused me to upgrade to Parcel v2, fail to solve the problem after following misleading error messages, then roll back to v1 - at least 3 times over the last year.
It blocks me from migrating any WebGL projects to Parcel v2, which in turn prevents me from benefitting from any of the latest developments and up-to-date support of Parcel v2.
It seems that a simple glslify transformer fix here in v2, looking at a correctly-working setup in v1, would solve all these issues.

💻 Code Sample

Included throughout above.

🌍 Your Environment

Included throughout above.

@mischnic
Copy link
Member

mischnic commented Nov 7, 2021

The reason that glsl-easings appears to be the culprit is the

	"engines" {
		"node": "..."
	}

line which causes Parcel to not bundle node_modules (so that glsl-easings/back-in import in GLSL is also theoretically excluded). So you need to remove that in any case.

Actual bug: #7263

@keeffEoghan
Copy link
Author

Can confirm this now works correctly in today's v2.0.1 release!
Also thanks @mischnic, I learned about the engines etc config today - though it seems that this now works with that field there anyway, doesn't seem to need node_modules to be bundled! (At least for my test)

@keeffEoghan
Copy link
Author

keeffEoghan commented Nov 8, 2021

Ah, however, it fails with a new error when attempting to run parcel build ... (rather than the dev server parcel ... which works now); the error is:

🚨 Build failed.

@parcel/transformer-glsl: Got unexpected null

  Error: Got unexpected null
  at nullthrows (.../node_modules/nullthrows/nullthrows.js:7:15)
  at resolve (.../node_modules/@parcel/core/lib/Transformation.js:578:100)
  at async Depper.resolve (.../node_modules/@parcel/transformer-glsl/lib/GLSLTransformer.js:72:26)

Since this is only with production build, I tried again with --no-scope-hoist/--no-optimize/--no-content-hash, but both scripts give identical errors; of these 3 scripts only start works:

{
  "scripts": {
    "start": "parcel --log-level verbose ./src/index.html",
    "dev": "parcel build --log-level verbose ./src/index.html --no-scope-hoist --no-optimize --no-content-hash",
    "build": "parcel build --log-level verbose ./src/index.html"
  }
}

Any ideas?

@mischnic
Copy link
Member

mischnic commented Nov 9, 2021

I only get that with engines.node (which as I've said should be removed)

(But that error message is not ideal)

@keeffEoghan
Copy link
Author

keeffEoghan commented Nov 9, 2021

Right you are, I got overconfident seeing the start command work with engines, should've rechecked from scratch - all working now, thank you so much :)

Also, adding this to package.json lets you keep the engines field (I use it to indicate what versions of external/global tools I used with a project):

  "targets": {
    "default": {
      "engines": {}
    }
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants