зеркало из https://github.com/mozilla/pjs.git
not part of mozilla build - merging from SpiderMonkey140_BRANCH
This commit is contained in:
Родитель
25fb25e0f1
Коммит
fbfb840a6c
|
@ -0,0 +1,18 @@
|
||||||
|
/* jband - 10/26/98 - */
|
||||||
|
|
||||||
|
js/jsd contains code for debugging support for the C-based JavaScript engine
|
||||||
|
in js/src.
|
||||||
|
|
||||||
|
Currently the makefiles are for Win32 only (using MS nmake.exe from MSDEV 4.2).
|
||||||
|
jsd.mak will build a standalone dll. jsdshell.mak will build the dll and also
|
||||||
|
a version of the js/src/js.c shell which will launch a Java VM and run the
|
||||||
|
JavaSript Debugger (built in js/jsdj). This version assumes that you have a
|
||||||
|
JRE compatible JVM installed. Only Windows is supported for this Java-based
|
||||||
|
debugging.
|
||||||
|
|
||||||
|
Though only Windows makefiles are supplied, the basic code in js/jsd should
|
||||||
|
compile for other platforms -- it is a newer version of code that builds and
|
||||||
|
ships with Communicator 4.x on many platforms.
|
||||||
|
|
||||||
|
js/jsd/jsdb is a console debugger using only native code (see README in that
|
||||||
|
directory)
|
|
@ -0,0 +1,35 @@
|
||||||
|
/* -*- 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This supplies non-functional stubs for a couple of JNI functions we need
|
||||||
|
* in order to link LiveConnect
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "jni.h"
|
||||||
|
|
||||||
|
jint JNICALL JNI_GetDefaultJavaVMInitArgs(void * ignored)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
jint JNICALL JNI_CreateJavaVM(JavaVM ** vm, JNIEnv ** env, void * ignored)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
|
||||||
|
JSDJNI = .
|
||||||
|
#CLASS_DIR_BASE = $(JSDJNI)\..\..\..\jsdj\dist\classes
|
||||||
|
# until jsdj moves to mozilla...
|
||||||
|
CLASS_DIR_BASE = $(JSDJNI)\..\..\..\..\..\ns\js\jsdj\dist\classes
|
||||||
|
GEN = $(JSDJNI)\_jni
|
||||||
|
HEADER_FILE = $(GEN)\jsdjnih.h
|
||||||
|
|
||||||
|
PACKAGE_SLASH = netscape\jsdebug
|
||||||
|
PACKAGE_DOT = netscape.jsdebug
|
||||||
|
|
||||||
|
STD_CLASSPATH = -classpath $(CLASS_DIR_BASE);$(CLASSPATH)
|
||||||
|
|
||||||
|
CLASSES_WITH_NATIVES = \
|
||||||
|
$(PACKAGE_DOT).DebugController \
|
||||||
|
$(PACKAGE_DOT).JSPC \
|
||||||
|
$(PACKAGE_DOT).JSSourceTextProvider \
|
||||||
|
$(PACKAGE_DOT).JSStackFrameInfo \
|
||||||
|
$(PACKAGE_DOT).JSThreadState \
|
||||||
|
$(PACKAGE_DOT).Script \
|
||||||
|
$(PACKAGE_DOT).SourceTextProvider \
|
||||||
|
$(PACKAGE_DOT).ThreadStateBase \
|
||||||
|
$(PACKAGE_DOT).Value
|
||||||
|
|
||||||
|
all: $(GEN)
|
||||||
|
@echo generating JNI headers
|
||||||
|
@javah -jni -o "$(HEADER_FILE)" $(STD_CLASSPATH) $(CLASSES_WITH_NATIVES)
|
||||||
|
|
||||||
|
$(GEN) :
|
||||||
|
@mkdir $(GEN)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@if exist $(HEADER_FILE) @del $(HEADER_FILE) > NUL
|
|
@ -0,0 +1,134 @@
|
||||||
|
/* -*- 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 Sun Microsystems, Inc.
|
||||||
|
* Portions created by Netscape are
|
||||||
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||||
|
* Reserved.
|
||||||
|
*
|
||||||
|
* Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
|
||||||
|
* modify and redistribute this software in source and binary code form,
|
||||||
|
* provided that i) this copyright notice and license appear on all copies of
|
||||||
|
* the software; and ii) Licensee does not utilize the software in a manner
|
||||||
|
* which is disparaging to Sun.
|
||||||
|
*
|
||||||
|
* This software is provided "AS IS," without a warranty of any kind. ALL
|
||||||
|
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
|
||||||
|
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
|
||||||
|
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
|
||||||
|
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||||
|
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
|
||||||
|
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
|
||||||
|
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
|
||||||
|
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
|
||||||
|
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
*
|
||||||
|
* This software is not designed or intended for use in on-line control of
|
||||||
|
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
|
||||||
|
* the design, construction, operation or maintenance of any nuclear
|
||||||
|
* facility. Licensee represents and warrants that it will not use or
|
||||||
|
* redistribute the Software for such purposes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Portable JRE support functions - pared this down to minimal set I need
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <jni.h>
|
||||||
|
#include "jre.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Exits the runtime with the specified error message.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
JRE_FatalError(JNIEnv *env, const char *msg)
|
||||||
|
{
|
||||||
|
if ((*env)->ExceptionOccurred(env)) {
|
||||||
|
(*env)->ExceptionDescribe(env);
|
||||||
|
}
|
||||||
|
(*env)->FatalError(env, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parses a runtime version string. Returns 0 if the successful, otherwise
|
||||||
|
* returns -1 if the format of the version string was invalid.
|
||||||
|
*/
|
||||||
|
jint
|
||||||
|
JRE_ParseVersion(const char *ver, char **majorp, char **minorp, char **microp)
|
||||||
|
{
|
||||||
|
int n1 = 0, n2 = 0, n3 = 0;
|
||||||
|
|
||||||
|
sscanf(ver, "%*[0-9]%n.%*[0-9]%n.%*[0-9a-zA-Z]%n", &n1, &n2, &n3);
|
||||||
|
if (n1 == 0 || n2 == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (n3 != 0) {
|
||||||
|
if (n3 != (int)strlen(ver)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else if (n2 != (int)strlen(ver)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*majorp = JRE_Malloc(n1 + 1);
|
||||||
|
strncpy(*majorp, ver, n1);
|
||||||
|
(*majorp)[n1] = 0;
|
||||||
|
*minorp = JRE_Malloc(n2 - n1);
|
||||||
|
strncpy(*minorp, ver + n1 + 1, n2 - n1 - 1);
|
||||||
|
(*minorp)[n2 - n1 - 1] = 0;
|
||||||
|
if (n3 != 0) {
|
||||||
|
*microp = JRE_Malloc(n3 - n2);
|
||||||
|
strncpy(*microp, ver + n2 + 1, n3 - n2 - 1);
|
||||||
|
(*microp)[n3 - n2 - 1] = 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates a version number string from the specified major, minor, and
|
||||||
|
* micro version numbers.
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
JRE_MakeVersion(const char *major, const char *minor, const char *micro)
|
||||||
|
{
|
||||||
|
char *ver = 0;
|
||||||
|
|
||||||
|
if (major != 0 && minor != 0) {
|
||||||
|
int len = strlen(major) + strlen(minor);
|
||||||
|
if (micro != 0) {
|
||||||
|
ver = JRE_Malloc(len + strlen(micro) + 3);
|
||||||
|
sprintf(ver, "%s.%s.%s", major, minor, micro);
|
||||||
|
} else {
|
||||||
|
ver = JRE_Malloc(len + 2);
|
||||||
|
sprintf(ver, "%s.%s", major, minor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ver;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate memory or die.
|
||||||
|
*/
|
||||||
|
void *
|
||||||
|
JRE_Malloc(size_t size)
|
||||||
|
{
|
||||||
|
void *p = malloc(size);
|
||||||
|
if (p == 0) {
|
||||||
|
perror("malloc");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
/* -*- 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 Sun Microsystems, Inc.
|
||||||
|
* Portions created by Netscape are
|
||||||
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||||
|
* Reserved.
|
||||||
|
*
|
||||||
|
* Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
|
||||||
|
* modify and redistribute this software in source and binary code form,
|
||||||
|
* provided that i) this copyright notice and license appear on all copies of
|
||||||
|
* the software; and ii) Licensee does not utilize the software in a manner
|
||||||
|
* which is disparaging to Sun.
|
||||||
|
*
|
||||||
|
* This software is provided "AS IS," without a warranty of any kind. ALL
|
||||||
|
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
|
||||||
|
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
|
||||||
|
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
|
||||||
|
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||||
|
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
|
||||||
|
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
|
||||||
|
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
|
||||||
|
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
|
||||||
|
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
*
|
||||||
|
* This software is not designed or intended for use in on-line control of
|
||||||
|
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
|
||||||
|
* the design, construction, operation or maintenance of any nuclear
|
||||||
|
* facility. Licensee represents and warrants that it will not use or
|
||||||
|
* redistribute the Software for such purposes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Portable JRE support functions - pared this down to minimal set I need
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
|
#include "jre_md.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Java runtime settings.
|
||||||
|
*/
|
||||||
|
typedef struct JRESettings {
|
||||||
|
char *javaHome; /* Java home directory */
|
||||||
|
char *runtimeLib; /* Runtime shared library or DLL */
|
||||||
|
char *classPath; /* Default class path */
|
||||||
|
char *compiler; /* Just-in-time (JIT) compiler */
|
||||||
|
char *majorVersion; /* Major version of runtime */
|
||||||
|
char *minorVersion; /* Minor version of runtime */
|
||||||
|
char *microVersion; /* Micro version of runtime */
|
||||||
|
} JRESettings;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* JRE functions.
|
||||||
|
*/
|
||||||
|
void *JRE_LoadLibrary(const char *path);
|
||||||
|
void JRE_UnloadLibrary(void *handle);
|
||||||
|
jint JRE_GetDefaultJavaVMInitArgs(void *handle, void *vmargsp);
|
||||||
|
jint JRE_CreateJavaVM(void *handle, JavaVM **vmp, JNIEnv **envp,
|
||||||
|
void *vmargsp);
|
||||||
|
jint JRE_GetCurrentSettings(JRESettings *set);
|
||||||
|
jint JRE_GetSettings(JRESettings *set, const char *ver);
|
||||||
|
jint JRE_GetDefaultSettings(JRESettings *set);
|
||||||
|
jint JRE_ParseVersion(const char *version,
|
||||||
|
char **majorp, char **minorp, char **microp);
|
||||||
|
char *JRE_MakeVersion(const char *major, const char *minor, const char *micro);
|
||||||
|
void *JRE_Malloc(size_t size);
|
||||||
|
void JRE_FatalError(JNIEnv *env, const char *msg);
|
||||||
|
char *JRE_GetDefaultRuntimeLib(const char *dir);
|
||||||
|
char *JRE_GetDefaultClassPath(const char *dir);
|
|
@ -0,0 +1,290 @@
|
||||||
|
/*
|
||||||
|
* @(#)jre_md.c 1.6 97/05/15 David Connelly
|
||||||
|
*
|
||||||
|
* Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
|
||||||
|
* modify and redistribute this software in source and binary code form,
|
||||||
|
* provided that i) this copyright notice and license appear on all copies of
|
||||||
|
* the software; and ii) Licensee does not utilize the software in a manner
|
||||||
|
* which is disparaging to Sun.
|
||||||
|
*
|
||||||
|
* This software is provided "AS IS," without a warranty of any kind. ALL
|
||||||
|
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
|
||||||
|
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
|
||||||
|
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
|
||||||
|
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||||
|
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
|
||||||
|
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
|
||||||
|
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
|
||||||
|
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
|
||||||
|
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
*
|
||||||
|
* This software is not designed or intended for use in on-line control of
|
||||||
|
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
|
||||||
|
* the design, construction, operation or maintenance of any nuclear
|
||||||
|
* facility. Licensee represents and warrants that it will not use or
|
||||||
|
* redistribute the Software for such purposes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Win32 specific JRE support functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <jni.h>
|
||||||
|
#include "jre.h"
|
||||||
|
|
||||||
|
#define JRE_KEY "Software\\JavaSoft\\Java Runtime Environment"
|
||||||
|
#define JDK_KEY "Software\\JavaSoft\\Java Development Kit"
|
||||||
|
|
||||||
|
#define RUNTIME_LIB "javai.dll"
|
||||||
|
|
||||||
|
/* From jre_main.c */
|
||||||
|
extern jboolean debug;
|
||||||
|
|
||||||
|
/* Forward Declarations */
|
||||||
|
jint LoadSettings(JRESettings *set, HKEY key);
|
||||||
|
jint GetSettings(JRESettings *set, const char *version, const char *keyname);
|
||||||
|
char *GetStringValue(HKEY key, const char *name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Retrieve settings from registry for current runtime version. Returns
|
||||||
|
* 0 if successful otherwise returns -1 if no installed runtime was found
|
||||||
|
* or the registry data was invalid.
|
||||||
|
*/
|
||||||
|
jint
|
||||||
|
JRE_GetCurrentSettings(JRESettings *set)
|
||||||
|
{
|
||||||
|
jint r = -1;
|
||||||
|
HKEY key;
|
||||||
|
|
||||||
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, JRE_KEY, 0, KEY_READ, &key) == 0) {
|
||||||
|
char *ver = GetStringValue(key, "CurrentVersion");
|
||||||
|
if (ver != 0) {
|
||||||
|
r = JRE_GetSettings(set, ver);
|
||||||
|
}
|
||||||
|
free(ver);
|
||||||
|
RegCloseKey(key);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Retrieves settings from registry for specified runtime version.
|
||||||
|
* Searches for either installed JRE and JDK runtimes. Returns 0 if
|
||||||
|
* successful otherwise returns -1 if requested version of runtime
|
||||||
|
* could not be found.
|
||||||
|
*/
|
||||||
|
jint
|
||||||
|
JRE_GetSettings(JRESettings *set, const char *version)
|
||||||
|
{
|
||||||
|
if (GetSettings(set, version, JRE_KEY) != 0) {
|
||||||
|
return GetSettings(set, version, JDK_KEY);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
jint
|
||||||
|
GetSettings(JRESettings *set, const char *version, const char *keyname)
|
||||||
|
{
|
||||||
|
HKEY key;
|
||||||
|
int r = -1;
|
||||||
|
|
||||||
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &key) == 0) {
|
||||||
|
char *major, *minor, *micro = 0;
|
||||||
|
if (JRE_ParseVersion(version, &major, &minor, µ) == 0) {
|
||||||
|
HKEY subkey;
|
||||||
|
char *ver = JRE_MakeVersion(major, minor, 0);
|
||||||
|
set->majorVersion = major;
|
||||||
|
set->minorVersion = minor;
|
||||||
|
if (RegOpenKeyEx(key, ver, 0, KEY_READ, &subkey) == 0) {
|
||||||
|
if ((r = LoadSettings(set, subkey)) == 0) {
|
||||||
|
if (micro != 0) {
|
||||||
|
if (set->microVersion == 0 ||
|
||||||
|
strcmp(micro, set->microVersion) != 0) {
|
||||||
|
r = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RegCloseKey(subkey);
|
||||||
|
}
|
||||||
|
free(ver);
|
||||||
|
}
|
||||||
|
RegCloseKey(key);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load runtime settings from specified registry key. Returns 0 if
|
||||||
|
* successful otherwise -1 if the registry data was invalid.
|
||||||
|
*/
|
||||||
|
static jint
|
||||||
|
LoadSettings(JRESettings *set, HKEY key)
|
||||||
|
{
|
||||||
|
/* Full path name of JRE home directory (required) */
|
||||||
|
set->javaHome = GetStringValue(key, "JavaHome");
|
||||||
|
if (set->javaHome == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* Full path name of JRE runtime DLL */
|
||||||
|
set->runtimeLib = GetStringValue(key, "RuntimeLib");
|
||||||
|
if (set->runtimeLib == 0) {
|
||||||
|
set->runtimeLib = JRE_GetDefaultRuntimeLib(set->javaHome);
|
||||||
|
}
|
||||||
|
/* Class path setting to override default */
|
||||||
|
set->classPath = GetStringValue(key, "ClassPath");
|
||||||
|
if (set->classPath == 0) {
|
||||||
|
set->classPath = JRE_GetDefaultClassPath(set->javaHome);
|
||||||
|
}
|
||||||
|
/* Optional JIT compiler library name */
|
||||||
|
set->compiler = GetStringValue(key, "Compiler");
|
||||||
|
/* Release micro-version */
|
||||||
|
set->microVersion = GetStringValue(key, "MicroVersion");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns string data for the specified registry value name, or
|
||||||
|
* NULL if not found.
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
GetStringValue(HKEY key, const char *name)
|
||||||
|
{
|
||||||
|
DWORD type, size;
|
||||||
|
char *value = 0;
|
||||||
|
|
||||||
|
if (RegQueryValueEx(key, name, 0, &type, 0, &size) == 0 &&
|
||||||
|
type == REG_SZ ) {
|
||||||
|
value = JRE_Malloc(size);
|
||||||
|
if (RegQueryValueEx(key, name, 0, 0, value, &size) != 0) {
|
||||||
|
free(value);
|
||||||
|
value = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns default runtime settings based on location of this program.
|
||||||
|
* Makes best attempt at determining location of runtime. Returns 0
|
||||||
|
* if successful or -1 if a runtime could not be found.
|
||||||
|
*/
|
||||||
|
jint
|
||||||
|
JRE_GetDefaultSettings(JRESettings *set)
|
||||||
|
{
|
||||||
|
char buf[MAX_PATH], *bp;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
// Try to obtain default value for Java home directory based on
|
||||||
|
// location of this executable.
|
||||||
|
|
||||||
|
if ((n = GetModuleFileName(0, buf, MAX_PATH)) == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
bp = buf + n;
|
||||||
|
while (*--bp != '\\') ;
|
||||||
|
bp -= 4;
|
||||||
|
if (bp < buf || strnicmp(bp, "\\bin", 4) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*bp = '\0';
|
||||||
|
set->javaHome = strdup(buf);
|
||||||
|
|
||||||
|
// Get default runtime library
|
||||||
|
set->runtimeLib = JRE_GetDefaultRuntimeLib(set->javaHome);
|
||||||
|
|
||||||
|
// Get default class path
|
||||||
|
set->classPath = JRE_GetDefaultClassPath(set->javaHome);
|
||||||
|
|
||||||
|
// Reset other fields since these are unknown
|
||||||
|
set->compiler = 0;
|
||||||
|
set->majorVersion = 0;
|
||||||
|
set->minorVersion = 0;
|
||||||
|
set->microVersion = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return default runtime library for specified Java home directory.
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
JRE_GetDefaultRuntimeLib(const char *dir)
|
||||||
|
{
|
||||||
|
char *cp = JRE_Malloc(strlen(dir) + sizeof(RUNTIME_LIB) + 8);
|
||||||
|
sprintf(cp, "%s\\bin\\" RUNTIME_LIB, dir);
|
||||||
|
return cp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return default class path for specified Java home directory.
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
JRE_GetDefaultClassPath(const char *dir)
|
||||||
|
{
|
||||||
|
char *cp = JRE_Malloc(strlen(dir) * 4 + 64);
|
||||||
|
sprintf(cp, "%s\\lib\\rt.jar;%s\\lib\\i18n.jar;%s\\lib\\classes.zip;"
|
||||||
|
"%s\\classes", dir, dir, dir, dir);
|
||||||
|
return cp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Loads the runtime library corresponding to 'libname' and returns
|
||||||
|
* an opaque handle to the library.
|
||||||
|
*/
|
||||||
|
void *
|
||||||
|
JRE_LoadLibrary(const char *path)
|
||||||
|
{
|
||||||
|
return (void *)LoadLibrary(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unloads the runtime library associated with handle.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
JRE_UnloadLibrary(void *handle)
|
||||||
|
{
|
||||||
|
FreeLibrary(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Loads default VM args for the specified runtime library handle.
|
||||||
|
*/
|
||||||
|
jint
|
||||||
|
JRE_GetDefaultJavaVMInitArgs(void *handle, void *vmargs)
|
||||||
|
{
|
||||||
|
FARPROC proc = GetProcAddress(handle, "JNI_GetDefaultJavaVMInitArgs");
|
||||||
|
return proc != 0 ? ((*proc)(vmargs), 0) : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates a Java VM for the specified runtime library handle.
|
||||||
|
*/
|
||||||
|
jint
|
||||||
|
JRE_CreateJavaVM(void *handle, JavaVM **vmp, JNIEnv **envp, void *vmargs)
|
||||||
|
{
|
||||||
|
FARPROC proc = GetProcAddress(handle, "JNI_CreateJavaVM");
|
||||||
|
return proc != 0 ? (*proc)(vmp, envp, vmargs) : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Entry point for JREW (Windows-only) version of the runtime loader.
|
||||||
|
* This entry point is called when the '-subsystem:windows' linker
|
||||||
|
* option is used, and will cause the resulting executable to run
|
||||||
|
* detached from the console.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* int WINAPI
|
||||||
|
* WinMain(HINSTANCE inst, HINSTANCE prevInst, LPSTR cmdLine, int cmdShow)
|
||||||
|
* {
|
||||||
|
* __declspec(dllimport) char **__initenv;
|
||||||
|
*
|
||||||
|
* __initenv = _environ;
|
||||||
|
* exit(main(__argc, __argv));
|
||||||
|
* }
|
||||||
|
*/
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* @(#)jre_md.h 1.1 97/05/19 David Connelly
|
||||||
|
*
|
||||||
|
* Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
|
||||||
|
* modify and redistribute this software in source and binary code form,
|
||||||
|
* provided that i) this copyright notice and license appear on all copies of
|
||||||
|
* the software; and ii) Licensee does not utilize the software in a manner
|
||||||
|
* which is disparaging to Sun.
|
||||||
|
*
|
||||||
|
* This software is provided "AS IS," without a warranty of any kind. ALL
|
||||||
|
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
|
||||||
|
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
|
||||||
|
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
|
||||||
|
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||||
|
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
|
||||||
|
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
|
||||||
|
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
|
||||||
|
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
|
||||||
|
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
*
|
||||||
|
* This software is not designed or intended for use in on-line control of
|
||||||
|
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
|
||||||
|
* the design, construction, operation or maintenance of any nuclear
|
||||||
|
* facility. Licensee represents and warrants that it will not use or
|
||||||
|
* redistribute the Software for such purposes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Win32 specific JRE support definitions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FILE_SEPARATOR '\\'
|
||||||
|
#define PATH_SEPARATOR ';'
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,349 @@
|
||||||
|
/* -*- 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 Sun Microsystems, Inc.
|
||||||
|
* Portions created by Netscape are
|
||||||
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||||
|
* Reserved.
|
||||||
|
*
|
||||||
|
* Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
|
||||||
|
* modify and redistribute this software in source and binary code form,
|
||||||
|
* provided that i) this copyright notice and license appear on all copies of
|
||||||
|
* the software; and ii) Licensee does not utilize the software in a manner
|
||||||
|
* which is disparaging to Sun.
|
||||||
|
*
|
||||||
|
* This software is provided "AS IS," without a warranty of any kind. ALL
|
||||||
|
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
|
||||||
|
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
|
||||||
|
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
|
||||||
|
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||||
|
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
|
||||||
|
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
|
||||||
|
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
|
||||||
|
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
|
||||||
|
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
*
|
||||||
|
* This software is not designed or intended for use in on-line control of
|
||||||
|
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
|
||||||
|
* the design, construction, operation or maintenance of any nuclear
|
||||||
|
* facility. Licensee represents and warrants that it will not use or
|
||||||
|
* redistribute the Software for such purposes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Code to start a Java VM (*some* code from the JRE)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "jsdj.h"
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
#ifdef JSD_STANDALONE_JAVA_VM
|
||||||
|
#include "jre.h"
|
||||||
|
|
||||||
|
static char* more_classpath[] =
|
||||||
|
{
|
||||||
|
{"..\\..\\jsdj\\dist\\classes"},
|
||||||
|
{"..\\..\\jsdj\\dist\\classes\\ifc11.jar"},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* {"..\\..\\..\\jsdj\\dist\\classes"},
|
||||||
|
* {"..\\..\\..\\jsdj\\dist\\classes\\ifc12.jar"},
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* {"..\\..\\samples\\jslogger"},
|
||||||
|
* {"classes"},
|
||||||
|
* {"ifc12.jar"},
|
||||||
|
* {"jsd10.jar"},
|
||||||
|
* {"jsdeb15.jar"}
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
#define MORE_CLASSPATH_COUNT (sizeof(more_classpath)/sizeof(more_classpath[0]))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* static char main_class[] = "callnative";
|
||||||
|
* static char main_class[] = "simpleIFC";
|
||||||
|
* static char* params[] = {"16 Dec 1997"};
|
||||||
|
* #define PARAM_COUNT (sizeof(params)/sizeof(params[0]))
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* static char main_class[] = "netscape/jslogger/JSLogger";
|
||||||
|
* static char main_class[] = "LaunchJSDebugger";
|
||||||
|
*/
|
||||||
|
static char main_class[] = "com/netscape/jsdebugging/ifcui/launcher/local/LaunchJSDebugger";
|
||||||
|
static char* params[] = {NULL};
|
||||||
|
#define PARAM_COUNT 0
|
||||||
|
|
||||||
|
/* Globals */
|
||||||
|
static char **props; /* User-defined properties */
|
||||||
|
static int numProps, maxProps; /* Current, max number of properties */
|
||||||
|
|
||||||
|
static void *handle;
|
||||||
|
static JavaVM *jvm;
|
||||||
|
static JNIEnv *env;
|
||||||
|
|
||||||
|
/* Check for null value and return */
|
||||||
|
#define NULL_CHECK(e) if ((e) == 0) return 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adds a user-defined system property definition.
|
||||||
|
*/
|
||||||
|
void AddProperty(char *def)
|
||||||
|
{
|
||||||
|
if (numProps >= maxProps) {
|
||||||
|
if (props == 0) {
|
||||||
|
maxProps = 4;
|
||||||
|
props = JRE_Malloc(maxProps * sizeof(char **));
|
||||||
|
} else {
|
||||||
|
char **tmp;
|
||||||
|
maxProps *= 2;
|
||||||
|
tmp = JRE_Malloc(maxProps * sizeof(char **));
|
||||||
|
memcpy(tmp, props, numProps * sizeof(char **));
|
||||||
|
free(props);
|
||||||
|
props = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
props[numProps++] = def;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Deletes a property definition by name.
|
||||||
|
*/
|
||||||
|
void DeleteProperty(const char *name)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < numProps; ) {
|
||||||
|
char *def = props[i];
|
||||||
|
char *c = strchr(def, '=');
|
||||||
|
int n;
|
||||||
|
if (c != 0) {
|
||||||
|
n = c - def;
|
||||||
|
} else {
|
||||||
|
n = strlen(def);
|
||||||
|
}
|
||||||
|
if (strncmp(name, def, n) == 0) {
|
||||||
|
if (i < --numProps) {
|
||||||
|
memmove(&props[i], &props[i+1], (numProps-i) * sizeof(char **));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates an array of Java string objects from the specified array of C
|
||||||
|
* strings. Returns 0 if the array could not be created.
|
||||||
|
*/
|
||||||
|
jarray NewStringArray(JNIEnv *env, char **cpp, int count)
|
||||||
|
{
|
||||||
|
jclass cls;
|
||||||
|
jarray ary;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
NULL_CHECK(cls = (*env)->FindClass(env, "java/lang/String"));
|
||||||
|
NULL_CHECK(ary = (*env)->NewObjectArray(env, count, cls, 0));
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
jstring str = (*env)->NewStringUTF(env, *cpp++);
|
||||||
|
NULL_CHECK(str);
|
||||||
|
(*env)->SetObjectArrayElement(env, ary, i, str);
|
||||||
|
(*env)->DeleteLocalRef(env, str);
|
||||||
|
}
|
||||||
|
return ary;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
|
||||||
|
static JNIEnv*
|
||||||
|
_CreateJavaVM(void)
|
||||||
|
{
|
||||||
|
JNIEnv* env = NULL;
|
||||||
|
JDK1_1InitArgs vmargs;
|
||||||
|
JRESettings set;
|
||||||
|
|
||||||
|
printf("Starting Java...\n");
|
||||||
|
|
||||||
|
if(JRE_GetCurrentSettings(&set) != 0)
|
||||||
|
{
|
||||||
|
if(JRE_GetDefaultSettings(&set) != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Could not locate Java runtime\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load runtime library */
|
||||||
|
handle = JRE_LoadLibrary(set.runtimeLib);
|
||||||
|
if (handle == 0) {
|
||||||
|
fprintf(stderr, "Could not load runtime library: %s\n",
|
||||||
|
set.runtimeLib);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add pre-defined system properties */
|
||||||
|
if (set.javaHome != 0) {
|
||||||
|
char *def = JRE_Malloc(strlen(set.javaHome) + 16);
|
||||||
|
sprintf(def, "java.home=%s", set.javaHome);
|
||||||
|
AddProperty(def);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (set.compiler != 0) {
|
||||||
|
char *def = JRE_Malloc(strlen(set.compiler) + 16);
|
||||||
|
sprintf(def, "java.compiler=%s", set.compiler);
|
||||||
|
AddProperty(def);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following is used to specify that we require at least
|
||||||
|
* JNI version 1.1. Currently, this field is not checked but
|
||||||
|
* will be starting with JDK/JRE 1.2. The value returned after
|
||||||
|
* calling JNI_GetDefaultJavaVMInitArgs() is the actual JNI version
|
||||||
|
* supported, and is always higher that the requested version.
|
||||||
|
*/
|
||||||
|
vmargs.version = 0x00010001;
|
||||||
|
|
||||||
|
if (JRE_GetDefaultJavaVMInitArgs(handle, &vmargs) != 0) {
|
||||||
|
fprintf(stderr, "Could not initialize Java VM\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tack on our classpath */
|
||||||
|
if(MORE_CLASSPATH_COUNT)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int size = strlen(set.classPath) + 1;
|
||||||
|
char sep[2];
|
||||||
|
|
||||||
|
sep[0] = PATH_SEPARATOR;
|
||||||
|
sep[1] = 0;
|
||||||
|
|
||||||
|
for(i = 0; i < MORE_CLASSPATH_COUNT; i++)
|
||||||
|
size += strlen(more_classpath[i]) + 1;
|
||||||
|
|
||||||
|
vmargs.classpath = malloc(size);
|
||||||
|
if(vmargs.classpath == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "malloc error\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(vmargs.classpath, set.classPath);
|
||||||
|
for(i = 0; i < MORE_CLASSPATH_COUNT; i++)
|
||||||
|
{
|
||||||
|
strcat(vmargs.classpath, sep);
|
||||||
|
strcat(vmargs.classpath, more_classpath[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vmargs.classpath = set.classPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fprintf(stderr, "classpath: %s\n", vmargs.classpath);
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Set user-defined system properties for Java VM */
|
||||||
|
if (props != 0) {
|
||||||
|
if (numProps == maxProps) {
|
||||||
|
char **tmp = JRE_Malloc((numProps + 1) * sizeof(char **));
|
||||||
|
memcpy(tmp, props, numProps * sizeof(char **));
|
||||||
|
free(props);
|
||||||
|
props = tmp;
|
||||||
|
}
|
||||||
|
props[numProps] = 0;
|
||||||
|
vmargs.properties = props;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* verbose? */
|
||||||
|
/*
|
||||||
|
* vmargs.verbose = JNI_TRUE;
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Load and initialize Java VM */
|
||||||
|
if (JRE_CreateJavaVM(handle, &jvm, &env, &vmargs) != 0) {
|
||||||
|
fprintf(stderr, "Could not create Java VM\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free properties */
|
||||||
|
if (props != 0) {
|
||||||
|
free(props);
|
||||||
|
}
|
||||||
|
return env;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSBool
|
||||||
|
_StartDebuggerFE(JNIEnv* env)
|
||||||
|
{
|
||||||
|
jclass clazz;
|
||||||
|
jmethodID mid;
|
||||||
|
jarray args;
|
||||||
|
|
||||||
|
/* Find class */
|
||||||
|
clazz = (*env)->FindClass(env, main_class);
|
||||||
|
if (clazz == 0) {
|
||||||
|
fprintf(stderr, "Class not found: %s\n", main_class);
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find main method of class */
|
||||||
|
mid = (*env)->GetStaticMethodID(env, clazz, "main",
|
||||||
|
"([Ljava/lang/String;)V");
|
||||||
|
if (mid == 0) {
|
||||||
|
fprintf(stderr, "In class %s: public static void main(String args[])"
|
||||||
|
" is not defined\n");
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Invoke main method */
|
||||||
|
args = NewStringArray(env, params, PARAM_COUNT);
|
||||||
|
|
||||||
|
if (args == 0) {
|
||||||
|
JRE_FatalError(env, "Couldn't build argument list for main\n");
|
||||||
|
}
|
||||||
|
(*env)->CallStaticVoidMethod(env, clazz, mid, args);
|
||||||
|
if ((*env)->ExceptionOccurred(env)) {
|
||||||
|
(*env)->ExceptionDescribe(env);
|
||||||
|
}
|
||||||
|
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEnv*
|
||||||
|
jsdj_CreateJavaVMAndStartDebugger(JSDJContext* jsdjc)
|
||||||
|
{
|
||||||
|
JNIEnv* env = NULL;
|
||||||
|
|
||||||
|
env = _CreateJavaVM();
|
||||||
|
if( ! env )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
jsdj_SetJNIEnvForCurrentThread(jsdjc, env);
|
||||||
|
if( ! jsdj_RegisterNatives(jsdjc) )
|
||||||
|
return NULL;
|
||||||
|
if( ! _StartDebuggerFE(env) )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return env;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* JSD_STANDALONE_JAVA_VM */
|
||||||
|
/***************************************************************************/
|
||||||
|
|
|
@ -0,0 +1,147 @@
|
||||||
|
/* -*- 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Header for JavaScript Debugger JNI support (internal functions)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef jsdj_h___
|
||||||
|
#define jsdj_h___
|
||||||
|
|
||||||
|
/* Get jstypes.h included first. After that we can use PR macros for doing
|
||||||
|
* this extern "C" stuff!
|
||||||
|
*/
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
#include "jstypes.h"
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
JS_BEGIN_EXTERN_C
|
||||||
|
#include "jsutil.h" /* Added by JSIFY */
|
||||||
|
#include "jshash.h" /* Added by JSIFY */
|
||||||
|
#include "jsdjava.h"
|
||||||
|
#include "jsobj.h"
|
||||||
|
#include "jsfun.h"
|
||||||
|
#include "jsdbgapi.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
JS_END_EXTERN_C
|
||||||
|
|
||||||
|
JS_BEGIN_EXTERN_C
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/* defines copied from Java sources.
|
||||||
|
** NOTE: javah used to put these in the h files, but with JNI does not seem
|
||||||
|
** to do this anymore. Be careful with synchronization of these
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* From: ThreadStateBase.java */
|
||||||
|
|
||||||
|
#define THR_STATUS_UNKNOWN 0x01
|
||||||
|
#define THR_STATUS_ZOMBIE 0x02
|
||||||
|
#define THR_STATUS_RUNNING 0x03
|
||||||
|
#define THR_STATUS_SLEEPING 0x04
|
||||||
|
#define THR_STATUS_MONWAIT 0x05
|
||||||
|
#define THR_STATUS_CONDWAIT 0x06
|
||||||
|
#define THR_STATUS_SUSPENDED 0x07
|
||||||
|
#define THR_STATUS_BREAK 0x08
|
||||||
|
|
||||||
|
#define DEBUG_STATE_DEAD 0x01
|
||||||
|
#define DEBUG_STATE_RUN 0x02
|
||||||
|
#define DEBUG_STATE_RETURN 0x03
|
||||||
|
#define DEBUG_STATE_THROW 0x04
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/* Our structures */
|
||||||
|
|
||||||
|
typedef struct JSDJContext
|
||||||
|
{
|
||||||
|
JSDContext* jsdc;
|
||||||
|
JSHashTable* envTable;
|
||||||
|
jobject controller;
|
||||||
|
JSDJ_UserCallbacks callbacks;
|
||||||
|
void* user;
|
||||||
|
JSBool ownJSDC;
|
||||||
|
} JSDJContext;
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/* Code validation support */
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
extern void JSDJ_ASSERT_VALID_CONTEXT(JSDJContext* jsdjc);
|
||||||
|
#else
|
||||||
|
#define JSDJ_ASSERT_VALID_CONTEXT(x) ((void)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/* higher level functions */
|
||||||
|
|
||||||
|
extern JSDJContext*
|
||||||
|
jsdj_SimpleInitForSingleContextMode(JSDContext* jsdc,
|
||||||
|
JSDJ_GetJNIEnvProc getEnvProc, void* user);
|
||||||
|
extern JSBool
|
||||||
|
jsdj_SetSingleContextMode();
|
||||||
|
|
||||||
|
extern JSDJContext*
|
||||||
|
jsdj_CreateContext();
|
||||||
|
|
||||||
|
extern void
|
||||||
|
jsdj_DestroyContext(JSDJContext* jsdjc);
|
||||||
|
|
||||||
|
extern void
|
||||||
|
jsdj_SetUserCallbacks(JSDJContext* jsdjc, JSDJ_UserCallbacks* callbacks,
|
||||||
|
void* user);
|
||||||
|
extern void
|
||||||
|
jsdj_SetJNIEnvForCurrentThread(JSDJContext* jsdjc, JNIEnv* env);
|
||||||
|
|
||||||
|
extern JNIEnv*
|
||||||
|
jsdj_GetJNIEnvForCurrentThread(JSDJContext* jsdjc);
|
||||||
|
|
||||||
|
extern void
|
||||||
|
jsdj_SetJSDContext(JSDJContext* jsdjc, JSDContext* jsdc);
|
||||||
|
|
||||||
|
extern JSDContext*
|
||||||
|
jsdj_GetJSDContext(JSDJContext* jsdjc);
|
||||||
|
|
||||||
|
extern JSBool
|
||||||
|
jsdj_RegisterNatives(JSDJContext* jsdjc);
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
#ifdef JSD_STANDALONE_JAVA_VM
|
||||||
|
|
||||||
|
extern JNIEnv*
|
||||||
|
jsdj_CreateJavaVMAndStartDebugger(JSDJContext* jsdjc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* extern JNIEnv*
|
||||||
|
* jsdj_CreateJavaVM(JSDContext* jsdc);
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* JSD_STANDALONE_JAVA_VM */
|
||||||
|
/***************************************************************************/
|
||||||
|
|
||||||
|
JS_END_EXTERN_C
|
||||||
|
|
||||||
|
#endif /* jsdj_h___ */
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
/* -*- 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Public functions to reflect JSD into Java
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "jsdj.h"
|
||||||
|
|
||||||
|
JSDJ_PUBLIC_API(JSDJContext*)
|
||||||
|
JSDJ_SimpleInitForSingleContextMode(JSDContext* jsdc,
|
||||||
|
JSDJ_GetJNIEnvProc getEnvProc, void* user)
|
||||||
|
{
|
||||||
|
return jsdj_SimpleInitForSingleContextMode(jsdc, getEnvProc, user);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSDJ_PUBLIC_API(JSBool)
|
||||||
|
JSDJ_SetSingleContextMode()
|
||||||
|
{
|
||||||
|
return jsdj_SetSingleContextMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
JSDJ_PUBLIC_API(JSDJContext*)
|
||||||
|
JSDJ_CreateContext()
|
||||||
|
{
|
||||||
|
return jsdj_CreateContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
JSDJ_PUBLIC_API(void)
|
||||||
|
JSDJ_DestroyContext(JSDJContext* jsdjc)
|
||||||
|
{
|
||||||
|
JSDJ_ASSERT_VALID_CONTEXT(jsdjc);
|
||||||
|
jsdj_DestroyContext(jsdjc);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSDJ_PUBLIC_API(void)
|
||||||
|
JSDJ_SetUserCallbacks(JSDJContext* jsdjc, JSDJ_UserCallbacks* callbacks,
|
||||||
|
void* user)
|
||||||
|
{
|
||||||
|
JSDJ_ASSERT_VALID_CONTEXT(jsdjc);
|
||||||
|
JS_ASSERT(!callbacks ||
|
||||||
|
(callbacks->size > 0 &&
|
||||||
|
callbacks->size <= sizeof(JSDJ_UserCallbacks)));
|
||||||
|
jsdj_SetUserCallbacks(jsdjc, callbacks, user);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSDJ_PUBLIC_API(void)
|
||||||
|
JSDJ_SetJNIEnvForCurrentThread(JSDJContext* jsdjc, JNIEnv* env)
|
||||||
|
{
|
||||||
|
JSDJ_ASSERT_VALID_CONTEXT(jsdjc);
|
||||||
|
JS_ASSERT(env);
|
||||||
|
jsdj_SetJNIEnvForCurrentThread(jsdjc, env);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSDJ_PUBLIC_API(JNIEnv*)
|
||||||
|
JSDJ_GetJNIEnvForCurrentThread(JSDJContext* jsdjc)
|
||||||
|
{
|
||||||
|
JSDJ_ASSERT_VALID_CONTEXT(jsdjc);
|
||||||
|
return jsdj_GetJNIEnvForCurrentThread(jsdjc);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSDJ_PUBLIC_API(void)
|
||||||
|
JSDJ_SetJSDContext(JSDJContext* jsdjc, JSDContext* jsdc)
|
||||||
|
{
|
||||||
|
JSDJ_ASSERT_VALID_CONTEXT(jsdjc);
|
||||||
|
JS_ASSERT(jsdc);
|
||||||
|
jsdj_SetJSDContext(jsdjc, jsdc);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSDJ_PUBLIC_API(JSDContext*)
|
||||||
|
JSDJ_GetJSDContext(JSDJContext* jsdjc)
|
||||||
|
{
|
||||||
|
JSDJ_ASSERT_VALID_CONTEXT(jsdjc);
|
||||||
|
return jsdj_GetJSDContext(jsdjc);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSDJ_PUBLIC_API(JSBool)
|
||||||
|
JSDJ_RegisterNatives(JSDJContext* jsdjc)
|
||||||
|
{
|
||||||
|
JSDJ_ASSERT_VALID_CONTEXT(jsdjc);
|
||||||
|
return jsdj_RegisterNatives(jsdjc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
#ifdef JSD_STANDALONE_JAVA_VM
|
||||||
|
|
||||||
|
JSDJ_PUBLIC_API(JNIEnv*)
|
||||||
|
JSDJ_CreateJavaVMAndStartDebugger(JSDJContext* jsdjc)
|
||||||
|
{
|
||||||
|
JSDJ_ASSERT_VALID_CONTEXT(jsdjc);
|
||||||
|
return jsdj_CreateJavaVMAndStartDebugger(jsdjc);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* JSD_STANDALONE_JAVA_VM */
|
||||||
|
/***************************************************************************/
|
|
@ -0,0 +1,133 @@
|
||||||
|
/* -*- 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Header for JavaScript Debugger JNI interfaces
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef jsdjava_h___
|
||||||
|
#define jsdjava_h___
|
||||||
|
|
||||||
|
/* Get jstypes.h included first. After that we can use PR macros for doing
|
||||||
|
* this extern "C" stuff!
|
||||||
|
*/
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
#include "jstypes.h"
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
JS_BEGIN_EXTERN_C
|
||||||
|
#include "jsdebug.h"
|
||||||
|
#include "jni.h"
|
||||||
|
JS_END_EXTERN_C
|
||||||
|
|
||||||
|
|
||||||
|
JS_BEGIN_EXTERN_C
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The linkage of JSDJ API functions differs depending on whether the file is
|
||||||
|
* used within the JSDJ library or not. Any source file within the JSDJ
|
||||||
|
* libraray should define EXPORT_JSDJ_API whereas any client of the library
|
||||||
|
* should not.
|
||||||
|
*/
|
||||||
|
#ifdef EXPORT_JSDJ_API
|
||||||
|
#define JSDJ_PUBLIC_API(t) JS_EXPORT_API(t)
|
||||||
|
#define JSDJ_PUBLIC_DATA(t) JS_EXPORT_DATA(t)
|
||||||
|
#else
|
||||||
|
#define JSDJ_PUBLIC_API(t) JS_IMPORT_API(t)
|
||||||
|
#define JSDJ_PUBLIC_DATA(t) JS_IMPORT_DATA(t)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define JSDJ_FRIEND_API(t) JSDJ_PUBLIC_API(t)
|
||||||
|
#define JSDJ_FRIEND_DATA(t) JSDJ_PUBLIC_DATA(t)
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/* Opaque typedefs for handles */
|
||||||
|
|
||||||
|
typedef struct JSDJContext JSDJContext;
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/* High Level functions */
|
||||||
|
|
||||||
|
#define JSDJ_START_SUCCESS 1
|
||||||
|
#define JSDJ_START_FAILURE 2
|
||||||
|
#define JSDJ_STOP 3
|
||||||
|
|
||||||
|
typedef void
|
||||||
|
(*JSDJ_StartStopProc)(JSDJContext* jsdjc, int event, void *user);
|
||||||
|
|
||||||
|
typedef JNIEnv*
|
||||||
|
(*JSDJ_GetJNIEnvProc)(JSDJContext* jsdjc, void* user);
|
||||||
|
|
||||||
|
/* This struct could have more fields in future versions */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uintN size; /* size of this struct (init before use)*/
|
||||||
|
JSDJ_StartStopProc startStop;
|
||||||
|
JSDJ_GetJNIEnvProc getJNIEnv;
|
||||||
|
} JSDJ_UserCallbacks;
|
||||||
|
|
||||||
|
extern JSDJ_PUBLIC_API(JSDJContext*)
|
||||||
|
JSDJ_SimpleInitForSingleContextMode(JSDContext* jsdc,
|
||||||
|
JSDJ_GetJNIEnvProc getEnvProc, void* user);
|
||||||
|
|
||||||
|
extern JSDJ_PUBLIC_API(JSBool)
|
||||||
|
JSDJ_SetSingleContextMode();
|
||||||
|
|
||||||
|
extern JSDJ_PUBLIC_API(JSDJContext*)
|
||||||
|
JSDJ_CreateContext();
|
||||||
|
|
||||||
|
extern JSDJ_PUBLIC_API(void)
|
||||||
|
JSDJ_DestroyContext(JSDJContext* jsdjc);
|
||||||
|
|
||||||
|
extern JSDJ_PUBLIC_API(void)
|
||||||
|
JSDJ_SetUserCallbacks(JSDJContext* jsdjc, JSDJ_UserCallbacks* callbacks,
|
||||||
|
void* user);
|
||||||
|
|
||||||
|
extern JSDJ_PUBLIC_API(void)
|
||||||
|
JSDJ_SetJNIEnvForCurrentThread(JSDJContext* jsdjc, JNIEnv* env);
|
||||||
|
|
||||||
|
extern JSDJ_PUBLIC_API(JNIEnv*)
|
||||||
|
JSDJ_GetJNIEnvForCurrentThread(JSDJContext* jsdjc);
|
||||||
|
|
||||||
|
extern JSDJ_PUBLIC_API(void)
|
||||||
|
JSDJ_SetJSDContext(JSDJContext* jsdjc, JSDContext* jsdc);
|
||||||
|
|
||||||
|
extern JSDJ_PUBLIC_API(JSDContext*)
|
||||||
|
JSDJ_GetJSDContext(JSDJContext* jsdjc);
|
||||||
|
|
||||||
|
extern JSDJ_PUBLIC_API(JSBool)
|
||||||
|
JSDJ_RegisterNatives(JSDJContext* jsdjc);
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
#ifdef JSD_STANDALONE_JAVA_VM
|
||||||
|
|
||||||
|
extern JSDJ_PUBLIC_API(JNIEnv*)
|
||||||
|
JSDJ_CreateJavaVMAndStartDebugger(JSDJContext* jsdjc);
|
||||||
|
|
||||||
|
#endif /* JSD_STANDALONE_JAVA_VM */
|
||||||
|
/***************************************************************************/
|
||||||
|
|
||||||
|
JS_END_EXTERN_C
|
||||||
|
|
||||||
|
#endif /* jsdjava_h___ */
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
|
||||||
|
PROJ = jsdjava
|
||||||
|
JSDJAVA = .
|
||||||
|
JSD = $(JSDJAVA)\..
|
||||||
|
JS = $(JSD)\..\src
|
||||||
|
JSPROJ = js32
|
||||||
|
JSDPROJ = jsd
|
||||||
|
|
||||||
|
!IF "$(BUILD_OPT)" != ""
|
||||||
|
OBJ = Release
|
||||||
|
CC_FLAGS = /DNDEBUG
|
||||||
|
!ELSE
|
||||||
|
OBJ = Debug
|
||||||
|
CC_FLAGS = /DDEBUG
|
||||||
|
LINK_FLAGS = /DEBUG
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
QUIET=@
|
||||||
|
|
||||||
|
CFLAGS = /nologo /MDd /W3 /Gm /GX /Zi /Od\
|
||||||
|
/I $(JS)\
|
||||||
|
/I $(JSD)\
|
||||||
|
/I $(JSDJAVA)\
|
||||||
|
/DDEBUG /DWIN32 /DXP_PC /D_WINDOWS /D_WIN32\
|
||||||
|
/DJSD_THREADSAFE\
|
||||||
|
/DEXPORT_JSDJ_API\
|
||||||
|
/DJSDEBUGGER\
|
||||||
|
!IF "$(JSD_STANDALONE_JAVA_VM)" != ""
|
||||||
|
/I $(JSDJAVA)\jre\
|
||||||
|
/I $(JSDJAVA)\jre\win32\
|
||||||
|
/DJSD_STANDALONE_JAVA_VM\
|
||||||
|
!ENDIF
|
||||||
|
$(CC_FLAGS)\
|
||||||
|
/c /Fp$(OBJ)\$(PROJ).pch /Fd$(OBJ)\$(PROJ).pdb /YX -Fo$@ $<
|
||||||
|
|
||||||
|
LFLAGS = /nologo /subsystem:console /DLL /incremental:no /machine:I386 \
|
||||||
|
$(LINK_FLAGS) /pdb:$(OBJ)\$(PROJ).pdb -out:$(OBJ)\$(PROJ).dll
|
||||||
|
|
||||||
|
LLIBS = kernel32.lib advapi32.lib \
|
||||||
|
$(JS)\$(OBJ)\$(JSPROJ).lib $(JSD)\$(OBJ)\$(JSDPROJ).lib
|
||||||
|
|
||||||
|
CPP=cl.exe
|
||||||
|
LINK32=link.exe
|
||||||
|
|
||||||
|
all: $(OBJ) $(OBJ)\$(PROJ).dll
|
||||||
|
|
||||||
|
|
||||||
|
$(OBJ)\$(PROJ).dll: \
|
||||||
|
!IF "$(JSD_STANDALONE_JAVA_VM)" != ""
|
||||||
|
$(OBJ)\jsd_jvm.obj \
|
||||||
|
$(OBJ)\jre.obj \
|
||||||
|
$(OBJ)\jre_md.obj \
|
||||||
|
!ENDIF
|
||||||
|
$(OBJ)\jsdjava.obj \
|
||||||
|
$(OBJ)\jsd_jntv.obj
|
||||||
|
$(QUIET)$(LINK32) $(LFLAGS) $** $(LLIBS)
|
||||||
|
|
||||||
|
{$(JSDJAVA)}.c{$(OBJ)}.obj :
|
||||||
|
$(QUIET)$(CPP) $(CFLAGS)
|
||||||
|
|
||||||
|
{$(JSDJAVA)\jre}.c{$(OBJ)}.obj :
|
||||||
|
$(QUIET)$(CPP) $(CFLAGS)
|
||||||
|
|
||||||
|
{$(JSDJAVA)\jre\win32}.c{$(OBJ)}.obj :
|
||||||
|
$(QUIET)$(CPP) $(CFLAGS)
|
||||||
|
|
||||||
|
$(OBJ) :
|
||||||
|
$(QUIET)mkdir $(OBJ)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@echo deleting old output
|
||||||
|
$(QUIET)del $(OBJ)\*.pch >NUL
|
||||||
|
$(QUIET)del $(OBJ)\*.obj >NUL
|
||||||
|
$(QUIET)del $(OBJ)\*.exp >NUL
|
||||||
|
$(QUIET)del $(OBJ)\*.lib >NUL
|
||||||
|
$(QUIET)del $(OBJ)\*.idb >NUL
|
||||||
|
$(QUIET)del $(OBJ)\*.pdb >NUL
|
||||||
|
$(QUIET)del $(OBJ)\*.dll >NUL
|
|
@ -0,0 +1,147 @@
|
||||||
|
|
||||||
|
PROJ = nativejsengine
|
||||||
|
PACKAGE_DOT = com.netscape.nativejsengine
|
||||||
|
|
||||||
|
NJSE = .
|
||||||
|
TESTS = $(NJSE)\tests
|
||||||
|
GEN = $(NJSE)\_jni
|
||||||
|
JSD = $(NJSE)\..
|
||||||
|
JS = $(JSD)\..\src
|
||||||
|
JSDJAVA = $(JSD)\java
|
||||||
|
|
||||||
|
JSPROJ = js32
|
||||||
|
JSDPROJ = jsd
|
||||||
|
JSDJAVAPROJ = jsdjava
|
||||||
|
|
||||||
|
EXPORT_BIN_BASE_DIR = $(NJSE)\..\..\jsdj\dist\bin
|
||||||
|
EXPORT_CLASSES_BASE_DIR = $(NJSE)\..\..\jsdj\dist\classes
|
||||||
|
|
||||||
|
!IF "$(BUILD_OPT)" != ""
|
||||||
|
OBJ = Release
|
||||||
|
CC_FLAGS = /DNDEBUG
|
||||||
|
!ELSE
|
||||||
|
OBJ = Debug
|
||||||
|
CC_FLAGS = /DDEBUG
|
||||||
|
LINK_FLAGS = /DEBUG
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
QUIET=@
|
||||||
|
|
||||||
|
EXPORT_BIN_DIR = $(EXPORT_BIN_BASE_DIR)\$(OBJ)
|
||||||
|
|
||||||
|
STD_CLASSPATH = -classpath $(EXPORT_CLASSES_BASE_DIR);$(CLASSPATH)
|
||||||
|
|
||||||
|
CFLAGS = /nologo /MDd /W3 /Gm /GX /Zi /Od\
|
||||||
|
/DWIN32 /DXP_PC /D_WINDOWS /D_WIN32\
|
||||||
|
/I $(JS)\
|
||||||
|
/I $(JSD)\
|
||||||
|
/I $(JSDJAVA)\
|
||||||
|
/DJSDEBUGGER\
|
||||||
|
/DJSD_THREADSAFE\
|
||||||
|
$(CC_FLAGS)\
|
||||||
|
/c /Fp$(OBJ)\$(PROJ).pch /Fd$(OBJ)\$(PROJ).pdb /YX -Fo$@ $<
|
||||||
|
|
||||||
|
LFLAGS = /nologo /subsystem:console /incremental:no /DLL /machine:I386 \
|
||||||
|
$(LINK_FLAGS) /pdb:$(OBJ)\$(PROJ).pdb -out:$(OBJ)\$(PROJ).dll
|
||||||
|
|
||||||
|
LLIBS = kernel32.lib advapi32.lib \
|
||||||
|
$(JS)\$(OBJ)\$(JSPROJ).lib \
|
||||||
|
$(JSD)\$(OBJ)\$(JSDPROJ).lib \
|
||||||
|
$(JSDJAVA)\$(OBJ)\$(JSDJAVAPROJ).lib
|
||||||
|
|
||||||
|
CPP=cl.exe
|
||||||
|
LINK32=link.exe
|
||||||
|
|
||||||
|
CLASSES_WITH_NATIVES = \
|
||||||
|
$(PACKAGE_DOT).JSRuntime\
|
||||||
|
$(PACKAGE_DOT).JSContext
|
||||||
|
|
||||||
|
|
||||||
|
all: $(GEN) $(OBJ) dlls mkjniheaders $(OBJ)\$(PROJ).dll export_binaries
|
||||||
|
|
||||||
|
$(OBJ)\$(PROJ).dll: \
|
||||||
|
$(OBJ)\nativejsengine.obj
|
||||||
|
$(QUIET)$(LINK32) $(LFLAGS) $** $(LLIBS)
|
||||||
|
|
||||||
|
.c{$(OBJ)}.obj:
|
||||||
|
$(QUIET)$(CPP) $(CFLAGS)
|
||||||
|
|
||||||
|
$(GEN) :
|
||||||
|
@mkdir $(GEN)
|
||||||
|
|
||||||
|
$(OBJ) :
|
||||||
|
@mkdir $(OBJ)
|
||||||
|
|
||||||
|
dlls :
|
||||||
|
$(QUIET)cd ..\..\src
|
||||||
|
!IF "$(BUILD_OPT)" != ""
|
||||||
|
$(QUIET)nmake -f js.mak CFG="js - Win32 Release"
|
||||||
|
!ELSE
|
||||||
|
$(QUIET)nmake -f js.mak CFG="js - Win32 Debug"
|
||||||
|
!ENDIF
|
||||||
|
$(QUIET)cd ..\jsd\javawrap
|
||||||
|
$(QUIET)cd ..
|
||||||
|
$(QUIET)nmake -f jsd.mak JSD_THREADSAFE=1 $(OPT)
|
||||||
|
$(QUIET)cd javawrap
|
||||||
|
$(QUIET)cd ..\java
|
||||||
|
$(QUIET)nmake -f jsdjava.mak $(OPT)
|
||||||
|
$(QUIET)cd ..\javawrap
|
||||||
|
|
||||||
|
|
||||||
|
export_binaries : mk_export_dirs
|
||||||
|
@echo exporting binaries
|
||||||
|
$(QUIET)copy $(JS)\$(OBJ)\$(JSPROJ).dll $(EXPORT_BIN_DIR) >NUL
|
||||||
|
$(QUIET)copy $(JS)\$(OBJ)\$(JSPROJ).pdb $(EXPORT_BIN_DIR) >NUL
|
||||||
|
$(QUIET)copy $(JSD)\$(OBJ)\$(JSDPROJ).dll $(EXPORT_BIN_DIR) >NUL
|
||||||
|
$(QUIET)copy $(JSD)\$(OBJ)\$(JSDPROJ).pdb $(EXPORT_BIN_DIR) >NUL
|
||||||
|
$(QUIET)copy $(JSDJAVA)\$(OBJ)\$(JSDJAVAPROJ).dll $(EXPORT_BIN_DIR) >NUL
|
||||||
|
$(QUIET)copy $(JSDJAVA)\$(OBJ)\$(JSDJAVAPROJ).pdb $(EXPORT_BIN_DIR) >NUL
|
||||||
|
$(QUIET)copy $(OBJ)\$(PROJ).pdb $(EXPORT_BIN_DIR) >NUL
|
||||||
|
$(QUIET)copy $(OBJ)\$(PROJ).dll $(EXPORT_BIN_DIR) >NUL
|
||||||
|
|
||||||
|
mkjniheaders :
|
||||||
|
@echo generating JNI header
|
||||||
|
$(QUIET)javah -jni -d "$(GEN)" $(STD_CLASSPATH) $(CLASSES_WITH_NATIVES)
|
||||||
|
@touch *.c >NUL
|
||||||
|
|
||||||
|
mk_export_dirs:
|
||||||
|
@if not exist $(JS)\..\jsdj\dist\NUL @mkdir $(JS)\..\jsdj\dist
|
||||||
|
@if not exist $(JS)\..\jsdj\dist\bin\NUL @mkdir $(JS)\..\jsdj\dist\bin
|
||||||
|
@if not exist $(EXPORT_BIN_DIR)\NUL @mkdir $(EXPORT_BIN_DIR)
|
||||||
|
|
||||||
|
#mktest :
|
||||||
|
# @echo compiling Java test file
|
||||||
|
# @sj $(JAVAFLAGS) $(TEST_CLASSPATH) $(TESTS)\Main.java
|
||||||
|
# @echo copying js and jsd dlls
|
||||||
|
# @copy $(JS)\$(OBJ)\$(JSPROJ).dll $(OBJ) >NUL
|
||||||
|
# @copy $(JS)\$(OBJ)\$(JSPROJ).pdb $(OBJ) >NUL
|
||||||
|
# @copy $(JSD)\$(OBJ)\$(JSDPROJ).dll $(OBJ) >NUL
|
||||||
|
# @copy $(JSD)\$(OBJ)\$(JSDPROJ).pdb $(OBJ) >NUL
|
||||||
|
# @copy $(TESTS)\*.js $(OBJ) >NUL
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@echo deleting old output
|
||||||
|
$(QUIET)del $(OBJ)\*.pch >NUL
|
||||||
|
$(QUIET)del $(OBJ)\*.obj >NUL
|
||||||
|
$(QUIET)del $(OBJ)\*.exp >NUL
|
||||||
|
$(QUIET)del $(OBJ)\*.lib >NUL
|
||||||
|
$(QUIET)del $(OBJ)\*.idb >NUL
|
||||||
|
$(QUIET)del $(OBJ)\*.pdb >NUL
|
||||||
|
$(QUIET)del $(OBJ)\*.dll >NUL
|
||||||
|
$(QUIET)del $(GEN)\*.h >NUL
|
||||||
|
|
||||||
|
|
||||||
|
deep_clean: clean
|
||||||
|
$(QUIET)cd ..\..\src
|
||||||
|
!IF "$(BUILD_OPT)" != ""
|
||||||
|
$(QUIET)nmake -f js.mak CFG="js - Win32 Release" clean
|
||||||
|
!ELSE
|
||||||
|
$(QUIET)nmake -f js.mak CFG="js - Win32 Debug" clean
|
||||||
|
!ENDIF
|
||||||
|
$(QUIET)cd ..\jsd\javawrap
|
||||||
|
$(QUIET)cd ..
|
||||||
|
$(QUIET)nmake -f jsd.mak clean
|
||||||
|
$(QUIET)cd javawrap
|
||||||
|
$(QUIET)cd ..\java
|
||||||
|
$(QUIET)nmake -f jsdjava.mak clean
|
||||||
|
$(QUIET)cd ..\javawrap
|
|
@ -0,0 +1 @@
|
||||||
|
nmake -f javawrap.mak %1 %2 %3 %4 %5
|
|
@ -0,0 +1,616 @@
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "_jni/com_netscape_nativejsengine_JSRuntime.h"
|
||||||
|
#include "_jni/com_netscape_nativejsengine_JSContext.h"
|
||||||
|
|
||||||
|
#include "jsapi.h"
|
||||||
|
#include "jstypes.h"
|
||||||
|
#include "jsutil.h" /* Added by JSIFY */
|
||||||
|
|
||||||
|
#ifdef JSDEBUGGER
|
||||||
|
#include "jsdebug.h"
|
||||||
|
#include "jsdjava.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
|
||||||
|
#define ASSERT_RETURN_VOID(x) \
|
||||||
|
JS_BEGIN_MACRO \
|
||||||
|
if(!(x)) \
|
||||||
|
{ \
|
||||||
|
JS_ASSERT(0); \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
JS_END_MACRO
|
||||||
|
|
||||||
|
#define ASSERT_RETURN_VALUE(x,v)\
|
||||||
|
JS_BEGIN_MACRO \
|
||||||
|
if(!(x)) \
|
||||||
|
{ \
|
||||||
|
JS_ASSERT(0); \
|
||||||
|
return v; \
|
||||||
|
} \
|
||||||
|
JS_END_MACRO
|
||||||
|
|
||||||
|
#define CHECK_RETURN_VOID(x) \
|
||||||
|
JS_BEGIN_MACRO \
|
||||||
|
if(!(x)) \
|
||||||
|
{ \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
JS_END_MACRO
|
||||||
|
|
||||||
|
#define CHECK_RETURN_VALUE(x,v) \
|
||||||
|
JS_BEGIN_MACRO \
|
||||||
|
if(!(x)) \
|
||||||
|
{ \
|
||||||
|
return v; \
|
||||||
|
} \
|
||||||
|
JS_END_MACRO
|
||||||
|
|
||||||
|
#define ASSERT_GOTO(x,w) \
|
||||||
|
JS_BEGIN_MACRO \
|
||||||
|
if(!(x)) \
|
||||||
|
{ \
|
||||||
|
JS_ASSERT(0); \
|
||||||
|
goto w; \
|
||||||
|
} \
|
||||||
|
JS_END_MACRO
|
||||||
|
|
||||||
|
#define CHECK_GOTO(x,w) \
|
||||||
|
JS_BEGIN_MACRO \
|
||||||
|
if(!(x)) \
|
||||||
|
{ \
|
||||||
|
goto w; \
|
||||||
|
} \
|
||||||
|
JS_END_MACRO
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define ASSERT_CLEAR_EXCEPTION(e) \
|
||||||
|
JS_BEGIN_MACRO \
|
||||||
|
if((*e)->ExceptionOccurred(e)) \
|
||||||
|
{ \
|
||||||
|
(*e)->ExceptionDescribe(e); \
|
||||||
|
JS_ASSERT(0); \
|
||||||
|
} \
|
||||||
|
(*e)->ExceptionClear(e); \
|
||||||
|
JS_END_MACRO
|
||||||
|
#else /* ! DEBUG */
|
||||||
|
#define ASSERT_CLEAR_EXCEPTION(e) (*e)->ExceptionClear(e)
|
||||||
|
#endif /* DEBUG */
|
||||||
|
|
||||||
|
#define CHECK_CLEAR_EXCEPTION(e) (*e)->ExceptionClear(e)
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
|
||||||
|
typedef struct ContextInfo {
|
||||||
|
JNIEnv* env;
|
||||||
|
jobject contextObject;
|
||||||
|
} ContextInfo;
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
|
||||||
|
#ifdef JSDEBUGGER
|
||||||
|
static void
|
||||||
|
_jamSourceIntoJSD(JSContext *cx, const char* src, int len, const char* filename)
|
||||||
|
{
|
||||||
|
jclass clazz_self;
|
||||||
|
jclass clazz;
|
||||||
|
JSDJContext* jsdjc;
|
||||||
|
jobject rtObject;
|
||||||
|
jobject contextObject;
|
||||||
|
jmethodID mid;
|
||||||
|
jfieldID fid;
|
||||||
|
ContextInfo* info;
|
||||||
|
JNIEnv* env;
|
||||||
|
|
||||||
|
info = (ContextInfo*) JS_GetContextPrivate(cx);
|
||||||
|
ASSERT_RETURN_VOID(info);
|
||||||
|
|
||||||
|
env = info->env;
|
||||||
|
ASSERT_RETURN_VOID(env);
|
||||||
|
|
||||||
|
contextObject = info->contextObject;
|
||||||
|
ASSERT_RETURN_VOID(contextObject);
|
||||||
|
|
||||||
|
clazz_self = (*env)->GetObjectClass(env, contextObject);
|
||||||
|
ASSERT_RETURN_VOID(clazz_self);
|
||||||
|
|
||||||
|
fid = (*env)->GetFieldID(env, clazz_self, "_runtime",
|
||||||
|
"Lcom/netscape/nativejsengine/JSRuntime;");
|
||||||
|
ASSERT_RETURN_VOID(fid);
|
||||||
|
|
||||||
|
rtObject = (*env)->GetObjectField(env, contextObject, fid);
|
||||||
|
ASSERT_RETURN_VOID(rtObject);
|
||||||
|
|
||||||
|
clazz = (*env)->GetObjectClass(env, rtObject);
|
||||||
|
ASSERT_RETURN_VOID(clazz);
|
||||||
|
|
||||||
|
mid = (*env)->GetMethodID(env, clazz, "getNativeDebugSupport", "()J");
|
||||||
|
ASSERT_RETURN_VOID(mid);
|
||||||
|
|
||||||
|
jsdjc = (JSDJContext*) (*env)->CallObjectMethod(env, rtObject, mid);
|
||||||
|
if(jsdjc)
|
||||||
|
{
|
||||||
|
JSDContext* jsdc;
|
||||||
|
|
||||||
|
jsdc = JSDJ_GetJSDContext(jsdjc);
|
||||||
|
ASSERT_RETURN_VOID(jsdc);
|
||||||
|
|
||||||
|
JSD_AddFullSourceText(jsdc, src, len, filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static JSBool
|
||||||
|
_loadSingleFile(JSContext *cx, JSObject *obj, const char* filename)
|
||||||
|
{
|
||||||
|
char* buf;
|
||||||
|
FILE* file;
|
||||||
|
int file_len;
|
||||||
|
jsval result;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
file = fopen(filename, "rb");
|
||||||
|
if (!file) {
|
||||||
|
JS_ReportError(cx, "can't open %s: %s", filename, strerror(errno));
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(file, 0, SEEK_END);
|
||||||
|
file_len = ftell(file);
|
||||||
|
fseek(file, 0, SEEK_SET);
|
||||||
|
|
||||||
|
if(! file_len) {
|
||||||
|
fclose(file);
|
||||||
|
JS_ReportError(cx, "%s is empty", filename);
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = (char*) malloc(file_len);
|
||||||
|
if(! buf) {
|
||||||
|
fclose(file);
|
||||||
|
JS_ReportError(cx, "memory alloc error while trying to read %s", filename);
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
fread(buf, 1, file_len, file);
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
#ifdef JSDEBUGGER
|
||||||
|
_jamSourceIntoJSD(cx, buf, file_len, filename);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
JS_EvaluateScript(cx, obj, buf, file_len, filename, 1, &result);
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void _sendPrintStringToJava(JNIEnv* env, jobject contextObject,
|
||||||
|
jmethodID mid, const char* str)
|
||||||
|
{
|
||||||
|
if(! str)
|
||||||
|
return;
|
||||||
|
(*env)->CallObjectMethod(env, contextObject, mid,
|
||||||
|
(*env)->NewStringUTF(env, str));
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSBool
|
||||||
|
Print(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
|
{
|
||||||
|
uintN i, n;
|
||||||
|
JSString *str;
|
||||||
|
|
||||||
|
ContextInfo* info;
|
||||||
|
jmethodID mid;
|
||||||
|
jclass clazz;
|
||||||
|
JNIEnv* env;
|
||||||
|
|
||||||
|
info = (ContextInfo*) JS_GetContextPrivate(cx);
|
||||||
|
ASSERT_RETURN_VALUE(info, JS_FALSE);
|
||||||
|
|
||||||
|
env = info->env;
|
||||||
|
ASSERT_RETURN_VALUE(env, JS_FALSE);
|
||||||
|
|
||||||
|
clazz = (*env)->GetObjectClass(env, info->contextObject);
|
||||||
|
ASSERT_RETURN_VALUE(clazz, JS_FALSE);
|
||||||
|
|
||||||
|
mid = (*env)->GetMethodID(env, clazz, "_print", "(Ljava/lang/String;)V");
|
||||||
|
ASSERT_RETURN_VALUE(mid, JS_FALSE);
|
||||||
|
|
||||||
|
for (i = n = 0; i < argc; i++) {
|
||||||
|
str = JS_ValueToString(cx, argv[i]);
|
||||||
|
if (!str)
|
||||||
|
return JS_FALSE;
|
||||||
|
|
||||||
|
if(i)
|
||||||
|
_sendPrintStringToJava(env, info->contextObject, mid, "");
|
||||||
|
_sendPrintStringToJava(env, info->contextObject, mid, JS_GetStringBytes(str));
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
if (n)
|
||||||
|
_sendPrintStringToJava(env, info->contextObject, mid, "\n");
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSBool
|
||||||
|
Version(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
|
{
|
||||||
|
if (argc > 0 && JSVAL_IS_INT(argv[0]))
|
||||||
|
*rval = INT_TO_JSVAL(JS_SetVersion(cx, JSVAL_TO_INT(argv[0])));
|
||||||
|
else
|
||||||
|
*rval = INT_TO_JSVAL(JS_GetVersion(cx));
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSBool
|
||||||
|
Load(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
|
{
|
||||||
|
uintN i;
|
||||||
|
JSString *str;
|
||||||
|
const char *filename;
|
||||||
|
|
||||||
|
for (i = 0; i < argc; i++) {
|
||||||
|
str = JS_ValueToString(cx, argv[i]);
|
||||||
|
if (!str)
|
||||||
|
return JS_FALSE;
|
||||||
|
argv[i] = STRING_TO_JSVAL(str);
|
||||||
|
filename = JS_GetStringBytes(str);
|
||||||
|
|
||||||
|
if(! _loadSingleFile(cx, obj, filename))
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSFunctionSpec shell_functions[] = {
|
||||||
|
{"version", Version, 0},
|
||||||
|
{"load", Load, 1},
|
||||||
|
{"print", Print, 0},
|
||||||
|
{0}
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
my_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
|
||||||
|
{
|
||||||
|
ContextInfo* info;
|
||||||
|
jmethodID mid;
|
||||||
|
jclass clazz;
|
||||||
|
JNIEnv* env;
|
||||||
|
|
||||||
|
jobject msg = NULL;
|
||||||
|
jobject filename = NULL;
|
||||||
|
jobject lineBuf = NULL;
|
||||||
|
int lineno = 0;
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
info = (ContextInfo*) JS_GetContextPrivate(cx);
|
||||||
|
ASSERT_RETURN_VOID(info);
|
||||||
|
|
||||||
|
env = info->env;
|
||||||
|
ASSERT_RETURN_VOID(env);
|
||||||
|
|
||||||
|
clazz = (*env)->GetObjectClass(env, info->contextObject);
|
||||||
|
ASSERT_RETURN_VOID(clazz);
|
||||||
|
|
||||||
|
mid = (*env)->GetMethodID(env, clazz, "_reportError",
|
||||||
|
"(Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;I)V");
|
||||||
|
ASSERT_RETURN_VOID(mid);
|
||||||
|
|
||||||
|
|
||||||
|
if(message)
|
||||||
|
msg = (*env)->NewStringUTF(env, message);
|
||||||
|
|
||||||
|
if(report)
|
||||||
|
{
|
||||||
|
lineno = report->lineno;
|
||||||
|
if(report->filename)
|
||||||
|
filename = (*env)->NewStringUTF(env, report->filename);
|
||||||
|
|
||||||
|
if(report->linebuf)
|
||||||
|
{
|
||||||
|
lineBuf = (*env)->NewStringUTF(env, report->linebuf);
|
||||||
|
if(report->tokenptr)
|
||||||
|
offset = report->tokenptr - report->linebuf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(*env)->CallObjectMethod(env, info->contextObject, mid,
|
||||||
|
msg, filename, lineno, lineBuf, offset);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSClass global_class = {
|
||||||
|
"global", 0,
|
||||||
|
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||||
|
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: com_netscape_nativejsengine_JSRuntime
|
||||||
|
* Method: _init
|
||||||
|
* Signature: (Z)Z
|
||||||
|
*/
|
||||||
|
JNIEXPORT jboolean JNICALL Java_com_netscape_nativejsengine_JSRuntime__1init
|
||||||
|
(JNIEnv * env, jobject self, jboolean enableDebugging)
|
||||||
|
{
|
||||||
|
JSRuntime *rt;
|
||||||
|
jclass clazz;
|
||||||
|
jfieldID fid;
|
||||||
|
|
||||||
|
rt = JS_NewRuntime(8L * 1024L * 1024L);
|
||||||
|
ASSERT_RETURN_VALUE(rt, JNI_FALSE);
|
||||||
|
|
||||||
|
clazz = (*env)->GetObjectClass(env, self);
|
||||||
|
ASSERT_RETURN_VALUE(clazz, JNI_FALSE);
|
||||||
|
|
||||||
|
fid = (*env)->GetFieldID(env, clazz, "_nativeRuntime", "J");
|
||||||
|
ASSERT_RETURN_VALUE(fid, JNI_FALSE);
|
||||||
|
(*env)->SetLongField(env, self, fid, (long) rt);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef JSDEBUGGER
|
||||||
|
if(enableDebugging)
|
||||||
|
{
|
||||||
|
JSDJContext* jsdjc;
|
||||||
|
JSDContext* jsdc;
|
||||||
|
|
||||||
|
jsdc = JSD_DebuggerOnForUser(rt, NULL, NULL);
|
||||||
|
ASSERT_RETURN_VALUE(jsdc, JNI_FALSE);
|
||||||
|
|
||||||
|
jsdjc = JSDJ_CreateContext();
|
||||||
|
ASSERT_RETURN_VALUE(jsdjc, JNI_FALSE);
|
||||||
|
|
||||||
|
JSDJ_SetJSDContext(jsdjc, jsdc);
|
||||||
|
JSDJ_SetJNIEnvForCurrentThread(jsdjc, env);
|
||||||
|
|
||||||
|
fid = (*env)->GetFieldID(env, clazz, "_nativeDebugSupport", "J");
|
||||||
|
ASSERT_RETURN_VALUE(fid, JNI_FALSE);
|
||||||
|
(*env)->SetLongField(env, self, fid, (long) jsdjc);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if(enableDebugging)
|
||||||
|
printf("ERROR - Context created with enableDebugging flag, but no debugging support compiled in!");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return JNI_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: com_netscape_nativejsengine_JSRuntime
|
||||||
|
* Method: _exit
|
||||||
|
* Signature: ()V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL Java_com_netscape_nativejsengine_JSRuntime__1exit
|
||||||
|
(JNIEnv * env, jobject self)
|
||||||
|
{
|
||||||
|
jfieldID fid;
|
||||||
|
jclass clazz;
|
||||||
|
JSRuntime *rt;
|
||||||
|
JSContext *iterp = NULL;
|
||||||
|
|
||||||
|
clazz = (*env)->GetObjectClass(env, self);
|
||||||
|
ASSERT_RETURN_VOID(clazz);
|
||||||
|
|
||||||
|
fid = (*env)->GetFieldID(env, clazz, "_nativeRuntime", "J");
|
||||||
|
ASSERT_RETURN_VOID(fid);
|
||||||
|
rt = (JSRuntime *) (*env)->GetLongField(env, self, fid);
|
||||||
|
ASSERT_RETURN_VOID(rt);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Can't kill runtime if it holds any contexts
|
||||||
|
*
|
||||||
|
* However, JSD may make it's own context(s), so don't ASSERT
|
||||||
|
*/
|
||||||
|
CHECK_RETURN_VOID(!JS_ContextIterator(rt, &iterp));
|
||||||
|
|
||||||
|
printf("runtime = %d\n", (int)rt);
|
||||||
|
|
||||||
|
JS_DestroyRuntime(rt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: com_netscape_nativejsengine_JSContext
|
||||||
|
* Method: _init
|
||||||
|
* Signature: ()Z
|
||||||
|
*/
|
||||||
|
JNIEXPORT jboolean JNICALL Java_com_netscape_nativejsengine_JSContext__1init
|
||||||
|
(JNIEnv *env, jobject self)
|
||||||
|
{
|
||||||
|
JSContext *cx;
|
||||||
|
JSObject *glob;
|
||||||
|
jfieldID fid;
|
||||||
|
jmethodID mid;
|
||||||
|
JSRuntime *rt;
|
||||||
|
jobject rtObject;
|
||||||
|
jclass clazz;
|
||||||
|
jclass clazz_self;
|
||||||
|
JSBool ok;
|
||||||
|
ContextInfo* info;
|
||||||
|
|
||||||
|
#ifdef JSDEBUGGER
|
||||||
|
JSDJContext* jsdjc;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
clazz_self = (*env)->GetObjectClass(env, self);
|
||||||
|
ASSERT_RETURN_VALUE(clazz_self, JNI_FALSE);
|
||||||
|
|
||||||
|
fid = (*env)->GetFieldID(env, clazz_self, "_runtime",
|
||||||
|
"Lcom/netscape/nativejsengine/JSRuntime;");
|
||||||
|
ASSERT_RETURN_VALUE(fid, JNI_FALSE);
|
||||||
|
|
||||||
|
rtObject = (*env)->GetObjectField(env, self, fid);
|
||||||
|
ASSERT_RETURN_VALUE(rtObject, JNI_FALSE);
|
||||||
|
|
||||||
|
clazz = (*env)->GetObjectClass(env, rtObject);
|
||||||
|
ASSERT_RETURN_VALUE(clazz, JNI_FALSE);
|
||||||
|
|
||||||
|
mid = (*env)->GetMethodID(env, clazz, "getNativeRuntime", "()J");
|
||||||
|
ASSERT_RETURN_VALUE(mid, JNI_FALSE);
|
||||||
|
|
||||||
|
rt = (JSRuntime *) (*env)->CallObjectMethod(env, rtObject, mid);
|
||||||
|
ASSERT_RETURN_VALUE(rt, JNI_FALSE);
|
||||||
|
|
||||||
|
cx = JS_NewContext(rt, 8192);
|
||||||
|
ASSERT_RETURN_VALUE(cx, JNI_FALSE);
|
||||||
|
|
||||||
|
JS_SetErrorReporter(cx, my_ErrorReporter);
|
||||||
|
|
||||||
|
glob = JS_NewObject(cx, &global_class, NULL, NULL);
|
||||||
|
ASSERT_RETURN_VALUE(glob, JNI_FALSE);
|
||||||
|
|
||||||
|
ok = JS_InitStandardClasses(cx, glob);
|
||||||
|
ASSERT_RETURN_VALUE(ok, JNI_FALSE);
|
||||||
|
|
||||||
|
ok = JS_DefineFunctions(cx, glob, shell_functions);
|
||||||
|
ASSERT_RETURN_VALUE(ok, JNI_FALSE);
|
||||||
|
|
||||||
|
fid = (*env)->GetFieldID(env, clazz_self, "_nativeContext", "J");
|
||||||
|
ASSERT_RETURN_VALUE(fid, JNI_FALSE);
|
||||||
|
(*env)->SetLongField(env, self, fid, (long) cx);
|
||||||
|
|
||||||
|
|
||||||
|
info = (ContextInfo*) malloc(sizeof(ContextInfo));
|
||||||
|
ASSERT_RETURN_VALUE(info, JNI_FALSE);
|
||||||
|
|
||||||
|
info->env = env;
|
||||||
|
info->contextObject = self;
|
||||||
|
|
||||||
|
JS_SetContextPrivate(cx, info);
|
||||||
|
|
||||||
|
#ifdef JSDEBUGGER
|
||||||
|
mid = (*env)->GetMethodID(env, clazz, "getNativeDebugSupport", "()J");
|
||||||
|
ASSERT_RETURN_VALUE(mid, JNI_FALSE);
|
||||||
|
|
||||||
|
jsdjc = (JSDJContext*) (*env)->CallObjectMethod(env, rtObject, mid);
|
||||||
|
if(jsdjc)
|
||||||
|
{
|
||||||
|
JSDContext* jsdc = JSDJ_GetJSDContext(jsdjc);
|
||||||
|
ASSERT_RETURN_VALUE(jsdc, JNI_FALSE);
|
||||||
|
|
||||||
|
JSDJ_SetJNIEnvForCurrentThread(jsdjc, env);
|
||||||
|
JSD_JSContextInUse(jsdc, cx);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return JNI_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: com_netscape_nativejsengine_JSContext
|
||||||
|
* Method: _exit
|
||||||
|
* Signature: ()V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL Java_com_netscape_nativejsengine_JSContext__1exit
|
||||||
|
(JNIEnv *env, jobject self)
|
||||||
|
{
|
||||||
|
jfieldID fid;
|
||||||
|
jclass clazz;
|
||||||
|
JSContext *cx;
|
||||||
|
ContextInfo* info;
|
||||||
|
|
||||||
|
clazz = (*env)->GetObjectClass(env, self);
|
||||||
|
ASSERT_RETURN_VOID(clazz);
|
||||||
|
|
||||||
|
fid = (*env)->GetFieldID(env, clazz, "_nativeContext", "J");
|
||||||
|
ASSERT_RETURN_VOID(fid);
|
||||||
|
|
||||||
|
cx = (JSContext *) (*env)->GetLongField(env, self, fid);
|
||||||
|
ASSERT_RETURN_VOID(cx);
|
||||||
|
|
||||||
|
info = (ContextInfo*) JS_GetContextPrivate(cx);
|
||||||
|
ASSERT_RETURN_VOID(info);
|
||||||
|
free(info);
|
||||||
|
|
||||||
|
printf("context = %d\n", (int)cx);
|
||||||
|
|
||||||
|
JS_DestroyContext(cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: com_netscape_nativejsengine_JSContext
|
||||||
|
* Method: _eval
|
||||||
|
* Signature: (Ljava/lang/String;)V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL Java_com_netscape_nativejsengine_JSContext__1eval
|
||||||
|
(JNIEnv * env, jobject self, jstring str, jstring filename, jint lineno)
|
||||||
|
{
|
||||||
|
jfieldID fid;
|
||||||
|
jclass clazz_self;
|
||||||
|
JSContext *cx;
|
||||||
|
JSObject *glob;
|
||||||
|
jsval rval;
|
||||||
|
int len;
|
||||||
|
const char* Cstr;
|
||||||
|
const char* Cfilename;
|
||||||
|
jboolean isCopy;
|
||||||
|
|
||||||
|
clazz_self = (*env)->GetObjectClass(env, self);
|
||||||
|
ASSERT_RETURN_VOID(clazz_self);
|
||||||
|
|
||||||
|
fid = (*env)->GetFieldID(env, clazz_self, "_nativeContext", "J");
|
||||||
|
ASSERT_RETURN_VOID(fid);
|
||||||
|
|
||||||
|
cx = (JSContext *) (*env)->GetLongField(env, self, fid);
|
||||||
|
ASSERT_RETURN_VOID(cx);
|
||||||
|
|
||||||
|
glob = JS_GetGlobalObject(cx);
|
||||||
|
ASSERT_RETURN_VOID(glob);
|
||||||
|
|
||||||
|
len = (*env)->GetStringUTFLength(env, str);
|
||||||
|
Cstr = (*env)->GetStringUTFChars(env, str, &isCopy);
|
||||||
|
Cfilename = (*env)->GetStringUTFChars(env, filename, &isCopy);
|
||||||
|
|
||||||
|
#ifdef JSDEBUGGER
|
||||||
|
/*
|
||||||
|
* XXX this just overwrites any previous source for this url!
|
||||||
|
*/
|
||||||
|
_jamSourceIntoJSD(cx, Cstr, len, Cfilename);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
JS_EvaluateScript(cx, glob, Cstr, len, Cfilename, lineno, &rval);
|
||||||
|
|
||||||
|
(*env)->ReleaseStringUTFChars(env, str, Cstr);
|
||||||
|
(*env)->ReleaseStringUTFChars(env, filename, Cfilename);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: com_netscape_nativejsengine_JSContext
|
||||||
|
* Method: _load
|
||||||
|
* Signature: (Ljava/lang/String;)V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL Java_com_netscape_nativejsengine_JSContext__1load
|
||||||
|
(JNIEnv *env, jobject self, jstring filename)
|
||||||
|
{
|
||||||
|
jfieldID fid;
|
||||||
|
jclass clazz;
|
||||||
|
JSContext *cx;
|
||||||
|
const char* Cfilename;
|
||||||
|
jboolean isCopy;
|
||||||
|
JSObject *glob;
|
||||||
|
|
||||||
|
clazz = (*env)->GetObjectClass(env, self);
|
||||||
|
ASSERT_RETURN_VOID(clazz);
|
||||||
|
|
||||||
|
fid = (*env)->GetFieldID(env, clazz, "_nativeContext", "J");
|
||||||
|
ASSERT_RETURN_VOID(fid);
|
||||||
|
|
||||||
|
cx = (JSContext *) (*env)->GetLongField(env, self, fid);
|
||||||
|
ASSERT_RETURN_VOID(cx);
|
||||||
|
|
||||||
|
glob = JS_GetGlobalObject(cx);
|
||||||
|
ASSERT_RETURN_VOID(glob);
|
||||||
|
|
||||||
|
Cfilename = (*env)->GetStringUTFChars(env, filename, &isCopy);
|
||||||
|
|
||||||
|
_loadSingleFile(cx, glob, Cfilename);
|
||||||
|
|
||||||
|
(*env)->ReleaseStringUTFChars(env, filename, Cfilename);
|
||||||
|
}
|
827
js/jsd/jsd.h
827
js/jsd/jsd.h
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,70 @@
|
||||||
|
|
||||||
|
PROJ = jsd
|
||||||
|
JSD = .
|
||||||
|
JS = $(JSD)\..\src
|
||||||
|
JSPROJ = js32
|
||||||
|
|
||||||
|
!IF "$(BUILD_OPT)" != ""
|
||||||
|
OBJ = Release
|
||||||
|
CC_FLAGS = /DNDEBUG
|
||||||
|
!ELSE
|
||||||
|
OBJ = Debug
|
||||||
|
CC_FLAGS = /DDEBUG
|
||||||
|
LINK_FLAGS = /DEBUG
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
QUIET=@
|
||||||
|
|
||||||
|
CFLAGS = /nologo /MDd /W3 /Gm /GX /Zi /Od\
|
||||||
|
/I $(JS)\
|
||||||
|
/I $(JSD)\
|
||||||
|
/DDEBUG /DWIN32 /D_CONSOLE /DXP_PC /D_WINDOWS /D_WIN32\
|
||||||
|
/DJSDEBUGGER\
|
||||||
|
!IF "$(JSD_THREADSAFE)" != ""
|
||||||
|
/DJSD_THREADSAFE\
|
||||||
|
!ENDIF
|
||||||
|
/DEXPORT_JSD_API\
|
||||||
|
$(CC_FLAGS)\
|
||||||
|
/c /Fp$(OBJ)\$(PROJ).pch /Fd$(OBJ)\$(PROJ).pdb /YX -Fo$@ $<
|
||||||
|
|
||||||
|
LFLAGS = /nologo /subsystem:console /DLL /incremental:no /machine:I386 \
|
||||||
|
$(LINK_FLAGS) /pdb:$(OBJ)\$(PROJ).pdb -out:$(OBJ)\$(PROJ).dll
|
||||||
|
|
||||||
|
LLIBS = kernel32.lib advapi32.lib $(JS)\$(OBJ)\$(JSPROJ).lib
|
||||||
|
# unused... user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib
|
||||||
|
|
||||||
|
CPP=cl.exe
|
||||||
|
LINK32=link.exe
|
||||||
|
|
||||||
|
all: $(OBJ) $(OBJ)\$(PROJ).dll
|
||||||
|
|
||||||
|
|
||||||
|
$(OBJ)\$(PROJ).dll: \
|
||||||
|
$(OBJ)\jsdebug.obj \
|
||||||
|
$(OBJ)\jsd_atom.obj \
|
||||||
|
$(OBJ)\jsd_high.obj \
|
||||||
|
$(OBJ)\jsd_hook.obj \
|
||||||
|
$(OBJ)\jsd_obj.obj \
|
||||||
|
$(OBJ)\jsd_scpt.obj \
|
||||||
|
$(OBJ)\jsd_stak.obj \
|
||||||
|
$(OBJ)\jsd_step.obj \
|
||||||
|
$(OBJ)\jsd_text.obj \
|
||||||
|
$(OBJ)\jsd_lock.obj \
|
||||||
|
$(OBJ)\jsd_val.obj
|
||||||
|
$(QUIET)$(LINK32) $(LFLAGS) $** $(LLIBS)
|
||||||
|
|
||||||
|
{$(JSD)}.c{$(OBJ)}.obj :
|
||||||
|
$(QUIET)$(CPP) $(CFLAGS)
|
||||||
|
|
||||||
|
$(OBJ) :
|
||||||
|
$(QUIET)mkdir $(OBJ)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@echo deleting old output
|
||||||
|
$(QUIET)del $(OBJ)\*.pch >NUL
|
||||||
|
$(QUIET)del $(OBJ)\*.obj >NUL
|
||||||
|
$(QUIET)del $(OBJ)\*.exp >NUL
|
||||||
|
$(QUIET)del $(OBJ)\*.lib >NUL
|
||||||
|
$(QUIET)del $(OBJ)\*.idb >NUL
|
||||||
|
$(QUIET)del $(OBJ)\*.pdb >NUL
|
||||||
|
$(QUIET)del $(OBJ)\*.dll >NUL
|
|
@ -0,0 +1,159 @@
|
||||||
|
/* -*- 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* JavaScript Debugging support - Atom support
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "jsd.h"
|
||||||
|
|
||||||
|
/* #define TEST_ATOMS 1 */
|
||||||
|
|
||||||
|
#ifdef TEST_ATOMS
|
||||||
|
static void
|
||||||
|
_testAtoms(JSDContext*jsdc)
|
||||||
|
{
|
||||||
|
JSDAtom* atom0 = jsd_AddAtom(jsdc, "foo");
|
||||||
|
JSDAtom* atom1 = jsd_AddAtom(jsdc, "foo");
|
||||||
|
JSDAtom* atom2 = jsd_AddAtom(jsdc, "bar");
|
||||||
|
JSDAtom* atom3 = jsd_CloneAtom(jsdc, atom1);
|
||||||
|
JSDAtom* atom4 = jsd_CloneAtom(jsdc, atom2);
|
||||||
|
|
||||||
|
const char* c0 = JSD_ATOM_TO_STRING(atom0);
|
||||||
|
const char* c1 = JSD_ATOM_TO_STRING(atom1);
|
||||||
|
const char* c2 = JSD_ATOM_TO_STRING(atom2);
|
||||||
|
const char* c3 = JSD_ATOM_TO_STRING(atom3);
|
||||||
|
const char* c4 = JSD_ATOM_TO_STRING(atom4);
|
||||||
|
|
||||||
|
jsd_DropAtom(jsdc, atom0);
|
||||||
|
jsd_DropAtom(jsdc, atom1);
|
||||||
|
jsd_DropAtom(jsdc, atom2);
|
||||||
|
jsd_DropAtom(jsdc, atom3);
|
||||||
|
jsd_DropAtom(jsdc, atom4);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
JS_STATIC_DLL_CALLBACK(intN)
|
||||||
|
_atom_smasher(JSHashEntry *he, intN i, void *arg)
|
||||||
|
{
|
||||||
|
JS_ASSERT(he);
|
||||||
|
JS_ASSERT(he->value);
|
||||||
|
JS_ASSERT(((JSDAtom*)(he->value))->str);
|
||||||
|
|
||||||
|
free(((JSDAtom*)(he->value))->str);
|
||||||
|
free(he->value);
|
||||||
|
he->value = NULL;
|
||||||
|
he->key = NULL;
|
||||||
|
return HT_ENUMERATE_NEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_STATIC_DLL_CALLBACK(intN)
|
||||||
|
_compareAtomKeys(const void *v1, const void *v2)
|
||||||
|
{
|
||||||
|
return 0 == strcmp((const char*)v1, (const char*)v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_STATIC_DLL_CALLBACK(intN)
|
||||||
|
_compareAtoms(const void *v1, const void *v2)
|
||||||
|
{
|
||||||
|
return 0 == strcmp(((JSDAtom*)v1)->str, ((JSDAtom*)v2)->str);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
jsd_CreateAtomTable(JSDContext* jsdc)
|
||||||
|
{
|
||||||
|
jsdc->atoms = JS_NewHashTable(256, JS_HashString,
|
||||||
|
_compareAtomKeys, _compareAtoms,
|
||||||
|
NULL, NULL);
|
||||||
|
#ifdef TEST_ATOMS
|
||||||
|
_testAtoms(jsdc);
|
||||||
|
#endif
|
||||||
|
return (JSBool) jsdc->atoms;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
jsd_DestroyAtomTable(JSDContext* jsdc)
|
||||||
|
{
|
||||||
|
if( jsdc->atoms )
|
||||||
|
{
|
||||||
|
JS_HashTableEnumerateEntries(jsdc->atoms, _atom_smasher, NULL);
|
||||||
|
JS_HashTableDestroy(jsdc->atoms);
|
||||||
|
jsdc->atoms = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JSDAtom*
|
||||||
|
jsd_AddAtom(JSDContext* jsdc, const char* str)
|
||||||
|
{
|
||||||
|
JSDAtom* atom;
|
||||||
|
|
||||||
|
if(!str)
|
||||||
|
{
|
||||||
|
JS_ASSERT(0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSD_LOCK_ATOMS(jsdc);
|
||||||
|
|
||||||
|
atom = (JSDAtom*) JS_HashTableLookup(jsdc->atoms, str);
|
||||||
|
|
||||||
|
if( atom )
|
||||||
|
atom->refcount++;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
atom = (JSDAtom*) malloc(sizeof(JSDAtom));
|
||||||
|
if( atom )
|
||||||
|
{
|
||||||
|
atom->str = strdup(str);
|
||||||
|
atom->refcount = 1;
|
||||||
|
if(!JS_HashTableAdd(jsdc->atoms, atom->str, atom))
|
||||||
|
{
|
||||||
|
free(atom->str);
|
||||||
|
free(atom);
|
||||||
|
atom = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JSD_UNLOCK_ATOMS(jsdc);
|
||||||
|
return atom;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSDAtom*
|
||||||
|
jsd_CloneAtom(JSDContext* jsdc, JSDAtom* atom)
|
||||||
|
{
|
||||||
|
JSD_LOCK_ATOMS(jsdc);
|
||||||
|
atom->refcount++;
|
||||||
|
JSD_UNLOCK_ATOMS(jsdc);
|
||||||
|
return atom;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
jsd_DropAtom(JSDContext* jsdc, JSDAtom* atom)
|
||||||
|
{
|
||||||
|
JSD_LOCK_ATOMS(jsdc);
|
||||||
|
if(! --atom->refcount)
|
||||||
|
{
|
||||||
|
JS_HashTableRemove(jsdc->atoms, atom->str);
|
||||||
|
free(atom->str);
|
||||||
|
free(atom);
|
||||||
|
}
|
||||||
|
JSD_UNLOCK_ATOMS(jsdc);
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
/* -*- 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
|
* 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
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||||
|
@ -17,39 +17,38 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** JavaScript Debugger Navigator API - 'High Level' functions
|
* JavaScript Debugging support - 'High Level' functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "jsd.h"
|
#include "jsd.h"
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
/* use a global context for now (avoid direct references to it!) */
|
/* XXX not 'static' because of old Mac CodeWarrior bug */
|
||||||
static JSDContext _static_context;
|
JSCList _jsd_context_list = JS_INIT_STATIC_CLIST(&_jsd_context_list);
|
||||||
|
|
||||||
/* these are global now, they transcend our concept of JSDContext...*/
|
|
||||||
|
|
||||||
|
/* these are used to connect JSD_SetUserCallbacks() with JSD_DebuggerOn() */
|
||||||
static JSD_UserCallbacks _callbacks;
|
static JSD_UserCallbacks _callbacks;
|
||||||
static void* _user;
|
static void* _user = NULL;
|
||||||
static JSTaskState* _jstaskstate;
|
static JSRuntime* _jsrt = NULL;
|
||||||
static PRThread * _dangerousThread1;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef JSD_HAS_DANGEROUS_THREAD
|
||||||
void JSD_ASSERT_VALID_CONTEXT( JSDContext* jsdc )
|
static void* _dangerousThread = NULL;
|
||||||
{
|
|
||||||
PR_ASSERT( jsdc == &_static_context );
|
|
||||||
PR_ASSERT( jsdc->inited );
|
|
||||||
PR_ASSERT( jsdc->jstaskstate );
|
|
||||||
PR_ASSERT( jsdc->jscontexts );
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static PRHashNumber
|
#ifdef JSD_THREADSAFE
|
||||||
_hash_root(const void *key)
|
void* _jsd_global_lock = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
void JSD_ASSERT_VALID_CONTEXT(JSDContext* jsdc)
|
||||||
{
|
{
|
||||||
PRHashNumber num = (PRHashNumber) key;
|
JS_ASSERT(jsdc->inited);
|
||||||
return num >> 2;
|
JS_ASSERT(jsdc->jsrt);
|
||||||
|
JS_ASSERT(jsdc->dumbContext);
|
||||||
|
JS_ASSERT(jsdc->glob);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static JSClass global_class = {
|
static JSClass global_class = {
|
||||||
"JSDGlobal", 0,
|
"JSDGlobal", 0,
|
||||||
|
@ -57,242 +56,293 @@ static JSClass global_class = {
|
||||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
|
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
|
||||||
};
|
};
|
||||||
|
|
||||||
static JSDContext*
|
static JSBool
|
||||||
NewJSDContext(void)
|
_validateUserCallbacks(JSD_UserCallbacks* callbacks)
|
||||||
{
|
{
|
||||||
JSDContext* jsdc = &_static_context;
|
return !callbacks ||
|
||||||
|
(callbacks->size && callbacks->size <= sizeof(JSD_UserCallbacks));
|
||||||
|
}
|
||||||
|
|
||||||
if( jsdc->inited )
|
static JSDContext*
|
||||||
|
_newJSDContext(JSRuntime* jsrt,
|
||||||
|
JSD_UserCallbacks* callbacks,
|
||||||
|
void* user)
|
||||||
|
{
|
||||||
|
JSDContext* jsdc = NULL;
|
||||||
|
|
||||||
|
if( ! jsrt )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if( ! _jstaskstate )
|
if( ! _validateUserCallbacks(callbacks) )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
memset( jsdc, 0, sizeof(JSDContext) );
|
jsdc = (JSDContext*) calloc(1, sizeof(JSDContext));
|
||||||
jsdc->jstaskstate = _jstaskstate;
|
if( ! jsdc )
|
||||||
|
goto label_newJSDContext_failure;
|
||||||
|
|
||||||
PR_INIT_CLIST(&jsdc->threadsStates);
|
if( ! JSD_INIT_LOCKS(jsdc) )
|
||||||
|
goto label_newJSDContext_failure;
|
||||||
|
|
||||||
jsdc->dumbContext = JS_NewContext( _jstaskstate, 256 );
|
JS_INIT_CLIST(&jsdc->links);
|
||||||
|
|
||||||
|
jsdc->jsrt = jsrt;
|
||||||
|
|
||||||
|
if( callbacks )
|
||||||
|
memcpy(&jsdc->userCallbacks, callbacks, callbacks->size);
|
||||||
|
|
||||||
|
jsdc->user = user;
|
||||||
|
|
||||||
|
#ifdef JSD_HAS_DANGEROUS_THREAD
|
||||||
|
jsdc->dangerousThread = _dangerousThread;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
JS_INIT_CLIST(&jsdc->threadsStates);
|
||||||
|
JS_INIT_CLIST(&jsdc->scripts);
|
||||||
|
JS_INIT_CLIST(&jsdc->sources);
|
||||||
|
JS_INIT_CLIST(&jsdc->removedSources);
|
||||||
|
|
||||||
|
jsdc->sourceAlterCount = 1;
|
||||||
|
|
||||||
|
if( ! jsd_CreateAtomTable(jsdc) )
|
||||||
|
goto label_newJSDContext_failure;
|
||||||
|
|
||||||
|
if( ! jsd_InitObjectManager(jsdc) )
|
||||||
|
goto label_newJSDContext_failure;
|
||||||
|
|
||||||
|
jsdc->dumbContext = JS_NewContext(jsdc->jsrt, 256);
|
||||||
if( ! jsdc->dumbContext )
|
if( ! jsdc->dumbContext )
|
||||||
return NULL;
|
goto label_newJSDContext_failure;
|
||||||
|
|
||||||
jsdc->glob = JS_NewObject(jsdc->dumbContext, &global_class, NULL, NULL);
|
jsdc->glob = JS_NewObject(jsdc->dumbContext, &global_class, NULL, NULL);
|
||||||
if( ! jsdc->glob )
|
if( ! jsdc->glob )
|
||||||
return NULL;
|
goto label_newJSDContext_failure;
|
||||||
|
|
||||||
if( ! JS_InitStandardClasses(jsdc->dumbContext, jsdc->glob) )
|
if( ! JS_InitStandardClasses(jsdc->dumbContext, jsdc->glob) )
|
||||||
return NULL;
|
goto label_newJSDContext_failure;
|
||||||
|
|
||||||
jsdc->jscontexts = PR_NewHashTable(256, _hash_root,
|
|
||||||
PR_CompareValues, PR_CompareValues,
|
|
||||||
NULL, NULL);
|
|
||||||
if( ! jsdc->jscontexts )
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
jsdc->inited = JS_TRUE;
|
jsdc->inited = JS_TRUE;
|
||||||
return jsdc;
|
|
||||||
}
|
|
||||||
|
|
||||||
PR_STATIC_CALLBACK(PRIntn)
|
JSD_LOCK();
|
||||||
_hash_entry_zapper(PRHashEntry *he, PRIntn i, void *arg)
|
JS_INSERT_LINK(&jsdc->links, &_jsd_context_list);
|
||||||
{
|
JSD_UNLOCK();
|
||||||
PR_FREEIF(he->value);
|
|
||||||
he->value = NULL;
|
return jsdc;
|
||||||
he->key = NULL;
|
|
||||||
return HT_ENUMERATE_NEXT;
|
label_newJSDContext_failure:
|
||||||
|
jsd_DestroyObjectManager(jsdc);
|
||||||
|
jsd_DestroyAtomTable(jsdc);
|
||||||
|
if( jsdc )
|
||||||
|
free(jsdc);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
DestroyJSDContext( JSDContext* jsdc )
|
_destroyJSDContext(JSDContext* jsdc)
|
||||||
{
|
{
|
||||||
JSD_ASSERT_VALID_CONTEXT(jsdc);
|
JSD_ASSERT_VALID_CONTEXT(jsdc);
|
||||||
if( jsdc->jscontexts )
|
|
||||||
{
|
|
||||||
PR_HashTableEnumerateEntries(jsdc->jscontexts, _hash_entry_zapper, NULL);
|
|
||||||
PR_HashTableDestroy(jsdc->jscontexts);
|
|
||||||
}
|
|
||||||
jsdc->inited = JS_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSDContext*
|
JSD_LOCK();
|
||||||
jsd_GetDefaultJSDContext(void)
|
JS_REMOVE_LINK(&jsdc->links);
|
||||||
{
|
JSD_UNLOCK();
|
||||||
JSDContext* jsdc = &_static_context;
|
|
||||||
if( ! jsdc->inited )
|
jsd_DestroyObjectManager(jsdc);
|
||||||
return NULL;
|
jsd_DestroyAtomTable(jsdc);
|
||||||
return jsdc;
|
|
||||||
|
jsdc->inited = JS_FALSE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We should free jsdc here, but we let it leak in case there are any
|
||||||
|
* asynchronous hooks calling into the system using it as a handle
|
||||||
|
*
|
||||||
|
* XXX we also leak the locks
|
||||||
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
JSDContext*
|
JSDContext*
|
||||||
jsd_DebuggerOn(void)
|
jsd_DebuggerOnForUser(JSRuntime* jsrt,
|
||||||
|
JSD_UserCallbacks* callbacks,
|
||||||
|
void* user)
|
||||||
{
|
{
|
||||||
JSDContext* jsdc = NewJSDContext();
|
JSDContext* jsdc;
|
||||||
JSContext* iter = NULL;
|
JSContext* iter = NULL;
|
||||||
JSContext* cx;
|
|
||||||
|
|
||||||
|
jsdc = _newJSDContext(jsrt, callbacks, user);
|
||||||
if( ! jsdc )
|
if( ! jsdc )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* set hooks here */
|
/* set hooks here */
|
||||||
JS_SetNewScriptHookProc( jsdc->jstaskstate, jsd_NewScriptHookProc, jsdc );
|
JS_SetNewScriptHookProc(jsdc->jsrt, jsd_NewScriptHookProc, jsdc);
|
||||||
JS_SetDestroyScriptHookProc( jsdc->jstaskstate, jsd_DestroyScriptHookProc, jsdc );
|
JS_SetDestroyScriptHookProc(jsdc->jsrt, jsd_DestroyScriptHookProc, jsdc);
|
||||||
|
JS_SetDebuggerHandler(jsdc->jsrt, jsd_DebuggerHandler, jsdc);
|
||||||
/* enumerate contexts for JSTaskState and add them to our table */
|
JS_SetExecuteHook(jsdc->jsrt, jsd_InterpreterHook, jsdc);
|
||||||
while( NULL != (cx = JS_ContextIterator(jsdc->jstaskstate, &iter)) )
|
JS_SetCallHook(jsdc->jsrt, jsd_InterpreterHook, jsdc);
|
||||||
jsd_JSContextUsed( jsdc, cx );
|
JS_SetObjectHook(jsdc->jsrt, jsd_ObjectHook, jsdc);
|
||||||
|
JS_SetThrowHook(jsdc->jsrt, jsd_ThrowHandler, jsdc);
|
||||||
if( _callbacks.setContext )
|
JS_SetDebugErrorHook(jsdc->jsrt, jsd_DebugErrorHook, jsdc);
|
||||||
_callbacks.setContext( jsdc, _user );
|
#ifdef LIVEWIRE
|
||||||
|
LWDBG_SetNewScriptHookProc(jsd_NewScriptHookProc, jsdc);
|
||||||
|
#endif
|
||||||
|
if( jsdc->userCallbacks.setContext )
|
||||||
|
jsdc->userCallbacks.setContext(jsdc, jsdc->user);
|
||||||
return jsdc;
|
return jsdc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSDContext*
|
||||||
|
jsd_DebuggerOn(void)
|
||||||
|
{
|
||||||
|
JS_ASSERT(_jsrt);
|
||||||
|
JS_ASSERT(_validateUserCallbacks(&_callbacks));
|
||||||
|
return jsd_DebuggerOnForUser(_jsrt, &_callbacks, _user);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
jsd_DebuggerOff(JSDContext* jsdc)
|
jsd_DebuggerOff(JSDContext* jsdc)
|
||||||
{
|
{
|
||||||
/* clear hooks here */
|
/* clear hooks here */
|
||||||
JS_SetNewScriptHookProc( jsdc->jstaskstate, NULL, NULL );
|
JS_SetNewScriptHookProc(jsdc->jsrt, NULL, NULL);
|
||||||
JS_SetDestroyScriptHookProc( jsdc->jstaskstate, NULL, NULL );
|
JS_SetDestroyScriptHookProc(jsdc->jsrt, NULL, NULL);
|
||||||
|
JS_SetDebuggerHandler(jsdc->jsrt, NULL, NULL);
|
||||||
|
JS_SetExecuteHook(jsdc->jsrt, NULL, NULL);
|
||||||
|
JS_SetCallHook(jsdc->jsrt, NULL, NULL);
|
||||||
|
JS_SetObjectHook(jsdc->jsrt, NULL, NULL);
|
||||||
|
JS_SetThrowHook(jsdc->jsrt, NULL, NULL);
|
||||||
|
JS_SetDebugErrorHook(jsdc->jsrt, NULL, NULL);
|
||||||
|
#ifdef LIVEWIRE
|
||||||
|
LWDBG_SetNewScriptHookProc(NULL,NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* clean up */
|
/* clean up */
|
||||||
jsd_DestroyAllJSDScripts( jsdc );
|
jsd_DestroyAllJSDScripts(jsdc);
|
||||||
jsd_DestroyAllSources( jsdc );
|
jsd_DestroyAllSources(jsdc);
|
||||||
|
|
||||||
DestroyJSDContext( jsdc );
|
_destroyJSDContext(jsdc);
|
||||||
|
|
||||||
if( _callbacks.setContext )
|
if( jsdc->userCallbacks.setContext )
|
||||||
_callbacks.setContext( NULL, _user );
|
jsdc->userCallbacks.setContext(NULL, jsdc->user);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
jsd_SetUserCallbacks(JSTaskState* jstaskstate, JSD_UserCallbacks* callbacks, void* user)
|
jsd_SetUserCallbacks(JSRuntime* jsrt, JSD_UserCallbacks* callbacks, void* user)
|
||||||
{
|
{
|
||||||
_jstaskstate = jstaskstate;
|
_jsrt = jsrt;
|
||||||
_user = user;
|
_user = user;
|
||||||
_dangerousThread1 = PR_CurrentThread();
|
|
||||||
|
#ifdef JSD_HAS_DANGEROUS_THREAD
|
||||||
|
_dangerousThread = JSD_CURRENT_THREAD();
|
||||||
|
#endif
|
||||||
|
|
||||||
if( callbacks )
|
if( callbacks )
|
||||||
memcpy( &_callbacks, callbacks, sizeof(JSD_UserCallbacks) );
|
memcpy(&_callbacks, callbacks, sizeof(JSD_UserCallbacks));
|
||||||
else
|
else
|
||||||
memset( &_callbacks, 0 , sizeof(JSD_UserCallbacks) );
|
memset(&_callbacks, 0 , sizeof(JSD_UserCallbacks));
|
||||||
|
|
||||||
if( _callbacks.setContext && _static_context.inited )
|
|
||||||
_callbacks.setContext( &_static_context, _user );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JSDContextWrapper*
|
JSDContext*
|
||||||
jsd_JSDContextWrapperForJSContext( JSDContext* jsdc, JSContext* context )
|
jsd_JSDContextForJSContext(JSContext* context)
|
||||||
{
|
{
|
||||||
return (JSDContextWrapper*) PR_HashTableLookup(jsdc->jscontexts, context);
|
JSDContext* iter;
|
||||||
|
JSDContext* jsdc = NULL;
|
||||||
|
JSRuntime* runtime = JS_GetRuntime(context);
|
||||||
|
|
||||||
|
JSD_LOCK();
|
||||||
|
for( iter = (JSDContext*)_jsd_context_list.next;
|
||||||
|
iter != (JSDContext*)&_jsd_context_list;
|
||||||
|
iter = (JSDContext*)iter->links.next )
|
||||||
|
{
|
||||||
|
if( runtime == iter->jsrt )
|
||||||
|
{
|
||||||
|
jsdc = iter;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JSD_UNLOCK();
|
||||||
|
return jsdc;
|
||||||
}
|
}
|
||||||
|
|
||||||
PR_STATIC_CALLBACK(void)
|
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||||
jsd_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
|
jsd_DebugErrorHook(JSContext *cx, const char *message,
|
||||||
|
JSErrorReport *report, void *closure)
|
||||||
{
|
{
|
||||||
JSDContextWrapper* wrapper;
|
JSDContext* jsdc = (JSDContext*) closure;
|
||||||
JSDContext* jsdc;
|
JSD_ErrorReporter errorReporter;
|
||||||
PRUintn action = JSD_ERROR_REPORTER_PASS_ALONG;
|
void* errorReporterData;
|
||||||
|
|
||||||
jsdc = jsd_GetDefaultJSDContext();
|
|
||||||
if( ! jsdc )
|
if( ! jsdc )
|
||||||
{
|
{
|
||||||
PR_ASSERT(0);
|
JS_ASSERT(0);
|
||||||
return;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
if( JSD_IS_DANGEROUS_THREAD(jsdc) )
|
||||||
|
return JS_TRUE;
|
||||||
|
|
||||||
wrapper = jsd_JSDContextWrapperForJSContext( jsdc, cx );
|
/* local in case hook gets cleared on another thread */
|
||||||
if( ! wrapper )
|
JSD_LOCK();
|
||||||
{
|
errorReporter = jsdc->errorReporter;
|
||||||
PR_ASSERT(0);
|
errorReporterData = jsdc->errorReporterData;
|
||||||
return;
|
JSD_UNLOCK();
|
||||||
}
|
|
||||||
|
|
||||||
if( jsdc->errorReporter && ! jsd_IsCurrentThreadDangerous() )
|
if(!errorReporter)
|
||||||
action = jsdc->errorReporter(jsdc, cx, message, report,
|
return JS_TRUE;
|
||||||
jsdc->errorReporterData);
|
|
||||||
|
|
||||||
switch(action)
|
switch(errorReporter(jsdc, cx, message, report, errorReporterData))
|
||||||
{
|
{
|
||||||
case JSD_ERROR_REPORTER_PASS_ALONG:
|
case JSD_ERROR_REPORTER_PASS_ALONG:
|
||||||
if( wrapper->originalErrorReporter )
|
return JS_TRUE;
|
||||||
wrapper->originalErrorReporter(cx, message, report);
|
|
||||||
break;
|
|
||||||
case JSD_ERROR_REPORTER_RETURN:
|
case JSD_ERROR_REPORTER_RETURN:
|
||||||
break;
|
return JS_FALSE;
|
||||||
case JSD_ERROR_REPORTER_DEBUG:
|
case JSD_ERROR_REPORTER_DEBUG:
|
||||||
{
|
{
|
||||||
JSDThreadState* jsdthreadstate;
|
jsval rval;
|
||||||
|
JSD_ExecutionHookProc hook;
|
||||||
|
void* hookData;
|
||||||
|
|
||||||
if( ! jsdc->debugBreakHook )
|
/* local in case hook gets cleared on another thread */
|
||||||
return;
|
JSD_LOCK();
|
||||||
|
hook = jsdc->debugBreakHook;
|
||||||
|
hookData = jsdc->debugBreakHookData;
|
||||||
|
JSD_UNLOCK();
|
||||||
|
|
||||||
jsdthreadstate = jsd_NewThreadState(jsdc,cx);
|
jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_DEBUG_REQUESTED,
|
||||||
if( jsdthreadstate )
|
hook, hookData, &rval);
|
||||||
{
|
/* XXX Should make this dependent on ExecutionHook retval */
|
||||||
(*jsdc->debugBreakHook)(jsdc, jsdthreadstate,
|
return JS_TRUE;
|
||||||
JSD_HOOK_DEBUG_REQUESTED,
|
|
||||||
jsdc->debugBreakHookData );
|
|
||||||
|
|
||||||
jsd_DestroyThreadState(jsdc, jsdthreadstate);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
default:;
|
case JSD_ERROR_REPORTER_CLEAR_RETURN:
|
||||||
|
if(report && JSREPORT_IS_EXCEPTION(report->flags))
|
||||||
|
JS_ClearPendingException(cx);
|
||||||
|
return JS_FALSE;
|
||||||
|
default:
|
||||||
|
JS_ASSERT(0);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
return JS_TRUE;
|
||||||
|
|
||||||
void
|
|
||||||
jsd_JSContextUsed( JSDContext* jsdc, JSContext* context )
|
|
||||||
{
|
|
||||||
JSDContextWrapper* wrapper;
|
|
||||||
|
|
||||||
wrapper = jsd_JSDContextWrapperForJSContext(jsdc, context);
|
|
||||||
if( wrapper )
|
|
||||||
{
|
|
||||||
/* error reporters are sometimes overwritten by other code... */
|
|
||||||
JSErrorReporter oldrep = JS_SetErrorReporter(context, jsd_ErrorReporter);
|
|
||||||
if( jsd_ErrorReporter != oldrep )
|
|
||||||
wrapper->originalErrorReporter = oldrep;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* else... */
|
|
||||||
wrapper = PR_NEWZAP(JSDContextWrapper);
|
|
||||||
if( ! wrapper )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if( ! PR_HashTableAdd(jsdc->jscontexts, context, wrapper ) )
|
|
||||||
{
|
|
||||||
PR_FREEIF(wrapper);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
wrapper->context = context;
|
|
||||||
wrapper->jsdc = jsdc;
|
|
||||||
|
|
||||||
/* add our error reporter */
|
|
||||||
wrapper->originalErrorReporter = JS_SetErrorReporter(context, jsd_ErrorReporter);
|
|
||||||
|
|
||||||
/* add our printer */
|
|
||||||
/* add our loader */
|
|
||||||
}
|
|
||||||
|
|
||||||
JSD_ErrorReporter
|
|
||||||
jsd_SetErrorReporter( JSDContext* jsdc, JSD_ErrorReporter reporter, void* callerdata)
|
|
||||||
{
|
|
||||||
JSD_ErrorReporter old = jsdc->errorReporter;
|
|
||||||
|
|
||||||
jsdc->errorReporter = reporter;
|
|
||||||
jsdc->errorReporterData = callerdata;
|
|
||||||
return old;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JSBool
|
JSBool
|
||||||
jsd_IsCurrentThreadDangerous()
|
jsd_SetErrorReporter(JSDContext* jsdc,
|
||||||
|
JSD_ErrorReporter reporter,
|
||||||
|
void* callerdata)
|
||||||
{
|
{
|
||||||
return PR_CurrentThread() == _dangerousThread1;
|
JSD_LOCK();
|
||||||
|
jsdc->errorReporter = reporter;
|
||||||
|
jsdc->errorReporterData = callerdata;
|
||||||
|
JSD_UNLOCK();
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
jsd_GetErrorReporter(JSDContext* jsdc,
|
||||||
|
JSD_ErrorReporter* reporter,
|
||||||
|
void** callerdata)
|
||||||
|
{
|
||||||
|
JSD_LOCK();
|
||||||
|
if( reporter )
|
||||||
|
*reporter = jsdc->errorReporter;
|
||||||
|
if( callerdata )
|
||||||
|
*callerdata = jsdc->errorReporterData;
|
||||||
|
JSD_UNLOCK();
|
||||||
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
/* -*- 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
|
* 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
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||||
|
@ -17,52 +17,151 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** JavaScript Debugger Navigator API - Hook support
|
* JavaScript Debugging support - Hook support
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "jsd.h"
|
#include "jsd.h"
|
||||||
|
|
||||||
JSTrapStatus PR_CALLBACK
|
JSTrapStatus JS_DLL_CALLBACK
|
||||||
jsd_InterruptHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
|
jsd_InterruptHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
|
||||||
void *closure)
|
void *closure)
|
||||||
{
|
{
|
||||||
PRUintn hookanswer = JSD_HOOK_RETURN_CONTINUE;
|
|
||||||
JSDThreadState* jsdthreadstate;
|
|
||||||
JSDScript* jsdscript;
|
JSDScript* jsdscript;
|
||||||
JSDContext* jsdc = (JSDContext*) closure;
|
JSDContext* jsdc = (JSDContext*) closure;
|
||||||
|
JSD_ExecutionHookProc hook;
|
||||||
if( jsd_IsCurrentThreadDangerous() )
|
void* hookData;
|
||||||
return JSTRAP_CONTINUE;
|
|
||||||
|
|
||||||
if( ! jsdc || ! jsdc->inited )
|
if( ! jsdc || ! jsdc->inited )
|
||||||
return JSTRAP_CONTINUE;
|
return JSTRAP_CONTINUE;
|
||||||
|
|
||||||
jsd_JSContextUsed(jsdc, cx);
|
if( JSD_IS_DANGEROUS_THREAD(jsdc) )
|
||||||
|
|
||||||
if( ! jsdc->interruptHook )
|
|
||||||
return JSTRAP_CONTINUE;
|
return JSTRAP_CONTINUE;
|
||||||
|
|
||||||
|
JSD_LOCK_SCRIPTS(jsdc);
|
||||||
jsdscript = jsd_FindJSDScript(jsdc, script);
|
jsdscript = jsd_FindJSDScript(jsdc, script);
|
||||||
|
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||||
if( ! jsdscript )
|
if( ! jsdscript )
|
||||||
return JSTRAP_CONTINUE;
|
return JSTRAP_CONTINUE;
|
||||||
|
|
||||||
jsdthreadstate = jsd_NewThreadState(jsdc,cx);
|
#ifdef LIVEWIRE
|
||||||
if( jsdthreadstate )
|
if( ! jsdlw_UserCodeAtPC(jsdc, jsdscript, (jsuword)pc) )
|
||||||
{
|
return JSTRAP_CONTINUE;
|
||||||
hookanswer =
|
#endif
|
||||||
(*jsdc->interruptHook)(jsdc, jsdthreadstate,
|
|
||||||
JSD_HOOK_INTERRUPTED,
|
|
||||||
jsdc->interruptHookData );
|
|
||||||
|
|
||||||
|
/* local in case jsdc->interruptHook gets cleared on another thread */
|
||||||
|
JSD_LOCK();
|
||||||
|
hook = jsdc->interruptHook;
|
||||||
|
hookData = jsdc->interruptHookData;
|
||||||
|
JSD_UNLOCK();
|
||||||
|
|
||||||
|
return jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_INTERRUPTED,
|
||||||
|
hook, hookData, rval);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSTrapStatus JS_DLL_CALLBACK
|
||||||
|
jsd_DebuggerHandler(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||||
|
jsval *rval, void *closure)
|
||||||
|
{
|
||||||
|
JSDScript* jsdscript;
|
||||||
|
JSDContext* jsdc = (JSDContext*) closure;
|
||||||
|
JSD_ExecutionHookProc hook;
|
||||||
|
void* hookData;
|
||||||
|
|
||||||
|
if( ! jsdc || ! jsdc->inited )
|
||||||
|
return JSTRAP_CONTINUE;
|
||||||
|
|
||||||
|
if( JSD_IS_DANGEROUS_THREAD(jsdc) )
|
||||||
|
return JSTRAP_CONTINUE;
|
||||||
|
|
||||||
|
JSD_LOCK_SCRIPTS(jsdc);
|
||||||
|
jsdscript = jsd_FindJSDScript(jsdc, script);
|
||||||
|
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||||
|
if( ! jsdscript )
|
||||||
|
return JSTRAP_CONTINUE;
|
||||||
|
|
||||||
|
/* local in case jsdc->debuggerHook gets cleared on another thread */
|
||||||
|
JSD_LOCK();
|
||||||
|
hook = jsdc->debuggerHook;
|
||||||
|
hookData = jsdc->debuggerHookData;
|
||||||
|
JSD_UNLOCK();
|
||||||
|
|
||||||
|
return jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_DEBUGGER_KEYWORD,
|
||||||
|
hook, hookData, rval);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
JSTrapStatus JS_DLL_CALLBACK
|
||||||
|
jsd_ThrowHandler(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||||
|
jsval *rval, void *closure)
|
||||||
|
{
|
||||||
|
JSDScript* jsdscript;
|
||||||
|
JSDContext* jsdc = (JSDContext*) closure;
|
||||||
|
JSD_ExecutionHookProc hook;
|
||||||
|
void* hookData;
|
||||||
|
|
||||||
|
JS_GetPendingException(cx, rval);
|
||||||
|
|
||||||
|
if( ! jsdc || ! jsdc->inited )
|
||||||
|
return JSD_HOOK_RETURN_CONTINUE_THROW;
|
||||||
|
|
||||||
|
if( JSD_IS_DANGEROUS_THREAD(jsdc) )
|
||||||
|
return JSD_HOOK_RETURN_CONTINUE_THROW;
|
||||||
|
|
||||||
|
JSD_LOCK_SCRIPTS(jsdc);
|
||||||
|
jsdscript = jsd_FindJSDScript(jsdc, script);
|
||||||
|
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||||
|
if( ! jsdscript )
|
||||||
|
return JSD_HOOK_RETURN_CONTINUE_THROW;
|
||||||
|
|
||||||
|
/* local in case jsdc->throwHook gets cleared on another thread */
|
||||||
|
JSD_LOCK();
|
||||||
|
hook = jsdc->throwHook;
|
||||||
|
hookData = jsdc->throwHookData;
|
||||||
|
JSD_UNLOCK();
|
||||||
|
|
||||||
|
return jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_THROW,
|
||||||
|
hook, hookData, rval);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSTrapStatus
|
||||||
|
jsd_CallExecutionHook(JSDContext* jsdc,
|
||||||
|
JSContext *cx,
|
||||||
|
uintN type,
|
||||||
|
JSD_ExecutionHookProc hook,
|
||||||
|
void* hookData,
|
||||||
|
jsval* rval)
|
||||||
|
{
|
||||||
|
uintN hookanswer = JSD_HOOK_THROW == type ?
|
||||||
|
JSD_HOOK_RETURN_CONTINUE_THROW :
|
||||||
|
JSD_HOOK_RETURN_CONTINUE;
|
||||||
|
JSDThreadState* jsdthreadstate;
|
||||||
|
|
||||||
|
if(hook && NULL != (jsdthreadstate = jsd_NewThreadState(jsdc,cx)))
|
||||||
|
{
|
||||||
|
hookanswer = hook(jsdc, jsdthreadstate, type, hookData, rval);
|
||||||
jsd_DestroyThreadState(jsdc, jsdthreadstate);
|
jsd_DestroyThreadState(jsdc, jsdthreadstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
*rval = NULL; /* XXX fix this!!! */
|
switch(hookanswer)
|
||||||
|
{
|
||||||
if( JSD_HOOK_RETURN_ABORT == hookanswer )
|
case JSD_HOOK_RETURN_ABORT:
|
||||||
return JSTRAP_ERROR;
|
case JSD_HOOK_RETURN_HOOK_ERROR:
|
||||||
|
return JSTRAP_ERROR;
|
||||||
return JSTRAP_CONTINUE; /* XXX fix this!!! */
|
case JSD_HOOK_RETURN_RET_WITH_VAL:
|
||||||
|
return JSTRAP_RETURN;
|
||||||
|
case JSD_HOOK_RETURN_THROW_WITH_VAL:
|
||||||
|
return JSTRAP_THROW;
|
||||||
|
case JSD_HOOK_RETURN_CONTINUE:
|
||||||
|
break;
|
||||||
|
case JSD_HOOK_RETURN_CONTINUE_THROW:
|
||||||
|
/* only makes sense for jsd_ThrowHandler (which init'd rval) */
|
||||||
|
JS_ASSERT(JSD_HOOK_THROW == type);
|
||||||
|
return JSTRAP_THROW;
|
||||||
|
default:
|
||||||
|
JS_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return JSTRAP_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSBool
|
JSBool
|
||||||
|
@ -70,17 +169,24 @@ jsd_SetInterruptHook(JSDContext* jsdc,
|
||||||
JSD_ExecutionHookProc hook,
|
JSD_ExecutionHookProc hook,
|
||||||
void* callerdata)
|
void* callerdata)
|
||||||
{
|
{
|
||||||
jsdc->interruptHook = hook;
|
JSD_LOCK();
|
||||||
jsdc->interruptHookData = callerdata;
|
jsdc->interruptHookData = callerdata;
|
||||||
|
jsdc->interruptHook = hook;
|
||||||
|
JS_SetInterrupt(jsdc->jsrt, jsd_InterruptHandler, (void*) jsdc);
|
||||||
|
JSD_UNLOCK();
|
||||||
|
|
||||||
return JS_SetInterrupt(jsdc->jstaskstate, jsd_InterruptHandler, (void*) jsdc);
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSBool
|
JSBool
|
||||||
jsd_ClearInterruptHook(JSDContext* jsdc)
|
jsd_ClearInterruptHook(JSDContext* jsdc)
|
||||||
{
|
{
|
||||||
|
JSD_LOCK();
|
||||||
|
JS_ClearInterrupt(jsdc->jsrt, NULL, NULL );
|
||||||
jsdc->interruptHook = NULL;
|
jsdc->interruptHook = NULL;
|
||||||
return JS_ClearInterrupt(jsdc->jstaskstate, NULL, NULL );
|
JSD_UNLOCK();
|
||||||
|
|
||||||
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSBool
|
JSBool
|
||||||
|
@ -88,14 +194,67 @@ jsd_SetDebugBreakHook(JSDContext* jsdc,
|
||||||
JSD_ExecutionHookProc hook,
|
JSD_ExecutionHookProc hook,
|
||||||
void* callerdata)
|
void* callerdata)
|
||||||
{
|
{
|
||||||
jsdc->debugBreakHook = hook;
|
JSD_LOCK();
|
||||||
jsdc->debugBreakHookData = callerdata;
|
jsdc->debugBreakHookData = callerdata;
|
||||||
|
jsdc->debugBreakHook = hook;
|
||||||
|
JSD_UNLOCK();
|
||||||
|
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSBool
|
JSBool
|
||||||
jsd_ClearDebugBreakHook(JSDContext* jsdc)
|
jsd_ClearDebugBreakHook(JSDContext* jsdc)
|
||||||
{
|
{
|
||||||
|
JSD_LOCK();
|
||||||
jsdc->debugBreakHook = NULL;
|
jsdc->debugBreakHook = NULL;
|
||||||
|
JSD_UNLOCK();
|
||||||
|
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
jsd_SetDebuggerHook(JSDContext* jsdc,
|
||||||
|
JSD_ExecutionHookProc hook,
|
||||||
|
void* callerdata)
|
||||||
|
{
|
||||||
|
JSD_LOCK();
|
||||||
|
jsdc->debuggerHookData = callerdata;
|
||||||
|
jsdc->debuggerHook = hook;
|
||||||
|
JSD_UNLOCK();
|
||||||
|
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
jsd_ClearDebuggerHook(JSDContext* jsdc)
|
||||||
|
{
|
||||||
|
JSD_LOCK();
|
||||||
|
jsdc->debuggerHook = NULL;
|
||||||
|
JSD_UNLOCK();
|
||||||
|
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
jsd_SetThrowHook(JSDContext* jsdc,
|
||||||
|
JSD_ExecutionHookProc hook,
|
||||||
|
void* callerdata)
|
||||||
|
{
|
||||||
|
JSD_LOCK();
|
||||||
|
jsdc->throwHookData = callerdata;
|
||||||
|
jsdc->throwHook = hook;
|
||||||
|
JSD_UNLOCK();
|
||||||
|
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
jsd_ClearThrowHook(JSDContext* jsdc)
|
||||||
|
{
|
||||||
|
JSD_LOCK();
|
||||||
|
jsdc->throwHook = NULL;
|
||||||
|
JSD_UNLOCK();
|
||||||
|
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,10 @@
|
||||||
* Reserved.
|
* Reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* this is all going away... replaced by code in js/jsd/java */
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
#include "native.h"
|
#include "native.h"
|
||||||
#include "jsdebug.h"
|
#include "jsdebug.h"
|
||||||
|
|
||||||
|
@ -794,4 +798,4 @@ void netscape_jsdebug_JSSourceTextProvider_refreshSourceTextVector(struct Hnetsc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
/* -*- 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
|
* 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
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||||
|
@ -17,8 +17,220 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 2/17/98 jband
|
* JavaScript Debugging support - Locking and threading support
|
||||||
* This is a temporary placeholder for this file
|
*/
|
||||||
* to supporet adding this file to existing makefiles before
|
|
||||||
* the real file is pulled in off of a branch
|
/*
|
||||||
|
* ifdef JSD_USE_NSPR_LOCKS then you musat build and run against NSPR2.
|
||||||
|
* Otherwise, there are stubs that can be filled in with your own locking
|
||||||
|
* code. Also, note that these stubs include a jsd_CurrentThread()
|
||||||
|
* implementation that only works on Win32 - this is needed for the inprocess
|
||||||
|
* Java-based debugger.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "jsd.h"
|
||||||
|
|
||||||
|
#ifdef JSD_THREADSAFE
|
||||||
|
|
||||||
|
#ifdef JSD_USE_NSPR_LOCKS
|
||||||
|
|
||||||
|
#include "prlock.h"
|
||||||
|
#include "prthread.h"
|
||||||
|
|
||||||
|
#ifdef JSD_ATTACH_THREAD_HACK
|
||||||
|
#include "pprthred.h" /* need this as long as JS_AttachThread is needed */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct JSDStaticLock
|
||||||
|
{
|
||||||
|
void* owner;
|
||||||
|
PRLock* lock;
|
||||||
|
int count;
|
||||||
|
#ifdef DEBUG
|
||||||
|
uint16 sig;
|
||||||
|
#endif
|
||||||
|
} JSDStaticLock;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This exists to wrap non-NSPR theads (e.g. Java threads) in NSPR wrappers.
|
||||||
|
* XXX We ignore the memory leak issue.
|
||||||
|
* It is claimed that future versions of NSPR will automatically wrap on
|
||||||
|
* the call to PR_GetCurrentThread.
|
||||||
|
*
|
||||||
|
* XXX We ignore the memory leak issue - i.e. we never call PR_DetachThread.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#undef _CURRENT_THREAD
|
||||||
|
#ifdef JSD_ATTACH_THREAD_HACK
|
||||||
|
#define _CURRENT_THREAD(out) \
|
||||||
|
JS_BEGIN_MACRO \
|
||||||
|
out = (void*) PR_GetCurrentThread(); \
|
||||||
|
if(!out) \
|
||||||
|
out = (void*) JS_AttachThread(PR_USER_THREAD,PR_PRIORITY_NORMAL,NULL);\
|
||||||
|
JS_ASSERT(out); \
|
||||||
|
JS_END_MACRO
|
||||||
|
#else
|
||||||
|
#define _CURRENT_THREAD(out) \
|
||||||
|
JS_BEGIN_MACRO \
|
||||||
|
out = (void*) PR_GetCurrentThread(); \
|
||||||
|
JS_ASSERT(out); \
|
||||||
|
JS_END_MACRO
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define JSD_LOCK_SIG 0x10CC10CC
|
||||||
|
void ASSERT_VALID_LOCK(JSDStaticLock* lock)
|
||||||
|
{
|
||||||
|
JS_ASSERT(lock);
|
||||||
|
JS_ASSERT(lock->lock);
|
||||||
|
JS_ASSERT(lock->count >= 0);
|
||||||
|
JS_ASSERT((! lock->count && ! lock->owner) || (lock->count && lock->owner));
|
||||||
|
JS_ASSERT(lock->sig == (uint16) JSD_LOCK_SIG);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define ASSERT_VALID_LOCK(x) ((void)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void*
|
||||||
|
jsd_CreateLock()
|
||||||
|
{
|
||||||
|
JSDStaticLock* lock;
|
||||||
|
|
||||||
|
if( ! (lock = calloc(1, sizeof(JSDStaticLock))) ||
|
||||||
|
! (lock->lock = PR_NewLock()) )
|
||||||
|
{
|
||||||
|
if(lock)
|
||||||
|
{
|
||||||
|
free(lock);
|
||||||
|
lock = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
if(lock) lock->sig = (uint16) JSD_LOCK_SIG;
|
||||||
|
#endif
|
||||||
|
return lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
jsd_Lock(JSDStaticLock* lock)
|
||||||
|
{
|
||||||
|
void* me;
|
||||||
|
|
||||||
|
_CURRENT_THREAD(me);
|
||||||
|
|
||||||
|
ASSERT_VALID_LOCK(lock);
|
||||||
|
|
||||||
|
if(lock->owner == me)
|
||||||
|
lock->count++;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PR_Lock(lock->lock); /* this can block... */
|
||||||
|
JS_ASSERT(lock->owner == 0);
|
||||||
|
lock->count = 1;
|
||||||
|
lock->owner = me;
|
||||||
|
}
|
||||||
|
ASSERT_VALID_LOCK(lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
jsd_Unlock(JSDStaticLock* lock)
|
||||||
|
{
|
||||||
|
void* me;
|
||||||
|
|
||||||
|
ASSERT_VALID_LOCK(lock);
|
||||||
|
_CURRENT_THREAD(me);
|
||||||
|
|
||||||
|
if(lock->owner != me)
|
||||||
|
{
|
||||||
|
JS_ASSERT(0); /* it's an error to unlock a lock you don't own */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(--lock->count == 0)
|
||||||
|
{
|
||||||
|
lock->owner = NULL;
|
||||||
|
PR_Unlock(lock->lock);
|
||||||
|
}
|
||||||
|
ASSERT_VALID_LOCK(lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
JSBool
|
||||||
|
jsd_IsLocked(JSDStaticLock* lock)
|
||||||
|
{
|
||||||
|
void* me;
|
||||||
|
ASSERT_VALID_LOCK(lock);
|
||||||
|
_CURRENT_THREAD(me);
|
||||||
|
return lock->owner == me ? JS_TRUE : JS_FALSE;
|
||||||
|
}
|
||||||
|
#endif /* DEBUG */
|
||||||
|
|
||||||
|
void*
|
||||||
|
jsd_CurrentThread()
|
||||||
|
{
|
||||||
|
void* me;
|
||||||
|
_CURRENT_THREAD(me);
|
||||||
|
return me;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#else /* ! JSD_USE_NSPR_LOCKS */
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#pragma message("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
|
||||||
|
#pragma message("!! you are compiling the stubbed version of jsd_lock.c !!")
|
||||||
|
#pragma message("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: 'Real' versions of these locks must be reentrant in the sense that
|
||||||
|
* they support nested calls to lock and unlock.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void*
|
||||||
|
jsd_CreateLock()
|
||||||
|
{
|
||||||
|
return (void*)1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
jsd_Lock(void* lock)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
jsd_Unlock(void* lock)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
JSBool
|
||||||
|
jsd_IsLocked(void* lock)
|
||||||
|
{
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
#endif /* DEBUG */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This Windows only thread id code is here to allow the Java-based
|
||||||
|
* JSDebugger to work with the single threaded js.c shell (even without
|
||||||
|
* real locking and threading support).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
/* bogus (but good enough) declaration*/
|
||||||
|
extern void* __stdcall GetCurrentThreadId(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void*
|
||||||
|
jsd_CurrentThread()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
return GetCurrentThreadId();
|
||||||
|
#else
|
||||||
|
return (void*)1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* JSD_USE_NSPR_LOCKS */
|
||||||
|
|
||||||
|
#endif /* JSD_THREADSAFE */
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
/* -*- 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Header for JavaScript Debugging support - Locking and threading functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef jsd_lock_h___
|
||||||
|
#define jsd_lock_h___
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If you want to support threading and locking, define JSD_THREADSAFE and
|
||||||
|
* implement the functions below.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: These locks must be reentrant in the sense that they support
|
||||||
|
* nested calls to lock and unlock.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern void*
|
||||||
|
jsd_CreateLock();
|
||||||
|
|
||||||
|
extern void
|
||||||
|
jsd_Lock(void* lock);
|
||||||
|
|
||||||
|
extern void
|
||||||
|
jsd_Unlock(void* lock);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
extern JSBool
|
||||||
|
jsd_IsLocked(void* lock);
|
||||||
|
#endif /* DEBUG */
|
||||||
|
|
||||||
|
extern void*
|
||||||
|
jsd_CurrentThread();
|
||||||
|
|
||||||
|
#endif /* jsd_lock_h___ */
|
|
@ -0,0 +1,307 @@
|
||||||
|
/* -*- 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* JavaScript Debugging support - Object support
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "jsd.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #define JSD_TRACE 1
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef JSD_TRACE
|
||||||
|
#define TRACEOBJ(jsdc, jsdobj, which) _traceObj(jsdc, jsdobj, which)
|
||||||
|
|
||||||
|
static char *
|
||||||
|
_describeObj(JSDContext* jsdc, JSDObject *jsdobj)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
JS_smprintf("%0x new'd in %s at line %d using ctor %s in %s at line %d",
|
||||||
|
(int)jsdobj,
|
||||||
|
JSD_GetObjectNewURL(jsdc, jsdobj),
|
||||||
|
JSD_GetObjectNewLineNumber(jsdc, jsdobj),
|
||||||
|
JSD_GetObjectConstructorName(jsdc, jsdobj),
|
||||||
|
JSD_GetObjectConstructorURL(jsdc, jsdobj),
|
||||||
|
JSD_GetObjectConstructorLineNumber(jsdc, jsdobj));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_traceObj(JSDContext* jsdc, JSDObject* jsdobj, int which)
|
||||||
|
{
|
||||||
|
char* description;
|
||||||
|
|
||||||
|
if( !jsdobj )
|
||||||
|
return;
|
||||||
|
|
||||||
|
description = _describeObj(jsdc, jsdobj);
|
||||||
|
|
||||||
|
printf("%s : %s\n",
|
||||||
|
which == 0 ? "new " :
|
||||||
|
which == 1 ? "final" :
|
||||||
|
"ctor ",
|
||||||
|
description);
|
||||||
|
if(description)
|
||||||
|
free(description);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define TRACEOBJ(jsdc, jsdobj, which) ((void)0)
|
||||||
|
#endif /* JSD_TRACE */
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
void JSD_ASSERT_VALID_OBJECT(JSDObject* jsdobj)
|
||||||
|
{
|
||||||
|
JS_ASSERT(jsdobj);
|
||||||
|
JS_ASSERT(!JS_CLIST_IS_EMPTY(&jsdobj->links));
|
||||||
|
JS_ASSERT(jsdobj->obj);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
_destroyJSDObject(JSDContext* jsdc, JSDObject* jsdobj)
|
||||||
|
{
|
||||||
|
JS_ASSERT(JSD_OBJECTS_LOCKED(jsdc));
|
||||||
|
|
||||||
|
JS_REMOVE_LINK(&jsdobj->links);
|
||||||
|
JS_HashTableRemove(jsdc->objectsTable, jsdobj->obj);
|
||||||
|
|
||||||
|
if(jsdobj->newURL)
|
||||||
|
jsd_DropAtom(jsdc, jsdobj->newURL);
|
||||||
|
if(jsdobj->ctorURL)
|
||||||
|
jsd_DropAtom(jsdc, jsdobj->ctorURL);
|
||||||
|
if(jsdobj->ctorName)
|
||||||
|
jsd_DropAtom(jsdc, jsdobj->ctorName);
|
||||||
|
free(jsdobj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSDObject*
|
||||||
|
_createJSDObject(JSDContext* jsdc, JSContext *cx, JSObject *obj)
|
||||||
|
{
|
||||||
|
JSDObject* jsdobj;
|
||||||
|
JSStackFrame* fp;
|
||||||
|
JSStackFrame* iter = NULL;
|
||||||
|
const char* newURL;
|
||||||
|
jsbytecode* pc;
|
||||||
|
|
||||||
|
JS_ASSERT(JSD_OBJECTS_LOCKED(jsdc));
|
||||||
|
|
||||||
|
jsdobj = (JSDObject*) calloc(1, sizeof(JSDObject));
|
||||||
|
if( jsdobj )
|
||||||
|
{
|
||||||
|
JS_INIT_CLIST(&jsdobj->links);
|
||||||
|
JS_APPEND_LINK(&jsdobj->links, &jsdc->objectsList);
|
||||||
|
jsdobj->obj = obj;
|
||||||
|
JS_HashTableAdd(jsdc->objectsTable, obj, jsdobj);
|
||||||
|
|
||||||
|
/* walk the stack to find js frame (if any) causing creation */
|
||||||
|
while( NULL != (fp = JS_FrameIterator(cx, &iter)) )
|
||||||
|
{
|
||||||
|
if( !JS_IsNativeFrame(cx, fp) )
|
||||||
|
{
|
||||||
|
JSScript* script = JS_GetFrameScript(cx, fp);
|
||||||
|
if( !script )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
newURL = JS_GetScriptFilename(cx, script);
|
||||||
|
if( newURL )
|
||||||
|
jsdobj->newURL = jsd_AddAtom(jsdc, newURL);
|
||||||
|
|
||||||
|
pc = JS_GetFramePC(cx, fp);
|
||||||
|
if( pc )
|
||||||
|
jsdobj->newLineno = JS_PCToLineNumber(cx, script, pc);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return jsdobj;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JS_DLL_CALLBACK
|
||||||
|
jsd_ObjectHook(JSContext *cx, JSObject *obj, JSBool isNew, void *closure)
|
||||||
|
{
|
||||||
|
JSDObject* jsdobj;
|
||||||
|
JSDContext* jsdc = (JSDContext*) closure;
|
||||||
|
|
||||||
|
if( ! jsdc || ! jsdc->inited )
|
||||||
|
return;
|
||||||
|
|
||||||
|
JSD_LOCK_OBJECTS(jsdc);
|
||||||
|
if(isNew)
|
||||||
|
{
|
||||||
|
jsdobj = _createJSDObject(jsdc, cx, obj);
|
||||||
|
TRACEOBJ(jsdc, jsdobj, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
jsdobj = jsd_GetJSDObjectForJSObject(jsdc, obj);
|
||||||
|
if( jsdobj )
|
||||||
|
{
|
||||||
|
TRACEOBJ(jsdc, jsdobj, 1);
|
||||||
|
_destroyJSDObject(jsdc, jsdobj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JSD_UNLOCK_OBJECTS(jsdc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
jsd_Constructing(JSDContext* jsdc, JSContext *cx, JSObject *obj,
|
||||||
|
JSStackFrame *fp)
|
||||||
|
{
|
||||||
|
JSDObject* jsdobj;
|
||||||
|
JSScript* script;
|
||||||
|
JSDScript* jsdscript;
|
||||||
|
const char* ctorURL;
|
||||||
|
const char* ctorName;
|
||||||
|
|
||||||
|
JSD_LOCK_OBJECTS(jsdc);
|
||||||
|
jsdobj = jsd_GetJSDObjectForJSObject(jsdc, obj);
|
||||||
|
if( jsdobj && !jsdobj->ctorURL && !JS_IsNativeFrame(cx, fp) )
|
||||||
|
{
|
||||||
|
script = JS_GetFrameScript(cx, fp);
|
||||||
|
if( script )
|
||||||
|
{
|
||||||
|
ctorURL = JS_GetScriptFilename(cx, script);
|
||||||
|
if( ctorURL )
|
||||||
|
jsdobj->ctorURL = jsd_AddAtom(jsdc, ctorURL);
|
||||||
|
|
||||||
|
JSD_LOCK_SCRIPTS(jsdc);
|
||||||
|
jsdscript = jsd_FindJSDScript(jsdc, script);
|
||||||
|
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||||
|
if( jsdscript )
|
||||||
|
{
|
||||||
|
ctorName = jsd_GetScriptFunctionName(jsdc, jsdscript);
|
||||||
|
if( ctorName )
|
||||||
|
jsdobj->ctorName = jsd_AddAtom(jsdc, ctorName);
|
||||||
|
}
|
||||||
|
jsdobj->ctorLineno = JS_GetScriptBaseLineNumber(cx, script);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TRACEOBJ(jsdc, jsdobj, 3);
|
||||||
|
JSD_UNLOCK_OBJECTS(jsdc);
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_STATIC_DLL_CALLBACK(JSHashNumber)
|
||||||
|
_hash_root(const void *key)
|
||||||
|
{
|
||||||
|
return ((JSHashNumber) key) >> 2; /* help lame MSVC1.5 on Win16 */
|
||||||
|
}
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
jsd_InitObjectManager(JSDContext* jsdc)
|
||||||
|
{
|
||||||
|
JS_INIT_CLIST(&jsdc->objectsList);
|
||||||
|
jsdc->objectsTable = JS_NewHashTable(256, _hash_root,
|
||||||
|
JS_CompareValues, JS_CompareValues,
|
||||||
|
NULL, NULL);
|
||||||
|
return (JSBool) jsdc->objectsTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
jsd_DestroyObjectManager(JSDContext* jsdc)
|
||||||
|
{
|
||||||
|
JSD_LOCK_OBJECTS(jsdc);
|
||||||
|
while( !JS_CLIST_IS_EMPTY(&jsdc->objectsList) )
|
||||||
|
_destroyJSDObject(jsdc, (JSDObject*)JS_NEXT_LINK(&jsdc->objectsList));
|
||||||
|
JS_HashTableDestroy(jsdc->objectsTable);
|
||||||
|
JSD_UNLOCK_OBJECTS(jsdc);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSDObject*
|
||||||
|
jsd_IterateObjects(JSDContext* jsdc, JSDObject** iterp)
|
||||||
|
{
|
||||||
|
JSDObject *jsdobj = *iterp;
|
||||||
|
|
||||||
|
JS_ASSERT(JSD_OBJECTS_LOCKED(jsdc));
|
||||||
|
|
||||||
|
if( !jsdobj )
|
||||||
|
jsdobj = (JSDObject *)jsdc->objectsList.next;
|
||||||
|
if( jsdobj == (JSDObject *)&jsdc->objectsList )
|
||||||
|
return NULL;
|
||||||
|
*iterp = (JSDObject*) jsdobj->links.next;
|
||||||
|
return jsdobj;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSObject*
|
||||||
|
jsd_GetWrappedObject(JSDContext* jsdc, JSDObject* jsdobj)
|
||||||
|
{
|
||||||
|
return jsdobj->obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char*
|
||||||
|
jsd_GetObjectNewURL(JSDContext* jsdc, JSDObject* jsdobj)
|
||||||
|
{
|
||||||
|
if( jsdobj->newURL )
|
||||||
|
return JSD_ATOM_TO_STRING(jsdobj->newURL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintN
|
||||||
|
jsd_GetObjectNewLineNumber(JSDContext* jsdc, JSDObject* jsdobj)
|
||||||
|
{
|
||||||
|
return jsdobj->newLineno;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char*
|
||||||
|
jsd_GetObjectConstructorURL(JSDContext* jsdc, JSDObject* jsdobj)
|
||||||
|
{
|
||||||
|
if( jsdobj->ctorURL )
|
||||||
|
return JSD_ATOM_TO_STRING(jsdobj->ctorURL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintN
|
||||||
|
jsd_GetObjectConstructorLineNumber(JSDContext* jsdc, JSDObject* jsdobj)
|
||||||
|
{
|
||||||
|
return jsdobj->ctorLineno;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char*
|
||||||
|
jsd_GetObjectConstructorName(JSDContext* jsdc, JSDObject* jsdobj)
|
||||||
|
{
|
||||||
|
if( jsdobj->ctorName )
|
||||||
|
return JSD_ATOM_TO_STRING(jsdobj->ctorName);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSDObject*
|
||||||
|
jsd_GetJSDObjectForJSObject(JSDContext* jsdc, JSObject* jsobj)
|
||||||
|
{
|
||||||
|
JSDObject* jsdobj;
|
||||||
|
|
||||||
|
JSD_LOCK_OBJECTS(jsdc);
|
||||||
|
jsdobj = (JSDObject*) JS_HashTableLookup(jsdc->objectsTable, jsobj);
|
||||||
|
JSD_UNLOCK_OBJECTS(jsdc);
|
||||||
|
return jsdobj;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSDObject*
|
||||||
|
jsd_GetObjectForValue(JSDContext* jsdc, JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
return jsd_GetJSDObjectForJSObject(jsdc, JSVAL_TO_OBJECT(jsdval->val));
|
||||||
|
}
|
||||||
|
|
||||||
|
JSDValue*
|
||||||
|
jsd_GetValueForObject(JSDContext* jsdc, JSDObject* jsdobj)
|
||||||
|
{
|
||||||
|
return jsd_NewValue(jsdc, OBJECT_TO_JSVAL(jsdobj->obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
/* -*- 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
|
* 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
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||||
|
@ -17,17 +17,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** JavaScript Debugger Navigator API - Script support
|
* JavaScript Debugging support - Script support
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "jsd.h"
|
#include "jsd.h"
|
||||||
#ifdef NSPR20
|
|
||||||
#ifdef XP_MAC
|
|
||||||
#include "prpriv.h"
|
|
||||||
#else
|
|
||||||
#include "private/prpriv.h"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Comment this out to disable (NT specific) dumping as we go */
|
/* Comment this out to disable (NT specific) dumping as we go */
|
||||||
/*
|
/*
|
||||||
|
@ -39,75 +32,130 @@
|
||||||
#define NOT_SET_YET -1
|
#define NOT_SET_YET -1
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
PRCList jsd_script_list = PR_INIT_STATIC_CLIST(&jsd_script_list);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void JSD_ASSERT_VALID_SCRIPT( JSDScript* jsdscript )
|
void JSD_ASSERT_VALID_SCRIPT(JSDScript* jsdscript)
|
||||||
{
|
{
|
||||||
PR_ASSERT( jsdscript );
|
JS_ASSERT(jsdscript);
|
||||||
PR_ASSERT( jsdscript->script );
|
JS_ASSERT(jsdscript->script);
|
||||||
}
|
}
|
||||||
void JSD_ASSERT_VALID_EXEC_HOOK( JSDExecHook* jsdhook )
|
void JSD_ASSERT_VALID_EXEC_HOOK(JSDExecHook* jsdhook)
|
||||||
{
|
{
|
||||||
PR_ASSERT( jsdhook );
|
JS_ASSERT(jsdhook);
|
||||||
PR_ASSERT( jsdhook->hook );
|
JS_ASSERT(jsdhook->hook);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef LIVEWIRE
|
||||||
|
static JSBool
|
||||||
|
HasFileExtention(const char* name, const char* ext)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int len = strlen(ext);
|
||||||
|
const char* p = strrchr(name,'.');
|
||||||
|
if( !p )
|
||||||
|
return JS_FALSE;
|
||||||
|
p++;
|
||||||
|
for(i = 0; i < len; i++ )
|
||||||
|
{
|
||||||
|
JS_ASSERT(islower(ext[i]));
|
||||||
|
if( 0 == p[i] || tolower(p[i]) != ext[i] )
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
if( 0 != p[i] )
|
||||||
|
return JS_FALSE;
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
#endif /* LIVEWIRE */
|
||||||
|
|
||||||
static JSDScript*
|
static JSDScript*
|
||||||
NewJSDScript( JSDContext* jsdc,
|
_newJSDScript(JSDContext* jsdc,
|
||||||
JSContext *cx,
|
JSContext *cx,
|
||||||
JSScript *script,
|
JSScript *script,
|
||||||
JSFunction* function )
|
JSFunction* function)
|
||||||
{
|
{
|
||||||
JSDScript* jsdscript;
|
JSDScript* jsdscript;
|
||||||
PRUintn lineno;
|
uintN lineno;
|
||||||
|
const char* raw_filename;
|
||||||
|
|
||||||
|
JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc));
|
||||||
|
|
||||||
/* these are inlined javascript: urls and we can't handle them now */
|
/* these are inlined javascript: urls and we can't handle them now */
|
||||||
lineno = (PRUintn) JS_GetScriptBaseLineNumber(cx, script);
|
lineno = (uintN) JS_GetScriptBaseLineNumber(cx, script);
|
||||||
if( lineno == 0 )
|
if( lineno == 0 )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
jsdscript = PR_NEWZAP(JSDScript);
|
jsdscript = (JSDScript*) calloc(1, sizeof(JSDScript));
|
||||||
if( ! jsdscript )
|
if( ! jsdscript )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
PR_APPEND_LINK(&jsdscript->links, &jsd_script_list);
|
raw_filename = JS_GetScriptFilename(cx,script);
|
||||||
|
|
||||||
|
JS_APPEND_LINK(&jsdscript->links, &jsdc->scripts);
|
||||||
jsdscript->jsdc = jsdc;
|
jsdscript->jsdc = jsdc;
|
||||||
jsdscript->script = script;
|
jsdscript->script = script;
|
||||||
jsdscript->function = function;
|
jsdscript->function = function;
|
||||||
jsdscript->lineBase = lineno;
|
jsdscript->lineBase = lineno;
|
||||||
jsdscript->lineExtent = (PRUintn)NOT_SET_YET;
|
jsdscript->lineExtent = (uintN)NOT_SET_YET;
|
||||||
jsdscript->url = (char*)jsd_BuildNormalizedURL(JS_GetScriptFilename(cx,script));
|
#ifndef LIVEWIRE
|
||||||
|
jsdscript->url = (char*) jsd_BuildNormalizedURL(raw_filename);
|
||||||
|
#else
|
||||||
|
jsdscript->app = LWDBG_GetCurrentApp();
|
||||||
|
if( jsdscript->app && raw_filename )
|
||||||
|
{
|
||||||
|
jsdscript->url = jsdlw_BuildAppRelativeFilename(jsdscript->app, raw_filename);
|
||||||
|
if( function )
|
||||||
|
{
|
||||||
|
jsdscript->lwscript =
|
||||||
|
LWDBG_GetScriptOfFunction(jsdscript->app,
|
||||||
|
JS_GetFunctionName(function));
|
||||||
|
|
||||||
PR_INIT_CLIST(&jsdscript->hooks);
|
/* also, make sure this file is added to filelist if is .js file */
|
||||||
|
if( HasFileExtention(raw_filename,"js") ||
|
||||||
|
HasFileExtention(raw_filename,"sjs") )
|
||||||
|
{
|
||||||
|
jsdlw_PreLoadSource(jsdc, jsdscript->app, raw_filename, JS_FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
jsdscript->lwscript = LWDBG_GetCurrentTopLevelScript();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
JS_INIT_CLIST(&jsdscript->hooks);
|
||||||
|
|
||||||
return jsdscript;
|
return jsdscript;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
DestroyJSDScript( JSDContext* jsdc,
|
_destroyJSDScript(JSDContext* jsdc,
|
||||||
JSDScript* jsdscript )
|
JSDScript* jsdscript)
|
||||||
{
|
{
|
||||||
|
JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc));
|
||||||
|
|
||||||
/* destroy all hooks */
|
/* destroy all hooks */
|
||||||
jsd_ClearAllExecutionHooksForScript(jsdc, jsdscript);
|
jsd_ClearAllExecutionHooksForScript(jsdc, jsdscript);
|
||||||
|
|
||||||
PR_REMOVE_LINK(&jsdscript->links);
|
JS_REMOVE_LINK(&jsdscript->links);
|
||||||
PR_FREEIF(jsdscript->url);
|
if(jsdscript->url)
|
||||||
|
free(jsdscript->url);
|
||||||
|
|
||||||
PR_FREEIF(jsdscript);
|
if(jsdscript)
|
||||||
|
free(jsdscript);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
#ifdef JSD_DUMP
|
#ifdef JSD_DUMP
|
||||||
static void
|
static void
|
||||||
DumpJSDScript( JSDContext* jsdc, JSDScript* jsdscript, const char* leadingtext)
|
_dumpJSDScript(JSDContext* jsdc, JSDScript* jsdscript, const char* leadingtext)
|
||||||
{
|
{
|
||||||
const char* name;
|
const char* name;
|
||||||
const char* fun;
|
const char* fun;
|
||||||
PRUintn base;
|
uintN base;
|
||||||
PRUintn extent;
|
uintN extent;
|
||||||
char Buf[256];
|
char Buf[256];
|
||||||
|
|
||||||
name = jsd_GetScriptFilename(jsdc, jsdscript);
|
name = jsd_GetScriptFilename(jsdc, jsdscript);
|
||||||
|
@ -125,54 +173,32 @@ DumpJSDScript( JSDContext* jsdc, JSDScript* jsdscript, const char* leadingtext)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
DumpJSDScriptList( JSDContext* jsdc )
|
_dumpJSDScriptList( JSDContext* jsdc )
|
||||||
{
|
{
|
||||||
JSDScript* iterp = NULL;
|
JSDScript* iterp = NULL;
|
||||||
JSDScript* jsdscript = NULL;
|
JSDScript* jsdscript = NULL;
|
||||||
|
|
||||||
OutputDebugString( "*** JSDScriptDump\n" );
|
OutputDebugString( "*** JSDScriptDump\n" );
|
||||||
while( NULL != (jsdscript = jsd_IterateScripts(jsdc, &iterp)) )
|
while( NULL != (jsdscript = jsd_IterateScripts(jsdc, &iterp)) )
|
||||||
DumpJSDScript( jsdc, jsdscript, " script: " );
|
_dumpJSDScript( jsdc, jsdscript, " script: " );
|
||||||
}
|
}
|
||||||
#endif /* JSD_DUMP */
|
#endif /* JSD_DUMP */
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
#ifndef JSD_SIMULATION
|
|
||||||
static PRMonitor *jsd_script_mon = NULL;
|
|
||||||
#endif /* JSD_SIMULATION */
|
|
||||||
|
|
||||||
void
|
|
||||||
jsd_LockScriptSubsystem(JSDContext* jsdc)
|
|
||||||
{
|
|
||||||
#ifndef JSD_SIMULATION
|
|
||||||
if (jsd_script_mon == NULL)
|
|
||||||
jsd_script_mon = PR_NewNamedMonitor("jsd-script-monitor");
|
|
||||||
|
|
||||||
PR_EnterMonitor(jsd_script_mon);
|
|
||||||
#endif /* JSD_SIMULATION */
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
jsd_UnlockScriptSubsystem(JSDContext* jsdc)
|
|
||||||
{
|
|
||||||
#ifndef JSD_SIMULATION
|
|
||||||
PR_ExitMonitor(jsd_script_mon);
|
|
||||||
#endif /* JSD_SIMULATION */
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
jsd_DestroyAllJSDScripts( JSDContext* jsdc )
|
jsd_DestroyAllJSDScripts( JSDContext* jsdc )
|
||||||
{
|
{
|
||||||
JSDScript *jsdscript;
|
JSDScript *jsdscript;
|
||||||
JSDScript *next;
|
JSDScript *next;
|
||||||
|
|
||||||
for (jsdscript = (JSDScript*)jsd_script_list.next;
|
JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc));
|
||||||
jsdscript != (JSDScript*)&jsd_script_list;
|
|
||||||
jsdscript = next)
|
for( jsdscript = (JSDScript*)jsdc->scripts.next;
|
||||||
|
jsdscript != (JSDScript*)&jsdc->scripts;
|
||||||
|
jsdscript = next )
|
||||||
{
|
{
|
||||||
next = (JSDScript*)jsdscript->links.next;
|
next = (JSDScript*)jsdscript->links.next;
|
||||||
DestroyJSDScript( jsdc, jsdscript );
|
_destroyJSDScript( jsdc, jsdscript );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,9 +208,12 @@ jsd_FindJSDScript( JSDContext* jsdc,
|
||||||
{
|
{
|
||||||
JSDScript *jsdscript;
|
JSDScript *jsdscript;
|
||||||
|
|
||||||
for (jsdscript = (JSDScript *)jsd_script_list.next;
|
JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc));
|
||||||
jsdscript != (JSDScript *)&jsd_script_list;
|
|
||||||
jsdscript = (JSDScript *)jsdscript->links.next) {
|
for( jsdscript = (JSDScript *)jsdc->scripts.next;
|
||||||
|
jsdscript != (JSDScript *)&jsdc->scripts;
|
||||||
|
jsdscript = (JSDScript *)jsdscript->links.next )
|
||||||
|
{
|
||||||
if (jsdscript->script == script)
|
if (jsdscript->script == script)
|
||||||
return jsdscript;
|
return jsdscript;
|
||||||
}
|
}
|
||||||
|
@ -196,14 +225,33 @@ jsd_IterateScripts(JSDContext* jsdc, JSDScript **iterp)
|
||||||
{
|
{
|
||||||
JSDScript *jsdscript = *iterp;
|
JSDScript *jsdscript = *iterp;
|
||||||
|
|
||||||
if (!jsdscript)
|
JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc));
|
||||||
jsdscript = (JSDScript *)jsd_script_list.next;
|
|
||||||
if (jsdscript == (JSDScript *)&jsd_script_list)
|
if( !jsdscript )
|
||||||
|
jsdscript = (JSDScript *)jsdc->scripts.next;
|
||||||
|
if( jsdscript == (JSDScript *)&jsdc->scripts )
|
||||||
return NULL;
|
return NULL;
|
||||||
*iterp = (JSDScript *)jsdscript->links.next;
|
*iterp = (JSDScript*) jsdscript->links.next;
|
||||||
return jsdscript;
|
return jsdscript;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
jsd_IsActiveScript(JSDContext* jsdc, JSDScript *jsdscript)
|
||||||
|
{
|
||||||
|
JSDScript *current;
|
||||||
|
|
||||||
|
JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc));
|
||||||
|
|
||||||
|
for( current = (JSDScript *)jsdc->scripts.next;
|
||||||
|
current != (JSDScript *)&jsdc->scripts;
|
||||||
|
current = (JSDScript *)current->links.next )
|
||||||
|
{
|
||||||
|
if(jsdscript == current)
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
jsd_GetScriptFilename(JSDContext* jsdc, JSDScript *jsdscript)
|
jsd_GetScriptFilename(JSDContext* jsdc, JSDScript *jsdscript)
|
||||||
{
|
{
|
||||||
|
@ -218,13 +266,13 @@ jsd_GetScriptFunctionName(JSDContext* jsdc, JSDScript *jsdscript)
|
||||||
return JS_GetFunctionName(jsdscript->function);
|
return JS_GetFunctionName(jsdscript->function);
|
||||||
}
|
}
|
||||||
|
|
||||||
PRUintn
|
uintN
|
||||||
jsd_GetScriptBaseLineNumber(JSDContext* jsdc, JSDScript *jsdscript)
|
jsd_GetScriptBaseLineNumber(JSDContext* jsdc, JSDScript *jsdscript)
|
||||||
{
|
{
|
||||||
return jsdscript->lineBase;
|
return jsdscript->lineBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRUintn
|
uintN
|
||||||
jsd_GetScriptLineExtent(JSDContext* jsdc, JSDScript *jsdscript)
|
jsd_GetScriptLineExtent(JSDContext* jsdc, JSDScript *jsdscript)
|
||||||
{
|
{
|
||||||
if( NOT_SET_YET == jsdscript->lineExtent )
|
if( NOT_SET_YET == jsdscript->lineExtent )
|
||||||
|
@ -232,88 +280,120 @@ jsd_GetScriptLineExtent(JSDContext* jsdc, JSDScript *jsdscript)
|
||||||
return jsdscript->lineExtent;
|
return jsdscript->lineExtent;
|
||||||
}
|
}
|
||||||
|
|
||||||
prword_t
|
jsuword
|
||||||
jsd_GetClosestPC(JSDContext* jsdc, JSDScript* jsdscript, PRUintn line)
|
jsd_GetClosestPC(JSDContext* jsdc, JSDScript* jsdscript, uintN line)
|
||||||
{
|
{
|
||||||
return (prword_t) JS_LineNumberToPC(jsdc->dumbContext,
|
#ifdef LIVEWIRE
|
||||||
|
if( jsdscript && jsdscript->lwscript )
|
||||||
|
{
|
||||||
|
uintN newline;
|
||||||
|
jsdlw_RawToProcessedLineNumber(jsdc, jsdscript, line, &newline);
|
||||||
|
if( line != newline )
|
||||||
|
line = newline;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (jsuword) JS_LineNumberToPC(jsdc->dumbContext,
|
||||||
jsdscript->script, line );
|
jsdscript->script, line );
|
||||||
}
|
}
|
||||||
|
|
||||||
PRUintn
|
uintN
|
||||||
jsd_GetClosestLine(JSDContext* jsdc, JSDScript* jsdscript, prword_t pc)
|
jsd_GetClosestLine(JSDContext* jsdc, JSDScript* jsdscript, jsuword pc)
|
||||||
{
|
{
|
||||||
PRUintn first = jsdscript->lineBase;
|
uintN first = jsdscript->lineBase;
|
||||||
PRUintn last = first + jsd_GetScriptLineExtent(jsdc, jsdscript) - 1;
|
uintN last = first + jsd_GetScriptLineExtent(jsdc, jsdscript) - 1;
|
||||||
PRUintn line = JS_PCToLineNumber(jsdc->dumbContext,
|
uintN line = JS_PCToLineNumber(jsdc->dumbContext,
|
||||||
jsdscript->script, (jsbytecode*)pc);
|
jsdscript->script, (jsbytecode*)pc);
|
||||||
|
|
||||||
if( line < first )
|
if( line < first )
|
||||||
return first;
|
return first;
|
||||||
if( line > last )
|
if( line > last )
|
||||||
return last;
|
return last;
|
||||||
|
|
||||||
|
#ifdef LIVEWIRE
|
||||||
|
if( jsdscript && jsdscript->lwscript )
|
||||||
|
{
|
||||||
|
uintN newline;
|
||||||
|
jsdlw_ProcessedToRawLineNumber(jsdc, jsdscript, line, &newline);
|
||||||
|
line = newline;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSD_ScriptHookProc
|
JSBool
|
||||||
jsd_SetScriptHook(JSDContext* jsdc, JSD_ScriptHookProc hook, void* callerdata)
|
jsd_SetScriptHook(JSDContext* jsdc, JSD_ScriptHookProc hook, void* callerdata)
|
||||||
{
|
{
|
||||||
JSD_ScriptHookProc oldHook = jsdc->scriptHook;
|
JSD_LOCK();
|
||||||
jsdc->scriptHook = hook;
|
jsdc->scriptHook = hook;
|
||||||
jsdc->scriptHookData = callerdata;
|
jsdc->scriptHookData = callerdata;
|
||||||
return oldHook;
|
JSD_UNLOCK();
|
||||||
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSD_ScriptHookProc
|
JSBool
|
||||||
jsd_GetScriptHook(JSDContext* jsdc)
|
jsd_GetScriptHook(JSDContext* jsdc, JSD_ScriptHookProc* hook, void** callerdata)
|
||||||
{
|
{
|
||||||
return jsdc->scriptHook;
|
JSD_LOCK();
|
||||||
|
if( hook )
|
||||||
|
*hook = jsdc->scriptHook;
|
||||||
|
if( callerdata )
|
||||||
|
*callerdata = jsdc->scriptHookData;
|
||||||
|
JSD_UNLOCK();
|
||||||
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
void PR_CALLBACK
|
void JS_DLL_CALLBACK
|
||||||
jsd_NewScriptHookProc(
|
jsd_NewScriptHookProc(
|
||||||
JSContext *cx,
|
JSContext *cx,
|
||||||
const char *filename, /* URL this script loads from */
|
const char *filename, /* URL this script loads from */
|
||||||
PRUintn lineno, /* line where this script starts */
|
uintN lineno, /* line where this script starts */
|
||||||
JSScript *script,
|
JSScript *script,
|
||||||
JSFunction *fun,
|
JSFunction *fun,
|
||||||
void* callerdata )
|
void* callerdata )
|
||||||
{
|
{
|
||||||
JSDScript* jsdscript = NULL;
|
JSDScript* jsdscript = NULL;
|
||||||
JSDContext* jsdc = (JSDContext*) callerdata;
|
JSDContext* jsdc = (JSDContext*) callerdata;
|
||||||
|
JSD_ScriptHookProc hook;
|
||||||
if( jsd_IsCurrentThreadDangerous() )
|
void* hookData;
|
||||||
return;
|
|
||||||
|
|
||||||
JSD_ASSERT_VALID_CONTEXT(jsdc);
|
JSD_ASSERT_VALID_CONTEXT(jsdc);
|
||||||
|
|
||||||
jsd_LockScriptSubsystem(jsdc);
|
if( JSD_IS_DANGEROUS_THREAD(jsdc) )
|
||||||
|
return;
|
||||||
jsd_JSContextUsed(jsdc, cx);
|
|
||||||
|
#ifdef LIVEWIRE
|
||||||
jsdscript = NewJSDScript( jsdc, cx, script, fun );
|
if( 1 == lineno )
|
||||||
if( ! jsdscript )
|
jsdlw_PreLoadSource(jsdc, LWDBG_GetCurrentApp(), filename, JS_TRUE );
|
||||||
{
|
#endif
|
||||||
jsd_UnlockScriptSubsystem(jsdc);
|
|
||||||
|
JSD_LOCK_SCRIPTS(jsdc);
|
||||||
|
jsdscript = _newJSDScript(jsdc, cx, script, fun);
|
||||||
|
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||||
|
if( ! jsdscript )
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef JSD_DUMP
|
#ifdef JSD_DUMP
|
||||||
if( jsdscript )
|
JSD_LOCK_SCRIPTS(jsdc);
|
||||||
{
|
_dumpJSDScript(jsdc, jsdscript, "***NEW Script: ");
|
||||||
DumpJSDScript( jsdc, jsdscript, "***NEW Script: " );
|
_dumpJSDScriptList( jsdc );
|
||||||
DumpJSDScriptList( jsdc );
|
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||||
}
|
|
||||||
#endif /* JSD_DUMP */
|
#endif /* JSD_DUMP */
|
||||||
|
|
||||||
if( jsdc->scriptHook )
|
/* local in case jsdc->scriptHook gets cleared on another thread */
|
||||||
jsdc->scriptHook( jsdc, jsdscript, TRUE, jsdc->scriptHookData );
|
JSD_LOCK();
|
||||||
|
hook = jsdc->scriptHook;
|
||||||
|
hookData = jsdc->scriptHookData;
|
||||||
|
JSD_UNLOCK();
|
||||||
|
|
||||||
jsd_UnlockScriptSubsystem(jsdc);
|
if( hook )
|
||||||
|
hook(jsdc, jsdscript, JS_TRUE, hookData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PR_CALLBACK
|
void JS_DLL_CALLBACK
|
||||||
jsd_DestroyScriptHookProc(
|
jsd_DestroyScriptHookProc(
|
||||||
JSContext *cx,
|
JSContext *cx,
|
||||||
JSScript *script,
|
JSScript *script,
|
||||||
|
@ -321,51 +401,59 @@ jsd_DestroyScriptHookProc(
|
||||||
{
|
{
|
||||||
JSDScript* jsdscript = NULL;
|
JSDScript* jsdscript = NULL;
|
||||||
JSDContext* jsdc = (JSDContext*) callerdata;
|
JSDContext* jsdc = (JSDContext*) callerdata;
|
||||||
|
JSD_ScriptHookProc hook;
|
||||||
if( jsd_IsCurrentThreadDangerous() )
|
void* hookData;
|
||||||
return;
|
|
||||||
|
|
||||||
JSD_ASSERT_VALID_CONTEXT(jsdc);
|
JSD_ASSERT_VALID_CONTEXT(jsdc);
|
||||||
|
|
||||||
jsd_LockScriptSubsystem(jsdc);
|
if( JSD_IS_DANGEROUS_THREAD(jsdc) )
|
||||||
|
return;
|
||||||
jsd_JSContextUsed(jsdc, cx);
|
|
||||||
|
JSD_LOCK_SCRIPTS(jsdc);
|
||||||
jsdscript = jsd_FindJSDScript( jsdc, script );
|
jsdscript = jsd_FindJSDScript(jsdc, script);
|
||||||
if( ! jsdscript )
|
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||||
{
|
|
||||||
jsd_UnlockScriptSubsystem(jsdc);
|
if( ! jsdscript )
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef JSD_DUMP
|
#ifdef JSD_DUMP
|
||||||
DumpJSDScript( jsdc, jsdscript, "***DESTROY Script: " );
|
JSD_LOCK_SCRIPTS(jsdc);
|
||||||
|
_dumpJSDScript(jsdc, jsdscript, "***DESTROY Script: ");
|
||||||
|
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||||
#endif /* JSD_DUMP */
|
#endif /* JSD_DUMP */
|
||||||
|
|
||||||
if( jsdc->scriptHook )
|
/* local in case hook gets cleared on another thread */
|
||||||
jsdc->scriptHook( jsdc, jsdscript, FALSE, jsdc->scriptHookData );
|
JSD_LOCK();
|
||||||
|
hook = jsdc->scriptHook;
|
||||||
|
hookData = jsdc->scriptHookData;
|
||||||
|
JSD_UNLOCK();
|
||||||
|
|
||||||
DestroyJSDScript( jsdc, jsdscript );
|
if( hook )
|
||||||
|
hook(jsdc, jsdscript, JS_FALSE, hookData);
|
||||||
|
|
||||||
|
JSD_LOCK_SCRIPTS(jsdc);
|
||||||
|
_destroyJSDScript(jsdc, jsdscript);
|
||||||
|
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||||
|
|
||||||
#ifdef JSD_DUMP
|
#ifdef JSD_DUMP
|
||||||
DumpJSDScriptList( jsdc );
|
JSD_LOCK_SCRIPTS(jsdc);
|
||||||
|
_dumpJSDScriptList(jsdc);
|
||||||
|
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||||
#endif /* JSD_DUMP */
|
#endif /* JSD_DUMP */
|
||||||
|
|
||||||
jsd_UnlockScriptSubsystem(jsdc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
static JSDExecHook*
|
static JSDExecHook*
|
||||||
FindHook( JSDContext* jsdc, JSDScript* jsdscript, prword_t pc)
|
_findHook(JSDContext* jsdc, JSDScript* jsdscript, jsuword pc)
|
||||||
{
|
{
|
||||||
JSDExecHook* jsdhook;
|
JSDExecHook* jsdhook;
|
||||||
PRCList* list = &jsdscript->hooks;
|
JSCList* list = &jsdscript->hooks;
|
||||||
|
|
||||||
for (jsdhook = (JSDExecHook*)list->next;
|
for( jsdhook = (JSDExecHook*)list->next;
|
||||||
jsdhook != (JSDExecHook*)list;
|
jsdhook != (JSDExecHook*)list;
|
||||||
jsdhook = (JSDExecHook*)jsdhook->links.next)
|
jsdhook = (JSDExecHook*)jsdhook->links.next )
|
||||||
{
|
{
|
||||||
if (jsdhook->pc == pc)
|
if (jsdhook->pc == pc)
|
||||||
return jsdhook;
|
return jsdhook;
|
||||||
|
@ -373,45 +461,82 @@ FindHook( JSDContext* jsdc, JSDScript* jsdscript, prword_t pc)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSTrapStatus PR_CALLBACK
|
static JSBool
|
||||||
|
_isActiveHook(JSDContext* jsdc, JSScript *script, JSDExecHook* jsdhook)
|
||||||
|
{
|
||||||
|
JSDExecHook* current;
|
||||||
|
JSCList* list;
|
||||||
|
JSDScript* jsdscript;
|
||||||
|
|
||||||
|
JSD_LOCK_SCRIPTS(jsdc);
|
||||||
|
jsdscript = jsd_FindJSDScript(jsdc, script);
|
||||||
|
if( ! jsdscript)
|
||||||
|
{
|
||||||
|
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
list = &jsdscript->hooks;
|
||||||
|
|
||||||
|
for( current = (JSDExecHook*)list->next;
|
||||||
|
current != (JSDExecHook*)list;
|
||||||
|
current = (JSDExecHook*)current->links.next )
|
||||||
|
{
|
||||||
|
if(current == jsdhook)
|
||||||
|
{
|
||||||
|
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
JSTrapStatus JS_DLL_CALLBACK
|
||||||
jsd_TrapHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
|
jsd_TrapHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
|
||||||
void *closure)
|
void *closure)
|
||||||
{
|
{
|
||||||
PRUintn hookanswer = JSD_HOOK_RETURN_CONTINUE;
|
|
||||||
JSDThreadState* jsdthreadstate;
|
|
||||||
JSDExecHook* jsdhook = (JSDExecHook*) closure;
|
JSDExecHook* jsdhook = (JSDExecHook*) closure;
|
||||||
|
JSD_ExecutionHookProc hook;
|
||||||
|
void* hookData;
|
||||||
JSDContext* jsdc;
|
JSDContext* jsdc;
|
||||||
|
JSDScript* jsdscript;
|
||||||
|
|
||||||
if( jsd_IsCurrentThreadDangerous() )
|
JSD_LOCK();
|
||||||
|
|
||||||
|
if( NULL == (jsdc = jsd_JSDContextForJSContext(cx)) ||
|
||||||
|
! _isActiveHook(jsdc, script, jsdhook) )
|
||||||
|
{
|
||||||
|
JSD_UNLOCK();
|
||||||
return JSTRAP_CONTINUE;
|
return JSTRAP_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
JSD_ASSERT_VALID_EXEC_HOOK(jsdhook);
|
JSD_ASSERT_VALID_EXEC_HOOK(jsdhook);
|
||||||
PR_ASSERT(jsdhook->pc == (prword_t)pc);
|
JS_ASSERT(jsdhook->pc == (jsuword)pc);
|
||||||
PR_ASSERT(jsdhook->jsdscript->script == script);
|
JS_ASSERT(jsdhook->jsdscript->script == script);
|
||||||
|
JS_ASSERT(jsdhook->jsdscript->jsdc == jsdc);
|
||||||
|
|
||||||
|
hook = jsdhook->hook;
|
||||||
|
hookData = jsdhook->callerdata;
|
||||||
|
jsdscript = jsdhook->jsdscript;
|
||||||
|
|
||||||
|
/* do not use jsdhook-> after this point */
|
||||||
|
JSD_UNLOCK();
|
||||||
|
|
||||||
jsdc = jsdhook->jsdscript->jsdc;
|
|
||||||
if( ! jsdc || ! jsdc->inited )
|
if( ! jsdc || ! jsdc->inited )
|
||||||
return JSTRAP_CONTINUE;
|
return JSTRAP_CONTINUE;
|
||||||
|
|
||||||
jsd_JSContextUsed(jsdc, cx);
|
if( JSD_IS_DANGEROUS_THREAD(jsdc) )
|
||||||
|
return JSTRAP_CONTINUE;
|
||||||
|
|
||||||
jsdthreadstate = jsd_NewThreadState(jsdc,cx);
|
#ifdef LIVEWIRE
|
||||||
if( jsdthreadstate )
|
if( ! jsdlw_UserCodeAtPC(jsdc, jsdscript, (jsuword)pc) )
|
||||||
{
|
return JSTRAP_CONTINUE;
|
||||||
hookanswer =
|
#endif
|
||||||
(*jsdhook->hook)(jsdc, jsdthreadstate,
|
|
||||||
JSD_HOOK_BREAKPOINT,
|
|
||||||
jsdhook->callerdata );
|
|
||||||
|
|
||||||
jsd_DestroyThreadState(jsdc, jsdthreadstate);
|
return jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_BREAKPOINT,
|
||||||
}
|
hook, hookData, rval);
|
||||||
|
|
||||||
*rval = NULL; /* XXX fix this!!! */
|
|
||||||
|
|
||||||
if( JSD_HOOK_RETURN_ABORT == hookanswer )
|
|
||||||
return JSTRAP_ERROR;
|
|
||||||
|
|
||||||
return JSTRAP_CONTINUE; /* XXX fix this!!! */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -419,16 +544,21 @@ jsd_TrapHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
|
||||||
JSBool
|
JSBool
|
||||||
jsd_SetExecutionHook(JSDContext* jsdc,
|
jsd_SetExecutionHook(JSDContext* jsdc,
|
||||||
JSDScript* jsdscript,
|
JSDScript* jsdscript,
|
||||||
prword_t pc,
|
jsuword pc,
|
||||||
JSD_ExecutionHookProc hook,
|
JSD_ExecutionHookProc hook,
|
||||||
void* callerdata)
|
void* callerdata)
|
||||||
{
|
{
|
||||||
JSDExecHook* jsdhook;
|
JSDExecHook* jsdhook;
|
||||||
|
|
||||||
|
JSD_LOCK();
|
||||||
if( ! hook )
|
if( ! hook )
|
||||||
return jsd_ClearExecutionHook(jsdc, jsdscript, pc);
|
{
|
||||||
|
jsd_ClearExecutionHook(jsdc, jsdscript, pc);
|
||||||
|
JSD_UNLOCK();
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
jsdhook = FindHook(jsdc, jsdscript, pc);
|
jsdhook = _findHook(jsdc, jsdscript, pc);
|
||||||
if( jsdhook )
|
if( jsdhook )
|
||||||
{
|
{
|
||||||
jsdhook->hook = hook;
|
jsdhook->hook = hook;
|
||||||
|
@ -437,7 +567,7 @@ jsd_SetExecutionHook(JSDContext* jsdc,
|
||||||
}
|
}
|
||||||
/* else... */
|
/* else... */
|
||||||
|
|
||||||
jsdhook = PR_NEWZAP(JSDExecHook);
|
jsdhook = (JSDExecHook*)calloc(1, sizeof(JSDExecHook));
|
||||||
if( ! jsdhook )
|
if( ! jsdhook )
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
jsdhook->jsdscript = jsdscript;
|
jsdhook->jsdscript = jsdscript;
|
||||||
|
@ -448,34 +578,40 @@ jsd_SetExecutionHook(JSDContext* jsdc,
|
||||||
if( ! JS_SetTrap(jsdc->dumbContext, jsdscript->script,
|
if( ! JS_SetTrap(jsdc->dumbContext, jsdscript->script,
|
||||||
(jsbytecode*)pc, jsd_TrapHandler, (void*) jsdhook) )
|
(jsbytecode*)pc, jsd_TrapHandler, (void*) jsdhook) )
|
||||||
{
|
{
|
||||||
PR_FREEIF(jsdhook);
|
free(jsdhook);
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
PR_APPEND_LINK(&jsdhook->links, &jsdscript->hooks);
|
JS_APPEND_LINK(&jsdhook->links, &jsdscript->hooks);
|
||||||
|
JSD_UNLOCK();
|
||||||
|
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSBool
|
JSBool
|
||||||
jsd_ClearExecutionHook(JSDContext* jsdc,
|
jsd_ClearExecutionHook(JSDContext* jsdc,
|
||||||
JSDScript* jsdscript,
|
JSDScript* jsdscript,
|
||||||
prword_t pc)
|
jsuword pc)
|
||||||
{
|
{
|
||||||
JSDExecHook* jsdhook;
|
JSDExecHook* jsdhook;
|
||||||
|
|
||||||
jsdhook = FindHook(jsdc, jsdscript, pc);
|
JSD_LOCK();
|
||||||
|
|
||||||
|
jsdhook = _findHook(jsdc, jsdscript, pc);
|
||||||
if( ! jsdhook )
|
if( ! jsdhook )
|
||||||
{
|
{
|
||||||
PR_ASSERT(0);
|
JS_ASSERT(0);
|
||||||
|
JSD_UNLOCK();
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_ClearTrap(jsdc->dumbContext, jsdscript->script,
|
JS_ClearTrap(jsdc->dumbContext, jsdscript->script,
|
||||||
(jsbytecode*)pc, NULL, NULL );
|
(jsbytecode*)pc, NULL, NULL );
|
||||||
|
|
||||||
PR_REMOVE_LINK(&jsdhook->links);
|
JS_REMOVE_LINK(&jsdhook->links);
|
||||||
PR_FREEIF(jsdhook);
|
free(jsdhook);
|
||||||
|
|
||||||
|
JSD_UNLOCK();
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,15 +619,19 @@ JSBool
|
||||||
jsd_ClearAllExecutionHooksForScript(JSDContext* jsdc, JSDScript* jsdscript)
|
jsd_ClearAllExecutionHooksForScript(JSDContext* jsdc, JSDScript* jsdscript)
|
||||||
{
|
{
|
||||||
JSDExecHook* jsdhook;
|
JSDExecHook* jsdhook;
|
||||||
PRCList* list = &jsdscript->hooks;
|
JSCList* list = &jsdscript->hooks;
|
||||||
|
|
||||||
|
JSD_LOCK();
|
||||||
|
|
||||||
while( (JSDExecHook*)list != (jsdhook = (JSDExecHook*)list->next) )
|
while( (JSDExecHook*)list != (jsdhook = (JSDExecHook*)list->next) )
|
||||||
{
|
{
|
||||||
PR_REMOVE_LINK(&jsdhook->links);
|
JS_REMOVE_LINK(&jsdhook->links);
|
||||||
PR_FREEIF(jsdhook);
|
free(jsdhook);
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_ClearScriptTraps(jsdc->dumbContext, jsdscript->script);
|
JS_ClearScriptTraps(jsdc->dumbContext, jsdscript->script);
|
||||||
|
JSD_UNLOCK();
|
||||||
|
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -501,8 +641,28 @@ jsd_ClearAllExecutionHooks(JSDContext* jsdc)
|
||||||
JSDScript* jsdscript;
|
JSDScript* jsdscript;
|
||||||
JSDScript* iterp = NULL;
|
JSDScript* iterp = NULL;
|
||||||
|
|
||||||
|
JSD_LOCK();
|
||||||
while( NULL != (jsdscript = jsd_IterateScripts(jsdc, &iterp)) )
|
while( NULL != (jsdscript = jsd_IterateScripts(jsdc, &iterp)) )
|
||||||
jsd_ClearAllExecutionHooksForScript(jsdc, jsdscript);
|
jsd_ClearAllExecutionHooksForScript(jsdc, jsdscript);
|
||||||
|
JSD_UNLOCK();
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
jsd_ScriptCreated(JSDContext* jsdc,
|
||||||
|
JSContext *cx,
|
||||||
|
const char *filename, /* URL this script loads from */
|
||||||
|
uintN lineno, /* line where this script starts */
|
||||||
|
JSScript *script,
|
||||||
|
JSFunction *fun)
|
||||||
|
{
|
||||||
|
jsd_NewScriptHookProc(cx, filename, lineno, script, fun, jsdc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
jsd_ScriptDestroyed(JSDContext* jsdc,
|
||||||
|
JSContext *cx,
|
||||||
|
JSScript *script)
|
||||||
|
{
|
||||||
|
jsd_DestroyScriptHookProc(cx, script, jsdc);
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
/* -*- 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
|
* 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
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||||
|
@ -17,71 +17,63 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** JavaScript Debugger Navigator API - Call Stack support
|
* JavaScript Debugging support - Call stack support
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "jsd.h"
|
#include "jsd.h"
|
||||||
#ifdef NSPR20
|
|
||||||
#ifdef XP_MAC
|
|
||||||
#include "prpriv.h"
|
|
||||||
#else
|
|
||||||
#include "private/prpriv.h"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void JSD_ASSERT_VALID_THREAD_STATE( JSDThreadState* jsdthreadstate )
|
void JSD_ASSERT_VALID_THREAD_STATE(JSDThreadState* jsdthreadstate)
|
||||||
{
|
{
|
||||||
PR_ASSERT(jsdthreadstate);
|
JS_ASSERT(jsdthreadstate);
|
||||||
PR_ASSERT(jsdthreadstate->stackDepth > 0);
|
JS_ASSERT(jsdthreadstate->stackDepth > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JSD_ASSERT_VALID_STACK_FRAME( JSDStackFrameInfo* jsdframe )
|
void JSD_ASSERT_VALID_STACK_FRAME(JSDStackFrameInfo* jsdframe)
|
||||||
{
|
{
|
||||||
PR_ASSERT(jsdframe);
|
JS_ASSERT(jsdframe);
|
||||||
PR_ASSERT(jsdframe->jsdthreadstate);
|
JS_ASSERT(jsdframe->jsdthreadstate);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static JSDStackFrameInfo*
|
static JSDStackFrameInfo*
|
||||||
AddNewFrame( JSDContext* jsdc,
|
_addNewFrame(JSDContext* jsdc,
|
||||||
JSDThreadState* jsdthreadstate,
|
JSDThreadState* jsdthreadstate,
|
||||||
JSScript* script,
|
JSScript* script,
|
||||||
prword_t pc,
|
jsuword pc,
|
||||||
JSObject* object,
|
JSStackFrame* fp)
|
||||||
JSObject* thisp,
|
|
||||||
JSStackFrame* fp )
|
|
||||||
{
|
{
|
||||||
JSDStackFrameInfo* jsdframe;
|
JSDStackFrameInfo* jsdframe;
|
||||||
JSDScript* jsdscript;
|
JSDScript* jsdscript;
|
||||||
|
|
||||||
|
JSD_LOCK_SCRIPTS(jsdc);
|
||||||
jsdscript = jsd_FindJSDScript(jsdc, script);
|
jsdscript = jsd_FindJSDScript(jsdc, script);
|
||||||
|
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||||
if( ! jsdscript )
|
if( ! jsdscript )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
jsdframe = PR_NEWZAP(JSDStackFrameInfo);
|
jsdframe = (JSDStackFrameInfo*) calloc(1, sizeof(JSDStackFrameInfo));
|
||||||
if( ! jsdframe )
|
if( ! jsdframe )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
jsdframe->jsdthreadstate = jsdthreadstate;
|
jsdframe->jsdthreadstate = jsdthreadstate;
|
||||||
jsdframe->jsdscript = jsdscript ;
|
jsdframe->jsdscript = jsdscript ;
|
||||||
jsdframe->pc = pc ;
|
jsdframe->pc = pc ;
|
||||||
jsdframe->object = object ;
|
|
||||||
jsdframe->thisp = thisp ;
|
|
||||||
jsdframe->fp = fp ;
|
jsdframe->fp = fp ;
|
||||||
|
|
||||||
PR_APPEND_LINK(&jsdframe->links, &jsdthreadstate->stack);
|
JS_APPEND_LINK(&jsdframe->links, &jsdthreadstate->stack);
|
||||||
jsdthreadstate->stackDepth++;
|
jsdthreadstate->stackDepth++;
|
||||||
|
|
||||||
return jsdframe;
|
return jsdframe;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
DestroyFrame(JSDStackFrameInfo* jsdframe)
|
_destroyFrame(JSDStackFrameInfo* jsdframe)
|
||||||
{
|
{
|
||||||
/* kill any alloc'd objects in frame here... */
|
/* kill any alloc'd objects in frame here... */
|
||||||
|
|
||||||
PR_FREEIF(jsdframe);
|
if( jsdframe )
|
||||||
|
free(jsdframe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,31 +84,36 @@ jsd_NewThreadState(JSDContext* jsdc, JSContext *cx )
|
||||||
JSStackFrame * iter = NULL;
|
JSStackFrame * iter = NULL;
|
||||||
JSStackFrame * fp;
|
JSStackFrame * fp;
|
||||||
|
|
||||||
jsdthreadstate = PR_NEWZAP(JSDThreadState);
|
jsdthreadstate = (JSDThreadState*)calloc(1, sizeof(JSDThreadState));
|
||||||
if( ! jsdthreadstate )
|
if( ! jsdthreadstate )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
jsdthreadstate->context = cx;
|
jsdthreadstate->context = cx;
|
||||||
jsdthreadstate->thread = PR_CurrentThread();
|
jsdthreadstate->thread = JSD_CURRENT_THREAD();
|
||||||
PR_INIT_CLIST(&jsdthreadstate->stack);
|
JS_INIT_CLIST(&jsdthreadstate->stack);
|
||||||
jsdthreadstate->stackDepth = 0;
|
jsdthreadstate->stackDepth = 0;
|
||||||
|
|
||||||
while( NULL != (fp = JS_FrameIterator(cx, &iter)) )
|
while( NULL != (fp = JS_FrameIterator(cx, &iter)) )
|
||||||
{
|
{
|
||||||
JSScript* script = JS_GetFrameScript(cx, fp);
|
JSScript* script = JS_GetFrameScript(cx, fp);
|
||||||
prword_t pc = (prword_t) JS_GetFramePC(cx, fp);
|
jsuword pc = (jsuword) JS_GetFramePC(cx, fp);
|
||||||
|
|
||||||
if( ! script || ! pc || JS_IsNativeFrame(cx, fp) )
|
if( ! script || ! pc || JS_IsNativeFrame(cx, fp) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
AddNewFrame( jsdc, jsdthreadstate, script, pc,
|
_addNewFrame( jsdc, jsdthreadstate, script, pc, fp );
|
||||||
JS_GetFrameObject(cx, fp),
|
|
||||||
JS_GetFrameThis(cx, fp), fp );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jsd_LockThreadsStates(jsdc);
|
/* if there is no stack, then this threadstate can not be constructed */
|
||||||
PR_APPEND_LINK(&jsdthreadstate->links, &jsdc->threadsStates);
|
if( 0 == jsdthreadstate->stackDepth )
|
||||||
jsd_UnlockThreadStates(jsdc);
|
{
|
||||||
|
free(jsdthreadstate);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSD_LOCK_THREADSTATES(jsdc);
|
||||||
|
JS_APPEND_LINK(&jsdthreadstate->links, &jsdc->threadsStates);
|
||||||
|
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||||
|
|
||||||
return jsdthreadstate;
|
return jsdthreadstate;
|
||||||
}
|
}
|
||||||
|
@ -125,50 +122,35 @@ void
|
||||||
jsd_DestroyThreadState(JSDContext* jsdc, JSDThreadState* jsdthreadstate)
|
jsd_DestroyThreadState(JSDContext* jsdc, JSDThreadState* jsdthreadstate)
|
||||||
{
|
{
|
||||||
JSDStackFrameInfo* jsdframe;
|
JSDStackFrameInfo* jsdframe;
|
||||||
PRCList* list;
|
JSCList* list;
|
||||||
int64 i;
|
|
||||||
|
|
||||||
#ifndef NSPR20
|
JSD_ASSERT_VALID_THREAD_STATE(jsdthreadstate);
|
||||||
LL_I2L(i,100);
|
JS_ASSERT(JSD_CURRENT_THREAD() == jsdthreadstate->thread);
|
||||||
#endif
|
|
||||||
|
|
||||||
/* we need to wait if someone else is using the threadstate */
|
|
||||||
|
|
||||||
jsd_LockThreadsStates(jsdc);
|
|
||||||
while( jsdthreadstate->wait )
|
|
||||||
{
|
|
||||||
jsd_UnlockThreadStates(jsdc);
|
|
||||||
#ifndef NSPR20
|
|
||||||
PR_Sleep(i);
|
|
||||||
#else
|
|
||||||
PR_Sleep(PR_MicrosecondsToInterval(100));
|
|
||||||
#endif
|
|
||||||
jsd_LockThreadsStates(jsdc);
|
|
||||||
}
|
|
||||||
PR_REMOVE_LINK(&jsdthreadstate->links);
|
|
||||||
jsd_UnlockThreadStates(jsdc);
|
|
||||||
|
|
||||||
|
JSD_LOCK_THREADSTATES(jsdc);
|
||||||
|
JS_REMOVE_LINK(&jsdthreadstate->links);
|
||||||
|
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||||
|
|
||||||
list = &jsdthreadstate->stack;
|
list = &jsdthreadstate->stack;
|
||||||
while( (JSDStackFrameInfo*)list != (jsdframe = (JSDStackFrameInfo*)list->next) )
|
while( (JSDStackFrameInfo*)list != (jsdframe = (JSDStackFrameInfo*)list->next) )
|
||||||
{
|
{
|
||||||
PR_REMOVE_LINK(&jsdframe->links);
|
JS_REMOVE_LINK(&jsdframe->links);
|
||||||
DestroyFrame(jsdframe);
|
_destroyFrame(jsdframe);
|
||||||
}
|
}
|
||||||
PR_FREEIF(jsdthreadstate);
|
free(jsdthreadstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
PRUintn
|
uintN
|
||||||
jsd_GetCountOfStackFrames(JSDContext* jsdc, JSDThreadState* jsdthreadstate)
|
jsd_GetCountOfStackFrames(JSDContext* jsdc, JSDThreadState* jsdthreadstate)
|
||||||
{
|
{
|
||||||
PRUintn count = 0;
|
uintN count = 0;
|
||||||
|
|
||||||
jsd_LockThreadsStates(jsdc);
|
JSD_LOCK_THREADSTATES(jsdc);
|
||||||
|
|
||||||
if( jsd_IsValidThreadState(jsdc, jsdthreadstate) )
|
if( jsd_IsValidThreadState(jsdc, jsdthreadstate) )
|
||||||
count = jsdthreadstate->stackDepth;
|
count = jsdthreadstate->stackDepth;
|
||||||
|
|
||||||
jsd_UnlockThreadStates(jsdc);
|
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
@ -178,12 +160,11 @@ jsd_GetStackFrame(JSDContext* jsdc, JSDThreadState* jsdthreadstate)
|
||||||
{
|
{
|
||||||
JSDStackFrameInfo* jsdframe = NULL;
|
JSDStackFrameInfo* jsdframe = NULL;
|
||||||
|
|
||||||
jsd_LockThreadsStates(jsdc);
|
JSD_LOCK_THREADSTATES(jsdc);
|
||||||
|
|
||||||
if( jsd_IsValidThreadState(jsdc, jsdthreadstate) )
|
if( jsd_IsValidThreadState(jsdc, jsdthreadstate) )
|
||||||
jsdframe = (JSDStackFrameInfo*) PR_LIST_HEAD(&jsdthreadstate->stack);
|
jsdframe = (JSDStackFrameInfo*) JS_LIST_HEAD(&jsdthreadstate->stack);
|
||||||
|
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||||
jsd_UnlockThreadStates(jsdc);
|
|
||||||
|
|
||||||
return jsdframe;
|
return jsdframe;
|
||||||
}
|
}
|
||||||
|
@ -195,13 +176,13 @@ jsd_GetCallingStackFrame(JSDContext* jsdc,
|
||||||
{
|
{
|
||||||
JSDStackFrameInfo* nextjsdframe = NULL;
|
JSDStackFrameInfo* nextjsdframe = NULL;
|
||||||
|
|
||||||
jsd_LockThreadsStates(jsdc);
|
JSD_LOCK_THREADSTATES(jsdc);
|
||||||
|
|
||||||
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
|
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
|
||||||
if( PR_LIST_HEAD(&jsdframe->links) != &jsdframe->jsdthreadstate->stack )
|
if( JS_LIST_HEAD(&jsdframe->links) != &jsdframe->jsdthreadstate->stack )
|
||||||
nextjsdframe = (JSDStackFrameInfo*) PR_LIST_HEAD(&jsdframe->links);
|
nextjsdframe = (JSDStackFrameInfo*) JS_LIST_HEAD(&jsdframe->links);
|
||||||
|
|
||||||
jsd_UnlockThreadStates(jsdc);
|
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||||
|
|
||||||
return nextjsdframe;
|
return nextjsdframe;
|
||||||
}
|
}
|
||||||
|
@ -213,58 +194,130 @@ jsd_GetScriptForStackFrame(JSDContext* jsdc,
|
||||||
{
|
{
|
||||||
JSDScript* jsdscript = NULL;
|
JSDScript* jsdscript = NULL;
|
||||||
|
|
||||||
jsd_LockThreadsStates(jsdc);
|
JSD_LOCK_THREADSTATES(jsdc);
|
||||||
|
|
||||||
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
|
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
|
||||||
jsdscript = jsdframe->jsdscript;
|
jsdscript = jsdframe->jsdscript;
|
||||||
|
|
||||||
jsd_UnlockThreadStates(jsdc);
|
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||||
|
|
||||||
return jsdscript;
|
return jsdscript;
|
||||||
}
|
}
|
||||||
|
|
||||||
prword_t
|
jsuword
|
||||||
jsd_GetPCForStackFrame(JSDContext* jsdc,
|
jsd_GetPCForStackFrame(JSDContext* jsdc,
|
||||||
JSDThreadState* jsdthreadstate,
|
JSDThreadState* jsdthreadstate,
|
||||||
JSDStackFrameInfo* jsdframe)
|
JSDStackFrameInfo* jsdframe)
|
||||||
{
|
{
|
||||||
prword_t pc = 0;
|
jsuword pc = 0;
|
||||||
|
|
||||||
jsd_LockThreadsStates(jsdc);
|
JSD_LOCK_THREADSTATES(jsdc);
|
||||||
|
|
||||||
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
|
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
|
||||||
pc = jsdframe->pc;
|
pc = jsdframe->pc;
|
||||||
|
|
||||||
jsd_UnlockThreadStates(jsdc);
|
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||||
|
|
||||||
return pc;
|
return pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSDValue*
|
||||||
|
jsd_GetCallObjectForStackFrame(JSDContext* jsdc,
|
||||||
|
JSDThreadState* jsdthreadstate,
|
||||||
|
JSDStackFrameInfo* jsdframe)
|
||||||
|
{
|
||||||
|
JSObject* obj;
|
||||||
|
JSDValue* jsdval = NULL;
|
||||||
|
|
||||||
|
JSD_LOCK_THREADSTATES(jsdc);
|
||||||
|
|
||||||
|
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
|
||||||
|
{
|
||||||
|
obj = JS_GetFrameCallObject(jsdthreadstate->context, jsdframe->fp);
|
||||||
|
if(obj)
|
||||||
|
jsdval = JSD_NewValue(jsdc, OBJECT_TO_JSVAL(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||||
|
|
||||||
|
return jsdval;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSDValue*
|
||||||
|
jsd_GetScopeChainForStackFrame(JSDContext* jsdc,
|
||||||
|
JSDThreadState* jsdthreadstate,
|
||||||
|
JSDStackFrameInfo* jsdframe)
|
||||||
|
{
|
||||||
|
JSObject* obj;
|
||||||
|
JSDValue* jsdval = NULL;
|
||||||
|
|
||||||
|
JSD_LOCK_THREADSTATES(jsdc);
|
||||||
|
|
||||||
|
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
|
||||||
|
{
|
||||||
|
obj = JS_GetFrameScopeChain(jsdthreadstate->context, jsdframe->fp);
|
||||||
|
if(obj)
|
||||||
|
jsdval = JSD_NewValue(jsdc, OBJECT_TO_JSVAL(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||||
|
|
||||||
|
return jsdval;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSDValue*
|
||||||
|
jsd_GetThisForStackFrame(JSDContext* jsdc,
|
||||||
|
JSDThreadState* jsdthreadstate,
|
||||||
|
JSDStackFrameInfo* jsdframe)
|
||||||
|
{
|
||||||
|
JSObject* obj;
|
||||||
|
JSDValue* jsdval = NULL;
|
||||||
|
|
||||||
|
JSD_LOCK_THREADSTATES(jsdc);
|
||||||
|
|
||||||
|
if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
|
||||||
|
{
|
||||||
|
obj = JS_GetFrameThis(jsdthreadstate->context, jsdframe->fp);
|
||||||
|
if(obj)
|
||||||
|
jsdval = JSD_NewValue(jsdc, OBJECT_TO_JSVAL(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||||
|
|
||||||
|
return jsdval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
JSBool
|
JSBool
|
||||||
jsd_EvaluateScriptInStackFrame(JSDContext* jsdc,
|
jsd_EvaluateScriptInStackFrame(JSDContext* jsdc,
|
||||||
JSDThreadState* jsdthreadstate,
|
JSDThreadState* jsdthreadstate,
|
||||||
JSDStackFrameInfo* jsdframe,
|
JSDStackFrameInfo* jsdframe,
|
||||||
const char *bytes, PRUintn length,
|
const char *bytes, uintN length,
|
||||||
const char *filename, PRUintn lineno, jsval *rval)
|
const char *filename, uintN lineno, jsval *rval)
|
||||||
{
|
{
|
||||||
JSBool retval;
|
JSBool retval;
|
||||||
|
JSBool valid;
|
||||||
|
JSExceptionState* exceptionState;
|
||||||
|
JSContext* cx;
|
||||||
|
|
||||||
jsd_LockThreadsStates(jsdc);
|
JS_ASSERT(JSD_CURRENT_THREAD() == jsdthreadstate->thread);
|
||||||
|
|
||||||
if( ! jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
|
JSD_LOCK_THREADSTATES(jsdc);
|
||||||
{
|
valid = jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe);
|
||||||
jsd_UnlockThreadStates(jsdc);
|
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||||
|
|
||||||
|
if( ! valid )
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
|
||||||
jsdthreadstate->wait++ ;
|
|
||||||
jsd_UnlockThreadStates(jsdc);
|
|
||||||
|
|
||||||
retval = JS_EvaluateInStackFrame(jsdthreadstate->context, jsdframe->fp,
|
cx = jsdthreadstate->context;
|
||||||
bytes, length, filename, lineno, rval);
|
JS_ASSERT(cx);
|
||||||
|
|
||||||
jsd_LockThreadsStates(jsdc);
|
exceptionState = JS_SaveExceptionState(cx);
|
||||||
jsdthreadstate->wait-- ;
|
jsd_StartingEvalUsingFilename(jsdc, filename);
|
||||||
jsd_UnlockThreadStates(jsdc);
|
retval = JS_EvaluateInStackFrame(cx, jsdframe->fp, bytes, length,
|
||||||
|
filename, lineno, rval);
|
||||||
|
jsd_FinishedEvalUsingFilename(jsdc, filename);
|
||||||
|
JS_RestoreExceptionState(cx, exceptionState);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -275,72 +328,37 @@ jsd_ValToStringInStackFrame(JSDContext* jsdc,
|
||||||
JSDStackFrameInfo* jsdframe,
|
JSDStackFrameInfo* jsdframe,
|
||||||
jsval val)
|
jsval val)
|
||||||
{
|
{
|
||||||
JSString* jsstr = NULL;
|
JSBool valid;
|
||||||
|
JSString* retval;
|
||||||
|
JSExceptionState* exceptionState;
|
||||||
|
JSContext* cx;
|
||||||
|
|
||||||
jsd_LockThreadsStates(jsdc);
|
JSD_LOCK_THREADSTATES(jsdc);
|
||||||
|
valid = jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe);
|
||||||
|
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||||
|
|
||||||
if( ! jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
|
if( ! valid )
|
||||||
{
|
|
||||||
jsd_UnlockThreadStates(jsdc);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
jsdthreadstate->wait++ ;
|
|
||||||
jsd_UnlockThreadStates(jsdc);
|
|
||||||
|
|
||||||
jsstr = JS_ValueToString(jsdthreadstate->context, val);
|
cx = jsdthreadstate->context;
|
||||||
|
JS_ASSERT(cx);
|
||||||
|
|
||||||
jsd_LockThreadsStates(jsdc);
|
exceptionState = JS_SaveExceptionState(cx);
|
||||||
jsdthreadstate->wait-- ;
|
retval = JS_ValueToString(cx, val);
|
||||||
jsd_UnlockThreadStates(jsdc);
|
JS_RestoreExceptionState(cx, exceptionState);
|
||||||
|
|
||||||
return jsstr;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************/
|
|
||||||
|
|
||||||
#ifndef JSD_SIMULATION
|
|
||||||
static PRMonitor *jsd_threadstate_mon = NULL;
|
|
||||||
#endif /* JSD_SIMULATION */
|
|
||||||
|
|
||||||
void
|
|
||||||
jsd_LockThreadsStates(JSDContext* jsdc)
|
|
||||||
{
|
|
||||||
#ifndef JSD_SIMULATION
|
|
||||||
if (jsd_threadstate_mon == NULL)
|
|
||||||
jsd_threadstate_mon = PR_NewNamedMonitor("jsd-threadstate-monitor");
|
|
||||||
|
|
||||||
PR_EnterMonitor(jsd_threadstate_mon);
|
|
||||||
#endif /* JSD_SIMULATION */
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
jsd_UnlockThreadStates(JSDContext* jsdc)
|
|
||||||
{
|
|
||||||
#ifndef JSD_SIMULATION
|
|
||||||
PR_ExitMonitor(jsd_threadstate_mon);
|
|
||||||
#endif /* JSD_SIMULATION */
|
|
||||||
}
|
|
||||||
|
|
||||||
JSBool
|
|
||||||
jsd_ThreadStatesIsLocked(JSDContext* jsdc)
|
|
||||||
{
|
|
||||||
#ifndef JSD_SIMULATION
|
|
||||||
return jsd_threadstate_mon && PR_InMonitor(jsd_threadstate_mon);
|
|
||||||
#else
|
|
||||||
return JS_TRUE;
|
|
||||||
#endif /* JSD_SIMULATION */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JSBool
|
JSBool
|
||||||
jsd_IsValidThreadState(JSDContext* jsdc,
|
jsd_IsValidThreadState(JSDContext* jsdc,
|
||||||
JSDThreadState* jsdthreadstate )
|
JSDThreadState* jsdthreadstate)
|
||||||
{
|
{
|
||||||
JSDThreadState *cur;
|
JSDThreadState *cur;
|
||||||
|
|
||||||
PR_ASSERT( jsd_ThreadStatesIsLocked(jsdc) );
|
JS_ASSERT( JSD_THREADSTATES_LOCKED(jsdc) );
|
||||||
|
|
||||||
for (cur = (JSDThreadState*)jsdc->threadsStates.next;
|
for( cur = (JSDThreadState*)jsdc->threadsStates.next;
|
||||||
cur != (JSDThreadState*)&jsdc->threadsStates;
|
cur != (JSDThreadState*)&jsdc->threadsStates;
|
||||||
cur = (JSDThreadState*)cur->links.next )
|
cur = (JSDThreadState*)cur->links.next )
|
||||||
{
|
{
|
||||||
|
@ -353,9 +371,9 @@ jsd_IsValidThreadState(JSDContext* jsdc,
|
||||||
JSBool
|
JSBool
|
||||||
jsd_IsValidFrameInThreadState(JSDContext* jsdc,
|
jsd_IsValidFrameInThreadState(JSDContext* jsdc,
|
||||||
JSDThreadState* jsdthreadstate,
|
JSDThreadState* jsdthreadstate,
|
||||||
JSDStackFrameInfo* jsdframe )
|
JSDStackFrameInfo* jsdframe)
|
||||||
{
|
{
|
||||||
PR_ASSERT( jsd_ThreadStatesIsLocked(jsdc) );
|
JS_ASSERT(JSD_THREADSTATES_LOCKED(jsdc));
|
||||||
|
|
||||||
if( ! jsd_IsValidThreadState(jsdc, jsdthreadstate) )
|
if( ! jsd_IsValidThreadState(jsdc, jsdthreadstate) )
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
@ -367,3 +385,45 @@ jsd_IsValidFrameInThreadState(JSDContext* jsdc,
|
||||||
|
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static JSContext*
|
||||||
|
_getContextForThreadState(JSDContext* jsdc, JSDThreadState* jsdthreadstate)
|
||||||
|
{
|
||||||
|
JSBool valid;
|
||||||
|
JSD_LOCK_THREADSTATES(jsdc);
|
||||||
|
valid = jsd_IsValidThreadState(jsdc, jsdthreadstate);
|
||||||
|
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||||
|
if( valid )
|
||||||
|
return jsdthreadstate->context;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSDValue*
|
||||||
|
jsd_GetException(JSDContext* jsdc, JSDThreadState* jsdthreadstate)
|
||||||
|
{
|
||||||
|
JSContext* cx;
|
||||||
|
jsval val;
|
||||||
|
|
||||||
|
if(!(cx = _getContextForThreadState(jsdc, jsdthreadstate)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if(JS_GetPendingException(cx, &val))
|
||||||
|
return jsd_NewValue(jsdc, val);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
jsd_SetException(JSDContext* jsdc, JSDThreadState* jsdthreadstate,
|
||||||
|
JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
JSContext* cx;
|
||||||
|
|
||||||
|
if(!(cx = _getContextForThreadState(jsdc, jsdthreadstate)))
|
||||||
|
return JS_FALSE;
|
||||||
|
|
||||||
|
if(jsdval)
|
||||||
|
JS_SetPendingException(cx, JSD_GetValueWrappedJSVal(jsdc, jsdval));
|
||||||
|
else
|
||||||
|
JS_ClearPendingException(cx);
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
|
@ -0,0 +1,116 @@
|
||||||
|
/* -*- 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* JavaScript Debugging support - Stepping support
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "jsd.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #define JSD_TRACE 1
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef JSD_TRACE
|
||||||
|
|
||||||
|
static char*
|
||||||
|
_indentSpaces(int i)
|
||||||
|
{
|
||||||
|
#define MAX_INDENT 63
|
||||||
|
static char* p = NULL;
|
||||||
|
if(!p)
|
||||||
|
{
|
||||||
|
p = calloc(1, MAX_INDENT+1);
|
||||||
|
if(!p) return "";
|
||||||
|
memset(p, ' ', MAX_INDENT);
|
||||||
|
}
|
||||||
|
if(i > MAX_INDENT) return p;
|
||||||
|
return p + MAX_INDENT-i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_interpreterTrace(JSDContext* jsdc, JSContext *cx, JSStackFrame *fp,
|
||||||
|
JSBool before, JSBool *ok)
|
||||||
|
{
|
||||||
|
JSDScript* jsdscript = NULL;
|
||||||
|
JSScript * script;
|
||||||
|
static indent = 0;
|
||||||
|
char* buf;
|
||||||
|
const char* funName = NULL;
|
||||||
|
|
||||||
|
script = JS_GetFrameScript(cx, fp);
|
||||||
|
if(script)
|
||||||
|
{
|
||||||
|
JSD_LOCK_SCRIPTS(jsdc);
|
||||||
|
jsdscript = jsd_FindJSDScript(jsdc, script);
|
||||||
|
JSD_UNLOCK_SCRIPTS(jsdc);
|
||||||
|
if(jsdscript)
|
||||||
|
funName = JSD_GetScriptFunctionName(jsdc, jsdscript);
|
||||||
|
}
|
||||||
|
if(!funName)
|
||||||
|
funName = "TOP_LEVEL";
|
||||||
|
|
||||||
|
if(before)
|
||||||
|
{
|
||||||
|
buf = JS_smprintf("%sentering %s %s this: %0x\n",
|
||||||
|
_indentSpaces(indent++),
|
||||||
|
funName,
|
||||||
|
JS_IsContructorFrame(cx, fp) ? "constructing":"",
|
||||||
|
(int)JS_GetFrameThis(cx, fp));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buf = JS_smprintf("%sleaving %s\n",
|
||||||
|
_indentSpaces(--indent),
|
||||||
|
funName);
|
||||||
|
}
|
||||||
|
JS_ASSERT(indent >= 0);
|
||||||
|
|
||||||
|
if(!buf)
|
||||||
|
return;
|
||||||
|
|
||||||
|
printf(buf);
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void * JS_DLL_CALLBACK
|
||||||
|
jsd_InterpreterHook(JSContext *cx, JSStackFrame *fp, JSBool before,
|
||||||
|
JSBool *ok, void *closure)
|
||||||
|
{
|
||||||
|
JSDContext* jsdc = (JSDContext*) closure;
|
||||||
|
|
||||||
|
if( ! jsdc || ! jsdc->inited )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if(before && JS_IsContructorFrame(cx, fp))
|
||||||
|
jsd_Constructing(jsdc, cx, JS_GetFrameThis(cx, fp), fp);
|
||||||
|
|
||||||
|
#ifdef JSD_TRACE
|
||||||
|
_interpreterTrace(jsdc, cx, fp, before, ok);
|
||||||
|
return closure;
|
||||||
|
#else
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* use this before calling any hook...
|
||||||
|
* if( JSD_IS_DANGEROUS_THREAD(jsdc) )
|
||||||
|
* return NULL;
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
/* -*- 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
|
* 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
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||||
|
@ -17,182 +17,149 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** JavaScript Debugger Navigator API - Source Text functions
|
* JavaScript Debugging support - Source Text functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "jsd.h"
|
#include "jsd.h"
|
||||||
#ifdef NSPR20
|
|
||||||
#ifdef XP_MAC
|
|
||||||
#include "prpriv.h"
|
|
||||||
#else
|
|
||||||
#include "private/prpriv.h"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* XXX convert this and jsd_conv so that all accumulation of text done here
|
|
||||||
* Also, use handle oriented alloc for Win16 64k limit problem
|
|
||||||
*/
|
|
||||||
|
|
||||||
PRCList jsd_source_list = PR_INIT_STATIC_CLIST(&jsd_source_list);
|
|
||||||
PRCList jsd_removed_source_list = PR_INIT_STATIC_CLIST(&jsd_removed_source_list);
|
|
||||||
|
|
||||||
/***************************************************************************/
|
|
||||||
/*
|
|
||||||
* typedef enum
|
|
||||||
* {
|
|
||||||
* JSD_SOURCE_INITED,
|
|
||||||
* JSD_SOURCE_PARTIAL,
|
|
||||||
* JSD_SOURCE_COMPLETED,
|
|
||||||
* JSD_SOURCE_ABORTED,
|
|
||||||
* JSD_SOURCE_FAILED
|
|
||||||
*
|
|
||||||
* } JSDSourceStatus;
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void JSD_ASSERT_VALID_SOURCE_TEXT( JSDSourceText* jsdsrc )
|
void JSD_ASSERT_VALID_SOURCE_TEXT(JSDSourceText* jsdsrc)
|
||||||
{
|
{
|
||||||
PR_ASSERT( jsdsrc );
|
JS_ASSERT(jsdsrc);
|
||||||
PR_ASSERT( jsdsrc->url );
|
JS_ASSERT(jsdsrc->url);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
/* XXX add serial number instead of dirty */
|
|
||||||
/* XXX add notification */
|
/* XXX add notification */
|
||||||
|
|
||||||
static PRUintn g_alterCount = 1;
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ClearText( JSDContext* jsdc, JSDSourceText* jsdsrc )
|
_clearText(JSDContext* jsdc, JSDSourceText* jsdsrc)
|
||||||
{
|
{
|
||||||
if( jsdsrc->text )
|
if( jsdsrc->text )
|
||||||
MY_XP_HUGE_FREE(jsdsrc->text);
|
free(jsdsrc->text);
|
||||||
jsdsrc->text = NULL;
|
jsdsrc->text = NULL;
|
||||||
jsdsrc->textLength = 0;
|
jsdsrc->textLength = 0;
|
||||||
jsdsrc->textSpace = 0;
|
jsdsrc->textSpace = 0;
|
||||||
jsdsrc->status = JSD_SOURCE_CLEARED;
|
jsdsrc->status = JSD_SOURCE_CLEARED;
|
||||||
jsdsrc->dirty = JS_TRUE;
|
jsdsrc->dirty = JS_TRUE;
|
||||||
jsdsrc->alterCount = g_alterCount++ ;
|
jsdsrc->alterCount = jsdc->sourceAlterCount++ ;
|
||||||
|
jsdsrc->doingEval = JS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSBool
|
static JSBool
|
||||||
AppendText( JSDContext* jsdc, JSDSourceText* jsdsrc,
|
_appendText(JSDContext* jsdc, JSDSourceText* jsdsrc,
|
||||||
const char* text, size_t length )
|
const char* text, size_t length)
|
||||||
{
|
{
|
||||||
#define MEMBUF_GROW 1000
|
#define MEMBUF_GROW 1000
|
||||||
|
|
||||||
PRUintn neededSize = jsdsrc->textLength + length;
|
uintN neededSize = jsdsrc->textLength + length;
|
||||||
|
|
||||||
if( neededSize > jsdsrc->textSpace )
|
if( neededSize > jsdsrc->textSpace )
|
||||||
{
|
{
|
||||||
MY_XP_HUGE_CHAR_PTR pBuf;
|
char* newBuf;
|
||||||
PRUintn iNewSize;
|
uintN iNewSize;
|
||||||
|
|
||||||
/* if this is the first alloc, the req might be all that's needed*/
|
/* if this is the first alloc, the req might be all that's needed*/
|
||||||
if( ! jsdsrc->textSpace )
|
if( ! jsdsrc->textSpace )
|
||||||
iNewSize = length;
|
iNewSize = length;
|
||||||
else
|
else
|
||||||
iNewSize = (neededSize * 5 / 4) + MEMBUF_GROW;
|
iNewSize = (neededSize * 5 / 4) + MEMBUF_GROW;
|
||||||
|
|
||||||
pBuf = (MY_XP_HUGE_CHAR_PTR) MY_XP_HUGE_ALLOC(iNewSize);
|
newBuf = (char*) realloc(jsdsrc->text, iNewSize);
|
||||||
if( pBuf )
|
if( ! newBuf )
|
||||||
{
|
{
|
||||||
if( jsdsrc->text )
|
/* try again with the minimal size really asked for */
|
||||||
|
iNewSize = neededSize;
|
||||||
|
newBuf = (char*) realloc(jsdsrc->text, iNewSize);
|
||||||
|
if( ! newBuf )
|
||||||
{
|
{
|
||||||
MY_XP_HUGE_MEMCPY(pBuf, jsdsrc->text, jsdsrc->textLength);
|
/* out of memory */
|
||||||
MY_XP_HUGE_FREE(jsdsrc->text);
|
_clearText( jsdc, jsdsrc );
|
||||||
|
jsdsrc->status = JSD_SOURCE_FAILED;
|
||||||
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
jsdsrc->text = pBuf;
|
|
||||||
jsdsrc->textSpace = iNewSize;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* LTNOTE: throw an out of memory exception */
|
|
||||||
ClearText( jsdc, jsdsrc );
|
|
||||||
jsdsrc->status = JSD_SOURCE_FAILED;
|
|
||||||
return JS_FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jsdsrc->text = newBuf;
|
||||||
|
jsdsrc->textSpace = iNewSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
MY_XP_HUGE_MEMCPY( &jsdsrc->text[jsdsrc->textLength], text, length );
|
memcpy(jsdsrc->text + jsdsrc->textLength, text, length);
|
||||||
jsdsrc->textLength += length;
|
jsdsrc->textLength += length;
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSDSourceText*
|
static JSDSourceText*
|
||||||
NewSource( JSDContext* jsdc, const char* url )
|
_newSource(JSDContext* jsdc, const char* url)
|
||||||
{
|
{
|
||||||
JSDSourceText* jsdsrc = PR_NEWZAP(JSDSourceText);
|
JSDSourceText* jsdsrc = (JSDSourceText*)calloc(1,sizeof(JSDSourceText));
|
||||||
if( ! jsdsrc )
|
if( ! jsdsrc )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
jsdsrc->url = (char*) url; /* already a copy */
|
jsdsrc->url = (char*) url; /* already a copy */
|
||||||
jsdsrc->status = JSD_SOURCE_INITED;
|
jsdsrc->status = JSD_SOURCE_INITED;
|
||||||
jsdsrc->dirty = JS_TRUE;
|
jsdsrc->dirty = JS_TRUE;
|
||||||
jsdsrc->alterCount = g_alterCount++ ;
|
jsdsrc->alterCount = jsdc->sourceAlterCount++ ;
|
||||||
|
|
||||||
return jsdsrc;
|
return jsdsrc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
DestroySource( JSDContext* jsdc, JSDSourceText* jsdsrc )
|
_destroySource(JSDContext* jsdc, JSDSourceText* jsdsrc)
|
||||||
{
|
{
|
||||||
PR_ASSERT( NULL == jsdsrc->text ); /* must ClearText() first */
|
JS_ASSERT(NULL == jsdsrc->text); /* must _clearText() first */
|
||||||
MY_XP_FREE(jsdsrc->url);
|
free(jsdsrc->url);
|
||||||
MY_XP_FREE(jsdsrc);
|
free(jsdsrc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
RemoveSource( JSDContext* jsdc, JSDSourceText* jsdsrc )
|
_removeSource(JSDContext* jsdc, JSDSourceText* jsdsrc)
|
||||||
{
|
{
|
||||||
PR_REMOVE_LINK(&jsdsrc->links);
|
JS_REMOVE_LINK(&jsdsrc->links);
|
||||||
ClearText( jsdc, jsdsrc );
|
_clearText(jsdc, jsdsrc);
|
||||||
DestroySource( jsdc, jsdsrc );
|
_destroySource(jsdc, jsdsrc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSDSourceText*
|
static JSDSourceText*
|
||||||
AddSource( JSDContext* jsdc, const char* url )
|
_addSource(JSDContext* jsdc, const char* url)
|
||||||
{
|
{
|
||||||
JSDSourceText* jsdsrc = NewSource( jsdc, url );
|
JSDSourceText* jsdsrc = _newSource(jsdc, url);
|
||||||
if( ! jsdsrc )
|
if( ! jsdsrc )
|
||||||
return NULL;
|
return NULL;
|
||||||
PR_INSERT_LINK(&jsdsrc->links, &jsd_source_list);
|
JS_INSERT_LINK(&jsdsrc->links, &jsdc->sources);
|
||||||
return jsdsrc;
|
return jsdsrc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
MoveSourceToFront( JSDContext* jsdc, JSDSourceText* jsdsrc )
|
_moveSourceToFront(JSDContext* jsdc, JSDSourceText* jsdsrc)
|
||||||
{
|
{
|
||||||
PR_REMOVE_LINK(&jsdsrc->links);
|
JS_REMOVE_LINK(&jsdsrc->links);
|
||||||
PR_INSERT_LINK(&jsdsrc->links, &jsd_source_list);
|
JS_INSERT_LINK(&jsdsrc->links, &jsdc->sources);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
MoveSourceToRemovedList( JSDContext* jsdc, JSDSourceText* jsdsrc )
|
_moveSourceToRemovedList(JSDContext* jsdc, JSDSourceText* jsdsrc)
|
||||||
{
|
{
|
||||||
ClearText(jsdc, jsdsrc);
|
_clearText(jsdc, jsdsrc);
|
||||||
PR_REMOVE_LINK(&jsdsrc->links);
|
JS_REMOVE_LINK(&jsdsrc->links);
|
||||||
PR_INSERT_LINK(&jsdsrc->links, &jsd_removed_source_list);
|
JS_INSERT_LINK(&jsdsrc->links, &jsdc->removedSources);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
RemoveSourceFromRemovedList( JSDContext* jsdc, JSDSourceText* jsdsrc )
|
_removeSourceFromRemovedList( JSDContext* jsdc, JSDSourceText* jsdsrc )
|
||||||
{
|
{
|
||||||
PR_REMOVE_LINK(&jsdsrc->links);
|
JS_REMOVE_LINK(&jsdsrc->links);
|
||||||
DestroySource( jsdc, jsdsrc );
|
_destroySource( jsdc, jsdsrc );
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSBool
|
static JSBool
|
||||||
IsSourceInSourceList( JSDContext* jsdc, JSDSourceText* jsdsrcToFind )
|
_isSourceInSourceList(JSDContext* jsdc, JSDSourceText* jsdsrcToFind)
|
||||||
{
|
{
|
||||||
JSDSourceText *jsdsrc;
|
JSDSourceText *jsdsrc;
|
||||||
|
|
||||||
for (jsdsrc = (JSDSourceText*)jsd_source_list.next;
|
for( jsdsrc = (JSDSourceText*)jsdc->sources.next;
|
||||||
jsdsrc != (JSDSourceText*)&jsd_source_list;
|
jsdsrc != (JSDSourceText*)&jsdc->sources;
|
||||||
jsdsrc = (JSDSourceText*)jsdsrc->links.next )
|
jsdsrc = (JSDSourceText*)jsdsrc->links.next )
|
||||||
{
|
{
|
||||||
if( jsdsrc == jsdsrcToFind )
|
if( jsdsrc == jsdsrcToFind )
|
||||||
|
@ -201,26 +168,26 @@ IsSourceInSourceList( JSDContext* jsdc, JSDSourceText* jsdsrcToFind )
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* compare strings in a case insensitive manner with a length limit
|
/* compare strings in a case insensitive manner with a length limit
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
strncasecomp (const char* one, const char * two, int n)
|
strncasecomp (const char* one, const char * two, int n)
|
||||||
{
|
{
|
||||||
const char *pA;
|
const char *pA;
|
||||||
const char *pB;
|
const char *pB;
|
||||||
|
|
||||||
for(pA=one, pB=two;; pA++, pB++)
|
for(pA=one, pB=two;; pA++, pB++)
|
||||||
{
|
{
|
||||||
int tmp;
|
int tmp;
|
||||||
if (pA == one+n)
|
if (pA == one+n)
|
||||||
return 0;
|
return 0;
|
||||||
if (!(*pA && *pB))
|
if (!(*pA && *pB))
|
||||||
return *pA - *pB;
|
return *pA - *pB;
|
||||||
tmp = MY_XP_TO_LOWER(*pA) - MY_XP_TO_LOWER(*pB);
|
tmp = tolower(*pA) - tolower(*pB);
|
||||||
if (tmp)
|
if (tmp)
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static char file_url_prefix[] = "file:";
|
static char file_url_prefix[] = "file:";
|
||||||
|
@ -234,63 +201,40 @@ jsd_BuildNormalizedURL( const char* url_string )
|
||||||
if( ! url_string )
|
if( ! url_string )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!MY_XP_STRNCASECMP(url_string, file_url_prefix, FILE_URL_PREFIX_LEN) &&
|
if (!strncasecomp(url_string, file_url_prefix, FILE_URL_PREFIX_LEN) &&
|
||||||
url_string[FILE_URL_PREFIX_LEN + 0] == '/' &&
|
url_string[FILE_URL_PREFIX_LEN + 0] == '/' &&
|
||||||
url_string[FILE_URL_PREFIX_LEN + 1] == '/') {
|
url_string[FILE_URL_PREFIX_LEN + 1] == '/') {
|
||||||
new_url_string = PR_smprintf("%s%s",
|
new_url_string = JS_smprintf("%s%s",
|
||||||
file_url_prefix,
|
file_url_prefix,
|
||||||
url_string + FILE_URL_PREFIX_LEN + 2);
|
url_string + FILE_URL_PREFIX_LEN + 2);
|
||||||
} else {
|
} else {
|
||||||
new_url_string = MY_XP_STRDUP(url_string);
|
new_url_string = strdup(url_string);
|
||||||
}
|
}
|
||||||
return new_url_string;
|
return new_url_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
#ifndef JSD_SIMULATION
|
|
||||||
static PRMonitor *jsd_text_mon = NULL;
|
|
||||||
#endif /* JSD_SIMULATION */
|
|
||||||
|
|
||||||
void
|
|
||||||
jsd_LockSourceTextSubsystem(JSDContext* jsdc)
|
|
||||||
{
|
|
||||||
#ifndef JSD_SIMULATION
|
|
||||||
if (jsd_text_mon == NULL)
|
|
||||||
jsd_text_mon = PR_NewNamedMonitor("jsd-text-monitor");
|
|
||||||
|
|
||||||
PR_EnterMonitor(jsd_text_mon);
|
|
||||||
#endif /* JSD_SIMULATION */
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
jsd_UnlockSourceTextSubsystem(JSDContext* jsdc)
|
|
||||||
{
|
|
||||||
#ifndef JSD_SIMULATION
|
|
||||||
PR_ExitMonitor(jsd_text_mon);
|
|
||||||
#endif /* JSD_SIMULATION */
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
jsd_DestroyAllSources( JSDContext* jsdc )
|
jsd_DestroyAllSources( JSDContext* jsdc )
|
||||||
{
|
{
|
||||||
JSDSourceText *jsdsrc;
|
JSDSourceText *jsdsrc;
|
||||||
JSDSourceText *next;
|
JSDSourceText *next;
|
||||||
|
|
||||||
for (jsdsrc = (JSDSourceText*)jsd_source_list.next;
|
for( jsdsrc = (JSDSourceText*)jsdc->sources.next;
|
||||||
jsdsrc != (JSDSourceText*)&jsd_source_list;
|
jsdsrc != (JSDSourceText*)&jsdc->sources;
|
||||||
jsdsrc = next)
|
jsdsrc = next )
|
||||||
{
|
{
|
||||||
next = (JSDSourceText*)jsdsrc->links.next;
|
next = (JSDSourceText*)jsdsrc->links.next;
|
||||||
RemoveSource( jsdc, jsdsrc );
|
_removeSource( jsdc, jsdsrc );
|
||||||
}
|
}
|
||||||
|
|
||||||
for (jsdsrc = (JSDSourceText*)jsd_removed_source_list.next;
|
for( jsdsrc = (JSDSourceText*)jsdc->removedSources.next;
|
||||||
jsdsrc != (JSDSourceText*)&jsd_removed_source_list;
|
jsdsrc != (JSDSourceText*)&jsdc->removedSources;
|
||||||
jsdsrc = next)
|
jsdsrc = next )
|
||||||
{
|
{
|
||||||
next = (JSDSourceText*)jsdsrc->links.next;
|
next = (JSDSourceText*)jsdsrc->links.next;
|
||||||
RemoveSourceFromRemovedList( jsdc, jsdsrc );
|
_removeSourceFromRemovedList( jsdc, jsdsrc );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -300,9 +244,9 @@ jsd_IterateSources(JSDContext* jsdc, JSDSourceText **iterp)
|
||||||
{
|
{
|
||||||
JSDSourceText *jsdsrc = *iterp;
|
JSDSourceText *jsdsrc = *iterp;
|
||||||
|
|
||||||
if (!jsdsrc)
|
if( !jsdsrc )
|
||||||
jsdsrc = (JSDSourceText *)jsd_source_list.next;
|
jsdsrc = (JSDSourceText *)jsdc->sources.next;
|
||||||
if (jsdsrc == (JSDSourceText *)&jsd_source_list)
|
if( jsdsrc == (JSDSourceText *)&jsdc->sources )
|
||||||
return NULL;
|
return NULL;
|
||||||
*iterp = (JSDSourceText *)jsdsrc->links.next;
|
*iterp = (JSDSourceText *)jsdsrc->links.next;
|
||||||
return jsdsrc;
|
return jsdsrc;
|
||||||
|
@ -313,10 +257,11 @@ jsd_FindSourceForURL(JSDContext* jsdc, const char* url)
|
||||||
{
|
{
|
||||||
JSDSourceText *jsdsrc;
|
JSDSourceText *jsdsrc;
|
||||||
|
|
||||||
for (jsdsrc = (JSDSourceText *)jsd_source_list.next;
|
for( jsdsrc = (JSDSourceText *)jsdc->sources.next;
|
||||||
jsdsrc != (JSDSourceText *)&jsd_source_list;
|
jsdsrc != (JSDSourceText *)&jsdc->sources;
|
||||||
jsdsrc = (JSDSourceText *)jsdsrc->links.next) {
|
jsdsrc = (JSDSourceText *)jsdsrc->links.next )
|
||||||
if (0 == strcmp(jsdsrc->url, url))
|
{
|
||||||
|
if( 0 == strcmp(jsdsrc->url, url) )
|
||||||
return jsdsrc;
|
return jsdsrc;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -330,7 +275,7 @@ jsd_GetSourceURL(JSDContext* jsdc, JSDSourceText* jsdsrc)
|
||||||
|
|
||||||
JSBool
|
JSBool
|
||||||
jsd_GetSourceText(JSDContext* jsdc, JSDSourceText* jsdsrc,
|
jsd_GetSourceText(JSDContext* jsdc, JSDSourceText* jsdsrc,
|
||||||
const char** ppBuf, int* pLen )
|
const char** ppBuf, intN* pLen )
|
||||||
{
|
{
|
||||||
*ppBuf = jsdsrc->text;
|
*ppBuf = jsdsrc->text;
|
||||||
*pLen = jsdsrc->textLength;
|
*pLen = jsdsrc->textLength;
|
||||||
|
@ -343,7 +288,7 @@ jsd_ClearSourceText(JSDContext* jsdc, JSDSourceText* jsdsrc)
|
||||||
if( JSD_SOURCE_INITED != jsdsrc->status &&
|
if( JSD_SOURCE_INITED != jsdsrc->status &&
|
||||||
JSD_SOURCE_PARTIAL != jsdsrc->status )
|
JSD_SOURCE_PARTIAL != jsdsrc->status )
|
||||||
{
|
{
|
||||||
ClearText(jsdc, jsdsrc);
|
_clearText(jsdc, jsdsrc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,16 +310,16 @@ jsd_SetSourceDirty(JSDContext* jsdc, JSDSourceText* jsdsrc, JSBool dirty)
|
||||||
jsdsrc->dirty = dirty;
|
jsdsrc->dirty = dirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRUintn
|
uintN
|
||||||
jsd_GetSourceAlterCount(JSDContext* jsdc, JSDSourceText* jsdsrc)
|
jsd_GetSourceAlterCount(JSDContext* jsdc, JSDSourceText* jsdsrc)
|
||||||
{
|
{
|
||||||
return jsdsrc->alterCount;
|
return jsdsrc->alterCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRUintn
|
uintN
|
||||||
jsd_IncrementSourceAlterCount(JSDContext* jsdc, JSDSourceText* jsdsrc)
|
jsd_IncrementSourceAlterCount(JSDContext* jsdc, JSDSourceText* jsdsrc)
|
||||||
{
|
{
|
||||||
return ++jsdsrc->alterCount;
|
return jsdsrc->alterCount = jsdc->sourceAlterCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
@ -415,20 +360,35 @@ jsd_NewSourceText(JSDContext* jsdc, const char* url)
|
||||||
JSDSourceText* jsdsrc;
|
JSDSourceText* jsdsrc;
|
||||||
const char* new_url_string;
|
const char* new_url_string;
|
||||||
|
|
||||||
jsd_LockSourceTextSubsystem(jsdc);
|
JSD_LOCK_SOURCE_TEXT(jsdc);
|
||||||
|
|
||||||
|
#ifdef LIVEWIRE
|
||||||
|
new_url_string = url; /* we take ownership of alloc'd string */
|
||||||
|
#else
|
||||||
new_url_string = jsd_BuildNormalizedURL(url);
|
new_url_string = jsd_BuildNormalizedURL(url);
|
||||||
|
#endif
|
||||||
if( ! new_url_string )
|
if( ! new_url_string )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
jsdsrc = jsd_FindSourceForURL(jsdc, new_url_string);
|
jsdsrc = jsd_FindSourceForURL(jsdc, new_url_string);
|
||||||
|
|
||||||
if( jsdsrc )
|
if( jsdsrc )
|
||||||
MoveSourceToRemovedList(jsdc, jsdsrc);
|
{
|
||||||
|
if( jsdsrc->doingEval )
|
||||||
|
{
|
||||||
|
#ifdef LIVEWIRE
|
||||||
|
free((char*)new_url_string);
|
||||||
|
#endif
|
||||||
|
JSD_UNLOCK_SOURCE_TEXT(jsdc);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_moveSourceToRemovedList(jsdc, jsdsrc);
|
||||||
|
}
|
||||||
|
|
||||||
jsdsrc = AddSource( jsdc, new_url_string );
|
jsdsrc = _addSource( jsdc, new_url_string );
|
||||||
|
|
||||||
jsd_UnlockSourceTextSubsystem(jsdc);
|
JSD_UNLOCK_SOURCE_TEXT(jsdc);
|
||||||
|
|
||||||
return jsdsrc;
|
return jsdsrc;
|
||||||
}
|
}
|
||||||
|
@ -440,32 +400,148 @@ jsd_AppendSourceText(JSDContext* jsdc,
|
||||||
size_t length,
|
size_t length,
|
||||||
JSDSourceStatus status)
|
JSDSourceStatus status)
|
||||||
{
|
{
|
||||||
jsd_LockSourceTextSubsystem(jsdc);
|
JSD_LOCK_SOURCE_TEXT(jsdc);
|
||||||
|
|
||||||
if( ! IsSourceInSourceList( jsdc, jsdsrc ) )
|
if( jsdsrc->doingEval )
|
||||||
{
|
{
|
||||||
RemoveSourceFromRemovedList( jsdc, jsdsrc );
|
JSD_UNLOCK_SOURCE_TEXT(jsdc);
|
||||||
jsd_UnlockSourceTextSubsystem(jsdc);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( text && length && ! AppendText( jsdc, jsdsrc, text, length ) )
|
if( ! _isSourceInSourceList( jsdc, jsdsrc ) )
|
||||||
|
{
|
||||||
|
_removeSourceFromRemovedList( jsdc, jsdsrc );
|
||||||
|
JSD_UNLOCK_SOURCE_TEXT(jsdc);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( text && length && ! _appendText( jsdc, jsdsrc, text, length ) )
|
||||||
{
|
{
|
||||||
jsdsrc->dirty = JS_TRUE;
|
jsdsrc->dirty = JS_TRUE;
|
||||||
jsdsrc->alterCount = g_alterCount++ ;
|
jsdsrc->alterCount = jsdc->sourceAlterCount++ ;
|
||||||
jsdsrc->status = JSD_SOURCE_FAILED;
|
jsdsrc->status = JSD_SOURCE_FAILED;
|
||||||
MoveSourceToRemovedList(jsdc, jsdsrc);
|
_moveSourceToRemovedList(jsdc, jsdsrc);
|
||||||
jsd_UnlockSourceTextSubsystem(jsdc);
|
JSD_UNLOCK_SOURCE_TEXT(jsdc);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
jsdsrc->dirty = JS_TRUE;
|
jsdsrc->dirty = JS_TRUE;
|
||||||
jsdsrc->alterCount = g_alterCount++ ;
|
jsdsrc->alterCount = jsdc->sourceAlterCount++ ;
|
||||||
jsdsrc->status = status;
|
jsdsrc->status = status;
|
||||||
DEBUG_ITERATE_SOURCES(jsdc);
|
DEBUG_ITERATE_SOURCES(jsdc);
|
||||||
jsd_UnlockSourceTextSubsystem(jsdc);
|
JSD_UNLOCK_SOURCE_TEXT(jsdc);
|
||||||
return jsdsrc;
|
return jsdsrc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSDSourceText*
|
||||||
|
jsd_AppendUCSourceText(JSDContext* jsdc,
|
||||||
|
JSDSourceText* jsdsrc,
|
||||||
|
const jschar* text, /* *not* zero terminated */
|
||||||
|
size_t length,
|
||||||
|
JSDSourceStatus status)
|
||||||
|
{
|
||||||
|
#define UNICODE_TRUNCATE_BUF_SIZE 1024
|
||||||
|
static char* buf = NULL;
|
||||||
|
int remaining = length;
|
||||||
|
|
||||||
|
if(!text || !length)
|
||||||
|
return jsd_AppendSourceText(jsdc, jsdsrc, NULL, 0, status);
|
||||||
|
|
||||||
|
JSD_LOCK_SOURCE_TEXT(jsdc);
|
||||||
|
if(!buf)
|
||||||
|
{
|
||||||
|
buf = malloc(UNICODE_TRUNCATE_BUF_SIZE);
|
||||||
|
if(!buf)
|
||||||
|
{
|
||||||
|
JSD_UNLOCK_SOURCE_TEXT(jsdc);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(remaining && jsdsrc) {
|
||||||
|
int bytes = JS_MIN(remaining, UNICODE_TRUNCATE_BUF_SIZE);
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < bytes; i++)
|
||||||
|
buf[i] = (const char) *(text++);
|
||||||
|
jsdsrc = jsd_AppendSourceText(jsdc,jsdsrc,
|
||||||
|
buf, bytes,
|
||||||
|
JSD_SOURCE_PARTIAL);
|
||||||
|
remaining -= bytes;
|
||||||
|
}
|
||||||
|
if(jsdsrc && status != JSD_SOURCE_PARTIAL)
|
||||||
|
jsdsrc = jsd_AppendSourceText(jsdc, jsdsrc, NULL, 0, status);
|
||||||
|
|
||||||
|
JSD_UNLOCK_SOURCE_TEXT(jsdc);
|
||||||
|
return jsdsrc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* convienence function for adding complete source of url in one call */
|
||||||
|
JSBool
|
||||||
|
jsd_AddFullSourceText(JSDContext* jsdc,
|
||||||
|
const char* text, /* *not* zero terminated */
|
||||||
|
size_t length,
|
||||||
|
const char* url)
|
||||||
|
{
|
||||||
|
JSDSourceText* jsdsrc;
|
||||||
|
|
||||||
|
JSD_LOCK_SOURCE_TEXT(jsdc);
|
||||||
|
|
||||||
|
jsdsrc = jsd_NewSourceText(jsdc, url);
|
||||||
|
if( jsdsrc )
|
||||||
|
jsdsrc = jsd_AppendSourceText(jsdc, jsdsrc,
|
||||||
|
text, length, JSD_SOURCE_PARTIAL );
|
||||||
|
if( jsdsrc )
|
||||||
|
jsdsrc = jsd_AppendSourceText(jsdc, jsdsrc,
|
||||||
|
NULL, 0, JSD_SOURCE_COMPLETED );
|
||||||
|
|
||||||
|
JSD_UNLOCK_SOURCE_TEXT(jsdc);
|
||||||
|
|
||||||
|
return jsdsrc ? JS_TRUE : JS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
|
void
|
||||||
|
jsd_StartingEvalUsingFilename(JSDContext* jsdc, const char* url)
|
||||||
|
{
|
||||||
|
JSDSourceText* jsdsrc;
|
||||||
|
|
||||||
|
/* NOTE: We leave it locked! */
|
||||||
|
JSD_LOCK_SOURCE_TEXT(jsdc);
|
||||||
|
|
||||||
|
jsdsrc = jsd_FindSourceForURL(jsdc, url);
|
||||||
|
if(jsdsrc)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
#ifndef JSD_LOWLEVEL_SOURCE
|
||||||
|
JS_ASSERT(! jsdsrc->doingEval);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
jsdsrc->doingEval = JS_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
jsd_FinishedEvalUsingFilename(JSDContext* jsdc, const char* url)
|
||||||
|
{
|
||||||
|
JSDSourceText* jsdsrc;
|
||||||
|
|
||||||
|
/* NOTE: We ASSUME it is locked! */
|
||||||
|
|
||||||
|
jsdsrc = jsd_FindSourceForURL(jsdc, url);
|
||||||
|
if(jsdsrc)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
#ifndef JSD_LOWLEVEL_SOURCE
|
||||||
|
/*
|
||||||
|
* when using this low level source addition, this jsdsrc might
|
||||||
|
* not have existed before the eval, but does exist now (without
|
||||||
|
* this flag set!)
|
||||||
|
*/
|
||||||
|
JS_ASSERT(jsdsrc->doingEval);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
jsdsrc->doingEval = JS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSD_UNLOCK_SOURCE_TEXT(jsdc);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,601 @@
|
||||||
|
/* -*- 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* JavaScript Debugging support - Value and Property support
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "jsd.h"
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
void JSD_ASSERT_VALID_VALUE(JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
JS_ASSERT(jsdval);
|
||||||
|
JS_ASSERT(jsdval->nref > 0);
|
||||||
|
if(!JS_CLIST_IS_EMPTY(&jsdval->props))
|
||||||
|
{
|
||||||
|
JS_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS));
|
||||||
|
JS_ASSERT(JSVAL_IS_OBJECT(jsdval->val));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(jsdval->proto)
|
||||||
|
{
|
||||||
|
JS_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_PROTO));
|
||||||
|
JS_ASSERT(jsdval->proto->nref > 0);
|
||||||
|
}
|
||||||
|
if(jsdval->parent)
|
||||||
|
{
|
||||||
|
JS_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_PARENT));
|
||||||
|
JS_ASSERT(jsdval->parent->nref > 0);
|
||||||
|
}
|
||||||
|
if(jsdval->ctor)
|
||||||
|
{
|
||||||
|
JS_ASSERT(CHECK_BIT_FLAG(jsdval->flags, GOT_CTOR));
|
||||||
|
JS_ASSERT(jsdval->ctor->nref > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JSD_ASSERT_VALID_PROPERTY(JSDProperty* jsdprop)
|
||||||
|
{
|
||||||
|
JS_ASSERT(jsdprop);
|
||||||
|
JS_ASSERT(jsdprop->name);
|
||||||
|
JS_ASSERT(jsdprop->name->nref > 0);
|
||||||
|
JS_ASSERT(jsdprop->val);
|
||||||
|
JS_ASSERT(jsdprop->val->nref > 0);
|
||||||
|
if(jsdprop->alias)
|
||||||
|
JS_ASSERT(jsdprop->alias->nref > 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
jsd_IsValueObject(JSDContext* jsdc, JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
return JSVAL_IS_OBJECT(jsdval->val);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
jsd_IsValueNumber(JSDContext* jsdc, JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
return JSVAL_IS_NUMBER(jsdval->val);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
jsd_IsValueInt(JSDContext* jsdc, JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
return JSVAL_IS_INT(jsdval->val);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
jsd_IsValueDouble(JSDContext* jsdc, JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
return JSVAL_IS_DOUBLE(jsdval->val);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
jsd_IsValueString(JSDContext* jsdc, JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
return JSVAL_IS_STRING(jsdval->val);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
jsd_IsValueBoolean(JSDContext* jsdc, JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
return JSVAL_IS_BOOLEAN(jsdval->val);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
jsd_IsValueNull(JSDContext* jsdc, JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
return JSVAL_IS_NULL(jsdval->val);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
jsd_IsValueVoid(JSDContext* jsdc, JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
return JSVAL_IS_VOID(jsdval->val);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
jsd_IsValuePrimitive(JSDContext* jsdc, JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
return JSVAL_IS_PRIMITIVE(jsdval->val);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
jsd_IsValueFunction(JSDContext* jsdc, JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
return JSVAL_IS_FUNCTION(jsdc->dumbContext, jsdval->val);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
jsd_IsValueNative(JSDContext* jsdc, JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
JSContext* cx = jsdc->dumbContext;
|
||||||
|
jsval val = jsdval->val;
|
||||||
|
JSFunction* fun;
|
||||||
|
JSExceptionState* exceptionState;
|
||||||
|
|
||||||
|
if(!JSVAL_IS_OBJECT(val))
|
||||||
|
return JS_FALSE;
|
||||||
|
|
||||||
|
if(JSVAL_IS_FUNCTION(cx, val))
|
||||||
|
{
|
||||||
|
exceptionState = JS_SaveExceptionState(cx);
|
||||||
|
fun = JS_ValueToFunction(cx, val);
|
||||||
|
JS_RestoreExceptionState(cx, exceptionState);
|
||||||
|
if(!fun)
|
||||||
|
{
|
||||||
|
JS_ASSERT(0);
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
return JS_GetFunctionScript(cx, fun) ? JS_FALSE : JS_TRUE;
|
||||||
|
}
|
||||||
|
return JSVAL_TO_OBJECT(val) && OBJ_IS_NATIVE(JSVAL_TO_OBJECT(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
jsd_GetValueBoolean(JSDContext* jsdc, JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
jsval val = jsdval->val;
|
||||||
|
if(!JSVAL_IS_BOOLEAN(val))
|
||||||
|
return JS_FALSE;
|
||||||
|
return JSVAL_TO_BOOLEAN(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
jsd_GetValueInt(JSDContext* jsdc, JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
jsval val = jsdval->val;
|
||||||
|
if(!JSVAL_IS_INT(val))
|
||||||
|
return 0;
|
||||||
|
return JSVAL_TO_INT(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
jsdouble*
|
||||||
|
jsd_GetValueDouble(JSDContext* jsdc, JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
jsval val = jsdval->val;
|
||||||
|
if(!JSVAL_IS_DOUBLE(val))
|
||||||
|
return 0;
|
||||||
|
return JSVAL_TO_DOUBLE(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSString*
|
||||||
|
jsd_GetValueString(JSDContext* jsdc, JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
JSContext* cx = jsdc->dumbContext;
|
||||||
|
JSExceptionState* exceptionState;
|
||||||
|
|
||||||
|
if(!jsdval->string)
|
||||||
|
{
|
||||||
|
/* if the jsval is a string, then we don't need to double root it */
|
||||||
|
if(JSVAL_IS_STRING(jsdval->val))
|
||||||
|
jsdval->string = JSVAL_TO_STRING(jsdval->val);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
exceptionState = JS_SaveExceptionState(cx);
|
||||||
|
jsdval->string = JS_ValueToString(cx, jsdval->val);
|
||||||
|
JS_RestoreExceptionState(cx, exceptionState);
|
||||||
|
if(jsdval->string)
|
||||||
|
{
|
||||||
|
if(!JS_AddRoot(cx, &jsdval->string))
|
||||||
|
jsdval->string = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return jsdval->string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char*
|
||||||
|
jsd_GetValueFunctionName(JSDContext* jsdc, JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
JSContext* cx = jsdc->dumbContext;
|
||||||
|
jsval val = jsdval->val;
|
||||||
|
JSFunction* fun;
|
||||||
|
JSExceptionState* exceptionState;
|
||||||
|
|
||||||
|
if(!jsdval->funName && JSVAL_IS_FUNCTION(cx, val))
|
||||||
|
{
|
||||||
|
exceptionState = JS_SaveExceptionState(cx);
|
||||||
|
fun = JS_ValueToFunction(cx, val);
|
||||||
|
JS_RestoreExceptionState(cx, exceptionState);
|
||||||
|
if(!fun)
|
||||||
|
return NULL;
|
||||||
|
jsdval->funName = JS_GetFunctionName(fun);
|
||||||
|
}
|
||||||
|
return jsdval->funName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
|
||||||
|
JSDValue*
|
||||||
|
jsd_NewValue(JSDContext* jsdc, jsval val)
|
||||||
|
{
|
||||||
|
JSDValue* jsdval;
|
||||||
|
|
||||||
|
if(!(jsdval = (JSDValue*) calloc(1, sizeof(JSDValue))))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if(JSVAL_IS_GCTHING(val))
|
||||||
|
{
|
||||||
|
if(!JS_AddRoot(jsdc->dumbContext, &jsdval->val))
|
||||||
|
{
|
||||||
|
free(jsdval);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
jsdval->val = val;
|
||||||
|
jsdval->nref = 1;
|
||||||
|
JS_INIT_CLIST(&jsdval->props);
|
||||||
|
|
||||||
|
return jsdval;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
jsd_DropValue(JSDContext* jsdc, JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
JS_ASSERT(jsdval->nref > 0);
|
||||||
|
if(0 == --jsdval->nref)
|
||||||
|
{
|
||||||
|
jsd_RefreshValue(jsdc, jsdval);
|
||||||
|
if(JSVAL_IS_GCTHING(jsdval->val))
|
||||||
|
JS_RemoveRoot(jsdc->dumbContext, &jsdval->val);
|
||||||
|
free(jsdval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jsval
|
||||||
|
jsd_GetValueWrappedJSVal(JSDContext* jsdc, JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
return jsdval->val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSDProperty* _newProperty(JSDContext* jsdc, JSPropertyDesc* pd,
|
||||||
|
uintN additionalFlags)
|
||||||
|
{
|
||||||
|
JSDProperty* jsdprop;
|
||||||
|
|
||||||
|
if(!(jsdprop = (JSDProperty*) calloc(1, sizeof(JSDProperty))))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
JS_INIT_CLIST(&jsdprop->links);
|
||||||
|
jsdprop->nref = 1;
|
||||||
|
jsdprop->flags = pd->flags | additionalFlags;
|
||||||
|
jsdprop->slot = pd->slot;
|
||||||
|
|
||||||
|
if(!(jsdprop->name = jsd_NewValue(jsdc, pd->id)))
|
||||||
|
goto new_prop_fail;
|
||||||
|
|
||||||
|
if(!(jsdprop->val = jsd_NewValue(jsdc, pd->value)))
|
||||||
|
goto new_prop_fail;
|
||||||
|
|
||||||
|
if((jsdprop->flags & JSDPD_ALIAS) &&
|
||||||
|
!(jsdprop->alias = jsd_NewValue(jsdc, pd->alias)))
|
||||||
|
goto new_prop_fail;
|
||||||
|
|
||||||
|
return jsdprop;
|
||||||
|
new_prop_fail:
|
||||||
|
jsd_DropProperty(jsdc, jsdprop);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _freeProps(JSDContext* jsdc, JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
JSDProperty* jsdprop;
|
||||||
|
|
||||||
|
while(jsdprop = (JSDProperty*)jsdval->props.next,
|
||||||
|
jsdprop != (JSDProperty*)&jsdval->props)
|
||||||
|
{
|
||||||
|
JS_REMOVE_AND_INIT_LINK(&jsdprop->links);
|
||||||
|
jsd_DropProperty(jsdc, jsdprop);
|
||||||
|
}
|
||||||
|
JS_ASSERT(JS_CLIST_IS_EMPTY(&jsdval->props));
|
||||||
|
CLEAR_BIT_FLAG(jsdval->flags, GOT_PROPS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSBool _buildProps(JSDContext* jsdc, JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
JSContext* cx = jsdc->dumbContext;
|
||||||
|
JSPropertyDescArray pda;
|
||||||
|
uintN i;
|
||||||
|
|
||||||
|
JS_ASSERT(JS_CLIST_IS_EMPTY(&jsdval->props));
|
||||||
|
JS_ASSERT(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)));
|
||||||
|
JS_ASSERT(JSVAL_IS_OBJECT(jsdval->val));
|
||||||
|
|
||||||
|
if(!JSVAL_IS_OBJECT(jsdval->val) || JSVAL_IS_NULL(jsdval->val))
|
||||||
|
return JS_FALSE;
|
||||||
|
|
||||||
|
if(!JS_GetPropertyDescArray(cx, JSVAL_TO_OBJECT(jsdval->val), &pda))
|
||||||
|
return JS_FALSE;
|
||||||
|
|
||||||
|
for(i = 0; i < pda.length; i++)
|
||||||
|
{
|
||||||
|
JSDProperty* prop = _newProperty(jsdc, &pda.array[i], 0);
|
||||||
|
if(!prop)
|
||||||
|
{
|
||||||
|
_freeProps(jsdc, jsdval);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
JS_APPEND_LINK(&prop->links, &jsdval->props);
|
||||||
|
}
|
||||||
|
JS_PutPropertyDescArray(cx, &pda);
|
||||||
|
SET_BIT_FLAG(jsdval->flags, GOT_PROPS);
|
||||||
|
return !JS_CLIST_IS_EMPTY(&jsdval->props);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef DROP_CLEAR_VALUE
|
||||||
|
#define DROP_CLEAR_VALUE(jsdc, x) if(x){jsd_DropValue(jsdc,x); x = NULL;}
|
||||||
|
|
||||||
|
void
|
||||||
|
jsd_RefreshValue(JSDContext* jsdc, JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
JSContext* cx = jsdc->dumbContext;
|
||||||
|
|
||||||
|
if(jsdval->string)
|
||||||
|
{
|
||||||
|
/* if the jsval is a string, then we didn't need to root the string */
|
||||||
|
if(!JSVAL_IS_STRING(jsdval->val))
|
||||||
|
JS_RemoveRoot(cx, &jsdval->string);
|
||||||
|
jsdval->string = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
jsdval->funName = NULL;
|
||||||
|
jsdval->className = NULL;
|
||||||
|
DROP_CLEAR_VALUE(jsdc, jsdval->proto);
|
||||||
|
DROP_CLEAR_VALUE(jsdc, jsdval->parent);
|
||||||
|
DROP_CLEAR_VALUE(jsdc, jsdval->ctor);
|
||||||
|
_freeProps(jsdc, jsdval);
|
||||||
|
jsdval->flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
|
||||||
|
uintN
|
||||||
|
jsd_GetCountOfProperties(JSDContext* jsdc, JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
JSDProperty* jsdprop;
|
||||||
|
uintN count = 0;
|
||||||
|
|
||||||
|
if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)))
|
||||||
|
if(!_buildProps(jsdc, jsdval))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for(jsdprop = (JSDProperty*)jsdval->props.next;
|
||||||
|
jsdprop != (JSDProperty*)&jsdval->props;
|
||||||
|
jsdprop = (JSDProperty*)jsdprop->links.next)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSDProperty*
|
||||||
|
jsd_IterateProperties(JSDContext* jsdc, JSDValue* jsdval, JSDProperty **iterp)
|
||||||
|
{
|
||||||
|
JSDProperty* jsdprop = *iterp;
|
||||||
|
if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)))
|
||||||
|
{
|
||||||
|
JS_ASSERT(!jsdprop);
|
||||||
|
if(!_buildProps(jsdc, jsdval))
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!jsdprop)
|
||||||
|
jsdprop = (JSDProperty*)jsdval->props.next;
|
||||||
|
if(jsdprop == (JSDProperty*)&jsdval->props)
|
||||||
|
return NULL;
|
||||||
|
*iterp = (JSDProperty*)jsdprop->links.next;
|
||||||
|
|
||||||
|
JS_ASSERT(jsdprop);
|
||||||
|
jsdprop->nref++;
|
||||||
|
return jsdprop;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSDProperty*
|
||||||
|
jsd_GetValueProperty(JSDContext* jsdc, JSDValue* jsdval, JSString* name)
|
||||||
|
{
|
||||||
|
JSContext* cx = jsdc->dumbContext;
|
||||||
|
JSDProperty* jsdprop;
|
||||||
|
JSDProperty* iter = NULL;
|
||||||
|
JSObject* obj;
|
||||||
|
uintN attrs = 0;
|
||||||
|
JSBool found;
|
||||||
|
JSPropertyDesc pd;
|
||||||
|
const jschar * nameChars;
|
||||||
|
size_t nameLen;
|
||||||
|
jsval val;
|
||||||
|
|
||||||
|
if(!jsd_IsValueObject(jsdc, jsdval))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* If we already have the prop, then return it */
|
||||||
|
while(NULL != (jsdprop = jsd_IterateProperties(jsdc, jsdval, &iter)))
|
||||||
|
{
|
||||||
|
JSString* propName = jsd_GetValueString(jsdc, jsdprop->name);
|
||||||
|
if(propName && !JS_CompareStrings(propName, name))
|
||||||
|
return jsdprop;
|
||||||
|
JSD_DropProperty(jsdc, jsdprop);
|
||||||
|
}
|
||||||
|
/* Not found in property list, look it up explicitly */
|
||||||
|
|
||||||
|
if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
nameChars = JS_GetStringChars(name);
|
||||||
|
nameLen = JS_GetStringLength(name);
|
||||||
|
|
||||||
|
/* It's OK if this fails - we just don't get attribs */
|
||||||
|
JS_GetUCPropertyAttributes(cx, obj, nameChars, nameLen, &attrs, &found);
|
||||||
|
|
||||||
|
if(!JS_GetUCProperty(cx, obj, nameChars, nameLen, &val))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* XXX screwy! no good way to detect that property does not exist at all */
|
||||||
|
if(!found && JSVAL_IS_VOID(val))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
pd.id = STRING_TO_JSVAL(name);
|
||||||
|
pd.value = val;
|
||||||
|
pd.alias = pd.slot = pd.spare = 0;
|
||||||
|
pd.flags = 0
|
||||||
|
| (attrs & JSPROP_ENUMERATE) ? JSPD_ENUMERATE : 0
|
||||||
|
| (attrs & JSPROP_READONLY) ? JSPD_READONLY : 0
|
||||||
|
| (attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0;
|
||||||
|
|
||||||
|
return _newProperty(jsdc, &pd, JSDPD_HINTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
JSDValue*
|
||||||
|
jsd_GetValuePrototype(JSDContext* jsdc, JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROTO)))
|
||||||
|
{
|
||||||
|
JSObject* obj;
|
||||||
|
JSObject* proto;
|
||||||
|
JS_ASSERT(!jsdval->proto);
|
||||||
|
SET_BIT_FLAG(jsdval->flags, GOT_PROTO);
|
||||||
|
if(!JSVAL_IS_OBJECT(jsdval->val))
|
||||||
|
return NULL;
|
||||||
|
if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
|
||||||
|
return NULL;
|
||||||
|
if(!(proto = OBJ_GET_PROTO(jsdc->dumbContext,obj)))
|
||||||
|
return NULL;
|
||||||
|
jsdval->proto = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(proto));
|
||||||
|
}
|
||||||
|
if(jsdval->proto)
|
||||||
|
jsdval->proto->nref++;
|
||||||
|
return jsdval->proto;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSDValue*
|
||||||
|
jsd_GetValueParent(JSDContext* jsdc, JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PARENT)))
|
||||||
|
{
|
||||||
|
JSObject* obj;
|
||||||
|
JSObject* parent;
|
||||||
|
JS_ASSERT(!jsdval->parent);
|
||||||
|
SET_BIT_FLAG(jsdval->flags, GOT_PARENT);
|
||||||
|
if(!JSVAL_IS_OBJECT(jsdval->val))
|
||||||
|
return NULL;
|
||||||
|
if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
|
||||||
|
return NULL;
|
||||||
|
if(!(parent = OBJ_GET_PARENT(jsdc->dumbContext,obj)))
|
||||||
|
return NULL;
|
||||||
|
jsdval->parent = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(parent));
|
||||||
|
}
|
||||||
|
if(jsdval->parent)
|
||||||
|
jsdval->parent->nref++;
|
||||||
|
return jsdval->parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSDValue*
|
||||||
|
jsd_GetValueConstructor(JSDContext* jsdc, JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_CTOR)))
|
||||||
|
{
|
||||||
|
JSObject* obj;
|
||||||
|
JSObject* proto;
|
||||||
|
JSObject* ctor;
|
||||||
|
JS_ASSERT(!jsdval->ctor);
|
||||||
|
SET_BIT_FLAG(jsdval->flags, GOT_CTOR);
|
||||||
|
if(!JSVAL_IS_OBJECT(jsdval->val))
|
||||||
|
return NULL;
|
||||||
|
if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
|
||||||
|
return NULL;
|
||||||
|
if(!(proto = OBJ_GET_PROTO(jsdc->dumbContext,obj)))
|
||||||
|
return NULL;
|
||||||
|
if(!(ctor = JS_GetConstructor(jsdc->dumbContext,proto)))
|
||||||
|
return NULL;
|
||||||
|
jsdval->ctor = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(ctor));
|
||||||
|
}
|
||||||
|
if(jsdval->ctor)
|
||||||
|
jsdval->ctor->nref++;
|
||||||
|
return jsdval->ctor;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char*
|
||||||
|
jsd_GetValueClassName(JSDContext* jsdc, JSDValue* jsdval)
|
||||||
|
{
|
||||||
|
jsval val = jsdval->val;
|
||||||
|
if(!jsdval->className && JSVAL_IS_OBJECT(val))
|
||||||
|
{
|
||||||
|
JSObject* obj;
|
||||||
|
if(!(obj = JSVAL_TO_OBJECT(val)))
|
||||||
|
return NULL;
|
||||||
|
if(OBJ_GET_CLASS(jsdc->dumbContext, obj))
|
||||||
|
jsdval->className = OBJ_GET_CLASS(jsdc->dumbContext, obj)->name;
|
||||||
|
}
|
||||||
|
return jsdval->className;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/***************************************************************************/
|
||||||
|
|
||||||
|
JSDValue*
|
||||||
|
jsd_GetPropertyName(JSDContext* jsdc, JSDProperty* jsdprop)
|
||||||
|
{
|
||||||
|
jsdprop->name->nref++;
|
||||||
|
return jsdprop->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSDValue*
|
||||||
|
jsd_GetPropertyValue(JSDContext* jsdc, JSDProperty* jsdprop)
|
||||||
|
{
|
||||||
|
jsdprop->val->nref++;
|
||||||
|
return jsdprop->val;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSDValue*
|
||||||
|
jsd_GetPropertyAlias(JSDContext* jsdc, JSDProperty* jsdprop)
|
||||||
|
{
|
||||||
|
if(jsdprop->alias)
|
||||||
|
jsdprop->alias->nref++;
|
||||||
|
return jsdprop->alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintN
|
||||||
|
jsd_GetPropertyFlags(JSDContext* jsdc, JSDProperty* jsdprop)
|
||||||
|
{
|
||||||
|
return jsdprop->flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintN
|
||||||
|
jsd_GetPropertyVarArgSlot(JSDContext* jsdc, JSDProperty* jsdprop)
|
||||||
|
{
|
||||||
|
return jsdprop->slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
jsd_DropProperty(JSDContext* jsdc, JSDProperty* jsdprop)
|
||||||
|
{
|
||||||
|
JS_ASSERT(jsdprop->nref > 0);
|
||||||
|
if(0 == --jsdprop->nref)
|
||||||
|
{
|
||||||
|
JS_ASSERT(JS_CLIST_IS_EMPTY(&jsdprop->links));
|
||||||
|
DROP_CLEAR_VALUE(jsdc, jsdprop->val);
|
||||||
|
DROP_CLEAR_VALUE(jsdc, jsdprop->name);
|
||||||
|
DROP_CLEAR_VALUE(jsdc, jsdprop->alias);
|
||||||
|
free(jsdprop);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
/* jband - 10/26/98 - */
|
||||||
|
|
||||||
|
js/jsd/jsdb is a console debugger using only native code. It is experimental.
|
||||||
|
The only makefile supplied is for Win32.
|
||||||
|
|
||||||
|
jsdb.mak will build a debugger enabled js/src/js.c shell. The debugger is
|
||||||
|
implemented by reflecting the JSD api into JavaScript. The actual debugger
|
||||||
|
logic is fully implemented in debugger.js. The debugger can debug itself. It
|
||||||
|
can also be modified and reloaded at runtime.
|
||||||
|
|
||||||
|
The JavaScript keyword 'debugger' is used to break into the debugger. A 'help()'
|
||||||
|
command is supplied to show available commands when exectution is stopped.
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,46 @@
|
||||||
|
|
||||||
|
/**
|
||||||
|
* for(var p in Script.scripts) {
|
||||||
|
*
|
||||||
|
* var script = Script.scripts[p];
|
||||||
|
* var handle = script.handle;
|
||||||
|
* var base = script.base;
|
||||||
|
* var limit = base + script.extent;
|
||||||
|
*
|
||||||
|
* print(script+"\n");
|
||||||
|
*
|
||||||
|
* for(var i = base; i < limit; i++) {
|
||||||
|
* var pc = jsd.GetClosestPC(handle,i)
|
||||||
|
* var hascode = String(pc).length && i == jsd.GetClosestLine(handle,pc);
|
||||||
|
* print("line "+i+" "+ (hascode ? "has code" : "has NO code"));
|
||||||
|
* }
|
||||||
|
* print("...............................\n");
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
|
||||||
|
function rlocals()
|
||||||
|
{
|
||||||
|
var retval = "";
|
||||||
|
var name = "___UNIQUE_NAME__";
|
||||||
|
var fun = ""+
|
||||||
|
"var text = \\\"\\\";"+
|
||||||
|
"for(var p in ob)"+
|
||||||
|
"{"+
|
||||||
|
" if(text != \\\"\\\")"+
|
||||||
|
" text += \\\",\\\";"+
|
||||||
|
" text += p;"+
|
||||||
|
"}"+
|
||||||
|
"return text;";
|
||||||
|
|
||||||
|
reval(name+" = new Function(\"ob\",\""+fun+"\")");
|
||||||
|
// show(name);
|
||||||
|
retval = _reval([name+"("+"arguments.callee"+")"]);
|
||||||
|
reval("delete "+name);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
function e(a)
|
||||||
|
{
|
||||||
|
return eval(a);
|
||||||
|
}
|
|
@ -0,0 +1,449 @@
|
||||||
|
/* -*- 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* JSDB public and callback functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "jsdbpriv.h"
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
|
||||||
|
JS_STATIC_DLL_CALLBACK(void)
|
||||||
|
_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
|
||||||
|
{
|
||||||
|
int i, j, k, n;
|
||||||
|
|
||||||
|
fputs("jsdb: ", stderr);
|
||||||
|
if (!report) {
|
||||||
|
fprintf(stderr, "%s\n", message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (report->filename)
|
||||||
|
fprintf(stderr, "%s, ", report->filename);
|
||||||
|
if (report->lineno)
|
||||||
|
fprintf(stderr, "line %u: ", report->lineno);
|
||||||
|
fputs(message, stderr);
|
||||||
|
if (!report->linebuf) {
|
||||||
|
putc('\n', stderr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, ":\n%s\n", report->linebuf);
|
||||||
|
n = report->tokenptr - report->linebuf;
|
||||||
|
for (i = j = 0; i < n; i++) {
|
||||||
|
if (report->linebuf[i] == '\t') {
|
||||||
|
for (k = (j + 8) & ~7; j < k; j++)
|
||||||
|
putc('.', stderr);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
putc('.', stderr);
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
fputs("^\n", stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_STATIC_DLL_CALLBACK(void)
|
||||||
|
jsdb_ScriptHookProc(JSDContext* jsdc,
|
||||||
|
JSDScript* jsdscript,
|
||||||
|
JSBool creating,
|
||||||
|
void* callerdata)
|
||||||
|
{
|
||||||
|
JSDB_Data* data = (JSDB_Data*) callerdata;
|
||||||
|
JSFunction* fun;
|
||||||
|
|
||||||
|
if(data->jsScriptHook &&
|
||||||
|
NULL != (fun = JS_ValueToFunction(data->cxDebugger, data->jsScriptHook)))
|
||||||
|
{
|
||||||
|
jsval result;
|
||||||
|
jsval args[2] = {P2H_SCRIPT(data->cxDebugger, jsdscript),
|
||||||
|
creating ? JSVAL_TRUE : JSVAL_FALSE };
|
||||||
|
JS_CallFunction(data->cxDebugger, NULL, fun, 2, args, &result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uintN JS_DLL_CALLBACK
|
||||||
|
jsdb_ExecHookHandler(JSDContext* jsdc,
|
||||||
|
JSDThreadState* jsdthreadstate,
|
||||||
|
uintN type,
|
||||||
|
void* callerdata,
|
||||||
|
jsval* rval)
|
||||||
|
{
|
||||||
|
uintN ourRetVal = JSD_HOOK_RETURN_CONTINUE;
|
||||||
|
jsval result;
|
||||||
|
JSFunction* fun;
|
||||||
|
int answer;
|
||||||
|
JSDB_Data* data = (JSDB_Data*) callerdata;
|
||||||
|
JS_ASSERT(data);
|
||||||
|
|
||||||
|
/* if we're already stopped, then don't stop */
|
||||||
|
if(data->jsdthreadstate)
|
||||||
|
return JSD_HOOK_RETURN_CONTINUE;
|
||||||
|
|
||||||
|
if(!jsdb_SetThreadState(data, jsdthreadstate))
|
||||||
|
goto label_bail;
|
||||||
|
|
||||||
|
if(data->jsExecutionHook &&
|
||||||
|
NULL != (fun = JS_ValueToFunction(data->cxDebugger, data->jsExecutionHook)))
|
||||||
|
{
|
||||||
|
jsval arg = INT_TO_JSVAL((int)type);
|
||||||
|
if(!JS_CallFunction(data->cxDebugger, NULL, fun, 1, &arg, &result))
|
||||||
|
goto label_bail;
|
||||||
|
if(!JSVAL_IS_INT(result))
|
||||||
|
goto label_bail;
|
||||||
|
answer = JSVAL_TO_INT(result);
|
||||||
|
|
||||||
|
|
||||||
|
if((answer == JSD_HOOK_RETURN_RET_WITH_VAL ||
|
||||||
|
answer == JSD_HOOK_RETURN_THROW_WITH_VAL) &&
|
||||||
|
!jsdb_EvalReturnExpression(data, rval))
|
||||||
|
{
|
||||||
|
goto label_bail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(answer >= JSD_HOOK_RETURN_HOOK_ERROR &&
|
||||||
|
answer <= JSD_HOOK_RETURN_CONTINUE_THROW)
|
||||||
|
ourRetVal = answer;
|
||||||
|
else
|
||||||
|
ourRetVal = JSD_HOOK_RETURN_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
label_bail:
|
||||||
|
jsdb_SetThreadState(data, NULL);
|
||||||
|
return ourRetVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
ARG_MSG = 0,
|
||||||
|
ARG_FILENAME,
|
||||||
|
ARG_LINENO,
|
||||||
|
ARG_LINEBUF,
|
||||||
|
ARG_TOKEN_OFFSET,
|
||||||
|
ARG_LIMIT
|
||||||
|
} ER_ARGS;
|
||||||
|
|
||||||
|
uintN JS_DLL_CALLBACK
|
||||||
|
jsdb_ErrorReporter(JSDContext* jsdc,
|
||||||
|
JSContext* cx,
|
||||||
|
const char* message,
|
||||||
|
JSErrorReport* report,
|
||||||
|
void* callerdata)
|
||||||
|
{
|
||||||
|
uintN ourRetVal = JSD_ERROR_REPORTER_PASS_ALONG;
|
||||||
|
jsval result;
|
||||||
|
JSFunction* fun;
|
||||||
|
int32 answer;
|
||||||
|
JSDB_Data* data = (JSDB_Data*) callerdata;
|
||||||
|
JS_ASSERT(data);
|
||||||
|
|
||||||
|
if(data->jsErrorReporterHook &&
|
||||||
|
NULL != (fun = JS_ValueToFunction(data->cxDebugger,
|
||||||
|
data->jsErrorReporterHook)))
|
||||||
|
{
|
||||||
|
jsval args[ARG_LIMIT] = {JSVAL_NULL};
|
||||||
|
|
||||||
|
if(message)
|
||||||
|
args[ARG_MSG] =
|
||||||
|
STRING_TO_JSVAL(JS_NewStringCopyZ(cx, message));
|
||||||
|
if(report && report->filename)
|
||||||
|
args[ARG_FILENAME] =
|
||||||
|
STRING_TO_JSVAL(JS_NewStringCopyZ(cx, report->filename));
|
||||||
|
if(report && report->linebuf)
|
||||||
|
args[ARG_LINEBUF] =
|
||||||
|
STRING_TO_JSVAL(JS_NewStringCopyZ(cx, report->linebuf));
|
||||||
|
if(report)
|
||||||
|
args[ARG_LINENO] =
|
||||||
|
INT_TO_JSVAL(report->lineno);
|
||||||
|
if(report && report->linebuf && report->tokenptr)
|
||||||
|
args[ARG_TOKEN_OFFSET] =
|
||||||
|
INT_TO_JSVAL((int)(report->tokenptr - report->linebuf));
|
||||||
|
|
||||||
|
if(!JS_CallFunction(data->cxDebugger, NULL, fun, ARG_LIMIT, args, &result))
|
||||||
|
return ourRetVal;
|
||||||
|
|
||||||
|
if(JS_ValueToInt32(data->cxDebugger, result, &answer))
|
||||||
|
ourRetVal = (uintN) answer;
|
||||||
|
}
|
||||||
|
return ourRetVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||||
|
Load(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
|
{
|
||||||
|
uintN i;
|
||||||
|
JSString *str;
|
||||||
|
const char *filename;
|
||||||
|
JSScript *script;
|
||||||
|
JSBool ok;
|
||||||
|
jsval result;
|
||||||
|
|
||||||
|
ok = JS_TRUE;
|
||||||
|
for (i = 0; i < argc; i++) {
|
||||||
|
str = JS_ValueToString(cx, argv[i]);
|
||||||
|
if (!str) {
|
||||||
|
ok = JS_FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
argv[i] = STRING_TO_JSVAL(str);
|
||||||
|
filename = JS_GetStringBytes(str);
|
||||||
|
errno = 0;
|
||||||
|
script = JS_CompileFile(cx, obj, filename);
|
||||||
|
if (!script)
|
||||||
|
continue;
|
||||||
|
ok = JS_ExecuteScript(cx, obj, script, &result);
|
||||||
|
JS_DestroyScript(cx, script);
|
||||||
|
if (!ok)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
JS_GC(cx);
|
||||||
|
*rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx,""));
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||||
|
Write(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
|
{
|
||||||
|
JSString *str = JS_ValueToString(cx, argv[0]);
|
||||||
|
if (!str)
|
||||||
|
return JS_FALSE;
|
||||||
|
printf(JS_GetStringBytes(str));
|
||||||
|
*rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx,""));
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||||
|
Gets(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
|
{
|
||||||
|
char buf[1024];
|
||||||
|
if(! gets(buf))
|
||||||
|
return JS_FALSE;
|
||||||
|
*rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, buf));
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||||
|
Version(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
|
{
|
||||||
|
if (argc > 0 && JSVAL_IS_INT(argv[0]))
|
||||||
|
*rval = INT_TO_JSVAL(JS_SetVersion(cx, JSVAL_TO_INT(argv[0])));
|
||||||
|
else
|
||||||
|
*rval = INT_TO_JSVAL(JS_GetVersion(cx));
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||||
|
SafeEval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
|
{
|
||||||
|
static char default_filename[] = "jsdb_eval";
|
||||||
|
/* JSContext *cx2; */
|
||||||
|
JSString* textJSString;
|
||||||
|
char* filename;
|
||||||
|
int32 lineno;
|
||||||
|
JSDB_Data* data = (JSDB_Data*) JS_GetContextPrivate(cx);
|
||||||
|
JS_ASSERT(data);
|
||||||
|
|
||||||
|
if(argc < 1 || !(textJSString = JS_ValueToString(cx, argv[0])))
|
||||||
|
{
|
||||||
|
JS_ReportError(cx, "safeEval requires source text as a first argument");
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(argc < 2)
|
||||||
|
filename = default_filename;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
JSString* filenameJSString;
|
||||||
|
if(!(filenameJSString = JS_ValueToString(cx, argv[1])))
|
||||||
|
{
|
||||||
|
JS_ReportError(cx, "safeEval passed non-string filename as 2nd param");
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
filename = JS_GetStringBytes(filenameJSString);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(argc < 3)
|
||||||
|
lineno = 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(!JS_ValueToInt32(cx, argv[2], &lineno))
|
||||||
|
{
|
||||||
|
JS_ReportError(cx, "safeEval passed non-int lineno as 3rd param");
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(! JS_EvaluateScript(cx, obj,
|
||||||
|
JS_GetStringBytes(textJSString),
|
||||||
|
JS_GetStringLength(textJSString),
|
||||||
|
filename, lineno, rval))
|
||||||
|
*rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx,""));
|
||||||
|
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||||
|
NativeBreak(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
|
{
|
||||||
|
#ifdef _WINDOWS
|
||||||
|
_asm int 3;
|
||||||
|
*rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx,"did _asm int 3;"));
|
||||||
|
#else
|
||||||
|
*rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx,"only supported for Windows"));
|
||||||
|
#endif
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSFunctionSpec debugger_functions[] = {
|
||||||
|
{"version", Version, 0},
|
||||||
|
{"load", Load, 1},
|
||||||
|
{"write", Write, 0},
|
||||||
|
{"gets", Gets, 0},
|
||||||
|
{"safeEval", SafeEval, 3},
|
||||||
|
{"nativeBreak", NativeBreak, 0},
|
||||||
|
{0}
|
||||||
|
};
|
||||||
|
|
||||||
|
static JSClass debugger_global_class = {
|
||||||
|
"debugger_global", 0,
|
||||||
|
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||||
|
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
|
||||||
|
};
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
|
||||||
|
#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.
|
||||||
|
*/
|
||||||
|
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) {
|
||||||
|
jsdsrc = JSD_AppendUCSourceText(jsdc,jsdsrc, str, length,
|
||||||
|
JSD_SOURCE_PARTIAL);
|
||||||
|
}
|
||||||
|
*listenerTSData = jsdsrc;
|
||||||
|
}
|
||||||
|
#endif /* JSD_LOWLEVEL_SOURCE */
|
||||||
|
|
||||||
|
static JSBool
|
||||||
|
_initReturn(const char* str, JSBool retval)
|
||||||
|
{
|
||||||
|
if(str)
|
||||||
|
printf("%s\n", str);
|
||||||
|
if(retval)
|
||||||
|
; /* printf("debugger initialized\n"); */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
JS_ASSERT(0);
|
||||||
|
printf("debugger FAILED to initialize\n");
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAX_DEBUGGER_DEPTH 3
|
||||||
|
|
||||||
|
JS_EXPORT_API(JSBool)
|
||||||
|
JSDB_InitDebugger(JSRuntime* rt, JSDContext* jsdc, int depth)
|
||||||
|
{
|
||||||
|
jsval rvalIgnore;
|
||||||
|
static char load_deb[] = "load('debugger.js')";
|
||||||
|
|
||||||
|
JSDB_Data* data = (JSDB_Data*) calloc(1, sizeof(JSDB_Data));
|
||||||
|
if(!data)
|
||||||
|
return _initReturn("memory alloc error", JS_FALSE);
|
||||||
|
|
||||||
|
data->rtTarget = rt;
|
||||||
|
data->jsdcTarget = jsdc;
|
||||||
|
data->debuggerDepth = depth+1;
|
||||||
|
|
||||||
|
if(!(data->rtDebugger = JS_NewRuntime(8L * 1024L * 1024L)))
|
||||||
|
return _initReturn("debugger runtime creation error", JS_FALSE);
|
||||||
|
|
||||||
|
if(!(data->cxDebugger = JS_NewContext(data->rtDebugger, 8192)))
|
||||||
|
return _initReturn("debugger creation error", JS_FALSE);
|
||||||
|
|
||||||
|
JS_SetContextPrivate(data->cxDebugger, data);
|
||||||
|
|
||||||
|
JS_SetErrorReporter(data->cxDebugger, _ErrorReporter);
|
||||||
|
|
||||||
|
if(!(data->globDebugger =
|
||||||
|
JS_NewObject(data->cxDebugger, &debugger_global_class, NULL, NULL)))
|
||||||
|
return _initReturn("debugger global object creation error", JS_FALSE);
|
||||||
|
|
||||||
|
if(!JS_InitStandardClasses(data->cxDebugger, data->globDebugger))
|
||||||
|
return _initReturn("debugger InitStandardClasses error", JS_FALSE);
|
||||||
|
|
||||||
|
if(!JS_DefineFunctions(data->cxDebugger, data->globDebugger, debugger_functions))
|
||||||
|
return _initReturn("debugger DefineFunctions error", JS_FALSE);
|
||||||
|
|
||||||
|
if(!jsdb_ReflectJSD(data))
|
||||||
|
return _initReturn("debugger reflection of JSD API error", JS_FALSE);
|
||||||
|
|
||||||
|
if(data->debuggerDepth < MAX_DEBUGGER_DEPTH)
|
||||||
|
{
|
||||||
|
JSDContext* jsdc;
|
||||||
|
if(!(jsdc = JSD_DebuggerOnForUser(data->rtDebugger, NULL, NULL)))
|
||||||
|
return _initReturn("failed to create jsdc for nested debugger", JS_FALSE);
|
||||||
|
JSD_JSContextInUse(jsdc, data->cxDebugger);
|
||||||
|
if(!JSDB_InitDebugger(data->rtDebugger, jsdc, data->debuggerDepth))
|
||||||
|
return _initReturn("failed to init nested debugger", JS_FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSD_SetScriptHook(jsdc, jsdb_ScriptHookProc, data);
|
||||||
|
JSD_SetDebuggerHook(jsdc, jsdb_ExecHookHandler, data);
|
||||||
|
JSD_SetThrowHook(jsdc, jsdb_ExecHookHandler, data);
|
||||||
|
JSD_SetDebugBreakHook(jsdc, jsdb_ExecHookHandler, data);
|
||||||
|
JSD_SetErrorReporter(jsdc, jsdb_ErrorReporter, data);
|
||||||
|
|
||||||
|
#ifdef JSD_LOWLEVEL_SOURCE
|
||||||
|
JS_SetSourceHandler(data->rtDebugger, SendSourceToJSDebugger, jsdc);
|
||||||
|
#endif /* JSD_LOWLEVEL_SOURCE */
|
||||||
|
|
||||||
|
JS_EvaluateScript(data->cxDebugger, data->globDebugger,
|
||||||
|
load_deb, sizeof(load_deb)-1, "jsdb_autoload", 1,
|
||||||
|
&rvalIgnore);
|
||||||
|
|
||||||
|
return _initReturn(NULL, JS_TRUE);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
/* -*- 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Public headers for JSDB
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef jsdb_h___
|
||||||
|
#define jsdb_h___
|
||||||
|
|
||||||
|
/* Get jstypes.h included first. After that we can use PR macros for doing
|
||||||
|
* this extern "C" stuff!
|
||||||
|
*/
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
#include "jstypes.h"
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
JS_BEGIN_EXTERN_C
|
||||||
|
#include "jsapi.h"
|
||||||
|
#include "jsdebug.h"
|
||||||
|
JS_END_EXTERN_C
|
||||||
|
|
||||||
|
JS_BEGIN_EXTERN_C
|
||||||
|
|
||||||
|
extern JS_EXPORT_API(JSBool)
|
||||||
|
JSDB_InitDebugger(JSRuntime* rt, JSDContext* jsdc, int depth);
|
||||||
|
|
||||||
|
JS_END_EXTERN_C
|
||||||
|
|
||||||
|
#endif /* jsdb_h___ */
|
|
@ -0,0 +1,102 @@
|
||||||
|
|
||||||
|
PROJ = jsdb
|
||||||
|
JSDB = .
|
||||||
|
JSD = $(JSDB)\..
|
||||||
|
JSSRC = $(JSD)\..\src
|
||||||
|
|
||||||
|
!IF "$(BUILD_OPT)" != ""
|
||||||
|
OBJ = Release
|
||||||
|
CC_FLAGS = /DNDEBUG
|
||||||
|
!ELSE
|
||||||
|
OBJ = Debug
|
||||||
|
CC_FLAGS = /DDEBUG
|
||||||
|
LINK_FLAGS = /DEBUG
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
CFLAGS = /nologo /MDd /W3 /Gm /GX /Zi /Od\
|
||||||
|
/I $(JSSRC)\
|
||||||
|
/I $(JSD)\
|
||||||
|
/I $(JSDB)\
|
||||||
|
$(CC_FLAGS)\
|
||||||
|
/DWIN32 /DXP_PC /D_WINDOWS /D_WIN32\
|
||||||
|
/DJSDEBUGGER\
|
||||||
|
/DJSDEBUGGER_C_UI\
|
||||||
|
/DJSD_LOWLEVEL_SOURCE\
|
||||||
|
/DJSFILE\
|
||||||
|
/c /Fp$(OBJ)\$(PROJ).pch /Fd$(OBJ)\$(PROJ).pdb /YX -Fo$@ $<
|
||||||
|
|
||||||
|
LFLAGS = /nologo /subsystem:console /incremental:no /machine:I386 $(LINK_FLAGS)\
|
||||||
|
/pdb:$(OBJ)\$(PROJ).pdb -out:$(OBJ)\$(PROJ).exe
|
||||||
|
|
||||||
|
LLIBS = kernel32.lib advapi32.lib $(JSSRC)\$(OBJ)\js32.lib $(JSD)\$(OBJ)\jsd.lib
|
||||||
|
|
||||||
|
CPP=cl.exe
|
||||||
|
LINK32=link.exe
|
||||||
|
|
||||||
|
all: $(OBJ) dlls $(OBJ)\$(PROJ).exe $(OBJ)\debugger.js
|
||||||
|
|
||||||
|
|
||||||
|
HEADERS = $(JSDB)\jsdb.h \
|
||||||
|
$(JSDB)\jsdbpriv.h
|
||||||
|
|
||||||
|
|
||||||
|
OBJECTS = $(OBJ)\js.obj \
|
||||||
|
$(OBJ)\jsdb.obj \
|
||||||
|
$(OBJ)\jsdrefl.obj
|
||||||
|
|
||||||
|
|
||||||
|
$(OBJECTS) : $(HEADERS)
|
||||||
|
|
||||||
|
|
||||||
|
$(OBJ)\$(PROJ).exe: $(OBJECTS)
|
||||||
|
$(LINK32) $(LFLAGS) $** $(LLIBS)
|
||||||
|
|
||||||
|
.c{$(OBJ)}.obj:
|
||||||
|
$(CPP) $(CFLAGS)
|
||||||
|
|
||||||
|
{$(JSSRC)}.c.obj:
|
||||||
|
$(CPP) $(CFLAGS)
|
||||||
|
|
||||||
|
$(OBJ) :
|
||||||
|
mkdir $(OBJ)
|
||||||
|
|
||||||
|
$(OBJ)\js32.dll :
|
||||||
|
@cd ..\..\src
|
||||||
|
@nmake -f js.mak CFG="js - Win32 Debug"
|
||||||
|
@cd ..\jsd\jsdb
|
||||||
|
@echo Copying dll from js/src
|
||||||
|
@copy $(JSSRC)\$(OBJ)\js32.dll $(OBJ) >NUL
|
||||||
|
@copy $(JSSRC)\$(OBJ)\js32.pdb $(OBJ) >NUL
|
||||||
|
|
||||||
|
$(OBJ)\jsd.dll :
|
||||||
|
@cd ..
|
||||||
|
@nmake -f jsd.mak JSD_THREADSAFE=1
|
||||||
|
@cd jsdb
|
||||||
|
@echo Copying dll from js/jsd
|
||||||
|
@copy $(JSD)\$(OBJ)\jsd.dll $(OBJ) >NUL
|
||||||
|
@copy $(JSD)\$(OBJ)\jsd.pdb $(OBJ) >NUL
|
||||||
|
|
||||||
|
dlls : $(OBJ)\js32.dll $(OBJ)\jsd.dll
|
||||||
|
|
||||||
|
$(OBJ)\debugger.js: *.js
|
||||||
|
@echo Copying *.js
|
||||||
|
@copy *.js $(OBJ) >NUL
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@echo Deleting built files
|
||||||
|
@del $(OBJ)\*.pch >NUL
|
||||||
|
@del $(OBJ)\*.obj >NUL
|
||||||
|
@del $(OBJ)\*.exp >NUL
|
||||||
|
@del $(OBJ)\*.lib >NUL
|
||||||
|
@del $(OBJ)\*.idb >NUL
|
||||||
|
@del $(OBJ)\*.pdb >NUL
|
||||||
|
@del $(OBJ)\*.dll >NUL
|
||||||
|
@del $(OBJ)\*.exe >NUL
|
||||||
|
|
||||||
|
deep_clean: clean
|
||||||
|
@cd ..\..\src
|
||||||
|
@nmake -f js.mak CFG="js - Win32 Debug" clean
|
||||||
|
@cd ..\jsd\jsdb
|
||||||
|
@cd ..
|
||||||
|
@nmake -f jsd.mak clean
|
||||||
|
@cd jsdb
|
|
@ -0,0 +1,117 @@
|
||||||
|
/* -*- 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Private Headers for JSDB
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef jsdbpriv_h___
|
||||||
|
#define jsdbpriv_h___
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "jstypes.h"
|
||||||
|
#include "jsutil.h" /* Added by JSIFY */
|
||||||
|
#include "jsprf.h"
|
||||||
|
#include "jsdbgapi.h"
|
||||||
|
#include "jsdb.h"
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
|
||||||
|
typedef struct JSDB_Data
|
||||||
|
{
|
||||||
|
JSDContext* jsdcTarget;
|
||||||
|
JSRuntime* rtTarget;
|
||||||
|
JSRuntime* rtDebugger;
|
||||||
|
JSContext* cxDebugger;
|
||||||
|
JSObject* globDebugger;
|
||||||
|
JSObject* jsdOb;
|
||||||
|
jsval jsScriptHook;
|
||||||
|
jsval jsExecutionHook;
|
||||||
|
jsval jsErrorReporterHook;
|
||||||
|
JSDThreadState* jsdthreadstate;
|
||||||
|
int debuggerDepth;
|
||||||
|
|
||||||
|
} JSDB_Data;
|
||||||
|
|
||||||
|
extern JSBool
|
||||||
|
jsdb_ReflectJSD(JSDB_Data* data);
|
||||||
|
|
||||||
|
/***********************************/
|
||||||
|
/*
|
||||||
|
* System to store JSD_xxx handles in jsvals. This supports tracking the
|
||||||
|
* handle's type - both for debugging and for automatic 'dropping' of
|
||||||
|
* reference counted handle types (e.g. JSDValue).
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
JSDB_GENERIC = 0,
|
||||||
|
JSDB_CONTEXT,
|
||||||
|
JSDB_SCRIPT,
|
||||||
|
JSDB_SOURCETEXT,
|
||||||
|
JSDB_THREADSTATE,
|
||||||
|
JSDB_STACKFRAMEINFO,
|
||||||
|
JSDB_VALUE,
|
||||||
|
JSDB_PROPERTY,
|
||||||
|
JSDB_OBJECT
|
||||||
|
} JSDBHandleType;
|
||||||
|
|
||||||
|
#define H2P_GENERIC(cx,val) (void*) jsdb_HandleValToPointer((cx),(val),JSDB_GENERIC)
|
||||||
|
#define H2P_CONTEXT(cx,val) (JSDContext*) jsdb_HandleValToPointer((cx),(val),JSDB_CONTEXT)
|
||||||
|
#define H2P_SCRIPT(cx,val) (JSDScript*) jsdb_HandleValToPointer((cx),(val),JSDB_SCRIPT)
|
||||||
|
#define H2P_SOURCETEXT(cx,val) (JSDSourceText*) jsdb_HandleValToPointer((cx),(val),JSDB_SOURCETEXT)
|
||||||
|
#define H2P_THREADSTATE(cx,val) (JSDThreadState*) jsdb_HandleValToPointer((cx),(val),JSDB_THREADSTATE)
|
||||||
|
#define H2P_STACKFRAMEINFO(cx,val) (JSDStackFrameInfo*) jsdb_HandleValToPointer((cx),(val),JSDB_STACKFRAMEINFO)
|
||||||
|
#define H2P_VALUE(cx,val) (JSDValue*) jsdb_HandleValToPointer((cx),(val),JSDB_VALUE)
|
||||||
|
#define H2P_PROPERTY(cx,val) (JSDProperty*) jsdb_HandleValToPointer((cx),(val),JSDB_PROPERTY)
|
||||||
|
#define H2P_OBJECT(cx,val) (JSDObject*) jsdb_HandleValToPointer((cx),(val),JSDB_OBJECT)
|
||||||
|
|
||||||
|
#define P2H_GENERIC(cx,ptr) jsdb_PointerToNewHandleVal((cx),(ptr),JSDB_GENERIC)
|
||||||
|
#define P2H_CONTEXT(cx,ptr) jsdb_PointerToNewHandleVal((cx),(ptr),JSDB_CONTEXT)
|
||||||
|
#define P2H_SCRIPT(cx,ptr) jsdb_PointerToNewHandleVal((cx),(ptr),JSDB_SCRIPT)
|
||||||
|
#define P2H_SOURCETEXT(cx,ptr) jsdb_PointerToNewHandleVal((cx),(ptr),JSDB_SOURCETEXT)
|
||||||
|
#define P2H_THREADSTATE(cx,ptr) jsdb_PointerToNewHandleVal((cx),(ptr),JSDB_THREADSTATE)
|
||||||
|
#define P2H_STACKFRAMEINFO(cx,ptr) jsdb_PointerToNewHandleVal((cx),(ptr),JSDB_STACKFRAMEINFO)
|
||||||
|
#define P2H_VALUE(cx,ptr) jsdb_PointerToNewHandleVal((cx),(ptr),JSDB_VALUE)
|
||||||
|
#define P2H_PROPERTY(cx,ptr) jsdb_PointerToNewHandleVal((cx),(ptr),JSDB_PROPERTY)
|
||||||
|
#define P2H_OBJECT(cx,ptr) jsdb_PointerToNewHandleVal((cx),(ptr),JSDB_OBJECT)
|
||||||
|
|
||||||
|
extern jsval
|
||||||
|
jsdb_PointerToNewHandleVal(JSContext *cx, void* ptr, JSDBHandleType type);
|
||||||
|
|
||||||
|
extern void*
|
||||||
|
jsdb_HandleValToPointer(JSContext *cx, jsval val, JSDBHandleType type);
|
||||||
|
|
||||||
|
/***********************************/
|
||||||
|
|
||||||
|
extern JSBool
|
||||||
|
jsdb_SetThreadState(JSDB_Data* data, JSDThreadState* jsdthreadstate);
|
||||||
|
|
||||||
|
extern uintN JS_DLL_CALLBACK
|
||||||
|
jsdb_ExecHookHandler(JSDContext* jsdc,
|
||||||
|
JSDThreadState* jsdthreadstate,
|
||||||
|
uintN type,
|
||||||
|
void* callerdata,
|
||||||
|
jsval* rval);
|
||||||
|
|
||||||
|
extern JSBool
|
||||||
|
jsdb_EvalReturnExpression(JSDB_Data* data, jsval* rval);
|
||||||
|
|
||||||
|
#endif /* jsdbpriv_h___ */
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1 @@
|
||||||
|
nmake -f jsdb.mak %1 %2 %3 %4 %5 %6 %7 %8 %9
|
|
@ -0,0 +1,56 @@
|
||||||
|
// some tests...
|
||||||
|
|
||||||
|
function set_a(a) {this.a = a;}
|
||||||
|
function set_b(b) {this.b = b;}
|
||||||
|
function set_c(c) {this.c = c;}
|
||||||
|
|
||||||
|
function f_ctor(a,b,c)
|
||||||
|
{
|
||||||
|
this.set_a = set_a;
|
||||||
|
this.set_b = set_b;
|
||||||
|
this.set_c = set_c;
|
||||||
|
|
||||||
|
// NOTE: these break JSD_LOWLEVEL_SOURCE in shell debugger
|
||||||
|
this.get_a = new Function("return this.a;");
|
||||||
|
// this.get_b = new Function("return this.b;");
|
||||||
|
// this.get_c = new Function("return this.c;");
|
||||||
|
|
||||||
|
// this.get_a = function() {return this.a;};
|
||||||
|
this.get_b = function() {return this.b;};
|
||||||
|
this.get_c = function() {return this.c;};
|
||||||
|
|
||||||
|
this.set_a(a);
|
||||||
|
this.set_b(b);
|
||||||
|
this.set_c(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f2_ctor(param)
|
||||||
|
{
|
||||||
|
this.A = new f_ctor(1,2,3);
|
||||||
|
this.b = new f_ctor("A","B","C");
|
||||||
|
this.number = param;
|
||||||
|
}
|
||||||
|
|
||||||
|
function callMe()
|
||||||
|
{
|
||||||
|
var A = new f2_ctor(1);
|
||||||
|
debugger;
|
||||||
|
var b = new f2_ctor(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
function foo(a,b,c,d,e,f)
|
||||||
|
{
|
||||||
|
var g;
|
||||||
|
var h;
|
||||||
|
var i;
|
||||||
|
var j;
|
||||||
|
debugger;
|
||||||
|
}
|
||||||
|
|
||||||
|
A = new f2_ctor(0);
|
||||||
|
AA = new f2_ctor(100);
|
||||||
|
callMe();
|
||||||
|
foo(1,2,3,4,5);
|
||||||
|
|
||||||
|
A.A.set_b(8);
|
||||||
|
print(A.A.get_b());
|
|
@ -0,0 +1 @@
|
||||||
|
load('objects.js')
|
807
js/jsd/jsdebug.c
807
js/jsd/jsdebug.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
1163
js/jsd/jsdebug.h
1163
js/jsd/jsdebug.h
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,112 @@
|
||||||
|
|
||||||
|
PROJ = jsdshell
|
||||||
|
JSD = .
|
||||||
|
JSDJAVA = $(JSD)\java
|
||||||
|
JS = $(JSD)\..\src
|
||||||
|
RUN = $(JSD)\run
|
||||||
|
JSPROJ = js32
|
||||||
|
JSDPROJ = jsd
|
||||||
|
JSDJAVAPROJ = jsdjava
|
||||||
|
|
||||||
|
!IF "$(BUILD_OPT)" != ""
|
||||||
|
OPT = BUILD_OPT=1
|
||||||
|
OBJ = Release
|
||||||
|
CC_FLAGS = /DNDEBUG
|
||||||
|
!ELSE
|
||||||
|
OPT =
|
||||||
|
OBJ = Debug
|
||||||
|
CC_FLAGS = /DDEBUG
|
||||||
|
LINK_FLAGS = /DEBUG
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
QUIET=@
|
||||||
|
|
||||||
|
CFLAGS = /nologo /MDd /W3 /Gm /GX /Zi /Od\
|
||||||
|
/I $(JS)\
|
||||||
|
/I $(JSD)\
|
||||||
|
/DDEBUG /DWIN32 /D_CONSOLE /DXP_PC /D_WINDOWS /D_WIN32\
|
||||||
|
/DJSDEBUGGER\
|
||||||
|
!IF "$(JSDEBUGGER_JAVA_UI)" != ""
|
||||||
|
/I $(JSDJAVA)\
|
||||||
|
/DJSDEBUGGER_JAVA_UI\
|
||||||
|
/DJSD_STANDALONE_JAVA_VM\
|
||||||
|
!ENDIF
|
||||||
|
/DJSD_LOWLEVEL_SOURCE\
|
||||||
|
/DJSFILE\
|
||||||
|
$(CC_FLAGS)\
|
||||||
|
/c /Fp$(OBJ)\$(PROJ).pch /Fd$(OBJ)\$(PROJ).pdb /YX -Fo$@ $<
|
||||||
|
|
||||||
|
LFLAGS = /nologo /subsystem:console /incremental:no /machine:I386 \
|
||||||
|
$(LINK_FLAGS) /pdb:$(OBJ)\$(PROJ).pdb -out:$(OBJ)\$(PROJ).exe
|
||||||
|
|
||||||
|
LLIBS = kernel32.lib advapi32.lib \
|
||||||
|
$(JS)\$(OBJ)\$(JSPROJ).lib \
|
||||||
|
$(JSD)\$(OBJ)\$(JSDPROJ).lib \
|
||||||
|
$(JSDJAVA)\$(OBJ)\$(JSDJAVAPROJ).lib
|
||||||
|
|
||||||
|
CPP=cl.exe
|
||||||
|
LINK32=link.exe
|
||||||
|
|
||||||
|
all: $(OBJ) $(RUN) dlls $(OBJ)\$(PROJ).exe copy_binaries
|
||||||
|
|
||||||
|
$(OBJ)\$(PROJ).exe: \
|
||||||
|
$(OBJ)\js.obj
|
||||||
|
$(QUIET)$(LINK32) $(LFLAGS) $** $(LLIBS)
|
||||||
|
|
||||||
|
|
||||||
|
{$(JS)}.c{$(OBJ)}.obj :
|
||||||
|
$(QUIET)$(CPP) $(CFLAGS)
|
||||||
|
|
||||||
|
dlls :
|
||||||
|
$(QUIET)cd ..\src
|
||||||
|
!IF "$(BUILD_OPT)" != ""
|
||||||
|
$(QUIET)nmake -f js.mak CFG="js - Win32 Release"
|
||||||
|
!ELSE
|
||||||
|
$(QUIET)nmake -f js.mak CFG="js - Win32 Debug"
|
||||||
|
!ENDIF
|
||||||
|
$(QUIET)cd ..\jsd
|
||||||
|
$(QUIET)nmake -f jsd.mak JSD_THREADSAFE=1 $(OPT)
|
||||||
|
$(QUIET)cd java
|
||||||
|
$(QUIET)nmake -f jsdjava.mak JSD_STANDALONE_JAVA_VM=1 $(OPT)
|
||||||
|
$(QUIET)cd ..
|
||||||
|
|
||||||
|
copy_binaries :
|
||||||
|
@echo copying binaries
|
||||||
|
$(QUIET)copy $(JS)\$(OBJ)\$(JSPROJ).dll $(RUN) >NUL
|
||||||
|
$(QUIET)copy $(JS)\$(OBJ)\$(JSPROJ).pdb $(RUN) >NUL
|
||||||
|
$(QUIET)copy $(JSD)\$(OBJ)\$(JSDPROJ).dll $(RUN) >NUL
|
||||||
|
$(QUIET)copy $(JSD)\$(OBJ)\$(JSDPROJ).pdb $(RUN) >NUL
|
||||||
|
$(QUIET)copy $(JSDJAVA)\$(OBJ)\$(JSDJAVAPROJ).dll $(RUN) >NUL
|
||||||
|
$(QUIET)copy $(JSDJAVA)\$(OBJ)\$(JSDJAVAPROJ).pdb $(RUN) >NUL
|
||||||
|
$(QUIET)copy $(OBJ)\$(PROJ).pdb $(RUN) >NUL
|
||||||
|
$(QUIET)copy $(OBJ)\$(PROJ).exe $(RUN) >NUL
|
||||||
|
|
||||||
|
$(OBJ) :
|
||||||
|
$(QUIET)mkdir $(OBJ)
|
||||||
|
|
||||||
|
$(RUN) :
|
||||||
|
$(QUIET)mkdir $(RUN)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@echo deleting old output
|
||||||
|
$(QUIET)del $(OBJ)\js.obj >NUL
|
||||||
|
$(QUIET)del $(OBJ)\$(PROJ).pch >NUL
|
||||||
|
$(QUIET)del $(OBJ)\$(PROJ)*.idb >NUL
|
||||||
|
$(QUIET)del $(OBJ)\$(PROJ).pdb >NUL
|
||||||
|
$(QUIET)del $(OBJ)\$(PROJ).exe >NUL
|
||||||
|
$(QUIET)del $(RUN)\*.pdb >NUL
|
||||||
|
$(QUIET)del $(RUN)\*.exe >NUL
|
||||||
|
$(QUIET)del $(RUN)\*.dll >NUL
|
||||||
|
|
||||||
|
deep_clean: clean
|
||||||
|
$(QUIET)cd ..\src
|
||||||
|
!IF "$(BUILD_OPT)" != ""
|
||||||
|
$(QUIET)nmake -f js.mak CFG="js - Win32 Release" clean
|
||||||
|
!ELSE
|
||||||
|
$(QUIET)nmake -f js.mak CFG="js - Win32 Debug" clean
|
||||||
|
!ENDIF
|
||||||
|
$(QUIET)cd ..\jsd
|
||||||
|
$(QUIET)nmake -f jsd.mak clean
|
||||||
|
$(QUIET)cd java
|
||||||
|
$(QUIET)nmake -f jsdjava.mak clean
|
||||||
|
$(QUIET)cd ..
|
|
@ -16,6 +16,10 @@
|
||||||
* Reserved.
|
* Reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* this is all going away... replaced by code in js/jsd/java */
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
#ifndef XP_MAC
|
#ifndef XP_MAC
|
||||||
#include "_stubs/netscape_jsdebug_Script.c"
|
#include "_stubs/netscape_jsdebug_Script.c"
|
||||||
#include "_stubs/netscape_jsdebug_DebugController.c"
|
#include "_stubs/netscape_jsdebug_DebugController.c"
|
||||||
|
@ -31,3 +35,5 @@
|
||||||
#include "netscape_jsdebug_JSPC.c"
|
#include "netscape_jsdebug_JSPC.c"
|
||||||
#include "n_j_JSSourceTextProvider.c"
|
#include "n_j_JSSourceTextProvider.c"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,35 +1,29 @@
|
||||||
#!gmake
|
#// 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
|
||||||
# The contents of this file are subject to the Netscape Public License
|
#// compliance with the NPL. You may obtain a copy of the NPL at
|
||||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
#// http://www.mozilla.org/NPL/
|
||||||
# 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
|
||||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
#// for the specific language governing rights and limitations under the
|
||||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
#// 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
|
||||||
# The Initial Developer of this code under the NPL is Netscape
|
#// Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||||
# Communications Corporation. Portions created by Netscape are
|
#// Reserved.
|
||||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
||||||
# Reserved.
|
|
||||||
|
|
||||||
IGNORE_MANIFEST=1
|
|
||||||
|
|
||||||
#
|
|
||||||
#//------------------------------------------------------------------------
|
#//------------------------------------------------------------------------
|
||||||
#//
|
#//
|
||||||
#// Specify the depth of the current directory relative to the
|
#// Specify the depth of the current directory relative to the
|
||||||
#// root of NS
|
#// root of NS
|
||||||
#//
|
#//
|
||||||
#//------------------------------------------------------------------------
|
#//------------------------------------------------------------------------
|
||||||
|
DEPTH=..\..
|
||||||
|
include <$(DEPTH)\config\config.mak>
|
||||||
|
|
||||||
DEPTH = ..\..
|
!ifdef MOZ_OJI
|
||||||
|
# DIRS = java classes
|
||||||
# Turn on/off depending on
|
|
||||||
!ifdef MOZ_JSD
|
|
||||||
DIRS = classes
|
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
#//------------------------------------------------------------------------
|
#//------------------------------------------------------------------------
|
||||||
|
@ -41,87 +35,58 @@ DIRS = classes
|
||||||
DLLNAME = jsd$(MOZ_BITS)$(VERSION_NUMBER)
|
DLLNAME = jsd$(MOZ_BITS)$(VERSION_NUMBER)
|
||||||
PDBFILE = $(DLLNAME).pdb
|
PDBFILE = $(DLLNAME).pdb
|
||||||
MAPFILE = $(DLLNAME).map
|
MAPFILE = $(DLLNAME).map
|
||||||
RESFILE = $(DLLNAME).res
|
RESFILE = jsd$(MOZ_BITS)40.res
|
||||||
DLL =.\$(OBJDIR)\$(DLLNAME).dll
|
DLL =.\$(OBJDIR)\$(DLLNAME).dll
|
||||||
MAKE_OBJ_TYPE = DLL
|
MAKE_OBJ_TYPE = DLL
|
||||||
|
|
||||||
!if "$(MOZ_BITS)" != "16"
|
!if "$(MOZ_BITS)" != "16"
|
||||||
LINCS = -I$(PUBLIC)/java \
|
LINCS = -I$(DEPTH)\include \
|
||||||
-I$(PUBLIC)/applet \
|
-I$(PUBLIC)\js
|
||||||
-I$(DEPTH)\include
|
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
!if "$(MOZ_BITS)" == "16"
|
!if "$(MOZ_BITS)" == "16"
|
||||||
DEFFILE = $(DLLNAME).def
|
DEFFILE = $(DLLNAME).def
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
|
# LCFLAGS= $(LCFLAGS) -DEXPORT_JSD_API -DJSD_THREADSAFE
|
||||||
|
|
||||||
LLIBS= $(LIBNSPR) \
|
LLIBS= $(LIBNSPR) \
|
||||||
$(DIST)\lib\js$(MOZ_BITS)$(VERSION_NUMBER).lib \
|
$(DIST)\lib\js$(MOZ_BITS)$(VERSION_NUMBER).lib \
|
||||||
$(DIST)\lib\jrt$(MOZ_BITS)$(VERSION_NUMBER).lib
|
!ifdef MOZ_OJI
|
||||||
|
$(DIST)\lib\oji$(MOZ_BITS).lib
|
||||||
|
!endif
|
||||||
|
|
||||||
!if "$(MOZ_BITS)"=="32" && defined(MOZ_DEBUG) && defined(GLOWCODE)
|
!if "$(MOZ_BITS)"=="32" && defined(MOZ_DEBUG) && defined(GLOWCODE)
|
||||||
LLIBS=$(LLIBS) $(GLOWDIR)\glowcode.lib
|
LLIBS=$(LLIBS) $(GLOWDIR)\glowcode.lib
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
|
#//------------------------------------------------------------------------
|
||||||
|
#//
|
||||||
|
#// Define the files necessary to build the target (ie. OBJS)
|
||||||
|
#//
|
||||||
|
#//------------------------------------------------------------------------
|
||||||
|
OBJS = \
|
||||||
|
.\$(OBJDIR)\jsdebug.obj \
|
||||||
|
.\$(OBJDIR)\jsd_high.obj \
|
||||||
|
.\$(OBJDIR)\jsd_hook.obj \
|
||||||
|
.\$(OBJDIR)\jsd_lock.obj \
|
||||||
|
.\$(OBJDIR)\jsd_scpt.obj \
|
||||||
|
.\$(OBJDIR)\jsd_stak.obj \
|
||||||
|
.\$(OBJDIR)\jsd_step.obj \
|
||||||
|
.\$(OBJDIR)\jsd_text.obj \
|
||||||
|
.\$(OBJDIR)\jsd_val.obj \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
#//------------------------------------------------------------------------
|
#//------------------------------------------------------------------------
|
||||||
#//
|
#//
|
||||||
#// install headers
|
#// install headers
|
||||||
#//
|
#//
|
||||||
#//------------------------------------------------------------------------
|
#//------------------------------------------------------------------------
|
||||||
|
INSTALL_DIR=$(PUBLIC)\jsd
|
||||||
INSTALL_DIR=$(PUBLIC)\jsdebug
|
|
||||||
|
|
||||||
INSTALL_FILE_LIST= \
|
INSTALL_FILE_LIST= \
|
||||||
jsdebug.h \
|
jsdebug.h \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
|
||||||
MODULE=jsdebug
|
|
||||||
|
|
||||||
REQUIRES=java js nspr
|
|
||||||
|
|
||||||
CSRCS= \
|
|
||||||
jsdebug.c \
|
|
||||||
jsd_high.c \
|
|
||||||
jsd_hook.c \
|
|
||||||
!ifdef MOZ_JSD
|
|
||||||
jsdstubs.c \
|
|
||||||
jsd_java.c \
|
|
||||||
!endif
|
|
||||||
jsd_scpt.c \
|
|
||||||
jsd_stak.c \
|
|
||||||
jsd_text.c
|
|
||||||
|
|
||||||
LIBRARY_NAME=jsd
|
|
||||||
|
|
||||||
!ifdef MOZ_JSD
|
|
||||||
JDK_GEN=netscape.jsdebug.Script netscape.jsdebug.DebugController \
|
|
||||||
netscape.jsdebug.JSThreadState netscape.jsdebug.JSStackFrameInfo \
|
|
||||||
netscape.jsdebug.JSPC netscape.jsdebug.JSSourceTextProvider \
|
|
||||||
netscape.jsdebug.JSErrorReporter
|
|
||||||
!endif
|
|
||||||
|
|
||||||
EXPORTS=jsdebug.h
|
|
||||||
|
|
||||||
C_OBJS= \
|
|
||||||
.\$(OBJDIR)\jsdebug.obj \
|
|
||||||
.\$(OBJDIR)\jsd_high.obj \
|
|
||||||
.\$(OBJDIR)\jsd_hook.obj \
|
|
||||||
!ifdef MOZ_JSD
|
|
||||||
.\$(OBJDIR)\jsdstubs.obj \
|
|
||||||
.\$(OBJDIR)\jsd_java.obj \
|
|
||||||
!endif
|
|
||||||
.\$(OBJDIR)\jsd_scpt.obj \
|
|
||||||
.\$(OBJDIR)\jsd_stak.obj \
|
|
||||||
.\$(OBJDIR)\jsd_text.obj
|
|
||||||
|
|
||||||
|
|
||||||
!if "$(MOZ_BITS)" != "16"
|
|
||||||
LINCS=-I$(XPDIST)\public\java -I$(XPDIST)\public\js \
|
|
||||||
-I$(XPDIST)\public\nspr
|
|
||||||
!endif
|
|
||||||
|
|
||||||
#//------------------------------------------------------------------------
|
#//------------------------------------------------------------------------
|
||||||
#//
|
#//
|
||||||
#// Include the common makefile rules
|
#// Include the common makefile rules
|
||||||
|
@ -133,18 +98,6 @@ install:: $(DLL)
|
||||||
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).dll $(DIST)\bin
|
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).dll $(DIST)\bin
|
||||||
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).lib $(DIST)\lib
|
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).lib $(DIST)\lib
|
||||||
|
|
||||||
clobber::
|
|
||||||
$(RM_R) _gen
|
|
||||||
$(RM_R) _stubs
|
|
||||||
|
|
||||||
.\$(OBJDIR)\jsdstubs.o: \
|
|
||||||
$(JDK_STUB_DIR)\netscape_jsdebug_Script.c \
|
|
||||||
$(JDK_STUB_DIR)\netscape_jsdebug_DebugController.c \
|
|
||||||
$(JDK_STUB_DIR)\netscape_jsdebug_JSThreadState.c \
|
|
||||||
$(JDK_STUB_DIR)\netscape_jsdebug_JSStackFrameInfo.c \
|
|
||||||
$(JDK_STUB_DIR)\netscape_jsdebug_JSPC.c \
|
|
||||||
$(JDK_STUB_DIR)\netscape_jsdebug_JSSourceTextProvider.c
|
|
||||||
|
|
||||||
export:: INSTALL_FILES
|
export:: INSTALL_FILES
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
@echo off
|
||||||
|
REM nmake -f jsdshell.mak JSDEBUGGER_JAVA_UI=1 LIVECONNECT=1 %1 %2 %3 %4 %5
|
||||||
|
@echo on
|
||||||
|
nmake -f jsdshell.mak JSDEBUGGER_JAVA_UI=1 %1 %2 %3 %4 %5
|
Загрузка…
Ссылка в новой задаче