Skip to content

Commit

Permalink
Improve type smoke tests (not finished yet)
Browse files Browse the repository at this point in the history
  • Loading branch information
wycats committed Dec 4, 2024
1 parent 721cbb2 commit 8bb696e
Show file tree
Hide file tree
Showing 16 changed files with 288 additions and 134 deletions.
92 changes: 91 additions & 1 deletion bin/clean.mjs
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,3 +1,93 @@
#!/usr/bin/env node
import { rimraf } from 'rimraf';

await rimraf('**/{dist,.turbo,node_modules}/', { glob: true });
function parseArgs() {
const args = process.argv.slice(2);
const options = {
preserve: new Set(),
help: false,
dryRun: false
};

for (let i = 0; i < args.length; i++) {
const arg = args[i];
switch (arg) {
case '--preserve':
const value = args[++i];
if (!value || value.startsWith('--')) {
console.error('Error: --preserve requires a value (node-modules, turbo, or both)');
process.exit(1);
}
const items = value.split(',');
for (const item of items) {
if (!['node-modules', 'turbo'].includes(item)) {
console.error(`Error: Invalid preserve value: ${item}. Must be 'node-modules' or 'turbo'`);
process.exit(1);
}
options.preserve.add(item);
}
break;
case '--dry-run':
options.dryRun = true;
break;
case '--help':
case '-h':
options.help = true;
break;
default:
console.warn(`Unknown option: ${arg}`);
}
}

return options;
}

function showHelp() {
console.log(`
Usage: clean.mjs [options]
Options:
--preserve <items> Skip cleaning specified items (comma-separated)
Valid values: node-modules, turbo
Example: --preserve node-modules,turbo
--dry-run Show what would be deleted without actually deleting
--help, -h Show this help message
Description:
Cleans build artifacts and dependencies from the project.
By default removes dist, .turbo, and node_modules directories.
`);
}

async function main() {
const options = parseArgs();

if (options.help) {
showHelp();
process.exit(0);
}

const patterns = ['**/dist/'];
if (!options.preserve.has('node-modules')) patterns.push('**/node_modules/');
if (!options.preserve.has('turbo')) patterns.push('**/.turbo/');

const glob = `{${patterns.join(',')}}`;

if (options.dryRun) {
console.log('Would delete the following pattern:', glob);
process.exit(0);
}

try {
await rimraf(glob, { glob: true });
console.log('Clean completed successfully');
} catch (error) {
console.error('Error during cleanup:', error);
process.exit(1);
}
}

main().catch(error => {
console.error('Fatal error:', error);
process.exit(1);
});
2 changes: 1 addition & 1 deletion bin/run-types-tests.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ async function main() {
for (const pkg of packages) {
try {
console.log(`# Smoke testing ${pkg.name}`);
await execa('tsc', ['-p', resolve(root, 'tsconfig.dist.json')], {
await execa('tsc', ['--noEmit', '--strict', '--skipLibCheck'], {
cwd: resolve(pkg.path, 'dist'),
preferLocal: true,
});
Expand Down
1 change: 0 additions & 1 deletion packages/@glimmer-workspace/build/lib/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ export function tsconfig(updates) {
target: ScriptTarget.ESNext,
noEmit: true,
declarationDir: 'dist',
types: ['vite/client'],
...updates,
};
}
Expand Down
1 change: 1 addition & 0 deletions packages/@glimmer-workspace/smoke-types/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import "@glimmer/runtime";
12 changes: 12 additions & 0 deletions packages/@glimmer-workspace/smoke-types/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"private": true,
"name": "@glimmer-workspace/smoke-types",
"main": "index.ts",
"scripts": {
"test:lint": "eslint .",
"test:types": "tsc --noEmit -p ../tsconfig.json"
},
"devDependencies": {
"eslint": "^8.52.0"
}
}
19 changes: 19 additions & 0 deletions packages/@glimmer-workspace/smoke-types/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"compilerOptions": {
"noEmit": true,
"target": "esnext",
"module": "esnext",
"moduleResolution": "bundler",
"baseUrl": ".",
"strict": true,
"paths": {
"@glimmer/*": [
"../../@glimmer/*/dist/prod/index.d.ts"
],
},
"skipLibCheck": true
},
"files": [
"index.ts"
]
}
2 changes: 1 addition & 1 deletion packages/@glimmer/debug/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export type { DebugOp, SomeDisassembledOperand } from './lib/debug';
export { debugOp, describeOpcode, logOpcodeSlice } from './lib/debug';
export { describeOp } from './lib/dism/opcode';
export {
Expand Down Expand Up @@ -49,6 +48,7 @@ export {
wrap,
} from './lib/stack-check';
export { type VmDiff, VmSnapshot, type VmSnapshotValueDiff } from './lib/vm/snapshot';
export type { DebugOp, SomeDisassembledOperand } from '@glimmer/interfaces';
// Types are optimized await automatically
export type {
NormalizedMetadata,
Expand Down
115 changes: 4 additions & 111 deletions packages/@glimmer/debug/lib/debug.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import type {
BlockMetadata,
CompilationContext,
DebugOp,
Dict,
Nullable,
OpSnapshot,
Program,
ProgramConstants,
RawDisassembledOperand,
RuntimeOp,
SomeDisassembledOperand,
} from '@glimmer/interfaces';
import {
CURRIED_COMPONENT,
Expand Down Expand Up @@ -167,99 +170,6 @@ function json(param: SomeDisassembledOperand): string | string[] | null {
}
}

export type AnyOperand = [type: string, value: never, options?: object];
export type OperandTypeOf<O extends AnyOperand> = O[0];
export type OperandValueOf<O extends AnyOperand> = O[1];
export type OperandOptionsOf<O extends AnyOperand> = O extends [
type: string,
value: never,
options: infer Options,
]
? Options
: void;
export type OperandOptionsA<O extends AnyOperand> = O extends [
type: string,
value: never,
options: infer Options,
]
? Options
: {};

type ExtractA<O> = O extends { a: infer A } ? A : never;
type ExpandUnion<U> = U extends infer O ? ExtractA<{ a: O }> : never;

export type NullableOperand<O extends AnyOperand> =
| [OperandTypeOf<O>, OperandValueOf<O>, Expand<OperandOptionsA<O> & { nullable?: false }>]
| [
OperandTypeOf<O>,
Nullable<OperandValueOf<O>>,
Expand<OperandOptionsA<O> & { nullable: true }>,
];

export type NullableName<T extends string> = T extends `${infer N}?` ? N : never;

export type WithOptions<O extends AnyOperand, Options> = ExpandUnion<
[OperandTypeOf<O>, OperandValueOf<O>, Expand<OperandOptionsA<O> & Options>]
>;

// expands object types one level deep
type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;

type DefineOperand<T extends string, V, Options = undefined> = undefined extends Options
? readonly [type: T, value: V]
: readonly [type: T, value: V, options: Options];

type DefineNullableOperand<T extends string, V, Options = undefined> = Options extends undefined
?
| readonly [type: T, value: V]
| readonly [type: T, value: Nullable<V>, options: { nullable: true }]
| readonly [type: T, value: V, options: { nullable?: false }]
:
| readonly [type: T, value: Nullable<V>, options: Expand<Options & { nullable: true }>]
| readonly [type: T, value: V, options: Expand<Options & { nullable?: false }>]
| readonly [type: T, value: V, options: Options];

/**
* A dynamic operand has a value that can't be easily represented as an embedded string.
*/
export type RawDynamicDisassembledOperand =
| DefineOperand<'dynamic', unknown>
| DefineOperand<'constant', number>
| DefineNullableOperand<'array', unknown[]>
| DefineOperand<'variable', number, { name?: string | null }>;

export type RawStaticDisassembledOperand =
| DefineOperand<'error:operand', number, { label: NormalizedOperand }>
| DefineOperand<'error:opcode', number, { kind: number }>
| DefineOperand<'number', number>
| DefineOperand<'boolean', boolean>
| DefineOperand<'primitive', Primitive>
| DefineOperand<'register', RegisterName>
| DefineOperand<'instruction', number>
| DefineOperand<'enum<curry>', 'component' | 'helper' | 'modifier'>
| DefineOperand<'array', number[], { kind: typeof Number }>
| DefineNullableOperand<'array', string[], { kind: typeof String }>
/**
* A variable is a numeric offset into the stack (relative to the $fp register).
*/
| DefineNullableOperand<'string', string>;

export type RawDisassembledOperand = RawStaticDisassembledOperand | RawDynamicDisassembledOperand;

type ObjectForRaw<R> = R extends RawDisassembledOperand
? R[2] extends undefined
? {
type: R[0];
value: R[1];
options?: R[2];
}
: {
type: R[0];
value: R[1];
options: R[2];
}
: never;

export class DisassembledOperand<R extends RawDisassembledOperand = RawDisassembledOperand> {
static of(raw: RawDisassembledOperand): SomeDisassembledOperand {
return new DisassembledOperand(raw) as never;
Expand All @@ -284,23 +194,6 @@ export class DisassembledOperand<R extends RawDisassembledOperand = RawDisassemb
}
}

export type StaticDisassembledOperand = ObjectForRaw<RawStaticDisassembledOperand> & {
isDynamic: false;
};
export type DynamicDisassembledOperand = ObjectForRaw<RawDynamicDisassembledOperand> & {
isDynamic: true;
};

export type SomeDisassembledOperand = StaticDisassembledOperand | DynamicDisassembledOperand;

export interface DebugOp {
name: string;
params: Dict<SomeDisassembledOperand>;
meta: BlockMetadata | null;
}

export type OpSnapshot = Pick<RuntimeOp, 'offset' | 'size' | 'type' | 'op1' | 'op2' | 'op3'>;

export function getOpSnapshot(op: RuntimeOp): OpSnapshot {
return {
offset: op.offset,
Expand Down
6 changes: 3 additions & 3 deletions packages/@glimmer/debug/lib/dism/opcode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
BlockMetadata,
BlockSymbolNames,
Cursor,
DisassembledOperand,
NamedArguments,
Nullable,
PositionalArguments,
Expand All @@ -12,9 +13,8 @@ import type {
VMArguments,
} from '@glimmer/interfaces';
import { dev, exhausted, getLocalDebugType } from '@glimmer/debug-util';
import { isIndexable } from '@glimmer/util';
import { entries, isIndexable } from '@glimmer/util';

import type { DisassembledOperand } from '../debug';
import type { ValueRefOptions } from '../render/basic';
import type { IntoFragment } from '../render/fragment';
import type { RegisterName, SomeDisassembledOperand } from './dism';
Expand All @@ -33,7 +33,7 @@ export function describeOp(

const block = new SerializeBlockContext(meta?.symbols ?? null);

let args: IntoFragment[] = Object.entries(params).map(
let args: IntoFragment[] = entries(params).map(
([p, v]) => frag`${as.attrName(p)}=${block.serialize(v)}`
);

Expand Down
8 changes: 6 additions & 2 deletions packages/@glimmer/debug/lib/dism/operands.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import type { BlockMetadata, ProgramConstants, ProgramHeap } from '@glimmer/interfaces';
import type {
BlockMetadata,
ProgramConstants,
ProgramHeap,
RawDisassembledOperand,
} from '@glimmer/interfaces';
import { decodeHandle } from '@glimmer/constants';

import type { RawDisassembledOperand } from '../debug';
import type {
NonNullableOperandType,
NormalizedOperand,
Expand Down
1 change: 1 addition & 0 deletions packages/@glimmer/interfaces/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ export type * from './lib/template.d.ts';
export type * from './lib/tier1/symbol-table.d.ts';
export type * from './lib/type-utils.d.ts';
export type * from './lib/vm-opcodes.d.ts';
export type * from './lib/debug/dism.d.ts';

export { WireFormat };
Loading

0 comments on commit 8bb696e

Please sign in to comment.