Skip to content

Commit

Permalink
module: maintain separate cache for native modules
Browse files Browse the repository at this point in the history
  • Loading branch information
vkurchatkin committed Apr 12, 2016
1 parent 819b2d3 commit f44432a
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 1 deletion.
14 changes: 13 additions & 1 deletion lib/module.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const fs = require('fs');
const path = require('path');
const internalModuleReadFile = process.binding('fs').internalModuleReadFile;
const internalModuleStat = process.binding('fs').internalModuleStat;
const internalModuleRealpath = process.binding('fs').internalModuleRealpath;

const splitRe = process.platform === 'win32' ? /[\/\\]/ : /\//;
const isIndexRe = /^index\.\w+?$/;
Expand Down Expand Up @@ -438,9 +439,20 @@ Module._extensions['.json'] = function(module, filename) {
};


const nativeModuleCache = {};

//Native extension for .node
Module._extensions['.node'] = function(module, filename) {
return process.dlopen(module, path._makeLong(filename));
const normalizedPath = internalModuleRealpath(path._makeLong(filename));
const cachedNativeModule = nativeModuleCache[normalizedPath];

if (cachedNativeModule) {
module.exports = cachedNativeModule;
return;
}

process.dlopen(module, path._makeLong(filename));
nativeModuleCache[normalizedPath] = module.exports;
};


Expand Down
20 changes: 20 additions & 0 deletions src/node_file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,25 @@ static void InternalModuleStat(const FunctionCallbackInfo<Value>& args) {
args.GetReturnValue().Set(rc);
}

static void InternalModuleRealpath(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);

CHECK(args[0]->IsString());
node::Utf8Value path(env->isolate(), args[0]);

uv_fs_t req;
int rc = uv_fs_realpath(env->event_loop(), &req, *path, nullptr);
if (rc == 0) {
const char* r = static_cast<const char*>(req.ptr);
Local<String> str = String::NewFromUtf8(env->isolate(),
r, v8::NewStringType::kNormal).ToLocalChecked();
args.GetReturnValue().Set(str);
} else {
args.GetReturnValue().Set(args[0]);
}
uv_fs_req_cleanup(&req);
}

static void Stat(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);

Expand Down Expand Up @@ -1422,6 +1441,7 @@ void InitFs(Local<Object> target,
env->SetMethod(target, "readdir", ReadDir);
env->SetMethod(target, "internalModuleReadFile", InternalModuleReadFile);
env->SetMethod(target, "internalModuleStat", InternalModuleStat);
env->SetMethod(target, "internalModuleRealpath", InternalModuleRealpath);
env->SetMethod(target, "stat", Stat);
env->SetMethod(target, "lstat", LStat);
env->SetMethod(target, "fstat", FStat);
Expand Down
13 changes: 13 additions & 0 deletions test/addons/clear-cache/binding.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <node.h>
#include <v8.h>

void Method(const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::Isolate* isolate = args.GetIsolate();
args.GetReturnValue().Set(v8::String::NewFromUtf8(isolate, "world"));
}

void init(v8::Local<v8::Object> target) {
NODE_SET_METHOD(target, "hello", Method);
}

NODE_MODULE(binding, init);
8 changes: 8 additions & 0 deletions test/addons/clear-cache/binding.gyp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
'targets': [
{
'target_name': 'binding',
'sources': [ 'binding.cc' ]
}
]
}
13 changes: 13 additions & 0 deletions test/addons/clear-cache/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use strict';
require('../../common');
const assert = require('assert');

function clearCache() {
Object.keys(require.cache).forEach((key) => delete require.cache[key]);
}

const val1 = require('./build/release/binding.node').hello;
clearCache();
const val2 = require('./build/release/binding.node').hello;

assert(val1 == val2);

0 comments on commit f44432a

Please sign in to comment.