Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add base support for exporting objects and classes in node_loader #343

Draft
wants to merge 12 commits into
base: develop
Choose a base branch
from
4 changes: 4 additions & 0 deletions source/adt/include/adt/adt_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ ADT_API int map_insert_array(map m, map_key keys[], map_value values[], size_t s

ADT_API vector map_get(map m, map_key key);

ADT_API vector map_get_keys(map m);

ADT_API vector map_get_values(map m);

ADT_API int map_contains(map m, map_key key);

ADT_API int map_contains_any(map dest, map src);
Expand Down
5 changes: 5 additions & 0 deletions source/adt/include/adt/adt_set.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include <adt/adt_comparable.h>
#include <adt/adt_hash.h>
#include <adt/adt_vector.h>

#ifdef __cplusplus
extern "C" {
Expand Down Expand Up @@ -62,6 +63,10 @@ ADT_API int set_insert_array(set s, set_key keys[], set_value values[], size_t s

ADT_API set_value set_get(set s, set_key key);

ADT_API vector set_get_keys(set s);

ADT_API vector set_get_values(set s);

ADT_API int set_contains(set s, set_key key);

ADT_API int set_contains_any(set dest, set src);
Expand Down
66 changes: 66 additions & 0 deletions source/adt/source/adt_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,72 @@ vector map_get(map m, map_key key)
return NULL;
}

vector map_get_keys(map m)
{
if (m != NULL)
{
vector v = vector_create(sizeof(void *));

if (v == NULL)
{
return NULL;
}

for (size_t iterator = 0; iterator < m->capacity; ++iterator)
{
bucket b = &m->buckets[iterator];

if (b->pairs != NULL && b->count > 0)
{
size_t index;

for (index = 0; index < b->count; ++index)
{
pair p = &b->pairs[index];
vector_push_back(v, &p->key);
}
}
}

return v;
}

return NULL;
}

vector map_get_values(map m)
{
if (m != NULL)
{
vector v = vector_create(sizeof(void *));

if (v == NULL)
{
return NULL;
}

for (size_t iterator = 0; iterator < m->capacity; ++iterator)
{
bucket b = &m->buckets[iterator];

if (b->pairs != NULL && b->count > 0)
{
size_t index;

for (index = 0; index < b->count; ++index)
{
pair p = &b->pairs[index];
vector_push_back(v, &p->value);
}
}
}

return v;
}

return NULL;
}

int map_contains(map m, map_key key)
{
if (m != NULL && key != NULL)
Expand Down
66 changes: 66 additions & 0 deletions source/adt/source/adt_set.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,72 @@ set_value set_get(set s, set_key key)
return NULL;
}

vector set_get_keys(set s)
{
if (s != NULL)
{
vector v = vector_create(sizeof(void *));

if (v == NULL)
{
return NULL;
}

for (size_t iterator = 0; iterator < s->capacity; ++iterator)
{
bucket b = &s->buckets[iterator];

if (b->pairs != NULL && b->count > 0)
{
size_t index;

for (index = 0; index < b->count; ++index)
{
pair p = &b->pairs[index];
vector_push_back(v, &p->key);
}
}
}

return v;
}

return NULL;
}

vector set_get_values(set s)
{
if (s != NULL)
{
vector v = vector_create(sizeof(void *));

if (v == NULL)
{
return NULL;
}

for (size_t iterator = 0; iterator < s->capacity; ++iterator)
{
bucket b = &s->buckets[iterator];

if (b->pairs != NULL && b->count > 0)
{
size_t index;

for (index = 0; index < b->count; ++index)
{
pair p = &b->pairs[index];
vector_push_back(v, &p->value);
}
}
}

return v;
}

return NULL;
}

int set_contains(set s, set_key key)
{
if (s != NULL && key != NULL)
Expand Down
99 changes: 96 additions & 3 deletions source/loaders/node_loader/bootstrap/lib/bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ function node_loader_trampoline_discover_function(func) {
if (node_loader_trampoline_is_callable(func)) {
// Espree can't parse native code functions so we can do a workaround
const str = func.toString().replace('{ [native code] }', '{}');

const ast = espree.parse(`(${str})`, {
ecmaVersion: 14
});
Expand All @@ -276,7 +277,7 @@ function node_loader_trampoline_discover_function(func) {
if (node_loader_trampoline_is_valid_symbol(node)) {
const args = node_loader_trampoline_discover_arguments(node);
const discover = {
ptr: func,
func,
signature: args,
async: node.async,
};
Expand All @@ -287,12 +288,101 @@ function node_loader_trampoline_discover_function(func) {

return discover;
}
else
{
return node_loader_trampoline_discover_klass(func);
}
}
} catch (ex) {
console.log(`Exception while parsing '${func}' in node_loader_trampoline_discover_function`, ex);
}
}

function node_loader_trampoline_discover_klass_attributes(node) {
let attributes = [];
for (let i = 0; i < node.length; i++) {
if (node[i].kind === 'constructor')
{
for (let exp of node[i].value.body.body)
{
if (exp.type === 'ExpressionStatement' && exp.expression.type === 'AssignmentExpression') {
let left = exp.expression.left;

if (left.type == 'MemberExpression' && (left.object && left.object.type === 'ThisExpression')) {
attributes.push(left.property && left.property.name);
}
}
}
}
}

return attributes;
}

function node_loader_trampoline_discover_klass_methods(node, str) {
const ret = {};
for (let method of node) {
if (method.type === 'MethodDefinition') {
let method_name = method.key.name;
if (method.kind === 'constructor') {
method_name = 'klass_' + method_name;
}
ret[method_name] = {
name: method.key.name,
signature: node_loader_trampoline_discover_arguments(method.value)
}

if (method.kind === 'method' && str.substring(method.start-1, method.start+5) === 'static') {
ret[method_name].static = true;
}
}
}

return ret
}

function node_loader_trampoline_discover_klass(klass) {
try {
if (node_loader_trampoline_is_callable(klass)) {
const str = klass.toString();
const ast = espree.parse(`(${str})`, {
ecmaVersion: 14
});

const node = (ast.body[0].type === 'ExpressionStatement') && ast.body[0].expression;
if (node.type === 'ClassExpression') {
const methods = node_loader_trampoline_discover_klass_methods(node.body.body, str)
const discover = {
klass,
methods
};

if (node.id && node.id.name) {
discover['name'] = node.id.name;
}

if (methods.klass_constructor) {
discover['attributes'] = node_loader_trampoline_discover_klass_attributes(node.body.body);
}

return discover;
}
}
} catch (ex) {
console.log(`Exception while parsing '${klass}' in node_loader_trampoline_discover_klass`, ex);
}
}

function node_loader_trampoline_discover_object(obj) {
if (typeof obj === 'object') {
const constructor = (obj && obj.constructor) && obj.constructor.name
if (constructor !== 'Object' && constructor !== 'Array')
return {
obj
};
}
}

function node_loader_trampoline_discover(handle) {
const discover = {};

Expand All @@ -305,8 +395,9 @@ function node_loader_trampoline_discover(handle) {

for (let j = 0; j < keys.length; ++j) {
const key = keys[j];
const func = exports[key];
const descriptor = node_loader_trampoline_discover_function(func);
const value = exports[key];
const descriptor = node_loader_trampoline_discover_function(value)
|| node_loader_trampoline_discover_klass(value) || node_loader_trampoline_discover_object(value);

if (descriptor !== undefined) {
discover[key] = descriptor;
Expand Down Expand Up @@ -411,6 +502,8 @@ module.exports = ((impl, ptr) => {
'clear': node_loader_trampoline_clear,
'discover': node_loader_trampoline_discover,
'discover_function': node_loader_trampoline_discover_function,
'discover_klass': node_loader_trampoline_discover_klass,
'discover_object': node_loader_trampoline_discover_object,
'test': node_loader_trampoline_test,
'await_function': node_loader_trampoline_await_function(trampoline),
'await_future': node_loader_trampoline_await_future(trampoline),
Expand Down
Loading