JS closing explanation in terms of perl

I understand without problems how perl closure works, like the following

 use 5.012; use strict; use warnings; sub countdown { my $start = shift; return sub { $start-- } } my $c10 = countdown(3); say while( $_ = $c10->() ); 

I am trying to understand the following Javascript snippet:

 var runInSandbox = (function(js, inputPath) { (function() { if ((!context.initialized__QUERY)) { return createContext(); }; })(); (function() { if (typeof(inputPath) !== 'undefined') { (process.argv)[1] = inputPath;; (context)["__dirname"] = path.dirname(inputPath);; return (module)["filename"] = inputPath;; }; })(); return vm.runInContext(js, context, "sibilant"); }); 

NO CHANCE! :( PLEASE can someone rewrite above perl ? I know a little perl - so it will be extremely useful for me to understand the basics of JS and such constructions as:

 (...)() - more precisely (function(){.....})() 

double (( in if

  if ((!context.initialized__QUERY)) { 

or next

  (context)["__dirname"] = something ;; 

or

  return (module)["filename"] = inputPath;; // why double ;;? 

And if someone offers me some resource something like: Learning Javascript for perl programmers - it would be very nice;)

Ps: JS (abbreviated) from here: https://github.com/jbr/sibilant/blob/master/lib/cli.js

+4
source share
2 answers

I am not very good at closing Perl, so I will at least try to demystify this for you.

The form:

 (function(...) { ... })(); 

- self-dependent anonymous function 1 . This means that you write out an anonymous function and then call it immediately. This is usually done for encapsulation 2 . For example, if you create a bunch of variables but don’t want it to pollute the global namespace, you can put it in an anonymous self-running function. However, in this case, I don’t see why the first call is necessary at all, because it just checks the flag or something like that. Even stranger is return inside these self-invoking functions. They are not attached to anything. I would venture to suggest that createContext() initializes the context variable, but that return is useless in it. The same can be said of the following:

 return (module)["filename"] = inputPath;; 

As for the doubles (( and )) , they don't seem to be pretty much needed, and so I'm not sure why the author originally posted it there. For instance:

 if ((!context.initialized__QUERY)) 

No different from:

 if (!context.initialized__QUERY) 

In addition, the brackets in the following are also not needed, as are the double semicolons:

 (context)["__dirname"] = something ;; 

Honestly, it looks like poorly written Javascript or, possibly, JavaScript that was autogenerated (this is most likely the case).

You can rewrite it like this:

 var runInSandbox = function(js, inputPath) { if (!context.initialized__QUERY) { createContext(); }; if (typeof inputPath !== 'undefined') { process.argv[1] = inputPath; context["__dirname"] = path.dirname(inputPath); module["filename"] = inputPath; }; return vm.runInContext(js, context, "sibilant"); }; 

Notes:

  • In Perl, it will be sub { ... }->() .
  • In Perl, you can use { my $var; ... } { my $var; ... } instead of sub { my $var; ... }->() sub { my $var; ... }->() and do { my $var; ...; EXPR } do { my $var; ...; EXPR } do { my $var; ...; EXPR } instead of sub { my $var; ...; return EXPR; }->() sub { my $var; ...; return EXPR; }->() sub { my $var; ...; return EXPR; }->() .
+7
source

I think this is what perl should look like.

 my $runInSandbox = sub { local($js, $inputPath) = ($_[0], $_[1]); sub{if (!$context.initialized_QUERY) { &createContext(); }}->(); sub{ if (defined($inputPath) { $process{"argv"][1] = inputPath; $context{"__dirname"} = &$path{"dirname"}(inputPath); $module["filename"] = inputPath; } }->(); return &$vm{"runInContext"}($js,$context,"sibilant"); }; 
0
source

Source: https://habr.com/ru/post/1480005/


All Articles