diff --git a/src/nodes/TemplateLiteral.ts b/src/nodes/TemplateLiteral.ts new file mode 100644 index 0000000..489ebc3 --- /dev/null +++ b/src/nodes/TemplateLiteral.ts @@ -0,0 +1,36 @@ +import type ESTree from 'estree'; +import BaseJSNode from './BaseJSNode.js'; + +export default class TemplateLiteral extends BaseJSNode { + public run() { + let result: string = ""; + + for (let i = 0; i < this.node.quasis.length; ++i) { + let quasi = this.node.quasis[i]; + + if (quasi.type === 'TemplateElement') { + if (quasi.value.cooked === null) { + throw new Error(`Invalid template literal: ${quasi.value.raw}`); + } + + if (quasi.value.cooked !== undefined) { + result += quasi.value.cooked; + } + + if (!quasi.tail) { + let expr = this.node.expressions[i]; + if (expr !== undefined) { + // This will automatically stringify the node's return value, since result is a string. + result += this.visitor.visitNode(expr); + } else { + throw new Error(`Expected expression after: ${quasi.value}`); + } + } + } else { + throw new Error(`Unhandled quasi type: ${quasi.type}`); + } + } + + return result; + } +} diff --git a/src/nodes/index.ts b/src/nodes/index.ts index d09b83b..89de4d5 100644 --- a/src/nodes/index.ts +++ b/src/nodes/index.ts @@ -25,6 +25,7 @@ export { default as ReturnStatement } from './ReturnStatement.js'; export { default as SequenceExpression } from './SequenceExpression.js'; export { default as SwitchCase } from './SwitchCase.js'; export { default as SwitchStatement } from './SwitchStatement.js'; +export { default as TemplateLiteral } from './TemplateLiteral.js'; export { default as ThisExpression } from './ThisExpression.js'; export { default as ThrowStatement } from './ThrowStatement.js'; export { default as TryStatement } from './TryStatement.js'; diff --git a/test/main.test.ts b/test/main.test.ts index 02a2256..7f770a9 100644 --- a/test/main.test.ts +++ b/test/main.test.ts @@ -608,5 +608,18 @@ describe('Jinter Tests', () => { expect(jinter.scope.get('result')).toBeTruthy(); }); + + it('should support template literals', () => { + const code = ` + let a = \`world\`; + let b = 1234; + const result = \`hello \${a}\${a}, \\u{55} \${b * 2}! \${'test'}\`; + `; + + const jinter = new Jinter(); + jinter.evaluate(code) + + expect(jinter.scope.get('result')).toBe('hello worldworld, U 2468! test'); + }); }); });