summaryrefslogtreecommitdiff
path: root/ext/node/01_node.js
blob: 543a559f18b0bfcf93cc04569b771be1b1a2fc17 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.

// deno-lint-ignore-file

const internals = globalThis.__bootstrap.internals;
const primordials = globalThis.__bootstrap.primordials;
const {
  ArrayPrototypePush,
  ArrayPrototypeFilter,
  ObjectEntries,
  ObjectCreate,
  ObjectDefineProperty,
  Proxy,
  ReflectDefineProperty,
  ReflectDeleteProperty,
  ReflectGet,
  ReflectGetOwnPropertyDescriptor,
  ReflectHas,
  ReflectOwnKeys,
  ReflectSet,
  Set,
  SetPrototypeHas,
} = primordials;

function assert(cond) {
  if (!cond) {
    throw Error("assert");
  }
}

let initialized = false;
const nodeGlobals = {};
const nodeGlobalThis = new Proxy(globalThis, {
  get(target, prop) {
    if (ReflectHas(nodeGlobals, prop)) {
      return ReflectGet(nodeGlobals, prop);
    } else {
      return ReflectGet(target, prop);
    }
  },
  set(target, prop, value) {
    if (ReflectHas(nodeGlobals, prop)) {
      return ReflectSet(nodeGlobals, prop, value);
    } else {
      return ReflectSet(target, prop, value);
    }
  },
  has(target, prop) {
    return ReflectHas(nodeGlobals, prop) || ReflectHas(target, prop);
  },
  deleteProperty(target, prop) {
    const nodeDeleted = ReflectDeleteProperty(nodeGlobals, prop);
    const targetDeleted = ReflectDeleteProperty(target, prop);
    return nodeDeleted || targetDeleted;
  },
  ownKeys(target) {
    const targetKeys = ReflectOwnKeys(target);
    const nodeGlobalsKeys = ReflectOwnKeys(nodeGlobals);
    const nodeGlobalsKeySet = new Set(nodeGlobalsKeys);
    return [
      ...ArrayPrototypeFilter(
        targetKeys,
        (k) => !SetPrototypeHas(nodeGlobalsKeySet, k),
      ),
      ...nodeGlobalsKeys,
    ];
  },
  defineProperty(target, prop, desc) {
    if (ReflectHas(nodeGlobals, prop)) {
      return ReflectDefineProperty(nodeGlobals, prop, desc);
    } else {
      return ReflectDefineProperty(target, prop, desc);
    }
  },
  getOwnPropertyDescriptor(target, prop) {
    if (ReflectHas(nodeGlobals, prop)) {
      return ReflectGetOwnPropertyDescriptor(nodeGlobals, prop);
    } else {
      return ReflectGetOwnPropertyDescriptor(target, prop);
    }
  },
});

const nativeModuleExports = ObjectCreate(null);
const builtinModules = [];

function initialize(nodeModules, nodeGlobalThisName) {
  assert(!initialized);
  initialized = true;
  for (const [name, exports] of ObjectEntries(nodeModules)) {
    nativeModuleExports[name] = exports;
    ArrayPrototypePush(builtinModules, name);
  }
  nodeGlobals.Buffer = nativeModuleExports["buffer"].Buffer;
  nodeGlobals.clearImmediate = nativeModuleExports["timers"].clearImmediate;
  nodeGlobals.clearInterval = nativeModuleExports["timers"].clearInterval;
  nodeGlobals.clearTimeout = nativeModuleExports["timers"].clearTimeout;
  nodeGlobals.console = nativeModuleExports["console"];
  nodeGlobals.global = nodeGlobalThis;
  nodeGlobals.process = nativeModuleExports["process"];
  nodeGlobals.setImmediate = nativeModuleExports["timers"].setImmediate;
  nodeGlobals.setInterval = nativeModuleExports["timers"].setInterval;
  nodeGlobals.setTimeout = nativeModuleExports["timers"].setTimeout;

  // add a hidden global for the esm code to use in order to reliably
  // get node's globalThis
  ObjectDefineProperty(globalThis, nodeGlobalThisName, {
    enumerable: false,
    writable: false,
    value: nodeGlobalThis,
  });
  // FIXME(bartlomieju): not nice to depend on `Deno` namespace here
  internals.__bootstrapNodeProcess(Deno.args);
}

internals.node = {
  globalThis: nodeGlobalThis,
  initialize,
  nativeModuleExports,
  builtinModules,
};