Skip to content

Commit 72ff0d7

Browse files
committed
Implemented support for compilerhandle.
1 parent a64892a commit 72ff0d7

File tree

5 files changed

+227
-1
lines changed

5 files changed

+227
-1
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.11)
33
project (live_elements_js_compiler)
44
set(CMAKE_CXX_STANDARD 17)
55

6-
add_library(live_elements_js_compiler SHARED src/compilerwrap.cpp ${CMAKE_JS_SRC})
6+
add_library(live_elements_js_compiler SHARED src/compilerwrap.cpp src/compilerhandle.cpp ${CMAKE_JS_SRC})
77

88
include(${CMAKE_CURRENT_SOURCE_DIR}/project/functions.cmake)
99

src/compilerhandle.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#include "compilerhandle.h"
2+
#include "live/visuallog.h"
3+
4+
namespace lv{
5+
6+
Napi::FunctionReference CompilerHandle::constructor;
7+
8+
Napi::Object CompilerHandle::Init(Napi::Env env, Napi::Object exports) {
9+
Napi::Function func = DefineClass(env, "CompilerHandle", {});
10+
11+
constructor = Napi::Persistent(func);
12+
constructor.SuppressDestruct();
13+
14+
exports.Set("CompilerHandle", func);
15+
return exports;
16+
}
17+
18+
CompilerHandle::CompilerHandle(const Napi::CallbackInfo& info)
19+
: Napi::ObjectWrap<CompilerHandle>(info)
20+
{
21+
if (info.Length() == 1 && info[0].IsExternal()) {
22+
Napi::External<lv::el::Compiler::Ptr> externalCompiler = info[0].As<Napi::External<lv::el::Compiler::Ptr>>();
23+
m_compiler = *(externalCompiler.Data());
24+
} else {
25+
Napi::TypeError::New(info.Env(), "CompilerHandle can only be created internally.").ThrowAsJavaScriptException();
26+
}
27+
}
28+
29+
lv::el::Compiler::Ptr CompilerHandle::getInternalInstance() const {
30+
return m_compiler;
31+
}
32+
33+
} // namespace

src/compilerhandle.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include <napi.h>
2+
#include "live/elements/compiler/compiler.h"
3+
4+
namespace lv{
5+
6+
class CompilerHandle : public Napi::ObjectWrap<CompilerHandle> {
7+
public:
8+
static Napi::Object Init(Napi::Env env, Napi::Object exports);
9+
static Napi::FunctionReference constructor;
10+
11+
public:
12+
CompilerHandle(const Napi::CallbackInfo& info);
13+
lv::el::Compiler::Ptr getInternalInstance() const;
14+
15+
private:
16+
lv::el::Compiler::Ptr m_compiler;
17+
};
18+
19+
} // namespace
20+
21+

src/compilerwrap.cpp

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
****************************************************************************/
1515

1616
#include "compilerwrap.h"
17+
#include "compilerhandle.h"
1718
#include "live/visuallog.h"
1819
#include "live/utf8.h"
1920
#include "live/path.h"
@@ -292,9 +293,177 @@ void compileModuleWrap(const Napi::CallbackInfo &info){
292293
}
293294
}
294295

296+
Napi::Value createCompilerWrap(const Napi::CallbackInfo &info){
297+
Napi::Env env = info.Env();
298+
if( info.Length() < 1 || !info[0].IsObject() ){
299+
Napi::TypeError::New(env, "Expected options argument: createCompiler(options:Object)").ThrowAsJavaScriptException();
300+
return env.Null();;
301+
}
302+
303+
Napi::Object optionsArg = info[0].As<Napi::Object>();
304+
305+
Napi::Value err = env.Undefined();
306+
Napi::Value res = env.Undefined();
307+
308+
try{
309+
MLNode compilerOptions;
310+
311+
if ( optionsArg.Has("log") ){
312+
Napi::Object logOptionsArg = optionsArg.Get("log").As<Napi::Object>();
313+
MLNode logOptions;
314+
convertToMLNode(logOptionsArg, logOptions);
315+
316+
VisualLog().configure("global", logOptions);
317+
optionsArg.Delete("log");
318+
}
319+
320+
convertToMLNode(optionsArg, compilerOptions);
321+
322+
lv::el::Compiler::Config config;
323+
config.initialize(compilerOptions);
324+
lv::el::Compiler::Ptr compiler = lv::el::Compiler::create(config);
325+
326+
327+
auto externalCompilerPtr = Napi::External<lv::el::Compiler::Ptr>::New(
328+
env,
329+
new lv::el::Compiler::Ptr(compiler),
330+
[](Napi::Env env, lv::el::Compiler::Ptr* data){
331+
delete data; // Clean up when the external is garbage collected
332+
}
333+
);
334+
335+
336+
Napi::Object obj = CompilerHandle::constructor.New({ externalCompilerPtr });
337+
Napi::Object result = Napi::Object::New(env);
338+
result.Set("value", obj);
339+
return result;
340+
341+
} catch ( lv::el::SyntaxException& e ){
342+
Napi::Object ob = Napi::Object::New(env);
343+
populateSyntaxError(env, ob, &e);
344+
err = ob;
345+
} catch ( lv::el::TracePointException& e ){
346+
Napi::Object ob = Napi::Object::New(env);
347+
populateError(env, ob, &e);
348+
err = ob;
349+
} catch ( lv::Exception& e ){
350+
Napi::Object ob = Napi::Object::New(env);
351+
populateError(env, ob, &e);
352+
err = ob;
353+
} catch ( std::exception& e ){
354+
Napi::Object ob = Napi::Object::New(env);
355+
populateErrorMessage(env, ob, &e);
356+
err = ob;
357+
} catch ( ... ){
358+
Napi::Object ob = Napi::Object::New(env);
359+
populateErrorMessage(env, ob, nullptr);
360+
err = ob;
361+
}
362+
363+
Napi::Object result = Napi::Object::New(env);
364+
result.Set("error", err);
365+
return result;
366+
}
367+
368+
void runCompilerWrap(const Napi::CallbackInfo &info){
369+
Napi::Env env = info.Env();
370+
if( info.Length() < 2 || !info[0].IsObject() || !info[1].IsString()){
371+
Napi::TypeError::New(env, "Expected arguments of type: runCompiler(compiler:CompilerHandle, path:String)").ThrowAsJavaScriptException();
372+
return;
373+
}
374+
375+
Napi::Object obj = info[0].As<Napi::Object>();
376+
CompilerHandle* handle = Napi::ObjectWrap<CompilerHandle>::Unwrap(obj);
377+
378+
lv::el::Compiler::Ptr compiler = handle->getInternalInstance();
379+
380+
Napi::String fileArg = info[1].As<Napi::String>();
381+
382+
Napi::Value err = env.Undefined();
383+
Napi::Value res = env.Undefined();
384+
385+
try{
386+
std::string file = fileArg.Utf8Value();
387+
std::string scriptFile = Path::resolve(file);
388+
std::string pluginPath = Path::parent(scriptFile);
389+
390+
if ( Module::existsIn(pluginPath) ){
391+
Package::Ptr package(nullptr);
392+
if ( Module::fileExistsIn(pluginPath) ){
393+
Module::Ptr module = Module::createFromPath(pluginPath);
394+
package = Package::createFromPath(module->package());
395+
} else {
396+
std::string packagePath = Module::findPackageFrom(pluginPath);
397+
if ( !packagePath.empty() ){
398+
Module::Ptr module = Module::createFromPath(pluginPath);
399+
package = Package::createFromPath(module->package());
400+
}
401+
}
402+
403+
if ( package ){
404+
std::string current = package->path();
405+
std::vector<std::string> importPaths;
406+
while ( Path::exists(current) ){
407+
auto importPath = Path::join(current, compiler->importLocalPath() );
408+
if ( Package::existsIn(current) && Path::exists( importPath ) ){
409+
importPaths.push_back(importPath);
410+
}
411+
if ( Path::rootPath(current) == current ){
412+
break;
413+
}
414+
current = Path::parent(current);
415+
}
416+
compiler->setPackageImportPaths(importPaths);
417+
}
418+
}
419+
420+
lv::el::ElementsModule::Ptr elemMod = lv::el::Compiler::compile(compiler, scriptFile);
421+
lv::el::ModuleFile* mf = elemMod->moduleFileBypath(scriptFile);
422+
423+
424+
if ( mf ){
425+
Napi::Object result = Napi::Object::New(env);
426+
Napi::Value file = Napi::String::New(env, Path::toUnixSeparator(mf->jsFilePath()));
427+
result.Set("file", file);
428+
res = result;
429+
}
430+
431+
} catch ( lv::el::SyntaxException& e ){
432+
Napi::Object ob = Napi::Object::New(env);
433+
populateSyntaxError(env, ob, &e);
434+
err = ob;
435+
} catch ( lv::el::TracePointException& e ){
436+
Napi::Object ob = Napi::Object::New(env);
437+
populateError(env, ob, &e);
438+
err = ob;
439+
} catch ( lv::Exception& e ){
440+
Napi::Object ob = Napi::Object::New(env);
441+
populateError(env, ob, &e);
442+
err = ob;
443+
} catch ( std::exception& e ){
444+
Napi::Object ob = Napi::Object::New(env);
445+
populateErrorMessage(env, ob, &e);
446+
err = ob;
447+
} catch ( ... ){
448+
Napi::Object ob = Napi::Object::New(env);
449+
populateErrorMessage(env, ob, nullptr);
450+
err = ob;
451+
}
452+
453+
if ( info.Length() > 2 ){
454+
Napi::Function cb = info[2].As<Napi::Function>();
455+
cb.Call(env.Global(), {res, err});
456+
}
457+
458+
}
459+
295460
Napi::Object Init(Napi::Env env, Napi::Object exports) {
461+
CompilerHandle::Init(env, exports);
462+
296463
exports.Set("compile", Napi::Function::New(env, lv::compileWrap));
297464
exports.Set("compileModule", Napi::Function::New(env, lv::compileModuleWrap));
465+
exports.Set("createCompiler", Napi::Function::New(env, lv::createCompilerWrap));
466+
exports.Set("runCompiler", Napi::Function::New(env, lv::runCompilerWrap));
298467
return exports;
299468
}
300469

src/compilerwrap.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ namespace lv{
1919

2020
void compileWrap(const Napi::CallbackInfo& info);
2121
void compileModuleWrap(const Napi::CallbackInfo& info);
22+
Napi::Value createCompilerWrap(const Napi::CallbackInfo& info);
23+
void runCompilerWrap(const Napi::CallbackInfo& info);
24+
2225
Napi::Object Init(Napi::Env env, Napi::Object exports);
2326

2427
NODE_API_MODULE(live_elements_js_compiler, Init)

0 commit comments

Comments
 (0)