зеркало из https://github.com/mozilla/pjs.git
(not part of mozilla build) added source hook to jsdbgapi so that debugger can get clean access to source from jsscan when the JSFILE hack is used
This commit is contained in:
Родитель
a65a3ac653
Коммит
a176d21d9e
61
js/ref/js.c
61
js/ref/js.c
|
@ -1082,6 +1082,63 @@ static JSPropertySpec its_props[] = {
|
|||
{0}
|
||||
};
|
||||
|
||||
#ifdef JSD_LOWLEVEL_SOURCE
|
||||
/*
|
||||
* This facilitates sending source to JSD (the debugger system) in the shell
|
||||
* where the source is loaded using the JSFILE hack in jsscan. The function
|
||||
* below is used as a callback for the jsdbgapi JS_SetSourceHandler hook.
|
||||
* A more normal embedding (e.g. mozilla) loads source itself and can send
|
||||
* source directly to JSD without using this hook scheme.
|
||||
*
|
||||
* XXX At some future point JSD will understand Unicode source and the
|
||||
* *very* ugly conversion below will be unnecessary.
|
||||
*/
|
||||
static void
|
||||
SendSourceToJSDebugger(const char *filename, uintN lineno,
|
||||
jschar *str, size_t length,
|
||||
void **listenerTSData, JSDContext* jsdc)
|
||||
{
|
||||
JSDSourceText *jsdsrc = (JSDSourceText *) *listenerTSData;
|
||||
|
||||
if (!jsdsrc) {
|
||||
if (!filename)
|
||||
filename = "typein";
|
||||
if (1 == lineno) {
|
||||
jsdsrc = JSD_NewSourceText(jsdc, filename);
|
||||
} else {
|
||||
jsdsrc = JSD_FindSourceForURL(jsdc, filename);
|
||||
if (jsdsrc && JSD_SOURCE_PARTIAL !=
|
||||
JSD_GetSourceStatus(jsdc, jsdsrc)) {
|
||||
jsdsrc = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (jsdsrc) {
|
||||
/* here we convert our Unicode into a C string to pass to JSD */
|
||||
#define JSD_BUF_SIZE 1024
|
||||
static char* buf = NULL;
|
||||
int remaining = length;
|
||||
|
||||
if (!buf)
|
||||
buf = malloc(JSD_BUF_SIZE);
|
||||
if (buf)
|
||||
{
|
||||
while (remaining && jsdsrc) {
|
||||
int bytes = PR_MIN(remaining, JSD_BUF_SIZE);
|
||||
int i;
|
||||
for (i = 0; i < bytes; i++)
|
||||
buf[i] = (const char) *(str++);
|
||||
jsdsrc = JSD_AppendSourceText(jsdc,jsdsrc,
|
||||
buf, bytes,
|
||||
JSD_SOURCE_PARTIAL);
|
||||
remaining -= bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
*listenerTSData = jsdsrc;
|
||||
}
|
||||
#endif /* JSD_LOWLEVEL_SOURCE */
|
||||
|
||||
static JSBool its_noisy; /* whether to be noisy when finalizing it */
|
||||
|
||||
static JSBool
|
||||
|
@ -1438,7 +1495,9 @@ main(int argc, char **argv)
|
|||
if (!_jsdc)
|
||||
return 1;
|
||||
JSD_JSContextInUse(_jsdc, cx);
|
||||
|
||||
#ifdef JSD_LOWLEVEL_SOURCE
|
||||
JS_SetSourceHandler(rt, SendSourceToJSDebugger, _jsdc);
|
||||
#endif /* JSD_LOWLEVEL_SOURCE */
|
||||
#ifdef JSDEBUGGER_JAVA_UI
|
||||
_jsdjc = JSDJ_CreateContext();
|
||||
if (! _jsdjc)
|
||||
|
|
|
@ -82,6 +82,8 @@ struct JSRuntime {
|
|||
void *destroyScriptHookData;
|
||||
JSTrapHandler debuggerHandler;
|
||||
void *debuggerHandlerData;
|
||||
JSSourceHandler sourceHandler;
|
||||
void *sourceHandlerData;
|
||||
|
||||
/* More debugging state, see jsdbgapi.c. */
|
||||
PRCList trapList;
|
||||
|
|
|
@ -806,3 +806,11 @@ JS_SetDebuggerHandler(JSRuntime *rt, JSTrapHandler handler, void *closure)
|
|||
rt->debuggerHandlerData = closure;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetSourceHandler(JSRuntime *rt, JSSourceHandler handler, void *closure)
|
||||
{
|
||||
rt->sourceHandler = handler;
|
||||
rt->sourceHandlerData = closure;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
|
|
@ -223,6 +223,9 @@ JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda);
|
|||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetDebuggerHandler(JSRuntime *rt, JSTrapHandler handler, void *closure);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetSourceHandler(JSRuntime *rt, JSSourceHandler handler, void *closure);
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* jsdbgapi_h___ */
|
||||
|
|
|
@ -96,4 +96,9 @@ typedef void
|
|||
JSScript *script,
|
||||
void *callerdata );
|
||||
|
||||
typedef void
|
||||
(*JSSourceHandler)(const char *filename, uintN lineno,
|
||||
jschar *str, size_t length,
|
||||
void **listenerTSData, void *closure);
|
||||
|
||||
#endif /* jsprvtd_h___ */
|
||||
|
|
|
@ -201,9 +201,8 @@ js_NewBufferTokenStream(JSContext *cx, const jschar *base, size_t length)
|
|||
ts->userbuf.base = (jschar *)base;
|
||||
ts->userbuf.limit = (jschar *)base + length;
|
||||
ts->userbuf.ptr = (jschar *)base;
|
||||
#ifdef JSD_LOWLEVEL_SOURCE
|
||||
ts->jsdc = JSD_JSDContextForJSContext(cx);
|
||||
#endif
|
||||
ts->listener = cx->runtime->sourceHandler;
|
||||
ts->listenerData = cx->runtime->sourceHandlerData;
|
||||
return ts;
|
||||
}
|
||||
|
||||
|
@ -250,48 +249,6 @@ js_CloseTokenStream(JSContext *cx, JSTokenStream *ts)
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifdef JSD_LOWLEVEL_SOURCE
|
||||
static void
|
||||
SendSourceToJSDebugger(JSTokenStream *ts, jschar *str, size_t length)
|
||||
{
|
||||
if (!ts->jsdsrc) {
|
||||
const char* filename = ts->filename ? ts->filename : "typein";
|
||||
|
||||
if (1 == ts->lineno) {
|
||||
ts->jsdsrc = JSD_NewSourceText(ts->jsdc, filename);
|
||||
} else {
|
||||
ts->jsdsrc = JSD_FindSourceForURL(ts->jsdc, filename);
|
||||
if (ts->jsdsrc && JSD_SOURCE_PARTIAL !=
|
||||
JSD_GetSourceStatus(ts->jsdc, ts->jsdsrc)) {
|
||||
ts->jsdsrc = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ts->jsdsrc) {
|
||||
/* here we convert our Unicode into a C string to pass to JSD */
|
||||
#define JSD_BUF_SIZE 1024
|
||||
static char* buf = NULL;
|
||||
int remaining = length;
|
||||
|
||||
if (!buf)
|
||||
buf = malloc(JSD_BUF_SIZE);
|
||||
if (buf)
|
||||
{
|
||||
while (remaining && ts->jsdsrc) {
|
||||
int bytes = PR_MIN(remaining, JSD_BUF_SIZE);
|
||||
int i;
|
||||
for (i = 0; i < bytes; i++)
|
||||
buf[i] = (const char) *(str++);
|
||||
ts->jsdsrc = JSD_AppendSourceText(ts->jsdc,ts->jsdsrc,
|
||||
buf, bytes,
|
||||
JSD_SOURCE_PARTIAL);
|
||||
remaining -= bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int32
|
||||
GetChar(JSTokenStream *ts)
|
||||
{
|
||||
|
@ -341,12 +298,9 @@ GetChar(JSTokenStream *ts)
|
|||
return EOF;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef JSD_LOWLEVEL_SOURCE
|
||||
if (ts->jsdc)
|
||||
SendSourceToJSDebugger(ts, ts->userbuf.ptr, len);
|
||||
#endif
|
||||
|
||||
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).
|
||||
*/
|
||||
|
|
265
js/ref/jsscan.h
265
js/ref/jsscan.h
|
@ -1,265 +0,0 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsscan_h___
|
||||
#define jsscan_h___
|
||||
/*
|
||||
* JS lexical scanner interface.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#ifdef JSFILE
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#include "jsopcode.h"
|
||||
#include "jsprvtd.h"
|
||||
#include "jspubtd.h"
|
||||
|
||||
#ifdef JSD_LOWLEVEL_SOURCE
|
||||
#include "jsdebug.h"
|
||||
#endif
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
typedef enum JSTokenType {
|
||||
TOK_ERROR = -1, /* well-known as the only code < EOF */
|
||||
TOK_EOF = 0, /* end of file */
|
||||
TOK_EOL = 1, /* end of line */
|
||||
TOK_SEMI = 2, /* semicolon */
|
||||
TOK_LB = 3, TOK_RB = 4, /* left and right brackets */
|
||||
TOK_LC = 5, TOK_RC = 6, /* left and right curlies (braces) */
|
||||
TOK_LP = 7, TOK_RP = 8, /* left and right parentheses */
|
||||
TOK_COMMA = 9, /* comma operator */
|
||||
TOK_ASSIGN = 10, /* assignment ops (= += -= etc.) */
|
||||
TOK_HOOK = 11, TOK_COLON = 12, /* conditional (?:) */
|
||||
TOK_OR = 13, /* logical or (||) */
|
||||
TOK_AND = 14, /* logical and (&&) */
|
||||
TOK_BITOR = 15, /* bitwise-or (|) */
|
||||
TOK_BITXOR = 16, /* bitwise-xor (^) */
|
||||
TOK_BITAND = 17, /* bitwise-and (&) */
|
||||
TOK_EQOP = 18, /* equality ops (== !=) */
|
||||
TOK_RELOP = 19, /* relational ops (< <= > >=) */
|
||||
TOK_SHOP = 20, /* shift ops (<< >> >>>) */
|
||||
TOK_PLUS = 21, /* plus */
|
||||
TOK_MINUS = 22, /* minus */
|
||||
TOK_STAR = 23, TOK_DIVOP = 24, /* multiply/divide ops (* / %) */
|
||||
TOK_UNARYOP = 25, /* unary prefix operator */
|
||||
TOK_INC = 26, TOK_DEC = 27, /* increment/decrement (++ --) */
|
||||
TOK_DOT = 28, /* member operator (.) */
|
||||
TOK_NAME = 29, /* identifier */
|
||||
TOK_NUMBER = 30, /* numeric constant */
|
||||
TOK_STRING = 31, /* string constant */
|
||||
TOK_OBJECT = 32, /* RegExp or other object constant */
|
||||
TOK_PRIMARY = 33, /* true, false, null, this, super */
|
||||
TOK_FUNCTION = 34, /* function keyword */
|
||||
TOK_EXPORT = 35, /* export keyword */
|
||||
TOK_IMPORT = 36, /* import keyword */
|
||||
TOK_IF = 37, /* if keyword */
|
||||
TOK_ELSE = 38, /* else keyword */
|
||||
TOK_SWITCH = 39, /* switch keyword */
|
||||
TOK_CASE = 40, /* case keyword */
|
||||
TOK_DEFAULT = 41, /* default keyword */
|
||||
TOK_WHILE = 42, /* while keyword */
|
||||
TOK_DO = 43, /* do keyword */
|
||||
TOK_FOR = 44, /* for keyword */
|
||||
TOK_BREAK = 45, /* break keyword */
|
||||
TOK_CONTINUE = 46, /* continue keyword */
|
||||
TOK_IN = 47, /* in keyword */
|
||||
TOK_VAR = 48, /* var keyword */
|
||||
TOK_WITH = 49, /* with keyword */
|
||||
TOK_RETURN = 50, /* return keyword */
|
||||
TOK_NEW = 51, /* new keyword */
|
||||
TOK_DELETE = 52, /* delete keyword */
|
||||
TOK_DEFSHARP = 53, /* #n= for object/array initializers */
|
||||
TOK_USESHARP = 54, /* #n# for object/array initializers */
|
||||
TOK_TRY = 55, /* try keyword */
|
||||
TOK_CATCH = 56, /* catch keyword */
|
||||
TOK_FINALLY = 57, /* finally keyword */
|
||||
TOK_THROW = 58, /* throw keyword */
|
||||
TOK_INSTANCEOF = 59, /* instanceof keyword */
|
||||
TOK_DEBUGGER = 60, /* debugger keyword */
|
||||
TOK_RESERVED, /* reserved keywords */
|
||||
TOK_LIMIT /* domain size */
|
||||
} JSTokenType;
|
||||
|
||||
#define IS_PRIMARY_TOKEN(tt) \
|
||||
((uintN)((tt) - TOK_NAME) <= (uintN)(TOK_PRIMARY - TOK_NAME))
|
||||
|
||||
struct JSTokenPtr {
|
||||
uint16 index; /* index of char in physical line */
|
||||
uint16 lineno; /* physical line number */
|
||||
};
|
||||
|
||||
struct JSTokenPos {
|
||||
JSTokenPtr begin; /* first character and line of token */
|
||||
JSTokenPtr end; /* index 1 past last char, last line */
|
||||
};
|
||||
|
||||
struct JSToken {
|
||||
JSTokenType type; /* char value or above enumerator */
|
||||
JSTokenPos pos; /* token position in file */
|
||||
jschar *ptr; /* beginning of token in line buffer */
|
||||
union {
|
||||
struct {
|
||||
JSOp op; /* operator, for minimal parser */
|
||||
JSAtom *atom; /* atom table entry */
|
||||
} s;
|
||||
jsdouble dval; /* floating point number */
|
||||
} u;
|
||||
};
|
||||
|
||||
#define t_op u.s.op
|
||||
#define t_atom u.s.atom
|
||||
#define t_dval u.dval
|
||||
|
||||
typedef struct JSTokenBuf {
|
||||
jschar *base; /* base of line or stream buffer */
|
||||
jschar *limit; /* limit for quick bounds check */
|
||||
jschar *ptr; /* next char to get, or slot to use */
|
||||
} JSTokenBuf;
|
||||
|
||||
#define JS_LINE_LIMIT 256 /* logical line buffer size limit --
|
||||
physical line length is unlimited */
|
||||
|
||||
struct JSTokenStream {
|
||||
JSToken token; /* last token scanned */
|
||||
JSToken pushback; /* pushed-back already-scanned token */
|
||||
uintN lineno; /* current line number */
|
||||
uintN ungetpos; /* next free char slot in ungetbuf */
|
||||
jschar ungetbuf[4]; /* at most 4, for \uXXXX lookahead */
|
||||
uintN flags; /* flags -- see below */
|
||||
ptrdiff_t linelen; /* physical linebuf segment length */
|
||||
ptrdiff_t linepos; /* linebuf offset in physical line */
|
||||
JSTokenBuf linebuf; /* line buffer for diagnostics */
|
||||
JSTokenBuf userbuf; /* user input buffer if !file */
|
||||
JSTokenBuf tokenbuf; /* current token string buffer */
|
||||
const char *filename; /* input filename or null */
|
||||
#ifdef JSFILE
|
||||
FILE *file; /* stdio stream if reading from file */
|
||||
#endif
|
||||
JSPrincipals *principals; /* principals associated with given input */
|
||||
#ifdef JSD_LOWLEVEL_SOURCE
|
||||
JSDContext *jsdc; /* used to cram source into debugger */
|
||||
JSDSourceText *jsdsrc; /* used to cram source into debugger */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* JSTokenStream flags */
|
||||
#define TSF_ERROR 0x01 /* fatal error while scanning */
|
||||
#define TSF_EOF 0x02 /* hit end of file */
|
||||
#define TSF_NEWLINES 0x04 /* tokenize newlines */
|
||||
#define TSF_REGEXP 0x08 /* looking for a regular expression */
|
||||
#define TSF_INTERACTIVE 0x10 /* interactive parsing mode */
|
||||
#define TSF_NLFLAG 0x20 /* last linebuf ended with \n */
|
||||
#define TSF_CRFLAG 0x40 /* linebuf would have ended with \r */
|
||||
|
||||
/*
|
||||
* At most one non-EOF token can be pushed back onto a TokenStream between
|
||||
* Get or successful Match operations. These macros manipulate the pushback
|
||||
* token to clear it when changing scanning modes (upon initialzation, after
|
||||
* errors, or between newline-sensitive and insensitive states).
|
||||
*/
|
||||
#define CLEAR_PUSHBACK(ts) ((ts)->pushback.type = TOK_EOF)
|
||||
#define SCAN_NEWLINES(ts) ((ts)->flags |= TSF_NEWLINES)
|
||||
#define HIDE_NEWLINES(ts) \
|
||||
PR_BEGIN_MACRO \
|
||||
(ts)->flags &= ~TSF_NEWLINES; \
|
||||
if ((ts)->pushback.type == TOK_EOL) \
|
||||
(ts)->pushback.type = TOK_EOF; \
|
||||
PR_END_MACRO
|
||||
|
||||
/* Clear ts member that might point above a released cx->tempPool mark. */
|
||||
#define RESET_TOKENBUF(ts) ((ts)->tokenbuf.base = (ts)->tokenbuf.limit = NULL)
|
||||
|
||||
/*
|
||||
* Create a new token stream, either from an input buffer or from a file.
|
||||
* Return null on file-open or memory-allocation failure.
|
||||
*
|
||||
* NB: All of js_New{,Buffer,File}TokenStream() return a pointer to transient
|
||||
* memory in the current context's temp pool. This memory is deallocated via
|
||||
* PR_ARENA_RELEASE() after parsing is finished.
|
||||
*/
|
||||
extern JSTokenStream *
|
||||
js_NewTokenStream(JSContext *cx, const jschar *base, size_t length,
|
||||
const char *filename, uintN lineno, JSPrincipals *principals);
|
||||
|
||||
extern JS_FRIEND_API(JSTokenStream *)
|
||||
js_NewBufferTokenStream(JSContext *cx, const jschar *base, size_t length);
|
||||
|
||||
#ifdef JSFILE
|
||||
extern JS_FRIEND_API(JSTokenStream *)
|
||||
js_NewFileTokenStream(JSContext *cx, const char *filename, FILE *defaultfp);
|
||||
#endif
|
||||
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
js_CloseTokenStream(JSContext *cx, JSTokenStream *ts);
|
||||
|
||||
/*
|
||||
* Initialize the scanner, installing JS keywords into cx's global scope.
|
||||
*/
|
||||
extern JSBool
|
||||
js_InitScanner(JSContext *cx);
|
||||
|
||||
/*
|
||||
* Friend-exported API entry point to call a mapping function on each reserved
|
||||
* identifier in the scanner's keyword table.
|
||||
*/
|
||||
extern JS_FRIEND_API(void)
|
||||
js_MapKeywords(void (*mapfun)(const char *));
|
||||
|
||||
/*
|
||||
* Report an error found while scanning ts to a window or other output device
|
||||
* associated with cx.
|
||||
*/
|
||||
extern void
|
||||
js_ReportCompileError(JSContext *cx, JSTokenStream *ts, uintN flags,
|
||||
const char *format, ...);
|
||||
|
||||
void
|
||||
js_ReportCompileErrorNumber(JSContext *cx, JSTokenStream *ts, uintN flags,
|
||||
const uintN errorNumber, ...);
|
||||
|
||||
/*
|
||||
* Look ahead one token and return its type.
|
||||
*/
|
||||
extern JSTokenType
|
||||
js_PeekToken(JSContext *cx, JSTokenStream *ts);
|
||||
|
||||
extern JSTokenType
|
||||
js_PeekTokenSameLine(JSContext *cx, JSTokenStream *ts);
|
||||
|
||||
/*
|
||||
* Get the next token from ts.
|
||||
*/
|
||||
extern JSTokenType
|
||||
js_GetToken(JSContext *cx, JSTokenStream *ts);
|
||||
|
||||
/*
|
||||
* Push back the last scanned token onto ts.
|
||||
*/
|
||||
extern void
|
||||
js_UngetToken(JSTokenStream *ts);
|
||||
|
||||
/*
|
||||
* Get the next token from ts if its type is tt.
|
||||
*/
|
||||
extern JSBool
|
||||
js_MatchToken(JSContext *cx, JSTokenStream *ts, JSTokenType tt);
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* jsscan_h___ */
|
Загрузка…
Ссылка в новой задаче