Skip to content
Merged
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
17 changes: 11 additions & 6 deletions src/widget-core/WidgetBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,19 @@ import {
DefaultWidgetBaseInterface,
LazyWidget,
Render,
WidgetMetaBase,
WidgetMetaConstructor,
WidgetBaseInterface,
WidgetProperties,
WNode,
VNode,
LazyDefine
LazyDefine,
MetaBase
} from './interfaces';
import RegistryHandler from './RegistryHandler';
import NodeHandler from './NodeHandler';
import { isWidgetBaseConstructor, WIDGET_BASE_TYPE } from './Registry';
import { Handle } from '../core/Destroyable';
import { Base } from './meta/Base';

interface ReactionFunctionConfig {
propertyName: string;
Expand Down Expand Up @@ -67,6 +68,10 @@ function isLazyDefine(item: any): item is LazyDefine {
return Boolean(item && item.label);
}

function isDomMeta(meta: any): meta is Base {
return Boolean(meta.afterRender);
}

/**
* Main widget base for all widgets to extend
*/
Expand Down Expand Up @@ -108,7 +113,7 @@ export class WidgetBase<P = WidgetProperties, C extends DNode = DNode> implement
*/
private _bindFunctionPropertyMap: WeakMap<(...args: any[]) => any, BoundFunctionData> | undefined;

private _metaMap: Map<WidgetMetaConstructor<any>, WidgetMetaBase> | undefined;
private _metaMap: Map<WidgetMetaConstructor<any>, MetaBase> | undefined;

private _boundRenderFunc: Render;

Expand Down Expand Up @@ -153,9 +158,9 @@ export class WidgetBase<P = WidgetProperties, C extends DNode = DNode> implement
this._runAfterConstructors();
}

protected meta<T extends WidgetMetaBase>(MetaType: WidgetMetaConstructor<T>): T {
protected meta<T extends MetaBase>(MetaType: WidgetMetaConstructor<T>): T {
if (this._metaMap === undefined) {
this._metaMap = new Map<WidgetMetaConstructor<any>, WidgetMetaBase>();
this._metaMap = new Map<WidgetMetaConstructor<any>, MetaBase>();
}
let cached = this._metaMap.get(MetaType);
if (!cached) {
Expand Down Expand Up @@ -514,7 +519,7 @@ export class WidgetBase<P = WidgetProperties, C extends DNode = DNode> implement

if (this._metaMap !== undefined) {
this._metaMap.forEach((meta) => {
meta.afterRender();
isDomMeta(meta) && meta.afterRender();
});
}

Expand Down
9 changes: 7 additions & 2 deletions src/widget-core/interfaces.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -487,15 +487,20 @@ export interface WidgetBaseInterface<P = WidgetProperties, C extends DNode = DNo
/**
* Meta Base type
*/
export interface WidgetMetaBase extends Destroyable {
export interface MetaBase extends Destroyable {}

/**
* Meta Base type
*/
export interface WidgetMetaBase extends MetaBase {
has(key: string | number): boolean;
afterRender(): void;
}

/**
* Meta Base constructor type
*/
export interface WidgetMetaConstructor<T extends WidgetMetaBase> {
export interface WidgetMetaConstructor<T extends MetaBase> {
new (properties: WidgetMetaProperties): T;
}

Expand Down
43 changes: 43 additions & 0 deletions src/widget-core/meta/Build.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { Destroyable } from '../../core/Destroyable';
import Map from '../../shim/Map';
import WeakMap from '../../shim/WeakMap';
import { WidgetMetaProperties, MetaBase } from '../interfaces';

export class Build extends Destroyable implements MetaBase {
private _moduleMap = new WeakMap<Function, any>();
private _invalidate: () => void;

constructor(properties: WidgetMetaProperties) {
super();
this._invalidate = properties.invalidate;
}

public run<T extends Function>(module: T): T {
const decoratedModule: any = (...args: any[]) => {
let valueMap = this._moduleMap.get(module);
if (!valueMap) {
valueMap = new Map();
this._moduleMap.set(module, valueMap);
}
const argsString = JSON.stringify(args);
const value = valueMap.get(argsString);
if (value !== undefined) {
return value;
}

valueMap.set(argsString, null);
const result = module(...args);
if (typeof result.then === 'function') {
result.then((result: any) => {
valueMap.set(argsString, result);
this._invalidate();
});
return null;
}
return result;
};
return decoratedModule as T;
}
}

export default Build;
4 changes: 2 additions & 2 deletions tests/widget-core/unit/WidgetBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { spy, stub, SinonStub } from 'sinon';
import { WidgetBase, noBind, widgetInstanceMap } from '../../../src/widget-core/WidgetBase';
import { v, w, WNODE } from '../../../src/widget-core/d';
import { WIDGET_BASE_TYPE } from '../../../src/widget-core/Registry';
import { Constructor, VNode, WidgetMetaConstructor, WidgetMetaBase, WNode } from '../../../src/widget-core/interfaces';
import { Constructor, VNode, WidgetMetaConstructor, WNode, MetaBase } from '../../../src/widget-core/interfaces';
import { handleDecorator } from '../../../src/widget-core/decorators/handleDecorator';
import { diffProperty } from '../../../src/widget-core/decorators/diffProperty';
import { Base } from '../../../src/widget-core/meta/Base';
Expand Down Expand Up @@ -38,7 +38,7 @@ class TestMeta extends Base {
}

class BaseTestWidget extends WidgetBase<TestProperties> {
public meta<T extends WidgetMetaBase>(metaType: WidgetMetaConstructor<T>) {
public meta<T extends MetaBase>(metaType: WidgetMetaConstructor<T>) {
return super.meta(metaType) as T;
}

Expand Down
71 changes: 71 additions & 0 deletions tests/widget-core/unit/meta/Build.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
const { assert } = intern.getPlugin('chai');
const { describe, it } = intern.getInterface('bdd');
import * as sinon from 'sinon';
import NodeHandler from '../../../../src/widget-core/NodeHandler';
import WidgetBase from '../../../../src/widget-core/WidgetBase';
import Build from '../../../../src/widget-core/meta/Build';

let bindInstance = new WidgetBase();

describe('Build Meta', () => {
it('Should resolve module result when async', () => {
let resolverOne: any;
let resolverTwo: any;
const promiseOne = new Promise((resolve) => {
resolverOne = resolve;
});
const promiseTwo = new Promise((resolve) => {
resolverTwo = resolve;
});

const invalidate = sinon.stub();
const nodeHandler = new NodeHandler();

function testModule(a: string): string | null {
return promiseOne as any;
}

function testModuleOther(a: string): string | null {
return promiseTwo as any;
}

const meta = new Build({
invalidate,
nodeHandler,
bind: bindInstance
});

const resultOne = meta.run(testModule)('test');
const resultTwo = meta.run(testModuleOther)('test');
assert.isNull(resultOne);
assert.isNull(resultTwo);

resolverOne('resultOne');
resolverTwo('resultTwo');

return Promise.all([promiseOne, promiseTwo]).then(() => {
const resultOne = meta.run(testModule)('test');
assert.strictEqual(resultOne, 'resultOne');
const resultTwo = meta.run(testModuleOther)('test');
assert.strictEqual(resultTwo, 'resultTwo');
});
});

it('Should return the result immediately when sync', () => {
const invalidate = sinon.stub();
const nodeHandler = new NodeHandler();

function testModule(a: string): string | null {
return 'sync';
}

const meta = new Build({
invalidate,
nodeHandler,
bind: bindInstance
});

const resultOne = meta.run(testModule)('test');
assert.strictEqual(resultOne, 'sync');
});
});
1 change: 1 addition & 0 deletions tests/widget-core/unit/meta/all.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import './Build';
import './meta';
import './Dimensions';
import './Drag';
Expand Down