|
|
|
|
@@ -1,13 +1,13 @@
|
|
|
|
|
;;; js2-mode.el --- Improved JavaScript editing mode -*- lexical-binding: t -*-
|
|
|
|
|
|
|
|
|
|
;; Copyright (C) 2009, 2011-2018 Free Software Foundation, Inc.
|
|
|
|
|
;; Copyright (C) 2009, 2011-2020 Free Software Foundation, Inc.
|
|
|
|
|
|
|
|
|
|
;; Author: Steve Yegge <steve.yegge@gmail.com>
|
|
|
|
|
;; mooz <stillpedant@gmail.com>
|
|
|
|
|
;; Dmitry Gutov <dgutov@yandex.ru>
|
|
|
|
|
;; URL: https://github.com/mooz/js2-mode/
|
|
|
|
|
;; http://code.google.com/p/js2-mode/
|
|
|
|
|
;; Version: 20190219
|
|
|
|
|
;; Version: 20201220
|
|
|
|
|
;; Keywords: languages, javascript
|
|
|
|
|
;; Package-Requires: ((emacs "24.1") (cl-lib "0.5"))
|
|
|
|
|
|
|
|
|
|
@@ -285,7 +285,7 @@ If `js2-dynamic-idle-timer-adjust' is 0 or negative,
|
|
|
|
|
|
|
|
|
|
(defcustom js2-concat-multiline-strings t
|
|
|
|
|
"When non-nil, `js2-line-break' in mid-string will make it a
|
|
|
|
|
string concatenation. When `eol', the '+' will be inserted at the
|
|
|
|
|
string concatenation. When `eol', the `+' will be inserted at the
|
|
|
|
|
end of the line, otherwise, at the beginning of the next line."
|
|
|
|
|
:type '(choice (const t) (const eol) (const nil))
|
|
|
|
|
:group 'js2-mode)
|
|
|
|
|
@@ -338,10 +338,10 @@ interferes with type inference (in systems that support it.)"
|
|
|
|
|
:group 'js2-mode)
|
|
|
|
|
|
|
|
|
|
(defcustom js2-strict-cond-assign-warning t
|
|
|
|
|
"Non-nil to warn about expressions like if (a = b).
|
|
|
|
|
This often should have been '==' instead of '='. If the warning
|
|
|
|
|
"Non-nil to warn about usage like `if (a = b)'.
|
|
|
|
|
This often should have been `==' instead of `='. If the warning
|
|
|
|
|
is enabled, you can suppress it on a per-expression basis by
|
|
|
|
|
parenthesizing the expression, e.g. if ((a = b)) ..."
|
|
|
|
|
parenthesizing the expression, e.g., `if ((a = b)) ...'."
|
|
|
|
|
:type 'boolean
|
|
|
|
|
:group 'js2-mode)
|
|
|
|
|
|
|
|
|
|
@@ -422,7 +422,7 @@ setting `allowMemberExprAsFunctionName'. The experimental syntax is:
|
|
|
|
|
|
|
|
|
|
function <member-expr> ( [ arg-list ] ) { <body> }
|
|
|
|
|
|
|
|
|
|
Where member-expr is a non-parenthesized 'member expression', which
|
|
|
|
|
Where member-expr is a non-parenthesized `member expression', which
|
|
|
|
|
is anything at the grammar level of a new-expression or lower, meaning
|
|
|
|
|
any expression that does not involve infix or unary operators.
|
|
|
|
|
|
|
|
|
|
@@ -564,96 +564,100 @@ which doesn't seem particularly useful, but Rhino permits it."
|
|
|
|
|
(defvar js2-ASSIGN_MUL 98) ; *=
|
|
|
|
|
(defvar js2-ASSIGN_DIV 99) ; /=
|
|
|
|
|
(defvar js2-ASSIGN_MOD 100) ; %=
|
|
|
|
|
(defvar js2-ASSIGN_EXPON 101)
|
|
|
|
|
(defvar js2-ASSIGN_EXPON 101) ; **=
|
|
|
|
|
(defvar js2-ASSIGN_AND 102) ; &&=
|
|
|
|
|
(defvar js2-ASSIGN_OR 103) ; ||=
|
|
|
|
|
(defvar js2-ASSIGN_NULLISH 104) ; ??=
|
|
|
|
|
|
|
|
|
|
(defvar js2-first-assign js2-ASSIGN)
|
|
|
|
|
(defvar js2-last-assign js2-ASSIGN_EXPON)
|
|
|
|
|
(defvar js2-last-assign js2-ASSIGN_NULLISH)
|
|
|
|
|
|
|
|
|
|
(defvar js2-COLON 102)
|
|
|
|
|
(defvar js2-OR 103) ; logical or (||)
|
|
|
|
|
(defvar js2-AND 104) ; logical and (&&)
|
|
|
|
|
(defvar js2-INC 105) ; increment/decrement (++ --)
|
|
|
|
|
(defvar js2-DEC 106)
|
|
|
|
|
(defvar js2-DOT 107) ; member operator (.)
|
|
|
|
|
(defvar js2-FUNCTION 108) ; function keyword
|
|
|
|
|
(defvar js2-EXPORT 109) ; export keyword
|
|
|
|
|
(defvar js2-IMPORT 110) ; import keyword
|
|
|
|
|
(defvar js2-IF 111) ; if keyword
|
|
|
|
|
(defvar js2-ELSE 112) ; else keyword
|
|
|
|
|
(defvar js2-SWITCH 113) ; switch keyword
|
|
|
|
|
(defvar js2-CASE 114) ; case keyword
|
|
|
|
|
(defvar js2-DEFAULT 115) ; default keyword
|
|
|
|
|
(defvar js2-WHILE 116) ; while keyword
|
|
|
|
|
(defvar js2-DO 117) ; do keyword
|
|
|
|
|
(defvar js2-FOR 118) ; for keyword
|
|
|
|
|
(defvar js2-BREAK 119) ; break keyword
|
|
|
|
|
(defvar js2-CONTINUE 120) ; continue keyword
|
|
|
|
|
(defvar js2-VAR 121) ; var keyword
|
|
|
|
|
(defvar js2-WITH 122) ; with keyword
|
|
|
|
|
(defvar js2-CATCH 123) ; catch keyword
|
|
|
|
|
(defvar js2-FINALLY 124) ; finally keyword
|
|
|
|
|
(defvar js2-VOID 125) ; void keyword
|
|
|
|
|
(defvar js2-RESERVED 126) ; reserved keywords
|
|
|
|
|
(defvar js2-COLON 105)
|
|
|
|
|
(defvar js2-OR 106) ; logical or (||)
|
|
|
|
|
(defvar js2-AND 107) ; logical and (&&)
|
|
|
|
|
(defvar js2-INC 108) ; increment/decrement (++ --)
|
|
|
|
|
(defvar js2-DEC 109)
|
|
|
|
|
(defvar js2-DOT 110) ; member operator (.)
|
|
|
|
|
(defvar js2-FUNCTION 111) ; function keyword
|
|
|
|
|
(defvar js2-EXPORT 112) ; export keyword
|
|
|
|
|
(defvar js2-IMPORT 113) ; import keyword
|
|
|
|
|
(defvar js2-IF 114) ; if keyword
|
|
|
|
|
(defvar js2-ELSE 115) ; else keyword
|
|
|
|
|
(defvar js2-SWITCH 116) ; switch keyword
|
|
|
|
|
(defvar js2-CASE 117) ; case keyword
|
|
|
|
|
(defvar js2-DEFAULT 118) ; default keyword
|
|
|
|
|
(defvar js2-WHILE 119) ; while keyword
|
|
|
|
|
(defvar js2-DO 120) ; do keyword
|
|
|
|
|
(defvar js2-FOR 121) ; for keyword
|
|
|
|
|
(defvar js2-BREAK 122) ; break keyword
|
|
|
|
|
(defvar js2-CONTINUE 123) ; continue keyword
|
|
|
|
|
(defvar js2-VAR 124) ; var keyword
|
|
|
|
|
(defvar js2-WITH 125) ; with keyword
|
|
|
|
|
(defvar js2-CATCH 126) ; catch keyword
|
|
|
|
|
(defvar js2-FINALLY 127) ; finally keyword
|
|
|
|
|
(defvar js2-VOID 128) ; void keyword
|
|
|
|
|
(defvar js2-RESERVED 129) ; reserved keywords
|
|
|
|
|
|
|
|
|
|
(defvar js2-EMPTY 127)
|
|
|
|
|
(defvar js2-EMPTY 130)
|
|
|
|
|
|
|
|
|
|
;; Types used for the parse tree - never returned by scanner.
|
|
|
|
|
|
|
|
|
|
(defvar js2-BLOCK 128) ; statement block
|
|
|
|
|
(defvar js2-LABEL 129) ; label
|
|
|
|
|
(defvar js2-TARGET 130)
|
|
|
|
|
(defvar js2-LOOP 131)
|
|
|
|
|
(defvar js2-EXPR_VOID 132) ; expression statement in functions
|
|
|
|
|
(defvar js2-EXPR_RESULT 133) ; expression statement in scripts
|
|
|
|
|
(defvar js2-JSR 134)
|
|
|
|
|
(defvar js2-SCRIPT 135) ; top-level node for entire script
|
|
|
|
|
(defvar js2-TYPEOFNAME 136) ; for typeof(simple-name)
|
|
|
|
|
(defvar js2-USE_STACK 137)
|
|
|
|
|
(defvar js2-SETPROP_OP 138) ; x.y op= something
|
|
|
|
|
(defvar js2-SETELEM_OP 139) ; x[y] op= something
|
|
|
|
|
(defvar js2-LOCAL_BLOCK 140)
|
|
|
|
|
(defvar js2-SET_REF_OP 141) ; *reference op= something
|
|
|
|
|
(defvar js2-BLOCK 131) ; statement block
|
|
|
|
|
(defvar js2-LABEL 132) ; label
|
|
|
|
|
(defvar js2-TARGET 133)
|
|
|
|
|
(defvar js2-LOOP 134)
|
|
|
|
|
(defvar js2-EXPR_VOID 135) ; expression statement in functions
|
|
|
|
|
(defvar js2-EXPR_RESULT 136) ; expression statement in scripts
|
|
|
|
|
(defvar js2-JSR 137)
|
|
|
|
|
(defvar js2-SCRIPT 138) ; top-level node for entire script
|
|
|
|
|
(defvar js2-TYPEOFNAME 139) ; for typeof(simple-name)
|
|
|
|
|
(defvar js2-USE_STACK 140)
|
|
|
|
|
(defvar js2-SETPROP_OP 141) ; x.y op= something
|
|
|
|
|
(defvar js2-SETELEM_OP 142) ; x[y] op= something
|
|
|
|
|
(defvar js2-LOCAL_BLOCK 143)
|
|
|
|
|
(defvar js2-SET_REF_OP 144) ; *reference op= something
|
|
|
|
|
|
|
|
|
|
;; For XML support:
|
|
|
|
|
(defvar js2-DOTDOT 142) ; member operator (..)
|
|
|
|
|
(defvar js2-COLONCOLON 143) ; namespace::name
|
|
|
|
|
(defvar js2-XML 144) ; XML type
|
|
|
|
|
(defvar js2-DOTQUERY 145) ; .() -- e.g., x.emps.emp.(name == "terry")
|
|
|
|
|
(defvar js2-XMLATTR 146) ; @
|
|
|
|
|
(defvar js2-XMLEND 147)
|
|
|
|
|
(defvar js2-DOTDOT 145) ; member operator (..)
|
|
|
|
|
(defvar js2-COLONCOLON 146) ; namespace::name
|
|
|
|
|
(defvar js2-XML 147) ; XML type
|
|
|
|
|
(defvar js2-DOTQUERY 148) ; .() -- e.g., x.emps.emp.(name == "terry")
|
|
|
|
|
(defvar js2-XMLATTR 149) ; @
|
|
|
|
|
(defvar js2-XMLEND 150)
|
|
|
|
|
|
|
|
|
|
;; Optimizer-only tokens
|
|
|
|
|
(defvar js2-TO_OBJECT 148)
|
|
|
|
|
(defvar js2-TO_DOUBLE 149)
|
|
|
|
|
(defvar js2-TO_OBJECT 151)
|
|
|
|
|
(defvar js2-TO_DOUBLE 152)
|
|
|
|
|
|
|
|
|
|
(defvar js2-GET 150) ; JS 1.5 get pseudo keyword
|
|
|
|
|
(defvar js2-SET 151) ; JS 1.5 set pseudo keyword
|
|
|
|
|
(defvar js2-LET 152) ; JS 1.7 let pseudo keyword
|
|
|
|
|
(defvar js2-CONST 153)
|
|
|
|
|
(defvar js2-SETCONST 154)
|
|
|
|
|
(defvar js2-SETCONSTVAR 155)
|
|
|
|
|
(defvar js2-ARRAYCOMP 156)
|
|
|
|
|
(defvar js2-LETEXPR 157)
|
|
|
|
|
(defvar js2-WITHEXPR 158)
|
|
|
|
|
(defvar js2-DEBUGGER 159)
|
|
|
|
|
(defvar js2-GET 153) ; JS 1.5 get pseudo keyword
|
|
|
|
|
(defvar js2-SET 154) ; JS 1.5 set pseudo keyword
|
|
|
|
|
(defvar js2-LET 155) ; JS 1.7 let pseudo keyword
|
|
|
|
|
(defvar js2-CONST 156)
|
|
|
|
|
(defvar js2-SETCONST 157)
|
|
|
|
|
(defvar js2-SETCONSTVAR 158)
|
|
|
|
|
(defvar js2-ARRAYCOMP 159)
|
|
|
|
|
(defvar js2-LETEXPR 160)
|
|
|
|
|
(defvar js2-WITHEXPR 161)
|
|
|
|
|
(defvar js2-DEBUGGER 162)
|
|
|
|
|
|
|
|
|
|
(defvar js2-COMMENT 160)
|
|
|
|
|
(defvar js2-TRIPLEDOT 161) ; for rest parameter
|
|
|
|
|
(defvar js2-ARROW 162) ; function arrow (=>)
|
|
|
|
|
(defvar js2-CLASS 163)
|
|
|
|
|
(defvar js2-EXTENDS 164)
|
|
|
|
|
(defvar js2-SUPER 165)
|
|
|
|
|
(defvar js2-TEMPLATE_HEAD 166) ; part of template literal before substitution
|
|
|
|
|
(defvar js2-NO_SUBS_TEMPLATE 167) ; template literal without substitutions
|
|
|
|
|
(defvar js2-TAGGED_TEMPLATE 168) ; tagged template literal
|
|
|
|
|
(defvar js2-COMMENT 163)
|
|
|
|
|
(defvar js2-TRIPLEDOT 164) ; for rest parameter
|
|
|
|
|
(defvar js2-ARROW 165) ; function arrow (=>)
|
|
|
|
|
(defvar js2-CLASS 166)
|
|
|
|
|
(defvar js2-EXTENDS 167)
|
|
|
|
|
(defvar js2-SUPER 168)
|
|
|
|
|
(defvar js2-TEMPLATE_HEAD 169) ; part of template literal before substitution
|
|
|
|
|
(defvar js2-NO_SUBS_TEMPLATE 170) ; template literal without substitutions
|
|
|
|
|
(defvar js2-TAGGED_TEMPLATE 171) ; tagged template literal
|
|
|
|
|
|
|
|
|
|
(defvar js2-AWAIT 169) ; await (pseudo keyword)
|
|
|
|
|
(defvar js2-AWAIT 172) ; await (pseudo keyword)
|
|
|
|
|
|
|
|
|
|
(defvar js2-HOOK 170) ; conditional (?:)
|
|
|
|
|
(defvar js2-OPTIONAL-CHAINING 171) ; optional chaining (?.prop obj?.[expr] func?.())
|
|
|
|
|
(defvar js2-EXPON 172)
|
|
|
|
|
(defvar js2-HOOK 173) ; conditional (?:)
|
|
|
|
|
(defvar js2-OPTIONAL-CHAINING 174) ; optional chaining (?.prop obj?.[expr] func?.())
|
|
|
|
|
(defvar js2-EXPON 175)
|
|
|
|
|
(defvar js2-NULLISH-COALESCING 176) ; nullish coalescing (obj.value ?? obj.defaultValue ?? 0))
|
|
|
|
|
|
|
|
|
|
(defconst js2-num-tokens (1+ js2-EXPON))
|
|
|
|
|
(defconst js2-num-tokens (1+ js2-NULLISH-COALESCING))
|
|
|
|
|
|
|
|
|
|
(defconst js2-debug-print-trees nil)
|
|
|
|
|
|
|
|
|
|
@@ -2759,7 +2763,7 @@ It contains a local-name node which is the name of the value in the
|
|
|
|
|
current scope, and extern-name which is the name of the value in the
|
|
|
|
|
imported or exported scope. By default these are the same, but if the
|
|
|
|
|
name is aliased as in {foo as bar}, it would have an extern-name node
|
|
|
|
|
containing 'foo' and a local-name node containing 'bar'."
|
|
|
|
|
containing `foo' and a local-name node containing `bar'."
|
|
|
|
|
local-name ; js2-name-node with the variable name in this scope
|
|
|
|
|
extern-name) ; js2-name-node with the value name in the exporting module
|
|
|
|
|
|
|
|
|
|
@@ -2777,8 +2781,8 @@ different, visit the extern-name."
|
|
|
|
|
(js2-visit-ast extern-name v))))
|
|
|
|
|
|
|
|
|
|
(defun js2-print-extern-binding (n _i)
|
|
|
|
|
"Print a representation of a single extern binding. E.g. 'foo' or
|
|
|
|
|
'foo as bar'."
|
|
|
|
|
"Print a representation of a single extern binding. E.g. `foo' or
|
|
|
|
|
`foo as bar'."
|
|
|
|
|
(let ((local-name (js2-export-binding-node-local-name n))
|
|
|
|
|
(extern-name (js2-export-binding-node-extern-name n)))
|
|
|
|
|
(insert (js2-name-node-name extern-name))
|
|
|
|
|
@@ -2903,9 +2907,9 @@ local context."
|
|
|
|
|
len
|
|
|
|
|
name)))
|
|
|
|
|
"AST node for a complete namespace import.
|
|
|
|
|
E.g. the '* as lib' expression in:
|
|
|
|
|
E.g. the `* as lib' expression in:
|
|
|
|
|
|
|
|
|
|
import * as lib from 'src/lib'
|
|
|
|
|
import * as lib from \\='src/lib\\='
|
|
|
|
|
|
|
|
|
|
It contains a single name node referring to the bound name."
|
|
|
|
|
name) ; js2-name-node of the bound name.
|
|
|
|
|
@@ -2924,7 +2928,7 @@ It contains a single name node referring to the bound name."
|
|
|
|
|
module-id
|
|
|
|
|
metadata-p)))
|
|
|
|
|
"AST node for the from clause in an import or export statement.
|
|
|
|
|
E.g. from 'my/module'. It can refere to either an external module, or to the
|
|
|
|
|
E.g. from \\='my/module\\='. It can refere to either an external module, or to the
|
|
|
|
|
modules metadata itself."
|
|
|
|
|
module-id ; string containing the module specifier.
|
|
|
|
|
metadata-p) ; true if this clause refers to the module's metadata
|
|
|
|
|
@@ -3223,7 +3227,7 @@ NODE is a `js2-labels-node'. LABEL is an identifier."
|
|
|
|
|
len label target)))
|
|
|
|
|
"AST node for a break statement.
|
|
|
|
|
The label field is a `js2-name-node', possibly nil, for the named label
|
|
|
|
|
if provided. E.g. in 'break foo', it represents 'foo'. The target field
|
|
|
|
|
if provided. E.g. in `break foo', it represents `foo'. The target field
|
|
|
|
|
is the target of the break - a label node or enclosing loop/switch statement.")
|
|
|
|
|
|
|
|
|
|
(js2--struct-put 'js2-break-node 'js2-visitor 'js2-visit-jump-node)
|
|
|
|
|
@@ -3482,6 +3486,7 @@ The type field inherited from `js2-node' holds the operator."
|
|
|
|
|
(cons js2-COLON ":")
|
|
|
|
|
(cons js2-OR "||")
|
|
|
|
|
(cons js2-AND "&&")
|
|
|
|
|
(cons js2-NULLISH-COALESCING "??")
|
|
|
|
|
(cons js2-INC "++")
|
|
|
|
|
(cons js2-DEC "--")
|
|
|
|
|
(cons js2-BITOR "|")
|
|
|
|
|
@@ -3521,7 +3526,10 @@ The type field inherited from `js2-node' holds the operator."
|
|
|
|
|
(cons js2-ASSIGN_MUL "*=")
|
|
|
|
|
(cons js2-ASSIGN_EXPON "**=")
|
|
|
|
|
(cons js2-ASSIGN_DIV "/=")
|
|
|
|
|
(cons js2-ASSIGN_MOD "%="))))
|
|
|
|
|
(cons js2-ASSIGN_MOD "%=")
|
|
|
|
|
(cons js2-ASSIGN_AND "&&=")
|
|
|
|
|
(cons js2-ASSIGN_OR "||=")
|
|
|
|
|
(cons js2-ASSIGN_NULLISH "??="))))
|
|
|
|
|
(cl-loop for (k . v) in tokens do
|
|
|
|
|
(puthash k v table))
|
|
|
|
|
table))
|
|
|
|
|
@@ -4270,7 +4278,7 @@ no explicit target, which is valid in certain expression contexts such as
|
|
|
|
|
|
|
|
|
|
company..employee.(@id < 100)
|
|
|
|
|
|
|
|
|
|
in this case, the @id is a `js2-xml-ref' that is part of an infix '<'
|
|
|
|
|
in this case, the @id is a `js2-xml-ref' that is part of an infix `<'
|
|
|
|
|
expression whose parent is a `js2-xml-dot-query-node'."
|
|
|
|
|
namespace
|
|
|
|
|
at-pos
|
|
|
|
|
@@ -4291,7 +4299,7 @@ expression whose parent is a `js2-xml-dot-query-node'."
|
|
|
|
|
"AST node for an E4X XML [expr] property-ref expression.
|
|
|
|
|
The JavaScript syntax is an optional @, an optional ns::, and a name.
|
|
|
|
|
|
|
|
|
|
[ '@' ] [ name '::' ] name
|
|
|
|
|
[ `@' ] [ name `::' ] name
|
|
|
|
|
|
|
|
|
|
Examples include name, ns::name, ns::*, *::name, *::*, @attr, @ns::attr,
|
|
|
|
|
@ns::*, @*::attr, @*::*, and @*.
|
|
|
|
|
@@ -4329,7 +4337,7 @@ expression."
|
|
|
|
|
"AST node for an E4X XML [expr] member-ref expression.
|
|
|
|
|
Syntax:
|
|
|
|
|
|
|
|
|
|
[ '@' ] [ name '::' ] '[' expr ']'
|
|
|
|
|
[ `@' ] [ name `::' ] `[' expr `]'
|
|
|
|
|
|
|
|
|
|
Examples include ns::[expr], @ns::[expr], @[expr], *::[expr] and @*::[expr].
|
|
|
|
|
|
|
|
|
|
@@ -4494,7 +4502,7 @@ For a simple name, the kids list has exactly one node, a `js2-name-node'."
|
|
|
|
|
(pos js2-ts-cursor)
|
|
|
|
|
len name value
|
|
|
|
|
eq-pos quote-type)))
|
|
|
|
|
"AST node representing a foo='bar' XML attribute value. Not yet used."
|
|
|
|
|
"AST node representing a foo=\\='bar\\=' XML attribute value. Not yet used."
|
|
|
|
|
name ; a `js2-xml-name-node'
|
|
|
|
|
value ; a `js2-xml-name-node'
|
|
|
|
|
eq-pos ; buffer position of "=" sign
|
|
|
|
|
@@ -5056,6 +5064,9 @@ You should use `js2-print-tree' instead of this function."
|
|
|
|
|
js2-ASSIGN_SUB
|
|
|
|
|
js2-ASSIGN_URSH
|
|
|
|
|
js2-ASSIGN_EXPON
|
|
|
|
|
js2-ASSIGN_AND
|
|
|
|
|
js2-ASSIGN_OR
|
|
|
|
|
js2-ASSIGN_NULLISH
|
|
|
|
|
js2-BLOCK
|
|
|
|
|
js2-BREAK
|
|
|
|
|
js2-CALL
|
|
|
|
|
@@ -5134,7 +5145,8 @@ You should use `js2-print-tree' instead of this function."
|
|
|
|
|
((= tt js2-COMMA)
|
|
|
|
|
(js2-node-has-side-effects (js2-infix-node-right node)))
|
|
|
|
|
((or (= tt js2-AND)
|
|
|
|
|
(= tt js2-OR))
|
|
|
|
|
(= tt js2-OR)
|
|
|
|
|
(= tt js2-NULLISH-COALESCING))
|
|
|
|
|
(or (js2-node-has-side-effects (js2-infix-node-right node))
|
|
|
|
|
(js2-node-has-side-effects (js2-infix-node-left node))))
|
|
|
|
|
((= tt js2-HOOK)
|
|
|
|
|
@@ -5446,7 +5458,7 @@ Returns logical OR of END_* flags"
|
|
|
|
|
|
|
|
|
|
(defun js2-always-defined-boolean-p (node)
|
|
|
|
|
"Check if NODE always evaluates to true or false in boolean context.
|
|
|
|
|
Returns 'ALWAYS_TRUE, 'ALWAYS_FALSE, or nil if it's neither always true
|
|
|
|
|
Returns `ALWAYS_TRUE', `ALWAYS_FALSE', or nil if it's neither always true
|
|
|
|
|
nor always false."
|
|
|
|
|
(let ((tt (js2-node-type node))
|
|
|
|
|
num)
|
|
|
|
|
@@ -5501,7 +5513,7 @@ Signals an error if it's not a recognized token."
|
|
|
|
|
(error "Invalid token: %s" code)))))
|
|
|
|
|
|
|
|
|
|
(defsubst js2-tt-sym (tok)
|
|
|
|
|
"Return symbol for TOK given its code, e.g. 'js2-LP for code 86."
|
|
|
|
|
"Return symbol for TOK given its code, e.g. `js2-LP' for code 86."
|
|
|
|
|
(intern (js2-tt-name tok)))
|
|
|
|
|
|
|
|
|
|
(defconst js2-token-codes
|
|
|
|
|
@@ -5516,7 +5528,7 @@ Signals an error if it's not a recognized token."
|
|
|
|
|
"Hashtable mapping token type symbols to their bytecodes.")
|
|
|
|
|
|
|
|
|
|
(defsubst js2-tt-code (sym)
|
|
|
|
|
"Return code for token symbol SYM, e.g. 86 for 'js2-LP."
|
|
|
|
|
"Return code for token symbol SYM, e.g. 86 for `js2-LP'."
|
|
|
|
|
(or (gethash sym js2-token-codes)
|
|
|
|
|
(error "Invalid token symbol: %s " sym))) ; signal code bug
|
|
|
|
|
|
|
|
|
|
@@ -5570,7 +5582,7 @@ Also updates `js2-ts-hit-eof' and `js2-ts-line-start' as needed."
|
|
|
|
|
|
|
|
|
|
(defun js2-read-unicode-escape ()
|
|
|
|
|
"Read a \\uNNNN sequence from the input.
|
|
|
|
|
Assumes the ?\ and ?u have already been read.
|
|
|
|
|
Assumes the ?\\ and ?u have already been read.
|
|
|
|
|
Returns the unicode character, or nil if it wasn't a valid character.
|
|
|
|
|
Doesn't change the values of any scanner variables."
|
|
|
|
|
;; I really wish I knew a better way to do this, but I can't
|
|
|
|
|
@@ -5762,7 +5774,7 @@ The values are default faces to use for highlighting the keywords.")
|
|
|
|
|
do
|
|
|
|
|
(puthash (symbol-name k) 'js2-RESERVED table))
|
|
|
|
|
table)
|
|
|
|
|
"JavaScript reserved words by name, mapped to 'js2-RESERVED.")
|
|
|
|
|
"JavaScript reserved words by name, mapped to `js2-RESERVED'.")
|
|
|
|
|
|
|
|
|
|
(defun js2-collect-string (buf)
|
|
|
|
|
"Convert BUF, a list of chars, to a string.
|
|
|
|
|
@@ -5773,7 +5785,7 @@ Reverses BUF before converting."
|
|
|
|
|
|
|
|
|
|
(defun js2-string-to-keyword (s)
|
|
|
|
|
"Return token for S, a string, if S is a keyword or reserved word.
|
|
|
|
|
Returns a symbol such as 'js2-BREAK, or nil if not keyword/reserved."
|
|
|
|
|
Returns a symbol such as `js2-BREAK', or nil if not keyword/reserved."
|
|
|
|
|
(or (gethash s js2-keyword-names)
|
|
|
|
|
(gethash s js2-reserved-word-names)))
|
|
|
|
|
|
|
|
|
|
@@ -6093,9 +6105,13 @@ its relevant fields and puts it into `js2-ti-tokens'."
|
|
|
|
|
(?,
|
|
|
|
|
(throw 'return js2-COMMA))
|
|
|
|
|
(??
|
|
|
|
|
(if (js2-match-char ?.)
|
|
|
|
|
(throw 'return js2-OPTIONAL-CHAINING)
|
|
|
|
|
(throw 'return js2-HOOK)))
|
|
|
|
|
(if (js2-match-char ??)
|
|
|
|
|
(if (js2-match-char ?=)
|
|
|
|
|
js2-ASSIGN_NULLISH
|
|
|
|
|
(throw 'return js2-NULLISH-COALESCING))
|
|
|
|
|
(if (js2-match-char ?.)
|
|
|
|
|
(throw 'return js2-OPTIONAL-CHAINING)
|
|
|
|
|
(throw 'return js2-HOOK))))
|
|
|
|
|
(?:
|
|
|
|
|
(if (js2-match-char ?:)
|
|
|
|
|
js2-COLONCOLON
|
|
|
|
|
@@ -6109,7 +6125,9 @@ its relevant fields and puts it into `js2-ti-tokens'."
|
|
|
|
|
(throw 'return js2-DOT))))
|
|
|
|
|
(?|
|
|
|
|
|
(if (js2-match-char ?|)
|
|
|
|
|
(throw 'return js2-OR)
|
|
|
|
|
(if (js2-match-char ?=)
|
|
|
|
|
js2-ASSIGN_OR
|
|
|
|
|
(throw 'return js2-OR))
|
|
|
|
|
(if (js2-match-char ?=)
|
|
|
|
|
js2-ASSIGN_BITOR
|
|
|
|
|
(throw 'return js2-BITOR))))
|
|
|
|
|
@@ -6119,7 +6137,9 @@ its relevant fields and puts it into `js2-ti-tokens'."
|
|
|
|
|
(throw 'return js2-BITXOR)))
|
|
|
|
|
(?&
|
|
|
|
|
(if (js2-match-char ?&)
|
|
|
|
|
(throw 'return js2-AND)
|
|
|
|
|
(if (js2-match-char ?=)
|
|
|
|
|
js2-ASSIGN_AND
|
|
|
|
|
(throw 'return js2-AND))
|
|
|
|
|
(if (js2-match-char ?=)
|
|
|
|
|
js2-ASSIGN_BITAND
|
|
|
|
|
(throw 'return js2-BITAND))))
|
|
|
|
|
@@ -7610,7 +7630,7 @@ When passed arguments of wrong type, does nothing."
|
|
|
|
|
(js2-record-object-literal node qname (js2-node-pos node)))))))))
|
|
|
|
|
|
|
|
|
|
(defun js2-compute-nested-prop-get (node)
|
|
|
|
|
"If NODE is of form foo.bar, foo['bar'], or any nested combination, return
|
|
|
|
|
"If NODE is of form foo.bar, foo[\\='bar\\='], or any nested combination, return
|
|
|
|
|
component nodes as a list. Otherwise return nil. Element-gets are treated
|
|
|
|
|
as property-gets if the index expression is a string, or a positive integer."
|
|
|
|
|
(let (left right head)
|
|
|
|
|
@@ -7823,19 +7843,19 @@ Recurses through nodes, and for each one whose second element is a list,
|
|
|
|
|
appends the list's flattened elements to the current element. Also
|
|
|
|
|
changes the tails into conses. For instance, this pre-flattened trie
|
|
|
|
|
|
|
|
|
|
'(a ((b 20)
|
|
|
|
|
(a ((b 20)
|
|
|
|
|
(c ((d 30)
|
|
|
|
|
(e 40)))))
|
|
|
|
|
|
|
|
|
|
becomes
|
|
|
|
|
|
|
|
|
|
'(a (b . 20)
|
|
|
|
|
(a (b . 20)
|
|
|
|
|
(c (d . 30)
|
|
|
|
|
(e . 40)))
|
|
|
|
|
|
|
|
|
|
Note that the root of the trie has no key, just a list of chains.
|
|
|
|
|
This is also true for the value of any key with multiple children,
|
|
|
|
|
e.g. key 'c' in the example above."
|
|
|
|
|
e.g. key `c' in the example above."
|
|
|
|
|
(cond
|
|
|
|
|
((listp (car trie))
|
|
|
|
|
(mapcar #'js2-flatten-trie trie))
|
|
|
|
|
@@ -8119,11 +8139,11 @@ The returned AST root node is given some additional properties:
|
|
|
|
|
so the value is not necessarily reliable.
|
|
|
|
|
|
|
|
|
|
An optional callback CB can be specified to report parsing
|
|
|
|
|
progress. If `(functionp CB)' returns t, it will be called with
|
|
|
|
|
progress. If (functionp CB) returns t, it will be called with
|
|
|
|
|
the current line number once before parsing begins, then again
|
|
|
|
|
each time the lexer reaches a new line number.
|
|
|
|
|
|
|
|
|
|
CB can also be a list of the form `(symbol cb ...)' to specify
|
|
|
|
|
CB can also be a list of the form (symbol cb ...) to specify
|
|
|
|
|
multiple callbacks with different criteria. Each symbol is a
|
|
|
|
|
criterion keyword, and the following element is the callback to
|
|
|
|
|
call
|
|
|
|
|
@@ -8746,11 +8766,11 @@ Return value is a list (EXPR LP RP), with absolute paren positions."
|
|
|
|
|
"Parse the bindings in an import statement.
|
|
|
|
|
This can take many forms:
|
|
|
|
|
|
|
|
|
|
ImportedDefaultBinding -> 'foo'
|
|
|
|
|
NameSpaceImport -> '* as lib'
|
|
|
|
|
NamedImports -> '{foo as bar, bang}'
|
|
|
|
|
ImportedDefaultBinding , NameSpaceImport -> 'foo, * as lib'
|
|
|
|
|
ImportedDefaultBinding , NamedImports -> 'foo, {bar, baz as bif}'
|
|
|
|
|
ImportedDefaultBinding -> `foo'
|
|
|
|
|
NameSpaceImport -> `* as lib'
|
|
|
|
|
NamedImports -> `{foo as bar, bang}'
|
|
|
|
|
ImportedDefaultBinding , NameSpaceImport -> `foo, * as lib'
|
|
|
|
|
ImportedDefaultBinding , NamedImports -> `foo, {bar, baz as bif}'
|
|
|
|
|
|
|
|
|
|
Try to match namespace imports and named imports first because nothing can
|
|
|
|
|
come after them. If it is an imported default binding, then it could have named
|
|
|
|
|
@@ -8809,7 +8829,7 @@ imports or a namespace import that follows it.
|
|
|
|
|
clause))
|
|
|
|
|
|
|
|
|
|
(defun js2-parse-namespace-import ()
|
|
|
|
|
"Parse a namespace import expression such as '* as bar'.
|
|
|
|
|
"Parse a namespace import expression such as `* as bar'.
|
|
|
|
|
The current token must be js2-MUL."
|
|
|
|
|
(let ((beg (js2-current-token-beg)))
|
|
|
|
|
(cond
|
|
|
|
|
@@ -8832,7 +8852,8 @@ The current token must be js2-MUL."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(defun js2-parse-from-clause ()
|
|
|
|
|
"Parse the from clause in an import or export statement. E.g. from 'src/lib'"
|
|
|
|
|
"Parse the from clause in an import or export statement.
|
|
|
|
|
E.g., \"from \\='src/lib\\='\"."
|
|
|
|
|
(if (js2-match-contextual-kwd "from")
|
|
|
|
|
(let ((beg (js2-current-token-beg)))
|
|
|
|
|
(cond
|
|
|
|
|
@@ -8875,8 +8896,8 @@ js2-LC. Return a lisp list of js2-export-binding-node"
|
|
|
|
|
|
|
|
|
|
(defun js2-maybe-parse-export-binding (&optional import-p)
|
|
|
|
|
"Attempt to parse a binding expression found inside an import/export statement.
|
|
|
|
|
This can take the form of either as single js2-NAME token as in 'foo' or as in a
|
|
|
|
|
rebinding expression 'bar as foo'. If it matches, it will return an instance of
|
|
|
|
|
This can take the form of either as single js2-NAME token as in `foo' or as in a
|
|
|
|
|
rebinding expression `bar as foo'. If it matches, it will return an instance of
|
|
|
|
|
js2-export-binding-node and consume all the tokens. If it does not match, it
|
|
|
|
|
consumes no tokens."
|
|
|
|
|
(let ((extern-name (when (js2-match-prop-name) (js2-current-token-string)))
|
|
|
|
|
@@ -9035,7 +9056,7 @@ consumes no tokens."
|
|
|
|
|
|
|
|
|
|
(defun js2-parse-export ()
|
|
|
|
|
"Parse an export statement.
|
|
|
|
|
The Last matched token must be js2-EXPORT. Currently, the 'default' and 'expr'
|
|
|
|
|
The Last matched token must be js2-EXPORT. Currently, the `default' and `expr'
|
|
|
|
|
expressions should only be either hoistable expressions (function or generator)
|
|
|
|
|
or assignment expressions, but there is no checking to enforce that and so it
|
|
|
|
|
will parse without error a small subset of
|
|
|
|
|
@@ -9667,10 +9688,10 @@ expression and return it wrapped in a `js2-expr-stmt-node'."
|
|
|
|
|
|
|
|
|
|
(defun js2-parse-variables (decl-type pos)
|
|
|
|
|
"Parse a comma-separated list of variable declarations.
|
|
|
|
|
Could be a 'var', 'const' or 'let' expression, possibly in a for-loop initializer.
|
|
|
|
|
Could be a `var', `const' or `let' expression, possibly in a for-loop initializer.
|
|
|
|
|
|
|
|
|
|
DECL-TYPE is a token value: either VAR, CONST, or LET depending on context.
|
|
|
|
|
For 'var' or 'const', the keyword should be the token last scanned.
|
|
|
|
|
For `var' or `const', the keyword should be the token last scanned.
|
|
|
|
|
|
|
|
|
|
POS is the position where the node should start. It's sometimes the
|
|
|
|
|
var/const/let keyword, and other times the beginning of the first token
|
|
|
|
|
@@ -9933,7 +9954,7 @@ If NODE is non-nil, it is the AST node associated with the symbol."
|
|
|
|
|
|
|
|
|
|
(defun js2-parse-cond-expr ()
|
|
|
|
|
(let ((pos (js2-current-token-beg))
|
|
|
|
|
(pn (js2-parse-or-expr))
|
|
|
|
|
(pn (js2-parse-nullish-coalescing-expr))
|
|
|
|
|
test-expr
|
|
|
|
|
if-true
|
|
|
|
|
if-false
|
|
|
|
|
@@ -10018,6 +10039,15 @@ FIXME: The latter option is unused?"
|
|
|
|
|
'js2-parse-eq-expr)))
|
|
|
|
|
pn))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(defun js2-parse-nullish-coalescing-expr ()
|
|
|
|
|
(let ((pn (js2-parse-or-expr)))
|
|
|
|
|
(when (js2-match-token js2-NULLISH-COALESCING)
|
|
|
|
|
(setq pn (js2-make-binary js2-NULLISH-COALESCING
|
|
|
|
|
pn
|
|
|
|
|
'js2-parse-nullish-coalescing-expr)))
|
|
|
|
|
pn))
|
|
|
|
|
|
|
|
|
|
(defconst js2-parse-eq-ops
|
|
|
|
|
(list js2-EQ js2-NE js2-SHEQ js2-SHNE))
|
|
|
|
|
|
|
|
|
|
@@ -10487,7 +10517,7 @@ This includes expressions of the forms:
|
|
|
|
|
@* @*::attr @*::*
|
|
|
|
|
@[expr] @*::[expr] @ns::[expr]
|
|
|
|
|
|
|
|
|
|
Called if we peeked an '@' token."
|
|
|
|
|
Called if we peeked an `@' token."
|
|
|
|
|
(let ((tt (js2-get-prop-name-token))
|
|
|
|
|
(at-pos (js2-current-token-beg)))
|
|
|
|
|
(cond
|
|
|
|
|
@@ -10508,11 +10538,11 @@ Called if we peeked an '@' token."
|
|
|
|
|
(defun js2-parse-property-name (at-pos s member-type-flags)
|
|
|
|
|
"Check if :: follows name in which case it becomes qualified name.
|
|
|
|
|
|
|
|
|
|
AT-POS is a natural number if we just read an '@' token, else nil.
|
|
|
|
|
S is the name or string that was matched: an identifier, 'throw' or '*'.
|
|
|
|
|
MEMBER-TYPE-FLAGS is a bit set tracking whether we're a '.' or '..' child.
|
|
|
|
|
AT-POS is a natural number if we just read an `@' token, else nil.
|
|
|
|
|
S is the name or string that was matched: an identifier, `throw' or `*'.
|
|
|
|
|
MEMBER-TYPE-FLAGS is a bit set tracking whether we're a `.' or `..' child.
|
|
|
|
|
|
|
|
|
|
Returns a `js2-xml-ref-node' if it's an attribute access, a child of a '..'
|
|
|
|
|
Returns a `js2-xml-ref-node' if it's an attribute access, a child of a `..'
|
|
|
|
|
operator, or the name is followed by ::. For a plain name, returns a
|
|
|
|
|
`js2-name-node'. Returns a `js2-error-node' for malformed XML expressions."
|
|
|
|
|
(let ((pos (or at-pos (js2-current-token-beg)))
|
|
|
|
|
@@ -10768,7 +10798,7 @@ array-literals, array comprehensions and regular expressions."
|
|
|
|
|
"Parse a legacy array comprehension (JavaScript 1.7).
|
|
|
|
|
EXPR is the first expression after the opening left-bracket.
|
|
|
|
|
POS is the beginning of the LB token preceding EXPR.
|
|
|
|
|
We should have just parsed the 'for' keyword before calling this function."
|
|
|
|
|
We should have just parsed the `for' keyword before calling this function."
|
|
|
|
|
(let ((current-scope js2-current-scope)
|
|
|
|
|
loops first filter result)
|
|
|
|
|
(unwind-protect
|
|
|
|
|
@@ -10805,7 +10835,7 @@ We should have just parsed the 'for' keyword before calling this function."
|
|
|
|
|
(defun js2-parse-array-comp (pos)
|
|
|
|
|
"Parse an ES6 array comprehension.
|
|
|
|
|
POS is the beginning of the LB token.
|
|
|
|
|
We should have just parsed the 'for' keyword before calling this function."
|
|
|
|
|
We should have just parsed the `for' keyword before calling this function."
|
|
|
|
|
(let ((pn (js2-parse-comprehension pos 'ARRAY)))
|
|
|
|
|
(js2-must-match js2-RB "msg.no.bracket.arg" pos)
|
|
|
|
|
pn))
|
|
|
|
|
@@ -10846,9 +10876,9 @@ We should have just parsed the 'for' keyword before calling this function."
|
|
|
|
|
result))
|
|
|
|
|
|
|
|
|
|
(defun js2-parse-comp-loop (pn &optional only-of-p)
|
|
|
|
|
"Parse a 'for [each] (foo [in|of] bar)' expression in an Array comprehension.
|
|
|
|
|
"Parse a `for [each] (foo [in|of] bar)' expression in an Array comprehension.
|
|
|
|
|
The current token should be the initial FOR.
|
|
|
|
|
If ONLY-OF-P is non-nil, only the 'for (foo of bar)' form is allowed."
|
|
|
|
|
If ONLY-OF-P is non-nil, only the `for (foo of bar)' form is allowed."
|
|
|
|
|
(let ((pos (js2-comp-loop-node-pos pn))
|
|
|
|
|
tt iter obj foreach-p forof-p in-pos each-pos lp rp)
|
|
|
|
|
(when (and (not only-of-p) (js2-match-token js2-NAME))
|
|
|
|
|
@@ -11711,18 +11741,13 @@ highlighting features of `js2-mode'."
|
|
|
|
|
map)
|
|
|
|
|
"Keymap used for js2 diagnostics buffers.")
|
|
|
|
|
|
|
|
|
|
(defun js2-error-buffer-mode ()
|
|
|
|
|
(define-derived-mode js2-error-buffer-mode special-mode "JS Lint Diagnostics"
|
|
|
|
|
"Major mode for js2 diagnostics buffers.
|
|
|
|
|
Selecting an error will jump it to the corresponding source-buffer error.
|
|
|
|
|
\\{js2-error-buffer-mode-map}"
|
|
|
|
|
(interactive)
|
|
|
|
|
(setq major-mode 'js2-error-buffer-mode
|
|
|
|
|
mode-name "JS Lint Diagnostics")
|
|
|
|
|
(use-local-map js2-error-buffer-mode-map)
|
|
|
|
|
(setq truncate-lines t)
|
|
|
|
|
(set-buffer-modified-p nil)
|
|
|
|
|
(setq buffer-read-only t)
|
|
|
|
|
(run-hooks 'js2-error-buffer-mode-hook))
|
|
|
|
|
(setq buffer-read-only t))
|
|
|
|
|
|
|
|
|
|
(defun js2-error-buffer-next ()
|
|
|
|
|
"Move to next error and view it."
|
|
|
|
|
@@ -11751,7 +11776,7 @@ Selecting an error will jump it to the corresponding source-buffer error.
|
|
|
|
|
"Scroll source buffer to show error at current line."
|
|
|
|
|
(interactive)
|
|
|
|
|
(cond
|
|
|
|
|
((not (eq major-mode 'js2-error-buffer-mode))
|
|
|
|
|
((not (derived-mode-p 'js2-error-buffer-mode))
|
|
|
|
|
(message "Not in a js2 errors buffer"))
|
|
|
|
|
((not (buffer-live-p js2-source-buffer))
|
|
|
|
|
(message "Source buffer has been killed"))
|
|
|
|
|
@@ -12897,7 +12922,7 @@ it marks the next defun after the ones already marked."
|
|
|
|
|
(defun js2-search-object-for-prop (object prop-names)
|
|
|
|
|
"Return node in OBJECT that matches PROP-NAMES or nil.
|
|
|
|
|
PROP-NAMES is a list of values representing a path to a value in OBJECT.
|
|
|
|
|
i.e. ('name' 'value') = {name : { value: 3}}"
|
|
|
|
|
i.e. (\\='name\\=' \\='value\\=') = {name : { value: 3}}"
|
|
|
|
|
(let (node
|
|
|
|
|
(temp-object object)
|
|
|
|
|
(temp t) ;temporay node
|
|
|
|
|
|