Most of us, much of the time, react to "You're wrong" with "No I'm not! And you can't tell me otherwise!" An engineer's response is "How? Show me."
Tuesday, 26 April 2011
Saturday, 23 April 2011
Thinking outside the box with the ASP.Net Development Server
A well-known limitation of the ASP.Net Development Server is that it will only bind to the local interface of the development machine, never the LAN interface, and so you can't bring up pages served from the development server from anywhere but on the box itself via the localhost name or 127.0.0.1 address. And fair enough, it's meant to be a debugger aid, not a web server. But there are situations where you want to think outside that box, and fortunately, it's dead easy to do so.
I wanted to do that because I'm working on a project where the server-side code is C# assemblies and the client-side is pure HTML, CSS, and JavaScript (no server controls or other ASP.Net-isms). I wanted to use VS.Net for debugging server-side C# code, and Chrome's Dev Tools or Firebug for debugging the client-side code in the browser. VS.Net makes it remarkably easy to debug server-side code — just mark the "project" with the client code as the startup project, chooose a port if you want, set the virtual path, make sure the server-side assembly projects are in the solution, and hit F5 (or click Run). It fires up the ASP.Net Development Server and you have full debugging of the server-side code (and client-side code as well, if you like, with its integration with IE). Excellent, couldn't be much easier. But for me, this is all happening in a VM (this is for a client, and I keep all my client stuff isolated from my work and each other using VMs) but I'd like to do the client-side debugging with Chrome's Dev Tools on my main machine.
It was only a mild irritation (I can run a browser in the VM happily enough), so I didn't want to spend any time on it, but I figured this has to be one of the simplest examples of the need for port forwarding or proxy serving on the planet (just bridging interfaces), and so I did a quick web search and found this article about using Squid to do it. Now, Squid is a big hammer for this nail, but it's so easy to set up, that it's still reasonable to use it.
That article's good, but I thought a few things weren't as clear as they may have been, so here's my step-by-step:
- Tell the ASP.Net Development Server to use a particular port rather than picking one at random:
- Click the client code project in your solution
- Look at the properties
- Make sure that Use dynamic ports is False
- Choose your port under Port number (if you just turned off the Use dynamic ports option, you may have to click away from the properties and click back again to unlock the field; minor bug in VS.Net)
- Be sure your dev machine's firewall allows incoming connections whatever external port you're going to use.
- Get and install Squid. The quick-and-easy thing is to get a binary from these nice people who are kind enough to maintain a Windows port built using the Microsoft toolchain: Just scroll down under the features list and click the "Squid download Page" link. Or, of course, you could grab the source and do it yourself (with the MS toolchain, or Cygwin and GCC). I grabbed 2.7.STABLE8 from the the nice people.
- Unzip it somewhere handy. The Windows binary assumes C:\Squid, so I went with the path of least resistance and put it there.
- Install it as a service:
- Open a command prompt (as Administrator, if you're on Windows 7 or similar)
- Change to C:\Squid\sbin.
- Type squid -i -n Squid
- Set up the default config: Using your favorite file browser:
- Go to C:\Squid\etc
- Copy squid.conf.default as squid.conf
- Copy mime.conf.default as mime.conf (we're not going to edit it, but it's required)
- Set up the proxying:
- Open squid.conf with your favorite text editor
- Go to the very end of the file
- Paste this in, replacing the bits in curly braces with your own values (without the curly braces) (mind the word-wrapping, Blogger is giving me a hard time yet again; best to copy and paste):
http_port {EXTERNAL_PORT} accel defaultsite={EXTERNAL_IP_ADDRESS}So in my case, since I want both the internal and external ports to be 80 and my VM's external (LAN) IP is 192.168.142.153, it's
cache_peer localhost parent {INTERNAL_PORT} 0 no-query originserver name=myAccel
acl our_sites dstdomain {EXTERNAL_IP_ADDRESS}
http_access allow our_sites
cache_peer_access myAccel allow our_sites
cache_peer_access myAccel deny allhttp_port 80 accel defaultsite=192.168.142.153
...but if you use different internal and external ports, be sure to set them according to the placeholders in the above.
cache_peer localhost parent 80 0 no-query originserver name=myAccel
acl our_sites dstdomain 192.168.142.153
http_access allow our_sites
cache_peer_access myAccel allow our_sites
cache_peer_access myAccel deny all - Save the file
- In your (Administrator) command window, tell Squid to validate the config:
squid -z
You should see the message Creating Swap Directories and pretty much nothing else. - Start the service:
net start Squid - You might choose to have Squid start when you boot the machine, via the usual services.msc settings
Sorted!
Tuesday, 29 March 2011
Friday, 18 March 2011
No Excuse
I'm active in a couple of places where people go for help with, amongst other things, JavaScript code running in web browsers. Routinely, you'll get questions like this one where the person asking the question is having trouble visualizing what's happening on the client side, and is stabbing in the dark with alert or console.log to try to figure out what's going on. It's like the old days of debugging with printf. I see it over and over again.
Folks, maybe that was reasonable in, oh, 2002 or so, but here in 2011 if you're using a desktop browser there's just no excuse for not using a proper debugger to set breakpoints, walk through code, inspect variables, inspect the structure of the DOM, etc., etc. No excuse at all. None! Pas d'excuse! ¡No excusa! Keine Entschuldigung! Nessuna scusa!
Why not? Because these days, client-side JavaScript debuggers are a dime a dozen, and they're free. Pick your browser:
- IE8 & IE9: Semi-reasonable debugger and tools built in, or use the free version of VS.Net
- IE6 & IE7: Use the free version of VS.Net (or the old standalone script debugger)
- Firefox: Get the excellent, and free, Firebug plug-in
- Chrome: Has a good debugger and tools built in
- Safari: Has a good debugger and tools built in (you may have to enable the menu item in the options)
- Opera: Has a good debugger and tools built in
Happy coding debugging!
Sunday, 30 January 2011
Skipping the protocol
I just found out about this incredibly useful trick for loading absolute resources with either http: or https: depending on the protocol with which your page was loaded (to avoid those "mixed content" complaints from browsers).
Amazingly, you can just leave the scheme (protocol) part off the URL entirely. So for instance, if you're loading jQuery from the Google CDN with this path:
<script src='https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js'></script>you can load it like this instead:<script src='//ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js'></script>If the page that's in is served via http, that path will become http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.jsIf it's https, that will become
https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.jsE.g., it's a path relative to the protocol (scheme) but in all other ways absolute.
(Naturally, if you load a file via the file: protocol — e.g., locally — it will try to resolve that locally and blow up. But you don't do that, do you?)
Don't trust it? Neither did I, but I haven't found a browser in which it doesn't work, nor apparently have these guys.
And you thought you knew all there was to know about URIs...
Sunday, 23 January 2011
A myth of arrays
When is an array not an array?
When it's a JavaScript array.
(Update: Here I'm talking about JavaScript's standard Array type. Many environments now also support new typed arrays, which are different.)
JavaScript objects are basically just key=value maps, and JavaScript arrays are nothing more than objects that have:
- special handling for keys that are numeric strings
- a special length property
- and some functions they inherit from Array.prototype
All of this is covered by Section 15.4 of the specification, which starts with this paragraph:
Array objects give special treatment to a certain class of property names. A property name P (in the form of a String value) is an array index if and only if ToString(ToUint32(P)) is equal to P and ToUint32(P) is not equal to 2^32−1. A property whose property name is an array index is also called an element. Every Array object has a length property whose value is always a nonnegative integer less than 2^32. The value of the length property is numerically greater than the name of every property whose name is an array index; whenever a property of an Array object is created or changed, other properties are adjusted as necessary to maintain this invariant. Specifically, whenever a property is added whose name is an array index, the length property is changed, if necessary, to be one more than the numeric value of that array index; and whenever the length property is changed, every property whose name is an array index whose value is not smaller than the new length is automatically deleted. This constraint applies only to own properties of an Array object and is unaffected by length or array index properties that may be inherited from its prototypes.
There are some consequences to this:
- Barring implementation optimizations, accessing array elements by index is not a constant-time operation as it is in (say) C; like all maps, it will vary depending on the layout of the key storage, the size of the map, and the specific key you're looking up.
- Barring implementation optimizations, using an array is no more efficient than using a plain object.
- JavaScript arrays are inherently "sparse" (since the whole concept of a contiguous block of memory just doesn't exist for them anyway).
- Arrays are inherently one-dimensional. A "2D" JavaScript array is merely an array in which each element is, in turn, an array, and it's important to remember that those sub-arrays may have different lengths (and you may even choose to intermix arrays and non-arrays as values of the outer array's elements).
- Arrays can have non-index properties, which can be handy. For instance, this is perfectly valid:
This is one reason why it's important to understand for..in loops before using them on arrays (see Myths and realities of for..in).var a = ["zero", "one", "two", "three"];
a.foo = "bar";
alert(a.length); // alerts "4"
alert(a.foo); // alerts "bar"
None of which means that we shouldn't use arrays for ordered lists of things. We should. Doing so is useful semantically, and of course it's entirely possible that an implementation will optimize some of those things above. But it's important to remember what you're dealing with, and taking advantage of an array's non-array nature can be very useful sometimes.
Happy coding,
Thursday, 23 December 2010
Say what?
(Updated 2014/12/30)
Something that sometimes comes up in JavaScript work is the need to figure out what kind of thing you're dealing with — is it a string? a number? a Date? And JavaScript has various features to help you do that, but there are some "gotchas" to watch out for. In this post I'll talk about various strategies for figuring out what things are.
Basically, you have four tools you can use, each of which has its place:
- typeof
- instanceof
- Object.prototype.toString
- Learn to stop worrying and love the duck
Let's look at each of them:
typeof
typeof is fast but fairly limited. It basically tells you whether something is a primitive or an object, and if it's a primitive it tells you what kind of primitive it is, but for all objects other than functions, it just says "object". So:
console.log(typeof "testing"); // "string"
console.log(typeof {}); // "object"But it's useful for, say, determining if something is a function:
if (typeof x === "function") {
// Yes it is
}(Although in some environments, host-provided functions like alert give us "object" rather than "function".)
typeof's chief advantage is speed, although with modern JavaScript engines, speed isn't anywhere near the concern it was a few years ago.
instanceof
instanceof sort of picks up where typeof leaves off. It's good for checking whether something is a specific kind of object, e.g.:
var dt = new Date(...);
console.log(dt instanceof Date); // trueSpecifically, obj instanceof Func it looks at each object in obj's prototype chain and sees if any of them is the one that Func assigns when used to construct objects. In the example above, for instance, since dt's prototype is Date.prototype, dt instanceof Date is true. dt instanceof Object is also true, because dt's prototype's prototype is Object.prototype. If you'd set up a multi-level hierarchy of constructors and prototypes so that Cat derives from Mammal which derives from Animal, and used c = new Cat(), instanceof would be true for a c instanceof Cat, c instanceof Mammal, and c instanceof Animal (and c instanceof Object, normally).
You do have to be careful with instanceof in some edge cases, though, particularly if you're writing a library and so have less control / knowledge of the environment in which it will be running. The issue is that if you're working in a multiple-window environment (frames, iframes), you might receive a Date d (for instance) from another window, in which case d instanceof Date will be false — because d's prototype is the Date.prototype in the other window, not the Date.prototype in the window where your code is running. And in most cases you don't care, you just want to know whether it has all the Date stuff on it so you can use it.
Object.prototype.toString
Calling Object.prototype.toString is slower than typeof or instanceof, but more useful for differentiating what kind of object you have — but sadly, only if the object is one created by one of the built-in JavaScript constructor functions like Date or String, not our own constructor functions. The return value of the Object prototype's toString function is defined in the standard for all the built-in constructor functions (Array, Date, etc.): It returns "[object ___]" where ___ is the constructor function name. So:
var what = Object.prototype.toString;
console.log(what.call(new Date())); // "[object Date]"
console.log(what.call(function(){})); // "[object Function]"
console.log(what.call([])); // "[object Array]"...etc. Note that this is very different from just calling toString on the object itself; the object probably has an overridden toString. That's why we explicitly use Object.prototype.toString above. (Remember, these things are just functions, not methods.) Object.prototype.toString works on primitives too, because it coerces its argument into an object before checking. So if you call it with a string primitive, you get "[object String]" (and "[object Number]" for numbers, etc.).
The chief advantage of this is that it doesn't care what window the object came from; referring back to our Date object d from another window, we'll get "[object Date]" regardless.
But sadly for our own constructor functions, all we get is "[object Object]":
var what = Object.prototype.toString;
console.log(what.call(new MyNiftyThing("foo"))); // "[object Object]"Ah, well...
At one point I was tempted to wrap all of the above (plus support for my own object hierarchy) up into an uber-function that definitively figured out what the thing was. Then I thought: Enh, maybe I should just use the right tool in each given situation.
Speaking of which, our last tool:
Learn to stop worrying and love the duck
When reaching for instanceof or typeof or whatever, ask yourself: Do you really care? How 'bout looking to see if the object seems to have the things on it you need (feature detection) rather than worrying about what it is? This is usually called "duck typing," from the phrase "If it walks like a duck and talks like a duck..." Sometimes, obviously, you do care, but if you get in the habit of asking yourself the question, it's interesting how frequently the answer is "Actually, no, I don't care whether that's a Foo; I just care that it has X on it" or "...I just care that it works if I pass it into getElementById" (that latter case being, basically, it's a string or its toString does what you need). I find myself doing a lot less worrying about types and just getting on with the job these days. I've learned to love the duck. (And always remember, be kind to your web-footed friends; a duck may be somebody's mother.)
Happy coding!
Postscript: You may be wondering why I haven't mentioned the constructor property in any of the above. The answer is: Because it's not very useful, and there are common anti-patterns that mess it up. At some point I'll do an article on what's wrong with constructor...