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

@cicada/render

Package Overview
Dependencies
Maintainers
7
Versions
107
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@cicada/render - npm Package Compare versions

Comparing version 1.1.21 to 1.1.22-alpha1

10

lib/__test__/integration/dynamicRender.test.js

@@ -11,2 +11,4 @@ 'use strict';

require('raf/polyfill');
var _enzyme = require('enzyme');

@@ -350,7 +352,9 @@

expect(Button.getRendered()).toBe(2);
expect(Button.getRendered()).toBe(1);
expect(Input.getRendered()).toBe(2);
});
test('change with mapBackgroundToState', function () {});
//
// test('change with mapBackgroundToState', () => {
//
// })
});

@@ -7,2 +7,6 @@ 'use strict';

var _defineProperty2 = require('babel-runtime/helpers/defineProperty');
var _defineProperty3 = _interopRequireDefault(_defineProperty2);
var _extends2 = require('babel-runtime/helpers/extends');

@@ -131,2 +135,21 @@

function syncChange(statePath, changes) {
var stateId = stateTree.getWithDetail(statePath).stateId;
if (changesGroupById[stateId] === undefined) {
changesGroupById[stateId] = [];
}
var changesToReturn = (0, _defineProperty3.default)({}, stateId, []);
changes.forEach(function (change) {
changesGroupById[stateId].push((0, _extends3.default)({}, change, {
stateId: stateId,
statePath: statePath
}));
changesToReturn[stateId].push((0, _extends3.default)({}, change, {
stateId: stateId,
statePath: statePath
}));
});
return changesToReturn;
}
return (0, _extends3.default)({

@@ -145,2 +168,8 @@ origin: stateTree

resetHardById: cacheInSession(saveChangesGroupById(stateTree.resetHardById, 1)),
// 专门针对有 stateProxy
syncChange: cacheInSession(syncChange),
getChanges: function getChanges() {
return (0, _extends3.default)({}, changesGroupById);
},
subscribe: subscribe,

@@ -147,0 +176,0 @@ forceSubscribe: forceSubscribe,

@@ -312,3 +312,5 @@ 'use strict';

if (typeof value === 'function') {
/* eslint-disable no-console */
console.error('business.set(\'' + statePath + path + '\', value) should not be set a function.');
/* eslint-enable no-console */
return false;

@@ -324,3 +326,5 @@ }

if (!Array.isArray(value) && !(0, _isPlainObject2.default)(value)) {
/* eslint-disable no-console */
console.error('business.set(\'' + statePath + path + '\', value) should be set a plain value.');
/* eslint-enable no-console */
return false;

@@ -327,0 +331,0 @@ }

@@ -84,2 +84,12 @@ 'use strict';

function wrapWithInstance(instance, fn) {
return fn !== undefined ? function () {
for (var _len = arguments.length, arg = Array(_len), _key = 0; _key < _len; _key++) {
arg[_key] = arguments[_key];
}
return fn.apply(undefined, [{ instance: instance }].concat(arg));
} : undefined;
}
var createComponentId = (0, _util.createUniqueIdGenerator)();

@@ -109,3 +119,4 @@

_DeclarativeComponent7 = DeclarativeComponent.display,
display = _DeclarativeComponent7 === undefined ? _constant.DISPLAY_BLOCK : _DeclarativeComponent7;
display = _DeclarativeComponent7 === undefined ? _constant.DISPLAY_BLOCK : _DeclarativeComponent7,
getStateProxy = DeclarativeComponent.getStateProxy;

@@ -177,3 +188,3 @@ var primitiveFns = (0, _util.pick)(DeclarativeComponent, _constant.primitiveFnNames);

var _stateTree$register = stateTree.register(statePath, finalGetInitialState, displayName, pathGetter),
var _stateTree$register = stateTree.register(statePath, finalGetInitialState, displayName, pathGetter, wrapWithInstance(this.instance, getStateProxy)),
stateId = _stateTree$register.stateId,

@@ -238,4 +249,4 @@ cancelStateTree = _stateTree$register.cancel;

return function () {
for (var _len = arguments.length, runtimeArgs = Array(_len), _key = 0; _key < _len; _key++) {
runtimeArgs[_key] = arguments[_key];
for (var _len2 = arguments.length, runtimeArgs = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
runtimeArgs[_key2] = arguments[_key2];
}

@@ -245,2 +256,5 @@

var nextState = defaultListener.apply(undefined, [_this4.getRenderArg(statePath)].concat(runtimeArgs));
// 如果组件有 stateProxy,说明不需要外部 stateTree 的 merge。只需要收到通知就够了。注意,此时 nexState 返回的其实是 changes。
if (getStateProxy !== undefined) return _this4.context.stateTree.syncChange(_this4.getResolvedStatePath(), nextState);
if (nextState !== undefined && nextState !== null && _this4.registeredStateTree) {

@@ -311,4 +325,4 @@ _this4.context.stateTree.merge(_this4.getResolvedStatePath(), nextState, {

for (var _len2 = arguments.length, runtimeArgs = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
runtimeArgs[_key2] = arguments[_key2];
for (var _len3 = arguments.length, runtimeArgs = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
runtimeArgs[_key3] = arguments[_key3];
}

@@ -425,3 +439,3 @@

}
// 新增的声明周期函数
// 新增的声明周期函数,专门针对复合组件和动态组件。
if (type === _constant.CHANGE_STATETREE && typeof componentWillReceiveState === 'function') {

@@ -428,0 +442,0 @@ componentWillReceiveState(_this6.getRenderArg(), changes);

@@ -7,5 +7,5 @@ 'use strict';

var _stringify = require('babel-runtime/core-js/json/stringify');
var _extends2 = require('babel-runtime/helpers/extends');
var _stringify2 = _interopRequireDefault(_stringify);
var _extends3 = _interopRequireDefault(_extends2);

@@ -22,2 +22,6 @@ exports.default = createDynamicRender;

var _cloneDeep = require('lodash/cloneDeep');
var _cloneDeep2 = _interopRequireDefault(_cloneDeep);
var _Render = require('./Render');

@@ -27,4 +31,2 @@

var _constant = require('./constant');
var _exist = require('./exist');

@@ -34,20 +36,11 @@

var _util = require('./util');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function cheapClone(obj) {
return JSON.parse((0, _stringify2.default)(obj));
function removePathHeader(path, header) {
var result = path.slice(header.length);
return result[0] === '.' ? result.slice(1) : result;
}
function startWith(str, toTest) {
return str.slice(0, toTest.length) === toTest;
}
function isConfigChanged(changes) {
return changes.some(function (_ref) {
var valuePath = _ref.valuePath;
return startWith(valuePath, 'config');
});
}
function createDynamicRender(createStateTree, createAppearance, createBackground, backgroundDef) {

@@ -67,6 +60,9 @@ var getDefaultState = function getDefaultState() {

var defaultListeners = {
onChange: function onChange(_ref2, changeFn, name, path) {
var instance = _ref2.instance;
onChange: function onChange(_ref, changeFn, name, path) {
var instance = _ref.instance,
state = _ref.state,
statePath = _ref.statePath;
if (changeFn === undefined) return;
instance.stateTree.cache();

@@ -78,45 +74,100 @@ for (var _len = arguments.length, runtimeArgs = Array(_len > 4 ? _len - 4 : 0), _key = 4; _key < _len; _key++) {

changeFn.apply(undefined, runtimeArgs);
// 如果 stateTree 都没变, 那么 return undefined 只是通知一下外部
return instance.stateTreeVersion === instance.stateTree.getVersion() ? undefined : { value: cheapClone(instance.stateTree.get()) };
// 如果 stateTree 都没变, 那么 return 空数组只是通知一下外部,注意,dynamic 是有 stateProxy,所以这里 return 的是 changes。
var changesGroupById = instance.stateTree.getChanges();
var changesReplaced = [];
(0, _util.each)(changesGroupById, function (changes) {
changes.forEach(function (change) {
changesReplaced.push((0, _extends3.default)({
valuePath: 'value.' + change.valuePath
}, change));
});
});
return changesReplaced;
}
};
var shouldComponentUpdate = function shouldComponentUpdate(_, type, changes) {
// 收到 config 变化才 return true
return type === _constant.CHANGE_STATETREE && isConfigChanged(changes);
};
// state 的 proxy 模式,可以接管 stateTree 的变化
var getStateProxy = function getStateProxy(_ref2) {
var instance = _ref2.instance;
var initialValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var componentWillReceiveState = function componentWillReceiveState(_ref3, changes) {
var instance = _ref3.instance,
state = _ref3.state;
instance.stateTree = createStateTree(initialValue.value || {});
instance.config = initialValue.config ? (0, _extends3.default)({}, initialValue.config) : {};
return {
get: function get(statePath) {
var _instance$stateTree;
// CAUTION 如果 config 数据变化了,那么肯定会进入重新渲染的流程。
if (isConfigChanged(changes)) return;
for (var _len2 = arguments.length, arg = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
arg[_key2 - 1] = arguments[_key2];
}
// 收到数据变化,那么对 stateTree 进行操作
var valuePathsToChange = changes.reduce(function (last, _ref4) {
var valuePath = _ref4.valuePath,
inputStatePath = _ref4.inputStatePath;
if (/^value/.test(statePath)) return (_instance$stateTree = instance.stateTree).get.apply(_instance$stateTree, [removePathHeader(statePath, 'value')].concat(arg));
if (/^config/.test(statePath)) return _exist2.default.get.apply(_exist2.default, [instance.config, removePathHeader(statePath, 'config')].concat(arg));
throw new Error('get unknown state name: ' + statePath);
},
set: function set(statePath, value) {
for (var _len3 = arguments.length, arg = Array(_len3 > 2 ? _len3 - 2 : 0), _key3 = 2; _key3 < _len3; _key3++) {
arg[_key3 - 2] = arguments[_key3];
}
// inputStatePath 为 undefined 的是内部变化,所以忽略掉
if (inputStatePath === undefined) return last;
// 如果改的不是 value
if (!startWith(valuePath, 'value')) return last;
if (/^value/.test(statePath)) {
var path = removePathHeader(statePath, 'value');
if (path) {
var _instance$stateTree2;
// 去掉前面的 'value.' 就得到了 value 下的改变的 path
var inputValuePath = valuePath.slice(6);
var isParentSaved = last.some(function (parent) {
return inputValuePath.slice(0, parent.length) === parent;
});
return isParentSaved ? last : last.concat(inputValuePath);
}, []);
(_instance$stateTree2 = instance.stateTree).set.apply(_instance$stateTree2, [removePathHeader(statePath, 'value'), value].concat(arg));
} else {
(0, _util.each)(value, function (v, k) {
var _instance$stateTree3;
valuePathsToChange.forEach(function (inputValuePath) {
instance.stateTree.merge(inputValuePath, _exist2.default.get(state.value, inputValuePath));
});
(_instance$stateTree3 = instance.stateTree).set.apply(_instance$stateTree3, [k, v].concat(arg));
});
}
return;
}
// 注意,config 没有 merge,只是创建不存在的路径
if (/^config/.test(statePath)) {
// 对于外界的 set,记录一下,之后要用。
instance.isConfigChanged = true;
var _path = removePathHeader(statePath, 'config');
if (!_path) {
instance.config = value;
} else {
_exist2.default.set(instance.config, removePathHeader(statePath, 'config'), value, true);
}
return;
}
throw new Error('set unknown state name: ' + statePath);
}
};
};
instance.stateTreeVersion = instance.stateTree.getVersion();
instance.backgroundVersion = instance.background.getVersion();
// CAUTION 这是提高效率的关键,只有当 config 变化时,我们才完全从头渲染
// 当只有 stateTree 变化时,使用内部的机制更新。
var shouldComponentUpdate = function shouldComponentUpdate(_ref3) {
var instance = _ref3.instance;
return instance.isConfigChanged;
};
var componentWillReceiveState = function componentWillReceiveState(_ref4) {
var instance = _ref4.instance;
// 不管是外部的 set,还是内部的变化,都会走到这里来。
// 1. 引起 config 变化的,只可能是外部的 listener。由于外部在 set 上做了个记号,所以可以短路。
// config 变化了,那么一定要完全重新渲染,所有东西都要重建,因此不用管数据了。
if (instance.isConfigChanged) {
return;
}
// 2. config 没变化,只有 stateTree 发生了变化,那么有两种情况:
// 2.1 外部通过 set 也改变了 state,那么应该合并进来。
// 这种情况在 stateProxy 中已经合并到 stateTree 里了
// 2.2 只有内部改变了 stateTree。这种情况在调用 onChange 的时候就已经真实触发了
// 无论哪种情况,这个时候都应该准确地通知到界面更新了,因此不需要再做其他操作。
instance.stateTree.flush();
};
return {

@@ -127,17 +178,18 @@ getDefaultState: getDefaultState,

componentWillReceiveState: componentWillReceiveState,
getStateProxy: getStateProxy,
defaultListeners: defaultListeners,
render: function render(_ref5) {
var state = _ref5.state,
instance = _ref5.instance,
var instance = _ref5.instance,
listeners = _ref5.listeners;
var config = state.config,
value = state.value;
instance.stateTree = createStateTree(value);
var config = instance.config;
// 清空一下这个标记,这是用来记录是否要重新渲染的
if (instance.isConfigChanged) {
// 如果是二次渲染,stateTree 要重做,否则的 getProxy 的时候已经创建了,不用管
instance.isConfigChanged = false;
instance.stateTree = createStateTree((0, _cloneDeep2.default)(instance.stateTree.get('')));
}
instance.appearance = createAppearance();
instance.background = createBackground(backgroundDef, instance.stateTree, instance.appearance);
instance.stateTreeVersion = instance.stateTree.getVersion();
instance.backgroundVersion = instance.background.getVersion();
return _react2.default.createElement(_Render2.default, {

@@ -144,0 +196,0 @@ config: config,

@@ -72,3 +72,5 @@ 'use strict';

if (statePath.split('.').length !== detectArr.length) {
/* eslint-disable no-console */
console.error('Warning: ' + new _errors.ErrorWrongStateTreePath(statePath, detectArr.join('.')));
/* eslint-enable no-console */
}

@@ -82,3 +84,16 @@ }

function get(statePath, defaultValue) {
return _exist2.default.get(stateTree, statePath, defaultValue);
if (!statePath) return stateTree;
var path = statePath.split(_exist.rxAccess);
var result = stateTree;
while (path.length !== 0) {
result = result[path.shift()];
if (result === undefined && path.length !== 0) {
if (defaultValue === undefined) throw new _errors.ErrorWrongStateTreePath(statePath, path);
return defaultValue;
}
// 如果碰到 stateProxy,就都交给 proxy 处理
if (result && result._isStateProxy && path.length !== 0) return result.get(path.join('.'));
}
return result === undefined ? defaultValue : result;
}

@@ -100,2 +115,3 @@

var pathGetters = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
var isStateProxy = arguments[3];

@@ -106,2 +122,8 @@ Object.defineProperty(state, '_id', {

if (isStateProxy) {
Object.defineProperty(state, '_isStateProxy', {
value: true
});
}
// CAUTION 目前 pathGetter 必须要有 getStatePath

@@ -116,8 +138,14 @@ // 除此还有 getRootStatePath/getScopes/getRenderScopes

function registerToStateTree(statePath, getInitialState, pathGetters) {
complete(statePath, getInitialState());
function registerToStateTree(statePath, getInitialState, pathGetters, getStateProxy) {
if (getStateProxy !== undefined) {
// 有 stateProxy 的情况下,就用这个 Proxy
_exist2.default.set(stateTree, statePath, getStateProxy(_exist2.default.get(stateTree, statePath)));
} else {
complete(statePath, getInitialState());
}
var stateId = createStateId();
var state = get(statePath);
try {
defineState(state, stateId, pathGetters);
defineState(state, stateId, pathGetters, getStateProxy !== undefined);
} catch (e) {

@@ -159,6 +187,4 @@ throw new _errors.ErrorDuplicateOriginDataPath(statePath);

function setNaive(stateNodePath, relativePath, value, inputStateId, inputStatePath) {
var stateId = inputStateId || get(stateNodePath)._id;
_exist2.default.set(stateTree, (0, _common.joinPath)([stateNodePath, relativePath]), value, true);
return [{
function createChange(stateId, stateNodePath, relativePath, inputStatePath) {
return {
stateId: stateId,

@@ -168,5 +194,11 @@ statePath: stateNodePath,

inputStatePath: inputStatePath
}];
};
}
function setNaive(stateNodePath, relativePath, value, inputStateId, inputStatePath) {
var stateId = inputStateId || get(stateNodePath)._id;
_exist2.default.set(stateTree, (0, _common.joinPath)([stateNodePath, relativePath]), value, true);
return [createChange(stateId, stateNodePath, relativePath, inputStatePath)];
}
function shapeObject(stateNodePath, relativePath, nextValue) {

@@ -191,6 +223,7 @@ var origin = _exist2.default.get(stateTree, (0, _common.joinPath)([stateNodePath, relativePath]));

var stateId = inputStateId || get(stateNodePath)._id;
// 需要更新子组件
// 在处理对象时,有可能碰到了递归的子组件
if (targetStateId && stateId !== targetStateId) {
return setObject((0, _common.joinPath)([stateNodePath, relativePath]), '', inputValue, targetStateId, mergeLastState, initialValue, inputStatePath);
return setStateNode((0, _common.joinPath)([stateNodePath, relativePath]), inputValue, mergeLastState, inputStatePath);
}
var changes = [{ stateId: stateId, statePath: stateNodePath, valuePath: relativePath }];

@@ -257,4 +290,11 @@ var nextValue = mergeLastState ? inputValue : (0, _extends3.default)({}, initialValue, inputValue);

function setStateNode(statePath, inputState, mergeLastState, inputStatePath, stupid) {
var state = get(statePath);
var stateId = state._id;
if (state._isStateProxy) {
// 如果是 proxy,就直接交给 proxy 操作了,里面的细节不管
state.set(findRelativePath(statePath, inputStatePath), inputState, mergeLastState, inputStatePath);
return [createChange(stateId, statePath, '', inputStatePath)];
}
var changes = [];
var stateId = get(statePath)._id;
var initialState = initialStates[stateId].getInitialState();

@@ -283,4 +323,12 @@ var finalState = mergeLastState ? inputState : (0, _extends3.default)({}, initialState, inputState);

var stateNodePath = findClosestInitialPath(inputStatePath);
var stateId = get(stateNodePath)._id;
var state = get(stateNodePath);
var stateId = state._id;
if (!stateId || !initialStates[stateId]) throw new _errors.ErrorWrongStateTreePath(inputStatePath.split('.')[0], inputStatePath);
if (state._isStateProxy) {
// 如果是 proxy,就直接交给 proxy 操作了,里面的细节不管
state.set(findRelativePath(stateNodePath, inputStatePath), inputState, mergeLastState, inputStatePath);
return [createChange(stateId, stateNodePath, '', inputStatePath)];
}
var initialState = initialStates[stateId].getInitialState();

@@ -376,5 +424,6 @@ var relativeChildPath = findRelativePath(stateNodePath, inputStatePath);

defaults: guardWithPathDetect(defaults),
// 用于同步 stateProxy
// CAUTION register 对外暴露的接口会自动补全数据
register: function register(statePath, getInitialState, type, pathGetters) {
var stateId = registerToStateTree(statePath, getInitialState, pathGetters);
register: function register(statePath, getInitialState, type, pathGetters, getStateProxy) {
var stateId = registerToStateTree(statePath, getInitialState, pathGetters, getStateProxy);
var cancelInitialState = registerInitialState(stateId, getInitialState, type);

@@ -381,0 +430,0 @@ return {

@@ -6,2 +6,3 @@ 'use strict';

});
exports.rxAccess = undefined;

@@ -23,3 +24,3 @@ var _assign = require('babel-runtime/core-js/object/assign');

/* eslint-disable no-useless-escape */
var rxAccess = /[\[\]\.]+/;
var rxAccess = exports.rxAccess = /[\[\]\.]+/;
/* eslint-enable no-useless-escape */

@@ -26,0 +27,0 @@

@@ -140,5 +140,3 @@ 'use strict';

// 这里才真的通知子组件开始渲染
if (!this.isControlled) {
this.stateTree.flush();
}
this.stateTree.flush();
}

@@ -145,0 +143,0 @@ }, {

{
"name": "@cicada/render",
"version": "1.1.21",
"version": "1.1.22-alpha1",
"main": "./lib/index.js",

@@ -14,3 +14,4 @@ "scripts": {

"exist.js": "^0.3.0",
"lodash": "^4.17.4"
"lodash": "^4.17.4",
"raf": "^3.4.0"
},

@@ -61,2 +62,3 @@ "peerDependencies": {

"setupFiles": [
"raf/polyfill",
"<rootDir>/src/__test__/_setup.js"

@@ -74,4 +76,4 @@ ]

"babel-preset-stage-0": "^6.22.0",
"enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.1",
"enzyme": "^3.7.0",
"enzyme-adapter-react-16": "^1.6.0",
"eslint-plugin-markdown": "^1.0.0-beta.4",

@@ -78,0 +80,0 @@ "jest": "^19.0.2",

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