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

Ensure node understands that nodo module is CJS #7

Merged
merged 1 commit into from
Sep 26, 2024
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
78 changes: 39 additions & 39 deletions lib/nodo/core.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,48 +9,48 @@ class Core
ARRAY_CLASS_ATTRIBUTES = %i[dependencies constants scripts].freeze
HASH_CLASS_ATTRIBUTES = %i[functions].freeze
CLASS_ATTRIBUTES = (ARRAY_CLASS_ATTRIBUTES + HASH_CLASS_ATTRIBUTES).freeze

@@node_pid = nil
@@tmpdir = nil
@@mutex = Mutex.new
@@exiting = nil

class << self
extend Forwardable

attr_accessor :class_defined

def inherited(subclass)
CLASS_ATTRIBUTES.each do |attr|
subclass.send "#{attr}=", send(attr).dup
end
end

def instance
@instance ||= new
end

def class_defined?
!!class_defined
end

def clsid
name || "Class:0x#{object_id.to_s(0x10)}"
end

CLASS_ATTRIBUTES.each do |attr|
define_method "#{attr}=" do |value|
instance_variable_set :"@#{attr}", value
end
protected "#{attr}="
end

ARRAY_CLASS_ATTRIBUTES.each do |attr|
define_method "#{attr}" do
instance_variable_get(:"@#{attr}") || instance_variable_set(:"@#{attr}", [])
end
end

HASH_CLASS_ATTRIBUTES.each do |attr|
define_method "#{attr}" do
instance_variable_get(:"@#{attr}") || instance_variable_set(:"@#{attr}", {})
Expand All @@ -60,15 +60,15 @@ def clsid
def generate_core_code
<<~JS
global.nodo = require(#{nodo_js});

const socket = process.argv[1];
if (!socket) {
process.stderr.write('Socket path is required\\n');
process.exit(1);
}

process.title = `nodo-core ${socket}`;

const shutdown = () => {
nodo.core.close(() => { process.exit(0) });
};
Expand All @@ -92,19 +92,19 @@ def generate_class_code
})()
JS
end

protected

def finalize_context(context_id)
proc do
if not @@exiting and core = Nodo::Core.instance
core.send(:call_js_method, GC_METHOD, context_id)
end
end
end

private

def require(*mods)
deps = mods.last.is_a?(Hash) ? mods.pop : {}
mods = mods.map { |m| [m, m] }.to_h
Expand All @@ -118,28 +118,28 @@ def function(name, _code = nil, timeout: Nodo.timeout, code: nil, &block)
self.functions = functions.merge(name => Function.new(name, _code || code, source_location, timeout, &block))
define_method(name) { |*args| call_js_method(name, args) }
end

def class_function(*methods)
singleton_class.def_delegators(:instance, *methods)
end

def const(name, value)
self.constants = constants + [Constant.new(name, value)]
end

def script(code = nil, &block)
self.scripts = scripts + [Script.new(code, &block)]
end

def nodo_js
Pathname.new(__FILE__).dirname.join('nodo.js').to_s.to_json
Pathname.new(__FILE__).dirname.join('nodo.cjs').to_s.to_json
end

def reserved_method_name?(name)
Nodo::Core.method_defined?(name, false) || Nodo::Core.private_method_defined?(name, false) || name.to_s == DEFINE_METHOD
end
end

def initialize
raise ClassError, :new if self.class == Nodo::Core
@@mutex.synchronize do
Expand All @@ -148,52 +148,52 @@ def initialize
ensure_class_is_defined
end
end

def evaluate(code)
ensure_context_is_defined
call_js_method(EVALUATE_METHOD, code)
end

private

def node_pid
@@node_pid
end

def tmpdir
@@tmpdir
end

def socket_path
tmpdir && tmpdir.join(SOCKET_NAME)
end

def clsid
self.class.clsid
end

def context_defined?
@context_defined
end

def log_exception(e)
return unless logger = Nodo.logger
message = "\n#{e.class} (#{e.message})"
message << ":\n\n#{e.backtrace.join("\n")}" if e.backtrace
logger.error message
end

def ensure_process_is_spawned
return if node_pid
spawn_process
end

def ensure_class_is_defined
return if self.class.class_defined?
call_js_method(DEFINE_METHOD, self.class.generate_class_code)
self.class.class_defined = true
end

def ensure_context_is_defined
return if context_defined?
@@mutex.synchronize do
Expand All @@ -202,7 +202,7 @@ def ensure_context_is_defined
@context_defined = true
end
end

def spawn_process
@@tmpdir = Pathname.new(Dir.mktmpdir('nodo'))
env = Nodo.env.merge('NODE_PATH' => Nodo.modules_root.to_s)
Expand All @@ -215,7 +215,7 @@ def spawn_process
FileUtils.remove_entry(tmpdir) if File.directory?(tmpdir)
end
end

def wait_for_socket
start = Time.now
socket = nil
Expand Down Expand Up @@ -257,7 +257,7 @@ def call_js_method(method, args)
# TODO: restart or something? If this happens the process is completely broken
raise Error, 'Node process failed'
end

def handle_error(response, function)
if response.body
result = parse_response(response)
Expand All @@ -270,12 +270,12 @@ def handle_error(response, function)
log_exception(error)
raise error
end

def parse_response(response)
data = response.body.force_encoding('UTF-8')
JSON.parse(data) unless data == ''
end

def with_tempfile(name)
ext = File.extname(name)
result = nil
Expand All @@ -284,6 +284,6 @@ def with_tempfile(name)
end
result
end

end
end
20 changes: 10 additions & 10 deletions lib/nodo/nodo.js → lib/nodo/nodo.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ module.exports = (function() {
let server, closing;
const classes = {};
const contexts = {};

function render_error(e) {
let errInfo = {};
if (e instanceof Error) {
Expand All @@ -31,7 +31,7 @@ module.exports = (function() {
debug(`Error ${code} ${rendered}`);
res.end(rendered, 'utf8');
}

function respond_with_data(res, data, start) {
let timing;
res.statusCode = 200;
Expand All @@ -58,18 +58,18 @@ module.exports = (function() {
debug('Starting up...');
server = http.createServer((req, res) => {
const start = performance.now();

res.setHeader('Content-Type', 'application/json');
debug(`${req.method} ${req.url}`);

if (req.method !== 'POST' || !req.url.startsWith('/')) {
return respond_with_error(res, 405, 'Method Not Allowed');
}

const url = req.url.substring(1);
const [class_name, object_id, method] = url.split('/');
let klass, context;

if (classes.hasOwnProperty(class_name)) {
klass = classes[class_name];
if (EVALUATE_METHOD == method) {
Expand All @@ -83,9 +83,9 @@ module.exports = (function() {
} else if (DEFINE_METHOD != method) {
return respond_with_error(res, 404, `Class ${class_name} not defined`);
}

let body = '';

req.on('data', (data) => { body += data; });

req.on('end', () => {
Expand Down Expand Up @@ -120,7 +120,7 @@ module.exports = (function() {
} catch(error) {
return respond_with_error(res, 500, error);
}

});
});

Expand All @@ -129,7 +129,7 @@ module.exports = (function() {
debug(`server ready, listening on ${socket} (max connections: ${server.maxConnections})`);
});
},

close: (finalizer) => {
debug("Shutting down");
if (!closing) {
Expand All @@ -138,6 +138,6 @@ module.exports = (function() {
}
}
};

return { core: core, debug: debug, import: import_module };
})();
Loading