[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] master 2a904e0 057/110: Implement object literal rest/spread (...
From: |
Dmitry Gutov |
Subject: |
[elpa] master 2a904e0 057/110: Implement object literal rest/spread (...) |
Date: |
Thu, 23 Jun 2016 01:12:57 +0000 (UTC) |
branch: master
commit 2a904e08fe3e009409ccfb8f928fab43f7efaeed
Author: David Greenspan <address@hidden>
Commit: David Greenspan <address@hidden>
Implement object literal rest/spread (...)
As discussed in #245, this syntax is not part of ES6/2015, but it is
a stage 2 proposal, meaning the committee expects it to be included
in the standard. It's already seeing heavy use by e.g. the React
community.
This change causes `...expr` in an object literal to be parsed as a
unary-node element of an object-node, and modifies places where an
element of an object-node is expected to be an infix-node. Note that
only weak typing assumptions are made already about object-node elems.
In addition, this change implements proper name extraction in
object literal destructuring. The cases are:
1. `let {a} = x;`
2. `let {a: b} = x;` (should define `b`)
3. `let {a = b} = x;` (should define `a`)
4. `let {...a} = x;` (should define `a`)
This change fixes case (2), which was broken, and adds case (4).
---
js2-mode.el | 85 +++++++++++++++++++++++++++++++++----------------------
tests/parser.el | 6 ++++
2 files changed, 57 insertions(+), 34 deletions(-)
diff --git a/js2-mode.el b/js2-mode.el
index 4ad9c6a..22442b9 100644
--- a/js2-mode.el
+++ b/js2-mode.el
@@ -7445,22 +7445,23 @@ We do a depth-first traversal of NODE. For any
functions we find,
we append the property name to QNAME, then call `js2-record-imenu-entry'."
(let (right)
(dolist (e (js2-object-node-elems node)) ; e is a `js2-object-prop-node'
- (let ((left (js2-infix-node-left e))
- ;; Element positions are relative to the parent position.
- (pos (+ pos (js2-node-pos e))))
- (cond
- ;; foo: function() {...}
- ((js2-function-node-p (setq right (js2-infix-node-right e)))
- (when (js2-prop-node-name left)
- ;; As a policy decision, we record the position of the property,
- ;; not the position of the `function' keyword, since the property
- ;; is effectively the name of the function.
- (js2-record-imenu-entry right (append qname (list left)) pos)))
- ;; foo: {object-literal} -- add foo to qname, offset position, and
recurse
- ((js2-object-node-p right)
- (js2-record-object-literal right
- (append qname (list (js2-infix-node-left
e)))
- (+ pos (js2-node-pos right)))))))))
+ (when (js2-infix-node-p e)
+ (let ((left (js2-infix-node-left e))
+ ;; Element positions are relative to the parent position.
+ (pos (+ pos (js2-node-pos e))))
+ (cond
+ ;; foo: function() {...}
+ ((js2-function-node-p (setq right (js2-infix-node-right e)))
+ (when (js2-prop-node-name left)
+ ;; As a policy decision, we record the position of the property,
+ ;; not the position of the `function' keyword, since the property
+ ;; is effectively the name of the function.
+ (js2-record-imenu-entry right (append qname (list left)) pos)))
+ ;; foo: {object-literal} -- add foo to qname, offset position, and
recurse
+ ((js2-object-node-p right)
+ (js2-record-object-literal right
+ (append qname (list
(js2-infix-node-left e)))
+ (+ pos (js2-node-pos right))))))))))
(defun js2-node-top-level-decl-p (node)
"Return t if NODE's name is defined in the top-level scope.
@@ -8068,13 +8069,20 @@ declared; probably to check them for errors."
(list node)))
((js2-object-node-p node)
(dolist (elem (js2-object-node-elems node))
- ;; js2-infix-node-p catches both object prop node and initialized
- ;; binding element (which is directly an infix node).
- (when (js2-infix-node-p elem)
- (push (js2-define-destruct-symbols
- (js2-infix-node-left elem)
- decl-type face ignore-not-in-block)
- name-nodes)))
+ (let ((subexpr (cond
+ ((and (js2-infix-node-p elem)
+ (= js2-ASSIGN (js2-infix-node-type elem)))
+ (js2-infix-node-left elem))
+ ((and (js2-infix-node-p elem)
+ (= js2-COLON (js2-infix-node-type elem)))
+ (js2-infix-node-right elem))
+ ((and (js2-unary-node-p elem)
+ (= js2-TRIPLEDOT (js2-unary-node-type elem)))
+ (js2-unary-node-operand elem)))))
+ (when subexpr
+ (push (js2-define-destruct-symbols
+ subexpr decl-type face ignore-not-in-block)
+ name-nodes))))
(apply #'append (nreverse name-nodes)))
((js2-array-node-p node)
(dolist (elem (js2-array-node-elems node))
@@ -10700,16 +10708,19 @@ If ONLY-OF-P is non-nil, only the 'for (foo of bar)'
form is allowed."
`js2-method-node') as a string, or nil if it can't be
represented as a string (e.g., the key is computed by an
expression)."
- (let ((key (js2-infix-node-left property-node)))
- (when (js2-computed-prop-name-node-p key)
- (setq key (js2-computed-prop-name-node-expr key)))
- (cond
- ((js2-name-node-p key)
- (js2-name-node-name key))
- ((js2-string-node-p key)
- (js2-string-node-value key))
- ((js2-number-node-p key)
- (js2-number-node-value key)))))
+ (cond
+ ((js2-unary-node-p property-node) nil) ;; {...foo}
+ (t
+ (let ((key (js2-infix-node-left property-node)))
+ (when (js2-computed-prop-name-node-p key)
+ (setq key (js2-computed-prop-name-node-expr key)))
+ (cond
+ ((js2-name-node-p key)
+ (js2-name-node-name key))
+ ((js2-string-node-p key)
+ (js2-string-node-value key))
+ ((js2-number-node-p key)
+ (js2-number-node-value key)))))))
(defun js2-parse-object-literal-elems (&optional class-p)
(let ((pos (js2-current-token-beg))
@@ -10744,7 +10755,13 @@ expression)."
(setq previous-token (js2-current-token)
tt (js2-get-prop-name-token))))
(cond
- ;; Found a property (of any sort)
+ ;; Rest/spread (...expr)
+ ((and (>= js2-language-version 200)
+ (not class-p) (not static) (not previous-token)
+ (= js2-TRIPLEDOT tt))
+ (setq after-comma nil
+ elem (js2-make-unary js2-TRIPLEDOT 'js2-parse-assign-expr)))
+ ;; Found a key/value property (of any sort)
((member tt (list js2-NAME js2-STRING js2-NUMBER js2-LB))
(setq after-comma nil
elem (js2-parse-named-prop tt pos previous-token))
diff --git a/tests/parser.el b/tests/parser.el
index 5e19c5b..ea3584a 100644
--- a/tests/parser.el
+++ b/tests/parser.el
@@ -368,6 +368,12 @@ the test."
(js2-deftest-parse array-destructure-expr-default
"let [[x] = [3]] = y;")
+(js2-deftest-parse spread-in-object-literal
+ "f({x, y, ...z});")
+
+(js2-deftest-parse rest-in-object-literal
+ "const {x, y, ...z} = f();")
+
;;; Arrow functions
(js2-deftest-parse arrow-function-with-empty-args-and-no-curlies
- [elpa] master 0b1704b 041/110: Merge pull request #284 from XeCycle/0o-octals, (continued)
- [elpa] master 0b1704b 041/110: Merge pull request #284 from XeCycle/0o-octals, Dmitry Gutov, 2016/06/22
- [elpa] master 7abe15e 043/110: Merge pull request #285 from dgreensp/fix-param-destruct, Dmitry Gutov, 2016/06/22
- [elpa] master 38aa66b 054/110: Do not print trailing semicolon for export function and class, Dmitry Gutov, 2016/06/22
- [elpa] master 4cd81c7 050/110: Exported decls print a little funny; update tests, Dmitry Gutov, 2016/06/22
- [elpa] master 00a455f 009/110: Merge pull request #266 from jacksonrayhamilton/no-getter-setter-duplicate, Dmitry Gutov, 2016/06/22
- [elpa] master 4894200 056/110: Merge pull request #290 from XeCycle/export-async-fn, Dmitry Gutov, 2016/06/22
- [elpa] master 027d546 051/110: Merge pull request #287 from dgreensp/fix-export-decls, Dmitry Gutov, 2016/06/22
- [elpa] master 13f0ffb 042/110: Fix parsing of param with destructure and default, Dmitry Gutov, 2016/06/22
- [elpa] master e48e862 055/110: Also parse async function statement in export node, Dmitry Gutov, 2016/06/22
- [elpa] master e9227bd 058/110: Fix a byte-compilation warning, Dmitry Gutov, 2016/06/22
- [elpa] master 2a904e0 057/110: Implement object literal rest/spread (...),
Dmitry Gutov <=
- [elpa] master 8047d7f 061/110: Recognize for-of and for-in loops with const, Dmitry Gutov, 2016/06/22
- [elpa] master 983f20a 072/110: Fix typo, Dmitry Gutov, 2016/06/22
- [elpa] master f8248df 066/110: Record class declarations for IMenu, Dmitry Gutov, 2016/06/22
- [elpa] master d92e772 069/110: Fix async parsing, Dmitry Gutov, 2016/06/22
- [elpa] master 5c97dce 002/110: Fix typo; Refs #185, Dmitry Gutov, 2016/06/22
- [elpa] master 97065c8 075/110: Fix compiler warning, Dmitry Gutov, 2016/06/22
- [elpa] master 849e061 081/110: js2-indent-operator-re, js2-declaration-keyword-re: Use symbols boundaries, Dmitry Gutov, 2016/06/22
- [elpa] master b2af331 083/110: Special-case unary + and -, Dmitry Gutov, 2016/06/22
- [elpa] master 7e7b6da 076/110: Simplify await parsing, Dmitry Gutov, 2016/06/22
- [elpa] master b57d129 077/110: Merge pull request #304 from jacksonrayhamilton/fix-void-async-await, Dmitry Gutov, 2016/06/22