예제 #1
0
파일: jsexn.cpp 프로젝트: ahadzi/celtx
/*
 * Convert to string.
 *
 * This method only uses JavaScript-modifiable properties name, message.  It
 * is left to the host to check for private data and report filename and line
 * number information along with this message.
 */
static JSBool
exn_toString(JSContext *cx, uintN argc, jsval *vp)
{
    JSObject *obj;
    jsval v;
    JSString *name, *message, *result;
    jschar *chars, *cp;
    size_t name_length, message_length, length;

    obj = JS_THIS_OBJECT(cx, vp);
    if (!obj ||
        !OBJ_GET_PROPERTY(cx, obj,
                          ATOM_TO_JSID(cx->runtime->atomState.nameAtom),
                          &v)) {
        return JS_FALSE;
    }
    name = JSVAL_IS_STRING(v) ? JSVAL_TO_STRING(v) : cx->runtime->emptyString;
    *vp = STRING_TO_JSVAL(name);

    if (!JS_GetProperty(cx, obj, js_message_str, &v))
        return JS_FALSE;
    message = JSVAL_IS_STRING(v) ? JSVAL_TO_STRING(v)
                                 : cx->runtime->emptyString;

    if (JSSTRING_LENGTH(message) != 0) {
        name_length = JSSTRING_LENGTH(name);
        message_length = JSSTRING_LENGTH(message);
        length = (name_length ? name_length + 2 : 0) + message_length;
        cp = chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar));
        if (!chars)
            return JS_FALSE;

        if (name_length) {
            js_strncpy(cp, JSSTRING_CHARS(name), name_length);
            cp += name_length;
            *cp++ = ':'; *cp++ = ' ';
        }
        js_strncpy(cp, JSSTRING_CHARS(message), message_length);
        cp += message_length;
        *cp = 0;

        result = js_NewString(cx, chars, length);
        if (!result) {
            JS_free(cx, chars);
            return JS_FALSE;
        }
    } else {
        result = name;
    }

    *vp = STRING_TO_JSVAL(result);
    return JS_TRUE;
}
예제 #2
0
/*
 * Convert to string.
 *
 * This method only uses JavaScript-modifiable properties name, message.  It
 * is left to the host to check for private data and report filename and line
 * number information along with this message.
 */
static JSBool
exn_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
    jsval v;
    JSString *name, *message, *result;
    jschar *chars, *cp;
    size_t name_length, message_length, length;

    if (!OBJ_GET_PROPERTY(cx, obj, (jsid)cx->runtime->atomState.nameAtom, &v))
        return JS_FALSE;
    name = js_ValueToString(cx, v);
    if (!name)
        return JS_FALSE;

    if (!JS_GetProperty(cx, obj, js_message_str, &v) ||
        !(message = js_ValueToString(cx, v))) {
        return JS_FALSE;
    }

    if (JSSTRING_LENGTH(message) != 0) {
        name_length = JSSTRING_LENGTH(name);
        message_length = JSSTRING_LENGTH(message);
        length = name_length + message_length + 2;
        cp = chars = (jschar*) JS_malloc(cx, (length + 1) * sizeof(jschar));
        if (!chars)
            return JS_FALSE;

        js_strncpy(cp, JSSTRING_CHARS(name), name_length);
        cp += name_length;
        *cp++ = ':'; *cp++ = ' ';
        js_strncpy(cp, JSSTRING_CHARS(message), message_length);
        cp += message_length;
        *cp = 0;

        result = js_NewString(cx, chars, length, 0);
        if (!result) {
            JS_free(cx, chars);
            return JS_FALSE;
        }
    } else {
        result = name;
    }

    *rval = STRING_TO_JSVAL(result);
    return JS_TRUE;
}
예제 #3
0
/*
 * The arguments from ap need to be packaged up into an array and stored
 * into the report struct.
 *
 * The format string addressed by the error number may contain operands
 * identified by the format {N}, where N is a decimal digit. Each of these
 * is to be replaced by the Nth argument from the va_list. The complete
 * message is placed into reportp->ucmessage converted to a JSString.
 *
 * Returns true if the expansion succeeds (can fail if out of memory).
 */
JSBool
js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
                        void *userRef, const uintN errorNumber,
                        char **messagep, JSErrorReport *reportp,
                        JSBool *warningp, JSBool charArgs, va_list ap)
{
    const JSErrorFormatString *efs;
    int i;
    int argCount;

    *warningp = JSREPORT_IS_WARNING(reportp->flags);
    if (*warningp && JS_HAS_WERROR_OPTION(cx)) {
        reportp->flags &= ~JSREPORT_WARNING;
        *warningp = JS_FALSE;
    }

    *messagep = NULL;
    if (callback) {
        efs = callback(userRef, NULL, errorNumber);
        if (efs) {
            size_t totalArgsLength = 0;
            size_t argLengths[10]; /* only {0} thru {9} supported */
            argCount = efs->argCount;
            JS_ASSERT(argCount <= 10);
            if (argCount > 0) {
                /*
                 * Gather the arguments into an array, and accumulate
                 * their sizes. We allocate 1 more than necessary and
                 * null it out to act as the caboose when we free the
                 * pointers later.
                 */
                reportp->messageArgs = (const jschar **)
                    JS_malloc(cx, sizeof(jschar *) * (argCount + 1));
                if (!reportp->messageArgs)
                    return JS_FALSE;
                reportp->messageArgs[argCount] = NULL;
                for (i = 0; i < argCount; i++) {
                    if (charArgs) {
                        char *charArg = va_arg(ap, char *);
                        reportp->messageArgs[i]
                            = js_InflateString(cx, charArg, strlen(charArg));
                        if (!reportp->messageArgs[i])
                            goto error;
                    }
                    else
                        reportp->messageArgs[i] = va_arg(ap, jschar *);
                    argLengths[i] = js_strlen(reportp->messageArgs[i]);
                    totalArgsLength += argLengths[i];
                }
                /* NULL-terminate for easy copying. */
                reportp->messageArgs[i] = NULL;
            }
            /*
             * Parse the error format, substituting the argument X
             * for {X} in the format.
             */
            if (argCount > 0) {
                if (efs->format) {
                    const char *fmt;
                    const jschar *arg;
                    jschar *out;
                    int expandedArgs = 0;
                    size_t expandedLength
                        = strlen(efs->format)
                            - (3 * argCount) /* exclude the {n} */
                            + totalArgsLength;
                    /*
                     * Note - the above calculation assumes that each argument
                     * is used once and only once in the expansion !!!
                     */
                    reportp->ucmessage = out = (jschar *)
                        JS_malloc(cx, (expandedLength + 1) * sizeof(jschar));
                    if (!out)
                        goto error;
                    fmt = efs->format;
                    while (*fmt) {
                        if (*fmt == '{') {
                            if (isdigit(fmt[1])) {
                                int d = JS7_UNDEC(fmt[1]);
                                JS_ASSERT(expandedArgs < argCount);
                                arg = reportp->messageArgs[d];
                                js_strncpy(out, arg, argLengths[d]);
                                out += argLengths[d];
                                fmt += 3;
                                expandedArgs++;
                                continue;
                            }
                        }
                        /*
                         * is this kosher?
                         */
                        *out++ = (unsigned char)(*fmt++);
                    }
                    JS_ASSERT(expandedArgs == argCount);
                    *out = 0;
                    *messagep =
                        js_DeflateString(cx, reportp->ucmessage,
                                         (size_t)(out - reportp->ucmessage));
                    if (!*messagep)
                        goto error;
                }
            } else {
                /*
                 * Zero arguments: the format string (if it exists) is the
                 * entire message.
                 */
                if (efs->format) {
                    *messagep = JS_strdup(cx, efs->format);
                    if (!*messagep)
                        goto error;
                    reportp->ucmessage
                        = js_InflateString(cx, *messagep, strlen(*messagep));
                    if (!reportp->ucmessage)
                        goto error;
                }
            }
        }
예제 #4
0
/*
 * Return a string that may eval to something similar to the original object.
 */
static JSBool
exn_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
    jsval v;
    JSString *name, *message, *filename, *lineno_as_str, *result;
    int32 lineno;
    size_t lineno_length, name_length, message_length, filename_length, length;
    jschar *chars, *cp;

    if (!OBJ_GET_PROPERTY(cx, obj, (jsid)cx->runtime->atomState.nameAtom, &v))
        return JS_FALSE;
    name = js_ValueToString(cx, v);
    if (!name)
        return JS_FALSE;

    if (!JS_GetProperty(cx, obj, js_message_str, &v) ||
        !(message = js_ValueToSource(cx, v))) {
        return JS_FALSE;
    }

    if (!JS_GetProperty(cx, obj, js_filename_str, &v) ||
        !(filename = js_ValueToSource(cx, v))) {
        return JS_FALSE;
    }

    if (!JS_GetProperty(cx, obj, js_lineno_str, &v) ||
        !js_ValueToInt32 (cx, v, &lineno)) {
        return JS_FALSE;
    }

    if (lineno != 0) {
        if (!(lineno_as_str = js_ValueToString(cx, v))) {
            return JS_FALSE;
        }
        lineno_length = JSSTRING_LENGTH(lineno_as_str);
    } else {
        lineno_as_str = NULL;
        lineno_length = 0;
    }

    /* Magic 8, for the characters in ``(new ())''. */
    name_length = JSSTRING_LENGTH(name);
    message_length = JSSTRING_LENGTH(message);
    length = 8 + name_length + message_length;

    filename_length = JSSTRING_LENGTH(filename);
    if (filename_length != 0) {
        /* append filename as ``, {filename}'' */
        length += 2 + filename_length;
        if (lineno_as_str) {
            /* append lineno as ``, {lineno_as_str}'' */
            length += 2 + lineno_length;
        }
    } else {
        if (lineno_as_str) {
            /*
             * no filename, but have line number,
             * need to append ``, "", {lineno_as_str}''
             */
            length += 6 + lineno_length;
        }
    }

    cp = chars = (jschar*) JS_malloc(cx, (length + 1) * sizeof(jschar));
    if (!chars)
        return JS_FALSE;

    *cp++ = '('; *cp++ = 'n'; *cp++ = 'e'; *cp++ = 'w'; *cp++ = ' ';
    js_strncpy(cp, JSSTRING_CHARS(name), name_length);
    cp += name_length;
    *cp++ = '(';
    if (message_length != 0) {
        js_strncpy(cp, JSSTRING_CHARS(message), message_length);
        cp += message_length;
    }

    if (filename_length != 0) {
        /* append filename as ``, {filename}'' */
        *cp++ = ','; *cp++ = ' ';
        js_strncpy(cp, JSSTRING_CHARS(filename), filename_length);
        cp += filename_length;
    } else {
        if (lineno_as_str) {
            /*
             * no filename, but have line number,
             * need to append ``, "", {lineno_as_str}''
             */
            *cp++ = ','; *cp++ = ' '; *cp++ = '"'; *cp++ = '"';
        }
    }
    if (lineno_as_str) {
        /* append lineno as ``, {lineno_as_str}'' */
        *cp++ = ','; *cp++ = ' ';
        js_strncpy(cp, JSSTRING_CHARS(lineno_as_str), lineno_length);
        cp += lineno_length;
    }

    *cp++ = ')'; *cp++ = ')'; *cp = 0;

    result = js_NewString(cx, chars, length, 0);
    if (!result) {
        JS_free(cx, chars);
        return JS_FALSE;
    }
    *rval = STRING_TO_JSVAL(result);
    return JS_TRUE;
}
예제 #5
0
/*
 * Copy everything interesting about an error into allocated memory.
 */
static JSExnPrivate *
exn_newPrivate(JSContext *cx, JSErrorReport *report)
{
    intN i;
    JSExnPrivate *newPrivate;
    JSErrorReport *newReport;
    size_t capacity;

    newPrivate = (JSExnPrivate *)JS_malloc(cx, sizeof (JSExnPrivate));
    if (!newPrivate)
        return NULL;
    memset(newPrivate, 0, sizeof (JSExnPrivate));

    /* Copy the error report */
    newReport = (JSErrorReport *)JS_malloc(cx, sizeof (JSErrorReport));
    if (!newReport)
        goto error;
    memset(newReport, 0, sizeof (JSErrorReport));
    newPrivate->errorReport = newReport;

    if (report->filename != NULL) {
        newReport->filename = JS_strdup(cx, report->filename);
        if (!newReport->filename)
            goto error;
    } else {
        newReport->filename = NULL;
    }

    newReport->lineno = report->lineno;

    /*
     * We don't need to copy linebuf and tokenptr, because they
     * point into the deflated string cache.  (currently?)
     */
    newReport->linebuf = report->linebuf;
    newReport->tokenptr = report->tokenptr;

    /*
     * But we do need to copy uclinebuf, uctokenptr, because they're
     * pointers into internal tokenstream structs, and may go away.
     */
    if (report->uclinebuf != NULL) {
        capacity = js_strlen(report->uclinebuf) + 1;
        newReport->uclinebuf =
            (const jschar *)JS_malloc(cx, capacity * sizeof(jschar));
        if (!newReport->uclinebuf)
            goto error;
        js_strncpy((jschar *)newReport->uclinebuf, report->uclinebuf, capacity);
        newReport->uctokenptr = newReport->uclinebuf + (report->uctokenptr -
                                                        report->uclinebuf);
    } else {
        newReport->uclinebuf = newReport->uctokenptr = NULL;
    }

    if (report->ucmessage != NULL) {
        capacity = js_strlen(report->ucmessage) + 1;
        newReport->ucmessage = (const jschar *)JS_malloc(cx, capacity * sizeof(jschar));
        if (!newReport->ucmessage)
            goto error;
        js_strncpy((jschar *)newReport->ucmessage, report->ucmessage, capacity);

        if (report->messageArgs) {
            for (i = 0; report->messageArgs[i] != NULL; i++)
                continue;
            JS_ASSERT(i);
            newReport->messageArgs =
                (const jschar **)JS_malloc(cx, (i + 1) * sizeof(jschar *));
            if (!newReport->messageArgs)
                goto error;
            for (i = 0; report->messageArgs[i] != NULL; i++) {
                capacity = js_strlen(report->messageArgs[i]) + 1;
                newReport->messageArgs[i] =
                    (const jschar *)JS_malloc(cx, capacity * sizeof(jschar));
                if (!newReport->messageArgs[i])
                    goto error;
                js_strncpy((jschar *)(newReport->messageArgs[i]),
                           report->messageArgs[i], capacity);
            }
            newReport->messageArgs[i] = NULL;
        } else {
            newReport->messageArgs = NULL;
        }
    } else {
        newReport->ucmessage = NULL;
        newReport->messageArgs = NULL;
    }
    newReport->errorNumber = report->errorNumber;

    /* Note that this is before it gets flagged with JSREPORT_EXCEPTION */
    newReport->flags = report->flags;

    return newPrivate;
error:
    exn_destroyPrivate(cx, newPrivate);
    return NULL;
}
예제 #6
0
파일: jsexn.cpp 프로젝트: ahadzi/celtx
/*
 * Return a string that may eval to something similar to the original object.
 */
static JSBool
exn_toSource(JSContext *cx, uintN argc, jsval *vp)
{
    JSObject *obj;
    JSString *name, *message, *filename, *lineno_as_str, *result;
    jsval localroots[3] = {JSVAL_NULL, JSVAL_NULL, JSVAL_NULL};
    JSTempValueRooter tvr;
    JSBool ok;
    uint32 lineno;
    size_t lineno_length, name_length, message_length, filename_length, length;
    jschar *chars, *cp;

    obj = JS_THIS_OBJECT(cx, vp);
    if (!obj ||
        !OBJ_GET_PROPERTY(cx, obj,
                          ATOM_TO_JSID(cx->runtime->atomState.nameAtom),
                          vp)) {
        return JS_FALSE;
    }
    name = js_ValueToString(cx, *vp);
    if (!name)
        return JS_FALSE;
    *vp = STRING_TO_JSVAL(name);

    /* After this, control must flow through label out: to exit. */
    JS_PUSH_TEMP_ROOT(cx, 3, localroots, &tvr);

#ifdef __GNUC__
    message = filename = NULL;
#endif
    ok = JS_GetProperty(cx, obj, js_message_str, &localroots[0]) &&
         (message = js_ValueToSource(cx, localroots[0]));
    if (!ok)
        goto out;
    localroots[0] = STRING_TO_JSVAL(message);

    ok = JS_GetProperty(cx, obj, js_fileName_str, &localroots[1]) &&
         (filename = js_ValueToSource(cx, localroots[1]));
    if (!ok)
        goto out;
    localroots[1] = STRING_TO_JSVAL(filename);

    ok = JS_GetProperty(cx, obj, js_lineNumber_str, &localroots[2]);
    if (!ok)
        goto out;
    lineno = js_ValueToECMAUint32 (cx, &localroots[2]);
    ok = !JSVAL_IS_NULL(localroots[2]);
    if (!ok)
        goto out;

    if (lineno != 0) {
        lineno_as_str = js_ValueToString(cx, localroots[2]);
        if (!lineno_as_str) {
            ok = JS_FALSE;
            goto out;
        }
        lineno_length = JSSTRING_LENGTH(lineno_as_str);
    } else {
        lineno_as_str = NULL;
        lineno_length = 0;
    }

    /* Magic 8, for the characters in ``(new ())''. */
    name_length = JSSTRING_LENGTH(name);
    message_length = JSSTRING_LENGTH(message);
    length = 8 + name_length + message_length;

    filename_length = JSSTRING_LENGTH(filename);
    if (filename_length != 0) {
        /* append filename as ``, {filename}'' */
        length += 2 + filename_length;
        if (lineno_as_str) {
            /* append lineno as ``, {lineno_as_str}'' */
            length += 2 + lineno_length;
        }
    } else {
        if (lineno_as_str) {
            /*
             * no filename, but have line number,
             * need to append ``, "", {lineno_as_str}''
             */
            length += 6 + lineno_length;
        }
    }

    cp = chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar));
    if (!chars) {
        ok = JS_FALSE;
        goto out;
    }

    *cp++ = '('; *cp++ = 'n'; *cp++ = 'e'; *cp++ = 'w'; *cp++ = ' ';
    js_strncpy(cp, JSSTRING_CHARS(name), name_length);
    cp += name_length;
    *cp++ = '(';
    if (message_length != 0) {
        js_strncpy(cp, JSSTRING_CHARS(message), message_length);
        cp += message_length;
    }

    if (filename_length != 0) {
        /* append filename as ``, {filename}'' */
        *cp++ = ','; *cp++ = ' ';
        js_strncpy(cp, JSSTRING_CHARS(filename), filename_length);
        cp += filename_length;
    } else {
        if (lineno_as_str) {
            /*
             * no filename, but have line number,
             * need to append ``, "", {lineno_as_str}''
             */
            *cp++ = ','; *cp++ = ' '; *cp++ = '"'; *cp++ = '"';
        }
    }
    if (lineno_as_str) {
        /* append lineno as ``, {lineno_as_str}'' */
        *cp++ = ','; *cp++ = ' ';
        js_strncpy(cp, JSSTRING_CHARS(lineno_as_str), lineno_length);
        cp += lineno_length;
    }

    *cp++ = ')'; *cp++ = ')'; *cp = 0;

    result = js_NewString(cx, chars, length);
    if (!result) {
        JS_free(cx, chars);
        ok = JS_FALSE;
        goto out;
    }
    *vp = STRING_TO_JSVAL(result);
    ok = JS_TRUE;

out:
    JS_POP_TEMP_ROOT(cx, &tvr);
    return ok;
}
예제 #7
0
파일: jsarray.c 프로젝트: bluecherrydvr/omv
static JSBool
array_join_sub(JSContext *cx, JSObject *obj, JSString *sep, JSBool literalize,
               jsval *rval, JSBool localeString)
{
    JSBool ok;
    jsval v;
    jsuint length, index;
    jschar *chars, *ochars;
    size_t nchars, growth, seplen, tmplen;
    const jschar *sepstr;
    JSString *str;
    JSHashEntry *he;
    JSObject *obj2;

    ok = js_GetLengthProperty(cx, obj, &length);
    if (!ok)
        return JS_FALSE;

    he = js_EnterSharpObject(cx, obj, NULL, &chars);
    if (!he)
        return JS_FALSE;
    if (literalize) {
        if (IS_SHARP(he)) {
#if JS_HAS_SHARP_VARS
            nchars = js_strlen(chars);
#else
            chars[0] = '[';
            chars[1] = ']';
            chars[2] = 0;
            nchars = 2;
#endif
            goto make_string;
        }

        /*
         * Allocate 1 + 3 + 1 for "[", the worst-case closing ", ]", and the
         * terminating 0.
         */
        growth = (1 + 3 + 1) * sizeof(jschar);
        if (!chars) {
            nchars = 0;
            chars = (jschar *) malloc(growth);
            if (!chars)
                goto done;
        } else {
            MAKE_SHARP(he);
            nchars = js_strlen(chars);
            chars = (jschar *)
                realloc((ochars = chars), nchars * sizeof(jschar) + growth);
            if (!chars) {
                free(ochars);
                goto done;
            }
        }
        chars[nchars++] = '[';
    } else {
        /*
         * Free any sharp variable definition in chars.  Normally, we would
         * MAKE_SHARP(he) so that only the first sharp variable annotation is
         * a definition, and all the rest are references, but in the current
         * case of (!literalize), we don't need chars at all.
         */
        if (chars)
            JS_free(cx, chars);
        chars = NULL;
        nchars = 0;

        /* Return the empty string on a cycle as well as on empty join. */
        if (IS_BUSY(he) || length == 0) {
            js_LeaveSharpObject(cx, NULL);
            *rval = JS_GetEmptyStringValue(cx);
            return ok;
        }

        /* Flag he as BUSY so we can distinguish a cycle from a join-point. */
        MAKE_BUSY(he);
    }
    sepstr = NULL;
    seplen = JSSTRING_LENGTH(sep);

    v = JSVAL_NULL;
    for (index = 0; index < length; index++) {
        ok = JS_GetElement(cx, obj, index, &v);
        if (!ok)
            goto done;

        if (!literalize && (JSVAL_IS_VOID(v) || JSVAL_IS_NULL(v))) {
            str = cx->runtime->emptyString;
        } else {
            if (localeString) {
                if (!js_ValueToObject(cx, v, &obj2) ||
                    !js_TryMethod(cx, obj2,
                                  cx->runtime->atomState.toLocaleStringAtom,
                                  0, NULL, &v)) {
                    str = NULL;
                } else {
                    str = js_ValueToString(cx, v);
                }
            } else {
                str = (literalize ? js_ValueToSource : js_ValueToString)(cx, v);
            }
            if (!str) {
                ok = JS_FALSE;
                goto done;
            }
        }

        /* Allocate 3 + 1 at end for ", ", closing bracket, and zero. */
        growth = (nchars + (sepstr ? seplen : 0) +
                  JSSTRING_LENGTH(str) +
                  3 + 1) * sizeof(jschar);
        if (!chars) {
            chars = (jschar *) malloc(growth);
            if (!chars)
                goto done;
        } else {
            chars = (jschar *) realloc((ochars = chars), growth);
            if (!chars) {
                free(ochars);
                goto done;
            }
        }

        if (sepstr) {
            js_strncpy(&chars[nchars], sepstr, seplen);
            nchars += seplen;
        }
        sepstr = JSSTRING_CHARS(sep);

        tmplen = JSSTRING_LENGTH(str);
        js_strncpy(&chars[nchars], JSSTRING_CHARS(str), tmplen);
        nchars += tmplen;
    }

  done:
    if (literalize) {
        if (chars) {
            if (JSVAL_IS_VOID(v)) {
                chars[nchars++] = ',';
                chars[nchars++] = ' ';
            }
            chars[nchars++] = ']';
        }
    } else {
        CLEAR_BUSY(he);
    }
    js_LeaveSharpObject(cx, NULL);
    if (!ok) {
        if (chars)
            free(chars);
        return ok;
    }

  make_string:
    if (!chars) {
        JS_ReportOutOfMemory(cx);
        return JS_FALSE;
    }
    chars[nchars] = 0;
    str = js_NewString(cx, chars, nchars, 0);
    if (!str) {
        free(chars);
        return JS_FALSE;
    }
    *rval = STRING_TO_JSVAL(str);
    return JS_TRUE;
}
예제 #8
0
JSBool
js_obj_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
		jsval *rval)
{
    jschar *chars;
    size_t nchars;
    char *clazz, *prefix;
    JSString *str;

#if JS_HAS_OBJECT_LITERAL
    if (cx->version >= JSVERSION_1_2) {
	JSProperty *list, *prop;
	JSBool ok;
	char *comma, *idquote, *valquote;
	jsval id, val;
	JSString *idstr, *valstr;
#if JS_HAS_SHARP_VARS
	PRHashEntry *he;
#endif

	/* Early returns after this must unlock, or goto done with ok set. */
	JS_LOCK(cx);
	list = obj->map->props;

#if JS_HAS_SHARP_VARS
	he = js_EnterSharpObject(cx, obj, &chars);
	if (!he) {
	    JS_UNLOCK(cx);
	    return JS_FALSE;
	}
	if (IS_SHARP(he)) {	/* we didn't enter -- obj is already sharp */
	    JS_UNLOCK(cx);
	    nchars = js_strlen(chars);
	    goto make_string;
	}
	MAKE_SHARP(he);
#else
	/* Shut off recursion by temporarily clearing obj's property list. */
	obj->map->props = NULL;
	chars = NULL;
#endif
	ok = JS_TRUE;

	/* Allocate 2 + 1 for "{}" and the terminator. */
	if (!chars) {
	    chars = malloc((2 + 1) * sizeof(jschar));
	    nchars = 0;
	} else {
	    nchars = js_strlen(chars);
	    chars = realloc(chars, (nchars + 2 + 1) * sizeof(jschar));
	}
	if (!chars)
	    goto done;
	chars[nchars++] = '{';

	comma = NULL;

	for (prop = list; prop; prop = prop->next) {
	    if (!prop->symbols || !(prop->flags & JSPROP_ENUMERATE))
		continue;

	    /* Get strings for id and val and GC-root them via argv. */
	    id = js_IdToValue(sym_id(prop->symbols));
	    idstr = js_ValueToString(cx, id);
	    if (idstr)
		argv[0] = STRING_TO_JSVAL(idstr);
	    val = prop->object->slots[prop->slot];
	    valstr = js_ValueToString(cx, val);
	    if (!idstr || !valstr) {
		ok = JS_FALSE;
		goto done;
	    }
	    argv[1] = STRING_TO_JSVAL(valstr);

	    /* If id is a non-identifier string, it needs to be quoted. */
	    if (JSVAL_IS_STRING(id) && !js_IsIdentifier(idstr)) {
		idquote = "'";
		idstr = js_EscapeString(cx, idstr, *idquote);
		if (!idstr) {
		    ok = JS_FALSE;
		    goto done;
		}
		argv[0] = STRING_TO_JSVAL(idstr);
	    } else {
		idquote = NULL;
	    }

	    /* Same for val, except it can't be an identifier. */
	    if (JSVAL_IS_STRING(val)) {
		valquote = "\"";
		valstr = js_EscapeString(cx, valstr, *valquote);
		if (!valstr) {
		    ok = JS_FALSE;
		    goto done;
		}
		argv[1] = STRING_TO_JSVAL(valstr);
	    } else {
		valquote = NULL;
	    }

	    /* Allocate 1 + 1 at end for closing brace and terminating 0. */
	    chars = realloc(chars,
			    (nchars + (comma ? 2 : 0) +
			     (idquote ? 2 : 0) + idstr->length + 1 +
			     (valquote ? 2 : 0) + valstr->length +
			     1 + 1) * sizeof(jschar));
	    if (!chars)
		goto done;

	    if (comma) {
		chars[nchars++] = comma[0];
		chars[nchars++] = comma[1];
	    }
	    comma = ", ";

	    if (idquote)
		chars[nchars++] = *idquote;
	    js_strncpy(&chars[nchars], idstr->chars, idstr->length);
	    nchars += idstr->length;
	    if (idquote)
		chars[nchars++] = *idquote;

	    chars[nchars++] = ':';

	    if (valquote)
		chars[nchars++] = *valquote;
	    js_strncpy(&chars[nchars], valstr->chars, valstr->length);
	    nchars += valstr->length;
	    if (valquote)
		chars[nchars++] = *valquote;
	}

      done:
	if (chars) {
	    chars[nchars++] = '}';
	    chars[nchars] = 0;
	}
#if JS_HAS_SHARP_VARS
	js_LeaveSharpObject(cx);
#else
	/* Restore obj's property list before bailing on error. */
	obj->map->props = list;
#endif

	JS_UNLOCK(cx);
	if (!ok) {
	    if (chars)
		free(chars);
	    return ok;
	}
    } else
#endif /* JS_HAS_OBJECT_LITERAL */
    {
	clazz = obj->map->clasp->name;
	nchars = 9 + strlen(clazz);		/* 9 for "[object ]" */
	chars = malloc((nchars + 1) * sizeof(jschar));
	if (chars) {
	    prefix = "[object ";
	    nchars = 0;
	    while ((chars[nchars] = (jschar)*prefix) != 0)
		nchars++, prefix++;
	    while ((chars[nchars] = (jschar)*clazz) != 0)
		nchars++, clazz++;
	    chars[nchars++] = ']';
	    chars[nchars] = 0;
	}
    }

#if JS_HAS_SHARP_VARS
  make_string:
#endif
    if (!chars) {
	JS_ReportOutOfMemory(cx);
	return JS_FALSE;
    }
    str = js_NewString(cx, chars, nchars, 0);
    if (!str) {
	free(chars);
	return JS_FALSE;
    }
    *rval = STRING_TO_JSVAL(str);
    return JS_TRUE;
}
예제 #9
0
JSBool onJSONStringifyFinished(const jschar *buf, uint32_t len, void *data)
{
	jsSrcBufferSize = len;
	js_strncpy(jsSrcBuffer, buf, len);
	return JS_TRUE;
}
예제 #10
0
파일: jsscan.c 프로젝트: artcom/y60
static int32
GetChar(JSTokenStream *ts)
{
    int32 c;
    ptrdiff_t i, j, len, olen;
    JSBool crflag;
    char cbuf[JS_LINE_LIMIT];
    jschar *ubuf, *nl;

    if (ts->ungetpos != 0) {
        c = ts->ungetbuf[--ts->ungetpos];
    } else {
        do {
            if (ts->linebuf.ptr == ts->linebuf.limit) {
                len = PTRDIFF(ts->userbuf.limit, ts->userbuf.ptr, jschar);
                if (len <= 0) {
                    if (!ts->file) {
                        ts->flags |= TSF_EOF;
                        return EOF;
                    }

                    /* Fill ts->userbuf so that \r and \r\n convert to \n. */
                    crflag = (ts->flags & TSF_CRFLAG) != 0;
                    len = my_fgets(cbuf, JS_LINE_LIMIT - crflag, ts->file);
                    if (len <= 0) {
                        ts->flags |= TSF_EOF;
                        return EOF;
                    }
                    olen = len;
                    ubuf = ts->userbuf.base;
                    i = 0;
                    if (crflag) {
                        ts->flags &= ~TSF_CRFLAG;
                        if (cbuf[0] != '\n') {
                            ubuf[i++] = '\n';
                            len++;
                            ts->linepos--;
                        }
                    }
                    for (j = 0; i < len; i++, j++)
                        ubuf[i] = (jschar) (unsigned char) cbuf[j];
                    ts->userbuf.limit = ubuf + len;
                    ts->userbuf.ptr = ubuf;
                }
                if (ts->listener) {
                    ts->listener(ts->filename, ts->lineno, ts->userbuf.ptr, len,
                                 &ts->listenerTSData, ts->listenerData);
                }

                /*
                 * Any one of \n, \r, or \r\n ends a line (longest match wins).
                 * Also allow the Unicode line and paragraph separators.
                 */
                for (nl = ts->userbuf.ptr; nl < ts->userbuf.limit; nl++) {
                    /*
                     * Try to prevent value-testing on most characters by
                     * filtering out characters that aren't 000x or 202x.
                     */
                    if ((*nl & 0xDFD0) == 0) {
                        if (*nl == '\n')
                            break;
                        if (*nl == '\r') {
                            if (nl + 1 < ts->userbuf.limit && nl[1] == '\n')
                                nl++;
                            break;
                        }
                        if (*nl == LINE_SEPARATOR || *nl == PARA_SEPARATOR)
                            break;
                    }
                }

                /*
                 * If there was a line terminator, copy thru it into linebuf.
                 * Else copy JS_LINE_LIMIT-1 bytes into linebuf.
                 */
                if (nl < ts->userbuf.limit)
                    len = PTRDIFF(nl, ts->userbuf.ptr, jschar) + 1;
                if (len >= JS_LINE_LIMIT)
                    len = JS_LINE_LIMIT - 1;
                js_strncpy(ts->linebuf.base, ts->userbuf.ptr, len);
                ts->userbuf.ptr += len;
                olen = len;

                /*
                 * Make sure linebuf contains \n for EOL (don't do this in
                 * userbuf because the user's string might be readonly).
                 */
                if (nl < ts->userbuf.limit) {
                    if (*nl == '\r') {
                        if (ts->linebuf.base[len-1] == '\r') {
                            /*
                             * Does the line segment end in \r?  We must check
                             * for a \n at the front of the next segment before
                             * storing a \n into linebuf.  This case matters
                             * only when we're reading from a file.
                             */
                            if (nl + 1 == ts->userbuf.limit && ts->file) {
                                len--;
                                ts->flags |= TSF_CRFLAG; /* clear NLFLAG? */
                                if (len == 0) {
                                    /*
                                     * This can happen when a segment ends in
                                     * \r\r.  Start over.  ptr == limit in this
                                     * case, so we'll fall into buffer-filling
                                     * code.
                                     */
                                    return GetChar(ts);
                                }
                            } else {
                                ts->linebuf.base[len-1] = '\n';
                            }
                        }
                    } else if (*nl == '\n') {
                        if (nl > ts->userbuf.base &&
                            nl[-1] == '\r' &&
                            ts->linebuf.base[len-2] == '\r') {
                            len--;
                            JS_ASSERT(ts->linebuf.base[len] == '\n');
                            ts->linebuf.base[len-1] = '\n';
                        }
                    } else if (*nl == LINE_SEPARATOR || *nl == PARA_SEPARATOR) {
                        ts->linebuf.base[len-1] = '\n';
                    }
                }

                /* Reset linebuf based on adjusted segment length. */
                ts->linebuf.limit = ts->linebuf.base + len;
                ts->linebuf.ptr = ts->linebuf.base;

                /* Update position of linebuf within physical userbuf line. */
                if (!(ts->flags & TSF_NLFLAG))
                    ts->linepos += ts->linelen;
                else
                    ts->linepos = 0;
                if (ts->linebuf.limit[-1] == '\n')
                    ts->flags |= TSF_NLFLAG;
                else
                    ts->flags &= ~TSF_NLFLAG;

                /* Update linelen from original segment length. */
                ts->linelen = olen;
            }
            c = *ts->linebuf.ptr++;
        } while (JS_ISFORMAT(c));
    }
    if (c == '\n')
        ts->lineno++;
    return c;
}