From 0be359614aff0282381c753f490daa98bef8e1e2 Mon Sep 17 00:00:00 2001 From: Vladimir Kurchatkin Date: Sat, 14 Feb 2015 22:53:34 +0300 Subject: [PATCH 1/4] iojs: introduce internal modules Internal modules can be used to share private code between public modules without risk to expose private APIs to the user. --- lib/_http_common.js | 2 +- lib/freelist.js | 25 +----------------- lib/internal/freelist.js | 26 +++++++++++++++++++ lib/module.js | 6 ++--- node.gyp | 2 ++ src/node.js | 8 ++++++ test/fixtures/internal-modules/index.js | 1 + .../node_modules/internal/freelist.js | 1 + test/parallel/test-internal-modules.js | 8 ++++++ tools/js2c.py | 16 +++++++----- 10 files changed, 60 insertions(+), 35 deletions(-) create mode 100644 lib/internal/freelist.js create mode 100644 test/fixtures/internal-modules/index.js create mode 100644 test/fixtures/internal-modules/node_modules/internal/freelist.js create mode 100644 test/parallel/test-internal-modules.js diff --git a/lib/_http_common.js b/lib/_http_common.js index 209bd77bf452cc..7861848b46a9d4 100644 --- a/lib/_http_common.js +++ b/lib/_http_common.js @@ -1,6 +1,6 @@ 'use strict'; -const FreeList = require('freelist').FreeList; +const FreeList = require('internal/freelist').FreeList; const HTTPParser = process.binding('http_parser').HTTPParser; const incoming = require('_http_incoming'); diff --git a/lib/freelist.js b/lib/freelist.js index 78a581d6acb37b..9300c1148754c4 100644 --- a/lib/freelist.js +++ b/lib/freelist.js @@ -1,26 +1,3 @@ 'use strict'; -// This is a free list to avoid creating so many of the same object. -exports.FreeList = function(name, max, constructor) { - this.name = name; - this.constructor = constructor; - this.max = max; - this.list = []; -}; - - -exports.FreeList.prototype.alloc = function() { - //debug("alloc " + this.name + " " + this.list.length); - return this.list.length ? this.list.shift() : - this.constructor.apply(this, arguments); -}; - - -exports.FreeList.prototype.free = function(obj) { - //debug("free " + this.name + " " + this.list.length); - if (this.list.length < this.max) { - this.list.push(obj); - return true; - } - return false; -}; +module.exports = require('internal/freelist'); diff --git a/lib/internal/freelist.js b/lib/internal/freelist.js new file mode 100644 index 00000000000000..78a581d6acb37b --- /dev/null +++ b/lib/internal/freelist.js @@ -0,0 +1,26 @@ +'use strict'; + +// This is a free list to avoid creating so many of the same object. +exports.FreeList = function(name, max, constructor) { + this.name = name; + this.constructor = constructor; + this.max = max; + this.list = []; +}; + + +exports.FreeList.prototype.alloc = function() { + //debug("alloc " + this.name + " " + this.list.length); + return this.list.length ? this.list.shift() : + this.constructor.apply(this, arguments); +}; + + +exports.FreeList.prototype.free = function(obj) { + //debug("free " + this.name + " " + this.list.length); + if (this.list.length < this.max) { + this.list.push(obj); + return true; + } + return false; +}; diff --git a/lib/module.js b/lib/module.js index b2ddbd80c31913..719f8bd50c5716 100644 --- a/lib/module.js +++ b/lib/module.js @@ -200,7 +200,7 @@ Module._nodeModulePaths = function(from) { Module._resolveLookupPaths = function(request, parent) { - if (NativeModule.exists(request)) { + if (NativeModule.nonInternalExists(request)) { return [request, []]; } @@ -262,7 +262,7 @@ Module._load = function(request, parent, isMain) { return cachedModule.exports; } - if (NativeModule.exists(filename)) { + if (NativeModule.nonInternalExists(filename)) { // REPL is a special case, because it needs the real require. if (filename == 'repl') { var replModule = new Module('repl'); @@ -299,7 +299,7 @@ Module._load = function(request, parent, isMain) { }; Module._resolveFilename = function(request, parent) { - if (NativeModule.exists(request)) { + if (NativeModule.nonInternalExists(request)) { return request; } diff --git a/node.gyp b/node.gyp index cae5340b273a48..c38a4ae8935a68 100644 --- a/node.gyp +++ b/node.gyp @@ -69,6 +69,8 @@ 'lib/v8.js', 'lib/vm.js', 'lib/zlib.js', + + 'lib/internal/freelist.js' ], }, diff --git a/src/node.js b/src/node.js index dbadc6637307e4..826545180b60ba 100644 --- a/src/node.js +++ b/src/node.js @@ -838,6 +838,14 @@ return NativeModule._source.hasOwnProperty(id); }; + NativeModule.nonInternalExists = function(id) { + return NativeModule.exists(id) && !NativeModule.isInternal(id); + }; + + NativeModule.isInternal = function(id) { + return id.startsWith('internal/'); + }; + NativeModule.getSource = function(id) { return NativeModule._source[id]; }; diff --git a/test/fixtures/internal-modules/index.js b/test/fixtures/internal-modules/index.js new file mode 100644 index 00000000000000..7543c9b7376ff7 --- /dev/null +++ b/test/fixtures/internal-modules/index.js @@ -0,0 +1 @@ +module.exports = require('internal/freelist'); diff --git a/test/fixtures/internal-modules/node_modules/internal/freelist.js b/test/fixtures/internal-modules/node_modules/internal/freelist.js new file mode 100644 index 00000000000000..ec01c2c1416672 --- /dev/null +++ b/test/fixtures/internal-modules/node_modules/internal/freelist.js @@ -0,0 +1 @@ +module.exports = true; diff --git a/test/parallel/test-internal-modules.js b/test/parallel/test-internal-modules.js new file mode 100644 index 00000000000000..df251fc60f5d04 --- /dev/null +++ b/test/parallel/test-internal-modules.js @@ -0,0 +1,8 @@ +var common = require('../common'); +var assert = require('assert'); + +assert.throws(function() { + require('internal/freelist'); +}); + +assert(require('../fixtures/internal-modules') === true); diff --git a/tools/js2c.py b/tools/js2c.py index bbbccb289ad67e..9e381d56c93a53 100755 --- a/tools/js2c.py +++ b/tools/js2c.py @@ -238,11 +238,11 @@ def ReadMacros(lines): NATIVE_DECLARATION = """\ - { "%(id)s", %(id)s_native, sizeof(%(id)s_native)-1 }, + { "%(id)s", %(escaped_id)s_native, sizeof(%(escaped_id)s_native)-1 }, """ SOURCE_DECLARATION = """\ - const char %(id)s_native[] = { %(data)s }; + const char %(escaped_id)s_native[] = { %(data)s }; """ @@ -293,16 +293,18 @@ def JS2C(source, target): lines = ExpandMacros(lines, macros) lines = CompressScript(lines, do_jsmin) data = ToCArray(s, lines) - id = os.path.basename(str(s)).split('.')[0] + id = '/'.join((str(s).split(os.sep)[1:])).split('.')[0] if delay: id = id[:-6] if delay: delay_ids.append((id, len(lines))) else: ids.append((id, len(lines))) - source_lines.append(SOURCE_DECLARATION % { 'id': id, 'data': data }) - source_lines_empty.append(SOURCE_DECLARATION % { 'id': id, 'data': 0 }) - native_lines.append(NATIVE_DECLARATION % { 'id': id }) - + + escaped_id = id.replace('/', '$') + source_lines.append(SOURCE_DECLARATION % { 'id': id, 'escaped_id': escaped_id, 'data': data }) + source_lines_empty.append(SOURCE_DECLARATION % { 'id': id, 'escaped_id': escaped_id, 'data': 0 }) + native_lines.append(NATIVE_DECLARATION % { 'id': id, 'escaped_id': escaped_id }) + # Build delay support functions get_index_cases = [ ] get_script_source_cases = [ ] From 57d0df50c6b62db292297d562f91fda18dee78de Mon Sep 17 00:00:00 2001 From: Vladimir Kurchatkin Date: Tue, 10 Mar 2015 15:34:23 +0300 Subject: [PATCH 2/4] node: env flag to expose internals --- src/node.js | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/node.js b/src/node.js index 826545180b60ba..41c77b4c2c8034 100644 --- a/src/node.js +++ b/src/node.js @@ -838,13 +838,22 @@ return NativeModule._source.hasOwnProperty(id); }; - NativeModule.nonInternalExists = function(id) { - return NativeModule.exists(id) && !NativeModule.isInternal(id); - }; + if (process.env['NODE_EXPOSE_INTERNALS']) { + NativeModule.nonInternalExists = NativeModule.exists; + + NativeModule.isInternal = function(id) { + return false; + }; + } else { + NativeModule.nonInternalExists = function(id) { + return NativeModule.exists(id) && !NativeModule.isInternal(id); + }; + + NativeModule.isInternal = function(id) { + return id.startsWith('internal/'); + }; + } - NativeModule.isInternal = function(id) { - return id.startsWith('internal/'); - }; NativeModule.getSource = function(id) { return NativeModule._source[id]; From b293da97eba9a722409ba79972ac4325b6bccd83 Mon Sep 17 00:00:00 2001 From: Vladimir Kurchatkin Date: Wed, 11 Mar 2015 01:32:15 +0300 Subject: [PATCH 3/4] use cli arg instead --- src/node.cc | 3 +++ src/node.js | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/node.cc b/src/node.cc index 92ace4fe3ec8b7..e82ea37c1abef8 100644 --- a/src/node.cc +++ b/src/node.cc @@ -3133,6 +3133,9 @@ static void ParseArgs(int* argc, } else if (strncmp(arg, "--icu-data-dir=", 15) == 0) { icu_data_dir = arg + 15; #endif + } else if (strcmp(arg, "--expose-internals") == 0 || + strcmp(arg, "--expose_internals") == 0) { + // consumed in js } else { // V8 option. Pass through as-is. new_v8_argv[new_v8_argc] = arg; diff --git a/src/node.js b/src/node.js index 41c77b4c2c8034..8ad727b7822ebf 100644 --- a/src/node.js +++ b/src/node.js @@ -838,7 +838,11 @@ return NativeModule._source.hasOwnProperty(id); }; - if (process.env['NODE_EXPOSE_INTERNALS']) { + const EXPOSE_INTERNALS = process.execArgv.some(function(arg) { + return arg.match(/^--expose[-_]internals$/); + }); + + if (EXPOSE_INTERNALS) { NativeModule.nonInternalExists = NativeModule.exists; NativeModule.isInternal = function(id) { From 461d77e3a6b9c7006c239c0963d4dcf7d842763e Mon Sep 17 00:00:00 2001 From: Vladimir Kurchatkin Date: Sat, 14 Mar 2015 21:32:03 +0300 Subject: [PATCH 4/4] fixes for bnoordhuis --- lib/internal/freelist.js | 2 -- node.gyp | 2 +- .../node_modules/internal/freelist.js | 2 +- test/parallel/test-internal-modules-expose.js | 6 ++++++ test/parallel/test-internal-modules.js | 2 +- tools/js2c.py | 19 +++++++++++++++---- 6 files changed, 24 insertions(+), 9 deletions(-) create mode 100644 test/parallel/test-internal-modules-expose.js diff --git a/lib/internal/freelist.js b/lib/internal/freelist.js index 78a581d6acb37b..4b17d154d4acef 100644 --- a/lib/internal/freelist.js +++ b/lib/internal/freelist.js @@ -10,14 +10,12 @@ exports.FreeList = function(name, max, constructor) { exports.FreeList.prototype.alloc = function() { - //debug("alloc " + this.name + " " + this.list.length); return this.list.length ? this.list.shift() : this.constructor.apply(this, arguments); }; exports.FreeList.prototype.free = function(obj) { - //debug("free " + this.name + " " + this.list.length); if (this.list.length < this.max) { this.list.push(obj); return true; diff --git a/node.gyp b/node.gyp index c38a4ae8935a68..dab7f6b28f1c56 100644 --- a/node.gyp +++ b/node.gyp @@ -70,7 +70,7 @@ 'lib/vm.js', 'lib/zlib.js', - 'lib/internal/freelist.js' + 'lib/internal/freelist.js', ], }, diff --git a/test/fixtures/internal-modules/node_modules/internal/freelist.js b/test/fixtures/internal-modules/node_modules/internal/freelist.js index ec01c2c1416672..888cae37af95c5 100644 --- a/test/fixtures/internal-modules/node_modules/internal/freelist.js +++ b/test/fixtures/internal-modules/node_modules/internal/freelist.js @@ -1 +1 @@ -module.exports = true; +module.exports = 42; diff --git a/test/parallel/test-internal-modules-expose.js b/test/parallel/test-internal-modules-expose.js new file mode 100644 index 00000000000000..4ea79dbbf73512 --- /dev/null +++ b/test/parallel/test-internal-modules-expose.js @@ -0,0 +1,6 @@ +// Flags: --expose_internals + +var common = require('../common'); +var assert = require('assert'); + +assert.equal(typeof require('internal/freelist').FreeList, 'function'); diff --git a/test/parallel/test-internal-modules.js b/test/parallel/test-internal-modules.js index df251fc60f5d04..ebba2500d568b2 100644 --- a/test/parallel/test-internal-modules.js +++ b/test/parallel/test-internal-modules.js @@ -5,4 +5,4 @@ assert.throws(function() { require('internal/freelist'); }); -assert(require('../fixtures/internal-modules') === true); +assert(require('../fixtures/internal-modules') === 42); diff --git a/tools/js2c.py b/tools/js2c.py index 9e381d56c93a53..cc2c3045d07369 100755 --- a/tools/js2c.py +++ b/tools/js2c.py @@ -293,7 +293,7 @@ def JS2C(source, target): lines = ExpandMacros(lines, macros) lines = CompressScript(lines, do_jsmin) data = ToCArray(s, lines) - id = '/'.join((str(s).split(os.sep)[1:])).split('.')[0] + id = '/'.join(re.split('/|\\\\', s)[1:]).split('.')[0] if delay: id = id[:-6] if delay: delay_ids.append((id, len(lines))) @@ -301,9 +301,20 @@ def JS2C(source, target): ids.append((id, len(lines))) escaped_id = id.replace('/', '$') - source_lines.append(SOURCE_DECLARATION % { 'id': id, 'escaped_id': escaped_id, 'data': data }) - source_lines_empty.append(SOURCE_DECLARATION % { 'id': id, 'escaped_id': escaped_id, 'data': 0 }) - native_lines.append(NATIVE_DECLARATION % { 'id': id, 'escaped_id': escaped_id }) + source_lines.append(SOURCE_DECLARATION % { + 'id': id, + 'escaped_id': escaped_id, + 'data': data + }) + source_lines_empty.append(SOURCE_DECLARATION % { + 'id': id, + 'escaped_id': escaped_id, + 'data': 0 + }) + native_lines.append(NATIVE_DECLARATION % { + 'id': id, + 'escaped_id': escaped_id + }) # Build delay support functions get_index_cases = [ ]