简体   繁体   中英

V8Engine.Execute returns 'undefined', whereas Microsoft.JScript's eval returns a value

I am looking to replace the Microsoft.JScript engine in our C#.NET 4.0 program with a V8.Net engine in order to be able to execute passed in javascript functions. The program runs fine and correctly executes a number of scripts until it hits the following;

const t_sch_ohd = 0.1;
const t_fn = 8.302;
const t_byte = 0.04307;

var n_byte = Lookup.IndexedMsgSize (1);

var t_total = t_fn + (n_byte * t_byte) + t_sch_ohd;

The V8Engine.Execute command returns undefined , whereas our Microsoft.JScript implementation returns 9.091119999999998 which I'm not sure is correct either. I get the feeling this is something to do with how each engine handles what is considered an 'output' at the end of executing the script but I'm not sure.

Lookup.IndexesMsgSize is a function we have defined in our C#.NET application, and is consistent through both versions, I believe it returns 16 in this instance;

public uint IndexedMsgSize(uint mIndex)
{
    // only intended for MsgProcess_Fn
    if (m_message == null)
    {
        if (m_function == null)
        {
            throw new RaceException("Function reference not specified for Lookup.IndexedMsgSize");
        }
        uint count = (uint)m_function.RelatedMessagesByUDC[((int)mIndex) - 1].MessageLength;
        return count;
    }
    else
    {
        throw new RaceException("message reference not allowed for Lookup.IndexedMsgSize");
    }
}

The implementation for the Microsoft.JScript evaluation is as follows;

public string Execute(string script)
{
    string result = "";

    try
    {
        //  EVALUATE THE SCRIPT                                 
        result = Evaluator.Eval(script);
        //using (var engine = new ScriptEngine("jscript"))
        //{
        //    ParsedScript parsed =
        //        engine.Parse("function MyFunc(x){return eval(x,'unsafe')}");
        //    engine.SetNamedItem("Lookup", m_lookup);
        //    result = parsed.CallMethod("MyFunc", script).ToString();
        //}
    }
    catch (Exception ex)
    {
        // JScript error?
        if (ex.Source.CompareTo("Microsoft.JScript") == 0)
        {
            // Yes, turn it into a Race JScript Exception to avoid a stack trace dump.
            throw new RaceScriptException(ex as JScriptException);
        }
        // Not a JScript error, so just re-throw exception.
        throw ex;
    }

    return result;
}

Evaluator is a class defined through a .dll, the Eval function is as follows in Javascript;

static function Eval(expression : String) : String {
        return eval(expression,'unsafe');
}

And In our V8.Net Implementation we simply use the built in V8Engine.Execute command;

public string Execute(string script)
{
    string result = "";

    try
    {
        //  EVALUATE THE SCRIPT

        //Create the V8.Net Engine                  
        V8Engine e = new V8Engine();
        //Set the Lookup instance as a global object so that the JS code in the V8.Net wrapper can access it
        e.GlobalObject.SetProperty("Lookup", m_lookup, null, true, ScriptMemberSecurity.Permanent);
        //Execute the script
        result = e.Execute(script);

        //Deprecated code:
        //result = Evaluator.Eval(script);
        //using (var engine = new ScriptEngine("jscript"))
        //{
        //    ParsedScript parsed =
        //        engine.Parse("function MyFunc(x){return eval(x,'unsafe')}");
        //    engine.SetNamedItem("Lookup", m_lookup);
        //    result = parsed.CallMethod("MyFunc", script).ToString();
        //}
    }
    catch (Exception ex)
    {
        // V8.NET error?
        if (ex.Source.CompareTo("V8.Net") == 0)
        {
            // Yes, turn it into a Race V8 Exception to avoid a stack trace dump.
            throw (V8Exception)ex;
        }
        // Not a V8 error, so just re-throw exception.
        throw ex;
    }

    return result;
}

I hope someone can shed some light on why the above results are happening,

Thanks in advance!

JS engine uses eval function when you pass script to it. In turn, undefined is correct result of your script execution, because eval() returns the value of the last expression evaluated MDN eval docs

In your code:

var t_total = t_fn + (n_byte * t_byte) + t_sch_ohd;

Variable Statement is the last executed expression. And it always returns undefined .

A variable statement declares variables that are created as defined in 10.5. Variables are initialised to undefined when created. A variable with an Initialiser is assigned the value of its AssignmentExpression when the VariableStatement is executed, not when the variable is created.

In your case t_fn + (n_byte * t_byte) + t_sch_ohd; is AssignmentExpression initialiser. VariableStatement -> AssignmentExpression;

So, your code folows:

  1. Perform AssignmentExpression
  2. Perform VariableStatement

There couple of ways to overcome your problem:

  • Implicitly define variable:
t_total = t_fn + (n_byte * t_byte) + t_sch_ohd;
  • Return the result explicitly by:
var t_total = t_fn + (n_byte * t_byte) + t_sch_ohd;
t_total;
  • Define variable explicitly, but above:
var t_total;
t_total = t_fn + (n_byte * t_byte) + t_sch_ohd;

Microsoft.JScript works as you expects just due to misbehaviour.

For deep understanding of JS nature look through http://es5.github.io/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM