smipper 16.0.0 → 17.0.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.
package/index.js CHANGED
@@ -1,59 +1,104 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
-
4
- const fs = require("fs");
5
- const got = require("got");
6
- const path = require("path");
7
- const sourceMap = require("source-map");
8
- const url = require("url");
9
-
10
- let verbose = false;
11
- let stack;
12
- let json = false;
13
- let retries = 3;
14
- let jsc = 0;
15
-
16
- let hasInput = false;
17
- for (let i=2; i<process.argv.length; ++i) {
3
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
4
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
5
+ return new (P || (P = Promise))(function (resolve, reject) {
6
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
7
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
8
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
9
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
10
+ });
11
+ };
12
+ var __generator = (this && this.__generator) || function (thisArg, body) {
13
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
14
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
15
+ function verb(n) { return function (v) { return step([n, v]); }; }
16
+ function step(op) {
17
+ if (f) throw new TypeError("Generator is already executing.");
18
+ while (_) try {
19
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
20
+ if (y = 0, t) op = [op[0] & 2, t.value];
21
+ switch (op[0]) {
22
+ case 0: case 1: t = op; break;
23
+ case 4: _.label++; return { value: op[1], done: false };
24
+ case 5: _.label++; y = op[1]; op = [0]; continue;
25
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
26
+ default:
27
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
28
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
29
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
30
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
31
+ if (t[2]) _.ops.pop();
32
+ _.trys.pop(); continue;
33
+ }
34
+ op = body.call(thisArg, _);
35
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
36
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
37
+ }
38
+ };
39
+ exports.__esModule = true;
40
+ var fs = require("fs");
41
+ var got = require("got");
42
+ var path = require("path");
43
+ var sourceMap = require("source-map");
44
+ var url = require("url");
45
+ var verbose = false;
46
+ var stack;
47
+ var json = false;
48
+ var retries = 3;
49
+ var jsc = 0;
50
+ for (var i = 2; i < process.argv.length; ++i) {
18
51
  try {
19
- const arg = process.argv[i];
20
- if (verbose)
52
+ var arg = process.argv[i] || "";
53
+ if (verbose) {
21
54
  console.error("got arg", arg);
55
+ }
22
56
  if (arg === "-f" || arg === "--file") {
23
57
  stack = fs.readFileSync(process.argv[++i]).toString();
24
- } else if ( arg.startsWith("-f") === 0) {
25
- stack = fs.readFileSync(arg.substr(2)).toString();
26
- } else if (arg.startsWith("--file=") === 0) {
27
- stack = fs.readFileSync(arg.substr(7)).toString();
28
- } else if (arg === "--verbose" || arg === "-v") {
58
+ }
59
+ else if (arg.startsWith("-f")) {
60
+ stack = fs.readFileSync(arg.substring(2)).toString();
61
+ }
62
+ else if (arg.startsWith("--file=")) {
63
+ stack = fs.readFileSync(arg.substring(7)).toString();
64
+ }
65
+ else if (arg === "--verbose" || arg === "-v") {
29
66
  verbose = true;
30
- } else if (arg === "--version") {
67
+ }
68
+ else if (arg === "--version") {
31
69
  console.log(JSON.parse(fs.readFileSync(path.join(__dirname, "package.json"), "utf8")).version);
32
70
  process.exit(0);
33
- } else if (arg === "--json") {
71
+ }
72
+ else if (arg === "--json") {
34
73
  json = true;
35
- } else if (arg === "--jsc") { // jsc has the wrong column for some reason
74
+ }
75
+ else if (arg === "--jsc") {
76
+ // jsc has the wrong column for some reason
36
77
  jsc = 1;
37
- } else if (arg.startsWith("--retries")) {
38
- retries = parseInt(arg.substr(9));
78
+ }
79
+ else if (arg.startsWith("--retries")) {
80
+ retries = parseInt(arg.substring(9));
39
81
  if (isNaN(retries) || retries < 0) {
40
82
  console.error("smipper [stack|-h|--help|-v|--verbose|--version|--retries=<number>|--jsc|--json|-f=@FILE@|-");
41
83
  process.exit(1);
42
84
  }
43
- } else if (arg === "-h" || arg === "--help") {
85
+ }
86
+ else if (arg === "-h" || arg === "--help") {
44
87
  console.error("smipper [stack|-h|--help|-v|--verbose|--version|--retries=<number>|--jsc|--json|-f=@FILE@|-");
45
88
  process.exit(0);
46
- } else if (arg === "-") {
89
+ }
90
+ else if (arg === "-") {
47
91
  // stdin
48
- } else {
92
+ }
93
+ else {
49
94
  stack = arg;
50
95
  }
51
- } catch (err) {
96
+ }
97
+ catch (err) {
52
98
  console.error("Error: " + err.toString());
53
99
  process.exit(1);
54
100
  }
55
101
  }
56
-
57
102
  if (!stack) {
58
103
  stack = fs.readFileSync("/dev/stdin").toString();
59
104
  if (!stack) {
@@ -61,14 +106,51 @@ if (!stack) {
61
106
  process.exit(0);
62
107
  }
63
108
  }
64
-
65
- function load(path)
66
- {
67
- return new Promise((resolve, reject) => {
109
+ function build(functionName, url, line, column) {
110
+ return "".concat(functionName ? "at " + functionName + " " : "").concat(url, ":").concat(line, ":").concat(column);
111
+ }
112
+ function findFile(dir, fn) {
113
+ var list = fs.readdirSync(dir);
114
+ for (var _i = 0, list_1 = list; _i < list_1.length; _i++) {
115
+ var file = list_1[_i];
116
+ var match = file === fn;
117
+ file = dir + "/" + file;
118
+ var stat = fs.statSync(file);
119
+ if (stat && stat.isDirectory()) {
120
+ var ret = findFile(file, fn);
121
+ if (ret) {
122
+ return ret;
123
+ }
124
+ }
125
+ else if (match) {
126
+ return "file://" + file;
127
+ }
128
+ }
129
+ return undefined;
130
+ }
131
+ function rewriteLocalControl(url) {
132
+ var found = findFile(process.cwd(), path.basename(url.substring(6)));
133
+ if (found) {
134
+ return found;
135
+ }
136
+ throw new Error("Couldn't resolve localcontrol " + url);
137
+ }
138
+ function load(path) {
139
+ return new Promise(function (resolve, reject) {
140
+ if (path.startsWith("http://localcontrol.netflix.com/")) {
141
+ try {
142
+ path = rewriteLocalControl(path);
143
+ }
144
+ catch (err) {
145
+ reject(err);
146
+ return;
147
+ }
148
+ }
68
149
  if (path.startsWith("file:///")) {
69
150
  try {
70
- resolve(fs.readFileSync(path.substr(7), "utf8"));
71
- } catch (err) {
151
+ resolve(fs.readFileSync(path.substring(7), "utf8"));
152
+ }
153
+ catch (err) {
72
154
  reject(err);
73
155
  }
74
156
  return;
@@ -77,146 +159,173 @@ function load(path)
77
159
  reject(new Error("Not a url"));
78
160
  return;
79
161
  }
80
- if (path.startsWith("http://localcontrol.netflix.com/")) {
81
- reject(new Error("No need to resolve this one"));
82
- return;
83
- }
84
- let retryIndex = 0;
85
- async function get()
86
- {
87
- try {
88
- const response = await got.get(path, { retry: { limit: retries } });
89
- return response.body;
90
- } catch (err) {
91
- reject(err);
92
- }
162
+ // let retryIndex = 0;
163
+ function get() {
164
+ return __awaiter(this, void 0, void 0, function () {
165
+ var response;
166
+ return __generator(this, function (_a) {
167
+ switch (_a.label) {
168
+ case 0: return [4 /*yield*/, got.get(path, { timeout: 10000 })];
169
+ case 1:
170
+ response = _a.sent();
171
+ console.log(response.headers);
172
+ return [2 /*return*/, response.body || ""];
173
+ }
174
+ });
175
+ });
93
176
  }
94
-
95
177
  get().then(resolve, reject);
96
178
  });
97
179
  }
98
-
99
- const sourceMaps = {};
180
+ var sourceMaps = {};
100
181
  function loadUri(path) {
182
+ var _this = this;
101
183
  if (path[0] === "/") {
102
184
  path = "file://" + path;
103
185
  }
104
- return new Promise((resolve, reject) => {
105
- if (verbose)
186
+ return new Promise(function (resolve, reject) {
187
+ if (verbose) {
106
188
  console.log("loading", path);
189
+ }
107
190
  if (!(path in sourceMaps)) {
108
191
  sourceMaps[path] = {
109
- resolvers: [ resolve ],
110
- rejecters: [ reject ]
192
+ resolvers: [resolve],
193
+ rejecters: [reject]
111
194
  };
112
- load(path).then(jsData => {
113
- const idx = jsData.lastIndexOf("//# sourceMappingURL=");
114
- if (verbose)
195
+ load(path)
196
+ .then(function (jsData) {
197
+ var idx = jsData.lastIndexOf("//# sourceMappingURL=");
198
+ if (verbose) {
115
199
  console.error("Got the file", jsData.length, idx);
116
- if (idx == -1)
200
+ }
201
+ if (idx == -1) {
117
202
  return path + ".map";
118
-
119
- const mapUrl = jsData.substr(idx + 21);
120
- const match = /^(data:.+\/.+;)base64,/.exec(mapUrl);
203
+ }
204
+ var mapUrl = jsData.substring(idx + 21);
205
+ var match = /^(data:.+\/.+;)base64,/.exec(mapUrl);
121
206
  if (match) {
122
- return mapUrl.substr(match[1].length);
207
+ return mapUrl.substring(match[1].length);
123
208
  }
124
209
  if (mapUrl.indexOf("://") != -1) {
125
210
  return mapUrl;
126
211
  }
127
212
  // console.log(mapUrl);
128
- return (new url.URL(mapUrl, path)).href;
129
- }).then(mapUrl => {
130
- // console.log(mapUrl.substr(0, 20));
213
+ return new url.URL(mapUrl, path).href;
214
+ })
215
+ .then(function (mapUrl) {
216
+ // console.log(mapUrl.substring(0, 20));
131
217
  if (mapUrl.startsWith("base64,")) {
132
- return Buffer.from(mapUrl.substr(7), "base64").toString();
218
+ return Buffer.from(mapUrl.substring(7), "base64").toString();
133
219
  }
134
220
  return load(mapUrl);
135
- }).then(sourceMapData => {
136
- const parsed = JSON.parse(sourceMapData);
137
- const smap = new sourceMap.SourceMapConsumer(parsed);
138
- const pending = sourceMaps[path];
139
- pending.resolvers.forEach(func => {
140
- func(smap);
221
+ })
222
+ .then(function (sourceMapData) { return __awaiter(_this, void 0, void 0, function () {
223
+ var parsed, smap, pending;
224
+ return __generator(this, function (_a) {
225
+ switch (_a.label) {
226
+ case 0:
227
+ parsed = JSON.parse(sourceMapData);
228
+ return [4 /*yield*/, new sourceMap.SourceMapConsumer(parsed)];
229
+ case 1:
230
+ smap = _a.sent();
231
+ pending = sourceMaps[path];
232
+ // sourceMaps.delete(path);
233
+ if (pending) {
234
+ pending.resolvers.forEach(function (func) {
235
+ func(smap);
236
+ });
237
+ }
238
+ return [2 /*return*/];
239
+ }
141
240
  });
142
- }).catch((err) => {
143
- const pending = sourceMaps[path];
144
- pending.rejecters.forEach(func => {
241
+ }); })["catch"](function (err) {
242
+ var pending = sourceMaps[path];
243
+ if (!pending) {
244
+ throw new Error("Gotta have pending");
245
+ }
246
+ // sourceMaps.delete(path);
247
+ pending.rejecters.forEach(function (func) {
145
248
  func(err);
146
249
  });
147
250
  });
148
- } else {
149
- const cur = sourceMaps[path];
150
- if (verbose)
251
+ }
252
+ else {
253
+ var cur = sourceMaps[path];
254
+ if (verbose) {
151
255
  console.error("path is in source maps already", cur);
256
+ }
257
+ if (!cur) {
258
+ throw new Error("Gotta have cur");
259
+ }
152
260
  cur.resolvers.push(resolve);
153
261
  cur.rejecters.push(reject);
154
262
  }
155
263
  });
156
264
  }
157
-
158
- function processFrame(functionName, url, line, column)
159
- {
160
- if (verbose)
265
+ function processFrame(functionName, url, line, column) {
266
+ if (verbose) {
161
267
  console.log("got frame", functionName, url, line, column);
162
- if (functionName.endsWith("@"))
163
- functionName = functionName.substr(0, functionName.length - 1);
164
- return new Promise((resolve, reject) => {
165
- let newUrl, newLine, newColumn;
166
- if (verbose)
268
+ }
269
+ if (functionName.endsWith("@")) {
270
+ functionName = functionName.substring(0, functionName.length - 1);
271
+ }
272
+ return new Promise(function (resolve) {
273
+ var newUrl, newLine, newColumn;
274
+ if (verbose) {
167
275
  console.error("calling loadUri", url);
276
+ }
168
277
  if (!url.includes("://") && url[0] !== "/" && fs.existsSync(url)) {
169
- url = `file://${process.cwd()}/${url}`;
278
+ url = "file://".concat(process.cwd(), "/").concat(url);
170
279
  }
171
- return loadUri(url).then((smap) => {
172
- if (verbose)
280
+ return loadUri(url)
281
+ .then(function (smap) {
282
+ if (verbose) {
173
283
  console.error("got map", url, Object.keys(smap));
174
-
284
+ }
175
285
  // it appears that we're supposed to reduce the column
176
286
  // number by 1 when we get this from jsc
177
- const pos = smap.originalPositionFor({ line, column: column - jsc });
287
+ var pos = smap.originalPositionFor({ line: line, column: column - jsc });
178
288
  if (!pos.source) {
179
- if (verbose)
289
+ if (verbose) {
180
290
  console.error("nothing here", pos);
291
+ }
181
292
  throw new Error("Mapping not found");
182
293
  }
183
-
184
294
  // smc.sourceContentFor(pos.source);
185
-
186
295
  newUrl = pos.source;
187
- newLine = pos.line;
188
- newColumn = pos.column;
189
- }).catch((err) => {
190
- if (verbose)
296
+ newLine = pos.line || 0;
297
+ newColumn = pos.column || 0;
298
+ })["catch"](function (err) {
299
+ if (verbose) {
191
300
  console.error("didn't get map", url, err);
301
+ }
192
302
  // console.error(err);
193
- }).finally(() => {
303
+ })["finally"](function () {
194
304
  if (json) {
195
- const ret = {
305
+ var ret = {
196
306
  functionName: functionName,
197
307
  sourceURL: newUrl ? newUrl : url,
198
308
  line: newUrl ? newLine : line,
199
309
  column: newUrl ? newColumn : column
200
310
  };
201
- if (newUrl) {
202
- ret.oldSourceURL = url;
203
- ret.oldLine = line;
204
- ret.oldColumn = column;
205
- }
311
+ // if (newUrl) {
312
+ // ret.oldSourceURL = url;
313
+ // ret.oldLine = line;
314
+ // ret.oldColumn = column;
315
+ // }
206
316
  // if (newUrl) {
207
317
  // ret.newUrl = newUrl;
208
318
  // ret.newLine = newLine;
209
319
  // ret.newColumn = newColumn;
210
320
  // }
211
321
  resolve(ret);
212
- } else {
213
- function build(functionName, url, line, column) {
214
- return `${functionName ? "at " + functionName + " " : ""}${url}:${line}:${column}`;
215
- }
216
- let str;
322
+ }
323
+ else {
324
+ var str = void 0;
217
325
  if (newUrl) {
218
- str = `${build(functionName, newUrl, newLine, newColumn)} (${build("", url, line, column)})`;
219
- } else {
326
+ str = "".concat(build(functionName, newUrl, newLine, newColumn), " (").concat(build("", url, line, column), ")");
327
+ }
328
+ else {
220
329
  str = build(functionName, url, line, column);
221
330
  }
222
331
  resolve(str);
@@ -224,56 +333,68 @@ function processFrame(functionName, url, line, column)
224
333
  });
225
334
  });
226
335
  }
227
-
228
336
  if (json) {
229
- let parsed;
337
+ var parsed = void 0;
230
338
  try {
231
339
  parsed = JSON.parse(stack);
232
- if (!Array.isArray(parsed))
340
+ if (!Array.isArray(parsed)) {
233
341
  throw new Error("Expected array");
234
- } catch (err) {
235
- console.error(`Can't parse json ${err}`);
342
+ }
343
+ }
344
+ catch (err) {
345
+ console.error("Can't parse json ".concat(err));
236
346
  process.exit(1);
237
347
  }
238
- Promise.all(parsed.map((frame) => {
239
- if (verbose)
348
+ Promise.all(parsed.map(function (frame) {
349
+ if (verbose) {
240
350
  console.error("got frame frame", frame);
351
+ }
241
352
  return processFrame(frame.functionName || "", frame.sourceURL || "", frame.line, frame.column);
242
- })).then((results) => {
243
- results.forEach((frame, index) => {
353
+ }))
354
+ .then(function (results) {
355
+ results.forEach(function (frame, index) {
356
+ if (typeof frame !== "object") {
357
+ throw new Error("Huh?");
358
+ }
244
359
  frame.index = index;
245
360
  });
246
361
  // console.log("shit", results);
247
362
  console.log(JSON.stringify(results, null, 4));
248
- }).catch((error) => {
363
+ })["catch"](function (error) {
249
364
  console.error("Got an error", error);
250
365
  process.exit(2);
251
366
  });
252
- } else {
253
- Promise.all(stack.split("\n").filter(x => x).map(x => {
367
+ }
368
+ else {
369
+ Promise.all(stack
370
+ .split("\n")
371
+ .filter(function (x) { return x; })
372
+ .map(function (x) {
254
373
  x = x.trim();
255
- let match = / *at *([^ ]*).* \(?([^ ]+):([0-9]+):([0-9]+)/.exec(x);
374
+ var match = / *at *([^ ]*).* \(?([^ ]+):([0-9]+):([0-9]+)/.exec(x);
256
375
  if (!match) {
257
376
  match = /([^ ]+@)?(.*):([0-9]+):([0-9]+)/.exec(x);
258
377
  }
259
- if (verbose)
378
+ if (verbose) {
260
379
  console.error(x, " => ", match);
380
+ }
261
381
  if (!match) {
262
- const nolinecol = /([^ ]*)(.*)/.exec(x);
382
+ var nolinecol = /([^ ]*)(.*)/.exec(x);
263
383
  if (nolinecol) {
264
384
  return nolinecol[0];
265
385
  }
266
386
  return x;
267
387
  }
268
388
  return processFrame(match[1] || "", match[2], parseInt(match[3]), parseInt(match[4]));
269
- })).then((results) => {
389
+ }))
390
+ .then(function (results) {
270
391
  if (!results.length) {
271
392
  throw new Error("Empty output");
272
393
  }
273
- results.forEach(str => {
394
+ results.forEach(function (str) {
274
395
  console.log(str);
275
396
  });
276
- }).catch((error) => {
397
+ })["catch"](function (error) {
277
398
  console.error("Got an error", error);
278
399
  process.exit(3);
279
400
  });
package/index.ts ADDED
@@ -0,0 +1,373 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ import * as fs from "fs";
5
+ import * as got from "got";
6
+ import * as path from "path";
7
+ import * as sourceMap from "source-map";
8
+ import * as url from "url";
9
+
10
+ let verbose = false;
11
+ let stack;
12
+ let json = false;
13
+ let retries = 3;
14
+ let jsc = 0;
15
+
16
+ for (let i = 2; i < process.argv.length; ++i) {
17
+ try {
18
+ const arg = process.argv[i] || "";
19
+ if (verbose) {
20
+ console.error("got arg", arg);
21
+ }
22
+ if (arg === "-f" || arg === "--file") {
23
+ stack = fs.readFileSync(process.argv[++i]).toString();
24
+ } else if (arg.startsWith("-f")) {
25
+ stack = fs.readFileSync(arg.substring(2)).toString();
26
+ } else if (arg.startsWith("--file=")) {
27
+ stack = fs.readFileSync(arg.substring(7)).toString();
28
+ } else if (arg === "--verbose" || arg === "-v") {
29
+ verbose = true;
30
+ } else if (arg === "--version") {
31
+ console.log(JSON.parse(fs.readFileSync(path.join(__dirname, "package.json"), "utf8")).version);
32
+ process.exit(0);
33
+ } else if (arg === "--json") {
34
+ json = true;
35
+ } else if (arg === "--jsc") {
36
+ // jsc has the wrong column for some reason
37
+ jsc = 1;
38
+ } else if (arg.startsWith("--retries")) {
39
+ retries = parseInt(arg.substring(9));
40
+ if (isNaN(retries) || retries < 0) {
41
+ console.error(
42
+ "smipper [stack|-h|--help|-v|--verbose|--version|--retries=<number>|--jsc|--json|-f=@FILE@|-"
43
+ );
44
+ process.exit(1);
45
+ }
46
+ } else if (arg === "-h" || arg === "--help") {
47
+ console.error(
48
+ "smipper [stack|-h|--help|-v|--verbose|--version|--retries=<number>|--jsc|--json|-f=@FILE@|-"
49
+ );
50
+ process.exit(0);
51
+ } else if (arg === "-") {
52
+ // stdin
53
+ } else {
54
+ stack = arg;
55
+ }
56
+ } catch (err) {
57
+ console.error("Error: " + err.toString());
58
+ process.exit(1);
59
+ }
60
+ }
61
+
62
+ if (!stack) {
63
+ stack = fs.readFileSync("/dev/stdin").toString();
64
+ if (!stack) {
65
+ console.error("Nothing to do");
66
+ process.exit(0);
67
+ }
68
+ }
69
+
70
+ function build(functionName: string, url: string, line: number, column: number): string {
71
+ return `${functionName ? "at " + functionName + " " : ""}${url}:${line}:${column}`;
72
+ }
73
+
74
+ function findFile(dir: string, fn: string): string | undefined {
75
+ const list = fs.readdirSync(dir);
76
+ for (let file of list) {
77
+ const match = file === fn;
78
+ file = dir + "/" + file;
79
+ const stat = fs.statSync(file);
80
+ if (stat && stat.isDirectory()) {
81
+ const ret = findFile(file, fn);
82
+ if (ret) {
83
+ return ret;
84
+ }
85
+ } else if (match) {
86
+ return "file://" + file;
87
+ }
88
+ }
89
+ return undefined;
90
+ }
91
+
92
+ function rewriteLocalControl(url: string) {
93
+ const found = findFile(process.cwd(), path.basename(url.substring(6)));
94
+ if (found) {
95
+ return found;
96
+ }
97
+ throw new Error("Couldn't resolve localcontrol " + url);
98
+ }
99
+
100
+ function load(path: string): Promise<string> {
101
+ return new Promise<string>((resolve, reject) => {
102
+ if (path.startsWith("http://localcontrol.netflix.com/")) {
103
+ try {
104
+ path = rewriteLocalControl(path);
105
+ } catch (err) {
106
+ reject(err);
107
+ return;
108
+ }
109
+ }
110
+
111
+ if (path.startsWith("file:///")) {
112
+ try {
113
+ resolve(fs.readFileSync(path.substring(7), "utf8"));
114
+ } catch (err) {
115
+ reject(err);
116
+ }
117
+ return;
118
+ }
119
+
120
+ if (!path.startsWith("http://") && !path.startsWith("https://")) {
121
+ reject(new Error("Not a url"));
122
+ return;
123
+ }
124
+
125
+ // let retryIndex = 0;
126
+ async function get(): Promise<string> {
127
+ const response = await got.get(path, { timeout: 10000 });
128
+ console.log(response.headers);
129
+ return response.body || "";
130
+ }
131
+
132
+ get().then(resolve, reject);
133
+ });
134
+ }
135
+
136
+ type SourceMapResolve = (res: sourceMap.SourceMapConsumer) => void;
137
+ type Rejecter = (err: Error) => void;
138
+ type SourceMapData = {
139
+ resolvers: SourceMapResolve[];
140
+ rejecters: Rejecter[];
141
+ };
142
+ const sourceMaps: Record<string, SourceMapData> = {};
143
+ function loadUri(path: string): Promise<sourceMap.SourceMapConsumer> {
144
+ if (path[0] === "/") {
145
+ path = "file://" + path;
146
+ }
147
+ return new Promise((resolve: SourceMapResolve, reject: Rejecter) => {
148
+ if (verbose) {
149
+ console.log("loading", path);
150
+ }
151
+ if (!(path in sourceMaps)) {
152
+ sourceMaps[path] = {
153
+ resolvers: [resolve],
154
+ rejecters: [reject]
155
+ };
156
+ load(path)
157
+ .then((jsData: string) => {
158
+ const idx = jsData.lastIndexOf("//# sourceMappingURL=");
159
+ if (verbose) {
160
+ console.error("Got the file", jsData.length, idx);
161
+ }
162
+ if (idx == -1) {
163
+ return path + ".map";
164
+ }
165
+
166
+ const mapUrl = jsData.substring(idx + 21);
167
+ const match = /^(data:.+\/.+;)base64,/.exec(mapUrl);
168
+ if (match) {
169
+ return mapUrl.substring(match[1].length);
170
+ }
171
+ if (mapUrl.indexOf("://") != -1) {
172
+ return mapUrl;
173
+ }
174
+ // console.log(mapUrl);
175
+ return new url.URL(mapUrl, path).href;
176
+ })
177
+ .then((mapUrl) => {
178
+ // console.log(mapUrl.substring(0, 20));
179
+ if (mapUrl.startsWith("base64,")) {
180
+ return Buffer.from(mapUrl.substring(7), "base64").toString();
181
+ }
182
+ return load(mapUrl);
183
+ })
184
+ .then(async (sourceMapData: string) => {
185
+ const parsed = JSON.parse(sourceMapData);
186
+ const smap: sourceMap.SourceMapConsumer = await new sourceMap.SourceMapConsumer(parsed);
187
+ const pending = sourceMaps[path];
188
+ // sourceMaps.delete(path);
189
+ if (pending) {
190
+ pending.resolvers.forEach((func: SourceMapResolve) => {
191
+ func(smap);
192
+ });
193
+ }
194
+ })
195
+ .catch((err) => {
196
+ const pending = sourceMaps[path];
197
+ if (!pending) {
198
+ throw new Error("Gotta have pending");
199
+ }
200
+ // sourceMaps.delete(path);
201
+ pending.rejecters.forEach((func: (err: Error) => void) => {
202
+ func(err);
203
+ });
204
+ });
205
+ } else {
206
+ const cur = sourceMaps[path];
207
+ if (verbose) {
208
+ console.error("path is in source maps already", cur);
209
+ }
210
+
211
+ if (!cur) {
212
+ throw new Error("Gotta have cur");
213
+ }
214
+ cur.resolvers.push(resolve);
215
+ cur.rejecters.push(reject);
216
+ }
217
+ });
218
+ }
219
+
220
+ type Frame = {
221
+ functionName: string;
222
+ sourceURL: string;
223
+ line: number;
224
+ column: number;
225
+ index?: number;
226
+ };
227
+
228
+ function processFrame(functionName: string, url: string, line: number, column: number): Promise<Frame | string> {
229
+ if (verbose) {
230
+ console.log("got frame", functionName, url, line, column);
231
+ }
232
+ if (functionName.endsWith("@")) {
233
+ functionName = functionName.substring(0, functionName.length - 1);
234
+ }
235
+ return new Promise((resolve) => {
236
+ let newUrl: string, newLine: number, newColumn: number;
237
+ if (verbose) {
238
+ console.error("calling loadUri", url);
239
+ }
240
+ if (!url.includes("://") && url[0] !== "/" && fs.existsSync(url)) {
241
+ url = `file://${process.cwd()}/${url}`;
242
+ }
243
+ return loadUri(url)
244
+ .then((smap) => {
245
+ if (verbose) {
246
+ console.error("got map", url, Object.keys(smap));
247
+ }
248
+
249
+ // it appears that we're supposed to reduce the column
250
+ // number by 1 when we get this from jsc
251
+ const pos = smap.originalPositionFor({ line, column: column - jsc });
252
+ if (!pos.source) {
253
+ if (verbose) {
254
+ console.error("nothing here", pos);
255
+ }
256
+ throw new Error("Mapping not found");
257
+ }
258
+
259
+ // smc.sourceContentFor(pos.source);
260
+
261
+ newUrl = pos.source;
262
+
263
+ newLine = pos.line || 0;
264
+ newColumn = pos.column || 0;
265
+ })
266
+ .catch((err) => {
267
+ if (verbose) {
268
+ console.error("didn't get map", url, err);
269
+ }
270
+ // console.error(err);
271
+ })
272
+ .finally(() => {
273
+ if (json) {
274
+ const ret = {
275
+ functionName: functionName,
276
+ sourceURL: newUrl ? newUrl : url,
277
+ line: newUrl ? newLine : line,
278
+ column: newUrl ? newColumn : column
279
+ };
280
+ // if (newUrl) {
281
+ // ret.oldSourceURL = url;
282
+ // ret.oldLine = line;
283
+ // ret.oldColumn = column;
284
+ // }
285
+ // if (newUrl) {
286
+ // ret.newUrl = newUrl;
287
+ // ret.newLine = newLine;
288
+ // ret.newColumn = newColumn;
289
+ // }
290
+ resolve(ret);
291
+ } else {
292
+ let str;
293
+ if (newUrl) {
294
+ str = `${build(functionName, newUrl, newLine, newColumn)} (${build("", url, line, column)})`;
295
+ } else {
296
+ str = build(functionName, url, line, column);
297
+ }
298
+ resolve(str);
299
+ }
300
+ });
301
+ });
302
+ }
303
+
304
+ if (json) {
305
+ let parsed;
306
+ try {
307
+ parsed = JSON.parse(stack);
308
+ if (!Array.isArray(parsed)) {
309
+ throw new Error("Expected array");
310
+ }
311
+ } catch (err) {
312
+ console.error(`Can't parse json ${err}`);
313
+ process.exit(1);
314
+ }
315
+ Promise.all(
316
+ parsed.map((frame) => {
317
+ if (verbose) {
318
+ console.error("got frame frame", frame);
319
+ }
320
+ return processFrame(frame.functionName || "", frame.sourceURL || "", frame.line, frame.column);
321
+ })
322
+ )
323
+ .then((results) => {
324
+ results.forEach((frame: Frame | string, index: number) => {
325
+ if (typeof frame !== "object") {
326
+ throw new Error("Huh?");
327
+ }
328
+ frame.index = index;
329
+ });
330
+ // console.log("shit", results);
331
+ console.log(JSON.stringify(results, null, 4));
332
+ })
333
+ .catch((error) => {
334
+ console.error("Got an error", error);
335
+ process.exit(2);
336
+ });
337
+ } else {
338
+ Promise.all(
339
+ stack
340
+ .split("\n")
341
+ .filter((x) => x)
342
+ .map((x) => {
343
+ x = x.trim();
344
+ let match = / *at *([^ ]*).* \(?([^ ]+):([0-9]+):([0-9]+)/.exec(x);
345
+ if (!match) {
346
+ match = /([^ ]+@)?(.*):([0-9]+):([0-9]+)/.exec(x);
347
+ }
348
+ if (verbose) {
349
+ console.error(x, " => ", match);
350
+ }
351
+ if (!match) {
352
+ const nolinecol = /([^ ]*)(.*)/.exec(x);
353
+ if (nolinecol) {
354
+ return nolinecol[0];
355
+ }
356
+ return x;
357
+ }
358
+ return processFrame(match[1] || "", match[2], parseInt(match[3]), parseInt(match[4]));
359
+ })
360
+ )
361
+ .then((results) => {
362
+ if (!results.length) {
363
+ throw new Error("Empty output");
364
+ }
365
+ results.forEach((str) => {
366
+ console.log(str);
367
+ });
368
+ })
369
+ .catch((error) => {
370
+ console.error("Got an error", error);
371
+ process.exit(3);
372
+ });
373
+ }
package/package.json CHANGED
@@ -1,18 +1,23 @@
1
1
  {
2
2
  "name": "smipper",
3
- "version": "16.0.0",
3
+ "version": "17.0.1",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
+ "build": "node ./node_modules/.bin/tsc index.ts && chmod +x ./index.js",
7
8
  "test": "echo \"Error: no test specified\" && exit 1"
8
9
  },
9
- "bin": {
10
- "smipper": "index.js"
11
- },
12
10
  "author": "",
13
11
  "license": "ISC",
14
12
  "dependencies": {
15
13
  "got": "^9.6.0",
16
14
  "source-map": "^0.7.4"
15
+ },
16
+ "devDependencies": {
17
+ "@types/got": "^9.6.12",
18
+ "@types/node": "^18.7.18",
19
+ "@types/source-map": "^0.5.7",
20
+ "prettier": "^2.7.1",
21
+ "typescript": "^4.8.3"
17
22
  }
18
23
  }
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ tabWidth: 4,
3
+ printWidth: 120,
4
+ proseWrap: "never",
5
+ trailingComma: "none"
6
+ };
package/tsconfig.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "exclude": ["**/.*/", "examples/**", "autobahn/**", "node_modules/**", "dist/**", "*.def.ts"],
3
+ "compilerOptions": {
4
+ "target": "es2020",
5
+ "typeRoots": ["./src/typings", "./node_modules/@nf-types"],
6
+ "noUncheckedIndexedAccess": true,
7
+ "strictBindCallApply": true,
8
+ "newLine": "LF",
9
+ "module": "es6",
10
+ "declaration": false,
11
+ "moduleResolution": "node",
12
+ "pretty": true,
13
+ "noImplicitAny": true,
14
+ "esModuleInterop": true,
15
+ "strictNullChecks": true,
16
+ "strictPropertyInitialization": true,
17
+ "downlevelIteration": true,
18
+ "strict": true,
19
+ "sourceMap": true,
20
+ "incremental": true,
21
+ "lib": ["es2019"],
22
+ "baseUrl": ".",
23
+ "paths": {
24
+ "~/*": ["src/*"]
25
+ },
26
+ "plugins": [{ "transform": "@zerollup/ts-transform-paths" }]
27
+ }
28
+ }