Problem using "eval" to define a top-level function when called from within an object

I wrote (in JavaScript) an interactive read-eval-print loop that is encapsulated inside an object. However, I recently noticed that the definitions of top-level functions specified by the interpreter are not interpreted by the interpreter. After some diagnostic work, I reduced the main problem:

   var evaler = {
     eval: function (str)
     {
       return eval(str);
     },
   };

   eval("function t1() { return 1; }");         // GOOD
   evaler.eval("function t2() { return 2; }");  // FAIL

At this point, I hope that the following two statements will work as expected:

print(t1());     // => Results in 1 (This works)
print(t2());     // => Results in 2 (this fails with an error that t2 is undefined.)

Instead, I get the expected value for the row t1, and the row t2fails with an error, which t2is unrelated.

IOW: script, t1, defintion t2. eval evaler , . , , evaler.eval , , t2 , . ( evaler.)

- ? , . ( , , , eval , chainging __parent__ ..).

, ?

:


tl; dr: Rhino . t2 , . @Matt: "" .

- , jdb, , . , function t1() { return 42; } .

  • , , function() { return 42; }
  • t1.

, , , eval .

, Rhino, -, org.mozilla.javascript.ScriptRuntime.initFunction.

    if (type == FunctionNode.FUNCTION_STATEMENT) {
         ....
                scope.put(name, scope, function);

t1 , scope - , . , , :

main[1] print function.getFunctionName()
 function.getFunctionName() = "t1"
main[1] print scope
 scope = "com.me.testprogram.Main@24148662"

t2 scope - :

main[1] print function.getFunctionName()
 function.getFunctionName() = "t2"
main[1] print scope
 scope = "org.mozilla.javascript.NativeCall@23abcc03"

NativeCall, :

main[1] print scope.getParentScope()
 scope.getParentScope() = "com.me.testprogram.Main@24148662"

, , : " eval t2 . evaler " ". , ' ' NativeCall... t2 , t2 NativeCall, NativeCall , evaler.eval .

... , , , NativeCall , this evaler evaler.eval. ( , NativeCall Interpreter.initFrame, " " . , , , . , .)

+3
5

. eval function, .

print(evaler.eval("function t2() { return 2; }")()); // prints 2

:

x = evaler.eval("function t2() { return 2; }"); // this returns a function
y = x(); // this invokes it, and saves the return value
print(y); // this prints the result

:

read-eval-print-loop, eval?

Rhino.. , Rhino Java Java js?

, :

test.js

function tf2() {
  return 2;
}

print(tf2());

, Rhino :

process = java.lang.Runtime.getRuntime().exec('java -jar js.jar test.js');
result = java.io.BufferedReader(java.io.InputStreamReader(process.getInputStream()));
print(result.readLine()); // prints 2, believe it or not

, , eval , ...

, .

+3

, , , JavaScript .

eval() eval, , , t2() eval: function(str) {}.

evaler.eval('global.t2 = function() { return 2; }'); t2();

- :

t2 = evaler.eval("function t2() { return 2; }");
t2();

....

var someFunc = evaler.eval("function t2() { return 2; }");
// if we got a "named" function, lets drop it into our namespace:
if (someFunc.name) this[someFunc.name] = someFunc;
// now lets try calling it?
t2();
// returns 2

:

var evaler = (function(global){
  return {
    eval: function (str)
    {
      var ret = eval(str);
      if (ret.name) global[ret.name] = ret;
      return ret;
    }
  };
})(this);

evaler.eval('function t2() { return 2; }');
t2(); // returns 2

DOM , "root level" script eval(). <script>, , , DOM -.

+1

, "eval" eval? :

var evaler = {
  evalit: function (str)
  {
    return window.eval(str);
  },
};

eval("function t1() { return 1; }");
evaler.evalit("function t2() { return 2; }");

Edit
@Matt . .

? eval, . .

0

, :

evaler.eval("function t2() { return 2; }");

t2, Function ( function declaration, it function operator), .

, evaler.eval (.. t2 evaler.eval):

js> function foo () {
eval ("function baz() { return 'baz'; }");
print (baz);
}
js> foo ();
function baz() {
    return "baz";
}
js> print(baz);
typein:36: ReferenceError: baz is not defined
0

Rhino , , .

var window = this;

var evaler = {
    eval : function (str) {
         eval.call(window, str);
    }
};

The key is that it callexplicitly establishes this, and it receives t2, determined in the right place.

0
source

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


All Articles