Thu, 15 Jan 2015 15:59:08 +0100
Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 "use strict";
3 var Method = require("../core")
5 function type(value) {
6 return Object.prototype.toString.call(value).
7 split(" ").
8 pop().
9 split("]").
10 shift().
11 toLowerCase()
12 }
14 var values = [
15 null, // 0
16 undefined, // 1
17 Infinity, // 2
18 NaN, // 3
19 5, // 4
20 {}, // 5
21 Object.create({}), // 6
22 Object.create(null), // 7
23 [], // 8
24 /foo/, // 9
25 new Date(), // 10
26 Function, // 11
27 function() {}, // 12
28 true, // 13
29 false, // 14
30 "string" // 15
31 ]
33 function True() { return true }
34 function False() { return false }
36 var trues = values.map(True)
37 var falses = values.map(False)
39 exports["test throws if not implemented"] = function(assert) {
40 var method = Method("nope")
42 assert.throws(function() {
43 method({})
44 }, /not implement/i, "method throws if not implemented")
46 assert.throws(function() {
47 method(null)
48 }, /not implement/i, "method throws on null")
49 }
51 exports["test all types inherit from default"] = function(assert) {
52 var isImplemented = Method("isImplemented")
53 isImplemented.define(function() { return true })
55 values.forEach(function(value) {
56 assert.ok(isImplemented(value),
57 type(value) + " inherits deafult implementation")
58 })
59 }
61 exports["test default can be implemented later"] = function(assert) {
62 var isImplemented = Method("isImplemented")
63 isImplemented.define(function() {
64 return true
65 })
67 values.forEach(function(value) {
68 assert.ok(isImplemented(value),
69 type(value) + " inherits deafult implementation")
70 })
71 }
73 exports["test dispatch not-implemented"] = function(assert) {
74 var isDefault = Method("isDefault")
75 values.forEach(function(value) {
76 assert.throws(function() {
77 isDefault(value)
78 }, /not implement/, type(value) + " throws if not implemented")
79 })
80 }
82 exports["test dispatch default"] = function(assert) {
83 var isDefault = Method("isDefault")
85 // Implement default
86 isDefault.define(True)
87 assert.deepEqual(values.map(isDefault), trues,
88 "all implementation inherit from default")
90 }
92 exports["test dispatch null"] = function(assert) {
93 var isNull = Method("isNull")
95 // Implement default
96 isNull.define(False)
97 isNull.define(null, True)
98 assert.deepEqual(values.map(isNull),
99 [ true ].
100 concat(falses.slice(1)),
101 "only null gets methods defined for null")
102 }
104 exports["test dispatch undefined"] = function(assert) {
105 var isUndefined = Method("isUndefined")
107 // Implement default
108 isUndefined.define(False)
109 isUndefined.define(undefined, True)
110 assert.deepEqual(values.map(isUndefined),
111 [ false, true ].
112 concat(falses.slice(2)),
113 "only undefined gets methods defined for undefined")
114 }
116 exports["test dispatch object"] = function(assert) {
117 var isObject = Method("isObject")
119 // Implement default
120 isObject.define(False)
121 isObject.define(Object, True)
122 assert.deepEqual(values.map(isObject),
123 [ false, false, false, false, false ].
124 concat(trues.slice(5, 13)).
125 concat([false, false, false]),
126 "all values except primitives inherit Object methods")
128 }
130 exports["test dispatch number"] = function(assert) {
131 var isNumber = Method("isNumber")
132 isNumber.define(False)
133 isNumber.define(Number, True)
135 assert.deepEqual(values.map(isNumber),
136 falses.slice(0, 2).
137 concat(true, true, true).
138 concat(falses.slice(5)),
139 "all numbers inherit from Number method")
140 }
142 exports["test dispatch string"] = function(assert) {
143 var isString = Method("isString")
144 isString.define(False)
145 isString.define(String, True)
147 assert.deepEqual(values.map(isString),
148 falses.slice(0, 15).
149 concat(true),
150 "all strings inherit from String method")
151 }
153 exports["test dispatch function"] = function(assert) {
154 var isFunction = Method("isFunction")
155 isFunction.define(False)
156 isFunction.define(Function, True)
158 assert.deepEqual(values.map(isFunction),
159 falses.slice(0, 11).
160 concat(true, true).
161 concat(falses.slice(13)),
162 "all functions inherit from Function method")
163 }
165 exports["test dispatch date"] = function(assert) {
166 var isDate = Method("isDate")
167 isDate.define(False)
168 isDate.define(Date, True)
170 assert.deepEqual(values.map(isDate),
171 falses.slice(0, 10).
172 concat(true).
173 concat(falses.slice(11)),
174 "all dates inherit from Date method")
175 }
177 exports["test dispatch RegExp"] = function(assert) {
178 var isRegExp = Method("isRegExp")
179 isRegExp.define(False)
180 isRegExp.define(RegExp, True)
182 assert.deepEqual(values.map(isRegExp),
183 falses.slice(0, 9).
184 concat(true).
185 concat(falses.slice(10)),
186 "all regexps inherit from RegExp method")
187 }
189 exports["test redefine for descendant"] = function(assert) {
190 var isFoo = Method("isFoo")
191 var ancestor = {}
192 isFoo.implement(ancestor, function() { return true })
193 var descendant = Object.create(ancestor)
194 isFoo.implement(descendant, function() { return false })
196 assert.ok(isFoo(ancestor), "defined on ancestor")
197 assert.ok(!isFoo(descendant), "overrided for descendant")
198 }
200 exports["test on custom types"] = function(assert) {
201 function Bar() {}
202 var isBar = Method("isBar")
204 isBar.define(function() { return false })
205 isBar.define(Bar, function() { return true })
207 assert.ok(!isBar({}), "object is get's default implementation")
208 assert.ok(isBar(new Bar()), "Foo type objects get own implementation")
210 var isObject = Method("isObject")
211 isObject.define(function() { return false })
212 isObject.define(Object, function() { return true })
214 assert.ok(isObject(new Bar()), "foo inherits implementation from object")
217 isObject.define(Bar, function() { return false })
219 assert.ok(!isObject(new Bar()),
220 "implementation inherited form object can be overrided")
221 }
224 exports["test error types"] = function(assert) {
225 var isError = Method("isError")
226 isError.define(function() { return false })
227 isError.define(Error, function() { return true })
229 assert.ok(isError(Error("boom")), "error is error")
230 assert.ok(isError(TypeError("boom")), "type error is an error")
231 assert.ok(isError(EvalError("boom")), "eval error is an error")
232 assert.ok(isError(RangeError("boom")), "range error is an error")
233 assert.ok(isError(ReferenceError("boom")), "reference error is an error")
234 assert.ok(isError(SyntaxError("boom")), "syntax error is an error")
235 assert.ok(isError(URIError("boom")), "URI error is an error")
236 }
238 exports["test override define polymorphic method"] = function(assert) {
239 var define = Method.define
240 var implement = Method.implement
242 var fn = Method("fn")
243 var methods = {}
244 implement(define, fn, function(method, label, implementation) {
245 methods[label] = implementation
246 })
248 function foo() {}
250 define(fn, "foo-case", foo)
252 assert.equal(methods["foo-case"], foo, "define set property")
253 }
255 exports["test override define via method API"] = function(assert) {
256 var define = Method.define
257 var implement = Method.implement
259 var fn = Method("fn")
260 var methods = {}
261 define.implement(fn, function(method, label, implementation) {
262 methods[label] = implementation
263 })
265 function foo() {}
267 define(fn, "foo-case", foo)
269 assert.equal(methods["foo-case"], foo, "define set property")
270 }
272 require("test").run(exports)