Skip to content

Commit

Permalink
start todomvc
Browse files Browse the repository at this point in the history
  • Loading branch information
mbasso committed May 5, 2017
1 parent f33da73 commit 3f14495
Show file tree
Hide file tree
Showing 34 changed files with 667 additions and 122 deletions.
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ and add this object to your loaders:
}
```

also, if you have some problems with fs, you can add this to your webpack config:

```js
node: {
fs: 'empty',
},
```

## Motivation
asm-dom is a minimal WebAssembly virtual DOM focused on performance. It is born from the idea to test the powerful of WebAssembly in a common use case that is not gaming, VR, AR or Image / video editing. Unfortunately, at the moment, [GC / DOM / Web API Integration](http://webassembly.org/docs/gc/) is a future feature 🦄, so, asm-dom isn't totally developed in wasm. All interactions with the DOM are written in Javascript. This is a big disadvantage because of the overhead of the binding between JS and WASM, in the future asm-dom will be even more powerful, anyway results are satisfying.
Last but not least, this project aims to be an example for those who want to try WebAssembly and emscripten!
Expand Down Expand Up @@ -96,7 +104,7 @@ By default asm-dom returns an `init` function that takes an optional configurati

By default asm-dom uses WebAssembly if supported, otherwise asm.js

Please note that **this function have to be called only one time in your application**.
Please note that **this function creates the module only the first time that is called, the next times returns a Promise that resolve with the same, cached object**.

```js
import init from 'asm-dom';
Expand Down Expand Up @@ -152,8 +160,7 @@ patch(vnode, newVnode);
Here is a list of things that have to be done to complete this project:

- examples
- sometimes tests fail in a non-deterministic way with error `err.uncaught = true;`
- use requestAnimationFrame? (there is a branch with this name)
- sometimes tests fail in a non-deterministic way with error `err.uncaught = true;`
- use the closure compiler (cause problems with wasm, need to update emscripten)

## Benchmarks
Expand Down
Binary file modified compiled/asm-dom.bc
Binary file not shown.
Binary file modified compiled/asm-dom.o
Binary file not shown.
10 changes: 5 additions & 5 deletions compiled/asmjs/asm-dom.asm.js

Large diffs are not rendered by default.

94 changes: 47 additions & 47 deletions compiled/wasm/asm-dom.asm.js

Large diffs are not rendered by default.

Binary file modified compiled/wasm/asm-dom.wasm
Binary file not shown.
18 changes: 18 additions & 0 deletions examples/todomvc/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"presets": ["es2015", "stage-0"],
"plugins": [
"dynamic-import-webpack",
"transform-object-rest-spread",
"transform-es3-member-expression-literals",
"transform-es3-property-literals"
],
"env": {
"commonjs": {
"plugins": [
["transform-es2015-modules-commonjs", { "loose": true }]]
},
"es": {
"plugins": []
}
}
}
15 changes: 15 additions & 0 deletions examples/todomvc/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# EditorConfig helps developers define and maintain
# consistent coding styles between different editors and IDEs.

root = true

[*]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
indent_style = tab
indent_size = 2

[*.md]
trim_trailing_whitespace = false
2 changes: 2 additions & 0 deletions examples/todomvc/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
**/dist/**
**/node_modules/**
34 changes: 34 additions & 0 deletions examples/todomvc/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"ecmaFeatures": {
"modules": true
},
"env": {
"browser": true,
"node": true
},
"parser": "babel-eslint",
"rules": {
"global-require": "off",
"object-shorthand": "off",
"no-mixed-operators": "off",
"no-plusplus": "off",
"no-continue": "off",
"dot-notation": "off",
"no-restricted-syntax": "off",
"quote-props": "off",
"no-underscore-dangle": "off",
"no-param-reassign": "off",
"valid-jsdoc": 2,
"quotes": [2, "single"],
"strict": [2, "never"]
},
"extends": "airbnb/base",
"globals": {
"describe" : false,
"it" : false,
"before" : false,
"beforeEach" : false,
"after" : false,
"afterEach" : false
}
}
10 changes: 10 additions & 0 deletions examples/todomvc/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
node_modules
.DS_Store
*.log
dist
lib
es
coverage
_book
.nyc_output
.vscode
43 changes: 43 additions & 0 deletions examples/todomvc/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"name": "reorder-animation",
"version": "0.0.1",
"description": "A simple asm-dom example",
"scripts": {
"start": "webpack-dev-server --env.dev",
"build": "cross-env BABEL_ENV=commonjs webpack --env.prod src/index.js",
"lint": "eslint src"
},
"devDependencies": {
"arraybuffer-loader": "0.2.2",
"babel-cli": "6.24.1",
"babel-core": "6.24.1",
"babel-eslint": "7.2.3",
"babel-loader": "7.0.0",
"babel-plugin-dynamic-import-webpack": "1.0.1",
"babel-plugin-transform-es2015-modules-commonjs": "6.24.1",
"babel-plugin-transform-es3-member-expression-literals": "6.22.0",
"babel-plugin-transform-es3-property-literals": "6.22.0",
"babel-plugin-transform-object-rest-spread": "6.23.0",
"babel-preset-es2015": "6.24.1",
"babel-preset-stage-0": "6.24.1",
"babel-register": "6.24.1",
"compression-webpack-plugin": "0.4.0",
"cross-env": "4.0.0",
"css-loader": "0.28.1",
"eslint": "3.19.0",
"eslint-config-airbnb": "14.1.0",
"eslint-plugin-import": "2.2.0",
"eslint-plugin-jsx-a11y": "4.0.0",
"eslint-plugin-react": "6.10.3",
"style-loader": "0.17.0",
"webpack": "2.4.1",
"webpack-dev-server": "2.4.5"
},
"dependencies": {
"asm-dom": "file:../../",
"babel-polyfill": "6.23.0",
"todomvc-app-css": "2.0.1",
"todomvc-common": "1.0.2",
"union-type": "0.1.6"
}
}
41 changes: 41 additions & 0 deletions examples/todomvc/src/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
export function classnames(obj) {
return Object.keys(obj).reduce((x, y) => {
if (obj[y]) {
return `${x} ${y}`;
}
return x;
}, '');
}

export function isBoolean(arg) {
return typeof arg === 'boolean';
}

export function bind(fn, ...args) {
return (...args2) => fn(...[...args, ...args2]);
}

export function sequence(...fns) {
return (...args) => {
let res = fns[0](...args);
for (let i = 1; i < fns.length; i++) {
res = fns[i](res);
}
return res;
};
}

export function propGetter(path) {
const props = path.split('.');
return (target) => {
for (let i = 0; i < props.length; i++) {
if (!target) {
target = target[props[i]];
} else {
return;
}
}
// eslint-disable-next-line
return target;
};
}
24 changes: 24 additions & 0 deletions examples/todomvc/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import init from 'asm-dom';
import 'todomvc-common/base.css';
import 'todomvc-app-css/index.css';
import todos from './todos';

init().then((asmDom) => {
const { h, patch } = asmDom;

function main(initState, oldVnode, { view, update }) {
const newVnode = view(h, initState, (e) => {
const newState = update(initState, e);
main(newState, newVnode, { view, update });
});
patch(oldVnode, newVnode);
}

const state = todos.init();

main(
state,
document.querySelector('.todoapp'),
todos,
);
});
74 changes: 74 additions & 0 deletions examples/todomvc/src/task.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import Type from 'union-type';
import { bind, sequence, isBoolean, classnames } from './helpers';

const KEY_ENTER = 13;

// model : {id: Number, title: String, done: Boolean, editing: Boolean, editingValue: String }
const Action = Type({
SetTitle: [String],
Toggle: [isBoolean],
StartEdit: [],
CommitEdit: [String],
CancelEdit: [],
});

const targetChecked = e => e.target.checked;
// const targetValue = e => e.target.value;

function onInput(handler, e) {
if (e.keyCode === KEY_ENTER) {
handler(Action.CommitEdit(e.target.value));
}
}

function view(h, task, handler, remove) {
return h('li', {
className: classnames({ completed: !!task.done && !task.editing, editing: task.editing }),
key: task.id,
}, [
h('div.view', [
h('input', {
checked: !!task.done,
type: 'checkbox',
className: 'toggle',
raw: {
onclick: sequence(targetChecked, Action.Toggle, handler),
},
}),
h('label', {
raw: {
ondblclick: bind(handler, Action.StartEdit()),
},
}, task.title),
h('button.destroy', {
className: 'destroy',
raw: {
onclick: bind(remove, task.id),
},
}),
]),
h('input', {
value: task.title,
className: 'edit',
raw: {
onblur: bind(handler, Action.CancelEdit()),
onkeydown: bind(onInput, handler),
},
}),
]);
}

function init(id, title) {
return { id, title, done: false, editing: false, editingValue: '' };
}

function update(task, action) {
return Action.case({
Toggle: done => ({ ...task, done }),
StartEdit: () => ({ ...task, editing: true, editingValue: task.title }),
CommitEdit: title => ({ ...task, title, editing: false, editingValue: '' }),
CancelEdit: () => ({ ...task, editing: false, editingValue: '' }),
}, action);
}

export default { view, init, update, Action };
Loading

0 comments on commit 3f14495

Please sign in to comment.