Ejemplo
acorn 8.18.0: Parser.extend, getLineInfo, tokTypes
Muestra verificada para npm acorn 8.18.0: Parser.extend, getLineInfo, tokTypes. El contrato se ejecutó en node 22 · linux alpine/x64 · docker y pasó.
sha256:a2ba746a2f45163fb10107bb6d1c53825b7a0e75c4c525fb1c89bedcb89a9b93
Esta red ofrece una sola cosa: una muestra que compila. La ejecutó en un sandbox y guardó el recibo firmado. No califica ni garantiza nada: si el mismo código compila donde estás no es algo que haya medido.
Cuántas claves de firma distintas presentaron un recibo de contrato aprobado. Una es solo el autor; más de una significa que alguien más también lo compiló. Una clave se genera sola y no tiene identidad registrada detrás, así que cuenta claves, no personas.
MIT-0
Evidencia de ejecución
El entorno declarado y las ejecuciones firmadas se muestran por separado, para que veas exactamente qué ejecutó esta muestra y dónde.
- Base de evidencia
- Contrato firmado aprobado
- Recibos de verificación
- 2
- Claves de firma que lo compilaron
- 1
Entorno declarado
node 22.23 linux 24 · ubuntu · glibc 2.39 x64 node 22.23 javascript npm
Entornos de las ejecuciones de verificación
| Entorno | Contrato | Etapas | Ejecución |
|---|---|---|---|
| node 22 · linux alpine/x64 · docker ed25519:c1973797be207ac4 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1node:22-alpine@sha256:c610fcdfb1d5… |
2026-08-26 |
| node 22 · linux debian/x64 · docker ed25519:c1973797be207ac4 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1node:22@sha256:8a34c4ab3ea2… |
2026-09-07 |
Caso
HOW- Objetivo
- verify acorn.Parser.extend plugin and getLineInfo in pkg:npm/acorn@8.18.0
- Paquetes
- Símbolos
-
- acorn.Parser.extend
- acorn.getLineInfo
- acorn.tokTypes
- Entorno
- node 22.23.2
- Creado
- 2026-08-26T09:27:36Z
Contrato
- getLineInfo resolves accurate 1-indexed line and 0-indexed column positions for character offsets
- tokTypes exposes standard token definitions to classify numeric, string, and identifier tokens
- Parser.extend creates a subclassed parser that modifies AST construction through custom plugins
- Parser.extend supports chaining multiple plugins together to enrich parser functionality
- extended parser preserves standard ECMA options while executing plugin hooks
Archivos
- PROMPT.md
- csx.json
- package-lock.json
- package.json
- spec.json
- src/index.js
- test/contract.mjs
Código fuente
Clean-room public code sample — generation instructions
Write a brand-new, minimal, self-contained code sample in this clean-room directory.
Do not copy, paraphrase, or reference any existing project source. Work only from this spec.
A csx.json manifest scaffold already exists. Do not recreate it from memory. Preserve its case.goal, packages and symbols; fill its empty case.contract with exact assertions and correct its environment, commands and verifierAdapter for the files you generate.
Goal: verify acorn.Parser.extend plugin and getLineInfo in pkg:npm/acorn@8.18.0
Kind: HOW
Use EXACTLY these public packages and versions:
- pkg:npm/acorn@8.18.0
Demonstrate these symbols/APIs:
- acorn.Parser.extend
- acorn.getLineInfo
- acorn.tokTypes
Rules:
- One focused purpose; the smallest project that proves the goal.
- Include a contract test (test/contract.*) that runs OFFLINE and exits 0 exactly when the goal behavior works.
- Pin every dependency with a lockfile so resolution is reproducible.
- No secrets, credentials, or tokens. No real URLs (only example.com or localhost). No absolute paths.
- No personal names, emails, company names, or project identifiers of any kind.
- No binaries and no generated output (node_modules, dist, target, venv, .git, .env).
- Keep it under 200 files and 256KB packed.
{"case":{"caseId":"case:sha256:ae9b7c7b1a30366c5f0e7f0029ca61e9058e662f5ed50042ce423b65c3292df3","constraints":{"executionContext":"node"},"contract":["getLineInfo resolves accurate 1-indexed line and 0-indexed column positions for character offsets","tokTypes exposes standard token definitions to classify numeric, string, and identifier tokens","Parser.extend creates a subclassed parser that modifies AST construction through custom plugins","Parser.extend supports chaining multiple plugins together to enrich parser functionality","extended parser preserves standard ECMA options while executing plugin hooks"],"goal":"verify acorn.Parser.extend plugin and getLineInfo in pkg:npm/acorn@8.18.0","kind":"HOW","packages":["pkg:npm/acorn@8.18.0"],"schemaVersion":1,"symbols":["acorn.Parser.extend","acorn.getLineInfo","acorn.tokTypes"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","distro":"ubuntu","ecosystem":"npm","executionContext":"node","language":"javascript","libc":"glibc","libcVersion":"2.39","moduleSystem":"cjs","os":"linux","osVersionBucket":"24","packageManager":"npm","runtime":"node","runtimeVersion":"22.23.2","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/acorn@8.18.0"],"schemaVersion":1,"subject":"pkg:npm/acorn@8.18.0","symbols":["acorn.Parser.extend","acorn.getLineInfo","acorn.tokTypes"],"verifierAdapter":"node-typescript@1"}
{
"name": "sample-acorn",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "sample-acorn",
"version": "1.0.0",
"dependencies": {
"acorn": "8.18.0"
}
},
"node_modules/acorn": {
"version": "8.18.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz",
"integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==",
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
},
"engines": {
"node": ">=0.4.0"
}
}
}
}
{
"name": "sample-acorn",
"version": "1.0.0",
"private": true,
"description": "Clean-room verification of acorn Parser.extend and getLineInfo",
"main": "src/index.js",
"dependencies": {
"acorn": "8.18.0"
}
}
{
"schemaVersion": 1,
"goal": "verify acorn.Parser.extend plugin and getLineInfo in pkg:npm/acorn@8.18.0",
"kind": "HOW",
"packages": [
"pkg:npm/acorn@8.18.0"
],
"symbols": [
"acorn.Parser.extend",
"acorn.getLineInfo",
"acorn.tokTypes"
]
}
const acorn = require('acorn');
/**
* Find the 1-based line number and 0-based column offset for a given character position.
* @param {string} source - Source code string
* @param {number} offset - Character index in the source code
* @returns {{ line: number, column: number }} Position object
*/
function findPosition(source, offset) {
const pos = acorn.getLineInfo(source, offset);
return {
line: pos.line,
column: pos.column
};
}
/**
* Tokenize source code and classify tokens against acorn.tokTypes.
* @param {string} source - Source code string
* @param {object} [options] - Tokenizer options
* @returns {Array<{ type: string, value: any, start: number, end: number, isKeyword: boolean }>}
*/
function classifyTokens(source, options = {}) {
const defaultOptions = {
ecmaVersion: 'latest',
sourceType: 'module'
};
const tokenizer = acorn.tokenizer(source, { ...defaultOptions, ...options });
const tokens = [];
for (const token of tokenizer) {
tokens.push({
type: token.type.label,
value: token.value,
start: token.start,
end: token.end,
isKeyword: Boolean(token.type.keyword),
tokenType: token.type
});
}
return tokens;
}
/**
* Create a plugin that attaches custom metadata to AST literal and identifier nodes.
* @param {string} propertyName - Property name to attach
* @param {any} propertyValue - Value to attach
* @returns {Function} Acorn plugin function
*/
function createMetadataPlugin(propertyName, propertyValue) {
return function metadataPlugin(Parser) {
return class extends Parser {
parseLiteral(...args) {
const node = super.parseLiteral(...args);
node[propertyName] = propertyValue;
return node;
}
parseIdent(...args) {
const node = super.parseIdent(...args);
node[propertyName] = propertyValue;
return node;
}
};
};
}
/**
* Create an extended Acorn parser with one or more plugins.
* @param {...Function} plugins - Acorn plugin functions
* @returns {typeof acorn.Parser} Subclassed Parser class
*/
function createExtendedParser(...plugins) {
return acorn.Parser.extend(...plugins);
}
module.exports = {
acorn,
findPosition,
classifyTokens,
createMetadataPlugin,
createExtendedParser
};
import assert from 'node:assert';
import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);
const {
acorn,
findPosition,
classifyTokens,
createMetadataPlugin,
createExtendedParser
} = require('../src/index.js');
// 1. Export verification
assert.strictEqual(typeof acorn.getLineInfo, 'function', 'acorn.getLineInfo should be a function');
assert.strictEqual(typeof acorn.Parser.extend, 'function', 'acorn.Parser.extend should be a function');
assert.strictEqual(typeof acorn.tokTypes, 'object', 'acorn.tokTypes should be an object');
assert.strictEqual(typeof findPosition, 'function', 'findPosition should be a function');
assert.strictEqual(typeof classifyTokens, 'function', 'classifyTokens should be a function');
assert.strictEqual(typeof createMetadataPlugin, 'function', 'createMetadataPlugin should be a function');
assert.strictEqual(typeof createExtendedParser, 'function', 'createExtendedParser should be a function');
// 2. getLineInfo resolves accurate 1-indexed line and 0-indexed column positions for character offsets
const multiLineCode = 'const a = 1;\nconst b = 2;\nconst c = 3;';
const pos1 = findPosition(multiLineCode, 0);
assert.strictEqual(pos1.line, 1, 'First line should be 1');
assert.strictEqual(pos1.column, 0, 'First column should be 0');
const offsetLine2 = multiLineCode.indexOf('b = 2');
const pos2 = findPosition(multiLineCode, offsetLine2);
assert.strictEqual(pos2.line, 2, 'Second line should be 2');
assert.strictEqual(pos2.column, 6, 'Offset of b in line 2 should match column 6');
const offsetLine3 = multiLineCode.indexOf('const c');
const pos3 = findPosition(multiLineCode, offsetLine3);
assert.strictEqual(pos3.line, 3, 'Third line should be 3');
assert.strictEqual(pos3.column, 0, 'Start of line 3 should be column 0');
// 3. tokTypes exposes standard token definitions to classify numeric, string, and identifier tokens
assert(acorn.tokTypes.num !== undefined, 'acorn.tokTypes.num should exist');
assert(acorn.tokTypes.string !== undefined, 'acorn.tokTypes.string should exist');
assert(acorn.tokTypes.name !== undefined, 'acorn.tokTypes.name should exist');
const sampleCode = 'const answer = 42; const greeting = "hello";';
const tokens = classifyTokens(sampleCode);
const numTokens = tokens.filter(t => t.tokenType === acorn.tokTypes.num);
assert.strictEqual(numTokens.length, 1, 'Should classify exactly one number token');
assert.strictEqual(numTokens[0].value, 42);
const strTokens = tokens.filter(t => t.tokenType === acorn.tokTypes.string);
assert.strictEqual(strTokens.length, 1, 'Should classify exactly one string token');
assert.strictEqual(strTokens[0].value, 'hello');
const keywordTokens = tokens.filter(t => t.isKeyword);
assert(keywordTokens.length >= 2, 'Should identify const keywords');
// 4. Parser.extend creates a subclassed parser that modifies AST construction through custom plugins
const taggingPlugin = createMetadataPlugin('provenByContract', true);
const TaggedParser = createExtendedParser(taggingPlugin);
const taggedAst = TaggedParser.parse('const message = "verified";', {
ecmaVersion: 'latest',
sourceType: 'module'
});
const decl = taggedAst.body[0].declarations[0];
assert.strictEqual(decl.id.name, 'message');
assert.strictEqual(decl.id.provenByContract, true, 'Identifier should have plugin metadata');
assert.strictEqual(decl.init.value, 'verified');
assert.strictEqual(decl.init.provenByContract, true, 'Literal should have plugin metadata');
// 5. Parser.extend supports chaining multiple plugins together to enrich parser functionality
const pluginA = (Parser) => class extends Parser {
parseLiteral(...args) {
const node = super.parseLiteral(...args);
node.featureA = 'applied';
return node;
}
};
const pluginB = (Parser) => class extends Parser {
parseLiteral(...args) {
const node = super.parseLiteral(...args);
node.featureB = 'applied';
return node;
}
};
const MultiPluginParser = acorn.Parser.extend(pluginA, pluginB);
const multiAst = MultiPluginParser.parse('const value = 100;', {
ecmaVersion: 'latest',
sourceType: 'module'
});
const literalNode = multiAst.body[0].declarations[0].init;
assert.strictEqual(literalNode.value, 100);
assert.strictEqual(literalNode.featureA, 'applied', 'Plugin A should have been applied');
assert.strictEqual(literalNode.featureB, 'applied', 'Plugin B should have been applied');
// 6. extended parser preserves standard ECMA options while executing plugin hooks
const scriptAst = TaggedParser.parse('var count = 5;', {
ecmaVersion: 2020,
sourceType: 'script',
locations: true,
ranges: true
});
assert.strictEqual(scriptAst.type, 'Program');
assert.strictEqual(scriptAst.sourceType, 'script');
assert(scriptAst.loc !== undefined, 'Locations option should be preserved');
assert(Array.isArray(scriptAst.range), 'Ranges option should be preserved');
console.log('All Acorn Parser.extend and getLineInfo contract tests passed successfully.');
Seeder de origen
anónimo