Something went wrong. Try again.
composable JavaScript eval templating
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126import assert from 'node:assert/strict';import { test } from 'node:test';
import { create } from '../src/index.ts';
const mockTrustedTypes = (t, value) => { const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'trustedTypes'); Object.defineProperty(globalThis, 'trustedTypes', { configurable: true, value }); t.after(() => { if (descriptor) { Object.defineProperty(globalThis, 'trustedTypes', descriptor); } else { Reflect.deleteProperty(globalThis, 'trustedTypes'); } });};
test('values retain identity and are never interpolated as source', () => { const x = create(); const object = {}; const text = '); throw new Error("injected"); //'; const fn = () => object; assert.equal(x`return ${fn}(${object});`.eval(), object); assert.equal(x`return ${text};`.eval(), text); assert.deepEqual(x`return [${0}, ${-0}, ${NaN}, ${undefined}, ${1n}];`.eval(), [0, -0, NaN, undefined, 1n]);});
test('nested fragments and locals compose across instances', () => { const x = create(); const y = create(); const first = x.local('a-b'); const second = y.local('a-b'); const unnamed = x.local(); const declaration = y`const ${first} = ${20}; const ${second} = ${22};`; const body = x`${declaration} const ${unnamed} = ${first} + ${second}; return ${unnamed};`; assert.equal(body.eval(), 42); assert.equal(body.eval(), 42); assert.equal(first.name, 'a_b'); assert.equal(x`return ${x.raw('6 * 7')};`.eval(), 42); assert.equal(x``.eval(), undefined);});
test('syntax and runtime errors propagate', () => { const x = create(); const error = new Error('test'); assert.throws(() => x.raw('return (').eval(), SyntaxError); assert.throws( () => x`throw ${error};`.eval(), (actual) => actual === error, );});
test('named policy is private, created once, and trusts both Function arguments', (t) => { const names = []; const sources = []; const trusted = new WeakSet(); const NativeFunction = globalThis.Function; mockTrustedTypes(t, { createPolicy(name, rules) { names.push(name); return { createScript(source) { sources.push(source); const value = { toString: () => rules.createScript(source) }; trusted.add(value); return value; }, }; }, }); t.mock.property( globalThis, 'Function', new Proxy(NativeFunction, { construct(target, args) { assert.equal(args.length, 2); assert.ok(args.every((arg) => trusted.has(arg))); return Reflect.construct(target, args); }, }), ); const x = create({ policyName: 'app-eval' }); const y = create(); assert.equal(x`return ${y`${21}`} * 2;`.eval(), 42); assert.equal(x.raw('return 7;').eval(), 7); assert.deepEqual(names, ['app-eval']); assert.deepEqual(sources, ['_$_0', 'return _$_0 * 2;', '', 'return 7;']);});
test('policy creation and evaluation errors propagate', (t) => { const error = new TypeError('policy blocked'); let attempts = 0; mockTrustedTypes(t, { createPolicy() { attempts++; throw error; }, }); const x = create(); assert.equal(x.raw('return 42;').eval(), 42); assert.equal(attempts, 0); assert.throws( () => create({ policyName: 'blocked' }), (actual) => actual === error, ); assert.equal(attempts, 1); t.mock.property( globalThis, 'Function', new Proxy(globalThis.Function, { construct() { throw error; }, }), ); assert.throws( () => x.raw('return 42;').eval(), (actual) => actual === error, );});
test('named instances work when Trusted Types is unavailable', (t) => { mockTrustedTypes(t, undefined); assert.equal(create({ policyName: 'app-eval' }).raw('return 42;').eval(), 42);});