DOCUMENTATION XS XS linker warnings
Overview
Getting Started
BASE
Reference
Worker
Setup modules
COMMODETTO
Reference
Poco Renderer
Outlines
Creating Fonts
Crypt
Data
DEVICES
Moddable One
Moddable Two
Moddable Three
Moddable Four
ESP32
ESP8266
nRF52
nRF52 Low Power Notes
Raspberry Pi Pico
M5Core Ink
M5Paper
Wasm
SiLabs Gecko
QCA4020
Moddable Zero
DISPLAYS
Overview
Adafruit 1.8" ST7735
Adafruit OLED Display
BuyDisplay 2.8" CTP - ESP8266
Crystalfontz ePaper
DotStar
Generic 1.44"
Generic 2.4" & 2.8" (Resistive Touch) - ESP32
Generic 2.4" & 2.8" (Resistive Touch) - ESP8266
Generic 2.4" & 2.8" (Resistive Touch) - Pico
Sharp Memory
Sharp Memory Screen 1.3"
SparkFun TeensyView
Switch Science Reflective LCD
DRIVERS
DESTM32S display
DotStar display
ILI9341 display
LPM013M126A display
LS013B4DN04 display
MCP230XX GPIO expander
NeoStrand
SSD1306 display
SSD1351 display
ST7735 display
Files
IO
TC53 IO
Firmata
NETWORK
Reference
TLS (SecureSocket)
BLE
Ethernet
Web Things
PINS
Reference
Audio Output
PIU
Reference
Localization
Keyboard
Expanding Keyboard
Die Cut
Using After Effects Motion Data
TOOLS
Reference
Manifest
Defines in Manifests
Testing
XS
Handle
JavaScript language considerations on embedded devices using the XS engine
Mods – User Installed Extensions
ROM Colors
Using XS Preload to Optimize Applications
XS Conformance
XS Marshalling
XS Platforms
XS in C
XS linker warnings
xsbug
xst
XS Compartment
XS Profiler

XS Linker Warnings

Copyright 2019 Moddable Tech, Inc.
Revised: November 9, 2019

Preload

The XS linker can preload modules by executing their body at link time. The resulting closures and objects will be in ROM at run time.

XS supports an aliasing mechanism to allow such closures and objects to be modified at run time. Modified closures and objects are aliased in RAM.

But the aliasing mechanism has a cost, even if closures and objects are never modified: XS uses one pointer for each aliasable closure and object.

So it is recommended to freeze objects and to use const instead of let in the body of modules. For details see Using XS Preload to Optimize Applications

But it is common to forget a few closures and objects so the XS linker now warns you about closures and objects that are aliasable.

The XS linker forces a garbage collection after preloading modules. So closures and objects that are not referenced by modules namespaces are discarded.

Compartments

XS supports compartments, as defined by Secure ECMAScript. See the Draft Spec for Standalone SES for details.

Preloaded modules are shared by all compartments, their bodies are considered as vetted customization code. So the XS linker warnings are especially significant when security matters.

When the XS linker reports warnings about a module, it means that the module exports mutable closures or objects.

Objects

Here is a simple "test" module which exports one object:

export const o = { p: 0 };

If the "test" module is preloaded, the XS linker reports:

### warning: "test": o: not frozen

The fix is:

export const o = Object.freeze({ p: 0 });

Objects are checked recursively.

export const o = Object.freeze({ p: { q: 0 } });

The XS linker reports:

### warning: "test": o.p: not frozen

Using the non standard deep freeze feature of XS, the fix is:

export const o = Object.freeze({ p: { q: 0 } }, true);

Closures

Here is a simple "test" module which exports one function that returns a variable in the module scope:

let v = 1;
export function f(a) {
	return v;
}

If the "test" module is preloaded, the XS linker reports:

### warning: "test": f() v: no const

The fix is:

const v = 1;
export function f() {
	return v;
}

Closures and objects are checked together. For instance:

const o = { p: 0 };
export function f() {
	return o;
}

The XS linker reports:

### warning: "test": f() o: not frozen

The fix is:

const o = Object.freeze({ p: 0 });
export function f() {
	return o;
}

Globals

Preloaded modules can modify the global scope. The resulting object will be in ROM at runtime and will be used to initialize the global scope of the Moddable app (a.k.a. the SES start-compartment). The XS linker also reports warnings about globals.

Here is a simple "test" module which adds one object to the global scope:

globalThis.g = { p: 0 };

If the "test" module is preloaded, the XS linker reports:

### warning: globalThis.g: not frozen

The fix is:

globalThis.g = Object.freeze({ p: 0 });

Exceptions

Preloaded objects are either aliasable or frozen. Preloaded aliasable objects are mutable. Preloaded frozen objects are immutable, their properties and their private properties are read-only.

Most instances of built-ins classes can be preloaded but cannot be aliased. Once preloaded, such instances are immutable and several built-ins methods throw type errors.

Instances of Preload Alias Throw Type Error
Array Yes Yes -
ArrayBuffer* Yes No -
AsyncGenerator* No No
Boolean Yes No -
DataView Yes No set
Date Yes No setDate, setFullYear, setHours, setMilliseconds, setMinutes, setMonth, setSeconds, setTime, setYear, setUTCDate, setUTCFullYear, setUTCHours, setUTCMilliseconds, setUTCMinutes, setUTCMonth, setUTCSeconds
Error Yes No -
FinalizationGroup Yes No cleanupSome, register, unregister
Function* Yes No -
Generator* No No
Map Yes No clear, delete, set
Number Yes No -
Promise Yes No -
Proxy Yes No revoke
RegExp Yes No
Set Yes No add, clear, delete
String Yes No -
Symbol Yes No -
TypedArray* Yes No copyWithin, fill, reverse, set, sort
WeakMap Yes No delete, set
WeakRef Yes No -
WeakSet Yes No add, delete
  • Instances of ArrayBuffer are mostly accessed thru instances of DataView and TypedArray. Currently the endianness at build time has to be the same as the endianness at run time.
  • Since classes are instances of Function, static properties and static private properties of preloaded classes are read-only.
  • The XS linker reports errors when instances of AsyncGenerator or Generator are preloaded.
  • For preloaded instances of TypedArray, integer-indexed assignment also throws a type error.