├── .arc ├── .gitignore ├── .static └── favicon.ico ├── LICENSE ├── README.md ├── package-lock.json ├── package.json └── src ├── html ├── get-about │ ├── about.html │ ├── index.js │ ├── package-lock.json │ └── package.json ├── get-index │ ├── index.html │ ├── index.js │ ├── package-lock.json │ └── package.json ├── get-license │ ├── index.js │ ├── license.html │ ├── package-lock.json │ └── package.json ├── get-wtfs-000wtfID │ ├── index.js │ ├── package-lock.json │ └── package.json └── get-wtfs │ ├── index.js │ ├── package-lock.json │ └── package.json └── shared ├── index.css ├── layout.js ├── md ├── 2010-02-12-almost-but-not-quite.md ├── 2010-02-12-foonanny.md ├── 2010-02-12-function-context-fun.md ├── 2010-02-12-maths-fun.md ├── 2010-02-12-min-number-treachery.md ├── 2010-02-12-not-a-number-is-a-number.md ├── 2010-02-12-not-a-number-is-not-a-not-a-number.md ├── 2010-02-12-null-is-not-an-object.md ├── 2010-02-12-parseint-treachery.md ├── 2010-02-13-null-is-not-falsy.md ├── 2010-02-13-string-is-not-string.md ├── 2010-02-15-accidental-global.md ├── 2010-02-15-careful.md ├── 2010-02-15-coerce-equality.md ├── 2010-02-15-firebug-reserved.md ├── 2010-02-15-hoisting.md ├── 2010-02-15-more-coerce-fun.md ├── 2010-02-15-scope-fun.md ├── 2010-02-15-thc-timetravel.md ├── 2010-02-15-timeout-delay.md ├── 2010-02-15-true-has-a-value.md ├── 2010-02-15-undefined-is-mutable.md ├── 2010-02-16-automagic-semicolons.md ├── 2010-02-16-more-floating-point-rounding.md ├── 2010-02-16-reserved-for-future-use-maybe.md ├── 2010-02-19-concat-coerce.md ├── 2010-02-23-arguing-with-arguments.md ├── 2010-02-23-boolean-paradox.md ├── 2010-02-23-coerced.md ├── 2010-02-23-declaration-vs-initialization.md ├── 2010-02-23-makes-perfect-sense.md ├── 2010-02-24-messing-with-number-prototype.md ├── 2010-02-25-ie-and-webkit-agree.md ├── 2010-02-25-ie-scope.md ├── 2010-02-25-jsftw ├── 2010-02-25-jsftw:-google-closure-compiler.md ├── 2010-02-26-array-crazy.md ├── 2010-02-26-implicit-tostring-fun.md ├── 2010-03-02-ie-cursed-recursion.md ├── 2010-03-04-max-vs-the-infinite.md ├── 2010-04-02-object-to-primitive-coerce.md ├── 2010-04-12-call-in-ur-call.md ├── 2010-04-15-hello-world.md ├── 2010-04-16-build-your-own-wtfjs.md ├── 2010-04-16-contributing-to-wtfjs.md ├── 2010-04-16-express-js-gotcha.md ├── 2010-04-16-syntax-highlighting-wtf.md ├── 2010-04-17-global-scope-mindtricks.md ├── 2010-04-30-operators-and-regexp-fun.md ├── 2010-04-31-isNaN.md ├── 2010-04-31-syntax-highlighting-serverside-with-google-prettyfy.md ├── 2010-06-02-instances-and-default-values.md ├── 2010-06-08-void-is-a-black-hole.md ├── 2010-06-09-function-in-ur-string.md ├── 2010-07-11-length-of-what-now.md ├── 2010-07-12-fail.md ├── 2010-07-15-typeof-number-is-not-number.md ├── 2010-07-22-magic-increasing-number.md ├── 2010-07-23-im-not-a-number-really.md ├── 2010-09-16-eval-changes.md ├── 2010-10-15-ie-754.md ├── 2010-11-10-false-advertising.md ├── 2010-11-15-i-am-myself-but-also-not-myself.md ├── 2010-12-06-convert-to-integer.md ├── 2011-02-11-all-your-commas-are-belong-to-Array.md ├── 2011-05-12-parseInt-is-not-eval.md ├── 2011-06-23-parseint-magic.md ├── 2011-06-27-min-less-max.md ├── 2011-07-26-iteration-demoralization.md ├── 2011-09-24-Date-silently-accepts-anything.md ├── 2011-11-08-undefined-identity-crisis.md ├── 2011-11-11-the-universe-answers-and-JavaScript-still-makes-us-wtf.md ├── 2011-12-16-negative-zero-equal-but-not-equal.md ├── 2012-04-18-changing-variables-changes-arguments.md ├── 2012-05-07-Numbers-and-dots.md ├── 2012-08-11-Slashes!.md ├── 2012-09-19-Hexadecimal-weirdness.md ├── 2012-10-10-infinity-madness.md ├── 2012-12-28-undefined-props-on-numbers.md ├── 2013-01-28-array-comparison.md ├── 2013-02-05-magic-function-properties.md ├── 2013-02-12-obfuscated-fibonacci.md ├── 2013-02-13-unicode-vars.md ├── 2013-02-21-why-am-i-a-number.md ├── 2013-02-22-parseint-radix.md ├── 2013-02-28-null,-undefined-and-test.md ├── 2013-03-06-false-isnt-false.md ├── 2013-03-25-null-to-bool.md ├── 2013-03-27-automatic-semicolon-insertion.md ├── 2013-04-18-true-story-bro.md ├── 2013-04-28-isfinite-null-is-true.md ├── 2013-06-20-negative-indexes.md ├── 2013-07-04-array-constructor.md ├── 2013-07-18-array-ruse.md ├── 2013-08-07-Math.max()-behaviour.md ├── 2013-09-30-Array-Constructor2-is-Very-Undefined.md ├── 2013-10-02-implicit-getElementById.md ├── 2013-10-07-Local-storage-limitations.md ├── 2013-12-15-charAt-is-not-the-same-as-[].md ├── 2013-12-19-The-Hungry-Variable.md ├── 2014-01-11-multiplying-arrays-and-objects.md ├── 2014-01-29-regular-expression-and-slash.md ├── 2014-02-04-Date.Date-vs-Year.md ├── 2014-02-20-math-pow.md ├── 2014-02-22-wtf_document.all.md ├── 2014-02-25-array-indexof.md ├── 2014-03-13-String-Integers-Comparison.md ├── 2014-03-13-regex-test-true-false.md ├── 2014-05-05-this-length.md ├── 2014-10-07-true-equals-false.md ├── 2014-11-22-object-as-object-key.md ├── 2015-02-02-Boolean-constructor.md ├── 2015-02-05-good-old-octal-decimal-wtf.md ├── 2015-03-23-adding-arrays.md ├── 2015-04-08-array-sort.md ├── 2015-04-16-moving-numbers.md ├── 2015-04-23-screwy-negative-array-index.md ├── 2016-03-09-Two-Special-Numbers.md ├── 2016-03-10-Object-And-Array-Prototype-Length.md ├── 2016-03-19-weird-instanceof.md ├── 2018-19-01-weird-number-addition.md ├── package-lock.json └── package.json └── readme.md /.arc: -------------------------------------------------------------------------------- 1 | @app 2 | wtfjs 3 | 4 | @domain 5 | wtfjs.com 6 | 7 | @static 8 | staging wtfjs-staging 9 | production wtfjs-production 10 | 11 | @aws 12 | profile personal 13 | region us-west-1 14 | 15 | @html 16 | get / 17 | get /about 18 | get /license 19 | get /wtfs 20 | get /wtfs/:wtfID 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /.static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brianleroux/wtfjs/01cd583e474f9b64fdcd65fece03848397e3dd46/.static/favicon.ico -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2010 Brian LeRoux 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
 2 |     :::       :::::::::::::::::::::::::::::::::::::::::::
 3 |     :+:       :+:    :+:    :+:           :+:   :+:    :+:
 4 |     +:+       +:+    +:+    +:+           +:+   +:+
 5 |     +#+  +:+  +#+    +#+    :#::+::#      +#+   +#++:++#++
 6 |     +#+ +#+#+ +#+    +#+    +#+           +#+          +#+
 7 |      #+#+# #+#+#     #+#    #+#       #+# #+#   #+#    #+#
 8 |       ###   ###      ###    ###        #####     ########
 9 |       ---------------------------------------------------
10 |       JavaScript code blog.
11 | 
12 | 13 | 14 | Share your wtfjs moment 15 | --- 16 | 17 | It has never been easier to contribute a wtf to wtfjs.com! 18 | 19 | - fork this repo 20 | - add your wtf under `src/shared/md` (format: `yyyy-mm-dd-title.md`) 21 | - don't forget to add your name and link to twitter/github at the bottom! 22 | - send a pull request 23 | - WTF 24 | 25 | ### Example post format 26 |
27 | ```
28 | Array(20).map(function(elem) { return 'a'; }); // Array of undefined x 20
29 | ```
30 | 
31 | More info [here](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.19).
32 | Thanks [Paul Irish](https://twitter.com/paul_irish) for the explanation.
33 | 
34 | — [@yourtwitterhandle_or_githubhandle][1]
35 | 
36 | [1]:https://githubortwitter.com/yourusername
37 | 
38 | 39 | was created by [@brianleroux](http://twitter.com/brianleroux). Everything here is under the [WTFPL 2.0 license](http://wtfjs.com/license). 40 | 41 | [1]: http://github.com/DTrejo 42 | 43 | --- 44 | 45 | ### Contributors 46 | Ordered by date of first contribution. 47 | [Auto-generated](http://github.com/dtrejo/node-authors) on Thu Aug 09 2012 19:07:44 GMT-0700 (PDT). 48 | 49 | - [Brian LeRoux aka `brianleroux`](https://github.com/brianleroux) 50 | - [Oleg Slobodskoi aka `kof`](https://github.com/kof) 51 | - [Allen Pike aka `akrabat`](https://github.com/akrabat) 52 | - [Rémi Prévost aka `remiprev`](https://github.com/remiprev) 53 | - [rwldrn aka `rwldrn`](https://github.com/rwldrn) 54 | - [Luke Andrews aka `attaboy`](https://github.com/attaboy) 55 | - [AJ ONeal aka `coolaj86`](https://github.com/coolaj86) 56 | - [Kambfhase aka `Kambfhase`](https://github.com/Kambfhase) 57 | - [Thomas Fuchs aka `madrobby`](https://github.com/madrobby) 58 | - [Arnout Kazemier aka `3rd-Eden`](https://github.com/3rd-Eden) 59 | - [Bradley Meck aka `bmeck`](https://github.com/bmeck) 60 | - [airportyh aka `airportyh`](https://github.com/airportyh) 61 | - [Diogo Baeder de Paula Pinto aka `diogobaeder`](https://github.com/diogobaeder) 62 | - [Peter Galiba aka `Poetro`](https://github.com/Poetro) 63 | - [Dan Beam aka `danbeam`](https://github.com/danbeam) 64 | - [David Trejo aka `DTrejo`](https://github.com/DTrejo) 65 | - [Jakub Vrana aka `vrana`](https://github.com/vrana) 66 | - [Bodo Tasche aka `bitboxer`](https://github.com/bitboxer) 67 | - [qfox aka `qfox`](https://github.com/qfox) 68 | - [Johan Sundström aka `johan`](https://github.com/johan) 69 | - [Mathias Bynens aka `mathiasbynens`](https://github.com/mathiasbynens) 70 | - [Ken Snyder aka `kensnyder`](https://github.com/kensnyder) 71 | - [David Wolever aka `wolever`](https://github.com/wolever) 72 | - [Brandon Benvie aka `Benvie`](https://github.com/Benvie) 73 | - [Stephen Belanger aka `Qard`](https://github.com/Qard) 74 | - [Dan Lash aka `danlash`](https://github.com/danlash) 75 | - [Pawel 'lord_T' Maruszczyk aka `pawel`](https://github.com/pawel) 76 | - [David Chambers aka `mikechambers`](https://github.com/mikechambers) 77 | - [Jamund Ferguson aka `xjamundx`](https://github.com/xjamundx) 78 | - [Thaddee Tyl aka `espadrine`](https://github.com/espadrine) 79 | - [Stanley Stuart aka `fivetanley`](https://github.com/fivetanley) 80 | - [Ben Combee aka `unwiredben`](https://github.com/unwiredben) 81 | - [Gonçalo Morais aka `gnclmorais`](https://github.com/gnclmorais) 82 | - [Maxime Euzière aka `xem`](https://github.com/xem) 83 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wtf", 3 | "description": "The wtfs of javascript at wtfjs.com", 4 | "version": "5.0.2", 5 | "homepage": "wtfjs.com", 6 | "repository": { 7 | "type": "git", 8 | "url": "git://github.com/brianleroux/wtfjs.git" 9 | }, 10 | "author": "Brian Leroux ", 11 | "subdomain": "wtfjs", 12 | "domains": [ 13 | "wtfjs.com", 14 | "www.wtfjs.com" 15 | ], 16 | "license": "WTFPL", 17 | "dependencies": { 18 | "@architect/workflows": "^3.4.2" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/html/get-about/about.html: -------------------------------------------------------------------------------- 1 |

about

2 |

JavaScript is a language we love despite it giving us so much to hate. This is a collection of those very special irregularities, inconsistencies and just plain painfully unintuitive moments for the language of the web.

3 | 4 | 5 |

contributing authors

6 |

7 | These fine folk have been the brave warriors of code whom kicked out a wtf for your laughter (or perhaps compassionate tears). Adding a post is simple: 8 |

9 | 10 |
    11 |
  1. Fork the code on Github
  2. 12 |
  3. Add a post to the ./posts folder in the following format: yyyy-mm-dd-title-text-here.md ..yes its Markdown. See the other posts for examples.
  4. 13 |
  5. Send @brianleroux a pull request.
  6. 14 |
15 | 16 |

Meta

17 |

18 | 19 | The first crack at this site was a quick and dirty Tumblr thing authored w/ 20 | @alunny. The second iteration was a 21 | ground up custom authored NodeJS (0.1.x) blog by @brianleroux. This most recent 23 | incarnation is an evolution of the original NodeJS codebase (0.4.x) with 24 | help from David Trejo (@ddtrejo). The latest 25 | latest incarnation is an migration from 0.4.x to 0.8.x, also with help from 26 | @ddtrejo. 27 |

28 | -------------------------------------------------------------------------------- /src/html/get-about/index.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | var path = require('path') 3 | var arc = require('@architect/functions') 4 | var layout = require('@architect/shared/layout') 5 | var about = fs.readFileSync(path.join(__dirname, 'about.html')).toString() 6 | 7 | function route(req, res) { 8 | res({html:layout(about)}) 9 | } 10 | 11 | exports.handler = arc.html.get(route) 12 | -------------------------------------------------------------------------------- /src/html/get-about/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wtfjs-get-about", 3 | "requires": true, 4 | "lockfileVersion": 1, 5 | "dependencies": { 6 | "@architect/data": { 7 | "version": "2.0.5", 8 | "resolved": "https://registry.npmjs.org/@architect/data/-/data-2.0.5.tgz", 9 | "integrity": "sha512-potdYRGmgpelOfGncPw6W2iCUyJ7S+N8hdFxM/Uc9Hh6V9cQIBQK9nuinogaNGkGTQTk7MiN86Szszynp1uWjw==", 10 | "requires": { 11 | "@architect/parser": "^1.0.6", 12 | "chalk": "^2.3.0" 13 | } 14 | }, 15 | "@architect/functions": { 16 | "version": "1.9.2", 17 | "resolved": "https://registry.npmjs.org/@architect/functions/-/functions-1.9.2.tgz", 18 | "integrity": "sha512-nQFEc2deBwKYTUR8Do6gwx2oIPyyviIoEeV6OQiE+WCcP+rLslkE0zArGiDUj11GgzCF6VWblto5vKTaM1spNQ==", 19 | "requires": { 20 | "@architect/parser": "^1.1.0", 21 | "@smallwins/err": "^1.0.0", 22 | "cookie": "^0.3.1", 23 | "cookie-signature": "^1.1.0", 24 | "csrf": "^3.0.6", 25 | "is-plain-object": "^2.0.4", 26 | "run-parallel": "^1.1.9", 27 | "run-waterfall": "^1.1.6", 28 | "serialize-error": "^2.1.0", 29 | "uid-safe": "^2.1.5" 30 | } 31 | }, 32 | "@architect/parser": { 33 | "version": "1.1.2", 34 | "resolved": "https://registry.npmjs.org/@architect/parser/-/parser-1.1.2.tgz", 35 | "integrity": "sha512-MrCoCcZnEhvLI+6BiOs45/qAWD/NnpBY/fLnX1MSxyzr9DR5cz8lat0Nip1E+a10h5BxLpMoFO/nXUWEfq3OQA==" 36 | }, 37 | "@smallwins/err": { 38 | "version": "1.0.0", 39 | "resolved": "https://registry.npmjs.org/@smallwins/err/-/err-1.0.0.tgz", 40 | "integrity": "sha1-tk2WSldWcGukV/Dhwtem7h2GZwA=", 41 | "requires": { 42 | "clean-stack": "^1.3.0", 43 | "serialize-error": "^2.1.0" 44 | } 45 | }, 46 | "ansi-styles": { 47 | "version": "3.2.1", 48 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 49 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 50 | "requires": { 51 | "color-convert": "^1.9.0" 52 | } 53 | }, 54 | "chalk": { 55 | "version": "2.4.1", 56 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", 57 | "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", 58 | "requires": { 59 | "ansi-styles": "^3.2.1", 60 | "escape-string-regexp": "^1.0.5", 61 | "supports-color": "^5.3.0" 62 | } 63 | }, 64 | "clean-stack": { 65 | "version": "1.3.0", 66 | "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-1.3.0.tgz", 67 | "integrity": "sha1-noIVAa6XmYbEax1m0tQy2y/UrjE=" 68 | }, 69 | "color-convert": { 70 | "version": "1.9.3", 71 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 72 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 73 | "requires": { 74 | "color-name": "1.1.3" 75 | } 76 | }, 77 | "color-name": { 78 | "version": "1.1.3", 79 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 80 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 81 | }, 82 | "cookie": { 83 | "version": "0.3.1", 84 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 85 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" 86 | }, 87 | "cookie-signature": { 88 | "version": "1.1.0", 89 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.1.0.tgz", 90 | "integrity": "sha512-Alvs19Vgq07eunykd3Xy2jF0/qSNv2u7KDbAek9H5liV1UMijbqFs5cycZvv5dVsvseT/U4H8/7/w8Koh35C4A==" 91 | }, 92 | "csrf": { 93 | "version": "3.0.6", 94 | "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.0.6.tgz", 95 | "integrity": "sha1-thEg3c7q/JHnbtUxO7XAsmZ7cQo=", 96 | "requires": { 97 | "rndm": "1.2.0", 98 | "tsscmp": "1.0.5", 99 | "uid-safe": "2.1.4" 100 | }, 101 | "dependencies": { 102 | "uid-safe": { 103 | "version": "2.1.4", 104 | "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz", 105 | "integrity": "sha1-Otbzg2jG1MjHXsF2I/t5qh0HHYE=", 106 | "requires": { 107 | "random-bytes": "~1.0.0" 108 | } 109 | } 110 | } 111 | }, 112 | "escape-string-regexp": { 113 | "version": "1.0.5", 114 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 115 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 116 | }, 117 | "has-flag": { 118 | "version": "3.0.0", 119 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 120 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" 121 | }, 122 | "is-plain-object": { 123 | "version": "2.0.4", 124 | "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", 125 | "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", 126 | "requires": { 127 | "isobject": "^3.0.1" 128 | } 129 | }, 130 | "isobject": { 131 | "version": "3.0.1", 132 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", 133 | "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" 134 | }, 135 | "random-bytes": { 136 | "version": "1.0.0", 137 | "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", 138 | "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" 139 | }, 140 | "rndm": { 141 | "version": "1.2.0", 142 | "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", 143 | "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=" 144 | }, 145 | "run-parallel": { 146 | "version": "1.1.9", 147 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", 148 | "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==" 149 | }, 150 | "run-waterfall": { 151 | "version": "1.1.6", 152 | "resolved": "https://registry.npmjs.org/run-waterfall/-/run-waterfall-1.1.6.tgz", 153 | "integrity": "sha512-dApPbpIK0hbFi2zqfJxrsnfmJW2HCQHFrSsmqF3Fp9TKm5WVf++zE6BSw0hPcA7rPapO37h12Swk2E6Va3tF7Q==" 154 | }, 155 | "serialize-error": { 156 | "version": "2.1.0", 157 | "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz", 158 | "integrity": "sha1-ULZ51WNc34Rme9yOWa9OW4HV9go=" 159 | }, 160 | "supports-color": { 161 | "version": "5.5.0", 162 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 163 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 164 | "requires": { 165 | "has-flag": "^3.0.0" 166 | } 167 | }, 168 | "tsscmp": { 169 | "version": "1.0.5", 170 | "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", 171 | "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=" 172 | }, 173 | "uid-safe": { 174 | "version": "2.1.5", 175 | "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", 176 | "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", 177 | "requires": { 178 | "random-bytes": "~1.0.0" 179 | } 180 | } 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /src/html/get-about/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wtfjs-get-about", 3 | "dependencies": { 4 | "@architect/data": "^2.0.5", 5 | "@architect/functions": "^1.9.2" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/html/get-index/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brianleroux/wtfjs/01cd583e474f9b64fdcd65fece03848397e3dd46/src/html/get-index/index.html -------------------------------------------------------------------------------- /src/html/get-index/index.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | var path = require('path') 3 | var arc = require('@architect/functions') 4 | var layout = require('@architect/shared/layout') 5 | var filter = f=> f.includes('.md') 6 | var files = fs.readdirSync(__dirname + '/node_modules/@architect/shared/md').filter(filter).reverse() 7 | var index = false 8 | 9 | function link(file) { 10 | var val = file.replace('.md', '') 11 | var name = val.replace(/-/g, ' ') 12 | return `
  • ${name}
  • ` 13 | } 14 | 15 | function route(req, res) { 16 | if (!index) index = fs.readFileSync(path.join(__dirname, 'index.html')).toString() 17 | var list = files.map(link).join('') 18 | res({html:layout(index + list)}) 19 | } 20 | 21 | exports.handler = arc.html.get(route) 22 | -------------------------------------------------------------------------------- /src/html/get-index/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wtfjs-get-index", 3 | "requires": true, 4 | "lockfileVersion": 1, 5 | "dependencies": { 6 | "@architect/data": { 7 | "version": "2.0.5", 8 | "resolved": "https://registry.npmjs.org/@architect/data/-/data-2.0.5.tgz", 9 | "integrity": "sha512-potdYRGmgpelOfGncPw6W2iCUyJ7S+N8hdFxM/Uc9Hh6V9cQIBQK9nuinogaNGkGTQTk7MiN86Szszynp1uWjw==", 10 | "requires": { 11 | "@architect/parser": "^1.0.6", 12 | "chalk": "^2.3.0" 13 | } 14 | }, 15 | "@architect/functions": { 16 | "version": "1.9.2", 17 | "resolved": "https://registry.npmjs.org/@architect/functions/-/functions-1.9.2.tgz", 18 | "integrity": "sha512-nQFEc2deBwKYTUR8Do6gwx2oIPyyviIoEeV6OQiE+WCcP+rLslkE0zArGiDUj11GgzCF6VWblto5vKTaM1spNQ==", 19 | "requires": { 20 | "@architect/parser": "^1.1.0", 21 | "@smallwins/err": "^1.0.0", 22 | "cookie": "^0.3.1", 23 | "cookie-signature": "^1.1.0", 24 | "csrf": "^3.0.6", 25 | "is-plain-object": "^2.0.4", 26 | "run-parallel": "^1.1.9", 27 | "run-waterfall": "^1.1.6", 28 | "serialize-error": "^2.1.0", 29 | "uid-safe": "^2.1.5" 30 | } 31 | }, 32 | "@architect/parser": { 33 | "version": "1.1.2", 34 | "resolved": "https://registry.npmjs.org/@architect/parser/-/parser-1.1.2.tgz", 35 | "integrity": "sha512-MrCoCcZnEhvLI+6BiOs45/qAWD/NnpBY/fLnX1MSxyzr9DR5cz8lat0Nip1E+a10h5BxLpMoFO/nXUWEfq3OQA==" 36 | }, 37 | "@smallwins/err": { 38 | "version": "1.0.0", 39 | "resolved": "https://registry.npmjs.org/@smallwins/err/-/err-1.0.0.tgz", 40 | "integrity": "sha1-tk2WSldWcGukV/Dhwtem7h2GZwA=", 41 | "requires": { 42 | "clean-stack": "^1.3.0", 43 | "serialize-error": "^2.1.0" 44 | } 45 | }, 46 | "ansi-styles": { 47 | "version": "3.2.1", 48 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 49 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 50 | "requires": { 51 | "color-convert": "^1.9.0" 52 | } 53 | }, 54 | "chalk": { 55 | "version": "2.4.1", 56 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", 57 | "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", 58 | "requires": { 59 | "ansi-styles": "^3.2.1", 60 | "escape-string-regexp": "^1.0.5", 61 | "supports-color": "^5.3.0" 62 | } 63 | }, 64 | "clean-stack": { 65 | "version": "1.3.0", 66 | "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-1.3.0.tgz", 67 | "integrity": "sha1-noIVAa6XmYbEax1m0tQy2y/UrjE=" 68 | }, 69 | "color-convert": { 70 | "version": "1.9.3", 71 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 72 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 73 | "requires": { 74 | "color-name": "1.1.3" 75 | } 76 | }, 77 | "color-name": { 78 | "version": "1.1.3", 79 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 80 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 81 | }, 82 | "cookie": { 83 | "version": "0.3.1", 84 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 85 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" 86 | }, 87 | "cookie-signature": { 88 | "version": "1.1.0", 89 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.1.0.tgz", 90 | "integrity": "sha512-Alvs19Vgq07eunykd3Xy2jF0/qSNv2u7KDbAek9H5liV1UMijbqFs5cycZvv5dVsvseT/U4H8/7/w8Koh35C4A==" 91 | }, 92 | "csrf": { 93 | "version": "3.0.6", 94 | "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.0.6.tgz", 95 | "integrity": "sha1-thEg3c7q/JHnbtUxO7XAsmZ7cQo=", 96 | "requires": { 97 | "rndm": "1.2.0", 98 | "tsscmp": "1.0.5", 99 | "uid-safe": "2.1.4" 100 | }, 101 | "dependencies": { 102 | "uid-safe": { 103 | "version": "2.1.4", 104 | "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz", 105 | "integrity": "sha1-Otbzg2jG1MjHXsF2I/t5qh0HHYE=", 106 | "requires": { 107 | "random-bytes": "~1.0.0" 108 | } 109 | } 110 | } 111 | }, 112 | "escape-string-regexp": { 113 | "version": "1.0.5", 114 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 115 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 116 | }, 117 | "has-flag": { 118 | "version": "3.0.0", 119 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 120 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" 121 | }, 122 | "is-plain-object": { 123 | "version": "2.0.4", 124 | "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", 125 | "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", 126 | "requires": { 127 | "isobject": "^3.0.1" 128 | } 129 | }, 130 | "isobject": { 131 | "version": "3.0.1", 132 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", 133 | "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" 134 | }, 135 | "random-bytes": { 136 | "version": "1.0.0", 137 | "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", 138 | "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" 139 | }, 140 | "rndm": { 141 | "version": "1.2.0", 142 | "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", 143 | "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=" 144 | }, 145 | "run-parallel": { 146 | "version": "1.1.9", 147 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", 148 | "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==" 149 | }, 150 | "run-waterfall": { 151 | "version": "1.1.6", 152 | "resolved": "https://registry.npmjs.org/run-waterfall/-/run-waterfall-1.1.6.tgz", 153 | "integrity": "sha512-dApPbpIK0hbFi2zqfJxrsnfmJW2HCQHFrSsmqF3Fp9TKm5WVf++zE6BSw0hPcA7rPapO37h12Swk2E6Va3tF7Q==" 154 | }, 155 | "serialize-error": { 156 | "version": "2.1.0", 157 | "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz", 158 | "integrity": "sha1-ULZ51WNc34Rme9yOWa9OW4HV9go=" 159 | }, 160 | "supports-color": { 161 | "version": "5.5.0", 162 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 163 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 164 | "requires": { 165 | "has-flag": "^3.0.0" 166 | } 167 | }, 168 | "tsscmp": { 169 | "version": "1.0.5", 170 | "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", 171 | "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=" 172 | }, 173 | "uid-safe": { 174 | "version": "2.1.5", 175 | "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", 176 | "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", 177 | "requires": { 178 | "random-bytes": "~1.0.0" 179 | } 180 | } 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /src/html/get-index/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wtfjs-get-index", 3 | "dependencies": { 4 | "@architect/data": "^2.0.5", 5 | "@architect/functions": "^1.9.2" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/html/get-license/index.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | var path = require('path') 3 | var arc = require('@architect/functions') 4 | var layout = require('@architect/shared/layout') 5 | var index = fs.readFileSync(path.join(__dirname, 'license.html')).toString() 6 | let html = layout(index) 7 | 8 | function route(req, res) { 9 | res({html}) 10 | } 11 | 12 | exports.handler = arc.html.get(route) 13 | -------------------------------------------------------------------------------- /src/html/get-license/license.html: -------------------------------------------------------------------------------- 1 |
     2 | 
     3 |                DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
     4 |                        Version 2, December 2004
     5 | 
     6 |     Copyright (C) 2010 Brian LeRoux
     7 | 
     8 |     Everyone is permitted to copy and distribute verbatim or modified
     9 |     copies of this license document, and changing it is allowed as long
    10 |     as the name is changed.
    11 | 
    12 |                DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
    13 |       TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
    14 | 
    15 |      0. You just DO WHAT THE FUCK YOU WANT TO.
    16 | 
    17 | 
    18 | -------------------------------------------------------------------------------- /src/html/get-license/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wtfjs-get-license", 3 | "requires": true, 4 | "lockfileVersion": 1, 5 | "dependencies": { 6 | "@architect/data": { 7 | "version": "2.0.5", 8 | "resolved": "https://registry.npmjs.org/@architect/data/-/data-2.0.5.tgz", 9 | "integrity": "sha512-potdYRGmgpelOfGncPw6W2iCUyJ7S+N8hdFxM/Uc9Hh6V9cQIBQK9nuinogaNGkGTQTk7MiN86Szszynp1uWjw==", 10 | "requires": { 11 | "@architect/parser": "^1.0.6", 12 | "chalk": "^2.3.0" 13 | } 14 | }, 15 | "@architect/functions": { 16 | "version": "1.9.2", 17 | "resolved": "https://registry.npmjs.org/@architect/functions/-/functions-1.9.2.tgz", 18 | "integrity": "sha512-nQFEc2deBwKYTUR8Do6gwx2oIPyyviIoEeV6OQiE+WCcP+rLslkE0zArGiDUj11GgzCF6VWblto5vKTaM1spNQ==", 19 | "requires": { 20 | "@architect/parser": "^1.1.0", 21 | "@smallwins/err": "^1.0.0", 22 | "cookie": "^0.3.1", 23 | "cookie-signature": "^1.1.0", 24 | "csrf": "^3.0.6", 25 | "is-plain-object": "^2.0.4", 26 | "run-parallel": "^1.1.9", 27 | "run-waterfall": "^1.1.6", 28 | "serialize-error": "^2.1.0", 29 | "uid-safe": "^2.1.5" 30 | } 31 | }, 32 | "@architect/parser": { 33 | "version": "1.1.2", 34 | "resolved": "https://registry.npmjs.org/@architect/parser/-/parser-1.1.2.tgz", 35 | "integrity": "sha512-MrCoCcZnEhvLI+6BiOs45/qAWD/NnpBY/fLnX1MSxyzr9DR5cz8lat0Nip1E+a10h5BxLpMoFO/nXUWEfq3OQA==" 36 | }, 37 | "@smallwins/err": { 38 | "version": "1.0.0", 39 | "resolved": "https://registry.npmjs.org/@smallwins/err/-/err-1.0.0.tgz", 40 | "integrity": "sha1-tk2WSldWcGukV/Dhwtem7h2GZwA=", 41 | "requires": { 42 | "clean-stack": "^1.3.0", 43 | "serialize-error": "^2.1.0" 44 | } 45 | }, 46 | "ansi-styles": { 47 | "version": "3.2.1", 48 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 49 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 50 | "requires": { 51 | "color-convert": "^1.9.0" 52 | } 53 | }, 54 | "chalk": { 55 | "version": "2.4.1", 56 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", 57 | "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", 58 | "requires": { 59 | "ansi-styles": "^3.2.1", 60 | "escape-string-regexp": "^1.0.5", 61 | "supports-color": "^5.3.0" 62 | } 63 | }, 64 | "clean-stack": { 65 | "version": "1.3.0", 66 | "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-1.3.0.tgz", 67 | "integrity": "sha1-noIVAa6XmYbEax1m0tQy2y/UrjE=" 68 | }, 69 | "color-convert": { 70 | "version": "1.9.3", 71 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 72 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 73 | "requires": { 74 | "color-name": "1.1.3" 75 | } 76 | }, 77 | "color-name": { 78 | "version": "1.1.3", 79 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 80 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 81 | }, 82 | "cookie": { 83 | "version": "0.3.1", 84 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 85 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" 86 | }, 87 | "cookie-signature": { 88 | "version": "1.1.0", 89 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.1.0.tgz", 90 | "integrity": "sha512-Alvs19Vgq07eunykd3Xy2jF0/qSNv2u7KDbAek9H5liV1UMijbqFs5cycZvv5dVsvseT/U4H8/7/w8Koh35C4A==" 91 | }, 92 | "csrf": { 93 | "version": "3.0.6", 94 | "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.0.6.tgz", 95 | "integrity": "sha1-thEg3c7q/JHnbtUxO7XAsmZ7cQo=", 96 | "requires": { 97 | "rndm": "1.2.0", 98 | "tsscmp": "1.0.5", 99 | "uid-safe": "2.1.4" 100 | }, 101 | "dependencies": { 102 | "uid-safe": { 103 | "version": "2.1.4", 104 | "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz", 105 | "integrity": "sha1-Otbzg2jG1MjHXsF2I/t5qh0HHYE=", 106 | "requires": { 107 | "random-bytes": "~1.0.0" 108 | } 109 | } 110 | } 111 | }, 112 | "escape-string-regexp": { 113 | "version": "1.0.5", 114 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 115 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 116 | }, 117 | "has-flag": { 118 | "version": "3.0.0", 119 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 120 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" 121 | }, 122 | "is-plain-object": { 123 | "version": "2.0.4", 124 | "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", 125 | "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", 126 | "requires": { 127 | "isobject": "^3.0.1" 128 | } 129 | }, 130 | "isobject": { 131 | "version": "3.0.1", 132 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", 133 | "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" 134 | }, 135 | "random-bytes": { 136 | "version": "1.0.0", 137 | "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", 138 | "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" 139 | }, 140 | "rndm": { 141 | "version": "1.2.0", 142 | "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", 143 | "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=" 144 | }, 145 | "run-parallel": { 146 | "version": "1.1.9", 147 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", 148 | "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==" 149 | }, 150 | "run-waterfall": { 151 | "version": "1.1.6", 152 | "resolved": "https://registry.npmjs.org/run-waterfall/-/run-waterfall-1.1.6.tgz", 153 | "integrity": "sha512-dApPbpIK0hbFi2zqfJxrsnfmJW2HCQHFrSsmqF3Fp9TKm5WVf++zE6BSw0hPcA7rPapO37h12Swk2E6Va3tF7Q==" 154 | }, 155 | "serialize-error": { 156 | "version": "2.1.0", 157 | "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz", 158 | "integrity": "sha1-ULZ51WNc34Rme9yOWa9OW4HV9go=" 159 | }, 160 | "supports-color": { 161 | "version": "5.5.0", 162 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 163 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 164 | "requires": { 165 | "has-flag": "^3.0.0" 166 | } 167 | }, 168 | "tsscmp": { 169 | "version": "1.0.5", 170 | "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", 171 | "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=" 172 | }, 173 | "uid-safe": { 174 | "version": "2.1.5", 175 | "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", 176 | "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", 177 | "requires": { 178 | "random-bytes": "~1.0.0" 179 | } 180 | } 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /src/html/get-license/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wtfjs-get-license", 3 | "dependencies": { 4 | "@architect/data": "^2.0.5", 5 | "@architect/functions": "^1.9.2" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/html/get-wtfs-000wtfID/index.js: -------------------------------------------------------------------------------- 1 | var marked = require('marked') 2 | var fs = require('fs') 3 | var path = require('path') 4 | var exists = require('file-exists') 5 | var arc = require('@architect/functions') 6 | var layout = require('@architect/shared/layout') 7 | 8 | function route(req, res) { 9 | var filename = req.params.wtfID + '.md' 10 | var filepath = path.join(__dirname, 'node_modules', '@architect', 'shared', 'md', filename) 11 | exists(filepath, function _exists(err, yasqueen) { 12 | if (err) { 13 | res({ 14 | status: 500, 15 | html: 'internal serverless error' 16 | }) 17 | } 18 | else if (yasqueen === false) { 19 | res({ 20 | status: 404, 21 | html: layout('wtf! not found') 22 | }) 23 | } 24 | else { 25 | var title = req.params.wtfID.replace(/-/g, ' ') 26 | var body = marked(fs.readFileSync(filepath).toString()) 27 | var tmpl = `

    ${title}

    ${body}
    ` 28 | var html = layout(tmpl) 29 | res({ 30 | html 31 | }) 32 | } 33 | }) 34 | } 35 | 36 | exports.handler = arc.html.get(route) 37 | -------------------------------------------------------------------------------- /src/html/get-wtfs-000wtfID/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wtfjs-get-wtfs-000wtfID", 3 | "requires": true, 4 | "lockfileVersion": 1, 5 | "dependencies": { 6 | "@architect/data": { 7 | "version": "2.0.5", 8 | "resolved": "https://registry.npmjs.org/@architect/data/-/data-2.0.5.tgz", 9 | "integrity": "sha512-potdYRGmgpelOfGncPw6W2iCUyJ7S+N8hdFxM/Uc9Hh6V9cQIBQK9nuinogaNGkGTQTk7MiN86Szszynp1uWjw==", 10 | "requires": { 11 | "@architect/parser": "^1.0.6", 12 | "chalk": "^2.3.0" 13 | } 14 | }, 15 | "@architect/functions": { 16 | "version": "1.9.2", 17 | "resolved": "https://registry.npmjs.org/@architect/functions/-/functions-1.9.2.tgz", 18 | "integrity": "sha512-nQFEc2deBwKYTUR8Do6gwx2oIPyyviIoEeV6OQiE+WCcP+rLslkE0zArGiDUj11GgzCF6VWblto5vKTaM1spNQ==", 19 | "requires": { 20 | "@architect/parser": "^1.1.0", 21 | "@smallwins/err": "^1.0.0", 22 | "cookie": "^0.3.1", 23 | "cookie-signature": "^1.1.0", 24 | "csrf": "^3.0.6", 25 | "is-plain-object": "^2.0.4", 26 | "run-parallel": "^1.1.9", 27 | "run-waterfall": "^1.1.6", 28 | "serialize-error": "^2.1.0", 29 | "uid-safe": "^2.1.5" 30 | } 31 | }, 32 | "@architect/parser": { 33 | "version": "1.1.2", 34 | "resolved": "https://registry.npmjs.org/@architect/parser/-/parser-1.1.2.tgz", 35 | "integrity": "sha512-MrCoCcZnEhvLI+6BiOs45/qAWD/NnpBY/fLnX1MSxyzr9DR5cz8lat0Nip1E+a10h5BxLpMoFO/nXUWEfq3OQA==" 36 | }, 37 | "@smallwins/err": { 38 | "version": "1.0.0", 39 | "resolved": "https://registry.npmjs.org/@smallwins/err/-/err-1.0.0.tgz", 40 | "integrity": "sha1-tk2WSldWcGukV/Dhwtem7h2GZwA=", 41 | "requires": { 42 | "clean-stack": "^1.3.0", 43 | "serialize-error": "^2.1.0" 44 | } 45 | }, 46 | "ansi-styles": { 47 | "version": "3.2.1", 48 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 49 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 50 | "requires": { 51 | "color-convert": "^1.9.0" 52 | } 53 | }, 54 | "chalk": { 55 | "version": "2.4.1", 56 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", 57 | "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", 58 | "requires": { 59 | "ansi-styles": "^3.2.1", 60 | "escape-string-regexp": "^1.0.5", 61 | "supports-color": "^5.3.0" 62 | } 63 | }, 64 | "clean-stack": { 65 | "version": "1.3.0", 66 | "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-1.3.0.tgz", 67 | "integrity": "sha1-noIVAa6XmYbEax1m0tQy2y/UrjE=" 68 | }, 69 | "color-convert": { 70 | "version": "1.9.3", 71 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 72 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 73 | "requires": { 74 | "color-name": "1.1.3" 75 | } 76 | }, 77 | "color-name": { 78 | "version": "1.1.3", 79 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 80 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 81 | }, 82 | "cookie": { 83 | "version": "0.3.1", 84 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 85 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" 86 | }, 87 | "cookie-signature": { 88 | "version": "1.1.0", 89 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.1.0.tgz", 90 | "integrity": "sha512-Alvs19Vgq07eunykd3Xy2jF0/qSNv2u7KDbAek9H5liV1UMijbqFs5cycZvv5dVsvseT/U4H8/7/w8Koh35C4A==" 91 | }, 92 | "csrf": { 93 | "version": "3.0.6", 94 | "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.0.6.tgz", 95 | "integrity": "sha1-thEg3c7q/JHnbtUxO7XAsmZ7cQo=", 96 | "requires": { 97 | "rndm": "1.2.0", 98 | "tsscmp": "1.0.5", 99 | "uid-safe": "2.1.4" 100 | }, 101 | "dependencies": { 102 | "uid-safe": { 103 | "version": "2.1.4", 104 | "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz", 105 | "integrity": "sha1-Otbzg2jG1MjHXsF2I/t5qh0HHYE=", 106 | "requires": { 107 | "random-bytes": "~1.0.0" 108 | } 109 | } 110 | } 111 | }, 112 | "escape-string-regexp": { 113 | "version": "1.0.5", 114 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 115 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 116 | }, 117 | "file-exists": { 118 | "version": "4.0.0", 119 | "resolved": "https://registry.npmjs.org/file-exists/-/file-exists-4.0.0.tgz", 120 | "integrity": "sha1-EE6s8l0/1rPkYpUa6SNTMZX/tSs=" 121 | }, 122 | "has-flag": { 123 | "version": "3.0.0", 124 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 125 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" 126 | }, 127 | "is-plain-object": { 128 | "version": "2.0.4", 129 | "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", 130 | "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", 131 | "requires": { 132 | "isobject": "^3.0.1" 133 | } 134 | }, 135 | "isobject": { 136 | "version": "3.0.1", 137 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", 138 | "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" 139 | }, 140 | "marked": { 141 | "version": "0.3.19", 142 | "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.19.tgz", 143 | "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==" 144 | }, 145 | "random-bytes": { 146 | "version": "1.0.0", 147 | "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", 148 | "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" 149 | }, 150 | "rndm": { 151 | "version": "1.2.0", 152 | "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", 153 | "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=" 154 | }, 155 | "run-parallel": { 156 | "version": "1.1.9", 157 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", 158 | "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==" 159 | }, 160 | "run-waterfall": { 161 | "version": "1.1.6", 162 | "resolved": "https://registry.npmjs.org/run-waterfall/-/run-waterfall-1.1.6.tgz", 163 | "integrity": "sha512-dApPbpIK0hbFi2zqfJxrsnfmJW2HCQHFrSsmqF3Fp9TKm5WVf++zE6BSw0hPcA7rPapO37h12Swk2E6Va3tF7Q==" 164 | }, 165 | "serialize-error": { 166 | "version": "2.1.0", 167 | "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz", 168 | "integrity": "sha1-ULZ51WNc34Rme9yOWa9OW4HV9go=" 169 | }, 170 | "supports-color": { 171 | "version": "5.5.0", 172 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 173 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 174 | "requires": { 175 | "has-flag": "^3.0.0" 176 | } 177 | }, 178 | "tsscmp": { 179 | "version": "1.0.5", 180 | "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", 181 | "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=" 182 | }, 183 | "uid-safe": { 184 | "version": "2.1.5", 185 | "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", 186 | "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", 187 | "requires": { 188 | "random-bytes": "~1.0.0" 189 | } 190 | } 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /src/html/get-wtfs-000wtfID/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wtfjs-get-wtfs-000wtfID", 3 | "dependencies": { 4 | "@architect/data": "^2.0.5", 5 | "@architect/functions": "^1.9.2", 6 | "file-exists": "^4.0.0", 7 | "marked": "^0.3.19" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/html/get-wtfs/index.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | var path = require('path') 3 | var arc = require('@architect/functions') 4 | var layout = require('@architect/shared/layout') 5 | var filter = f=> f.includes('.md') 6 | var files = fs.readdirSync(__dirname + '/node_modules/@architect/shared/md').filter(filter).reverse() 7 | 8 | function link(file) { 9 | var val = file.replace('.md', '') 10 | var name = val.replace(/-/g, ' ') 11 | return `
  • ${name}
  • ` 12 | } 13 | 14 | function route(req, res) { 15 | var index = files.map(link).join('') 16 | var html = layout(index) 17 | res({html}) 18 | } 19 | 20 | exports.handler = arc.html.get(route) 21 | -------------------------------------------------------------------------------- /src/html/get-wtfs/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wtfjs-get-wtfs", 3 | "requires": true, 4 | "lockfileVersion": 1, 5 | "dependencies": { 6 | "@architect/data": { 7 | "version": "2.0.5", 8 | "resolved": "https://registry.npmjs.org/@architect/data/-/data-2.0.5.tgz", 9 | "integrity": "sha512-potdYRGmgpelOfGncPw6W2iCUyJ7S+N8hdFxM/Uc9Hh6V9cQIBQK9nuinogaNGkGTQTk7MiN86Szszynp1uWjw==", 10 | "requires": { 11 | "@architect/parser": "^1.0.6", 12 | "chalk": "^2.3.0" 13 | } 14 | }, 15 | "@architect/functions": { 16 | "version": "1.9.2", 17 | "resolved": "https://registry.npmjs.org/@architect/functions/-/functions-1.9.2.tgz", 18 | "integrity": "sha512-nQFEc2deBwKYTUR8Do6gwx2oIPyyviIoEeV6OQiE+WCcP+rLslkE0zArGiDUj11GgzCF6VWblto5vKTaM1spNQ==", 19 | "requires": { 20 | "@architect/parser": "^1.1.0", 21 | "@smallwins/err": "^1.0.0", 22 | "cookie": "^0.3.1", 23 | "cookie-signature": "^1.1.0", 24 | "csrf": "^3.0.6", 25 | "is-plain-object": "^2.0.4", 26 | "run-parallel": "^1.1.9", 27 | "run-waterfall": "^1.1.6", 28 | "serialize-error": "^2.1.0", 29 | "uid-safe": "^2.1.5" 30 | } 31 | }, 32 | "@architect/parser": { 33 | "version": "1.1.2", 34 | "resolved": "https://registry.npmjs.org/@architect/parser/-/parser-1.1.2.tgz", 35 | "integrity": "sha512-MrCoCcZnEhvLI+6BiOs45/qAWD/NnpBY/fLnX1MSxyzr9DR5cz8lat0Nip1E+a10h5BxLpMoFO/nXUWEfq3OQA==" 36 | }, 37 | "@smallwins/err": { 38 | "version": "1.0.0", 39 | "resolved": "https://registry.npmjs.org/@smallwins/err/-/err-1.0.0.tgz", 40 | "integrity": "sha1-tk2WSldWcGukV/Dhwtem7h2GZwA=", 41 | "requires": { 42 | "clean-stack": "^1.3.0", 43 | "serialize-error": "^2.1.0" 44 | } 45 | }, 46 | "ansi-styles": { 47 | "version": "3.2.1", 48 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 49 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 50 | "requires": { 51 | "color-convert": "^1.9.0" 52 | } 53 | }, 54 | "chalk": { 55 | "version": "2.4.1", 56 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", 57 | "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", 58 | "requires": { 59 | "ansi-styles": "^3.2.1", 60 | "escape-string-regexp": "^1.0.5", 61 | "supports-color": "^5.3.0" 62 | } 63 | }, 64 | "clean-stack": { 65 | "version": "1.3.0", 66 | "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-1.3.0.tgz", 67 | "integrity": "sha1-noIVAa6XmYbEax1m0tQy2y/UrjE=" 68 | }, 69 | "color-convert": { 70 | "version": "1.9.3", 71 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 72 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 73 | "requires": { 74 | "color-name": "1.1.3" 75 | } 76 | }, 77 | "color-name": { 78 | "version": "1.1.3", 79 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 80 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 81 | }, 82 | "cookie": { 83 | "version": "0.3.1", 84 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 85 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" 86 | }, 87 | "cookie-signature": { 88 | "version": "1.1.0", 89 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.1.0.tgz", 90 | "integrity": "sha512-Alvs19Vgq07eunykd3Xy2jF0/qSNv2u7KDbAek9H5liV1UMijbqFs5cycZvv5dVsvseT/U4H8/7/w8Koh35C4A==" 91 | }, 92 | "csrf": { 93 | "version": "3.0.6", 94 | "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.0.6.tgz", 95 | "integrity": "sha1-thEg3c7q/JHnbtUxO7XAsmZ7cQo=", 96 | "requires": { 97 | "rndm": "1.2.0", 98 | "tsscmp": "1.0.5", 99 | "uid-safe": "2.1.4" 100 | }, 101 | "dependencies": { 102 | "uid-safe": { 103 | "version": "2.1.4", 104 | "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz", 105 | "integrity": "sha1-Otbzg2jG1MjHXsF2I/t5qh0HHYE=", 106 | "requires": { 107 | "random-bytes": "~1.0.0" 108 | } 109 | } 110 | } 111 | }, 112 | "escape-string-regexp": { 113 | "version": "1.0.5", 114 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 115 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 116 | }, 117 | "has-flag": { 118 | "version": "3.0.0", 119 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 120 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" 121 | }, 122 | "is-plain-object": { 123 | "version": "2.0.4", 124 | "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", 125 | "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", 126 | "requires": { 127 | "isobject": "^3.0.1" 128 | } 129 | }, 130 | "isobject": { 131 | "version": "3.0.1", 132 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", 133 | "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" 134 | }, 135 | "random-bytes": { 136 | "version": "1.0.0", 137 | "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", 138 | "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" 139 | }, 140 | "rndm": { 141 | "version": "1.2.0", 142 | "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", 143 | "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=" 144 | }, 145 | "run-parallel": { 146 | "version": "1.1.9", 147 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", 148 | "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==" 149 | }, 150 | "run-waterfall": { 151 | "version": "1.1.6", 152 | "resolved": "https://registry.npmjs.org/run-waterfall/-/run-waterfall-1.1.6.tgz", 153 | "integrity": "sha512-dApPbpIK0hbFi2zqfJxrsnfmJW2HCQHFrSsmqF3Fp9TKm5WVf++zE6BSw0hPcA7rPapO37h12Swk2E6Va3tF7Q==" 154 | }, 155 | "serialize-error": { 156 | "version": "2.1.0", 157 | "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz", 158 | "integrity": "sha1-ULZ51WNc34Rme9yOWa9OW4HV9go=" 159 | }, 160 | "supports-color": { 161 | "version": "5.5.0", 162 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 163 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 164 | "requires": { 165 | "has-flag": "^3.0.0" 166 | } 167 | }, 168 | "tsscmp": { 169 | "version": "1.0.5", 170 | "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", 171 | "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=" 172 | }, 173 | "uid-safe": { 174 | "version": "2.1.5", 175 | "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", 176 | "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", 177 | "requires": { 178 | "random-bytes": "~1.0.0" 179 | } 180 | } 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /src/html/get-wtfs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wtfjs-get-wtfs", 3 | "dependencies": { 4 | "@architect/data": "^2.0.5", 5 | "@architect/functions": "^1.9.2" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/shared/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Georgia, Palatino, 'Palatino Linotype', Times, 'Times New Roman', serif; 3 | padding:20px; 4 | margin:0; 5 | } 6 | 7 | h1 { 8 | font-size:19pt; 9 | font-family: Georgia, Palatino, 'Palatino Linotype', Times, 'Times New Roman', serif; 10 | letter-spacing: -1px; 11 | } 12 | 13 | h1 a { 14 | text-decoration:none; 15 | color:#333; 16 | } 17 | 18 | pre, code { 19 | font-family: monaco, monospace; 20 | overflow-x: auto; 21 | width: 100%; 22 | } 23 | 24 | pre { 25 | border:1px solid #5d6778; 26 | border-radius:5px; 27 | -moz-border-radius: 5px; 28 | padding:10px 10px 20px 0; 29 | background:-webkit-gradient(linear, 0% 0%, 0% 100%, from(#000), to(#0F2925)); 30 | background:-moz-linear-gradient(top, #000, #0F2925); 31 | } 32 | 33 | hr { 34 | border:none; 35 | background-color: #eaeaea; 36 | height: 10px; 37 | border-radius:5px; 38 | -moz-border-radius: 5px; 39 | } 40 | 41 | #wrap { 42 | width:800px; 43 | margin:0 auto 0 auto; 44 | } 45 | 46 | #nav { 47 | border:1px solid #000; 48 | border-radius:5px; 49 | -moz-border-radius: 5px; 50 | height:50px; 51 | } 52 | 53 | #nav ul { 54 | list-style:none; 55 | margin:0; 56 | padding:0; 57 | background:-webkit-gradient(linear, 0% 0%, 0% 100%, from(#666666), to(#010F01)); 58 | background:-moz-linear-gradient(top, #666666, #010F01); 59 | border:1px solid #5d6778; 60 | border-radius:5px; 61 | -moz-border-radius: 5px; 62 | height:48px; 63 | } 64 | 65 | #nav ul li { 66 | display:inline; 67 | margin:0; 68 | padding:0; 69 | } 70 | 71 | #nav li a { 72 | font-family:Helvetica, Verdana, Sans-Serif; 73 | color:#fff; 74 | text-decoration:none; 75 | font-size:11pt; 76 | display:block; 77 | float:left; 78 | padding:0 20px 0 20px; 79 | line-height:46px; 80 | text-shadow: 0px -1px 0px #000; 81 | 82 | } 83 | 84 | #nav ul li a:hover { 85 | background:-webkit-gradient(linear, 0% 0%, 0% 100%, from(#000), to(#010F01)); 86 | background:-moz-linear-gradient(top, #000, #010F01); 87 | } 88 | 89 | #nav ul li:first-child a { 90 | color:#FF0000; 91 | font-family: Georgia, Palatino, 'Palatino Linotype', Times, 'Times New Roman', serif; 92 | letter-spacing: -1px; 93 | font-size:19pt; 94 | } 95 | 96 | #content { 97 | 98 | } 99 | 100 | #pager { 101 | height:48px; 102 | background:#eaeaea; 103 | border:1px solid #eaeaea; 104 | border-radius:5px; 105 | -moz-border-radius: 5px; 106 | } 107 | 108 | #prev { 109 | float:left; 110 | margin:0 0 0 20px; 111 | } 112 | 113 | #next { 114 | float:right; 115 | margin:0 20px 0; 116 | } 117 | 118 | #prev, 119 | #next { 120 | text-decoration:none; 121 | display:block; 122 | font-size:30pt; 123 | color:#333; 124 | text-shadow: 0px 3px 0px #fff; 125 | } 126 | 127 | #foot { 128 | clear:both; 129 | margin:0; 130 | padding:0; 131 | background:-webkit-gradient(linear, 0% 0%, 0% 100%, from(#666666), to(#010F01)); 132 | background:-moz-linear-gradient(top, #666666, #010F01); 133 | border:1px solid #5d6778; 134 | border-radius:5px; 135 | -moz-border-radius: 5px; 136 | height:48px; 137 | width:800px; 138 | text-align:center; 139 | } 140 | #foot, 141 | #foot a { 142 | color:#eaeaea; 143 | font-size:12pt; 144 | text-shadow: 0px -1px 0px #000; 145 | line-height:48px; 146 | } 147 | 148 | .clear { 149 | clear:both; 150 | } 151 | 152 | .date { 153 | color: #666666; 154 | } 155 | /* 156 | IR_Black style (c) Vasily Mikhailitchenko 157 | */ 158 | 159 | pre code { 160 | color: #f8f8f8; 161 | } 162 | 163 | pre { 164 | background: #000; 165 | } 166 | 167 | pre .shebang, 168 | pre .comment, 169 | pre .template_comment, 170 | pre .javadoc { 171 | color: #7c7c7c; 172 | } 173 | 174 | pre .keyword, 175 | pre .tag, 176 | pre .ruby .function .keyword, 177 | pre .tex .command { 178 | color: #96CBFE; 179 | } 180 | 181 | pre .function .keyword, 182 | pre .sub .keyword, 183 | pre .method, 184 | pre .list .title { 185 | color: #FFFFB6; 186 | } 187 | 188 | pre .string, 189 | pre .attribute .value, 190 | pre .cdata, 191 | pre .filter .argument, 192 | pre .attr_selector, 193 | pre .apache .cbracket, 194 | pre .date { 195 | color: #A8FF60; 196 | } 197 | 198 | pre .subst { 199 | color: #DAEFA3; 200 | } 201 | 202 | pre .regexp { 203 | color: #E9C062; 204 | } 205 | 206 | pre .function .title, 207 | pre .sub .identifier, 208 | pre .pi, 209 | pre .decorator, 210 | pre .ini .title, 211 | pre .tex .special { 212 | color: #FFFFB6; 213 | } 214 | 215 | pre .class .title, 216 | pre .constant, 217 | pre .smalltalk .class, 218 | pre .javadoctag, 219 | pre .yardoctag, 220 | pre .phpdoc, 221 | pre .nginx .built_in { 222 | color: #FFFFB6; 223 | } 224 | 225 | pre .symbol, 226 | pre .ruby .symbol .string, 227 | pre .ruby .symbol .keyword, 228 | pre .ruby .symbol .keymethods, 229 | pre .number, 230 | pre .variable, 231 | pre .vbscript, 232 | pre .literal { 233 | color: #C6C5FE; 234 | } 235 | 236 | pre .css .keyword { 237 | color: #96CBFE; 238 | } 239 | 240 | pre .css .rule .keyword, 241 | pre .css .id { 242 | color: #FFFFB6; 243 | } 244 | 245 | pre .css .class { 246 | color: #FFF; 247 | } 248 | 249 | pre .hexcolor { 250 | color: #C6C5FE; 251 | } 252 | 253 | pre .number { 254 | color:#FF73FD; 255 | } 256 | 257 | pre .tex .formula { 258 | opacity: 0.7; 259 | } 260 | 261 | 262 | h2.about { 263 | font-weight: 200; 264 | font-size: 1rem; 265 | color: #ccc; 266 | text-align: right; 267 | font-style: italic; 268 | } 269 | 270 | h2.about a { 271 | color: #bbb; 272 | } 273 | -------------------------------------------------------------------------------- /src/shared/layout.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | var path = require('path') 3 | var css = fs.readFileSync(path.join(__dirname, 'index.css')).toString() 4 | 5 | module.exports = function layout(body) { 6 | return ` 7 | 8 | 9 | 10 | wtfjs - a little code blog about that language we love despite giving us so much to hate 11 | 12 | 13 | 14 | 19 | 20 | 21 |
    22 | 28 | 29 |

    30 | created by 31 | Brian LeRoux & 32 | Andrew Lunny. 33 | sparodically uncurated by 34 | David Trejo. 35 |

    36 | 37 |
    ${body}
    38 | 39 |
    40 | Fork me on GitHub 41 | 42 | 43 | 54 | 55 | 56 | 57 | ` 58 | } 59 | -------------------------------------------------------------------------------- /src/shared/md/2010-02-12-almost-but-not-quite.md: -------------------------------------------------------------------------------- 1 | 2 | alert(111111111111111111111); // alerts 111111111111111110000 3 | -------------------------------------------------------------------------------- /src/shared/md/2010-02-12-foonanny.md: -------------------------------------------------------------------------------- 1 | Evaluted as `"foo" + (+ "bar")`, which converts “bar” to not a number. 2 | 3 | Proposal to rename this site: NaNwtf 4 | 5 | 6 | ("foo" + + "bar") === "fooNaN" // true 7 | 8 | 9 | **Explanation** 10 | 1. `+"bar"` calls `"bar".valueOf()` which tries to return a number 11 | 2. Because "bar" is a string, it returns `NaN` instead 12 | 3. `"foo"` is concatenated with `NaN` 13 | 4. Because of the concatenation `NaN.toString()` is called which results in `"foo" + "NaN"` 14 | -------------------------------------------------------------------------------- /src/shared/md/2010-02-12-function-context-fun.md: -------------------------------------------------------------------------------- 1 | 2 | (x=[].reverse)() === window // true 3 | 4 | 5 | - Thanks to [@tobeytailor](http://twitter.com/tobeytailor) for pointing out this beauty. 6 | - Updated: an error is thrown when the code is executed in Chrome 49 7 | -------------------------------------------------------------------------------- /src/shared/md/2010-02-12-maths-fun.md: -------------------------------------------------------------------------------- 1 | Clearly JavaScript is not the most beautiful, or intuitive, language for maths. 2 | 3 | ``` 4 | typeof NaN === 'number' // true 5 | Infinity === 1/0 // true 6 | 0.1 + 0.2 === 0.3 // false 7 | ``` -------------------------------------------------------------------------------- /src/shared/md/2010-02-12-min-number-treachery.md: -------------------------------------------------------------------------------- 1 | 2 | Number.MIN_VALUE > 0; 3 | // true? really? wtf. 4 | 5 | 6 | It turns out that MIN_VALUE is the smallest number GREATER THAN ZERO, which of course totally makes sense. -------------------------------------------------------------------------------- /src/shared/md/2010-02-12-not-a-number-is-a-number.md: -------------------------------------------------------------------------------- 1 | 2 | typeof NaN // number, of course. 3 | 4 | 5 | Now that makes sense. -------------------------------------------------------------------------------- /src/shared/md/2010-02-12-not-a-number-is-not-a-not-a-number.md: -------------------------------------------------------------------------------- 1 | Some argue this makes sense. Some ppl also like to sniff glue. 2 | 3 | 4 | NaN === NaN // false 5 | -------------------------------------------------------------------------------- /src/shared/md/2010-02-12-null-is-not-an-object.md: -------------------------------------------------------------------------------- 1 | ``` 2 | typeof null // object 3 | null instanceof Object // false 4 | ``` 5 | 6 | Classic null is not an Object. -------------------------------------------------------------------------------- /src/shared/md/2010-02-12-parseint-treachery.md: -------------------------------------------------------------------------------- 1 | ``` 2 | parseInt('06'); // 6 3 | parseInt('08'); // 0 4 | ``` 5 | 6 | This is because parseInt accepts a second argument for radix. If it is not supplied and the string starts with a 0 it will be parsed as an octal number. Riiiiiiight, of COURSE. -------------------------------------------------------------------------------- /src/shared/md/2010-02-13-null-is-not-falsy.md: -------------------------------------------------------------------------------- 1 | ``` 2 | [] == false; // true 3 | "" == false; // true 4 | null == false; // false, that's more like it 5 | ``` -------------------------------------------------------------------------------- /src/shared/md/2010-02-13-string-is-not-string.md: -------------------------------------------------------------------------------- 1 | ``` 2 | "string" instanceof String; // false. 3 | // 'course it isn't not a string, it may look like a string 4 | // but actually it's masquerading as a banana. 5 | ``` 6 | 7 | When is a string, not a string? When it’s a duck - [@rem](http://twitter.com/rem) -------------------------------------------------------------------------------- /src/shared/md/2010-02-15-accidental-global.md: -------------------------------------------------------------------------------- 1 | This one is fun and sneaky. 2 | 3 | ``` 4 | (function(){ 5 | var x = y = 1; 6 | })(); 7 | alert(x); // undefined 8 | alert(y); // 1 -- oops, auto-global! 9 | ``` 10 | 11 | It’s treated like: var x = (y = 1); thus, “y=1” creates an auto-global since there’s no binding “var” statement for it. Afterwards, that value gets copied into the properly defined local var “x”. -------------------------------------------------------------------------------- /src/shared/md/2010-02-15-careful.md: -------------------------------------------------------------------------------- 1 | 2 | [] == ![] // true 3 | 4 | 5 | Arrays evaluate as true in a boolean condition so this does make some sense even if it doesn’t read very well! Thanks to [@collintmiller](http://twitter.com/collintmiller)! -------------------------------------------------------------------------------- /src/shared/md/2010-02-15-coerce-equality.md: -------------------------------------------------------------------------------- 1 | 2 | 3 == "3" // true 3 | 4 | 5 | [@robertnyman](http://twitter.com/robertnyman) reminding us why === is a best practice. -------------------------------------------------------------------------------- /src/shared/md/2010-02-15-firebug-reserved.md: -------------------------------------------------------------------------------- 1 | ``` 2 | // whilst in firebug, try: 3 | var console = {}; // or, well - anything actually... 4 | ``` 5 | 6 | Firebug absolutely won’t let you create a variable called console, try and it’ll kick you in the happy sack - [@rem](http://twitter.com/rem) -------------------------------------------------------------------------------- /src/shared/md/2010-02-15-hoisting.md: -------------------------------------------------------------------------------- 1 | ``` 2 | (function(){ 3 | alert(window); // "undefined" 4 | var window = window; 5 | })(); 6 | ``` 7 | 8 | Because of “hoisting”, all variable *declarations* will be executed immediately at the top of a function scope. However, the variable *initializations* are not hoisted. So, local variable “window” is declared but uninitialized/”undefined”. wt-fun! -------------------------------------------------------------------------------- /src/shared/md/2010-02-15-more-coerce-fun.md: -------------------------------------------------------------------------------- 1 | 2 | 3 == "03" // true! 3 | 4 | 5 | [@dandean](http://twitter.com/dandean) tweets, Don’t mind that zero there. I’m _sure_ it’s not important. 6 | 7 | Bwahahaha! -------------------------------------------------------------------------------- /src/shared/md/2010-02-15-scope-fun.md: -------------------------------------------------------------------------------- 1 | [@kriskowal](http://twitter.com/kriskowal), of [CommonJS](http://commonjs.org) fame, points out lexical scoping could solve this issue. Ah, JavaScript you are a dirty little language. Dirty dirty…slut! Ya you like those global variables… aaaaaw yah… 2 | 3 | ``` 4 | Object.prototype.foo = 10; 5 | console.log(foo); // 10 6 | ``` -------------------------------------------------------------------------------- /src/shared/md/2010-02-15-thc-timetravel.md: -------------------------------------------------------------------------------- 1 | [@sh1mmer](http://twitter.com/sh1mmer) reminds us that we all want to understand Infinity. And you can’t take anything away from Infinity, man. 2 | 3 | Woah! 4 | 5 | ``` 6 | var bignum = 1e300; 7 | var ∞ = 1e400; //Infinity 8 | alert(∞ - bignum); //Infinity 9 | ``` 10 | 11 | Also note: [@sh1mmer](http://twitter.com/sh1mmer) is from the future wherein Unicode entities are valid for variable identifiers. Rename above to something sane in our old school present day interpreters. -------------------------------------------------------------------------------- /src/shared/md/2010-02-15-timeout-delay.md: -------------------------------------------------------------------------------- 1 | For Firefox only, any function executed by a setTimeout or setInterval invocation will get passed to it (whether you want it to or not) a mysterious “lateness” variable, which represents the number of milliseconds late the function is in executing. Sucks because it can clobber an intentionally unpassed “default” variable to your function. Sucks even more if this variable is intended to be boolean, because you end up with ”random” true/false’y values. 2 | 3 | ``` 4 | // for FF only 5 | setTimeout(function(rand){ alert(rand); },10); // FF passes a "magic" param we call "rand" 6 | for (var i=0; i<100000; i++) { i; } // take some time 7 | ``` -------------------------------------------------------------------------------- /src/shared/md/2010-02-15-true-has-a-value.md: -------------------------------------------------------------------------------- 1 | [@AtomFusion](http://twitter.com/AtomFusion) shows us that true sometimes has a value. 2 | 3 | ``` 4 | (true + 1) === 2;​ ​// true 5 | (true + true) === 2; // true 6 | true === 2; // false 7 | true === 1; // false 8 | ``` 9 | 10 | Wow wtf. -------------------------------------------------------------------------------- /src/shared/md/2010-02-15-undefined-is-mutable.md: -------------------------------------------------------------------------------- 1 | In JavaScript, undefined is nothing but a global variable name without a default value. Therefore, its primitive value is undefined. You can change the value of undefined: 2 | 3 | ``` 4 | var a = {}; 5 | a.b === undefined; // true because property b is not set 6 | undefined = 42; 7 | a.b === undefined; // false 8 | ``` 9 | 10 | Due to the mutability of undefined, it is generally a better idea to check for undefined-ness through typeof: 11 | 12 | ``` 13 | var a = {}; 14 | typeof a.b == 'undefined'; // always true 15 | ``` 16 | 17 | – [@mathias](http://mathiasbynens.be/) -------------------------------------------------------------------------------- /src/shared/md/2010-02-16-automagic-semicolons.md: -------------------------------------------------------------------------------- 1 | I’m certain that this will end all debate about where curly braces belong… right? 2 | 3 | ``` 4 | function laugh() 5 | { 6 | return 7 | { 8 | haha: "ha!" 9 | }; 10 | } 11 | laugh(); 12 | // returns undefined 13 | ``` 14 | 15 | See also: [Automatic semicolon insertion](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Automatic_semicolon_insertion) 16 | -------------------------------------------------------------------------------- /src/shared/md/2010-02-16-more-floating-point-rounding.md: -------------------------------------------------------------------------------- 1 | In my quest to find whether Infinity was a finite number, I found this. Two numbers that are different are the exact same. - [@rem](http://twitter.com/rem) 2 | 3 | ``` 4 | // note the number to the left of the 'e', 7 and 8 respectively 5 | alert( 1.7976931348623157e+308 === 1.7976931348623158e+308 ); // true! 6 | ``` -------------------------------------------------------------------------------- /src/shared/md/2010-02-16-reserved-for-future-use-maybe.md: -------------------------------------------------------------------------------- 1 | JavaScript has a [ludicrous list of reserved words](https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Reserved_Words); most of them aren’t even used as keywords in the language. Modern browsers allow using most of these words as identifiers, despite what the spec says. But Safari doesn’t like enum for some reason. 2 | 3 | ``` 4 | // In Safari, try... 5 | var enum; 6 | //-> SyntaxError: Parse error 7 | ``` -------------------------------------------------------------------------------- /src/shared/md/2010-02-19-concat-coerce.md: -------------------------------------------------------------------------------- 1 | More concat “fun”. 2 | 3 | ``` 4 | "3" + 1 // '31' 5 | "3" - 1 // 2 6 | "222" - -"111" // 333 (⊙﹏⊙) 7 | ``` -------------------------------------------------------------------------------- /src/shared/md/2010-02-23-arguing-with-arguments.md: -------------------------------------------------------------------------------- 1 | Nice arguments hackery going on here. 2 | 3 | ``` 4 | (function(a,b,c) { 5 | print(a,b,c); // one two three 6 | print(arguments[0], arguments[1], arguments[2]); // one two three 7 | arguments[0] = "uno"; 8 | print(a,b,c); // uno two three 9 | print(arguments[0], arguments[1], arguments[2]); // uno two three 10 | // a is magically married to arguments[0], b to arguments[1] etc 11 | // so one could change locally scoped variables from another scope like so: 12 | changeArguments(arguments); 13 | print(a,b,c); // I messed up your dataz 14 | })("one", "two", "three"); 15 | // not cool. 16 | function changeArguments(args){ 17 | args[0] = "I messed" 18 | args[1] = "up your"; 19 | args[2] = "dataz"; 20 | } 21 | ``` 22 | 23 | ``` 24 | // A more real world example: 25 | (function(arg1, arg2) { 26 | print(arg1, arg2); 27 | //-> uno dos 28 | Array.prototype.shift.apply(arguments); 29 | print(arg1, arg2); 30 | //-> dose undefined 31 | })('uno', 'dos'); 32 | ``` 33 | 34 | Thanks to [@deadlyicon](http://twitter.com/deadlyicon)! -------------------------------------------------------------------------------- /src/shared/md/2010-02-23-boolean-paradox.md: -------------------------------------------------------------------------------- 1 | Boolean logic paradox via [@amattie](amattie)! 2 | 3 | ``` 4 | "0" && {} // true 5 | 0 && {} // false, ok...fair enough 6 | 0 == "0" // true, wtf! 7 | ``` -------------------------------------------------------------------------------- /src/shared/md/2010-02-23-coerced.md: -------------------------------------------------------------------------------- 1 | Careful w/ number type coercion! Thanks [@kelemen_viktor](http://twitter.com/kelemen_viktor)! 2 | 3 | 4 | a = 012 // 10 5 | 6 | 7 | That's why JavaScript assumes (for whatever reason) that the number is octal (e. g. `parseInt('012', 8)`). 8 | -------------------------------------------------------------------------------- /src/shared/md/2010-02-23-declaration-vs-initialization.md: -------------------------------------------------------------------------------- 1 | ``` 2 | var a = 8; 3 | var someFunc = function(){ 4 | document.write(a); 5 | var a = 8; 6 | }; 7 | someFunc(); // writes undefined 8 | ``` 9 | 10 | Of course, the variable is undefined because its being declared but not initialized until after the document.write in the function context which itself runs before the first declaration of a. Yowza. Cheers to [Boaz, Al & Rick](http://weblog.bocoup.com/weird-var-behavior-in-javascript) for this one! -------------------------------------------------------------------------------- /src/shared/md/2010-02-23-makes-perfect-sense.md: -------------------------------------------------------------------------------- 1 | Ha! This one is great. 2 | 3 | 4 | 3 > 2 > 1 // false 5 | 6 | 7 | Remember how [true sometimes has a value](https://wtfjs.com/wtfs/2010-02-15-true-has-a-value) so in the above 3 > 2 evaluates to true making the second part of the expression evaluate true > 1 which is false. Of course! Thanks to [void_0](http://twitter.com/void_0) for this one! -------------------------------------------------------------------------------- /src/shared/md/2010-02-24-messing-with-number-prototype.md: -------------------------------------------------------------------------------- 1 | [@rcanine](http://twitter.com/rcanine) shows us this interesting this coerce behaviour within the prototype of Number. Fun! 2 | 3 | ``` 4 | (1) === 1; // true 5 | 6 | Number.prototype.isOne = function () { return this === 1; } 7 | 8 | (1).isOne(); // false! 9 | 10 | Number.prototype.reallyIsOne = function () { return this - 1 === 0; } 11 | 12 | (1).reallyIsOne(); // true 13 | ``` -------------------------------------------------------------------------------- /src/shared/md/2010-02-25-ie-and-webkit-agree.md: -------------------------------------------------------------------------------- 1 | Interesting how IE and WebKit treat this differently than Firefox and Opera. Some sort of pre-compilation going on? Who knows. Thanks [@jeronevw](http://twitter.com/jeronevw)! 2 | 3 | ``` 4 | (function(){return 2*3;}).toString() === (function(){return 6;}).toString(); // true in FF & Opera, false in IE & WebKit 5 | ``` -------------------------------------------------------------------------------- /src/shared/md/2010-02-25-ie-scope.md: -------------------------------------------------------------------------------- 1 | [@jaffathecake](http://twitter.com/jaffathecake) has some more fun with IE. As we do. 2 | 3 | ``` 4 | window.window == window // true 5 | window.window === window // false 6 | window == document // true. wtf! 7 | ``` 8 | 9 | [@filmaj](http://twitter.com/filmaj) says, “I think it’s because object equality implicitly calls toString(), and in IE most native DOM objects return just ‘[object]’ in toString(), whereas standard browser return something like ‘[object ClassName]’, which is probably why WebKit doesn’t do the same thing.” 10 | 11 | Fuckin IE, eh. 12 | -------------------------------------------------------------------------------- /src/shared/md/2010-02-25-jsftw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brianleroux/wtfjs/01cd583e474f9b64fdcd65fece03848397e3dd46/src/shared/md/2010-02-25-jsftw -------------------------------------------------------------------------------- /src/shared/md/2010-02-25-jsftw:-google-closure-compiler.md: -------------------------------------------------------------------------------- 1 | 2 | // Google closure compiler 1000 to 1E3 - love it! 3 | 1000 === 1E3; // true 4 | 5 | 6 | When going through the result of Google’s closure compiler, I found that it had compressed 1000 to 1E3 - brilliant! - [@rem](http://twitter.com/rem) -------------------------------------------------------------------------------- /src/shared/md/2010-02-26-array-crazy.md: -------------------------------------------------------------------------------- 1 | Plausible code: 2 | 3 | ``` 4 | [] == 0 // true 5 | +[] === 0 // true, wait whu? 6 | ++[] === 1 // sorta, though this is invalid js syntax, so... 7 | ``` 8 | 9 | Somewhat unlikely and, lets be honest, regrettable code: 10 | 11 | ``` 12 | [[]][0] === [] 13 | ++[[]][0] === 1 14 | ++[[]][+[]] === 1 // yay! wtf! 15 | ``` 16 | 17 | [John Resig explains here.](http://news.ycombinator.com/item?id=1154338) 18 | -------------------------------------------------------------------------------- /src/shared/md/2010-02-26-implicit-tostring-fun.md: -------------------------------------------------------------------------------- 1 | Be careful with those implicit .toString() calls in == comparisons. 2 | 3 | ``` 4 | typeof "abc" == "string" // true 5 | typeof String("abc") == "string" // true 6 | String("abc") == "abc" // true -- same types get casted to equal each other 7 | ``` 8 | 9 | Also, instantiation via the _new_ operator can yield interesting results! 10 | 11 | ``` 12 | String("abc") instanceof String // false -- hmmm... 13 | (new String("abc")) instanceof String // true 14 | String("abc") == (new String("abc")) // true -- wait, wtf? 15 | ``` 16 | 17 | As always, we are reminded to test with the strict equality operator: _===_. -------------------------------------------------------------------------------- /src/shared/md/2010-03-02-ie-cursed-recursion.md: -------------------------------------------------------------------------------- 1 | ``` 2 | window.recurse = function(times) { 3 | if (times !== 0) 4 | recurse(times - 1); 5 | }; 6 | recurse(13); // stack overflow at: 0 7 | ``` 8 | 9 | [@tlrobinson](http://twitter.com/tlrobinson) of [280 North](http://280north.com/), [Cappuccino](http://cappuccino.org/), [Narwhal](http://narwhaljs.org/) and [CommonJS](http://commonjs.org/) points out some lovely IE behavior in [this great blog post](http://cappuccino.org/discuss/2010/03/01/internet-explorer-global-variables-and-stack-overflows/). 10 | 11 | WTFIE should really be a blog of its own. 12 | -------------------------------------------------------------------------------- /src/shared/md/2010-03-04-max-vs-the-infinite.md: -------------------------------------------------------------------------------- 1 | 2 | [@pbakaus](http://twitter.com/pbakaus) points out that Number.MAX_VALUE is close to infinity, but not too close. 3 | 4 | ``` 5 | Number.MAX_VALUE*1.0000000000000001 === (1/0) // false 6 | Number.MAX_VALUE*1.0000000000000002 === (1/0) // true 7 | ``` -------------------------------------------------------------------------------- /src/shared/md/2010-04-02-object-to-primitive-coerce.md: -------------------------------------------------------------------------------- 1 | ``` 2 | var foo = { 3 | toString: function () { 4 | return 5; 5 | }, 6 | valueOf: function () { 7 | return "foo"; 8 | } 9 | }; 10 | alert(foo.toString() + 1); // 6 (bad!) 11 | alert(foo + 1); // "foo1" (no good!) 12 | alert(+foo); // NaN (the worst!) 13 | ``` 14 | 15 | Thanks to [Ajaxian](http://ajaxian.com/archives/a-very-detailed-look-at-object-to-primitive-conversions) for pointing out this [amazingly detailed look at object to primitive coercion](http://www.adequatelygood.com/2010/3/Object-to-Primitive-Conversions-in-JavaScript). -------------------------------------------------------------------------------- /src/shared/md/2010-04-12-call-in-ur-call.md: -------------------------------------------------------------------------------- 1 | That must be some good shit [@cramforce](http://twitter.com/cramforce) was smoking when he found this one. 2 | 3 | 4 | alert.call.call.call.call.call.apply(function (a) {return a}, [1,2]) // 2 5 | -------------------------------------------------------------------------------- /src/shared/md/2010-04-15-hello-world.md: -------------------------------------------------------------------------------- 1 | At first, wtfjs was a silly little thought experiment. Almost like a solution log except documenting potential traps instead of, ya know, actual solutions! I set the whole thing up in 10 minutes w/ Tumblr and the help of GitHub Gists. This served well enough to get things started but, as always, there was room for improvement. The rss feed didn't show the code samples. Hosting a site about JavaScript should probably be written in JavaScript. For purity. And science. 2 | 3 | Anyhow, welcome to the new blog. Here's the score: 4 | 5 | - 100% cloud friendly SSJS. Deployed on Heroku with NodeJS. 6 | - Microframework! Utilizes the awesome sauce that is ExpressJS. 7 | - Totally open source. Fork wtfjs.com GitHub. 8 | 9 | Sure, there were a few wtf's along the way. Heroku literally just squeezed NodeJS hosting a few short weeks ago and it is not without a couple of occasional rough edges. 10 | 11 | The bonus of this reauthor is also an improved workflow for contribution. Fork the repo. Add your post in the posts folder. Send me a pull request. Easy. 12 | 13 | what did I learn? 14 | --- 15 | 16 | - Package management in serverside js land is still a total fuck up. 17 | - Heroku and Express have awesome communities; whenever I had a question folks really helped. 18 | - jsftw! The future is here. This code blog can be forked and deployed live in literally one minute. 19 | 20 | Have fun! - brianleroux -------------------------------------------------------------------------------- /src/shared/md/2010-04-16-build-your-own-wtfjs.md: -------------------------------------------------------------------------------- 1 | Maybe you want to deploy a code blog quickly. Maybe you want an excuse to play with NodeJS. I don't know what it is you are up to but here's a quick guide to building your own wtfjs. This requires a Heroku NodeJS access, of course. 2 | 3 | ``` 4 | $ git clone git@github.com:brianleroux/wtfjs.git 5 | $ cd wtfjs/ 6 | $ heroku create --stack beech 7 | $ git push heroku master 8 | ``` 9 | 10 | You're done! 11 | -------------------------------------------------------------------------------- /src/shared/md/2010-04-16-contributing-to-wtfjs.md: -------------------------------------------------------------------------------- 1 | You can either fix up the wtfs here or help broadcast wtfs to the rest of the world! 2 | 3 | contributing an article 4 | --- 5 | 6 | Fork the source on GitHub and then add your post to the posts/ folder. The title has to be of the format: 7 | 8 | **_yyyy-mm-dd-title-of-article.md_** 9 | 10 | The post itself is markdown. Code blocks go into a code element. Its assumed any code is JavaScript (and subsequently syntax highlighted as such) but you can specify other language types. You might have to grab extra language files. Thats it. 11 | 12 | contributing code 13 | --- 14 | 15 | Maybe you found a bug or something is driving you crazy. Perhaps you want to give back. Theres always something TODO and I've littered a few FIXME's around for the adventurous. 16 | 17 | either way 18 | --- 19 | 20 | [Fork it.](http://github.com/brianleroux/wtfjs) Send a pull request. Don't forget to add yourself as a committer to the /about page. -------------------------------------------------------------------------------- /src/shared/md/2010-04-16-express-js-gotcha.md: -------------------------------------------------------------------------------- 1 | Less of a wtf and more of a gotcha. In [ExpressJS](http://expressjs.com/). you can serve static files from a _/public_ directory with this simple directive in your configure block: 2 | 3 | ``` 4 | configure(function() { 5 | set("root", __dirname); 6 | // allow static file serving from public directory 7 | use(Static); 8 | }); 9 | ``` 10 | 11 | But be careful! This sets a the path to be _/public/app.css_ rather than _/app.css_. [More background here.](http://groups.google.com/group/express-js/browse_thread/thread/863ed1888597e630) -------------------------------------------------------------------------------- /src/shared/md/2010-04-16-syntax-highlighting-wtf.md: -------------------------------------------------------------------------------- 1 | Syntax highlighting seems like a solved problem. Over solved. To make matters worse it appears that the production of Sinatra clones and Syntax Highlighters are escalating. Perhaps its a sign. 2 | 3 | After struggling w/ the overly complex Chili jQuery plugin I had a second look at the classic Syntax Highlighter which, while palatable, feels like overkill. Its a bummer b/c I would prefer a highlighter than can deal w/ nested DOM elements. Pygments does all this but Heroku won't let play with the sandbox, and I didn't want to pre-process the markdown treating it like an intermediate format, so I settled on SHJS which has the right characteristics: lightweight, simple install and straightforward docs. 4 | 5 | Only caveat: it only works on _pre_ tags. Thus: 6 | 7 | ``` 8 | $(function(){ 9 | // change code elements into pre elements with class sh_javascript_dom 10 | $('code').each(function(){ 11 | var node = $(this); 12 | node.hide() 13 | .after('pre tag would be here') 14 | .next() 15 | .html(node.html()) 16 | .addClass('sh_javascript_dom'); 17 | node.remove(); 18 | }); 19 | // invoke clientside syntax highlighter 20 | sh_highlightDocument(); 21 | }); 22 | ``` 23 | 24 | Not entirely hideous but plenty to wtf about. Inspect the actual code and compare to the embed above you'll notice I had to swap a nested _pre_ element with a string "pre tag would be here". It gets better: double line breaks mindfuck SHJS forcing it to create new nested pre tags. So no line double breaks. If that wasn't enough all the underscores in the class identifier have been removed. Daaamnit wtf?! 25 | 26 | Problem: unsolved. - brianleroux -------------------------------------------------------------------------------- /src/shared/md/2010-04-17-global-scope-mindtricks.md: -------------------------------------------------------------------------------- 1 | An update by [@deadlyicon](http://twitter.com/deadlyicon) on the previous post. 2 | 3 | This is just a really silly way of saying this: 4 | 5 | ``` 6 | Function.prototype.call.apply(function (a) {return a}, [1,2]) 7 | // 2 8 | ``` 9 | 10 | If this still seems weird to you. Consider this: 11 | 12 | ``` 13 | function logThisAndArgs() { 14 | console.log(this, arguments); 15 | }; 16 | Function.prototype.call.apply(logThisAndArgs, [{'some':'object'},1,2,3,4]) 17 | // logs -> Object { some="object"} [1, 2, 3, 4] 18 | ``` 19 | 20 | Now this! 21 | 22 | ``` 23 | Function.prototype.call.call(logThisAndArgs, {'some':'object'},1,2,3,4) 24 | // logs -> Object { some="object"} [1, 2, 3, 4] 25 | ``` -------------------------------------------------------------------------------- /src/shared/md/2010-04-30-operators-and-regexp-fun.md: -------------------------------------------------------------------------------- 1 | [@ThomasFuchs](http://twitter.com/thomasfuchs) throws down this obfuscated beauty: 2 | 3 | ``` 4 | 1 + + 1 // => 2 5 | 1 + - + 1 // => 0 6 | 1 + - + - + 1 // => 2 7 | 1 + - + - + - + 1 // => 0 8 | 1 + - + + + - + 1 // => 2 9 | 1 + / + + + / + 1 // => 1/ + + + /1 10 | ``` 11 | 12 | [Be sure to read the comments!](http://mir.aculo.us/2010/05/28/valid-javascript-or-not/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed:+miraculous+(mir.aculo.us)) -------------------------------------------------------------------------------- /src/shared/md/2010-04-31-isNaN.md: -------------------------------------------------------------------------------- 1 | So, [null is not an object](https://wtfjs.com/wtfs/2010-02-12-null-is-not-an-object) though sometimes null is a Number. 2 | 3 | ``` 4 | isNaN( null ); // false 5 | null === NaN; // false 6 | null == NaN; // false 7 | ``` 8 | 9 | isNaN converts null to number. 10 | 11 | 12 | Number( null ); // 0 13 | 14 | 15 | But WTF. :) - [@oleg008](http://twitter.com/oleg008) 16 | -------------------------------------------------------------------------------- /src/shared/md/2010-04-31-syntax-highlighting-serverside-with-google-prettyfy.md: -------------------------------------------------------------------------------- 1 | This is much more awesome. I have to thank the guys at [HowToNode.org](http://howtonode.org) for the idea in their [WheatJS](http://github.com/creationix/wheat) static site blog engine. Essentially, it all boils down to running the rather awesome [Google Code Prettyfy](http://code.google.com/p/google-code-prettify/) _serverside_. 2 | 3 | The only remaining problem with the syntax highlighting is now nested <code> elements have to be escaped to display correctly in the final render. 4 | 5 | ``` 6 | // replace the raw code blocks with prettyfied html 7 | t = t.replace(/<code>[^<]+<\/code>/g, function(code) { 8 | return prettyfy(code.match(/<code>([\s\S]+)<\/code>/)[1]); 9 | }); 10 | ``` 11 | 12 | Perhaps, in the future, a quick routine to fetch only the root code elements rather than blinding fetching all of them. Problem: more solved than before! -------------------------------------------------------------------------------- /src/shared/md/2010-06-02-instances-and-default-values.md: -------------------------------------------------------------------------------- 1 | When you create instances of `String` or `Number`, they take the default value (`""` for strings and `0` for numbers). This is not the same for `Object` and `Array`. 2 | 3 | ``` 4 | var a = new Number; 5 | a == 0 // true 6 | 7 | var a = new String; 8 | a == "" // true 9 | 10 | var a = new Object; 11 | a == {} // false 12 | 13 | var a = new Array; 14 | a == [] // false 15 | ``` 16 | 17 | This is even more confusing when using the JSON-style syntax to create objects and arrays. 18 | 19 | ``` 20 | var a = {}; 21 | a == {} // false 22 | 23 | var a = []; 24 | a == [] // false 25 | ``` 26 | 27 | -- [@remi](http://twitter.com/remi) 28 | 29 | (Never forget: [====](http://crockfordfacts.com/MHDTvKwy3xGzI183Akuh_Q) - [@brianleroux](http://twitter.com/brianleroux)) -------------------------------------------------------------------------------- /src/shared/md/2010-06-08-void-is-a-black-hole.md: -------------------------------------------------------------------------------- 1 | Void is a blackhole... 2 | 3 | ``` 4 | var void = function () {} 5 | //=> SyntaxError: missing variable name 6 | ``` 7 | 8 | -- [@rwaldron](http://twitter.com/rwaldron) -------------------------------------------------------------------------------- /src/shared/md/2010-06-09-function-in-ur-string.md: -------------------------------------------------------------------------------- 1 | Old friend (_and clearly damaged by a career of JavaScript programming_) [@jakedevine](http://twitter.com/jakedevine) threw this down on twitter a few days ago. 2 | 3 | ``` 4 | var Z = "constructor"; 5 | Z[Z][Z]("alert('wtfjs!')")(); 6 | // alerts wtfjs! 7 | ``` 8 | 9 | Ok. So wtf exactly is happening here? 10 | 11 | ``` 12 | Z[Z] 13 | // function String() { [native code] } 14 | 15 | Z[Z][Z] 16 | // function Function() { [native code] } 17 | ``` 18 | 19 | AHA! The constructor property of a string is `String` and the constructor property of `String` is `Function`. Makes sense. 20 | 21 | ``` 22 | Z[Z][Z]("console.log('new Function accepts string for eval as argument')")(); 23 | // new Function accepts string for eval as argument 24 | ``` 25 | 26 | Of course. One wonders, as usual, wtf the programmer was up to when he discovered this! 27 | 28 | --- [@brianleroux](http://twitter.com/brianleroux) -------------------------------------------------------------------------------- /src/shared/md/2010-07-11-length-of-what-now.md: -------------------------------------------------------------------------------- 1 | This made me laugh. Out loud even! 2 | 3 | ``` 4 | console.log((!+[]+[]+![]).length); 5 | // 9 6 | ``` 7 | 8 | Huh, wtf?! Lets see what we're getting the length of... 9 | 10 | ``` 11 | console.log((!+[]+[]+![])); 12 | // "truefalse" 13 | ``` 14 | 15 | Ah! lulz. thanks to @stepiiik and @DavidGrudl! 16 | 17 | -------------------------------------------------------------------------------- /src/shared/md/2010-07-12-fail.md: -------------------------------------------------------------------------------- 1 | Let's take the last post a step further: 2 | 3 | ``` 4 | console.log( (![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]] ) // "fail" 5 | ``` 6 | 7 | Breaking that mass of symbols into pieces we notices, that the following patten occurs often: 8 | 9 | ``` 10 | console.log( (![]+[]) ) // "false" 11 | console.log( ![] ) // false 12 | ``` 13 | 14 | So we try adding `[]` to `false`. But through a number of internal function calls( `binary + Operator` -> `ToPrimitive` -> `[[DefaultValue]]`) we end up with converting the right operand to a String: 15 | 16 | ``` 17 | console.log( [].toString() ) // "" 18 | console.log( (![]+[].toString()) ) // false + "" 19 | ``` 20 | 21 | Aha, so we are concatenating strings here! Now this is plain obvious! Moving on to the next bit: 22 | 23 | ``` 24 | console.log( [+[]] ) // [ 0] 25 | console.log( +[] ) // 0 26 | ``` 27 | 28 | Thinking of a `String` as an `Array` we can access its first character via `[0]`. So `"false"[0]` returns `"f"`. 29 | 30 | I think you got the idea now and can figure out the rest by yourself! 31 | 32 | Thanks to Mathias Bynens for pushing this out int the web. -------------------------------------------------------------------------------- /src/shared/md/2010-07-15-typeof-number-is-not-number.md: -------------------------------------------------------------------------------- 1 | How do you determine if a number is an integer in JavaScript? 2 | 3 | ``` 4 | x = 1; 5 | 6 | x === Math.floor(x); 7 | // returns true 8 | ``` 9 | 10 | But what happens if we try to add a method for this to the Number prototype? 11 | 12 | ``` 13 | Number.prototype.isInteger = function() { 14 | return this === Math.floor(this); 15 | } 16 | 17 | x = 1; 18 | 19 | x.isInteger(); 20 | // returns false! 21 | ``` 22 | 23 | Why? It turns out that when you add methods to Number, the type of the number inside the method becomes "object" rather than "number", but Math.floor returns a result of type "number". If you use the === operator, the two values are no longer equal because they're different types. So the method can be fixed two ways. 24 | 25 | Solution 1 is to avoid comparing types: 26 | 27 | ``` 28 | Number.prototype.isInteger = function() { 29 | return this == Math.floor(this); 30 | // works but breaks if you care about 0 vs other falsy values 31 | } 32 | ``` 33 | 34 | Solution 2 is better; cast "this" to the Number type and then the types are equal. 35 | 36 | ``` 37 | Number.prototype.isInteger = function() { 38 | return Number(this) === Math.floor(this); 39 | } 40 | ``` 41 | 42 | --- [@attaboy](http://twitter.com/attaboy) 43 | -------------------------------------------------------------------------------- /src/shared/md/2010-07-22-magic-increasing-number.md: -------------------------------------------------------------------------------- 1 | Look at me, I'm the magic increasing number! 2 | 3 | ``` 4 | 9999999999999999 5 | //=> 10000000000000000 6 | ``` 7 | 8 | 9 | --- [@thomasfuchs](http://twitter.com/thomasfuchs) 10 | 11 | That's because `9999999999999999` > [`Number.MAX_SAFE_INTEGER`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER). That's the highest integer possible without loosing precision. You can check if your integer is save using [`Number.isSafeInteger()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isSafeInteger). 12 | 13 | To keep precision above that integer, you have to use [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) 14 | 15 | --- [@shaedrich](https://github.com/shaedrich) 16 | -------------------------------------------------------------------------------- /src/shared/md/2010-07-23-im-not-a-number-really.md: -------------------------------------------------------------------------------- 1 | You've probably seen this one here before. NaN (**N**ot **a** **N**umber) suffers from a terrible case of self-deception. 2 | 3 | 4 | typeof NaN 5 | //=> number 6 | 7 | 8 | 9 | --- [@3rdEden](http://twitter.com/3rdEden) 10 | 11 | Its still hilarious. Now, check this out: 12 | 13 | 14 | 3..toString(); 15 | // "3" 16 | 17 | 18 | [Explanation here.](http://stackoverflow.com/questions/1995113/strangest-language-feature/3297392#3297392) 19 | 20 | (By way of the wtfjs twitter firehouse. Cheers: [@devongovett](http://twitter.com/devongovett), [@getify](http://twitter.com/getify), [@mahemoff](http://twitter.com/mahemoff), [@cramforce](http://twitter.com/cramforce), [@mathias](http://twitter.com/mathias)!) -------------------------------------------------------------------------------- /src/shared/md/2010-09-16-eval-changes.md: -------------------------------------------------------------------------------- 1 | eval() is a mysterious function. More so than people believe, hell, its spec isn't even clear. And so i present... The two stages of eval denial. 2 | 3 | Try out these functions with 4 | 5 | [foo("foo=2"),foo] 6 | 7 | and take that path with me. 8 | 9 | Tested on chrome, firefox, opera, and safari. 10 | 11 | 12 | #### Apparently eval is evil. 13 | Doesn't seem so evil. 14 | 15 | ``` 16 | function foo(x){var foo=1;eval(x);return foo;}; 17 | 18 | //[2,function foo(x){var foo=1;eval(x);return foo;}] 19 | ``` 20 | 21 | #### Apparently assigning eval to a variable changes how it acts. WTF. 22 | ...Ok I can deal with that I guess. 23 | 24 | ``` 25 | function foo(x){var foo=1, bar=eval;bar(x);return foo;}; 26 | 27 | //and just returning it, not saving it 28 | 29 | function foo(x){var foo=1;(function(){return eval})(x);return foo;}; 30 | 31 | //[1, 2] 32 | ``` -------------------------------------------------------------------------------- /src/shared/md/2010-10-15-ie-754.md: -------------------------------------------------------------------------------- 1 | You wouldn't believe me... 2 | 3 | ``` 4 | ie-754 5 | //=> -754 6 | ``` 7 | 8 | Edit: I think this is a WTF WebKit 9 | 10 | 11 | --- [@rwaldron](http://twitter.com/rwaldron) 12 | 13 | [Screenshot](http://gyazo.com/e61700154b6be109110c1f57b56b1c14.png) 14 | 15 | [Another Screenshot](http://gyazo.com/0ac601fc10179046b7d51106c374a1d7.png) 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/shared/md/2010-11-10-false-advertising.md: -------------------------------------------------------------------------------- 1 | What do you think this constructor returns for `new Dude('Bob')`? Doug or Bob? 2 | 3 | ``` 4 | function Dude(name){ 5 | this.name = name; 6 | return {name: 'Doug'}; 7 | } 8 | ``` 9 | 10 | Answer: 11 | ``` 12 | var bob = new Dude('Bob'); 13 | // { name: 'Doug' } 14 | bob instanceof Dude 15 | // false 16 | ``` 17 | 18 | Huh!? So you can just slip in anything? What about arrays? 19 | ``` 20 | function Dude(name){ 21 | this.name = name; 22 | return [1, 2, 3]; 23 | } 24 | new Dude('Bob'); 25 | // [1, 2, 3] 26 | ``` 27 | 28 | That can't be! What about... 29 | ``` 30 | function Dude(name){ 31 | this.name = name; 32 | return 3; 33 | } 34 | new Dude('Bob'); 35 | // { name: 'Bob' } 36 | ``` 37 | Wah? No way! So, if you try to return a primitive type from a constructor(number, string, date), it 38 | will ignore the return value and return the originally initialized object, but otherwise, the returned value overrides. 39 | 40 | --- [@airportyh](http://twitter.com/airportyh) -------------------------------------------------------------------------------- /src/shared/md/2010-11-15-i-am-myself-but-also-not-myself.md: -------------------------------------------------------------------------------- 1 | Sometimes JavaScript has identity crisis: 2 | 3 | ``` 4 | var foo = [0]; 5 | console.log(foo == !foo); 6 | console.log(foo == foo); 7 | ``` 8 | 9 | Is it time to have a "maybe" operator? :-P 10 | 11 | --- [@diogobaeder](http://twitter.com/diogobaeder) 12 | -------------------------------------------------------------------------------- /src/shared/md/2010-12-06-convert-to-integer.md: -------------------------------------------------------------------------------- 1 | The following will return an Integer with a default of 0 from any String or Number. 2 | 3 | ``` 4 | function toInt(number) { 5 | return number && + number | 0 || 0; 6 | } 7 | console.log(toInt("1")); // 1 8 | console.log(toInt("1.2")); // 1 9 | console.log(toInt("-1.2")); // -1 10 | console.log(toInt(1.2)); // 1 11 | console.log(toInt(0)); // 0 12 | console.log(toInt("0")); // 0 13 | console.log(toInt(Number.NaN)); // 0 14 | console.log(toInt(1/0)); // 0 15 | ``` 16 | 17 | Explanation 18 | -- 19 | 20 | `number && x` will return `x` if `number` is truthy, and `number` otherwise. 21 | 22 | `x || 0` will return `x` if `x` is truthy, and 0 otherwise. 23 | 24 | `+ number` will convert number to a Number. 25 | 26 | `12.34 | 0` will convert 12.34 to the integer `12`. It will do it, as all binary operations can only be done on 32 bit integers in JavaScript. 27 | 28 | -- [@Poetro](http://twitter.com/Poetro) 29 | -------------------------------------------------------------------------------- /src/shared/md/2011-02-11-all-your-commas-are-belong-to-Array.md: -------------------------------------------------------------------------------- 1 | This installment of wtfjs has to do with the Abstract Equality Comparison Algorithm (as most do), Array's constructor, and expressions. 2 | 3 | Let's take the following example: 4 | 5 | 6 | new Array([],null,undefined,null) == ",,,"; // true 7 | 8 | 9 | WTF? Why does this work? 10 | 11 | Firstly, the == causes type coersion (pretty common). From the ECMAScript Specification, 5th edition (final draft), 12 | 11.9.3 The Abstract Equality Comparison Algorithm: 13 | 14 | > The comparison `x == y`, where `x` and `y` are values produces true or false. Such a comparison is performed as follows: 15 | 16 | [snip] 17 | 18 | > 8. If `Type(x)` is either String or Number and Type(y) is Object, return the result of the comparison `x == ToPrimitive(y)`. 19 | > 9. If `Type(x)` is Object and `Type(y)` is either String or Number, return the result of the comparison `ToPrimitive(x) == y`. 20 | 21 | So both uses of `Array` are run through `ToPrimitive`. But what does `ToPrimitive` do, exactly? Well, according to another 22 | part of the Final final final final draft Standard ECMA-262 5th edition (the document seriously has this title...), 9.1. ToPrimitive: 23 | 24 | [snip] 25 | 26 | > Object Return a default value for the Object. The default value of an object is retrieved by calling the `[[DefaultValue]]` 27 | > internal method of the object, passing the optional hint PreferredType. The behavior of the `[[DefaultValue]]` internal 28 | > method is defined by this specification for all native ECMAScript objects in 8.12.8. 29 | 30 | So we're hinting to the [[DefaultValue]] method within Array with the type of `String`, so according (again) to the spec, 31 | 8.12.8 [[DefaultValue]] (hint): 32 | 33 | > 1. Let toString be the results of calling the `[[Get]]` internal method of object O with argument "toString". 34 | 35 | Unless of course, `IsCallable(toString)` (i.e. the object has a `.toString` method on it's prototype). 36 | 37 | > 2. If IsCallable(toString) is true, then, 38 | >     a. Let str be the results of calling the [[Call]] internal method of toString with O as the this value and an empty argument list. 39 | 40 | And according to 15.4.4.2 Array.prototype.toString (): 41 | 42 | > When the toString method is called, the following steps are taken: 43 | > 44 | > 1. Let array be the result of calling `ToObject` on the this value. 45 | > 2. Let func be the result of calling the `[[Get]]` internal method of array with argument "join". 46 | 47 | Oh, but we're not done yet! 48 | 49 | Stay with me - we're type-coersing to a string, and `Array.prototype.toString` calls `Array.prototype.join` with no arguments, so we're 50 | joining all the internal members of the array with the default separator is the single-character String "," (again, according to the spec). 51 | When an Array calls join on itself, it's going from 1 .. len (all it's members) and calling `ToString` on these members and concatenating 52 | them together. Essentially doing this: 53 | 54 | ``` 55 | Array.prototype.join = function (separator) { 56 | var result = ""; 57 | if ("undefined" === typeof separator) { 58 | separator = ","; 59 | } 60 | for (var k = 0, len = this.length; k < len; ++k && result += separator) { 61 | var isToS = this[k] !== null && this[k] !== undefined && "function" === typeof this[k].toString 62 | result += isToS ? this[k].toString() : String(this[k]); 63 | } 64 | return result; 65 | }; 66 | ``` 67 | 68 | So in the end, we end up with weird stuff like this actually working, as `[]`, `null`, and `undefined` all result in "" when their 69 | respective `ToPrimitive` methods ask for `[[DefaultValue]]` with String as the type hint. 70 | 71 | Another similar WTF on the same topic: 72 | 73 | 74 | ",,," == new Array(4); // true 75 | 76 | 77 | This is similar, but not quite the same. When you call Array's constructor, if there are multiple arguments, they're intepretted as being 78 | members of the Array. If you've only put 1 Integer (n) as the argument, an Array object is initiatilized with (n) `undefined` items. 79 | Again, from the spec 15.4.2.2 new Array (len): 80 | 81 | >If the argument len is a `Number` and `ToUint32(len)` is equal to `len`, then the length property of the newly constructed object 82 | >is set to `ToUint32(len)`. 83 | 84 | So essentially end up with 85 | 86 | 87 | [undefined,undefined,undefined,undefined].join(), 88 | 89 | 90 | Which yields something like: 91 | 92 | 93 | "" + String(undefined) + "," + String(undefined) + "," + String(undefined) + "," + String(undefined) 94 | 95 | 96 | Which ends up being ",,," (which evaluates to `true`, as it matches). 97 | 98 | Lastly, adding just one more level of WTF to this post, you can also accidentally (or intetionally?) add an expression within 99 | Array's constructor function (and you can also omit new, as the spec also says: "When Array is called as a function rather than as a 100 | constructor, it creates and initialises a new Array object."). 101 | 102 | So we can finally end up with the weirdest rendition of this WTF as so: 103 | 104 | 105 | ",,," == Array((null,'cool',false,NaN,4)); // true 106 | 107 | 108 | If this doesn't make you WTF, I'm not sure what will. 109 | 110 | [@danbeam](http://twitter.com/danbeam) 111 | -------------------------------------------------------------------------------- /src/shared/md/2011-05-12-parseInt-is-not-eval.md: -------------------------------------------------------------------------------- 1 | Remember folks, parseInt() is not eval(). 2 | 3 | ``` 4 | parseInt("1", 10); // 1 5 | eval("1") // 1 6 | ``` 7 | 8 | Pretty much the same thing....wait. 9 | 10 | ``` 11 | parseInt("1 + 1", 10); // 1 12 | eval("1 + 1") // 2 13 | ``` 14 | 15 | In the first example the first digit is recognized and the rest of the string is thrown away. How intuitive. 16 | eval() at least gets it right. 17 | 18 | ``` 19 | parseInt("1 - 1", 10); // 1 20 | eval("1 - 1") // 0 21 | ``` 22 | 23 | The string example takes the first digit and just throws out the rest of the string. 24 | And again, eval() with the correct solution. 25 | 26 | ``` 27 | parseInt("1" + "1", 10) // 11 28 | eval("1" + "1") // 11 29 | ``` 30 | 31 | This time they both get the wrong answer, because the strings are concatenated before the numbers are evaluated. 32 | 33 | ``` 34 | parseInt("1" - "1", 10); // 0 35 | eval ("1" - "1") // 0 36 | ``` 37 | 38 | Both right answers, because the subtraction symbol forces the strings into numbers before they get used. 39 | 40 | -- [@xjamundx](http://twitter.com/xjamundx) 41 | -------------------------------------------------------------------------------- /src/shared/md/2011-06-23-parseint-magic.md: -------------------------------------------------------------------------------- 1 | Be aware of parseInt! 2 | 3 | 4 | parseInt(null, 24) === 23 // true 5 | 6 | 7 | [Answer and source!](http://stackoverflow.com/q/6459758/269804) 8 | 9 | -- [@lord_T](http://twitter.com/silesianlordt) 10 | -------------------------------------------------------------------------------- /src/shared/md/2011-06-27-min-less-max.md: -------------------------------------------------------------------------------- 1 | This beauty is courtesy of [TiTi](https://github.com/TiTi) ...lets look at some code. 2 | 3 | ``` 4 | Math.max(); 5 | // -Infinity 6 | 7 | Math.min(); 8 | // Infinity 9 | ``` 10 | 11 | Ok, so, there *is* a good reason for this behaviour. It might even make sense if you happen to occasionally omit args from your min/max calls. ;) 12 | 13 | You see, the min/max implementations need something to compare to and Infinity and -Infinity are the only safe values to use for that comparison. [@kriskowell goes into more better detail here](https://twitter.com/#!/kriskowal/status/85402842650783744) and was quickly followed by [@brendaneich](https://twitter.com/#!/BrendanEich/status/85406752136368128) who not only [wrote js in 10 days](http://brendaneich.com/2008/04/popularity/) but can rock out unicode Infinity symbols without looking them up ...I shit you not. 14 | 15 | Of course, due to this behaviour js allows for this code humour: 16 | 17 | ``` 18 | Math.min() < Math.max(); 19 | // false 20 | ``` 21 | 22 | Oh JavaScript, I still love you. 23 | -------------------------------------------------------------------------------- /src/shared/md/2011-07-26-iteration-demoralization.md: -------------------------------------------------------------------------------- 1 | See if you can guess what this will output: 2 | 3 | ``` 4 | function allNames() { 5 | var names = [ 'dan', 'anthony', 'pavel' ]; 6 | for (name in names) { 7 | console.log(name); 8 | } 9 | } 10 | 11 | allNames(); 12 | ``` 13 | 14 | If you guessed this: 15 | 16 | > 0
    17 | > 1
    18 | > 2
    19 | 20 | 21 | ...then you are right! Congratulations! 22 | 23 | What you might not have guessed, is what this will output: 24 | 25 | 26 | console.log(window.name); 27 | 28 | 29 | it's: 30 | 31 | > "2" 32 | 33 | 34 | Iteration is assignment, and without the use of the `var` keyword, you're really using the global object - which in this context is the `window` object. 35 | 36 | So the original function is equivalent to: 37 | 38 | ``` 39 | function allNames() { 40 | var names = [ 'dan', 'anthony', 'pavel' ]; 41 | for (window.name in names) { 42 | console.log(name); 43 | } 44 | } 45 | ``` 46 | 47 | By [@danlash][1] 48 | 49 | [1]:https://twitter.com/danlash 50 | -------------------------------------------------------------------------------- /src/shared/md/2011-09-24-Date-silently-accepts-anything.md: -------------------------------------------------------------------------------- 1 | ``` 2 | d = new Date("couldn't you please throw an exception here instead?"); 3 | 4 | // No! You get the joy of discovering this error somewhere unrelated, 5 | // much later; at the point of use, in an innocent part of your code: 6 | 7 | d.getTime(); // => NaN 8 | ``` 9 | 10 | [johan](https://github.com/johan) || [@ecmanaut](http://twitter.com/ecmanaut) 11 | -------------------------------------------------------------------------------- /src/shared/md/2011-11-08-undefined-identity-crisis.md: -------------------------------------------------------------------------------- 1 | Everyone loves Yoda Conditionals, right? They stop you from accidentally assigning stuff when you should be comparing, breaking everything! Or do they? 2 | 3 | ``` 4 | function test (a) { 5 | if (undefined = a) { 6 | a = {} 7 | } 8 | return a; 9 | } 10 | undefined === test(null) 11 | ``` 12 | 13 | I encountered this gem recently. It's more a bug in the code than the implementation, but it's the implementation that allows this quirky disaster to occur. A single missing equals symbol in the comparison of undefined against a is the source of the chaos. 14 | 15 | When the type equality comparison is evaluated, the state of undefined is stored, then test is executed and it's return value is stored, then the comparison is made. Before running test, undefined will be what we expect; undefined. But after running test, it will now be null. Because the value of undefined was stored for the comparison before running test, the first time running this will return false, while the second time will return true. Undefined identity crisis! 16 | 17 | By [@stephenbelanger][1] 18 | 19 | [1]:https://twitter.com/stephenbelanger 20 | 21 | **EDIT**: This has been fixed in ECMAScript 5. `undefined` is now a constant instead of a global variable. The above sample code will now always return false. –[@TimoTijhof](https://twitter.com/TimoTijhof) 22 | -------------------------------------------------------------------------------- /src/shared/md/2011-11-11-the-universe-answers-and-JavaScript-still-makes-us-wtf.md: -------------------------------------------------------------------------------- 1 | This installment of wtfjs has to do with implicit type conversion during 2 | arithmetics and operator ambiguity / overloading. 3 | 4 | If you can figure out what this returns on the first guess, I'll give you a 5 | great big hug the next time I see you: 6 | 7 | ``` 8 | // is there an error (if not, what do I return?) 9 | "3" -+-+-+ "1" + "1" / "3" * "6" + "2" 10 | ``` 11 | 12 | Now, I won't spoil the fun for those of you at home trying to do this mentally, 13 | but the answer probably isn't what you'd expect. Go ahead, run it in a 14 | JavaScript console - WTF?! ^)*&#) right? 15 | 16 | Firstly, I'm not sure about you guys, but I forgot some basic stuff from 17 | elementary school math - order of operations. One usually doesn't look at these 18 | when doing (supposed) string concatenation (but we're doing a little bit more 19 | than that, aren't we?). 20 | 21 | The precedence of operators in JavaScript are (from highest to lowest): 22 | 23 | ``` 24 | delete 25 | void 26 | typeof 27 | ++ 28 | -- 29 | + 30 | - 31 | ~ 32 | ! 33 | 34 | * 35 | / 36 | % 37 | 38 | + 39 | - 40 | << 41 | >> 42 | >>> 43 | 44 | < 45 | > 46 | <= 47 | >= 48 | instanceof 49 | in 50 | 51 | == 52 | != 53 | === 54 | !== 55 | 56 | & 57 | ^ 58 | | 59 | 60 | && 61 | || 62 | 63 | ? : 64 | 65 | = 66 | *= 67 | /= 68 | %= 69 | += 70 | -= 71 | <<= 72 | >>= 73 | >>>= 74 | &= 75 | ^= 76 | |= 77 | ``` 78 | 79 | http://es5.github.com/#x11.4.6 80 | 81 | First you'll notice that the `+` occurs twice (already a bit confusing), but 82 | additionally can be used for string concatenation based on contextual cues and 83 | type hints (i.e. `5 + "2" = "52"`, not `7`). 84 | 85 | > 11.6.1 The Addition operator ( + ) 86 | > The addition operator either performs string concatenation or numeric addition. 87 | 88 | [snip] 89 | 90 | > If Type(lprim) is String or Type(rprim) is String, then 91 | 92 | > Return the String that is the result of concatenating ToString(lprim) followed by ToString(rprim) 93 | 94 | > [Else,] 95 | 96 | > Return the result of applying the addition operation to ToNumber(lprim) and ToNumber(rprim). 97 | 98 | So this means we'll have to find out what which + is doing what. 99 | 100 | Additionally, you can throw a unary `+` or `-` operator onto `UnaryExpression`s 101 | like candy to change their signs and make things prettier and easier to 102 | understand for your fellow developers. Note that every `-` flips the sign, but 103 | `+` does essentially nothing functionally to the result of the `UnaryExpression` 104 | (i.e. `+1 === 1`). 105 | 106 | NOTE: Unary `+` can be useful to cast to numbers (hence the `+new Date` hack we 107 | often see to emulate `Date.now()`) and to guarantee you're casting to decimal 108 | (i.e. `+"013"` is `13` but `parseInt("013")` is `11`). This method has the 109 | drawback, however, that it can't handle letters in the string (i.e. `+"1a"` 110 | gives `NaN` whereas `parseInt("1a")` gives `1`, and accidental octal conversion 111 | number guessing by `parseInt` can be fixed by adding a base to `parseInt` (i.e. 112 | `parseInt("08", 10)` is `8`). 113 | 114 | http://es5.github.com/#x11.6.1 115 | 116 | These unary operators are evaluated first as they have the highest precedence, 117 | so we start with the result of `+-+-+"1"` (notice how the first `-` is treated 118 | as the operator when evaluating an `AdditiveExpression`). The result of this is 119 | simply `1`. 120 | 121 | NOTE: This ignores your grammar teacher's rules about double negatives. 122 | 123 | Let's make this line into an expression tree. After unary operators are 124 | evaluated, we have: 125 | 126 | ``` 127 | + 128 | 129 | "2" + 130 | 131 | * - 132 | 133 | / "6" 1 "3" 134 | 135 | "1" "3" 136 | ``` 137 | 138 | However, we don't know what types are implicitly cast yet. Let's make another 139 | tree showing non-ambiguous operations (`/`, `*`, `-`): 140 | 141 | ``` 142 | + 143 | 144 | "2" + 145 | 146 | * - 147 | 148 | / 6 1 3 149 | 150 | 1 3 151 | ``` 152 | 153 | This greatly simplifies the bottom of the tree as they're all now numbers. We 154 | continue evaluating from bottom left most child up, which evaluates the 155 | expression as so: (3-1)+((1/3)*2) = 2 + 2 = 4. This leaves us with this tree: 156 | 157 | ``` 158 | + 159 | 160 | "2" 4 161 | ``` 162 | 163 | 164 | This last operation is ambiguous, so we look to see if either operand is a 165 | string (which `"2"` is), so the type of `lprim` or `rprim` is `String` after 166 | calling `ToPrimitive` (which `rprim is`), so the final result is 167 | 168 | ``` 169 | "42" 170 | ``` 171 | 172 | (which is the obvious answer to life the universe and everything, really). 173 | 174 | [@danbeam](http://twitter.com/danbeam) 175 | -------------------------------------------------------------------------------- /src/shared/md/2011-12-16-negative-zero-equal-but-not-equal.md: -------------------------------------------------------------------------------- 1 | ``` 2 | 0 === -0 //true 3 | 1/0 === 1/-0 //false 4 | ``` 5 | 6 | By [Benvie][1] 7 | 8 | [1]:https://github.com/Benvie 9 | -------------------------------------------------------------------------------- /src/shared/md/2012-04-18-changing-variables-changes-arguments.md: -------------------------------------------------------------------------------- 1 | It turns out that changing the value of an argument variable will change its 2 | value in the `arguments` "array": 3 | 4 | ``` 5 | > function hello(what) { 6 | . what = "world"; 7 | . return "Hello, " + arguments[0] + "!"; 8 | . } 9 | > hello("shazow") 10 | "Hello, world!" 11 | ``` 12 | 13 | This is documented behaviour (see *NOTE 1* in §10.6 *Arguments Object* of 14 | [ECMA-262](http://es5.github.com/#x10.6)). 15 | 16 | I suspect, without evidence, that this allows named argument value lookups to 17 | be transformed at compile time into a lookup into the `arguments` array (so, 18 | for example, the `what = "world";` would be transformed into `arguments[0] = 19 | "world"`; much like Python's fast locals). 20 | 21 | [@wolever](http://twitter.com/wolever) 22 | -------------------------------------------------------------------------------- /src/shared/md/2012-05-07-Numbers-and-dots.md: -------------------------------------------------------------------------------- 1 | A JavaScript syntax oddity with Numbers and Dots: 2 | 3 | ``` 4 | // Ok, you may have seen wrapping a number literal with parens to call Number methods 5 | (42).toFixed(2); // "42.00" 6 | 7 | // And it is understandable that without parens you get a syntax error 8 | 42.toFixed(2); // SyntaxError: identifier starts immediately after numeric literal 9 | 10 | // But numbers with decimals work fine without parens (WTF?) 11 | 42.888.toFixed(2); // "42.89" 12 | 13 | // And whole numbers with two dots work as well (WTF?) 14 | 42..toFixed(2); // "42.00" 15 | 16 | // Hey, so what about 3 dots!? Firefox gives XML-related error (WTF?) 17 | 42...toFixed(2); // TypeError: XML descendants internal method called on incompatible Number 18 | ``` 19 | 20 | [kensnyder](https://github.com/kensnyder) via [@ryanflorence](https://twitter.com/ryanflorence/status/199523604092821504) 21 | 22 | **Explanation** 23 | JS processes the characters and when it finds the dot after 42 it thinks, 42 must be decimal and expects further digits after the dot. A string is obviously not a number therefore JS throws an error. 24 | 25 | — [@shaedrich](https://github.com/shaedrich) 26 | -------------------------------------------------------------------------------- /src/shared/md/2012-08-11-Slashes!.md: -------------------------------------------------------------------------------- 1 | What should the following JS yield? 2 | 3 | ``` 4 | n = 1 5 | /1*"\/\//.test(n + '"//') 6 | ``` 7 | 8 | Should it be `true`? (It is `NaN`.) 9 | 10 | Using semicolons, on the other hand, makes it behave like you'd expect: 11 | 12 | ``` 13 | n = 1; 14 | /1*"\/\//.test(n + '"//'); 15 | ``` 16 | 17 | (Returns `true`.) 18 | 19 | The fun around this WTFJS comes from trying to understand how this should be 20 | parsed, so please have fun experimenting with the snippet of code. 21 | 22 | When you're done understanding the different levels on which it plays, read on. 23 | 24 | The trick revolves around the different cases in which the slash character has 25 | meaning. There are three cases: comments, regular expressions, and division, 26 | all of which are meant to be on display here. 27 | 28 | In the first, semicolon-free snippet, the first slash on the second line is a 29 | division. We divide 1 by 1, multiply it by a long string, and after that there 30 | is a comment. 31 | 32 | In the second snippet, with semicolons, the second line is a regex, tested 33 | against the global variable in the first line, transmuted to a string via 34 | concatenation. 35 | 36 | An interesting variation that shows what happens more clearly is the following: 37 | 38 | ``` 39 | n = 1 40 | /1?":n\/\//.test(n + '":n//') 41 | ``` 42 | 43 | That returns `":n///.test(n + '"`. It gives the trick away. 44 | (It uses the ternary operator `?:`, if you're wondering.) 45 | 46 | Obviously, if you really want your friends to have a headache, give them this 47 | version: 48 | 49 | ``` 50 | n = 0 51 | /0?":n\/\//.test(n + '":n//') 52 | ``` 53 | 54 | That returns `undefined`, which is even more obscure than the `NaN` that we got 55 | in the first snippet. 56 | Yes, `0/0` is `NaN`, which is falsy. 57 | 58 | — [@espadrine](http://espadrine.github.com/) 59 | -------------------------------------------------------------------------------- /src/shared/md/2012-09-19-Hexadecimal-weirdness.md: -------------------------------------------------------------------------------- 1 | In JS you can represent numbers in hexadecimal, right? 2 | 3 | 4 | var hex = 0xFF55; 5 | 6 | 7 | You can also perform shift operations, right? 8 | Left shift is equivalent to a multiplication... 9 | 10 | ``` 11 | var hex = 0xFF55 << 8; // Shift 8 bits = add 0x00 at the end. 12 | alert(hex.toString(16)); // 0xFF5500 13 | ``` 14 | 15 | But from a certain point, this produces negative numbers 16 | 17 | ``` 18 | // Before 0x800000 it's ok 19 | alert((0x777777 << 8).toString(16)); // 0x77777700 20 | 21 | // After 0x800000 it's not ok 22 | alert((0x888888 << 8).toString(16)); // -77777800, WTF? 23 | 24 | // The only way to remain positive is to multiply instead of shifting 25 | alert((0x888888 * 0x100).toString(16)); // 88888800 26 | ``` 27 | 28 | Thanks JS for making left shift different than a multiplication! 29 | 30 | I do have an explanation! 31 | 32 | ES5 states that the left-shift operator is a signed shift on 32 bits represented by two's complement which means 33 | that the highest order bit defines the sign. 34 | 35 | 7 in hexa = 0111 in binary (every number below 7 starts with 0) 36 | 8 in hexa = 1000 in binary (every number above 8 starts with 1) 37 | 38 | So in binary: 39 | 40 | (0x777777 << 8) in hexa = 0111 0111 0111 0111 0111 0111 0111 0000 0000 in binary (the 32nd bit is still 0) 41 | 42 | (0x888888 << 8) in hexa = 1000 1000 1000 1000 1000 1000 0000 0000 in binary (the 32nd bit becomes 1 => negative) 43 | 44 | As for why multiplying 0x888888 * 0x100 yields a different result, both operands to the * operator are numeric, so 45 | each is casted to a IEEE 64-bit double, then multiplied, which means this is what is really happening: 46 | 47 | ``` 48 | 0x888888 * 0x100 === 8947848.0 * 256.0 === 2290649088.0 49 | ``` 50 | 51 | When this is converted into a string with base 16, what you get is 88888800. 52 | 53 | — [@MaximeEuziere](https://twitter.com/MaximeEuziere) 54 | -------------------------------------------------------------------------------- /src/shared/md/2012-10-10-infinity-madness.md: -------------------------------------------------------------------------------- 1 | ```js 2 | parseFloat( 'Infinity' ) // returns Infinity 3 | Number( 'Infinity' ) // returns Infinity 4 | parseInt( 'Infinity' ) // returns NaN 5 | ``` 6 | — [@fivetanley][1] 7 | 8 | But of course, you should always specify a radix when calling `parseInt`: 9 | 10 | ```js 11 | parseInt( 'Infinity', 10 ) // returns NaN 12 | // ... 13 | parseInt( 'Infinity', 18 ) // returns NaN... 14 | parseInt( 'Infinity', 19 ) // returns 18 15 | // ... 16 | parseInt( 'Infinity', 23 ) // returns 18... 17 | parseInt( 'Infinity', 24 ) // returns 151176378 18 | // ... 19 | parseInt( 'Infinity', 29 ) // returns 385849803 20 | parseInt( 'Infinity', 30 ) // returns 13693557269 21 | // ... 22 | parseInt( 'Infinity', 34 ) // returns 28872273981 23 | parseInt( 'Infinity', 35 ) // returns 1201203301724 24 | parseInt( 'Infinity', 36 ) // returns 1461559270678... 25 | parseInt( 'Infinity', 37 ) // returns NaN 26 | // ... 27 | ``` 28 | — [@stuartpb][2] 29 | 30 | [1]: https://twitter.com/fivetanley 31 | [2]: https://twitter.com/stuartpb 32 | -------------------------------------------------------------------------------- /src/shared/md/2012-12-28-undefined-props-on-numbers.md: -------------------------------------------------------------------------------- 1 | ``` 2 | function getBounds(node) { 3 | var n = node || 0; 4 | return { width: n.width, height: n.height }; 5 | } 6 | ``` 7 | 8 | If you call `getBounds()` with _null_, you'll get back `{ width: undefined, height: undefined }` 9 | because in JS, numbers have properties (inherited from Number), and using an undefined 10 | property doesn't throw, it just returns undefined. `null` and `undefined` are propertyless. 11 | Definitely not what I expected in a quick reading of code like this. 12 | 13 | — [@unwiredben][1] 14 | 15 | [1]:https://twitter.com/unwiredben 16 | -------------------------------------------------------------------------------- /src/shared/md/2013-01-28-array-comparison.md: -------------------------------------------------------------------------------- 1 | Did you know that JavaScript can compare arrays using lexicographical ordering? 2 | 3 | ``` 4 | [1, 2, 4] < [1, 2, 5] // true 5 | [1, 3, 4] < [1, 2, 5] // false 6 | ``` 7 | 8 | Just don't expect trichotomy to hold. 9 | 10 | ``` 11 | [1, 2, 3] === [1, 2, 3] // false 12 | [1, 2, 3] < [1, 2, 3] // false 13 | [1, 2, 3] == [1, 2, 3] // false 14 | [1, 2, 3] > [1, 2, 3] // false 15 | ``` 16 | 17 | Oh, and just in case you're wondering, it knows it's messing with you. 18 | 19 | ``` 20 | [1, 2, 3] <= [1, 2, 3] // true 21 | [1, 2, 3] >= [1, 2, 3] // true 22 | ``` 23 | 24 | — [@pwnall][1] 25 | 26 | [1]:https://twitter.com/pwnall 27 | 28 | *** 29 | 30 | It's hard to understand, but ECMA always helps. 31 | 32 | http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3 33 | 34 | Paragraph 10 says that "Comparison Algorithm" returns false if paragraphs 1-9 don't satisfy the condition. 35 | 9.If Type(x) is Object and Type(y) is either String or Number, 36 | return the result of the comparison ToPrimitive(x) == y. 37 | 10.Return false. 38 | 39 | 40 | ``` 41 | [] === []; // false 42 | [] == []; // false 43 | 44 | //its like 45 | ({}) === ({}); // false 46 | ({}) == ({}); // false 47 | 48 | //BUT 49 | [] == 0; // true 50 | ``` 51 | 52 | http://www.ecma-international.org/ecma-262/5.1/#sec-11.8.1 53 | 54 | The Less-than Operator ( < ) and The Greater-than Operator ( > ) 55 | 5.Let r be the result of performing abstract relational comparison lval < rval or lval > rval. 56 | 6.If r is undefined, return false. Otherwise, return r. 57 | 58 | ``` 59 | [] < []; // false 60 | [] > []; // false 61 | // its like 1 < 1 ==> false and 1 > 1 ==> false 62 | ``` 63 | 64 | http://www.ecma-international.org/ecma-262/5.1/#sec-11.8.3 65 | 66 | 5.Let r be the result of performing abstract relational comparison rval < lval with LeftFirst equal to false. 67 | 6.If r is true or undefined, return false. Otherwise, return true. 68 | 69 | ``` 70 | [] <= []; // true 71 | [] >= []; // true 72 | // its like 1 <= 1 ==> true and 1 >= 1 ==> true 73 | ``` 74 | 75 | — [kirillov-artur][1] 76 | 77 | [1]:https://github.com/kirillov-artur 78 | -------------------------------------------------------------------------------- /src/shared/md/2013-02-05-magic-function-properties.md: -------------------------------------------------------------------------------- 1 | ``` 2 | var f = function() { }; 3 | f.foo = 'foo'; // sets f.foo to 'foo' 4 | ``` 5 | 6 | Functions are objects, so you can set properties on them after creation. 7 | 8 | ``` 9 | f.name; // is '' 10 | f.name = 'foo'; 11 | f.name; // is still '' 12 | ``` 13 | 14 | But not all the time. 15 | 16 | ``` 17 | var f = function myFunction() { }; 18 | f.name; // is 'myFunction' 19 | ``` 20 | 21 | Functions happen to have magic properties. One of them is the non-standard `.name`, 22 | which stores the function's first name and read-only. 23 | 24 | — [@tmcw][1] 25 | 26 | [1]:https://twitter.com/tmcw 27 | -------------------------------------------------------------------------------- /src/shared/md/2013-02-12-obfuscated-fibonacci.md: -------------------------------------------------------------------------------- 1 | ``` 2 | var fib = function (_) { 3 | for(_=[+[],++[[]][+[]],+[],_],_[++[++[++[[]][+[]]][+[]]][+[]]]=(((_[++[++[++[[]][+[]]][+[]]][+[]]]-(++[[]][+[]]))&(((--[[]][+[]])>>>(++[[]][+[]]))))===(_[++[++[++[[]][+[]]][+[]]][+[]]]-(++[[]][+[]])))?(_[++[++[[]][+[]]][+[]]]=++[[]][+[]],_[++[++[++[[]][+[]]][+[]]][+[]]]-(++[[]][+[]])):+[];_[++[++[++[[]][+[]]][+[]]][+[]]]--;_[+[]]=(_[++[[]][+[]]]=_[++[++[[]][+[]]][+[]]]=_[+[]]+_[++[[]][+[]]])-_[+[]]); 4 | return _[++[++[[]][+[]]][+[]]]; 5 | } 6 | 7 | console.assert(fib(-1) === 0); 8 | console.assert(fib(0) === 0); 9 | console.assert(fib(1) === 1); 10 | console.assert(fib(2) === 1); 11 | console.assert(fib(3) === 2); 12 | console.assert(fib(4) === 3); 13 | console.assert(fib(5) === 5); 14 | console.assert(fib(6) === 8); 15 | console.assert(fib(7) === 13); 16 | console.assert(fib(32) === 2178309); 17 | console.assert(fib(46) === 1836311903); 18 | console.assert(fib(47) === 2971215073); 19 | console.assert(fib(63) === 6557470319842); 20 | 21 | console.log('done!'); 22 | ``` 23 | 24 | I've combined (for fun) a few WTFs to make something bigger. 25 | 26 | Just in case... don't code in JS like that. Seriously. 27 | 28 | -- [@s3a](https://github.com/s3a/) 29 | -------------------------------------------------------------------------------- /src/shared/md/2013-02-13-unicode-vars.md: -------------------------------------------------------------------------------- 1 | ECMAScript allows you to use unicode variable names, just use the usual \uXXXX codes: 2 | 3 | ``` 4 | var \u1000 = { 5 | \u1001: 'foo', 6 | \u1011: 'bar' 7 | }; 8 | 9 | console.log( \u1000.\u1001 ); // prints 'foo' 10 | console.log( \u1000.\u1011 ); // prints 'bar' 11 | ``` 12 | 13 | WTF right? 14 | 15 | 16 | By [@manekinekko][1] 17 | 18 | [1]:https://twitter.com/manekinekko 19 | -------------------------------------------------------------------------------- /src/shared/md/2013-02-21-why-am-i-a-number.md: -------------------------------------------------------------------------------- 1 | Can someone tell me? 2 | 3 | ``` 4 | "Why am I a " + typeof + ""; // "Why am I a number" 5 | ``` 6 | 7 | — [@jhnnns][1] 8 | 9 | *** 10 | 11 | I think I can tell you. 12 | 13 | typeof requires some value or expression that is evaluated and passed then to typeof as an argument. +"" is treated as expression because + operator 14 | can be used as an unary operator (syntax is: + UnaryExpression). + converts its operand to Number type. So, + "" is evaluated to 0 and then 0 is passed to typeof. 15 | 16 | Note that we can cast strings to numbers by preceding them with +: 17 | 18 | ``` 19 | 20 | (2 + "3"); // 23 21 | (2 + +"3"); // 5 22 | (+""); // 0 23 | 24 | ``` 25 | 26 | — [@wojciechfornal][2] 27 | 28 | 29 | 30 | *** 31 | 32 | ``` 33 | typeof +""; // number 34 | 35 | // even 36 | typeof -""; // "number" 37 | 38 | // BUT!!! 39 | -"foo"; //NaN 40 | typeof -"foo"; // "number" 41 | 42 | // because 43 | typeof NaN === 'number'; // Despite being "Not-A-Number" 44 | 45 | ``` 46 | 47 | — [kirillov-artur][3] 48 | 49 | [1]:https://twitter.com/jhnnns 50 | [2]:https://twitter.com/wojciechfornal 51 | [3]:https://github.com/kirillov-artur 52 | -------------------------------------------------------------------------------- /src/shared/md/2013-02-22-parseint-radix.md: -------------------------------------------------------------------------------- 1 | ``` 2 | parseInt('fuck'); // NaN 3 | parseInt('fuck', 16); // 15 4 | ``` 5 | 6 | So remember kids, always supply a radix! 7 | 8 | 9 | — [@kevincennis][1] 10 | 11 | This occurs because parseInt will continue parsing character-by-character 12 | until it hits a character it doesn't know. The `f` in `fuck` is hexadecimal 13 | 15. You can get similar behavior with: 14 | ``` 15 | parseInt('3fucks') // 3 16 | parseInt('3fucks', 16) // 3f in hex = 63 17 | ``` 18 | 19 | [1]:https://twitter.com/kevincennis 20 | [2]:https://github.com/stevendesu 21 | -------------------------------------------------------------------------------- /src/shared/md/2013-02-28-null,-undefined-and-test.md: -------------------------------------------------------------------------------- 1 | Checking a variable for one word with one to ten letters lowercase only? 2 | 3 | Try this regular expression: `/^[a-z]{1,10}$/.test('wakaluba')`. 4 | 5 | ``` 6 | /^[a-z]{1,10}$/.test(null); 7 | /^[a-z]{1,10}$/.test(undefined); 8 | ``` 9 | 10 | Both should obviously fail, but return **true**. srsly, WTF JS? 11 | 12 | — [@damienklinnert][1] 13 | 14 | This happens because regex.test() converts its parameter to a string: 15 | 16 | ``` 17 | String(null) // "null" 18 | ``` 19 | 20 | The string "null" matches the regular expression `/^[a-z]{1,10}$/` 21 | 22 | — [@stevendesu][2] 23 | 24 | [1]:https://twitter.com/damienklinnert 25 | [2]:https://github.com/stevendesu 26 | -------------------------------------------------------------------------------- /src/shared/md/2013-03-06-false-isnt-false.md: -------------------------------------------------------------------------------- 1 | ``` 2 | true == 'true' // true 3 | false == 'false'; // false 4 | ``` 5 | 6 | This is expected behaviour as == doesn't do value equality, 7 | but rather it does numeric value [equality][1], thus 'false' is truthy, thus equals 1 8 | 9 | 10 | — [@grnadav][2] 11 | 12 | [1]:http://es5.github.com/#x11.9.1 13 | [2]:https://twitter.com/grnadav 14 | -------------------------------------------------------------------------------- /src/shared/md/2013-03-25-null-to-bool.md: -------------------------------------------------------------------------------- 1 | ``` 2 | null == false // false 3 | ``` 4 | Okay, we know this. Null doesn't convert to boolean. 5 | 6 | Now try this... 7 | ``` 8 | !null // true 9 | ``` 10 | 11 | Well, this is awkward. 12 | 13 | — [@noway421][1] 14 | 15 | The issue here is that Null **can** be converted to a boolean, it just 16 | isn't **implicitly** converted: 17 | ``` 18 | Boolean(null) // false 19 | ``` 20 | 21 | See [The Abstract Equality Comparison Algorithm](http://es5.github.io/#x11.9.3) 22 | Null is only implicitly converted if compared to `undefined` 23 | 24 | — [@stevendesu][2] 25 | 26 | [1]:https://twitter.com/noway421 27 | [2]:https://github.com/stevendesu 28 | -------------------------------------------------------------------------------- /src/shared/md/2013-03-27-automatic-semicolon-insertion.md: -------------------------------------------------------------------------------- 1 | This is another case of an accidental global: 2 | 3 | ``` 4 | var a = 1 5 | b = 1; 6 | 7 | (function(){ 8 | var a = 2 9 | b = 2; 10 | }()) 11 | 12 | console.log(a); // prints 1 13 | console.log(b); // prints 2 14 | ``` 15 | 16 | While debugging, one might be looking only at the “b” statements, but the 17 | problem is the missing comma after “a”. Since JavaScript has “automatic 18 | semicolon insertion” for some statements like “var”, a semicolon gets inserted 19 | after “a = 2”, and variable “b” gets declared as a global! 20 | 21 | — [@jfparadis](http://twitter.com/jfparadis)! 22 | -------------------------------------------------------------------------------- /src/shared/md/2013-04-18-true-story-bro.md: -------------------------------------------------------------------------------- 1 | True story bro! 2 | 3 | 4 | 'true' == true // returns false 5 | 6 | 7 | — [ProfessorWeb][1] 8 | 9 | The issue here is that strings are only implicitly converted to numbers 10 | when using the equality operator. 11 | 12 | See [The Abstract Equality Comparison Algorithm](http://es5.github.io/#x11.9.3) 13 | 14 | >4. If Type(x) is Number and Type(y) is String, return the result of the comparison x == ToNumber(y). 15 | >5. If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y. 16 | >8. If Type(x) is either String or Number and Type(y) is Object, return the result of the comparison x == ToPrimitive(y). 17 | >9. If Type(x) is Object and Type(y) is either String or Number, return the result of the comparison ToPrimitive(x) == y. 18 | 19 | Failing to match any of these criteria, the algorithm returns `false` 20 | 21 | — [@stevendesu][2] 22 | 23 | [1]:https://github.com/ProfessorWeb 24 | [2]:https://github.com/stevendesu 25 | -------------------------------------------------------------------------------- /src/shared/md/2013-04-28-isfinite-null-is-true.md: -------------------------------------------------------------------------------- 1 | `isFinite` function of JavaScript tests whether a number is finite. 2 | 3 | ``` 4 | isFinite(42); // true 5 | isFinite(1/0); // false 6 | isFinite(0/0); // NaN is not finite -> false 7 | isFinite('42'); // true 8 | isFinite('hi'); // false 9 | ``` 10 | 11 | These are normal results. 12 | 13 | ``` 14 | isFinite(); // false 15 | isFinite(undefined); // false 16 | ``` 17 | 18 | Undefined values are not finite. These are normal results too. 19 | 20 | ``` 21 | isFinite(null); // true 22 | ``` 23 | 24 | Wait, what? Is null a number? [It is converted into 0](http://ecma-international.org/ecma-262/5.1/#sec-9.3)? Why? 25 | 26 | Since `null != 0` and `null == undefined`, (even thought `null !== undefined`) I expected null will behave something like undefined! 27 | 28 | — [@123jimin][1] 29 | 30 | [1]:https://github.com/123jimin 31 | -------------------------------------------------------------------------------- /src/shared/md/2013-06-20-negative-indexes.md: -------------------------------------------------------------------------------- 1 | Negative numbers mean different things to different functions on the Array prototype. 2 | 3 | ``` 4 | var nums = [1, 2, 3]; 5 | nums.splice(nums.indexOf('wtf'), 1); 6 | nums; // [1, 2] 7 | ``` 8 | 9 | — [@markdalgleish][0] 10 | 11 | 12 | Interestingly, negative numbers put inside Array.Splice splice the item that is that amount from the end of the array. 13 | 14 | e.g. 15 | 16 | ``` 17 | var nums = [1, 2, 3, 4, 5]; 18 | nums.splice(-1, 1); // removes the last item 19 | nums.splice(-2, 1); // removes the second last item 20 | ``` 21 | 22 | until....... 23 | 24 | you reach the start of your array - afterwards, the first item will always be the item spliced: 25 | 26 | ``` 27 | var nums = [1, 2, 3]; 28 | nums.splice(-12, 1); 29 | nums; // [2, 3] 30 | ``` 31 | 32 | — [@MichalPaszkiewicz][1] 33 | 34 | [0]:https://twitter.com/markdalgleish 35 | [1]:http://www.michalpaszkiewicz.co.uk/ 36 | -------------------------------------------------------------------------------- /src/shared/md/2013-07-04-array-constructor.md: -------------------------------------------------------------------------------- 1 | ``` 2 | Array(20).map(function(elem) { return 'a'; }); // Array of undefined x 20 3 | ``` 4 | 5 | More info [here](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.19). 6 | Thanks [Paul Irish](https://twitter.com/paul_irish) for the explanation. 7 | 8 | 9 | — [@philogb][1] 10 | 11 | [1]:https://twitter.com/philogb 12 | -------------------------------------------------------------------------------- /src/shared/md/2013-07-18-array-ruse.md: -------------------------------------------------------------------------------- 1 | ``` javascript 2 | [,,,].join() // ==> ",," 3 | ``` 4 | 5 | wtf? 6 | 7 | — [@eliranmal][1] 8 | 9 | 10 | 11 | Turns out that the trailing comma is removed (trailing commas are allowed in 12 | javascript, but not JSON). Once removed, there are only three "elements" in the 13 | array, and both are undefined. When `join` is called, by default it uses a comma, 14 | yielding ",,". I think this is what happens. 15 | 16 | — [@DDTrejo][2] 17 | 18 | 19 | JSON has nothing to do with this issue. Although a trailing comma is really 20 | allowed by Javascript and that's the case. So `[1,2,3,]` equals to `[1,2,3]`. 21 | So literally `[,,,]` is something like `[undefined, undefined, undefined,]`. 22 | You can add `undefined` to the end explicitly to get an array with 4 elements: 23 | 24 | ``` javascript 25 | [,,,undefined].join() // ==> ',,,' 26 | ``` 27 | 28 | — [@ixti][3] 29 | 30 | 31 | Each beginning or ending comma is Elision (except comma after AssignmentExpression). Each Elision are evaluated as one array field. 32 | http://www.ecma-international.org/ecma-262/5.1/#sec-11.1.4 33 | 34 | — [@tomi77] 35 | 36 | 37 | [1]:https://twitter.com/eliranmal] 38 | [2]:https://twitter.com/ddtrejo 39 | [3]:http://ixti.net 40 | -------------------------------------------------------------------------------- /src/shared/md/2013-08-07-Math.max()-behaviour.md: -------------------------------------------------------------------------------- 1 | `Math.max()` has an interesting behaviour, handling different **JavaScript data 2 | types** in different ways. 3 | 4 | ``` 5 | Math.max(3, 0); // 3 6 | Math.max(3, {}); // NaN 7 | Math.max(3, []); // 3 8 | Math.max(3, true); // 3 9 | Math.max(3, 'foo'); // NaN 10 | Math.max(-1, null); // 0 11 | Math.max(-1, undefined); // NaN 12 | ``` 13 | 14 | Now, let's focus on **Booleans**: 15 | 16 | ``` 17 | Math.max(1, true); // 1 18 | Math.max(0, true); // 1 19 | Math.max(1, false); // 1 20 | Math.max(-1, true); // 1 21 | Math.max(-1, false); // 0 22 | ``` 23 | 24 | And now, on **Arrays**: 25 | 26 | ``` 27 | Math.max(-1, []); // 0 28 | Math.max(-1, [1]); // 1 29 | Math.max(-1, [1, 4]); // NaN 30 | ``` 31 | 32 | So next time, watch out for what you pass into `Math.max()`. 33 | 34 | — [@gnclmorais](http://gnclmorais.com/gnclmorais) 35 | 36 | 37 | `Math.max()` typecasts all values to Numbers (`Number(x)`), e.g.: 38 | 39 | ``` javascript 40 | Math.max(false, -1); // 0 41 | Math.max(5, "10"); // 10 42 | ``` 43 | 44 | — [@ixti](http://ixti.net) 45 | -------------------------------------------------------------------------------- /src/shared/md/2013-09-30-Array-Constructor2-is-Very-Undefined.md: -------------------------------------------------------------------------------- 1 | Have you ever thought that `Array(3)` will return you an array of 3 `undefined`'s, 2 | the same as `[undefined,undefined,undefined]`? 3 | 4 | So try this: 5 | ``` 6 | Array(3).forEach(function(elem) { console.log(elem); }); 7 | ``` 8 | And you will get no result at all, however 9 | ``` 10 | [undefined,undefined,undefined].forEach(function(elem) { console.log(elem); }); 11 | ``` 12 | will give you 3 nice log entries. 13 | 14 | Are the first example's `undefined` less defined than the second example's `undefined`s? 15 | 16 | Not really. According to [forEach spec](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18): 17 | "`callbackfn` is called only for elements of the array which actually *exist*", 18 | and [constructor spec](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.2.2) 19 | says nothing about putting in any elements (even `undefined`). 20 | 21 | — [@tomalec][1] 22 | 23 | [1]:https://github.com/tomalec 24 | -------------------------------------------------------------------------------- /src/shared/md/2013-10-02-implicit-getElementById.md: -------------------------------------------------------------------------------- 1 | document.getElementById can be omitted in all major browsers, including IE6+. 2 | This is non-standard, but all of them save the elements ids as globals. 3 | 4 | ``` 5 |
    6 | 10 | ``` 11 | 12 | 13 | Or do they? Let's search myId in the window object. 14 | 15 | ``` 16 | // Way 1 17 | alert('myId' in window); // --> true (right...) 18 | // Way 2 19 | var present = false; 20 | for(var i in window){ 21 | if(i == 'myId'){ 22 | present = true; 23 | } 24 | } 25 | alert(present); // --> false (wat!) 26 | ``` 27 | 28 | Looks like all browsers create Shroedinger's globals, that are here and not here at the same time... 29 | 30 | What happens to globals when an element with the same id is created? 31 | 32 | ``` 33 | 36 | 37 |
    38 | 39 | 43 | ``` 44 | 45 | So implicit getElementById's can't overload global vars, be they native or custom. 46 | What about the other way? Well, it depends on how the global var is set. 47 | 48 | Let's try with "window." 49 | 50 | ``` 51 |
    52 | 53 | 59 | ``` 60 | 61 | OK. 62 | 63 | Let's try without any prefix. 64 | 65 | ``` 66 |
    67 | 68 | 75 | ``` 76 | 77 | Weird. 78 | 79 | And what happens if the global var is declared with "var" ? 80 | 81 | ``` 82 |
    83 | 84 | 90 | ``` 91 | 92 | WAT. 93 | 94 | — [@MaximeEuziere][1] 95 | 96 | [1]:https://twitter.com/MaximeEuziere 97 | -------------------------------------------------------------------------------- /src/shared/md/2013-10-07-Local-storage-limitations.md: -------------------------------------------------------------------------------- 1 | The **local storage** functionality in browsers is a bit limited and this can 2 | lead to some rather surprising behaviour. 3 | 4 | ``` 5 | localStorage[0] = false; 6 | 7 | if (localStorage[0]) { 8 | console.log('wtf'); // runs?! 9 | } 10 | ``` 11 | 12 | When checking the value stored in `localStorage`, it appears that the boolean 13 | was silently converted to the string `"false"`, which is truthy. 14 | 15 | Turns out that this is one of those cases where it pays off to carefully read 16 | the [specification](https://html.spec.whatwg.org/multipage/webstorage.html#storage), which states 17 | that local storage only accepts string values! 18 | 19 | If you want to store an object or other type of value, you can serialize the 20 | data with `JSON.stringify` and load it again with `JSON.parse`. 21 | 22 | — [@Overv](http://twitter.com/Overv) of 23 | -------------------------------------------------------------------------------- /src/shared/md/2013-12-15-charAt-is-not-the-same-as-[].md: -------------------------------------------------------------------------------- 1 | In case someone tells you it doesn't matter how you access characters in strings, they're wrong: 2 | 3 | 4 | 'hello'[1] // 'e' 5 | 'hello'.charAt(1) // 'e' 6 | 7 | 'hello'[-1] // undefined 8 | 'hello'.charAt(-1) // '' 9 | 10 | 11 | What better "character" than the empty string to say "no such index"? 12 | 13 | — [@rtoal](https://twitter.com/rtoal) 14 | -------------------------------------------------------------------------------- /src/shared/md/2013-12-19-The-Hungry-Variable.md: -------------------------------------------------------------------------------- 1 | Consider this JS: 2 | ``` 3 | x = /[/ + "javascript"[0] + '///' 4 | ``` 5 | What do you expect the value of `x` to be? 6 | 7 | Those well-versed in Javascript's concatenation may either reject the statement 8 | or perhaps say: 9 | 10 | ``` 11 | "/[/j///" 12 | ``` 13 | 14 | Chromium's console, however says: 15 | ``` 16 | x = /[/ + "javascript"[0] + '///' 17 | /[/ + "javascript"[0] + '/ 18 | ``` 19 | 20 | ### The Hungry Variable 21 | Those who don't immediately see through this may notice a few things. 22 | 23 | * Like `/(/`, `/[/` throws an error. 24 | * `"javascript"[0]` returns `"j"` as expected. 25 | * `'///'` returns `"///"` as expected. 26 | 27 | What should be noted is that the errors for `/(/` and `/[/` are subtly 28 | different. In Chromium console: 29 | 30 | ``` 31 | /(/ 32 | //SyntaxError: Invalid regular expression: /(/: Unterminated group 33 | 34 | /[/ 35 | //SyntaxError: Invalid regular expression: missing / 36 | ``` 37 | 38 | It seems that Javascript cannot see the second `/` for some reason. This is 39 | because choice groups (`/[any letter]/`) don't require escaping of the forward- 40 | slash, so `/[/]/` is perfectly acceptable and the same as `/\//`. 41 | 42 | If the pre was syntax highlighted, you perhaps would notice that the highlighter 43 | was just as confused as you in that regard, only Github's highlighter seems to 44 | highlight this correctly. 45 | 46 | Thus, the regex extends across the apparent string addition statement and 47 | terminates at the "]" (you can't nest choice blocks). 48 | 49 | The regex then extends to the slash after the typewriter single quote, and so 50 | the `//'` is simply a comment. 51 | 52 | 53 | If you want the pre to do as expected, add a single forward slash before the 54 | first "[": 55 | 56 | ``` 57 | x = /\[/ + "javascript"[0] + '///' 58 | "/\[/j///" 59 | 60 | //for comparison 61 | x = /[/ + "javascript"[0] + '///' 62 | /[/ + "javascript"[0] + '/ 63 | ``` 64 | 65 | It is an interesting example of a statement that can completely change meaning 66 | with the insertion of one character without creating any errors. 67 | 68 | — [@zemnmez][1] 69 | 70 | [1]:http://twitter.com/zemnmez 71 | -------------------------------------------------------------------------------- /src/shared/md/2014-01-11-multiplying-arrays-and-objects.md: -------------------------------------------------------------------------------- 1 | 2 | [4] * [4] // 16 3 | [] * [] // 0 4 | [] * {} // NaN 5 | [4, 4] * [4, 4] // NaN 6 | ({} * {}) // NaN 7 | 8 | — [@Tobiaqs][1] 9 | 10 | [1]:https://github.com/Tobiaqs 11 | -------------------------------------------------------------------------------- /src/shared/md/2014-01-29-regular-expression-and-slash.md: -------------------------------------------------------------------------------- 1 | When I use regular expressions and I want to validate a range of letters, I can 2 | do it using `a-z` or `A-Z`. Even when I use `A-z` it works fine too. The problem 3 | comes doing some test: 4 | 5 | ``` 6 | /[A-Z]/.test("A"); // true 7 | /[A-Z]/.test("b"); // false 8 | /[A-Z]/.test("Z"); // true 9 | /[A-Z]/.test("z"); // false 10 | /[a-z]/.test("a"); // true 11 | /[a-z]/.test("A"); // false 12 | /[a-z]/.test("z"); // true 13 | /[a-z]/.test("Z"); // false 14 | ``` 15 | 16 | The weird thing comes when I do this test: 17 | 18 | ``` 19 | /[A-z]/.test("A"); // true 20 | /[A-z]/.test("a"); // true 21 | /[A-z]/.test("Z"); // true 22 | /[A-z]/.test("z"); // true 23 | /[A-z]/.test("m"); // true 24 | /[A-z]/.test("D"); // true 25 | /[A-z]/.test("\\"); // true WTF? 26 | ``` 27 | 28 | It's supposed to accept only letters from `A to Z` and `a to z`. 29 | Can someone explain this? 30 | 31 | — [@byoigres][1] 32 | 33 | 34 | I had a look into this with the following code: 35 | ```javascript 36 | var re = /[A-z]/g,s=(function(){ 37 | var f = String.fromCharCode; 38 | for(var i=0;i<6000;i++) f=f.bind(0, i); 39 | return f(); 40 | })(),q,z=[];while((q=re.exec(s)) != null) z.push(q[0]);z 41 | ``` 42 | 43 | It returns 44 | 45 | ```javascript 46 | ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", 47 | "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", "\", "]", "^", 48 | "_", "`", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", 49 | "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"] 50 | ``` 51 | 52 | A-z literally means 'any character between 'A' and 53 | 'z' in unicode code-point order, or at least charCode order. This allows (I 54 | think non-standard) statements like `/[ -y]/g`: 55 | 56 | ```javascript 57 | var re = /[ -y]/g,s=(function(){ 58 | var f = String.fromCharCode; 59 | for(var i=0;i<6000;i++) f=f.bind(0, i); 60 | return f(); 61 | })(),q,z=[];while((q=re.exec(s)) != null) z.push(q[0]);z 62 | ``` 63 | 64 | Which returns 65 | ```javascript 66 | [" ", "!", """, "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", 67 | "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", 68 | ">", "?", "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", 69 | "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", 70 | "\", "]", "^", "_", "`", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", 71 | "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y"]` 72 | ``` 73 | 74 | This probably has some potential security implications because if you're using 75 | [A-z] to sanitise something, you'll accept [\]^_` 76 | 77 | A very interesting find! 78 | 79 | — [zemnmez][2] 80 | 81 | [1]:https://twitter.com/byoigres 82 | [2]:https://twitter.com/zemnmez 83 | -------------------------------------------------------------------------------- /src/shared/md/2014-02-04-Date.Date-vs-Year.md: -------------------------------------------------------------------------------- 1 | `Date.getDate()` returns the day of the Month, whereas `Date.getMonth()` returns the previous month (somehow *zero-indexed*). 2 | 3 | ``` 4 | var date = new Date('Tue Apr 01 2014') 5 | date // Tue Apr 01 2014 00:00:00 GMT+0200 6 | date.getDate() // 1 7 | date.getMonth() // 3 8 | ``` 9 | 10 | 11 | — [@depoulo](https://github.com/depoulo) 12 | -------------------------------------------------------------------------------- /src/shared/md/2014-02-20-math-pow.md: -------------------------------------------------------------------------------- 1 | [The spec of ECMAScript](http://ecma-international.org/ecma-262/5.1/#sec-15.8.2.13) specifies some default values of `Math.pow`. 2 | 3 | ``` 4 | console.log(Math.pow(NaN, 42) === NaN) 5 | ``` 6 | 7 | [Oops, sorry.](https://wtfjs.com/wtfs/2010-02-12-not-a-number-is-not-a-not-a-number) 8 | 9 | ``` 10 | console.log(Math.pow(NaN, 42)); // NaN 11 | ``` 12 | 13 | As you can see, if the first argument is `NaN`, `Math.pow` returns `NaN`, which is quite normal. 14 | However, there's an exception: when the second argument is `0` (`+0` or `-0`). 15 | 16 | ``` 17 | console.log(Math.pow(NaN, 0)); // 1 18 | ``` 19 | 20 | When the second argument is `0`, then `Math.pow` should return `1`, no matter what the first argument is. 21 | This can be considered as a normal behavior, unless... 22 | 23 | ``` 24 | console.log(Math.pow(Infinity, 0), Math.pow(0, 0)); // Still 1? 25 | ``` 26 | 27 | Basically the spec asserts values of some [indeterminate forms](http://en.wikipedia.org/wiki/Indeterminate_forms). 28 | Sure, some can argue that lim(x->infinity) x^0 is zero (infinity is not a real number, anyway) and 0^0 is [usually considered as one](http://en.wikipedia.org/wiki/Exponentiation#Zero_to_the_power_of_zero), but according to the same spec... 29 | 30 | ``` 31 | console.log(Math.pow(1, Infinity)); // NaN 32 | ``` 33 | 34 | So 1^infinity is `NaN` while infinity^0 is `1`. Great. 35 | 36 | — [@123jimin][1] 37 | 38 | [1]:https://github.com/123jimin 39 | -------------------------------------------------------------------------------- /src/shared/md/2014-02-22-wtf_document.all.md: -------------------------------------------------------------------------------- 1 | In Chrome 2 | ``` 3 | document.all // HTMLAllCollection[843] 4 | document.all[0] // ... 5 | 6 | typeof document.all // "undefined"! WTF! 7 | !{} // false. It's OK 8 | !document.all // true! WTF! 9 | ``` -------------------------------------------------------------------------------- /src/shared/md/2014-02-25-array-indexof.md: -------------------------------------------------------------------------------- 1 | **Not empty array doesn't contain its element:** 2 | ``` 3 | var a = [,]; 4 | a.length; //1, some element exists 5 | a.indexOf(a[0]); //-1 6 | // We have the array with non-zero length, which doesn't contain its first element. WTF? 7 | ``` 8 | 9 | **The problem is in this:** 10 | 11 | `a[0]` is `undefined`. `undefined` is the javascript primitive type. But when we init an array 12 | the ES5 spec tells us the following about [array initialisers](http://es5.github.io/#x11.1.4): 13 | 14 | ``` 15 | Elided array elements are not defined. 16 | ... 17 | The missing array element contributes to the length of the Array and increases the index of subsequent elements. 18 | ``` 19 | 20 | Elements are not `undefined`, they are `not initialized`. 21 | When we invoke `indexOf` on an array this is one of the steps that happens: 22 | ``` 23 | Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument ToString(k). 24 | ``` 25 | 26 | In that, `k` is a number corresponding to an array index and `O` is the array itself. 27 | Since elided elements were not defined the array does not have a property for the corresponding index. 28 | 29 | *Ok. But why do we get `undefined` when get the first array element?* 30 | 31 | Javascript is a prototype-based scripting language and Array is an object, too. 32 | So if there is no property `0` in an array, the internal engine goes deeper to the prototype 33 | and there is no such property in the prototype chain - return undefined. 34 | When we try to access the value `0` property of array the internal method `[[GetProperty]]` gets called. 35 | If there is no such property `[[GetProperty]]` we try to get it from the prototype chain 36 | and `undefined` is returned if it stops on `null` (end of prototype chains). 37 | 38 | 39 | — [frontenddeveloping](https://github.com/frontenddeveloping) 40 | -------------------------------------------------------------------------------- /src/shared/md/2014-03-13-String-Integers-Comparison.md: -------------------------------------------------------------------------------- 1 | 2 | ```javascript 3 | "9" > "19" // true 4 | "01" == "1" // false 5 | ``` 6 | 7 | If you have accidently forgotten to parse integers, or you have a blind sort function for attributes, you might face this problem. 8 | 9 | In JavaScript's string comparison, it takes the first character's code. So, what is really happening equivalent to: 10 | ```javascript 11 | "9".charCodeAt(0) > "19".charCodeAt(0) // 57 > 49 --> true 12 | "01".charCodeAt(0) == "1".charCodeAt(0) // 48 == 49 --> false 13 | ``` 14 | 15 | — [@rashad612](https://github.com/rashad612) 16 | -------------------------------------------------------------------------------- /src/shared/md/2014-03-13-regex-test-true-false.md: -------------------------------------------------------------------------------- 1 | ``` 2 | var re = new RegExp('Foo B', 'gi'); 3 | alert(re.test('Foo Bar')); // true 4 | alert(re.test('Foo Bar')); // false 5 | ``` -------------------------------------------------------------------------------- /src/shared/md/2014-05-05-this-length.md: -------------------------------------------------------------------------------- 1 | ``` 2 | var foo = ["lval0", "lval1", "lval2", "lval3"]; 3 | foo[this.length] = "lval4"; 4 | foo[0]; //result same as foo.splice(0,1,"lval4"); =>lval4 5 | ``` -------------------------------------------------------------------------------- /src/shared/md/2014-10-07-true-equals-false.md: -------------------------------------------------------------------------------- 1 | So, `!!` converts a value to a boolean and ensures a boolean type. 2 | 3 | ``` 4 | !!false // --> false 5 | !!true // --> true 6 | ``` 7 | 8 | Ok, that makes sense. What about strings? 9 | 10 | ``` 11 | !!"false" // --> true 12 | !!"true" // --> true 13 | ``` 14 | 15 | Weird. But wait, does this mean... 16 | 17 | ``` 18 | !!"false" == !!"true" // --> true 19 | ``` 20 | 21 | I bet if we also compare the type at least... 22 | 23 | 24 | ``` 25 | !!"false" === !!"true" // --> true 26 | ``` 27 | 28 | Then again... 29 | 30 | ``` 31 | !!false == !!true // --> false 32 | ``` 33 | 34 | ..., but... 35 | 36 | ``` 37 | !!"false" == !!true // --> true 38 | !!"false" === !!true // --> true 39 | ``` 40 | -------------------------------------------------------------------------------- /src/shared/md/2014-11-22-object-as-object-key.md: -------------------------------------------------------------------------------- 1 | What happens when we set empty objects as keys: 2 | 3 | ``` 4 | var result = (function() { 5 | var foo = new Object(); 6 | var bar = new Object(); 7 | var map = new Object(); 8 | 9 | map[foo] = 'foo'; 10 | map[bar] = 'bar'; 11 | 12 | return map[foo]; 13 | })(); 14 | 15 | console.log(result); // "bar" 16 | ``` 17 | 18 | Explained: 19 | 20 | ``` 21 | var result = (function() { 22 | var foo = new Object(); // {} 23 | var bar = new Object(); // {} 24 | var map = new Object(); // {} 25 | 26 | map[foo] = "foo"; // map["[object Object] "] = "foo" 27 | map[bar] = "bar"; // map["[object Object] "] = "bar" 28 | 29 | // Behind the scenes the key the toString method is called for object keys, so: 30 | // {}.toString() = "[object Object]" 31 | 32 | console.log({}.toString()); // "[object Object]" 33 | 34 | // Notice that only one key is returned because of the same key name: 35 | console.log(Object.keys(map)); // ["[object Object]"] 36 | 37 | // map["[object Object]"] 38 | return map[foo]; 39 | })(); 40 | 41 | console.log(result); // "bar" 42 | ``` 43 | 44 | Thanks [Miguel Mota](http://www.miguelmota.com/). 45 | -------------------------------------------------------------------------------- /src/shared/md/2015-02-02-Boolean-constructor.md: -------------------------------------------------------------------------------- 1 | Why would you _ever_ use this function, or constructor, or ...? 2 | 3 | ``` 4 | > Boolean(false) 5 | false 6 | > new Boolean(false) 7 | {} 8 | > {} == true 9 | false 10 | > Boolean({}) 11 | true 12 | > Boolean(new Boolean(false)) 13 | true 14 | > new Boolean(Boolean(false)) 15 | {} 16 | > if (new Boolean(false)) console.log('Indeed') 17 | Indeed 18 | ``` 19 | 20 | You couldn't _make_ this stuff up. 21 | 22 | — [@rtoal](https://twitter.com/rtoal) 23 | -------------------------------------------------------------------------------- /src/shared/md/2015-02-05-good-old-octal-decimal-wtf.md: -------------------------------------------------------------------------------- 1 | 0-prefixed numbers are handled are automatically treated as octals. Or not. 2 | ``` 3 | 038 - 037 // 7 !? 4 | 037 // 31 thx to silent octal-to-decimal conversion 5 | 038 // 38 .. Silently switch to octal, silently fails to, and silently fallback to decimal 6 | ``` 7 | 8 | Instead of throwing a SyntaxError (8 & 9 should be invalid characters), 9 | octal mode silently switches to decimal if possible. 10 | 11 | 12 | — [@nlesconnec](https://twitter.com/nlesconnec) 13 | -------------------------------------------------------------------------------- /src/shared/md/2015-03-23-adding-arrays.md: -------------------------------------------------------------------------------- 1 | ``` 2 | [1, 2, 3] + [4, 5, 6] // "1,2,34,5,6" 3 | ``` 4 | 5 | Being able to concatenate two comma-seperated strings without a comma in the middle is such a common use case. I'm glad the JS develpoers thought to optimise for the most common use case. 6 | 7 | — [Gaelan][me] 8 | 9 | [me]: https://github.com/Gaelan 10 | -------------------------------------------------------------------------------- /src/shared/md/2015-04-08-array-sort.md: -------------------------------------------------------------------------------- 1 | ```js 2 | [1,2,3,15,30,7,5,45,60].sort() 3 | // = [1,15,2,3,30,45,5,60,7] 4 | ``` 5 | 6 | See [String Integers Comparison](https://wtfjs.com/wtfs/2014-03-13-String-Integers-Comparison) for the explanation. 7 | 8 | —[@stuartpb][] 9 | 10 | [@stuartpb]: https://twitter.com/stuartpb 11 | -------------------------------------------------------------------------------- /src/shared/md/2015-04-16-moving-numbers.md: -------------------------------------------------------------------------------- 1 | Javascript numbers are facetious, sometimes they [play hide and seek](https://wtfjs.com/wtfs/2010-07-22-magic-increasing-number), sometimes they just won't obey: 2 | 3 | 4 | 1 << 32 // 1 5 | 6 | -------------------------------------------------------------------------------- /src/shared/md/2015-04-23-screwy-negative-array-index.md: -------------------------------------------------------------------------------- 1 | ``` 2 | var arr = [1, 2, 3, 4, 5, 6, 7, 8]; 3 | arr[-1] = "yo wazzzup"; 4 | console.log(arr.length); // > 8 5 | console.log(arr[arr.indexOf(99)]); // log's > "yo wazzzup" 6 | ``` 7 | -------------------------------------------------------------------------------- /src/shared/md/2016-03-09-Two-Special-Numbers.md: -------------------------------------------------------------------------------- 1 | There seems to be a number that fulfills all of these conditions: 2 | 3 | ``` 4 | i * i = 0 5 | i + 1 = 1 6 | i - 1 = -1 7 | i / i = 1 8 | ``` 9 | 10 | Turns out that this magical number is not even an integer: 11 | 12 | ``` 13 | i = Number.MIN_VALUE 14 | ``` 15 | 16 | It's the smallest possible fraction JavaScript can produce, and is treated as zero for the most part. 17 | 18 | Conversely, the largest possible fraction claims to be greater than one, but reduces to zero: 19 | 20 | ``` 21 | i = Number.MAX_VALUE 22 | 23 | i > 1 // true 24 | i|0 // 0 25 | ``` 26 | 27 | Furthermore, both the largest possible fraction and integer refuse to wrap around: 28 | 29 | ``` 30 | i = Number.MAX_VALUE 31 | j = 0xffffffffffffffff 32 | 33 | i === (i + 1) // true 34 | j === (j + 1) // true 35 | ``` 36 | 37 | – [@ionpot](https://github.com/ionpot) 38 | -------------------------------------------------------------------------------- /src/shared/md/2016-03-10-Object-And-Array-Prototype-Length.md: -------------------------------------------------------------------------------- 1 | ```javascript 2 | Object.create(Array).length === 1 //true 3 | ``` 4 | And 5 | ```javascript 6 | Object.keys(Object.create(Array)).length === 0 //true 7 | ``` 8 | [@juliomatcom](https://github.com/juliomatcom) 9 | -------------------------------------------------------------------------------- /src/shared/md/2016-03-19-weird-instanceof.md: -------------------------------------------------------------------------------- 1 | ``` 2 | function Test(){} 3 | Test.prototype = null; 4 | var a = new Test(); 5 | a instanceof Test; //Uncaught TypeError: Function has non-object prototype 'null' in instanceof check(…) 6 | a instanceof Object; // true WTF? 7 | ``` 8 | 9 | [ref](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof) 10 | "The instanceof operator tests whether an object has in its prototype chain the prototype property of a constructor." 11 | 12 | -------------------------------------------------------------------------------- /src/shared/md/2018-19-01-weird-number-addition.md: -------------------------------------------------------------------------------- 1 | ``` 2 | console.log(.2+.1); // 0.30000000000000004 3 | console.log(999999999999999999); // 1000000000000000000 4 | console.log(true+true === 2); // true 5 | console.log(true-true === 0); // true // So true must be 1 right ? 6 | console.log(true === 1); // false 7 | console.log('5' + 3); // 53 8 | console.log('5' - 3); // 2 9 | ``` 10 | [@Darth-koder007](https://github.com/@Darth-koder007) 11 | 12 | -------------------------------------------------------------------------------- /src/shared/md/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@wtfjs/md", 3 | "version": "2.0.1", 4 | "lockfileVersion": 1 5 | } 6 | -------------------------------------------------------------------------------- /src/shared/md/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@wtfjs/md", 3 | "version": "2.0.1" 4 | } 5 | -------------------------------------------------------------------------------- /src/shared/readme.md: -------------------------------------------------------------------------------- 1 | # Magical `src/shared` 2 | 3 | The contents of this folder get copied into every Lambda function `node_modules/@architect/shared` when: 4 | 5 | - running `npm start` 6 | - running `npm test` 7 | - running `npm run deploy` 8 | 9 | This means modules in this folder can be required from any function in this `@app` 10 | 11 | For example: 12 | 13 | ```javascript 14 | var layout = require('@architect/shared/layout') 15 | ``` 16 | 17 | Resolves locally to `src/shared/layout.js`. 18 | 19 | ## Organizing 20 | 21 | Organize shared code however it makes sense for your project. 22 | 23 | Here is an example starting structure: 24 | 25 | - src/shared/views 26 | - src/shared/middleware 27 | - src/shared/helpers 28 | - src/shared/components 29 | 30 | Overwrite the contents of this file to describe the structure you've chosen. 31 | 32 | ## Use Caution! 33 | 34 | Everything in src/shared will be copied into all Lambdas which could quickly bloat an application. Remember you want to keep your Lambda functions sub 5 MB for optimal coldstart performance. 35 | --------------------------------------------------------------------------------