Browse Source

Error handling improvements

Josh Engebretson 11 years ago
parent
commit
16473c77cb

+ 53 - 14
Source/Atomic/Javascript/JSVM.cpp

@@ -30,7 +30,16 @@ JSVM::JSVM(Context* context) :
     assert(!instance_);
     assert(!instance_);
 
 
     instance_ = this;
     instance_ = this;
+}
+
+JSVM::~JSVM()
+{
+    duk_destroy_heap(ctx_);
+    instance_ = NULL;
+}
 
 
+void JSVM::InitJSContext()
+{
     ctx_ = duk_create_heap_default();
     ctx_ = duk_create_heap_default();
 
 
     // create root Atomic Object
     // create root Atomic Object
@@ -55,14 +64,10 @@ JSVM::JSVM(Context* context) :
 
 
     // handle this elsewhere?
     // handle this elsewhere?
     SubscribeToEvents();
     SubscribeToEvents();
-}
 
 
-JSVM::~JSVM()
-{
-    duk_destroy_heap(ctx_);
-    instance_ = NULL;
 }
 }
 
 
+
 void JSVM::SubscribeToEvents()
 void JSVM::SubscribeToEvents()
 {
 {
     SubscribeToEvent(E_UPDATE, HANDLER(JSVM, HandleUpdate));
     SubscribeToEvent(E_UPDATE, HANDLER(JSVM, HandleUpdate));
@@ -177,7 +182,7 @@ void JSVM::GenerateComponent(const String &cname, const String &jsfilename, cons
     {
     {
         if (duk_is_object(ctx_, -1))
         if (duk_is_object(ctx_, -1))
         {
         {
-            SendJSErrorEvent();
+            SendJSErrorEvent(jsfilename);
             duk_pop(ctx_);
             duk_pop(ctx_);
         }
         }
         else
         else
@@ -189,7 +194,7 @@ void JSVM::GenerateComponent(const String &cname, const String &jsfilename, cons
     {
     {
         if (duk_is_object(ctx_, -1))
         if (duk_is_object(ctx_, -1))
         {
         {
-            SendJSErrorEvent();
+            SendJSErrorEvent(jsfilename);
             duk_pop(ctx_);
             duk_pop(ctx_);
         }
         }
         else
         else
@@ -315,7 +320,7 @@ int JSVM::js_module_search(duk_context* ctx)
         path = vm->moduleSearchPath_ + "/" + path + ".js";
         path = vm->moduleSearchPath_ + "/" + path + ".js";
     }
     }
 
 
-    SharedPtr<File> jsfile(cache->GetFile(path));
+    SharedPtr<File> jsfile(cache->GetFile(path));    
 
 
     if (!jsfile)
     if (!jsfile)
     {
     {
@@ -323,6 +328,7 @@ int JSVM::js_module_search(duk_context* ctx)
     }
     }
     else
     else
     {
     {
+        vm->SetLastModuleSearchFile(jsfile->GetFullPath());
         String source;
         String source;
         jsfile->ReadText(source);
         jsfile->ReadText(source);
         duk_push_string(ctx, source.CString());
         duk_push_string(ctx, source.CString());
@@ -331,7 +337,7 @@ int JSVM::js_module_search(duk_context* ctx)
     return 1;
     return 1;
 }
 }
 
 
-void JSVM::SendJSErrorEvent()
+void JSVM::SendJSErrorEvent(const String& filename)
 {
 {
     duk_context* ctx = GetJSContext();
     duk_context* ctx = GetJSContext();
     assert(duk_is_object(ctx, -1));
     assert(duk_is_object(ctx, -1));
@@ -341,8 +347,14 @@ void JSVM::SendJSErrorEvent()
     VariantMap eventData;
     VariantMap eventData;
 
 
     duk_get_prop_string(ctx, -1, "fileName");
     duk_get_prop_string(ctx, -1, "fileName");
-    String filename = duk_to_string(ctx, -1);
-    eventData[P_ERRORFILENAME] = filename;
+    if (duk_is_string(ctx, -1))
+    {
+        eventData[P_ERRORFILENAME] = duk_to_string(ctx, -1);
+    }
+    else
+    {
+        eventData[P_ERRORFILENAME] = filename;
+    }
 
 
     // Component script are wrapped within a closure, the line number
     // Component script are wrapped within a closure, the line number
     // needs to be offset by this header
     // needs to be offset by this header
@@ -359,6 +371,33 @@ void JSVM::SendJSErrorEvent()
     String message = duk_to_string(ctx, -1);
     String message = duk_to_string(ctx, -1);
     eventData[P_ERRORMESSAGE] = message;
     eventData[P_ERRORMESSAGE] = message;
 
 
+    // we're not getting good file/line from duktape on parser errors
+    if (name == "SyntaxError")
+    {
+        lineNumber = -1;
+        // parse line if we have it
+        if (message.Contains("(line "))
+        {
+            if (!filename.Length())
+                eventData[P_ERRORFILENAME] = lastModuleSearchFilename_;
+
+            unsigned pos = message.Find("(line ");
+            const char* parse = message.CString() + pos + 6;
+            String number;
+            while (*parse >= '0' && *parse<='9')
+            {
+                number += *parse;
+                parse++;
+            }
+
+            lineNumber = ToInt(number);
+
+        }
+
+        eventData[P_ERRORLINENUMBER] =  lineNumber;
+
+    }
+
     duk_get_prop_string(ctx, -5, "stack");
     duk_get_prop_string(ctx, -5, "stack");
     String stack = duk_to_string(ctx, -1);
     String stack = duk_to_string(ctx, -1);
     eventData[P_ERRORSTACK] = stack;
     eventData[P_ERRORSTACK] = stack;
@@ -397,7 +436,7 @@ bool JSVM::ExecuteScript(const String& scriptPath)
                      DUK_COMPILE_EVAL | DUK_COMPILE_SAFE | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN) != 0)
                      DUK_COMPILE_EVAL | DUK_COMPILE_SAFE | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN) != 0)
     {
     {
         if (duk_is_object(ctx_, -1))
         if (duk_is_object(ctx_, -1))
-            SendJSErrorEvent();
+            SendJSErrorEvent(path);
 
 
         duk_pop(ctx_);
         duk_pop(ctx_);
         return false;
         return false;
@@ -422,7 +461,7 @@ bool JSVM::ExecuteFile(File *file)
                      DUK_COMPILE_EVAL | DUK_COMPILE_SAFE | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN) != 0)
                      DUK_COMPILE_EVAL | DUK_COMPILE_SAFE | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN) != 0)
     {
     {
         if (duk_is_object(ctx_, -1))
         if (duk_is_object(ctx_, -1))
-            SendJSErrorEvent();
+            SendJSErrorEvent(file->GetFullPath());
 
 
         duk_pop(ctx_);
         duk_pop(ctx_);
         return false;
         return false;
@@ -452,7 +491,7 @@ bool JSVM::ExecuteMain()
                      DUK_COMPILE_EVAL | DUK_COMPILE_SAFE | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN) != 0)
                      DUK_COMPILE_EVAL | DUK_COMPILE_SAFE | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN) != 0)
     {
     {
         if (duk_is_object(ctx_, -1))
         if (duk_is_object(ctx_, -1))
-            SendJSErrorEvent();
+            SendJSErrorEvent(file->GetFullPath());
 
 
         duk_pop(ctx_);
         duk_pop(ctx_);
         return false;
         return false;

+ 9 - 1
Source/Atomic/Javascript/JSVM.h

@@ -25,6 +25,8 @@ public:
     /// Destruct.
     /// Destruct.
     virtual ~JSVM();
     virtual ~JSVM();
 
 
+    void InitJSContext();
+
     bool ExecuteFile(File* file);
     bool ExecuteFile(File* file);
 
 
     // Resources/Scripts/*.js
     // Resources/Scripts/*.js
@@ -111,9 +113,14 @@ public:
     {
     {
         moduleSearchPath_ = searchPath;
         moduleSearchPath_ = searchPath;
     }
     }
+
+    void SetLastModuleSearchFile(const String& fileName) { lastModuleSearchFilename_ = fileName; }
+
+    const String& GetLastModuleSearchFile() { return lastModuleSearchFilename_; }
+
     const String& GetErrorString() { return errorString_; }
     const String& GetErrorString() { return errorString_; }
 
 
-    void SendJSErrorEvent();
+    void SendJSErrorEvent(const String& filename = String::EMPTY);
 
 
 private:
 private:
 
 
@@ -142,6 +149,7 @@ private:
     float gcTime_;
     float gcTime_;
 
 
     String moduleSearchPath_;
     String moduleSearchPath_;
+    String lastModuleSearchFilename_;
 
 
     String errorString_;
     String errorString_;
 
 

+ 1 - 0
Source/Tools/AtomicPlayer/AtomicPlayer.cpp

@@ -149,6 +149,7 @@ void AtomicPlayer::Start()
     context_->RegisterSubsystem(javascript);
     context_->RegisterSubsystem(javascript);
 
 
     vm = javascript->InstantiateVM("MainVM");
     vm = javascript->InstantiateVM("MainVM");
+    vm->InitJSContext();
 
 
     vm->SetModuleSearchPath("Modules");
     vm->SetModuleSearchPath("Modules");