Re: Any way to detect an async stack trace (like Chrome devtools does)?
> The way promises are chained means that some patterns like async loops would
> theoretically unroll to very long stack traces
Devtools in fact does that (has a button at the bottom of the stack to
keep loading more frames).
I think it would be better for it to be smart and not have duplicate
frames in the stack, so a loop would result in only one unique set of
entries in the stack trace and not repeat.
#!/JoePea
On Sun, Jul 12, 2020 at 11:53 AM Jacob Bloom wrote:
>
> Reading through the issue JoePea linked to, it looks like the difficulties
> with standardized async stack traces are twofold:
>
> 1. Even with the error stacks proposal, the implementer has total say over
> what qualifies as a stack frame
> 2. The way promises are chained means that some patterns like async loops
> would theoretically unroll to very long stack traces, and right now engines
> aren't required to keep track of those frames; requiring them to do so would
> place a burden on implementers that could quickly lead to slowdowns and
> memory issues
>
> What if there was a standard way to mark a Promise as an important stack
> frame, which the implementer is free to ignore? Maybe something like
> `Promise.prototype.trace()`
>
> On Fri, Jul 10, 2020 at 10:22 PM #!/JoePea wrote:
>>
>> Hello Kai! That example is so meta with its own output showing the
>> numbers relative to the code including its own output! :)
>>
>> That's what I originally wanted to do, but that doesn't give us an
>> async stack trace, it only gives a sync stack trace (I presume within
>> the current event loop task).
>>
>> For example:
>>
>> ```js
>> const originalFetch = globalThis.fetch
>>
>> globalThis.fetch = function(...args) {
>> const stack = new Error().stack
>> console.log(stack)
>> return originalFetch.apply(globalThis, args)
>> }
>>
>> const sleep = t => new Promise(r => setTimeout(r, t))
>>
>> async function one() {
>> console.log('1')
>> await sleep(10)
>> two()
>> }
>>
>> async function two() {
>> console.log('2')
>> await sleep(10)
>> three()
>> }
>>
>> async function three() {
>> console.log('3')
>> await sleep(10)
>> return await fetch('https://unpkg.com/[email protected]')
>> }
>>
>> async function main() {
>> await one()
>> }
>>
>> main()
>> ```
>>
>> Output:
>>
>> ```
>> 1
>> 2
>> 3
>> Error
>> at globalThis.fetch (pen.js:5)
>> at three (pen.js:27)
>> ```
>>
>> Live example:
>>
>> https://codepen.io/trusktr/pen/b8fd92752b4671268f516ad3804869e4?editors=1010
>>
>> I opened a request for this over here:
>> https://github.com/tc39/proposal-error-stacks/issues/34
>>
>> #!/JoePea
>>
>> On Fri, Jul 10, 2020 at 1:21 PM kai zhu wrote:
>> >
>> > > (I want to detect traces in third-party code installed locally).
>> >
>> > 1. here's 15-line javascript-hack to trace async-fetch-calls from
>> > 3rd-party-cdn-library
>> >
>> > ```html
>> >
>> >
>> >
>> > test.html
>> >
>> > (function () {
>> > /*
>> > * 15-line-javascript-hack to trace async-fetch-calls
>> > * enable hack by adding search-query "?modeDebugFetch=1" to web-url
>> > */
>> > "use strict";
>> > if ((/\bmodeDebugFetch=1\b/).test(location.search)) {
>> > let fetch0;
>> > fetch0 = globalThis.fetch;
>> > globalThis.fetch = function (...argList) {
>> > let errStack = new Error().stack;
>> > console.error("\n\nfetch-call-arguments:");
>> > console.error(JSON.stringify(argList, undefined, 4));
>> > console.error("\n\nfetch-call-trace:");
>> > console.error(errStack);
>> > return fetch0(...argList);
>> > };
>> > }
>> > }());
>> >
>> >
>> > https://unpkg.com/http-client/umd/http-client.js";>
>> >
>> > (async function foo() {
>> > "use strict";
>> > let thirdParty = window.HTTPClient;
>> > let myFetch = thirdParty.createFetch(
>> > thirdParty.base("https://api.stripe.com/v1";),
>> > thirdParty.accept("application/json")
>> > );
>> > let response = await myFetch("/customers/5");
>> > console.log(response.jsonData);
>> > /*
>> > dev-console-output - http://localhost:8081/test.html?modeDebugFetch=1
>> > fetch-call-arguments:
>> > [
>> > "https://api.stripe.com/v1/customers/5";,
>> > {
>> > "headers": {
>> > "Accept": "application/json"
>> > },
>> > "responseHandlers": [
>> > null
>> > ]
>> > }
>> > ]
>> > fetch-call-trace:
>> > Error
>> > at globalThis.fetch (test.html?modeDebugFetch=1:16)
>> > at http-client.js:194
>> > at http-client.js:127
>> > at http-client.js:217
>> > at http-client.js:126
>> > at http-client.js:154
>> > at http-client.js:95
>> > at foo (test.html?modeDebugFetch=1:35)
>> >
Re: Any way to detect an async stack trace (like Chrome devtools does)?
Reading through the issue JoePea linked to, it looks like the difficulties
with standardized async stack traces are twofold:
1. Even with the error stacks proposal, the implementer has total say over
what qualifies as a stack frame
2. The way promises are chained means that some patterns like async loops
would theoretically unroll to very long stack traces, and right now engines
aren't required to keep track of those frames; requiring them to do so
would place a burden on implementers that could quickly lead to slowdowns
and memory issues
What if there was a standard way to mark a Promise as an important stack
frame, which the implementer is free to ignore? Maybe something like
`Promise.prototype.trace()`
On Fri, Jul 10, 2020 at 10:22 PM #!/JoePea wrote:
> Hello Kai! That example is so meta with its own output showing the
> numbers relative to the code including its own output! :)
>
> That's what I originally wanted to do, but that doesn't give us an
> async stack trace, it only gives a sync stack trace (I presume within
> the current event loop task).
>
> For example:
>
> ```js
> const originalFetch = globalThis.fetch
>
> globalThis.fetch = function(...args) {
> const stack = new Error().stack
> console.log(stack)
> return originalFetch.apply(globalThis, args)
> }
>
> const sleep = t => new Promise(r => setTimeout(r, t))
>
> async function one() {
> console.log('1')
> await sleep(10)
> two()
> }
>
> async function two() {
> console.log('2')
> await sleep(10)
> three()
> }
>
> async function three() {
> console.log('3')
> await sleep(10)
> return await fetch('https://unpkg.com/[email protected]')
> }
>
> async function main() {
> await one()
> }
>
> main()
> ```
>
> Output:
>
> ```
> 1
> 2
> 3
> Error
> at globalThis.fetch (pen.js:5)
> at three (pen.js:27)
> ```
>
> Live example:
>
>
> https://codepen.io/trusktr/pen/b8fd92752b4671268f516ad3804869e4?editors=1010
>
> I opened a request for this over here:
> https://github.com/tc39/proposal-error-stacks/issues/34
>
> #!/JoePea
>
> On Fri, Jul 10, 2020 at 1:21 PM kai zhu wrote:
> >
> > > (I want to detect traces in third-party code installed locally).
> >
> > 1. here's 15-line javascript-hack to trace async-fetch-calls from
> 3rd-party-cdn-library
> >
> > ```html
> >
> >
> >
> > test.html
> >
> > (function () {
> > /*
> > * 15-line-javascript-hack to trace async-fetch-calls
> > * enable hack by adding search-query "?modeDebugFetch=1" to web-url
> > */
> > "use strict";
> > if ((/\bmodeDebugFetch=1\b/).test(location.search)) {
> > let fetch0;
> > fetch0 = globalThis.fetch;
> > globalThis.fetch = function (...argList) {
> > let errStack = new Error().stack;
> > console.error("\n\nfetch-call-arguments:");
> > console.error(JSON.stringify(argList, undefined, 4));
> > console.error("\n\nfetch-call-trace:");
> > console.error(errStack);
> > return fetch0(...argList);
> > };
> > }
> > }());
> >
> >
> > https://unpkg.com/http-client/umd/http-client.js";>
> >
> > (async function foo() {
> > "use strict";
> > let thirdParty = window.HTTPClient;
> > let myFetch = thirdParty.createFetch(
> > thirdParty.base("https://api.stripe.com/v1";),
> > thirdParty.accept("application/json")
> > );
> > let response = await myFetch("/customers/5");
> > console.log(response.jsonData);
> > /*
> > dev-console-output - http://localhost:8081/test.html?modeDebugFetch=1
> > fetch-call-arguments:
> > [
> > "https://api.stripe.com/v1/customers/5";,
> > {
> > "headers": {
> > "Accept": "application/json"
> > },
> > "responseHandlers": [
> > null
> > ]
> > }
> > ]
> > fetch-call-trace:
> > Error
> > at globalThis.fetch (test.html?modeDebugFetch=1:16)
> > at http-client.js:194
> > at http-client.js:127
> > at http-client.js:217
> > at http-client.js:126
> > at http-client.js:154
> > at http-client.js:95
> > at foo (test.html?modeDebugFetch=1:35)
> > at test.html?modeDebugFetch=1:64
> > */
> > }());
> >
> >
> > ```
> >
> >
> > 2. here's real-world-hack added to npm-cli.js to debug its http-requests
> >
> > ```diff
> > C:\Program Files\nodejs\node_modules\npm>git diff
> > diff --git a/bin/npm-cli.js b/bin/npm-cli.js
> > index 561dec0..98cafb8 100644
> > --- a/bin/npm-cli.js
> > +++ b/bin/npm-cli.js
> > @@ -2,17 +2,6 @@
> > ;(function () { // wrapper in case we're in module_context mode
> > +// hack - debug http-request
> > +let httpRequest;
> > +httpRequest = require("https").request.bind(require("https"));
> > +require("https").request = function (...argList) {
> > +if
Re: Any way to detect an async stack trace (like Chrome devtools does)?
Hello Kai! That example is so meta with its own output showing the
numbers relative to the code including its own output! :)
That's what I originally wanted to do, but that doesn't give us an
async stack trace, it only gives a sync stack trace (I presume within
the current event loop task).
For example:
```js
const originalFetch = globalThis.fetch
globalThis.fetch = function(...args) {
const stack = new Error().stack
console.log(stack)
return originalFetch.apply(globalThis, args)
}
const sleep = t => new Promise(r => setTimeout(r, t))
async function one() {
console.log('1')
await sleep(10)
two()
}
async function two() {
console.log('2')
await sleep(10)
three()
}
async function three() {
console.log('3')
await sleep(10)
return await fetch('https://unpkg.com/[email protected]')
}
async function main() {
await one()
}
main()
```
Output:
```
1
2
3
Error
at globalThis.fetch (pen.js:5)
at three (pen.js:27)
```
Live example:
https://codepen.io/trusktr/pen/b8fd92752b4671268f516ad3804869e4?editors=1010
I opened a request for this over here:
https://github.com/tc39/proposal-error-stacks/issues/34
#!/JoePea
On Fri, Jul 10, 2020 at 1:21 PM kai zhu wrote:
>
> > (I want to detect traces in third-party code installed locally).
>
> 1. here's 15-line javascript-hack to trace async-fetch-calls from
> 3rd-party-cdn-library
>
> ```html
>
>
>
> test.html
>
> (function () {
> /*
> * 15-line-javascript-hack to trace async-fetch-calls
> * enable hack by adding search-query "?modeDebugFetch=1" to web-url
> */
> "use strict";
> if ((/\bmodeDebugFetch=1\b/).test(location.search)) {
> let fetch0;
> fetch0 = globalThis.fetch;
> globalThis.fetch = function (...argList) {
> let errStack = new Error().stack;
> console.error("\n\nfetch-call-arguments:");
> console.error(JSON.stringify(argList, undefined, 4));
> console.error("\n\nfetch-call-trace:");
> console.error(errStack);
> return fetch0(...argList);
> };
> }
> }());
>
>
> https://unpkg.com/http-client/umd/http-client.js";>
>
> (async function foo() {
> "use strict";
> let thirdParty = window.HTTPClient;
> let myFetch = thirdParty.createFetch(
> thirdParty.base("https://api.stripe.com/v1";),
> thirdParty.accept("application/json")
> );
> let response = await myFetch("/customers/5");
> console.log(response.jsonData);
> /*
> dev-console-output - http://localhost:8081/test.html?modeDebugFetch=1
> fetch-call-arguments:
> [
> "https://api.stripe.com/v1/customers/5";,
> {
> "headers": {
> "Accept": "application/json"
> },
> "responseHandlers": [
> null
> ]
> }
> ]
> fetch-call-trace:
> Error
> at globalThis.fetch (test.html?modeDebugFetch=1:16)
> at http-client.js:194
> at http-client.js:127
> at http-client.js:217
> at http-client.js:126
> at http-client.js:154
> at http-client.js:95
> at foo (test.html?modeDebugFetch=1:35)
> at test.html?modeDebugFetch=1:64
> */
> }());
>
>
> ```
>
>
> 2. here's real-world-hack added to npm-cli.js to debug its http-requests
>
> ```diff
> C:\Program Files\nodejs\node_modules\npm>git diff
> diff --git a/bin/npm-cli.js b/bin/npm-cli.js
> index 561dec0..98cafb8 100644
> --- a/bin/npm-cli.js
> +++ b/bin/npm-cli.js
> @@ -2,17 +2,6 @@
> ;(function () { // wrapper in case we're in module_context mode
> +// hack - debug http-request
> +let httpRequest;
> +httpRequest = require("https").request.bind(require("https"));
> +require("https").request = function (...argList) {
> +if (process.env.NPM_DEBUG) {
> +console.error(
> +"npm - httpRequest - " + JSON.stringify(argList.slice(0, 2),
> undefined, 4)
> +);
> +}
> +return httpRequest(...argList);
> +};
>// windows: running "npm blah" in this folder will invoke WSH, not node.
>
> C:\Program Files\nodejs\node_modules\npm>
> ```
>
> ```mingw-bash
> $ NPM_DEBUG=1 npm publish foo
> # console-ouput:
> # npm - httpRequest - [
> # {
> # "protocol": "https:",
> # "href": "https://registry.npmjs.org/foo";,
> # "method": "GET",
> # "headers": {
> # "connection": [
> # "keep-alive"
> # ],
> # "user-agent": [
> # "npm/6.13.4 node/v12.16.1 win32 x64"
> # ],
> # ...
> ```
>
>
>
>
>
> On Fri, Jul 10, 2020 at 3:34 AM #!/JoePea wrote:
>>
>> Thanks for the idea! That's similar to what I thought would be necessary. I
>> was hoping to monkey patch `fetch()` to have it get the trace if any `fetch`
>> call, but they would not be async stack
Re: Any way to detect an async stack trace (like Chrome devtools does)?
> (I want to detect traces in third-party code installed locally).
1. here's 15-line javascript-hack to trace async-fetch-calls from
3rd-party-cdn-library
```html
test.html
(function () {
/*
* 15-line-javascript-hack to trace async-fetch-calls
* enable hack by adding search-query "?modeDebugFetch=1" to web-url
*/
"use strict";
if ((/\bmodeDebugFetch=1\b/).test(location.search)) {
let fetch0;
fetch0 = globalThis.fetch;
globalThis.fetch = function (...argList) {
let errStack = new Error().stack;
console.error("\n\nfetch-call-arguments:");
console.error(JSON.stringify(argList, undefined, 4));
console.error("\n\nfetch-call-trace:");
console.error(errStack);
return fetch0(...argList);
};
}
}());
https://unpkg.com/http-client/umd/http-client.js";>
(async function foo() {
"use strict";
let thirdParty = window.HTTPClient;
let myFetch = thirdParty.createFetch(
thirdParty.base("https://api.stripe.com/v1";),
thirdParty.accept("application/json")
);
let response = await myFetch("/customers/5");
console.log(response.jsonData);
/*
dev-console-output - http://localhost:8081/test.html?modeDebugFetch=1
fetch-call-arguments:
[
"https://api.stripe.com/v1/customers/5";,
{
"headers": {
"Accept": "application/json"
},
"responseHandlers": [
null
]
}
]
fetch-call-trace:
Error
at globalThis.fetch (test.html?modeDebugFetch=1:16)
at http-client.js:194
at http-client.js:127
at http-client.js:217
at http-client.js:126
at http-client.js:154
at http-client.js:95
at foo (test.html?modeDebugFetch=1:35)
at test.html?modeDebugFetch=1:64
*/
}());
```
2. here's real-world-hack added to npm-cli.js to debug its http-requests
```diff
C:\Program Files\nodejs\node_modules\npm>git diff
diff --git a/bin/npm-cli.js b/bin/npm-cli.js
index 561dec0..98cafb8 100644
--- a/bin/npm-cli.js
+++ b/bin/npm-cli.js
@@ -2,17 +2,6 @@
;(function () { // wrapper in case we're in module_context mode
+// hack - debug http-request
+let httpRequest;
+httpRequest = require("https").request.bind(require("https"));
+require("https").request = function (...argList) {
+if (process.env.NPM_DEBUG) {
+console.error(
+"npm - httpRequest - " + JSON.stringify(argList.slice(0, 2),
undefined, 4)
+);
+}
+return httpRequest(...argList);
+};
// windows: running "npm blah" in this folder will invoke WSH, not node.
C:\Program Files\nodejs\node_modules\npm>
```
```mingw-bash
$ NPM_DEBUG=1 npm publish foo
# console-ouput:
# npm - httpRequest - [
# {
# "protocol": "https:",
# "href": "https://registry.npmjs.org/foo";,
# "method": "GET",
# "headers": {
# "connection": [
# "keep-alive"
# ],
# "user-agent": [
# "npm/6.13.4 node/v12.16.1 win32 x64"
# ],
# ...
```
On Fri, Jul 10, 2020 at 3:34 AM #!/JoePea wrote:
> Thanks for the idea! That's similar to what I thought would be necessary.
> I was hoping to monkey patch `fetch()` to have it get the trace if any
> `fetch` call, but they would not be async stack traces. For async traces it
> would require instrumentation by injecting code similar to yours (I want to
> detect traces in third-party code installed locally).
>
> #!/JoePea
>
> On Wed, Jul 8, 2020, 2:13 AM kai zhu wrote:
>
>> here's a simple throwaway-function you can wrap around promises like fetch
>> to get the caller's async-stack-trace `promiseWithErrorStack`:
>>
>> ```html
>>
>>
>>
>> test.html
>>
>> (async function foo() {
>> function promiseWithErrorStack(promise) {
>> /*
>> * this function will append current-stack to any err caught from
>>
>> */
>> let errStack;
>> errStack = new Error().stack;
>> return new Promise(function (resolve, reject) {
>> promise.then(resolve).catch(function (err) {
>> // append current errStack to err.stack
>> if (err && typeof err.stack === "string") {
>> err.stack += "\n" + errStack;
>> }
>> reject(err);
>> });
>> });
>> }
>> await promiseWithErrorStack(fetch("https://example.com";)); // at foo
>> (test.html:23)
>>
>> /*
>> console-output:
>>
>> Uncaught (in promise) TypeError: Failed to fetch
>> Error
>> at promiseWithErrorStack (test.html:12)
>> at foo (test.html:23) // async-stack-trace
>> at test.html:32
>> */
>> }());
>>
Re: Any way to detect an async stack trace (like Chrome devtools does)?
Thanks for the idea! That's similar to what I thought would be necessary. I
was hoping to monkey patch `fetch()` to have it get the trace if any
`fetch` call, but they would not be async stack traces. For async traces it
would require instrumentation by injecting code similar to yours (I want to
detect traces in third-party code installed locally).
#!/JoePea
On Wed, Jul 8, 2020, 2:13 AM kai zhu wrote:
> here's a simple throwaway-function you can wrap around promises like fetch
> to get the caller's async-stack-trace `promiseWithErrorStack`:
>
> ```html
>
>
>
> test.html
>
> (async function foo() {
> function promiseWithErrorStack(promise) {
> /*
> * this function will append current-stack to any err caught from
>
> */
> let errStack;
> errStack = new Error().stack;
> return new Promise(function (resolve, reject) {
> promise.then(resolve).catch(function (err) {
> // append current errStack to err.stack
> if (err && typeof err.stack === "string") {
> err.stack += "\n" + errStack;
> }
> reject(err);
> });
> });
> }
> await promiseWithErrorStack(fetch("https://example.com";)); // at foo
> (test.html:23)
>
> /*
> console-output:
>
> Uncaught (in promise) TypeError: Failed to fetch
> Error
> at promiseWithErrorStack (test.html:12)
> at foo (test.html:23) // async-stack-trace
> at test.html:32
> */
> }());
>
>
> ```
>
> On Tue, Jul 7, 2020 at 11:54 PM #!/JoePea wrote:
>
>> Is there some way (perhaps by patching methods on objects?) so we can
>> track async call stacks?
>>
>> When we pause code in devtools, we are able to see the async stack
>> trace of the code.
>>
>> What I'd like to do is to effectively detect the same thing as
>> devtools does at some point in any code. As a specific example, I'd
>> like to detect the async stack trace of any call to `fetch`.
>>
>> Is such a thing possible with runtime code?
>>
>> Or would it require instrumentation of the source code?
>>
>> #!/JoePea
>> ___
>> es-discuss mailing list
>> [email protected]
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>
___
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss
Re: Any way to detect an async stack trace (like Chrome devtools does)?
here's a simple throwaway-function you can wrap around promises like fetch
to get the caller's async-stack-trace `promiseWithErrorStack`:
```html
test.html
(async function foo() {
function promiseWithErrorStack(promise) {
/*
* this function will append current-stack to any err caught from
*/
let errStack;
errStack = new Error().stack;
return new Promise(function (resolve, reject) {
promise.then(resolve).catch(function (err) {
// append current errStack to err.stack
if (err && typeof err.stack === "string") {
err.stack += "\n" + errStack;
}
reject(err);
});
});
}
await promiseWithErrorStack(fetch("https://example.com";)); // at foo
(test.html:23)
/*
console-output:
Uncaught (in promise) TypeError: Failed to fetch
Error
at promiseWithErrorStack (test.html:12)
at foo (test.html:23) // async-stack-trace
at test.html:32
*/
}());
```
On Tue, Jul 7, 2020 at 11:54 PM #!/JoePea wrote:
> Is there some way (perhaps by patching methods on objects?) so we can
> track async call stacks?
>
> When we pause code in devtools, we are able to see the async stack
> trace of the code.
>
> What I'd like to do is to effectively detect the same thing as
> devtools does at some point in any code. As a specific example, I'd
> like to detect the async stack trace of any call to `fetch`.
>
> Is such a thing possible with runtime code?
>
> Or would it require instrumentation of the source code?
>
> #!/JoePea
> ___
> es-discuss mailing list
> [email protected]
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

