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

feat (core): add getenv, getcwd, mkdir #7

Merged
merged 2 commits into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ LO_HOME=$(shell pwd)
BINDINGS=lib/core/core.a
ARCH=x64
os=linux
TARGET=${RUNTIME}

ifeq ($(OS),Windows_NT)
os=win
Expand Down Expand Up @@ -55,28 +56,35 @@ else
endif
$(CC) ${CCARGS} ${OPT} -DRUNTIME='"${RUNTIME}"' -DVERSION='"${VERSION}"' -I./v8 -I./v8/include ${WARN} main.cc
$(CC) ${CCARGS} ${OPT} -DRUNTIME='"${RUNTIME}"' -DVERSION='"${VERSION}"' -I./v8 -I./v8/include ${WARN} ${RUNTIME}.cc
$(CC) $(LARGS) ${OPT} main.o ${RUNTIME}.o builtins.o ${BINDINGS} v8/libv8_monolith.a -o ${RUNTIME}
$(CC) $(LARGS) ${OPT} main.o ${RUNTIME}.o builtins.o ${BINDINGS} v8/libv8_monolith.a -o ${TARGET}

${RUNTIME}.exe: v8/include v8/v8_monolith.lib main.js
cl /EHsc /std:c++17 /DRUNTIME='"${RUNTIME}"' /DVERSION='"${VERSION}"' /I./v8 /I./v8/include /c main.cc
cl /EHsc /std:c++17 /DRUNTIME='"${RUNTIME}"' /DVERSION='"${VERSION}"' /I./v8 /I./v8/include /c ${RUNTIME}.cc
cl v8/v8_monolith.lib ${RUNTIME}.obj main.obj winmm.lib dbghelp.lib advapi32.lib /link /out:${RUNTIME}.exe
cl v8/v8_monolith.lib ${RUNTIME}.obj main.obj winmm.lib dbghelp.lib advapi32.lib /link /out:${TARGET}.exe

check:
./${RUNTIME} test/runtime.js

lib/core/core.a:
lib/core/core.a: lib/core/api.js
$(MAKE) BINDING=core staticlib

lib/${BINDING}/${BINDING}.a:
lib/${BINDING}/${BINDING}.a: lib/${BINDING}/api.js
$(MAKE) BINDING=${BINDING} staticlib

staticlib: v8/include v8/libv8_monolith.a
staticlib: v8/include v8/libv8_monolith.a lib/${BINDING}/api.js
ARCH="${ARCH}" os="${os}" LARGS="${LARGS}" WARN="${WARN}" LO_HOME="${LO_HOME}" CCARGS="${CCARGS}" OPT="${OPT}" $(MAKE) -C lib/${BINDING}/ ${BINDING}.a

sharedlib: v8/include v8/libv8_monolith.a lib/${BINDING}/${BINDING}.a
ARCH="${ARCH}" os="${os}" LARGS="${LARGS}" WARN="${WARN}" LO_HOME="${LO_HOME}" CCARGS="${CCARGS}" OPT="${OPT}" $(MAKE) -C lib/${BINDING}/ ${BINDING}.so

docs:
rm -fr docs
curl -L -o docs.tar.gz https://github.com/just-js/docs/archive/$(VERSION).tar.gz
tar -xvf docs.tar.gz
mv docs-$(VERSION) docs
rm -f docs.tar.gz

clean:
ifeq ($(os),win)
@del /q *.obj > NUL 2>&1
Expand Down
2 changes: 2 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
- [ ] **todo**: language server
- [ ] **todo**: snake case
- [ ] **todo**: can we unload bindings and modules? have a look into this
- [ ] **bug**: if i embed the binding definition and change it then the lib won't rebuild as it uses embedded one
- [ ] **todo**: change binding defs so we can have multiple entries with same name but with different options for arch and platform

## features

Expand Down
10 changes: 10 additions & 0 deletions builtins.S
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ __binary_lo_h_start:
.incbin "lo.h"
.global __binary_lo_h_end
__binary_lo_h_end:
.global __binary_globals_d_ts_start
__binary_globals_d_ts_start:
.incbin "globals.d.ts"
.global __binary_globals_d_ts_end
__binary_globals_d_ts_end:
.global __binary_jsconfig_json_start
__binary_jsconfig_json_start:
.incbin "jsconfig.json"
.global __binary_jsconfig_json_end
__binary_jsconfig_json_end:
.global __binary_lib_core_api_js_start
__binary_lib_core_api_js_start:
.incbin "lib/core/api.js"
Expand Down
30 changes: 20 additions & 10 deletions builtins.h

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions builtins_linux.S
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ _binary_lo_h_start:
.incbin "lo.h"
.global _binary_lo_h_end
_binary_lo_h_end:
.global _binary_globals_d_ts_start
_binary_globals_d_ts_start:
.incbin "globals.d.ts"
.global _binary_globals_d_ts_end
_binary_globals_d_ts_end:
.global _binary_jsconfig_json_start
_binary_jsconfig_json_start:
.incbin "jsconfig.json"
.global _binary_jsconfig_json_end
_binary_jsconfig_json_end:
.global _binary_lib_core_api_js_start
_binary_lib_core_api_js_start:
.incbin "lib/core/api.js"
Expand Down
26 changes: 24 additions & 2 deletions lib/core/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ const api = {
parameters: ['i32', 'buffer', 'i32'],
result: 'i32'
},
getcwd: {
parameters: ['pointer', 'i32'],
pointers: ['char*'],
result: 'pointer'
},
write_string: {
parameters: ['i32', 'string', 'i32'],
pointers: [, 'const char*'],
Expand Down Expand Up @@ -69,6 +74,10 @@ const api = {
pointers: ['const char*'],
rpointer: 'DIR*'
},
mkdir: {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how would you define the -p flag?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we will have to write the code to do that in js, which would be quite a bit simpler than the equivalent C.

parameters: ['string', 'u32'],
result: 'i32',
},
closedir: {
parameters: ['pointer'],
pointers: ['DIR*'],
Expand Down Expand Up @@ -109,8 +118,18 @@ const api = {
pointers: ['struct fastcall*'],
result: 'void',
name: 'lo_fastcall'
}

},
// misc
getenv: {
parameters: ['string'],
pointers: ['const char*'],
rpointer: 'char*',
result: 'pointer'
},
dup2: {
parameters: ['i32', 'i32'],
result: 'i32'
},
}

const constants = {
Expand All @@ -120,6 +139,9 @@ const constants = {
O_RDONLY: 'i32',
O_WRONLY: 'i32',
O_CREAT: 'i32',
S_IRWXU: 'i32',
S_IRWXG: 'i32',
S_IXOTH: 'i32',
O_TRUNC: 'i32', STDIN: 0, STDOUT: 1, STDERR: 2
}

Expand Down
103 changes: 103 additions & 0 deletions lib/core/core.cc
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,17 @@ v8::CTypeInfo rcwrite = v8::CTypeInfo(v8::CTypeInfo::Type::kInt32);
v8::CFunctionInfo infowrite = v8::CFunctionInfo(rcwrite, 4, cargswrite);
v8::CFunction pFwrite = v8::CFunction((const void*)&writeFast, &infowrite);

void getcwdFast(void* p, void* p0, int32_t p1, struct FastApiTypedArray* const p_ret);
v8::CTypeInfo cargsgetcwd[4] = {
v8::CTypeInfo(v8::CTypeInfo::Type::kV8Value),
v8::CTypeInfo(v8::CTypeInfo::Type::kUint64),
v8::CTypeInfo(v8::CTypeInfo::Type::kInt32),
v8::CTypeInfo(v8::CTypeInfo::Type::kUint32, v8::CTypeInfo::SequenceType::kIsTypedArray, v8::CTypeInfo::Flags::kNone)
};
v8::CTypeInfo rcgetcwd = v8::CTypeInfo(v8::CTypeInfo::Type::kVoid);
v8::CFunctionInfo infogetcwd = v8::CFunctionInfo(rcgetcwd, 4, cargsgetcwd);
v8::CFunction pFgetcwd = v8::CFunction((const void*)&getcwdFast, &infogetcwd);

int32_t write_stringFast(void* p, int32_t p0, struct FastOneByteString* const p1);
v8::CTypeInfo cargswrite_string[4] = {
v8::CTypeInfo(v8::CTypeInfo::Type::kV8Value),
Expand Down Expand Up @@ -421,6 +432,16 @@ v8::CTypeInfo rcopendir = v8::CTypeInfo(v8::CTypeInfo::Type::kVoid);
v8::CFunctionInfo infoopendir = v8::CFunctionInfo(rcopendir, 3, cargsopendir);
v8::CFunction pFopendir = v8::CFunction((const void*)&opendirFast, &infoopendir);

int32_t mkdirFast(void* p, struct FastOneByteString* const p0, uint32_t p1);
v8::CTypeInfo cargsmkdir[3] = {
v8::CTypeInfo(v8::CTypeInfo::Type::kV8Value),
v8::CTypeInfo(v8::CTypeInfo::Type::kSeqOneByteString),
v8::CTypeInfo(v8::CTypeInfo::Type::kUint32),
};
v8::CTypeInfo rcmkdir = v8::CTypeInfo(v8::CTypeInfo::Type::kInt32);
v8::CFunctionInfo infomkdir = v8::CFunctionInfo(rcmkdir, 3, cargsmkdir);
v8::CFunction pFmkdir = v8::CFunction((const void*)&mkdirFast, &infomkdir);

int32_t closedirFast(void* p, void* p0);
v8::CTypeInfo cargsclosedir[2] = {
v8::CTypeInfo(v8::CTypeInfo::Type::kV8Value),
Expand Down Expand Up @@ -500,6 +521,26 @@ v8::CTypeInfo rcfastcall = v8::CTypeInfo(v8::CTypeInfo::Type::kVoid);
v8::CFunctionInfo infofastcall = v8::CFunctionInfo(rcfastcall, 2, cargsfastcall);
v8::CFunction pFfastcall = v8::CFunction((const void*)&fastcallFast, &infofastcall);

void getenvFast(void* p, struct FastOneByteString* const p0, struct FastApiTypedArray* const p_ret);
v8::CTypeInfo cargsgetenv[3] = {
v8::CTypeInfo(v8::CTypeInfo::Type::kV8Value),
v8::CTypeInfo(v8::CTypeInfo::Type::kSeqOneByteString),
v8::CTypeInfo(v8::CTypeInfo::Type::kUint32, v8::CTypeInfo::SequenceType::kIsTypedArray, v8::CTypeInfo::Flags::kNone)
};
v8::CTypeInfo rcgetenv = v8::CTypeInfo(v8::CTypeInfo::Type::kVoid);
v8::CFunctionInfo infogetenv = v8::CFunctionInfo(rcgetenv, 3, cargsgetenv);
v8::CFunction pFgetenv = v8::CFunction((const void*)&getenvFast, &infogetenv);

int32_t dup2Fast(void* p, int32_t p0, int32_t p1);
v8::CTypeInfo cargsdup2[3] = {
v8::CTypeInfo(v8::CTypeInfo::Type::kV8Value),
v8::CTypeInfo(v8::CTypeInfo::Type::kInt32),
v8::CTypeInfo(v8::CTypeInfo::Type::kInt32),
};
v8::CTypeInfo rcdup2 = v8::CTypeInfo(v8::CTypeInfo::Type::kInt32);
v8::CFunctionInfo infodup2 = v8::CFunctionInfo(rcdup2, 3, cargsdup2);
v8::CFunction pFdup2 = v8::CFunction((const void*)&dup2Fast, &infodup2);



void dlopenSlow(const FunctionCallbackInfo<Value> &args) {
Expand Down Expand Up @@ -639,6 +680,21 @@ int32_t writeFast(void* p, int32_t p0, struct FastApiTypedArray* const p1, int32
int32_t v2 = p2;
return write(v0, v1, v2);
}
void getcwdSlow(const FunctionCallbackInfo<Value> &args) {
char* v0 = reinterpret_cast<char*>((uint64_t)Local<Integer>::Cast(args[0])->Value());
int32_t v1 = Local<Integer>::Cast(args[1])->Value();
void* rc = getcwd(v0, v1);
Local<ArrayBuffer> ab = args[2].As<Uint32Array>()->Buffer();
((void**)ab->Data())[0] = rc;
}

void getcwdFast(void* p, void* p0, int32_t p1, struct FastApiTypedArray* const p_ret) {
char* v0 = reinterpret_cast<char*>(p0);
int32_t v1 = p1;
void* r = getcwd(v0, v1);
((void**)p_ret->data)[0] = r;

}
void write_stringSlow(const FunctionCallbackInfo<Value> &args) {
Isolate *isolate = args.GetIsolate();
int32_t v0 = Local<Integer>::Cast(args[0])->Value();
Expand Down Expand Up @@ -707,6 +763,19 @@ void opendirFast(void* p, struct FastOneByteString* const p0, struct FastApiType
((DIR**)p_ret->data)[0] = r;

}
void mkdirSlow(const FunctionCallbackInfo<Value> &args) {
Isolate *isolate = args.GetIsolate();
String::Utf8Value v0(isolate, args[0]);
uint32_t v1 = Local<Integer>::Cast(args[1])->Value();
int32_t rc = mkdir(*v0, v1);
args.GetReturnValue().Set(Number::New(isolate, rc));
}

int32_t mkdirFast(void* p, struct FastOneByteString* const p0, uint32_t p1) {
struct FastOneByteString* const v0 = p0;
uint32_t v1 = p1;
return mkdir(v0->data, v1);
}
void closedirSlow(const FunctionCallbackInfo<Value> &args) {
Isolate *isolate = args.GetIsolate();
DIR* v0 = reinterpret_cast<DIR*>((uint64_t)Local<Integer>::Cast(args[0])->Value());
Expand Down Expand Up @@ -814,6 +883,33 @@ void fastcallFast(void* p, void* p0) {
struct fastcall* v0 = reinterpret_cast<struct fastcall*>(p0);
lo_fastcall(v0);
}
void getenvSlow(const FunctionCallbackInfo<Value> &args) {
Isolate *isolate = args.GetIsolate();
String::Utf8Value v0(isolate, args[0]);
char* rc = getenv(*v0);
Local<ArrayBuffer> ab = args[1].As<Uint32Array>()->Buffer();
((char**)ab->Data())[0] = rc;
}

void getenvFast(void* p, struct FastOneByteString* const p0, struct FastApiTypedArray* const p_ret) {
struct FastOneByteString* const v0 = p0;
char* r = getenv(v0->data);
((char**)p_ret->data)[0] = r;

}
void dup2Slow(const FunctionCallbackInfo<Value> &args) {
Isolate *isolate = args.GetIsolate();
int32_t v0 = Local<Integer>::Cast(args[0])->Value();
int32_t v1 = Local<Integer>::Cast(args[1])->Value();
int32_t rc = dup2(v0, v1);
args.GetReturnValue().Set(Number::New(isolate, rc));
}

int32_t dup2Fast(void* p, int32_t p0, int32_t p1) {
int32_t v0 = p0;
int32_t v1 = p1;
return dup2(v0, v1);
}

void Init(Isolate* isolate, Local<ObjectTemplate> target) {
Local<ObjectTemplate> module = ObjectTemplate::New(isolate);
Expand All @@ -826,11 +922,13 @@ void Init(Isolate* isolate, Local<ObjectTemplate> target) {
SET_FAST_METHOD(isolate, module, "pread", &pFpread, preadSlow);
SET_FAST_METHOD(isolate, module, "lseek", &pFlseek, lseekSlow);
SET_FAST_METHOD(isolate, module, "write", &pFwrite, writeSlow);
SET_FAST_METHOD(isolate, module, "getcwd", &pFgetcwd, getcwdSlow);
SET_FAST_METHOD(isolate, module, "write_string", &pFwrite_string, write_stringSlow);
SET_FAST_METHOD(isolate, module, "fstat", &pFfstat, fstatSlow);
SET_FAST_METHOD(isolate, module, "unlink", &pFunlink, unlinkSlow);
SET_FAST_METHOD(isolate, module, "readdir", &pFreaddir, readdirSlow);
SET_FAST_METHOD(isolate, module, "opendir", &pFopendir, opendirSlow);
SET_FAST_METHOD(isolate, module, "mkdir", &pFmkdir, mkdirSlow);
SET_FAST_METHOD(isolate, module, "closedir", &pFclosedir, closedirSlow);
SET_FAST_METHOD(isolate, module, "fcntl", &pFfcntl, fcntlSlow);
SET_FAST_METHOD(isolate, module, "mprotect", &pFmprotect, mprotectSlow);
Expand All @@ -840,6 +938,8 @@ void Init(Isolate* isolate, Local<ObjectTemplate> target) {
SET_METHOD(isolate, module, "bind_fastcall", bind_fastcallSlow);
SET_METHOD(isolate, module, "bind_slowcall", bind_slowcallSlow);
SET_FAST_METHOD(isolate, module, "fastcall", &pFfastcall, fastcallSlow);
SET_FAST_METHOD(isolate, module, "getenv", &pFgetenv, getenvSlow);
SET_FAST_METHOD(isolate, module, "dup2", &pFdup2, dup2Slow);

SET_VALUE(isolate, module, "S_IFBLK", Integer::New(isolate, S_IFBLK));
SET_VALUE(isolate, module, "S_IFCHR", Integer::New(isolate, S_IFCHR));
Expand All @@ -853,6 +953,9 @@ void Init(Isolate* isolate, Local<ObjectTemplate> target) {
SET_VALUE(isolate, module, "O_RDONLY", Integer::New(isolate, O_RDONLY));
SET_VALUE(isolate, module, "O_WRONLY", Integer::New(isolate, O_WRONLY));
SET_VALUE(isolate, module, "O_CREAT", Integer::New(isolate, O_CREAT));
SET_VALUE(isolate, module, "S_IRWXU", Integer::New(isolate, S_IRWXU));
SET_VALUE(isolate, module, "S_IRWXG", Integer::New(isolate, S_IRWXG));
SET_VALUE(isolate, module, "S_IXOTH", Integer::New(isolate, S_IXOTH));
SET_VALUE(isolate, module, "O_TRUNC", Integer::New(isolate, O_TRUNC));
SET_VALUE(isolate, module, "STDIN", Integer::New(isolate, 0));
SET_VALUE(isolate, module, "STDOUT", Integer::New(isolate, 1));
Expand Down
9 changes: 9 additions & 0 deletions lib/gen.js
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,13 @@ all: ## make all
`
}

const { S_IRWXU, S_IRWXG, S_IROTH, S_IXOTH } = lo.core

function init_application (dir_path) {
const rc = lo.core.mkdir(`${dir_path}\0`, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)
console.log(rc)
}

const encoder = new TextEncoder()
const decoder = new TextDecoder()

Expand Down Expand Up @@ -525,6 +532,8 @@ async function gen (args) {
source = await headerFile(args.slice(next))
} else if (args[0] === '--make') {
source = await makeFile(args[1])
} else if (args[0] === '--init') {
source = await init_application(args[1])
} else if (args[0] === '--wrap') {
source = await wrapper(args[1])
} else {
Expand Down
6 changes: 6 additions & 0 deletions main.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ extern char _binary_lo_cc_start[];
extern char _binary_lo_cc_end[];
extern char _binary_lo_h_start[];
extern char _binary_lo_h_end[];
extern char _binary_globals_d_ts_start[];
extern char _binary_globals_d_ts_end[];
extern char _binary_jsconfig_json_start[];
extern char _binary_jsconfig_json_end[];
extern char _binary_lib_core_api_js_start[];
extern char _binary_lib_core_api_js_end[];

Expand All @@ -43,6 +47,8 @@ void register_builtins() {
lo::builtins_add("main.cc", _binary_main_cc_start, _binary_main_cc_end - _binary_main_cc_start);
lo::builtins_add("lo.cc", _binary_lo_cc_start, _binary_lo_cc_end - _binary_lo_cc_start);
lo::builtins_add("lo.h", _binary_lo_h_start, _binary_lo_h_end - _binary_lo_h_start);
lo::builtins_add("globals.d.ts", _binary_globals_d_ts_start, _binary_globals_d_ts_end - _binary_globals_d_ts_start);
lo::builtins_add("jsconfig.json", _binary_jsconfig_json_start, _binary_jsconfig_json_end - _binary_jsconfig_json_start);
lo::builtins_add("lib/core/api.js", _binary_lib_core_api_js_start, _binary_lib_core_api_js_end - _binary_lib_core_api_js_start);
lo::modules_add("core", &_register_core);
}
Expand Down
11 changes: 11 additions & 0 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,15 @@ function on_load_builtin (identifier) {
return builtin(identifier)
}

function wrap_getenv () {
const getenv = wrap(new Uint32Array(2), core.getenv, 1)
return str => {
const ptr = getenv(str)
if (!ptr) return ''
return lo.utf8Decode(ptr, -1)
}
}

async function global_main () {
if (args[1] === 'gen') {
(await import('lib/gen.js')).gen(lo.args.slice(2))
Expand Down Expand Up @@ -293,6 +302,8 @@ lo.cstr = cstr
lo.ptr = ptr
lo.addr = addr
lo.core = core
lo.getenv = wrap_getenv()
//const module_caching = parseInt(lo.getenv('LO_CACHE') || '0', 10)
core.dlopen = wrap(handle, core.dlopen, 2)
core.dlsym = wrap(handle, core.dlsym, 2)
core.mmap = wrap(handle, core.mmap, 6)
Expand Down
2 changes: 2 additions & 0 deletions main_win.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ void register_builtins() {
lo::builtins_add("main.cc", _binary_main_cc_start, _binary_main_cc_len);
lo::builtins_add("lo.cc", _binary_lo_cc_start, _binary_lo_cc_len);
lo::builtins_add("lo.h", _binary_lo_h_start, _binary_lo_h_len);
lo::builtins_add("globals.d.ts", _binary_globals_d_ts_start, _binary_globals_d_ts_len);
lo::builtins_add("jsconfig.json", _binary_jsconfig_json_start, _binary_jsconfig_json_len);
lo::builtins_add("lib/core/api.js", _binary_lib_core_api_js_start, _binary_lib_core_api_js_len);
}

Expand Down
Loading