Generated modules
We strive to make the generated module as simple as possible while maininting all the behavior from the original code.
Sometimes it is impossible to identify whether some edge cases will happen or not, so the generated code might be more complicated than the original code.
Simple values
Section titled “Simple values”Simple values that can fully inspected are serialized with their normal JS syntax. Those include:
- Strings
- Numbers
- Plain objects without nesting
- Arrays without nesting
- Booleans
BigInt
s- Symbols
For example the following module declaration:
inlineModule({ constExports: { aString: 'some text', normalNumber: 123, float: 123.456, NaN: Number.NaN, negativeZero: -0, infinity: Infinity, negativeInfinity: -Infinity, bool: true, uniqueSymbol: Symbol('foo'), globalSymbol: Symbol.for('foo'), wellKnownSymbol: Symbol.match, simpleObject: { string: 'some text', normalNumber: 123, float: 123.456, NaN: Number.NaN, negativeZero: -0, infinity: Infinity, negativeInfinity: -Infinity, bool: true, }, simpleArray: ['some text', 123, 123.456, Number.NaN, -0, Infinity, -Infinity, true], },});
Generates the following module:
const __uniqueSymbol = Symbol('foo');const __globalSymbol = Symbol.for('foo');
const __simpleObject = { string: 'some text', normalNumber: 123, float: 123.456, NaN: Number.NaN, negativeZero: -0, infinity: Number.POSITIVE_INFINITY, negativeInfinity: Number.NEGATIVE_INFINITY, bool: true,};
const __simpleArray = [ 'some text', 123, 123.456, Number.NaN, -0, Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY, true,];
export const aString = 'some text';export const normalNumber = 123;export const float = 123.456;export const NaN = Number.NaN;export const negativeZero = -0;export const infinity = Number.POSITIVE_INFINITY;export const negativeInfinity = Number.NEGATIVE_INFINITY;export const bool = true;export const uniqueSymbol = __uniqueSymbol;export const globalSymbol = __globalSymbol;export const wellKnownSymbol = Symbol.match;export const simpleObject = __simpleObject;export const simpleArray = __simpleArray;
Nested arrays and objects
Section titled “Nested arrays and objects”inlineModule({ constExports: { nestedArray: [123, [456], 789], nestedObject: { some: 'nested', value: { here: 123, }, }, },});
Generates:
const __nestedArray_1 = [456];
const __nestedArray = [];__nestedArray[0] = 123;__nestedArray[1] = __nestedArray_1;__nestedArray[2] = 789;
const __nestedObject = {};
const __nestedObject_value = { here: 123 };__nestedObject.some = 'nested';__nestedObject.value = __nestedObject_value;
export const nestedArray = __nestedArray;export const nestedObject = __nestedObject;
A bit more verbose than the original, but with the same result.
Circular values
Section titled “Circular values”const circularArray = [];circularArray.push(circularArray);const circularObject = {};circularObject.self = circularObject;
inlineModule({ constExports: { circularArray, circularObject, },});
Generates:
const __circularArray = [];__circularArray[0] = __circularArray;
const __circularObject = {};__circularObject.self = __circularObject;
export const circularArray = __circularArray;export const circularObject = __circularObject;
Sparse arrays
Section titled “Sparse arrays”const array = [];array[50] = 123;
inlineModule({ constExports: { array, },});
Generates:
const __array = [];__array[50] = 123;
export const array = __array;
Simple functions
Section titled “Simple functions”inlineModule({ constExports: { getValue: () => Math.random(), },});
Generates:
const __f0 = () => Math.random();
export const getValue = __f0;
Classes
Section titled “Classes”Classes in ECMAScript are syntactic sugar for defining values on the prototype chain. At runtime, it is impossible to find the original syntax that generated the values.
For maximum compatibility and to maintain all the minute bahaviors that an implementation might need this library serializes the verbose detailed definition of the class, even if some of those might not be needed.
class FancyClass { public constructor(public state: string) {}
public method() { console.log(this.state); }}
inlineModule({ constExports: { FancyClass, },});
Generates:
function __f0(__0) { return function () { return function constructor(state) { this.state = state; }; } .apply(undefined, undefined) .apply(this, arguments);}
const __f0_prototype = {};const __f1 = function method() { console.log(this.state);};
Object.defineProperty(__f0_prototype, 'constructor', { configurable: true, enumerable: false, writable: true, value: __f0,});Object.defineProperty(__f0_prototype, 'method', { configurable: true, enumerable: false, writable: true, value: __f1,});Object.defineProperty(__f0, 'prototype', { configurable: false, enumerable: false, writable: false, value: __f0_prototype,});
export const FancyClass = __f0;
Instances
Section titled “Instances”Serializing an instance implicitly serialize the class that originated them as well as the instance state.
class FancyClass { public constructor(public state: string) {}
public method() { console.log(this.state); }}
inlineModule({ constExports: { instance: new FancyClass('instance value'), },});
Generates:
const __instance_proto = {};const __f0 = function method() { console.log(this.state);};
function __f1(__0) { return function () { return function constructor(state) { this.state = state; }; } .apply(undefined, undefined) .apply(this, arguments);}
Object.defineProperty(__f1, 'prototype', { configurable: false, enumerable: false, writable: false, value: __instance_proto,});Object.defineProperty(__instance_proto, 'method', { configurable: true, enumerable: false, writable: true, value: __f0,});Object.defineProperty(__instance_proto, 'constructor', { configurable: true, enumerable: false, writable: true, value: __f1,});
const __instance = Object.create(__instance_proto);__instance.state = 'instance value';
export const instance = __instance;
Capturing functions
Section titled “Capturing functions”const capturedValue = { counter: 0 };
inlineModule({ constExports: { increment: () => capturedValue.counter++, read: () => capturedValue.counter, },});
Generates:
const __capturedValue = { counter: 0 };
function __f0() { return function () { const capturedValue = __capturedValue; return () => capturedValue.counter++; } .apply(undefined, undefined) .apply(this, arguments);}
function __f1() { return function () { const capturedValue = __capturedValue; return () => capturedValue.counter; } .apply(undefined, undefined) .apply(this, arguments);}
export const increment = __f0;
export const read = __f1;
Imports of built-in modules
Section titled “Imports of built-in modules”Values that were imported from a native Node module are detected and instead of serialized they are re-imported at runtime.
import * as path from 'node:path';import fs from 'node:fs';import { inspect } from 'node:util';
inlineModule({ constExports: { path, fs, inspect, },});
Generates:
import * as __path from 'path';import __fs from 'fs';import { inspect as __inspect } from 'util';
export const path = __path;export const fs = __fs;export const inspect = __inspect;
Import of third-party dependencies
Section titled “Import of third-party dependencies”Values imported from third-party libraries are also detected and not serialized. But this only works for values that are exported somewhere in the third-party library.
import * as one from 'lib-one';import two from 'lib-two';import { three } from 'lib-three';
inlineModule({ constExports: { one, two, three, },});
Generates:
import * as __one from 'lib-one';import __two from 'lib-two';import { three as __three } from 'lib-three';
export const one = __one;export const two = __two;export const three = __three;
Non-standard properties
Section titled “Non-standard properties”const value = {};
Object.defineProperty(value, 'property', { value: 'value', writable: false, enumerable: false, configurable: false,});
inlineModule({ constExports: { obj: value, },});
Generates:
const __obj = {};
Object.defineProperty(__obj, 'property', { configurable: false, enumerable: false, writable: false, value: 'value',});
export const obj = __obj;