mirror of
https://github.com/bendtherules/ask262.git
synced 2026-08-18 13:21:55 +00:00
Merge branch 'opencode/annotate-code/mimo-v2-pro'
This commit is contained in:
@@ -0,0 +1,224 @@
|
|||||||
|
---
|
||||||
|
model: mimo-v2-pro
|
||||||
|
---
|
||||||
|
|
||||||
|
# Plan: `ask262Debug` Module for engine262
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Runtime execution tracker that records which ECMAScript spec sections are entered during execution. The Babel transform auto-injects `ask262Debug.mark()` at the start of every function body with URL comments — developer writes nothing. All metadata (sectionId, file, line) resolved at build time.
|
||||||
|
|
||||||
|
## Files to Change
|
||||||
|
|
||||||
|
| File | Action |
|
||||||
|
|------|--------|
|
||||||
|
| `engine262/src/ask262-debug.mts` | **CREATE** — the module |
|
||||||
|
| `engine262/src/index.mts` | **MODIFY** — add re-export |
|
||||||
|
| `engine262/tsconfig.base.json` | **MODIFY** — add `#self/ask262Debug` path |
|
||||||
|
| `engine262/package.json` | **MODIFY** — add `#self/ask262Debug` import |
|
||||||
|
| `engine262/scripts/rollup.config.mts` | **MODIFY** — extend `resolve-self` plugin |
|
||||||
|
| `engine262/scripts/transform.mts` | **MODIFY** — auto-inject `mark()` into function bodies |
|
||||||
|
|
||||||
|
## 1. `scripts/transform.mts` — Enhance the Babel plugin
|
||||||
|
|
||||||
|
### 1a. Refactor `addSectionFromComments` to also inject `mark()` into body
|
||||||
|
|
||||||
|
Current behavior: sets `FuncName.section = 'url'` after the declaration.
|
||||||
|
New behavior: also injects `ask262Debug.mark(["sec-..."], "file.mts", lineNumber)` as the first statement inside the function body.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
function addSectionFromComments(path, getName) {
|
||||||
|
if (!path.node.leadingComments) return;
|
||||||
|
|
||||||
|
const sectionIds = [];
|
||||||
|
let url = '';
|
||||||
|
for (const c of path.node.leadingComments) {
|
||||||
|
for (const line of c.value.split('\n')) {
|
||||||
|
const matches = line.match(/#(sec-[a-zA-Z0-9._%-]+)/g);
|
||||||
|
if (matches) {
|
||||||
|
sectionIds.push(...matches.map(m => m.substring(1)));
|
||||||
|
if (!url) {
|
||||||
|
const section = line.split(' ').find(l => l.includes('#sec'));
|
||||||
|
url = section.includes('https') ? section : `https://tc39.es/ecma262/${section}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sectionIds.length === 0) return;
|
||||||
|
|
||||||
|
const name = getName();
|
||||||
|
|
||||||
|
// 1. Keep existing .section (backward compat)
|
||||||
|
path.insertAfter(template.ast(`${name}.section = '${url}';`));
|
||||||
|
|
||||||
|
// 2. Inject mark() at start of function body
|
||||||
|
const body = path.node.body;
|
||||||
|
if (body?.type === 'BlockStatement') {
|
||||||
|
const relativeFile = getRelativeFilePath(state);
|
||||||
|
const line = path.node.loc?.start.line ?? 0;
|
||||||
|
const markCall = template.ast(
|
||||||
|
'ask262Debug.mark(SECTION_IDS, FILE, LINE);'
|
||||||
|
.replace('SECTION_IDS', JSON.stringify(sectionIds))
|
||||||
|
.replace('FILE', JSON.stringify(relativeFile))
|
||||||
|
.replace('LINE', String(line))
|
||||||
|
);
|
||||||
|
body.body.unshift(markCall);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1b. Add visitors for all function-like nodes
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
FunctionDeclaration(path) {
|
||||||
|
addSectionFromComments(path, () => path.node.id!.name);
|
||||||
|
},
|
||||||
|
ClassMethod(path) {
|
||||||
|
addSectionFromComments(path, () => (path.node.key as t.Identifier).name);
|
||||||
|
},
|
||||||
|
ObjectMethod(path) {
|
||||||
|
addSectionFromComments(path, () => (path.node.key as t.Identifier).name);
|
||||||
|
},
|
||||||
|
// Existing visitors (VariableDeclaration, ExportNamedDeclaration) unchanged
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1c. Multi-section support
|
||||||
|
|
||||||
|
Functions with multiple URL comments get all section IDs as an array:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
/** https://tc39.es/ecma262/#sec-array.prototype.every */
|
||||||
|
/** https://tc39.es/ecma262/#sec-%typedarray%.prototype.every */
|
||||||
|
function* ArrayProto_every(args) { ... }
|
||||||
|
|
||||||
|
// Transform injects:
|
||||||
|
function* ArrayProto_every(args) {
|
||||||
|
ask262Debug.mark(["sec-array.prototype.every", "sec-%typedarray%.prototype.every"], "intrinsics/ArrayPrototypeShared.mts", 173);
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. `engine262/package.json` — Add subpath import
|
||||||
|
|
||||||
|
```json
|
||||||
|
"#self/ask262Debug": "./src/ask262-debug.mts"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. `engine262/tsconfig.base.json` — Add path mapping
|
||||||
|
|
||||||
|
```json
|
||||||
|
"#self/ask262Debug": ["./src/ask262-debug.mts"]
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4. `scripts/rollup.config.mts` — Extend resolve-self plugin
|
||||||
|
|
||||||
|
Change from exact `#self` match to prefix `#self/` match in both builds:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
resolveId(source, _importer, _options) {
|
||||||
|
if (source === '#self' || source.startsWith('#self/')) {
|
||||||
|
return { id: './engine262.mjs' } as any; // inspector build
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
Add similar plugin to main engine262 build (which currently lacks one):
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
{
|
||||||
|
name: 'resolve-self',
|
||||||
|
resolveId(source) {
|
||||||
|
if (source === '#self' || source.startsWith('#self/')) return { id: '#self' };
|
||||||
|
},
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
## 5. `engine262/src/index.mts` — Add re-export
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export { default as ask262Debug, type MarkData } from './ask262-debug.mts';
|
||||||
|
```
|
||||||
|
|
||||||
|
## 6. `engine262/src/ask262-debug.mts` — The module
|
||||||
|
|
||||||
|
Pure data collection. No stack parsing, no `node:` imports, no decorators.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export interface MarkData {
|
||||||
|
readonly sectionIds: string[];
|
||||||
|
readonly fileRelativePath: string;
|
||||||
|
readonly lineNumber: number;
|
||||||
|
readonly important: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Ask262Debug {
|
||||||
|
marks: MarkData[] = [];
|
||||||
|
private _importantStack = false;
|
||||||
|
|
||||||
|
mark(sectionIds: string[], file: string, line: number) {
|
||||||
|
this.marks.push({
|
||||||
|
sectionIds,
|
||||||
|
fileRelativePath: file,
|
||||||
|
lineNumber: line,
|
||||||
|
important: this._importantStack,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
startImportant() {
|
||||||
|
this._importantStack = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
stopImportant() {
|
||||||
|
this._importantStack = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ask262Debug = new Ask262Debug();
|
||||||
|
export default ask262Debug;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Developer writes
|
||||||
|
|
||||||
|
Nothing. The transform auto-injects `mark()` into every function body with URL comments.
|
||||||
|
|
||||||
|
### What the transform produces
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Original:
|
||||||
|
/** https://tc39.es/ecma262/#sec-proxycreate */
|
||||||
|
export function ProxyCreate(target, handler) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transformed:
|
||||||
|
export function ProxyCreate(target, handler) {
|
||||||
|
ask262Debug.mark(["sec-proxycreate"], "abstract-ops/proxy-objects.mts", 540);
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
ProxyCreate.section = 'https://tc39.es/ecma262/#sec-proxycreate';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Key Design Decisions
|
||||||
|
|
||||||
|
| Decision | Choice | Rationale |
|
||||||
|
|----------|--------|-----------|
|
||||||
|
| Module name | `#self/ask262Debug` | Follows existing `#self` pattern |
|
||||||
|
| Export style | Singleton class, default export | `ask262Debug.marks` access |
|
||||||
|
| `MarkData` type | Named export | Users can type-annotate |
|
||||||
|
| All metadata | From transform (build time) | No runtime stack parsing, no `node:` imports |
|
||||||
|
| `mark()` injection | Auto-injected at start of function body | Developer writes nothing |
|
||||||
|
| Multi-section | Array of section IDs per function | Functions can implement multiple spec sections |
|
||||||
|
| `markLine()` | Removed | `mark()` covers all cases |
|
||||||
|
| `.section` | Kept (backward compat) | Used by test262-intrinsics |
|
||||||
|
| `important` | Stubbed with boolean flag | `startImportant()`/`stopImportant()` |
|
||||||
|
| Function types | FunctionDeclaration + ClassMethod + ObjectMethod | Covers all URL comment patterns |
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
1. `cd engine262 && npx tsc -b .` — types compile
|
||||||
|
2. `cd engine262 && npm run lint` — no ESLint violations
|
||||||
|
3. Verify transform output: check that functions with URL comments have `ask262Debug.mark(...)` injected at start of body
|
||||||
|
4. Verify multi-section: check `ArrayProto_every` gets both section IDs
|
||||||
|
5. Run `npm run build:engine` — rollup resolves `#self/ask262Debug` correctly
|
||||||
|
6. Inspect `ask262Debug.marks` after running a test to verify marks are populated with correct data
|
||||||
Reference in New Issue
Block a user