Skip to content

Statics & Constants

Tests in this category ensure static methods, static properties and constants are accessible from the host.

Constants can be read

Test: constantsCanBeRead

static readonly properties of a jsii class are constants. The host MUST be able to read constants of any type, including object references, without creating an instance of the class. Reading a constant MUST return the value initialized in JavaScript.

Reference Implementation

// GIVEN
export class DoubleTrouble {
  public hello() {
    return 'world';
  }
}

export class Statics {
  public static readonly Foo = 'hello';
  public static readonly BAR = 1234;
  public static readonly zooBar: { [name: string]: string } = { hello: 'world' };
  public static readonly ConstObj = new DoubleTrouble();
}

// WHEN
const obj = Statics.ConstObj;

// THEN
expect(Statics.Foo).toBe('hello');
expect(Statics.BAR).toBe(1234);
expect(Statics.zooBar['hello']).toBe('world');
expect(obj.hello()).toBe('world');

Static methods and properties can be used

Test: staticMembersCanBeUsed

Static methods of a jsii class MUST be invocable from the host without an instance, and MUST accept and return values of their declared types. Static properties MUST be readable from the host, and static properties that are not readonly MUST also be writable. A value assigned from the host MUST be returned by subsequent reads, and MAY be an object reference created by the host.

Reference Implementation

// GIVEN
export class Statics {
  public constructor(public readonly value: string) {}

  public static staticMethod(name: string) {
    return `hello ,${name}!`;
  }

  private static _instance?: Statics;
  public static get instance(): Statics {
    this._instance ??= new Statics('default');
    return this._instance;
  }
  public static set instance(val: Statics) {
    this._instance = val;
  }

  public static nonConstStatic = 100;
}

// WHEN
const greeting = Statics.staticMethod('Yoyo');
const defaultInstance = Statics.instance;

const newStatics = new Statics('new value');
Statics.instance = newStatics;

// THEN
expect(greeting).toBe('hello ,Yoyo!');
expect(defaultInstance.value).toBe('default');
expect(Statics.instance).toBe(newStatics);
expect(Statics.instance.value).toBe('new value');
expect(Statics.nonConstStatic).toBe(100);

Assigning a static property updates the value in JavaScript

Test: staticPropertyAssignmentUpdatesJavaScript

Assigning a value to a static property from the host MUST call the property's setter in the kernel, so that the new value is observable from JavaScript. The host MUST NOT store the assigned value only on the host side, for example by replacing the host representation of the property.

Reference Implementation

// GIVEN
export class StaticPropertyAssignment {
  public static value = 'default';

  /** Reads `value` from within JavaScript, so that host language assignments are observable. */
  public static readValue(): string {
    return StaticPropertyAssignment.value;
  }

  private constructor() {}
}

// WHEN
const before = StaticPropertyAssignment.readValue();
StaticPropertyAssignment.value = 'assigned';

// THEN
expect(before).toBe('default');
expect(StaticPropertyAssignment.readValue()).toBe('assigned');
expect(StaticPropertyAssignment.value).toBe('assigned');

Kernel Trace

> {"api":"sinvoke","fqn":"jsii-calc.StaticPropertyAssignment","method":"readValue","args":[]}
< {"ok":{"result":"default"}}
> {"api":"sset","fqn":"jsii-calc.StaticPropertyAssignment","property":"value","value":"assigned"}
< {"ok":{}}
> {"api":"sinvoke","fqn":"jsii-calc.StaticPropertyAssignment","method":"readValue","args":[]}
< {"ok":{"result":"assigned"}}
> {"api":"sget","fqn":"jsii-calc.StaticPropertyAssignment","property":"value"}
< {"ok":{"value":"assigned"}}