Skip to content

Commit cc9d793

Browse files
authored
Merge pull request #120 from Encrylize/node-port
Add support for local scopes to Node port
2 parents 97bb90b + c6fb1b6 commit cc9d793

File tree

3 files changed

+239
-28
lines changed

3 files changed

+239
-28
lines changed

source/loaders/node_loader/source/node_loader_port.cpp

Lines changed: 177 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,10 +186,99 @@ napi_value node_loader_port_load_from_file(napi_env env, napi_callback_info info
186186

187187
delete[] paths;
188188

189-
/* TODO */
190189
return NULL;
191190
}
192191

192+
napi_value node_loader_port_load_from_file_export(napi_env env, napi_callback_info info)
193+
{
194+
/* TODO: Detect if input argument types are valid */
195+
196+
const size_t args_size = 2;
197+
size_t argc = args_size, tag_length;
198+
napi_value argv[args_size];
199+
uint32_t paths_size, path_index = 0;
200+
char *tag;
201+
202+
napi_get_cb_info(env, info, &argc, argv, NULL, NULL);
203+
204+
napi_get_value_string_utf8(env, argv[0], NULL, 0, &tag_length);
205+
206+
if (tag_length == 0)
207+
{
208+
napi_throw_error(env, NULL, "Invalid MetaCall tag");
209+
return NULL;
210+
}
211+
212+
tag = new char[tag_length + 1];
213+
214+
napi_get_value_string_utf8(env, argv[0], tag, tag_length + 1, &tag_length);
215+
216+
tag[tag_length] = '\0';
217+
218+
napi_get_array_length(env, argv[1], &paths_size);
219+
220+
char **paths = new char *[paths_size];
221+
222+
for (uint32_t i = 0; i < paths_size; ++i)
223+
{
224+
napi_value path;
225+
size_t path_length;
226+
227+
napi_get_element(env, argv[1], i, &path);
228+
229+
napi_get_value_string_utf8(env, path, NULL, 0, &path_length);
230+
231+
if (path_length != 0)
232+
{
233+
paths[path_index] = new char[path_length + 1];
234+
235+
napi_get_value_string_utf8(env, path, paths[path_index], path_length + 1, &path_length);
236+
237+
paths[path_index][path_length] = '\0';
238+
239+
++path_index;
240+
}
241+
}
242+
243+
loader_impl_node node_impl = NULL;
244+
void *handle = NULL;
245+
246+
if (path_index == paths_size)
247+
{
248+
/* Obtain NodeJS loader implementation */
249+
loader_impl impl = loader_get_impl("node");
250+
node_impl = (loader_impl_node)loader_impl_get(impl);
251+
252+
/* Store current reference of the environment */
253+
node_loader_impl_env(node_impl, env);
254+
255+
if (metacall_load_from_file(tag, (const char **)paths, paths_size, &handle) != 0)
256+
{
257+
napi_throw_error(env, NULL, "MetaCall could not load from file");
258+
}
259+
260+
/* Release current reference of the environment */
261+
// node_loader_impl_env(node_impl, NULL);
262+
}
263+
else
264+
{
265+
napi_throw_error(env, NULL, "Invalid input paths");
266+
}
267+
268+
delete[] tag;
269+
270+
for (uint32_t i = 0; i < path_index; ++i)
271+
{
272+
delete[] paths[i];
273+
}
274+
275+
delete[] paths;
276+
277+
void *exports = metacall_handle_export(handle);
278+
279+
return node_loader_impl_value_to_napi(node_impl, env, exports);
280+
}
281+
193282
/**
194283
* @brief
195284
* Loads a script from string by tag
@@ -280,6 +369,86 @@ napi_value node_loader_port_load_from_memory(napi_env env, napi_callback_info in
280369
return NULL;
281370
}
282371

372+
napi_value node_loader_port_load_from_memory_export(napi_env env, napi_callback_info info)
373+
{
374+
const size_t args_size = 2;
375+
size_t argc = args_size, tag_length, script_length, script_size;
376+
napi_value argv[args_size];
377+
napi_status status;
378+
char *tag, *script;
379+
380+
// Get arguments
381+
status = napi_get_cb_info(env, info, &argc, argv, NULL, NULL);
382+
383+
node_loader_impl_exception(env, status);
384+
385+
// Get tag length
386+
status = napi_get_value_string_utf8(env, argv[0], NULL, 0, &tag_length);
387+
388+
node_loader_impl_exception(env, status);
389+
390+
// Allocate tag
391+
tag = static_cast<char *>(malloc(sizeof(char) * (tag_length + 1)));
392+
393+
if (tag == NULL)
394+
{
395+
napi_throw_error(env, NULL, "MetaCall could not load from memory, tag allocation failed");
396+
return NULL;
397+
}
398+
399+
// Get tag
400+
status = napi_get_value_string_utf8(env, argv[0], tag, tag_length + 1, &tag_length);
401+
402+
node_loader_impl_exception(env, status);
403+
404+
// Get script length
405+
status = napi_get_value_string_utf8(env, argv[1], NULL, 0, &script_length);
406+
407+
node_loader_impl_exception(env, status);
408+
409+
script_size = script_length + 1;
410+
411+
// Allocate script
412+
script = static_cast<char *>(malloc(sizeof(char) * script_size));
413+
414+
if (script == NULL)
415+
{
416+
free(tag);
417+
napi_throw_error(env, NULL, "MetaCall could not load from memory, script allocation failed");
418+
return NULL;
419+
}
420+
421+
// Get script
422+
status = napi_get_value_string_utf8(env, argv[1], script, script_size, &script_length);
423+
424+
node_loader_impl_exception(env, status);
425+
426+
/* Obtain NodeJS loader implementation */
427+
loader_impl impl = loader_get_impl("node");
428+
loader_impl_node node_impl = (loader_impl_node)loader_impl_get(impl);
429+
430+
/* Store current reference of the environment */
431+
node_loader_impl_env(node_impl, env);
432+
433+
void *handle = NULL;
434+
435+
// Load script from memory
436+
if (metacall_load_from_memory(tag, script, script_size, &handle) != 0)
437+
{
438+
napi_throw_error(env, NULL, "MetaCall could not load from memory");
439+
}
440+
441+
/* Release current reference of the environment */
442+
// node_loader_impl_env(node_impl, NULL);
443+
444+
free(tag);
445+
free(script);
446+
447+
void *exports = metacall_handle_export(handle);
448+
449+
return node_loader_impl_value_to_napi(node_impl, env, exports);
450+
}
451+
283452
/* TODO: Add documentation */
284453
napi_value node_loader_port_inspect(napi_env env, napi_callback_info)
285454
{
@@ -330,21 +499,27 @@ void node_loader_port_exports(napi_env env, napi_value exports)
330499
{
331500
const char function_metacall_str[] = "metacall";
332501
const char function_load_from_file_str[] = "metacall_load_from_file";
502+
const char function_load_from_file_export_str[] = "metacall_load_from_file_export";
333503
const char function_load_from_memory_str[] = "metacall_load_from_memory";
504+
const char function_load_from_memory_export_str[] = "metacall_load_from_memory_export";
334505
const char function_inspect_str[] = "metacall_inspect";
335506
const char function_logs_str[] = "metacall_logs";
336507

337-
napi_value function_metacall, function_load_from_file, function_load_from_memory, function_inspect, function_logs;
508+
napi_value function_metacall, function_load_from_file, function_load_from_file_export, function_load_from_memory, function_load_from_memory_export, function_inspect, function_logs;
338509

339510
napi_create_function(env, function_metacall_str, sizeof(function_metacall_str) - 1, node_loader_port_call, NULL, &function_metacall);
340511
napi_create_function(env, function_load_from_file_str, sizeof(function_load_from_file_str) - 1, node_loader_port_load_from_file, NULL, &function_load_from_file);
512+
napi_create_function(env, function_load_from_file_export_str, sizeof(function_load_from_file_export_str) - 1, node_loader_port_load_from_file_export, NULL, &function_load_from_file_export);
341513
napi_create_function(env, function_load_from_memory_str, sizeof(function_load_from_memory_str) - 1, node_loader_port_load_from_memory, NULL, &function_load_from_memory);
514+
napi_create_function(env, function_load_from_memory_export_str, sizeof(function_load_from_memory_export_str) - 1, node_loader_port_load_from_memory_export, NULL, &function_load_from_memory_export);
342515
napi_create_function(env, function_inspect_str, sizeof(function_inspect_str) - 1, node_loader_port_inspect, NULL, &function_inspect);
343516
napi_create_function(env, function_logs_str, sizeof(function_logs_str) - 1, node_loader_port_logs, NULL, &function_logs);
344517

345518
napi_set_named_property(env, exports, function_metacall_str, function_metacall);
346519
napi_set_named_property(env, exports, function_load_from_file_str, function_load_from_file);
520+
napi_set_named_property(env, exports, function_load_from_file_export_str, function_load_from_file_export);
347521
napi_set_named_property(env, exports, function_load_from_memory_str, function_load_from_memory);
522+
napi_set_named_property(env, exports, function_load_from_memory_export_str, function_load_from_memory_export);
348523
napi_set_named_property(env, exports, function_inspect_str, function_inspect);
349524
napi_set_named_property(env, exports, function_logs_str, function_logs);
350525
}

source/ports/node_port/index.js

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,18 @@ const metacall_load_from_file = (tag, paths) => {
9494
return addon.metacall_load_from_file(tag, paths);
9595
};
9696

97+
const metacall_load_from_file_export = (tag, paths) => {
98+
if (Object.prototype.toString.call(tag) !== '[object String]') {
99+
throw Error('Tag should be a string indicating the id of the loader to be used [py, rb, cs, js, node, mock...].');
100+
}
101+
102+
if (!(paths instanceof Array)) {
103+
throw Error('Paths should be an array with file names and paths to be loaded by the loader.');
104+
}
105+
106+
return addon.metacall_load_from_file_export(tag, paths);
107+
};
108+
97109
const metacall_load_from_memory = (tag, code) => {
98110
if (Object.prototype.toString.call(tag) !== '[object String]') {
99111
throw Error('Tag should be a string indicating the id of the loader to be used [py, rb, cs, js, node, mock...].');
@@ -104,8 +116,18 @@ const metacall_load_from_memory = (tag, code) => {
104116
}
105117

106118
return addon.metacall_load_from_memory(tag, code);
119+
};
107120

108-
// TODO: Implement here the inspect of the memory module by handle
121+
const metacall_load_from_memory_export = (tag, code) => {
122+
if (Object.prototype.toString.call(tag) !== '[object String]') {
123+
throw Error('Tag should be a string indicating the id of the loader to be used [py, rb, cs, js, node, mock...].');
124+
}
125+
126+
if (Object.prototype.toString.call(code) !== '[object String]') {
127+
throw Error('Code should be a string with the inline code to be loaded.');
128+
}
129+
130+
return addon.metacall_load_from_memory_export(tag, code);
109131
};
110132

111133
const metacall_inspect = () => {
@@ -140,29 +162,17 @@ const metacall_handle = (tag, name) => {
140162
};
141163

142164
const metacall_require = (tag, name) => {
143-
// TODO: Inspect only the handle instead of the whole metacall namespace
144-
/* return */ addon.metacall_load_from_file(tag, [ name ]);
145-
146-
/* TODO: Replace metacall_inspect by retrieving the handle and metacall_export */
147-
const inspect = metacall_inspect();
148-
const script = inspect[tag].find(s => s.name === path.basename(name));
149-
150-
const obj = {};
151-
152-
/* TODO: Support async functions */
153-
for (const func of script.scope.funcs) {
154-
obj[func.name] = (...args) => addon.metacall(func.name, ...args);
155-
}
156-
157-
return obj;
165+
return addon.metacall_load_from_file_export(tag, [ name ]);
158166
};
159167

160168
/* Module exports */
161169
const module_exports = {
162170
metacall,
163171
metacall_inspect,
164172
metacall_load_from_file,
173+
metacall_load_from_file_export,
165174
metacall_load_from_memory,
175+
metacall_load_from_memory_export,
166176
metacall_handle,
167177

168178
/* TODO: Remove this from user or provide better ways of configuring logs */

0 commit comments

Comments
 (0)