SlideShare una empresa de Scribd logo
1 de 61
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
JavaScript Puzzlers: Puzzles to Make You Think (and write fewer bugs)
Charles Bihis | Computer Scientist
1
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
Who am I?
 Charles Bihis
 Computer Scientist
 Adobe Identity Team
 Blog: blogs.adobe.com/charles
 Twitter: @charlesbihis
 GitHub: github.com/charlesbihis
2
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
What can I expect?
 What are we going to talk about?
 Puzzlers!
 Maximus the Confused!
 Block Party!
 Let’s Print Some ZIP-Codes!
 Loopty Loop!
 Why Are We Bankrupt?!
 A Case of Mistaken Identity
 Will deal with only pure JavaScript
 (i.e. no libraries!)
3
 What are we NOT going to talk about?
 3rd- party libraries or frameworks
 e.g. jQuery, Node.js, etc.
 Bugs
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
What is a Puzzler?
A Puzzler is a very simple programming puzzle that demonstrates or exploits
weird behaviours and quirky edge-cases of a given programming language.
4
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
How does this work?
1. Code – I introduce the code.
2. Question – I pose a multiple-choice question and you guess what the
answer is…think hard!
3. Walkthrough – I walk through a reasonable explanation.
4. Answer – I tell you the real answer.
5. Moral – How can you avoid making mistakes like this in your own code.
5
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
Let’s start!
6
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
JavaScript Puzzler – Maximus the Confused!
7
var commodusRule = 'thumbsUp';
alert('Maximus the ' + (commodusRule === 'thumbsUp') ? 'Gladiator' : 'Merciful');
What does this print?
a) Maximus the Gladiator
b) Maximus the Merciful
c) Error
d) It varies
e) None of the above
 prints only "Gladiator"
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
But why?
 Order of operations dictates that the binary “+” operator takes precedence over the conditional “?”
operator.
8
*Reference: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Operator_Precedence
'Maximus the ' + (commodusRule === 'thumbsUp') ? 'Gladiator' : 'Merciful';
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
But why?
 Order of operations dictates that the binary “+” operator takes precedence over the conditional “?”
operator.
9
*Reference: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Operator_Precedence
'Maximus the true' ? 'Gladiator' : 'Merciful';
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
But why?
 Order of operations dictates that the binary “+” operator takes precedence over the conditional “?”
operator.
10
*Reference: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Operator_Precedence
'Gladiator';
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
But why?
 Order of operations dictates that the binary “+” operator takes precedence over the conditional “?”
operator.
 According to the MDN (Mozilla Developer Network), the binary “+” operator has a precedence of 6
while the conditional “?” operator has a precedence of 15.
 Note: This is below MOST commonly used operators (i.e. “*”, “/”, “%”, “<“, “>>” “!=”, “===“, etc).
11
*Reference: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Operator_Precedence
'Gladiator';
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
JavaScript Puzzler – Maximus the Confused…FIXED!
12
var commodusRule = 'thumbsUp';
alert('Maximus the ' + (commodusRule === 'thumbsUp') ? 'Gladiator' : 'Merciful');
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
JavaScript Puzzler – Maximus the Confused…FIXED!
13
var commodusRule = 'thumbsUp';
alert('Maximus the ' + (commodusRule === 'thumbsUp' ? 'Gladiator' : 'Merciful'));
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
Moral
 Be aware of order-of-operations!
 Be explicit and place parenthesis accordingly to ensure correct
and predictable order of execution.
14
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
JavaScript Puzzler – Block Party!
// global var
var name = "World!";
(function() {
// check if "name" defined
if (typeof name === "undefined") {
// local "shadow" var
var name = "Mr. Bond.";
alert("Goodbye, " + name);
} else {
alert("Hello, " + name);
}
})();
15
What does this print?
a) “Hello, World!”
b) “Goodbye, Mr. Bond.”
c) “Hello, ”
d) “Hello, undefined”
e) Error
f) It varies
g) None of the above
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
But why?
1. No block scope!
2. “Hoisting”
16
for (var i = 0; i < MAX; i++)
{
// do something
}
alert(i); // Note: "i" exists here!
alert(i);
for (var i = 0; i < MAX; i++)
{
// do something
}
// Note: "i" exists here too!
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
But why?
1. No block scope!
2. “Hoisting”
17
for (var i = 0; i < MAX; i++)
{
// do something
}
alert(i); // Note: "i" exists here!
var i;
alert(i); // Note: "i" exists here too!
for (i = 0; i < MAX; i++)
{
// do something
}
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
JavaScript Puzzler – Block Party…FIXED!
// global var
var name = "World!";
(function() {
// check if "name" defined
if (typeof name === "undefined") {
// local "shadow" var
var name = "Mr. Bond.";
alert("Goodbye, " + name);
} else {
alert("Hello, " + name);
}
})();
18
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
JavaScript Puzzler – Block Party…FIXED!
// global var
var name = "World!";
(function() {
var name;
// check if "name" defined
if (typeof name === "undefined") {
// local "shadow" var
name = "Mr. Bond.";
alert("Goodbye, " + name);
} else {
alert("Hello, " + name);
}
})();
19
// declaration hoisted here
// assignment remains here
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
JavaScript Puzzler – Block Party…FIXED!
// global var
var name = "World!";
(function() {
var name = "Mr. Bond.";
// check if "name" defined
if (typeof name === "undefined") {
alert("Goodbye, " + name);
} else {
alert("Hello, " + name);
}
})();
20
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
Moral
 There is no block-level scoping in JavaScript
 Declare ALL of your variables at the top of your function
21
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
What does this print?
a) 93021
19
20341
32959
b) 93021
2392
20341
8163
32959
c) 93021
20341
32959
d) Error
e) It varies
f) None of the
above
JavaScript Puzzler – Let’s Print Some ZIP Codes!
22
// array of 5 valid zip-codes
var zipCodes = new Array("93021",
"02392",
"20341",
"08163",
"32959");
// let's do something with each zip-code
// for now, display them
for (var i = 0; i < zipCodes.length; i++) {
// sanity check
if (!isNaN(parseInt(zipCodes[i])) &&
parseInt(zipCodes[i]) > 0) {
alert(parseInt(zipCodes[i]));
}
}
Firefox 
Chrome 
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
But why?
 Syntax
 When you omit the optional “radix” parameter, the following behavior takes place:
 If the input string begins with “0x” or “0X”, radix of 16 is used (i.e. hexadecimal)
 If the input string begins with “0”, radix 8 is used (i.e. octal) OR radix 10 is used (i.e. decimal)
 If the input string begins with any other values, radix 10 is used (i.e. decimal)
 Particularly when dealing with string values with leading 0’s, Mozilla had this to say…
23
var num = parseInt(string, radix); // "radix" is optional
Exactly which radix is chosen is implementation-dependent.
For this reason ALWAYS SPECIFY A RADIX WHEN USING parseInt.
*Reference: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/parseInt
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
But why?
 Another important note about the parseInt() API…
 A closer look…
24
// behaviour in Firefox v20.0
parseInt("93021") = 93021 // displays
parseInt("02392") = (2 * 8) + (3 * 1) = 19 // displays
parseInt("20341") = 20341 // displays
parseInt("08163") = 0 // does NOT display
parseInt("32959") = 32959 // displays
*Reference: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/parseInt
If parseInt encounters a character that is not a numeral in the
specified radix, it ignores it and all succeeding characters
and returns the integer value parsed up to that point.
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
JavaScript Puzzler – Let’s Print Some ZIP Codes…FIXED!
25
// array of 5 valid zip-codes
var zipCodes = new Array("93021",
"02392",
"20341",
"08163",
"32959");
// let's do something with each zip-code
// for now, display them
for (var i = 0; i < zipCodes.length; i++) {
// sanity check
if (!isNaN(parseInt(zipCodes[i])) &&
parseInt(zipCodes[i]) > 0) {
alert(parseInt(zipCodes[i]));
}
}
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
JavaScript Puzzler – Let’s Print Some ZIP Codes…FIXED!
26
// array of 5 valid zip-codes
var zipCodes = new Array("93021",
"02392",
"20341",
"08163",
"32959");
// let's do something with each zip-code
// for now, display them
for (var i = 0; i < zipCodes.length; i++) {
// sanity check
if (!isNaN(parseInt(zipCodes[i], 10)) && // radix value added
parseInt(zipCodes[i], 10) > 0) { // here too
alert(parseInt(zipCodes[i], 10)); // and here too
}
}
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
Moral
 parseInt() takes an optional radix parameter.
 Omitting this optional parameter will cause unpredictable
behavior across browsers.
 Be explicit and ALWAYS include the radix parameter.
27
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
JavaScript Puzzler – Loopty Loop!
28
var END = 9007199254740992;
var START = END - 100;
var count = 0;
for (var i = START; i <= END; i++) {
count++;
}
alert(count);
// Math.pow(2, 53) What does this print?
a) 0
b) 100
c) 101
d) Error
e) It varies
f) None of the
above
 enters infinite loop
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
But why?
 9007199254740992 is a special number. Particularly, it is 2^53.
 Why is this special?
 First, we need to know something about how JavaScript represents numbers.
29
*Reference: http://ecma262-5.com/ELS5_HTML.htm#Section_8.5
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
But why?
 JavaScript numbers abide by the IEEE Standard for Floating-Point Arithmetic (IEEE 754).
 As such, all numbers in JavaScript are represented by double-precision 64-bit floating point
values…
 In binary…
30
*Reference: http://ecma262-5.com/ELS5_HTML.htm#Section_8.5
1.2345 = 12345 10x -4
mantissa
exponent
1 11...111 11111111111...111
63 62 53 52 0
exponent mantissasign
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
But why?
 2^53 is the largest exact integral value that can be represented in JavaScript!
 From the ECMA specification…
 What does this mean?
31
*Reference: http://ecma262-5.com/ELS5_HTML.htm#Section_8.5
Note that all the positive and negative integers whose magnitude
is no greater than 2^53 are representable in the Number type.
var numA = Math.pow(2, 53);
var numB = numA + 1;
alert(numA === numB); // true!
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
JavaScript Puzzler – Loopty Loop…FIXED!
32
var END = 9007199254740992; // Math.pow(2, 53)
var START = END - 100;
var count = 0;
for (var i = START; i <= END; i++) {
count++;
}
alert(count);
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
JavaScript Puzzler – Loopty Loop…FIXED!
33
var START = 0;
var END = 100;
var count = 0;
for (var i = START; i <= END; i++) {
count++;
}
alert(count);
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
Moral
 Be aware of your number representations and number ranges!
 There are REAL limitations imposed by your computer. When
dealing with large (or important) numbers, know them!
34
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
JavaScript Puzzler – Why Are We Bankrupt?!
35
What does this print?
a) 0
b) 0.2
c) 0.20
d) None of the above
var costOfCandy = 0.60; // 60 cents
function calculateChange(cost, paid) {
return paid - cost;
}
// pay for candy with 80 cents
alert(calculateChange(costOfCandy, 0.80));
 0.20000000000000007
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
But why?
 As we learned from the previous Puzzler, all JavaScript numbers use the IEEE 754 floating-point
arithmetic specification.
 Because of this, values are not represented exactly, but rather as a fraction.
 Some non-integer values simply CANNOT be expressed exactly in this way. They must be
approximated.
36
Example:
123.45 = 12345 * 10^-2 // exact
1 / 3 = 0.333333333333333 * 10^0 // approximation!
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
JavaScript Puzzler – Why Are We Bankrupt?!...FIXED!
37
var costOfCandy = 0.60; // 60 cents
function calculateChange(cost, paid) {
return paid - cost;
}
// pay for candy with 80 cents
alert(calculateChange(costOfCandy, 0.80));
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
JavaScript Puzzler – Why Are We Bankrupt?!...FIXED!
38
var costOfCandy = 60; // 60 cents
function calculateChange(cost, paid) {
return paid - cost;
}
// pay for candy with 80 cents
alert(calculateChange(costOfCandy, 80));
// Use only integer math when dealing with money! To do this,
// represent your money in terms of cents to begin with!
//
// e.g. use 1599 instead of 15.99 to represent $15.99
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
Moral
 Floating-point arithmetic can be inaccurate when representing fractions.
 When dealing with money, deal in terms of cents! This makes all of your calculations integer-
calculations, which are exact!
 BUT, not completely exact, though…
 Remember from our last Puzzler, it is exact only up until the largest representable integer value…
 9007199254740992 (i.e. 2^53)
 So, as long as you are dealing with less than $9 quintillion, you’re fine using integer arithmetic in
JavaScript :)
39
*Reference: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
JavaScript Puzzler – A Case of Mistaken Identity!
function showCase(value) {
switch(value) {
case "A":
alert("Case A was selected.");
break;
case "B":
alert("Case B here!");
break;
case "C":
alert("This is Case C.");
break;
default:
alert("Don't know what happened.");
break;
}
}
showCase(new String("A"));
40
What does this print?
a) Case A was selected.
b) Case B here!
c) This is Case C.
d) Don’t know what
happened.
e) Error
f) It varies
g) None of the above
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
But why?
 The switch statement in JavaScript internally uses the strict equality operator (i.e. ===) as opposed
to the non-strict equality operator (i.e. ==).
 The strict equality operator behaves exactly as the non-strict version, except that no type-
conversions are done.
 So, when the switch statement evaluates equality, it checks that the following are true…
 Their types are equal
 Their uncast values are equal
 Notice, we invoked showCase() with a new String object.
41
alert(typeof "A"); // "string"
alert(typeof new String("A")); // "object"
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
JavaScript Puzzler – A Case of Mistaken Identity…FIXED!
function showCase(value) {
switch(value) {
case "A":
alert("Case A was selected.");
break;
case "B":
alert("Case B here!");
break;
case "C":
alert("This is Case C.");
break;
default:
alert("Don't know what happened.");
break;
}
}
showCase(new String("A"));
42
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
JavaScript Puzzler – A Case of Mistaken Identity…FIXED!
function showCase(value) {
switch(value) {
case "A":
alert("Case A was selected.");
break;
case "B":
alert("Case B here!");
break;
case "C":
alert("This is Case C.");
break;
default:
alert("Don't know what happened.");
break;
}
}
showCase("A");
43
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
Moral
 Get used to using the strict equality operator when possible. It will make you more aware of type
conversions and true equalities.
 From Douglas Crockford’s book “JavaScript: The Good Parts”…
44
JavaScript has two sets of equality operators: === and !==, and their evil twins == and !=.
The good ones work the way you would expect. The evil twins do the right thing when the
operands are of the same type, but if they are of different types, they attempt to coerce the
values, the rules by which they do that are complicated and unmemorable.
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
That’s it!
Questions?
45
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
Thanks for coming!
 Charles Bihis
 Computer Scientist
 Adobe Identity Team
 Blog: blogs.adobe.com/charles
 Twitter: @charlesbihis
 GitHub: github.com/charlesbihis
46
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
JavaScript Puzzler – That’s Odd!
(function(){
var values = [7, 4, '13', Infinity, -9];
for (var i = 0; i < values.length; i++) {
if (isOdd(values[i])) {
alert(values[i]);
}
}
})();
function isOdd(num) {
return num % 2 == 1;
}
48
What does this print?
a) 7, 13
b) 7, 13, Infinity, -9
c) 7, -9
d) 7, 13, -9
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
But why?
 Let’s take a closer look…
49
7 % 2 = 1 // displays
4 % 2 = 0 // does NOT display
13 % 2 = 1 // displays
Infinity % 2 = NaN // does NOT display
-9 % 2 = -1 // does NOT display
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
But why?
 -9 % 2 = -1? Really?
 JavaScript shares the same behavior as the Java implementation of the modulus (%) operator.
That is, it must satisfy the following identity function for all integer values a and non-zero integer
values b.
 A side-implication of this behavior is that the result will have the same sign as the left operand!
50
(a / b) * b + (a % b) == a
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
JavaScript Puzzler – That’s Odd…FIXED!
(function(){
var values = [7, 4, '13', Infinity, -9];
for (var i = 0; i < values.length; i++) {
if (isOdd(values[i])) {
alert(values[i]);
}
}
})();
function isOdd(num) {
return num % 2 == 1;
}
51
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
JavaScript Puzzler – That’s Odd…FIXED!
(function(){
var values = [7, 4, '13', Infinity, -9];
for (var i = 0; i < values.length; i++) {
if (isOdd(values[i])) {
alert(values[i]);
}
}
})();
function isOdd(num) {
return num % 2 != 0;
}
52
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
Moral
 Be careful about the signs of operands when using the modulus
operator.
53
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
JavaScript Puzzler – Say What?!
54
What does this print?
a) alert("BOOM!“);
b) Hello, </script><script>alert("BOOM!");</script>
c) BOOM!
d) Error
function sayHello(name) {
alert('Hello, ' + name);
}
sayHello('</script><script>alert("BOOM!");</script>');
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
But why?
 Let’s take a look at the code again…
55
function sayHello(name) {
alert('Hello, ' + name);
}
sayHello('</script><script>alert("BOOM!");</script>');
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
But why?
 Let’s take a look at the code again…
 When a browser renders a page, first the HTML parser will parse the page and tokenize out all of
the tags.
 Only after this is done, will it then allow the JavaScript parser to tokenize and execute whatever
tokens the HTML parser believes are JavaScript scripts!
56
<script>
function sayHello(name) {
alert('Hello, ' + name);
}
sayHello('</script><script>alert("BOOM!");</script>');
</script>
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
But why?
 Let’s take a look at the code again…
 Armed with this knowledge, we can see that the HTML parser will send 2 scripts to the JavaScript
parser to tokenize and execute…
 <script>function sayHello(name) { alert('Hello, ' + name); } sayHello('</script>
 <script>alert("BOOM!");</script>
57
<script>
function sayHello(name) {
alert('Hello, ' + name);
}
sayHello('</script><script>alert("BOOM!");</script>');
</script>
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
A closer look
 Again, the HTML parser will send these two script tags to the JavaScript parser…
 <script>function sayHello(name) { alert('Hello, ' + name); } sayHello('</script>
 <script>alert("BOOM!");</script>
 If that name parameter is user-controlled, perhaps taken as input from the browser, or pulled from
a datasource, whatever, then this is an open invitation for XSS attacks!
 Errors like this can expose huge security holes which may allow an attacker to potentially take
over a user’s browser!
58
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
JavaScript Puzzler – Say What?!...FIXED!
 In this particular case, the fix must be done on the server-side.
 We want to eliminate the <script></script> tags from appearing in the source in the first place.
 Suggested solution is to use the OWASP ESAPI APIs…
 Stands for “The Open Web Application Security Project” “Enterprise Security API”
 https://www.owasp.org/index.php/Category:OWASP_Enterprise_Security_API
 Have API bindings in all major languages including…
 Java
 Dot NET
 PHP
 JavaScript
 Python
 PHP
59
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
JavaScript Puzzler – Say What?!...FIXED!
 For this particular Puzzler, we want to use ESAPI.encoder().encodeForJavaScript()
 Doing this on the server to JavaScript-encode the user-inputted variable, name, we get what we
expect…
60
© 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
Moral
 NEVER . TRUST . THE . USER
 Validate your input.
 Encode your output appropriately.
 i.e. HTML-encode for HTML
URL-encode for URLs
JavaScript-encode for JavaScript
etc.
 Use standard libraries (i.e. don’t reinvent the wheel).
61

Más contenido relacionado

Similar a JavaScript Puzzlers!

Tom Krcha: Building Games with Adobe Technologies
Tom Krcha: Building Games with Adobe TechnologiesTom Krcha: Building Games with Adobe Technologies
Tom Krcha: Building Games with Adobe TechnologiesDevGAMM Conference
 
Advanced iOS Debbuging (Reloaded)
Advanced iOS Debbuging (Reloaded)Advanced iOS Debbuging (Reloaded)
Advanced iOS Debbuging (Reloaded)Massimo Oliviero
 
Joxean Koret - Database Security Paradise [Rooted CON 2011]
Joxean Koret - Database Security Paradise [Rooted CON 2011]Joxean Koret - Database Security Paradise [Rooted CON 2011]
Joxean Koret - Database Security Paradise [Rooted CON 2011]RootedCON
 
Middy.js - A powerful Node.js middleware framework for your lambdas​
Middy.js - A powerful Node.js middleware framework for your lambdas​ Middy.js - A powerful Node.js middleware framework for your lambdas​
Middy.js - A powerful Node.js middleware framework for your lambdas​ Luciano Mammino
 
Building native Android applications with Mirah and Pindah
Building native Android applications with Mirah and PindahBuilding native Android applications with Mirah and Pindah
Building native Android applications with Mirah and PindahNick Plante
 
GermaniumWeb training for CXA2010
GermaniumWeb training for CXA2010GermaniumWeb training for CXA2010
GermaniumWeb training for CXA2010ianloh13
 
Creating Custom Dojo Widgets Using WTP
Creating Custom Dojo Widgets Using WTPCreating Custom Dojo Widgets Using WTP
Creating Custom Dojo Widgets Using WTPnsandonato
 
LISA Qooxdoo Tutorial Handouts
LISA Qooxdoo Tutorial HandoutsLISA Qooxdoo Tutorial Handouts
LISA Qooxdoo Tutorial HandoutsTobias Oetiker
 
FGS 2011: Flash+ A Whole New Dimension for Games
FGS 2011: Flash+ A Whole New Dimension for GamesFGS 2011: Flash+ A Whole New Dimension for Games
FGS 2011: Flash+ A Whole New Dimension for Gamesmochimedia
 
Sandboxing JS and HTML. A lession Learned
Sandboxing JS and HTML. A lession LearnedSandboxing JS and HTML. A lession Learned
Sandboxing JS and HTML. A lession LearnedMinded Security
 
Raising the Bar on Robotics Code Quality
Raising the Bar on Robotics Code QualityRaising the Bar on Robotics Code Quality
Raising the Bar on Robotics Code QualityThomas Moulard
 
HTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyHTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyDavid Padbury
 
Developing cross platform desktop application with Ruby
Developing cross platform desktop application with RubyDeveloping cross platform desktop application with Ruby
Developing cross platform desktop application with RubyAnis Ahmad
 
Robotlegs on Top of Gaia
Robotlegs on Top of GaiaRobotlegs on Top of Gaia
Robotlegs on Top of GaiaJesse Warden
 
Griffon: Re-imaging Desktop Java Technology
Griffon: Re-imaging Desktop Java TechnologyGriffon: Re-imaging Desktop Java Technology
Griffon: Re-imaging Desktop Java TechnologyJames Williams
 
Docker and Your Path to a Better Staging Environment - webinar by Gil Tayar
Docker and Your Path to a Better Staging Environment - webinar by Gil TayarDocker and Your Path to a Better Staging Environment - webinar by Gil Tayar
Docker and Your Path to a Better Staging Environment - webinar by Gil TayarApplitools
 
I thought you were my friend - Malicious Markup
I thought you were my friend - Malicious MarkupI thought you were my friend - Malicious Markup
I thought you were my friend - Malicious MarkupMario Heiderich
 
Android Development w/ ArcGIS Server - Esri Dev Meetup - Charlotte, NC
Android Development w/ ArcGIS Server - Esri Dev Meetup - Charlotte, NCAndroid Development w/ ArcGIS Server - Esri Dev Meetup - Charlotte, NC
Android Development w/ ArcGIS Server - Esri Dev Meetup - Charlotte, NCJim Tochterman
 
Kernel Recipes 2014 - Writing Code: Keep It Short, Stupid!
Kernel Recipes 2014 - Writing Code: Keep It Short, Stupid!Kernel Recipes 2014 - Writing Code: Keep It Short, Stupid!
Kernel Recipes 2014 - Writing Code: Keep It Short, Stupid!Anne Nicolas
 

Similar a JavaScript Puzzlers! (20)

Tom Krcha: Building Games with Adobe Technologies
Tom Krcha: Building Games with Adobe TechnologiesTom Krcha: Building Games with Adobe Technologies
Tom Krcha: Building Games with Adobe Technologies
 
Advanced iOS Debbuging (Reloaded)
Advanced iOS Debbuging (Reloaded)Advanced iOS Debbuging (Reloaded)
Advanced iOS Debbuging (Reloaded)
 
Joxean Koret - Database Security Paradise [Rooted CON 2011]
Joxean Koret - Database Security Paradise [Rooted CON 2011]Joxean Koret - Database Security Paradise [Rooted CON 2011]
Joxean Koret - Database Security Paradise [Rooted CON 2011]
 
Middy.js - A powerful Node.js middleware framework for your lambdas​
Middy.js - A powerful Node.js middleware framework for your lambdas​ Middy.js - A powerful Node.js middleware framework for your lambdas​
Middy.js - A powerful Node.js middleware framework for your lambdas​
 
Building native Android applications with Mirah and Pindah
Building native Android applications with Mirah and PindahBuilding native Android applications with Mirah and Pindah
Building native Android applications with Mirah and Pindah
 
GermaniumWeb training for CXA2010
GermaniumWeb training for CXA2010GermaniumWeb training for CXA2010
GermaniumWeb training for CXA2010
 
Creating Custom Dojo Widgets Using WTP
Creating Custom Dojo Widgets Using WTPCreating Custom Dojo Widgets Using WTP
Creating Custom Dojo Widgets Using WTP
 
LISA Qooxdoo Tutorial Handouts
LISA Qooxdoo Tutorial HandoutsLISA Qooxdoo Tutorial Handouts
LISA Qooxdoo Tutorial Handouts
 
FGS 2011: Flash+ A Whole New Dimension for Games
FGS 2011: Flash+ A Whole New Dimension for GamesFGS 2011: Flash+ A Whole New Dimension for Games
FGS 2011: Flash+ A Whole New Dimension for Games
 
Sandboxing JS and HTML. A lession Learned
Sandboxing JS and HTML. A lession LearnedSandboxing JS and HTML. A lession Learned
Sandboxing JS and HTML. A lession Learned
 
Raising the Bar on Robotics Code Quality
Raising the Bar on Robotics Code QualityRaising the Bar on Robotics Code Quality
Raising the Bar on Robotics Code Quality
 
HTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyHTML5 for the Silverlight Guy
HTML5 for the Silverlight Guy
 
Demystifying The Solid Works Api
Demystifying The Solid Works ApiDemystifying The Solid Works Api
Demystifying The Solid Works Api
 
Developing cross platform desktop application with Ruby
Developing cross platform desktop application with RubyDeveloping cross platform desktop application with Ruby
Developing cross platform desktop application with Ruby
 
Robotlegs on Top of Gaia
Robotlegs on Top of GaiaRobotlegs on Top of Gaia
Robotlegs on Top of Gaia
 
Griffon: Re-imaging Desktop Java Technology
Griffon: Re-imaging Desktop Java TechnologyGriffon: Re-imaging Desktop Java Technology
Griffon: Re-imaging Desktop Java Technology
 
Docker and Your Path to a Better Staging Environment - webinar by Gil Tayar
Docker and Your Path to a Better Staging Environment - webinar by Gil TayarDocker and Your Path to a Better Staging Environment - webinar by Gil Tayar
Docker and Your Path to a Better Staging Environment - webinar by Gil Tayar
 
I thought you were my friend - Malicious Markup
I thought you were my friend - Malicious MarkupI thought you were my friend - Malicious Markup
I thought you were my friend - Malicious Markup
 
Android Development w/ ArcGIS Server - Esri Dev Meetup - Charlotte, NC
Android Development w/ ArcGIS Server - Esri Dev Meetup - Charlotte, NCAndroid Development w/ ArcGIS Server - Esri Dev Meetup - Charlotte, NC
Android Development w/ ArcGIS Server - Esri Dev Meetup - Charlotte, NC
 
Kernel Recipes 2014 - Writing Code: Keep It Short, Stupid!
Kernel Recipes 2014 - Writing Code: Keep It Short, Stupid!Kernel Recipes 2014 - Writing Code: Keep It Short, Stupid!
Kernel Recipes 2014 - Writing Code: Keep It Short, Stupid!
 

Último

08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGSujit Pal
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 

Último (20)

08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAG
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 

JavaScript Puzzlers!

  • 1. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. JavaScript Puzzlers: Puzzles to Make You Think (and write fewer bugs) Charles Bihis | Computer Scientist 1
  • 2. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. Who am I?  Charles Bihis  Computer Scientist  Adobe Identity Team  Blog: blogs.adobe.com/charles  Twitter: @charlesbihis  GitHub: github.com/charlesbihis 2
  • 3. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. What can I expect?  What are we going to talk about?  Puzzlers!  Maximus the Confused!  Block Party!  Let’s Print Some ZIP-Codes!  Loopty Loop!  Why Are We Bankrupt?!  A Case of Mistaken Identity  Will deal with only pure JavaScript  (i.e. no libraries!) 3  What are we NOT going to talk about?  3rd- party libraries or frameworks  e.g. jQuery, Node.js, etc.  Bugs
  • 4. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. What is a Puzzler? A Puzzler is a very simple programming puzzle that demonstrates or exploits weird behaviours and quirky edge-cases of a given programming language. 4
  • 5. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. How does this work? 1. Code – I introduce the code. 2. Question – I pose a multiple-choice question and you guess what the answer is…think hard! 3. Walkthrough – I walk through a reasonable explanation. 4. Answer – I tell you the real answer. 5. Moral – How can you avoid making mistakes like this in your own code. 5
  • 6. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. Let’s start! 6
  • 7. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. JavaScript Puzzler – Maximus the Confused! 7 var commodusRule = 'thumbsUp'; alert('Maximus the ' + (commodusRule === 'thumbsUp') ? 'Gladiator' : 'Merciful'); What does this print? a) Maximus the Gladiator b) Maximus the Merciful c) Error d) It varies e) None of the above  prints only "Gladiator"
  • 8. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. But why?  Order of operations dictates that the binary “+” operator takes precedence over the conditional “?” operator. 8 *Reference: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Operator_Precedence 'Maximus the ' + (commodusRule === 'thumbsUp') ? 'Gladiator' : 'Merciful';
  • 9. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. But why?  Order of operations dictates that the binary “+” operator takes precedence over the conditional “?” operator. 9 *Reference: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Operator_Precedence 'Maximus the true' ? 'Gladiator' : 'Merciful';
  • 10. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. But why?  Order of operations dictates that the binary “+” operator takes precedence over the conditional “?” operator. 10 *Reference: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Operator_Precedence 'Gladiator';
  • 11. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. But why?  Order of operations dictates that the binary “+” operator takes precedence over the conditional “?” operator.  According to the MDN (Mozilla Developer Network), the binary “+” operator has a precedence of 6 while the conditional “?” operator has a precedence of 15.  Note: This is below MOST commonly used operators (i.e. “*”, “/”, “%”, “<“, “>>” “!=”, “===“, etc). 11 *Reference: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Operator_Precedence 'Gladiator';
  • 12. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. JavaScript Puzzler – Maximus the Confused…FIXED! 12 var commodusRule = 'thumbsUp'; alert('Maximus the ' + (commodusRule === 'thumbsUp') ? 'Gladiator' : 'Merciful');
  • 13. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. JavaScript Puzzler – Maximus the Confused…FIXED! 13 var commodusRule = 'thumbsUp'; alert('Maximus the ' + (commodusRule === 'thumbsUp' ? 'Gladiator' : 'Merciful'));
  • 14. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. Moral  Be aware of order-of-operations!  Be explicit and place parenthesis accordingly to ensure correct and predictable order of execution. 14
  • 15. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. JavaScript Puzzler – Block Party! // global var var name = "World!"; (function() { // check if "name" defined if (typeof name === "undefined") { // local "shadow" var var name = "Mr. Bond."; alert("Goodbye, " + name); } else { alert("Hello, " + name); } })(); 15 What does this print? a) “Hello, World!” b) “Goodbye, Mr. Bond.” c) “Hello, ” d) “Hello, undefined” e) Error f) It varies g) None of the above
  • 16. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. But why? 1. No block scope! 2. “Hoisting” 16 for (var i = 0; i < MAX; i++) { // do something } alert(i); // Note: "i" exists here! alert(i); for (var i = 0; i < MAX; i++) { // do something } // Note: "i" exists here too!
  • 17. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. But why? 1. No block scope! 2. “Hoisting” 17 for (var i = 0; i < MAX; i++) { // do something } alert(i); // Note: "i" exists here! var i; alert(i); // Note: "i" exists here too! for (i = 0; i < MAX; i++) { // do something }
  • 18. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. JavaScript Puzzler – Block Party…FIXED! // global var var name = "World!"; (function() { // check if "name" defined if (typeof name === "undefined") { // local "shadow" var var name = "Mr. Bond."; alert("Goodbye, " + name); } else { alert("Hello, " + name); } })(); 18
  • 19. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. JavaScript Puzzler – Block Party…FIXED! // global var var name = "World!"; (function() { var name; // check if "name" defined if (typeof name === "undefined") { // local "shadow" var name = "Mr. Bond."; alert("Goodbye, " + name); } else { alert("Hello, " + name); } })(); 19 // declaration hoisted here // assignment remains here
  • 20. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. JavaScript Puzzler – Block Party…FIXED! // global var var name = "World!"; (function() { var name = "Mr. Bond."; // check if "name" defined if (typeof name === "undefined") { alert("Goodbye, " + name); } else { alert("Hello, " + name); } })(); 20
  • 21. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. Moral  There is no block-level scoping in JavaScript  Declare ALL of your variables at the top of your function 21
  • 22. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. What does this print? a) 93021 19 20341 32959 b) 93021 2392 20341 8163 32959 c) 93021 20341 32959 d) Error e) It varies f) None of the above JavaScript Puzzler – Let’s Print Some ZIP Codes! 22 // array of 5 valid zip-codes var zipCodes = new Array("93021", "02392", "20341", "08163", "32959"); // let's do something with each zip-code // for now, display them for (var i = 0; i < zipCodes.length; i++) { // sanity check if (!isNaN(parseInt(zipCodes[i])) && parseInt(zipCodes[i]) > 0) { alert(parseInt(zipCodes[i])); } } Firefox  Chrome 
  • 23. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. But why?  Syntax  When you omit the optional “radix” parameter, the following behavior takes place:  If the input string begins with “0x” or “0X”, radix of 16 is used (i.e. hexadecimal)  If the input string begins with “0”, radix 8 is used (i.e. octal) OR radix 10 is used (i.e. decimal)  If the input string begins with any other values, radix 10 is used (i.e. decimal)  Particularly when dealing with string values with leading 0’s, Mozilla had this to say… 23 var num = parseInt(string, radix); // "radix" is optional Exactly which radix is chosen is implementation-dependent. For this reason ALWAYS SPECIFY A RADIX WHEN USING parseInt. *Reference: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/parseInt
  • 24. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. But why?  Another important note about the parseInt() API…  A closer look… 24 // behaviour in Firefox v20.0 parseInt("93021") = 93021 // displays parseInt("02392") = (2 * 8) + (3 * 1) = 19 // displays parseInt("20341") = 20341 // displays parseInt("08163") = 0 // does NOT display parseInt("32959") = 32959 // displays *Reference: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/parseInt If parseInt encounters a character that is not a numeral in the specified radix, it ignores it and all succeeding characters and returns the integer value parsed up to that point.
  • 25. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. JavaScript Puzzler – Let’s Print Some ZIP Codes…FIXED! 25 // array of 5 valid zip-codes var zipCodes = new Array("93021", "02392", "20341", "08163", "32959"); // let's do something with each zip-code // for now, display them for (var i = 0; i < zipCodes.length; i++) { // sanity check if (!isNaN(parseInt(zipCodes[i])) && parseInt(zipCodes[i]) > 0) { alert(parseInt(zipCodes[i])); } }
  • 26. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. JavaScript Puzzler – Let’s Print Some ZIP Codes…FIXED! 26 // array of 5 valid zip-codes var zipCodes = new Array("93021", "02392", "20341", "08163", "32959"); // let's do something with each zip-code // for now, display them for (var i = 0; i < zipCodes.length; i++) { // sanity check if (!isNaN(parseInt(zipCodes[i], 10)) && // radix value added parseInt(zipCodes[i], 10) > 0) { // here too alert(parseInt(zipCodes[i], 10)); // and here too } }
  • 27. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. Moral  parseInt() takes an optional radix parameter.  Omitting this optional parameter will cause unpredictable behavior across browsers.  Be explicit and ALWAYS include the radix parameter. 27
  • 28. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. JavaScript Puzzler – Loopty Loop! 28 var END = 9007199254740992; var START = END - 100; var count = 0; for (var i = START; i <= END; i++) { count++; } alert(count); // Math.pow(2, 53) What does this print? a) 0 b) 100 c) 101 d) Error e) It varies f) None of the above  enters infinite loop
  • 29. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. But why?  9007199254740992 is a special number. Particularly, it is 2^53.  Why is this special?  First, we need to know something about how JavaScript represents numbers. 29 *Reference: http://ecma262-5.com/ELS5_HTML.htm#Section_8.5
  • 30. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. But why?  JavaScript numbers abide by the IEEE Standard for Floating-Point Arithmetic (IEEE 754).  As such, all numbers in JavaScript are represented by double-precision 64-bit floating point values…  In binary… 30 *Reference: http://ecma262-5.com/ELS5_HTML.htm#Section_8.5 1.2345 = 12345 10x -4 mantissa exponent 1 11...111 11111111111...111 63 62 53 52 0 exponent mantissasign
  • 31. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. But why?  2^53 is the largest exact integral value that can be represented in JavaScript!  From the ECMA specification…  What does this mean? 31 *Reference: http://ecma262-5.com/ELS5_HTML.htm#Section_8.5 Note that all the positive and negative integers whose magnitude is no greater than 2^53 are representable in the Number type. var numA = Math.pow(2, 53); var numB = numA + 1; alert(numA === numB); // true!
  • 32. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. JavaScript Puzzler – Loopty Loop…FIXED! 32 var END = 9007199254740992; // Math.pow(2, 53) var START = END - 100; var count = 0; for (var i = START; i <= END; i++) { count++; } alert(count);
  • 33. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. JavaScript Puzzler – Loopty Loop…FIXED! 33 var START = 0; var END = 100; var count = 0; for (var i = START; i <= END; i++) { count++; } alert(count);
  • 34. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. Moral  Be aware of your number representations and number ranges!  There are REAL limitations imposed by your computer. When dealing with large (or important) numbers, know them! 34
  • 35. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. JavaScript Puzzler – Why Are We Bankrupt?! 35 What does this print? a) 0 b) 0.2 c) 0.20 d) None of the above var costOfCandy = 0.60; // 60 cents function calculateChange(cost, paid) { return paid - cost; } // pay for candy with 80 cents alert(calculateChange(costOfCandy, 0.80));  0.20000000000000007
  • 36. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. But why?  As we learned from the previous Puzzler, all JavaScript numbers use the IEEE 754 floating-point arithmetic specification.  Because of this, values are not represented exactly, but rather as a fraction.  Some non-integer values simply CANNOT be expressed exactly in this way. They must be approximated. 36 Example: 123.45 = 12345 * 10^-2 // exact 1 / 3 = 0.333333333333333 * 10^0 // approximation!
  • 37. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. JavaScript Puzzler – Why Are We Bankrupt?!...FIXED! 37 var costOfCandy = 0.60; // 60 cents function calculateChange(cost, paid) { return paid - cost; } // pay for candy with 80 cents alert(calculateChange(costOfCandy, 0.80));
  • 38. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. JavaScript Puzzler – Why Are We Bankrupt?!...FIXED! 38 var costOfCandy = 60; // 60 cents function calculateChange(cost, paid) { return paid - cost; } // pay for candy with 80 cents alert(calculateChange(costOfCandy, 80)); // Use only integer math when dealing with money! To do this, // represent your money in terms of cents to begin with! // // e.g. use 1599 instead of 15.99 to represent $15.99
  • 39. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. Moral  Floating-point arithmetic can be inaccurate when representing fractions.  When dealing with money, deal in terms of cents! This makes all of your calculations integer- calculations, which are exact!  BUT, not completely exact, though…  Remember from our last Puzzler, it is exact only up until the largest representable integer value…  9007199254740992 (i.e. 2^53)  So, as long as you are dealing with less than $9 quintillion, you’re fine using integer arithmetic in JavaScript :) 39 *Reference: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
  • 40. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. JavaScript Puzzler – A Case of Mistaken Identity! function showCase(value) { switch(value) { case "A": alert("Case A was selected."); break; case "B": alert("Case B here!"); break; case "C": alert("This is Case C."); break; default: alert("Don't know what happened."); break; } } showCase(new String("A")); 40 What does this print? a) Case A was selected. b) Case B here! c) This is Case C. d) Don’t know what happened. e) Error f) It varies g) None of the above
  • 41. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. But why?  The switch statement in JavaScript internally uses the strict equality operator (i.e. ===) as opposed to the non-strict equality operator (i.e. ==).  The strict equality operator behaves exactly as the non-strict version, except that no type- conversions are done.  So, when the switch statement evaluates equality, it checks that the following are true…  Their types are equal  Their uncast values are equal  Notice, we invoked showCase() with a new String object. 41 alert(typeof "A"); // "string" alert(typeof new String("A")); // "object"
  • 42. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. JavaScript Puzzler – A Case of Mistaken Identity…FIXED! function showCase(value) { switch(value) { case "A": alert("Case A was selected."); break; case "B": alert("Case B here!"); break; case "C": alert("This is Case C."); break; default: alert("Don't know what happened."); break; } } showCase(new String("A")); 42
  • 43. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. JavaScript Puzzler – A Case of Mistaken Identity…FIXED! function showCase(value) { switch(value) { case "A": alert("Case A was selected."); break; case "B": alert("Case B here!"); break; case "C": alert("This is Case C."); break; default: alert("Don't know what happened."); break; } } showCase("A"); 43
  • 44. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. Moral  Get used to using the strict equality operator when possible. It will make you more aware of type conversions and true equalities.  From Douglas Crockford’s book “JavaScript: The Good Parts”… 44 JavaScript has two sets of equality operators: === and !==, and their evil twins == and !=. The good ones work the way you would expect. The evil twins do the right thing when the operands are of the same type, but if they are of different types, they attempt to coerce the values, the rules by which they do that are complicated and unmemorable.
  • 45. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. That’s it! Questions? 45
  • 46. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. Thanks for coming!  Charles Bihis  Computer Scientist  Adobe Identity Team  Blog: blogs.adobe.com/charles  Twitter: @charlesbihis  GitHub: github.com/charlesbihis 46
  • 47. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential.
  • 48. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. JavaScript Puzzler – That’s Odd! (function(){ var values = [7, 4, '13', Infinity, -9]; for (var i = 0; i < values.length; i++) { if (isOdd(values[i])) { alert(values[i]); } } })(); function isOdd(num) { return num % 2 == 1; } 48 What does this print? a) 7, 13 b) 7, 13, Infinity, -9 c) 7, -9 d) 7, 13, -9
  • 49. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. But why?  Let’s take a closer look… 49 7 % 2 = 1 // displays 4 % 2 = 0 // does NOT display 13 % 2 = 1 // displays Infinity % 2 = NaN // does NOT display -9 % 2 = -1 // does NOT display
  • 50. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. But why?  -9 % 2 = -1? Really?  JavaScript shares the same behavior as the Java implementation of the modulus (%) operator. That is, it must satisfy the following identity function for all integer values a and non-zero integer values b.  A side-implication of this behavior is that the result will have the same sign as the left operand! 50 (a / b) * b + (a % b) == a
  • 51. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. JavaScript Puzzler – That’s Odd…FIXED! (function(){ var values = [7, 4, '13', Infinity, -9]; for (var i = 0; i < values.length; i++) { if (isOdd(values[i])) { alert(values[i]); } } })(); function isOdd(num) { return num % 2 == 1; } 51
  • 52. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. JavaScript Puzzler – That’s Odd…FIXED! (function(){ var values = [7, 4, '13', Infinity, -9]; for (var i = 0; i < values.length; i++) { if (isOdd(values[i])) { alert(values[i]); } } })(); function isOdd(num) { return num % 2 != 0; } 52
  • 53. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. Moral  Be careful about the signs of operands when using the modulus operator. 53
  • 54. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. JavaScript Puzzler – Say What?! 54 What does this print? a) alert("BOOM!“); b) Hello, </script><script>alert("BOOM!");</script> c) BOOM! d) Error function sayHello(name) { alert('Hello, ' + name); } sayHello('</script><script>alert("BOOM!");</script>');
  • 55. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. But why?  Let’s take a look at the code again… 55 function sayHello(name) { alert('Hello, ' + name); } sayHello('</script><script>alert("BOOM!");</script>');
  • 56. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. But why?  Let’s take a look at the code again…  When a browser renders a page, first the HTML parser will parse the page and tokenize out all of the tags.  Only after this is done, will it then allow the JavaScript parser to tokenize and execute whatever tokens the HTML parser believes are JavaScript scripts! 56 <script> function sayHello(name) { alert('Hello, ' + name); } sayHello('</script><script>alert("BOOM!");</script>'); </script>
  • 57. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. But why?  Let’s take a look at the code again…  Armed with this knowledge, we can see that the HTML parser will send 2 scripts to the JavaScript parser to tokenize and execute…  <script>function sayHello(name) { alert('Hello, ' + name); } sayHello('</script>  <script>alert("BOOM!");</script> 57 <script> function sayHello(name) { alert('Hello, ' + name); } sayHello('</script><script>alert("BOOM!");</script>'); </script>
  • 58. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. A closer look  Again, the HTML parser will send these two script tags to the JavaScript parser…  <script>function sayHello(name) { alert('Hello, ' + name); } sayHello('</script>  <script>alert("BOOM!");</script>  If that name parameter is user-controlled, perhaps taken as input from the browser, or pulled from a datasource, whatever, then this is an open invitation for XSS attacks!  Errors like this can expose huge security holes which may allow an attacker to potentially take over a user’s browser! 58
  • 59. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. JavaScript Puzzler – Say What?!...FIXED!  In this particular case, the fix must be done on the server-side.  We want to eliminate the <script></script> tags from appearing in the source in the first place.  Suggested solution is to use the OWASP ESAPI APIs…  Stands for “The Open Web Application Security Project” “Enterprise Security API”  https://www.owasp.org/index.php/Category:OWASP_Enterprise_Security_API  Have API bindings in all major languages including…  Java  Dot NET  PHP  JavaScript  Python  PHP 59
  • 60. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. JavaScript Puzzler – Say What?!...FIXED!  For this particular Puzzler, we want to use ESAPI.encoder().encodeForJavaScript()  Doing this on the server to JavaScript-encode the user-inputted variable, name, we get what we expect… 60
  • 61. © 2013 Adobe Systems Incorporated. All Rights Reserved. Adobe Confidential. Moral  NEVER . TRUST . THE . USER  Validate your input.  Encode your output appropriately.  i.e. HTML-encode for HTML URL-encode for URLs JavaScript-encode for JavaScript etc.  Use standard libraries (i.e. don’t reinvent the wheel). 61