diff --git a/LICENSE b/LICENSE index dfa2290..c2f5fd0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014 Massimo Artizzu (MaxArt2501) +Copyright (c) 2014-2015 Massimo Artizzu (MaxArt2501) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/benchmark/benchmarks-lite.js b/benchmark/benchmarks-lite.js new file mode 100644 index 0000000..0854f56 --- /dev/null +++ b/benchmark/benchmarks-lite.js @@ -0,0 +1,143 @@ +(function(root, tests) { + if (typeof define === "function" && define.amd) + define(["expect", "object-observe-lite"], tests); + else if (typeof exports === "object") + tests(require("benchmark"), global, require("../dist/object-observe-lite.js")); + else tests(root.Benchmark, root); +})(this, function(Benchmark, root) { +"use strict"; + +root.generateObject = function(numberOfProperties) { + var object = {}; + + for (var i = 0; i < numberOfProperties; i++) + object["prop" + i] = i; + + return object; +} + +function noop() {} + +var padspace = (new Array(81)).join(" "); +function padL(text, length) { + return (padspace + text).slice(-length); +} +function padR(text, length) { + return (text + padspace).slice(0, length); +} + +var onDOM = typeof document !== "undefined"; + +if (onDOM) { + var parent = document.getElementsByTagName("tbody")[0]; + + var initBench = function() { + var row = this.row = document.createElement("tr"), + cell = document.createElement("td"); + cell.innerHTML = this.props; + row.appendChild(cell); + cell = document.createElement("td"); + cell.innerHTML = this.objects; + row.appendChild(cell); + cell = document.createElement("td"); + cell.className = "changes"; + cell.innerHTML = this.name; + row.appendChild(cell); + + this.cells = []; + cell = document.createElement("td"); + cell.className = "samples"; + this.cells.push(cell); + row.appendChild(cell); + cell = document.createElement("td"); + cell.className = "count"; + this.cells.push(cell); + row.appendChild(cell); + cell = document.createElement("td"); + cell.className = "frequency"; + this.cells.push(cell); + row.appendChild(cell); + + parent.appendChild(row); + }, + onCycle = function() { + this.cells[0].innerHTML = ++this.samples; + this.cells[1].innerHTML = this.count; + this.cells[2].innerHTML = this.hz.toFixed(2); + }; +} else { + var writeOut = typeof process === "undefined" || !process.stdout || !process.stdout.isTTY + ? function(text) { console.log(text); } + : function(text) { process.stdout.write(text); }; + writeOut("\x1b[1;37mProperties Objects Changes Samples Loops FPS (Hz)\n"); + writeOut( "---------------------------------------------------------------------"); + var initBench = function() { + writeOut("\n\x1b[1;30m" + padL(this.props, 10) + " " + padL(this.objects, 7) + " " + padR(this.name, 48)); + }, + onCycle = function() { + writeOut("\x1b[38D\x1b[1;31m" + padL(++this.samples, 9) + "\x1b[1;36m" + padL(this.count, 12) + + "\x1b[1;32m" + padL(this.hz.toFixed(2), 17) + "\x1b[0;37m"); + }; +} + +function errorBench(e) { + console.log(e); +} + +var benches = []; + +function generateBenchGroup(props, objects) { + var propsPerObject = props / objects; + var options = { + setup: "\ + var handler = function() {};\n\ + var objects = [];\n\ + for (var i = 0; i < " + objects + "; i++) {\n\ + objects[i] = generateObject(" + propsPerObject + ");\n\ + Object.observe(objects[i], handler);\n\ + }\n", + teardown: "\ + for (var i = 0; i < " + objects + "; i++)\ + Object.unobserve(objects[i], handler);\n", + props: props, + objects: objects, + onStart: initBench, + onCycle: onCycle, + onError: errorBench, + onComplete: nextBench, + async: true, + samples: 0 + }; + var midIndex = objects >> 1, + midProp = "prop" + (propsPerObject >> 1); + + benches.push(new Benchmark("none", "\ + Object.deliverChangeRecords(handler);\n", options)); + benches.push(new Benchmark("one", "\ + objects[" + midIndex + "]." + midProp + "++;\n\ + Object.deliverChangeRecords(handler);\n", options)); + benches.push(new Benchmark("all", "\ + for (var i = 0; i < " + objects + "; i++)\n\ + for (var j = 0; j < " + propsPerObject + "; j++)\n\ + objects[i][\"prop\" + j]++;\n\ + Object.deliverChangeRecords(handler);\n", options)); +} + +generateBenchGroup(10, 1); +generateBenchGroup(10, 2); +generateBenchGroup(100, 1); +generateBenchGroup(100, 20); +generateBenchGroup(1000, 1); +generateBenchGroup(1000, 200); + +var index = 0; + +function nextBench() { + if (index >= benches.length) return; + + benches[index++].run(); +} + +nextBench(); + +}); diff --git a/benchmark/benchmarks.js b/benchmark/benchmarks.js new file mode 100644 index 0000000..b63599f --- /dev/null +++ b/benchmark/benchmarks.js @@ -0,0 +1,143 @@ +(function(root, tests) { + if (typeof define === "function" && define.amd) + define(["expect", "object-observe"], tests); + else if (typeof exports === "object") + tests(require("benchmark"), global, require("../dist/object-observe.js")); + else tests(root.Benchmark, root); +})(this, function(Benchmark, root) { +"use strict"; + +root.generateObject = function(numberOfProperties) { + var object = {}; + + for (var i = 0; i < numberOfProperties; i++) + object["prop" + i] = i; + + return object; +} + +function noop() {} + +var padspace = (new Array(81)).join(" "); +function padL(text, length) { + return (padspace + text).slice(-length); +} +function padR(text, length) { + return (text + padspace).slice(0, length); +} + +var onDOM = typeof document !== "undefined"; + +if (onDOM) { + var parent = document.getElementsByTagName("tbody")[0]; + + var initBench = function() { + var row = this.row = document.createElement("tr"), + cell = document.createElement("td"); + cell.innerHTML = this.props; + row.appendChild(cell); + cell = document.createElement("td"); + cell.innerHTML = this.objects; + row.appendChild(cell); + cell = document.createElement("td"); + cell.className = "changes"; + cell.innerHTML = this.name; + row.appendChild(cell); + + this.cells = []; + cell = document.createElement("td"); + cell.className = "samples"; + this.cells.push(cell); + row.appendChild(cell); + cell = document.createElement("td"); + cell.className = "count"; + this.cells.push(cell); + row.appendChild(cell); + cell = document.createElement("td"); + cell.className = "frequency"; + this.cells.push(cell); + row.appendChild(cell); + + parent.appendChild(row); + }, + onCycle = function() { + this.cells[0].innerHTML = ++this.samples; + this.cells[1].innerHTML = this.count; + this.cells[2].innerHTML = this.hz.toFixed(2); + }; +} else { + var writeOut = typeof process === "undefined" || !process.stdout || !process.stdout.isTTY + ? function(text) { console.log(text); } + : function(text) { process.stdout.write(text); }; + writeOut("\x1b[1;37mProperties Objects Changes Samples Loops FPS (Hz)\n"); + writeOut( "---------------------------------------------------------------------"); + var initBench = function() { + writeOut("\n\x1b[1;30m" + padL(this.props, 10) + " " + padL(this.objects, 7) + " " + padR(this.name, 48)); + }, + onCycle = function() { + writeOut("\x1b[38D\x1b[1;31m" + padL(++this.samples, 9) + "\x1b[1;36m" + padL(this.count, 12) + + "\x1b[1;32m" + padL(this.hz.toFixed(2), 17) + "\x1b[0;37m"); + }; +} + +function errorBench(e) { + console.log(e); +} + +var benches = []; + +function generateBenchGroup(props, objects) { + var propsPerObject = props / objects; + var options = { + setup: "\ + var handler = function() {};\n\ + var objects = [];\n\ + for (var i = 0; i < " + objects + "; i++) {\n\ + objects[i] = generateObject(" + propsPerObject + ");\n\ + Object.observe(objects[i], handler);\n\ + }\n", + teardown: "\ + for (var i = 0; i < " + objects + "; i++)\ + Object.unobserve(objects[i], handler);\n", + props: props, + objects: objects, + onStart: initBench, + onCycle: onCycle, + onError: errorBench, + onComplete: nextBench, + async: true, + samples: 0 + }; + var midIndex = objects >> 1, + midProp = "prop" + (propsPerObject >> 1); + + benches.push(new Benchmark("none", "\ + Object.deliverChangeRecords(handler);\n", options)); + benches.push(new Benchmark("one", "\ + objects[" + midIndex + "]." + midProp + "++;\n\ + Object.deliverChangeRecords(handler);\n", options)); + benches.push(new Benchmark("all", "\ + for (var i = 0; i < " + objects + "; i++)\n\ + for (var j = 0; j < " + propsPerObject + "; j++)\n\ + objects[i][\"prop\" + j]++;\n\ + Object.deliverChangeRecords(handler);\n", options)); +} + +generateBenchGroup(10, 1); +generateBenchGroup(10, 2); +generateBenchGroup(100, 1); +generateBenchGroup(100, 20); +generateBenchGroup(1000, 1); +generateBenchGroup(1000, 200); + +var index = 0; + +function nextBench() { + if (index >= benches.length) return; + + benches[index++].run(); +} + +nextBench(); + +}); diff --git a/benchmark/index-lite.html b/benchmark/index-lite.html new file mode 100644 index 0000000..0357b21 --- /dev/null +++ b/benchmark/index-lite.html @@ -0,0 +1,48 @@ + + + + + Object.observe polyfill tests + + + + + + + + + + + + + + + +
PropertiesObjectsChangesSamplesLoopsFPS (Hz)
+ Regular version + + + + + diff --git a/benchmark/index.html b/benchmark/index.html new file mode 100644 index 0000000..bbe0776 --- /dev/null +++ b/benchmark/index.html @@ -0,0 +1,48 @@ + + + + + Object.observe polyfill tests + + + + + + + + + + + + + + + +
PropertiesObjectsChangesSamplesLoopsFPS (Hz)
+ Lite version + + + + + diff --git a/doc/benchmarks.md b/doc/benchmarks.md new file mode 100644 index 0000000..174ea5a --- /dev/null +++ b/doc/benchmarks.md @@ -0,0 +1,124 @@ +Benchmarks +========== + +Here are some benchmarks performed using [benchmark.js](http://benchmarkjs.com/), the library behind [jsPerf](http://jsperf.com/). Old one, but still good. + +To ensure the most reliable results, the polyfill is tested *synchronously*, which can be done using `Object.deliverChangeRecords`. + +The *Properties* column refers to the number of properties that are subject to observation. The *Objects* column means the number of observed objects. For example, if the number of properties is 100 and the objects are 20, then each object has 5 properties. + +The *Changes* column tells how many changes are performed in the test. When it's "all", then all properties are changed. No properties are added or deleted, no property descriptors are altered, object frozen or prototype changed. It's a mere benchmark on the dirty checking routine. + +The results are given in cycles per second, with some native implementations given as a reference. Keep in mind that *anything above 60 Hz is more than enough*, as the polyfill caps the iterations to 60 frames per second. + +## Desktop/server + +Test platform: +* Chrome, io.js, node.js, Edge, IE and Firefox on Windows 10 64 bit (Intel Core i7-4702, 2.2 GHz, 8 GB RAM) + +### Regular version + +| Properties | Objects | Changes | Chrome 44 (native) | io.js (native) | Edge 20 | IE 11 | Firefox 42 | Safari 8 | node.js 0.10.40 | +|-----------:|--------:|:--------|-------------------:|---------------:|-----------:|----------:|-----------:|---------:|----------------:| +| 10 | 1 | none | 12695226.07 | 9049899.39 | 130434.97 | 83872.44 | 73352.65 | | 101291.62 | +| 10 | 1 | one | 474152.37 | 605161.84 | 125770.03 | 78540.56 | 69110.05 | | 99470.16 | +| 10 | 1 | all | 65370.32 | 72723.21 | 73645.72 | 50913.31 | 33597.83 | | 67420.76 | +| 10 | 2 | none | 11055704.90 | 9714097.84 | 124025.56 | 83853.47 | 74785.66 | | 98065.76 | +| 10 | 2 | one | 503978.73 | 345396.99 | 117530.59 | 79384.80 | 67676.77 | | 63901.37 | +| 10 | 2 | all | 65479.07 | 49071.59 | 71660.27 | 50796.94 | 34059.22 | | 63650.51 | +| 100 | 1 | none | 12556039.14 | 7948191.02 | 9989.80 | 5757.68 | 4517.18 | | 8092.19 | +| 100 | 1 | one | 480307.76 | 280002.44 | 10109.94 | 5094.36 | 4462.59 | | 7969.60 | +| 100 | 1 | all | 7745.07 | 4670.98 | 5989.60 | 3859.97 | 2596.89 | | 5494.10 | +| 100 | 20 | none | 12055798.16 | 9231993.34 | 11334.37 | 7884.65 | 7873.30 | | 9814.64 | +| 100 | 20 | one | 482869.76 | 393232.06 | 11699.48 | 7992.85 | 7885.51 | | 9515.44 | +| 100 | 20 | all | 7233.48 | 6120.82 | 6447.95 | 4896.90 | 3347.28 | | 5914.51 | +| 1000 | 1 | none | 10151267.78 | 7107230.89 | 280.01 | 122.47 | 79.84 | | 249.47 | +| 1000 | 1 | one | 502903.60 | 278385.46 | 268.66 | 119.83 | 79.85 | | 247.07 | +| 1000 | 1 | all | 779.45 | 798.78 | 232.99 | 106.65 | 68.20 | | 229.31 | +| 1000 | 200 | none | 10414350.34 | 10352455.73 | 1163.79 | 805.99 | 803.90 | | 972.77 | +| 1000 | 200 | one | 496837.38 | 359983.36 | 1042.34 | 679.55 | 785.10 | | 962.21 | +| 1000 | 200 | all | 743.03 | 532.97 | 620.28 | 481.21 | 364.61 | | 483.60 | + + +### Lite version + +| Properties | Objects | Changes | Chrome 44 (native) | io.js (native) | Edge 20 | IE 11 | Firefox 42 | Safari 8 | node.js 0.10.40 | +|-----------:|--------:|:--------|-------------------:|---------------:|-----------:|----------:|-----------:|---------:|----------------:| +| 10 | 1 | none | 12695226.07 | 9049899.39 | 396917.52 | 366848.35 | 216419.76 | | 214778.07 | +| 10 | 1 | one | 474152.37 | 605161.84 | 327993.13 | 320364.92 | 157258.96 | | 200435.74 | +| 10 | 1 | all | 65370.32 | 72723.21 | 87167.82 | 110067.97 | 49040.88 | | 103307.57 | +| 10 | 2 | none | 11055704.90 | 9714097.84 | 348254.48 | 373360.56 | 208276.39 | | 191128.14 | +| 10 | 2 | one | 503978.73 | 345396.99 | 316159.48 | 289281.85 | 150637.00 | | 180886.68 | +| 10 | 2 | all | 65479.07 | 49071.59 | 106801.76 | 105960.07 | 48047.94 | | 98055.80 | +| 100 | 1 | none | 12556039.14 | 7948191.02 | 21057.95 | 11794.79 | 7012.34 | | 13166.59 | +| 100 | 1 | one | 480307.76 | 280002.44 | 21536.84 | 10974.59 | 6959.01 | | 9922.74 | +| 100 | 1 | all | 7745.07 | 4670.98 | 8787.08 | 6385.73 | 2867.63 | | 8140.72 | +| 100 | 20 | none | 12055798.16 | 9231993.34 | 37112.96 | 36455.26 | 22106.36 | | 20560.18 | +| 100 | 20 | one | 482869.76 | 393232.06 | 33943.99 | 40519.03 | 21700.42 | | 19932.32 | +| 100 | 20 | all | 7233.48 | 6120.82 | 10537.17 | 10312.76 | 4841.93 | | 9720.20 | +| 1000 | 1 | none | 10151267.78 | 7107230.89 | 328.28 | 144.99 | 85.34 | | 267.41 | +| 1000 | 1 | one | 502903.60 | 278385.46 | 326.86 | 138.71 | 85.74 | | 271.37 | +| 1000 | 1 | all | 779.45 | 798.78 | 255.39 | 129.40 | 74.68 | | 234.86 | +| 1000 | 200 | none | 10414350.34 | 10352455.73 | 3637.22 | 4146.43 | 2312.70 | | 2019.55 | +| 1000 | 200 | one | 496837.38 | 359983.36 | 3621.43 | 3570.93 | 2176.87 | | 2034.43 | +| 1000 | 200 | all | 743.03 | 532.97 | 1015.30 | 905.53 | 510.69 | | 665.03 | + + +## Mobile + +Test platforms: +* Chrome 44, Firefox 40 on Samsung Galaxy Note 3 with Android 5.0 (Qualcomm Snapdragon 800, quad core, 2.3 GHz, 3 GB RAM) + +### Regular version + +| Properties | Objects | Changes | Chrome 44 (native) | Firefox 40 | Safari 8 | Blackberry 10 | IE Mobile | +|-----------:|--------:|:--------|-------------------:|-----------:|---------:|--------------:|----------:| +| 10 | 1 | none | 2935925.26 | 12597.76 | | | | +| 10 | 1 | one | 45891.64 | 7942.07 | | | | +| 10 | 1 | all | 6731.94 | 3729.48 | | | | +| 10 | 2 | none | 2840198.42 | 7375.12 | | | | +| 10 | 2 | one | 44824.87 | 9923.59 | | | | +| 10 | 2 | all | 5669.78 | 3906.25 | | | | +| 100 | 1 | none | 3189570.94 | 1018.38 | | | | +| 100 | 1 | one | 40600.19 | 1008.52 | | | | +| 100 | 1 | all | 890.46 | 361.72 | | | | +| 100 | 20 | none | 3165550.58 | 1357.33 | | | | +| 100 | 20 | one | 40863.50 | 1260.03 | | | | +| 100 | 20 | all | 677.30 | 325.42 | | | | +| 1000 | 1 | none | 2059353.05 | 27.43 | | | | +| 1000 | 1 | one | 45913.34 | 26.62 | | | | +| 1000 | 1 | all | 76.61 | 18.59 | | | | +| 1000 | 200 | none | 2968757.38 | 70.96 | | | | +| 1000 | 200 | one | 41713.60 | 113.50 | | | | +| 1000 | 200 | all | 76.98 | 41.75 | | | | + +### Lite version + +| Properties | Objects | Changes | Chrome 44 (native) | Firefox 40 | Safari 8 | Blackberry 10 | IE Mobile | +|-----------:|--------:|:--------|-------------------:|-----------:|---------:|--------------:|----------:| +| 10 | 1 | none | 2935925.26 | 28742.57 | | | | +| 10 | 1 | one | 45891.64 | 18272.91 | | | | +| 10 | 1 | all | 6731.94 | 4773.90 | | | | +| 10 | 2 | none | 2840198.42 | 22611.80 | | | | +| 10 | 2 | one | 44824.87 | 19874.12 | | | | +| 10 | 2 | all | 5669.78 | 4786.42 | | | | +| 100 | 1 | none | 3189570.94 | 2581.15 | | | | +| 100 | 1 | one | 40600.19 | 2278.73 | | | | +| 100 | 1 | all | 890.46 | 401.35 | | | | +| 100 | 20 | none | 3165550.58 | 3198.00 | | | | +| 100 | 20 | one | 40863.50 | 3298.02 | | | | +| 100 | 20 | all | 677.30 | 522.06 | | | | +| 1000 | 1 | none | 2059353.05 | 26.63 | | | | +| 1000 | 1 | one | 45913.34 | 31.63 | | | | +| 1000 | 1 | all | 76.61 | 10.59 | | | | +| 1000 | 200 | none | 2968757.38 | 316.54 | | | | +| 1000 | 200 | one | 41713.60 | 381.54 | | | | +| 1000 | 200 | all | 76.98 | 49.85 | | | | + +## Running the benchmarks + +After having installed the development dependencies with `npm install`, open the [index.html](../benchmark/index.html) file in the benchmark/ directory (or its counterpart [index-lite.html](../benchmark/index-lite.html) for the "lite" version of the polyfill) in your browser of choice. + +To test node.js < 0.11.13, run `npm run benchmark` or `npm run benchmark-lite`. Any other version of node.js, or io.js, will test a native implentation of `Object.observe`. + +For other environments, refer to [benchmarks.js](../benchmark/benchmarks.js) or its ["lite" counterpart](../benchmark/benchmarks-lite.js). diff --git a/package.json b/package.json index 0aaf3e1..7ad056f 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,9 @@ "test": "test" }, "scripts": { - "test": "node_modules/.bin/mocha" + "test": "node_modules/.bin/mocha", + "benchmark": "node benchmark/benchmark.js", + "benchmark-lite": "node benchmark/benchmark-lite.js" }, "repository": { "type": "git", @@ -28,6 +30,7 @@ }, "homepage": "https://github.com/MaxArt2501/object-observe", "devDependencies": { + "benchmark": "^1.0.0", "expect.js": "^0.3.1", "mocha": "^2.1.0" } diff --git a/readme.md b/readme.md index 957701c..3d4e362 100644 --- a/readme.md +++ b/readme.md @@ -85,14 +85,21 @@ For more details about loading the polyfill on a client, read the [documentation This polyfill has been tested (and is working) in the following environments: -* Firefox 35-36 stable and 37-38 Developer Edition +* Firefox 35-39 stable and 37-41 Developer Edition * Internet Explorer 11 * Microsoft Edge 20 +* Safari desktop 8 +* Safari iOS 8.2 +* Android browser 4.4 * Internet Explorer 5, 7, 8, 9, 10 (as IE11 in emulation mode) * node.js 0.10.33-40 It also does *not* overwrite the native implentation in Chrome 36+, Opera 23+, node.js 0.11.13+ and io.js. +## Performances + +Some benchmarks have been done on the dirty checking loop. See [the docs](doc/benchmarks.md) for more details. + ## License The MIT License (MIT) diff --git a/test/tests.js b/test/tests.js index 4bafdda..695d0f4 100644 --- a/test/tests.js +++ b/test/tests.js @@ -27,6 +27,8 @@ if (typeof Object.observe === "function") : "Object.observe has been correctly polyfilled"); else console.log("Object.observe has NOT been polyfilled"); +var timeout = 30; + describe("Object.observe", function() { it("should notify 'add', 'update' and 'delete' changes", function(done) { function handler(changes) { @@ -55,7 +57,7 @@ describe("Object.observe", function() { expect(tested).to.be(true); done(); } catch (e) { done(e); } - }, 30); + }, timeout); }); it("should only notify on actual changes", function(done) { @@ -77,7 +79,7 @@ describe("Object.observe", function() { expect(changed).to.be(false); done(); } catch (e) { done(e); } - }, 30); + }, timeout); }); it("should observe plain objects", function(done) { @@ -101,7 +103,7 @@ describe("Object.observe", function() { expect(tested).to.be(true); done(); } catch (e) { done(e); } - }, 30); + }, timeout); }); it("should observe arrays", function(done) { @@ -127,7 +129,7 @@ describe("Object.observe", function() { expect(tested).to.be(true); done(); } catch (e) { done(e); } - }, 30); + }, timeout); }); it("should observe functions", function(done) { @@ -153,7 +155,7 @@ describe("Object.observe", function() { expect(tested).to.be(true); done(); } catch (e) { done(e); } - }, 30); + }, timeout); }); it("should observe all kinds of objects, including instances of user defined classes", function(done) { @@ -193,7 +195,7 @@ describe("Object.observe", function() { expect(tested).to.be(true); done(); } catch (e) { done(e); } - }, 30); + }, timeout); }); it("should throw when given any non-object", function() { @@ -255,7 +257,7 @@ describe("Object.observe", function() { expect(tested).to.be(true); done(); } catch (e) { done(e); } - }, 30); + }, timeout); }); if (Object.defineProperties) it("should notify 'reconfigure' changes", function(done) { @@ -281,7 +283,7 @@ describe("Object.observe", function() { expect(tested).to.be(true); done(); } catch (e) { done(e); } - }, 30); + }, timeout); }); if (Object.seal) it("should notify 'preventExtensions' changes", function(done) { @@ -307,7 +309,7 @@ describe("Object.observe", function() { expect(tested).to.be(true); done(); } catch (e) { done(e); } - }, 30); + }, timeout); }); var setProto = Object.setPrototypeOf || "__proto__" in {} @@ -335,7 +337,7 @@ describe("Object.observe", function() { expect(tested).to.be(true); done(); } catch (e) { done(e); } - }, 30); + }, timeout); }); it("should deliver changes for multiple objects observed by the same handler", function(done) { @@ -366,7 +368,7 @@ describe("Object.observe", function() { expect(tested).to.be(true); done(); } catch (e) { done(e); } - }, 30); + }, timeout); }); it("should not follow changes in the accept list array", function(done) { @@ -395,7 +397,7 @@ describe("Object.observe", function() { expect(tested).to.be(true); done(); } catch (e) { done(e); } - }, 30); + }, timeout); }); }); @@ -425,7 +427,7 @@ describe("Object.unobserve", function() { expect(tested).to.be(true); done(); } catch (e) { done(e); } - }, 30); + }, timeout); }); it("should allow asynchronous delivering of pending changes", function(done) { @@ -452,7 +454,7 @@ describe("Object.unobserve", function() { expect(tested).to.be(true); done(); } catch (e) { done(e); } - }, 30); + }, timeout); }); it("should unobserve one handler at time", function(done) { @@ -485,7 +487,7 @@ describe("Object.unobserve", function() { expect(tested).to.be(true); done(); } catch (e) { done(e); } - }, 30); + }, timeout); }); it("should not throw errors on any non-observed object", function() { @@ -622,7 +624,7 @@ describe("Object.getNotifier", function() { expect(tested).to.be(true); done(); } catch (e) { done(e); } - }, 30); + }, timeout); }); it("should ignore other changes when performing a custom change", function(done) { @@ -654,7 +656,7 @@ describe("Object.getNotifier", function() { expect(tested).to.be(true); done(); } catch (e) { done(e); } - }, 30); + }, timeout); }); it("should notify a custom record when performing a custom change returns an object", function(done) { @@ -683,7 +685,7 @@ describe("Object.getNotifier", function() { expect(tested).to.be(true); done(); } catch (e) { done(e); } - }, 30); + }, timeout); }); it("should perform custom changes synchronously", function() { @@ -724,8 +726,8 @@ describe("Object.getNotifier", function() { expect(tested).to.be(true); done(); } catch (e) { done(e); } - }, 30); + }, timeout); }); }); -}); \ No newline at end of file +});