Skip to content

Commit

Permalink
util: add createClassWrapper to internal/util
Browse files Browse the repository at this point in the history
Utility function for wrapping an ES6 class with a constructor
function that does not require the new keyword

PR-URL: #11391
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
  • Loading branch information
jasnell committed Feb 17, 2017
1 parent 804bb22 commit 4151ab3
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 0 deletions.
20 changes: 20 additions & 0 deletions lib/internal/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,23 @@ exports.toLength = function toLength(argument) {
const len = toInteger(argument);
return len <= 0 ? 0 : Math.min(len, Number.MAX_SAFE_INTEGER);
};

// Useful for Wrapping an ES6 Class with a constructor Function that
// does not require the new keyword. For instance:
// class A { constructor(x) {this.x = x;}}
// const B = createClassWrapper(A);
// B() instanceof A // true
// B() instanceof B // true
exports.createClassWrapper = function createClassWrapper(type) {
const fn = function(...args) {
return Reflect.construct(type, args, new.target || type);
};
// Mask the wrapper function name and length values
Object.defineProperties(fn, {
name: {value: type.name},
length: {value: type.length}
});
Object.setPrototypeOf(fn, type);
fn.prototype = type.prototype;
return fn;
};
31 changes: 31 additions & 0 deletions test/parallel/test-internal-util-classwrapper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Flags: --expose-internals
'use strict';

require('../common');
const assert = require('assert');
const util = require('internal/util');

const createClassWrapper = util.createClassWrapper;

class A {
constructor(a, b, c) {
this.a = a;
this.b = b;
this.c = c;
}
}

const B = createClassWrapper(A);

assert.strictEqual(typeof B, 'function');
assert(B(1, 2, 3) instanceof B);
assert(B(1, 2, 3) instanceof A);
assert(new B(1, 2, 3) instanceof B);
assert(new B(1, 2, 3) instanceof A);
assert.strictEqual(B.name, A.name);
assert.strictEqual(B.length, A.length);

const b = new B(1, 2, 3);
assert.strictEqual(b.a, 1);
assert.strictEqual(b.b, 2);
assert.strictEqual(b.c, 3);

0 comments on commit 4151ab3

Please sign in to comment.