Skip to content

Commit

Permalink
Merge pull request #466 from StoneCypher/FluentTransitionHooks
Browse files Browse the repository at this point in the history
Fluent transition hooks, fixes StoneCypher/fsl#684, fixes StoneCypher/fsl#685, fixes StoneCypher/fsl#686
  • Loading branch information
StoneCypher committed May 12, 2022
2 parents aab4f29 + f2c361e commit c61e59e
Show file tree
Hide file tree
Showing 20 changed files with 173 additions and 53 deletions.
14 changes: 7 additions & 7 deletions benchmark/results/general.chart.html
Expand Up @@ -28,7 +28,7 @@
</head>
<body>
<div class="container">
<canvas id="chart1652389370396" width="16" height="9"></canvas>
<canvas id="chart1652390472468" width="16" height="9"></canvas>
</div>
<script>
const format = (num) => {
Expand All @@ -51,18 +51,18 @@
chunked.map((chunk) => chunk.join('')).join(' ') + fractionStr
)
}
const ctx1652389370396 = document
.getElementById('chart1652389370396')
const ctx1652390472468 = document
.getElementById('chart1652390472468')
.getContext('2d')
const chart1652389370396 = new Chart(ctx1652389370396, {
const chart1652390472468 = new Chart(ctx1652390472468, {
type: 'bar',
data: {
labels: ["Blind cycle a traffic light 500 times by transition","Blind cycle a hooked traffic light 500 times by transition","Blind cycle a traffic light 500 times by action","Blind cycle a hooked traffic light 500 times by action"],
datasets: [
{
data: [6055,1240,13648,712],
backgroundColor: ["hsl(53.244, 85%, 55%)","hsl(10.908000000000005, 85%, 55%)","hsl(120, 85%, 55%)","hsl(6.2639999999999985, 85%, 55%)"],
borderColor: ["hsl(53.244, 85%, 55%)","hsl(10.908000000000005, 85%, 55%)","hsl(120, 85%, 55%)","hsl(6.2639999999999985, 85%, 55%)"],
data: [6804,1366,14372,792],
backgroundColor: ["hsl(56.80800000000001, 85%, 55%)","hsl(11.4, 85%, 55%)","hsl(120, 85%, 55%)","hsl(6.612000000000006, 85%, 55%)"],
borderColor: ["hsl(56.80800000000001, 85%, 55%)","hsl(11.4, 85%, 55%)","hsl(120, 85%, 55%)","hsl(6.612000000000006, 85%, 55%)"],
borderWidth: 2,
},
],
Expand Down
24 changes: 12 additions & 12 deletions benchmark/results/general.json
@@ -1,31 +1,31 @@
{
"name": "General performance suite",
"date": "2022-05-12T21:02:50.396Z",
"date": "2022-05-12T21:21:12.468Z",
"version": "1.1.0",
"results": [
{
"name": "Blind cycle a traffic light 500 times by transition",
"ops": 6055,
"margin": 6.36,
"percentSlower": 55.63
"ops": 6804,
"margin": 1.94,
"percentSlower": 52.66
},
{
"name": "Blind cycle a hooked traffic light 500 times by transition",
"ops": 1240,
"margin": 2.31,
"percentSlower": 90.91
"ops": 1366,
"margin": 0.99,
"percentSlower": 90.5
},
{
"name": "Blind cycle a traffic light 500 times by action",
"ops": 13648,
"margin": 2.99,
"ops": 14372,
"margin": 2.3,
"percentSlower": 0
},
{
"name": "Blind cycle a hooked traffic light 500 times by action",
"ops": 712,
"margin": 5.72,
"percentSlower": 94.78
"ops": 792,
"margin": 1.98,
"percentSlower": 94.49
}
],
"fastest": {
Expand Down
3 changes: 3 additions & 0 deletions dist/es6/jssm.d.ts
Expand Up @@ -106,6 +106,9 @@ declare class Machine<mDT> {
hook_action(from: string, to: string, action: string, handler: HookHandler): Machine<mDT>;
hook_global_action(action: string, handler: HookHandler): Machine<mDT>;
hook_any_action(handler: HookHandler): Machine<mDT>;
hook_standard_transition(handler: HookHandler): Machine<mDT>;
hook_main_transition(handler: HookHandler): Machine<mDT>;
hook_forced_transition(handler: HookHandler): Machine<mDT>;
hook_any_transition(handler: HookHandler): Machine<mDT>;
hook_entry(to: string, handler: HookHandler): Machine<mDT>;
hook_exit(from: string, handler: HookHandler): Machine<mDT>;
Expand Down
15 changes: 15 additions & 0 deletions dist/es6/jssm.js
Expand Up @@ -781,6 +781,21 @@ class Machine {
this.set_hook({ kind: 'any action', handler });
return this;
}
hook_standard_transition(handler) {
// TODO: should this throw if setting the hook fails, or ignore it and continue?
this.set_hook({ kind: 'standard transition', handler });
return this;
}
hook_main_transition(handler) {
// TODO: should this throw if setting the hook fails, or ignore it and continue?
this.set_hook({ kind: 'main transition', handler });
return this;
}
hook_forced_transition(handler) {
// TODO: should this throw if setting the hook fails, or ignore it and continue?
this.set_hook({ kind: 'forced transition', handler });
return this;
}
hook_any_transition(handler) {
// TODO: should this throw if setting the hook fails, or ignore it and continue?
this.set_hook({ kind: 'any transition', handler });
Expand Down
6 changes: 0 additions & 6 deletions dist/es6/jssm_types.d.ts
Expand Up @@ -164,20 +164,14 @@ declare type HookDescriptionWithAction = {
};
declare type StandardTransitionHook = {
kind: 'standard transition';
from: string;
to: string;
handler: HookHandler;
};
declare type MainTransitionHook = {
kind: 'main transition';
from: string;
to: string;
handler: HookHandler;
};
declare type ForcedTransitionHook = {
kind: 'forced transition';
from: string;
to: string;
handler: HookHandler;
};
declare type AnyTransitionHook = {
Expand Down
2 changes: 1 addition & 1 deletion dist/es6/version.js
@@ -1,2 +1,2 @@
const version = "5.60.3";
const version = "5.60.4";
export { version };
2 changes: 1 addition & 1 deletion dist/jssm.es5.cjs.js

Large diffs are not rendered by default.

17 changes: 16 additions & 1 deletion dist/jssm.es5.cjs.nonmin.js
Expand Up @@ -15886,7 +15886,7 @@ function peg$parse(input, options) {
}
}

const version = "5.60.3";
const version = "5.60.4";

// whargarbl lots of these return arrays could/should be sets
/* eslint-disable complexity */
Expand Down Expand Up @@ -16667,6 +16667,21 @@ class Machine {
this.set_hook({ kind: 'any action', handler });
return this;
}
hook_standard_transition(handler) {
// TODO: should this throw if setting the hook fails, or ignore it and continue?
this.set_hook({ kind: 'standard transition', handler });
return this;
}
hook_main_transition(handler) {
// TODO: should this throw if setting the hook fails, or ignore it and continue?
this.set_hook({ kind: 'main transition', handler });
return this;
}
hook_forced_transition(handler) {
// TODO: should this throw if setting the hook fails, or ignore it and continue?
this.set_hook({ kind: 'forced transition', handler });
return this;
}
hook_any_transition(handler) {
// TODO: should this throw if setting the hook fails, or ignore it and continue?
this.set_hook({ kind: 'any transition', handler });
Expand Down
2 changes: 1 addition & 1 deletion dist/jssm.es5.iife.js

Large diffs are not rendered by default.

17 changes: 16 additions & 1 deletion dist/jssm.es5.iife.nonmin.js
Expand Up @@ -15885,7 +15885,7 @@ var jssm = (function (exports) {
}
}

const version = "5.60.3";
const version = "5.60.4";

// whargarbl lots of these return arrays could/should be sets
/* eslint-disable complexity */
Expand Down Expand Up @@ -16666,6 +16666,21 @@ var jssm = (function (exports) {
this.set_hook({ kind: 'any action', handler });
return this;
}
hook_standard_transition(handler) {
// TODO: should this throw if setting the hook fails, or ignore it and continue?
this.set_hook({ kind: 'standard transition', handler });
return this;
}
hook_main_transition(handler) {
// TODO: should this throw if setting the hook fails, or ignore it and continue?
this.set_hook({ kind: 'main transition', handler });
return this;
}
hook_forced_transition(handler) {
// TODO: should this throw if setting the hook fails, or ignore it and continue?
this.set_hook({ kind: 'forced transition', handler });
return this;
}
hook_any_transition(handler) {
// TODO: should this throw if setting the hook fails, or ignore it and continue?
this.set_hook({ kind: 'any transition', handler });
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/assets/search.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/docs/classes/Machine.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/docs/modules.html

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions jssm.d.ts
Expand Up @@ -106,6 +106,9 @@ declare class Machine<mDT> {
hook_action(from: string, to: string, action: string, handler: HookHandler): Machine<mDT>;
hook_global_action(action: string, handler: HookHandler): Machine<mDT>;
hook_any_action(handler: HookHandler): Machine<mDT>;
hook_standard_transition(handler: HookHandler): Machine<mDT>;
hook_main_transition(handler: HookHandler): Machine<mDT>;
hook_forced_transition(handler: HookHandler): Machine<mDT>;
hook_any_transition(handler: HookHandler): Machine<mDT>;
hook_entry(to: string, handler: HookHandler): Machine<mDT>;
hook_exit(from: string, handler: HookHandler): Machine<mDT>;
Expand Down
6 changes: 0 additions & 6 deletions jssm_types.d.ts
Expand Up @@ -164,20 +164,14 @@ declare type HookDescriptionWithAction = {
};
declare type StandardTransitionHook = {
kind: 'standard transition';
from: string;
to: string;
handler: HookHandler;
};
declare type MainTransitionHook = {
kind: 'main transition';
from: string;
to: string;
handler: HookHandler;
};
declare type ForcedTransitionHook = {
kind: 'forced transition';
from: string;
to: string;
handler: HookHandler;
};
declare type AnyTransitionHook = {
Expand Down
2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "jssm",
"version": "5.60.3",
"version": "5.60.4",
"engines": {
"node": ">=10.0.0"
},
Expand Down
30 changes: 30 additions & 0 deletions src/ts/jssm.ts
Expand Up @@ -1127,6 +1127,36 @@ class Machine<mDT> {



hook_standard_transition(handler: HookHandler): Machine<mDT> {

// TODO: should this throw if setting the hook fails, or ignore it and continue?
this.set_hook({ kind: 'standard transition', handler });
return this;

}



hook_main_transition(handler: HookHandler): Machine<mDT> {

// TODO: should this throw if setting the hook fails, or ignore it and continue?
this.set_hook({ kind: 'main transition', handler });
return this;

}



hook_forced_transition(handler: HookHandler): Machine<mDT> {

// TODO: should this throw if setting the hook fails, or ignore it and continue?
this.set_hook({ kind: 'forced transition', handler });
return this;

}



hook_any_transition(handler: HookHandler): Machine<mDT> {

// TODO: should this throw if setting the hook fails, or ignore it and continue?
Expand Down
6 changes: 0 additions & 6 deletions src/ts/jssm_types.ts
Expand Up @@ -328,22 +328,16 @@ type HookDescriptionWithAction = {

type StandardTransitionHook = {
kind : 'standard transition',
from : string,
to : string,
handler : HookHandler
};

type MainTransitionHook = {
kind : 'main transition',
from : string,
to : string,
handler : HookHandler
};

type ForcedTransitionHook = {
kind : 'forced transition',
from : string,
to : string,
handler : HookHandler
};

Expand Down
69 changes: 63 additions & 6 deletions src/ts/tests/hooks.spec.ts
Expand Up @@ -156,11 +156,11 @@ test('Standard transition hook rejection works', () => {

const foo = sm`a -> b;`;

foo.set_hook({ from: 'a', to: 'b', kind: 'standard transition', handler: () => false });
foo.set_hook({ kind: 'standard transition', handler: () => false });
expect(foo.transition('b')).toBe(false);
expect(foo.state()).toBe('a');

foo.set_hook({ from: 'a', to: 'b', kind: 'standard transition', handler: () => true });
foo.set_hook({ kind: 'standard transition', handler: () => true });
expect(foo.transition('b')).toBe(true);
expect(foo.state()).toBe('b');

Expand All @@ -174,11 +174,11 @@ test('Main transition hook rejection works', () => {

const foo = sm`a => b;`;

foo.set_hook({ from: 'a', to: 'b', kind: 'main transition', handler: () => false });
foo.set_hook({ kind: 'main transition', handler: () => false });
expect(foo.transition('b')).toBe(false);
expect(foo.state()).toBe('a');

foo.set_hook({ from: 'a', to: 'b', kind: 'main transition', handler: () => true });
foo.set_hook({ kind: 'main transition', handler: () => true });
expect(foo.transition('b')).toBe(true);
expect(foo.state()).toBe('b');

Expand All @@ -192,11 +192,68 @@ test('Forced transition hook rejection works', () => {

const foo = sm`a ~> b;`;

foo.set_hook({ from: 'a', to: 'b', kind: 'forced transition', handler: () => false });
foo.set_hook({ kind: 'forced transition', handler: () => false });
expect(foo.force_transition('b')).toBe(false);
expect(foo.state()).toBe('a');

foo.set_hook({ from: 'a', to: 'b', kind: 'forced transition', handler: () => true });
foo.set_hook({ kind: 'forced transition', handler: () => true });
expect(foo.force_transition('b')).toBe(true);
expect(foo.state()).toBe('b');

});





test('Standard transition fluent hook rejection works', () => {

const foo = sm`a -> b;`
.hook_standard_transition( () => false );

expect(foo.transition('b')).toBe(false);
expect(foo.state()).toBe('a');

foo.hook_standard_transition( () => true );

expect(foo.transition('b')).toBe(true);
expect(foo.state()).toBe('b');

});





test('Main transition fluent hook rejection works', () => {

const foo = sm`a => b;`
.hook_main_transition( () => false );

expect(foo.transition('b')).toBe(false);
expect(foo.state()).toBe('a');

foo.hook_main_transition( () => true );

expect(foo.transition('b')).toBe(true);
expect(foo.state()).toBe('b');

});





test('Forced transition fluent hook rejection works', () => {

const foo = sm`a ~> b;`
.hook_forced_transition( () => false );

expect(foo.force_transition('b')).toBe(false);
expect(foo.state()).toBe('a');

foo.hook_forced_transition( () => true );

expect(foo.force_transition('b')).toBe(true);
expect(foo.state()).toBe('b');

Expand Down
2 changes: 1 addition & 1 deletion src/ts/version.ts
@@ -1,3 +1,3 @@

const version: string = "5.60.3";
const version: string = "5.60.4";
export { version };

0 comments on commit c61e59e

Please sign in to comment.