bool CSComponentAssembly::PreloadClassAssemblies()
    {
        // TEMPORARY SOLUTION, Desktop only

        ATOMIC_LOGINFO("Preloading Class Assemblies");

        Context* context = ScriptSystem::GetContext();
        assert(context);

        ResourceCache* cache = context->GetSubsystem<ResourceCache>();
        FileSystem* fileSystem = context->GetSubsystem<FileSystem>();

        const StringVector& resourceDirs = cache->GetResourceDirs();

        for (unsigned i = 0; i < resourceDirs.Size(); i++)
        {
            const String& resourceDir = resourceDirs[i];

            ATOMIC_LOGINFOF("Scanning: %s", resourceDir.CString());

            StringVector results;
            fileSystem->ScanDir(results, resourceDir, "*.dll", SCAN_FILES, true);

            for (unsigned j = 0; j < results.Size(); j++)
            {
                // FIXME: This filtering is necessary as we're loading setting project root folder as a resource dir
                // https://github.com/AtomicGameEngine/AtomicGameEngine/issues/1037

                String filter = results[j].ToLower();

                if (filter.StartsWith("atomicnet/") || filter.StartsWith("resources/"))
                {
                    ATOMIC_LOGINFOF("Skipping Assembly: %s (https://github.com/AtomicGameEngine/AtomicGameEngine/issues/1037)", results[j].CString());
                    continue;
                }

                ATOMIC_LOGINFOF("Loading Assembly: %s", results[j].CString());

                cache->GetResource<CSComponentAssembly>(results[j]);
            }

        }

        return true;

    }
    // see http://duktape.org/guide.html#modules   
    static int js_module_search(duk_context* ctx)
    {       
        JSVM* vm = JSVM::GetJSVM(ctx);
        FileSystem* fs = vm->GetSubsystem<FileSystem>();
        ResourceCache* cache = vm->GetSubsystem<ResourceCache>();

        int top = duk_get_top(ctx);

        assert(top ==  4);

        String moduleID = duk_to_string(ctx, 0);

        if (top > 1)
        {
            // require function
            assert(duk_is_function(ctx, 1));
        }
        
        if (top > 2)
        {
            // exports
            assert(duk_is_object(ctx, 2));
        }

        if (top > 3)        
        {
            // module (module.id == a resolved absolute identifier for the module being loaded)
            assert(duk_is_object(ctx, 3));
        }

        String pathName, fileName, extension;
        SplitPath(moduleID, pathName, fileName, extension);
        String path = moduleID;

        // Do we really want this?  It is nice to not have to specify the Atomic path
        if (fileName.StartsWith("Atomic"))
        {
            path = "AtomicModules/" + path + ".js";
        }
        else
        {
            path += ".js";

            if (!cache->Exists(path))
            {
                const Vector<String>& searchPaths = vm->GetModuleSearchPaths();
                for (unsigned i = 0; i < searchPaths.Size(); i++)
                {
                    String search = searchPaths[i] + path;
                    if (cache->Exists(search))
                    {
                        path = search;
                        break;
                    }
                }
            }
        }

        if (cache->Exists(path))
        {
            SharedPtr<File> jsfile(cache->GetFile(path, false));
            vm->SetLastModuleSearchFile(jsfile->GetFullPath());
            String source;
            jsfile->ReadText(source);
            source.Append('\n');
            duk_push_string(ctx, source.CString());
            return 1;
        }
        else
        {
            // we're not a JS file, so check if we're a native module
            const Vector<String>& resourceDirs = cache->GetResourceDirs();

            for (unsigned i = 0; i < resourceDirs.Size(); i++)
            {

             String pluginLibrary;

             // TODO: proper platform folder detection
#ifdef ATOMIC_PLATFORM_WINDOWS              
              pluginLibrary = resourceDirs.At(i) + "Plugins/Windows/x64/" + moduleID + ".dll";
#elif ATOMIC_PLATFORM_OSX
             pluginLibrary = resourceDirs.At(i) + "Plugins/Mac/x64/lib" + moduleID + ".dylib";
#endif

               if (pluginLibrary.Length() && fs->FileExists(pluginLibrary))
                {
                    // let duktape know we loaded a native module
                    if (jsplugin_load(vm, pluginLibrary))
                    {
                        duk_push_undefined(ctx);
                        return 1;
                    }
                    else
                    {
                        duk_push_sprintf(ctx, "Failed loading native plugins: %s", pluginLibrary.CString());
                        duk_throw(ctx);
                    }
                }
            }

        }

        duk_push_sprintf(ctx, "Failed loading module: %s", path.CString());
        duk_throw(ctx);

    }