Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Happy Thread
Jul 10, 2005

by Fluffdaddy
Plaster Town Cop
If I want to make HTML content that is embeddable into other people's pages, is there any reason not to forego iframes for this, but rather just a div tag + a script tag wherever the user wants it to embed? I'm picturing the plan of: The script expands out the div with content, and also loads a custom stylesheet for it that only applies to children of that div, and loads a couple other small helper script files so the embedded code stays small.

Adbot
ADBOT LOVES YOU

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



Dumb Lowtax posted:

If I want to make HTML content that is embeddable into other people's pages, is there any reason not to forego iframes for this, but rather just a div tag + a script tag wherever the user wants it to embed? I'm picturing the plan of: The script expands out the div with content, and also loads a custom stylesheet for it that only applies to children of that div, and loads a couple other small helper script files so the embedded code stays small.

CORS, for one. Do all of your users have permission and understanding of how to alter the CORS headers of the sites they're including your content into?

Conflicting styles, for another. You could mitigate this by randomizing the style names in your packaging step and including an exhaustive CSS reset type thing in the one you pull in.

Rand Ecliptic
May 23, 2003

Jesus Saves! - And Takes Half Damage!!
edit: reposted in the web development thread

Rand Ecliptic fucked around with this message at 04:43 on Oct 18, 2018

Raskolnikov2089
Nov 3, 2006

Schizzy to the matic
I'm writing a Node script to perform a lighthouse audit on about 5-600 webpages. Each audit returns a large JSON response, of which I only need a very small part of ( I end up with about 5KB from each 29MB response and writing that to a separate JSON file, for further parsing down the line.). You have to run each audit individually, there's not a batch method provided in the library.

I'm primarily a front ender and know enough Node to be dangerous. I'm assuming my normal Promises based pattern won't be sufficient with this large a volume.

I thought about wrapping each response in a JSON stream, but the individual responses aren't really large enough to justify it. It's just that I will have so many individual response that will quickly add up to a large number that I don't think it would be best to store in memory.

The time it takes isn't a big deal, this will eventually be offloaded to a chron-job that runs a headless browser.

What's the best path forward? I'm thinking of just running my promises in serial, but I'm hoping there's a less naive solution out there. Maybe a promise queue of some sort?

Help me JS thread, you're my only hope.

Raskolnikov2089 fucked around with this message at 19:01 on Oct 20, 2018

Doom Mathematic
Sep 2, 2008
Honestly I don't see a serious problem with just running all those promises serially. That's something you might be able to write yourself if you enjoy that kind of thing, or if not you can pull in a slightly more fully-feature promise library like Bluebird and use its built-in serial promise iteration method.

The key thing is what you do in the then block once the 29MB response comes back after the audit is done. Don't save the entire 29MB response. Just grab the relevant 5kB, append it to your small output JSON object, then discard the rest of the response object (i.e. let it drop out of scope, and Node.js will eventually free up the memory it was using). You'll be fine.

But be sure to correctly handle the case where one or more of the audits fails. You'll probably want a way to log that failure but press on with the rest of the batch?

Ranzear
Jul 25, 2013

29MB each (holy cow) is gonna be big enough that serial should work just fine (else you have a pipe big enough to not care). If you were grabbing >1000 ~1kb files, yeah, that's when parallelism kicks in to high gear because the majority is taken up by latency and handshakes/ssl.

Raskolnikov2089
Nov 3, 2006

Schizzy to the matic

Doom Mathematic posted:

But be sure to correctly handle the case where one or more of the audits fails. You'll probably want a way to log that failure but press on with the rest of the batch?

Very good point I hadn't considered, thanks, and a very likely scenario given how prone to failure lighthouse audits are.

Ranzear posted:

29MB each (holy cow) is gonna be big enough that serial should work just fine (else you have a pipe big enough to not care). If you were grabbing >1000 ~1kb files, yeah, that's when parallelism kicks in to high gear because the majority is taken up by latency and handshakes/ssl.

Yeah and its 29MB after I've cut out every other audit. Unfortunately this particular audit is the one that saves all the artifacts. One thing to add more color, there's not a remote connection going on, aside from loading the URL in the browser. This is all happening on my machine, the audit happens in Node, and the audit report is completed locally, without any external connections. Eventually I will offload it to an EC2, but for MVP I just want it running locally.

Unless that changes things, I believe I will press forward with Promises in serial. It's funny how the longer I code, the more often something I think is the naive solution is usually an alright way to do things.

Raskolnikov2089 fucked around with this message at 19:38 on Oct 21, 2018

TIP
Mar 21, 2006

Your move, creep.



I'm trying to set up a static file server using Node, Express, and Passport that requires you to be logged in to access certain files.

My server is all set up and working for authentication and static file serving, I just can't figure out how to configure Express to only serve a certain folder if the user is logged in.

For my public files the setup is like this:
app.use(express.static(__dirname + '/public'));

Looking around, someone said you could add a call to your auth middleware in that, which I tried like this:
app.use(isLoggedIn, express.static(__dirname + '/private'));
(isLoggedIn is a function that returns next() if the user is authenticated)

This... did not work. I also tried setting up a route that runs this:
app.use(express.static('./private'));
when the user is logged in. However, as I expected, that makes all those files accessible to anyone once a logged in user tries to access them.

Any ideas? I'm pretty sure this is stupid simple, but my brain is melted after hours of reading documentation and forum posts on the subject. :downs:

[edit]
Nevermind, I got it working. The auth middleware on the app.use turned out to work, if I put it after every other route.
So, in case it ever helps anyone, here's the code I put after all my routes:
app.use(isLoggedIn, express.static('./private'));
[/edit]

TIP fucked around with this message at 04:01 on Oct 23, 2018

Happy Thread
Jul 10, 2005

by Fluffdaddy
Plaster Town Cop
That's a good tip, Tip!

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
What genius thought that coalesce and logical or being the same operator would be a good idea...

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



Joda posted:

What genius thought that coalesce and logical or being the same operator would be a good idea...

Like a lot of JS it's taking syntax from Java and making it do something similar but different and more complicated. It's really more accurate to say there is no logical or operator, just a coalescing operator that looks like the logical or operator from other popular languages. Similarly, the 'and operator' is really sort of a right-coalesce, I guess? There's probably a more accurate technical term for that that I just don't know.

Of course, that explanation would have confused the poo poo out of me when I was trying to learn the language ten years ago :|

Khorne
May 1, 2002

Munkeymon posted:

Like a lot of JS it's taking syntax from Java and making it do something similar but different and more complicated. It's really more accurate to say there is no logical or operator, just a coalescing operator that looks like the logical or operator from other popular languages. Similarly, the 'and operator' is really sort of a right-coalesce, I guess? There's probably a more accurate technical term for that that I just don't know.

Of course, that explanation would have confused the poo poo out of me when I was trying to learn the language ten years ago :|
The truth is always worse.

The first line of the page blew my mind as someone who will casually drop an & or | without thinking when appropriate:

quote:

Bitwise operators treat their operands as a sequence of 32 bits
I'm glad I usually change them to something anyone will intuitively understand before letting the code leave my hands.

Khorne fucked around with this message at 21:02 on Oct 23, 2018

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



Khorne posted:

The truth is always worse.

The first line of the page blew my mind as someone who will casually drop an & or | when it makes sense to:
I'm glad I usually change them to something anyone will intuitively understand before letting the code leave my hands.

To be clear, I was talking about the 'logical operators' || and &&, not the bitwise operators | and &. I've been bitten by the bitwise thing, too.

Khorne
May 1, 2002

Munkeymon posted:

To be clear, I was talking about the 'logical operators' || and &&, not the bitwise operators | and &. I've been bitten by the bitwise thing, too.
Not sure how I got confused there. And yeah, using || to coalesce is mildly confusing at first. At least to me, "why would or work this way?"

Something of a tangent, but I ran into this code:
code:
let {code} = obj || {code: 'stuff'};
setting the lhs to undefined/null instead of to the rhs.

edit: Fixed wording. Apologies.

Khorne fucked around with this message at 21:28 on Oct 23, 2018

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



Khorne posted:

Not sure how I got confused there. And yeah, using || to coalesce is mildly confusing at first. At least to me, "why would or work this way?"

Something of a tangent, but I ran into this code:
code:
let {code} = obj || {code: 'stuff'};
Throwing undefined/null errors.

&& behaves similarly! Try 1 && 2 in a browser console.

Yeah, if obj doesn't exist, that'll error. It's always an error to direct-reference something that doesn't exist. You'd do window.obj instead.

Khorne
May 1, 2002

Munkeymon posted:

&& behaves similarly! Try 1 && 2 in a browser console.

Yeah, if obj doesn't exist, that'll error. It's always an error to direct-reference something that doesn't exist. You'd do window.obj instead.
I worded that poorly. Object deconstruction doesn't work with ||, at least not in chrome. It will always set the variable to the lhs as long as the lhs itself isn't undefined. If obj itself is undefined, it will go with the rhs.

code:
let {test} = 1 || {test: "yes"};
//test = undefined; 
//presumably because the key is undefined

let {test} = undefined || {test: "yes"};
//test = "yes"; 
//lhs is undefined, go with rhs

let {test} = {test: undefined} || {test: "yes"};
//test = undefined;
//because that's the key's value
 
There are a bunch of react tutorials with people using it with object deconstruction anyway. Things like const {foo} = this.props || {foo: 'I never test my code'}; I'm sure bugs exist due to this in many JS code bases.

Khorne fucked around with this message at 21:47 on Oct 23, 2018

Doom Mathematic
Sep 2, 2008
This happens because the || operator is testing the truthiness of obj, not the truthiness of obj.code.

For a more relaxing solution:

JavaScript code:
let code = obj.code || 'stuff'

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



Khorne posted:

I worded that poorly. Object deconstruction doesn't work with ||, at least not in chrome. It will always set the variable to the lhs as long as the lhs itself isn't undefined. If obj itself is undefined, it will go with the rhs.

code:
let {test} = 1 || {test: "yes"};
//test = undefined; 
//presumably because the key is undefined

let {test} = undefined || {test: "yes"};
//test = "yes"; 
//lhs is undefined, go with rhs

let {test} = {test: undefined} || {test: "yes"};
//test = undefined;
//because that's the key's value
 
There are a bunch of react tutorials with people using it with object deconstruction anyway. Things like const {foo} = this.props || {foo: 'I never test my code'}; I'm sure bugs exist due to this in many JS code bases.

Oh, yeah, gotcha. That's the behavior I'd expect, but a lot of JS users don't know the language - especially the way newer features work :(

Love Stole the Day
Nov 4, 2012
Please give me free quality professional advice so I can be a baby about it and insult you
The only piece of feedback that I got from those TripleByte people after doing their interview thing recently that wasn't BS imo is that I was too slow with debugging a Javascript codebase that they sent me.

One of the main reasons for this is that when I'm trying to read Javascript code is that often I have no idea what I'm looking at. In VSCode, their Intellisense has no idea what anything is (i.e. everything has the "any" type when you mouse-over it) so I can't just F12 my way to figure out what I'm looking at. With TypeScript and other C++-like languages it's much easier to find out what you're looking at and therefore get accquainted more quickly with a codebase that you need to debug.

My question is about how I can move more quickly with debugging a Javascript code base because I was only able to fix like 1 and a half bugs out of 5 in the 20 minutes they gave me to poke around in there.

Happy Thread
Jul 10, 2005

by Fluffdaddy
Plaster Town Cop
Isn't F12 "jump to definition"?

I remedied the lack of this in JavaScript by coding up a special code displayer, that

1. Prints out into the browser the source code of any of my JavaScript classes (and everything I do is inside es6 classes), one at a time using a table of links
2. Places links inline in that code to definitions. It scans an array of all my class names, and replaces every instance of one of those identifiers in the source code with a link that causes that code to pop up instead
3. Distribute my code library with this special code displayer

lol

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



Love Stole the Day posted:

The only piece of feedback that I got from those TripleByte people after doing their interview thing recently that wasn't BS imo is that I was too slow with debugging a Javascript codebase that they sent me.

One of the main reasons for this is that when I'm trying to read Javascript code is that often I have no idea what I'm looking at. In VSCode, their Intellisense has no idea what anything is (i.e. everything has the "any" type when you mouse-over it) so I can't just F12 my way to figure out what I'm looking at. With TypeScript and other C++-like languages it's much easier to find out what you're looking at and therefore get accquainted more quickly with a codebase that you need to debug.

My question is about how I can move more quickly with debugging a Javascript code base because I was only able to fix like 1 and a half bugs out of 5 in the 20 minutes they gave me to poke around in there.

Can you run it in a browser? Chrome should be able to take you to definitions when you're stopped on an appropriate breakpoint.

Chenghiz
Feb 14, 2007

WHITE WHALE
HOLY GRAIL

Love Stole the Day posted:

My question is about how I can move more quickly with debugging a Javascript code base because I was only able to fix like 1 and a half bugs out of 5 in the 20 minutes they gave me to poke around in there.

F12 works in VSCode (usually). If not at least you can ctrl-f on a function or variable name and get to its definition that way.

duz
Jul 11, 2005

Come on Ilhan, lets go bag us a shitpost


I think you have to open the containing folder for VS Code to scan the files that aren't open.
Also, I discovered that VS Code will still consume .d.ts files and give you proper intellisense even if you're using JavaScript. You just use a jsconfig.json file instead of a tsconfig.json file.

spacebard
Jan 1, 2007

Football~
I use the npm intellisense extension for any non-relative node_module imports. It's worth it to check out vscode-awesome for any other extensions like IntelliJ key bindings. Because gently caress, F12 is dumb.

Roadie
Jun 30, 2013
Focusing on types is the wrong approach for cursory JS debugging. You should be looking for all the casual mistakes it's really easy to make in this language, like ==/=== problems, this bindings in callbacks, pulling vars from the wrong nested scope, undefined vs null confusion, etc.

Happy Thread
Jul 10, 2005

by Fluffdaddy
Plaster Town Cop

Doom Mathematic posted:

The system of loading which uses module to export things from one source file and require to import them into another file is called "CommonJS". This works fine in an environment like Node.js which actually supports/implements CommonJS. A web browser, though, doesn't. Trying to access module or require in this context should cause an error, as you've seen.

Since reading this (which was helpful), I just now found out es6 has its own support for modules!

https://stackoverflow.com/questions/950087/how-do-i-include-a-javascript-file-in-another-javascript-file

quote:

ECMAScript modules in browsers
Browsers have had support for loading ECMAScript modules directly (no tools like Webpack required) since Safari 10.1, Chrome 61, Firefox 60, and Edge 16. Check the current support at caniuse.

<script type="module">
import { hello } from './hello.mjs';
hello('world');
</script>
// hello.mjs
export function hello(text) {
const div = document.createElement('div');
div.textContent = `Hello ${text}`;
document.body.appendChild(div);
}
Read more at: https://jakearchibald.com/2017/es-modules-in-browsers/

Hopefully this means the the code library I wrote can just be referenced by people through one script tag's URL and the other three .js files can come along for the ride due to including this syntax. This is still part of my effort mentioned above to let users easily embed panels from my site in their pages, with the least amount of stuff added to their HTML file as possible.

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



Dumb Lowtax posted:

Since reading this (which was helpful), I just now found out es6 has its own support for modules!

https://stackoverflow.com/questions/950087/how-do-i-include-a-javascript-file-in-another-javascript-file


Hopefully this means the the code library I wrote can just be referenced by people through one script tag's URL and the other three .js files can come along for the ride due to including this syntax. This is still part of my effort mentioned above to let users easily embed panels from my site in their pages, with the least amount of stuff added to their HTML file as possible.

https://jakearchibald.com/2017/es-modules-in-browsers/#no-credentials

TheFluff
Dec 13, 2006

FRIENDS, LISTEN TO ME
I AM A SEAGULL
OF WEALTH AND TASTE

Joda posted:

What genius thought that coalesce and logical or being the same operator would be a good idea...

The logical AND/OR operators returning one of their operands rather than a boolean is actually quite common in dynamically typed languages. Perl and Python both have the same behavior, and using logical OR to coalesce is pretty useful and idiomatic in all of them. It's much less useful in statically typed languages of course, and quickly gets obnoxious in Typescript where you get weird union types if you do it with operands of (potentially) different types.

22 Eargesplitten
Oct 10, 2010



Is it possible to insert a flex container and elements to a page through JS? I’ve got a header container and items I want at the top of every page as a banner but I’m tired of editing on every single page. insertAdjacentHTML() only seems to work with one element rather than multiple so I think I would have to use it for every element. That is awkward and possibly slow, although I don’t know about the second one.

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

22 Eargesplitten posted:

Is it possible to insert a flex container and elements to a page through JS? I’ve got a header container and items I want at the top of every page as a banner but I’m tired of editing on every single page. insertAdjacentHTML() only seems to work with one element rather than multiple so I think I would have to use it for every element. That is awkward and possibly slow, although I don’t know about the second one.

Sure, just add an element like normal and either give it class that already exists to make it a flexbox, or slap on style attributes to do the same. Nothing magic about flex; it's just CSS.

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



22 Eargesplitten posted:

Is it possible to insert a flex container and elements to a page through JS? I’ve got a header container and items I want at the top of every page as a banner but I’m tired of editing on every single page. insertAdjacentHTML() only seems to work with one element rather than multiple so I think I would have to use it for every element. That is awkward and possibly slow, although I don’t know about the second one.

You can inline the style in attributes and insert the whole thing at once

JavaScript code:
document.getElementById('header-box-or-whatever')
  .insertAdjacentHTML('<div style="display: flex"><div>etc</div></div>');

22 Eargesplitten
Oct 10, 2010



Lumpy posted:

Sure, just add an element like normal and either give it class that already exists to make it a flexbox, or slap on style attributes to do the same. Nothing magic about flex; it's just CSS.

Okay. I'm still futzing with it, but it looks like the cPanel editor is just an rear end in a top hat that throws fake errors and warnings. I've got a ticket in with my hosting provider to see if I can do remote editing with Atom. I've got Remote-FTP set up in Atom but I think I did it wrong or didn't give the account the right permissions or something.

The Fool
Oct 16, 2003


22 Eargesplitten posted:

Okay. I'm still futzing with it, but it looks like the cPanel editor is just an rear end in a top hat that throws fake errors and warnings. I've got a ticket in with my hosting provider to see if I can do remote editing with Atom. I've got Remote-FTP set up in Atom but I think I did it wrong or didn't give the account the right permissions or something.

Have you tried using a regular ftp client like FileZilla to test? If a regular FTP client works, then your issue is with your Atom configuration.

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
In a React component I have this function:

JavaScript code:
async generateMaze(maze_id) {
    const mazeRequest = new Request(
        "someAPIURL" + maze_id.toString(),
        {
            method: "GET",
            headers: {
                "accept": "application/json"
            }
        }
    );

    const mazeResponse = await fetch(mazeRequest);

    if (mazeResponse.status !== 200) {
        throw new Error("Something went wrong when fecthing maze");
    }

    const mazeData = await mazeResponse.json();

    this.setState({labyrinthState: Object.assign({}, mazeData)});
}
Why am I getting "this.setState is not a function" when it's run?

E: When debugging, it looks like the only thing that exists on "this" is the function itself and nothing else... I thought classes were supposed to get rid of weird this scoping in JS :gonk:

E2: Found the issue. I was calling the function from another component, and the function inherited the scope I guess.

Joda fucked around with this message at 12:39 on Nov 10, 2018

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Joda posted:

E2: Found the issue. I was calling the function from another component, and the function inherited the scope I guess.
I guess this was something like
code:
setTimeout(someObj.someFunc, 1000);
Which tends to mess with the "this", because you're passing the function pointer, which doesn't come with embedded 'this'.
You can instead do this kind of thing like
code:
setTimeout(() => someObj.someFunc(), 1000);
This way setTimeout's function pointer is to the lambda that calls someObj.someFunc - when you call a member function via its owner that implicitly includes giving it the 'this' parameter, but if you use it as a variable it's just a function pointer and doesn't have any bound parameters.

Bruegels Fuckbooks
Sep 14, 2004

Now, listen - I know the two of you are very different from each other in a lot of ways, but you have to understand that as far as Grandpa's concerned, you're both pieces of shit! Yeah. I can prove it mathematically.

roomforthetuna posted:

I guess this was something like
code:
setTimeout(someObj.someFunc, 1000);
Which tends to mess with the "this", because you're passing the function pointer, which doesn't come with embedded 'this'.
You can instead do this kind of thing like
code:
setTimeout(() => someObj.someFunc(), 1000);
This way setTimeout's function pointer is to the lambda that calls someObj.someFunc - when you call a member function via its owner that implicitly includes giving it the 'this' parameter, but if you use it as a variable it's just a function pointer and doesn't have any bound parameters.

i would generally prefer
code:
someObj.someFunc.bind(this)
over the arrow function in this case, it's a little terser and makes it more obvious that the scope is important

MrMoo
Sep 14, 2000

Once you are in ES6/7 land you end up with a lot of empty lambda parameter functions like that. It's ugly for the most part everywhere.
JavaScript code:
wait(1000).then(() => someObj.someFunc())
It's so easy to mess this up and just insert the function call directly and have it actually work in testing then fail spectacularly in production.
JavaScript code:
wait(1000).then(someObj.someFunc())

MrMoo fucked around with this message at 17:23 on Nov 10, 2018

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Bruegels Fuckbooks posted:

[prefer bind] it's a little terser
.bind(this) adds 10 characters, the lambda adds 8 characters including spaces, as few as 6 if you skip the spaces.

The "more explicit" thing is an okay reason though. I prefer the lambda because I use it elsewhere too - not using bind means one fewer thing I have to remember how it works.

Edit: oh wait, someObj.someFunc.bind(this) would do the thing that you probably *don't* want, anyway. someObj.someFunc.bind(someObj) would be the thing you more likely want to do.

roomforthetuna fucked around with this message at 02:10 on Nov 11, 2018

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
I prefer the lambda notation as well, and actually find it more declarative than bind. I've had to do this kind of thing before with callbacks in TS, but I thiught it was a thing of the past with es6. Like in C++ you can throw a lambda (with the right capturing setup) or a member function pointer around willy nilly and this will always refer to the original scope.

Adbot
ADBOT LOVES YOU

Osmosisch
Sep 9, 2007

I shall make everyone look like me! Then when they trick each other, they will say "oh that Coyote, he is the smartest one, he can even trick the great Coyote."



Grimey Drawer
In general I've found that using 'this' is mostly unnecessary and confusing. Arrow functions only made it worse (except if you were already avoiding 'this' in the first place).

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply