dot file cargo culting
ADD
packages/error-stack-shim/.eslintrc.js
+/* global module */
+module.exports = {
+ extends: ['airbnb', 'plugin:prettier/recommended'],
+ env: {
+ es6: true, // supports new ES6 globals (e.g., new types such as Set)
+ },
+ rules: {
+ 'implicit-arrow-linebreak': 'off',
+ 'function-paren-newline': 'off',
+ 'arrow-parens': 'off',
+ strict: 'off',
+ 'no-console': 'off',
+ 'no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
+ 'no-return-assign': 'off',
+ 'no-param-reassign': 'off',
+ 'no-restricted-syntax': ['off', 'ForOfStatement'],
+ 'no-unused-expressions': 'off',
+ 'no-loop-func': 'off',
+ 'import/prefer-default-export': 'off', // contrary to Agoric standard
+ },
+};

ADD
packages/error-stack-shim/.gitignore
+# emacs
+*~
+
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Runtime data
+pids
+*.pid
+*.seed
+*.pid.lock
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+
+# nyc test coverage
+.nyc_output
+
+# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# Bower dependency directory (https://bower.io/)
+bower_components
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (https://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directories
+node_modules/
+jspm_packages/
+
+# TypeScript v1 declaration files
+typings/
+
+# Optional npm cache directory
+.npm
+
+# Optional eslint cache
+.eslintcache
+
+# Optional REPL history
+.node_repl_history
+
+# Yarn Integrity file
+.yarn-integrity
+
+# dotenv environment variables file
+.env
+
+# next.js build output
+.next
+
+.idea/

ADD
packages/error-stack-shim/.prettierrc.json
+{
+ "trailingComma": "all",
+ "singleQuote": true
+}

ADD
packages/error-stack-shim/package.json
+{
+ "name": "@erights/error-stack-shim",
+ "version": "0.0.1",
+ "description": "Shim the Error Stack proposal plus async deep stacks",
+ "main": "index.js",
+ "engines": {
+ "node": ">=11.0"
+ },
+ "scripts": {
+ "test": "tape -r esm 'test/**/test*.js' | tap-spec",
+ "pretty-fix": "prettier --write '**/*.{js,jsx}'",
+ "pretty-check": "prettier --check '**/*.{js,jsx}'",
+ "lint-fix": "eslint --fix '**/*.{js,jsx}'",
+ "lint-check": "eslint '**/*.{js,jsx}'"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/erights/error-stack-shim.git"
+ },
+ "keywords": [
+ "debugging",
+ "stack",
+ "error",
+ "proposal"
+ ],
+ "author": "erights",
+ "license": "Apache-2.0",
+ "bugs": {
+ "url": "https://github.com/erights/error-stack-shim/issues"
+ },
+ "homepage": "https://github.com/erights/error-stack-shim#readme",
+ "dependencies": {
+ "@agoric/harden": "0.0.4",
+ },
+ "devDependencies": {
+ "eslint": "^5.16.0",
+ "eslint-config-airbnb": "^17.1.0",
+ "eslint-config-prettier": "^4.3.0",
+ "eslint-plugin-import": "^2.17.3",
+ "eslint-plugin-jsx-a11y": "^6.2.1",
+ "eslint-plugin-prettier": "^3.1.0",
+ "eslint-plugin-react": "^7.13.0",
+ "esm": "^3.2.25",
+ "prettier": "^1.17.1",
+ "tap-spec": "^5.0.0",
+ "tape": "^4.10.2",
+ "tape-promise": "^4.0.0"
+ },
+ "bundledDependencies": [
+ ]
+}

MODIFY
packages/error-stack-shim/src/scrapedStackFrames.js
packages/error-stack-shim/src/scrapedStackFrames.js
function getScrapedStackFramesUsing(getRawStackString) {
+ /**
+ * line2CWFrame(line) takes a (typically) single line string,
+ * representing a single stackframe of a stacktrace, and returns an
+ * Extended Causeway frame JSON object as defined above.
+ *
+ * <p>There is no standard for how these lines are formatted and
+ * they vary widely between platforms. line2CWFrame scrapes this
+ * line unreliably by using a variety of regular expressions that
+ * we've accumulated over time, to cover all the cases we've seen
+ * across platforms. There are a variety of user-triggered
+ * conditions that can cause this scraping to fail, such as a
+ * methodName that contains an "(" or "@" character.
+ */
+ var line2CWFrame = (function() {
+ // Each of these frame patterns should have the first capture
+ // group be the function name, and the second capture group be
+ // the source URL together with position
+ // information. Afterwards, the lineColPattern will pull apart
+ // these source position components. On all, we assume the
+ // function name, if any, has no colon (":"), at-sign ("@"), or
+ // open paren ("("), as each of these are used to recognize
+ // other parts of a debug line.
+
+ // See https://code.google.com/p/v8/issues/detail?id=4268
+ var V8NestedCallSitePattern = /^eval at (.*) \((.*)\)$/;
+
+ // Seen on FF: The function name is sometimes followed by
+ // argument descriptions enclosed in parens, which we
+ // ignore. Then there is always an at-sign followed by possibly
+ // empty source position.
+ var FFFramePattern = /^\s*([^:@(]*?)\s*(?:\(.*\))?@(.*?)$/;
+
+ // Seen on IE: The line begins with " at ", as on v8, which we
+ // ignore. Then the function name, then the source position
+ // enclosed in parens.
+ var IEFramePattern = /^\s*(?:at\s+)?([^:@(]*?)\s*\((.*?)\)$/;
+
+ // Seem on Safari (JSC): The name optionally followed by an
+ // at-sign and source position information. This is like FF,
+ // except that the at-sign and source position info may
+ // together be absent.
+ var JSCFramePatt1 = /^\s*([^:@(]*?)\s*(?:@(.*?))?$/;
+
+ // Also seen on Safari (JSC): Just the source position info by
+ // itself, with no preceding function name. The source position
+ // always seems to contain at least a colon, which is how we
+ // decide that it is a source position rather than a function
+ // name. The pattern here is a bit more flexible, in that it
+ // will accept a function name preceding the source position
+ // and separated by whitespace.
+ var JSCFramePatt2 = /^\s*?([^:@(]*?)\s*?(.*?)$/;
+
+ // List the above patterns in priority order, where the first
+ // matching pattern is the one used for any one stack line.
+ var framePatterns = [V8NestedCallSitePattern,
+ FFFramePattern, IEFramePattern,
+ JSCFramePatt1, JSCFramePatt2];
+
+
+ // Each of the LineColPatterns should have the first capture
+ // group be the source URL if any, the second be the line
+ // number if any, and the third be the column number if any.
+ // If there are more, then we have an eval where the next three
+ // are the function-name, line, and column within the evaled string.
+
+ // Seen on FF Nightly 30 for execution in evaled strings.
+ // On the left of the &gt; is the position from which eval was
+ // called. On the right is the position within the evaled
+ // string.
+ //
+ // TODO(erights): Handle multiple eval nestings. This is low
+ // priority because SES only exposes eval through functions
+ // that call eval, and so SES never has direct eval
+ // nestings. In any case, if the multiple eval syntax is
+ // encountered, e.g.,
+ // http://example.com line 16 > eval line 1 > eval:2:8
+ // it will match this pattern, but with the first capture
+ // group being "http://example.com line 16 > eval"
+ var FFEvalLineColPatterns =
+ /^(.*) line (\d+)() > ([^:]*):(\d+):(\d+)$/;
+
+ // If the source position ends in either one or two
+ // colon-digit-sequence suffixes, then the first of these are
+ // the line number, and the second, if present, is the column
+ // number.
+ var MainLineColPattern = /^(.*?)(?::(\d+)(?::(\d+))?)?$/;
+
+ // List the above patterns in priority order, where the first
+ // matching pattern is the one used for any one stack line.
+ var lineColPatterns = [FFEvalLineColPatterns, MainLineColPattern];
+
+ function line2CWFrame(line) {
+ var name = line.trim();
+ var source = '?';
+ var span = [];
+ // Using .some here only because it gives us a way to escape
+ // the loop early. We do not use the results of the .some.
+ framePatterns.some(function(framePattern) {
+ var match = framePattern.exec(line);
+ if (match) {
+ name = match[1] || '?';
+ source = match[2] || '?';
+ // Using .some here only because it gives us a way to escape
+ // the loop early. We do not use the results of the .some.
+ lineColPatterns.some(function(lineColPattern) {
+ var sub = lineColPattern.exec(source);
+ if (sub) {
+ // sub[1] if present is the source URL.
+ // sub[2] if present is the line number.
+ // sub[3] if present is the column number.
+ // sub[4] if present is the function name within the evaled
+ // string.
+ // sub[5] if present is the line number within the
+ // evaled string.
+ // sub[6] if present is the column number within
+ // the evaled string.
+ source = sub[1] || '?';
+ if (sub[2]) {
+ if (sub[3]) {
+ span = [[+sub[2], +sub[3]]];
+ } else {
+ span = [[+sub[2]]];
+ }
+ }
+ if (sub.length >= 5) {
+ source = {
+ name: sub[4] === 'eval' ? '?' : (sub[4] || '?'),
+ source: source,
+ span: span
+ };
+ span = [];
+ if (sub[5]) {
+ if (sub[6]) {
+ span = [[+sub[5], +sub[6]]];
+ } else {
+ span = [[+sub[5]]];
+ }
+ }
+ }
+ return true;
+ }
+ return false;
+ });
+ return true;
+ }
+ return false;
+ });
+ if (name === 'Anonymous function') {
+ // Adjust for weirdness seen on IE
+ name = '?';
+ } else if (name.indexOf('/') !== -1) {
+ // Adjust for function name weirdness seen on FF.
+ name = name.replace(/[/<]/g,'');
+ var parts = name.split('/');
+ name = parts[parts.length -1];
+ }
+ if (source === 'Unknown script code' || source === 'eval code') {
+ // Adjust for weirdness seen on IE
+ source = '?';
+ }
+ return {
+ name: name,
+ source: source,
+ span: span
+ };
+ }
+
+
+ });
}
export { getScrapedStackFramesUsing };
+

MODIFY
packages/error-stack-shim/src/v8StackFrames.js
packages/error-stack-shim/src/v8StackFrames.js
function getV8StackFramesUsing(UnsafeError) {
+ const unsafeCaptureStackTrace = UnsafeError.captureStackTrace;
+
+ UnsafeError.prepareStackTrace = function(err, sst) {
+ if (ssts === undefined) {
+ // If an error happens in the debug module after setting up
+ // this prepareStackTrace but before or during the
+ // initialization of ssts, then this method gets called
+ // with ssts still undefined (undefined). In that case, we
+ // should report the error we're asked to prepare, rather
+ // than an error thrown by failing to prepare it.
+ ses.logger.error('Error while initializing debug module', err);
+ } else {
+ ssts.set(err, sst);
+ }
+ // Technically redundant, but prepareStackTrace is supposed
+ // to return a value, so this makes it clearer that this value
+ // is undefined (undefined).
+ return undefined;
+ };
+
+ UnsafeError.captureStackTrace = function(obj, opt_MyError) {
+ const wasFrozen = Object.isFrozen(obj);
+ const stackDesc = Object.getOwnPropertyDescriptor(obj, 'stack');
+ try {
+ const result = unsafeCaptureStackTrace(obj, opt_MyError);
+ const ignore = obj.stack;
+ return result;
+ } finally {
+ if (wasFrozen && !Object.isFrozen(obj)) {
+ if (stackDesc) {
+ Object.defineProperty(obj, 'stack', stackDesc);
+ } else {
+ delete obj.stack;
+ }
+ Object.freeze(obj);
+ }
+ }
+ };
+
+ const ssts = new WeakMap(); // error -> sst
+
+ /**
+ * Given a v8 CallSite object as defined at
+ * https://code.google.com/p/v8-wiki/wiki/JavaScriptStackTraceApi
+ * return a stack frame in Extended Causeway Format as defined
+ * above.
+ */
+ function callSite2CWFrame(callSite) {
+ if (typeof callSite === 'string') {
+ // See https://code.google.com/p/v8/issues/detail?id=4268
+ return line2CWFrame(callSite);
+ }
+ const source = callSite.isEval() ?
+ callSite2CWFrame(callSite.getEvalOrigin()) :
+ '' + (callSite.getFileName() || '?');
+ const name = '' + (callSite.getFunctionName() ||
+ callSite.getMethodName() || '?');
+ return {
+ name: name,
+ source: source,
+ span: [ [ callSite.getLineNumber(), callSite.getColumnNumber() ] ]
+ };
+ }
+
+ /**
+ * Returns a stack in Extended Causeway Format as defined above.
+ */
+ function getCWStack(err) {
+ if (Object(err) !== err) { return undefined; }
+ const sst = ssts.get(err);
+ if (sst === undefined && err instanceof Error) {
+ // We hope it triggers prepareStackTrace
+ const ignore = err.stack;
+ sst = ssts.get(err);
+ }
+ if (sst === undefined) { return undefined; }
+
+ return {calls: sst.map(callSite2CWFrame)};
+ };
+
+
}
export { getV8StackFramesUsing };

dot file cargo culting