diff --git a/src/runner/__tests__/runners.ts b/src/runner/__tests__/runners.ts index 5e698fb7b..50f1fa3d4 100644 --- a/src/runner/__tests__/runners.ts +++ b/src/runner/__tests__/runners.ts @@ -179,6 +179,37 @@ describe('Additional JavaScript features are not available in Source Native', () ) }) +describe('Functions in Source libraries (e.g. list, streams) are available in Source Native', () => { + test('List functions are present in Source Native', async () => { + // Test chapters from Source 2 - 4 + for (let chapterNum = 2; chapterNum <= 4; chapterNum++) { + const sourceNativeContext: Context = mockContext(chapterNum, Variant.NATIVE) + // The following snippet is equivalent to sum(list(1..10)) + const sourceNativeSnippet: string = + 'accumulate((x, y) => x + y , 0, append(build_list(x => x + 1, 5), enum_list(6, 10)));' + const result = await runInContext(sourceNativeSnippet, sourceNativeContext) + + expect(result.status).toStrictEqual('finished') + expect((result as any).value).toStrictEqual(55) + expect(sourceNativeContext.errors.length).toBe(0) + } + }) + test('Stream functions are present in Source Native', async () => { + // Test chapters from Source 3 - 4 + for (let chapterNum = 3; chapterNum <= 4; chapterNum++) { + const sourceNativeContext: Context = mockContext(chapterNum, Variant.NATIVE) + // The following snippet is equivalent to sum(list(stream(1..10))) + const sourceNativeSnippet: string = + 'accumulate((x, y) => x + y, 0, stream_to_list(stream_append(build_stream(x => x + 1, 5), enum_stream(6, 10))));' + const result = await runInContext(sourceNativeSnippet, sourceNativeContext) + + expect(result.status).toStrictEqual('finished') + expect((result as any).value).toStrictEqual(55) + expect(sourceNativeContext.errors.length).toBe(0) + } + }) +}) + // HTML Unit Tests test('Error handling script is injected in HTML code', async () => { diff --git a/src/runner/fullJSRunner.ts b/src/runner/fullJSRunner.ts index 4924d6de5..ea9ad0d16 100644 --- a/src/runner/fullJSRunner.ts +++ b/src/runner/fullJSRunner.ts @@ -12,6 +12,7 @@ import { parse } from '../parser/parser' import { evallerReplacer, getBuiltins, transpile } from '../transpiler/transpiler' import type { Context, NativeStorage } from '../types' import * as create from '../utils/astCreator' +import { getIdentifiersInProgram } from '../utils/uniqueIds' import { toSourceError } from './errors' import { appendModulesToContext, resolvedErrorPromise } from './utils' @@ -69,6 +70,9 @@ export async function fullJSRunner( ...preludeAndBuiltins, evallerReplacer(create.identifier(NATIVE_STORAGE_ID), new Set()) ]) + getIdentifiersInProgram(preEvalProgram).forEach(id => + context.nativeStorage.previousProgramsIdentifiers.add(id) + ) const preEvalCode: string = generate(preEvalProgram) const requireProvider = getRequireProvider(context) await fullJSEval(preEvalCode, requireProvider, context.nativeStorage) diff --git a/src/runner/sourceRunner.ts b/src/runner/sourceRunner.ts index 406f31cb8..faef4a78c 100644 --- a/src/runner/sourceRunner.ts +++ b/src/runner/sourceRunner.ts @@ -166,7 +166,6 @@ async function runNative( value }) } catch (error) { - // console.error(error) const isDefaultVariant = options.variant === undefined || options.variant === Variant.DEFAULT if (isDefaultVariant && isPotentialInfiniteLoop(error)) { const detectedInfiniteLoop = testForInfiniteLoop(program, context.previousPrograms.slice(1)) diff --git a/src/transpiler/transpiler.ts b/src/transpiler/transpiler.ts index df6865089..b33bb6b66 100644 --- a/src/transpiler/transpiler.ts +++ b/src/transpiler/transpiler.ts @@ -678,6 +678,9 @@ function transpileToFullJS( globalIds.native ) + getGloballyDeclaredIdentifiers(program).forEach(id => + context.nativeStorage.previousProgramsIdentifiers.add(id) + ) const transpiledProgram: es.Program = create.program([ evallerReplacer(create.identifier(NATIVE_STORAGE_ID), new Set()), create.expressionStatement(create.identifier('undefined')),