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
6 changes: 6 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

module.exports = {
root: true,
ignorePatterns: [
// These fixtures intentionally exercise AssemblyScript-only syntax that
// TypeScript's parser rejects before lint rules can run.
"tests/compiler/parameter-decorators.ts",
"tests/transform/parameter-decorators.ts"
],
parser: "@typescript-eslint/parser",
plugins: [
"@typescript-eslint",
Expand Down
5 changes: 4 additions & 1 deletion cli/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,10 @@ export abstract class Transform {
/** Called when parsing is complete, before a program is instantiated from the AST. */
afterParse?(parser: Parser): void | Promise<void>;

/** Called after the program is instantiated. */
/**
* Called after the program is instantiated and before compilation-time validation runs.
* This is the last hook where transforms can rewrite preserved AST-only syntax before it is rejected.
*/
afterInitialize?(program: Program): void | Promise<void>;

/** Called when compilation is complete, before the module is being validated. */
Expand Down
2 changes: 1 addition & 1 deletion cli/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -718,7 +718,7 @@ export async function main(argv, options) {
stats.initializeTime += stats.end(begin);
}

// Call afterInitialize transform hook
// Call afterInitialize transform hook, the last AST rewrite point before compilation-time validation.
{
let error = await applyTransform("afterInitialize", program);
if (error) return prepareResult(error);
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@
"test:browser": "node --enable-source-maps tests/browser",
"test:asconfig": "cd tests/asconfig && npm run test",
"test:transform": "npm run test:transform:esm && npm run test:transform:cjs",
"test:transform:esm": "node bin/asc tests/compiler/empty --transform ./tests/transform/index.js --noEmit && node bin/asc tests/compiler/empty --transform ./tests/transform/simple.js --noEmit",
"test:transform:cjs": "node bin/asc tests/compiler/empty --transform ./tests/transform/cjs/index.js --noEmit && node bin/asc tests/compiler/empty --transform ./tests/transform/cjs/simple.js --noEmit",
"test:transform:esm": "node bin/asc tests/compiler/empty --transform ./tests/transform/index.js --noEmit && node bin/asc tests/compiler/empty --transform ./tests/transform/simple.js --noEmit && node bin/asc tests/transform/parameter-decorators.ts --transform ./tests/transform/remove-parameter-decorators.js --noEmit",
"test:transform:cjs": "node bin/asc tests/compiler/empty --transform ./tests/transform/cjs/index.js --noEmit && node bin/asc tests/compiler/empty --transform ./tests/transform/cjs/simple.js --noEmit && node bin/asc tests/transform/parameter-decorators.ts --transform ./tests/transform/cjs/remove-parameter-decorators.js --noEmit",
"test:cli": "node tests/cli/options.js",
"asbuild": "npm run asbuild:debug && npm run asbuild:release",
"asbuild:debug": "node bin/asc --config src/asconfig.json --target debug",
Expand Down
12 changes: 10 additions & 2 deletions src/ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,12 @@ export abstract class Node {
name: IdentifierExpression,
type: TypeNode,
initializer: Expression | null,
range: Range
range: Range,
decorators: DecoratorNode[] | null = null
): ParameterNode {
return new ParameterNode(parameterKind, name, type, initializer, range);
let parameter = new ParameterNode(parameterKind, name, type, initializer, range);
parameter.decorators = decorators;
return parameter;
}

// special
Expand Down Expand Up @@ -926,6 +929,9 @@ export class FunctionTypeNode extends TypeNode {
) {
super(NodeKind.FunctionType, isNullable, range);
}

/** Decorators on an explicit `this` parameter, if any, preserved for transforms. */
explicitThisDecorators: DecoratorNode[] | null = null;
}

/** Represents a type parameter. */
Expand Down Expand Up @@ -971,6 +977,8 @@ export class ParameterNode extends Node {
super(NodeKind.Parameter, range);
}

/** Decorators, if any, preserved so transforms can rewrite them before validation. */
decorators: DecoratorNode[] | null = null;
/** Implicit field declaration, if applicable. */
implicitFieldDeclaration: FieldDeclaration | null = null;
/** Common flags indicating specific traits. */
Expand Down
2 changes: 2 additions & 0 deletions src/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,8 @@ export class Compiler extends DiagnosticEmitter {

// initialize lookup maps, built-ins, imports, exports, etc.
this.program.initialize();
// Reject any parameter decorators that transforms left on the AST.
this.program.validateParameterDecorators();


// Binaryen treats all function references as being leaked to the outside world when
Expand Down
31 changes: 31 additions & 0 deletions src/extra/ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,7 @@ export class ASTBuilder {
sb.push(isNullable ? "((" : "(");
let explicitThisType = node.explicitThisType;
if (explicitThisType) {
this.serializeParameterDecorators(node.explicitThisDecorators);
sb.push("this: ");
this.visitTypeNode(explicitThisType);
}
Expand Down Expand Up @@ -1153,6 +1154,7 @@ export class ASTBuilder {
let numParameters = parameters.length;
let explicitThisType = signature.explicitThisType;
if (explicitThisType) {
this.serializeParameterDecorators(signature.explicitThisDecorators);
sb.push("this: ");
this.visitTypeNode(explicitThisType);
}
Expand Down Expand Up @@ -1563,9 +1565,38 @@ export class ASTBuilder {
indent(sb, this.indentLevel);
}

serializeParameterDecorators(decorators: DecoratorNode[] | null): void {
if (decorators) {
for (let i = 0, k = decorators.length; i < k; ++i) {
this.serializeParameterDecorator(decorators[i]);
}
}
}

private serializeParameterDecorator(node: DecoratorNode): void {
let sb = this.sb;
sb.push("@");
this.visitNode(node.name);
let args = node.args;
if (args) {
sb.push("(");
let numArgs = args.length;
if (numArgs) {
this.visitNode(args[0]);
for (let i = 1; i < numArgs; ++i) {
sb.push(", ");
this.visitNode(args[i]);
}
}
sb.push(")");
}
sb.push(" ");
}

serializeParameter(node: ParameterNode): void {
let sb = this.sb;
let kind = node.parameterKind;
this.serializeParameterDecorators(node.decorators);
let implicitFieldDeclaration = node.implicitFieldDeclaration;
if (implicitFieldDeclaration) {
this.serializeAccessModifiers(implicitFieldDeclaration);
Expand Down
2 changes: 1 addition & 1 deletion src/index-wasm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ export function getDependee(program: Program, file: string): string | null {

// Compiler

/** Initializes the program pre-emptively for transform hooks. */
/** Initializes the program pre-emptively so `afterInitialize` transforms can rewrite the AST before compilation. */
export function initializeProgram(program: Program): void {
program.initialize();
}
Expand Down
Loading
Loading