js-confuser-vm 0.1.1 → 0.1.2

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.
Files changed (58) hide show
  1. package/README.md +242 -89
  2. package/dist/compiler.js +583 -208
  3. package/dist/disassembler.js +58 -8
  4. package/dist/runtime.js +93 -74
  5. package/dist/template.js +81 -76
  6. package/dist/transforms/bytecode/concealConstants.js +2 -2
  7. package/dist/transforms/bytecode/controlFlowFlattening.js +143 -25
  8. package/dist/transforms/bytecode/dispatcher.js +3 -3
  9. package/dist/transforms/bytecode/resolveRegisters.js +19 -4
  10. package/dist/transforms/bytecode/selfModifying.js +88 -21
  11. package/dist/transforms/bytecode/specializedOpcodes.js +6 -3
  12. package/dist/transforms/bytecode/stringConcealing.js +253 -75
  13. package/dist/utils/ast-utils.js +61 -0
  14. package/dist/utils/op-utils.js +1 -0
  15. package/package.json +7 -1
  16. package/.gitmodules +0 -4
  17. package/.prettierignore +0 -1
  18. package/CHANGELOG.md +0 -358
  19. package/babel-plugin-inline-runtime.cjs +0 -34
  20. package/babel.config.json +0 -23
  21. package/bench.ts +0 -146
  22. package/disassemble.ts +0 -12
  23. package/index.ts +0 -43
  24. package/jest-strip-types.js +0 -10
  25. package/jest.config.js +0 -64
  26. package/output.disassembled.js +0 -41
  27. package/src/build-runtime.ts +0 -113
  28. package/src/compiler.ts +0 -2703
  29. package/src/disassembler.ts +0 -329
  30. package/src/index.ts +0 -24
  31. package/src/minify.ts +0 -21
  32. package/src/options.ts +0 -24
  33. package/src/runtime.ts +0 -956
  34. package/src/template.ts +0 -265
  35. package/src/transforms/bytecode/aliasedOpcodes.ts +0 -151
  36. package/src/transforms/bytecode/concealConstants.ts +0 -52
  37. package/src/transforms/bytecode/controlFlowFlattening.ts +0 -566
  38. package/src/transforms/bytecode/dispatcher.ts +0 -292
  39. package/src/transforms/bytecode/macroOpcodes.ts +0 -193
  40. package/src/transforms/bytecode/resolveConstants.ts +0 -126
  41. package/src/transforms/bytecode/resolveLabels.ts +0 -112
  42. package/src/transforms/bytecode/resolveRegisters.ts +0 -226
  43. package/src/transforms/bytecode/selfModifying.ts +0 -121
  44. package/src/transforms/bytecode/specializedOpcodes.ts +0 -164
  45. package/src/transforms/bytecode/stringConcealing.ts +0 -130
  46. package/src/transforms/runtime/aliasedOpcodes.ts +0 -191
  47. package/src/transforms/runtime/classObfuscation.ts +0 -59
  48. package/src/transforms/runtime/macroOpcodes.ts +0 -138
  49. package/src/transforms/runtime/minify.ts +0 -1
  50. package/src/transforms/runtime/shuffleOpcodes.ts +0 -24
  51. package/src/transforms/runtime/specializedOpcodes.ts +0 -161
  52. package/src/types.ts +0 -134
  53. package/src/utils/ast-utils.ts +0 -19
  54. package/src/utils/op-utils.ts +0 -46
  55. package/src/utils/pass-utils.ts +0 -126
  56. package/src/utils/profile-utils.ts +0 -3
  57. package/src/utils/random-utils.ts +0 -31
  58. package/tsconfig.json +0 -12
@@ -1,110 +1,288 @@
1
1
  // String Concealing
2
2
  //
3
- // Encodes every string constant in each function with base64, then inserts a
4
- // decode closure (atob) that is called immediately after each LOAD_CONST to
5
- // recover the original value at runtime.
3
+ // Replaces every string constant with a slice into a single shared "string
4
+ // bank" that is decoded at runtime with a position-dependent keystream cipher.
6
5
  //
7
- // ── How it works ─────────────────────────────────────────────────────────────
6
+ // ── Why a bank ───────────────────────────────────────────────────────────────
7
+ // Previously each string was its own encoded constant, so the encoded length
8
+ // leaked the plaintext length (an attacker could map by length + frequency).
9
+ // Here every string is concatenated into ONE opaque blob padded with random
10
+ // decoy bytes, so individual boundaries and lengths are no longer visible from
11
+ // static inspection of the constant pool.
8
12
  //
9
- // Each function that contains at least one string LOAD_CONST gets:
13
+ // bank = [100‑250 decoys] str0 [0‑5 decoys] str1 [0‑5 decoys] … [100‑250 decoys]
10
14
  //
11
- // rClosure a register holding the decode closure, created ONCE at function
12
- // entry (hoisted). All decode calls within the function reuse it.
15
+ // Each original string is referenced by the triple (key, start, length).
13
16
  //
14
- // The decode function is compiled ONCE (shared across all functions) from a
15
- // Template:
17
+ // ── Cipher ───────────────────────────────────────────────────────────────────
18
+ // A Weyl-sequence keystream (golden-ratio increment + xorshift mix) produces a
19
+ // fresh 16-bit keyword per character, XOR'd against the char code:
16
20
  //
17
- // function decode(encoded) { return atob(encoded); }
21
+ // key = (key + 0x9e3779b9) | 0 // 32-bit Weyl step
22
+ // ks = (key ^ (key >>> 13)) & 0xffff // 16-bit keystream word
23
+ // enc = charCode ^ ks // XOR (self-inverse)
18
24
  //
19
- // String constant transformations:
25
+ // XOR over the full 16-bit range means EVERY UTF-16 code unit round-trips,
26
+ // including control characters, newlines and non-ASCII / astral text. The
27
+ // per-string key is a full 32-bit seed (2^32 keyspace) so the encoding is not
28
+ // trivially enumerable.
20
29
  //
21
- // Original: LOAD_CONST rDst, "hello"
22
- // Becomes: LOAD_CONST rDst, "aGVsbG8=" (base64-encoded)
23
- // CALL rDst, rClosure, 1, rDst (decode in-place)
30
+ // ── Transport / storage ──────────────────────────────────────────────────────
31
+ // The encoded bank is full-range u16, which would serialise as a wall of CJK /
32
+ // control glyphs. Instead it is packed as u16-LE bytes and base64-encoded, so
33
+ // the stored constant is pure ASCII (and smaller on disk than the raw glyphs).
34
+ //
35
+ // ── Runtime shape — PROGRAM-LEVEL bank ───────────────────────────────────────
36
+ // The bank is inflated EXACTLY ONCE, in the program's main scope, into a plain
37
+ // main-scope register (NOT a global — nothing is written to globalThis). That
38
+ // register is shared with the functions that need it through the VM's ordinary
39
+ // upvalue mechanism: an extra upvalue is threaded down the closure-creation tree
40
+ // to every string-using function and its ancestors. Each string-using function
41
+ // reads the already-inflated bank from that upvalue and passes it to a small
42
+ // per-function `decode` closure (decode itself is function-level — cheap):
43
+ //
44
+ // main: MAKE_CLOSURE rInflate
45
+ // LOAD_CONST rB64, <base64 bank>
46
+ // CALL rBankMain, rInflate, 1, rB64 (once)
47
+ // string-using fn: LOAD_UPVALUE rBank, <threaded idx>
48
+ // MAKE_CLOSURE rDecode
49
+ // per site: LOAD_INT rKey/rStart/rLen
50
+ // CALL rDst, rDecode, 4, rBank, rKey, rStart, rLen
24
51
  //
25
52
  // ── Pipeline position ─────────────────────────────────────────────────────────
26
- // Runs BEFORE resolveRegisters and resolveLabels (same slot as Dispatcher/CFF).
53
+ // Runs BEFORE resolveRegisters and resolveLabels (same slot as Dispatcher/CFF),
54
+ // and FIRST among the bytecode passes so each FnDescriptor.upvalues count is
55
+ // still pristine (used to pick the threaded upvalue index).
27
56
 
28
57
  import { Template } from "../../template.js";
29
58
  import * as b from "../../types.js";
30
59
  import { ref, buildMaxIdMap, allocReg, forEachFunction } from "../../utils/pass-utils.js";
60
+ import { getRandomInt } from "../../utils/random-utils.js";
61
+ import { U32_MAX } from "../../utils/op-utils.js";
31
62
 
32
- // ── Per-function transformation ──────────────────────────────────────────────
33
-
34
- function processFunctionBlock(instrs, fnId, compiler, maxId, decodeDesc) {
35
- const OP = compiler.OP;
36
-
37
- // Only transform functions that contain string constants.
38
- const hasStringConst = instrs.some(instr => {
39
- if (instr[0] !== OP.LOAD_CONST) return false;
40
- const operands = instr.slice(1);
41
- return operands.length === 2 && operands[1]?.type === "constant" && typeof operands[1].value === "string";
42
- });
43
- if (!hasStringConst) return {
44
- instrs
45
- };
46
- const rClosure = allocReg(fnId, maxId);
47
- const out = [];
48
-
49
- // Hoist: create the decode closure once at function entry.
50
- out.push([OP.MAKE_CLOSURE, ref(rClosure), {
51
- type: "label",
52
- label: decodeDesc.entryLabel
53
- }, decodeDesc.paramCount,
54
- // 1 (encoded)
55
- b.fnRegCountOperand(decodeDesc._fnIdx), 0,
56
- // no upvalues
57
- 0 // hasRest = false
58
- ]);
59
-
60
- // Transform each instruction.
61
- for (const instr of instrs) {
62
- if (instr[0] === OP.LOAD_CONST && instr.length === 3 && instr[2]?.type === "constant" && typeof instr[2].value === "string") {
63
- const dst = instr[1];
64
- const constOp = instr[2];
63
+ // ── Cipher ────────────────────────────────────────────────────────────────────
64
+ // Encode mirrors the runtime decode EXACTLY (see the decode template). XOR is
65
+ // self-inverse. `key` must be the raw (unmasked) seed emitted as the LOAD_INT
66
+ // operand, so both sides begin the Weyl sequence from the same integer.
67
+ function xorEncode(str, key) {
68
+ let k = key;
69
+ let out = "";
70
+ for (let i = 0; i < str.length; i++) {
71
+ k = k + 0x9e3779b9 | 0;
72
+ const ks = (k ^ k >>> 13) & 0xffff;
73
+ out += String.fromCharCode(str.charCodeAt(i) ^ ks);
74
+ }
75
+ return out;
76
+ }
65
77
 
66
- // Encode the string in-place.
67
- constOp.value = Buffer.from(constOp.value, "utf-8").toString("base64");
68
- out.push(instr);
78
+ // Random decoy run, full 16-bit range so decoys look like encoded payload.
79
+ function decoyRun(count) {
80
+ let out = "";
81
+ for (let i = 0; i < count; i++) out += String.fromCharCode(getRandomInt(0, 0xffff));
82
+ return out;
83
+ }
69
84
 
70
- // Decode: rDst = decode(rDst)
71
- out.push([OP.CALL, ref(dst),
72
- // dst — receives decoded string
73
- ref(rClosure),
74
- // the hoisted decode closure
75
- 1,
76
- // argc
77
- ref(dst) // arg[0] = encoded value
78
- ]);
79
- } else {
80
- out.push(instr);
81
- }
85
+ // Pack the u16 bank as little-endian bytes and base64-encode (ASCII, compact).
86
+ // Mirrored at runtime by the inflate template: byte[2i] = low, byte[2i+1] = high.
87
+ function bankToBase64(bank) {
88
+ const bytes = new Uint8Array(bank.length * 2);
89
+ for (let i = 0; i < bank.length; i++) {
90
+ const c = bank.charCodeAt(i);
91
+ bytes[i * 2] = c & 0xff;
92
+ bytes[i * 2 + 1] = c >> 8 & 0xff;
82
93
  }
94
+ return Buffer.from(bytes).toString("base64");
95
+ }
96
+ function buildBank(strings) {
97
+ const parts = [];
98
+ const table = new Map();
99
+ let pos = 0;
100
+ const lead = decoyRun(getRandomInt(100, 250)); // leading decoys
101
+ parts.push(lead);
102
+ pos += lead.length;
103
+ for (const str of strings) {
104
+ const gap = decoyRun(getRandomInt(0, 5)); // 0‑5 decoys between strings
105
+ parts.push(gap);
106
+ pos += gap.length;
107
+ const key = getRandomInt(1, U32_MAX);
108
+ const encoded = xorEncode(str, key);
109
+ table.set(str, {
110
+ key,
111
+ start: pos,
112
+ length: str.length
113
+ });
114
+ parts.push(encoded);
115
+ pos += encoded.length;
116
+ }
117
+ parts.push(decoyRun(getRandomInt(100, 250))); // trailing decoys
83
118
  return {
84
- instrs: out
119
+ bank: parts.join(""),
120
+ table
85
121
  };
86
122
  }
123
+ function isStringLoadConst(instr, OP) {
124
+ return instr[0] === OP.LOAD_CONST && instr.length === 3 && instr[2]?.type === "constant" && typeof instr[2].value === "string";
125
+ }
87
126
 
88
127
  // ── Pass entry point ──────────────────────────────────────────────────────────
89
128
  export function stringConcealing(bc, compiler) {
129
+ const OP = compiler.OP;
130
+ const mainId = compiler.mainFn._fnIdx;
131
+ const entryLabelToFnId = new Map(compiler.fnDescriptors.map(d => [d.entryLabel, d._fnIdx]));
132
+ const entryLabels = new Set(entryLabelToFnId.keys());
133
+
134
+ // ── Prescan: collect strings + closure-creation graph ───────────────────────
135
+ // directUser — functions that contain a string LOAD_CONST.
136
+ // parentOf — childFnId → creating (lexical parent) fnId.
137
+ const strings = new Set();
138
+ const directUser = new Set();
139
+ const parentOf = new Map();
140
+ let curFn = -1;
141
+ for (const instr of bc) {
142
+ if (instr[0] === null && instr[1]?.type === "defineLabel" && entryLabels.has(instr[1].label)) {
143
+ curFn = entryLabelToFnId.get(instr[1].label);
144
+ continue;
145
+ }
146
+ if (curFn < 0) continue;
147
+ if (isStringLoadConst(instr, OP)) {
148
+ strings.add(instr[2].value);
149
+ directUser.add(curFn);
150
+ } else if (instr[0] === OP.MAKE_CLOSURE) {
151
+ const childId = entryLabelToFnId.get(instr[2]?.label);
152
+ if (childId !== undefined) parentOf.set(childId, curFn);
153
+ }
154
+ }
155
+ if (strings.size === 0) return {
156
+ bytecode: bc
157
+ };
158
+
159
+ // ── needSet = string users ∪ all their ancestors (so the upvalue can be
160
+ // threaded down to them). Walking each user to the root adds every ancestor. ──
161
+ const needSet = new Set();
162
+ for (const u of directUser) {
163
+ let p = u;
164
+ while (p !== undefined && !needSet.has(p)) {
165
+ needSet.add(p);
166
+ p = parentOf.get(p);
167
+ }
168
+ }
169
+
170
+ // Threaded upvalue index per function = its ORIGINAL upvalue count (appended
171
+ // last). main holds the bank as a local, so it has no threaded index.
172
+ const bankUvIndex = new Map();
173
+ for (const f of needSet) {
174
+ if (f === mainId) continue;
175
+ bankUvIndex.set(f, compiler.fnDescriptors[f]?.upvalues?.length ?? 0);
176
+ }
90
177
  const maxId = buildMaxIdMap(bc);
178
+ const rBankMain = allocReg(mainId, maxId); // program-level inflated bank
179
+ const {
180
+ bank,
181
+ table
182
+ } = buildBank(strings);
183
+ const bankB64 = bankToBase64(bank);
91
184
 
92
- // Compile the decode function ONCE all functions share the same closure body.
93
- const decodeTemplate = new Template(`
94
- function decode(encoded) {
95
- return atob(encoded);
185
+ // Helper closures, compiled once and shared by reference.
186
+ // inflate(b64) → reconstruct the u16 bank from base64
187
+ // decode(bank, key, start, len) → slice + keystream-decrypt one string
188
+ const helpers = new Template(`
189
+ function inflate(s) {
190
+ var bytes = atob(s);
191
+ var out = "";
192
+ for (var i = 0; i < bytes["length"]; i += 2) {
193
+ out += String["fromCharCode"](
194
+ bytes["charCodeAt"](i) | (bytes["charCodeAt"](i + 1) << 8)
195
+ );
196
+ }
197
+ return out;
198
+ }
199
+ function decode(bank, key, start, length) {
200
+ var result = "";
201
+ for (var i = 0; i < length; i++) {
202
+ key = (key + 0x9e3779b9) | 0;
203
+ var ks = (key ^ (key >>> 13)) & 0xffff;
204
+ result += String["fromCharCode"](bank["charCodeAt"](start + i) ^ ks);
205
+ }
206
+ return result;
96
207
  }
97
208
  `).compile({}, compiler);
98
- const decodeDesc = decodeTemplate.functions[0];
209
+ const [inflateDesc, decodeDesc] = helpers.functions;
210
+ const mkClosure = (dst, desc, params) => [OP.MAKE_CLOSURE, ref(dst), {
211
+ type: "label",
212
+ label: desc.entryLabel
213
+ }, params, b.fnRegCountOperand(desc._fnIdx), 0,
214
+ // upvalue count
215
+ 0 // hasRest
216
+ ];
99
217
  const {
100
218
  bytecode
101
- } = forEachFunction(bc, compiler, (fnInstrs, fnId) => processFunctionBlock(fnInstrs, fnId, compiler, maxId, decodeDesc));
219
+ } = forEachFunction(bc, compiler, (fnInstrs, fnId) => {
220
+ if (!needSet.has(fnId)) return {
221
+ instrs: fnInstrs
222
+ };
223
+ const isMain = fnId === mainId;
224
+ const usesStrings = directUser.has(fnId);
225
+
226
+ // Bank source for closures created in THIS frame: main captures its local,
227
+ // every other frame inherits its own threaded upvalue.
228
+ const childUpvalue = isMain ? [1, ref(rBankMain)] : [0, bankUvIndex.get(fnId)];
229
+ const prologue = [];
230
+ let rBank = null;
231
+ let rDecode = null;
232
+ let rKey, rStart, rLen;
233
+ if (isMain) {
234
+ const rInflate = allocReg(fnId, maxId);
235
+ const rB64 = allocReg(fnId, maxId);
236
+ prologue.push(mkClosure(rInflate, inflateDesc, 1));
237
+ prologue.push([OP.LOAD_CONST, ref(rB64), b.constantOperand(bankB64)]);
238
+ prologue.push([OP.CALL, ref(rBankMain), ref(rInflate), 1, ref(rB64)]);
239
+ rBank = rBankMain;
240
+ } else if (usesStrings) {
241
+ rBank = allocReg(fnId, maxId);
242
+ prologue.push([OP.LOAD_UPVALUE, ref(rBank), bankUvIndex.get(fnId)]);
243
+ }
244
+ if (usesStrings) {
245
+ rDecode = allocReg(fnId, maxId);
246
+ prologue.push(mkClosure(rDecode, decodeDesc, 4));
247
+ rKey = allocReg(fnId, maxId);
248
+ rStart = allocReg(fnId, maxId);
249
+ rLen = allocReg(fnId, maxId);
250
+ }
251
+ const out = [...prologue];
252
+ for (const instr of fnInstrs) {
253
+ // Thread the bank upvalue into every closure this frame creates that
254
+ // needs it (string users + ancestors).
255
+ if (instr[0] === OP.MAKE_CLOSURE) {
256
+ const childId = entryLabelToFnId.get(instr[2]?.label);
257
+ if (childId !== undefined && needSet.has(childId)) {
258
+ instr[5] = instr[5] + 1; // bump uvCount
259
+ instr.push(childUpvalue[0], childUpvalue[1]);
260
+ }
261
+ out.push(instr);
262
+ continue;
263
+ }
264
+ if (usesStrings && isStringLoadConst(instr, OP)) {
265
+ const dst = instr[1];
266
+ const entry = table.get(instr[2].value);
267
+ out.push([OP.LOAD_INT, ref(rKey), entry.key]);
268
+ out.push([OP.LOAD_INT, ref(rStart), entry.start]);
269
+ out.push([OP.LOAD_INT, ref(rLen), entry.length]);
270
+ out.push([OP.CALL, ref(dst), ref(rDecode), 4, ref(rBank), ref(rKey), ref(rStart), ref(rLen)]);
271
+ continue;
272
+ }
273
+ out.push(instr);
274
+ }
275
+ return {
276
+ instrs: out
277
+ };
278
+ });
102
279
 
103
- // Append the decode function's bytecode at the end (defines its entryLabel).
104
- // This is a single shared closure, not per-function, so it lives outside
105
- // forEachFunction's tail mechanism.
106
- bytecode.push(...decodeTemplate.bytecode);
280
+ // Append the helper functions' bytecode (defines their entryLabels).
281
+ bytecode.push(...helpers.bytecode);
107
282
  return {
108
283
  bytecode
109
284
  };
110
- }
285
+ }
286
+
287
+ // [isLocal flag, upvalue source] — RegisterOperand when capturing a local,
288
+ // plain number when inheriting a parent upvalue.
@@ -1,5 +1,66 @@
1
1
  import traverseImport from "@babel/traverse";
2
2
  const traverse = traverseImport.default || traverseImport;
3
+
4
+ // Recursively visits every statement reachable from `stmts` within the current
5
+ // function scope — traversing into blocks, if branches, loop bodies, switch
6
+ // cases, try/catch/finally, and labeled statements — but never crossing into
7
+ // nested FunctionDeclaration/FunctionExpression bodies (those are separate scopes).
8
+ //
9
+ // `visit` is called for each statement before its children are traversed.
10
+ // ForStatement init and ForInStatement left VariableDeclarations are also
11
+ // passed to `visit` so callers don't need to special-case them.
12
+ export function walkHoistScope(stmts, visit) {
13
+ for (const stmt of stmts) {
14
+ visit(stmt);
15
+ switch (stmt.type) {
16
+ case "BlockStatement":
17
+ walkHoistScope(stmt.body, visit);
18
+ break;
19
+ case "IfStatement":
20
+ {
21
+ const cons = stmt.consequent.type === "BlockStatement" ? stmt.consequent.body : [stmt.consequent];
22
+ walkHoistScope(cons, visit);
23
+ if (stmt.alternate) {
24
+ const alt = stmt.alternate.type === "BlockStatement" ? stmt.alternate.body : [stmt.alternate];
25
+ walkHoistScope(alt, visit);
26
+ }
27
+ break;
28
+ }
29
+ case "WhileStatement":
30
+ case "DoWhileStatement":
31
+ {
32
+ const body = stmt.body.type === "BlockStatement" ? stmt.body.body : [stmt.body];
33
+ walkHoistScope(body, visit);
34
+ break;
35
+ }
36
+ case "ForStatement":
37
+ {
38
+ if (stmt.init?.type === "VariableDeclaration") visit(stmt.init);
39
+ const body = stmt.body.type === "BlockStatement" ? stmt.body.body : [stmt.body];
40
+ walkHoistScope(body, visit);
41
+ break;
42
+ }
43
+ case "ForInStatement":
44
+ {
45
+ if (stmt.left.type === "VariableDeclaration") visit(stmt.left);
46
+ const body = stmt.body.type === "BlockStatement" ? stmt.body.body : [stmt.body];
47
+ walkHoistScope(body, visit);
48
+ break;
49
+ }
50
+ case "SwitchStatement":
51
+ for (const c of stmt.cases) walkHoistScope(c.consequent, visit);
52
+ break;
53
+ case "TryStatement":
54
+ walkHoistScope(stmt.block.body, visit);
55
+ if (stmt.handler) walkHoistScope(stmt.handler.body.body, visit);
56
+ if (stmt.finalizer) walkHoistScope(stmt.finalizer.body, visit);
57
+ break;
58
+ case "LabeledStatement":
59
+ walkHoistScope([stmt.body], visit);
60
+ break;
61
+ }
62
+ }
63
+ }
3
64
  export function getSwitchStatement(ast) {
4
65
  let switchStatement = null;
5
66
  traverse(ast, {
@@ -1,5 +1,6 @@
1
1
  import { getRandomInt } from "./random-utils.js";
2
2
  export const U16_MAX = 0xffff; // bytecode operands are u16
3
+ export const U32_MAX = 0xffffffff; // max sentinel / operand value
3
4
 
4
5
  /** Returns the next free opcode slot, or -1 when the space is exhausted. */
5
6
  export function nextFreeSlot(compiler) {
package/package.json CHANGED
@@ -1,7 +1,13 @@
1
1
  {
2
2
  "name": "js-confuser-vm",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "main": "dist/index.js",
5
+ "files": [
6
+ "dist",
7
+ "LICENSE",
8
+ "README.md",
9
+ "package.json"
10
+ ],
5
11
  "scripts": {
6
12
  "build": "babel src --out-dir dist --extensions \".ts,.js\"",
7
13
  "index": "cross-env NODE_OPTIONS=\"--disable-warning=ExperimentalWarning\" node index.ts",
package/.gitmodules DELETED
@@ -1,4 +0,0 @@
1
- [submodule "test262"]
2
- path = test262
3
- url = https://github.com/tc39/test262
4
- branch = es5-tests
package/.prettierignore DELETED
@@ -1 +0,0 @@
1
- *.md