allow $parent access of flow context

This commit is contained in:
Hiroyasu Nishiyama 2019-01-16 23:10:03 +09:00
parent 30aebc4ee3
commit 596fbfb517
2 changed files with 137 additions and 4 deletions

View File

@ -18,6 +18,7 @@ var clone = require("clone");
var log = require("@node-red/util").log;
var util = require("@node-red/util").util;
var memory = require("./memory");
var flows;
var settings;
@ -47,6 +48,7 @@ function logUnknownStore(name) {
}
function init(_settings) {
flows = require("../flows");
settings = _settings;
contexts = {};
stores = {};
@ -198,8 +200,24 @@ function getContextStorage(storage) {
}
}
function followParentContext(parent, key) {
if (key === "$parent") {
return [parent, ""];
}
else if (key.startsWith("$parent.")) {
var len = "$parent.".length;
var new_key = key.substring(len);
var ctx = parent;
while (ctx && new_key.startsWith("$parent.")) {
ctx = ctx.$parent;
new_key = new_key.substring(len);
}
return [ctx, new_key];
}
return null;
}
function createContext(id,seed) {
function createContext(id,seed,parent) {
// Seed is only set for global context - sourced from functionGlobalContext
var scope = id;
var obj = seed || {};
@ -254,6 +272,29 @@ function createContext(id,seed) {
if (!storage) {
storage = keyParts.store || "_";
}
var result = followParentContext(parent, key);
if (result) {
var [ctx, new_key] = result;
if (ctx) {
if (new_key === "") {
if (callback) {
return callback(ctx);
}
else {
return ctx;
}
}
return ctx.get(new_key, storage, callback);
}
else {
if (callback) {
return callback(undefined);
}
else {
return undefined;
}
}
}
} else {
if (!storage) {
storage = "_";
@ -321,6 +362,19 @@ function createContext(id,seed) {
if (!storage) {
storage = keyParts.store || "_";
}
var result = followParentContext(parent, key);
if (result) {
var [ctx, new_key] = result;
if (ctx) {
return ctx.set(new_key, value, storage, callback);
}
else {
if (callback) {
return callback();
}
return undefined;
}
}
} else {
if (!storage) {
storage = "_";
@ -361,10 +415,36 @@ function createContext(id,seed) {
}
}
});
if (parent) {
Object.defineProperty(obj, "$parent", {
value: parent
});
}
return obj;
}
function getContext(localId,flowId) {
function createRootContext() {
var obj = {};
Object.defineProperties(obj, {
get: {
value: function(key, storage, callback) {
return undefined;
}
},
set: {
value: function(key, value, storage, callback) {
}
},
keys: {
value: function(storage, callback) {
return undefined;
}
}
});
return obj;
}
function getContext(localId,flowId,parent) {
var contextId = localId;
if (flowId) {
contextId = localId+":"+flowId;
@ -372,10 +452,19 @@ function getContext(localId,flowId) {
if (contexts.hasOwnProperty(contextId)) {
return contexts[contextId];
}
var newContext = createContext(contextId);
var newContext = createContext(contextId,undefined,parent);
if (flowId) {
var node = flows.get(flowId);
var parent = undefined;
if (node && node.type.startsWith("subflow:")) {
parent = node.context().flow;
}
else {
parent = createRootContext();
}
var flowContext = getContext(flowId,undefined,parent);
Object.defineProperty(newContext, 'flow', {
value: getContext(flowId)
value: flowContext
});
}
Object.defineProperty(newContext, 'global', {

View File

@ -225,6 +225,50 @@ describe('context', function() {
});
})
describe("$parent", function() {
it('should access $parent', function() {
var context0 = Context.get("0","flowA");
var context1 = Context.get("1","flowB", context0);
var parent = context1.get("$parent");
parent.should.equal(context0);
});
it('should get undefined for $parent of root', function() {
var context0 = Context.get("0","flowA");
var context1 = Context.get("1","flowB", context0);
var parent = context1.get("$parent.$parent");
should.equal(parent, undefined);
});
it('should get $parent', function() {
var context0 = Context.get("0","flowA");
var context1 = Context.get("1","flowB", context0);
var parent = context1.get("$parent");
context0.set("K", "v");
var v = context1.get("$parent.K");
should.equal(v, "v");
});
it('should set $parent', function() {
var context0 = Context.get("0","flowA");
var context1 = Context.get("1","flowB", context0);
var parent = context1.get("$parent");
context1.set("$parent.K", "v");
var v = context0.get("K");
should.equal(v, "v");
});
it('should not contain $parent in keys', function() {
var context0 = Context.get("0","flowA");
var context1 = Context.get("1","flowB", context0);
var parent = context1.get("$parent");
context0.set("K0", "v0");
context1.set("K1", "v1");
var keys = context1.keys();
keys.should.have.length(1);
keys[0].should.equal("K1");
});
});
});