Skip to content
This repository was archived by the owner on Feb 11, 2021. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 26 additions & 34 deletions src/pointermap.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,55 +2,47 @@
* This module implements an map of pointer states
*/
var USE_MAP = window.Map && window.Map.prototype.forEach;
var POINTERS_FN = function() { return this.size; };
function PointerMap() {
if (USE_MAP) {
var m = new Map();
m.pointers = POINTERS_FN;
return m;
} else {
this.keys = [];
this.values = [];
}
return USE_MAP ? new Map() : new SparseArrayMap();
}

function SparseArrayMap() {
this.array = [];
this.size = 0;
}

PointerMap.prototype = {
set: function(inId, inEvent) {
var i = this.keys.indexOf(inId);
if (i > -1) {
this.values[i] = inEvent;
} else {
this.keys.push(inId);
this.values.push(inEvent);
SparseArrayMap.prototype = {
set: function(k, v) {
if (v === undefined) {
return this.delete(k);
}
if (!this.has(k)) {
this.size++;
}
this.array[k] = v;
},
has: function(inId) {
return this.keys.indexOf(inId) > -1;
has: function(k) {
return this.array[k] !== undefined;
},
delete: function(inId) {
var i = this.keys.indexOf(inId);
if (i > -1) {
this.keys.splice(i, 1);
this.values.splice(i, 1);
delete: function(k) {
if (this.has(k)) {
delete this.array[k];
this.size--;
}
},
get: function(inId) {
var i = this.keys.indexOf(inId);
return this.values[i];
get: function(k) {
return this.array[k];
},
clear: function() {
this.keys.length = 0;
this.values.length = 0;
this.array.length = 0;
this.size = 0;
},

// return value, key, map
forEach: function(callback, thisArg) {
this.values.forEach(function(v, i) {
callback.call(thisArg, v, this.keys[i], this);
return this.array.forEach(function(v, k) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this returning?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you care to explain in plain English instead of spec prose?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ending a function in tail position allows for tail call optimization - basically, functions that end with "return" and a call to another function relinquish their stack space to the next function.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I know no JS engine currently supports that optimization.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No engine supports that optimization yet, but it's slated, so why not be ready for it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so why not be ready for it?

It may avoid call stack limits but there's no guarantee it'll bring a perf win. It's probably better to program for things that are a bit more tangible.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any chance that there will be support of tail recursion in browsers, which don't support native Map? Or am I missing something?

callback.call(thisArg, v, k, this);
}, this);
},
pointers: function() {
return this.keys.length;
}
};

Expand Down
6 changes: 3 additions & 3 deletions src/touch.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ var touchEvents = {
setPrimaryTouch: function(inTouch) {

// set primary touch if there no pointers, or the only pointer is the mouse
if (pointermap.pointers() === 0 || (pointermap.pointers() === 1 && pointermap.has(1))) {
if (pointermap.size === 0 || (pointermap.size === 1 && pointermap.has(1))) {
this.firstTouch = inTouch.identifier;
this.firstXY = { X: inTouch.clientX, Y: inTouch.clientY };
this.scrolling = false;
Expand Down Expand Up @@ -233,9 +233,9 @@ var touchEvents = {
vacuumTouches: function(inEvent) {
var tl = inEvent.touches;

// pointermap.pointers() should be < tl.length here, as the touchstart has not
// pointermap.size should be < tl.length here, as the touchstart has not
// been processed yet.
if (pointermap.pointers() >= tl.length) {
if (pointermap.size >= tl.length) {
var d = [];
pointermap.forEach(function(value, key) {

Expand Down
24 changes: 10 additions & 14 deletions tests/unit/pointermap.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ define([
'get',
'has',
'delete',
'pointers',
'size',
'clear',
'forEach'
];
Expand All @@ -26,20 +26,16 @@ define([
test('PointerMap .set', function() {
var p = new PointerMap();
p.set(1, true);
if (!window.Map || !(p instanceof Map)) {
expect(p.keys).to.have.length(1);
expect(p.values).to.have.length(1);
}
expect(p.pointers()).to.equal(1);
expect(p.size).to.equal(1);
});
test('PointerMap .pointers', function() {
test('PointerMap .size', function() {
var p = new PointerMap();
expect(p.pointers).to.be.a('function');
expect(p.pointers()).to.equal(0);
expect(p.size).to.be.a('number');
expect(p.size).to.equal(0);
p.set(1, true);
expect(p.pointers()).to.equal(1);
expect(p.size).to.equal(1);
p.set(1, false);
expect(p.pointers()).to.equal(1);
expect(p.size).to.equal(1);
});
test('PointerMap .has', function() {
var p = new PointerMap();
Expand All @@ -51,16 +47,16 @@ define([
var p = new PointerMap();
p.set(1, true);
p.set(2, false);
expect(p.pointers()).to.equal(2);
expect(p.size).to.equal(2);
p.delete(1);
expect(p.pointers()).to.equal(1);
expect(p.size).to.equal(1);
expect(p.get(2)).to.equal(false);
});
test('PointerMap .clear', function() {
var p = new PointerMap();
p.set(1, true);
p.clear();
expect(p.pointers()).to.equal(0);
expect(p.size).to.equal(0);
});
test('PointerMap .forEach', function() {
var p = new PointerMap();
Expand Down