Josh Engebretson 11 years ago
parent
commit
56d11dcd55

+ 1 - 0
Source/Atomic/IO/File.cpp

@@ -92,6 +92,7 @@ File::File(Context* context, const String& fileName, FileMode mode) :
     writeSyncNeeded_(false)
 {
     Open(fileName, mode);
+    fullPath_ = fileName;
 }
 
 File::File(Context* context, PackageFile* package, const String& fileName) :

+ 9 - 0
Source/Atomic/IO/File.h

@@ -82,6 +82,8 @@ public:
     void Flush();
     /// Change the file name. Used by the resource system.
     void SetName(const String& name);
+    /// Set the fullpath to the file
+    void SetFullPath(const String& path) { fullPath_ = path; }
     
     /// Return the open mode.
     FileMode GetMode() const { return mode_; }
@@ -91,10 +93,16 @@ public:
     void* GetHandle() const { return handle_; }
     /// Return whether the file originates from a package.
     bool IsPackaged() const { return offset_ != 0; }
+    /// Return the fullpath to the file
+    const String& GetFullPath() const { return fullPath_; }
     
 private:
     /// File name.
     String fileName_;
+
+    /// Full path to file
+    String fullPath_;
+
     /// Open mode.
     FileMode mode_;
     /// File handle.
@@ -121,6 +129,7 @@ private:
     bool readSyncNeeded_;
     /// Synchronization needed before write -flag.
     bool writeSyncNeeded_;
+
 };
 
 }

+ 21 - 0
Source/Atomic/Javascript/JSAtomic.cpp

@@ -124,6 +124,24 @@ static int js_atomic_GetInput(duk_context* ctx)
     return 1;
 }
 
+static int js_atomic_script(duk_context* ctx)
+{
+    JSVM* vm = JSVM::GetJSVM(ctx);
+
+    if (duk_is_string(ctx, 0))
+    {
+        if ( vm->ExecuteScript(duk_to_string(ctx, 0)))
+            duk_push_boolean(ctx, 1);
+        else
+            duk_push_boolean(ctx, 0);
+    }
+    else
+        duk_push_boolean(ctx, 0);
+
+    return 1;
+}
+
+
 static int js_atomic_destroy(duk_context* ctx)
 {
     if (!duk_is_object(ctx, 0))
@@ -249,6 +267,9 @@ void jsapi_init_atomic(JSVM* vm)
     duk_push_c_function(ctx, js_atomic_GetUI, 0);
     duk_put_prop_string(ctx, -2, "GetUI");
 
+    duk_push_c_function(ctx, js_atomic_script, 1);
+    duk_put_prop_string(ctx, -2, "script");
+
     duk_push_c_function(ctx, js_atomic_destroy, 1);
     duk_put_prop_string(ctx, -2, "destroy");
 

+ 0 - 29
Source/Atomic/Javascript/JSComponent.cpp

@@ -20,7 +20,6 @@
 #include "../Atomic2D/RigidBody2D.h"
 
 #include "../Javascript/JSEvents.h"
-#include "../Javascript/JSFile.h"
 #include "../Javascript/JSComponent.h"
 #include "../Javascript/JSAPI.h"
 
@@ -176,25 +175,9 @@ void JSComponent::ReleaseObject()
 
 void JSComponent::SetScriptFile(JSFile* scriptFile)
 {
-    if (scriptFile == scriptFile_ && scriptObject_)
-        return;
 
     ReleaseObject();
 
-    // Unsubscribe from the reload event of previous script file (if any), then subscribe to the new
-    if (scriptFile_)
-    {
-        UnsubscribeFromEvent(scriptFile_, E_RELOADSTARTED);
-        UnsubscribeFromEvent(scriptFile_, E_RELOADFINISHED);
-    }
-    if (scriptFile)
-    {
-        SubscribeToEvent(scriptFile, E_RELOADSTARTED, HANDLER(JSComponent, HandleScriptFileReload));
-        SubscribeToEvent(scriptFile, E_RELOADFINISHED, HANDLER(JSComponent, HandleScriptFileReloadFinished));
-    }
-
-    scriptFile_ = scriptFile;
-
     CreateObject();
     MarkNetworkUpdate();
 }
@@ -359,17 +342,6 @@ void JSComponent::UpdateEventSubscription()
     }
 }
 
-void JSComponent::HandleScriptFileReload(StringHash eventType, VariantMap& eventData)
-{
-    ReleaseObject();
-}
-
-void JSComponent::HandleScriptFileReloadFinished(StringHash eventType, VariantMap& eventData)
-{
-    if (!className_.Empty())
-        CreateObject();
-}
-
 
 void JSComponent::HandleScenePostUpdate(StringHash eventType, VariantMap& eventData)
 {
@@ -423,7 +395,6 @@ void JSComponent::HandlePhysicsPostStep(StringHash eventType, VariantMap& eventD
 
     VariantVector parameters;
     parameters.Push(eventData[P_TIMESTEP]);
-    //scriptFile_->Execute(scriptObject_, methods_[METHOD_FIXEDPOSTUPDATE], parameters);
 }
 #endif
 void JSComponent::HandleScriptEvent(StringHash eventType, VariantMap& eventData)

+ 0 - 7
Source/Atomic/Javascript/JSComponent.h

@@ -85,10 +85,6 @@ private:
 #endif
     /// Handle an event in script.
     void HandleScriptEvent(StringHash eventType, VariantMap& eventData);
-    /// Handle script file reload start.
-    void HandleScriptFileReload(StringHash eventType, VariantMap& eventData);
-    /// Handle script file reload finished.
-    void HandleScriptFileReloadFinished(StringHash eventType, VariantMap& eventData);
 
     /// Class name.
     String className_;
@@ -98,9 +94,6 @@ private:
 
     WeakPtr<JSVM> vm_;
 
-    /// Script file.
-    WeakPtr<JSFile> scriptFile_;
-
     HashMap<StringHash, JS_HEAP_PTR> scriptEventFunctions_;
 
     /// Script object.

+ 0 - 68
Source/Atomic/Javascript/JSFile.cpp

@@ -1,68 +0,0 @@
-#include "Precompiled.h"
-#include "../Core/Context.h"
-#include "../IO/Deserializer.h"
-#include "../IO/FileSystem.h"
-#include "../IO/Log.h"
-#include "../Javascript/JSFile.h"
-#include "../Core/ProcessUtils.h"
-#include "../IO/Serializer.h"
-
-#include <Duktape/duktape.h>
-
-#include "DebugNew.h"
-
-namespace Atomic
-{
-
-JSFile::JSFile(Context* context) :
-    Resource(context),
-    size_(0)
-{
-
-}
-
-JSFile::~JSFile()
-{
-
-}
-
-void JSFile::RegisterObject(Context* context)
-{
-    context->RegisterFactory<JSFile>();
-}
-
-bool JSFile::BeginLoad(Deserializer& source)
-{
-    size_ = source.GetSize();
-
-    if (size_ == 0)
-    {
-        data_ = new char[1];
-        size_ = 1;
-        data_[0] = '\0';
-        return true;
-    }
-
-    // Read all data ensuring '\0' terminated
-    data_ = new char[size_ + 1];
-    if (source.Read(data_, size_) != size_)
-        return false;
-
-    data_[size_] = '\0';
-
-    SetMemoryUse(size_);
-
-    return true;
-}
-
-bool JSFile::Save(Serializer& dest) const
-{
-    if (size_ == 0)
-        return false;
-
-    dest.Write(data_, size_);
-
-    return true;
-}
-
-}

+ 0 - 38
Source/Atomic/Javascript/JSFile.h

@@ -1,38 +0,0 @@
-#pragma once
-
-#include "../Container/ArrayPtr.h"
-#include "../Resource/Resource.h"
-
-namespace Atomic
-{
-
-class JSVM;
-
-class ATOMIC_API JSFile : public Resource
-{
-    OBJECT(JSFile);
-
-public:
-    /// Construct.
-    JSFile(Context* context);
-    /// Destruct.
-    virtual ~JSFile();
-    /// Register object factory.
-    static void RegisterObject(Context* context);
-
-    /// Load resource from stream. May be called from a worker thread. Return true if successful.
-    virtual bool BeginLoad(Deserializer& source);
-    /// Save resource. Return true if successful.
-    virtual bool Save(Serializer& dest) const;
-
-    const char* GetSource() {  return data_; }
-
-
-private:
-    /// File size.
-    unsigned size_;
-    /// File data.
-    SharedArrayPtr<char> data_;
-};
-
-}

+ 128 - 180
Source/Atomic/Javascript/JSVM.cpp

@@ -14,7 +14,6 @@
 #include "../Resource/ResourceCache.h"
 
 #include "../Javascript/JSEvents.h"
-#include "../Javascript/JSFile.h"
 #include "../Javascript/JSVM.h"
 #include "../Javascript/JSAtomic.h"
 
@@ -25,34 +24,34 @@ JSVM* JSVM::instance_ = NULL;
 
 JSVM::JSVM(Context* context) :
     Object(context),
-    jsContext_(0),
+    ctx_(0),
     gcTime_(0.0f)
 {
     assert(!instance_);
 
     instance_ = this;
 
-    jsContext_ = duk_create_heap_default();
+    ctx_ = duk_create_heap_default();
 
     // create root Atomic Object
-    duk_push_global_object(jsContext_);
-    duk_push_object(jsContext_);
-    duk_put_prop_string(jsContext_, -2, "Atomic");
-    duk_pop(jsContext_);
+    duk_push_global_object(ctx_);
+    duk_push_object(ctx_);
+    duk_put_prop_string(ctx_, -2, "Atomic");
+    duk_pop(ctx_);
 
-    duk_push_global_stash(jsContext_);
-    duk_push_object(jsContext_);
-    duk_put_prop_index(jsContext_, -2, JS_GLOBALSTASH_INDEX_COMPONENTS);
-    duk_pop(jsContext_);
+    duk_push_global_stash(ctx_);
+    duk_push_object(ctx_);
+    duk_put_prop_index(ctx_, -2, JS_GLOBALSTASH_INDEX_COMPONENTS);
+    duk_pop(ctx_);
 
-    duk_get_global_string(jsContext_, "Duktape");
-    duk_push_c_function(jsContext_, js_module_search, 1);
-    duk_put_prop_string(jsContext_, -2, "modSearch");
-    duk_pop(jsContext_);
+    duk_get_global_string(ctx_, "Duktape");
+    duk_push_c_function(ctx_, js_module_search, 1);
+    duk_put_prop_string(ctx_, -2, "modSearch");
+    duk_pop(ctx_);
 
     jsapi_init_atomic(this);
 
-    InitScripts();
+    InitComponents();
 
     // handle this elsewhere?
     SubscribeToEvents();
@@ -60,7 +59,7 @@ JSVM::JSVM(Context* context) :
 
 JSVM::~JSVM()
 {
-    duk_destroy_heap(jsContext_);
+    duk_destroy_heap(ctx_);
     instance_ = NULL;
 }
 
@@ -88,39 +87,39 @@ void JSVM::HandleUpdate(StringHash eventType, VariantMap& eventData)
         // see duktape docs
         // also ensure #define DUK_OPT_NO_VOLUNTARY_GC
         // is enabled in duktape.h
-        duk_gc(jsContext_, 0);
-        duk_gc(jsContext_, 0);
+        duk_gc(ctx_, 0);
+        duk_gc(ctx_, 0);
 
         gcTime_ = 0;
 
     }
 
-    duk_get_global_string(jsContext_, "__js_atomicgame_update");
+    duk_get_global_string(ctx_, "__js_atomicgame_update");
 
-    if (duk_is_function(jsContext_, -1))
+    if (duk_is_function(ctx_, -1))
     {
-        duk_push_number(jsContext_, timeStep);
-        duk_pcall(jsContext_, 1);
-        duk_pop(jsContext_);
+        duk_push_number(ctx_, timeStep);
+        duk_pcall(ctx_, 1);
+        duk_pop(ctx_);
     }
 
     else
     {
-        duk_pop(jsContext_);
+        duk_pop(ctx_);
     }
 }
 
 bool JSVM::ExecuteFunction(const String& functionName)
 {
-    duk_get_global_string(jsContext_, functionName.CString());
-    if (duk_is_function(jsContext_, -1))
+    duk_get_global_string(ctx_, functionName.CString());
+    if (duk_is_function(ctx_, -1))
     {
         bool ok = true;
 
-        if (duk_pcall(jsContext_, 0) != 0)
+        if (duk_pcall(ctx_, 0) != 0)
         {
             ok = false;
-            if (duk_is_object(jsContext_, -1))
+            if (duk_is_object(ctx_, -1))
             {
                 SendJSErrorEvent();
             }
@@ -130,13 +129,13 @@ bool JSVM::ExecuteFunction(const String& functionName)
             }
                     }
 
-        duk_pop(jsContext_);
+        duk_pop(ctx_);
         return ok;
 
     }
     else
     {
-        duk_pop(jsContext_);
+        duk_pop(ctx_);
     }
 
     return false;
@@ -147,7 +146,7 @@ void JSVM::GenerateComponent(const String &cname, const String &jsfilename, cons
 {
     String source = "(function() {\n function __component_function(self) {\n";
 
-    source += csource;
+    source += csource.CString();
 
     source += "self.node.components = self.node.components || {};\n";
 
@@ -171,27 +170,27 @@ void JSVM::GenerateComponent(const String &cname, const String &jsfilename, cons
 
     source += "}\n return __component_function;\n});";
 
-    duk_push_string(jsContext_, jsfilename.CString());
+    duk_push_string(ctx_, jsfilename.CString());
 
-    if (duk_eval_raw(jsContext_, source.CString(), source.Length(),
+    if (duk_eval_raw(ctx_, source.CString(), source.Length(),
                      DUK_COMPILE_EVAL | DUK_COMPILE_NOSOURCE | DUK_COMPILE_SAFE) != 0)
     {
-        if (duk_is_object(jsContext_, -1))
+        if (duk_is_object(ctx_, -1))
         {
             SendJSErrorEvent();
-            duk_pop(jsContext_);
+            duk_pop(ctx_);
         }
         else
         {
             assert(0);
         }
     }
-    else if (duk_pcall(jsContext_, 0) != 0)
+    else if (duk_pcall(ctx_, 0) != 0)
     {
-        if (duk_is_object(jsContext_, -1))
+        if (duk_is_object(ctx_, -1))
         {
             SendJSErrorEvent();
-            duk_pop(jsContext_);
+            duk_pop(ctx_);
         }
         else
         {
@@ -200,22 +199,22 @@ void JSVM::GenerateComponent(const String &cname, const String &jsfilename, cons
     }
     else
     {
-        if (!duk_is_function(jsContext_, -1))
+        if (!duk_is_function(ctx_, -1))
         {
-            const char* error = duk_to_string(jsContext_, -1);
+            const char* error = duk_to_string(ctx_, -1);
             assert(false);
         }
 
-        duk_put_prop_string(jsContext_, -2, cname.CString());
+        duk_put_prop_string(ctx_, -2, cname.CString());
     }
 }
 
-void JSVM::InitPackageScripts()
+void JSVM::InitPackageComponents()
 {
     ResourceCache* cache = GetSubsystem<ResourceCache>();
 
-    duk_push_global_stash(jsContext_);
-    duk_get_prop_index(jsContext_, -1, JS_GLOBALSTASH_INDEX_COMPONENTS);
+    duk_push_global_stash(ctx_);
+    duk_get_prop_index(ctx_, -1, JS_GLOBALSTASH_INDEX_COMPONENTS);
 
     const Vector<SharedPtr<PackageFile> >& packageFiles = cache->GetPackageFiles();
 
@@ -233,34 +232,34 @@ void JSVM::InitPackageScripts()
             String cname = GetFileName(name);
             String jsname = name;
 
-            JSFile* jsfile = cache->GetResource<JSFile>(name);
-            String csource = jsfile->GetSource();
-
+            SharedPtr<File> jsfile(cache->GetFile(name));
+            String csource;
+            jsfile->ReadText(csource);
             GenerateComponent(cname, jsname, csource);
 
         }
     }
 
     // pop stash and component object
-    duk_pop_2(jsContext_);
+    duk_pop_2(ctx_);
 
 }
 
-void JSVM::InitScripts()
+void JSVM::InitComponents()
 {
     ResourceCache* cache = GetSubsystem<ResourceCache>();
 
     if (cache->GetPackageFiles().Size())
     {
-        InitPackageScripts();
+        InitPackageComponents();
         return;
     }
 
     FileSystem* fileSystem = GetSubsystem<FileSystem>();
     const Vector<String>& dirs = cache->GetResourceDirs();
 
-    duk_push_global_stash(jsContext_);
-    duk_get_prop_index(jsContext_, -1, JS_GLOBALSTASH_INDEX_COMPONENTS);
+    duk_push_global_stash(ctx_);
+    duk_get_prop_index(ctx_, -1, JS_GLOBALSTASH_INDEX_COMPONENTS);
 
     for (unsigned i = 0; i < dirs.Size(); i++)
     {
@@ -273,9 +272,10 @@ void JSVM::InitScripts()
             String cname = GetFileName(files[j]);
             String jsname = dirs[i]+"Components/" + files[j];
 
-            JSFile* jsfile = cache->GetResource<JSFile>("Components/" + files[j]);
+            SharedPtr<File> jsfile = cache->GetFile("Components/" + files[j]);
 
-            String csource = jsfile->GetSource();
+            String csource;
+            jsfile->ReadText(csource);
 
             GenerateComponent(cname, jsname, csource);
 
@@ -284,26 +284,8 @@ void JSVM::InitScripts()
     }
 
     // pop stash and component object
-    duk_pop_2(jsContext_);
-
-}
-
-bool JSVM::ExecuteFile(JSFile* jsfile)
-{
-    PROFILE(ExecuteFile);
-
-    bool ok = true;
-
-    if (duk_peval_string(jsContext_, jsfile->GetSource()) != 0)
-    {
-        ok = false;
-        printf("Error: %s\n", duk_safe_to_string(jsContext_, -1));
-    }
-
-    // ignore result
-    duk_pop(jsContext_);
+    duk_pop_2(ctx_);
 
-    return ok;
 }
 
 int JSVM::js_module_search(duk_context* ctx)
@@ -333,37 +315,22 @@ int JSVM::js_module_search(duk_context* ctx)
         path = vm->moduleSearchPath_ + "/" + path + ".js";
     }
 
-    JSFile* jsfile = cache->GetResource<JSFile>(path);
+    SharedPtr<File> jsfile(cache->GetFile(path));
+
     if (!jsfile)
     {
         duk_push_null(ctx);
     }
     else
     {
-        duk_push_string(ctx, jsfile->GetSource());
+        String source;
+        jsfile->ReadText(source);
+        duk_push_string(ctx, source.CString());
     }
 
     return 1;
 }
 
-/*
-name	standard	Name of error, e.g. TypeError, inherited
-message	standard	Optional message of error, own property, empty message inherited if absent
-fileName	Rhino	Filename related to error source, inherited accessor
-lineNumber	Rhino	Linenumber related to error source, inherited accessor
-stack	V8	Traceback as a multi-line human redable string, inherited accessor
-
-
-EVENT(E_JSERROR, JSError)
-{
-    PARAM(P_ERRORNAME, ErrorName); // string
-    PARAM(P_ERRORMESSAGE, ErrorMessage); // string
-    PARAM(P_ERRORFILENAME, ErrorFileName); // string
-    PARAM(P_ERRORLINENUMBER, ErrorLineNumber); // int
-    PARAM(P_ERRORSTACK, ErrorStack); // string
-}
-*/
-
 void JSVM::SendJSErrorEvent()
 {
     duk_context* ctx = GetJSContext();
@@ -374,7 +341,8 @@ void JSVM::SendJSErrorEvent()
     VariantMap eventData;
 
     duk_get_prop_string(ctx, -1, "fileName");
-    eventData[P_ERRORFILENAME] = duk_to_string(ctx, -1);
+    String filename = duk_to_string(ctx, -1);
+    eventData[P_ERRORFILENAME] = filename;
 
     // Component script are wrapped within a closure, the line number
     // needs to be offset by this header
@@ -384,133 +352,113 @@ void JSVM::SendJSErrorEvent()
     eventData[P_ERRORLINENUMBER] =  lineNumber;
 
     duk_get_prop_string(ctx, -3, "name");
-    eventData[P_ERRORNAME] = duk_to_string(ctx, -1);
+    String name = duk_to_string(ctx, -1);
+    eventData[P_ERRORNAME] = name;
 
     duk_get_prop_string(ctx, -4, "message");
-    eventData[P_ERRORMESSAGE] = duk_to_string(ctx, -1);
+    String message = duk_to_string(ctx, -1);
+    eventData[P_ERRORMESSAGE] = message;
 
     duk_get_prop_string(ctx, -5, "stack");
-    eventData[P_ERRORSTACK] = duk_to_string(ctx, -1);
+    String stack = duk_to_string(ctx, -1);
+    eventData[P_ERRORSTACK] = stack;
 
     duk_pop_n(ctx, 5);
 
+    LOGERRORF("JSErrorEvent: %s : Line %i\n Name: %s\n Message: %s\n Stack:%s",
+              filename.CString(), lineNumber, name.CString(), message.CString(), stack.CString());
+
     SendEvent(E_JSERROR, eventData);
 
 }
 
-bool JSVM::ExecuteMain(const String &mainPath)
+bool JSVM::ExecuteScript(const String& scriptPath)
 {
-    SharedPtr<JSFile> jsFile;
-    jsFile = GetSubsystem<ResourceCache>()->GetResource<JSFile>("Scripts/main.js");
-    if (jsFile.Null())
-        return false;
-
-    int top = duk_get_top(jsContext_);
+    String path = scriptPath;
+    if (!path.StartsWith("Scripts/"))
+        path = "Scripts/" + path;
 
-    // wrap in a closure
-    String source = "(function() {\n function __main_function(self) {\n";
+    SharedPtr<File> file (GetSubsystem<ResourceCache>()->GetFile(path));
 
-    source += "require(\"AtomicGame\");\n";
-
-    source += jsFile->GetSource();
-
-    source += "\nAtomic.game.init(Start, Update);\n";
+    if (file.Null())
+    {
+        return false;
+    }
 
-    source += "}\n return __main_function;\n});";
+    String source;
 
-    duk_push_string(jsContext_, mainPath.CString());
+    file->ReadText(source);
 
-    if (duk_eval_raw(jsContext_, source.CString(), source.Length(),
-                     DUK_COMPILE_EVAL | DUK_COMPILE_NOSOURCE | DUK_COMPILE_SAFE) != 0)
+    duk_push_string(ctx_, file->GetFullPath().CString());
+    if (duk_eval_raw(ctx_, source.CString(), 0,
+                     DUK_COMPILE_EVAL | DUK_COMPILE_SAFE | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN) != 0)
     {
-        if (duk_is_object(jsContext_, -1))
-        {
+        if (duk_is_object(ctx_, -1))
             SendJSErrorEvent();
-            duk_pop(jsContext_);
-            return false;
-        }
-        else
-        {
-            assert(0);
-        }
-    }
-    else if (duk_pcall(jsContext_, 0) != 0)
-    {
-        if (duk_is_object(jsContext_, -1))
-        {
-            SendJSErrorEvent();
-            duk_pop(jsContext_);
-            return false;
-        }
-        else
-        {
-            assert(0);
-        }
+
+        duk_pop(ctx_);
+        return false;
     }
 
-    if (!duk_is_function(jsContext_, -1))
-    {
+    duk_pop(ctx_);
 
-        duk_pop(jsContext_);
+    return true;
+}
+
+bool JSVM::ExecuteFile(File *file)
+{
+    if (!file)
         return false;
-    }
 
-    if (duk_pcall(jsContext_, 0) != 0)
+    String source;
+
+    file->ReadText(source);
+
+    duk_push_string(ctx_, file->GetFullPath().CString());
+    if (duk_eval_raw(ctx_, source.CString(), 0,
+                     DUK_COMPILE_EVAL | DUK_COMPILE_SAFE | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN) != 0)
     {
-        if (duk_is_object(jsContext_, -1))
-        {
+        if (duk_is_object(ctx_, -1))
             SendJSErrorEvent();
-            duk_pop(jsContext_);
-            return false;
-        }
-        else
-        {
-            assert(0);
-        }
-    }
 
-    duk_pop(jsContext_);
-
-    ExecuteFunction("__js_atomicgame_start");
+        duk_pop(ctx_);
+        return false;
+    }
 
-    assert(top == duk_get_top(jsContext_));
+    duk_pop(ctx_);
 
     return true;
-
 }
 
 
-/*
-void JSVM::DumpJavascriptObjects()
+bool JSVM::ExecuteMain()
 {
-    HashMap<String, unsigned> counts;
+    SharedPtr<File> file (GetSubsystem<ResourceCache>()->GetFile("Scripts/main.js"));
 
-    List<Object*>::Iterator itr = jsObjects_.Begin();
-    while (itr != jsObjects_.End())
+    if (file.Null())
     {
-        const String& tname = (*itr)->GetTypeName();
-        if (!counts.Contains(tname))
-        {
-            counts[tname] = 0;
-        }
-        else
-        {
-            counts[tname]++;
-        }
-        itr++;
+        return false;
     }
 
-    HashMap<String, unsigned>::Iterator oitr = counts.Begin();
-    while (oitr != counts.End())
+    String source;
+
+    file->ReadText(source);
+
+    duk_push_string(ctx_, file->GetFullPath().CString());
+    if (duk_eval_raw(ctx_, source.CString(), 0,
+                     DUK_COMPILE_EVAL | DUK_COMPILE_SAFE | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN) != 0)
     {
-        // currently outputting in destructor so log might already be gone
-        //LOGINFOF("%s: %u", oitr->first_.CString(), oitr->second_);
-        printf("%s: %u\n", oitr->first_.CString(), oitr->second_);
+        if (duk_is_object(ctx_, -1))
+            SendJSErrorEvent();
 
-        oitr++;
+        duk_pop(ctx_);
+        return false;
     }
 
+    duk_pop(ctx_);
+
+    ExecuteFunction("__js_atomicgame_start");
+    return true;
 }
-*/
 
 }

+ 11 - 6
Source/Atomic/Javascript/JSVM.h

@@ -25,9 +25,13 @@ public:
     /// Destruct.
     virtual ~JSVM();
 
-    bool ExecuteMain(const String& mainPath);
+    bool ExecuteFile(File* file);
 
-    bool ExecuteFile(JSFile* jsfile);
+    // Resources/Scripts/*.js
+    bool ExecuteScript(const String& scriptPath);
+    // Resources/Script/main.js
+
+    bool ExecuteMain();
 
     bool ExecuteFunction(const String& functionName);
 
@@ -36,7 +40,7 @@ public:
         return instance_;
     }
 
-    inline duk_context* GetJSContext() { return jsContext_; }
+    inline duk_context* GetJSContext() { return ctx_; }
 
     void DumpJavascriptObjects() {}
 
@@ -113,15 +117,16 @@ public:
 private:
 
     void GenerateComponent(const String& cname, const String& jsfilename, const String& csource);
-    void InitScripts();
-    void InitPackageScripts();
+
+    void InitComponents();
+    void InitPackageComponents();
 
     void SubscribeToEvents();
     void HandleUpdate(StringHash eventType, VariantMap& eventData);
 
     static int js_module_search(duk_context* ctx);
 
-    duk_context* jsContext_;
+    duk_context* ctx_;
 
     HashMap<void*, RefCounted*> heapToObject_;
 

+ 0 - 2
Source/Atomic/Javascript/Javascript.cpp

@@ -9,7 +9,6 @@
 #include "../Scene/Scene.h"
 
 #include "../Javascript/Javascript.h"
-#include "../Javascript/JSFile.h"
 #include "../Javascript/JSComponent.h"
 #include "../Javascript/JSVM.h"
 
@@ -45,7 +44,6 @@ void Javascript::ShutdownVM(const String& name)
 
 void RegisterJavascriptLibrary(Context* context)
 {
-    JSFile::RegisterObject(context);
     JSComponent::RegisterObject(context);
 }
 

+ 15 - 118
Source/Tools/AtomicPlayer/AtomicPlayer.cpp

@@ -33,7 +33,6 @@
 #include <Atomic/Environment/Environment.h>
 
 #include <Atomic/Javascript/Javascript.h>
-#include <Atomic/Javascript/JSFile.h>
 
 #include "AtomicPlayer.h"
 
@@ -81,7 +80,7 @@ int main(int argc, char** argv)
 
     emscripten_set_main_loop(RunFrame, 0, 1);
 
-/*
+    /*
     int firefox = EM_ASM_INT ( return ((navigator.userAgent.toLowerCase().indexOf('firefox') > -1) ? 1 : 0), 0);
     if (firefox)
         emscripten_set_main_loop(RunFrame, 0, 1);
@@ -110,28 +109,14 @@ AtomicPlayer::AtomicPlayer(Context* context) :
 
 void AtomicPlayer::Setup()
 {
-    FileSystem* filesystem = GetSubsystem<FileSystem>();       
-
-    // Check for script file name
-    const Vector<String>& arguments = GetArguments();    
-    for (unsigned i = 0; i < arguments.Size(); ++i)
-    {
-        if (arguments[i][0] != '-')
-        {
-            scriptFileName_ = GetInternalPath(arguments[i]);
-            break;
-        }
-    }
+    FileSystem* filesystem = GetSubsystem<FileSystem>();
 
 #ifdef EMSCRIPTEN
     engineParameters_["WindowWidth"] = 1280;
     engineParameters_["WindowHeight"] = 720;
-    engineParameters_["FullScreen"] = false;    
+    engineParameters_["FullScreen"] = false;
 #endif
     
-    scriptFileName_ = "Scripts/main.js";
-
-    FileSystem* fileSystem = GetSubsystem<FileSystem>();    
     engineParameters_["WindowTitle"] = "AtomicPlayer";
 
 #if (ATOMIC_PLATFORM_ANDROID)
@@ -152,120 +137,32 @@ void AtomicPlayer::Setup()
     engineParameters_["ResourcePrefixPath"] = "../Resources";
 #endif
 
-    // Show usage if not found
-    if (scriptFileName_.Empty())
-    {
-        ErrorExit("Usage: AtomicPlayer <scriptfile> [options]\n\n"
-            "The script file should implement the function void Start() for initializing the "
-            "application and subscribing to all necessary events, such as the frame update.\n"
-            #ifndef WIN32
-            "\nCommand line options:\n"
-            "-x <res>     Horizontal resolution\n"
-            "-y <res>     Vertical resolution\n"
-            "-m <level>   Enable hardware multisampling\n"
-            "-v           Enable vertical sync\n"
-            "-t           Enable triple buffering\n"
-            "-w           Start in windowed mode\n"
-            "-s           Enable resizing when in windowed mode\n"
-            "-q           Enable quiet mode which does not log to standard output stream\n"
-            "-b <length>  Sound buffer length in milliseconds\n"
-            "-r <freq>    Sound mixing frequency in Hz\n"
-            "-p <paths>   Resource path(s) to use, separated by semicolons\n"
-            "-ap <paths>  Autoload resource path(s) to use, seperated by semicolons\n"
-            "-log <level> Change the log level, valid 'level' values are 'debug', 'info', 'warning', 'error'\n"
-            "-ds <file>   Dump used shader variations to a file for precaching\n"
-            "-mq <level>  Material quality level, default 2 (high)\n"
-            "-tq <level>  Texture quality level, default 2 (high)\n"
-            "-tf <level>  Texture filter mode, default 2 (trilinear)\n"
-            "-af <level>  Texture anisotropy level, default 4. Also sets anisotropic filter mode\n"
-            "-flushgpu    Flush GPU command queue each frame. Effective only on Direct3D9\n"
-            "-borderless  Borderless window mode\n"
-            "-headless    Headless mode. No application window will be created\n"
-            "-landscape   Use landscape orientations (iOS only, default)\n"
-            "-portrait    Use portrait orientations (iOS only)\n"
-            "-prepass     Use light pre-pass rendering\n"
-            "-deferred    Use deferred rendering\n"
-            "-lqshadows   Use low-quality (1-sample) shadow filtering\n"
-            "-noshadows   Disable shadow rendering\n"
-            "-nolimit     Disable frame limiter\n"
-            "-nothreads   Disable worker threads\n"
-            "-nosound     Disable sound output\n"
-            "-noip        Disable sound mixing interpolation\n"
-            "-sm2         Force SM2.0 rendering\n"
-            "-touch       Touch emulation on desktop platform\n"
-            #endif
-        );
-    }
-    else
-    {
-        // Use the script file name as the base name for the log file
-        engineParameters_["LogName"] = filesystem->GetAppPreferencesDir("urho3d", "logs") + GetFileNameAndExtension(scriptFileName_) + ".log";
-    }
+
+    // Use the script file name as the base name for the log file
+    engineParameters_["LogName"] = filesystem->GetAppPreferencesDir("AtomicPlayer", "Logs") + "AtomicPlayer.log";
 }
 
 void AtomicPlayer::Start()
 {
-    String extension = GetExtension(scriptFileName_);
-
-    if (extension == ".js")
-    {
-
-        // Instantiate and register the Javascript subsystem
-        javascript = new Javascript(context_);
-        context_->RegisterSubsystem(javascript);
-
-        vm = javascript->InstantiateVM("MainVM");
-
-        vm->SetModuleSearchPath("Modules");
-
-        duk_eval_string_noresult(vm->GetJSContext(), "require(\"AtomicGame\");");
-
-        // Hold a shared pointer to the script file to make sure it is not unloaded during runtime
-        jsFile_ = GetSubsystem<ResourceCache>()->GetResource<JSFile>(scriptFileName_);        
-
-        // TODO: Live Reload
-        // Subscribe to script's reload event to allow live-reload of the application
-        //SubscribeToEvent(jsFile_, E_RELOADSTARTED, HANDLER(AtomicPlayer, HandleScriptReloadStarted));
-        //SubscribeToEvent(jsFile_, E_RELOADFINISHED, HANDLER(AtomicPlayer, HandleScriptReloadFinished));
-        //SubscribeToEvent(jsFile_, E_RELOADFAILED, HANDLER(AtomicPlayer, HandleScriptReloadFailed));
+    // Instantiate and register the Javascript subsystem
+    javascript = new Javascript(context_);
+    context_->RegisterSubsystem(javascript);
 
-        if (jsFile_)
-        {
-            bool ok = vm->ExecuteFile(jsFile_);
-            if (!ok)
-            {
-                ErrorExit("Error executing Javascript file");
-                return;
-            }
+    vm = javascript->InstantiateVM("MainVM");
 
-            LOGINFOF("Starting %s", scriptFileName_.CString());
+    vm->SetModuleSearchPath("Modules");
 
-            vm->ExecuteFunction("Start");
-        }
-        else
-        {
-            ErrorExit("Error loading Javascript file");
-            return;
-        }
-
-        return;
-
-        //javascript->ShutdownVM("MainVM");
+    if (!vm->ExecuteMain())
+    {
+        ErrorExit("Error executing Scripts/main.js");
     }
 
-
-    // The script was not successfully loaded. Show the last error message and do not run the main loop
-    ErrorExit();
+    return;
 }
 
 void AtomicPlayer::Stop()
 {
     context_->RemoveSubsystem<Javascript>();
-    /*
-    LuaScript* luaScript = GetSubsystem<LuaScript>();
-    if (luaScript && luaScript->GetFunction("Stop", true))
-        luaScript->ExecuteFunction("Stop");
-    */
 }
 
 void AtomicPlayer::HandleScriptReloadStarted(StringHash eventType, VariantMap& eventData)

+ 1 - 4
Source/Tools/AtomicPlayer/AtomicPlayer.h

@@ -49,11 +49,8 @@ private:
     void HandleScriptReloadFinished(StringHash eventType, VariantMap& eventData);
     /// Handle reload failure of the script file.
     void HandleScriptReloadFailed(StringHash eventType, VariantMap& eventData);
-
-    /// Script file name.
-    String scriptFileName_;
     
     /// Script file.
-    SharedPtr<JSFile> jsFile_;
+    SharedPtr<File> jsFile_;
 
 };