smipper 17.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,195 +106,226 @@ if (!stack) {
61
106
  process.exit(0);
62
107
  }
63
108
  }
64
-
109
+ function build(functionName, url, line, column) {
110
+ return "".concat(functionName ? "at " + functionName + " " : "").concat(url, ":").concat(line, ":").concat(column);
111
+ }
65
112
  function findFile(dir, fn) {
66
- const list = fs.readdirSync(dir);
67
- for (let file of list) {
68
- const match = (file === fn);
69
- file = dir + '/' + file;
70
- const stat = fs.statSync(file);
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);
71
119
  if (stat && stat.isDirectory()) {
72
- const ret = findFile(file, fn);
120
+ var ret = findFile(file, fn);
73
121
  if (ret) {
74
122
  return ret;
75
123
  }
76
- } else if (match) {
124
+ }
125
+ else if (match) {
77
126
  return "file://" + file;
78
127
  }
79
128
  }
80
129
  return undefined;
81
130
  }
82
-
83
- function rewriteLocalControl(url)
84
- {
85
- const found = findFile(process.cwd(), path.basename(url.substring(6)));
86
- if (found)
131
+ function rewriteLocalControl(url) {
132
+ var found = findFile(process.cwd(), path.basename(url.substring(6)));
133
+ if (found) {
87
134
  return found;
135
+ }
88
136
  throw new Error("Couldn't resolve localcontrol " + url);
89
137
  }
90
-
91
- function load(path)
92
- {
93
- return new Promise((resolve, reject) => {
138
+ function load(path) {
139
+ return new Promise(function (resolve, reject) {
94
140
  if (path.startsWith("http://localcontrol.netflix.com/")) {
95
141
  try {
96
142
  path = rewriteLocalControl(path);
97
- } catch (err) {
143
+ }
144
+ catch (err) {
98
145
  reject(err);
99
146
  return;
100
147
  }
101
148
  }
102
-
103
149
  if (path.startsWith("file:///")) {
104
150
  try {
105
- resolve(fs.readFileSync(path.substr(7), "utf8"));
106
- } catch (err) {
151
+ resolve(fs.readFileSync(path.substring(7), "utf8"));
152
+ }
153
+ catch (err) {
107
154
  reject(err);
108
155
  }
109
156
  return;
110
157
  }
111
-
112
158
  if (!path.startsWith("http://") && !path.startsWith("https://")) {
113
159
  reject(new Error("Not a url"));
114
160
  return;
115
161
  }
116
-
117
- let retryIndex = 0;
118
- async function get()
119
- {
120
- try {
121
- const response = await got.get(path, { retry: { limit: retries } });
122
- return response.body;
123
- } catch (err) {
124
- reject(err);
125
- }
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
+ });
126
176
  }
127
-
128
177
  get().then(resolve, reject);
129
178
  });
130
179
  }
131
-
132
- const sourceMaps = {};
180
+ var sourceMaps = {};
133
181
  function loadUri(path) {
182
+ var _this = this;
134
183
  if (path[0] === "/") {
135
184
  path = "file://" + path;
136
185
  }
137
- return new Promise((resolve, reject) => {
138
- if (verbose)
186
+ return new Promise(function (resolve, reject) {
187
+ if (verbose) {
139
188
  console.log("loading", path);
189
+ }
140
190
  if (!(path in sourceMaps)) {
141
191
  sourceMaps[path] = {
142
- resolvers: [ resolve ],
143
- rejecters: [ reject ]
192
+ resolvers: [resolve],
193
+ rejecters: [reject]
144
194
  };
145
- load(path).then(jsData => {
146
- const idx = jsData.lastIndexOf("//# sourceMappingURL=");
147
- if (verbose)
195
+ load(path)
196
+ .then(function (jsData) {
197
+ var idx = jsData.lastIndexOf("//# sourceMappingURL=");
198
+ if (verbose) {
148
199
  console.error("Got the file", jsData.length, idx);
149
- if (idx == -1)
200
+ }
201
+ if (idx == -1) {
150
202
  return path + ".map";
151
-
152
- const mapUrl = jsData.substr(idx + 21);
153
- const match = /^(data:.+\/.+;)base64,/.exec(mapUrl);
203
+ }
204
+ var mapUrl = jsData.substring(idx + 21);
205
+ var match = /^(data:.+\/.+;)base64,/.exec(mapUrl);
154
206
  if (match) {
155
- return mapUrl.substr(match[1].length);
207
+ return mapUrl.substring(match[1].length);
156
208
  }
157
209
  if (mapUrl.indexOf("://") != -1) {
158
210
  return mapUrl;
159
211
  }
160
212
  // console.log(mapUrl);
161
- return (new url.URL(mapUrl, path)).href;
162
- }).then(mapUrl => {
163
- // 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));
164
217
  if (mapUrl.startsWith("base64,")) {
165
- return Buffer.from(mapUrl.substr(7), "base64").toString();
218
+ return Buffer.from(mapUrl.substring(7), "base64").toString();
166
219
  }
167
220
  return load(mapUrl);
168
- }).then(sourceMapData => {
169
- const parsed = JSON.parse(sourceMapData);
170
- const smap = new sourceMap.SourceMapConsumer(parsed);
171
- const pending = sourceMaps[path];
172
- pending.resolvers.forEach(func => {
173
- 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
+ }
174
240
  });
175
- }).catch((err) => {
176
- const pending = sourceMaps[path];
177
- 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) {
178
248
  func(err);
179
249
  });
180
250
  });
181
- } else {
182
- const cur = sourceMaps[path];
183
- if (verbose)
251
+ }
252
+ else {
253
+ var cur = sourceMaps[path];
254
+ if (verbose) {
184
255
  console.error("path is in source maps already", cur);
256
+ }
257
+ if (!cur) {
258
+ throw new Error("Gotta have cur");
259
+ }
185
260
  cur.resolvers.push(resolve);
186
261
  cur.rejecters.push(reject);
187
262
  }
188
263
  });
189
264
  }
190
-
191
- function processFrame(functionName, url, line, column)
192
- {
193
- if (verbose)
265
+ function processFrame(functionName, url, line, column) {
266
+ if (verbose) {
194
267
  console.log("got frame", functionName, url, line, column);
195
- if (functionName.endsWith("@"))
196
- functionName = functionName.substr(0, functionName.length - 1);
197
- return new Promise((resolve, reject) => {
198
- let newUrl, newLine, newColumn;
199
- 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) {
200
275
  console.error("calling loadUri", url);
276
+ }
201
277
  if (!url.includes("://") && url[0] !== "/" && fs.existsSync(url)) {
202
- url = `file://${process.cwd()}/${url}`;
278
+ url = "file://".concat(process.cwd(), "/").concat(url);
203
279
  }
204
- return loadUri(url).then((smap) => {
205
- if (verbose)
280
+ return loadUri(url)
281
+ .then(function (smap) {
282
+ if (verbose) {
206
283
  console.error("got map", url, Object.keys(smap));
207
-
284
+ }
208
285
  // it appears that we're supposed to reduce the column
209
286
  // number by 1 when we get this from jsc
210
- const pos = smap.originalPositionFor({ line, column: column - jsc });
287
+ var pos = smap.originalPositionFor({ line: line, column: column - jsc });
211
288
  if (!pos.source) {
212
- if (verbose)
289
+ if (verbose) {
213
290
  console.error("nothing here", pos);
291
+ }
214
292
  throw new Error("Mapping not found");
215
293
  }
216
-
217
294
  // smc.sourceContentFor(pos.source);
218
-
219
295
  newUrl = pos.source;
220
- newLine = pos.line;
221
- newColumn = pos.column;
222
- }).catch((err) => {
223
- if (verbose)
296
+ newLine = pos.line || 0;
297
+ newColumn = pos.column || 0;
298
+ })["catch"](function (err) {
299
+ if (verbose) {
224
300
  console.error("didn't get map", url, err);
301
+ }
225
302
  // console.error(err);
226
- }).finally(() => {
303
+ })["finally"](function () {
227
304
  if (json) {
228
- const ret = {
305
+ var ret = {
229
306
  functionName: functionName,
230
307
  sourceURL: newUrl ? newUrl : url,
231
308
  line: newUrl ? newLine : line,
232
309
  column: newUrl ? newColumn : column
233
310
  };
234
- if (newUrl) {
235
- ret.oldSourceURL = url;
236
- ret.oldLine = line;
237
- ret.oldColumn = column;
238
- }
311
+ // if (newUrl) {
312
+ // ret.oldSourceURL = url;
313
+ // ret.oldLine = line;
314
+ // ret.oldColumn = column;
315
+ // }
239
316
  // if (newUrl) {
240
317
  // ret.newUrl = newUrl;
241
318
  // ret.newLine = newLine;
242
319
  // ret.newColumn = newColumn;
243
320
  // }
244
321
  resolve(ret);
245
- } else {
246
- function build(functionName, url, line, column) {
247
- return `${functionName ? "at " + functionName + " " : ""}${url}:${line}:${column}`;
248
- }
249
- let str;
322
+ }
323
+ else {
324
+ var str = void 0;
250
325
  if (newUrl) {
251
- str = `${build(functionName, newUrl, newLine, newColumn)} (${build("", url, line, column)})`;
252
- } else {
326
+ str = "".concat(build(functionName, newUrl, newLine, newColumn), " (").concat(build("", url, line, column), ")");
327
+ }
328
+ else {
253
329
  str = build(functionName, url, line, column);
254
330
  }
255
331
  resolve(str);
@@ -257,56 +333,68 @@ function processFrame(functionName, url, line, column)
257
333
  });
258
334
  });
259
335
  }
260
-
261
336
  if (json) {
262
- let parsed;
337
+ var parsed = void 0;
263
338
  try {
264
339
  parsed = JSON.parse(stack);
265
- if (!Array.isArray(parsed))
340
+ if (!Array.isArray(parsed)) {
266
341
  throw new Error("Expected array");
267
- } catch (err) {
268
- console.error(`Can't parse json ${err}`);
342
+ }
343
+ }
344
+ catch (err) {
345
+ console.error("Can't parse json ".concat(err));
269
346
  process.exit(1);
270
347
  }
271
- Promise.all(parsed.map((frame) => {
272
- if (verbose)
348
+ Promise.all(parsed.map(function (frame) {
349
+ if (verbose) {
273
350
  console.error("got frame frame", frame);
351
+ }
274
352
  return processFrame(frame.functionName || "", frame.sourceURL || "", frame.line, frame.column);
275
- })).then((results) => {
276
- 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
+ }
277
359
  frame.index = index;
278
360
  });
279
361
  // console.log("shit", results);
280
362
  console.log(JSON.stringify(results, null, 4));
281
- }).catch((error) => {
363
+ })["catch"](function (error) {
282
364
  console.error("Got an error", error);
283
365
  process.exit(2);
284
366
  });
285
- } else {
286
- 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) {
287
373
  x = x.trim();
288
- let match = / *at *([^ ]*).* \(?([^ ]+):([0-9]+):([0-9]+)/.exec(x);
374
+ var match = / *at *([^ ]*).* \(?([^ ]+):([0-9]+):([0-9]+)/.exec(x);
289
375
  if (!match) {
290
376
  match = /([^ ]+@)?(.*):([0-9]+):([0-9]+)/.exec(x);
291
377
  }
292
- if (verbose)
378
+ if (verbose) {
293
379
  console.error(x, " => ", match);
380
+ }
294
381
  if (!match) {
295
- const nolinecol = /([^ ]*)(.*)/.exec(x);
382
+ var nolinecol = /([^ ]*)(.*)/.exec(x);
296
383
  if (nolinecol) {
297
384
  return nolinecol[0];
298
385
  }
299
386
  return x;
300
387
  }
301
388
  return processFrame(match[1] || "", match[2], parseInt(match[3]), parseInt(match[4]));
302
- })).then((results) => {
389
+ }))
390
+ .then(function (results) {
303
391
  if (!results.length) {
304
392
  throw new Error("Empty output");
305
393
  }
306
- results.forEach(str => {
394
+ results.forEach(function (str) {
307
395
  console.log(str);
308
396
  });
309
- }).catch((error) => {
397
+ })["catch"](function (error) {
310
398
  console.error("Got an error", error);
311
399
  process.exit(3);
312
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": "17.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
+ }