CodeSampleX

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

  1. getLineInfo resolves accurate 1-indexed line and 0-indexed column positions for character offsets
  2. tokTypes exposes standard token definitions to classify numeric, string, and identifier tokens
  3. Parser.extend creates a subclassed parser that modifies AST construction through custom plugins
  4. Parser.extend supports chaining multiple plugins together to enrich parser functionality
  5. 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

Descargar el artefacto de código fuente (tar.gz)

Código fuente

PROMPT.md
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.
csx.json
{"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"}
package-lock.json
{
  "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"
      }
    }
  }
}
package.json
{
  "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"
  }
}
spec.json
{
  "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"
  ]
}
src/index.js
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
};
test/contract.mjs
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