Exemplo
typescript 7.0.2: Clone and duplicate synthesized TypeScript AST nodes using getSynthesizedDeepClone and getSynthesizedDeepClones
Amostra verificada para npm typescript 7.0.2: Clone and duplicate synthesized TypeScript AST nodes using getSynthesizedDeepClone and…
sha256:b825e6f5e2bcc408bb299633fbea559d439d5293dc80b9600075b2746159f6bf
Esta rede oferece uma coisa: uma amostra que compila. Ela a executou em um sandbox e guardou o recibo assinado. Não classifica nem garante nada — se o mesmo código compila onde você está, ela não mediu.
Quantas chaves de assinatura distintas enviaram um recibo de contrato aprovado. Uma é só o autor; mais de uma significa que outra pessoa também o compilou. Uma chave é gerada por conta própria e não tem identidade registrada por trás, então conta chaves, não pessoas.
MIT-0
Evidência de execução
O ambiente declarado e as execuções assinadas ficam separados, para você ver exatamente o que esta amostra executou e onde.
- Base da evidência
- Contrato assinado aprovado
- Recibos de verificação
- 1
- Chaves de assinatura que o compilaram
- 1
Ambiente declarado
linux 24 · ubuntu · glibc 2.39 x64 npm
Ambientes das execuções de verificação
| Ambiente | Contrato | Etapas | Execução |
|---|---|---|---|
| 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-28 |
Caso
HOW- Objetivo
- Clone and duplicate synthesized TypeScript AST nodes using getSynthesizedDeepClone and getSynthesizedDeepClones
- Pacotes
- Símbolos
-
- getSynthesizedDeepClone
- getSynthesizedDeepClones
- Criado
- 2026-08-28T07:00:15Z
Contrato
- cloneAstNode creates an independent deep copy of an AST node with identical structure and kind using getSynthesizedDeepClone
- cloneAstNodeArray creates an independent array of deep-cloned AST nodes using getSynthesizedDeepClones
- cloneAstNode with includeTrivia false resets pos and end text ranges to negative one
- duplicateObjectProperty deep-clones object properties and attaches transformed property assignments without mutating the original AST
- cloneFunctionWithNewName duplicates complete function declarations with parameters and body while retargeting identifier names
Arquivos
- PROMPT.md
- csx.json
- package-lock.json
- package.json
- spec.json
- src/index.mjs
- test/contract.mjs
Código-fonte
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: Clone and duplicate synthesized TypeScript AST nodes using getSynthesizedDeepClone and getSynthesizedDeepClones
Kind: HOW
Use EXACTLY these public packages and versions:
- pkg:npm/typescript@7.0.2
Demonstrate these symbols/APIs:
- getSynthesizedDeepClone
- getSynthesizedDeepClones
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:7b5c21ce860fd5cba7cdc5bd3bac4b9ce3dc96a313944aaf0987c02958f51e57","contract":["cloneAstNode creates an independent deep copy of an AST node with identical structure and kind using getSynthesizedDeepClone","cloneAstNodeArray creates an independent array of deep-cloned AST nodes using getSynthesizedDeepClones","cloneAstNode with includeTrivia false resets pos and end text ranges to negative one","duplicateObjectProperty deep-clones object properties and attaches transformed property assignments without mutating the original AST","cloneFunctionWithNewName duplicates complete function declarations with parameters and body while retargeting identifier names"],"goal":"Clone and duplicate synthesized TypeScript AST nodes using getSynthesizedDeepClone and getSynthesizedDeepClones","kind":"HOW","packages":["pkg:npm/typescript@7.0.2"],"schemaVersion":1,"symbols":["getSynthesizedDeepClone","getSynthesizedDeepClones"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","distro":"ubuntu","ecosystem":"npm","libc":"glibc","libcVersion":"2.39","os":"linux","osVersionBucket":"24","packageManager":"npm","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/typescript@7.0.2"],"schemaVersion":1,"subject":"pkg:npm/typescript@7.0.2","symbols":["getSynthesizedDeepClone","getSynthesizedDeepClones"],"verifierAdapter":"node-typescript@1"}
{
"name": "typescript-ast-clone-sample",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "typescript-ast-clone-sample",
"version": "1.0.0",
"license": "MIT-0",
"dependencies": {
"typescript": "7.0.2"
}
},
"node_modules/@typescript/typescript-aix-ppc64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-aix-ppc64/-/typescript-aix-ppc64-7.0.2.tgz",
"integrity": "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==",
"cpu": [
"ppc64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"aix"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-darwin-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-arm64/-/typescript-darwin-arm64-7.0.2.tgz",
"integrity": "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-darwin-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-x64/-/typescript-darwin-x64-7.0.2.tgz",
"integrity": "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-freebsd-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-arm64/-/typescript-freebsd-arm64-7.0.2.tgz",
"integrity": "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-freebsd-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-x64/-/typescript-freebsd-x64-7.0.2.tgz",
"integrity": "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-arm": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm/-/typescript-linux-arm-7.0.2.tgz",
"integrity": "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==",
"cpu": [
"arm"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm64/-/typescript-linux-arm64-7.0.2.tgz",
"integrity": "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-loong64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-loong64/-/typescript-linux-loong64-7.0.2.tgz",
"integrity": "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==",
"cpu": [
"loong64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-mips64el": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-mips64el/-/typescript-linux-mips64el-7.0.2.tgz",
"integrity": "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==",
"cpu": [
"mips64el"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-ppc64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-ppc64/-/typescript-linux-ppc64-7.0.2.tgz",
"integrity": "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==",
"cpu": [
"ppc64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-riscv64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-riscv64/-/typescript-linux-riscv64-7.0.2.tgz",
"integrity": "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==",
"cpu": [
"riscv64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-s390x": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-s390x/-/typescript-linux-s390x-7.0.2.tgz",
"integrity": "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==",
"cpu": [
"s390x"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-x64/-/typescript-linux-x64-7.0.2.tgz",
"integrity": "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-netbsd-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-arm64/-/typescript-netbsd-arm64-7.0.2.tgz",
"integrity": "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-netbsd-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-x64/-/typescript-netbsd-x64-7.0.2.tgz",
"integrity": "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-openbsd-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-arm64/-/typescript-openbsd-arm64-7.0.2.tgz",
"integrity": "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-openbsd-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-x64/-/typescript-openbsd-x64-7.0.2.tgz",
"integrity": "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-sunos-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-sunos-x64/-/typescript-sunos-x64-7.0.2.tgz",
"integrity": "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"sunos"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-win32-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-win32-arm64/-/typescript-win32-arm64-7.0.2.tgz",
"integrity": "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-win32-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-win32-x64/-/typescript-win32-x64-7.0.2.tgz",
"integrity": "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/typescript": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-7.0.2.tgz",
"integrity": "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==",
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc"
},
"engines": {
"node": ">=16.20.0"
},
"optionalDependencies": {
"@typescript/typescript-aix-ppc64": "7.0.2",
"@typescript/typescript-darwin-arm64": "7.0.2",
"@typescript/typescript-darwin-x64": "7.0.2",
"@typescript/typescript-freebsd-arm64": "7.0.2",
"@typescript/typescript-freebsd-x64": "7.0.2",
"@typescript/typescript-linux-arm": "7.0.2",
"@typescript/typescript-linux-arm64": "7.0.2",
"@typescript/typescript-linux-loong64": "7.0.2",
"@typescript/typescript-linux-mips64el": "7.0.2",
"@typescript/typescript-linux-ppc64": "7.0.2",
"@typescript/typescript-linux-riscv64": "7.0.2",
"@typescript/typescript-linux-s390x": "7.0.2",
"@typescript/typescript-linux-x64": "7.0.2",
"@typescript/typescript-netbsd-arm64": "7.0.2",
"@typescript/typescript-netbsd-x64": "7.0.2",
"@typescript/typescript-openbsd-arm64": "7.0.2",
"@typescript/typescript-openbsd-x64": "7.0.2",
"@typescript/typescript-sunos-x64": "7.0.2",
"@typescript/typescript-win32-arm64": "7.0.2",
"@typescript/typescript-win32-x64": "7.0.2"
}
}
}
}
{
"name": "typescript-ast-clone-sample",
"version": "1.0.0",
"description": "Clone and duplicate synthesized TypeScript AST nodes using getSynthesizedDeepClone and getSynthesizedDeepClones",
"type": "module",
"main": "src/index.mjs",
"scripts": {
"test": "node test/contract.mjs"
},
"dependencies": {
"typescript": "7.0.2"
},
"license": "MIT-0"
}
{
"schemaVersion": 1,
"goal": "Clone and duplicate synthesized TypeScript AST nodes using getSynthesizedDeepClone and getSynthesizedDeepClones",
"kind": "HOW",
"packages": [
"pkg:npm/typescript@7.0.2"
],
"symbols": [
"getSynthesizedDeepClone",
"getSynthesizedDeepClones"
]
}
import {
getSynthesizedDeepClone,
getSynthesizedDeepClones,
} from 'typescript/unstable/ast/clone';
import {
createIdentifier,
createStringLiteral,
createNumericLiteral,
createPropertyAssignment,
createObjectLiteralExpression,
createArrayLiteralExpression,
createFunctionDeclaration,
createParameterDeclaration,
createBlock,
createReturnStatement,
createBinaryExpression,
createCallExpression,
} from 'typescript/unstable/ast/factory';
import {
isIdentifier,
isStringLiteral,
isNumericLiteral,
isPropertyAssignment,
isObjectLiteralExpression,
isArrayLiteralExpression,
isFunctionDeclaration,
isParameterDeclaration,
isBlock,
isReturnStatement,
isBinaryExpression,
isCallExpression,
} from 'typescript/unstable/ast/is';
import {
SyntaxKind,
formatSyntaxKind,
} from 'typescript/unstable/ast';
/**
* Deep clones a single synthesized AST node.
*
* @param {object} node - The AST node to clone.
* @param {boolean} [includeTrivia=true] - Whether to preserve trivia / text range positions.
* @returns {object} A distinct deep clone of the input AST node.
*/
export function cloneAstNode(node, includeTrivia = true) {
if (!node || typeof node !== 'object') {
throw new TypeError('Expected AST node object to clone');
}
return getSynthesizedDeepClone(node, includeTrivia);
}
/**
* Deep clones an array of synthesized AST nodes.
*
* @param {Array<object>} nodes - Array of AST nodes to clone.
* @param {boolean} [includeTrivia=true] - Whether to preserve trivia / text range positions.
* @returns {Array<object>} A new array containing distinct deep clones of each node.
*/
export function cloneAstNodeArray(nodes, includeTrivia = true) {
if (!Array.isArray(nodes)) {
throw new TypeError('Expected an array of AST nodes to clone');
}
return getSynthesizedDeepClones(nodes, includeTrivia);
}
/**
* Clones an ObjectLiteralExpression and adds or replaces a property assignment with a transformed copy.
*
* @param {object} objectLiteral - The source ObjectLiteralExpression AST node.
* @param {string} sourcePropertyName - The name of the property to duplicate/transform.
* @param {string} targetPropertyName - The name for the newly cloned property.
* @param {Function} [transformFn] - Optional transformer for the property initializer.
* @returns {object} A new ObjectLiteralExpression with cloned and updated properties.
*/
export function duplicateObjectProperty(
objectLiteral,
sourcePropertyName,
targetPropertyName,
transformFn
) {
if (!objectLiteral || !isObjectLiteralExpression(objectLiteral)) {
throw new TypeError('Expected an ObjectLiteralExpression AST node');
}
const clonedProps = objectLiteral.properties.map((prop) => {
const cloned = getSynthesizedDeepClone(prop);
return cloned;
});
const sourceProp = objectLiteral.properties.find(
(prop) => isPropertyAssignment(prop) && prop.name?.text === sourcePropertyName
);
if (!sourceProp) {
throw new Error(`Property '${sourcePropertyName}' not found in object literal`);
}
const clonedInit = getSynthesizedDeepClone(sourceProp.initializer);
const transformedInit = transformFn ? transformFn(clonedInit) : clonedInit;
const newProp = createPropertyAssignment(
undefined,
createIdentifier(targetPropertyName),
undefined,
undefined,
transformedInit
);
return createObjectLiteralExpression([...clonedProps, newProp]);
}
/**
* Creates a cloned function declaration with a modified identifier name.
*
* @param {object} functionDecl - Source FunctionDeclaration AST node.
* @param {string} newName - New name for the cloned function.
* @returns {object} Cloned FunctionDeclaration AST node with the new name.
*/
export function cloneFunctionWithNewName(functionDecl, newName) {
if (!functionDecl || !isFunctionDeclaration(functionDecl)) {
throw new TypeError('Expected a FunctionDeclaration AST node');
}
const cloned = getSynthesizedDeepClone(functionDecl);
const newIdentifier = createIdentifier(newName);
return createFunctionDeclaration(
cloned.modifiers,
cloned.asteriskToken,
newIdentifier,
cloned.typeParameters,
cloned.parameters,
cloned.type,
cloned.body
);
}
export {
getSynthesizedDeepClone,
getSynthesizedDeepClones,
createIdentifier,
createStringLiteral,
createNumericLiteral,
createPropertyAssignment,
createObjectLiteralExpression,
createArrayLiteralExpression,
createFunctionDeclaration,
createParameterDeclaration,
createBlock,
createReturnStatement,
createBinaryExpression,
createCallExpression,
isIdentifier,
isStringLiteral,
isNumericLiteral,
isPropertyAssignment,
isObjectLiteralExpression,
isArrayLiteralExpression,
isFunctionDeclaration,
isParameterDeclaration,
isBlock,
isReturnStatement,
isBinaryExpression,
isCallExpression,
SyntaxKind,
formatSyntaxKind,
};
import assert from 'node:assert/strict';
import {
cloneAstNode,
cloneAstNodeArray,
duplicateObjectProperty,
cloneFunctionWithNewName,
getSynthesizedDeepClone,
getSynthesizedDeepClones,
createIdentifier,
createStringLiteral,
createNumericLiteral,
createPropertyAssignment,
createObjectLiteralExpression,
createArrayLiteralExpression,
createFunctionDeclaration,
createParameterDeclaration,
createBlock,
createReturnStatement,
isIdentifier,
isStringLiteral,
isNumericLiteral,
isPropertyAssignment,
isObjectLiteralExpression,
isArrayLiteralExpression,
isFunctionDeclaration,
SyntaxKind,
formatSyntaxKind,
} from '../src/index.mjs';
// Contract 1: cloneAstNode creates an independent deep copy of an AST node with identical structure and kind using getSynthesizedDeepClone
{
const id = createIdentifier('originalIdentifier');
const clonedId = cloneAstNode(id);
assert.ok(clonedId, 'Cloned identifier should be defined');
assert.strictEqual(isIdentifier(clonedId), true, 'Cloned node should satisfy isIdentifier');
assert.strictEqual(clonedId.text, 'originalIdentifier', 'Cloned identifier text should match original');
assert.notStrictEqual(id, clonedId, 'Cloned identifier should be a distinct memory reference');
assert.strictEqual(formatSyntaxKind(clonedId.kind), 'Identifier', 'Kind name should be Identifier');
const strLit = createStringLiteral('sample-value');
const clonedStr = cloneAstNode(strLit);
assert.strictEqual(isStringLiteral(clonedStr), true, 'Cloned node should satisfy isStringLiteral');
assert.strictEqual(clonedStr.text, 'sample-value', 'String literal text should match');
assert.notStrictEqual(strLit, clonedStr, 'String literal should be a distinct instance');
assert.throws(
() => cloneAstNode(null),
{ name: 'TypeError' },
'cloneAstNode should throw TypeError on null input'
);
}
// Contract 2: cloneAstNodeArray creates an independent array of deep-cloned AST nodes using getSynthesizedDeepClones
{
const list = [
createStringLiteral('entryA'),
createNumericLiteral('42'),
createIdentifier('variableX'),
];
const clonedList = cloneAstNodeArray(list);
assert.ok(Array.isArray(clonedList), 'Cloned list should be an array');
assert.strictEqual(clonedList.length, 3, 'Cloned list length should match original');
assert.notStrictEqual(list, clonedList, 'Cloned list array reference should be distinct');
assert.strictEqual(isStringLiteral(clonedList[0]), true, 'First element should be StringLiteral');
assert.strictEqual(clonedList[0].text, 'entryA', 'First element text should match');
assert.notStrictEqual(list[0], clonedList[0], 'First element should be distinct reference');
assert.strictEqual(isNumericLiteral(clonedList[1]), true, 'Second element should be NumericLiteral');
assert.strictEqual(clonedList[1].text, '42', 'Second element text should match');
assert.notStrictEqual(list[1], clonedList[1], 'Second element should be distinct reference');
assert.strictEqual(isIdentifier(clonedList[2]), true, 'Third element should be Identifier');
assert.strictEqual(clonedList[2].text, 'variableX', 'Third element text should match');
assert.notStrictEqual(list[2], clonedList[2], 'Third element should be distinct reference');
assert.throws(
() => cloneAstNodeArray('invalid'),
{ name: 'TypeError' },
'cloneAstNodeArray should throw TypeError on non-array input'
);
}
// Contract 3: cloneAstNode with includeTrivia false resets pos and end text ranges to negative one
{
const nodeWithPos = createIdentifier('positionedIdentifier');
nodeWithPos.pos = 12;
nodeWithPos.end = 32;
const cloneWithTrivia = cloneAstNode(nodeWithPos, true);
assert.strictEqual(cloneWithTrivia.pos, 12, 'Clone with trivia should retain pos');
assert.strictEqual(cloneWithTrivia.end, 32, 'Clone with trivia should retain end');
const cloneNoTrivia = cloneAstNode(nodeWithPos, false);
assert.strictEqual(cloneNoTrivia.pos, -1, 'Clone without trivia should have pos reset to -1');
assert.strictEqual(cloneNoTrivia.end, -1, 'Clone without trivia should have end reset to -1');
assert.strictEqual(cloneNoTrivia.text, 'positionedIdentifier', 'Identifier text should still be preserved');
}
// Contract 4: duplicateObjectProperty deep-clones object properties and attaches transformed property assignments without mutating the original AST
{
const propPort = createPropertyAssignment(
undefined,
createIdentifier('port'),
undefined,
undefined,
createNumericLiteral('8080')
);
const propHost = createPropertyAssignment(
undefined,
createIdentifier('host'),
undefined,
undefined,
createStringLiteral('localhost')
);
const originalObj = createObjectLiteralExpression([propPort, propHost]);
const updatedObj = duplicateObjectProperty(
originalObj,
'port',
'fallbackPort',
(init) => createNumericLiteral('9090')
);
assert.strictEqual(isObjectLiteralExpression(updatedObj), true, 'Updated object should be ObjectLiteralExpression');
assert.strictEqual(originalObj.properties.length, 2, 'Original object properties count should remain 2');
assert.strictEqual(updatedObj.properties.length, 3, 'Updated object should contain 3 properties');
assert.strictEqual(updatedObj.properties[0].name.text, 'port', 'First property should remain port');
assert.strictEqual(updatedObj.properties[0].initializer.text, '8080', 'First property value should remain 8080');
assert.notStrictEqual(originalObj.properties[0], updatedObj.properties[0], 'First property should be a deep clone');
assert.strictEqual(updatedObj.properties[2].name.text, 'fallbackPort', 'Third property should be fallbackPort');
assert.strictEqual(updatedObj.properties[2].initializer.text, '9090', 'Third property value should be 9090');
assert.throws(
() => duplicateObjectProperty(originalObj, 'nonExistentKey', 'newKey'),
/Property 'nonExistentKey' not found/,
'duplicateObjectProperty should throw when source property does not exist'
);
}
// Contract 5: cloneFunctionWithNewName duplicates complete function declarations with parameters and body while retargeting identifier names
{
const param = createParameterDeclaration(
undefined,
undefined,
createIdentifier('inputVal'),
undefined,
undefined,
undefined
);
const bodyReturn = createReturnStatement(createIdentifier('inputVal'));
const bodyBlock = createBlock([bodyReturn], true);
const originalFn = createFunctionDeclaration(
undefined,
undefined,
createIdentifier('handlerA'),
undefined,
[param],
undefined,
bodyBlock
);
const clonedFn = cloneFunctionWithNewName(originalFn, 'handlerB');
assert.strictEqual(isFunctionDeclaration(clonedFn), true, 'Cloned function should satisfy isFunctionDeclaration');
assert.strictEqual(originalFn.name.text, 'handlerA', 'Original function name should be handlerA');
assert.strictEqual(clonedFn.name.text, 'handlerB', 'Cloned function name should be handlerB');
assert.strictEqual(clonedFn.parameters.length, 1, 'Cloned function should retain 1 parameter');
assert.strictEqual(clonedFn.parameters[0].name.text, 'inputVal', 'Parameter name should match');
assert.notStrictEqual(originalFn.parameters[0], clonedFn.parameters[0], 'Parameter should be distinct clone');
assert.notStrictEqual(originalFn.body, clonedFn.body, 'Function body should be distinct clone');
assert.strictEqual(clonedFn.body.statements.length, 1, 'Body should retain return statement');
assert.throws(
() => cloneFunctionWithNewName(null, 'test'),
{ name: 'TypeError' },
'cloneFunctionWithNewName should throw on invalid function node'
);
}
Seeder de origem
anônimo