Skip to content

Commit

Permalink
feat: add splice strategies for array observation (#5999)
Browse files Browse the repository at this point in the history
* feat: extract splice merging to a strategy

* feat: enable splice strategy to control splice creation per array method

* feat: add reset splice strategy

* refactor: made array length observation part of the standard interface

* feat: add SpliceStrategySupport and fix enum/literals

* refactor: re-organize array observation code

* chore: add splice-strategies to the package and clean up exports

* Change files

* chore: remove invalid eslint comments

* test: add array observer tests for all array mutations

* fix: adding extensions back to exports

Co-authored-by: EisenbergEffect <[email protected]>
  • Loading branch information
EisenbergEffect and EisenbergEffect authored May 20, 2022
1 parent 85ef60c commit fc4dbc4
Show file tree
Hide file tree
Showing 14 changed files with 1,292 additions and 510 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "major",
"comment": "feat: add splice strategies for array observation",
"packageName": "@microsoft/fast-element",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "major",
"comment": "chore: update imports to match latest fast-element exports",
"packageName": "@microsoft/fast-foundation",
"email": "[email protected]",
"dependentChangeType": "patch"
}
91 changes: 67 additions & 24 deletions packages/web-components/fast-element/docs/api-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,31 +30,43 @@ export class AdoptedStyleSheetsStrategy implements StyleStrategy {
readonly sheets: CSSStyleSheet[];
}

// @public
export interface ArrayObserver extends SubscriberSet {
addSplice(splice: Splice): void;
flush(): void;
readonly lengthObserver: LengthObserver;
reset(oldCollection: any[] | undefined): void;
strategy: SpliceStrategy | null;
}

// @public
export const ArrayObserver: Readonly<{
readonly enable: () => void;
}>;

// @public
export const Aspect: Readonly<{
none: 0;
attribute: 1;
booleanAttribute: 2;
property: 3;
content: 4;
tokenList: 5;
event: 6;
assign(directive: Aspected, value: string): void;
readonly none: 0;
readonly attribute: 1;
readonly booleanAttribute: 2;
readonly property: 3;
readonly content: 4;
readonly tokenList: 5;
readonly event: 6;
readonly assign: (directive: Aspected, value: string) => void;
}>;

// @public
export type Aspect = typeof Aspect[Exclude<keyof typeof Aspect, "assign" | "none">];

// @public
export interface Aspected {
aspectType: AspectType;
aspectType: Aspect;
binding?: Binding;
sourceAspect: string;
targetAspect: string;
}

// @public
export type AspectType = Exclude<{
[K in keyof typeof Aspect]: typeof Aspect[K] extends number ? typeof Aspect[K] : never;
}[keyof typeof Aspect], typeof Aspect.none>;

// @public
export function attr(config?: DecoratorAttributeConfiguration): (target: {}, property: string) => void;

Expand Down Expand Up @@ -118,7 +130,7 @@ export const BindingConfig: Readonly<{
export type BindingConfigResolver<T> = (options: T) => BindingConfig<T>;

// @public
export type BindingMode = Record<AspectType, (directive: HTMLBindingDirective) => Pick<ViewBehaviorFactory, "createBehavior">>;
export type BindingMode = Record<Aspect, (directive: HTMLBindingDirective) => Pick<ViewBehaviorFactory, "createBehavior">>;

// @public
export const BindingMode: Readonly<{
Expand Down Expand Up @@ -345,9 +357,6 @@ export interface ElementViewTemplate<TSource = any, TParent = any> {
// @internal
export const emptyArray: readonly never[];

// @public
export function enableArrayObservation(): void;

// @public
export class EventBinding {
constructor(directive: HTMLBindingDirective);
Expand Down Expand Up @@ -430,7 +439,7 @@ export function html<TSource = any, TParent = any, TContext extends ExecutionCon
// @public
export class HTMLBindingDirective implements HTMLDirective, ViewBehaviorFactory, Aspected {
constructor(binding: Binding, mode: BindingMode, options: any);
aspectType: AspectType;
aspectType: Aspect;
// (undocumented)
binding: Binding;
createBehavior(targets: ViewBehaviorTargets): ViewBehavior;
Expand Down Expand Up @@ -512,6 +521,11 @@ export interface ItemViewTemplate<TSource = any, TParent = any> {
function length_2<T>(array: readonly T[]): number;
export { length_2 as length }

// @public
export interface LengthObserver extends Subscriber {
length: number;
}

// @public
export const Markup: Readonly<{
interpolation: (id: string) => string;
Expand Down Expand Up @@ -733,17 +747,46 @@ export interface SlottedDirectiveOptions<T = any> extends NodeBehaviorOptions<T>

// @public
export class Splice {
constructor(
index: number,
removed: any[],
addedCount: number);
constructor(index: number, removed: any[], addedCount: number);
// (undocumented)
addedCount: number;
adjustTo(array: any[]): this;
// (undocumented)
index: number;
// (undocumented)
static normalize(previous: unknown[] | undefined, current: unknown[], changes: Splice[] | undefined): Splice[] | undefined;
removed: any[];
reset?: boolean;
}

// @public
export interface SpliceStrategy {
normalize(previous: unknown[] | undefined, current: unknown[], changes: Splice[] | undefined): readonly Splice[];
pop(array: any[], observer: ArrayObserver, pop: typeof Array.prototype.pop, args: any[]): any;
push(array: any[], observer: ArrayObserver, push: typeof Array.prototype.push, args: any[]): any;
reverse(array: any[], observer: ArrayObserver, reverse: typeof Array.prototype.reverse, args: any[]): any;
shift(array: any[], observer: ArrayObserver, shift: typeof Array.prototype.shift, args: any[]): any;
sort(array: any[], observer: ArrayObserver, sort: typeof Array.prototype.sort, args: any[]): any[];
splice(array: any[], observer: ArrayObserver, splice: typeof Array.prototype.splice, args: any[]): any;
readonly support: SpliceStrategySupport;
unshift(array: any[], observer: ArrayObserver, unshift: typeof Array.prototype.unshift, args: any[]): any[];
}

// @public
export const SpliceStrategy: Readonly<{
readonly reset: Splice[];
readonly setDefaultStrategy: (strategy: SpliceStrategy) => void;
}>;

// @public
export const SpliceStrategySupport: Readonly<{
readonly reset: 1;
readonly splice: 2;
readonly optimized: 3;
}>;

// @public
export type SpliceStrategySupport = typeof SpliceStrategySupport[keyof typeof SpliceStrategySupport];

// @public
export abstract class StatelessAttachedAttributeDirective<T> implements HTMLDirective, ViewBehaviorFactory, ViewBehavior {
constructor(options: T);
Expand Down
4 changes: 4 additions & 0 deletions packages/web-components/fast-element/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
"./debug.js": {
"types": "./dist/dts/debug.d.ts",
"default": "./dist/esm/debug.js"
},
"./splice-strategies.js": {
"types": "./dist/dts/observation/splice-strategies.d.ts",
"default": "./dist/esm/observation/splice-strategies.js"
}
},
"unpkg": "dist/fast-element.min.js",
Expand Down
3 changes: 1 addition & 2 deletions packages/web-components/fast-element/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ export * from "./platform.js";
// Observation
export * from "./observation/observable.js";
export * from "./observation/notifier.js";
export * from "./observation/array-change-records.js";
export * from "./observation/array-observer.js";
export * from "./observation/arrays.js";
export * from "./observation/update-queue.js";
export type { Behavior } from "./observation/behavior.js";

Expand Down

This file was deleted.

Loading

0 comments on commit fc4dbc4

Please sign in to comment.