Skip to content
This repository has been archived by the owner on Nov 17, 2020. It is now read-only.

Add displayName property and DEBUG mode #35

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
"underscore": "^1.4.4"
},
"babelBoilerplateOptions": {
"entryFileName": "backbone-metal",
"entryFileName": "index",
"exportVarName": "Metal",
"mochaGlobals": [
"stub",
Expand Down
17 changes: 0 additions & 17 deletions src/backbone-metal.js

This file was deleted.

75 changes: 69 additions & 6 deletions src/class.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Metal from './metal';
import _ from 'underscore';
import Events from './events';

Expand Down Expand Up @@ -29,6 +30,23 @@ function _wrap(method, superMethod) {
*/
const CONTAINS_SUPER = (/xyz/.test(function() { xyz; })) ? /\b_super\b/ : /.*/; // eslint-disable-line

const defineProperty = Object.defineProperty || function() {};

const NON_ENUMERABLE = {
value: null,
enumerable: false
};

function _addDisplayName(target, value) {
NON_ENUMERABLE.value = value;
defineProperty(target, 'displayName', NON_ENUMERABLE);
NON_ENUMERABLE.value = null;
}

function _addSuperWrapperDisplayName(target, value) {
_addDisplayName(target, 'superWrapper(' + value + ')');
}

/**
* Assigns properties of source object to destination object, wrapping methods
* that call their super method.
Expand All @@ -38,24 +56,50 @@ const CONTAINS_SUPER = (/xyz/.test(function() { xyz; })) ? /\b_super\b/ : /.*/;
* @param {Object} dest - The destination object.
* @param {Object} source - The source object.
*/
function _wrapAll(dest, source) {
function _wrapAll(dest, source, classDisplayName, isOnPrototype) {
let keys = _.keys(source),
length = keys.length,
i, name, method, superMethod, hasSuper;
i, name, method, superMethod, hasSuper, methodIsFunction,
baseDisplayName, methodDisplayName;

// If a debug mode, add everything we need for adding displayName.
if (Metal.DEBUG) {
baseDisplayName = classDisplayName + (isOnPrototype ? '.prototype.' : '.');
}

for (i = 0; i < length; i++) {
name = keys[i];
method = source[name];
superMethod = dest[name];
methodIsFunction = _.isFunction(method);

// Test if new method calls `_super`
hasSuper = CONTAINS_SUPER.test(method);

// If debug mode, ensure displayNames
if (Metal.DEBUG) {
methodDisplayName = method.displayName;

// Add a displayName to any functions without one, whenever possible.
if (methodIsFunction && classDisplayName && !methodDisplayName) {
if (name === 'constructor') {
_addDisplayName(method, classDisplayName);
} else {
_addDisplayName(method, baseDisplayName + (method.name || name));
}
}
}

// Only wrap the new method if the original method was a function and the
// new method calls `_super`.
if (hasSuper && _.isFunction(method) && _.isFunction(superMethod)) {
if (hasSuper && methodIsFunction && _.isFunction(superMethod)) {
dest[name] = _wrap(method, superMethod);

// If in debug mode wrap displayName in superWrapper()
if (Metal.DEBUG) {
_addSuperWrapperDisplayName(dest[name], methodDisplayName);
}

// Otherwise just add the new method or property to the object.
} else {
dest[name] = method;
Expand All @@ -82,7 +126,7 @@ function _wrapAll(dest, source) {
* @memberOf Metal
* @memberOf Backbone
*/
const Class = function Class() {
const Class = Metal.Class = function Class() {
this.cid = _.uniqueId(this.cidPrefix);
this.initialize(...arguments);
};
Expand Down Expand Up @@ -144,6 +188,12 @@ _.extend(Class, {
extend(protoProps, staticProps) {
let Parent = this;
let Child;
let displayName;

// If debug mode, get displayName from protoProps.
if (Metal.DEBUG) {
displayName = protoProps && protoProps.displayName || '';
}

// The constructor function for the new subclass is either defined by you
// (the "constructor" property in your `extend` definition), or defaulted
Expand All @@ -152,14 +202,23 @@ _.extend(Class, {
Child = function() { Parent.apply(this, arguments); };
} else if (CONTAINS_SUPER.test(protoProps.constructor)) {
Child = _wrap(protoProps.constructor, Parent.prototype.constructor);

// If debug mode, add a superWrapper to the displayName.
if (Metal.DEBUG) {
_addSuperWrapperDisplayName(Child, displayName);
}
} else {
Child = protoProps.constructor;
}

// Add static properties to the constructor function, if supplied.
_.extend(Child, Parent);
if (staticProps) {
_wrapAll(Child, staticProps);
if (Metal.DEBUG) {
_wrapAll(Child, staticProps, displayName, false);
} else {
_wrapAll(Child, staticProps);
}
}

// Set the prototype chain to inherit from `parent`, without calling
Expand All @@ -174,7 +233,11 @@ _.extend(Class, {
// Add prototype properties (instance properties) to the subclass,
// if supplied.
if (protoProps) {
_wrapAll(Child.prototype, protoProps);
if (Metal.DEBUG) {
_wrapAll(Child.prototype, protoProps, displayName, true);
} else {
_wrapAll(Child.prototype, protoProps);
}
}

// Set a convenience property in case the parent class is needed later.
Expand Down
3 changes: 2 additions & 1 deletion src/deprecate.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Metal from './metal';
import _ from 'underscore';

/**
Expand All @@ -10,7 +11,7 @@ import _ from 'underscore';
* @param {String} message.next - The replacement for the deprecated item.
* @param {Boolean} [test] - An optional boolean. If falsy, the deprecation will be displayed.
*/
const deprecate = function deprecate(message, test) {
const deprecate = Metal.deprecate = function deprecate(message, test) {

// Returns if test is provided and is falsy.
if (test !== undefined && test) {
Expand Down
3 changes: 2 additions & 1 deletion src/error.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Metal from './metal';
import _ from 'underscore';
import Class from './class';

Expand All @@ -23,7 +24,7 @@ const ERROR_PROPS = [
* @extends Error
* @uses Metal.Class
*/
const Err = Class.extend.call(Error, {
const Err = Metal.Error = Class.extend.call(Error, {

/**
* @public
Expand Down
3 changes: 2 additions & 1 deletion src/events.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Metal from './metal';
import Backbone from 'backbone';
import Mixin from './mixin';

Expand All @@ -10,6 +11,6 @@ import Mixin from './mixin';
* @extends Metal.Mixin
* @mixes Backbone.Events
*/
const Events = new Mixin(Backbone.Events);
const Events = Metal.Events = new Mixin(Backbone.Events);

export default Events;
8 changes: 8 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Metal from './metal';
import './class';
import './mixin';
import './error';
import './deprecate';
import './events';

export default Metal;
10 changes: 10 additions & 0 deletions src/metal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Backbone from 'backbone';

/**
* @module Metal
*/
const Metal = Backbone.Metal = {
DEBUG: false
};

export default Metal;
3 changes: 2 additions & 1 deletion src/mixin.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Metal from './metal';
import _ from 'underscore';

/**
Expand All @@ -9,7 +10,7 @@ import _ from 'underscore';
* @memberOf Backbone
* @param {Object} protoProps - The properties to be added to the prototype.
*/
const Mixin = function Mixin(protoProps) {
const Mixin = Metal.Mixin = function Mixin(protoProps) {
// Add prototype properties (instance properties) to the class, if supplied.
_.extend(this, protoProps);
};
Expand Down
2 changes: 1 addition & 1 deletion test/unit/class.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Metal from '../../src/backbone-metal';
import Metal from '../../src/index';
import _ from 'underscore';

describe('Class', function() {
Expand Down
2 changes: 1 addition & 1 deletion test/unit/deprecate.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Metal from '../../src/backbone-metal';
import Metal from '../../src/index';

describe('deprecate', function() {
beforeEach(function() {
Expand Down
2 changes: 1 addition & 1 deletion test/unit/error.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Metal from '../../src/backbone-metal';
import Metal from '../../src/index';

describe('Error', function() {
it('should be subclass of native Error', function() {
Expand Down
2 changes: 1 addition & 1 deletion test/unit/events.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Metal from '../../src/backbone-metal';
import Metal from '../../src/index';
import Backbone from 'backbone';

describe('Events', function() {
Expand Down
2 changes: 1 addition & 1 deletion test/unit/mixin.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Metal from '../../src/backbone-metal';
import Metal from '../../src/index';
import _ from 'underscore';

describe('Mixin', function() {
Expand Down
2 changes: 1 addition & 1 deletion test/unit/support.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import ImportedMetal from '../../src/backbone-metal';
import ImportedMetal from '../../src/index';

let Metal = ImportedMetal;

Expand Down