Bug with JS Classes that have private fields

In k6 release 0.40 it was announced that k6 got native support for JS classes and specifically that private fields are now supported. I decided to give those features a try since they make the code a lot cleaner.

When putting all the code in 1 file and running it directly everything seems to work correctly:

class Value {
	#internal_private_value;

	constructor(value) {
		this.#internal_private_value = value;
	}

	get value() { return this.#internal_private_value; }
}

const test_object = new Value(5);
console.log(test_object.value);
console.log(test_object.#internal_private_value); // this throws a SyntaxError as it should

However when I separate the code into a k6 test script and a library module as it would be in real code, like so:
test_lib.js

class Value {
	#internal_private_value;

	constructor(value) {
		this.#internal_private_value = value;
	}

	get value() { return this.#internal_private_value; }
}

export function test_function(value){
	const test_object = new Value(value);
	console.log(test_object.value);
}

k6_script.js

import { test_function } from "./test_lib.js";
test_function(5);

Gives the following error when trying to run k6_script.js with k6:

ERRO[0000] SyntaxError: file:///Users/ ... /test_lib.js: Unexpected character '#' (2:1)
  1 | class Value {
> 2 | 	#internal_private_value;
    | 	^
  3 | 
  4 | 	constructor(value) {
  5 | 		this.#internal_private_value = value;
	at <internal/k6/compiler/lib/babel.min.js>:2:28536(100)
	at <internal/k6/compiler/lib/babel.min.js>:14:24413(11)
	at bound  (native)
	at s (<internal/k6/compiler/lib/babel.min.js>:1:1331(7))
	at native  hint="script exception"

Also simply trying to mark the class as exported yields the same result.
I’m running on the latest “k6 v0.42.0 ((devel), go1.19.4, darwin/amd64)”
Am I doing something wrong here or is this a bug in k6 or goja?

Hi @ramz, welcome to the community forum.

I have opened an issue for this.

It is kind of known problem with a bunch of syntaxes that the internal k6 babel version does not support but goja does.

As mentioned in the issue it is likely that we will be working on this in the following months and hopefully that will finally fix it.

You can read more information that likely is way too detailed here.

If you desire to use private fields - I would recommend that you just don’t do it until we fix them entirely.

If you need to I would recommend transpiling down to es5 with GitHub - grafana/k6-template-es6: Template repository for bundling test projects into single test scripts runnable by k6. This will hopefully soon not be needed as we will fix it, and arguably makes debugging and development harder, so I would still recommend to not use them.

If you need private classes in specific files you can be very careful to not use ecmascript modules in those files, but IMO that is way too complicated and fragile.

Hope this helps you!

1 Like

Hi @mstoykov,

Thanks for the very prompt and detailed reply, it’s much appreciated and exactly what I was looking for!
I’m already looking forward to the next k6 releases with this and other fixes and improvements.

Thanks again!

1 Like