Just a Theory

Black lives matter

Suggestion for Emulating Namespaces in JavaScript

I’ve been giving some thought on how to emulate namespaces in JavaScript (at least until they’re implemented in the language), and this is what I’ve come up with: use objects for namespaces. This was inspired by a glance at the prototype, where I noticed that Sam Stephenson was using objects to group related things into neat packages.

For example, say that you wanted to create a class for managing music on you CDs. Normally in JavaScript, you’d create a class named CDMusic. This is all well and fine, but if everyone creates classes with a single name, a JSAN repository would end with an awfully crowded list of classes. It allows for no effective hierarchical organization of code.

But if you use objects to represent namespaces, you can define a class something like this, instead (1990s-era example borrowed from Damian Conway’s Object Oriented Perl):

if (CD == undefined) var CD = {}; // Make sure the base namespace exists.
CD.Music = function () {};        // Constructor definition.

// Class definition.
CD.Music.prototype = {
    name:      null,
    artist:    null,
    publisher: null,
    isbn:      null,
    tracks:    [],

    location: function (shelf, room) {
        if (room != null) this._room = room;
        if (shelf != null) this._shelf = shelf;
        return [this._room, this._shelf];
    },

    rating: function (rate) {
        if (rate != null) this._rating = rate;
        return this._rating;
    }
};

So now, to use this class, you just:

var music = new CD.Music();
music.name = "Renegades";
music.artist = "Rage Against the Machine";
music.tracks.push("Microphone Fiend");
music.location("basement", 3); // I use an iPod, so it's in storage!

Of course, the key part of this example is var music = new CD.Music();. Note how the class is defined as an attribute of the CD object. This allows us to have a namespace, CD.Music, that is subsumed under another namespace, namely CD. The nice thing about this is that, in the hypothetical JSAN repository, the class might be defined the file Music.js in the CD directory. A use() function as described by Michael Schwern might then be smart enough to look for /use/CD/Music.js when you write use("CD.Music").

I also kind of like how the use of the namespace and prototype allows my class definition to be indented by the creation of the prototype object. But to make these types of namespaces work, you must have that first statement: if (CD == undefined) var CD = {};. This allows you to assign to a CD object whether you have to create it (because your class stand on its own), or because some other JavaScript class has defined it. This is especially important to ensure that you don’t stomp on someone else’s work. Say someone is using two different JavaScript classes, your CD.Music and someone else’s CD.Jukebox. The two classes might be completely unrelated to each other, but because they both define themselves under the CD top-level namespace using the if (CD == undefined) statement, they won’t stomp on each other.

The only downside to this proposal, in my estimation, is the requirement it imposes for defining inherited classes. Say you wanted a subclass of CD.Music for classical music. You’d have to do it like this:

// CD.Music must be loaded already. Create the constructor.
CD.Music.Classical = function () {}

// Inherit from CD.Music.
CD.Music.Classical.prototype = new CD.Music(); // Inheritance.

// Add to the class and/or override as necessary.
CD.Music.Classical.prototype.composer  = null;
CD.Music.Classical.prototype.orchestra = null;
CD.Music.Classical.prototype.conductor = null;
CD.Music.Classical.prototype.soloist   = null;

So we don’t get the block syntax, but in truth, that’s no different from how one typically handles inheritance in JavaScript. The only difference is the use of the dot notation. Nevertheless, suggestions for how to use a block syntax would be warmly received.

So what do you think? Is this something that makes sense to you? Would you do it to better organize your JavaScript classes and modules (and yes, I am thinking that you could group functional libraries this way, too, and then implement an import() function to export functions to another “namespace” or the global object)? Leave your opinions in a comment. Thanks!

Looking for the comments? Try the old layout.

The Purpose of TestSimple

In response to my TestSimple 0.03 announcement, Bill N1VUX asked a number of important questions about TestSimple’s purpose. Since this is just an alpha release and I’m still making my way though the port, I haven’t created a project page or started to promote it much, yet. Once I get the harness part written and feel like it’s stable and working well, I’ll likely start to promote it as widely as possible.

But yes, TestSimple is designed for doing unit testing in JavaScript. Of all the JavaScript I’ve seen, I’ve never seen any decent unit tests. People sometimes write a few integration tests to test them in browsers, but don’t write many tests that would ensure that their JS code runs where they need it to run and that would give them the freedom to refactor. There is generally very little coverage in JavaScript tests—if there are any tests at all.

While it’s true that JavaScript is nearly always an embedded language (but see also Rhino and SpiderMonkey), that doesn’t mean that one doesn’t write a lot of JavaScript functions or classes that need testing. It’s also important to have a lot of tests you can run in various browsers (just as you can run tests of a Perl module on various OSs and various versions of Perl). I started the port because, as I was learning JavaScript, I realized that I didn’t want to write much without writing tests. The purpose is to ensure the quality of JavaScript code as it goes through the development process. And the freedom to refactor that tests offer is very important for my personal development style.

So, to answer N1VUX’s questions:

Is the point to integration test the whole distributed front-ends of applications from the (EcmaScript compliant) browser?

Yes. And I expect that, as people write more JavaScript applications, there will be a lot more code that needs testing. However, unlike other JavaScript testing frameworks I’ve seen (all based on the xUnit framework), my suite doesn’t assume that tests will be run in a browser. Ultimately, I’d like to be able to automate tests outside of browsers—or by scripting browsers. But in the meantime, it will produce TAP-compliant output in the browser, and I plan on implementing a harness that will run all of your test scripts in a single browser window and output the results, just like Test::Harness does for Perl modules on the command-line.

Or to unit test the client-side java-script as an entity, mocking the server??

Yes, I would like to be able to do that eventually. I will likely mock the server by mocking XMLHttpRequest and Microsoft.XMLHTTP to return XML strings that can be used for testing. Stuff like that.

Or is the point to Unit test JavaScript functions in the browser in vitro, mocking everything outside the current function?

If need be, yes. The point is that you have the freedom to do it the way that makes sense to your particular project. The testing framework itself doesn’t care where it’s run or how.

Or is this for Unit Testing of the Presentation Layer on the server from the Browser? (If so, how can a JavaScript arrange to Mock the Model layer?)

Probably not, but again, it depends on the model of your application. I’ve tried to make no assumptions, just provide you with the tools to easily test your application. I hope and expect that others will start creating the appropriate JavaScript libraries to start mocking whatever other APIs one needs to fully unit test JavaScript code that relies on such libraries.

Or is it more likely for driving Integration Testing from the browser with the scripting simplicity we’ve come to love, without resorting to OLE-stuffing the browser from Perl?

That was my initial impetus, yes.

Digging into the TAR file (which I normally wouldn’t do before peaking at the web copy of the POD2HTML’s) I think I understand it’s for unit-testing JavaScript classes, which I hadn’t even considered. (JavaScript has classes that fancy? *shudder* no wonder pages don’t work between browser versions.) I hope I don’t need to do that.

Yes, as more people follow Google’s lead, more and more applications will be appearing in JavaScript, and they will require a lot of code. JavaScript already supports a prototype-based object-orientation scheme, and if JavaScript 2.0 ever becomes a reality (please, please, please, please please!), then we’ll have real classes, namespaces, and even import, include and use! Testing will become increasingly important as more organizations come to rely on growing amounts of production JavaScript code.

Looking for the comments? Try the old layout.

Quirks of IE’s JavaScript Implementation

Just a few notes about the quirks of IE’s JavaScript implementation that I had to figure out and work around to get TestSimple working in IE.:

  • IE doesn’t like serial commas. In other words, If I create an object like this:

    var obj = {
        foo: "yow",
        bar: "bat",
    };
    

    IE will complain. It seems it doesn’t like that last comma, but it doesn’t give you a decent diagnostic message to help you figure out that that’s what it doesn’t like. Fortunately, I didn’t have to figure this one out; Marshall did And now I know to expect that IE thinks that its JavaScript should parse like SQL. Whatever!

  • You can’t truncate an array using a single argument to splice(). In Firefox, ary.splice(0) will truncate the array, but in IE, you must provide the second argument, like this: ary.splice(0, ary.length)—or else it won’t actually truncate the array.

  • Many IE JavaScript functions don’t seem to actually inherit from the Function class! I discovered this when I tried to call document.write.apply() and it failed. Not only does the apply() method not exist, but I can’t even add it! I came up with a decent workaround for this problem in TestBuilder, but I still don’t have a general solution to the problem. I did find a page that might have a general solution, but it sure is ugly.

  • IE automatically converts line endings in to the platform specific alternatives whenever you assign a JavaScript string to a text element. When Marshall showed me output that wasn’t properly adding “#” after all line endings, this was my immediate suspicion, and a quick Googling confirmed the issue. So I had to add regular expressions to look for all variations on the line endings.

I’m sure I’ll notice other issues as I work more with JavaScript, but feel free to chime in here with any gotchas you’ve noticed, and then I won’t have to work so hard to figure them out on my own in the future (and neither will you)!

Looking for the comments? Try the old layout.

JavaScript TestSimple 0.03 Released

“I’m pleased to announce the third alpha release of TestSimple, the port of Test::Builder, Test::Simple, and Test::More to JavaScript. You can download it here. This release has the following changes:

  • Removed trailing commas from 3 arrays, since IE6/Win doesn’t like them. And now everything works in IE. Thanks to Marshall Roch for tracking down and nailing this problem.

  • isNum() and isntNum() in TestBuilder.js now properly convert values to numbers using the global Number() function.

  • CurrentTest is now properly initialized to 0 when creating a new TestBuilder object.

  • Values passed to like() and unlike() that are not strings now always fail to match the regular expression.

  • plan() now outputs better error messages.

  • isDeeply() now works better with circular and repeating references.

  • diag() is now smarter about converting objects to strings before outputting them.

  • Changed isEq() and isntEq() to use simple equivalence checks (== and !=, respectively) instead of stringified comparisons, as the equivalence checks are more generally useful. Use cmpOk(got, "eq", expect) to explicitly compare stringified versions of values.

  • TestBuilder.create() now properly returns a new TestBuilder object instead of the singleton.

  • The useNumbers(), noHeader(), and noEnding() accessors will now properly assign a non-null value passed to them.

  • The arrays returned from summary() and details() now have the appropriate structures.

  • diag() now always properly adds a “#” character after newlines.

  • Added output(), failureOutput(), todoOutput(), warnOutput(), and endOutput() to TestBuilder to set up function reference to which to send output for various purposes. The first three each default to document.write, while warnOutput() defaults to window.alert and endOutout() defaults to the appendData function of a text element inside an element with the ID “test” or, failing that, window.write.

  • todo() and todoSkip() now properly add “#” after all newlines in their messages.

  • Fixed line ending escapes in diagnostics to be platform-independent. Bug reported by Marshall Roch.

  • Ported about a third of the tests from Test::Simple (which is how I caught most of the above issues). The remaining test from Test::Simple will be ported for the next release.

Many thanks to Marshall Roch for help debugging issues in IE.

Now, there is one outstanding issue I’d like to address before I would consider this production ready (aside from porting all the remaining tests from Test::Simple): how to harness the output. Harnessing breaks down into a number of issues:

How to run all tests in a single window. I might be able to write a build script that builds a single HTML file that includes all the other HTML files in iframes or some such. But then will each run in its own space without stomping on the others? And how would the harness pull in the results of each? It might be able to go into each of its children and grab the results from the TestBuilder objects…

More Feedback/advice/insults welcome!

Originally published on use Perl;

TestSimple 0.03 Released

I’m pleased to announce the third alpha release of TestSimple, the port of Test::Builder, Test::Simple, and Test::More to JavaScript. You can download it here. This release has the following changes:

  • Removed trailing commas from 3 arrays, since IE6/Win doesn’t like them. And now everything works in IE. Thanks to Marshall Roch for tracking down and nailing this problem.
  • isNum() and isntNum() in TestBuilder.js now properly convert values to numbers using the global Number() function.
  • CurrentTest is now properly initialized to 0 when creating a new TestBuilder object.
  • Values passed to like() and unlike() that are not strings now always fail to match the regular expression.
  • plan() now outputs better error messages.
  • isDeeply() now works better with circular and repeating references.
  • diag() is now smarter about converting objects to strings before outputting them.
  • Changed isEq() and isntEq() to use simple equivalence checks (== and !=, respectively) instead of stringified comparisons, as the equivalence checks are more generally useful. Use cmpOk(got, "eq", expect) to explicitly compare stringified versions of values.
  • TestBuilder.create() now properly returns a new TestBuilder object instead of the singleton.
  • The useNumbers(), noHeader(), and noEnding() accessors will now properly assign a non-null value passed to them.
  • The arrays returned from summary() and details() now have the appropriate structures.
  • diag() now always properly adds a “#” character after newlines.
  • Added output(), failureOutput(), todoOutput(), warnOutput(), and endOutput() to TestBuilder to set up function reference to which to send output for various purposes. The first three each default to document.write, while warnOutput() defaults to window.alert and endOutout() defaults to the appendData function of a text element inside an element with the ID “test” or, failing that, window.write.
  • todo() and todoSkip() now properly add “#” after all newlines in their messages.
  • Fixed line ending escapes in diagnostics to be platform-independent. Bug reported by Marshall Roch.
  • Ported about a third of the tests from Test::Simple (which is how I caught most of the above issues). The remaining test from Test::Simple will be ported for the next release.

Many thanks to Marshall Roch for help debugging issues in IE.

Now, there is one outstanding issue I’d like to address before I would consider this production ready (aside from porting all the remaining tests from Test::Simple): how to harness the output. Harnessing breaks down into a number of issues:

How to run all tests in a single window. I might be able to write a build script that builds a single HTML file that includes all the other HTML files in iframes or some such. But then will each run in its own space without stomping on the others? And how would the harness pull in the results of each? It might be able to go into each of its children and grab the results from the TestBuilder objects…

More Feedback/advice/insults welcome!

Looking for the comments? Try the old layout.

How do I Add apply() to IE JavaScript Functions

This is really bugging me. I’ve added a feature to my TestSimple JavaScript library where one can specify a function to which to send test output. It executes the function, along with an object, if necessary, by calling its apply() method. If you don’t specify a function for output, it uses document.write by default:

if (!fn) {
    fn = document.write;
    obj = document;
}
var output = function () { fn.apply(obj, arguments) };

This works great in Firefox, as I can then just call fn.apply(this, arguments) and the arguments are properly passed on through to the function.

However, Internet Explorer doesn’t seem to have an apply() method on its write() function. If I execute document.write.apply(document ['foo']) in Firefox, it outputs “foo” to the browser. In Internet Explorer for Windows, however, it yields an error: “Object doesn’t support this property or method.” Wha??

I thought I could get around it by just adding the apply() method to document.write, but that doesn’t work, either. This code:

document.write.apply = Function.prototype.apply;
document.write.apply(document, ['foo']);

Yields the same error. Curiously, so does this code:

document.write.apply2 = Function.prototype.apply;
document.write.apply2(document, ['foo']);

So it seems that assigning a function to document.write is a no-op in IE. WTF?

So does anyone know a workaround for this bug? I found a page that says, “Beware that some native functions in IE were made to look like objects instead of functions.” This might explain why apply() doesn’t exist for the document.write object, but not why I can’t add it.

Help!

Looking for the comments? Try the old layout.

Control iTunes from Emacs

This has to be one of the geekiest things I’ve ever seen: You can control iTunes from Emacs! The nice thing about it is that you can control iTunes remotely via a terminal session.

Looking for the comments? Try the old layout.

TestSimple 0.02 Released

I’m pleased to announce the second alpha release of TestSimple, the port of Test::Builder, Test::Simple, and Test::More to JavaScript. You can download it here. This release has the following changes:

  • Removed eqArray() and eqAssoc() functions from TestMore per suggestion from Michael Schwern. The problem is that these are not test functions, and so are inconsistent with the way the rest of the functions work. isDeeply() is the function that users really want.
  • Changed eqSet() to isSet() and made it into a real test function.
  • Implemented skip(), todoSkip(), and todo(). These are a bit different than the Perl originals originals so read the docs!
  • Implemented skipAll() and BAILOUT() using exceptions and an exception handler installed in window.onerror.
  • The final message of a test file now properly outputs in the proper place. Tests must be run inside an element its “id” attribute set to “test”, such as <pre id="test">. The window.onload handler will find it and append the final test information.
  • Implemented skipRest() in TestBuilder and TestMore. This method is stubbed out the Perl original, but not yet implemented there!

The only truly outstanding issues I see before I would consider these “modules” ready for production use are:

  • Figure out how to get at file names and line numbers for better diagnostic messages. Is this even possible in JavaScript?
  • Decide where to send test output, and where to allow other output to be sent. Test::Builder clones STDERR and STDOUT for this purpose. We’ll probably have to do it by overriding document.write()>, but it’d be good to allow users to define alternate outputs (tests may not always run in a browser, eh?). Maybe we can use an output object? Currently, a browser and its DOM are expected to be present. I could really use some advice from real JavaScript gurus on this one.
  • Write tests!

Feedback/advice/insults welcome!

Looking for the comments? Try the old layout.

JavaScript TestSimple 0.02 Released

I’m pleased to announce the second alpha release of TestSimple, the port of Test::Builder, Test::Simple, and Test::More to JavaScript. You can download it here. This release has the following changes:

  • Removed eqArray() and eqAssoc() functions from TestMore per suggestion from Michael Schwern. The problem is that these are not test functions, and so are inconsistent with the way the rest of the functions work. isDeeply() is the function that users really want.

  • Changed eqSet() to isSet() and made it into a real test function.

  • Implemented skip(), todoSkip(), and todo(). These are a bit different than the Perl originals originals so read the docs!

  • Implemented skipAll() and BAILOUT() using exceptions and an exception handler installed in window.onerror.

  • The final message of a test file now properly outputs in the proper place. Tests must be run inside an element its “id” attribute set to “test”, such as <pre id="test">. The window.onload handler will find it and append the final test information.

  • Implemented skipRest() in TestBuilder and TestMore. This method is stubbed out the Perl original, but not yet implemented there!

The only truly outstanding issues I see before I would consider these “modules” ready for production use are:

  • Figure out how to get at file names and line numbers for better diagnostic messages. Is this even possible in JavaScript?

  • Decide where to send test output, and where to allow other output to be sent. Test::Builder clones STDERR and STDOUT for this purpose. We’ll probably have to do it by overriding document.write()>, but it’d be good to allow users to define alternate outputs (tests may not always run in a browser, eh?). Maybe we can use an output object? Currently, a browser and its DOM are expected to be present. I could really use some advice from real JavaScript gurus on this one.

  • Write tests!

Feedback/advice/insults welcome!

Originally published on use Perl;

New JavaScript Testing Method: TestSimple

I’m pleased to announce the first alpha release of my port of [Test::Simple/Test::Builder/Test::More] to JavaScript. Download it now and let me know what you think!

You can see what the tests look like by loading the files in the tests/ directory into your Web browser. This is my first stab at what I hope becomes a complete port. I could use some feedback/ideas on a number of outstanding issues:

  • I have made no decisions as to where to output test results, diagnostics, etc. Currently, they’re simply output to document.write(). This may well be the best place in the long run, though it might be nice to allow users to configure where output goes. It will also be easy to control the output, since the output functions can easily be replaced in JavaScript. Suggestions welcome.

  • I have no idea how to exit execution of tests other than by throwing an exception, which is only supported by JavaScript 1.5, anyway, AFAIK. As a result, skipAll(), BAILOUT(), and skipRest() do not work.

  • Skip and Todo tests currently don’t work because named blocks (e.g., SKIP: and TODO:) are lexical in JavaScript. Therefore I cannot get at them from within a function called from within a block (at least not that I can tell). It might be that I need to just pass function references to skip() and todo(), instead. This is a rather different interface than that supported by Test::More, but it might work. Thoughts?

  • Currently, one must call Test._ending() to finish running tests. This is because there is no END block to grab on to in JavaScript. Suggestions for how to capture output and append the output of _ending() are welcome. It might work to have the onload event execute it, but then it will have to look for the proper context in which to append it (a <pre> tag, at this point).

  • Anyone have any idea how to get at the line number and file name in a JavaScript? Failures currently aren’t too descriptive. As a result, I’m not sure if level() will have any part to play.

  • Is there threading in JavaScript?

  • I haven’t written TestHarness yet. It may not make sense to even have such a thing in JavaScript; I’m not sure.

  • I’m using a Module::Build script to build a distribution. I don’t think there’s a standard for distributing JavaScript libraries, but I think that this works reasonably well. I have all of the documentation in POD, and the script generates HTML and text versions before creating the tarball. The Build.PL script of course is not included in the distribution. I started out trying to write the documentation in JSDoc, but abandoned it for all of the reasons I recounted last week.

  • Is there a way to dynamically load a JavaScript file? I’d like to use an approach to have TestMore.js and TestSimple.js load TestBuilder.js. I’d also like to use it to implement loadOk() (equivalent to Test::More’s use_ok() and require_ok() subroutines).

More details are in the ToDo section of the TestBuilder docs.

Let me know what you think!

Originally published on use Perl;

New JavaScript Testing Method: TestSimple

I’m pleased to announce the first alpha release of my port of Test::Simple/Test::More/Test::Builder to JavaScript. Download it now and let me know what you think!

You can see what the tests look like by loading the files in the tests/ directory into your Web browser. This is my first stab at what I hope becomes a complete port. I could use some feedback/ideas on a number of outstanding issues:

  • I have made no decisions as to where to output test results, diagnostics, etc. Currently, they’re simply output to document.write(). This may well be the best place in the long run, though it might be nice to allow users to configure where output goes. It will also be easy to control the output, since the output functions can easily be replaced in JavaScript. Suggestions welcome.
  • I have no idea how to exit execution of tests other than by throwing an exception, which is only supported by JavaScript 1.5, anyway, AFAIK. As a result, skipAll(), BAILOUT(), and skipRest() do not work.
  • Skip and Todo tests currently don’t work because named blocks (e.g., SKIP: and TODO:) are lexical in JavaScript. Therefore I cannot get at them from within a function called from within a block (at least not that I can tell). It might be that I need to just pass function references to skip() and todo(), instead. This is a rather different interface than that supported by Test::More, but it might work. Thoughts?
  • Currently, one must call Test._ending() to finish running tests. This is because there is no END block to grab on to in JavaScript. Suggestions for how to capture output and append the output of _ending() are welcome. It might work to have the onload event execute it, but then it will have to look for the proper context in which to append it (a <pre> tag, at this point).
  • Anyone have any idea how to get at the line number and file name in a JavaScript? Failures currently aren’t too descriptive. As a result, I’m not sure if level() will have any part to play.
  • Is there threading in JavaScript?
  • I haven’t written TestHarness yet. It may not make sense to even have such a thing in JavaScript; I’m not sure.
  • I’m using a Module::Build script to build a distribution. I don’t think there’s a standard for distributing JavaScript libraries, but I think that this works reasonably well. I have all of the documentation in POD, and the script generates HTML and text versions before creating the tarball. The Build.PL script of course is not included in the distribution. I started out trying to write the documentation in JSDoc, but abandoned it for all of the reasons I recounted last week.
  • Is there a way to dynamically load a JavaScript file? I’d like to use an approach to have TestMore.js and TestSimple.js load TestBuilder.js. I’d also like to use it to implement loadOk() (equivalent to Test::More’s use_ok() and require_ok() subroutines).

More details are in the ToDo section of the TestBuilder docs.

Let me know what you think!

Looking for the comments? Try the old layout.

JSDoc Doesn’t Quite do the Trick for Me

After my request for JavaScript documentation standards, I investigated the one I found myself: JSDoc. I went ahead and used its syntax to document a JavaScript class I’d written, and it seemed to work pretty well. Initially, my main complaint was that their was no easy way to include arbitrary documentation. Everything has to be associated with a constructor, attribute, or method. Bleh.

But then I started documenting two purely functional JavaScript files I’d written. These just create functions in the Global scope for general use. And here’s where JSDoc started to really become a PITA. First, functions with the same names in the two files were declared to be pre-declared! They two files are part of the same project, but users will generally use one or the other, not both. But JSDoc has taken it upon itself to refuse to document functions that are in two different files in the same project. Surely that’s the JavaScript interpreter’s responsibility!

The next issue I ran into (after I commented out the code in JSDoc.pm that refused to document functions with the same names) was that it didn’t recognize one of the files as having documentation, because there was no constructor. Well duh! A purely functional implementation doesn’t have a constructor! It seems that Java’s bias for OO-only implementations has unduly influenced JSDoc, even though JavaScript applications often define no classes at all!

The clincher in my decision to ditch JSDoc, however, came when I realized that, for most projects, I won’t want the documentation in the same file as the code. While I generally prefer that they be in the same file, I will often have 4-10 times more documentation than actual code, and the bandwidth overhead seems unnecessary. JavaDoc and JSDoc of course require that any documentation be in the same files, since that’s where they parse method signatures and such.

So I think I’ll follow Chris Dolan’s advice from my original post and fall back on Good ‘ole POD. POD allows me to write as much or as little documentation as I like, with methods and functions documented in an order that makes sense to me, with headings even! I can write long descriptions, synopses, and even documentation completely unrelated to specifics of the interface. And all in a separate file, even!

This will do until someone formalizes a standard for JavaScript. Maybe it’ll be KwiD?

Looking for the comments? Try the old layout.

Is there a JavaScript Library Documentation Standard?

Is there a JavaScript documentation standard? I’ve been working on a test framework for JavaScript and I’d like to integrate documentation so that others can use it.

If there isn’t a documentation standard, I can see three possible options that I’d like to suggest:

Use XHTML.

Since JavaScript is mainly used for XHTML, it makes some sense to just use XHTML for its documentation. The downside to this is that there is currently no way to parse out the documentation, AFAIK. The format for putting the docs into comments would have to be standardized. I don’t really see that happening.

Use POD.

JavaScript is a dynamic language; it’d make some sense to use the documentation format of an existing dynamic language. And POD is a proven format. The downside, of course, is that there is not a parser for pulling POD out of a .js file. Same problem as for XHTML, essentially.

Use JavaDoc

Since the syntax of JavaScript is roughly based on JavaScript, and JavaScript supports the same comment syntax, one could simply use the JavaDoc format. The javadoc application probably couldn’t parse it out too well, since it parses the Java code (or byte code?) to automatically document method names, signatures, etc.

But a quick Googling yields JSDoc as a possible solution. The only downside to the JavaDoc/JSDoc solution is that it tends to allow authors to be too lazy. Since the application automatically documents the existence of functions and their signatures, often little else is documented. But that’s mainly a personal issue; I don’t have to be so lazy in my own documentation! I think I’ll give that a shot.

Meanwhile, if anyone knows of something better/more widely used, let me know!

Looking for the comments? Try the old layout.

Regular Expressions are Faster than Unpacking

Bricolage has always used unpack() to parse ISO-8601 date strings into their component parts. A few months back, I added support for subsecond precision using the DateTime, and couldn’t figure out how to parse out the optional subsecond part of the date (If it’s 0, PostgreSQL doesn’t include the decimal part of the seconds). So I switched to parsing with the regular expression /(\d\d\d\d).(\d\d).(\d\d).(\d\d).(\d\d).(\d\d)(\.\d*)?/. This worked well, but I lamented the loss of performance of unpack(). I mean, surely it’s faster to tell a parser where, exactly, to find each characters, than it is to use a pattern, right?

Well, last week I finally figured out how to unpack the decimal place using unpack() whether it’s there or not (the secret is the * modifier, which somehow I’d never noticed before). So I ran a benchmark to see how much of a performance gain I would get:

#!/usr/bin/perl -w
use strict;
use Benchmark;

my $date = '2005-03-23T19:30:05.1234';
my $ISO_TEMPLATE =  'a4 x a2 x a2 x a2 x a2 x a2 a*';

sub with_pack {
    my %args;
    @args{qw(year month day hour minute second nanosecond)}
        = unpack $ISO_TEMPLATE, $date;
    {
        no warnings;
        $args{nanosecond} *= 1.0E9;
    }
}

sub with_regex {
    $date =~ m/(\d\d\d\d).(\d\d).(\d\d).(\d\d).(\d\d).(\d\d)(\.\d*)?/;
    my %args = (
        year       => $1,
        month      => $2,
        day        => $3,
        hour       => $4,
        minute     => $5,
        second     => $6,
        nanosecond => $7 ? $7 * 1.0E9 : 0
    );
}

timethese(100000, {
    pack => \&with_pack,
    regex => \&with_regex
});

__END__

I quickly got my answer (all hail Benchmark!). This script outputs:

  Benchmark: timing 100000 iterations of pack, regex...
        pack:  3 wallclock secs ( 2.14 usr +  0.00 sys =  2.14 CPU) @ 46728.97/s (n=100000)
       regex:  3 wallclock secs ( 2.11 usr +  0.01 sys =  2.12 CPU) @ 47169.81/s (n=100000)

I sure didn’t expect them to be so close, let alone to see the regular expression approach nose out the unpack() solution. Clearly the Perl regex engine is highly optimized. And perhaps pack()/unpack() is not.

Live and learn, I guess.

Looking for the comments? Try the old layout.

Bricolage 1.8.5 Released

The Bricolage development team is pleased to announce the release of Bricolage 1.8.5. This maintenance release addresses a number of issues in Bricolage 1.8.3 and adds a number of improvements (there was no announcement for the short-lived 1.8.4 release). The SOAP server in particular sees improvements in this release, with improved character set support; better support for related stories and media using URIs in addition to IDs; and as support for top-level element relations. Issues with the ordering of story elements have also been corrected, as well as errors when attempting to revert a story or media document or template. Here are the other highlights of this release:

Improvements

  • Added Linux startup script contrib/start_scripts/linux. [David]
  • Related story and media elements managed through the SOAP server can now use a combination of URI and site ID to identify related assets in addition to the existing approach of using story and media IDs. [David]
  • A list of subelements is now less likely to mysteriously become out of order and thus lead to strange action-at-a-distance errors. And even if they do become out of order, the error message will be more appropriate (“Warning! State inconsistent” instead of “Can’t call method “get_name” on an undefined value”). Reported by Curtis Poe. [David]
  • The SOAP media interface now supports creating relationships between the media documents elements and other story and media documents, just like the SOAP story interface does. [David]
  • The SOAP interface now supports Related stories and media on story type and media type elements just as in the UI. This involved the somewhat hackish necessity for including the “related_story_id” and “related_media_id” (or “related_story_uri” and “related_media_uri”) attributes in the “elements” XML element, but it does the trick. [David]

Bug Fixes

  • Calls to publish documents via SOAP will no longer fail if the published_version attribute is not specified and the document to be published has never been published before. [David]
  • The Bricolage virtual FTP server will no longer fail to start if Template Toolkit is installed but its version number is less than 2.14. Reported by Adam Rinehart. [David]
  • Stories and Media created or updated via the SOAP interface will now associate contributors of the appropriate type, instead of “All Contributors”. [Scott & David]
  • Deleting an element that has a template no longer causes an error. Thanks to Susan for the spot! [David]
  • Eliminated encoding errors when using the SOAP interface to output stories, media, or templates with wide characters. Reported by Scott Lanning. [David]
  • Reverting (stories, media, templates) no longer gives an error. Reported by Simon Wilcox, Rachel Murray, and others. [David]
  • Publishing a published version of a document that has a later version in workflow will no longer cause that later version to be mysteriously removed from workflow. This could be caused by passing a document looked up using the published_version to list() to $burner->publish_another in a template. [David]
  • The SOAP server story and media interfaces now support elements that contain both related stories and media, rather than one or the other. [David]
  • Attempting to preview a story or media document currently checked out to another user no longer causes an error. Reported by Paul Orrock. [David]
  • Custom fields with default values now have their values included when they are added to stories and media. Thanks to Clare Parkinson for the spot! [David]
  • The bric_queued script now requires a username and password and will authenticate the user. This user will then be used for logging events. All events logged when a job is run via the UI are now also logged by bric_queued. [Mark and David]
  • Preview redirections now use the protocol setting of the preview output channel if it’s available, and falls back on using “http://” when it’s not, instead of using the hard-coded “http://”. Thanks to Martin Bacovsky for the spot! [David]
  • The has_keyword() method in the Business class (from which the story and media classes inherit) now works. Thanks to Clare Parkinson for the spot! [David]
  • Clicking a link in the left-side navigation after the session has expired now causes the whole window to show the login form, rather than it showing inside the nav frame, which was useless. [Marshall]
  • The JavaScript that validates form contents once again works with htmlArea, provided htmlArea itself is patched. See the relevant htmlArea bug report for the patch. As of this writing, you must run the version of htmlArea in CVS. [David & Marshall]
  • The JavaScript that handles the double list manager has been vastly optimized. It should now be able to better handle large lists, such as a list of thousands of categories. Reported by Scott. [Marshall]
  • Uploading a new image to a media document with a different media type than the previous image no longer causes an Imager error. [David]

For a complete list of the changes, see the changes. For the complete history of ongoing changes in Bricolage, see Bric::Changes.

Download Bricolage 1.8.5 now from the Bricolage Web site Downloads page, from the SourceForge download page, and from the Kineticode download page.

About Bricolage

Bricolage is a full-featured, enterprise-class content management and publishing system. It offers a browser-based interface for ease-of use, a full-fledged templating system with complete HTML::Mason, HTML::Template, and Template Toolkit support for flexibility, and many other features. It operates in an Apache/mod_perl environment and uses the PostgreSQL RDBMS for its repository. A comprehensive, actively-developed open source CMS, Bricolage was hailed as “quite possibly the most capable enterprise-class open-source application available” by eWEEK.

Looking for the comments? Try the old layout.

Bricolage 1.8.5 Released

The Bricolage development team is pleased to announce the release of Bricolage 1.8.5. This maintenance release addresses a number of issues in Bricolage 1.8.3 and adds a number of improvements (there was no announcement for the short-lived 1.8.4 release). The SOAP server in particular sees improvements in this release, with improved character set support; better support for related stories and media using URIs in addition to IDs; and as support for top-level element relations. Issues with the ordering of story elements have also been corrected, as well as errors when attempting to revert a story or media document or template. Here are the other highlights of this release:

Improvements

  • Added Linux startup script contrib/start_scripts/linux. [David]

  • Related story and media elements managed through the SOAP server can now use a combination of URI and site ID to identify related assets in addition to the existing approach of using story and media IDs. [David]

  • A list of subelements is now less likely to mysteriously become out of order and thus lead to strange action-at-a-distance errors. And even if they do become out of order, the error message will be more appropriate (“Warning! State inconsistent” instead of “Can’t call method “get_name” on an undefined value”). Reported by Curtis Poe. [David]

  • The SOAP media interface now supports creating relationships between the media documents elements and other story and media documents, just like the SOAP story interface does. [David]

  • The SOAP interface now supports Related stories and media on story type and media type elements just as in the UI. This involved the somewhat hackish necessity for including the “related_story_id” and “related_media_id” (or “related_story_uri” and “related_media_uri”) attributes in the “elements” XML element, but it does the trick. [David]

Bug Fixes

  • Calls to publish documents via SOAP will no longer fail if the published_version attribute is not specified and the document to be published has never been published before. [David]

  • The Bricolage virtual FTP server will no longer fail to start if Template Toolkit is installed but its version number is less than 2.14. Reported by Adam Rinehart. [David]

  • Stories and Media created or updated via the SOAP interface will now associate contributors of the appropriate type, instead of “All Contributors”. [Scott & David]

  • Deleting an element that has a template no longer causes an error. Thanks to Susan for the spot! [David]

  • Eliminated encoding errors when using the SOAP interface to output stories, media, or templates with wide characters. Reported by Scott Lanning. [David]

  • Reverting (stories, media, templates) no longer gives an error. Reported by Simon Wilcox, Rachel Murray, and others. [David]

  • Publishing a published version of a document that has a later version in workflow will no longer cause that later version to be mysteriously removed from workflow. This could be caused by passing a document looked up using the published_version to list() to $burner->publish_another in a template. [David]

  • The SOAP server story and media interfaces now support elements that contain both related stories and media, rather than one or the other. [David]

  • Attempting to preview a story or media document currently checked out to another user no longer causes an error. Reported by Paul Orrock. [David]

  • Custom fields with default values now have their values included when they are added to stories and media. Thanks to Clare Parkinson for the spot! [David]

  • The bric_queued script now requires a username and password and will authenticate the user. This user will then be used for logging events. All events logged when a job is run via the UI are now also logged by bric_queued. [Mark and David]

  • Preview redirections now use the protocol setting of the preview output channel if it’s available, and falls back on using “http://” when it’s not, instead of using the hard-coded “http://”. Thanks to Martin Bacovsky for the spot! [David]

  • The has_keyword() method in the Business class (from which the story and media classes inherit) now works. Thanks to Clare Parkinson for the spot! [David]

  • Clicking a link in the left-side navigation after the session has expired now causes the whole window to show the login form, rather than it showing inside the nav frame, which was useless. [Marshall]

  • The JavaScript that validates form contents once again works with htmlArea, provided htmlArea itself is patched. See the relevant htmlArea bug report for the patch. As of this writing, you must run the version of htmlArea in CVS. [David & Marshall]

  • The JavaScript that handles the double list manager has been vastly optimized. It should now be able to better handle large lists, such as a list of thousands of categories. Reported by Scott. [Marshall]

  • Uploading a new image to a media document with a different media type than the previous image no longer causes an Imager error. [David]

For a complete list of the changes, see the changes. For the complete history of ongoing changes in Bricolage, see Bric::Changes.

Download Bricolage 1.8.5 now from the Bricolage Web site Downloads page, from the SourceForge download page, and from the Kineticode download page.

About Bricolage

Bricolage is a full-featured, enterprise-class content management and publishing system. It offers a browser-based interface for ease-of use, a full-fledged templating system with complete HTML::Mason, HTML::Template, and Template Toolkit support for flexibility, and many other features. It operates in an Apache/mod_perl environment and uses the PostgreSQL RDBMS for its repository. A comprehensive, actively-developed open source CMS, Bricolage was hailed as “quite possibly the most capable enterprise-class open-source application available” by eWEEK.

Originally published on use Perl;