Commit 199c8068cdba50d9a6871e20fbc74e513514ecc8
1 parent
cb9bedfcdf
Exists in
master
included bind shim
Showing 4 changed files with 1554 additions and 1 deletions Inline Diff
Makefile
View file @
199c806
PNGS = built/use_cases_diagram.png built/schema_diagram.png built/schema_graph.png | 1 | 1 | PNGS = built/use_cases_diagram.png built/schema_diagram.png built/schema_graph.png | |
PDFS = built/DesignUseCases.pdf built/screen_sequence_diagram.pdf | 2 | 2 | PDFS = built/DesignUseCases.pdf built/screen_sequence_diagram.pdf | |
3 | 3 | |||
SCREEN_SEQUENCE_DOTS = $(wildcard screen_sequence_diagrams/*.dot) | 4 | 4 | SCREEN_SEQUENCE_DOTS = $(wildcard screen_sequence_diagrams/*.dot) | |
SCREEN_SEQUENCE_PNGS = $(patsubst screen_sequence_diagrams/%,built/%,$(patsubst %.dot,%.png,$(SCREEN_SEQUENCE_DOTS))) | 5 | 5 | SCREEN_SEQUENCE_PNGS = $(patsubst screen_sequence_diagrams/%,built/%,$(patsubst %.dot,%.png,$(SCREEN_SEQUENCE_DOTS))) | |
6 | 6 | |||
all: built/ $(PNGS) $(PDFS) built/screenshots/ | 7 | 7 | all: built/ $(PNGS) $(PDFS) built/screenshots/ | |
8 | 8 | |||
built/: | 9 | 9 | built/: | |
mkdir -p built | 10 | 10 | mkdir -p built | |
11 | 11 | |||
built/schema_diagram.png: | 12 | 12 | built/schema_diagram.png: | |
sqlt-diagram --color -c 3 -t png -o built/schema_diagram.png --gutter 60 --from PostgreSQL db_schema.sql --title "Flashy" | 13 | 13 | sqlt-diagram --color -c 3 -t png -o built/schema_diagram.png --gutter 60 --from PostgreSQL db_schema.sql --title "Flashy" | |
14 | 14 | |||
built/schema_graph.png: | 15 | 15 | built/schema_graph.png: | |
sqlt-graph -o built/schema_graph.png --from PostgreSQL db_schema.sql | 16 | 16 | sqlt-graph -o built/schema_graph.png --from PostgreSQL db_schema.sql | |
17 | 17 | |||
built/%.png: %.dot | 18 | 18 | built/%.png: %.dot | |
dot -Tpng -o $@ $< | 19 | 19 | dot -Tpng -o $@ $< | |
20 | 20 | |||
built/%.png: screen_sequence_diagrams/%.dot | 21 | 21 | built/%.png: screen_sequence_diagrams/%.dot | |
dot -Tpng -o $@ $< | 22 | 22 | dot -Tpng -o $@ $< | |
23 | 23 | |||
built/screen_sequence_diagram.pdf: built/ $(SCREEN_SEQUENCE_PNGS) | 24 | 24 | built/screen_sequence_diagram.pdf: built/ $(SCREEN_SEQUENCE_PNGS) | |
convert $(SCREEN_SEQUENCE_PNGS) built/screen_sequence_diagram.pdf | 25 | 25 | convert $(SCREEN_SEQUENCE_PNGS) built/screen_sequence_diagram.pdf | |
26 | 26 | |||
built/%.pdf: %.tex | 27 | 27 | built/%.pdf: %.tex | |
cd built/; pdflatex ../$< | 28 | 28 | cd built/; pdflatex ../$< | |
cd built/; pdflatex ../$< | 29 | 29 | cd built/; pdflatex ../$< | |
rm -f built/*.aux | 30 | 30 | rm -f built/*.aux | |
rm -f built/*.log | 31 | 31 | rm -f built/*.log | |
rm -f built/*.out | 32 | 32 | rm -f built/*.out |
es5-shim.js
View file @
199c806
File was created | 1 | /*! | ||
2 | * https://github.com/es-shims/es5-shim | |||
3 | * @license es5-shim Copyright 2009-2015 by contributors, MIT License | |||
4 | * see https://github.com/es-shims/es5-shim/blob/master/LICENSE | |||
5 | */ | |||
6 | ||||
7 | // vim: ts=4 sts=4 sw=4 expandtab | |||
8 | ||||
9 | // Add semicolon to prevent IIFE from being passed as argument to concatenated code. | |||
10 | ; | |||
11 | ||||
12 | // UMD (Universal Module Definition) | |||
13 | // see https://github.com/umdjs/umd/blob/master/returnExports.js | |||
14 | (function (root, factory) { | |||
15 | 'use strict'; | |||
16 | ||||
17 | /*global define, exports, module */ | |||
18 | if (typeof define === 'function' && define.amd) { | |||
19 | // AMD. Register as an anonymous module. | |||
20 | define(factory); | |||
21 | } else if (typeof exports === 'object') { | |||
22 | // Node. Does not work with strict CommonJS, but | |||
23 | // only CommonJS-like enviroments that support module.exports, | |||
24 | // like Node. | |||
25 | module.exports = factory(); | |||
26 | } else { | |||
27 | // Browser globals (root is window) | |||
28 | root.returnExports = factory(); | |||
29 | } | |||
30 | }(this, function () { | |||
31 | ||||
32 | /** | |||
33 | * Brings an environment as close to ECMAScript 5 compliance | |||
34 | * as is possible with the facilities of erstwhile engines. | |||
35 | * | |||
36 | * Annotated ES5: http://es5.github.com/ (specific links below) | |||
37 | * ES5 Spec: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf | |||
38 | * Required reading: http://javascriptweblog.wordpress.com/2011/12/05/extending-javascript-natives/ | |||
39 | */ | |||
40 | ||||
41 | // Shortcut to an often accessed properties, in order to avoid multiple | |||
42 | // dereference that costs universally. | |||
43 | var ArrayPrototype = Array.prototype; | |||
44 | var ObjectPrototype = Object.prototype; | |||
45 | var FunctionPrototype = Function.prototype; | |||
46 | var StringPrototype = String.prototype; | |||
47 | var NumberPrototype = Number.prototype; | |||
48 | var array_slice = ArrayPrototype.slice; | |||
49 | var array_splice = ArrayPrototype.splice; | |||
50 | var array_push = ArrayPrototype.push; | |||
51 | var array_unshift = ArrayPrototype.unshift; | |||
52 | var call = FunctionPrototype.call; | |||
53 | ||||
54 | // Having a toString local variable name breaks in Opera so use to_string. | |||
55 | var to_string = ObjectPrototype.toString; | |||
56 | ||||
57 | var isArray = Array.isArray || function isArray(obj) { | |||
58 | return to_string.call(obj) === '[object Array]'; | |||
59 | }; | |||
60 | ||||
61 | var hasToStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag === 'symbol'; | |||
62 | var isCallable; /* inlined from https://npmjs.com/is-callable */ var fnToStr = Function.prototype.toString, tryFunctionObject = function tryFunctionObject(value) { try { fnToStr.call(value); return true; } catch (e) { return false; } }, fnClass = '[object Function]', genClass = '[object GeneratorFunction]'; isCallable = function isCallable(value) { if (typeof value !== 'function') { return false; } if (hasToStringTag) { return tryFunctionObject(value); } var strClass = to_string.call(value); return strClass === fnClass || strClass === genClass; }; | |||
63 | var isRegex; /* inlined from https://npmjs.com/is-regex */ var regexExec = RegExp.prototype.exec, tryRegexExec = function tryRegexExec(value) { try { regexExec.call(value); return true; } catch (e) { return false; } }, regexClass = '[object RegExp]'; isRegex = function isRegex(value) { if (typeof value !== 'object') { return false; } return hasToStringTag ? tryRegexExec(value) : to_string.call(value) === regexClass; }; | |||
64 | var isString; /* inlined from https://npmjs.com/is-string */ var strValue = String.prototype.valueOf, tryStringObject = function tryStringObject(value) { try { strValue.call(value); return true; } catch (e) { return false; } }, stringClass = '[object String]'; isString = function isString(value) { if (typeof value === 'string') { return true; } if (typeof value !== 'object') { return false; } return hasToStringTag ? tryStringObject(value) : to_string.call(value) === stringClass; }; | |||
65 | ||||
66 | var isArguments = function isArguments(value) { | |||
67 | var str = to_string.call(value); | |||
68 | var isArgs = str === '[object Arguments]'; | |||
69 | if (!isArgs) { | |||
70 | isArgs = !isArray(value) && | |||
71 | value !== null && | |||
72 | typeof value === 'object' && | |||
73 | typeof value.length === 'number' && | |||
74 | value.length >= 0 && | |||
75 | isCallable(value.callee); | |||
76 | } | |||
77 | return isArgs; | |||
78 | }; | |||
79 | ||||
80 | /* inlined from http://npmjs.com/define-properties */ | |||
81 | var defineProperties = (function (has) { | |||
82 | var supportsDescriptors = Object.defineProperty && (function () { | |||
83 | try { | |||
84 | Object.defineProperty({}, 'x', {}); | |||
85 | return true; | |||
86 | } catch (e) { /* this is ES3 */ | |||
87 | return false; | |||
88 | } | |||
89 | }()); | |||
90 | ||||
91 | // Define configurable, writable and non-enumerable props | |||
92 | // if they don't exist. | |||
93 | var defineProperty; | |||
94 | if (supportsDescriptors) { | |||
95 | defineProperty = function (object, name, method, forceAssign) { | |||
96 | if (!forceAssign && (name in object)) { return; } | |||
97 | Object.defineProperty(object, name, { | |||
98 | configurable: true, | |||
99 | enumerable: false, | |||
100 | writable: true, | |||
101 | value: method | |||
102 | }); | |||
103 | }; | |||
104 | } else { | |||
105 | defineProperty = function (object, name, method, forceAssign) { | |||
106 | if (!forceAssign && (name in object)) { return; } | |||
107 | object[name] = method; | |||
108 | }; | |||
109 | } | |||
110 | return function defineProperties(object, map, forceAssign) { | |||
111 | for (var name in map) { | |||
112 | if (has.call(map, name)) { | |||
113 | defineProperty(object, name, map[name], forceAssign); | |||
114 | } | |||
115 | } | |||
116 | }; | |||
117 | }(ObjectPrototype.hasOwnProperty)); | |||
118 | ||||
119 | // | |||
120 | // Util | |||
121 | // ====== | |||
122 | // | |||
123 | ||||
124 | /* replaceable with https://npmjs.com/package/es-abstract /helpers/isPrimitive */ | |||
125 | var isPrimitive = function isPrimitive(input) { | |||
126 | var type = typeof input; | |||
127 | return input === null || (type !== 'object' && type !== 'function'); | |||
128 | }; | |||
129 | ||||
130 | var ES = { | |||
131 | // ES5 9.4 | |||
132 | // http://es5.github.com/#x9.4 | |||
133 | // http://jsperf.com/to-integer | |||
134 | /* replaceable with https://npmjs.com/package/es-abstract ES5.ToInteger */ | |||
135 | ToInteger: function ToInteger(num) { | |||
136 | var n = +num; | |||
137 | if (n !== n) { // isNaN | |||
138 | n = 0; | |||
139 | } else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) { | |||
140 | n = (n > 0 || -1) * Math.floor(Math.abs(n)); | |||
141 | } | |||
142 | return n; | |||
143 | }, | |||
144 | ||||
145 | /* replaceable with https://npmjs.com/package/es-abstract ES5.ToPrimitive */ | |||
146 | ToPrimitive: function ToPrimitive(input) { | |||
147 | var val, valueOf, toStr; | |||
148 | if (isPrimitive(input)) { | |||
149 | return input; | |||
150 | } | |||
151 | valueOf = input.valueOf; | |||
152 | if (isCallable(valueOf)) { | |||
153 | val = valueOf.call(input); | |||
154 | if (isPrimitive(val)) { | |||
155 | return val; | |||
156 | } | |||
157 | } | |||
158 | toStr = input.toString; | |||
159 | if (isCallable(toStr)) { | |||
160 | val = toStr.call(input); | |||
161 | if (isPrimitive(val)) { | |||
162 | return val; | |||
163 | } | |||
164 | } | |||
165 | throw new TypeError(); | |||
166 | }, | |||
167 | ||||
168 | // ES5 9.9 | |||
169 | // http://es5.github.com/#x9.9 | |||
170 | /* replaceable with https://npmjs.com/package/es-abstract ES5.ToObject */ | |||
171 | ToObject: function (o) { | |||
172 | /*jshint eqnull: true */ | |||
173 | if (o == null) { // this matches both null and undefined | |||
174 | throw new TypeError("can't convert " + o + ' to object'); | |||
175 | } | |||
176 | return Object(o); | |||
177 | }, | |||
178 | ||||
179 | /* replaceable with https://npmjs.com/package/es-abstract ES5.ToUint32 */ | |||
180 | ToUint32: function ToUint32(x) { | |||
181 | return x >>> 0; | |||
182 | } | |||
183 | }; | |||
184 | ||||
185 | // | |||
186 | // Function | |||
187 | // ======== | |||
188 | // | |||
189 | ||||
190 | // ES-5 15.3.4.5 | |||
191 | // http://es5.github.com/#x15.3.4.5 | |||
192 | ||||
193 | var Empty = function Empty() {}; | |||
194 | ||||
195 | defineProperties(FunctionPrototype, { | |||
196 | bind: function bind(that) { // .length is 1 | |||
197 | // 1. Let Target be the this value. | |||
198 | var target = this; | |||
199 | // 2. If IsCallable(Target) is false, throw a TypeError exception. | |||
200 | if (!isCallable(target)) { | |||
201 | throw new TypeError('Function.prototype.bind called on incompatible ' + target); | |||
202 | } | |||
203 | // 3. Let A be a new (possibly empty) internal list of all of the | |||
204 | // argument values provided after thisArg (arg1, arg2 etc), in order. | |||
205 | // XXX slicedArgs will stand in for "A" if used | |||
206 | var args = array_slice.call(arguments, 1); // for normal call | |||
207 | // 4. Let F be a new native ECMAScript object. | |||
208 | // 11. Set the [[Prototype]] internal property of F to the standard | |||
209 | // built-in Function prototype object as specified in 15.3.3.1. | |||
210 | // 12. Set the [[Call]] internal property of F as described in | |||
211 | // 15.3.4.5.1. | |||
212 | // 13. Set the [[Construct]] internal property of F as described in | |||
213 | // 15.3.4.5.2. | |||
214 | // 14. Set the [[HasInstance]] internal property of F as described in | |||
215 | // 15.3.4.5.3. | |||
216 | var bound; | |||
217 | var binder = function () { | |||
218 | ||||
219 | if (this instanceof bound) { | |||
220 | // 15.3.4.5.2 [[Construct]] | |||
221 | // When the [[Construct]] internal method of a function object, | |||
222 | // F that was created using the bind function is called with a | |||
223 | // list of arguments ExtraArgs, the following steps are taken: | |||
224 | // 1. Let target be the value of F's [[TargetFunction]] | |||
225 | // internal property. | |||
226 | // 2. If target has no [[Construct]] internal method, a | |||
227 | // TypeError exception is thrown. | |||
228 | // 3. Let boundArgs be the value of F's [[BoundArgs]] internal | |||
229 | // property. | |||
230 | // 4. Let args be a new list containing the same values as the | |||
231 | // list boundArgs in the same order followed by the same | |||
232 | // values as the list ExtraArgs in the same order. | |||
233 | // 5. Return the result of calling the [[Construct]] internal | |||
234 | // method of target providing args as the arguments. | |||
235 | ||||
236 | var result = target.apply( | |||
237 | this, | |||
238 | args.concat(array_slice.call(arguments)) | |||
239 | ); | |||
240 | if (Object(result) === result) { | |||
241 | return result; | |||
242 | } | |||
243 | return this; | |||
244 | ||||
245 | } else { | |||
246 | // 15.3.4.5.1 [[Call]] | |||
247 | // When the [[Call]] internal method of a function object, F, | |||
248 | // which was created using the bind function is called with a | |||
249 | // this value and a list of arguments ExtraArgs, the following | |||
250 | // steps are taken: | |||
251 | // 1. Let boundArgs be the value of F's [[BoundArgs]] internal | |||
252 | // property. | |||
253 | // 2. Let boundThis be the value of F's [[BoundThis]] internal | |||
254 | // property. | |||
255 | // 3. Let target be the value of F's [[TargetFunction]] internal | |||
256 | // property. | |||
257 | // 4. Let args be a new list containing the same values as the | |||
258 | // list boundArgs in the same order followed by the same | |||
259 | // values as the list ExtraArgs in the same order. | |||
260 | // 5. Return the result of calling the [[Call]] internal method | |||
261 | // of target providing boundThis as the this value and | |||
262 | // providing args as the arguments. | |||
263 | ||||
264 | // equiv: target.call(this, ...boundArgs, ...args) | |||
265 | return target.apply( | |||
266 | that, | |||
267 | args.concat(array_slice.call(arguments)) | |||
268 | ); | |||
269 | ||||
270 | } | |||
271 | ||||
272 | }; | |||
273 | ||||
274 | // 15. If the [[Class]] internal property of Target is "Function", then | |||
275 | // a. Let L be the length property of Target minus the length of A. | |||
276 | // b. Set the length own property of F to either 0 or L, whichever is | |||
277 | // larger. | |||
278 | // 16. Else set the length own property of F to 0. | |||
279 | ||||
280 | var boundLength = Math.max(0, target.length - args.length); | |||
281 | ||||
282 | // 17. Set the attributes of the length own property of F to the values | |||
283 | // specified in 15.3.5.1. | |||
284 | var boundArgs = []; | |||
285 | for (var i = 0; i < boundLength; i++) { | |||
286 | boundArgs.push('$' + i); | |||
287 | } | |||
288 | ||||
289 | // XXX Build a dynamic function with desired amount of arguments is the only | |||
290 | // way to set the length property of a function. | |||
291 | // In environments where Content Security Policies enabled (Chrome extensions, | |||
292 | // for ex.) all use of eval or Function costructor throws an exception. | |||
293 | // However in all of these environments Function.prototype.bind exists | |||
294 | // and so this code will never be executed. | |||
295 | bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this, arguments); }')(binder); | |||
296 | ||||
297 | if (target.prototype) { | |||
298 | Empty.prototype = target.prototype; | |||
299 | bound.prototype = new Empty(); | |||
300 | // Clean up dangling references. | |||
301 | Empty.prototype = null; | |||
302 | } | |||
303 | ||||
304 | // TODO | |||
305 | // 18. Set the [[Extensible]] internal property of F to true. | |||
306 | ||||
307 | // TODO | |||
308 | // 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3). | |||
309 | // 20. Call the [[DefineOwnProperty]] internal method of F with | |||
310 | // arguments "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]: | |||
311 | // thrower, [[Enumerable]]: false, [[Configurable]]: false}, and | |||
312 | // false. | |||
313 | // 21. Call the [[DefineOwnProperty]] internal method of F with | |||
314 | // arguments "arguments", PropertyDescriptor {[[Get]]: thrower, | |||
315 | // [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false}, | |||
316 | // and false. | |||
317 | ||||
318 | // TODO | |||
319 | // NOTE Function objects created using Function.prototype.bind do not | |||
320 | // have a prototype property or the [[Code]], [[FormalParameters]], and | |||
321 | // [[Scope]] internal properties. | |||
322 | // XXX can't delete prototype in pure-js. | |||
323 | ||||
324 | // 22. Return F. | |||
325 | return bound; | |||
326 | } | |||
327 | }); | |||
328 | ||||
329 | // _Please note: Shortcuts are defined after `Function.prototype.bind` as we | |||
330 | // us it in defining shortcuts. | |||
331 | var owns = call.bind(ObjectPrototype.hasOwnProperty); | |||
332 | ||||
333 | // | |||
334 | // Array | |||
335 | // ===== | |||
336 | // | |||
337 | ||||
338 | // ES5 15.4.4.12 | |||
339 | // http://es5.github.com/#x15.4.4.12 | |||
340 | var spliceNoopReturnsEmptyArray = (function () { | |||
341 | var a = [1, 2]; | |||
342 | var result = a.splice(); | |||
343 | return a.length === 2 && isArray(result) && result.length === 0; | |||
344 | }()); | |||
345 | defineProperties(ArrayPrototype, { | |||
346 | // Safari 5.0 bug where .splice() returns undefined | |||
347 | splice: function splice(start, deleteCount) { | |||
348 | if (arguments.length === 0) { | |||
349 | return []; | |||
350 | } else { | |||
351 | return array_splice.apply(this, arguments); | |||
352 | } | |||
353 | } | |||
354 | }, !spliceNoopReturnsEmptyArray); | |||
355 | ||||
356 | var spliceWorksWithEmptyObject = (function () { | |||
357 | var obj = {}; | |||
358 | ArrayPrototype.splice.call(obj, 0, 0, 1); | |||
359 | return obj.length === 1; | |||
360 | }()); | |||
361 | defineProperties(ArrayPrototype, { | |||
362 | splice: function splice(start, deleteCount) { | |||
363 | if (arguments.length === 0) { return []; } | |||
364 | var args = arguments; | |||
365 | this.length = Math.max(ES.ToInteger(this.length), 0); | |||
366 | if (arguments.length > 0 && typeof deleteCount !== 'number') { | |||
367 | args = array_slice.call(arguments); | |||
368 | if (args.length < 2) { | |||
369 | args.push(this.length - start); | |||
370 | } else { | |||
371 | args[1] = ES.ToInteger(deleteCount); | |||
372 | } | |||
373 | } | |||
374 | return array_splice.apply(this, args); | |||
375 | } | |||
376 | }, !spliceWorksWithEmptyObject); | |||
377 | ||||
378 | // ES5 15.4.4.12 | |||
379 | // http://es5.github.com/#x15.4.4.13 | |||
380 | // Return len+argCount. | |||
381 | // [bugfix, ielt8] | |||
382 | // IE < 8 bug: [].unshift(0) === undefined but should be "1" | |||
383 | var hasUnshiftReturnValueBug = [].unshift(0) !== 1; | |||
384 | defineProperties(ArrayPrototype, { | |||
385 | unshift: function () { | |||
386 | array_unshift.apply(this, arguments); | |||
387 | return this.length; | |||
388 | } | |||
389 | }, hasUnshiftReturnValueBug); | |||
390 | ||||
391 | // ES5 15.4.3.2 | |||
392 | // http://es5.github.com/#x15.4.3.2 | |||
393 | // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray | |||
394 | defineProperties(Array, { isArray: isArray }); | |||
395 | ||||
396 | // The IsCallable() check in the Array functions | |||
397 | // has been replaced with a strict check on the | |||
398 | // internal class of the object to trap cases where | |||
399 | // the provided function was actually a regular | |||
400 | // expression literal, which in V8 and | |||
401 | // JavaScriptCore is a typeof "function". Only in | |||
402 | // V8 are regular expression literals permitted as | |||
403 | // reduce parameters, so it is desirable in the | |||
404 | // general case for the shim to match the more | |||
405 | // strict and common behavior of rejecting regular | |||
406 | // expressions. | |||
407 | ||||
408 | // ES5 15.4.4.18 | |||
409 | // http://es5.github.com/#x15.4.4.18 | |||
410 | // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/forEach | |||
411 | ||||
412 | // Check failure of by-index access of string characters (IE < 9) | |||
413 | // and failure of `0 in boxedString` (Rhino) | |||
414 | var boxedString = Object('a'); | |||
415 | var splitString = boxedString[0] !== 'a' || !(0 in boxedString); | |||
416 | ||||
417 | var properlyBoxesContext = function properlyBoxed(method) { | |||
418 | // Check node 0.6.21 bug where third parameter is not boxed | |||
419 | var properlyBoxesNonStrict = true; | |||
420 | var properlyBoxesStrict = true; | |||
421 | if (method) { | |||
422 | method.call('foo', function (_, __, context) { | |||
423 | if (typeof context !== 'object') { properlyBoxesNonStrict = false; } | |||
424 | }); | |||
425 | ||||
426 | method.call([1], function () { | |||
427 | 'use strict'; | |||
428 | ||||
429 | properlyBoxesStrict = typeof this === 'string'; | |||
430 | }, 'x'); | |||
431 | } | |||
432 | return !!method && properlyBoxesNonStrict && properlyBoxesStrict; | |||
433 | }; | |||
434 | ||||
435 | defineProperties(ArrayPrototype, { | |||
436 | forEach: function forEach(callbackfn /*, thisArg*/) { | |||
437 | var object = ES.ToObject(this); | |||
438 | var self = splitString && isString(this) ? this.split('') : object; | |||
439 | var i = -1; | |||
440 | var length = self.length >>> 0; | |||
441 | var T; | |||
442 | if (arguments.length > 1) { | |||
443 | T = arguments[1]; | |||
444 | } | |||
445 | ||||
446 | // If no callback function or if callback is not a callable function | |||
447 | if (!isCallable(callbackfn)) { | |||
448 | throw new TypeError('Array.prototype.forEach callback must be a function'); | |||
449 | } | |||
450 | ||||
451 | while (++i < length) { | |||
452 | if (i in self) { | |||
453 | // Invoke the callback function with call, passing arguments: | |||
454 | // context, property value, property key, thisArg object | |||
455 | if (typeof T !== 'undefined') { | |||
456 | callbackfn.call(T, self[i], i, object); | |||
457 | } else { | |||
458 | callbackfn(self[i], i, object); | |||
459 | } | |||
460 | } | |||
461 | } | |||
462 | } | |||
463 | }, !properlyBoxesContext(ArrayPrototype.forEach)); | |||
464 | ||||
465 | // ES5 15.4.4.19 | |||
466 | // http://es5.github.com/#x15.4.4.19 | |||
467 | // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map | |||
468 | defineProperties(ArrayPrototype, { | |||
469 | map: function map(callbackfn/*, thisArg*/) { | |||
470 | var object = ES.ToObject(this); | |||
471 | var self = splitString && isString(this) ? this.split('') : object; | |||
472 | var length = self.length >>> 0; | |||
473 | var result = Array(length); | |||
474 | var T; | |||
475 | if (arguments.length > 1) { | |||
476 | T = arguments[1]; | |||
477 | } | |||
478 | ||||
479 | // If no callback function or if callback is not a callable function | |||
480 | if (!isCallable(callbackfn)) { | |||
481 | throw new TypeError('Array.prototype.map callback must be a function'); | |||
482 | } | |||
483 | ||||
484 | for (var i = 0; i < length; i++) { | |||
485 | if (i in self) { | |||
486 | if (typeof T !== 'undefined') { | |||
487 | result[i] = callbackfn.call(T, self[i], i, object); | |||
488 | } else { | |||
489 | result[i] = callbackfn(self[i], i, object); | |||
490 | } | |||
491 | } | |||
492 | } | |||
493 | return result; | |||
494 | } | |||
495 | }, !properlyBoxesContext(ArrayPrototype.map)); | |||
496 | ||||
497 | // ES5 15.4.4.20 | |||
498 | // http://es5.github.com/#x15.4.4.20 | |||
499 | // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter | |||
500 | defineProperties(ArrayPrototype, { | |||
501 | filter: function filter(callbackfn /*, thisArg*/) { | |||
502 | var object = ES.ToObject(this); | |||
503 | var self = splitString && isString(this) ? this.split('') : object; | |||
504 | var length = self.length >>> 0; | |||
505 | var result = []; | |||
506 | var value; | |||
507 | var T; | |||
508 | if (arguments.length > 1) { | |||
509 | T = arguments[1]; | |||
510 | } | |||
511 | ||||
512 | // If no callback function or if callback is not a callable function | |||
513 | if (!isCallable(callbackfn)) { | |||
514 | throw new TypeError('Array.prototype.filter callback must be a function'); | |||
515 | } | |||
516 | ||||
517 | for (var i = 0; i < length; i++) { | |||
518 | if (i in self) { | |||
519 | value = self[i]; | |||
520 | if (typeof T === 'undefined' ? callbackfn(value, i, object) : callbackfn.call(T, value, i, object)) { | |||
521 | result.push(value); | |||
522 | } | |||
523 | } | |||
524 | } | |||
525 | return result; | |||
526 | } | |||
527 | }, !properlyBoxesContext(ArrayPrototype.filter)); | |||
528 | ||||
529 | // ES5 15.4.4.16 | |||
530 | // http://es5.github.com/#x15.4.4.16 | |||
531 | // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every | |||
532 | defineProperties(ArrayPrototype, { | |||
533 | every: function every(callbackfn /*, thisArg*/) { | |||
534 | var object = ES.ToObject(this); | |||
535 | var self = splitString && isString(this) ? this.split('') : object; | |||
536 | var length = self.length >>> 0; | |||
537 | var T; | |||
538 | if (arguments.length > 1) { | |||
539 | T = arguments[1]; | |||
540 | } | |||
541 | ||||
542 | // If no callback function or if callback is not a callable function | |||
543 | if (!isCallable(callbackfn)) { | |||
544 | throw new TypeError('Array.prototype.every callback must be a function'); | |||
545 | } | |||
546 | ||||
547 | for (var i = 0; i < length; i++) { | |||
548 | if (i in self && !(typeof T === 'undefined' ? callbackfn(self[i], i, object) : callbackfn.call(T, self[i], i, object))) { | |||
549 | return false; | |||
550 | } | |||
551 | } | |||
552 | return true; | |||
553 | } | |||
554 | }, !properlyBoxesContext(ArrayPrototype.every)); | |||
555 | ||||
556 | // ES5 15.4.4.17 | |||
557 | // http://es5.github.com/#x15.4.4.17 | |||
558 | // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some | |||
559 | defineProperties(ArrayPrototype, { | |||
560 | some: function some(callbackfn/*, thisArg */) { | |||
561 | var object = ES.ToObject(this); | |||
562 | var self = splitString && isString(this) ? this.split('') : object; | |||
563 | var length = self.length >>> 0; | |||
564 | var T; | |||
565 | if (arguments.length > 1) { | |||
566 | T = arguments[1]; | |||
567 | } | |||
568 | ||||
569 | // If no callback function or if callback is not a callable function | |||
570 | if (!isCallable(callbackfn)) { | |||
571 | throw new TypeError('Array.prototype.some callback must be a function'); | |||
572 | } | |||
573 | ||||
574 | for (var i = 0; i < length; i++) { | |||
575 | if (i in self && (typeof T === 'undefined' ? callbackfn(self[i], i, object) : callbackfn.call(T, self[i], i, object))) { | |||
576 | return true; | |||
577 | } | |||
578 | } | |||
579 | return false; | |||
580 | } | |||
581 | }, !properlyBoxesContext(ArrayPrototype.some)); | |||
582 | ||||
583 | // ES5 15.4.4.21 | |||
584 | // http://es5.github.com/#x15.4.4.21 | |||
585 | // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce | |||
586 | var reduceCoercesToObject = false; | |||
587 | if (ArrayPrototype.reduce) { | |||
588 | reduceCoercesToObject = typeof ArrayPrototype.reduce.call('es5', function (_, __, ___, list) { return list; }) === 'object'; | |||
589 | } | |||
590 | defineProperties(ArrayPrototype, { | |||
591 | reduce: function reduce(callbackfn /*, initialValue*/) { | |||
592 | var object = ES.ToObject(this); | |||
593 | var self = splitString && isString(this) ? this.split('') : object; | |||
594 | var length = self.length >>> 0; | |||
595 | ||||
596 | // If no callback function or if callback is not a callable function | |||
597 | if (!isCallable(callbackfn)) { | |||
598 | throw new TypeError('Array.prototype.reduce callback must be a function'); | |||
599 | } | |||
600 | ||||
601 | // no value to return if no initial value and an empty array | |||
602 | if (length === 0 && arguments.length === 1) { | |||
603 | throw new TypeError('reduce of empty array with no initial value'); | |||
604 | } | |||
605 | ||||
606 | var i = 0; | |||
607 | var result; | |||
608 | if (arguments.length >= 2) { | |||
609 | result = arguments[1]; | |||
610 | } else { | |||
611 | do { | |||
612 | if (i in self) { | |||
613 | result = self[i++]; | |||
614 | break; | |||
615 | } | |||
616 | ||||
617 | // if array contains no values, no initial value to return | |||
618 | if (++i >= length) { | |||
619 | throw new TypeError('reduce of empty array with no initial value'); | |||
620 | } | |||
621 | } while (true); | |||
622 | } | |||
623 | ||||
624 | for (; i < length; i++) { | |||
625 | if (i in self) { | |||
626 | result = callbackfn(result, self[i], i, object); | |||
627 | } | |||
628 | } | |||
629 | ||||
630 | return result; | |||
631 | } | |||
632 | }, !reduceCoercesToObject); | |||
633 | ||||
634 | // ES5 15.4.4.22 | |||
635 | // http://es5.github.com/#x15.4.4.22 | |||
636 | // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight | |||
637 | var reduceRightCoercesToObject = false; | |||
638 | if (ArrayPrototype.reduceRight) { | |||
639 | reduceRightCoercesToObject = typeof ArrayPrototype.reduceRight.call('es5', function (_, __, ___, list) { return list; }) === 'object'; | |||
640 | } | |||
641 | defineProperties(ArrayPrototype, { | |||
642 | reduceRight: function reduceRight(callbackfn/*, initial*/) { | |||
643 | var object = ES.ToObject(this); | |||
644 | var self = splitString && isString(this) ? this.split('') : object; | |||
645 | var length = self.length >>> 0; | |||
646 | ||||
647 | // If no callback function or if callback is not a callable function | |||
648 | if (!isCallable(callbackfn)) { | |||
649 | throw new TypeError('Array.prototype.reduceRight callback must be a function'); | |||
650 | } | |||
651 | ||||
652 | // no value to return if no initial value, empty array | |||
653 | if (length === 0 && arguments.length === 1) { | |||
654 | throw new TypeError('reduceRight of empty array with no initial value'); | |||
655 | } | |||
656 | ||||
657 | var result; | |||
658 | var i = length - 1; | |||
659 | if (arguments.length >= 2) { | |||
660 | result = arguments[1]; | |||
661 | } else { | |||
662 | do { | |||
663 | if (i in self) { | |||
664 | result = self[i--]; | |||
665 | break; | |||
666 | } | |||
667 | ||||
668 | // if array contains no values, no initial value to return | |||
669 | if (--i < 0) { | |||
670 | throw new TypeError('reduceRight of empty array with no initial value'); | |||
671 | } | |||
672 | } while (true); | |||
673 | } | |||
674 | ||||
675 | if (i < 0) { | |||
676 | return result; | |||
677 | } | |||
678 | ||||
679 | do { | |||
680 | if (i in self) { | |||
681 | result = callbackfn(result, self[i], i, object); | |||
682 | } | |||
683 | } while (i--); | |||
684 | ||||
685 | return result; | |||
686 | } | |||
687 | }, !reduceRightCoercesToObject); | |||
688 | ||||
689 | // ES5 15.4.4.14 | |||
690 | // http://es5.github.com/#x15.4.4.14 | |||
691 | // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf | |||
692 | var hasFirefox2IndexOfBug = Array.prototype.indexOf && [0, 1].indexOf(1, 2) !== -1; | |||
693 | defineProperties(ArrayPrototype, { | |||
694 | indexOf: function indexOf(searchElement /*, fromIndex */) { | |||
695 | var self = splitString && isString(this) ? this.split('') : ES.ToObject(this); | |||
696 | var length = self.length >>> 0; | |||
697 | ||||
698 | if (length === 0) { | |||
699 | return -1; | |||
700 | } | |||
701 | ||||
702 | var i = 0; | |||
703 | if (arguments.length > 1) { | |||
704 | i = ES.ToInteger(arguments[1]); | |||
705 | } | |||
706 | ||||
707 | // handle negative indices | |||
708 | i = i >= 0 ? i : Math.max(0, length + i); | |||
709 | for (; i < length; i++) { | |||
710 | if (i in self && self[i] === searchElement) { | |||
711 | return i; | |||
712 | } | |||
713 | } | |||
714 | return -1; | |||
715 | } | |||
716 | }, hasFirefox2IndexOfBug); | |||
717 | ||||
718 | // ES5 15.4.4.15 | |||
719 | // http://es5.github.com/#x15.4.4.15 | |||
720 | // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf | |||
721 | var hasFirefox2LastIndexOfBug = Array.prototype.lastIndexOf && [0, 1].lastIndexOf(0, -3) !== -1; | |||
722 | defineProperties(ArrayPrototype, { | |||
723 | lastIndexOf: function lastIndexOf(searchElement /*, fromIndex */) { | |||
724 | var self = splitString && isString(this) ? this.split('') : ES.ToObject(this); | |||
725 | var length = self.length >>> 0; | |||
726 | ||||
727 | if (length === 0) { | |||
728 | return -1; | |||
729 | } | |||
730 | var i = length - 1; | |||
731 | if (arguments.length > 1) { | |||
732 | i = Math.min(i, ES.ToInteger(arguments[1])); | |||
733 | } | |||
734 | // handle negative indices | |||
735 | i = i >= 0 ? i : length - Math.abs(i); | |||
736 | for (; i >= 0; i--) { | |||
737 | if (i in self && searchElement === self[i]) { | |||
738 | return i; | |||
739 | } | |||
740 | } | |||
741 | return -1; | |||
742 | } | |||
743 | }, hasFirefox2LastIndexOfBug); | |||
744 | ||||
745 | // | |||
746 | // Object | |||
747 | // ====== | |||
748 | // | |||
749 | ||||
750 | // ES5 15.2.3.14 | |||
751 | // http://es5.github.com/#x15.2.3.14 | |||
752 | ||||
753 | // http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation | |||
754 | var hasDontEnumBug = !({'toString': null}).propertyIsEnumerable('toString'), | |||
755 | hasProtoEnumBug = function () {}.propertyIsEnumerable('prototype'), | |||
756 | hasStringEnumBug = !owns('x', '0'), | |||
757 | dontEnums = [ | |||
758 | 'toString', | |||
759 | 'toLocaleString', | |||
760 | 'valueOf', | |||
761 | 'hasOwnProperty', | |||
762 | 'isPrototypeOf', | |||
763 | 'propertyIsEnumerable', | |||
764 | 'constructor' | |||
765 | ], | |||
766 | dontEnumsLength = dontEnums.length; | |||
767 | ||||
768 | defineProperties(Object, { | |||
769 | keys: function keys(object) { | |||
770 | var isFn = isCallable(object), | |||
771 | isArgs = isArguments(object), | |||
772 | isObject = object !== null && typeof object === 'object', | |||
773 | isStr = isObject && isString(object); | |||
774 | ||||
775 | if (!isObject && !isFn && !isArgs) { | |||
776 | throw new TypeError('Object.keys called on a non-object'); | |||
777 | } | |||
778 | ||||
779 | var theKeys = []; | |||
780 | var skipProto = hasProtoEnumBug && isFn; | |||
781 | if ((isStr && hasStringEnumBug) || isArgs) { | |||
782 | for (var i = 0; i < object.length; ++i) { | |||
783 | theKeys.push(String(i)); | |||
784 | } | |||
785 | } | |||
786 | ||||
787 | if (!isArgs) { | |||
788 | for (var name in object) { | |||
789 | if (!(skipProto && name === 'prototype') && owns(object, name)) { | |||
790 | theKeys.push(String(name)); | |||
791 | } | |||
792 | } | |||
793 | } | |||
794 | ||||
795 | if (hasDontEnumBug) { | |||
796 | var ctor = object.constructor, | |||
797 | skipConstructor = ctor && ctor.prototype === object; | |||
798 | for (var j = 0; j < dontEnumsLength; j++) { | |||
799 | var dontEnum = dontEnums[j]; | |||
800 | if (!(skipConstructor && dontEnum === 'constructor') && owns(object, dontEnum)) { | |||
801 | theKeys.push(dontEnum); | |||
802 | } | |||
803 | } | |||
804 | } | |||
805 | return theKeys; | |||
806 | } | |||
807 | }); | |||
808 | ||||
809 | var keysWorksWithArguments = Object.keys && (function () { | |||
810 | // Safari 5.0 bug | |||
811 | return Object.keys(arguments).length === 2; | |||
812 | }(1, 2)); | |||
813 | var originalKeys = Object.keys; | |||
814 | defineProperties(Object, { | |||
815 | keys: function keys(object) { | |||
816 | if (isArguments(object)) { | |||
817 | return originalKeys(ArrayPrototype.slice.call(object)); | |||
818 | } else { | |||
819 | return originalKeys(object); | |||
820 | } | |||
821 | } | |||
822 | }, !keysWorksWithArguments); | |||
823 | ||||
824 | // | |||
825 | // Date | |||
826 | // ==== | |||
827 | // | |||
828 | ||||
829 | // ES5 15.9.5.43 | |||
830 | // http://es5.github.com/#x15.9.5.43 | |||
831 | // This function returns a String value represent the instance in time | |||
832 | // represented by this Date object. The format of the String is the Date Time | |||
833 | // string format defined in 15.9.1.15. All fields are present in the String. | |||
834 | // The time zone is always UTC, denoted by the suffix Z. If the time value of | |||
835 | // this object is not a finite Number a RangeError exception is thrown. | |||
836 | var negativeDate = -62198755200000; | |||
837 | var negativeYearString = '-000001'; | |||
838 | var hasNegativeDateBug = Date.prototype.toISOString && new Date(negativeDate).toISOString().indexOf(negativeYearString) === -1; | |||
839 | ||||
840 | defineProperties(Date.prototype, { | |||
841 | toISOString: function toISOString() { | |||
842 | var result, length, value, year, month; | |||
843 | if (!isFinite(this)) { | |||
844 | throw new RangeError('Date.prototype.toISOString called on non-finite value.'); | |||
845 | } | |||
846 | ||||
847 | year = this.getUTCFullYear(); | |||
848 | ||||
849 | month = this.getUTCMonth(); | |||
850 | // see https://github.com/es-shims/es5-shim/issues/111 | |||
851 | year += Math.floor(month / 12); | |||
852 | month = (month % 12 + 12) % 12; | |||
853 | ||||
854 | // the date time string format is specified in 15.9.1.15. | |||
855 | result = [month + 1, this.getUTCDate(), this.getUTCHours(), this.getUTCMinutes(), this.getUTCSeconds()]; | |||
856 | year = ( | |||
857 | (year < 0 ? '-' : (year > 9999 ? '+' : '')) + | |||
858 | ('00000' + Math.abs(year)).slice((0 <= year && year <= 9999) ? -4 : -6) | |||
859 | ); | |||
860 | ||||
861 | length = result.length; | |||
862 | while (length--) { | |||
863 | value = result[length]; | |||
864 | // pad months, days, hours, minutes, and seconds to have two | |||
865 | // digits. | |||
866 | if (value < 10) { | |||
867 | result[length] = '0' + value; | |||
868 | } | |||
869 | } | |||
870 | // pad milliseconds to have three digits. | |||
871 | return ( | |||
872 | year + '-' + result.slice(0, 2).join('-') + | |||
873 | 'T' + result.slice(2).join(':') + '.' + | |||
874 | ('000' + this.getUTCMilliseconds()).slice(-3) + 'Z' | |||
875 | ); | |||
876 | } | |||
877 | }, hasNegativeDateBug); | |||
878 | ||||
879 | // ES5 15.9.5.44 | |||
880 | // http://es5.github.com/#x15.9.5.44 | |||
881 | // This function provides a String representation of a Date object for use by | |||
882 | // JSON.stringify (15.12.3). | |||
883 | var dateToJSONIsSupported = (function () { | |||
884 | try { | |||
885 | return Date.prototype.toJSON && | |||
886 | new Date(NaN).toJSON() === null && | |||
887 | new Date(negativeDate).toJSON().indexOf(negativeYearString) !== -1 && | |||
888 | Date.prototype.toJSON.call({ // generic | |||
889 | toISOString: function () { return true; } | |||
890 | }); | |||
891 | } catch (e) { | |||
892 | return false; | |||
893 | } | |||
894 | }()); | |||
895 | if (!dateToJSONIsSupported) { | |||
896 | Date.prototype.toJSON = function toJSON(key) { | |||
897 | // When the toJSON method is called with argument key, the following | |||
898 | // steps are taken: | |||
899 | ||||
900 | // 1. Let O be the result of calling ToObject, giving it the this | |||
901 | // value as its argument. | |||
902 | // 2. Let tv be ES.ToPrimitive(O, hint Number). | |||
903 | var O = Object(this); | |||
904 | var tv = ES.ToPrimitive(O); | |||
905 | // 3. If tv is a Number and is not finite, return null. | |||
906 | if (typeof tv === 'number' && !isFinite(tv)) { | |||
907 | return null; | |||
908 | } | |||
909 | // 4. Let toISO be the result of calling the [[Get]] internal method of | |||
910 | // O with argument "toISOString". | |||
911 | var toISO = O.toISOString; | |||
912 | // 5. If IsCallable(toISO) is false, throw a TypeError exception. | |||
913 | if (!isCallable(toISO)) { | |||
914 | throw new TypeError('toISOString property is not callable'); | |||
915 | } | |||
916 | // 6. Return the result of calling the [[Call]] internal method of | |||
917 | // toISO with O as the this value and an empty argument list. | |||
918 | return toISO.call(O); | |||
919 | ||||
920 | // NOTE 1 The argument is ignored. | |||
921 | ||||
922 | // NOTE 2 The toJSON function is intentionally generic; it does not | |||
923 | // require that its this value be a Date object. Therefore, it can be | |||
924 | // transferred to other kinds of objects for use as a method. However, | |||
925 | // it does require that any such object have a toISOString method. An | |||
926 | // object is free to use the argument key to filter its | |||
927 | // stringification. | |||
928 | }; | |||
929 | } | |||
930 | ||||
931 | // ES5 15.9.4.2 | |||
932 | // http://es5.github.com/#x15.9.4.2 | |||
933 | // based on work shared by Daniel Friesen (dantman) | |||
934 | // http://gist.github.com/303249 | |||
935 | var supportsExtendedYears = Date.parse('+033658-09-27T01:46:40.000Z') === 1e15; | |||
936 | var acceptsInvalidDates = !isNaN(Date.parse('2012-04-04T24:00:00.500Z')) || !isNaN(Date.parse('2012-11-31T23:59:59.000Z')); | |||
937 | var doesNotParseY2KNewYear = isNaN(Date.parse('2000-01-01T00:00:00.000Z')); | |||
938 | if (!Date.parse || doesNotParseY2KNewYear || acceptsInvalidDates || !supportsExtendedYears) { | |||
939 | // XXX global assignment won't work in embeddings that use | |||
940 | // an alternate object for the context. | |||
941 | /*global Date: true */ | |||
942 | /*eslint-disable no-undef*/ | |||
943 | Date = (function (NativeDate) { | |||
944 | /*eslint-enable no-undef*/ | |||
945 | // Date.length === 7 | |||
946 | var DateShim = function Date(Y, M, D, h, m, s, ms) { | |||
947 | var length = arguments.length; | |||
948 | var date; | |||
949 | if (this instanceof NativeDate) { | |||
950 | date = length === 1 && String(Y) === Y ? // isString(Y) | |||
951 | // We explicitly pass it through parse: | |||
952 | new NativeDate(DateShim.parse(Y)) : | |||
953 | // We have to manually make calls depending on argument | |||
954 | // length here | |||
955 | length >= 7 ? new NativeDate(Y, M, D, h, m, s, ms) : | |||
956 | length >= 6 ? new NativeDate(Y, M, D, h, m, s) : | |||
957 | length >= 5 ? new NativeDate(Y, M, D, h, m) : | |||
958 | length >= 4 ? new NativeDate(Y, M, D, h) : | |||
959 | length >= 3 ? new NativeDate(Y, M, D) : | |||
960 | length >= 2 ? new NativeDate(Y, M) : | |||
961 | length >= 1 ? new NativeDate(Y) : | |||
962 | new NativeDate(); | |||
963 | } else { | |||
964 | date = NativeDate.apply(this, arguments); | |||
965 | } | |||
966 | // Prevent mixups with unfixed Date object | |||
967 | defineProperties(date, { constructor: DateShim }, true); | |||
968 | return date; | |||
969 | }; | |||
970 | ||||
971 | // 15.9.1.15 Date Time String Format. | |||
972 | var isoDateExpression = new RegExp('^' + | |||
973 | '(\\d{4}|[+-]\\d{6})' + // four-digit year capture or sign + | |||
974 | // 6-digit extended year | |||
975 | '(?:-(\\d{2})' + // optional month capture | |||
976 | '(?:-(\\d{2})' + // optional day capture | |||
977 | '(?:' + // capture hours:minutes:seconds.milliseconds | |||
978 | 'T(\\d{2})' + // hours capture | |||
979 | ':(\\d{2})' + // minutes capture | |||
980 | '(?:' + // optional :seconds.milliseconds | |||
981 | ':(\\d{2})' + // seconds capture | |||
982 | '(?:(\\.\\d{1,}))?' + // milliseconds capture | |||
983 | ')?' + | |||
984 | '(' + // capture UTC offset component | |||
985 | 'Z|' + // UTC capture | |||
986 | '(?:' + // offset specifier +/-hours:minutes | |||
987 | '([-+])' + // sign capture | |||
988 | '(\\d{2})' + // hours offset capture | |||
989 | ':(\\d{2})' + // minutes offset capture | |||
990 | ')' + | |||
991 | ')?)?)?)?' + | |||
992 | '$'); | |||
993 | ||||
994 | var months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365]; | |||
995 | ||||
996 | var dayFromMonth = function dayFromMonth(year, month) { | |||
997 | var t = month > 1 ? 1 : 0; | |||
998 | return ( | |||
999 | months[month] + | |||
1000 | Math.floor((year - 1969 + t) / 4) - | |||
1001 | Math.floor((year - 1901 + t) / 100) + | |||
1002 | Math.floor((year - 1601 + t) / 400) + | |||
1003 | 365 * (year - 1970) | |||
1004 | ); | |||
1005 | }; | |||
1006 | ||||
1007 | var toUTC = function toUTC(t) { | |||
1008 | return Number(new NativeDate(1970, 0, 1, 0, 0, 0, t)); | |||
1009 | }; | |||
1010 | ||||
1011 | // Copy any custom methods a 3rd party library may have added | |||
1012 | for (var key in NativeDate) { | |||
1013 | if (owns(NativeDate, key)) { | |||
1014 | DateShim[key] = NativeDate[key]; | |||
1015 | } | |||
1016 | } | |||
1017 | ||||
1018 | // Copy "native" methods explicitly; they may be non-enumerable | |||
1019 | DateShim.now = NativeDate.now; | |||
1020 | DateShim.UTC = NativeDate.UTC; | |||
1021 | DateShim.prototype = NativeDate.prototype; | |||
1022 | DateShim.prototype.constructor = DateShim; | |||
1023 | ||||
1024 | // Upgrade Date.parse to handle simplified ISO 8601 strings | |||
1025 | DateShim.parse = function parse(string) { | |||
1026 | var match = isoDateExpression.exec(string); | |||
1027 | if (match) { | |||
1028 | // parse months, days, hours, minutes, seconds, and milliseconds | |||
1029 | // provide default values if necessary | |||
1030 | // parse the UTC offset component | |||
1031 | var year = Number(match[1]), | |||
1032 | month = Number(match[2] || 1) - 1, | |||
1033 | day = Number(match[3] || 1) - 1, | |||
1034 | hour = Number(match[4] || 0), | |||
1035 | minute = Number(match[5] || 0), | |||
1036 | second = Number(match[6] || 0), | |||
1037 | millisecond = Math.floor(Number(match[7] || 0) * 1000), | |||
1038 | // When time zone is missed, local offset should be used | |||
1039 | // (ES 5.1 bug) | |||
1040 | // see https://bugs.ecmascript.org/show_bug.cgi?id=112 | |||
1041 | isLocalTime = Boolean(match[4] && !match[8]), | |||
1042 | signOffset = match[9] === '-' ? 1 : -1, | |||
1043 | hourOffset = Number(match[10] || 0), | |||
1044 | minuteOffset = Number(match[11] || 0), | |||
1045 | result; | |||
1046 | if ( | |||
1047 | hour < ( | |||
1048 | minute > 0 || second > 0 || millisecond > 0 ? | |||
1049 | 24 : 25 | |||
1050 | ) && | |||
1051 | minute < 60 && second < 60 && millisecond < 1000 && | |||
1052 | month > -1 && month < 12 && hourOffset < 24 && | |||
1053 | minuteOffset < 60 && // detect invalid offsets | |||
1054 | day > -1 && | |||
1055 | day < ( | |||
1056 | dayFromMonth(year, month + 1) - | |||
1057 | dayFromMonth(year, month) | |||
1058 | ) | |||
1059 | ) { | |||
1060 | result = ( | |||
1061 | (dayFromMonth(year, month) + day) * 24 + | |||
1062 | hour + | |||
1063 | hourOffset * signOffset | |||
1064 | ) * 60; | |||
1065 | result = ( | |||
1066 | (result + minute + minuteOffset * signOffset) * 60 + | |||
1067 | second | |||
1068 | ) * 1000 + millisecond; | |||
1069 | if (isLocalTime) { | |||
1070 | result = toUTC(result); | |||
1071 | } | |||
1072 | if (-8.64e15 <= result && result <= 8.64e15) { | |||
1073 | return result; | |||
1074 | } | |||
1075 | } | |||
1076 | return NaN; | |||
1077 | } | |||
1078 | return NativeDate.parse.apply(this, arguments); | |||
1079 | }; | |||
1080 | ||||
1081 | return DateShim; | |||
1082 | }(Date)); | |||
1083 | /*global Date: false */ | |||
1084 | } | |||
1085 | ||||
1086 | // ES5 15.9.4.4 | |||
1087 | // http://es5.github.com/#x15.9.4.4 | |||
1088 | if (!Date.now) { | |||
1089 | Date.now = function now() { | |||
1090 | return new Date().getTime(); | |||
1091 | }; | |||
1092 | } | |||
1093 | ||||
1094 | // | |||
1095 | // Number | |||
1096 | // ====== | |||
1097 | // | |||
1098 | ||||
1099 | // ES5.1 15.7.4.5 | |||
1100 | // http://es5.github.com/#x15.7.4.5 | |||
1101 | var hasToFixedBugs = NumberPrototype.toFixed && ( | |||
1102 | (0.00008).toFixed(3) !== '0.000' || | |||
1103 | (0.9).toFixed(0) !== '1' || | |||
1104 | (1.255).toFixed(2) !== '1.25' || | |||
1105 | (1000000000000000128).toFixed(0) !== '1000000000000000128' | |||
1106 | ); | |||
1107 | ||||
1108 | var toFixedHelpers = { | |||
1109 | base: 1e7, | |||
1110 | size: 6, | |||
1111 | data: [0, 0, 0, 0, 0, 0], | |||
1112 | multiply: function multiply(n, c) { | |||
1113 | var i = -1; | |||
1114 | var c2 = c; | |||
1115 | while (++i < toFixedHelpers.size) { | |||
1116 | c2 += n * toFixedHelpers.data[i]; | |||
1117 | toFixedHelpers.data[i] = c2 % toFixedHelpers.base; | |||
1118 | c2 = Math.floor(c2 / toFixedHelpers.base); | |||
1119 | } | |||
1120 | }, | |||
1121 | divide: function divide(n) { | |||
1122 | var i = toFixedHelpers.size, c = 0; | |||
1123 | while (--i >= 0) { | |||
1124 | c += toFixedHelpers.data[i]; | |||
1125 | toFixedHelpers.data[i] = Math.floor(c / n); | |||
1126 | c = (c % n) * toFixedHelpers.base; | |||
1127 | } | |||
1128 | }, | |||
1129 | numToString: function numToString() { | |||
1130 | var i = toFixedHelpers.size; | |||
1131 | var s = ''; | |||
1132 | while (--i >= 0) { | |||
1133 | if (s !== '' || i === 0 || toFixedHelpers.data[i] !== 0) { | |||
1134 | var t = String(toFixedHelpers.data[i]); | |||
1135 | if (s === '') { | |||
1136 | s = t; | |||
1137 | } else { | |||
1138 | s += '0000000'.slice(0, 7 - t.length) + t; | |||
1139 | } | |||
1140 | } | |||
1141 | } | |||
1142 | return s; | |||
1143 | }, | |||
1144 | pow: function pow(x, n, acc) { | |||
1145 | return (n === 0 ? acc : (n % 2 === 1 ? pow(x, n - 1, acc * x) : pow(x * x, n / 2, acc))); | |||
1146 | }, | |||
1147 | log: function log(x) { | |||
1148 | var n = 0; | |||
1149 | var x2 = x; | |||
1150 | while (x2 >= 4096) { | |||
1151 | n += 12; | |||
1152 | x2 /= 4096; | |||
1153 | } | |||
1154 | while (x2 >= 2) { | |||
1155 | n += 1; | |||
1156 | x2 /= 2; | |||
1157 | } | |||
1158 | return n; | |||
1159 | } | |||
1160 | }; | |||
1161 | ||||
1162 | defineProperties(NumberPrototype, { | |||
1163 | toFixed: function toFixed(fractionDigits) { | |||
1164 | var f, x, s, m, e, z, j, k; | |||
1165 | ||||
1166 | // Test for NaN and round fractionDigits down | |||
1167 | f = Number(fractionDigits); | |||
1168 | f = f !== f ? 0 : Math.floor(f); | |||
1169 | ||||
1170 | if (f < 0 || f > 20) { | |||
1171 | throw new RangeError('Number.toFixed called with invalid number of decimals'); | |||
1172 | } | |||
1173 | ||||
1174 | x = Number(this); | |||
1175 | ||||
1176 | // Test for NaN | |||
1177 | if (x !== x) { | |||
1178 | return 'NaN'; | |||
1179 | } | |||
1180 | ||||
1181 | // If it is too big or small, return the string value of the number | |||
1182 | if (x <= -1e21 || x >= 1e21) { | |||
1183 | return String(x); | |||
1184 | } | |||
1185 | ||||
1186 | s = ''; | |||
1187 | ||||
1188 | if (x < 0) { | |||
1189 | s = '-'; | |||
1190 | x = -x; | |||
1191 | } | |||
1192 | ||||
1193 | m = '0'; | |||
1194 | ||||
1195 | if (x > 1e-21) { | |||
1196 | // 1e-21 < x < 1e21 | |||
1197 | // -70 < log2(x) < 70 | |||
1198 | e = toFixedHelpers.log(x * toFixedHelpers.pow(2, 69, 1)) - 69; | |||
1199 | z = (e < 0 ? x * toFixedHelpers.pow(2, -e, 1) : x / toFixedHelpers.pow(2, e, 1)); | |||
1200 | z *= 0x10000000000000; // Math.pow(2, 52); | |||
1201 | e = 52 - e; | |||
1202 | ||||
1203 | // -18 < e < 122 | |||
1204 | // x = z / 2 ^ e | |||
1205 | if (e > 0) { | |||
1206 | toFixedHelpers.multiply(0, z); | |||
1207 | j = f; | |||
1208 | ||||
1209 | while (j >= 7) { | |||
1210 | toFixedHelpers.multiply(1e7, 0); | |||
1211 | j -= 7; | |||
1212 | } | |||
1213 | ||||
1214 | toFixedHelpers.multiply(toFixedHelpers.pow(10, j, 1), 0); | |||
1215 | j = e - 1; | |||
1216 | ||||
1217 | while (j >= 23) { | |||
1218 | toFixedHelpers.divide(1 << 23); | |||
1219 | j -= 23; | |||
1220 | } | |||
1221 | ||||
1222 | toFixedHelpers.divide(1 << j); | |||
1223 | toFixedHelpers.multiply(1, 1); | |||
1224 | toFixedHelpers.divide(2); | |||
1225 | m = toFixedHelpers.numToString(); | |||
1226 | } else { | |||
1227 | toFixedHelpers.multiply(0, z); | |||
1228 | toFixedHelpers.multiply(1 << (-e), 0); | |||
1229 | m = toFixedHelpers.numToString() + '0.00000000000000000000'.slice(2, 2 + f); | |||
1230 | } | |||
1231 | } | |||
1232 | ||||
1233 | if (f > 0) { | |||
1234 | k = m.length; | |||
1235 | ||||
1236 | if (k <= f) { | |||
1237 | m = s + '0.0000000000000000000'.slice(0, f - k + 2) + m; | |||
1238 | } else { | |||
1239 | m = s + m.slice(0, k - f) + '.' + m.slice(k - f); | |||
1240 | } | |||
1241 | } else { | |||
1242 | m = s + m; | |||
1243 | } | |||
1244 | ||||
1245 | return m; | |||
1246 | } | |||
1247 | }, hasToFixedBugs); | |||
1248 | ||||
1249 | // | |||
1250 | // String | |||
1251 | // ====== | |||
1252 | // | |||
1253 | ||||
1254 | // ES5 15.5.4.14 | |||
1255 | // http://es5.github.com/#x15.5.4.14 | |||
1256 | ||||
1257 | // [bugfix, IE lt 9, firefox 4, Konqueror, Opera, obscure browsers] | |||
1258 | // Many browsers do not split properly with regular expressions or they | |||
1259 | // do not perform the split correctly under obscure conditions. | |||
1260 | // See http://blog.stevenlevithan.com/archives/cross-browser-split | |||
1261 | // I've tested in many browsers and this seems to cover the deviant ones: | |||
1262 | // 'ab'.split(/(?:ab)*/) should be ["", ""], not [""] | |||
1263 | // '.'.split(/(.?)(.?)/) should be ["", ".", "", ""], not ["", ""] | |||
1264 | // 'tesst'.split(/(s)*/) should be ["t", undefined, "e", "s", "t"], not | |||
1265 | // [undefined, "t", undefined, "e", ...] | |||
1266 | // ''.split(/.?/) should be [], not [""] | |||
1267 | // '.'.split(/()()/) should be ["."], not ["", "", "."] | |||
1268 | ||||
1269 | var string_split = StringPrototype.split; | |||
1270 | if ( | |||
1271 | 'ab'.split(/(?:ab)*/).length !== 2 || | |||
1272 | '.'.split(/(.?)(.?)/).length !== 4 || | |||
1273 | 'tesst'.split(/(s)*/)[1] === 't' || | |||
1274 | 'test'.split(/(?:)/, -1).length !== 4 || | |||
1275 | ''.split(/.?/).length || | |||
1276 | '.'.split(/()()/).length > 1 | |||
1277 | ) { | |||
1278 | (function () { | |||
1279 | var compliantExecNpcg = typeof (/()??/).exec('')[1] === 'undefined'; // NPCG: nonparticipating capturing group | |||
1280 | ||||
1281 | StringPrototype.split = function (separator, limit) { | |||
1282 | var string = this; | |||
1283 | if (typeof separator === 'undefined' && limit === 0) { | |||
1284 | return []; | |||
1285 | } | |||
1286 | ||||
1287 | // If `separator` is not a regex, use native split | |||
1288 | if (!isRegex(separator)) { | |||
1289 | return string_split.call(this, separator, limit); | |||
1290 | } | |||
1291 | ||||
1292 | var output = []; | |||
1293 | var flags = (separator.ignoreCase ? 'i' : '') + | |||
1294 | (separator.multiline ? 'm' : '') + | |||
1295 | (separator.extended ? 'x' : '') + // Proposed for ES6 | |||
1296 | (separator.sticky ? 'y' : ''), // Firefox 3+ | |||
1297 | lastLastIndex = 0, | |||
1298 | // Make `global` and avoid `lastIndex` issues by working with a copy | |||
1299 | separator2, match, lastIndex, lastLength; | |||
1300 | var separatorCopy = new RegExp(separator.source, flags + 'g'); | |||
1301 | string += ''; // Type-convert | |||
1302 | if (!compliantExecNpcg) { | |||
1303 | // Doesn't need flags gy, but they don't hurt | |||
1304 | separator2 = new RegExp('^' + separatorCopy.source + '$(?!\\s)', flags); |
shim.js
View file @
199c806
File was created | 1 | casper.on( 'page.initialized', function(){ | ||
2 | this.evaluate(function(){ | |||
3 | var isFunction = function(o) { | |||
4 | return typeof o == 'function'; | |||
5 | }; | |||
6 | ||||
7 | var bind, | |||
8 | slice = [].slice, | |||
9 | proto = Function.prototype, | |||
10 | featureMap; | |||
11 | ||||
12 | featureMap = { | |||
13 | 'function-bind': 'bind' | |||
14 | }; | |||
15 | ||||
16 | function has(feature) { | |||
17 | var prop = featureMap[feature]; | |||
18 | return isFunction(proto[prop]); | |||
19 | } | |||
20 | ||||
21 | // check for missing features | |||
22 | if (!has('function-bind')) { | |||
23 | // adapted from Mozilla Developer Network example at | |||
24 | // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind | |||
25 | bind = function bind(obj) { | |||
26 | var args = slice.call(arguments, 1), | |||
27 | self = this, | |||
28 | nop = function() { | |||
29 | }, | |||
30 | bound = function() { | |||
31 | return self.apply(this instanceof nop ? this : (obj || {}), args.concat(slice.call(arguments))); | |||
32 | }; | |||
33 | nop.prototype = this.prototype || {}; // Firefox cries sometimes if prototype is undefined | |||
34 | bound.prototype = new nop(); | |||
35 | return bound; | |||
36 | }; |
take_screenshots.js
View file @
199c806
File was created | 1 | //http://docs.casperjs.org/en/latest/modules/casper.html#captureselector | ||
2 | //Run with: casperjs --ssl-protocol=tlsv1 ss_test.js | |||
3 | ||||
4 | var utils = require('utils'); | |||
5 | ||||
6 | var casper = require('casper').create({ | |||
7 | verbose: true, | |||
8 | logLevel: "debug", | |||
9 | viewportSize: {width: 1200, height: 800}, | |||
10 | onResourceReceived: function(C, requestData, request) { | |||
11 | //utils.dump(requestData); | |||
12 | }, | |||
13 | }); | |||
14 | casper.on('remote.msg', function(data){ | |||
15 | this.echo(data); | |||
16 | }); | |||
17 | ||||
18 | casper.on( 'page.error', function (msg, trace) { | |||
19 | this.echo(msg); | |||
20 | }); | |||
21 | phantom.page.injectJs( 'shim.js'); | |||
22 | function screenshot(pagename) { | |||
23 | casper.capture('built/screenshots/'+pagename+'.png', { | |||
24 | top: 0, | |||
25 | left: 0, | |||
26 | width: 1200, | |||
27 | height: 600, | |||
28 | quality:100 | |||
29 | }); | |||
30 | } | |||
31 | ||||
32 | casper.start('https://flashy.cards/app/login',function(){ | |||
33 | screenshot('login'); | |||
34 | /* this.fill('form', { | |||
35 | 'email': 'casper@flashy.cards', | |||
36 | 'password': 'casper' | |||
37 | }, true); | |||
38 | this.echo('logged in?');*/ | |||
39 | }).thenOpen('https://flashy.cards/app/requestpasswordreset', function () { | |||
40 | screenshot('requestpasswordreset.png'); | |||
41 | }).thenOpen('https://flashy.cards/app/resetpassword', function () { | |||
42 | screenshot('resetpassword.png'); | |||
43 | }).thenOpen('https://flashy.cards/app/addclass', function () { | |||
44 | screenshot('addclass.png'); | |||
45 | }).thenOpen('https://flashy.cards/app/deck', function () { | |||
46 | screenshot('deck.png'); | |||
47 | }).thenOpen('https://flashy.cards/app/feed', function () { | |||
48 | screenshot('feed.png'); | |||
49 | }).thenOpen('https://flashy.cards/app/study', function () { | |||
50 | screenshot('study.png'); | |||
51 | }).thenOpen('https://flashy.cards/app/flashcard', function () { | |||
52 | screenshot('flashcard.png'); | |||
53 | }).thenOpen('https://flashy.cards/app/logout', function () { | |||
54 | screenshot('logout.png'); |