JSRequire.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. #include <assert.h>
  2. #include <Atomic/IO/FileSystem.h>
  3. #include <Atomic/Resource/ResourceCache.h>
  4. /*
  5. // subsystem requires
  6. #include <Atomic/Engine/Engine.h>
  7. #include <Atomic/Graphics/Graphics.h>
  8. #include <Atomic/Graphics/Renderer.h>
  9. #include <Atomic/Input/Input.h>
  10. #include <Atomic/Resource/ResourceCache.h>
  11. */
  12. #include "JSVM.h"
  13. #include "JSRequire.h"
  14. #include "JSPlugin.h"
  15. namespace Atomic
  16. {
  17. /*
  18. static bool js_require_subsystem(const String& name, JSVM* vm)
  19. {
  20. duk_context* ctx = vm->GetJSContext();
  21. String lowername = name.ToLower();
  22. if (lowername.ToLower() == "input")
  23. {
  24. js_push_class_object_instance(ctx, vm->GetSubsystem<Input>());
  25. return true;
  26. }
  27. if (lowername.ToLower() == "resourcecache")
  28. {
  29. js_push_class_object_instance(ctx, vm->GetSubsystem<ResourceCache>());
  30. return true;
  31. }
  32. if (lowername.ToLower() == "engine")
  33. {
  34. js_push_class_object_instance(ctx, vm->GetSubsystem<Engine>());
  35. return true;
  36. }
  37. if (lowername.ToLower() == "renderer")
  38. {
  39. js_push_class_object_instance(ctx, vm->GetSubsystem<Renderer>());
  40. return true;
  41. }
  42. if (lowername == "graphics")
  43. {
  44. js_push_class_object_instance(ctx, vm->GetSubsystem<Graphics>());
  45. return true;
  46. }
  47. if (lowername.ToLower() == "vm")
  48. {
  49. js_push_class_object_instance(ctx, vm);
  50. return true;
  51. }
  52. return false;
  53. }
  54. */
  55. // see http://duktape.org/guide.html#modules
  56. static int js_module_search(duk_context* ctx)
  57. {
  58. JSVM* vm = JSVM::GetJSVM(ctx);
  59. FileSystem* fs = vm->GetSubsystem<FileSystem>();
  60. ResourceCache* cache = vm->GetSubsystem<ResourceCache>();
  61. int top = duk_get_top(ctx);
  62. assert(top == 4);
  63. String moduleID = duk_to_string(ctx, 0);
  64. if (top > 1)
  65. {
  66. // require function
  67. assert(duk_is_function(ctx, 1));
  68. }
  69. if (top > 2)
  70. {
  71. // exports
  72. assert(duk_is_object(ctx, 2));
  73. }
  74. if (top > 3)
  75. {
  76. // module (module.id == a resolved absolute identifier for the module being loaded)
  77. assert(duk_is_object(ctx, 3));
  78. }
  79. String pathName, fileName, extension;
  80. SplitPath(moduleID, pathName, fileName, extension);
  81. String path = moduleID;
  82. // Do we really want this? It is nice to not have to specify the Atomic path
  83. if (fileName.StartsWith("Atomic"))
  84. {
  85. path = "AtomicModules/" + path + ".js";
  86. }
  87. else
  88. {
  89. path += ".js";
  90. if (!cache->Exists(path))
  91. {
  92. const Vector<String>& searchPaths = vm->GetModuleSearchPaths();
  93. for (unsigned i = 0; i < searchPaths.Size(); i++)
  94. {
  95. String search = searchPaths[i] + path;
  96. if (cache->Exists(search))
  97. {
  98. path = search;
  99. break;
  100. }
  101. }
  102. }
  103. }
  104. if (cache->Exists(path))
  105. {
  106. SharedPtr<File> jsfile(cache->GetFile(path, false));
  107. vm->SetLastModuleSearchFile(jsfile->GetFullPath());
  108. String source;
  109. jsfile->ReadText(source);
  110. duk_push_string(ctx, source.CString());
  111. return 1;
  112. }
  113. else
  114. {
  115. // we're not a JS file, so check if we're a native module
  116. const Vector<String>& resourceDirs = cache->GetResourceDirs();
  117. for (unsigned i = 0; i < resourceDirs.Size(); i++)
  118. {
  119. String pluginLibrary;
  120. // TODO: proper platform folder detection
  121. #ifdef ATOMIC_PLATFORM_WINDOWS
  122. pluginLibrary = resourceDirs.At(i) + "Plugins/Windows/x64/" + moduleID + ".dll";
  123. #elif ATOMIC_PLATFORM_OSX
  124. pluginLibrary = resourceDirs.At(i) + "Plugins/Mac/x64/lib" + moduleID + ".dylib";
  125. #endif
  126. if (pluginLibrary.Length() && fs->FileExists(pluginLibrary))
  127. {
  128. // let duktape know we loaded a native module
  129. if (jsplugin_load(vm, pluginLibrary))
  130. {
  131. duk_push_undefined(ctx);
  132. return 1;
  133. }
  134. else
  135. {
  136. duk_push_sprintf(ctx, "Failed loading native plugins: %s", pluginLibrary.CString());
  137. duk_throw(ctx);
  138. }
  139. }
  140. }
  141. }
  142. duk_push_sprintf(ctx, "Failed loading module: %s", path.CString());
  143. duk_throw(ctx);
  144. }
  145. void js_init_require(JSVM* vm)
  146. {
  147. duk_context* ctx = vm->GetJSContext();
  148. duk_get_global_string(ctx, "Duktape");
  149. duk_push_c_function(ctx, js_module_search, 4);
  150. duk_put_prop_string(ctx, -2, "modSearch");
  151. duk_pop(ctx);
  152. }
  153. }