Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

mixwith

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mixwith - npm Package Compare versions

Comparing version 0.1.0 to 0.1.1

87

mixwith.js

@@ -24,42 +24,71 @@ 'use strict';

const mix = exports.mix = superClass => new MixinBuilder(superClass);
const _originalMixin = exports._originalMixin = Symbol('_originalMixin');
class MixinBuilder {
constructor(superclass) {
this.superclass = superclass;
const wrap = exports.wrap = (mixin, wrapper) => {
Object.setPrototypeOf(wrapper, mixin);
if (!mixin[_originalMixin]) {
mixin[_originalMixin] = mixin;
}
return wrapper;
};
with() {
let mixins = Array.prototype.slice.call(arguments);
return mixins.reduce((c, mixin) => {
let applicationRef = mixin[_cachedApplicationRef];
const Cached = exports.Cached = mixin => wrap(mixin, superclass => {
// Get or create a symbol used to look up a previous application of mixin
// to the class. This symbol is unique per mixin definition, so a class will have N
// applicationRefs if it has had N mixins applied to it. A mixin will have
// exactly one _cachedApplicationRef used to store its applications.
let applicationRef = mixin[_cachedApplicationRef];
if (!applicationRef) {
applicationRef = mixin[_cachedApplicationRef] = Symbol(mixin.name);
}
// Look up an existing application of `mixin` to `c`, return it if found.
if (superclass.hasOwnProperty(applicationRef)) {
return superclass[applicationRef];
}
// Apply the mixin
let application = mixin(superclass);
// Cache the mixin application on the superclass
superclass[applicationRef] = application;
return application;
});
if (!applicationRef) {
applicationRef = mixin[_cachedApplicationRef] = Symbol(mixin.name);
const HasInstance = exports.HasInstance = mixin => {
if (Symbol.hasInstance && !mixin.hasOwnProperty(Symbol.hasInstance)) {
Object.defineProperty(mixin, Symbol.hasInstance, {
value: function (o) {
const originalMixin = this[_originalMixin];
while (o != null) {
if (o.hasOwnProperty(_mixinRef) && o[_mixinRef] === originalMixin) {
return true;
}
o = Object.getPrototypeOf(o);
}
return false;
}
});
}
return mixin;
};
if (c.hasOwnProperty(applicationRef)) {
return c[applicationRef];
}
const BareMixin = exports.BareMixin = mixin => wrap(mixin, superclass => {
// Apply the mixin
let application = mixin(superclass);
let application = mixin(c);
application.prototype[_mixinRef] = mixin;
c[applicationRef] = application;
// Attach a reference from mixin applition to wrapped mixin for RTTI
// mixin[@@hasInstance] should use this.
application.prototype[_mixinRef] = mixin[_originalMixin];
return application;
});
if (Symbol.hasInstance && !mixin.hasOwnProperty(Symbol.hasInstance)) {
mixin[Symbol.hasInstance] = function (o) {
do {
if (o.hasOwnProperty(_mixinRef) && o[_mixinRef] === this) {
return true;
}
const Mixin = exports.Mixin = mixin => Cached(HasInstance(BareMixin(mixin)));
o = Object.getPrototypeOf(o);
} while (o !== Object);
const mix = exports.mix = superClass => new MixinBuilder(superClass);
return false;
};
}
class MixinBuilder {
constructor(superclass) {
this.superclass = superclass;
}
return application;
}, this.superclass);
with() {
return Array.from(arguments).reduce((c, m) => m(c), this.superclass);
}

@@ -66,0 +95,0 @@

{
"name": "mixwith",
"version": "0.1.0",
"version": "0.1.1",
"description": "A simple, powerful mixin applier for JavaScript classes",

@@ -5,0 +5,0 @@ "main": "mixwith.js",

@@ -7,3 +7,3 @@ # mixwith.js

`mixwith` differs from other mixin approaches because it does not copy properties object to another. Instead, `mixwith` works with "subclass factories" which create a new class that extends a superclass with the mixin - this is called a _mixin_ _application_.
`mixwith` differs from other mixin approaches because it does not copy properties from one object to another. Instead, `mixwith` works with "subclass factories" which create a new class that extends a superclass with the mixin - this is called a _mixin_ _application_.

@@ -10,0 +10,0 @@ Subclass factory style mixins take advantage of two awesome features of ES6 classes: _class_ _expressions_, and expressions in the `extends` clause of a class declaration.

@@ -5,62 +5,96 @@ 'use strict';

export const _mixinRef = Symbol('_mixinRef');
export const _originalMixin = Symbol('_originalMixin');
export const mix = (superClass) => new MixinBuilder(superClass);
/**
* Sets the prototype of mixin to wrapper so that properties set on mixin are
* inherited by the wrapper.
*
* This is needed in order to implement @@hasInstance as a decorator function.
*/
export const wrap = (mixin, wrapper) => {
Object.setPrototypeOf(wrapper, mixin);
if (!mixin[_originalMixin]) {
mixin[_originalMixin] = mixin;
}
return wrapper;
};
class MixinBuilder {
constructor(superclass) {
this.superclass = superclass;
/**
* Decorates mixin so that it caches its applications. When applied multiple
* times to the same superclass, mixin will only create one subclass and
* memoize it.
*/
export const Cached = (mixin) => wrap(mixin, (superclass) => {
// Get or create a symbol used to look up a previous application of mixin
// to the class. This symbol is unique per mixin definition, so a class will have N
// applicationRefs if it has had N mixins applied to it. A mixin will have
// exactly one _cachedApplicationRef used to store its applications.
let applicationRef = mixin[_cachedApplicationRef];
if (!applicationRef) {
applicationRef = mixin[_cachedApplicationRef] = Symbol(mixin.name);
}
// Look up an existing application of `mixin` to `c`, return it if found.
if (superclass.hasOwnProperty(applicationRef)) {
return superclass[applicationRef];
}
// Apply the mixin
let application = mixin(superclass);
// Cache the mixin application on the superclass
superclass[applicationRef] = application;
return application;
});
with() {
let mixins = Array.prototype.slice.call(arguments);
return mixins.reduce((c, mixin) => {
// Get or create a Symbol used to look up a previous application of mixin
// to the class. This symbol is unique per mixin, so a class will have N
// applicationRefs if it has had N mixins applied to it. A mixin will have
// exactly one _cachedApplicationRef use to store its applications.
let applicationRef = mixin[_cachedApplicationRef];
if (!applicationRef) {
applicationRef = mixin[_cachedApplicationRef] = Symbol(mixin.name);
/**
* Adds @@hasInstance (ES2015 instanceof support) to mixin.
* Note: @@hasInstance is not supported in any browsers yet.
*/
export const HasInstance = (mixin) => {
if (Symbol.hasInstance && !mixin.hasOwnProperty(Symbol.hasInstance)) {
Object.defineProperty(mixin, Symbol.hasInstance, {
value: function(o) {
const originalMixin = this[_originalMixin];
while (o != null) {
if (o.hasOwnProperty(_mixinRef) && o[_mixinRef] === originalMixin) {
return true;
}
o = Object.getPrototypeOf(o);
}
return false;
}
// Look up an existing application of `mixin` to `c`, return it if found.
if (c.hasOwnProperty(applicationRef)) {
return c[applicationRef];
}
});
}
return mixin;
};
// Apply the mixin
let application = mixin(c);
/**
* A basic mixin decorator that sets up a reference from mixin applications
* to the mixin defintion for use by other mixin decorators.
*/
export const BareMixin = (mixin) => wrap(mixin, (superclass) => {
// Apply the mixin
let application = mixin(superclass);
// Attach a reference from mixin applition to mixin for RTTI
// mixin[@@hasInstance] should use this
application.prototype[_mixinRef] = mixin;
// Attach a reference from mixin applition to wrapped mixin for RTTI
// mixin[@@hasInstance] should use this.
application.prototype[_mixinRef] = mixin[_originalMixin];
return application;
});
// Cache the mixin application on superclass c
c[applicationRef] = application;
/**
* Decorates a mixin function to add application caching and instanceof
* support.
*/
export const Mixin = (mixin) => Cached(HasInstance(BareMixin(mixin)));
// Patch in instanceof support to mixin
// not supported in any browsers yet?
if (Symbol.hasInstance && !mixin.hasOwnProperty(Symbol.hasInstance)) {
mixin[Symbol.hasInstance] = function(o) {
do {
if (o.hasOwnProperty(_mixinRef) && o[_mixinRef] === this) {
return true;
}
o = Object.getPrototypeOf(o);
} while (o !== Object)
return false;
}
}
export const mix = (superClass) => new MixinBuilder(superClass);
return application;
}, this.superclass);
class MixinBuilder {
constructor(superclass) {
this.superclass = superclass;
}
with() {
return Array.from(arguments).reduce((c, m) => m(c), this.superclass);
}
}
// function extend(subclass, superclass) {
// var prototype = Object.create(superclass.prototype);
// prototype.constructor = subclass;
// return prototype;
// }
'use strict';
import {mix, _mixinRef} from '../mixwith';
import {mix, _mixinRef, Mixin, _originalMixin} from '../mixwith';
import {assert} from 'chai';
let A = (superclass) => class A extends superclass {
// Enable the @@hasInstance patch in HasInstance
const originalHasInstance = Symbol.hasInstance;
Symbol.hasInstance = Symbol.hasInstance || Symbol('hasInstance');
let A = Mixin((superclass) => class A extends superclass {
foo() {

@@ -19,11 +23,11 @@ return ['A.foo'];

};
});
let B = (superclass) => class extends superclass {
let B = Mixin((superclass) => class extends superclass {
bar() {
console.log('B.bar');
}
};
});
let C = (superclass) => class extends superclass {
let C = Mixin((superclass) => class extends superclass {
constructor() {

@@ -37,3 +41,3 @@ console.log('C.constructor', arguments);

}
}
});

@@ -115,11 +119,12 @@ class D {

assert.isTrue(o.__proto__.__proto__.hasOwnProperty(_mixinRef));
assert.equal(o.__proto__.__proto__[_mixinRef], A);
assert.equal(o.__proto__.__proto__[_mixinRef], A[_originalMixin]);
});
if (Symbol.hasInstance) {
test('subclasses implement mixins', () => {
let o = new DwithA();
test('subclasses implement mixins', () => {
let o = new DwithA();
assert.isTrue(A[Symbol.hasInstance](o));
if (originalHasInstance) {
assert.instanceOf(o, A);
});
}
}
});

@@ -126,0 +131,0 @@ test('methods on mixin are present', () => {

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc