Instantiating a JavaScript object by calling prototype.constructor.apply

I’ve done more investigation of my own and came up with the conclusion that this is an impossible feat, due to how the Date class is implemented.

I’ve inspected the SpiderMonkey source code to see how Date was implemented. I think it all boils down to the following few lines:

static JSBool
Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
    jsdouble *date;
    JSString *str;
    jsdouble d;

    /* Date called as function. */
    if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
        int64 us, ms, us2ms;
        jsdouble msec_time;

        /* NSPR 2.0 docs say 'We do not support PRMJ_NowMS and PRMJ_NowS',
         * so compute ms from PRMJ_Now.
         */
        us = PRMJ_Now();
        JSLL_UI2L(us2ms, PRMJ_USEC_PER_MSEC);
        JSLL_DIV(ms, us, us2ms);
        JSLL_L2D(msec_time, ms);

        return date_format(cx, msec_time, FORMATSPEC_FULL, rval);
    }

    /* Date called as constructor. */
    // ... (from here on it checks the arg count to decide how to create the date)

When Date is used as a function (either as Date() or Date.prototype.constructor(), which are exactly the same thing), it defaults to returning the current time as a string in the locale format. This is regardless of any arguments that are passed in:

alert(Date()); // Returns "Thu Oct 09 2008 23:15:54 ..."
alert(typeof Date()); // Returns "string"

alert(Date(42)); // Same thing, "Thu Oct 09 2008 23:15:54 ..."
alert(Date(2008, 10, 10)); // Ditto
alert(Date(null)); // Just doesn't care

I don’t think there’s anything that can be done at the JS level to circumvent this. And this is probably the end of my pursuit in this topic.

I’ve also noticed something interesting:

    /* Set the value of the Date.prototype date to NaN */
    proto_date = date_constructor(cx, proto);
    if (!proto_date)
        return NULL;
    *proto_date = *cx->runtime->jsNaN;

Date.prototype is a Date instance with the internal value of NaN and therefore,

alert(Date.prototype); // Always returns "Invalid Date"
                       // on Firefox, Opera, Safari, Chrome
                       // but not Internet Explorer

IE doesn’t disappoint us. It does things a bit differently and probably sets the internal value to -1 so that Date.prototype always returns a date slightly before epoch.


Update

I’ve finally dug into ECMA-262 itself and it turns out, what I’m trying to achieve (with the Date object) is — by definition — not possible:

15.9.2 The Date Constructor Called as a Function

When Date is called as a
function rather than as a constructor,
it returns a string representing the
current time (UTC).

NOTE The function
call Date(…) is not equivalent to the
object creation expression new Date(…)
with the same arguments.

15.9.2.1 Date ( [ year [, month [, date [, hours [, minutes [, seconds [,
ms ] ] ] ] ] ] ] )

All of the
arguments are optional; any arguments
supplied are accepted but are
completely ignored. A string is
created and returned as if by the
expression (new Date()).toString().

Leave a Comment