nemo-observable-util
Advanced tools
Comparing version 4.5.3 to 5.0.0
@@ -75,23 +75,20 @@ 'use strict'; | ||
var uuid = 0; | ||
function getUUID() { | ||
return uuid++; | ||
} | ||
var TransactionManager = function TransactionManager() { | ||
this.runners = new Map(); | ||
this.duringTransaction = false; | ||
var StackManager = function StackManager(onFlush) { | ||
this.uuid = 0; | ||
this.stacks = []; | ||
this.onFlush = onFlush; | ||
}; | ||
TransactionManager.prototype.add = function add (reaction, operation) { | ||
// use last operation as source | ||
this.runners.set(reaction, operation); | ||
var prototypeAccessors = { duringStack: {} }; | ||
StackManager.prototype.getUUID = function getUUID () { | ||
return this.uuid++; | ||
}; | ||
TransactionManager.prototype.start = function start (target) { | ||
this.duringTransaction = true; | ||
StackManager.prototype.start = function start (target) { | ||
this.stacks.push(target); | ||
}; | ||
TransactionManager.prototype.end = function end (target) { | ||
StackManager.prototype.end = function end (target) { | ||
var lastStack = this.stacks[this.stacks.length - 1]; | ||
@@ -102,26 +99,73 @@ if (lastStack !== target) { | ||
this.stacks.pop(); | ||
if (this.stacks.length === 0) { | ||
this.flush(); | ||
if (!this.duringStack) { | ||
this.onFlush && this.onFlush(); | ||
} | ||
}; | ||
TransactionManager.prototype.flush = function flush () { | ||
// copy incase being modified during exec reaction | ||
var todoCopy = this.runners; | ||
prototypeAccessors.duringStack.get = function () { | ||
return this.stacks.length > 0; | ||
}; | ||
Object.defineProperties( StackManager.prototype, prototypeAccessors ); | ||
function decoratorFactory(wrapperFn) { | ||
return function (target, propertyKey, descriptor) { | ||
if (!propertyKey) { | ||
// 1. use as function wrapper | ||
return wrapperFn(target); | ||
} | ||
// 2. use as a decorator | ||
if (propertyKey in target) { | ||
// 2.1 use as class method decorator | ||
descriptor.value = wrapperFn(descriptor.value); | ||
return; | ||
} | ||
// 2.2 use as class attribute decorator | ||
var internalPropertyKey = Symbol(propertyKey); | ||
Object.defineProperty(target, propertyKey, { | ||
set: function (value) { | ||
if (!(internalPropertyKey in this)) { | ||
// must be attribute init setter,wrap it to a action | ||
value = wrapperFn(value); | ||
} | ||
this[internalPropertyKey] = value; | ||
}, | ||
get: function () { | ||
return this[internalPropertyKey]; | ||
} | ||
}); | ||
}; | ||
} | ||
var RunnerManager = function RunnerManager() { | ||
var this$1 = this; | ||
this.flush = function () { | ||
// copy incase being modified during exec reaction | ||
var todoCopy = this$1.runners; | ||
this$1.runners = new Map(); | ||
for (var [reaction, operation] of todoCopy.entries()) { | ||
queueReaction(reaction, operation); | ||
} | ||
}; | ||
this.runners = new Map(); | ||
this.duringTransaction = false; | ||
}; | ||
for (var [reaction, operation] of todoCopy.entries()) { | ||
queueReaction(reaction, operation); | ||
} | ||
RunnerManager.prototype.add = function add (reaction, operation) { | ||
// use last operation as source | ||
this.runners.set(reaction, operation); | ||
}; | ||
var transaction = new TransactionManager(); | ||
var runnerManager = new RunnerManager(); | ||
var transactionManager = new StackManager(runnerManager.flush); | ||
function startTransaction(target) { | ||
transaction.start(target); | ||
transactionManager.start(target); | ||
} | ||
function endTransaction(target) { | ||
transaction.end(target); | ||
transactionManager.end(target); | ||
} | ||
@@ -135,30 +179,4 @@ | ||
*/ | ||
function withTransaction(target, propertyKey, descriptor) { | ||
if (!propertyKey) { | ||
// 1. use as function wrapper | ||
return createTransaction(target); | ||
} | ||
// 2. use as a decorator | ||
if (propertyKey in target) { | ||
// 2.1 use as class method decorator | ||
descriptor.value = createTransaction(descriptor.value); | ||
return; | ||
} | ||
var withTransaction = decoratorFactory(createTransaction); | ||
// 2.2 use as class attribute decorator | ||
var internalPropertyKey = Symbol(propertyKey); | ||
Object.defineProperty(target, propertyKey, { | ||
set: function (value) { | ||
if (!(internalPropertyKey in this)) { | ||
// must be attribute init setter,wrap it to a action | ||
value = createTransaction(value); | ||
} | ||
this[internalPropertyKey] = value; | ||
}, | ||
get: function () { | ||
return this[internalPropertyKey]; | ||
} | ||
}); | ||
} | ||
function createTransaction(originalFunc) { | ||
@@ -168,3 +186,3 @@ if (typeof originalFunc !== 'function') { | ||
} | ||
var identity = getUUID(); | ||
var identity = transactionManager.getUUID(); | ||
return function () { | ||
@@ -174,7 +192,7 @@ var args = [], len = arguments.length; | ||
transaction.start(identity); | ||
transactionManager.start(identity); | ||
try { | ||
return originalFunc.apply(this, args); | ||
} finally { | ||
transaction.end(identity); | ||
transactionManager.end(identity); | ||
} | ||
@@ -226,4 +244,4 @@ }; | ||
getReactionsForOperation(operation).forEach(function (reaction) { | ||
if (transaction.duringTransaction) { | ||
transaction.add(reaction, operation); | ||
if (transactionManager.duringStack) { | ||
runnerManager.add(reaction, operation); | ||
} else { | ||
@@ -327,48 +345,7 @@ queueReaction(reaction, operation); | ||
var actionCount = 0; | ||
var action = decoratorFactory(createAction); | ||
var actionManager = new StackManager(); | ||
function action(target, propertyKey, descriptor) { | ||
if (!propertyKey) { | ||
// 1. use as function wrapper | ||
return createAction(target); | ||
} | ||
// 2. use as a decorator | ||
if (propertyKey in target) { | ||
// 2.1 use as class method decorator | ||
descriptor.value = createAction(descriptor.value); | ||
return; | ||
} | ||
// 2.2 use as class attribute decorator | ||
var internalPropertyKey = Symbol(propertyKey); | ||
Object.defineProperty(target, propertyKey, { | ||
set: function (value) { | ||
if (!(internalPropertyKey in this)) { | ||
// must be attribute init setter,wrap it to a action | ||
value = createAction(value); | ||
} | ||
this[internalPropertyKey] = value; | ||
}, | ||
get: function () { | ||
return this[internalPropertyKey]; | ||
} | ||
}); | ||
} | ||
function duringAction() { | ||
return actionCount > 0; | ||
} | ||
function startAction() { | ||
actionCount = actionCount + 1; | ||
} | ||
function endAction() { | ||
actionCount = actionCount - 1; | ||
if (actionCount < 0) { | ||
throw new Error('[nemo-observable-util] call endAction but no action is running!'); | ||
} | ||
} | ||
function canWrite() { | ||
return !InternalConfig.onlyAllowChangeInAction || duringAction(); | ||
return !InternalConfig.onlyAllowChangeInAction || actionManager.duringStack; | ||
} | ||
@@ -383,4 +360,8 @@ | ||
function createAction(fn) { | ||
var transactionFn = createTransaction(fn); | ||
function createAction(originalFunc) { | ||
if (typeof originalFunc !== 'function') { | ||
throw new Error('action should must wrap on Function: ' + typeof originalFunc); | ||
} | ||
var transactionFn = createTransaction(originalFunc); | ||
var identity = actionManager.getUUID(); | ||
return function () { | ||
@@ -390,7 +371,7 @@ var args = [], len = arguments.length; | ||
startAction(); | ||
actionManager.start(identity); | ||
try { | ||
return transactionFn.apply(this, args); | ||
} finally { | ||
endAction(); | ||
actionManager.end(identity); | ||
} | ||
@@ -713,2 +694,5 @@ }; | ||
exports.withTransaction = withTransaction; | ||
exports.transactionManager = transactionManager; | ||
exports.action = action; | ||
exports.actionManager = actionManager; | ||
exports.decoratorFactory = decoratorFactory; |
@@ -67,20 +67,15 @@ 'use strict'; | ||
let uuid = 0; | ||
function getUUID() { | ||
return uuid++; | ||
} | ||
class TransactionManager { | ||
constructor() { | ||
this.runners = new Map(); | ||
this.duringTransaction = false; | ||
class StackManager { | ||
constructor(onFlush) { | ||
this.uuid = 0; | ||
this.stacks = []; | ||
this.onFlush = onFlush; | ||
} | ||
add(reaction, operation) { | ||
// use last operation as source | ||
this.runners.set(reaction, operation); | ||
getUUID() { | ||
return this.uuid++; | ||
} | ||
start(target) { | ||
this.duringTransaction = true; | ||
this.stacks.push(target); | ||
@@ -95,27 +90,73 @@ } | ||
this.stacks.pop(); | ||
if (this.stacks.length === 0) { | ||
this.flush(); | ||
if (!this.duringStack) { | ||
this.onFlush && this.onFlush(); | ||
} | ||
} | ||
flush() { | ||
// copy incase being modified during exec reaction | ||
const todoCopy = this.runners; | ||
this.runners = new Map(); | ||
this.duringTransaction = false; | ||
get duringStack() { | ||
return this.stacks.length > 0; | ||
} | ||
} | ||
for (const [reaction, operation] of todoCopy.entries()) { | ||
queueReaction(reaction, operation); | ||
function decoratorFactory(wrapperFn) { | ||
return function (target, propertyKey, descriptor) { | ||
if (!propertyKey) { | ||
// 1. use as function wrapper | ||
return wrapperFn(target); | ||
} | ||
// 2. use as a decorator | ||
if (propertyKey in target) { | ||
// 2.1 use as class method decorator | ||
descriptor.value = wrapperFn(descriptor.value); | ||
return; | ||
} | ||
// 2.2 use as class attribute decorator | ||
const internalPropertyKey = Symbol(propertyKey); | ||
Object.defineProperty(target, propertyKey, { | ||
set: function (value) { | ||
if (!(internalPropertyKey in this)) { | ||
// must be attribute init setter,wrap it to a action | ||
value = wrapperFn(value); | ||
} | ||
this[internalPropertyKey] = value; | ||
}, | ||
get: function () { | ||
return this[internalPropertyKey]; | ||
} | ||
}); | ||
}; | ||
} | ||
class RunnerManager { | ||
constructor() { | ||
this.flush = () => { | ||
// copy incase being modified during exec reaction | ||
const todoCopy = this.runners; | ||
this.runners = new Map(); | ||
for (const [reaction, operation] of todoCopy.entries()) { | ||
queueReaction(reaction, operation); | ||
} | ||
}; | ||
this.runners = new Map(); | ||
} | ||
add(reaction, operation) { | ||
// use last operation as source | ||
this.runners.set(reaction, operation); | ||
} | ||
} | ||
const transaction = new TransactionManager(); | ||
const runnerManager = new RunnerManager(); | ||
const transactionManager = new StackManager(runnerManager.flush); | ||
function startTransaction(target) { | ||
transaction.start(target); | ||
transactionManager.start(target); | ||
} | ||
function endTransaction(target) { | ||
transaction.end(target); | ||
transactionManager.end(target); | ||
} | ||
@@ -129,30 +170,4 @@ | ||
*/ | ||
function withTransaction(target, propertyKey, descriptor) { | ||
if (!propertyKey) { | ||
// 1. use as function wrapper | ||
return createTransaction(target); | ||
} | ||
// 2. use as a decorator | ||
if (propertyKey in target) { | ||
// 2.1 use as class method decorator | ||
descriptor.value = createTransaction(descriptor.value); | ||
return; | ||
} | ||
const withTransaction = decoratorFactory(createTransaction); | ||
// 2.2 use as class attribute decorator | ||
const internalPropertyKey = Symbol(propertyKey); | ||
Object.defineProperty(target, propertyKey, { | ||
set: function (value) { | ||
if (!(internalPropertyKey in this)) { | ||
// must be attribute init setter,wrap it to a action | ||
value = createTransaction(value); | ||
} | ||
this[internalPropertyKey] = value; | ||
}, | ||
get: function () { | ||
return this[internalPropertyKey]; | ||
} | ||
}); | ||
} | ||
function createTransaction(originalFunc) { | ||
@@ -162,9 +177,9 @@ if (typeof originalFunc !== 'function') { | ||
} | ||
const identity = getUUID(); | ||
const identity = transactionManager.getUUID(); | ||
return function (...args) { | ||
transaction.start(identity); | ||
transactionManager.start(identity); | ||
try { | ||
return originalFunc.apply(this, args); | ||
} finally { | ||
transaction.end(identity); | ||
transactionManager.end(identity); | ||
} | ||
@@ -216,4 +231,4 @@ }; | ||
getReactionsForOperation(operation).forEach(reaction => { | ||
if (transaction.duringTransaction) { | ||
transaction.add(reaction, operation); | ||
if (transactionManager.duringStack) { | ||
runnerManager.add(reaction, operation); | ||
} else { | ||
@@ -308,48 +323,7 @@ queueReaction(reaction, operation); | ||
let actionCount = 0; | ||
const action = decoratorFactory(createAction); | ||
const actionManager = new StackManager(); | ||
function action(target, propertyKey, descriptor) { | ||
if (!propertyKey) { | ||
// 1. use as function wrapper | ||
return createAction(target); | ||
} | ||
// 2. use as a decorator | ||
if (propertyKey in target) { | ||
// 2.1 use as class method decorator | ||
descriptor.value = createAction(descriptor.value); | ||
return; | ||
} | ||
// 2.2 use as class attribute decorator | ||
const internalPropertyKey = Symbol(propertyKey); | ||
Object.defineProperty(target, propertyKey, { | ||
set: function (value) { | ||
if (!(internalPropertyKey in this)) { | ||
// must be attribute init setter,wrap it to a action | ||
value = createAction(value); | ||
} | ||
this[internalPropertyKey] = value; | ||
}, | ||
get: function () { | ||
return this[internalPropertyKey]; | ||
} | ||
}); | ||
} | ||
function duringAction() { | ||
return actionCount > 0; | ||
} | ||
function startAction() { | ||
actionCount = actionCount + 1; | ||
} | ||
function endAction() { | ||
actionCount = actionCount - 1; | ||
if (actionCount < 0) { | ||
throw new Error('[nemo-observable-util] call endAction but no action is running!'); | ||
} | ||
} | ||
function canWrite() { | ||
return !InternalConfig.onlyAllowChangeInAction || duringAction(); | ||
return !InternalConfig.onlyAllowChangeInAction || actionManager.duringStack; | ||
} | ||
@@ -364,10 +338,14 @@ | ||
function createAction(fn) { | ||
const transactionFn = createTransaction(fn); | ||
function createAction(originalFunc) { | ||
if (typeof originalFunc !== 'function') { | ||
throw new Error('action should must wrap on Function: ' + typeof originalFunc); | ||
} | ||
const transactionFn = createTransaction(originalFunc); | ||
const identity = actionManager.getUUID(); | ||
return function (...args) { | ||
startAction(); | ||
actionManager.start(identity); | ||
try { | ||
return transactionFn.apply(this, args); | ||
} finally { | ||
endAction(); | ||
actionManager.end(identity); | ||
} | ||
@@ -675,2 +653,5 @@ }; | ||
exports.withTransaction = withTransaction; | ||
exports.transactionManager = transactionManager; | ||
exports.action = action; | ||
exports.actionManager = actionManager; | ||
exports.decoratorFactory = decoratorFactory; |
@@ -71,23 +71,20 @@ var connectionStore = new WeakMap(); | ||
var uuid = 0; | ||
function getUUID() { | ||
return uuid++; | ||
} | ||
var TransactionManager = function TransactionManager() { | ||
this.runners = new Map(); | ||
this.duringTransaction = false; | ||
var StackManager = function StackManager(onFlush) { | ||
this.uuid = 0; | ||
this.stacks = []; | ||
this.onFlush = onFlush; | ||
}; | ||
TransactionManager.prototype.add = function add (reaction, operation) { | ||
// use last operation as source | ||
this.runners.set(reaction, operation); | ||
var prototypeAccessors = { duringStack: {} }; | ||
StackManager.prototype.getUUID = function getUUID () { | ||
return this.uuid++; | ||
}; | ||
TransactionManager.prototype.start = function start (target) { | ||
this.duringTransaction = true; | ||
StackManager.prototype.start = function start (target) { | ||
this.stacks.push(target); | ||
}; | ||
TransactionManager.prototype.end = function end (target) { | ||
StackManager.prototype.end = function end (target) { | ||
var lastStack = this.stacks[this.stacks.length - 1]; | ||
@@ -98,26 +95,73 @@ if (lastStack !== target) { | ||
this.stacks.pop(); | ||
if (this.stacks.length === 0) { | ||
this.flush(); | ||
if (!this.duringStack) { | ||
this.onFlush && this.onFlush(); | ||
} | ||
}; | ||
TransactionManager.prototype.flush = function flush () { | ||
// copy incase being modified during exec reaction | ||
var todoCopy = this.runners; | ||
prototypeAccessors.duringStack.get = function () { | ||
return this.stacks.length > 0; | ||
}; | ||
Object.defineProperties( StackManager.prototype, prototypeAccessors ); | ||
function decoratorFactory(wrapperFn) { | ||
return function (target, propertyKey, descriptor) { | ||
if (!propertyKey) { | ||
// 1. use as function wrapper | ||
return wrapperFn(target); | ||
} | ||
// 2. use as a decorator | ||
if (propertyKey in target) { | ||
// 2.1 use as class method decorator | ||
descriptor.value = wrapperFn(descriptor.value); | ||
return; | ||
} | ||
// 2.2 use as class attribute decorator | ||
var internalPropertyKey = Symbol(propertyKey); | ||
Object.defineProperty(target, propertyKey, { | ||
set: function (value) { | ||
if (!(internalPropertyKey in this)) { | ||
// must be attribute init setter,wrap it to a action | ||
value = wrapperFn(value); | ||
} | ||
this[internalPropertyKey] = value; | ||
}, | ||
get: function () { | ||
return this[internalPropertyKey]; | ||
} | ||
}); | ||
}; | ||
} | ||
var RunnerManager = function RunnerManager() { | ||
var this$1 = this; | ||
this.flush = function () { | ||
// copy incase being modified during exec reaction | ||
var todoCopy = this$1.runners; | ||
this$1.runners = new Map(); | ||
for (var [reaction, operation] of todoCopy.entries()) { | ||
queueReaction(reaction, operation); | ||
} | ||
}; | ||
this.runners = new Map(); | ||
this.duringTransaction = false; | ||
}; | ||
for (var [reaction, operation] of todoCopy.entries()) { | ||
queueReaction(reaction, operation); | ||
} | ||
RunnerManager.prototype.add = function add (reaction, operation) { | ||
// use last operation as source | ||
this.runners.set(reaction, operation); | ||
}; | ||
var transaction = new TransactionManager(); | ||
var runnerManager = new RunnerManager(); | ||
var transactionManager = new StackManager(runnerManager.flush); | ||
function startTransaction(target) { | ||
transaction.start(target); | ||
transactionManager.start(target); | ||
} | ||
function endTransaction(target) { | ||
transaction.end(target); | ||
transactionManager.end(target); | ||
} | ||
@@ -131,30 +175,4 @@ | ||
*/ | ||
function withTransaction(target, propertyKey, descriptor) { | ||
if (!propertyKey) { | ||
// 1. use as function wrapper | ||
return createTransaction(target); | ||
} | ||
// 2. use as a decorator | ||
if (propertyKey in target) { | ||
// 2.1 use as class method decorator | ||
descriptor.value = createTransaction(descriptor.value); | ||
return; | ||
} | ||
var withTransaction = decoratorFactory(createTransaction); | ||
// 2.2 use as class attribute decorator | ||
var internalPropertyKey = Symbol(propertyKey); | ||
Object.defineProperty(target, propertyKey, { | ||
set: function (value) { | ||
if (!(internalPropertyKey in this)) { | ||
// must be attribute init setter,wrap it to a action | ||
value = createTransaction(value); | ||
} | ||
this[internalPropertyKey] = value; | ||
}, | ||
get: function () { | ||
return this[internalPropertyKey]; | ||
} | ||
}); | ||
} | ||
function createTransaction(originalFunc) { | ||
@@ -164,3 +182,3 @@ if (typeof originalFunc !== 'function') { | ||
} | ||
var identity = getUUID(); | ||
var identity = transactionManager.getUUID(); | ||
return function () { | ||
@@ -170,7 +188,7 @@ var args = [], len = arguments.length; | ||
transaction.start(identity); | ||
transactionManager.start(identity); | ||
try { | ||
return originalFunc.apply(this, args); | ||
} finally { | ||
transaction.end(identity); | ||
transactionManager.end(identity); | ||
} | ||
@@ -222,4 +240,4 @@ }; | ||
getReactionsForOperation(operation).forEach(function (reaction) { | ||
if (transaction.duringTransaction) { | ||
transaction.add(reaction, operation); | ||
if (transactionManager.duringStack) { | ||
runnerManager.add(reaction, operation); | ||
} else { | ||
@@ -323,48 +341,7 @@ queueReaction(reaction, operation); | ||
var actionCount = 0; | ||
var action = decoratorFactory(createAction); | ||
var actionManager = new StackManager(); | ||
function action(target, propertyKey, descriptor) { | ||
if (!propertyKey) { | ||
// 1. use as function wrapper | ||
return createAction(target); | ||
} | ||
// 2. use as a decorator | ||
if (propertyKey in target) { | ||
// 2.1 use as class method decorator | ||
descriptor.value = createAction(descriptor.value); | ||
return; | ||
} | ||
// 2.2 use as class attribute decorator | ||
var internalPropertyKey = Symbol(propertyKey); | ||
Object.defineProperty(target, propertyKey, { | ||
set: function (value) { | ||
if (!(internalPropertyKey in this)) { | ||
// must be attribute init setter,wrap it to a action | ||
value = createAction(value); | ||
} | ||
this[internalPropertyKey] = value; | ||
}, | ||
get: function () { | ||
return this[internalPropertyKey]; | ||
} | ||
}); | ||
} | ||
function duringAction() { | ||
return actionCount > 0; | ||
} | ||
function startAction() { | ||
actionCount = actionCount + 1; | ||
} | ||
function endAction() { | ||
actionCount = actionCount - 1; | ||
if (actionCount < 0) { | ||
throw new Error('[nemo-observable-util] call endAction but no action is running!'); | ||
} | ||
} | ||
function canWrite() { | ||
return !InternalConfig.onlyAllowChangeInAction || duringAction(); | ||
return !InternalConfig.onlyAllowChangeInAction || actionManager.duringStack; | ||
} | ||
@@ -379,4 +356,8 @@ | ||
function createAction(fn) { | ||
var transactionFn = createTransaction(fn); | ||
function createAction(originalFunc) { | ||
if (typeof originalFunc !== 'function') { | ||
throw new Error('action should must wrap on Function: ' + typeof originalFunc); | ||
} | ||
var transactionFn = createTransaction(originalFunc); | ||
var identity = actionManager.getUUID(); | ||
return function () { | ||
@@ -386,7 +367,7 @@ var args = [], len = arguments.length; | ||
startAction(); | ||
actionManager.start(identity); | ||
try { | ||
return transactionFn.apply(this, args); | ||
} finally { | ||
endAction(); | ||
actionManager.end(identity); | ||
} | ||
@@ -700,2 +681,2 @@ }; | ||
export { observe, unobserve, observable, isObservable, raw, config, startTransaction, endTransaction, withTransaction, action }; | ||
export { observe, unobserve, observable, isObservable, raw, config, startTransaction, endTransaction, withTransaction, transactionManager, action, actionManager, decoratorFactory }; |
@@ -63,20 +63,15 @@ const connectionStore = new WeakMap(); | ||
let uuid = 0; | ||
function getUUID() { | ||
return uuid++; | ||
} | ||
class TransactionManager { | ||
constructor() { | ||
this.runners = new Map(); | ||
this.duringTransaction = false; | ||
class StackManager { | ||
constructor(onFlush) { | ||
this.uuid = 0; | ||
this.stacks = []; | ||
this.onFlush = onFlush; | ||
} | ||
add(reaction, operation) { | ||
// use last operation as source | ||
this.runners.set(reaction, operation); | ||
getUUID() { | ||
return this.uuid++; | ||
} | ||
start(target) { | ||
this.duringTransaction = true; | ||
this.stacks.push(target); | ||
@@ -91,27 +86,73 @@ } | ||
this.stacks.pop(); | ||
if (this.stacks.length === 0) { | ||
this.flush(); | ||
if (!this.duringStack) { | ||
this.onFlush && this.onFlush(); | ||
} | ||
} | ||
flush() { | ||
// copy incase being modified during exec reaction | ||
const todoCopy = this.runners; | ||
this.runners = new Map(); | ||
this.duringTransaction = false; | ||
get duringStack() { | ||
return this.stacks.length > 0; | ||
} | ||
} | ||
for (const [reaction, operation] of todoCopy.entries()) { | ||
queueReaction(reaction, operation); | ||
function decoratorFactory(wrapperFn) { | ||
return function (target, propertyKey, descriptor) { | ||
if (!propertyKey) { | ||
// 1. use as function wrapper | ||
return wrapperFn(target); | ||
} | ||
// 2. use as a decorator | ||
if (propertyKey in target) { | ||
// 2.1 use as class method decorator | ||
descriptor.value = wrapperFn(descriptor.value); | ||
return; | ||
} | ||
// 2.2 use as class attribute decorator | ||
const internalPropertyKey = Symbol(propertyKey); | ||
Object.defineProperty(target, propertyKey, { | ||
set: function (value) { | ||
if (!(internalPropertyKey in this)) { | ||
// must be attribute init setter,wrap it to a action | ||
value = wrapperFn(value); | ||
} | ||
this[internalPropertyKey] = value; | ||
}, | ||
get: function () { | ||
return this[internalPropertyKey]; | ||
} | ||
}); | ||
}; | ||
} | ||
class RunnerManager { | ||
constructor() { | ||
this.flush = () => { | ||
// copy incase being modified during exec reaction | ||
const todoCopy = this.runners; | ||
this.runners = new Map(); | ||
for (const [reaction, operation] of todoCopy.entries()) { | ||
queueReaction(reaction, operation); | ||
} | ||
}; | ||
this.runners = new Map(); | ||
} | ||
add(reaction, operation) { | ||
// use last operation as source | ||
this.runners.set(reaction, operation); | ||
} | ||
} | ||
const transaction = new TransactionManager(); | ||
const runnerManager = new RunnerManager(); | ||
const transactionManager = new StackManager(runnerManager.flush); | ||
function startTransaction(target) { | ||
transaction.start(target); | ||
transactionManager.start(target); | ||
} | ||
function endTransaction(target) { | ||
transaction.end(target); | ||
transactionManager.end(target); | ||
} | ||
@@ -125,30 +166,4 @@ | ||
*/ | ||
function withTransaction(target, propertyKey, descriptor) { | ||
if (!propertyKey) { | ||
// 1. use as function wrapper | ||
return createTransaction(target); | ||
} | ||
// 2. use as a decorator | ||
if (propertyKey in target) { | ||
// 2.1 use as class method decorator | ||
descriptor.value = createTransaction(descriptor.value); | ||
return; | ||
} | ||
const withTransaction = decoratorFactory(createTransaction); | ||
// 2.2 use as class attribute decorator | ||
const internalPropertyKey = Symbol(propertyKey); | ||
Object.defineProperty(target, propertyKey, { | ||
set: function (value) { | ||
if (!(internalPropertyKey in this)) { | ||
// must be attribute init setter,wrap it to a action | ||
value = createTransaction(value); | ||
} | ||
this[internalPropertyKey] = value; | ||
}, | ||
get: function () { | ||
return this[internalPropertyKey]; | ||
} | ||
}); | ||
} | ||
function createTransaction(originalFunc) { | ||
@@ -158,9 +173,9 @@ if (typeof originalFunc !== 'function') { | ||
} | ||
const identity = getUUID(); | ||
const identity = transactionManager.getUUID(); | ||
return function (...args) { | ||
transaction.start(identity); | ||
transactionManager.start(identity); | ||
try { | ||
return originalFunc.apply(this, args); | ||
} finally { | ||
transaction.end(identity); | ||
transactionManager.end(identity); | ||
} | ||
@@ -212,4 +227,4 @@ }; | ||
getReactionsForOperation(operation).forEach(reaction => { | ||
if (transaction.duringTransaction) { | ||
transaction.add(reaction, operation); | ||
if (transactionManager.duringStack) { | ||
runnerManager.add(reaction, operation); | ||
} else { | ||
@@ -304,48 +319,7 @@ queueReaction(reaction, operation); | ||
let actionCount = 0; | ||
const action = decoratorFactory(createAction); | ||
const actionManager = new StackManager(); | ||
function action(target, propertyKey, descriptor) { | ||
if (!propertyKey) { | ||
// 1. use as function wrapper | ||
return createAction(target); | ||
} | ||
// 2. use as a decorator | ||
if (propertyKey in target) { | ||
// 2.1 use as class method decorator | ||
descriptor.value = createAction(descriptor.value); | ||
return; | ||
} | ||
// 2.2 use as class attribute decorator | ||
const internalPropertyKey = Symbol(propertyKey); | ||
Object.defineProperty(target, propertyKey, { | ||
set: function (value) { | ||
if (!(internalPropertyKey in this)) { | ||
// must be attribute init setter,wrap it to a action | ||
value = createAction(value); | ||
} | ||
this[internalPropertyKey] = value; | ||
}, | ||
get: function () { | ||
return this[internalPropertyKey]; | ||
} | ||
}); | ||
} | ||
function duringAction() { | ||
return actionCount > 0; | ||
} | ||
function startAction() { | ||
actionCount = actionCount + 1; | ||
} | ||
function endAction() { | ||
actionCount = actionCount - 1; | ||
if (actionCount < 0) { | ||
throw new Error('[nemo-observable-util] call endAction but no action is running!'); | ||
} | ||
} | ||
function canWrite() { | ||
return !InternalConfig.onlyAllowChangeInAction || duringAction(); | ||
return !InternalConfig.onlyAllowChangeInAction || actionManager.duringStack; | ||
} | ||
@@ -360,10 +334,14 @@ | ||
function createAction(fn) { | ||
const transactionFn = createTransaction(fn); | ||
function createAction(originalFunc) { | ||
if (typeof originalFunc !== 'function') { | ||
throw new Error('action should must wrap on Function: ' + typeof originalFunc); | ||
} | ||
const transactionFn = createTransaction(originalFunc); | ||
const identity = actionManager.getUUID(); | ||
return function (...args) { | ||
startAction(); | ||
actionManager.start(identity); | ||
try { | ||
return transactionFn.apply(this, args); | ||
} finally { | ||
endAction(); | ||
actionManager.end(identity); | ||
} | ||
@@ -662,2 +640,2 @@ }; | ||
export { observe, unobserve, observable, isObservable, raw, config, startTransaction, endTransaction, withTransaction, action }; | ||
export { observe, unobserve, observable, isObservable, raw, config, startTransaction, endTransaction, withTransaction, transactionManager, action, actionManager, decoratorFactory }; |
{ | ||
"name": "nemo-observable-util", | ||
"version": "4.5.3", | ||
"version": "5.0.0", | ||
"description": "Simple transparent reactivity with 100% language coverage. Made with ES6 Proxies.", | ||
@@ -5,0 +5,0 @@ "main": "dist/cjs.es5.js", |
@@ -41,5 +41,10 @@ declare module 'nemo-observable-util' { | ||
): void; | ||
declare const transactionManager: any; | ||
function config(arg: ObservableConfig): ObservableConfig; | ||
function action<F extends Function>(fn: F): F; | ||
function action(target: any, key: any, d: TypedPropertyDescriptor<any>): void; | ||
declare const actionManager: any; | ||
function decoratorFactory<T extends Function>( | ||
wrapperFn: (f: T) => T | ||
): MethodDecorator | PropertyDecorator; | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
107044
2389