(defvar js2-COMMENT 160)
(defvar js2-ENUM 161) ; for "enum" reserved word
+(defvar js2-TRIPLEDOT 162) ; for rest parameter
-(defconst js2-num-tokens (1+ js2-ENUM))
+(defconst js2-num-tokens (1+ js2-TRIPLEDOT))
(defconst js2-debug-print-trees nil)
(js2-msg "msg.no.default.after.default.param" ; added by js2-mode
"parameter without default follows parameter with default")
+(js2-msg "msg.param.after.rest" ; added by js2-mode
+ "parameter after rest parameter")
+
(js2-msg "msg.no.brace.body"
"missing '{' before function body")
(form 'FUNCTION_STATEMENT)
(name "")
params
+ rest-p
body
lp
rp)))
form ; FUNCTION_{STATEMENT|EXPRESSION|EXPRESSION_STATEMENT}
name ; function name (a `js2-name-node', or nil if anonymous)
params ; a lisp list of destructuring forms or simple name nodes
+ rest-p ; if t, the last
body ; a `js2-block-node' or expression node (1.8 only)
lp ; position of arg-list open-paren, or nil if omitted
rp ; position of arg-list close-paren, or nil if omitted
(getter (js2-node-get-prop n 'GETTER_SETTER))
(name (js2-function-node-name n))
(params (js2-function-node-params n))
+ (rest-p (js2-function-node-rest-p n))
(body (js2-function-node-body n))
(expr (eq (js2-function-node-form n) 'FUNCTION_EXPRESSION)))
(unless getter
for param in params
for count from 1
do
+ (when (and rest-p (= count len))
+ (insert "..."))
(js2-print-ast param 0)
- (if (< count len)
- (insert ", ")))
+ (when (< count len)
+ (insert ", ")))
(insert ") {")
(unless expr
(insert "\n"))
(throw 'return js2-COLON)))
(?.
(if (js2-match-char ?.)
- (js2-ts-return js2-DOTDOT)
+ (if (js2-match-char ?.)
+ (js2-ts-return js2-TRIPLEDOT)
+ (js2-ts-return js2-DOTDOT))
(if (js2-match-char ?\()
(js2-ts-return js2-DOTQUERY)
(throw 'return js2-DOT))))
(defun js2-parse-function-params (fn-node pos)
(if (js2-match-token js2-RP)
(setf (js2-function-node-rp fn-node) (- js2-token-beg pos))
- (let (params len param default-found)
+ (let (params len param default-found rest-param-at)
(loop for tt = (js2-peek-token)
do
(cond
(push param params))
;; variable name
(t
+ (when (and (>= js2-language-version 200)
+ (js2-match-token js2-TRIPLEDOT)
+ (not rest-param-at))
+ ;; to report errors if there are more parameters
+ (setq rest-param-at (length params)))
(js2-must-match js2-NAME "msg.no.parm")
(js2-record-face 'js2-function-param-face)
(setq param (js2-create-name-node))
(js2-define-symbol js2-LP js2-ts-string param)
;; default parameter value
(when (or (and default-found
+ (not rest-param-at)
(js2-must-match js2-ASSIGN
"msg.no.default.after.default.param"
(js2-node-pos param)
default-found t)
(js2-node-add-children param left right)))
(push param params)))
+ (when (and rest-param-at (> (length params) (1+ rest-param-at)))
+ (js2-report-error "msg.param.after.rest" nil
+ (js2-node-pos param) (js2-node-len param)))
while
(js2-match-token js2-COMMA))
- (if (js2-must-match js2-RP "msg.no.paren.after.parms")
- (setf (js2-function-node-rp fn-node) (- js2-token-beg pos)))
+ (when (js2-must-match js2-RP "msg.no.paren.after.parms")
+ (setf (js2-function-node-rp fn-node) (- js2-token-beg pos)))
+ (when rest-param-at
+ (setf (js2-function-node-rest-p fn-node) t))
(dolist (p params)
(js2-node-add-children fn-node p)
(push p (js2-function-node-params fn-node))))))
(destructuring-bind (_ pos len) (first errors)\r
(should (string= syntax-error (substring code-string\r
(1- pos) (+ pos len -1))))))\r
+ (should (= 0 (length (js2-ast-root-errors ast))))\r
(ert-with-test-buffer (:name 'copy)\r
(js2-print-tree ast)\r
(skip-chars-backward " \t\n")\r
"[a + b for ([a, b] in [[0, 1], [1, 2]])];")\r
\r
(js2-deftest-ast destruct-in-catch-clause\r
- "try {\n} catch ({a, b}) {\n return a + b;\n}")\r
+ "try {\n} catch ({a, b}) {\n a + b;\n}")\r
\r
-;;; Function arguments.\r
+;;; Function parameters.\r
\r
(js2-deftest-ast function-with-default-parameters\r
"function foo(a = 1, b = a + 1) {\n}")\r
(js2-deftest-ast function-with-destruct-after-default\r
"function foo(a = 1, {b, c}) {\n}"\r
:syntax-error "{")\r
+\r
+(js2-deftest-ast function-with-rest-parameter\r
+ "function foo(a, b, ...rest) {\n}")\r
+\r
+(js2-deftest-ast function-with-param-after-rest-parameter\r
+ "function foo(a, ...b, rest) {\n}"\r
+ :syntax-error "rest")\r
+\r
+(js2-deftest-ast function-with-destruct-after-rest-parameter\r
+ "function foo(a, ...b, {}) {\n}"\r
+ :syntax-error "{}")\r
+\r
+(js2-deftest-ast function-with-rest-after-default-parameter\r
+ "function foo(a = 1, ...rest) {\n}")\r