Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
470 changes: 235 additions & 235 deletions package-lock.json

Large diffs are not rendered by default.

18 changes: 9 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,20 @@
},
"engineStrict": true,
"dependencies": {
"binaryen": "123.0.0-nightly.20250530",
"binaryen": "129.0.0-nightly.20260424",
"long": "^5.2.4"
},
"devDependencies": {
"@eslint/js": "^10.0.1",
"@types/node": "^25.5.0",
"@types/node": "^25.6.0",
"as-float": "^1.0.1",
"diff": "^8.0.4",
"esbuild": "^0.27.0",
"eslint": "^10.1.0",
"diff": "^9.0.0",
"esbuild": "^0.28.0",
"eslint": "^10.2.1",
"glob": "^13.0.6",
"globals": "^17.4.0",
"typescript": "^5.9.3",
"typescript-eslint": "^8.57.2"
"globals": "^17.5.0",
"typescript": "^6.0.3",
"typescript-eslint": "^8.59.0"
},
"type": "module",
"exports": {
Expand Down Expand Up @@ -74,7 +74,7 @@
"scripts": {
"check": "npm run check:config && npm run check:import && npm run lint",
"check:config": "tsc --noEmit -p src --diagnostics --listFiles",
"check:import": "tsc --noEmit --target ESNEXT --module nodenext --moduleResolution nodenext --experimentalDecorators tests/import/index",
"check:import": "tsc --noEmit --skipLibCheck --target ESNEXT --module nodenext --moduleResolution nodenext --experimentalDecorators tests/import/index",
"lint": "eslint --max-warnings 0 --ext js . && eslint --max-warnings 0 --ext ts .",
"build": "node scripts/build",
"watch": "node scripts/build --watch",
Expand Down
4 changes: 3 additions & 1 deletion scripts/build-dts.js
Original file line number Diff line number Diff line change
Expand Up @@ -319,9 +319,11 @@ const prefix = "types:assemblyscript";

export function generateSrc() {
const stdout = [];
const pathToSources = pathUtil.resolve(__dirname, "..", "src");

generate({
project: pathUtil.resolve(__dirname, "..", "src"),
project: pathToSources,
baseDir: pathToSources,
prefix,
exclude: [
"glue/**",
Expand Down
1 change: 1 addition & 0 deletions src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ export namespace CommonNames {
export const ASC_FEATURE_RELAXED_SIMD = "ASC_FEATURE_RELAXED_SIMD";
export const ASC_FEATURE_EXTENDED_CONST = "ASC_FEATURE_EXTENDED_CONST";
export const ASC_FEATURE_STRINGREF = "ASC_FEATURE_STRINGREF";
export const ASC_FEATURE_SHARED_EVERYTHING = "ASC_FEATURE_SHARED_EVERYTHING";
export const ASC_VERSION_MAJOR = "ASC_VERSION_MAJOR";
export const ASC_VERSION_MINOR = "ASC_VERSION_MINOR";
export const ASC_VERSION_PATCH = "ASC_VERSION_PATCH";
Expand Down
70 changes: 47 additions & 23 deletions src/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -325,8 +325,10 @@ export class Options {
/** Sets whether a feature is enabled. */
setFeature(feature: Feature, on: bool = true): void {
if (on) {
// Enabling Shared Everything also enables Threads and GC
if (feature & Feature.SharedEverything) feature |= Feature.Threads | Feature.GC;
// Enabling Stringref also enables GC
if (feature & Feature.Stringref) feature |= Feature.GC;
if (feature & Feature.Strings) feature |= Feature.GC;
// Enabling GC also enables Reference Types
if (feature & Feature.GC) feature |= Feature.ReferenceTypes;
// Enabling Relaxed SIMD also enables SIMD
Expand All @@ -336,9 +338,11 @@ export class Options {
// Disabling Reference Types also disables GC
if (feature & Feature.ReferenceTypes) feature |= Feature.GC;
// Disabling GC also disables Stringref
if (feature & Feature.GC) feature |= Feature.Stringref;
if (feature & Feature.GC) feature |= Feature.Strings;
// Disabling SIMD also disables Relaxed SIMD
if (feature & Feature.Simd) feature |= Feature.RelaxedSimd;
// Disabling Threads or GC also disables Shared Everything
if (feature & (Feature.Threads | Feature.GC)) feature |= Feature.SharedEverything;
this.features &= ~feature;
}
}
Expand Down Expand Up @@ -515,7 +519,8 @@ export class Compiler extends DiagnosticEmitter {
if (options.hasFeature(Feature.Memory64)) featureFlags |= FeatureFlags.Memory64;
if (options.hasFeature(Feature.RelaxedSimd)) featureFlags |= FeatureFlags.RelaxedSIMD;
if (options.hasFeature(Feature.ExtendedConst)) featureFlags |= FeatureFlags.ExtendedConst;
if (options.hasFeature(Feature.Stringref)) featureFlags |= FeatureFlags.Stringref;
if (options.hasFeature(Feature.Strings)) featureFlags |= FeatureFlags.Strings;
if (options.hasFeature(Feature.SharedEverything)) featureFlags |= FeatureFlags.SharedEverything;
module.setFeatures(featureFlags);

// set up the main start function
Expand All @@ -534,10 +539,16 @@ export class Compiler extends DiagnosticEmitter {
let resolver = this.resolver;
let hasShadowStack = options.stackSize > 0; // implies runtime=incremental

// Register a dummy memory so Binaryen's EffectAnalyzer can read
// memory.shared on loads/stores emitted during compilation. The real
// memory is installed by `initDefaultMemory` below, which can't run
// here: it needs `memoryOffset` (known only after data layout) and
// emits diagnostics / exports that must happen exactly once.
this.initDummyMemory();

// initialize lookup maps, built-ins, imports, exports, etc.
this.program.initialize();


// Binaryen treats all function references as being leaked to the outside world when
// the module isn't marked as closed-world (see WebAssembly/binaryen#7135). Therefore,
// we should mark the module as closed-world when we're definitely sure it is.
Expand Down Expand Up @@ -762,6 +773,19 @@ export class Compiler extends DiagnosticEmitter {
return module;
}

private initDummyMemory(): void {
let options = this.options;
this.module.setMemory(
0,
Module.UNLIMITED_MEMORY,
[],
options.target,
null,
CommonNames.DefaultMemory,
options.sharedMemory
);
}

private initDefaultMemory(memoryOffset: i64): void {
this.memoryOffset = memoryOffset;

Expand Down Expand Up @@ -1524,7 +1548,7 @@ export class Compiler extends DiagnosticEmitter {

private ensureEnumToString(enumElement: Enum, reportNode: Node): string | null {
if (enumElement.toStringFunctionName) return enumElement.toStringFunctionName;

if (!this.compileEnum(enumElement)) return null;
if (enumElement.is(CommonFlags.Const)) {
this.errorRelated(
Expand Down Expand Up @@ -2583,7 +2607,7 @@ export class Compiler extends DiagnosticEmitter {
// (then │ │ (body) │
// (?block $continue │ │ if loops: (incrementor) ─────┘
// (body) │ │ recompile body?
// ) ├◄┘
// ) ├◄┘
// (incrementor) ┌◄┘
// (br $loop)
// )
Expand Down Expand Up @@ -2872,17 +2896,17 @@ export class Compiler extends DiagnosticEmitter {
// Compile the condition (always executes)
let condExpr = this.compileExpression(statement.condition, Type.auto);
let condType = this.currentType;

// Shortcut if there are no cases
if (!numCases) return module.drop(condExpr);

// Assign the condition to a temporary local as we compare it multiple times
let outerFlow = this.currentFlow;
let tempLocal = outerFlow.getTempLocal(condType);
let tempLocalIndex = tempLocal.index;
let breaks = new Array<ExpressionRef>(1 + numCases);
breaks[0] = module.local_set(tempLocalIndex, condExpr, condType.isManaged);

// Make one br_if per labeled case and leave it to Binaryen to optimize the
// sequence of br_ifs to a br_table according to optimization levels
let breakIndex = 1;
Expand All @@ -2894,7 +2918,7 @@ export class Compiler extends DiagnosticEmitter {
defaultIndex = i;
continue;
}

// Compile the equality expression for this case
const left = statement.condition;
const leftExpr = module.local_get(tempLocalIndex, condType.toRef());
Expand All @@ -2909,7 +2933,7 @@ export class Compiler extends DiagnosticEmitter {
condType,
statement
);

// Add it to the list of breaks
breaks[breakIndex++] = module.br(`case${i}|${label}`, equalityExpr);
}
Expand Down Expand Up @@ -3863,7 +3887,7 @@ export class Compiler extends DiagnosticEmitter {
expression: BinaryExpression,
contextualType: Type,
): ExpressionRef {

const left = expression.left;
const leftExpr = this.compileExpression(left, contextualType);
const leftType = this.currentType;
Expand All @@ -3881,9 +3905,9 @@ export class Compiler extends DiagnosticEmitter {
);
}

/**
/**
* compile `==` `===` `!=` `!==` BinaryExpression, from previously compiled left and right expressions.
*
*
* This is split from `compileCommutativeCompareBinaryExpression` so that the logic can be reused
* for switch cases in `compileSwitchStatement`, where the left expression only should be compiled once.
*/
Expand All @@ -3901,15 +3925,15 @@ export class Compiler extends DiagnosticEmitter {

let module = this.module;
let operatorString = operatorTokenToString(operator);

// check operator overload
const operatorKind = OperatorKind.fromBinaryToken(operator);
const leftOverload = leftType.lookupOverload(operatorKind, this.program);
const rightOverload = rightType.lookupOverload(operatorKind, this.program);
if (leftOverload && rightOverload && leftOverload != rightOverload) {
this.error(
DiagnosticCode.Ambiguous_operator_overload_0_conflicting_overloads_1_and_2,
reportNode.range,
reportNode.range,
operatorString,
leftOverload.internalName,
rightOverload.internalName
Expand Down Expand Up @@ -3999,7 +4023,7 @@ export class Compiler extends DiagnosticEmitter {

leftExpr = this.compileExpression(left, contextualType);
leftType = this.currentType;

// check operator overload
const operatorKind = OperatorKind.fromBinaryToken(operator);
const leftOverload = leftType.lookupOverload(operatorKind, this.program);
Expand Down Expand Up @@ -4070,7 +4094,7 @@ export class Compiler extends DiagnosticEmitter {
return this.compileNonCommutativeCompareBinaryExpression(expression, contextualType);
}
case Token.Equals_Equals_Equals:
case Token.Equals_Equals:
case Token.Equals_Equals:
case Token.Exclamation_Equals_Equals:
case Token.Exclamation_Equals: {
return this.compileCommutativeCompareBinaryExpression(expression, contextualType);
Expand Down Expand Up @@ -6352,13 +6376,13 @@ export class Compiler extends DiagnosticEmitter {
if (numArguments < numParams) {
return argumentExpressions;
}

// make an array literal expression from the rest args
let elements = argumentExpressions.slice(numParams - 1);
let range = new Range(elements[0].range.start, elements[elements.length - 1].range.end);
range.source = reportNode.range.source;
let arrExpr = new ArrayLiteralExpression(elements, range);

// return the original args, but replace the rest args with the array
const exprs = argumentExpressions.slice(0, numParams - 1);
exprs.push(arrExpr);
Expand Down Expand Up @@ -6622,9 +6646,9 @@ export class Compiler extends DiagnosticEmitter {
let initializer = declaration.initializer;
let initExpr: ExpressionRef;
if (declaration.parameterKind === ParameterKind.Rest) {
const arrExpr = new ArrayLiteralExpression([], declaration.range.atEnd);
const arrExpr = new ArrayLiteralExpression([], declaration.range.atEnd);
initExpr = this.compileArrayLiteral(arrExpr, type, Constraints.ConvExplicit);
initExpr = module.local_set(operandIndex, initExpr, type.isManaged);
initExpr = module.local_set(operandIndex, initExpr, type.isManaged);
} else if (initializer) {
initExpr = this.compileExpression(
initializer,
Expand Down Expand Up @@ -7869,7 +7893,7 @@ export class Compiler extends DiagnosticEmitter {
stmts.length = 1;
stmts.push(
module.i32(1)
);
);
module.removeFunction(name);
module.addFunction(name, sizeType, TypeRef.I32, [ TypeRef.I32 ], module.block(null, stmts, TypeRef.I32));
}
Expand Down
19 changes: 9 additions & 10 deletions src/glue/binaryen.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export type Op = i32;
export type ExternalKind = u32;
export type SideEffects = u32;
export type ExpressionRunnerFlags = u32;
export type MemoryOrder = u32;

export type StringRef = Ref;
export type Pointer<T> = Ref;
Expand Down Expand Up @@ -95,12 +96,12 @@ export declare function _BinaryenModuleDispose(module: ModuleRef): void;

export declare function _BinaryenSizeofLiteral(): usize;
export declare function _BinaryenLiteralInt32(literalOut: LiteralRef, x: i32): void;
export declare function _BinaryenLiteralInt64(literalOut: LiteralRef, x: i32, y: i32): void;
export declare function _BinaryenLiteralInt64(literalOut: LiteralRef, value: i64): void;
export declare function _BinaryenLiteralFloat32(literalOut: LiteralRef, x: f32): void;
export declare function _BinaryenLiteralFloat64(literalOut: LiteralRef, x: f64): void;
export declare function _BinaryenLiteralVec128(literalOut: LiteralRef, x: ArrayRef<u8>): void;
export declare function _BinaryenLiteralFloat32Bits(literalOut: LiteralRef, x: i32): void;
export declare function _BinaryenLiteralFloat64Bits(literalOut: LiteralRef, x: i32, y: i32): void;
export declare function _BinaryenLiteralFloat64Bits(literalOut: LiteralRef, value: i64): void;

export declare function _BinaryenExpressionGetId(expr: ExpressionRef): ExpressionId;
export declare function _BinaryenExpressionGetType(expr: ExpressionRef): TypeRef;
Expand Down Expand Up @@ -228,7 +229,7 @@ export declare function _BinaryenLoadSetAlign(expr: ExpressionRef, align: u32):
export declare function _BinaryenLoadGetPtr(expr: ExpressionRef): ExpressionRef;
export declare function _BinaryenLoadSetPtr(expr: ExpressionRef, ptrExpr: ExpressionRef): void;
// ^ with atomic = true
export declare function _BinaryenAtomicLoad(module: ModuleRef, bytes: Index, offset: Index, type: TypeRef, ptrExpr: ExpressionRef, memoryName: StringRef): ExpressionRef;
export declare function _BinaryenAtomicLoad(module: ModuleRef, bytes: Index, offset: Index, type: TypeRef, ptrExpr: ExpressionRef, memoryName: StringRef, memoryOrder: MemoryOrder): ExpressionRef;

export declare function _BinaryenStore(module: ModuleRef, bytes: u32, offset: u32, align: u32, ptrExpr: ExpressionRef, valueExpr: ExpressionRef, type: TypeRef, memoryName: StringRef): ExpressionRef;
export declare function _BinaryenStoreIsAtomic(expr: ExpressionRef): bool;
Expand All @@ -246,15 +247,13 @@ export declare function _BinaryenStoreSetValue(expr: ExpressionRef, valueExpr: E
export declare function _BinaryenStoreGetValueType(expr: ExpressionRef): TypeRef;
export declare function _BinaryenStoreSetValueType(expr: ExpressionRef, valueType: TypeRef): void;
// ^ with atomic = true
export declare function _BinaryenAtomicStore(module: ModuleRef, bytes: Index, offset: Index, ptrExpr: ExpressionRef, valueExpr: ExpressionRef, type: TypeRef, memoryName: StringRef): ExpressionRef;
export declare function _BinaryenAtomicStore(module: ModuleRef, bytes: Index, offset: Index, ptrExpr: ExpressionRef, valueExpr: ExpressionRef, type: TypeRef, memoryName: StringRef, memoryOrder: MemoryOrder): ExpressionRef;

export declare function _BinaryenConst(module: ModuleRef, value: LiteralRef): ExpressionRef;
export declare function _BinaryenConstGetValueI32(expr: ExpressionRef): i32;
export declare function _BinaryenConstSetValueI32(expr: ExpressionRef, value: i32): void;
export declare function _BinaryenConstGetValueI64Low(expr: ExpressionRef): i32;
export declare function _BinaryenConstSetValueI64Low(expr: ExpressionRef, value: i32): void;
export declare function _BinaryenConstGetValueI64High(expr: ExpressionRef): i32;
export declare function _BinaryenConstSetValueI64High(expr: ExpressionRef, value: i32): void;
export declare function _BinaryenConstGetValueI64(expr: ExpressionRef): i64;
export declare function _BinaryenConstSetValueI64(expr: ExpressionRef, value: i64): void;
export declare function _BinaryenConstGetValueF32(expr: ExpressionRef): f32;
export declare function _BinaryenConstSetValueF32(expr: ExpressionRef, value: f32): void;
export declare function _BinaryenConstGetValueF64(expr: ExpressionRef): f64;
Expand Down Expand Up @@ -296,7 +295,7 @@ export declare function _BinaryenNop(module: ModuleRef): ExpressionRef;

export declare function _BinaryenUnreachable(module: ModuleRef): ExpressionRef;

export declare function _BinaryenAtomicRMW(module: ModuleRef, op: Op, bytes: u32, offset: u32, ptrExpr: ExpressionRef, valueExpr: ExpressionRef, type: TypeRef, memoryName: StringRef): ExpressionRef;
export declare function _BinaryenAtomicRMW(module: ModuleRef, op: Op, bytes: u32, offset: u32, ptrExpr: ExpressionRef, valueExpr: ExpressionRef, type: TypeRef, memoryName: StringRef, memoryOrder: MemoryOrder): ExpressionRef;
export declare function _BinaryenAtomicRMWGetOp(expr: ExpressionRef): Op;
export declare function _BinaryenAtomicRMWSetOp(expr: ExpressionRef, op: Op): void;
export declare function _BinaryenAtomicRMWGetBytes(expr: ExpressionRef): u32;
Expand All @@ -308,7 +307,7 @@ export declare function _BinaryenAtomicRMWSetPtr(expr: ExpressionRef, ptrExpr: E
export declare function _BinaryenAtomicRMWGetValue(expr: ExpressionRef): ExpressionRef;
export declare function _BinaryenAtomicRMWSetValue(expr: ExpressionRef, valueExpr: ExpressionRef): void;

export declare function _BinaryenAtomicCmpxchg(module: ModuleRef, bytes: u32, offset: u32, ptrExpr: ExpressionRef, expectedExpr: ExpressionRef, replacementExpr: ExpressionRef, type: TypeRef, memoryName: StringRef): ExpressionRef;
export declare function _BinaryenAtomicCmpxchg(module: ModuleRef, bytes: u32, offset: u32, ptrExpr: ExpressionRef, expectedExpr: ExpressionRef, replacementExpr: ExpressionRef, type: TypeRef, memoryName: StringRef, memoryOrder: MemoryOrder): ExpressionRef;
export declare function _BinaryenAtomicCmpxchgGetBytes(expr: ExpressionRef): u32;
export declare function _BinaryenAtomicCmpxchgSetBytes(expr: ExpressionRef, bytes: u32): void;
export declare function _BinaryenAtomicCmpxchgGetOffset(expr: ExpressionRef): u32;
Expand Down
Loading