Repository: source-academy/js-slang
Pull request #234 (2019-05-09 01:51:31)

Shift responsibility of deciding execution method to slang

coveralls: ## Pull Request Test Coverage Report for [Build 1070](https://coveralls.io/builds/23274735)

* **42** of **48**   **(87.5%)**  changed or added relevant lines in **2** files are covered.
* No unchanged relevant lines lost coverage.
* Overall coverage decreased (**-0.2%**) to **92.655%**

---

|  Changes Missing Coverage | Covered Lines | Changed/Added Lines | % |
| :-----|--------------|--------|---: |
| [src/index.ts](https://coveralls.io/builds/23274735/source?filename=src%2Findex.ts#L141) | 41 | 47 | 87.23%
<!-- | **Total:** | **42** | **48** | **87.5%** | -->


|  Totals | [![Coverage Status](https://coveralls.io/builds/23274735/badge)](https://coveralls.io/builds/23274735) |
| :-- | --: |
| Change from base [Build 1051](https://coveralls.io/builds/22859735): |  -0.2% |
| Covered Lines: | 1706 |
| Relevant Lines: | 1825 |

---
##### 💛  - [Coveralls](https://coveralls.io)


Patch:
diff --git a/src/createContext.ts b/src/createContext.ts
index 8a84ff1b..5db2b3d1 100644
--- a/src/createContext.ts
+++ b/src/createContext.ts
@@ -55,7 +55,8 @@ export const createEmptyContext = <T>(
     externalContext,
     runtime: createEmptyRuntime(),
     debugger: createEmptyDebugger(),
-    contextId: length - 1
+    contextId: length - 1,
+    executionMethod: 'auto'
   }
 }
 
diff --git a/src/index.ts b/src/index.ts
index bd48ab29..50673ab6 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,4 +1,5 @@
-import { Literal } from 'estree'
+import { simple } from 'acorn-walk/dist/walk'
+import { DebuggerStatement, Literal } from 'estree'
 import { RawSourceMap, SourceMapConsumer } from 'source-map'
 import { JSSLANG_PROPERTIES, UNKNOWN_LOCATION } from './constants'
 import createContext from './createContext'
@@ -12,22 +13,30 @@ import {
 } from './interpreter-errors'
 import { parse, parseAt } from './parser'
 import { AsyncScheduler, PreemptiveScheduler } from './schedulers'
-import { setBreakpointAtLine } from './stdlib/inspector'
+import { areBreakpointsSet, setBreakpointAtLine } from './stdlib/inspector'
 import { transpile } from './transpiler'
-import { Context, Error as ResultError, Finished, Result, Scheduler, SourceError } from './types'
+import {
+  Context,
+  Error as ResultError,
+  ExecutionMethod,
+  Finished,
+  Result,
+  Scheduler,
+  SourceError
+} from './types'
 import { locationDummyNode } from './utils/astCreator'
 import { sandboxedEval } from './utils/evalContainer'
 
 export interface IOptions {
   scheduler: 'preemptive' | 'async'
   steps: number
-  isNativeRunnable: boolean
+  executionMethod: ExecutionMethod
 }
 
 const DEFAULT_OPTIONS: IOptions = {
   scheduler: 'async',
   steps: 1000,
-  isNativeRunnable: false
+  executionMethod: 'auto'
 }
 
 // needed to work on browsers
@@ -122,71 +131,92 @@ export function runInContext(
 
   verboseErrors = getFirstLine(code) === 'enable verbose'
   const program = parse(code, context)
-  if (program) {
-    if (theOptions.isNativeRunnable) {
-      if (previousCode === code) {
-        JSSLANG_PROPERTIES.maxExecTime *= JSSLANG_PROPERTIES.factorToIncreaseBy
+  if (!program) {
+    return resolvedErrorPromise
+  }
+  let isNativeRunnable
+  if (theOptions.executionMethod === 'auto') {
+    if (context.executionMethod === 'auto') {
+      if (verboseErrors) {
+        isNativeRunnable = false
+      } else if (areBreakpointsSet()) {
+        isNativeRunnable = false
       } else {
-        JSSLANG_PROPERTIES.maxExecTime = JSSLANG_PROPERTIES.originalMaxExecTime
-      }
-      previousCode = code
-      let transpiled
-      let sourceMapJson: RawSourceMap | undefined
-      let lastStatementSourceMapJson: RawSourceMap | undefined
-      try {
-        const temp = transpile(program, context.contextId)
-        // some issues with formatting and semicolons and tslint so no destructure
-        transpiled = temp.transpiled
-        sourceMapJson = temp.codeMap
-        lastStatementSourceMapJson = temp.evalMap
-        return Promise.resolve({
-          status: 'finished',
-          value: sandboxedEval(transpiled)
-        } as Result)
-      } catch (error) {
-        if (error instanceof RuntimeSourceError) {
-          context.errors.push(error)
-          return resolvedErrorPromise
-        }
-        const errorStack = error.stack
-        const match = /<anonymous>:(\d+):(\d+)/.exec(errorStack)
-        if (match === null) {
-          context.errors.push(new ExceptionError(error, UNKNOWN_LOCATION))
-          return resolvedErrorPromise
-        }
-        const line = Number(match![1])
-        const column = Number(match![2])
-        return SourceMapConsumer.with(
-          line === 1 ? lastStatementSourceMapJson! : sourceMapJson!,
-          null,
-          consumer => {
-            const {
-              line: originalLine,
-              column: originalColumn,
-              name
-            } = consumer.originalPositionFor({
-              line,
-              column
-            })
-            context.errors.push(
-              convertNativeErrorToSourceError(error, originalLine, originalColumn, name)
-            )
-            return resolvedErrorPromise
+        let hasDeuggerStatement = false
+        simple(program, {
+          DebuggerStatement(node: DebuggerStatement) {
+            hasDeuggerStatement = true
           }
-        )
+        })
+        isNativeRunnable = !hasDeuggerStatement
       }
+      context.executionMethod = isNativeRunnable ? 'native' : 'interpreter'
     } else {
-      const it = evaluate(program, context)
-      let scheduler: Scheduler
-      if (theOptions.scheduler === 'async') {
-        scheduler = new AsyncScheduler()
-      } else {
-        scheduler = new PreemptiveScheduler(theOptions.steps)
+      isNativeRunnable = context.executionMethod === 'native'
+    }
+  } else {
+    isNativeRunnable = theOptions.executionMethod === 'native'
+  }
+
+  if (isNativeRunnable) {
+    if (previousCode === code) {
+      JSSLANG_PROPERTIES.maxExecTime *= JSSLANG_PROPERTIES.factorToIncreaseBy
+    } else {
+      JSSLANG_PROPERTIES.maxExecTime = JSSLANG_PROPERTIES.originalMaxExecTime
+    }
+    previousCode = code
+    let transpiled
+    let sourceMapJson: RawSourceMap | undefined
+    let lastStatementSourceMapJson: RawSourceMap | undefined
+    try {
+      const temp = transpile(program, context.contextId)
+      // some issues with formatting and semicolons and tslint so no destructure
+      transpiled = temp.transpiled
+      sourceMapJson = temp.codeMap
+      lastStatementSourceMapJson = temp.evalMap
+      return Promise.resolve({
+        status: 'finished',
+        value: sandboxedEval(transpiled)
+      } as Result)
+    } catch (error) {
+      if (error instanceof RuntimeSourceError) {
+        context.errors.push(error)
+        return resolvedErrorPromise
+      }
+      const errorStack = error.stack
+      const match = /<anonymous>:(\d+):(\d+)/.exec(errorStack)
+      if (match === null) {
+        context.errors.push(new ExceptionError(error, UNKNOWN_LOCATION))
+        return resolvedErrorPromise
       }
-      return scheduler.run(it, context)
+      const line = Number(match![1])
+      const column = Number(match![2])
+      return SourceMapConsumer.with(
+        line === 1 ? lastStatementSourceMapJson! : sourceMapJson!,
+        null,
+        consumer => {
+          const { line: originalLine, column: originalColumn, name } = consumer.originalPositionFor(
+            {
+              line,
+              column
+            }
+          )
+          context.errors.push(
+            convertNativeErrorToSourceError(error, originalLine, originalColumn, name)
+          )
+          return resolvedErrorPromise
+        }
+      )
     }
   } else {
-    return resolvedErrorPromise
+    const it = evaluate(program, context)
+    let scheduler: Scheduler
+    if (theOptions.scheduler === 'async') {
+      scheduler = new AsyncScheduler()
+    } else {
+      scheduler = new PreemptiveScheduler(theOptions.steps)
+    }
+    return scheduler.run(it, context)
   }
 }
 
diff --git a/src/stdlib/inspector.ts b/src/stdlib/inspector.ts
index e211d55f..c6bebca0 100644
--- a/src/stdlib/inspector.ts
+++ b/src/stdlib/inspector.ts
@@ -42,3 +42,5 @@ export const checkEditorBreakpoints = (context: Context, node: Node): void => {
     }
   }
 }
+
+export const areBreakpointsSet = () => breakpoints.length > 0
diff --git a/src/types.ts b/src/types.ts
index 45f2476c..e38ccf72 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -56,6 +56,8 @@ export interface Comment {
   loc: SourceLocation | undefined
 }
 
+export type ExecutionMethod = 'native' | 'interpreter' | 'auto'
+
 export interface Context<T = any> {
   /** The source version used */
   chapter: number
@@ -96,6 +98,8 @@ export interface Context<T = any> {
    * Used for storing id of the context to be referenced by native
    */
   contextId: number
+
+  executionMethod: ExecutionMethod
 }
 
 // tslint:disable:no-any


Test patch:
diff --git a/src/__tests__/__snapshots__/inspect.ts.snap b/src/__tests__/__snapshots__/inspect.ts.snap
index 85adcc35..4d7ed31d 100644
--- a/src/__tests__/__snapshots__/inspect.ts.snap
+++ b/src/__tests__/__snapshots__/inspect.ts.snap
@@ -18,6 +18,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -1536,6 +1537,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -2741,6 +2743,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -2988,6 +2991,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -3117,6 +3121,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -3946,6 +3951,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -4543,6 +4549,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -6223,6 +6230,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -6573,6 +6581,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -7771,6 +7780,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -8969,6 +8979,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -10167,6 +10178,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -11365,6 +11377,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -11493,6 +11506,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -11971,6 +11985,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -12633,6 +12648,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -12762,6 +12778,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -13174,6 +13191,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -14066,6 +14084,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -14958,6 +14977,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -15850,6 +15870,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -16759,6 +16780,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -16888,6 +16910,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -17796,6 +17819,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -18704,6 +18728,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -18833,6 +18858,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -19710,6 +19736,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -20717,6 +20744,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -21594,6 +21622,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -22601,6 +22630,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "interpreter",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
diff --git a/src/__tests__/__snapshots__/interpreter-errors.ts.snap b/src/__tests__/__snapshots__/interpreter-errors.ts.snap
index cef678c9..47c296a5 100644
--- a/src/__tests__/__snapshots__/interpreter-errors.ts.snap
+++ b/src/__tests__/__snapshots__/interpreter-errors.ts.snap
@@ -2374,6 +2374,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "auto",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -2515,6 +2516,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "auto",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -2652,6 +2654,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "auto",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -2793,6 +2796,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "auto",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -2930,6 +2934,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "auto",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -3084,6 +3089,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "auto",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -3225,6 +3231,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "auto",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -3362,6 +3369,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "auto",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -3503,6 +3511,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "auto",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -3640,6 +3649,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "auto",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -3781,6 +3791,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "auto",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -3918,6 +3929,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "auto",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -4062,6 +4074,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "auto",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -4199,6 +4212,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "auto",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -4343,6 +4357,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "auto",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -4480,6 +4495,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "auto",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
@@ -4624,6 +4640,7 @@ Object {
       "status": false,
     },
     "errors": Array [],
+    "executionMethod": "auto",
     "externalContext": undefined,
     "externalSymbols": Array [],
     "runtime": Object {
diff --git a/src/__tests__/inspect.ts b/src/__tests__/inspect.ts
index 5069ae82..836d8e23 100644
--- a/src/__tests__/inspect.ts
+++ b/src/__tests__/inspect.ts
@@ -10,7 +10,10 @@ test('debugger; statement basic test', () => {
   debugger;
   `
   const context = mockContext(3)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'auto'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('suspended')
     expect(parseError(context.errors)).toMatchSnapshot()
@@ -26,7 +29,10 @@ test('debugger; statement in function', () => {
   a(10);
   `
   const context = mockContext(3)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'auto'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('suspended')
     expect(parseError(context.errors)).toMatchSnapshot()
@@ -42,7 +48,10 @@ test('debugger; statement execution sequence', () => {
   a(10);
   `
   const context = mockContext(3)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'auto'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('finished')
     expect(parseError(context.errors)).toMatchSnapshot()
@@ -69,7 +78,10 @@ test('debugger; statement test function scope', () => {
   a(10);
   `
   const context = mockContext(3)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'auto'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('suspended')
     expect(parseError(context.errors)).toMatchSnapshot()
@@ -88,7 +100,10 @@ test('debugger; statement hoisting', () => {
   a(10);
   `
   const context = mockContext(3)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'auto'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('suspended')
     expect(parseError(context.errors)).toMatchSnapshot()
@@ -105,7 +120,10 @@ test('debugger; pauses for', () => {
   a(10);
   `
   const context = mockContext(3)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'auto'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('suspended')
     expect(parseError(context.errors)).toMatchSnapshot()
@@ -123,7 +141,10 @@ test('debugger; pauses while', () => {
   a(10);
   `
   const context = mockContext(3)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'auto'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('suspended')
     expect(parseError(context.errors)).toMatchSnapshot()
@@ -147,7 +168,10 @@ test('setBreakpointAtLine basic', () => {
   `
   const context = mockContext(3)
   setBreakpointAtLine(['helloworld'])
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'auto'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('suspended')
     expect(parseError(context.errors)).toMatchSnapshot()
@@ -165,7 +189,10 @@ test('setBreakpointAtLine function 1', () => {
   const breakline = []
   breakline[1] = 'asd'
   setBreakpointAtLine(breakline)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'auto'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('suspended')
     expect(parseError(context.errors)).toMatchSnapshot()
@@ -183,7 +210,10 @@ test('setBreakpointAtLine function 2', () => {
   const breakline = []
   breakline[2] = 'asd'
   setBreakpointAtLine(breakline)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'auto'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('suspended')
     expect(parseError(context.errors)).toMatchSnapshot()
@@ -203,7 +233,10 @@ test('setBreakpointAtLine function 3', () => {
   const breakline = []
   breakline[3] = 'asd'
   setBreakpointAtLine(breakline)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'auto'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('finished')
     expect(parseError(context.errors)).toMatchSnapshot()
@@ -221,7 +254,10 @@ test('setBreakpointAtLine function 4', () => {
   const breakline = []
   breakline[4] = 'asd'
   setBreakpointAtLine(breakline)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'auto'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('suspended')
     expect(parseError(context.errors)).toMatchSnapshot()
@@ -245,7 +281,10 @@ test('setBreakpointAtLine granularity 1', () => {
   // right now for some reason it breaks twice at the line.
   // this should not happen
   // if you do fix this issue, this is good to modify.
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'auto'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('suspended')
     expect(parseError(context.errors)).toMatchSnapshot()
@@ -280,7 +319,10 @@ test('setBreakpointAtLine granularity 2', () => {
   const breakline = []
   breakline[3] = 'a'
   setBreakpointAtLine(breakline)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'auto'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('suspended')
     expect(parseError(context.errors)).toMatchSnapshot()
@@ -307,7 +349,10 @@ test('setBreakpointAtLine granularity 3', () => {
   breakline[4] = 'a'
   setBreakpointAtLine(breakline)
   // for some reason this is safe from the breaking twice problem
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'auto'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('suspended')
     expect(parseError(context.errors)).toMatchSnapshot()
@@ -336,7 +381,10 @@ test('setBreakpointAtLine for loops', () => {
   breakline[2] = '2'
   setBreakpointAtLine(breakline)
   // for some reason this is safe from the breaking twice problem
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'auto'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('suspended')
     expect(parseError(context.errors)).toMatchSnapshot()
@@ -376,7 +424,10 @@ test('setBreakpointAtLine while loops', () => {
   breakline[3] = '3'
   setBreakpointAtLine(breakline)
   // for some reason this is safe from the breaking twice problem
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'auto'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('suspended')
     expect(parseError(context.errors)).toMatchSnapshot()
diff --git a/src/__tests__/interpreter-errors.ts b/src/__tests__/interpreter-errors.ts
index ec3db814..25554839 100644
--- a/src/__tests__/interpreter-errors.ts
+++ b/src/__tests__/interpreter-errors.ts
@@ -674,11 +674,17 @@ test('Runtime error when redeclaring constant in interpreter', () => {
     const f = x => x;
   `
   const context = mockContext(3)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'interpreter'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('finished')
     expect(parseError(context.errors)).toMatchSnapshot()
-    return runInContext(code2, context, { scheduler: 'preemptive' }).then(obj2 => {
+    return runInContext(code2, context, {
+      scheduler: 'preemptive',
+      executionMethod: 'interpreter'
+    }).then(obj2 => {
       expect(obj2).toMatchSnapshot()
       expect(obj2.status).toBe('error')
       expect(parseError(context.errors)).toMatchSnapshot()
@@ -694,18 +700,19 @@ test('Runtime error when redeclaring constant in native', () => {
     const f = x => x;
   `
   const context = mockContext(3)
-  return runInContext(code1, context, { scheduler: 'preemptive', isNativeRunnable: true }).then(
+  return runInContext(code1, context, { scheduler: 'preemptive', executionMethod: 'native' }).then(
     obj1 => {
       expect(obj1).toMatchSnapshot()
       expect(obj1.status).toBe('finished')
       expect(parseError(context.errors)).toMatchSnapshot()
-      return runInContext(code2, context, { scheduler: 'preemptive', isNativeRunnable: true }).then(
-        obj2 => {
-          expect(obj2).toMatchSnapshot()
-          expect(obj2.status).toBe('error')
-          expect(parseError(context.errors)).toMatchSnapshot()
-        }
-      )
+      return runInContext(code2, context, {
+        scheduler: 'preemptive',
+        executionMethod: 'native'
+      }).then(obj2 => {
+        expect(obj2).toMatchSnapshot()
+        expect(obj2.status).toBe('error')
+        expect(parseError(context.errors)).toMatchSnapshot()
+      })
     }
   )
 })
@@ -718,11 +725,17 @@ test('Runtime error when redeclaring constant as variable', () => {
     let f = x => x;
   `
   const context = mockContext(3)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'interpreter'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('finished')
     expect(parseError(context.errors)).toMatchSnapshot()
-    return runInContext(code2, context, { scheduler: 'preemptive' }).then(obj2 => {
+    return runInContext(code2, context, {
+      scheduler: 'preemptive',
+      executionMethod: 'interpreter'
+    }).then(obj2 => {
       expect(obj2).toMatchSnapshot()
       expect(obj2.status).toBe('error')
       expect(parseError(context.errors)).toMatchSnapshot()
@@ -739,11 +752,17 @@ test('Runtime error when redeclaring constant as variable - verbose', () => {
     let f = x => x;
   `
   const context = mockContext(3)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'interpreter'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('finished')
     expect(parseError(context.errors)).toMatchSnapshot()
-    return runInContext(code2, context, { scheduler: 'preemptive' }).then(obj2 => {
+    return runInContext(code2, context, {
+      scheduler: 'preemptive',
+      executionMethod: 'interpreter'
+    }).then(obj2 => {
       expect(obj2).toMatchSnapshot()
       expect(obj2.status).toBe('error')
       expect(parseError(context.errors)).toMatchSnapshot()
@@ -759,11 +778,17 @@ test('Runtime error when redeclaring constant as function', () => {
     function f(x) { return x; }
   `
   const context = mockContext(3)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'interpreter'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('finished')
     expect(parseError(context.errors)).toMatchSnapshot()
-    return runInContext(code2, context, { scheduler: 'preemptive' }).then(obj2 => {
+    return runInContext(code2, context, {
+      scheduler: 'preemptive',
+      executionMethod: 'interpreter'
+    }).then(obj2 => {
       expect(obj2).toMatchSnapshot()
       expect(obj2.status).toBe('error')
       expect(parseError(context.errors)).toMatchSnapshot()
@@ -780,11 +805,17 @@ test('Runtime error when redeclaring constant as function - verbose', () => {
     function f(x) { return x; }
   `
   const context = mockContext(3)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'interpreter'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('finished')
     expect(parseError(context.errors)).toMatchSnapshot()
-    return runInContext(code2, context, { scheduler: 'preemptive' }).then(obj2 => {
+    return runInContext(code2, context, {
+      scheduler: 'preemptive',
+      executionMethod: 'interpreter'
+    }).then(obj2 => {
       expect(obj2).toMatchSnapshot()
       expect(obj2.status).toBe('error')
       expect(parseError(context.errors)).toMatchSnapshot()
@@ -800,11 +831,17 @@ test('Runtime error when redeclaring variable as constant', () => {
     const f = x => x;
   `
   const context = mockContext(3)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'interpreter'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(parseError(context.errors)).toMatchSnapshot()
     expect(obj1.status).toBe('finished')
-    return runInContext(code2, context, { scheduler: 'preemptive' }).then(obj2 => {
+    return runInContext(code2, context, {
+      scheduler: 'preemptive',
+      executionMethod: 'interpreter'
+    }).then(obj2 => {
       expect(obj2).toMatchSnapshot()
       expect(parseError(context.errors)).toMatchSnapshot()
       expect(obj2.status).toBe('error')
@@ -821,11 +858,17 @@ test('Runtime error when redeclaring variable as constant - verbose', () => {
     const f = x => x;
   `
   const context = mockContext(3)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'interpreter'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(parseError(context.errors)).toMatchSnapshot()
     expect(obj1.status).toBe('finished')
-    return runInContext(code2, context, { scheduler: 'preemptive' }).then(obj2 => {
+    return runInContext(code2, context, {
+      scheduler: 'preemptive',
+      executionMethod: 'interpreter'
+    }).then(obj2 => {
       expect(obj2).toMatchSnapshot()
       expect(parseError(context.errors)).toMatchSnapshot()
       expect(obj2.status).toBe('error')
@@ -841,11 +884,17 @@ test('Runtime error when redeclaring variable', () => {
     let f = x => x;
   `
   const context = mockContext(3)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'interpreter'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('finished')
     expect(parseError(context.errors)).toMatchSnapshot()
-    return runInContext(code2, context, { scheduler: 'preemptive' }).then(obj2 => {
+    return runInContext(code2, context, {
+      scheduler: 'preemptive',
+      executionMethod: 'interpreter'
+    }).then(obj2 => {
       expect(obj2).toMatchSnapshot()
       expect(obj2.status).toBe('error')
       expect(parseError(context.errors)).toMatchSnapshot()
@@ -862,11 +911,17 @@ test('Runtime error when redeclaring variable - verbose', () => {
     let f = x => x;
   `
   const context = mockContext(3)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'interpreter'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('finished')
     expect(parseError(context.errors)).toMatchSnapshot()
-    return runInContext(code2, context, { scheduler: 'preemptive' }).then(obj2 => {
+    return runInContext(code2, context, {
+      scheduler: 'preemptive',
+      executionMethod: 'interpreter'
+    }).then(obj2 => {
       expect(obj2).toMatchSnapshot()
       expect(obj2.status).toBe('error')
       expect(parseError(context.errors)).toMatchSnapshot()
@@ -882,11 +937,17 @@ test('Runtime error when redeclaring variable as function', () => {
     function f(x) { return x; }
   `
   const context = mockContext(3)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'interpreter'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('finished')
     expect(parseError(context.errors)).toMatchSnapshot()
-    return runInContext(code2, context, { scheduler: 'preemptive' }).then(obj2 => {
+    return runInContext(code2, context, {
+      scheduler: 'preemptive',
+      executionMethod: 'interpreter'
+    }).then(obj2 => {
       expect(obj2).toMatchSnapshot()
       expect(obj2.status).toBe('error')
       expect(parseError(context.errors)).toMatchSnapshot()
@@ -903,11 +964,17 @@ test('Runtime error when redeclaring variable as function - verbose', () => {
     function f(x) { return x; }
   `
   const context = mockContext(3)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'interpreter'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('finished')
     expect(parseError(context.errors)).toMatchSnapshot()
-    return runInContext(code2, context, { scheduler: 'preemptive' }).then(obj2 => {
+    return runInContext(code2, context, {
+      scheduler: 'preemptive',
+      executionMethod: 'interpreter'
+    }).then(obj2 => {
       expect(obj2).toMatchSnapshot()
       expect(obj2.status).toBe('error')
       expect(parseError(context.errors)).toMatchSnapshot()
@@ -923,11 +990,17 @@ test('Runtime error when redeclaring function as constant', () => {
     const f = x => x;
   `
   const context = mockContext(3)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'interpreter'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(parseError(context.errors)).toMatchSnapshot()
     expect(obj1.status).toBe('finished')
-    return runInContext(code2, context, { scheduler: 'preemptive' }).then(obj2 => {
+    return runInContext(code2, context, {
+      scheduler: 'preemptive',
+      executionMethod: 'interpreter'
+    }).then(obj2 => {
       expect(obj2).toMatchSnapshot()
       expect(parseError(context.errors)).toMatchSnapshot()
       expect(obj2.status).toBe('error')
@@ -944,11 +1017,17 @@ test('Runtime error when redeclaring function as constant - verbose', () => {
     const f = x => x;
   `
   const context = mockContext(3)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'interpreter'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(parseError(context.errors)).toMatchSnapshot()
     expect(obj1.status).toBe('finished')
-    return runInContext(code2, context, { scheduler: 'preemptive' }).then(obj2 => {
+    return runInContext(code2, context, {
+      scheduler: 'preemptive',
+      executionMethod: 'interpreter'
+    }).then(obj2 => {
       expect(obj2).toMatchSnapshot()
       expect(parseError(context.errors)).toMatchSnapshot()
       expect(obj2.status).toBe('error')
@@ -964,11 +1043,17 @@ test('Runtime error when redeclaring function as variable', () => {
     let f = x => x;
   `
   const context = mockContext(3)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'interpreter'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('finished')
     expect(parseError(context.errors)).toMatchSnapshot()
-    return runInContext(code2, context, { scheduler: 'preemptive' }).then(obj2 => {
+    return runInContext(code2, context, {
+      scheduler: 'preemptive',
+      executionMethod: 'interpreter'
+    }).then(obj2 => {
       expect(obj2).toMatchSnapshot()
       expect(obj2.status).toBe('error')
       expect(parseError(context.errors)).toMatchSnapshot()
@@ -985,11 +1070,17 @@ test('Runtime error when redeclaring function as variable - verbose', () => {
     let f = x => x;
   `
   const context = mockContext(3)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'interpreter'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('finished')
     expect(parseError(context.errors)).toMatchSnapshot()
-    return runInContext(code2, context, { scheduler: 'preemptive' }).then(obj2 => {
+    return runInContext(code2, context, {
+      scheduler: 'preemptive',
+      executionMethod: 'interpreter'
+    }).then(obj2 => {
       expect(obj2).toMatchSnapshot()
       expect(obj2.status).toBe('error')
       expect(parseError(context.errors)).toMatchSnapshot()
@@ -1005,11 +1096,17 @@ test('Runtime error when redeclaring function', () => {
     function f(x) { return x; }
   `
   const context = mockContext(3)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'interpreter'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('finished')
     expect(parseError(context.errors)).toMatchSnapshot()
-    return runInContext(code2, context, { scheduler: 'preemptive' }).then(obj2 => {
+    return runInContext(code2, context, {
+      scheduler: 'preemptive',
+      executionMethod: 'interpreter'
+    }).then(obj2 => {
       expect(obj2).toMatchSnapshot()
       expect(obj2.status).toBe('error')
       expect(parseError(context.errors)).toMatchSnapshot()
@@ -1026,11 +1123,17 @@ test('Runtime error when redeclaring function - verbose', () => {
     function f(x) { return x; }
   `
   const context = mockContext(3)
-  return runInContext(code1, context, { scheduler: 'preemptive' }).then(obj1 => {
+  return runInContext(code1, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'interpreter'
+  }).then(obj1 => {
     expect(obj1).toMatchSnapshot()
     expect(obj1.status).toBe('finished')
     expect(parseError(context.errors)).toMatchSnapshot()
-    return runInContext(code2, context, { scheduler: 'preemptive' }).then(obj2 => {
+    return runInContext(code2, context, {
+      scheduler: 'preemptive',
+      executionMethod: 'interpreter'
+    }).then(obj2 => {
       expect(obj2).toMatchSnapshot()
       expect(obj2.status).toBe('error')
       expect(parseError(context.errors)).toMatchSnapshot()
diff --git a/src/__tests__/native.ts b/src/__tests__/native.ts
index 5b1f25b3..3084f7ab 100644
--- a/src/__tests__/native.ts
+++ b/src/__tests__/native.ts
@@ -11,7 +11,10 @@ test('Proper stringify-ing of arguments during potentially infinite iterative fu
     f(list(1, 2, f, () => 1, array));
   `
   const context = mockContext(4)
-  const promise = runInContext(code, context, { scheduler: 'preemptive', isNativeRunnable: true })
+  const promise = runInContext(code, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'native'
+  })
   return promise.then(obj => {
     const errors = parseError(context.errors)
     expect(errors).toMatch(stripIndent`
@@ -33,7 +36,10 @@ test('test increasing time limit for functions', () => {
   `
   const context = mockContext()
   const start = Date.now()
-  const promise = runInContext(code, context, { scheduler: 'preemptive', isNativeRunnable: true })
+  const promise = runInContext(code, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'native'
+  })
   return promise.then(obj => {
     const errors = parseError(context.errors)
     const timeTaken = Date.now() - start
@@ -44,7 +50,7 @@ test('test increasing time limit for functions', () => {
     const longerContext = mockContext()
     const longerPromise = runInContext(code, longerContext, {
       scheduler: 'preemptive',
-      isNativeRunnable: true
+      executionMethod: 'native'
     })
     return longerPromise.then(longerObj => {
       const longerErrors = parseError(longerContext.errors)
@@ -69,7 +75,10 @@ test('test increasing time limit for mutual recursion', () => {
   `
   const context = mockContext()
   const start = Date.now()
-  const promise = runInContext(code, context, { scheduler: 'preemptive', isNativeRunnable: true })
+  const promise = runInContext(code, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'native'
+  })
   return promise.then(obj => {
     const errors = parseError(context.errors)
     const timeTaken = Date.now() - start
@@ -80,7 +89,7 @@ test('test increasing time limit for mutual recursion', () => {
     const longerContext = mockContext()
     const longerPromise = runInContext(code, longerContext, {
       scheduler: 'preemptive',
-      isNativeRunnable: true
+      executionMethod: 'native'
     })
     return longerPromise.then(longerObj => {
       const longerErrors = parseError(longerContext.errors)
@@ -100,7 +109,10 @@ test('test increasing time limit for while loops', () => {
   `
   const context = mockContext(4)
   const start = Date.now()
-  const promise = runInContext(code, context, { scheduler: 'preemptive', isNativeRunnable: true })
+  const promise = runInContext(code, context, {
+    scheduler: 'preemptive',
+    executionMethod: 'native'
+  })
   return promise.then(obj => {
     const errors = parseError(context.errors)
     const timeTaken = Date.now() - start
@@ -110,7 +122,7 @@ test('test increasing time limit for while loops', () => {
     const longerContext = mockContext(4)
     const longerPromise = runInContext(code, longerContext, {
       scheduler: 'preemptive',
-      isNativeRunnable: true
+      executionMethod: 'native'
     })
     return longerPromise.then(longerObj => {
       const longerErrors = parseError(longerContext.errors)
diff --git a/src/utils/testing.ts b/src/utils/testing.ts
index d6fced69..b5caeb5f 100644
--- a/src/utils/testing.ts
+++ b/src/utils/testing.ts
@@ -39,7 +39,7 @@ interface TestOptions {
 function createTestContext({
   context,
   chapter = 1,
-  testBuiltins
+  testBuiltins = {}
 }: { context?: TestContext; chapter?: number; testBuiltins?: TestBuiltins } = {}): TestContext {
   if (context !== undefined) {
     return context
@@ -84,7 +84,7 @@ function testInContext(code: string, options: TestOptions): Promise<TestResult>
   const scheduler = 'preemptive'
   const interpreted = runInContext(code, interpretedTestContext, {
     scheduler,
-    isNativeRunnable: false
+    executionMethod: 'interpreter'
   }).then(result => {
     return {
       code,
@@ -100,7 +100,7 @@ function testInContext(code: string, options: TestOptions): Promise<TestResult>
   if (options.native) {
     const nativeTestContext = createTestContext(options)
     return interpreted.then(interpretedResult => {
-      return runInContext(code, nativeTestContext, { scheduler, isNativeRunnable: true }).then(
+      return runInContext(code, nativeTestContext, { scheduler, executionMethod: 'native' }).then(
         result => {
           let transpiled: string
           try {