From 450d406649768dc50d9517f02e688eb4810a199a Mon Sep 17 00:00:00 2001 From: Justin Chase Date: Sat, 19 Sep 2015 17:03:32 -0500 Subject: [PATCH] lib,test: Use long paths when loading native addons (windows only) When using require to load a native addon the path must be converted into a long path, otherwise the addon will fail to be loaded on windows if the path is longer than 260 characters. --- lib/module.js | 4 +++- test/addons/load-long-path/binding.cc | 14 +++++++++++++ test/addons/load-long-path/binding.gyp | 8 +++++++ test/addons/load-long-path/test.js | 29 ++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 test/addons/load-long-path/binding.cc create mode 100644 test/addons/load-long-path/binding.gyp create mode 100644 test/addons/load-long-path/test.js diff --git a/lib/module.js b/lib/module.js index da8a906f951541..c37f9a5da918cf 100644 --- a/lib/module.js +++ b/lib/module.js @@ -466,7 +466,9 @@ Module._extensions['.json'] = function(module, filename) { //Native extension for .node -Module._extensions['.node'] = process.dlopen; +Module._extensions['.node'] = function(module, filename) { + return process.dlopen(module, path._makeLong(filename)); +}; // bootstrap main module. diff --git a/test/addons/load-long-path/binding.cc b/test/addons/load-long-path/binding.cc new file mode 100644 index 00000000000000..b21f87d0fd5f4b --- /dev/null +++ b/test/addons/load-long-path/binding.cc @@ -0,0 +1,14 @@ +#include +#include + +void Method(const v8::FunctionCallbackInfo& args) { + v8::Isolate* isolate = args.GetIsolate(); + v8::HandleScope scope(isolate); + args.GetReturnValue().Set(v8::String::NewFromUtf8(isolate, "world")); +} + +void init(v8::Local target) { + NODE_SET_METHOD(target, "hello", Method); +} + +NODE_MODULE(binding, init); diff --git a/test/addons/load-long-path/binding.gyp b/test/addons/load-long-path/binding.gyp new file mode 100644 index 00000000000000..3bfb84493f3e87 --- /dev/null +++ b/test/addons/load-long-path/binding.gyp @@ -0,0 +1,8 @@ +{ + 'targets': [ + { + 'target_name': 'binding', + 'sources': [ 'binding.cc' ] + } + ] +} diff --git a/test/addons/load-long-path/test.js b/test/addons/load-long-path/test.js new file mode 100644 index 00000000000000..1de2b85fe94aa6 --- /dev/null +++ b/test/addons/load-long-path/test.js @@ -0,0 +1,29 @@ +'use strict'; +const common = require('../../common'); +const fs = require('fs'); +const path = require('path'); +const assert = require('assert'); + +common.refreshTmpDir(); + +// make a path that is more than 260 chars long. +// Any given folder cannot have a name longer than 260 characters, +// so create 10 nested folders each with 30 character long names. +var addonDestinationDir = path.resolve(common.tmpDir); + +for (var i = 0; i < 10; i++) { + addonDestinationDir = path.join(addonDestinationDir, 'x'.repeat(30)); + fs.mkdirSync(addonDestinationDir); +} + +const addonPath = path.join(__dirname, 'build', 'Release', 'binding.node'); +const addonDestinationPath = path.join(addonDestinationDir, 'binding.node'); + +// Copy binary to long path destination +var contents = fs.readFileSync(addonPath); +fs.writeFileSync(addonDestinationPath, contents); + +// Attempt to load at long path destination +var addon = require(addonDestinationPath); +assert(addon != null); +assert(addon.hello() == 'world');