UNPKG

2.41 kBJavaScriptView Raw
1'use strict';
2
3const PLUS_CODE = 43; // +
4const MINUS_CODE = 45; // -
5
6const plugin = {
7 name: 'assignment',
8
9 assignmentOperators: new Set([
10 '=',
11 '*=',
12 '**=',
13 '/=',
14 '%=',
15 '+=',
16 '-=',
17 '<<=',
18 '>>=',
19 '>>>=',
20 '&=',
21 '^=',
22 '|=',
23 ]),
24 updateOperators: [PLUS_CODE, MINUS_CODE],
25 assignmentPrecedence: 0.9,
26
27 init(jsep) {
28 const updateNodeTypes = [jsep.IDENTIFIER, jsep.MEMBER_EXP];
29 plugin.assignmentOperators.forEach(op => jsep.addBinaryOp(op, plugin.assignmentPrecedence, true));
30
31 jsep.hooks.add('gobble-token', function gobbleUpdatePrefix(env) {
32 const code = this.code;
33 if (plugin.updateOperators.some(c => c === code && c === this.expr.charCodeAt(this.index + 1))) {
34 this.index += 2;
35 env.node = {
36 type: 'UpdateExpression',
37 operator: code === PLUS_CODE ? '++' : '--',
38 argument: this.gobbleTokenProperty(this.gobbleIdentifier()),
39 prefix: true,
40 };
41 if (!env.node.argument || !updateNodeTypes.includes(env.node.argument.type)) {
42 this.throwError(`Unexpected ${env.node.operator}`);
43 }
44 }
45 });
46
47 jsep.hooks.add('after-token', function gobbleUpdatePostfix(env) {
48 if (env.node) {
49 const code = this.code;
50 if (plugin.updateOperators.some(c => c === code && c === this.expr.charCodeAt(this.index + 1))) {
51 if (!updateNodeTypes.includes(env.node.type)) {
52 this.throwError(`Unexpected ${env.node.operator}`);
53 }
54 this.index += 2;
55 env.node = {
56 type: 'UpdateExpression',
57 operator: code === PLUS_CODE ? '++' : '--',
58 argument: env.node,
59 prefix: false,
60 };
61 }
62 }
63 });
64
65 jsep.hooks.add('after-expression', function gobbleAssignment(env) {
66 if (env.node) {
67 // Note: Binaries can be chained in a single expression to respect
68 // operator precedence (i.e. a = b = 1 + 2 + 3)
69 // Update all binary assignment nodes in the tree
70 updateBinariesToAssignments(env.node);
71 }
72 });
73
74 function updateBinariesToAssignments(node) {
75 if (plugin.assignmentOperators.has(node.operator)) {
76 node.type = 'AssignmentExpression';
77 updateBinariesToAssignments(node.left);
78 updateBinariesToAssignments(node.right);
79 }
80 else if (!node.operator) {
81 Object.values(node).forEach((val) => {
82 if (val && typeof val === 'object') {
83 updateBinariesToAssignments(val);
84 }
85 });
86 }
87 }
88 },
89};
90
91module.exports = plugin;
92//# sourceMappingURL=index.cjs.js.map