On this page:
2.1 Constructing Javascript fragments
2.1.1 Javascript macros
js
JS
opt-js
OPT-JS
2.1.2 Javascript syntax
2.1.3 Custom Javascript syntax
define-javascript-syntax
javascript?
javascript-declaration?
javascript-statement?
javascript-expression?
2.2 Rendering Javascript and sending Javascript responses
2.2.1 Rendering Javascript in string form
javascript->string
javascript->pretty-string
render-pretty-javascript?
2.2.2 Sending HTTP responses with Javascript content
make-js-response
Version: 4.2.0.2

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:

  > (let ([message "Hello world"])
      (pretty-print (js (alert ,message))))

  #s((CallExpression Expression 0 Term 1)

     #f

     #s((VarReference Expression 0 Term 1)

        #f

        #s((Identifier Term 1) #f alert))

     (#s((StringLiteral

          Expression

          0

          Term

          1)

         #f

         "Hello world")))

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

  #s((CallExpression Expression 0 Term 1)

     #f

     #s((VarReference Expression 0 Term 1)

        #f

        #s((Identifier Term 1) #f js))

     ())

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:
  > (display (javascript->pretty-string
              (js (alert "First statement")
              (!raw "alert(\"Second sta tement\")")
              (alert "Third statement"))))

  alert("First statement");

  alert("Second sta tement");

  alert("Third statement");

  ; raw expressions are surrounded by parentheses:
  > (display (javascript->pretty-string
              (js (alert (+ 1 (!raw "2") 3)))))

  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:

  > (define-javascript-syntax (!max a b)
      (js (? (> a b) a b)))
  > (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:

  > (define-javascript-syntax !min
      (lambda (stx)
        (syntax-case stx ()
          [(_ a b) #'(js (? (< a b) a b))]))
      (lambda (stx)
        (syntax-case stx ()
          [(_ a b) #'(if (< a b) a b)])))
  > (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:

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

(make-js-response [#:code code    
  #:message message    
  #:seconds seconds    
  #:mime-type mime-type    
  #:headers headers]    
  content)  response
  code : integer = 200
  message : string = "OK"
  seconds : integer = (current-seconds)
  mime-type : (U string bytes)
   = #"text/javascript; charset=utf-8"
  headers : (alistof symbol string) = no-cache-http-headers
  content : javascript-statement

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.