2 Javascript
The Javascript language in Mirrors allows the programatic assembly of syntactically valid Javascript. The language uses the AST structures and pretty printing libraries from Dave Herman’s javascript.plt package as its underlying representation.
Constructing Javascript fragments describes the syntax for creating blocks of Javascript and Rendering Javascript and sending Javascript responses describes how to send Javascript responses in the PLT web server.
2.1 Constructing Javascript fragments
(require (planet untyped/mirrors/javascript/syntax)) |
2.1.1 Javascript macros
Mirrors provides the following macros for creating blocks of Javascript:
(js js-stmt ) |
Builds a block of Javascript. See Javascript syntax for the syntax of js-stmt.
Examples: | ||||||||||||
| ||||||||||||
|
To prevent double-quoting errors, it is a syntax error to use the following Mirrors quote forms within a js block: xml, xml*, xml-attrs, xml-attrs*, opt-xml, opt-xml-attr, js, opt-js:
> (js (js)) |
mirrors/javascript: cannot use this identifier here |
(possible double quoting error): switch the surrounding |
quote macro to "JS" or another uppercase equivalent in: name |
You can get around this restriction using the uppercase form, JS, described below.
(JS js-stmt ) |
Like js, but permits the use of the lowercase Mirrors quote forms as js-stmts:
> (pretty-print (JS (js))) ; 'js()' function call | ||||||
|
It is a syntax error to use the following identifiers in expression position within a JS block: XML, XML*, XML-ATTRS, XML-ATTRS*, OPT-XML, OPT-XML-ATTR, JS, OPT-JS:
> (JS (JS)) |
mirrors/javascript: cannot use this identifier here |
(possible double quoting error): switch the surrounding |
quote macro to "js" or another lowercase equivalent in: name |
(opt-js boolean-expr js-stmt ) |
Syntactic shorthand for:
(if boolean-expr |
(js js-stmt ) |
(js)) |
Examples: |
> (javascript->string (opt-js #t (alert "This statement will be printed...."))) |
"alert(\"This statement will be printed....\")" |
> (javascript->string (opt-js #f (alert "...but this statement won't."))) |
"" |
(OPT-JS boolean-expr js-stmt ) |
Like opt-js, but follows the same double-quoting rules as JS.
2.1.2 Javascript syntax
The forms above use the same parenthetical Javascript syntax:
js-stmt | = | js-decl | ||
| | (custom-syntax-id js-stmt ...) | |||
| | (!begin js-stmt ...) | |||
| | (!block js-stmt ...) | |||
| | (!raw string-expr) | |||
| | (!regexp str regexp-key ...) | |||
| | (if js-expr js-stmt js-stmt) | |||
| | (do js-stmt ... js-expr) | |||
| | (while js-expr js-stmt ...) | |||
| | (for (opt-decl opt-expr opt-expr) js-stmt ...) | |||
| | (for-in (decl js-expr) js-stmt ...) | |||
| | (break) | |||
| | (break id) | |||
| | (continue) | |||
| | (continue id) | |||
| | (return) | |||
| | (return js-expr) | |||
| | (with js-expr js-stmt ...) | |||
| | (switch switch-clause ...) | |||
| | (!label id js-stmt) | |||
| | (throw js-expr) | |||
| | (try try-clause ...) | |||
| | ,expr | |||
| | ,@expr | |||
| | js-expr | |||
js-decl | = | (custom-syntax-id js-decl ...) | ||
| | (function id (id ...) js-stmt ...) | |||
| | (var js-init ...) | |||
js-init | = | id | ||
| | [id js-expr] | |||
| | ,expr | |||
| | [id ,expr] | |||
js-expr | = | (custom-syntax-id js-expr ...) | ||
| | (js-operator js-expr ...) | |||
| | (!array js-expr ...) | |||
| | (!object [property js-expr] ...) | |||
| | (!index js-expr js-expr) | |||
| | (!dot js-expr dot-expr ...) | |||
| | (!raw string-expr) | |||
| | (!all js-expr ...) | |||
| | (? js-expr js-expr js-expr) | |||
| | (new js-expr js-expr ...) | |||
| | (function (id ...) js-stmt ...) | |||
| | ,expr | |||
| | null | |||
| | this | |||
| | id | |||
| | boolean-literal | |||
| | number-literal | |||
| | string-literal | |||
| | (quote symbol-literal) | |||
js-operator | = | ... ; Javascript operator: =, +, etc | ||
custom-syntax-id | = | id ; bound by define-js-syntax | ||
regexp-key | = | #:global? boolean-literal | ||
| | #:global? ,boolean-expr | |||
| | #:ci? boolean-literal | |||
| | #:ci? ,boolean-expr | |||
dot-expr | = | id ; property-style: a.b | ||
| | (!index id expr) ; array-style: a.b[1] | |||
| | (id js-expr ...) ; method-style: a.b(1, 2) | |||
opt-decl | = | _ | ||
| | var-decl | |||
opt-expr | = | _ | ||
| | expr |
!raw forms are treated as statements or expressions depending on their context. Semicolons and parentheses are added automatically depending on the interpretation of the block:
Examples: | ||||
; raw statements are followed by semicolons: | ||||
| ||||
| ||||
; raw expressions are surrounded by parentheses: | ||||
| ||||
alert(1 + (2) + 3) |
2.1.3 Custom Javascript syntax
(define-javascript-syntax (id arg ) js-expr) |
(define-javascript-syntax id js-transformer) |
(define-javascript-syntax id js-transformer expr-transformer) |
Defines a custom syntactic form for use in js blocks.
The first form above behaves like define-syntax-rule. js-expr should be a regular js block.
Examples: | ||
| ||
> (javascript->string (js (!max 1 2))) | ||
"1 > 2 ? 1 : 2;" | ||
> (!max 1 2) | ||
eval:12:0: !max: must be used as a javascript expression | ||
in: (!max 1 2) |
The second and third forms behave like define-match-expander. js-transformer is a syntax transformer procedure used during Javascript expansion, which accepts a Javascript form as an input and returns a complete js block representing the expansion. expr-transformer is a transformer procedure that is used in regular Scheme expansion. When js-transformer is omitted, use of the syntax form outside of a Javascript block results in a syntax error.
Examples: | |||||||
| |||||||
> (javascript->string (js (!min 1 2))) | |||||||
"1 < 2 ? 1 : 2;" | |||||||
> (!min 1 2) | |||||||
1 |
(javascript? val) → boolean? |
val : any |
Returns #t if val is a Javascript declaration, statement or expression.
(javascript-declaration? val) → boolean? |
val : any |
Returns #t if val is a Javascript declaration.
(javascript-statement? val) → boolean? |
val : any |
Returns #t if val is a Javascript statement.
(javascript-expression? val) → boolean? |
val : any |
Returns #t if val is a Javascript expression.
2.2 Rendering Javascript and sending Javascript responses
2.2.1 Rendering Javascript in string form
(javascript->string val) → string? |
val : javascript-statement? |
Renders a Javascript statement as a compact string with no line breaks or indentation.
(javascript->pretty-string val) → string? |
val : javascript-statement? |
Renders a Javascript statement as a formatted string with line breaks and indentation.
render-pretty-javascript? : (parameter boolean?) |
Affects the output of javascript->string and javascript->pretty-string:
when render-pretty-javascript? is set to #t (the default value), the rendering procedures behave as documented above;
when render-pretty-javascript? is set to #f, the rendering procedures switch to an experimental renderer that writes all Javascript extremely quickly onto a single line.
Essentially, setting render-pretty-javascript? to #t gives better rendering performance at the expense of legibility. The performance gains are only noticeable when rendering large (1000+ line) blocks of Javascript.
At the time of writing the fast renderer has not been properly tested: use it with caution!
2.2.2 Sending HTTP responses with Javascript content
Takes a js statement and wraps it in an HTTP response object that can be used with the PLT web server (including procedures such as send/suspend and send/suspend/dispatch). The keyword arguments correspond to the first five arguments of make-response/full.