-
Notifications
You must be signed in to change notification settings - Fork 12
Compiler
To run the compiler from a web page, include the script
stopify-full.bundle.js
. which exposes the following function:
stopify.stopifyLocally(url: string, copts?: CompileOpts, ropts?: RuntimeOpts): AsyncRun
The Stopify CLI compiler requires the name of the input file and the name of the output file. In addition, the compiler has several optional flags:
stopify [compile-opts] input.js output.js
To load a compiled file in the browser, the Stopify runtime provides the following function:
stopify.stopify(url: string, opts?: RuntimeOpts): AsyncRun
To use the Stopify compiler a Node library, first import the Stopify library:
const stopify = require('stopify');
This library exposes the following function:
stopify.stopify(url: string, copts?: CompileOpts): string
To load a compiled file in the browser, the Stopify runtime provides the following function:
stopify.stopify(url: string, opts?: RuntimeOpts): AsyncRun
The Stopify compiler accepts the following options:
interface CompilerOpts {
captureMethod?: "lazy" | "catch" | "retval" | "eager" | "original", // --transform from the CLI
newMethod?: "wrapper" | "direct", // --new from the CLI
getters?: boolean, // --getters from the CLI
debug?: boolean, // --debug from the CLI
eval?: boolean, // --eval from the CLI
eval2?: boolean, // --eval2 from the CLI
es?: "sane" | "es5", // --es from the CLI
jsArgs?: "simple" | "faithful" | "full", // --js-args from the CLI
}
If an option is not set, Stopify picks a default value that is documented
below. By default, Stopify is not completely faithful to the semantics of
JavaScript (certain JavaScript features are difficult to support and incur a
high runtime cost). Instead, Stopify's default values work with a number of
compilers that we've tested. By default, Stopify does not support getters,
setters, eval, builtin higher-order functions, implicit operations,
arguments
-object aliasing, and single-stepping. If you think you may need
these features, you will need to set their corresponding flags.
Stopify uses first-class continuations as a primitive to implement its
execution control features. Stopify can represent continuations in several
ways; the fastest approach depends on the application and the browser. The
valid options are "lazy"
, "catch"
, "retval"
, "eager"
, and
"original"
.
For most cases, we recommend using "lazy"
.
Stopify implements two mechanisms to support suspending execution within the dynamic extent of a constructor call.
-
"wrapper"
desugars allnew
expressions to ordinary function calls, usingObject.create
. -
"direct"
preservesnew
expressions, but instruments all functions to check if they are invoked as constructors, usingnew.target
.
The fastest approach depends on the browser. We recommend using wrapper
.
How should Stopify handle JavaScript's eval
function? By default, this flag
is false
and Stopify leaves eval
unchanged. Since Stopify typically
does not rename variables, using a stopfied program can use eval
, but the
evaluated code may lock-up the browser if it has an infinite loop.
If set to true
, Stopify rewrites calls to JavaScript's eval
function to
invoke the Stopify compiler. (Note: Stopify does not rewrite new Function
and dynamically generated <script>
tags.) This allows Stopify to control
execution in dynamically generated code. Naturally, this requires the online
compiler. However, the feature incurs considerable overhead.
The eval2
flag implements an alternative approach to supporting
JavaScript's eval
function from within Stopified code. This flag is
mutually exclusive with the eval
compiler flag; only one of the two can
be specified at compile-time.
If set to true
, Stopify supports evaluating new code in the same global
environment as the main program. This means that code executed by the
eval
function can refer to global variables and declare global variables
that escape the scope of eval
.
Stopify can suspend execution within user-written valueOf()
and
toString()
methods that JavaScript invokes implicitly.
For example, the following program is an infinite loop in JavaScript:
.. code-block:: javascript
var x = { toString: function() { while(true) { } } }; x + 1;
With the implicit operations flag is set to "es5"
, Stopify will be able to
gracefully suspend the program above. With the flag set to "sane"
, Stopify
will not be able to detect the the infinite loop. We have found that most
source language compilers do not rely on implicit operations, thus it is
usually safe to use "sane"
.
The arguments
object makes it difficult for Stopify to resume execution
after suspension. Stopify supports arguments
in full, but it also supports
two simple special cases that improve performance.
-
Use
"simple"
if the program (1) does not usearguments
to access declared formal arguments and (2) only reads additional arguments using thearguments
object. -
Use
"faithful"
if the program (1) does not usearguments
to access declared formal arguments and (2) may read or write additional arguments using thearguments
object. -
Use
"full"
for full support of JavaScript'sarguments
object.
Programs that suspend execution within getters/setters incur a lot of overhead
with Stopify. The .getters
flag has two possible values:
-
Use
true
to have Stopify instrument the program to support suspension within getters and setters. -
Use
false
if the program does not use getters and setters.
.. _debug-flag:
Set .debug
to true
to enable support for single-stepping and
breakpointing. However, note that this requires more instrumentation and slows
the program down further.