Get and set not working in JavaScript any more?


#1

I’ve just been trying to run some previously working code from inside the THREE.js library. I am getting syntax errors.

I’ve tracked it down to the get and set functions. These were working fine a few weeks ago, but not any more. So, I’ve further nailed it down to running this script in the console. It shouldn’t produce any syntax errors:

o = { 
  a:7, 
  get b() { return this.a+1; }, 
  set c(x) { this.a = x/2 } 
};

but it gives the following error:

[WARNING] [SyntaxError] Expected `:' in JSConcole:3(7)

The code works fine in a regular browser JS console. Can anyone shed any light on the subject?


#2

Did you try this?

var o = { a:7 }

Object.defineProperty(o, “b”, { get: function () { return this.a + 1; } });


#3

I am not sure if QTBrowser or the HiFi js defaupt engine actually supports getters and setters within a object definition. But if it did work, that is odd that it stopped. Have you tried identifying when it begun to fail? Thoys did some changes nearly a month ago to it though.

Most likely, @Cracker_Hax s solution will work. But you will also have to set c.
Cc: @Thoys


#4

@Cracker_Hax, @Menithal Thanks for the replies. Have we had an update to the QTBrowser / JS engine recently? I’m hoping it’s not a limitation of QTBrowser, as I’m not too keen on the idea of modifying a 3rd party library (THREE.js) just to make it play nicely with HiFi, especially when it used to work before :frowning:

I’ve put it up as a bug on worklist. If it doesn’t get picked up I’ll go ahead and modify the necessary classes - luckily I’m only using a very small sub-section of THREE.js. However, I do feel this is quite a limitation in terms of preventing / complicating the use of all 3rd party JS libraries that use get and set - not ideal!


#5

You’re right… your code should be working.


#6

… just tested on an old version of ./interface (~Jul 31st 2015) and the get syntax worked fine in both the Script Editor and a WebWindow:

> JSON.stringify(o = { a:7, get b() { return this.a+1; }, set c(x) { this.a = x/2 } })
< {"a":7,"b":8}
[DEBUG] [11/06 11:58:07] JS console message at line 1 from "" - "{"a":7,"b":8}"

EDIT: with a fresh pull/build and am seeing the described symptoms:

> JSON.stringify(o = { a:7, get b() { return this.a+1; }, set c(x) { this.a = x/2 } })
<
// [11/06 14:06:27] [WARNING] [SyntaxError] Expected `:' in JSConcole:1(31) 

Script.include'ing a test file also fails with a similar message.

Oddly enough, this works(!?):

> eval('JSON.stringify(o = { a:7, get b() { return this.a+1; }, set c(x) { this.a = x/2 } })')
< {"a":7,"b":8}

Any idea what Qt version you are using? (the version for all above is Qt5.4.2)

FWIW I faced similar compatibility issues with other 3rd party JS libraries and decided to monkey-patch their source live rather than adopting the hassle of maintaining/publishing ported copies (or rallying to fix antiques like Qt Script).

If going that route then http://cdnjs.com is CORS-friendly and you can XHR fetch three.js or three.min.js from there, adapt the source using RegExp (or JS diff/patch) and eval().

For most 3rd party libraries it wasn’t so much syntax errors but the polyfills that were a challenge – like jQuery or d3 depending on window, document, console, etc. I’m currently targeting seven+ JavaScript “environments” so currently use a universal bootstrapping layer to manage all the ugly sniffing and jury-rigging stuff.

Anyway, some day I’m going to gut Qt Script and try switching the HiFi code base over to V8 or SpiderMonkey. :wink: (which seems more straightforward than it sounds because in most cases memory pointers aren’t being exchanged across the C++/JS membrane – just flattened Object copies and opaque identifiers, which are essentially engine agnostic and context free already).


#7

Ok, have decided to do ‘monky patches’ on THREE.js, as I want to get on. I see from some reading around the subject that there are three getter / setter techniques:

Non-standard and deprecated way: /defineGetter and /defineSetter
Standard-compliant, using the set and get operators: currently non-functional in HiFi
Standard-compliant, using Object.defineProperty: looks like the best alternative

However, I’m having trouble coming up with an Object.defineProperty alternative for the ‘set’ function here, as it takes 3 parameters:

THREE.Vector3 = function ( x, y, z ) {

	this.x = x || 0;
	this.y = y || 0;
	this.z = z || 0;

};

THREE.Vector3.prototype = {

	constructor: THREE.Vector3,

	set: function ( x, y, z ) {

		this.x = x;
		this.y = y;
		this.z = z;

		return this;

	},

        ...

Does anyone have an idea how to implement the Object.defineProperty alternative to this?



@humbletim Thank you for the info and for confirming get and set used to work.

I’m unsure of which version of Qt I’m using, but I guess it’s whichever is used in the current version of Interface (I just use the public distribution version of Interface, always updated to the latest)

You’re way ahead of me on the technical side! Are you saying there’s a way to automate altering the code to use a different get / set techniques?


#8

… took a look on the C++ side and there seems to be something wonky going on between threading and scripting engine instances (almost feels like a race condition, or a memory corruption). anyway, doesn’t seem to me like a simple JavaScript version issue after all.

THREE.Vector3.prototype.set is just a regular-old boring function called “set” (not a special JS setter ;)).

… if by chance looking for other math functions you might try my glm-js wrappers (here’s a gist for using with HiFi). essentially it’s the GLSL math API overlaid onto one of several JS “backends” like THREE.js, gl-matrix or tdl-fast.

EDIT: had jsondiffpatch idea here, but THREE.js turned out to be too bulky for that to work; so here’s a ~64 line hybrid solution instead:

  1. load three.js source code (as a string) from cdnjs.com
  2. patch it just-enough to allow it to compile:
    { get x() { ... } } ->
    { get$x: function() { ... } }
    (plus replacing reserved keywords like delete and boolean)
  3. evaluate to produce the THREE object
  4. finish patching the getters/setters by adapting:
    THREE.oOo.prototype.get$x ->
    Object.defineProperty(THREE.oOo.prototype, 'x', THREE.oOo.prototype.get$x)

GIST: https://gist.github.com/humbletim/7069a894697370d02c00#file-three-cdnjs-hifi-js

Script.include('https://cdn.rawgit.com/humbletim/7069a894697370d02c00/raw/f1c8a897ecb394e6c83574822ccdcf1fc98e2f28/three-cdnjs-hifi.js');