Babylon.js: Cannot assign to read only property 'RGBA16F' of object in strict mode

Edit: This is caused by strict mode, see https://github.com/BabylonJS/Babylon.js/issues/2988#issuecomment-340539936

I have the exact same error as https://github.com/BabylonJS/Babylon.js/issues/2642 but the issue is closed and I don’t know why and how it has been resolved by OP

Context:

  • Developing on localhost
  • With MacOSX and ArchLinux
  • With Chrome and Firefox
  • Using babylonjs as a CommonJS module with rollup (and babel)
  • With babylon.3.0-beta12.max.js and babylon.3.0-beta12.js (with and without npm)

Error:

babylon.3.0-beta12.max.js:7623 Uncaught TypeError:
Cannot assign to read only property 'RGBA16F' of object '#<WebGL2RenderingContext>'
   at new Engine (babylon.3.0-beta12.max.js:7623)

It looks like the following WebGL constants RGBA16F, RGBA32F and DEPTH24_STENCIL8 are read only and cannot be set during engine creation.

See: https://github.com/BabylonJS/Babylon.js/blob/7482c84713f0b97d32e3e1a1ac42b70893b77468/src/Engine/babylon.engine.ts#L1080-L1083

Strangely HALF_FLOAT_OES can be set without any problem…

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 2
  • Comments: 16 (16 by maintainers)

Commits related to this issue

Most upvoted comments

@deltakosh I still have the issue with the latest release

I’ve seen that you’ve reverted the if (...) thing here in this commit 🤔 Why did you revert this? Is it related to strict check null #2982?

I figured out exactly why this is happening using a bundler like rollup or webpack, the thing is that the bundler is enabling strict mode by default by adding 'use strict'; which is good for ES6

In rollup documentation https://rollupjs.org/#strict

Strictly-speaking, ES6 modules are always in strict mode, so you shouldn’t disable this without good reason.

So I still have the problem with those 3 lines:

this._gl.RGBA16F = 0x881A; // RGBA 16-bit floating-point color-renderable internal sized forma
this._gl.RGBA32F = 0x8814; // RGBA 32-bit floating-point color-renderable internal sized forma
this._gl.DEPTH24_STENCIL8 = 35056;

But also in new Mesh(...) at this line, the Tools.DeepCopyfunction is throwing at this line:

Uncaught TypeError: Cannot set property source of [object Object] which has only a getter
    at Function.Tools.DeepCopy (babylon.3.0.7.max.js:5704)
    at new Mesh (babylon.3.0.7.max.js:19816)
    at Mesh.clone (babylon.3.0.7.max.js:21060)

The error details: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Getter_only

There is an attempt to set a new value to a property for which only a getter is specified. While this will be silently ignored in non-strict mode, it will throw a TypeError in strict mode.

Seems like Mesh.source is a getter (from this._source) and then cannot be set ⚠️

My workaround is to disable strict mode in my bundler, but I think there is several benefits to use strict mode directly in BabylonJS in development mode. In production mode we should be able to use it or not because there are many resources about performance improvements, see this and this and this.

@deltakosh do you want me to create 2 separate issues? Or to create another issue called Enable strict mode? Do you also think enabling strict mode is a good thing?

@vousk CC

I’m in a middle of an update so I’ll add it no worry 😃 (directly though)

@deltakosh I think you forgot DEPTH24_STENCIL8 (I made a copy/paste mistake in my issue)

There is another problem, in the case where the constants doesn’t equal what we are expecting (e.g. the browser only supports WEBGL 1) then we will still get the error in strict mode.

May I suggest something more explicit like:


// Inspired by https://stackoverflow.com/a/10480227/1480391
const isStrict = (function() { return !this; })();

// See https://github.com/BabylonJS/Babylon.js/issues/2988
const trySetReadOnlyProperty = (prop, value) => {
  if (this._gl[prop] === value) {
    return;
  }
  if (isStrict) {
    // I don't know how you actually log warnings
    console.warning(`Cannot force property "${prop}" of WebGL context with strict mode enabled`);
    return;
  }
  this._gl[prop] = value;
}


// RGBA 16-bit floating-point color-renderable internal sized format.
trySetReadOnlyProperty("RGBA16F", 0x881A);

// RGBA 32-bit floating-point color-renderable internal sized format.
trySetReadOnlyProperty("RGBA32F", 0x8814);

trySetReadOnlyProperty("DEPTH24_STENCIL8", 35056);

It’s verbose but it’s explicit 😉 You can refactor the trySetReadOnlyProperty function to make it generic to any target object if needed.

If you want me to fill a PR, I’ll do it.