fix: 修复关闭SSH终端标签页时会话状态未更新的问题

This commit is contained in:
2026-04-18 02:35:38 +08:00
commit 6e2e2f9387
43467 changed files with 5489040 additions and 0 deletions
@@ -0,0 +1,22 @@
import * as React from 'react';
import {renderToString} from 'react-dom/server';
import {expect} from 'chai';
import render from '../render';
import createEnhancer from '../createEnhancer';
const Parent = (props) => render(props, {foo: 'bar'});
const withParent = createEnhancer(Parent, 'parent');
describe('createEnhancer() SSR', () => {
it('exists and does not crash', () => {
expect(typeof createEnhancer).to.equal('function');
});
it('renders as expected', () => {
const Comp = (props) => <div>{props.parent.foo}</div>;
const CompEnhanced = withParent(Comp);
const html = renderToString(<CompEnhanced />);
expect(html).to.equal('<div data-reactroot="">bar</div>');
});
});
@@ -0,0 +1,22 @@
import * as React from 'react';
import {renderToString} from 'react-dom/server';
import {expect} from 'chai';
import render from '../render';
const Parent = (props) => render(props, {foo: 'bar'});
describe('render() SSR', () => {
it('exists and does not crash', () => {
expect(typeof render).to.equal('function');
});
it('renders as expected', () => {
const html = renderToString(
<Parent>
<div>foobar</div>
</Parent>
);
expect(html).to.equal('<div data-reactroot="">foobar</div>');
});
});
+8
View File
@@ -0,0 +1,8 @@
const {configure} = require('enzyme');
const Adapter = require('enzyme-adapter-react-16');
configure({
adapter: new Adapter()
});
global.requestAnimationFrame = window.requestAnimationFrame = (callback) => setTimeout(callback, 17);
@@ -0,0 +1,8 @@
import wrapInStatefulComponent from './wrapInStatefulComponent';
const addClassDecoratorSupport = (Comp) => {
const isSFC = !Comp.prototype;
return !isSFC ? Comp : wrapInStatefulComponent(Comp);
};
export default addClassDecoratorSupport;
+35
View File
@@ -0,0 +1,35 @@
import * as React from 'react';
import addClassDecoratorSupport from './addClassDecoratorSupport';
const h = React.createElement;
const noWrap = (Comp, propName, props, state) => h(Comp, propName ?
{[propName]: state, ...props} :
{...state, ...props}
);
export const divWrapper = (Comp, propName, props, state) =>
h('div', null, noWrap(Comp, propName, props, state)) as any;
const createEnhancer = (Facc, prop?: string, wrapper = noWrap) => {
const enhancer = (Comp, propName: any = prop, faccProps: object = null) => {
const isClassDecoratorMethodCall = typeof Comp === 'string';
if (isClassDecoratorMethodCall) {
return (Klass) => enhancer(Klass, Comp as any || prop, propName as any);
}
const Enhanced = (props) =>
h(Facc, faccProps, (state) => wrapper(Comp, propName, props, state));
if (process.env.NODE_ENV !== 'production') {
(Enhanced as any).displayName = `${Facc.displayName || Facc.name}(${Comp.displayName || Comp.name})`;
}
return isClassDecoratorMethodCall ? addClassDecoratorSupport(Enhanced) : Enhanced;
};
return enhancer;
}
export default createEnhancer;
+12
View File
@@ -0,0 +1,12 @@
import {FC} from 'react';
import render from './render';
export type MapPropsToArgs<Props extends {}, Args extends any[]> = (props: Props) => Args;
export type CreateRenderProp = <Props extends {}, Args extends any[], State extends any>(hook: (...args: Args) => State, mapPropsToArgs?: MapPropsToArgs<Props, Args>) => FC<Props>;
const defaultMapPropsToArgs = props => [props];
const hookToRenderProp: CreateRenderProp = (hook, mapPropsToArgs = defaultMapPropsToArgs as any) =>
props => render(props, hook(...mapPropsToArgs(props)));
export default hookToRenderProp;
+16
View File
@@ -0,0 +1,16 @@
import render from './render';
import createEnhancer from './createEnhancer';
import hookToRenderProp from './hookToRenderProp';
export interface UniversalProps<Data> {
children?: ((data: Data) => React.ReactNode) | React.ReactNode;
render?: (data: Data) => React.ReactNode;
comp?: React.ComponentType<Data & any>;
component?: React.ComponentType<Data & any>;
}
export {
render,
createEnhancer,
hookToRenderProp,
};
+67
View File
@@ -0,0 +1,67 @@
import {createElement as h, cloneElement, version} from 'react';
const isReact16Plus = parseInt(version.substr(0, version.indexOf('.'))) > 15;
const isFn = fn => typeof fn === 'function';
const render = (props, data, ...more) => {
if (process.env.NODE_ENV !== 'production') {
if (typeof props !== 'object') {
throw new TypeError('renderChildren(props, data) first argument must be a props object.');
}
const {children, render} = props;
if (isFn(children) && isFn(render)) {
console.warn(
'Both "render" and "children" are specified for in a universal interface component. ' +
'Children will be used.'
);
console.trace();
}
if (typeof data !== 'object') {
console.warn(
'Universal component interface normally expects data to be an object, ' +
`"${typeof data}" received.`
);
console.trace();
}
}
const {render, children = render, component, comp = component} = props;
if (isFn(children)) return children(data, ...more);
if (comp) {
return h(comp, data);
}
if (children instanceof Array)
return isReact16Plus ? children : h('div', null, ...children);
if (children && (children instanceof Object)) {
if (process.env.NODE_ENV !== 'production') {
if (!children.type || ((typeof children.type !== 'string') && (typeof children.type !== 'function') && (typeof children.type !== 'symbol'))) {
console.warn(
'Universal component interface received object as children, ' +
'expected React element, but received unexpected React "type".'
);
console.trace();
}
if (typeof children.type === 'string')
return children;
return cloneElement(children, Object.assign({}, children.props, data));
} else {
if (typeof children.type === 'string')
return children;
return cloneElement(children, Object.assign({}, children.props, data));
}
}
return children || null;
};
export default render;
@@ -0,0 +1,17 @@
import * as React from 'react';
const wrapInStatefulComponent = (Comp) => {
const Decorated = class extends React.Component<any, any> {
render () {
return Comp(this.props, this.context);
}
};
if (process.env.NODE_ENV !== 'production') {
(Decorated as any).displayName = `Decorated(${Comp.displayName || Comp.name})`;
}
return Decorated;
};
export default wrapInStatefulComponent;