@dacely/toildefender 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,69 +1,69 @@
1
- "use strict";
2
-
3
- var assert = require("assert");
4
-
5
- var _ = require("lodash");
6
-
7
- var estest = require("../estest");
8
- var traverser = require("../traverser");
9
- var utils = require("../utils");
10
-
11
- /**
12
- * Merges nested bind calls like
13
- * veilmark$bind(veilmark$bind(main, 1234), 5678)
14
- * to
15
- * veilmark$bind(main, 1234, 5678)
16
- * @param {Node} node
17
- * @returns {Node}
18
- */
19
- function mergeNestedBinds(node) {
20
- assert.ok(estest.isNode(node));
21
-
22
- if (isBindCall(node)) {
23
- return mergeNestedBinds(node.arguments[0]).concat(node.arguments.slice(1));
24
- } else {
25
- return [ node ];
26
- }
27
- }
28
-
29
- /**
30
- * Checks whether node is a call to veilmark$bind.
31
- * @param {Node} node
32
- * @returns {boolean}
33
- */
34
- function isBindCall(node) {
35
- assert.ok(estest.isNode(node));
36
-
37
- return node.type == "CallExpression"
38
- && node.callee.type == "Identifier"
39
- && node.callee.name == "veilmark$bind";
40
- }
41
-
42
- module.exports = class Postprocessing {
43
-
44
- constructor (logger) {
45
- this.logger = logger;
46
- }
47
-
48
- /**
49
- * Does postprocessing.
50
- * @param {Node} ast Root node
51
- * @return {Node} Root node
52
- */
53
- do (ast) {
54
- assert.ok(estest.isNode(ast));
55
-
56
- return traverser.traverse(ast, [], (node, stack) => {
57
- if (isBindCall(node)) {
58
- node.arguments = mergeNestedBinds(node);
59
- } else if (node.type == "BlockStatement" || node.type == "Program") {
60
- node.body = node.body.filter(x => estest.isNode(x) && x.type != "EmptyStatement");
61
- } else if (node.type == "SwitchCase") {
62
- node.consequent = node.consequent.filter(x => estest.isNode(x) && x.type != "EmptyStatement");
63
- }
64
-
65
- return node;
66
- });
67
- }
68
-
69
- };
1
+ "use strict";
2
+
3
+ var assert = require("assert");
4
+
5
+ var _ = require("lodash");
6
+
7
+ var estest = require("../estest");
8
+ var traverser = require("../traverser");
9
+ var utils = require("../utils");
10
+
11
+ /**
12
+ * Merges nested bind calls like
13
+ * veilmark$bind(veilmark$bind(main, 1234), 5678)
14
+ * to
15
+ * veilmark$bind(main, 1234, 5678)
16
+ * @param {Node} node
17
+ * @returns {Node}
18
+ */
19
+ function mergeNestedBinds(node) {
20
+ assert.ok(estest.isNode(node));
21
+
22
+ if (isBindCall(node)) {
23
+ return mergeNestedBinds(node.arguments[0]).concat(node.arguments.slice(1));
24
+ } else {
25
+ return [ node ];
26
+ }
27
+ }
28
+
29
+ /**
30
+ * Checks whether node is a call to veilmark$bind.
31
+ * @param {Node} node
32
+ * @returns {boolean}
33
+ */
34
+ function isBindCall(node) {
35
+ assert.ok(estest.isNode(node));
36
+
37
+ return node.type == "CallExpression"
38
+ && node.callee.type == "Identifier"
39
+ && node.callee.name == "veilmark$bind";
40
+ }
41
+
42
+ module.exports = class Postprocessing {
43
+
44
+ constructor (logger) {
45
+ this.logger = logger;
46
+ }
47
+
48
+ /**
49
+ * Does postprocessing.
50
+ * @param {Node} ast Root node
51
+ * @return {Node} Root node
52
+ */
53
+ do (ast) {
54
+ assert.ok(estest.isNode(ast));
55
+
56
+ return traverser.traverse(ast, [], (node, stack) => {
57
+ if (isBindCall(node)) {
58
+ node.arguments = mergeNestedBinds(node);
59
+ } else if (node.type == "BlockStatement" || node.type == "Program") {
60
+ node.body = node.body.filter(x => estest.isNode(x) && x.type != "EmptyStatement");
61
+ } else if (node.type == "SwitchCase") {
62
+ node.consequent = node.consequent.filter(x => estest.isNode(x) && x.type != "EmptyStatement");
63
+ }
64
+
65
+ return node;
66
+ });
67
+ }
68
+
69
+ };
@@ -1,248 +1,248 @@
1
- "use strict";
2
-
3
- var _ = require("lodash");
4
-
5
- var { Parser: Parser } = require("expr-eval");
6
-
7
- const DEFAULT_PREPROCESSOR_VARIABLES = {
8
- "true": 1,
9
- "false": 0
10
- };
11
-
12
- /**
13
- * Generates code from an array of text nodes.
14
- * @param {TextNode[]} nodes
15
- * @returns {string}
16
- */
17
- function codeFromNodeArray(nodes) {
18
- let lines = [];
19
- for (let node of nodes) {
20
- lines[node.line] = node.text;
21
- }
22
- return lines.join("\n");
23
- }
24
-
25
- /**
26
- * Removes shebang from beginning of code.
27
- * @param {string} code
28
- * @returns {string}
29
- */
30
- function removeShebangs(code) {
31
- if (_.startsWith(code, "#!")) {
32
- code = code.split(/\r?\n/).slice(1).join("\n");
33
- }
34
-
35
- return code;
36
- }
37
-
38
- class ArrayUtils {
39
- /**
40
- * Replaces all occurences of an object in an array with an other object in place.
41
- * @param {Array} arr
42
- * @param {Object} oldElem
43
- * @param {Object} newElem
44
- */
45
- static replace(arr, oldElem, newElem) {
46
- for (let i = 0; i < arr.length; ++i) {
47
- if (arr[i] == oldElem) {
48
- arr[i] = newElem;
49
- }
50
- }
51
- }
52
- }
53
-
54
- class Node {
55
- constructor() {
56
-
57
- }
58
- /**
59
- * Evaluates tree into an array of TextNodes.
60
- * @param {Object.<string, string>} defines Preprocessor variables
61
- * @returns {TextNode[]}
62
- */
63
- eval(defines) {
64
- throw new Error("Node.eval() can not be called directly");
65
- }
66
- }
67
-
68
- class BlockNode extends Node {
69
- constructor() {
70
- super();
71
- this.children = [];
72
- }
73
- eval(defines) {
74
- return _.flatten(this.children.map(x => x.eval(defines)));
75
- }
76
- }
77
-
78
- class TextNode extends Node {
79
- constructor(text) {
80
- super();
81
- this.text = text;
82
- }
83
- eval(defines) {
84
- return [this];
85
- }
86
- }
87
-
88
- class DefineNode extends Node {
89
- constructor(left, right) {
90
- super();
91
- this.left = left;
92
- this.right = right;
93
- }
94
- eval(defines) {
95
- defines[this.left] = this.right;
96
- return [];
97
- }
98
- }
99
-
100
- class ErrorNode extends Node {
101
- constructor(message) {
102
- super();
103
- this.message = message;
104
- }
105
- eval(defines) {
106
- throw new Error(this.message);
107
- }
108
- }
109
-
110
- class IfBlockNode extends BlockNode {
111
- constructor(condition) {
112
- super();
113
- this.condition = condition;
114
- }
115
- /**
116
- * Evaluates condition.
117
- * @param {Object.<string, string>} defines Preprocessor variables
118
- * @returns {boolean}
119
- */
120
- evalCond(defines) {
121
- let condition = this.condition;
122
- condition = condition.replace(/!defined\(([\w\d]+)\)/, (match, p1) => !defines.hasOwnProperty(p1) ? "true" : "false");
123
- condition = condition.replace(/defined\(([\w\d]+)\)/, (match, p1) => defines.hasOwnProperty(p1) ? "true" : "false");
124
- return Parser.evaluate(condition, defines);
125
- }
126
- /**
127
- * Evaluates node with given condition result.
128
- * @param {Object.<string, string>} defines Preprocessor variables
129
- * @returns {boolean}
130
- */
131
- evalWith(defines, result) {
132
- if (result) {
133
- return super.eval(defines);
134
- } else {
135
- return [];
136
- }
137
- }
138
- eval(defines) {
139
- return this.evalWith(defines, this.evalCond(defines));
140
- }
141
- }
142
-
143
- class ElseBlockNode extends BlockNode {
144
- constructor(ifNode) {
145
- super();
146
- this.ifNode = ifNode;
147
- }
148
- eval(defines) {
149
- if (this.ifNode.evalCond(defines)) {
150
- return this.ifNode.evalWith(defines, true);
151
- } else {
152
- return super.eval(defines);
153
- }
154
- }
155
- }
156
-
157
- module.exports = class Preprocessing {
158
-
159
- constructor (logger) {
160
- this.logger = logger;
161
- }
162
-
163
- /**
164
- * Processes preprocessor directives.
165
- * @param {string} code
166
- * @param {Object.<string, string>} preprocessorVariables
167
- * @returns {string} Processed code
168
- */
169
- processDirectives (code, preprocessorVariables) {
170
- let lines = code.split(/\r?\n/), stack = [new BlockNode()];
171
-
172
- let defines = {};
173
- _.merge(defines, DEFAULT_PREPROCESSOR_VARIABLES);
174
- _.merge(defines, preprocessorVariables);
175
-
176
- for (let i = 0; i < lines.length; ++i) {
177
- let line = lines[i];
178
- let [, directive, parameters] = /^\s*\/\/\s*#(\w+)\s*(.+)?$/.exec(line) || [];
179
- switch (directive) {
180
- case undefined: {
181
- let elem = new TextNode(line);
182
- elem.line = i;
183
- _.last(stack).children.push(elem);
184
- break;
185
- }
186
- case "define": {
187
- let [, left, right] = /^\s*([\w\d]+)\s*(?:=\s*([\w\d]+))?\s*$/.exec(parameters);
188
- let elem = new DefineNode(left, right);
189
- elem.line = i;
190
- _.last(stack).children.push(elem);
191
- break;
192
- }
193
- case "error": {
194
- let elem = new ErrorNode(parameters);
195
- elem.line = i;
196
- _.last(stack).children.push(elem);
197
- break;
198
- }
199
- case "if":
200
- case "ifdef":
201
- case "ifndef": {
202
- let elem =
203
- directive == "if" ? new IfBlockNode(parameters) :
204
- directive == "ifdef" ? new IfBlockNode(`defined(${parameters})`) :
205
- directive == "ifndef" ? new IfBlockNode(`!defined(${parameters})`) :
206
- null;
207
- elem.line = i;
208
- _.last(stack).children.push(elem);
209
- stack.push(elem);
210
- break;
211
- }
212
- case "else": {
213
- let elem = new ElseBlockNode(stack.pop());
214
- elem.line = i;
215
- ArrayUtils.replace(_.last(stack).children, elem.ifNode, elem);
216
- stack.push(elem);
217
- break;
218
- }
219
- case "endif": {
220
- let elem = stack.pop();
221
- break;
222
- }
223
- default: {
224
- this.logger.warn(`Unknown preprocessor directive #${directive}`);
225
- }
226
- }
227
- }
228
-
229
- if (stack.length > 1) {
230
- this.logger.warn("stack.length != 1 (preprocessor directive closing tag missing?)");
231
- }
232
-
233
- return codeFromNodeArray(stack[0].eval(defines));
234
- }
235
-
236
- /**
237
- * Does preprocessing.
238
- * @param {string} code
239
- * @param {Object.<string, string>} preprocessorVariables
240
- * @returns {string}
241
- */
242
- process (code, preprocessorVariables) {
243
- code = this.processDirectives(code, preprocessorVariables);
244
- code = removeShebangs(code);
245
- return code;
246
- }
247
-
248
- };
1
+ "use strict";
2
+
3
+ var _ = require("lodash");
4
+
5
+ var { Parser: Parser } = require("expr-eval");
6
+
7
+ const DEFAULT_PREPROCESSOR_VARIABLES = {
8
+ "true": 1,
9
+ "false": 0
10
+ };
11
+
12
+ /**
13
+ * Generates code from an array of text nodes.
14
+ * @param {TextNode[]} nodes
15
+ * @returns {string}
16
+ */
17
+ function codeFromNodeArray(nodes) {
18
+ let lines = [];
19
+ for (let node of nodes) {
20
+ lines[node.line] = node.text;
21
+ }
22
+ return lines.join("\n");
23
+ }
24
+
25
+ /**
26
+ * Removes shebang from beginning of code.
27
+ * @param {string} code
28
+ * @returns {string}
29
+ */
30
+ function removeShebangs(code) {
31
+ if (_.startsWith(code, "#!")) {
32
+ code = code.split(/\r?\n/).slice(1).join("\n");
33
+ }
34
+
35
+ return code;
36
+ }
37
+
38
+ class ArrayUtils {
39
+ /**
40
+ * Replaces all occurences of an object in an array with an other object in place.
41
+ * @param {Array} arr
42
+ * @param {Object} oldElem
43
+ * @param {Object} newElem
44
+ */
45
+ static replace(arr, oldElem, newElem) {
46
+ for (let i = 0; i < arr.length; ++i) {
47
+ if (arr[i] == oldElem) {
48
+ arr[i] = newElem;
49
+ }
50
+ }
51
+ }
52
+ }
53
+
54
+ class Node {
55
+ constructor() {
56
+
57
+ }
58
+ /**
59
+ * Evaluates tree into an array of TextNodes.
60
+ * @param {Object.<string, string>} defines Preprocessor variables
61
+ * @returns {TextNode[]}
62
+ */
63
+ eval(defines) {
64
+ throw new Error("Node.eval() can not be called directly");
65
+ }
66
+ }
67
+
68
+ class BlockNode extends Node {
69
+ constructor() {
70
+ super();
71
+ this.children = [];
72
+ }
73
+ eval(defines) {
74
+ return _.flatten(this.children.map(x => x.eval(defines)));
75
+ }
76
+ }
77
+
78
+ class TextNode extends Node {
79
+ constructor(text) {
80
+ super();
81
+ this.text = text;
82
+ }
83
+ eval(defines) {
84
+ return [this];
85
+ }
86
+ }
87
+
88
+ class DefineNode extends Node {
89
+ constructor(left, right) {
90
+ super();
91
+ this.left = left;
92
+ this.right = right;
93
+ }
94
+ eval(defines) {
95
+ defines[this.left] = this.right;
96
+ return [];
97
+ }
98
+ }
99
+
100
+ class ErrorNode extends Node {
101
+ constructor(message) {
102
+ super();
103
+ this.message = message;
104
+ }
105
+ eval(defines) {
106
+ throw new Error(this.message);
107
+ }
108
+ }
109
+
110
+ class IfBlockNode extends BlockNode {
111
+ constructor(condition) {
112
+ super();
113
+ this.condition = condition;
114
+ }
115
+ /**
116
+ * Evaluates condition.
117
+ * @param {Object.<string, string>} defines Preprocessor variables
118
+ * @returns {boolean}
119
+ */
120
+ evalCond(defines) {
121
+ let condition = this.condition;
122
+ condition = condition.replace(/!defined\(([\w\d]+)\)/, (match, p1) => !defines.hasOwnProperty(p1) ? "true" : "false");
123
+ condition = condition.replace(/defined\(([\w\d]+)\)/, (match, p1) => defines.hasOwnProperty(p1) ? "true" : "false");
124
+ return Parser.evaluate(condition, defines);
125
+ }
126
+ /**
127
+ * Evaluates node with given condition result.
128
+ * @param {Object.<string, string>} defines Preprocessor variables
129
+ * @returns {boolean}
130
+ */
131
+ evalWith(defines, result) {
132
+ if (result) {
133
+ return super.eval(defines);
134
+ } else {
135
+ return [];
136
+ }
137
+ }
138
+ eval(defines) {
139
+ return this.evalWith(defines, this.evalCond(defines));
140
+ }
141
+ }
142
+
143
+ class ElseBlockNode extends BlockNode {
144
+ constructor(ifNode) {
145
+ super();
146
+ this.ifNode = ifNode;
147
+ }
148
+ eval(defines) {
149
+ if (this.ifNode.evalCond(defines)) {
150
+ return this.ifNode.evalWith(defines, true);
151
+ } else {
152
+ return super.eval(defines);
153
+ }
154
+ }
155
+ }
156
+
157
+ module.exports = class Preprocessing {
158
+
159
+ constructor (logger) {
160
+ this.logger = logger;
161
+ }
162
+
163
+ /**
164
+ * Processes preprocessor directives.
165
+ * @param {string} code
166
+ * @param {Object.<string, string>} preprocessorVariables
167
+ * @returns {string} Processed code
168
+ */
169
+ processDirectives (code, preprocessorVariables) {
170
+ let lines = code.split(/\r?\n/), stack = [new BlockNode()];
171
+
172
+ let defines = {};
173
+ _.merge(defines, DEFAULT_PREPROCESSOR_VARIABLES);
174
+ _.merge(defines, preprocessorVariables);
175
+
176
+ for (let i = 0; i < lines.length; ++i) {
177
+ let line = lines[i];
178
+ let [, directive, parameters] = /^\s*\/\/\s*#(\w+)\s*(.+)?$/.exec(line) || [];
179
+ switch (directive) {
180
+ case undefined: {
181
+ let elem = new TextNode(line);
182
+ elem.line = i;
183
+ _.last(stack).children.push(elem);
184
+ break;
185
+ }
186
+ case "define": {
187
+ let [, left, right] = /^\s*([\w\d]+)\s*(?:=\s*([\w\d]+))?\s*$/.exec(parameters);
188
+ let elem = new DefineNode(left, right);
189
+ elem.line = i;
190
+ _.last(stack).children.push(elem);
191
+ break;
192
+ }
193
+ case "error": {
194
+ let elem = new ErrorNode(parameters);
195
+ elem.line = i;
196
+ _.last(stack).children.push(elem);
197
+ break;
198
+ }
199
+ case "if":
200
+ case "ifdef":
201
+ case "ifndef": {
202
+ let elem =
203
+ directive == "if" ? new IfBlockNode(parameters) :
204
+ directive == "ifdef" ? new IfBlockNode(`defined(${parameters})`) :
205
+ directive == "ifndef" ? new IfBlockNode(`!defined(${parameters})`) :
206
+ null;
207
+ elem.line = i;
208
+ _.last(stack).children.push(elem);
209
+ stack.push(elem);
210
+ break;
211
+ }
212
+ case "else": {
213
+ let elem = new ElseBlockNode(stack.pop());
214
+ elem.line = i;
215
+ ArrayUtils.replace(_.last(stack).children, elem.ifNode, elem);
216
+ stack.push(elem);
217
+ break;
218
+ }
219
+ case "endif": {
220
+ let elem = stack.pop();
221
+ break;
222
+ }
223
+ default: {
224
+ this.logger.warn(`Unknown preprocessor directive #${directive}`);
225
+ }
226
+ }
227
+ }
228
+
229
+ if (stack.length > 1) {
230
+ this.logger.warn("stack.length != 1 (preprocessor directive closing tag missing?)");
231
+ }
232
+
233
+ return codeFromNodeArray(stack[0].eval(defines));
234
+ }
235
+
236
+ /**
237
+ * Does preprocessing.
238
+ * @param {string} code
239
+ * @param {Object.<string, string>} preprocessorVariables
240
+ * @returns {string}
241
+ */
242
+ process (code, preprocessorVariables) {
243
+ code = this.processDirectives(code, preprocessorVariables);
244
+ code = removeShebangs(code);
245
+ return code;
246
+ }
247
+
248
+ };