github.com/goplusjs/gopherjs@v1.2.6-0.20211206034512-f187917453b8/node-syscall/syscall.cc (about)

     1  #include <cstdlib>
     2  #include <node.h>
     3  #include <v8.h>
     4  #include <unistd.h>
     5  #include <sys/syscall.h>
     6  #include <errno.h>
     7  
     8  using namespace v8;
     9  
    10  #if NODE_MAJOR_VERSION == 0
    11  #define ARRAY_BUFFER_DATA_OFFSET 23
    12  #else
    13  #define ARRAY_BUFFER_DATA_OFFSET 31
    14  #endif
    15  
    16  intptr_t toNative(Local<Value> value) {
    17    if (value.IsEmpty()) {
    18      return 0;
    19    }
    20    if (value->IsArrayBufferView()) {
    21      Local<ArrayBufferView> view = Local<ArrayBufferView>::Cast(value);
    22      return *reinterpret_cast<intptr_t*>(*reinterpret_cast<char**>(*view->Buffer()) + ARRAY_BUFFER_DATA_OFFSET) + view->ByteOffset(); // ugly hack, because of https://codereview.chromium.org/25221002
    23    }
    24    if (value->IsArray()) {
    25      Local<Array> array = Local<Array>::Cast(value);
    26      intptr_t* native = reinterpret_cast<intptr_t*>(malloc(array->Length() * sizeof(intptr_t))); // TODO memory leak
    27      for (uint32_t i = 0; i < array->Length(); i++) {
    28        native[i] = toNative(array->Get(i));
    29      }
    30      return reinterpret_cast<intptr_t>(native);
    31    }
    32    return static_cast<intptr_t>(static_cast<int32_t>(value->ToInteger()->Value()));
    33  }
    34  
    35  void Syscall(const FunctionCallbackInfo<Value>& info) {
    36    int trap = info[0]->ToInteger()->Value();
    37    int r1 = 0, r2 = 0;
    38    switch (trap) {
    39    case SYS_fork:
    40      r1 = fork();
    41      break;
    42    case SYS_pipe:
    43      int fd[2];
    44      r1 = pipe(fd);
    45      if (r1 == 0) {
    46        r1 = fd[0];
    47        r2 = fd[1];
    48      }
    49      break;
    50    default:
    51      r1 = syscall(
    52        trap,
    53        toNative(info[1]),
    54        toNative(info[2]),
    55        toNative(info[3])
    56      );
    57      break;
    58    }
    59    int err = 0;
    60    if (r1 < 0) {
    61      err = errno;
    62    }
    63    Isolate* isolate = info.GetIsolate();
    64    Local<Array> res = Array::New(isolate, 3);
    65    res->Set(0, Integer::New(isolate, r1));
    66    res->Set(1, Integer::New(isolate, r2));
    67    res->Set(2, Integer::New(isolate, err));
    68    info.GetReturnValue().Set(res);
    69  }
    70  
    71  void Syscall6(const FunctionCallbackInfo<Value>& info) {
    72    int r = syscall(
    73      info[0]->ToInteger()->Value(),
    74      toNative(info[1]),
    75      toNative(info[2]),
    76      toNative(info[3]),
    77      toNative(info[4]),
    78      toNative(info[5]),
    79      toNative(info[6])
    80    );
    81    int err = 0;
    82    if (r < 0) {
    83      err = errno;
    84    }
    85    Isolate* isolate = info.GetIsolate();
    86    Local<Array> res = Array::New(isolate, 3);
    87    res->Set(0, Integer::New(isolate, r));
    88    res->Set(1, Integer::New(isolate, 0));
    89    res->Set(2, Integer::New(isolate, err));
    90    info.GetReturnValue().Set(res);
    91  }
    92  
    93  void init(Handle<Object> target) {
    94    NODE_SET_METHOD(target, "Syscall", Syscall);
    95    NODE_SET_METHOD(target, "Syscall6", Syscall6);
    96  }
    97  
    98  NODE_MODULE(syscall, init);