From c9b4860a854418c6be0cd5bde5f3cbae732f852d Mon Sep 17 00:00:00 2001 From: Robert de Forest Date: Fri, 26 Aug 2016 18:00:48 -0700 Subject: [PATCH 1/4] Rebuild docs with latest sources --- documentation/docs/browser.html | 10 +- documentation/docs/coffee-script.html | 172 ++-- documentation/docs/command.html | 8 +- documentation/docs/grammar.html | 317 +++---- documentation/docs/lexer.html | 197 ++-- documentation/docs/nodes.html | 1208 ++++++++++++++----------- documentation/docs/optparse.html | 2 +- documentation/docs/register.html | 2 +- documentation/docs/repl.html | 4 +- documentation/docs/rewriter.html | 12 +- documentation/docs/scope.html | 10 +- documentation/docs/sourcemap.html | 4 +- 12 files changed, 1094 insertions(+), 852 deletions(-) diff --git a/documentation/docs/browser.html b/documentation/docs/browser.html index b3b0dd359b..e46725063b 100644 --- a/documentation/docs/browser.html +++ b/documentation/docs/browser.html @@ -158,7 +158,7 @@

browser.coffee

CoffeeScript.run = (code, options = {}) ->
-  options.bare = on
+  options.bare      = on
   options.shiftLine = on
   Function(compile code, options)()
@@ -192,12 +192,10 @@

browser.coffee

-
if btoa? and JSON? and unescape? and encodeURIComponent?
+            
if btoa? and JSON?
   compile = (code, options = {}) ->
-    options.sourceMap = true
-    options.inline = true
-    {js, v3SourceMap} = CoffeeScript.compile code, options
-    "#{js}\n//# sourceMappingURL=data:application/json;base64,#{btoa unescape encodeURIComponent v3SourceMap}\n//# sourceURL=coffeescript"
+ options.inlineMap = true + CoffeeScript.compile code, options
diff --git a/documentation/docs/coffee-script.html b/documentation/docs/coffee-script.html index ac4bf93c24..3a6b8859b9 100644 --- a/documentation/docs/coffee-script.html +++ b/documentation/docs/coffee-script.html @@ -172,6 +172,27 @@

coffee-script.coffee

+

Function that allows for btoa in both nodejs and the browser.

+ + + +
base64encode = (src) -> switch
+  when typeof Buffer is 'function'
+    new Buffer(src).toString('base64')
+  when typeof btoa is 'function'
+    btoa(src)
+  else
+    throw new Error('Unable to base64 encode inline sourcemap.')
+ + + + +
  • +
    + +
    + +

    Function wrapper to add source file information to SyntaxErrors thrown by the lexer/parser/compiler.

    @@ -188,11 +209,11 @@

    coffee-script.coffee

  • -
  • +
  • - +

    Compile CoffeeScript code to JavaScript, using the Coffee/Jison compiler.

    If options.sourceMap is specified, then options.filename must also be specified. All @@ -207,8 +228,9 @@

    coffee-script.coffee

    exports.compile = compile = withPrettyErrors (code, options) ->
       {merge, extend} = helpers
       options = extend {}, options
    +  generateSourceMap = options.sourceMap or options.inlineMap
     
    -  if options.sourceMap
    +  if generateSourceMap
         map = new SourceMap
     
       tokens = lexer.tokenize code, options
    @@ -216,11 +238,11 @@

    coffee-script.coffee

  • -
  • +
  • - +

    Pass a list of referenced variables, so that generated variables won’t get the same name.

    @@ -228,7 +250,7 @@

    coffee-script.coffee

      options.referencedVars = (
    -    token[1] for token in tokens when token.variable
    +    token[1] for token in tokens when token[0] is 'IDENTIFIER'
       )
     
       fragments = parser.parse(tokens).compileToFragments options
    @@ -243,26 +265,26 @@ 

    coffee-script.coffee

  • -
  • +
  • - +

    Update the sourcemap with data from each fragment

    -
        if options.sourceMap
    +
        if generateSourceMap
  • -
  • +
  • - +

    Do not include empty, whitespace, or semicolon-only fragments.

    @@ -283,11 +305,11 @@

    coffee-script.coffee

  • -
  • +
  • - +

    Copy the code from each fragment into the final JavaScript.

    @@ -299,22 +321,32 @@

    coffee-script.coffee

    header = "Generated by CoffeeScript #{@VERSION}" js = "// #{header}\n#{js}" + if generateSourceMap + v3SourceMap = map.generate(options, code) + + if options.inlineMap + encoded = base64encode JSON.stringify v3SourceMap + sourceMapDataURI = "//# sourceMappingURL=data:application/json;base64,#{encoded}" + sourceURL = "//# sourceURL=#{options.filename ? 'coffeescript'}" + js = "#{js}\n#{sourceMapDataURI}\n#{sourceURL}" + if options.sourceMap - answer = {js} - answer.sourceMap = map - answer.v3SourceMap = map.generate(options, code) - answer + { + js + sourceMap: map + v3SourceMap: JSON.stringify v3SourceMap, null, 2 + } else js
  • -
  • +
  • - +

    Tokenize a string of CoffeeScript code, and return the array of tokens.

    @@ -326,11 +358,11 @@

    coffee-script.coffee

  • -
  • +
  • - +

    Parse a string of CoffeeScript code or an array of lexed tokens, and return the AST. You can then compile it by calling .compile() on the root, @@ -347,11 +379,11 @@

    coffee-script.coffee

  • -
  • +
  • - +

    Compile and execute a string of CoffeeScript (on the server), correctly setting __filename, __dirname, and relative require().

    @@ -364,11 +396,11 @@

    coffee-script.coffee

  • -
  • +
  • - +

    Set the filename.

    @@ -380,11 +412,11 @@

    coffee-script.coffee

  • -
  • +
  • - +

    Clear the module cache.

    @@ -395,11 +427,11 @@

    coffee-script.coffee

  • -
  • +
  • - +

    Assign paths for node_modules loading

    @@ -414,11 +446,11 @@

    coffee-script.coffee

  • -
  • +
  • - +

    Compile.

    @@ -433,11 +465,11 @@

    coffee-script.coffee

  • -
  • +
  • - +

    Compile and evaluate a string of CoffeeScript (in a Node.js-like environment). The CoffeeScript REPL uses this to run the input.

    @@ -467,11 +499,11 @@

    coffee-script.coffee

  • -
  • +
  • - +

    define module/require only if they chose not to specify their own

    @@ -488,11 +520,11 @@

    coffee-script.coffee

  • -
  • +
  • - +

    use the same hack node currently uses for their own REPL

    @@ -514,39 +546,43 @@

    coffee-script.coffee

  • -
  • +
  • - +

    Throw error with deprecation warning when depending upon implicit require.extensions registration

    if require.extensions
    -  for ext in @FILE_EXTENSIONS
    +  for ext in @FILE_EXTENSIONS then do (ext) ->
         require.extensions[ext] ?= ->
           throw new Error """
           Use CoffeeScript.register() or require the coffee-script/register module to require #{ext} files.
           """
     
    -exports._compileFile = (filename, sourceMap = no) ->
    +exports._compileFile = (filename, sourceMap = no, inlineMap = no) ->
       raw = fs.readFileSync filename, 'utf8'
       stripped = if raw.charCodeAt(0) is 0xFEFF then raw.substring 1 else raw
     
       try
    -    answer = compile(stripped, {filename, sourceMap, literate: helpers.isLiterate filename})
    +    answer = compile stripped, {
    +      filename, sourceMap, inlineMap
    +      sourceFiles: [filename]
    +      literate: helpers.isLiterate filename
    +    }
       catch err
  • -
  • +
  • - +

    As the filename and code of a dynamically loaded file will be different from the original file compiled with CoffeeScript.run, add that @@ -561,11 +597,11 @@

    coffee-script.coffee

  • -
  • +
  • - +

    Instantiate a Lexer for our use here.

    @@ -576,11 +612,11 @@

    coffee-script.coffee

  • -
  • +
  • - +

    The real Lexer produces a generic stream of tokens. This object provides a thin wrapper around it, compatible with the Jison API. We can then pass it @@ -608,11 +644,11 @@

    coffee-script.coffee

  • -
  • +
  • - +

    Make all the AST nodes visible to the parser.

    @@ -623,11 +659,11 @@

    coffee-script.coffee

  • -
  • +
  • - +

    Override Jison’s default error handling function.

    @@ -638,13 +674,13 @@

    coffee-script.coffee

  • -
  • +
  • - +
    -

    Disregard Jison’s message, it contains redundant line numer information. +

    Disregard Jison’s message, it contains redundant line number information. Disregard the token, we take its value directly from the lexer in case the error is caused by a generated token which might refer to its origin.

    @@ -658,7 +694,7 @@

    coffee-script.coffee

    'end of input' when errorTag in ['INDENT', 'OUTDENT'] 'indentation' - when errorTag in ['IDENTIFIER', 'NUMBER', 'STRING', 'STRING_START', 'REGEX', 'REGEX_START'] + when errorTag in ['IDENTIFIER', 'NUMBER', 'INFINITY', 'STRING', 'STRING_START', 'REGEX', 'REGEX_START'] errorTag.replace(/_START$/, '').toLowerCase() else helpers.nameWhitespaceCharacter errorText
    @@ -666,11 +702,11 @@

    coffee-script.coffee

  • -
  • +
  • - +

    The second argument has a loc property, which should have the location data for this token. Unfortunately, Jison seems to send an outdated loc @@ -684,11 +720,11 @@

    coffee-script.coffee

  • -
  • +
  • - +

    Based on http://v8.googlecode.com/svn/branches/bleeding_edge/src/messages.js Modified to handle sourceMap

    @@ -716,11 +752,11 @@

    coffee-script.coffee

  • -
  • +
  • - +

    Check for a sourceMap position

    @@ -761,11 +797,11 @@

    coffee-script.coffee

  • -
  • +
  • - +

    Map of filenames -> sourceMap object.

    @@ -776,11 +812,11 @@

    coffee-script.coffee

  • -
  • +
  • - +

    Generates the source map for a coffee file and stores it in the local cache variable.

    @@ -795,11 +831,11 @@

    coffee-script.coffee

  • -
  • +
  • - +

    Based on michaelficarra/CoffeeScriptRedux NodeJS / V8 have no support for transforming positions in stack traces using diff --git a/documentation/docs/command.html b/documentation/docs/command.html index 374b74c717..acf8df40df 100644 --- a/documentation/docs/command.html +++ b/documentation/docs/command.html @@ -206,6 +206,7 @@

    command.coffee

    ['-i', '--interactive', 'run an interactive CoffeeScript REPL'] ['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling'] ['-m', '--map', 'generate source map and save as .js.map files'] + ['-M', '--inline-map', 'generate source map and include it directly in output'] ['-n', '--nodes', 'print out the parse tree that the parser produces'] [ '--nodejs [ARGS]', 'pass options directly to the "node" binary'] [ '--no-header', 'suppress the "Generated by" header'] @@ -447,12 +448,12 @@

    command.coffee

    compileStdio = ->
    -  code = ''
    +  buffers = []
       stdin = process.openStdin()
       stdin.on 'data', (buffer) ->
    -    code += buffer.toString() if buffer
    +    buffers.push buffer if buffer
       stdin.on 'end', ->
    -    compileScript null, code
    + compileScript null, Buffer.concat(buffers).toString()
  • @@ -796,6 +797,7 @@

    command.coffee

    bare: opts.bare header: opts.compile and not opts['no-header'] sourceMap: opts.map + inlineMap: opts['inline-map'] } if filename if base diff --git a/documentation/docs/grammar.html b/documentation/docs/grammar.html index 3a1d182591..97abb59e22 100644 --- a/documentation/docs/grammar.html +++ b/documentation/docs/grammar.html @@ -348,13 +348,16 @@

    Grammatical Rules

    -

    Block and statements, which make up a line in a body.

    +

    Block and statements, which make up a line in a body. YieldReturn is a +statement, but not included in Statement because that results in an ambiguous +grammar.

      Line: [
         o 'Expression'
         o 'Statement'
    +    o 'YieldReturn'
       ]
    @@ -373,7 +376,7 @@

    Grammatical Rules

      Statement: [
         o 'Return'
         o 'Comment'
    -    o 'STATEMENT',                              -> new Literal $1
    +    o 'STATEMENT',                              -> new StatementLiteral $1
       ]
    @@ -386,7 +389,7 @@

    Grammatical Rules

    All the different types of expressions in our language. The basic unit of -CoffeeScript is the Expression — everything that can be an expression +CoffeeScript is the Expression – everything that can be an expression is one. Blocks serve as the building blocks of many other rules, making them somewhat circular.

    @@ -405,6 +408,13 @@

    Grammatical Rules

    o 'Switch' o 'Class' o 'Throw' + o 'Yield' + ] + + Yield: [ + o 'YIELD', -> new Op $1, new Value new Literal '' + o 'YIELD Expression', -> new Op $1, $2 + o 'YIELD FROM Expression', -> new Op $1.concat($2), $3 ] @@ -425,6 +435,14 @@

    Grammatical Rules

      Block: [
         o 'INDENT OUTDENT',                         -> new Block
         o 'INDENT Body OUTDENT',                    -> $2
    +  ]
    +
    +  Identifier: [
    +    o 'IDENTIFIER',                             -> new IdentifierLiteral $1
    +  ]
    +
    +  Property: [
    +    o 'PROPERTY',                               -> new PropertyName $1
       ]
    @@ -436,51 +454,34 @@

    Grammatical Rules

    -

    A literal identifier, a variable name or property.

    - - - -
      Identifier: [
    -    o 'IDENTIFIER',                             -> new Literal $1
    -  ]
    - - - - -
  • -
    - -
    - -

    Alphanumerics are separated from the other Literal matchers because they can also serve as keys in object literals.

      AlphaNumeric: [
    -    o 'NUMBER',                                 -> new Literal $1
    +    o 'NUMBER',                                 -> new NumberLiteral $1
         o 'String'
       ]
     
       String: [
    -    o 'STRING',                                 -> new Literal $1
    -    o 'STRING_START Body STRING_END',           -> new Parens $2
    +    o 'STRING',                                 -> new StringLiteral $1
    +    o 'STRING_START Body STRING_END',           -> new StringWithInterpolations $2
       ]
     
       Regex: [
    -    o 'REGEX',                                  -> new Literal $1
    -    o 'REGEX_START Invocation REGEX_END',       -> $2
    +    o 'REGEX',                                  -> new RegexLiteral $1
    +    o 'REGEX_START Invocation REGEX_END',       -> new RegexWithInterpolations $2.args
       ]
  • -
  • +
  • - +

    All of our immediate values. Generally these can be passed straight through and printed to JavaScript.

    @@ -489,22 +490,23 @@

    Grammatical Rules

      Literal: [
         o 'AlphaNumeric'
    -    o 'JS',                                     -> new Literal $1
    +    o 'JS',                                     -> new PassthroughLiteral $1
         o 'Regex'
    -    o 'DEBUGGER',                               -> new Literal $1
    -    o 'UNDEFINED',                              -> new Undefined
    -    o 'NULL',                                   -> new Null
    -    o 'BOOL',                                   -> new Bool $1
    +    o 'UNDEFINED',                              -> new UndefinedLiteral
    +    o 'NULL',                                   -> new NullLiteral
    +    o 'BOOL',                                   -> new BooleanLiteral $1
    +    o 'INFINITY',                               -> new InfinityLiteral $1
    +    o 'NAN',                                    -> new NaNLiteral
       ]
  • -
  • +
  • - +

    Assignment of a variable, property, or index to a value.

    @@ -519,11 +521,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    Assignment when it happens within an object literal. The difference from the ordinary Assign is that these allow numbers and strings as keys.

    @@ -547,6 +549,7 @@

    Grammatical Rules

    SimpleObjAssignable: [ o 'Identifier' + o 'Property' o 'ThisProperty' ] @@ -558,11 +561,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    A return statement from a function body.

    @@ -571,16 +574,21 @@

    Grammatical Rules

      Return: [
         o 'RETURN Expression',                      -> new Return $2
         o 'RETURN',                                 -> new Return
    +  ]
    +
    +  YieldReturn: [
    +    o 'YIELD RETURN Expression',                -> new YieldReturn $3
    +    o 'YIELD RETURN',                           -> new YieldReturn
       ]
  • -
  • +
  • - +

    A block comment.

    @@ -593,11 +601,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    The Code node is the function literal. It’s defined by an indented block of Block preceded by a function arrow, with an optional parameter @@ -613,11 +621,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    CoffeeScript has two different symbols for functions. -> is for ordinary functions, and => is for functions bound to the current value of this.

    @@ -632,11 +640,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    An optional, trailing comma.

    @@ -650,11 +658,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    The list of parameters that a function accepts can be of any length.

    @@ -671,11 +679,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    A single parameter in a function definition can be ordinary, or a splat that hoovers up the remaining arguments.

    @@ -692,11 +700,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    Function Parameters

    @@ -712,11 +720,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    A splat that occurs outside of a parameter list.

    @@ -729,11 +737,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    Variables and properties that can be assigned to.

    @@ -749,11 +757,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    Everything that can be assigned to.

    @@ -768,13 +776,13 @@

    Grammatical Rules

  • -
  • +
  • - +
    -

    The types of things that can be treated as values — assigned to, invoked +

    The types of things that can be treated as values – assigned to, invoked as functions, indexed into, named as a class, etc.

    @@ -790,11 +798,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    The general group of accessors into an object, by property, by prototype or by array index or slice.

    @@ -802,22 +810,22 @@

    Grammatical Rules

      Accessor: [
    -    o '.  Identifier',                          -> new Access $2
    -    o '?. Identifier',                          -> new Access $2, 'soak'
    -    o ':: Identifier',                          -> [LOC(1)(new Access new Literal('prototype')), LOC(2)(new Access $2)]
    -    o '?:: Identifier',                         -> [LOC(1)(new Access new Literal('prototype'), 'soak'), LOC(2)(new Access $2)]
    -    o '::',                                     -> new Access new Literal 'prototype'
    +    o '.  Property',                            -> new Access $2
    +    o '?. Property',                            -> new Access $2, 'soak'
    +    o ':: Property',                            -> [LOC(1)(new Access new PropertyName('prototype')), LOC(2)(new Access $2)]
    +    o '?:: Property',                           -> [LOC(1)(new Access new PropertyName('prototype'), 'soak'), LOC(2)(new Access $2)]
    +    o '::',                                     -> new Access new PropertyName 'prototype'
         o 'Index'
       ]
  • -
  • +
  • - +

    Indexing into an object or array using bracket notation.

    @@ -836,11 +844,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    In CoffeeScript, an object literal is simply a list of assignments.

    @@ -853,11 +861,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    Assignment of properties within an object literal can be separated by comma, as in JavaScript, or simply by newline.

    @@ -875,11 +883,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    Class definitions have optional bodies of prototype property assignments, and optional references to the superclass.

    @@ -900,11 +908,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    Ordinary function invocation, or a chained series of calls.

    @@ -913,18 +921,22 @@

    Grammatical Rules

      Invocation: [
         o 'Value OptFuncExist Arguments',           -> new Call $1, $3, $2
         o 'Invocation OptFuncExist Arguments',      -> new Call $1, $3, $2
    -    o 'SUPER',                                  -> new Call 'super', [new Splat new Literal 'arguments']
    -    o 'SUPER Arguments',                        -> new Call 'super', $2
    +    o 'Super'
    +  ]
    +
    +  Super: [
    +    o 'SUPER',                                  -> new SuperCall
    +    o 'SUPER Arguments',                        -> new SuperCall $2
       ]
  • -
  • +
  • - +

    An optional existence check on a function.

    @@ -938,11 +950,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    The list of arguments to a function call.

    @@ -956,46 +968,46 @@

    Grammatical Rules

  • -
  • +
  • - +

    A reference to the this current object.

      This: [
    -    o 'THIS',                                   -> new Value new Literal 'this'
    -    o '@',                                      -> new Value new Literal 'this'
    +    o 'THIS',                                   -> new Value new ThisLiteral
    +    o '@',                                      -> new Value new ThisLiteral
       ]
  • -
  • +
  • - +

    A reference to a property on this.

      ThisProperty: [
    -    o '@ Identifier',                           -> new Value LOC(1)(new Literal('this')), [LOC(2)(new Access($2))], 'this'
    +    o '@ Property',                             -> new Value LOC(1)(new ThisLiteral), [LOC(2)(new Access($2))], 'this'
       ]
  • -
  • +
  • - +

    The array literal.

    @@ -1009,11 +1021,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    Inclusive and exclusive range dots.

    @@ -1027,11 +1039,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    The CoffeeScript range literal.

    @@ -1044,11 +1056,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    Array slice literals.

    @@ -1064,11 +1076,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    The ArgList is both the list of objects passed into a function call, as well as the contents of an array literal @@ -1087,11 +1099,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    Valid arguments are Blocks or Splats.

    @@ -1106,11 +1118,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    Just simple, comma-separated, required arguments (no fancy syntax). We need this to be separate from the ArgList for use in Switch blocks, where @@ -1126,11 +1138,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    The variants of try/catch/finally exception handling blocks.

    @@ -1146,11 +1158,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    A catch clause names its error and runs a block of code.

    @@ -1165,11 +1177,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    Throw an exception object.

    @@ -1182,11 +1194,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    Parenthetical expressions. Note that the Parenthetical is a Value, not an Expression, so if you need to use an expression in a place @@ -1203,11 +1215,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    The condition portion of a while loop.

    @@ -1223,11 +1235,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    The while loop can either be normal, with a block of expressions to execute, or postfix, with a single expression. There is no do..while.

    @@ -1242,18 +1254,18 @@

    Grammatical Rules

    ] Loop: [ - o 'LOOP Block', -> new While(LOC(1) new Literal 'true').addBody $2 - o 'LOOP Expression', -> new While(LOC(1) new Literal 'true').addBody LOC(2) Block.wrap [$2] + o 'LOOP Block', -> new While(LOC(1) new BooleanLiteral 'true').addBody $2 + o 'LOOP Expression', -> new While(LOC(1) new BooleanLiteral 'true').addBody LOC(2) Block.wrap [$2] ]
  • -
  • +
  • - +

    Array, object, and range comprehensions, at the most generic level. Comprehensions can either be normal, with a block of expressions to execute, @@ -1281,11 +1293,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    An array of all accepted values for a variable inside the loop. This enables support for pattern matching.

    @@ -1302,11 +1314,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    An array or range comprehension has variables for the current element and (optional) reference to the current index. Or, key, value, in the case @@ -1322,11 +1334,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    The source of a comprehension is an array or object with an optional guard clause. If it’s an array comprehension, you can also choose to step through @@ -1359,11 +1371,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    An individual When clause, with action.

    @@ -1377,11 +1389,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    The most basic form of if is a condition and an action. The following if-related rules are broken up along these lines in order to avoid @@ -1397,11 +1409,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    The full complement of if expressions, including postfix one-liner if and unless.

    @@ -1418,11 +1430,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    Arithmetic and logical operators, working on one or more operands. Here they are grouped by order of precedence. The actual precedence rules @@ -1438,9 +1450,6 @@

    Grammatical Rules

    o 'UNARY_MATH Expression', -> new Op $1 , $2 o '- Expression', (-> new Op '-', $2), prec: 'UNARY_MATH' o '+ Expression', (-> new Op '+', $2), prec: 'UNARY_MATH' - o 'YIELD Statement', -> new Op $1 , $2 - o 'YIELD Expression', -> new Op $1 , $2 - o 'YIELD FROM Expression', -> new Op $1.concat($2) , $3 o '-- SimpleAssignable', -> new Op '--', $2 o '++ SimpleAssignable', -> new Op '++', $2 @@ -1450,11 +1459,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    The existential operator.

    @@ -1488,11 +1497,11 @@

    Grammatical Rules

  • -
  • +
  • - +

    Precedence

    @@ -1501,11 +1510,11 @@

    Precedence

  • -
  • +
  • - +
    @@ -1513,11 +1522,11 @@

    Precedence

  • -
  • +
  • - +

    Operators at the top of this list have higher precedence than the ones lower down. Following these rules is what makes 2 + 3 * 4 parse as:

    @@ -1552,11 +1561,11 @@

    Precedence

  • -
  • +
  • - +

    Wrapping Up

    @@ -1565,11 +1574,11 @@

    Wrapping Up

  • -
  • +
  • - +
    @@ -1577,11 +1586,11 @@

    Wrapping Up

  • -
  • +
  • - +

    Finally, now that we have our grammar and our operators, we can create our Jison.Parser. We do this by processing all of our rules, recording all @@ -1601,11 +1610,11 @@

    Wrapping Up

  • -
  • +
  • - +

    Initialize the Parser with our list of terminal tokens, our grammar rules, and the name of the root. Reverse the operators because Jison orders diff --git a/documentation/docs/lexer.html b/documentation/docs/lexer.html index b7bb584599..cf05e66eb4 100644 --- a/documentation/docs/lexer.html +++ b/documentation/docs/lexer.html @@ -370,12 +370,15 @@

    Tokenizers

    @token 'FROM', id return id.length [..., prev] = @tokens - forcedIdentifier = colon or prev? and - (prev[0] in ['.', '?.', '::', '?::'] or - not prev.spaced and prev[0] is '@') - tag = 'IDENTIFIER' + tag = + if colon or prev? and + (prev[0] in ['.', '?.', '::', '?::'] or + not prev.spaced and prev[0] is '@') + 'PROPERTY' + else + 'IDENTIFIER' - if not forcedIdentifier and (id in JS_KEYWORDS or id in COFFEE_KEYWORDS) + if tag is 'IDENTIFIER' and (id in JS_KEYWORDS or id in COFFEE_KEYWORDS) tag = id.toUpperCase() if tag is 'WHEN' and @tag() in LINE_BREAK tag = 'LEADING_WHEN' @@ -395,15 +398,10 @@

    Tokenizers

    poppedToken = @tokens.pop() id = '!' + id - if id in JS_FORBIDDEN - if forcedIdentifier - tag = 'IDENTIFIER' - id = new String id - id.reserved = yes - else if id in RESERVED - @error "reserved word '#{id}'", length: id.length + if tag is 'IDENTIFIER' and id in RESERVED + @error "reserved word '#{id}'", length: id.length - unless forcedIdentifier + unless tag is 'PROPERTY' if id in COFFEE_ALIASES alias = id id = COFFEE_ALIAS_MAP[id] @@ -412,12 +410,12 @@

    Tokenizers

    when '==', '!=' then 'COMPARE' when '&&', '||' then 'LOGIC' when 'true', 'false' then 'BOOL' - when 'break', 'continue' then 'STATEMENT' + when 'break', 'continue', \ + 'debugger' then 'STATEMENT' else tag tagToken = @token tag, id, 0, idLength tagToken.origin = [tag, alias, tagToken[2]] if alias - tagToken.variable = not forcedIdentifier if poppedToken [tagToken[2].first_line, tagToken[2].first_column] = [poppedToken[2].first_line, poppedToken[2].first_column] @@ -455,10 +453,15 @@

    Tokenizers

    else if /^0\d+/.test number @error "octal literal '#{number}' must be prefixed with '0o'", length: lexedLength if octalLiteral = /^0o([0-7]+)/.exec number - number = '0x' + parseInt(octalLiteral[1], 8).toString 16 - if binaryLiteral = /^0b([01]+)/.exec number - number = '0x' + parseInt(binaryLiteral[1], 2).toString 16 - @token 'NUMBER', number, 0, lexedLength + numberValue = parseInt(octalLiteral[1], 8) + number = "0x#{numberValue.toString 16}" + else if binaryLiteral = /^0b([01]+)/.exec number + numberValue = parseInt(binaryLiteral[1], 2) + number = "0x#{numberValue.toString 16}" + else + numberValue = parseFloat(number) + tag = if numberValue is Infinity then 'INFINITY' else 'NUMBER' + @token tag, number, 0, lexedLength lexedLength
  • @@ -819,14 +822,20 @@

    Tokenizers

    value = @chunk.charAt 0 tag = value [..., prev] = @tokens - if value is '=' and prev - if not prev[1].reserved and prev[1] in JS_FORBIDDEN - prev = prev.origin if prev.origin - @error "reserved word '#{prev[1]}' can't be assigned", prev[2] - if prev[1] in ['||', '&&'] + + if prev and value in ['=', COMPOUND_ASSIGN...] + skipToken = false + if value is '=' and prev[1] in ['||', '&&'] and not prev.spaced prev[0] = 'COMPOUND_ASSIGN' prev[1] += '=' - return value.length + prev = @tokens[@tokens.length - 2] + skipToken = true + if prev and prev[0] isnt 'PROPERTY' + origin = prev.origin ? prev + message = isUnassignable prev[1], origin[1] + @error message, origin[2] if message + return value.length if skipToken + if value is ';' @seenFor = no tag = 'TERMINATOR' @@ -1440,7 +1449,7 @@

    Helpers

      unfinished: ->
         LINE_CONTINUER.test(@chunk) or
    -    @tag() in ['\\', '.', '?.', '?::', 'UNARY', 'MATH', 'UNARY_MATH', '+', '-', 'YIELD',
    +    @tag() in ['\\', '.', '?.', '?::', 'UNARY', 'MATH', 'UNARY_MATH', '+', '-',
                    '**', 'SHIFT', 'RELATION', 'COMPARE', 'LOGIC', 'THROW', 'EXTENDS']
     
       formatString: (str) ->
    @@ -1556,7 +1565,7 @@ 

    Helpers

    -

    Constants

    +

    Helper functions

    @@ -1572,6 +1581,19 @@

    Constants

    +
    +isUnassignable = (name, displayName = name) -> switch
    +  when name in [JS_KEYWORDS..., COFFEE_KEYWORDS...]
    +    "keyword '#{displayName}' can't be assigned"
    +  when name in STRICT_PROSCRIBED
    +    "'#{displayName}' can't be assigned"
    +  when name in RESERVED
    +    "reserved word '#{displayName}' can't be assigned"
    +  else
    +    false
    +
    +exports.isUnassignable = isUnassignable
    + @@ -1581,6 +1603,31 @@

    Constants

    +

    Constants

    + + + + + + +
  • +
    + +
    + +
    + +
    + +
  • + + +
  • +
    + +
    + +

    Keywords that CoffeeScript shares in common with JavaScript.

    @@ -1596,17 +1643,20 @@

    Constants

  • -
  • +
  • - +

    CoffeeScript-only keywords.

    -
    COFFEE_KEYWORDS = ['undefined', 'then', 'unless', 'until', 'loop', 'of', 'by', 'when']
    +            
    COFFEE_KEYWORDS = [
    +  'undefined', 'Infinity', 'NaN'
    +  'then', 'unless', 'until', 'loop', 'of', 'by', 'when'
    +]
     
     COFFEE_ALIAS_MAP =
       and  : '&&'
    @@ -1625,11 +1675,11 @@ 

    Constants

  • -
  • +
  • - +

    The list of keywords that are reserved by JavaScript, but not used, or are used by CoffeeScript internally. We throw an error when these are encountered, @@ -1643,35 +1693,32 @@

    Constants

    'protected', 'public', 'static' ] -STRICT_PROSCRIBED = ['arguments', 'eval', 'yield*']
    +STRICT_PROSCRIBED = ['arguments', 'eval']
  • -
  • +
  • - +

    The superset of both JavaScript keywords and reserved words, none of which may be used as identifiers or properties.

    -
    JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED).concat(STRICT_PROSCRIBED)
    -
    -exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS).concat(STRICT_PROSCRIBED)
    -exports.STRICT_PROSCRIBED = STRICT_PROSCRIBED
    +
    exports.JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED).concat(STRICT_PROSCRIBED)
  • -
  • +
  • - +

    The character code of the nasty Microsoft madness otherwise known as the BOM.

    @@ -1682,11 +1729,11 @@

    Constants

  • -
  • +
  • - +

    Token matching regexes.

    @@ -1728,11 +1775,11 @@

    Constants

  • -
  • +
  • - +

    String-matching-regexes.

    @@ -1755,11 +1802,11 @@

    Constants

  • -
  • +
  • - +

    Regex-matching-regexes.

    @@ -1793,11 +1840,11 @@

    Constants

  • -
  • +
  • - +

    Other regexes.

    @@ -1824,11 +1871,11 @@

    Constants

  • -
  • +
  • - +

    Compound assignment tokens.

    @@ -1842,11 +1889,11 @@

    Constants

  • -
  • +
  • - +

    Unary tokens.

    @@ -1859,11 +1906,11 @@

    Constants

  • -
  • +
  • - +

    Logical tokens.

    @@ -1874,11 +1921,11 @@

    Constants

  • -
  • +
  • - +

    Bit-shifting tokens.

    @@ -1889,11 +1936,11 @@

    Constants

  • -
  • +
  • - +

    Comparison tokens.

    @@ -1904,11 +1951,11 @@

    Constants

  • -
  • +
  • - +

    Mathematical tokens.

    @@ -1919,11 +1966,11 @@

    Constants

  • -
  • +
  • - +

    Relational tokens that are negatable with not prefix.

    @@ -1934,11 +1981,11 @@

    Constants

  • -
  • +
  • - +

    Boolean tokens.

    @@ -1949,11 +1996,11 @@

    Constants

  • -
  • +
  • - +

    Tokens which could legitimately be invoked or indexed. An opening parentheses or bracket following these tokens will be recorded as the start @@ -1961,20 +2008,20 @@

    Constants

    -
    CALLABLE  = ['IDENTIFIER', ')', ']', '?', '@', 'THIS', 'SUPER']
    +            
    CALLABLE  = ['IDENTIFIER', 'PROPERTY', ')', ']', '?', '@', 'THIS', 'SUPER']
     INDEXABLE = CALLABLE.concat [
    -  'NUMBER', 'STRING', 'STRING_END', 'REGEX', 'REGEX_END'
    +  'NUMBER', 'INFINITY', 'NAN', 'STRING', 'STRING_END', 'REGEX', 'REGEX_END'
       'BOOL', 'NULL', 'UNDEFINED', '}', '::'
     ]
  • -
  • +
  • - +

    Tokens which a regular expression will never immediately follow (except spaced CALLABLEs in some cases), but which a division operator can.

    @@ -1987,11 +2034,11 @@

    Constants

  • -
  • +
  • - +

    Tokens that, when immediately preceding a WHEN, indicate that the WHEN occurs at the start of a line. We disambiguate these from trailing whens to @@ -2004,11 +2051,11 @@

    Constants

  • -
  • +
  • - +

    Additional indent in front of these is ignored.

    diff --git a/documentation/docs/nodes.html b/documentation/docs/nodes.html index 475684f269..dbaa4c71ee 100644 --- a/documentation/docs/nodes.html +++ b/documentation/docs/nodes.html @@ -126,7 +126,7 @@

    nodes.coffee

    Error.stackTraceLimit = Infinity {Scope} = require './scope' -{RESERVED, STRICT_PROSCRIBED} = require './lexer'
    +{isUnassignable, JS_FORBIDDEN} = require './lexer'
  • @@ -320,13 +320,13 @@

    Base

    func = new Code [], Block.wrap [this] args = [] if (argumentsNode = @contains isLiteralArguments) or @contains isLiteralThis - args = [new Literal 'this'] + args = [new ThisLiteral] if argumentsNode meth = 'apply' - args.push new Literal 'arguments' + args.push new IdentifierLiteral 'arguments' else meth = 'call' - func = new Value func, [new Access new Literal meth] + func = new Value func, [new Access new PropertyName meth] parts = (new Call func, args).compileNode o if func.isGenerator or func.base?.isGenerator parts.unshift @makeCode "(yield* " @@ -354,7 +354,7 @@

    Base

      cache: (o, level, isComplex) ->
         complex = if isComplex? then isComplex this else @isComplex()
         if complex
    -      ref = new Literal o.scope.freeVariable 'ref'
    +      ref = new IdentifierLiteral o.scope.freeVariable 'ref'
           sub = new Assign ref, this
           if level then [sub.compileToFragments(o, level), [@makeCode(ref.value)]] else [sub, ref]
         else
    @@ -502,6 +502,7 @@ 

    Base

    isComplex : YES isChainable : NO isAssignable : NO + isNumber : NO unwrap : THIS unfoldSoak : NO
    @@ -609,7 +610,7 @@

    Block

    The block is the list of expressions that forms the body of an -indented block of code — the implementation of a function, a clause in an +indented block of code – the implementation of a function, a clause in an if, switch, or try, and so on…

    @@ -950,8 +951,8 @@

    Literal

    -

    Literals are static values that can be passed through directly into -JavaScript without translation, such as: strings, numbers, +

    Literal is a base class for static values that can be passed through +directly into JavaScript without translation, such as: strings, numbers, true, false, null

    @@ -959,53 +960,75 @@

    Literal

    exports.Literal = class Literal extends Base
       constructor: (@value) ->
     
    -  makeReturn: ->
    -    if @isStatement() then this else super
    -
    -  isAssignable: ->
    -    IDENTIFIER.test @value
    -
    -  isStatement: ->
    -    @value in ['break', 'continue', 'debugger']
    -
       isComplex: NO
     
       assigns: (name) ->
         name is @value
     
    +  compileNode: (o) ->
    +    [@makeCode @value]
    +
    +  toString: ->
    +    " #{if @isStatement() then super else @constructor.name}: #{@value}"
    +
    +exports.NumberLiteral = class NumberLiteral extends Literal
    +
    +exports.InfinityLiteral = class InfinityLiteral extends NumberLiteral
    +  compileNode: ->
    +    [@makeCode '2e308']
    +
    +exports.NaNLiteral = class NaNLiteral extends NumberLiteral
    +  constructor: ->
    +    super 'NaN'
    +
    +  compileNode: (o) ->
    +    code = [@makeCode '0/0']
    +    if o.level >= LEVEL_OP then @wrapInBraces code else code
    +
    +exports.StringLiteral = class StringLiteral extends Literal
    +
    +exports.RegexLiteral = class RegexLiteral extends Literal
    +
    +exports.PassthroughLiteral = class PassthroughLiteral extends Literal
    +
    +exports.IdentifierLiteral = class IdentifierLiteral extends Literal
    +  isAssignable: YES
    +
    +exports.PropertyName = class PropertyName extends Literal
    +  isAssignable: YES
    +
    +exports.StatementLiteral = class StatementLiteral extends Literal
    +  isStatement: YES
    +
    +  makeReturn: THIS
    +
       jumps: (o) ->
         return this if @value is 'break' and not (o?.loop or o?.block)
         return this if @value is 'continue' and not o?.loop
     
       compileNode: (o) ->
    -    code = if @value is 'this'
    -      if o.scope.method?.bound then o.scope.method.context else @value
    -    else if @value.reserved
    -      "\"#{@value}\""
    -    else
    -      @value
    -    answer = if @isStatement() then "#{@tab}#{code};" else code
    -    [@makeCode answer]
    +    [@makeCode "#{@tab}#{@value};"]
     
    -  toString: ->
    -    ' "' + @value + '"'
    +exports.ThisLiteral = class ThisLiteral extends Literal
    +  constructor: ->
    +    super 'this'
    +
    +  compileNode: (o) ->
    +    code = if o.scope.method?.bound then o.scope.method.context else @value
    +    [@makeCode code]
    +
    +exports.UndefinedLiteral = class UndefinedLiteral extends Literal
    +  constructor: ->
    +    super 'undefined'
     
    -class exports.Undefined extends Base
    -  isAssignable: NO
    -  isComplex: NO
       compileNode: (o) ->
         [@makeCode if o.level >= LEVEL_ACCESS then '(void 0)' else 'void 0']
     
    -class exports.Null extends Base
    -  isAssignable: NO
    -  isComplex: NO
    -  compileNode: -> [@makeCode "null"]
    +exports.NullLiteral = class NullLiteral extends Literal
    +  constructor: ->
    +    super 'null'
     
    -class exports.Bool extends Base
    -  isAssignable: NO
    -  isComplex: NO
    -  compileNode: -> [@makeCode @val]
    -  constructor: (@val) ->
    +exports.BooleanLiteral = class BooleanLiteral extends Literal @@ -1029,7 +1052,7 @@

    Return

    -

    A return is a pureStatement — wrapping it in a closure wouldn’t +

    A return is a pureStatement – wrapping it in a closure wouldn’t make sense.

    @@ -1048,8 +1071,7 @@

    Return

    if expr and expr not instanceof Return then expr.compileToFragments o, level else super o, level compileNode: (o) -> - answer = [] - exprIsYieldReturn = @expression?.isYieldReturn?() + answer = [] @@ -1064,11 +1086,10 @@

    Return

    -
        unless exprIsYieldReturn
    -      answer.push @makeCode @tab + "return#{if @expression then " " else ""}"
    +            
        answer.push @makeCode @tab + "return#{if @expression then " " else ""}"
         if @expression
           answer = answer.concat @expression.compileToFragments o, LEVEL_PAREN
    -    answer.push @makeCode ";" unless exprIsYieldReturn
    +    answer.push @makeCode ";"
         return answer
    @@ -1080,10 +1101,17 @@

    Return

    -

    Value

    +

    yield return works exactly like return, except that it turns the function +into a generator.

    +
    exports.YieldReturn = class YieldReturn extends Return
    +  compileNode: (o) ->
    +    unless o.scope.parent?
    +      @error 'yield can only occur inside functions'
    +    super
    + @@ -1093,6 +1121,19 @@

    Value

    +

    Value

    + +
    + + + + +
  • +
    + +
    + +

    A value, variable or literal or parenthesized, indexed or dotted into, or vanilla.

    @@ -1111,11 +1152,11 @@

    Value

  • -
  • +
  • - +

    Add a property (or properties ) Access to the list.

    @@ -1134,11 +1175,11 @@

    Value

  • -
  • +
  • - +

    Some boolean checks for the benefit of other nodes.

    @@ -1148,16 +1189,20 @@

    Value

    isRange : -> @bareLiteral(Range) isComplex : -> @hasProperties() or @base.isComplex() isAssignable : -> @hasProperties() or @base.isAssignable() - isSimpleNumber : -> @bareLiteral(Literal) and SIMPLENUM.test @base.value - isString : -> @bareLiteral(Literal) and IS_STRING.test @base.value - isRegex : -> @bareLiteral(Literal) and IS_REGEX.test @base.value + isNumber : -> @bareLiteral(NumberLiteral) + isString : -> @bareLiteral(StringLiteral) + isRegex : -> @bareLiteral(RegexLiteral) + isUndefined : -> @bareLiteral(UndefinedLiteral) + isNull : -> @bareLiteral(NullLiteral) + isBoolean : -> @bareLiteral(BooleanLiteral) isAtomic : -> for node in @properties.concat @base return no if node.soak or node instanceof Call yes - isNotCallable : -> @isSimpleNumber() or @isString() or @isRegex() or - @isArray() or @isRange() or @isSplice() or @isObject() + isNotCallable : -> @isNumber() or @isString() or @isRegex() or + @isArray() or @isRange() or @isSplice() or @isObject() or + @isUndefined() or @isNull() or @isBoolean() isStatement : (o) -> not @properties.length and @base.isStatement o assigns : (name) -> not @properties.length and @base.assigns name @@ -1178,11 +1223,11 @@

    Value

  • -
  • +
  • - +

    The value can be unwrapped as its inner node, if there are no attached properties.

    @@ -1195,11 +1240,11 @@

    Value

  • -
  • +
  • - +

    A reference has base part (this value) and name part. We cache them separately for compiling complex expressions. @@ -1213,11 +1258,11 @@

    Value

    return [this, this] # `a` `a.b` base = new Value @base, @properties[...-1] if base.isComplex() # `a().b` - bref = new Literal o.scope.freeVariable 'base' + bref = new IdentifierLiteral o.scope.freeVariable 'base' base = new Value new Parens new Assign bref, base return [base, bref] unless name # `a()` if name.isComplex() # `a[b()]` - nref = new Literal o.scope.freeVariable 'name' + nref = new IdentifierLiteral o.scope.freeVariable 'name' name = new Index new Assign nref, name.index nref = new Index nref [base.add(name), new Value(bref or base.base, [nref or name])]
    @@ -1225,11 +1270,11 @@

    Value

  • -
  • +
  • - +

    We compile a value to JavaScript by compiling and joining each property. Things get much more interesting if the chain of properties has soak @@ -1242,7 +1287,7 @@

    Value

    @base.front = @front props = @properties fragments = @base.compileToFragments o, (if props.length then LEVEL_ACCESS else null) - if (@base instanceof Parens or props.length) and SIMPLENUM.test fragmentsToText fragments + if props.length and SIMPLENUM.test fragmentsToText fragments fragments.push @makeCode '.' for prop in props fragments.push (prop.compileToFragments o)... @@ -1251,11 +1296,11 @@

    Value

  • -
  • +
  • - +

    Unfold a soak into an If: a?.b -> a.b if a?

    @@ -1271,7 +1316,7 @@

    Value

    fst = new Value @base, @properties[...i] snd = new Value @base, @properties[i..] if fst.isComplex() - ref = new Literal o.scope.freeVariable 'ref' + ref = new IdentifierLiteral o.scope.freeVariable 'ref' fst = new Parens new Assign ref, fst snd.base = ref return new If new Existence(fst), snd, soak: on @@ -1280,11 +1325,11 @@

    Value

  • -
  • +
  • - +

    Comment

    @@ -1293,11 +1338,11 @@

    Comment

  • -
  • +
  • - +

    CoffeeScript passes through block comments as JavaScript block comments at the same position.

    @@ -1319,11 +1364,11 @@

    Comment

  • -
  • +
  • - +

    Call

    @@ -1332,35 +1377,32 @@

    Call

  • -
  • +
  • - +
    -

    Node for a function invocation. Takes care of converting super() calls into -calls against the prototype’s function of the same name.

    +

    Node for a function invocation.

    exports.Call = class Call extends Base
    -  constructor: (variable, @args = [], @soak) ->
    +  constructor: (@variable, @args = [], @soak) ->
         @isNew    = false
    -    @isSuper  = variable is 'super'
    -    @variable = if @isSuper then null else variable
    -    if variable instanceof Value and variable.isNotCallable()
    -      variable.error "literal is not a function"
    +    if @variable instanceof Value and @variable.isNotCallable()
    +      @variable.error "literal is not a function"
     
       children: ['variable', 'args']
  • -
  • +
  • - +

    Tag this invocation as creating a new instance.

    @@ -1377,78 +1419,24 @@

    Call

  • -
  • -
    - -
    - -
    -

    Grab the reference to the superclass’s implementation of the current -method.

    - -
    - -
      superReference: (o) ->
    -    method = o.scope.namedMethod()
    -    if method?.klass
    -      {klass, name, variable} = method
    -      if klass.isComplex()
    -        bref = new Literal o.scope.parent.freeVariable 'base'
    -        base = new Value new Parens new Assign bref, klass
    -        variable.base = base
    -        variable.properties.splice 0, klass.properties.length
    -      if name.isComplex() or (name instanceof Index and name.index.isAssignable())
    -        nref = new Literal o.scope.parent.freeVariable 'name'
    -        name = new Index new Assign nref, name.index
    -        variable.properties.pop()
    -        variable.properties.push name
    -      accesses = [new Access new Literal '__super__']
    -      accesses.push new Access new Literal 'constructor' if method.static
    -      accesses.push if nref? then new Index nref else name
    -      (new Value bref ? klass, accesses).compile o
    -    else if method?.ctor
    -      "#{method.name}.__super__.constructor"
    -    else
    -      @error 'cannot call super outside of an instance method.'
    - -
  • - -
  • -

    The appropriate this value for a super call.

    - -
    - -
      superThis : (o) ->
    -    method = o.scope.method
    -    (method and not method.klass and method.context) or "this"
    - -
  • - - -
  • -
    - -
    - -

    Soaked chained invocations unfold into if/else ternary structures.

      unfoldSoak: (o) ->
         if @soak
    -      if @variable
    -        return ifn if ifn = unfoldSoak o, this, 'variable'
    -        [left, rite] = new Value(@variable).cacheReference o
    -      else
    +      if this instanceof SuperCall
             left = new Literal @superReference o
             rite = new Value left
    +      else
    +        return ifn if ifn = unfoldSoak o, this, 'variable'
    +        [left, rite] = new Value(@variable).cacheReference o
           rite = new Call rite, @args
           rite.isNew = @isNew
           left = new Literal "typeof #{ left.compile o } === \"function\""
    @@ -1475,11 +1463,11 @@ 

    Call

  • -
  • +
  • - +

    Compile a vanilla function call.

    @@ -1496,7 +1484,7 @@

    Call

    compiledArgs.push (arg.compileToFragments o, LEVEL_LIST)... fragments = [] - if @isSuper + if this instanceof SuperCall preface = @superReference(o) + ".call(#{@superThis(o)}" if compiledArgs.length then preface += ", " fragments.push @makeCode preface @@ -1511,11 +1499,11 @@

    Call

  • -
  • +
  • - +

    If you call a function with a splat, it’s converted into a JavaScript .apply() call to allow an array of arguments to be passed. @@ -1526,7 +1514,7 @@

    Call

      compileSplat: (o, splatArgs) ->
    -    if @isSuper
    +    if this instanceof SuperCall
           return [].concat @makeCode("#{ @superReference o }.apply(#{@superThis(o)}, "),
             splatArgs, @makeCode(")")
     
    @@ -1563,16 +1551,34 @@ 

    Call

  • +
  • +
    + +
    + +
    +

    Super

    + +
    + +
  • + +
  • -

    Extends

    +

    Takes care of converting super() calls into calls against the prototype’s +function of the same name.

    +
    exports.SuperCall = class SuperCall extends Call
    +  constructor: (args) ->
    +    super null, args ? [new Splat new IdentifierLiteral 'arguments']
    +
  • @@ -1582,6 +1588,119 @@

    Extends

    +

    Allow to recognize a bare super call without parentheses and arguments.

    + + + +
        @isBare = args?
    + + + + +
  • +
    + +
    + +
    +

    Grab the reference to the superclass’s implementation of the current +method.

    + +
    + +
      superReference: (o) ->
    +    method = o.scope.namedMethod()
    +    if method?.klass
    +      {klass, name, variable} = method
    +      if klass.isComplex()
    +        bref = new IdentifierLiteral o.scope.parent.freeVariable 'base'
    +        base = new Value new Parens new Assign bref, klass
    +        variable.base = base
    +        variable.properties.splice 0, klass.properties.length
    +      if name.isComplex() or (name instanceof Index and name.index.isAssignable())
    +        nref = new IdentifierLiteral o.scope.parent.freeVariable 'name'
    +        name = new Index new Assign nref, name.index
    +        variable.properties.pop()
    +        variable.properties.push name
    +      accesses = [new Access new PropertyName '__super__']
    +      accesses.push new Access new PropertyName 'constructor' if method.static
    +      accesses.push if nref? then new Index nref else name
    +      (new Value bref ? klass, accesses).compile o
    +    else if method?.ctor
    +      "#{method.name}.__super__.constructor"
    +    else
    +      @error 'cannot call super outside of an instance method.'
    + +
  • + + +
  • +
    + +
    + +
    +

    The appropriate this value for a super call.

    + +
    + +
      superThis : (o) ->
    +    method = o.scope.method
    +    (method and not method.klass and method.context) or "this"
    + +
  • + + +
  • +
    + +
    + +
    +

    RegexWithInterpolations

    + +
    + +
  • + + +
  • +
    + +
    + +
    +

    Regexes with interpolations are in fact just a variation of a Call (a +RegExp() call to be precise) with a StringWithInterpolations inside.

    + +
    + +
    exports.RegexWithInterpolations = class RegexWithInterpolations extends Call
    +  constructor: (args = []) ->
    +    super (new Value new IdentifierLiteral 'RegExp'), args, false
    + +
  • + + +
  • +
    + +
    + +
    +

    Extends

    + +
    + +
  • + + +
  • +
    + +
    + +

    Node to extend an object’s prototype with an ancestor object. After goog.inherits from the Closure Library.

    @@ -1596,11 +1715,11 @@

    Extends

  • -
  • +
  • - +

    Hooks one constructor into another’s prototype chain.

    @@ -1612,11 +1731,11 @@

    Extends

  • -
  • +
  • - +

    Access

    @@ -1625,11 +1744,11 @@

    Access

  • -
  • +
  • - +

    A . access into a property of a value, or the :: shorthand for an access into the object’s prototype.

    @@ -1645,23 +1764,25 @@

    Access

    compileToFragments: (o) -> name = @name.compileToFragments o - if IDENTIFIER.test fragmentsToText name - name.unshift @makeCode "." + node = @name.unwrap() + if node instanceof PropertyName + if node.value in JS_FORBIDDEN + [@makeCode('["'), name..., @makeCode('"]')] + else + [@makeCode('.'), name...] else - name.unshift @makeCode "[" - name.push @makeCode "]" - name + [@makeCode('['), name..., @makeCode(']')] isComplex: NO
  • -
  • +
  • - +

    Index

    @@ -1670,11 +1791,11 @@

    Index

  • -
  • +
  • - +

    A [ ... ] indexed access into an array or object.

    @@ -1694,11 +1815,11 @@

    Index

  • -
  • +
  • - +

    Range

    @@ -1707,11 +1828,11 @@

    Range

  • -
  • +
  • - +

    A range literal. Ranges can be used to extract portions (slices) of arrays, to specify a range for comprehensions, or as a value, to be expanded into the @@ -1730,13 +1851,13 @@

    Range

  • -
  • +
  • - +
    -

    Compiles the range’s source variables — where it starts and where it ends. +

    Compiles the range’s source variables – where it starts and where it ends. But only if they need to be cached to avoid double evaluation.

    @@ -1747,17 +1868,18 @@

    Range

    [@fromC, @fromVar] = @cacheToCodeFragments @from.cache o, LEVEL_LIST, isComplex [@toC, @toVar] = @cacheToCodeFragments @to.cache o, LEVEL_LIST, isComplex [@step, @stepVar] = @cacheToCodeFragments step.cache o, LEVEL_LIST, isComplex if step = del o, 'step' - [@fromNum, @toNum] = [@fromVar.match(NUMBER), @toVar.match(NUMBER)] - @stepNum = @stepVar.match(NUMBER) if @stepVar + @fromNum = if @from.isNumber() then Number @fromVar else null + @toNum = if @to.isNumber() then Number @toVar else null + @stepNum = if step?.isNumber() then Number @stepVar else null
  • -
  • +
  • - +

    When compiled normally, the range returns the contents of the for loop needed to iterate over the values in the range. Used by comprehensions.

    @@ -1771,17 +1893,17 @@

    Range

  • -
  • +
  • - +

    Set up endpoints.

    -
        known    = @fromNum and @toNum
    +            
        known    = @fromNum? and @toNum?
         idx      = del o, 'index'
         idxName  = del o, 'name'
         namedIndex = idxName and idxName isnt idx
    @@ -1793,20 +1915,20 @@ 

    Range

  • -
  • +
  • - +

    Generate the condition.

    -
        condPart = if @stepNum
    -      if parseNum(@stepNum[0]) > 0 then "#{lt} #{@toVar}" else "#{gt} #{@toVar}"
    +            
        condPart = if @stepNum?
    +      if @stepNum > 0 then "#{lt} #{@toVar}" else "#{gt} #{@toVar}"
         else if known
    -      [from, to] = [parseNum(@fromNum[0]), parseNum(@toNum[0])]
    +      [from, to] = [@fromNum, @toNum]
           if from <= to then "#{lt} #{to}" else "#{gt} #{to}"
         else
           cond = if @stepVar then "#{@stepVar} > 0" else "#{@fromVar} <= #{@toVar}"
    @@ -1815,11 +1937,11 @@ 

    Range

  • -
  • +
  • - +

    Generate the step.

    @@ -1844,11 +1966,11 @@

    Range

  • -
  • +
  • - +

    The final loop body.

    @@ -1859,26 +1981,27 @@

    Range

  • -
  • +
  • - +

    When used as a value, expand the range into the equivalent array.

      compileArray: (o) ->
    -    if @fromNum and @toNum and Math.abs(@fromNum - @toNum) <= 20
    -      range = [+@fromNum..+@toNum]
    +    known = @fromNum? and @toNum?
    +    if known and Math.abs(@fromNum - @toNum) <= 20
    +      range = [@fromNum..@toNum]
           range.pop() if @exclusive
           return [@makeCode "[#{ range.join(', ') }]"]
         idt    = @tab + TAB
         i      = o.scope.freeVariable 'i', single: true
         result = o.scope.freeVariable 'results'
         pre    = "\n#{idt}#{result} = [];"
    -    if @fromNum and @toNum
    +    if known
           o.index = i
           body    = fragmentsToText @compileNode o
         else
    @@ -1893,11 +2016,11 @@ 

    Range

  • -
  • +
  • - +

    Slice

    @@ -1906,11 +2029,11 @@

    Slice

  • -
  • +
  • - +

    An array slice literal. Unlike JavaScript’s Array#slice, the second parameter specifies the index of the end of the slice, just as the first parameter @@ -1928,11 +2051,11 @@

    Slice

  • -
  • +
  • - +

    We have to be careful when trying to slice through the end of the array, 9e9 is used because not all implementations respect undefined or 1/0. @@ -1947,11 +2070,11 @@

    Slice

  • -
  • +
  • - +

    TODO: jwalton - move this into the ‘if’?

    @@ -1963,7 +2086,7 @@

    Slice

    if not (not @range.exclusive and +compiledText is -1) toStr = ', ' + if @range.exclusive compiledText - else if SIMPLENUM.test compiledText + else if to.isNumber() "#{+compiledText + 1}" else compiled = to.compileToFragments o, LEVEL_ACCESS @@ -1973,11 +2096,11 @@

    Slice

  • -
  • +
  • - +

    Obj

    @@ -1986,11 +2109,11 @@

    Obj

  • -
  • +
  • - +

    An object literal, nothing fancy.

    @@ -2046,7 +2169,7 @@

    Obj

    value = prop.value else [key, value] = prop.base.cache o - prop = new Assign (new Value (new Literal oref), [new Access key]), value + prop = new Assign (new Value (new IdentifierLiteral oref), [new Access key]), value if indent then answer.push @makeCode indent answer.push prop.compileToFragments(o, LEVEL_TOP)... if join then answer.push @makeCode join @@ -2063,11 +2186,11 @@

    Obj

  • -
  • +
  • - +

    Arr

    @@ -2076,11 +2199,11 @@

    Arr

  • -
  • +
  • - +

    An array literal.

    @@ -2119,11 +2242,11 @@

    Arr

  • -
  • +
  • - +

    Class

    @@ -2132,11 +2255,11 @@

    Class

  • -
  • +
  • - +

    The CoffeeScript class definition. Initialize a Class with its name, an optional superclass, and a @@ -2149,40 +2272,46 @@

    Class

    @boundFuncs = [] @body.classBody = yes - children: ['variable', 'parent', 'body']
    + children: ['variable', 'parent', 'body'] + + defaultClassVariableName: '_Class'
  • -
  • +
  • - +

    Figure out the appropriate name for the constructor function of this class.

      determineName: ->
    -    return null unless @variable
    +    return @defaultClassVariableName unless @variable
         [..., tail] = @variable.properties
    -    decl = if tail
    -      tail instanceof Access and tail.name.value
    +    node = if tail
    +      tail instanceof Access and tail.name
         else
    -      @variable.base.value
    -    if decl in STRICT_PROSCRIBED
    -      @variable.error "class variable name may not be #{decl}"
    -    decl and= IDENTIFIER.test(decl) and decl
    + @variable.base + unless node instanceof IdentifierLiteral or node instanceof PropertyName + return @defaultClassVariableName + name = node.value + unless tail + message = isUnassignable name + @variable.error message if message + if name in JS_FORBIDDEN then "_#{name}" else name
  • -
  • +
  • - +

    For all this-references and bound functions in the class definition, this is the Class being constructed.

    @@ -2192,7 +2321,7 @@

    Class

      setContext: (name) ->
         @body.traverseChildren false, (node) ->
           return false if node.classBody
    -      if node instanceof Literal and node.value is 'this'
    +      if node instanceof ThisLiteral
             node.value    = name
           else if node instanceof Code
             node.context  = name if node.bound
    @@ -2200,11 +2329,11 @@

    Class

  • -
  • +
  • - +

    Ensure that all functions bound to the instance are proxied in the constructor.

    @@ -2213,18 +2342,18 @@

    Class

      addBoundFunctions: (o) ->
         for bvar in @boundFuncs
    -      lhs = (new Value (new Literal "this"), [new Access bvar]).compile o
    +      lhs = (new Value (new ThisLiteral), [new Access bvar]).compile o
           @ctor.body.unshift new Literal "#{lhs} = #{utility 'bind', o}(#{lhs}, this)"
         return
  • -
  • +
  • - +

    Merge the properties from a top-level object as prototypal properties on the class.

    @@ -2246,14 +2375,14 @@

    Class

    if func instanceof Code assign = @ctor = func else - @externalCtor = o.classScope.freeVariable 'class' - assign = new Assign new Literal(@externalCtor), func + @externalCtor = o.classScope.freeVariable 'ctor' + assign = new Assign new IdentifierLiteral(@externalCtor), func else if assign.variable.this func.static = yes else acc = if base.isComplex() then new Index base else new Access base - assign.variable = new Value(new Literal(name), [(new Access new Literal 'prototype'), acc]) + assign.variable = new Value(new IdentifierLiteral(name), [(new Access new PropertyName 'prototype'), acc]) if func instanceof Code and func.bound @boundFuncs.push base func.bound = no @@ -2263,11 +2392,11 @@

    Class

  • -
  • +
  • - +

    Walk the body of the class, looking for prototype properties to be converted and tagging static assignments.

    @@ -2291,11 +2420,11 @@

    Class

  • -
  • +
  • - +

    use strict (and other directives) must be the first expression statement(s) of a function body. This method ensures the prologue is correctly positioned @@ -2313,11 +2442,11 @@

    Class

  • -
  • +
  • - +

    Make sure that a constructor is defined for the class, and properly configured.

    @@ -2340,11 +2469,11 @@

    Class

  • -
  • +
  • - +

    Instead of generating the JavaScript string directly, we build up the equivalent syntax tree and compile that, in pieces. You can see the @@ -2358,9 +2487,8 @@

    Class

    if argumentsNode = @body.contains isLiteralArguments argumentsNode.error "Class bodies shouldn't reference arguments" - name = @determineName() or '_Class' - name = "_#{name}" if name.reserved - lname = new Literal name + name = @determineName() + lname = new IdentifierLiteral name func = new Code [], Block.wrap [@body] args = [] o.classScope = func.makeScope o.scope @@ -2374,7 +2502,7 @@

    Class

    @body.expressions.push lname if @parent - superClass = new Literal o.classScope.freeVariable 'superClass', reserve: no + superClass = new IdentifierLiteral o.classScope.freeVariable 'superClass', reserve: no @body.expressions.unshift new Extends lname, superClass func.params.push new Param superClass args.push @parent @@ -2388,11 +2516,11 @@

    Class

  • -
  • +
  • - +

    Assign

    @@ -2401,23 +2529,20 @@

    Assign

  • -
  • +
  • - +

    The Assign is used to assign a local variable to value, or to set the -property of an object — including within object literals.

    +property of an object – including within object literals.

    exports.Assign = class Assign extends Base
       constructor: (@variable, @value, @context, options = {}) ->
         {@param, @subpattern, @operatorToken} = options
    -    forbidden = (name = @variable.unwrapAll().value) in STRICT_PROSCRIBED
    -    if forbidden and @context isnt 'object'
    -      @variable.error "variable name may not be \"#{name}\""
     
       children: ['variable', 'value']
     
    @@ -2433,11 +2558,11 @@ 

    Assign

  • -
  • +
  • - +

    Compile an assignment, delegating to compilePatternMatch or compileSplice if appropriate. Keep track of the name of the base object @@ -2466,7 +2591,7 @@

    Assign

    unless @context varBase = @variable.unwrapAll() unless varBase.isAssignable() - @variable.error "\"#{@variable.compile o}\" cannot be assigned" + @variable.error "'#{@variable.compile o}' can't be assigned" unless varBase.hasProperties?() if @param o.scope.add varBase.value, 'var' @@ -2475,18 +2600,24 @@

    Assign

    val = @value.compileToFragments o, LEVEL_LIST @variable.front = true if isValue and @variable.base instanceof Obj compiledName = @variable.compileToFragments o, LEVEL_LIST - return (compiledName.concat @makeCode(": "), val) if @context is 'object' + + if @context is 'object' + if fragmentsToText(compiledName) in JS_FORBIDDEN + compiledName.unshift @makeCode '"' + compiledName.push @makeCode '"' + return compiledName.concat @makeCode(": "), val + answer = compiledName.concat @makeCode(" #{ @context or '=' } "), val if o.level <= LEVEL_LIST then answer else @wrapInBraces answer
  • -
  • +
  • - +

    Brief implementation of recursive pattern matching, when assigning array or object literals to a value. Peeks at their properties to assign inner names.

    @@ -2509,11 +2640,11 @@

    Assign

  • -
  • +
  • - +

    Pick the property straight off the value when there’s just one to pick (no need to cache the value into a variable).

    @@ -2526,11 +2657,11 @@

    Assign

  • -
  • +
  • - +

    A regular object pattern-match.

    @@ -2549,38 +2680,41 @@

    Assign

  • -
  • +
  • - +

    A shorthand {a, b, @c} = val pattern-match.

    -
              if obj.this then obj.properties[0].name else obj
    +            
              if obj.this
    +            obj.properties[0].name
    +          else
    +            new PropertyName obj.unwrap().value
             else
  • -
  • +
  • - +

    A regular array pattern-match.

    -
              new Literal 0
    -      acc   = IDENTIFIER.test idx.unwrap().value
    +            
              new NumberLiteral 0
    +      acc   = idx.unwrap() instanceof PropertyName
           value = new Value value
           value.properties.push new (if acc then Access else Index) idx
    -      if obj.unwrap().value in RESERVED
    -        obj.error "assignment to a reserved word: #{obj.compile o}"
    +      message = isUnassignable obj.unwrap().value
    +      obj.error message if message
           value = new Op '?', value, defaultValue if defaultValue
           return new Assign(obj, value, null, param: @param).compileToFragments o, LEVEL_TOP
         vvar     = value.compileToFragments o, LEVEL_LIST
    @@ -2591,17 +2725,17 @@ 

    Assign

  • -
  • +
  • - +

    Make vvar into a simple variable if it isn’t already.

    -
        if not IDENTIFIER.test(vvarText) or @variable.assigns(vvarText)
    +            
        if value.unwrap() not instanceof IdentifierLiteral or @variable.assigns(vvarText)
           assigns.push [@makeCode("#{ ref = o.scope.freeVariable 'ref' } = "), vvar...]
           vvar = [@makeCode ref]
           vvarText = ref
    @@ -2637,11 +2771,11 @@ 

    Assign

  • -
  • +
  • - +

    A regular object pattern-match.

    @@ -2660,27 +2794,30 @@

    Assign

  • -
  • +
  • - +

    A shorthand {a, b, @c} = val pattern-match.

    -
                if obj.this then obj.properties[0].name else obj
    +            
                if obj.this
    +              obj.properties[0].name
    +            else
    +              new PropertyName obj.unwrap().value
               else
  • -
  • +
  • - +

    A regular array pattern-match.

    @@ -2688,11 +2825,12 @@

    Assign

                new Literal expandedIdx or idx
             name = obj.unwrap().value
    -        acc = IDENTIFIER.test idx.unwrap().value
    +        acc = idx.unwrap() instanceof PropertyName
             val = new Value new Literal(vvarText), [new (if acc then Access else Index) idx]
             val = new Op '?', val, defaultValue if defaultValue
    -      if name? and name in RESERVED
    -        obj.error "assignment to a reserved word: #{obj.compile o}"
    +      if name?
    +        message = isUnassignable name
    +        obj.error message if message
           assigns.push new Assign(obj, val, null, param: @param, subpattern: yes).compileToFragments o, LEVEL_LIST
         assigns.push vvar unless top or @subpattern
         fragments = @joinFragmentArrays assigns, ', '
    @@ -2701,11 +2839,11 @@ 

    Assign

  • -
  • +
  • - +

    When compiling a conditional assignment, take care to ensure that the operands are only evaluated once, even though we have to reference them @@ -2719,18 +2857,18 @@

    Assign

  • -
  • +
  • - +

    Disallow conditional assignment of undefined variables.

        if not left.properties.length and left.base instanceof Literal and
    -           left.base.value != "this" and not o.scope.check left.base.value
    +           left.base not instanceof ThisLiteral and not o.scope.check left.base.value
           @variable.error "the variable \"#{left.base.value}\" can't be assigned with #{@context} because it has not been declared before"
         if "?" in @context
           o.isExistentialEquals = true
    @@ -2742,11 +2880,11 @@ 

    Assign

  • -
  • +
  • - +

    Convert special math assignment operators like a **= b to the equivalent extended form a = a ** b and then compiles that.

    @@ -2760,11 +2898,11 @@

    Assign

  • -
  • +
  • - +

    Compile the assignment from an array splice literal, using JavaScript’s Array#splice method.

    @@ -2779,8 +2917,7 @@

    Assign

    else fromDecl = fromRef = '0' if to - if from instanceof Value and from.isSimpleNumber() and - to instanceof Value and to.isSimpleNumber() + if from?.isNumber() and to.isNumber() to = to.compile(o) - fromRef to += 1 unless exclusive else @@ -2795,11 +2932,11 @@

    Assign

  • -
  • +
  • - +

    Code

    @@ -2808,15 +2945,15 @@

    Code

  • -
  • +
  • - +

    A function definition. This is the only node that creates a new Scope. When for the purposes of walking the contents of a function body, the Code -has no children — they’re within the inner scope.

    +has no children – they’re within the inner scope.

    @@ -2826,7 +2963,7 @@

    Code

    @body = body or new Block @bound = tag is 'boundfunc' @isGenerator = !!@body.contains (node) -> - node instanceof Op and node.operator in ['yield', 'yield*'] + (node instanceof Op and node.isYield()) or node instanceof YieldReturn children: ['params', 'body'] @@ -2839,11 +2976,11 @@

    Code

  • -
  • +
  • - +

    Compilation creates a new scope unless explicitly asked to share with the outer scope. Handles splat parameters in the parameter list by peeking at @@ -2861,11 +2998,11 @@

    Code

  • -
  • +
  • - +

    Handle bound functions early.

    @@ -2873,8 +3010,8 @@

    Code

        if @bound and not @context
           @context = '_this'
    -      wrapper = new Code [new Param new Literal @context], new Block [this]
    -      boundfunc = new Call(wrapper, [new Literal 'this'])
    +      wrapper = new Code [new Param new IdentifierLiteral @context], new Block [this]
    +      boundfunc = new Call(wrapper, [new ThisLiteral])
           boundfunc.updateLocationDataIfMissing @locationData
           return boundfunc.compileNode(o)
     
    @@ -2891,7 +3028,7 @@ 

    Code

    for p in @params when p not instanceof Expansion and p.name.value o.scope.add p.name.value, 'var', yes splats = new Assign new Value(new Arr(p.asReference o for p in @params)), - new Value new Literal 'arguments' + new Value new IdentifierLiteral 'arguments' break for param in @params if param.isComplex() @@ -2937,11 +3074,11 @@

    Code

  • -
  • +
  • - +

    Short-circuit traverseChildren method to prevent it from crossing scope boundaries unless crossScope is true.

    @@ -2954,11 +3091,11 @@

    Code

  • -
  • +
  • - +

    Param

    @@ -2967,13 +3104,13 @@

    Param

  • -
  • +
  • - +
    -

    A parameter in a function definition. Beyond a typical Javascript parameter, +

    A parameter in a function definition. Beyond a typical JavaScript parameter, these parameters can also attach themselves to the context of the function, as well as be a splat, gathering up a group of parameters into an array.

    @@ -2981,8 +3118,8 @@

    Param

    exports.Param = class Param extends Base
       constructor: (@name, @value, @splat) ->
    -    if (name = @name.unwrapAll().value) in STRICT_PROSCRIBED
    -      @name.error "parameter name \"#{name}\" is not allowed"
    +    message = isUnassignable @name.unwrapAll().value
    +    @name.error message if message
         if @name instanceof Obj and @name.generated
           token = @name.objects[0].operatorToken
           token.error "unexpected #{token.value}"
    @@ -2997,10 +3134,10 @@ 

    Param

    node = @name if node.this name = node.properties[0].name.value - name = "_#{name}" if name.reserved - node = new Literal o.scope.freeVariable name + name = "_#{name}" if name in JS_FORBIDDEN + node = new IdentifierLiteral o.scope.freeVariable name else if node.isComplex() - node = new Literal o.scope.freeVariable 'arg' + node = new IdentifierLiteral o.scope.freeVariable 'arg' node = new Value node node = new Splat node if @splat node.updateLocationDataIfMissing @locationData @@ -3012,11 +3149,11 @@

    Param

  • -
  • +
  • - +

    Iterates the name or names of a Param. In a sense, a destructured parameter represents multiple JS parameters. This @@ -3033,11 +3170,11 @@

    Param

  • -
  • +
  • - +
    • simple literals foo
    • @@ -3050,11 +3187,11 @@

      Param

      -
    • +
    • - +
      • at-params @foo
      • @@ -3063,16 +3200,16 @@

        Param

          return atParam name if name instanceof Value
      -    for obj in name.objects
      + for obj in name.objects ? []
  • -
  • +
  • - +
    • destructured parameter with default value
    • @@ -3086,11 +3223,11 @@

      Param

      -
    • +
    • - +
      • assignments within destructured parameters {foo:bar}
      • @@ -3098,17 +3235,33 @@

        Param

      -
            if obj instanceof Assign
      +            
            if obj instanceof Assign
      + +
    • + + +
    • +
      + +
      + +
      +

      … possibly with a default value

      + +
      + +
              if obj.value instanceof Assign
      +          obj = obj.value
               @eachName iterator, obj.value.unwrap()
    • -
    • +
    • - +
      • splats within destructured parameters [xs...]
      • @@ -3124,11 +3277,11 @@

        Param

        -
      • +
      • - +
        • destructured parameters within destructured parameters [{a}]
        • @@ -3142,11 +3295,11 @@

          Param

          -
        • +
        • - +
          • at-params within destructured parameters {@foo}
          • @@ -3160,11 +3313,11 @@

            Param

            -
          • +
          • - +
            • simple destructured parameters {foo}
            • @@ -3180,11 +3333,11 @@

              Param

              -
            • +
            • - +

              Splat

              @@ -3193,11 +3346,11 @@

              Splat

            • -
            • +
            • - +

              A splat, either as a parameter to a function, an argument to a call, or as part of a destructuring assignment.

              @@ -3224,11 +3377,11 @@

              Splat

            • -
            • +
            • - +

              Utility function that converts an arbitrary number of elements, mixed with splats, to a proper array.

              @@ -3263,11 +3416,11 @@

              Splat

            • -
            • +
            • - +

              Expansion

              @@ -3276,11 +3429,11 @@

              Expansion

            • -
            • +
            • - +

              Used to skip values inside an array destructuring (pattern matching) or parameter list.

              @@ -3302,11 +3455,11 @@

              Expansion

            • -
            • +
            • - +

              While

              @@ -3315,11 +3468,11 @@

              While

            • -
            • +
            • - +

              A while loop, the only sort of low-level loop exposed by CoffeeScript. From it, all other loops can be manufactured. Useful in cases where you need more @@ -3356,14 +3509,14 @@

              While

            • -
            • +
            • - +

              The main difference from a JavaScript while is that the CoffeeScript -while can be used as a part of a larger expression — while loops may +while can be used as a part of a larger expression – while loops may return an array containing the computed result of each iteration.

              @@ -3380,7 +3533,7 @@

              While

              set = "#{@tab}#{rvar} = [];\n" if @guard if body.expressions.length > 1 - body.expressions.unshift new If (new Parens @guard).invert(), new Literal "continue" + body.expressions.unshift new If (new Parens @guard).invert(), new StatementLiteral "continue" else body = Block.wrap [new If @guard, body] if @guard body = [].concat @makeCode("\n"), (body.compileToFragments o, LEVEL_TOP), @makeCode("\n#{@tab}") @@ -3393,11 +3546,11 @@

              While

            • -
            • +
            • - +

              Op

              @@ -3406,11 +3559,11 @@

              Op

            • -
            • +
            • - +

              Simple Arithmetic and logical operations. Performs some conversion from CoffeeScript operations into their JavaScript equivalents.

              @@ -3434,11 +3587,11 @@

              Op

            • -
            • +
            • - +

              The map of conversions from CoffeeScript to JavaScript symbols.

              @@ -3453,11 +3606,11 @@

              Op

            • -
            • +
            • - +

              The map of invertible operators.

              @@ -3469,29 +3622,27 @@

              Op

              children: ['first', 'second'] - isSimpleNumber: NO + isNumber: -> + @isUnary() and @operator in ['+', '-'] and + @first instanceof Value and @first.isNumber() isYield: -> @operator in ['yield', 'yield*'] - isYieldReturn: -> - @isYield() and @first instanceof Return - isUnary: -> not @second isComplex: -> - not (@isUnary() and @operator in ['+', '-'] and - @first instanceof Value and @first.isSimpleNumber())
            + not @isNumber()
      • -
      • +
      • - +

        Am I capable of Python-style comparison chaining?

        @@ -3553,11 +3704,11 @@

        Op

      • -
      • +
      • - +

        In chains, there’s no need to wrap bare obj literals in parens, as the chained expression is wrapped.

        @@ -3567,8 +3718,9 @@

        Op

            @first.front = @front unless isChain
             if @operator is 'delete' and o.scope.check(@first.unwrapAll().value)
               @error 'delete operand may not be argument or var'
        -    if @operator in ['--', '++'] and @first.unwrapAll().value in STRICT_PROSCRIBED
        -      @error "cannot increment/decrement \"#{@first.unwrapAll().value}\""
        +    if @operator in ['--', '++']
        +      message = isUnassignable @first.unwrapAll().value
        +      @first.error message if message
             return @compileYield     o if @isYield()
             return @compileUnary     o if @isUnary()
             return @compileChain     o if isChain
        @@ -3586,11 +3738,11 @@ 

        Op

      • -
      • +
      • - +

        Mimic Python’s chained comparisons when multiple comparison operators are used sequentially. For example:

        @@ -3609,11 +3761,11 @@

        Op

      • -
      • +
      • - +

        Keep reference to the left expression, unless this an existential assignment

        @@ -3621,7 +3773,7 @@

        Op

          compileExistence: (o) ->
             if @first.isComplex()
        -      ref = new Literal o.scope.freeVariable 'ref'
        +      ref = new IdentifierLiteral o.scope.freeVariable 'ref'
               fst = new Parens new Assign ref, @first
             else
               fst = @first
        @@ -3631,11 +3783,11 @@ 

        Op

      • -
      • +
      • - +

        Compile a unary Op.

        @@ -3662,17 +3814,16 @@

        Op

        compileYield: (o) -> parts = [] op = @operator - if not o.scope.parent? - @error 'yield statements must occur within a function generator.' + unless o.scope.parent? + @error 'yield can only occur inside functions' if 'expression' in Object.keys(@first) and not (@first instanceof Throw) - if @isYieldReturn() - parts.push @first.compileToFragments o, LEVEL_TOP - else if @first.expression? - parts.push @first.expression.compileToFragments o, LEVEL_OP + parts.push @first.expression.compileToFragments o, LEVEL_OP if @first.expression? else - parts.push [@makeCode "(#{op} "] + parts.push [@makeCode "("] if o.level >= LEVEL_PAREN + parts.push [@makeCode op] + parts.push [@makeCode " "] if @first.base?.value isnt '' parts.push @first.compileToFragments o, LEVEL_OP - parts.push [@makeCode ")"] + parts.push [@makeCode ")"] if o.level >= LEVEL_PAREN @joinFragmentArrays parts, '' compilePower: (o) ->
      @@ -3680,21 +3831,21 @@

      Op

    • -
    • +
    • - +

      Make a Math.pow call

      -
          pow = new Value new Literal('Math'), [new Access new Literal 'pow']
      +            
          pow = new Value new IdentifierLiteral('Math'), [new Access new PropertyName 'pow']
           new Call(pow, [@first, @second]).compileToFragments o
       
         compileFloorDivision: (o) ->
      -    floor = new Value new Literal('Math'), [new Access new Literal 'floor']
      +    floor = new Value new IdentifierLiteral('Math'), [new Access new PropertyName 'floor']
           div = new Op '/', @first, @second
           new Call(floor, [div]).compileToFragments o
       
      @@ -3708,11 +3859,11 @@ 

      Op

    • -
    • +
    • - +

      In

      @@ -3734,11 +3885,11 @@

      In

    • -
    • +
    • - +

      compileOrTest only if we have an array literal with no splats

      @@ -3770,11 +3921,11 @@

      In

    • -
    • +
    • - +

      Try

      @@ -3783,11 +3934,11 @@

      Try

    • -
    • +
    • - +

      A classic try/catch/finally block.

      @@ -3810,13 +3961,13 @@

      Try

    • -
    • +
    • - +
      -

      Compilation is more or less as you would expect — the finally clause +

      Compilation is more or less as you would expect – the finally clause is optional, the catch is not.

      @@ -3826,12 +3977,16 @@

      Try

      tryPart = @attempt.compileToFragments o, LEVEL_TOP catchPart = if @recovery - generatedErrorVariableName = o.scope.freeVariable 'error' - placeholder = new Literal generatedErrorVariableName - @recovery.unshift new Assign @errorVariable, placeholder if @errorVariable + generatedErrorVariableName = o.scope.freeVariable 'error', reserve: no + placeholder = new IdentifierLiteral generatedErrorVariableName + if @errorVariable + message = isUnassignable @errorVariable.unwrapAll().value + @errorVariable.error message if message + @recovery.unshift new Assign @errorVariable, placeholder [].concat @makeCode(" catch ("), placeholder.compileToFragments(o), @makeCode(") {\n"), @recovery.compileToFragments(o, LEVEL_TOP), @makeCode("\n#{@tab}}") else unless @ensure or @recovery + generatedErrorVariableName = o.scope.freeVariable 'error', reserve: no [@makeCode(" catch (#{generatedErrorVariableName}) {}")] else [] @@ -3846,11 +4001,11 @@

      Try

    • -
    • +
    • - +

      Throw

      @@ -3859,11 +4014,11 @@

      Throw

    • -
    • +
    • - +

      Simple node to throw an exception.

      @@ -3880,11 +4035,11 @@

      Throw

    • -
    • +
    • - +

      A Throw is already a return, of sorts…

      @@ -3898,11 +4053,11 @@

      Throw

    • -
    • +
    • - +

      Existence

      @@ -3911,13 +4066,13 @@

      Existence

    • -
    • +
    • - +
      -

      Checks a variable for existence — not null and not undefined. This is +

      Checks a variable for existence – not null and not undefined. This is similar to .nil? in Ruby, and avoids having to consult a JavaScript truth table.

      @@ -3933,7 +4088,7 @@

      Existence

      compileNode: (o) -> @expression.front = @front code = @expression.compile o, LEVEL_OP - if IDENTIFIER.test(code) and not o.scope.check code + if @expression.unwrap() instanceof IdentifierLiteral and not o.scope.check code [cmp, cnj] = if @negated then ['===', '||'] else ['!==', '&&'] code = "typeof #{code} #{cmp} \"undefined\" #{cnj} #{code} #{cmp} null" else
    @@ -3941,11 +4096,11 @@

    Existence

  • -
  • +
  • - +

    do not use strict equality here; it will break existing code

    @@ -3957,11 +4112,11 @@

    Existence

  • -
  • +
  • - +

    Parens

    @@ -3970,15 +4125,15 @@

    Parens

  • -
  • +
  • - +

    An extra set of parentheses, specified explicitly in the source. At one time we tried to clean up the results by detecting and removing redundant -parentheses, but no longer — you can put in as many as you please.

    +parentheses, but no longer – you can put in as many as you please.

    Parentheses are a good way to force any statement to become an expression.

    @@ -4004,11 +4159,41 @@

    Parens

  • -
  • +
  • - + +
    +

    StringWithInterpolations

    + +
    + +
  • + + +
  • +
    + +
    + +
    +

    Strings with interpolations are in fact just a variation of Parens with +string concatenation inside.

    + +
    + +
    +exports.StringWithInterpolations = class StringWithInterpolations extends Parens
    + +
  • + + +
  • +
    + +
    +

    For

    @@ -4017,11 +4202,11 @@

    For

  • -
  • +
  • - +

    CoffeeScript’s replacement for the for loop is our array and object comprehensions, that compile into for loops here. They also act as an @@ -4052,11 +4237,11 @@

    For

  • -
  • +
  • - +

    Welcome to the hairiest method in all of CoffeeScript. Handles the inner loop, filtering, stepping, and result saving for array, object, and range @@ -4081,7 +4266,7 @@

    For

    kvarAssign = if kvar isnt ivar then "#{kvar} = " else "" if @step and not @range [step, stepVar] = @cacheToCodeFragments @step.cache o, LEVEL_LIST, isComplexOrAssignable - stepNum = stepVar.match NUMBER + stepNum = Number stepVar if @step.isNumber() name = ivar if @pattern varPart = '' guardPart = '' @@ -4092,20 +4277,21 @@

    For

    {index: ivar, name, @step, isComplex: isComplexOrAssignable} else svar = @source.compile o, LEVEL_LIST - if (name or @own) and not IDENTIFIER.test svar + if (name or @own) and @source.unwrap() not instanceof IdentifierLiteral defPart += "#{@tab}#{ref = scope.freeVariable 'ref'} = #{svar};\n" svar = ref if name and not @pattern namePart = "#{name} = #{svar}[#{kvar}]" if not @object defPart += "#{@tab}#{step};\n" if step isnt stepVar - lvar = scope.freeVariable 'len' unless @step and stepNum and down = (parseNum(stepNum[0]) < 0) + down = stepNum < 0 + lvar = scope.freeVariable 'len' unless @step and stepNum? and down declare = "#{kvarAssign}#{ivar} = 0, #{lvar} = #{svar}.length" declareDown = "#{kvarAssign}#{ivar} = #{svar}.length - 1" compare = "#{ivar} < #{lvar}" compareDown = "#{ivar} >= 0" if @step - if stepNum + if stepNum? if down compare = compareDown declare = declareDown @@ -4122,7 +4308,7 @@

    For

    body.makeReturn rvar if @guard if body.expressions.length > 1 - body.expressions.unshift new If (new Parens @guard).invert(), new Literal "continue" + body.expressions.unshift new If (new Parens @guard).invert(), new StatementLiteral "continue" else body = Block.wrap [new If @guard, body] if @guard if @pattern @@ -4151,7 +4337,7 @@

    For

    val.properties.length is 1 and val.properties[0].name?.value in ['call', 'apply']) fn = val.base?.unwrapAll() or val - ref = new Literal o.scope.freeVariable 'fn' + ref = new IdentifierLiteral o.scope.freeVariable 'fn' base = new Value ref if val.base [val.base, base] = [base, val] @@ -4162,11 +4348,11 @@

    For

  • -
  • +
  • - +

    Switch

    @@ -4175,11 +4361,11 @@

    Switch

  • -
  • +
  • - +

    A JavaScript switch statement. Converts into a returnable expression on-demand.

    @@ -4226,11 +4412,11 @@

    Switch

  • -
  • +
  • - +

    If

    @@ -4239,11 +4425,11 @@

    If

  • -
  • +
  • - +

    If/else statements. Acts as an expression by pushing down requested returns to the last line of each clause.

    @@ -4267,11 +4453,11 @@

    If

  • -
  • +
  • - +

    Rewrite a chain of Ifs to add a default case as the final else.

    @@ -4289,11 +4475,11 @@

    If

  • -
  • +
  • - +

    The If only compiles into a statement if either of its bodies needs to be a statement. Otherwise a conditional operator is safe.

    @@ -4321,11 +4507,11 @@

    If

  • -
  • +
  • - +

    Compile the If as a regular if-else statement. Flattened chains force inner else bodies into statement form.

    @@ -4356,11 +4542,11 @@

    If

  • -
  • +
  • - +

    Compile the If as a conditional operator.

    @@ -4379,11 +4565,11 @@

    If

  • -
  • +
  • - +

    Constants

    @@ -4392,11 +4578,11 @@

    Constants

  • -
  • +
  • - +
    @@ -4407,11 +4593,11 @@

    Constants

  • -
  • +
  • - +

    Correctly set up a prototype chain for inheritance, including a reference to the superclass for super() calls, and copies of any static properties.

    @@ -4436,11 +4622,11 @@

    Constants

  • -
  • +
  • - +

    Create a function bound to the current value of “this”.

    @@ -4457,11 +4643,11 @@

    Constants

  • -
  • +
  • - +

    Discover if an item is in an array.

    @@ -4483,11 +4669,11 @@

    Constants

  • -
  • +
  • - +

    Shortcuts to speed up the lookup time for native functions.

    @@ -4499,11 +4685,11 @@

    Constants

  • -
  • +
  • - +

    Levels indicate a node’s position in the AST. Useful for knowing if parens are necessary or superfluous.

    @@ -4520,11 +4706,11 @@

    Constants

  • -
  • +
  • - +

    Tabs are two spaces for pretty printing.

    @@ -4532,38 +4718,16 @@

    Constants

    TAB = '  '
     
    -IDENTIFIER = /// ^ (?!\d) [$\w\x7f-\uffff]+ $ ///
    -SIMPLENUM  = /^[+-]?\d+$/
    -HEXNUM = /^[+-]?0x[\da-f]+/i
    -NUMBER    = ///^[+-]?(?:
    -  0x[\da-f]+ |              # hex
    -  \d*\.?\d+ (?:e[+-]?\d+)?  # decimal
    -)$///i
    - -
  • - - -
  • -
    - -
    - -
    -

    Is a literal value a string/regex?

    - -
    - -
    IS_STRING = /^['"]/
    -IS_REGEX = /^\//
    +SIMPLENUM = /^[+-]?\d+$/
  • -
  • +
  • - +

    Helper Functions

    @@ -4572,11 +4736,11 @@

    Helper Functions

  • -
  • +
  • - +
    @@ -4584,11 +4748,11 @@

    Helper Functions

  • -
  • +
  • - +

    Helper for ensuring that utility functions are assigned at the top level.

    @@ -4605,48 +4769,26 @@

    Helper Functions

    multident = (code, tab) -> code = code.replace /\n/g, '$&' + tab - code.replace /\s+$/, ''
    - -
  • - - -
  • -
    - -
    - -
    -

    Parse a number (+- decimal/hexadecimal) -Examples: 0, -1, 1, 2e3, 2e-3, -0xfe, 0xfe

    - -
    - -
    parseNum = (x) ->
    -  if not x?
    -    0
    -  else if x.match HEXNUM
    -    parseInt x, 16
    -  else
    -    parseFloat x
    +  code.replace /\s+$/, ''
     
     isLiteralArguments = (node) ->
       node instanceof Literal and node.value is 'arguments' and not node.asKey
     
     isLiteralThis = (node) ->
    -  (node instanceof Literal and node.value is 'this' and not node.asKey) or
    +  (node instanceof ThisLiteral and not node.asKey) or
         (node instanceof Code and node.bound) or
    -    (node instanceof Call and node.isSuper)
    +    node instanceof SuperCall
     
     isComplexOrAssignable = (node) -> node.isComplex() or node.isAssignable?()
  • -
  • +
  • - +

    Unfold a node’s child if soak, then tuck the node under created If

    diff --git a/documentation/docs/optparse.html b/documentation/docs/optparse.html index 67f59eb6ad..cb85da5022 100644 --- a/documentation/docs/optparse.html +++ b/documentation/docs/optparse.html @@ -151,7 +151,7 @@

    optparse.coffee

    Initialize with a list of valid options, in the form:

    [short-flag, long-flag, description]
    -

    Along with an an optional banner for the usage help.

    +

    Along with an optional banner for the usage help.

    diff --git a/documentation/docs/register.html b/documentation/docs/register.html index 1fcd9536c5..6251502634 100644 --- a/documentation/docs/register.html +++ b/documentation/docs/register.html @@ -137,7 +137,7 @@

    register.coffee

    loadFile = (module, filename) ->
    -  answer = CoffeeScript._compileFile filename, false
    +  answer = CoffeeScript._compileFile filename, no, yes
       module._compile answer, filename
  • diff --git a/documentation/docs/repl.html b/documentation/docs/repl.html index 3b7067ef4d..f70466b9da 100644 --- a/documentation/docs/repl.html +++ b/documentation/docs/repl.html @@ -208,7 +208,7 @@

    repl.coffee

          referencedVars = (
    -        token[1] for token in tokens when token.variable
    +        token[1] for token in tokens when token[0] is 'IDENTIFIER'
           )
    @@ -510,7 +510,7 @@

    repl.coffee

    fd = fs.openSync filename, 'a' repl.rli.addListener 'line', (code) -> - if code and code.length and code isnt '.history' and lastLine isnt code + if code and code.length and code isnt '.history' and code isnt '.exit' and lastLine isnt code diff --git a/documentation/docs/rewriter.html b/documentation/docs/rewriter.html index 52d7dc61b8..d67e3e0d8f 100644 --- a/documentation/docs/rewriter.html +++ b/documentation/docs/rewriter.html @@ -185,7 +185,7 @@

    rewriter.coffee

    Rewrite the token stream in multiple passes, one logical filter at a time. This could certainly be changed into a single pass through the stream, with a big ol’ efficient switch, but it’s much nicer to work with -like this. The order of these passes matters — indentation must be +like this. The order of these passes matters – indentation must be corrected before implicit parentheses can be wrapped around blocks of code.

    @@ -1117,7 +1117,7 @@

    Constants

    -
    IMPLICIT_FUNC    = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS']
    +
    IMPLICIT_FUNC    = ['IDENTIFIER', 'PROPERTY', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS']
    @@ -1133,9 +1133,11 @@

    Constants

    IMPLICIT_CALL    = [
    -  'IDENTIFIER', 'NUMBER', 'STRING', 'STRING_START', 'JS', 'REGEX', 'REGEX_START'
    -  'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'NULL'
    -  'UNDEFINED', 'UNARY', 'YIELD', 'UNARY_MATH', 'SUPER', 'THROW'
    +  'IDENTIFIER', 'PROPERTY', 'NUMBER', 'INFINITY', 'NAN'
    +  'STRING', 'STRING_START', 'REGEX', 'REGEX_START', 'JS'
    +  'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS'
    +  'UNDEFINED', 'NULL', 'BOOL'
    +  'UNARY', 'YIELD', 'UNARY_MATH', 'SUPER', 'THROW'
       '@', '->', '=>', '[', '(', '{', '--', '++'
     ]
     
    diff --git a/documentation/docs/scope.html b/documentation/docs/scope.html
    index 34ff76e43c..02deca36d3 100644
    --- a/documentation/docs/scope.html
    +++ b/documentation/docs/scope.html
    @@ -273,9 +273,15 @@ 

    scope.litcoffee

      temporary: (name, index, single=false) ->
         if single
    -      (index + parseInt name, 36).toString(36).replace /\d/g, 'a'
    +      startCode = name.charCodeAt(0)
    +      endCode = 'z'.charCodeAt(0)
    +      diff = endCode - startCode
    +      newCode = startCode + index % (diff + 1)
    +      letter = String.fromCharCode(newCode)
    +      num = index // (diff + 1)
    +      "#{letter}#{num or ''}"
         else
    -      name + (index or '')
    + "#{name}#{index or ''}"
    diff --git a/documentation/docs/sourcemap.html b/documentation/docs/sourcemap.html index 0d9bf1aacc..7af38ce41b 100644 --- a/documentation/docs/sourcemap.html +++ b/documentation/docs/sourcemap.html @@ -378,9 +378,9 @@

    V3 SourceMap Generation

    names: [] mappings: buffer - v3.sourcesContent = [code] if options.inline + v3.sourcesContent = [code] if options.inlineMap - JSON.stringify v3, null, 2 + v3 From 70d1f614a03b685121c822f060b3a07ad3e10137 Mon Sep 17 00:00:00 2001 From: Robert de Forest Date: Mon, 10 Oct 2016 19:23:18 -0700 Subject: [PATCH 2/4] Pretty sure this is a mistake? --- src/command.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/command.coffee b/src/command.coffee index 104ce86fcc..679334fc7d 100644 --- a/src/command.coffee +++ b/src/command.coffee @@ -180,7 +180,7 @@ compileScript = (file, input, base = null) -> CoffeeScript.eval opts.prelude, t.options if opts.prelude CoffeeScript.run t.input, t.options else if o.join and t.file isnt o.join - t.input = helpers.invertLiterate t.input if helpers.isLiterate file + t.input = helpers.invertLiterate t.input if helpers.isLiterate t.file sourceCode[sources.indexOf(t.file)] = t.input compileJoin() else From 4bf2263bf71642c6e504326030fd16344735a3be Mon Sep 17 00:00:00 2001 From: Robert de Forest Date: Fri, 2 Mar 2018 12:41:27 -0800 Subject: [PATCH 3/4] simplified test file skiping (#4996) --- Cakefile | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/Cakefile b/Cakefile index 599520f674..9018b8b16b 100644 --- a/Cakefile +++ b/Cakefile @@ -29,6 +29,15 @@ header = """ # Used in folder names like `docs/v1`. majorVersion = parseInt CoffeeScript.VERSION.split('.')[0], 10 +# Patterns of names of test files which depend on currently absent features +testFilesToSkip = [ + /async/ unless try new Function 'async () => {}' + /async_iterators/ unless try new Function 'async () * => {}' + /exponent_ops/ unless try new Function 'x = 3; x **= 2 ** 2; return x === 81' +].filter _.identity + +featuresPresentFor = (fileName) -> + not testFilesToSkip.find (filePattern) -> fileName.match filePattern # Log a message with a color. log = (message, color, explanation) -> @@ -378,7 +387,6 @@ task 'bench', 'quick benchmark of compilation time', -> console.log "Compile#{time()} (#{js.length} chars)" console.log "total #{ fmt total }" - # Run the CoffeeScript test suite. runTests = (CoffeeScript) -> CoffeeScript.register() unless global.testingBrowser @@ -425,12 +433,6 @@ runTests = (CoffeeScript) -> catch err onFail description, fn, err - global.supportsAsync = try - new Function('async () => {}')() - yes - catch - no - helpers.extend global, require './test/support/helpers' # When all the tests have run, collect and print errors. @@ -449,9 +451,9 @@ runTests = (CoffeeScript) -> return # Run every test in the `test` folder, recording failures. - files = fs.readdirSync 'test' - unless global.supportsAsync # Except for async tests, if async isn’t supported. - files = files.filter (filename) -> filename isnt 'async.coffee' + files = + fs.readdirSync 'test' + .filter featuresPresentFor startTime = Date.now() for file in files when helpers.isCoffee file From 930a757c9a66a75ac96bfc8d5b908ae0fd135f96 Mon Sep 17 00:00:00 2001 From: Robert de Forest Date: Fri, 2 Mar 2018 14:09:50 -0800 Subject: [PATCH 4/4] Remove unnecessary diff noise --- Cakefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cakefile b/Cakefile index 9018b8b16b..94a3bea3b6 100644 --- a/Cakefile +++ b/Cakefile @@ -387,6 +387,7 @@ task 'bench', 'quick benchmark of compilation time', -> console.log "Compile#{time()} (#{js.length} chars)" console.log "total #{ fmt total }" + # Run the CoffeeScript test suite. runTests = (CoffeeScript) -> CoffeeScript.register() unless global.testingBrowser @@ -451,9 +452,8 @@ runTests = (CoffeeScript) -> return # Run every test in the `test` folder, recording failures. - files = - fs.readdirSync 'test' - .filter featuresPresentFor + files = fs.readdirSync 'test' + .filter featuresPresentFor startTime = Date.now() for file in files when helpers.isCoffee file