aboutsummaryrefslogtreecommitdiff
path: root/src/javascript/jsc/bindings/Process.cpp
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-01-19 02:29:07 -0800
committerGravatar GitHub <noreply@github.com> 2022-01-19 02:29:07 -0800
commitd3a93d527336af73df838d69ca42ad1b18adebb8 (patch)
tree726dad460bf4ee2608ffa9557943df11da56f8c3 /src/javascript/jsc/bindings/Process.cpp
parented9637de5056af4572ec5e0a75feee9ca858798e (diff)
downloadbun-d3a93d527336af73df838d69ca42ad1b18adebb8.tar.gz
bun-d3a93d527336af73df838d69ca42ad1b18adebb8.tar.zst
bun-d3a93d527336af73df838d69ca42ad1b18adebb8.zip
`fs.*Sync()`, `bun wiptest`, and More ™ (#106)
* very very wip * almost ready to fix the errors * Update identity_context.zig * Update base.zig * [bun test] It runs successfully * Remove unnecessary call * [Bun.js] Improve JS <> Zig unicode string interop This fixes longstanding unicode bugs with `console.log` & `fetch`. I believe @evanwashere reported this first awhile ago * [Bun.js] Implement `Object.is()` binding and a way to set a timeout for script execution * Update PLCrashReport.zig * [Bun.js] Make `console.log` more closely match Node.js and Deno * [Bun.js] Implement formatting specifier for console.* * Implement `console.clear()` * bug fix * Support console.clear() * Buffer stderr * [bun test] Begin implementing Node.js `fs` * Update darwin_c.zig * Implement more of `fs` * `mkdir`, `mkdir` recursive, `mkdtemp` * `open`, `read` (and pread) * Move some things into more files * Implement readdir * `readFile`, `readLink`, and `realpath` * `writeFile`, `symlink`, `chown`, `rename`, `stat`, `unlink`, `truncate` * `lutimes` * Implement `SystemError` and begin wiring up the `fs` module * `"fs"` - Most of the arguments / validation * `fs` - Rest of the arguments / validations * Begin wiring up the `fs` module * Fix all the build errors * support printing typed arrays in console.log * It...works? * Support `require("fs")`, `import fs from 'fs';`, `import * as fs from 'fs'` * Fix a couple bugs * get rid of the crash reporter for now * Update fs.exports.js * [bun.js] slight improvement to startup time * [bun.js] Improve error message printing * [Bun.js] Add `Bun.gc()` to run the garbage collector manually and report heap size * [Bun.js] Add Bun.generateHeapSnapshot to return what JS types are using memory * [Bun.js] Add `Bun.shrink()` to tell JSC to shrink the VM size * Improve encoding reader * [bun.js] Improve callback & microtask performance * Update node_fs.zig * Implement `console.assert` * simple test * [Bun.js] Prepare for multiple globals/realms to support testing * Create callbacks-overhead.mjs * Update http.zig * [Bun.js] Implement `queueMicrotask` * Add test for queueMicrotask * :sleepy: * [Bun.js] Implement `process.versions`, `process.pid`, `process.ppid`, `process.nextTick`, `process.versions`, * Implement `process.env.toJSON()` * [Bun.js] Improve performance of `fs.existsSync` * :nail_care: * [Bun.js] Implement `process.chdir(str)` and `process.cwd()`, support up to 4 args in `process.nextTick` * Make creating Zig::Process lazy * Split processi nto separte file * [Bun.js] Node.js Streams - Part 1/? * [Bun.js] Node.js streams 2/? * WIP streams * fix crash * Reduce allocations in many places * swap * Make `bun` start 2ms faster * Always use an apiLock() * libBacktrace doesn't really work yet * Fix crash in the upgrade checker * Clean up code for importing the runtime when not bundling * :camera: * Update linker.zig * 68! * backtrace * no, really backtrace * Fix * Linux fixes * Fixes on Linux * Update mimalloc * [bun test] Automatically scan for {.test,_test,.spec,_spec}.{jsx,tsx,js,cts,mts,ts,cjs}
Diffstat (limited to 'src/javascript/jsc/bindings/Process.cpp')
-rw-r--r--src/javascript/jsc/bindings/Process.cpp340
1 files changed, 340 insertions, 0 deletions
diff --git a/src/javascript/jsc/bindings/Process.cpp b/src/javascript/jsc/bindings/Process.cpp
new file mode 100644
index 000000000..754c1d96b
--- /dev/null
+++ b/src/javascript/jsc/bindings/Process.cpp
@@ -0,0 +1,340 @@
+#include "Process.h"
+#include <JavaScriptCore/JSMicrotask.h>
+#include <JavaScriptCore/ObjectConstructor.h>
+
+#pragma mark - Node.js Process
+
+namespace Zig {
+
+using JSGlobalObject = JSC::JSGlobalObject;
+using Exception = JSC::Exception;
+using JSValue = JSC::JSValue;
+using JSString = JSC::JSString;
+using JSModuleLoader = JSC::JSModuleLoader;
+using JSModuleRecord = JSC::JSModuleRecord;
+using Identifier = JSC::Identifier;
+using SourceOrigin = JSC::SourceOrigin;
+using JSObject = JSC::JSObject;
+using JSNonFinalObject = JSC::JSNonFinalObject;
+namespace JSCastingHelpers = JSC::JSCastingHelpers;
+
+static JSC_DECLARE_CUSTOM_SETTER(Process_setTitle);
+static JSC_DECLARE_CUSTOM_GETTER(Process_getArgv);
+static JSC_DECLARE_CUSTOM_SETTER(Process_setArgv);
+static JSC_DECLARE_CUSTOM_GETTER(Process_getTitle);
+static JSC_DECLARE_CUSTOM_GETTER(Process_getVersionsLazy);
+static JSC_DECLARE_CUSTOM_SETTER(Process_setVersionsLazy);
+
+static JSC_DECLARE_CUSTOM_GETTER(Process_getPID);
+static JSC_DECLARE_CUSTOM_GETTER(Process_getPPID);
+
+static JSC_DECLARE_HOST_FUNCTION(Process_functionCwd);
+
+static JSC_DECLARE_HOST_FUNCTION(Process_functionNextTick);
+static JSC_DEFINE_HOST_FUNCTION(Process_functionNextTick,
+ (JSC::JSGlobalObject * globalObject, JSC::CallFrame *callFrame)) {
+ JSC::VM &vm = globalObject->vm();
+ auto argCount = callFrame->argumentCount();
+ if (argCount == 0) {
+ auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
+ JSC::throwTypeError(globalObject, scope, "nextTick requires 1 argument (a function)"_s);
+ return JSC::JSValue::encode(JSC::JSValue{});
+ }
+
+ JSC::JSValue job = callFrame->uncheckedArgument(0);
+
+ if (!job.isObject() || !job.getObject()->isCallable(vm)) {
+ auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
+ JSC::throwTypeError(globalObject, scope, "nextTick expects a function"_s);
+ return JSC::JSValue::encode(JSC::JSValue{});
+ }
+
+ switch (argCount) {
+
+ case 1: {
+ // This is a JSC builtin function
+ globalObject->queueMicrotask(JSC::createJSMicrotask(vm, job));
+ break;
+ }
+
+ case 2:
+ case 3:
+ case 4:
+ case 5: {
+ JSC::JSValue argument0 = callFrame->uncheckedArgument(1);
+ JSC::JSValue argument1 = argCount > 2 ? callFrame->uncheckedArgument(2) : JSC::JSValue{};
+ JSC::JSValue argument2 = argCount > 3 ? callFrame->uncheckedArgument(3) : JSC::JSValue{};
+ JSC::JSValue argument3 = argCount > 4 ? callFrame->uncheckedArgument(4) : JSC::JSValue{};
+ globalObject->queueMicrotask(
+ JSC::createJSMicrotask(vm, job, argument0, argument1, argument2, argument3));
+ break;
+ }
+
+ default: {
+ auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
+ JSC::throwTypeError(globalObject, scope,
+ "nextTick doesn't support more than 4 arguments currently"_s);
+ return JSC::JSValue::encode(JSC::JSValue{});
+
+ break;
+ }
+
+ // JSC::MarkedArgumentBuffer args;
+ // for (unsigned i = 1; i < callFrame->argumentCount(); i++) {
+ // args.append(callFrame->uncheckedArgument(i));
+ // }
+
+ // JSC::ArgList argsList(args);
+ // JSC::gcProtect(job);
+ // JSC::JSFunction *callback = JSC::JSNativeStdFunction::create(
+ // vm, globalObject, 0, String(),
+ // [job, &argsList](JSC::JSGlobalObject *globalObject, JSC::CallFrame *callFrame) {
+ // JSC::VM &vm = globalObject->vm();
+ // auto callData = getCallData(vm, job);
+
+ // return JSC::JSValue::encode(JSC::call(globalObject, job, callData, job, argsList));
+ // });
+
+ // globalObject->queueMicrotask(JSC::createJSMicrotask(vm, JSC::JSValue(callback)));
+ }
+
+ return JSC::JSValue::encode(JSC::jsUndefined());
+}
+
+static JSC_DECLARE_HOST_FUNCTION(Process_functionChdir);
+
+static JSC_DEFINE_HOST_FUNCTION(Process_functionChdir,
+ (JSC::JSGlobalObject * globalObject, JSC::CallFrame *callFrame)) {
+
+ auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
+
+ ZigString str = ZigString{nullptr, 0};
+ if (callFrame->argumentCount() > 0) {
+ str = Zig::toZigString(callFrame->uncheckedArgument(0).toWTFString(globalObject));
+ }
+
+ JSC::JSValue result = JSC::JSValue::decode(Bun__Process__setCwd(globalObject, &str));
+ JSC::JSObject *obj = result.getObject();
+ if (UNLIKELY(obj != nullptr && obj->isErrorInstance())) {
+ scope.throwException(globalObject, obj);
+ return JSValue::encode(JSC::jsUndefined());
+ }
+
+ return JSC::JSValue::encode(result);
+}
+
+void Process::finishCreation(JSC::VM &vm) {
+ Base::finishCreation(vm);
+ auto clientData = Bun::clientData(vm);
+
+ putDirectCustomAccessor(vm, clientData->builtinNames().pidPublicName(),
+ JSC::CustomGetterSetter::create(vm, Process_getPID, nullptr),
+ static_cast<unsigned>(JSC::PropertyAttribute::CustomValue));
+
+ putDirectCustomAccessor(vm, clientData->builtinNames().ppidPublicName(),
+ JSC::CustomGetterSetter::create(vm, Process_getPPID, nullptr),
+ static_cast<unsigned>(JSC::PropertyAttribute::CustomValue));
+
+ putDirectCustomAccessor(vm, clientData->builtinNames().titlePublicName(),
+ JSC::CustomGetterSetter::create(vm, Process_getTitle, Process_setTitle),
+ static_cast<unsigned>(JSC::PropertyAttribute::CustomValue));
+
+ putDirectCustomAccessor(vm, clientData->builtinNames().argvPublicName(),
+ JSC::CustomGetterSetter::create(vm, Process_getArgv, Process_setArgv),
+ static_cast<unsigned>(JSC::PropertyAttribute::CustomValue));
+
+ this->putDirect(vm, clientData->builtinNames().nextTickPublicName(),
+ JSC::JSFunction::create(vm, JSC::jsCast<JSC::JSGlobalObject *>(globalObject()), 0,
+ WTF::String("nextTick"), Process_functionNextTick),
+ 0);
+
+ this->putDirect(vm, clientData->builtinNames().cwdPublicName(),
+ JSC::JSFunction::create(vm, JSC::jsCast<JSC::JSGlobalObject *>(globalObject()), 0,
+ WTF::String("cwd"), Process_functionCwd),
+ 0);
+
+ this->putDirect(vm, clientData->builtinNames().chdirPublicName(),
+ JSC::JSFunction::create(vm, JSC::jsCast<JSC::JSGlobalObject *>(globalObject()), 0,
+ WTF::String("chdir"), Process_functionChdir),
+ 0);
+
+ putDirectCustomAccessor(
+ vm, clientData->builtinNames().versionsPublicName(),
+ JSC::CustomGetterSetter::create(vm, Process_getVersionsLazy, Process_setVersionsLazy), 0);
+ // this should be transpiled out, but just incase
+ this->putDirect(this->vm(), JSC::Identifier::fromString(this->vm(), "browser"),
+ JSC::JSValue(false));
+
+ this->putDirect(this->vm(), clientData->builtinNames().versionPublicName(),
+ JSC::jsString(this->vm(), WTF::String(Bun__version)));
+
+ // this gives some way of identifying at runtime whether the SSR is happening in node or not.
+ // this should probably be renamed to what the name of the bundler is, instead of "notNodeJS"
+ // but it must be something that won't evaluate to truthy in Node.js
+ this->putDirect(this->vm(), JSC::Identifier::fromString(this->vm(), "isBun"), JSC::JSValue(true));
+#if defined(__APPLE__)
+ this->putDirect(this->vm(), JSC::Identifier::fromString(this->vm(), "platform"),
+ JSC::jsString(this->vm(), WTF::String("darwin")));
+#else
+ this->putDirect(this->vm(), JSC::Identifier::fromString(this->vm(), "platform"),
+ JSC::jsString(this->vm(), WTF::String("linux")));
+#endif
+
+#if defined(__x86_64__)
+ this->putDirect(this->vm(), JSC::Identifier::fromString(this->vm(), "arch"),
+ JSC::jsString(this->vm(), WTF::String("x64")));
+#elif defined(__i386__)
+ this->putDirect(this->vm(), JSC::Identifier::fromString(this->vm(), "arch"),
+ JSC::jsString(this->vm(), WTF::String("x86")));
+#elif defined(__arm__)
+ this->putDirect(this->vm(), JSC::Identifier::fromString(this->vm(), "arch"),
+ JSC::jsString(this->vm(), WTF::String("arm")));
+#elif defined(__aarch64__)
+ this->putDirect(this->vm(), JSC::Identifier::fromString(this->vm(), "arch"),
+ JSC::jsString(this->vm(), WTF::String("arm64")));
+#endif
+}
+
+const JSC::ClassInfo Process::s_info = {"Process", &Base::s_info, nullptr, nullptr,
+ CREATE_METHOD_TABLE(Process)};
+
+JSC_DEFINE_CUSTOM_GETTER(Process_getTitle, (JSC::JSGlobalObject * globalObject,
+ JSC::EncodedJSValue thisValue, JSC::PropertyName)) {
+ ZigString str;
+ Bun__Process__getTitle(globalObject, &str);
+ return JSValue::encode(Zig::toJSStringValue(str, globalObject));
+}
+
+JSC_DEFINE_CUSTOM_SETTER(Process_setTitle,
+ (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue,
+ JSC::EncodedJSValue value, JSC::PropertyName)) {
+ JSC::VM &vm = globalObject->vm();
+
+ JSC::JSObject *thisObject = JSC::jsDynamicCast<JSC::JSObject *>(vm, JSValue::decode(thisValue));
+ JSC::JSString *jsString = JSC::jsDynamicCast<JSC::JSString *>(vm, JSValue::decode(value));
+ if (!thisObject || !jsString) { return false; }
+
+ ZigString str = Zig::toZigString(jsString, globalObject);
+ Bun__Process__setTitle(globalObject, &str);
+
+ return true;
+}
+
+JSC_DEFINE_CUSTOM_GETTER(Process_getArgv, (JSC::JSGlobalObject * globalObject,
+ JSC::EncodedJSValue thisValue, JSC::PropertyName)) {
+ JSC::VM &vm = globalObject->vm();
+
+ Zig::Process *thisObject = JSC::jsDynamicCast<Zig::Process *>(vm, JSValue::decode(thisValue));
+ if (!thisObject) { return JSValue::encode(JSC::jsUndefined()); }
+ auto clientData = Bun::clientData(vm);
+
+ if (JSC::JSValue argv = thisObject->getIfPropertyExists(
+ globalObject, clientData->builtinNames().argvPrivateName())) {
+ return JSValue::encode(argv);
+ }
+
+ JSC::EncodedJSValue argv_ = Bun__Process__getArgv(globalObject);
+ thisObject->putDirect(vm, clientData->builtinNames().argvPrivateName(),
+ JSC::JSValue::decode(argv_));
+
+ return argv_;
+}
+
+JSC_DEFINE_CUSTOM_SETTER(Process_setArgv,
+ (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue,
+ JSC::EncodedJSValue value, JSC::PropertyName)) {
+ JSC::VM &vm = globalObject->vm();
+
+ JSC::JSObject *thisObject = JSC::jsDynamicCast<JSC::JSObject *>(vm, JSValue::decode(thisValue));
+ if (!thisObject) { return false; }
+
+ auto clientData = Bun::clientData(vm);
+
+ return thisObject->putDirect(vm, clientData->builtinNames().argvPrivateName(),
+ JSC::JSValue::decode(value));
+}
+
+JSC_DEFINE_CUSTOM_GETTER(Process_getPID, (JSC::JSGlobalObject * globalObject,
+ JSC::EncodedJSValue thisValue, JSC::PropertyName)) {
+ return JSC::JSValue::encode(JSC::JSValue(getpid()));
+}
+
+JSC_DEFINE_CUSTOM_GETTER(Process_getPPID, (JSC::JSGlobalObject * globalObject,
+ JSC::EncodedJSValue thisValue, JSC::PropertyName)) {
+ return JSC::JSValue::encode(JSC::JSValue(getppid()));
+}
+
+JSC_DEFINE_CUSTOM_GETTER(Process_getVersionsLazy,
+ (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue,
+ JSC::PropertyName)) {
+ JSC::VM &vm = globalObject->vm();
+ auto clientData = Bun::clientData(vm);
+
+ Zig::Process *thisObject = JSC::jsDynamicCast<Zig::Process *>(vm, JSValue::decode(thisValue));
+ if (!thisObject) { return JSValue::encode(JSC::jsUndefined()); }
+
+ if (JSC::JSValue argv = thisObject->getIfPropertyExists(
+ globalObject, clientData->builtinNames().versionsPrivateName())) {
+ return JSValue::encode(argv);
+ }
+
+ JSC::JSObject *object =
+ JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 9);
+
+ object->putDirect(vm, JSC::Identifier::fromString(vm, "node"),
+ JSC::JSValue(JSC::jsString(vm, WTF::String("17.0.0"))));
+ object->putDirect(
+ vm, JSC::Identifier::fromString(vm, "bun"),
+ JSC::JSValue(JSC::jsString(vm, WTF::String(Bun__version + 1 /* prefix with v */))));
+ object->putDirect(vm, JSC::Identifier::fromString(vm, "webkit"),
+ JSC::JSValue(JSC::jsString(vm, WTF::String(Bun__versions_webkit))));
+ object->putDirect(vm, JSC::Identifier::fromString(vm, "mimalloc"),
+ JSC::JSValue(JSC::jsString(vm, WTF::String(Bun__versions_mimalloc))));
+ object->putDirect(vm, JSC::Identifier::fromString(vm, "libarchive"),
+ JSC::JSValue(JSC::jsString(vm, WTF::String(Bun__versions_libarchive))));
+ object->putDirect(vm, JSC::Identifier::fromString(vm, "picohttpparser"),
+ JSC::JSValue(JSC::jsString(vm, WTF::String(Bun__versions_picohttpparser))));
+ object->putDirect(vm, JSC::Identifier::fromString(vm, "boringssl"),
+ JSC::JSValue(JSC::jsString(vm, WTF::String(Bun__versions_boringssl))));
+ object->putDirect(vm, JSC::Identifier::fromString(vm, "zlib"),
+ JSC::JSValue(JSC::jsString(vm, WTF::String(Bun__versions_zlib))));
+ object->putDirect(vm, JSC::Identifier::fromString(vm, "zig"),
+ JSC::JSValue(JSC::jsString(vm, WTF::String(Bun__versions_zig))));
+
+ object->putDirect(vm, JSC::Identifier::fromString(vm, "modules"),
+ JSC::JSValue(JSC::jsString(vm, WTF::String("67"))));
+
+ thisObject->putDirect(vm, clientData->builtinNames().versionsPrivateName(), object);
+ return JSC::JSValue::encode(object);
+}
+JSC_DEFINE_CUSTOM_SETTER(Process_setVersionsLazy,
+ (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue,
+ JSC::EncodedJSValue value, JSC::PropertyName)) {
+
+ JSC::VM &vm = globalObject->vm();
+ auto clientData = Bun::clientData(vm);
+
+ Zig::Process *thisObject = JSC::jsDynamicCast<Zig::Process *>(vm, JSValue::decode(thisValue));
+ if (!thisObject) { return JSValue::encode(JSC::jsUndefined()); }
+
+ thisObject->putDirect(vm, clientData->builtinNames().versionsPrivateName(),
+ JSC::JSValue::decode(value));
+
+ return true;
+}
+
+static JSC_DEFINE_HOST_FUNCTION(Process_functionCwd,
+ (JSC::JSGlobalObject * globalObject, JSC::CallFrame *callFrame)) {
+
+ auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
+ JSC::JSValue result = JSC::JSValue::decode(Bun__Process__getCwd(globalObject));
+ JSC::JSObject *obj = result.getObject();
+ if (UNLIKELY(obj != nullptr && obj->isErrorInstance())) {
+ scope.throwException(globalObject, obj);
+ return JSValue::encode(JSC::jsUndefined());
+ }
+
+ return JSC::JSValue::encode(result);
+}
+
+} // namespace Zig \ No newline at end of file