diff --git a/frameworks/solid-js-v0.0.8-keyed/.babelrc b/frameworks/solid-js-v0.0.8-keyed/.babelrc
new file mode 100644
index 000000000..de0745369
--- /dev/null
+++ b/frameworks/solid-js-v0.0.8-keyed/.babelrc
@@ -0,0 +1,3 @@
+{
+ "plugins": [["jsx-dom-expressions", {"moduleName": "Solid"}]]
+}
\ No newline at end of file
diff --git a/frameworks/solid-js-v0.0.8-keyed/index.html b/frameworks/solid-js-v0.0.8-keyed/index.html
new file mode 100644
index 000000000..f19722f2e
--- /dev/null
+++ b/frameworks/solid-js-v0.0.8-keyed/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+ SolidJS-keyed
+
+
+
+
+
+
+
diff --git a/frameworks/solid-js-v0.0.8-keyed/package.json b/frameworks/solid-js-v0.0.8-keyed/package.json
new file mode 100644
index 000000000..c81e5b25e
--- /dev/null
+++ b/frameworks/solid-js-v0.0.8-keyed/package.json
@@ -0,0 +1,26 @@
+{
+ "name": "js-framework-benchmark-solid-js",
+ "version": "0.0.8",
+ "main": "index.js",
+ "scripts": {
+ "build-dev": "rollup -c",
+ "build-prod": "rollup -c --environment production"
+ },
+ "author": "Ryan Carniato",
+ "license": "Apache-2.0",
+ "homepage": "https://github.com/krausest/js-framework-benchmark",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/krausest/js-framework-benchmark.git"
+ },
+ "dependencies": {
+ "solid-js": "0.0.8"
+ },
+ "devDependencies": {
+ "@babel/core": "7.0.0-beta.49",
+ "rollup": "0.58.2",
+ "rollup-plugin-babel": "beta",
+ "rollup-plugin-node-resolve": "3.3.0",
+ "rollup-plugin-uglify": "3.0.0"
+ }
+}
diff --git a/frameworks/solid-js-v0.0.8-keyed/rollup.config.js b/frameworks/solid-js-v0.0.8-keyed/rollup.config.js
new file mode 100644
index 000000000..23d176aaa
--- /dev/null
+++ b/frameworks/solid-js-v0.0.8-keyed/rollup.config.js
@@ -0,0 +1,23 @@
+import resolve from 'rollup-plugin-node-resolve';
+import babel from 'rollup-plugin-babel';
+import uglify from 'rollup-plugin-uglify';
+
+const plugins = [
+ babel({
+ exclude: 'node_modules/**'
+ }),
+ resolve({ extensions: ['.js', '.jsx'] })
+];
+
+if (process.env.production) {
+ plugins.push(uglify());
+}
+
+export default {
+ input: 'src/main.js',
+ output: {
+ file: 'dist/main.js',
+ format: 'iife'
+ },
+ plugins
+};
\ No newline at end of file
diff --git a/frameworks/solid-js-v0.0.8-keyed/src/app.jsx b/frameworks/solid-js-v0.0.8-keyed/src/app.jsx
new file mode 100644
index 000000000..6dece7da1
--- /dev/null
+++ b/frameworks/solid-js-v0.0.8-keyed/src/app.jsx
@@ -0,0 +1,182 @@
+import Solid, { State } from 'solid-js';
+
+function _random (max) {
+ return Math.round(Math.random() * 1000) % max;
+};
+
+function rowId ({target: el}) {
+ while (el.tagName !== 'TR') {
+ el = el.parentElement;
+ }
+ return +el.childNodes[0].textContent;
+};
+
+var idCounter = 1
+var adjectives = ["pretty", "large", "big", "small", "tall", "short", "long", "handsome", "plain", "quaint", "clean", "elegant", "easy", "angry", "crazy", "helpful", "mushy", "odd", "unsightly", "adorable", "important", "inexpensive", "cheap", "expensive", "fancy"];
+var colours = ["red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black", "orange"];
+var nouns = ["table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger", "pizza", "mouse", "keyboard"];
+function buildData(count) {
+ var data, i, ref;
+ data = new Array(count);
+ for (i = 0, ref = count; i < ref; i++) {
+ data[i] = {
+ id: idCounter++,
+ label: adjectives[_random(adjectives.length)] + " " + colours[_random(colours.length)] + " " + nouns[_random(nouns.length)]
+ }
+ }
+ return data;
+}
+
+// Chrome for some reason clears more performantly after an animation frame
+// Thanks to Adam from Surplus.js pointing that out
+async function clearAfterAnimationFrame(v) {
+ if (v.length) return v;
+
+ await new Promise(requestAnimationFrame);
+ return v;
+};
+
+export default class App {
+ static template({state, run, runLots, add, update, clear, swapRows, handleClick}) {
+ return
+
+
SolidJS Keyed
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{
+ Solid(() => state.data).mapS(row =>
+
+ {/*@skip*/row.id} |
+ {row.label} |
+ |
+ |
+
+ ).map(clearAfterAnimationFrame)
+ }
+
+
+ }
+
+ constructor() {
+ this.handleClick = this.handleClick.bind(this);
+ this.onRemove = this.onRemove.bind(this);
+ this.onSelect = this.onSelect.bind(this);
+ this.run = this.run.bind(this);
+ this.runLots = this.runLots.bind(this);
+ this.add = this.add.bind(this);
+ this.update = this.update.bind(this);
+ this.swapRows = this.swapRows.bind(this);
+ this.clear = this.clear.bind(this);
+ this.state = new State({
+ data: [],
+ selected: null
+ });
+ }
+
+ handleClick(e) {
+ var el;
+ e.stopPropagation();
+ if (e.target.matches('.delete')) {
+ return this.onRemove(rowId(e));
+ } else {
+ el = e.target;
+ while (el.tagName !== 'TR') {
+ el = el.parentElement;
+ }
+ return this.onSelect(el);
+ }
+ }
+
+ onRemove(id) {
+ this.state.set({
+ data: this.state.data.filter(function(test) {
+ return test.id !== id;
+ })
+ });
+ }
+
+ onSelect(newSelected) {
+ var selected;
+ if (newSelected === (selected = this.state.selected)) {
+ return;
+ }
+ if (selected) {
+ selected.className = '';
+ }
+ newSelected.className = 'danger';
+ this.state.set({
+ selected: newSelected
+ });
+ }
+
+ run(e) {
+ e.stopPropagation();
+ this.state.set({
+ data: buildData(1000),
+ selected: null
+ });
+ }
+
+ runLots(e) {
+ e.stopPropagation();
+ this.state.set({
+ data: buildData(10000),
+ selected: null
+ });
+ }
+
+ add(e) {
+ e.stopPropagation();
+ this.state.set({
+ data: this.state.data.concat(buildData(1000))
+ });
+ }
+
+ update(e) {
+ var index;
+ e.stopPropagation();
+ index = 0;
+ while (index < this.state.data.length) {
+ this.state.replace('data', index, 'label', this.state.data[index].label += ' !!!');
+ index += 10;
+ }
+ }
+
+ swapRows(e) {
+ e.stopPropagation();
+ if (this.state.data.length >= 998) {
+ this.state.set('data', {
+ 1: this.state.data[998],
+ 998: this.state.data[1]
+ });
+ }
+ }
+
+ clear(e) {
+ e.stopPropagation();
+ this.state.set({
+ data: [],
+ selected: null
+ });
+ }
+};
+
diff --git a/frameworks/solid-js-v0.0.8-keyed/src/main.js b/frameworks/solid-js-v0.0.8-keyed/src/main.js
new file mode 100644
index 000000000..b329747c4
--- /dev/null
+++ b/frameworks/solid-js-v0.0.8-keyed/src/main.js
@@ -0,0 +1,7 @@
+import Solid from 'solid-js'
+import App from './app'
+
+Solid.root(() => {
+ var app = new App()
+ document.getElementById("main").appendChild(App.template(app));
+})
\ No newline at end of file
diff --git a/webdriver-ts/src/common.ts b/webdriver-ts/src/common.ts
index 66465cc4e..85394bdc9 100644
--- a/webdriver-ts/src/common.ts
+++ b/webdriver-ts/src/common.ts
@@ -133,6 +133,7 @@ export let frameworks = [
f("san-v3.5.5-non-keyed", false),
f("simulacra-v2.1.5-non-keyed", false),
f("slim-js-v3.0.2-non-keyed", false),
+ f("solid-js-v0.0.8-keyed", true),
f("stem-v0.2.70-non-keyed", false),
f("surplus-v0.5.0-keyed", true),
f("surplus-v0.5.0-non-keyed", false),