Ignore:
Timestamp:
11/13/12 13:38:22 (12 years ago)
Author:
tbretz
Message:
Some improvements to internal exception throwing; some improvements to HandleScopes; fixed the problem that with included file JsSetStat(3) was called several times.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/FACT++/src/InterpreterV8.cc

    r14603 r14607  
    6363// be checked in all placed to avoid that V8 will core dump.
    6464//
     65// HandleScope:
     66// ------------
     67// A handle scope is a garbage collector and collects all handles created
     68// until it goes out of scope. Handles which are not needed anymore are
     69// then deleted. To return a handle from a HandleScope you need to use
     70// Close(). E.g., String::Utf8Value does not create a new handle and
     71// hence does not need a HandleScope. Any ::New will need a handle scope.
     72// Forgetting the HandleScope could in principle fill your memory,
     73// but everything is properly deleted by the global HandleScope at
     74// script termination.
     75//
    6576
    6677// ==========================================================================
     
    110121    // Using a Javascript function has the advantage that it is fully
    111122    // interruptable without the need of C++ code
    112 
    113123    const string code =
    114124        "(function(){"
     
    117127        "})();";
    118128
    119     HandleScope handle_scope;
    120 
    121     const Handle<Script> script = Script::Compile(String::New(code.c_str()), String::New("internal"));
    122     if (script.IsEmpty())
    123         return Undefined();
    124 
    125     return handle_scope.Close(script->Run());
     129    return ExecuteInternal(code);
    126130}
    127131
     
    142146    TryCatch exception;
    143147
    144     const Handle<Script> sleep = Script::Compile(String::New(("dim.sleep("+to_string(ms)+");").c_str()), String::New("internal"));
    145     if (ms==0 || (!sleep.IsEmpty() && !sleep->Run().IsEmpty()))
     148    const bool rc = ms==0 || !ExecuteInternal("dim.sleep("+to_string(ms)+");").IsEmpty();
     149    if (rc)
    146150    {
    147151        Handle<Value> args[] = {  };
     
    173177        return ThrowException(String::New("Argument 0 not an uint32."));
    174178
     179    const HandleScope handle_scope;
     180
    175181    Handle<Function> handle = Handle<Function>::Cast(args[1]);
    176182
     
    190196    if (!args[0]->IsString())
    191197        return ThrowException(String::New("Argument 1 must be a string."));
    192 
    193     HandleScope handle_scope;
    194198
    195199    const String::Utf8Value str(args[0]);
     
    207211    }
    208212
    209     return handle_scope.Close(Boolean::New(JsSend(command)));
     213    return Boolean::New(JsSend(command));
    210214}
    211215
     
    263267    code +=        ");";
    264268
    265     HandleScope handle_scope;
    266 
    267     // It is not strictly necessary to catch the exception, instead
    268     // script->Run() could just be returned, but catching the
    269     // exception allow to print the position in the file in
    270     // the exception handler instead of just the posiiton in the script.
    271     TryCatch exception;
    272 
    273     const Handle<Script> script = Script::Compile(String::New(code.c_str()), String::New("internal"));
    274     if (script.IsEmpty())
    275         return Undefined();
    276 
    277     const Handle<Value> result = script->Run();
    278 
    279     return exception.HasCaught() ? exception.ReThrow() : handle_scope.Close(result);
    280 
    281     /*
    282     const string   server   = *String::Utf8Value(args[0]);
    283     const  int32_t state    = args[1]->Int32Value();
    284     const uint32_t millisec = args.Length()==3 ? args[2]->Int32Value() : 0;
    285 
    286     const int rc = JsWait(server, state, millisec);
    287 
    288     if (rc==0 || rc==1)
    289         return Boolean::New(rc);
    290 
    291     return ThrowException(String::New(("Waitig for state "+to_string(state)+" of server '"+server+"' failed.").c_str()));
    292         */
     269    return ExecuteInternal(code);
    293270}
    294271
     
    337314        return ThrowException(String::New("Argument 3 must be a string."));
    338315
    339     HandleScope handle_scope;
    340 
    341316    const uint32_t index   = args[0]->Int32Value();
    342317    const string   name    = *String::Utf8Value(args[1]);
     
    360335    }
    361336
    362     return handle_scope.Close(Boolean::New(JsNewState(index, name, comment)));
     337    return Boolean::New(JsNewState(index, name, comment));
    363338}
    364339
     
    370345    if (!args[0]->IsUint32() && !args[0]->IsString())
    371346        return ThrowException(String::New("Argument must be an unint32 or a  string."));
    372 
    373     HandleScope handle_scope;
    374347
    375348    int index = -2;
     
    389362        return ThrowException(String::New("State must be in the range [10, 255]."));
    390363
    391     return handle_scope.Close(Boolean::New(JsSetState(index)));
     364    return Boolean::New(JsSetState(index));
    392365}
    393366
     
    404377    for (int i=0; i<args.Length(); i++)
    405378    {
    406         const HandleScope handle_scope;
    407 
    408379        const String::Utf8Value str(args[i]);
    409380        if (*str)
     
    417388    for (int i=0; i<args.Length(); i++)
    418389    {
    419         const HandleScope handle_scope;
    420 
    421390        const String::Utf8Value str(args[i]);
    422391        if (*str)
     
    434403    for (int i=0; i<args.Length(); i++)
    435404    {
    436         const HandleScope handle_scope;
    437 
    438405        const String::Utf8Value str(args[i]);
    439406        if (*str)
     
    450417    for (int i=0; i<args.Length(); i++)
    451418    {
    452         const HandleScope handle_scope;
    453 
    454419        const String::Utf8Value file(args[i]);
    455420        if (*file == NULL)
    456             return ThrowException(String::New(("Error loading file '"+string(*file)+"'").c_str()));
     421            return ThrowException(String::New("File name missing"));
    457422
    458423        if (!ExecuteFile(*file))
    459             return ThrowException(String::New(("Execution of '"+string(*file)+"' failed").c_str()));
    460     }
    461     return Undefined();
     424            return Boolean::New(false);
     425    }
     426    return Boolean::New(true);
    462427}
    463428
     
    473438Handle<Value> InterpreterV8::FuncDbClose(const Arguments &args)
    474439{
    475     HandleScope handle_scope;
    476 
    477440    void *ptr = External::Unwrap(args.This()->GetInternalField(0));
    478441    if (!ptr)
    479         return handle_scope.Close(Boolean::New(false));
     442        return Boolean::New(false);
    480443
    481444#ifdef HAVE_SQL
     
    486449#endif
    487450
     451    HandleScope handle_scope;
     452
    488453    args.This()->SetInternalField(0, External::New(0));
    489454
     
    494459    if (args.Length()==0)
    495460        return ThrowException(String::New("Arguments expected."));
    496 
    497     HandleScope handle_scope;
    498461
    499462    void *ptr = External::Unwrap(args.This()->GetInternalField(0));
     
    509472    try
    510473    {
     474        HandleScope handle_scope;
     475
    511476        Database *db = reinterpret_cast<Database*>(ptr);
    512477
     
    651616        return ThrowException(String::New("Argument 1 not a string."));
    652617
    653     HandleScope handle_scope;
    654 
    655618#ifdef HAVE_SQL
    656619    try
    657620    {
     621        HandleScope handle_scope;
     622
    658623        Database *db = new Database(*String::Utf8Value(args[0]));
    659624        fDatabases.push_back(db);
     
    989954Handle<Value> InterpreterV8::OnChangeSet(Local<String> prop, Local< Value > value, const AccessorInfo &)
    990955{
    991     const HandleScope handle_scope;
    992 
    993956    // Returns the value if the setter intercepts the request. Otherwise, returns an empty handle.
    994957    const string server = *String::Utf8Value(prop);
     
    1023986    }
    1024987
    1025     const HandleScope handle_scope;
    1026 
    1027988    if (it->second.IsEmpty() || !it->second->IsFunction())
    1028989        return;
     990
     991    const HandleScope handle_scope;
    1029992
    1030993    fGlobalContext->Enter();
     
    10791042    //    return ThrowException(String::New("Must be used as constructor."));
    10801043
    1081     HandleScope handle_scope;
    1082 
    10831044    const String::Utf8Value str(args[0]);
    10841045
    10851046    const auto it = fReverseMap.find(*str);
    10861047    if (it!=fReverseMap.end())
    1087         return handle_scope.Close(it->second);
     1048        return it->second;
    10881049
    10891050    void *ptr = JsSubscribe(*str);
    10901051    if (ptr==0)
    10911052        return ThrowException(String::New(("Subscription to '"+string(*str)+"' already exists.").c_str()));
     1053
     1054    HandleScope handle_scope;
    10921055
    10931056    Handle<ObjectTemplate> tem = ObjectTemplate::New();
     
    11531116    Handle<ObjectTemplate> loc = ObjectTemplate::New();
    11541117
    1155     loc->Set(String::New("zd"), Number::New(zd), ReadOnly);
    1156     loc->Set(String::New("az"), Number::New(az), ReadOnly);
     1118    loc->Set(String::New("zd"),       Number::New(zd), ReadOnly);
     1119    loc->Set(String::New("az"),       Number::New(az), ReadOnly);
    11571120    loc->Set(String::New("toSky"),    FunctionTemplate::New(LocalToSky), ReadOnly);
    11581121    loc->Set(String::New("toString"), FunctionTemplate::New(LocalToString), ReadOnly);
     
    11671130    Handle<ObjectTemplate> sky = ObjectTemplate::New();
    11681131
    1169     sky->Set(String::New("ra"),  Number::New(ra),  ReadOnly);
    1170     sky->Set(String::New("dec"), Number::New(dec), ReadOnly);
     1132    sky->Set(String::New("ra"),       Number::New(ra),  ReadOnly);
     1133    sky->Set(String::New("dec"),      Number::New(dec), ReadOnly);
    11711134    sky->Set(String::New("toLocal"),  FunctionTemplate::New(ismoon?MoonToLocal :SkyToLocal),  ReadOnly);
    11721135    sky->Set(String::New("toString"), FunctionTemplate::New(ismoon?MoonToString:SkyToString), ReadOnly);
     
    11791142Handle<Value> InterpreterV8::LocalDist(const Arguments &args)
    11801143{
    1181     HandleScope handle_scope;
    1182 
    11831144    if (args.Length()!=2)
    11841145        return ThrowException(String::New("dist must not be called with two arguments."));
     
    11861147    if (!args[0]->IsObject() || !args[1]->IsObject())
    11871148        return ThrowException(String::New("at least one argument not an object."));
     1149
     1150    HandleScope handle_scope;
    11881151
    11891152    Handle<Object> obj[2] =
     
    12281191Handle<Value> InterpreterV8::MoonDisk(const Arguments &args)
    12291192{
    1230     HandleScope handle_scope;
    1231 
    12321193    if (args.Length()>1)
    12331194        return ThrowException(String::New("disk must not be called with more than one argument."));
     
    12361197    const Time utc = args.Length()==0 ? Time() : Time(v/1000, v%1000);
    12371198
    1238     return handle_scope.Close(Number::New(ln_get_lunar_disk(utc.JD())));
     1199    return Number::New(ln_get_lunar_disk(utc.JD()));
    12391200}
    12401201
    12411202Handle<Value> InterpreterV8::LocalToSky(const Arguments &args)
    12421203{
    1243     HandleScope handle_scope;
    1244 
    12451204    if (args.Length()>1)
    12461205        return ThrowException(String::New("toSky must not be called with more than one argument."));
     
    12521211    if (!finite(hrz.alt) || !finite(hrz.az))
    12531212        return ThrowException(String::New("zd and az must be finite."));
     1213
     1214    HandleScope handle_scope;
    12541215
    12551216    const Local<Value> date =
     
    12731234Handle<Value> InterpreterV8::SkyToLocal(const Arguments &args)
    12741235{
    1275     HandleScope handle_scope;
    1276 
    12771236    if (args.Length()>1)
    12781237        return ThrowException(String::New("toLocal must not be called with more than one argument."));
     
    12841243    if (!finite(equ.ra) || !finite(equ.dec))
    12851244        return ThrowException(String::New("Ra and dec must be finite."));
     1245
     1246    HandleScope handle_scope;
    12861247
    12871248    const Local<Value> date =
     
    13051266Handle<Value> InterpreterV8::MoonToLocal(const Arguments &args)
    13061267{
    1307     HandleScope handle_scope;
    1308 
    13091268    if (args.Length()>0)
    13101269        return ThrowException(String::New("toLocal must not be called with arguments."));
     
    13161275    if (!finite(equ.ra) || !finite(equ.dec))
    13171276        return ThrowException(String::New("ra and dec must be finite."));
     1277
     1278    HandleScope handle_scope;
    13181279
    13191280    const Local<Value> date =
     
    13371298Handle<Value> InterpreterV8::ConstructorMoon(const Arguments &args)
    13381299{
    1339     HandleScope handle_scope;
    1340 
    13411300    if (args.Length()>1)
    13421301        return ThrowException(String::New("Moon constructor must not be called with more than one argument."));
     1302
     1303    HandleScope handle_scope;
    13431304
    13441305    const Local<Value> date =
     
    13581319Handle<Value> InterpreterV8::ConstructorSky(const Arguments &args)
    13591320{
    1360     HandleScope handle_scope;
    1361 
    13621321    if (args.Length()!=2)
    13631322        return ThrowException(String::New("Sky constructor takes two arguments."));
     
    13691328        return ThrowException(String::New("Both arguments to Sky must be valid numbers."));
    13701329
    1371     return handle_scope.Close(ConstructSky(ra, dec));
     1330    return ConstructSky(ra, dec);
    13721331}
    13731332
    13741333Handle<Value> InterpreterV8::ConstructorLocal(const Arguments &args)
    13751334{
    1376     HandleScope handle_scope;
    1377 
    13781335    if (args.Length()!=2)
    13791336        return ThrowException(String::New("Local constructor takes two arguments."));
     
    13851342        return ThrowException(String::New("Both arguments to Local must be valid numbers."));
    13861343
    1387     return handle_scope.Close(ConstructLocal(zd, az));
     1344    return ConstructLocal(zd, az);
    13881345}
    13891346#endif
     
    14251382    }
    14261383
     1384    // -------------- SKIP if 'internal' and 'Error' ---------------
    14271385    if (*exception)
    14281386        out << *exception;
     
    14341392    if (*sourceline)
    14351393        JsException(*sourceline);
     1394    // -------------- SKIP if 'internal' and 'Error: ' ---------------
    14361395
    14371396    // Print wavy underline (GetUnderline is deprecated).
     
    14581417    const boost::tokenizer<separator> tokenizer(trace, separator("\n"));
    14591418
     1419    // maybe skip: "    at internal:"
     1420
    14601421    auto it = tokenizer.begin();
    14611422    JsException("");
     
    14661427}
    14671428
    1468 // Executes a string within the current v8 context.
    1469 bool InterpreterV8::ExecuteStringNT(const Handle<String> &code, const Handle<Value> &file)
    1470 {
    1471     if (code.IsEmpty())
    1472         return true;
    1473 
    1474     const HandleScope handle_scope;
    1475 
    1476     const Handle<Script> script = Script::Compile(code, file);
     1429Handle<Value> InterpreterV8::ExecuteInternal(const string &code)
     1430{
     1431    TryCatch exception;
     1432    const Handle<Value> result = ExecuteCode(code);
     1433    return exception.HasCaught() ? exception.ReThrow() : result;
     1434}
     1435
     1436Handle<Value> InterpreterV8::ExecuteCode(const string &code, const string &file, bool main)
     1437{
     1438    HandleScope handle_scope;
     1439
     1440    const Handle<String> source = String::New(code.c_str(), code.size());
     1441    const Handle<String> origin = String::New(file.c_str());
     1442    if (source.IsEmpty())
     1443        return Handle<Value>();
     1444
     1445    const Handle<Script> script = Script::Compile(source, origin);
    14771446    if (script.IsEmpty())
    1478         return false;
    1479 
    1480     JsSetState(3);
     1447        return Handle<Value>();
     1448
     1449    if (main)
     1450        JsSetState(3);
    14811451
    14821452    const Handle<Value> result = script->Run();
    14831453    if (result.IsEmpty())
    1484         return false;
     1454        return result;
    14851455
    14861456    // If all went well and the result wasn't undefined then print
     
    14891459        JsResult(*String::Utf8Value(result));
    14901460
    1491     return true;
    1492 }
    1493 
    1494 bool InterpreterV8::ExecuteCode(const Handle<String> &code, const Handle<Value> &file)
    1495 {
    1496     TryCatch exception;
    1497 
    1498     const bool rc = ExecuteStringNT(code, file);
    1499 
    1500     // Check if this is a termination exception
    1501     //if (!exception.CanContinue())
    1502     //    return false;
    1503 
    1504     if (exception.HasCaught())
    1505         return ReportException(&exception);
    1506 
    1507     return rc;
    1508 }
    1509 
    1510 bool InterpreterV8::ExecuteCode(const string &code, const string &file)
    1511 {
    1512     return ExecuteCode(String::New(code.c_str(), code.size()),
    1513                        String::New(file.c_str()));
    1514 }
    1515 
    1516 bool InterpreterV8::ExecuteFile(const string &name)
     1461    return handle_scope.Close(result);
     1462}
     1463
     1464bool InterpreterV8::ExecuteFile(const string &name, bool main)
    15171465{
    15181466    ifstream fin(name.c_str());
     
    15331481    }
    15341482
    1535     return ExecuteCode(buffer, name);
     1483    return !ExecuteCode(buffer, name, main).IsEmpty();
    15361484}
    15371485
     
    15671515                "case 'x': val = parseInt(arr[i]).toString(base?base:16); break;"
    15681516                "case 'd': val = parseFloat(parseInt(arr[i], base?base:10).toPrecision(exp)).toFixed(0); break;"
    1569                 "default:\n"
    1570                 "    throw new SyntaxError('Conversion specifier '+p4+' unknown.');\n"
     1517                //"default:\n"
     1518                //"    throw new SyntaxError('Conversion specifier '+p4+' unknown.');\n"
    15711519                "}"
    15721520                ""
     
    15811529            "}"
    15821530            ""
    1583             "var regex = /%(-)?(0?[0-9]+)?([.][0-9]+)?([#][0-9]+)?(.)/g;"
     1531            "var regex = /%(-)?(0?[0-9]+)?([.][0-9]+)?([#][0-9]+)?([scfpexd])/g;"
    15841532            "return str.replace(regex, callback);"
    15851533        "}"
    15861534        "\n"
    1587         "String.prototype.format = function()"
     1535        "String.prototype.$ = function()"
    15881536        "{"
    15891537            "return dim.format(this, Array.prototype.slice.call(arguments));"
    1590         "}"
     1538        "}"/*
    15911539        "\n"
    15921540        "var format = function()"
    15931541        "{"
    15941542            "return dim.format(arguments[0], Array.prototype.slice.call(arguments,1));"
    1595         "}";
     1543        "}"*/;
    15961544
    15971545    Script::New(String::New(code.c_str()), String::New("internal"))->Run();
     
    16071555    JsLoad(filename);
    16081556
    1609     HandleScope handle_scope;
     1557    const HandleScope handle_scope;
    16101558
    16111559    // Create a template for the global object.
     
    16681616
    16691617    //context->Enter();
     1618
     1619    TryCatch exception;
     1620
    16701621    Locker::StartPreemption(10);
    1671     const bool rc = ExecuteFile(filename);
     1622    bool rc = ExecuteFile(filename, true);
     1623    Locker::StopPreemption();
     1624
    16721625    Terminate();
     1626
     1627    if (exception.HasCaught())
     1628        rc = ReportException(&exception);
    16731629
    16741630    // -----
     
    16841640    // }
    16851641
    1686     Locker::StopPreemption();
    16871642    //context->Exit();
    16881643
Note: See TracChangeset for help on using the changeset viewer.