diff --git a/lib/javascript/.cvsignore b/lib/javascript/.cvsignore deleted file mode 100644 index cb1c7bae..00000000 --- a/lib/javascript/.cvsignore +++ /dev/null @@ -1,9 +0,0 @@ -*.pdb -*.ncb -*.opt -*.plg -Debug -Release -Makefile -jscpucfg -jsautocfg.h diff --git a/lib/javascript/.gitignore b/lib/javascript/.gitignore deleted file mode 100644 index c0ce277d..00000000 --- a/lib/javascript/.gitignore +++ /dev/null @@ -1 +0,0 @@ -Linux_All_DBG.OBJ diff --git a/lib/javascript/Makefile b/lib/javascript/Makefile deleted file mode 100644 index 5fd7b7db..00000000 --- a/lib/javascript/Makefile +++ /dev/null @@ -1,369 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Michael Ang -# Kevin Buhr -# -# Alternatively, the contents of this file may be used under the terms of -# either of the GNU General Public License Version 2 or later (the "GPL"), -# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# JSRef GNUmake makefile. -# -# Note: dependency rules are missing for some files (some -# .h, all .msg, etc.) Re-make clean if in doubt. -# - - -DEPTH = . - -include config.mk - -#NS_USE_NATIVE = 1 - -ifdef USE_MSVC -OTHER_LIBS += fdlibm/$(OBJDIR)/fdlibm.lib -else -OTHER_LIBS += -Lfdlibm/$(OBJDIR) -lfdm -endif - -ifdef JS_THREADSAFE -DEFINES += -DJS_THREADSAFE -INCLUDES += -I../../dist/$(OBJDIR)/include -ifdef USE_MSVC -OTHER_LIBS += ../../dist/$(OBJDIR)/lib/libnspr${NSPR_LIBSUFFIX}.lib -else -OTHER_LIBS += -L../../dist/$(OBJDIR)/lib -lnspr${NSPR_LIBSUFFIX} -endif -endif - -ifdef JS_NO_THIN_LOCKS -DEFINES += -DJS_USE_ONLY_NSPR_LOCKS -endif - -ifdef JS_HAS_FILE_OBJECT -DEFINES += -DJS_HAS_FILE_OBJECT -endif - -# -# XCFLAGS may be set in the environment or on the gmake command line -# -CFLAGS += $(OPTIMIZER) $(OS_CFLAGS) $(DEFINES) $(INCLUDES) $(XCFLAGS) - -LDFLAGS = $(XLDFLAGS) - -ifndef NO_LIBM -LDFLAGS += -lm -endif - -# Prevent floating point errors caused by VC++ optimizations -ifeq ($(OS_ARCH),WINNT) -_MSC_VER = $(shell $(CC) 2>&1 | sed -n 's/.*Compiler Version \([0-9]*\)\.\([0-9]*\).*/\1\2/p') -ifeq (,$(filter-out 1200 1300 1310,$(_MSC_VER))) -CFLAGS += -Op -else -CFLAGS += -fp:precise -endif -endif # WINNT - -# -# Ask perl what flags it was built with, so we can build js with similar flags -# and link properly. Viva gmake. -# -ifdef JS_PERLCONNECT -DEFINES += -DPERLCONNECT -D_GNU_SOURCE - -PERLCFLAGS := $(shell perl -MExtUtils::Embed -e ccopts) -PERLLDFLAGS := $(shell perl -MExtUtils::Embed -e ldopts) - -# perl erroneously reports compiler flag -rdynamic (interpreted by ld -# as -r) when it really meant -export-dynamic. -PERLLDFLAGS := $(subst -rdynamic,-export-dynamic,$(PERLLDFLAGS)) - -CFLAGS += $(PERLCFLAGS) -#LDFLAGS += $(PERLLDFLAGS) #PH removed this assgnment -INCLUDES += -I. #needed for perlconnect/jsperl.c -endif - -# -# Server-related changes : -# -ifdef NES40 -DEFINES += -DNES40 -endif - -# -# Line editing support. -# Define JS_READLINE or JS_EDITLINE to enable line editing in the -# js command-line interpreter. -# -ifdef JS_READLINE -# For those platforms with the readline library installed. -DEFINES += -DEDITLINE -PROG_LIBS += -lreadline -ltermcap -else -ifdef JS_EDITLINE -# Use the editline library, built locally. -PREDIRS += editline -DEFINES += -DEDITLINE -PROG_LIBS += editline/$(OBJDIR)/libedit.a -endif -endif - -# For purify -PURE_CFLAGS = -DXP_UNIX $(OPTIMIZER) $(PURE_OS_CFLAGS) $(DEFINES) \ - $(INCLUDES) $(XCFLAGS) - -# -# JS file lists -# -JS_HFILES = \ - jsarray.h \ - jsatom.h \ - jsbool.h \ - jsconfig.h \ - jscntxt.h \ - jsdate.h \ - jsemit.h \ - jsexn.h \ - jsfun.h \ - jsgc.h \ - jsinterp.h \ - jslibmath.h \ - jslock.h \ - jsmath.h \ - jsnum.h \ - jsobj.h \ - jsopcode.h \ - jsparse.h \ - jsarena.h \ - jsclist.h \ - jsdhash.h \ - jsdtoa.h \ - jshash.h \ - jslong.h \ - jsosdep.h \ - jstypes.h \ - jsprvtd.h \ - jspubtd.h \ - jsregexp.h \ - jsscan.h \ - jsscope.h \ - jsscript.h \ - jsstr.h \ - jsxdrapi.h \ - jsxml.h \ - $(NULL) - -API_HFILES = \ - jsapi.h \ - jsdbgapi.h \ - $(NULL) - -OTHER_HFILES = \ - jsbit.h \ - jscompat.h \ - jscpucfg.h \ - jsotypes.h \ - jsstddef.h \ - prmjtime.h \ - resource.h \ - jsopcode.tbl \ - js.msg \ - jsshell.msg \ - $(NULL) - -ifndef PREBUILT_CPUCFG -OTHER_HFILES += $(OBJDIR)/jsautocfg.h -endif - -HFILES = $(JS_HFILES) $(API_HFILES) $(OTHER_HFILES) - -JS_CFILES = \ - jsapi.c \ - jsarena.c \ - jsarray.c \ - jsatom.c \ - jsbool.c \ - jscntxt.c \ - jsdate.c \ - jsdbgapi.c \ - jsdhash.c \ - jsdtoa.c \ - jsemit.c \ - jsexn.c \ - jsfun.c \ - jsgc.c \ - jshash.c \ - jsinterp.c \ - jslock.c \ - jslog2.c \ - jslong.c \ - jsmath.c \ - jsnum.c \ - jsobj.c \ - jsopcode.c \ - jsparse.c \ - jsprf.c \ - jsregexp.c \ - jsscan.c \ - jsscope.c \ - jsscript.c \ - jsstr.c \ - jsutil.c \ - jsxdrapi.c \ - jsxml.c \ - prmjtime.c \ - $(NULL) - -PREDIRS += fdlibm - -ifdef USE_MSVC -FDLIBM_LIBRARY = fdlibm/$(OBJDIR)/fdlibm.lib -else -FDLIBM_LIBRARY = fdlibm/$(OBJDIR)/libfdm.a -endif -JSMATH_PRELINK = $(OBJDIR)/jsmathtemp.o -# Flag for incremental linking -DASH_R = -r - -ifeq ($(OS_ARCH),QNX) -ifneq ($(OS_TARGET),NTO) -# Don't use wildcard here, because we only want this resolved at link time. -OBJS += fdlibm/*.o -endif -endif - -ifdef JS_LIVECONNECT -DIRS += liveconnect -endif - -ifdef JS_PERLCONNECT -JS_CFILES += perlconnect/jsperl.c -endif - -ifdef JS_HAS_FILE_OBJECT -JS_CFILES += jsfile.c -JS_HFILES += jsfile.h -endif - -LIB_CFILES = $(JS_CFILES) -LIB_ASFILES := $(wildcard *_$(OS_ARCH).s) -PROG_CFILES = js.c - -include rules.mk - -MOZ_DEPTH = ../.. -include jsconfig.mk - -nsinstall-target: - cd ../../config; $(MAKE) OBJDIR=$(OBJDIR) OBJDIR_NAME=$(OBJDIR) -ifdef USE_MSVC -$(PROGRAM): $(PROG_OBJS) $(LIBRARY) $(FDLIBM_LIBRARY) - link.exe -out:"$@" $(EXE_LINK_FLAGS) $^ -else -$(PROGRAM): $(PROG_OBJS) $(LIBRARY) $(FDLIBM_LIBRARY) - $(CC) -o $@ $(CFLAGS) $(PROG_OBJS) $(LIBRARY) $(LDFLAGS) $(OTHER_LIBS) \ - $(PROG_LIBS) -endif - -$(PROGRAM).pure: $(PROG_OBJS) $(LIBRARY) - purify $(PUREFLAGS) \ - $(CC) -o $@ $(PURE_OS_CFLAGS) $(PROG_OBJS) $(LIBRARY) $(LDFLAGS) \ - $(OTHER_LIBS) $(PROG_LIBS) - -ifndef PREBUILT_CPUCFG -$(HFILES) $(CFILES): $(OBJDIR)/jsautocfg.h - -$(OBJDIR)/jsautocfg.h: $(OBJDIR)/jscpucfg - rm -f $@ - $(OBJDIR)/jscpucfg > $@ - -$(OBJDIR)/jscpucfg: $(OBJDIR)/jscpucfg.o - $(CC) -o $@ $(OBJDIR)/jscpucfg.o - -# Look in OBJDIR to find jsautocfg.h -INCLUDES += -I$(OBJDIR) - -# Add to TARGETS for clobber rule -TARGETS += $(OBJDIR)/jsautocfg.h $(OBJDIR)/jscpucfg \ - $(OBJDIR)/jscpucfg.o $(OBJDIR)/jsmathtemp.o -endif - - -# special rule for jsmath.o since we want to incrementally link -# against fdlibm to pull in only what is needed -$(OBJDIR)/jsmath.o: jsmath.c jsmath.h jslibmath.h $(FDLIBM_LIBRARY) -ifneq (,$(filter OS2 WINNT,$(OS_ARCH))) - $(CC) -Fo$(JSMATH_PRELINK) -c $(CFLAGS) $< -else - $(CC) -o $(JSMATH_PRELINK) -c $(CFLAGS) $< -endif - -ifeq ($(OS_ARCH),QNX) -ifneq ($(OS_TARGET),NTO) - @cp $(JSMATH_PRELINK) $@ -else - $(LD) $(DASH_R) -o $@ $(JSMATH_PRELINK) $(FDLIBM_LIBRARY) -endif -else -ifdef USE_MSVC - @echo Warning: to use $(LIBRARY) must also link against $(FDLIBM_LIBRARY) - @cp $(JSMATH_PRELINK) $@ -endif - $(LD) $(DASH_R) -o $@ $(JSMATH_PRELINK) $(FDLIBM_LIBRARY) -endif - -# Note: generated headers must be built before descending -# into fdlibm directory -$(FDLIBM_LIBRARY) : - $(MAKE) -C fdlibm -f Makefile.ref $(@F) - -# -# Hardwire dependencies on jsopcode.tbl -# -jsopcode.h jsopcode.c: jsopcode.tbl - --include $(DEPENDENCIES) - -TARNAME = jsref.tar -TARFILES = files `cat files` - -SUFFIXES: .i -%.i: %.c - $(CC) -C -E $(CFLAGS) $< > $*.i - -install: - echo "no install for javascript" diff --git a/lib/javascript/Makefile.in b/lib/javascript/Makefile.in deleted file mode 100644 index 444bc67c..00000000 --- a/lib/javascript/Makefile.in +++ /dev/null @@ -1,410 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either of the GNU General Public License Version 2 or later (the "GPL"), -# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -DEPTH = ../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(DEPTH)/config/autoconf.mk - -MODULE = js -LIBRARY_NAME = mozjs -LIB_IS_C_ONLY = 1 -GRE_MODULE = 1 - -ifeq (,$(filter-out WINNT WINCE,$(OS_ARCH))) -LIBRARY_NAME = js$(MOZ_BITS)$(VERSION_NUMBER) -RESFILE = js$(MOZ_BITS)40.res -endif - -PACKAGE_FILE = js.pkg - -# JavaScript must be built shared, even for static builds, as it is used by -# other modules which are always built shared. Failure to do so results in -# the js code getting copied into xpinstall and jsd as well as mozilla-bin, -# and then the static data cells used for locking no longer work. -FORCE_SHARED_LIB = 1 - -CSRCS = \ - jsapi.c \ - jsarena.c \ - jsarray.c \ - jsatom.c \ - jsbool.c \ - jscntxt.c \ - jsdate.c \ - jsdbgapi.c \ - jsdhash.c \ - jsdtoa.c \ - jsemit.c \ - jsexn.c \ - jsfun.c \ - jsgc.c \ - jshash.c \ - jsinterp.c \ - jslock.c \ - jslog2.c \ - jslong.c \ - jsmath.c \ - jsnum.c \ - jsobj.c \ - jsopcode.c \ - jsparse.c \ - jsprf.c \ - jsregexp.c \ - jsscan.c \ - jsscope.c \ - jsscript.c \ - jsstr.c \ - jsutil.c \ - jsxdrapi.c \ - jsxml.c \ - prmjtime.c \ - $(NULL) - -EXPORTS = \ - jsautocfg.h \ - js.msg \ - jsapi.h \ - jsarray.h \ - jsarena.h \ - jsatom.h \ - jsbit.h \ - jsbool.h \ - jsclist.h \ - jscntxt.h \ - jscompat.h \ - jsconfig.h \ - jsdate.h \ - jsdbgapi.h \ - jsdhash.h \ - jsemit.h \ - jsfun.h \ - jsgc.h \ - jshash.h \ - jsinterp.h \ - jslock.h \ - jslong.h \ - jsmath.h \ - jsnum.h \ - jsobj.h \ - jsopcode.tbl \ - jsopcode.h \ - jsosdep.h \ - jsotypes.h \ - jsparse.h \ - jsprf.h \ - jsprvtd.h \ - jspubtd.h \ - jsregexp.h \ - jsscan.h \ - jsscope.h \ - jsscript.h \ - jsstddef.h \ - jsstr.h \ - jstypes.h \ - jsutil.h \ - jsxdrapi.h \ - jsxml.h \ - $(NULL) - -ifeq (,$(filter-out WINNT WINCE,$(OS_ARCH))) -EXPORTS += jscpucfg.h -endif - -FDLIBM_LIBRARY = fdlibm/$(LIB_PREFIX)fdm.$(LIB_SUFFIX) -JSMATH_PRELINK = jsmathtemp.o -JS_SAFE_ARENA = 1 - -DASH_R = -r - -include $(topsrcdir)/config/config.mk - -EXTRA_DSO_LDOPTS += $(NSPR_LIBS) - -ifeq (,$(filter-out OS2 WINNT WINCE,$(OS_ARCH))) -SHARED_LIBRARY_LIBS += $(FDLIBM_LIBRARY) -endif - -# When using gcc the assembly is inlined in the C-file (see jslock.c) -ifeq ($(OS_ARCH),SunOS) -ifneq ($(OS_TEST),i86pc) -ifndef GNU_CC -ASFILES = lock_$(OS_ARCH).s -endif -endif -endif - -ifndef BUILD_OPT -MOCHAFILE = 1 -endif - -ifndef NSBUILDROOT -JSJAVA_STUBHEADERS = \ - -I$(topsrcdir)/sun-java/include/_gen \ - -I$(topsrcdir)/sun-java/netscape/javascript/_jri \ - -I$(topsrcdir)/sun-java/netscape/security/_jri -else -JSJAVA_STUBHEADERS = -I$(JRI_GEN_DIR) -I$(JDK_GEN_DIR) -endif - -JSJAVA_CFLAGS = \ - -I$(topsrcdir)/sun-java/md-include \ - -I$(topsrcdir)/sun-java/include \ - $(JSJAVA_STUBHEADERS) - -include $(topsrcdir)/config/rules.mk - -DEFINES += -DEXPORT_JS_API - -INCLUDES += -I$(srcdir) - -# MSVC '-Gy' cc flag and '/OPT:REF' linker flag cause JS_GetArgument and -# JS_GetLocalVariable to be folded to the same address by the linker, -# leading to a crash on startup. See bug 151066. So, in optimized builds, -# add the /OPT:NOICF flag, which turns off 'identical COMDAT folding'. -# -# N.B.: 'identical COMDAT folding' that folds functions whose addresses -# are taken violates the ISO C and C++ standards. -ifndef MOZ_DEBUG -ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH)) -LDFLAGS += -OPT:NOICF -endif -endif - -GARBAGE += $(JSMATH_PRELINK) jscpucfg.o jsautocfg.h jsautocfg.tmp jscpucfg - -ifneq (,$(CROSS_COMPILE)$(filter-out WINNT,$(OS_ARCH))) -TARGETS += jscpucfg$(HOST_BIN_SUFFIX) -endif - -ifdef JS_SAFE_ARENA -DEFINES += -DJS_USE_SAFE_ARENA -endif - -ifdef JS_THREADSAFE -DEFINES += -DJS_THREADSAFE -endif - -ifdef JS_NO_THIN_LOCKS -DEFINES += -DJS_USE_ONLY_NSPR_LOCKS -endif - -ifdef JS_VERSION -DEFINES += -DJS_VERSION=$(JS_VERSION) -endif - -ifneq ($(findstring -L,$(NSPR_LIBS)),) -NSPR_STATIC_PATH = $(subst -L,,$(findstring -L,$(NSPR_LIBS))) -else -NSPR_STATIC_PATH = $(DIST)/lib -endif - -LDFLAGS += $(pathsubst -l%,$(NSPR_STATIC_PATH)/%.a,$(NSPR_LIBS)) - -# BeOS and HP-UX do not require the extra linking of "-lm" -ifeq (,$(filter BeOS HP-UX WINNT WINCE OpenVMS,$(OS_ARCH))) -LDFLAGS += -lm -endif - -# Prevent floating point errors caused by VC++ optimizations -ifeq ($(OS_ARCH)_$(GNU_CC),WINNT_) -ifeq (,$(filter-out 1200 1300 1310,$(_MSC_VER))) -CFLAGS += -Op -else -CFLAGS += -fp:precise -endif -endif # WINNT - -ifeq ($(OS_ARCH),FreeBSD) -LDFLAGS += -pthread -endif -ifeq ($(OS_ARCH),IRIX) -ifdef USE_N32 -DASH_R += -n32 -endif -endif -ifeq ($(OS_ARCH),Linux) -LDFLAGS += -ldl -endif -ifeq ($(OS_ARCH),OSF1) -LDFLAGS += -lc_r -endif -ifeq ($(OS_ARCH),SunOS) -ifeq ($(TARGET_CPU),sparc) - -ifdef JS_ULTRASPARC_OPTS -DEFINES += -DULTRA_SPARC -ifdef GNU_CC -CFLAGS += -Wa,-xarch=v8plus,-DULTRA_SPARC,-P,-L,-D_ASM,-D__STDC__=0 -CXXFLAGS += -Wa,-xarch=v8plus,-DULTRA_SPARC,-P,-L,-D_ASM,-D__STDC__=0,-K,PIC -else -ASFLAGS += -xarch=v8plus -DULTRA_SPARC -P -L -D_ASM -D__STDC__=0 -K PIC -endif # GNU_CC -endif # JS_ULTRASPARC_OPTS - -endif -ifeq ($(OS_RELEASE),4.1) -LDFLAGS += -ldl -lnsl -else -LDFLAGS += -lposix4 -ldl -lnsl -lsocket -endif -endif - -ifeq ($(OS_ARCH),QNX) -ifneq ($(OS_TARGET),NTO) -# Don't use wildcard here, because we only want this resolved at link time. -OBJS += fdlibm/*.o -endif -endif - -ifeq ($(OS_ARCH),IRIX) -ifndef GNU_CC -_COMPILE_CFLAGS = $(patsubst -O%,-O1,$(COMPILE_CFLAGS)) -jsapi.o jsarena.o jsarray.o jsatom.o jsemit.o jsfun.o jsinterp.o jsregexp.o jsparse.o jsopcode.o jsscript.o: %.o: %.c Makefile.in - $(REPORT_BUILD) - @$(MAKE_DEPS_AUTO) - $(CC) -o $@ -c $(_COMPILE_CFLAGS) $< -endif -endif - -# On OS/2 & win32 we are already linking against fdlibm, so don't bother -# creating jsmathtemp -ifeq (,$(filter OS2 WINNT OpenVMS,$(OS_ARCH))) -# special rule for jsmath.o since we want to incrementally link -# against fdlibm to pull in only what is needed -# Do this in a single step to avoid dependency problems -jsmath.o: jsmath.c $(FDLIBM_LIBRARY) Makefile.in - $(REPORT_BUILD) - @$(MAKE_DEPS_AUTO) - $(ELOG) $(CC) $(OUTOPTION)$(JSMATH_PRELINK) -c $(COMPILE_CFLAGS) $< -ifeq ($(OS_ARCH),QNX) -ifneq ($(OS_TARGET),NTO) - @cp $(JSMATH_PRELINK) $@ -else - $(LD) $(DASH_R) -o $@ $(JSMATH_PRELINK) $(FDLIBM_LIBRARY) -endif -else - $(LD) $(DASH_R) -o $@ $(JSMATH_PRELINK) $(FDLIBM_LIBRARY) -endif - @$(RM) -f $(JSMATH_PRELINK) -else -# Create dependency so we build fdlibm -jsmath.o: $(FDLIBM_LIBRARY) Makefile.in -endif - -# An AIX Optimization bug causes PR_dtoa() & JS_dtoa to produce wrong result. -# This suppresses optimization for this single compilation unit. -ifeq ($(OS_ARCH),AIX) -jsatom.o: jsatom.c Makefile.in - $(REPORT_BUILD) - @$(MAKE_DEPS_AUTO) - $(CC) -o $@ -c $(filter-out $(MOZ_OPTIMIZE_FLAGS), $(COMPILE_CFLAGS)) $< -jsdtoa.o: jsdtoa.c Makefile.in - $(REPORT_BUILD) - @$(MAKE_DEPS_AUTO) - $(CC) -o $@ -c $(filter-out $(MOZ_OPTIMIZE_FLAGS), $(COMPILE_CFLAGS)) $< -endif - -$(FDLIBM_LIBRARY): - $(MAKE) -C $(@D) $(@F) - -jsopcode.h jsopcode.c: jsopcode.tbl - -ifeq (,$(CROSS_COMPILE)$(filter-out WINNT,$(OS_ARCH))) -jsautocfg.h: - touch $@ -else -ifeq ($(OS_ARCH),WINCE) -jsautocfg.h: - touch $@ -else -jsautocfg.h: jscpucfg$(HOST_BIN_SUFFIX) - @rm -f $@ jsautocfg.tmp - ./jscpucfg > jsautocfg.tmp - mv jsautocfg.tmp $@ -endif -endif - -# jscpucfg is a strange target -# Needs to be built with the host compiler but needs to include -# the mdcpucfg for the target so it needs the appropriate target defines -ifdef HOST_NSPR_MDCPUCFG -HOST_CC := $(HOST_CC) -DMDCPUCFG=$(TARGET_NSPR_MDCPUCFG) -HOST_CFLAGS := $(patsubst -DXP_%,,$(HOST_CFLAGS)) -endif - -ifdef CROSS_COMPILE -# jscpucfg needs to know when it's supposed to produce a config for the target -JSCPUCFG_DEFINES = $(ACDEFINES) - -# This is incredibly hacky. Darwin NSPR uses the same MDCPUCFG for multiple -# processors, and determines which processor to configure for based on -# #ifdef i386. This macro is among the NSPR defines, but is also automatically -# defined by the compiler when building for i386. It therefore needs to be -# defined here if targeting i386, and explicitly undefined otherwise. -ifeq ($(OS_ARCH),Darwin) -ifeq ($(TARGET_CPU),powerpc) -JSCPUCFG_DEFINES += -Ui386 -else -JSCPUCFG_DEFINES += -Di386=1 -endif -endif -endif - -ifeq ($(OS_ARCH),QNX) -ifneq ($(OS_TARGET),NTO) -# QNX's compiler apparently can't build a binary directly from a source file. -jscpucfg.o: jscpucfg.c Makefile.in - $(HOST_CC) $(HOST_CFLAGS) -c $(JSCPUCFG_DEFINES) $(DEFINES) $(NSPR_CFLAGS) -o $@ $< - -jscpucfg: jscpucfg.o - $(HOST_CC) $(HOST_CFLAGS) $(JSCPUCFG_DEFINES) $(DEFINES) -o $@ $< -endif -else -ifeq ($(OS_ARCH),WINCE) -jscpucfg$(HOST_BIN_SUFFIX): - echo no need to build jscpucfg $< -else -jscpucfg$(HOST_BIN_SUFFIX): jscpucfg.c Makefile.in - $(HOST_CC) $(HOST_CFLAGS) $(JSCPUCFG_DEFINES) $(DEFINES) $(NSPR_CFLAGS) $(OUTOPTION)$@ $< -endif -endif - diff --git a/lib/javascript/Makefile.ref b/lib/javascript/Makefile.ref deleted file mode 100644 index 3b6fbb5a..00000000 --- a/lib/javascript/Makefile.ref +++ /dev/null @@ -1,379 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Michael Ang -# Kevin Buhr -# -# Alternatively, the contents of this file may be used under the terms of -# either of the GNU General Public License Version 2 or later (the "GPL"), -# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# JSRef GNUmake makefile. -# -# Note: dependency rules are missing for some files (some -# .h, all .msg, etc.) Re-make clean if in doubt. -# - - -DEPTH = . - -include config.mk - -#NS_USE_NATIVE = 1 - -ifdef USE_MSVC -OTHER_LIBS += fdlibm/$(OBJDIR)/fdlibm.lib -else -OTHER_LIBS += -Lfdlibm/$(OBJDIR) -lfdm -endif - -ifdef JS_THREADSAFE -DEFINES += -DJS_THREADSAFE -INCLUDES += -I../../dist/$(OBJDIR)/include -ifdef USE_MSVC -OTHER_LIBS += ../../dist/$(OBJDIR)/lib/libnspr${NSPR_LIBSUFFIX}.lib -else -OTHER_LIBS += -L../../dist/$(OBJDIR)/lib -lnspr${NSPR_LIBSUFFIX} -endif -endif - -ifdef JS_NO_THIN_LOCKS -DEFINES += -DJS_USE_ONLY_NSPR_LOCKS -endif - -ifdef JS_HAS_FILE_OBJECT -DEFINES += -DJS_HAS_FILE_OBJECT -endif - -# -# XCFLAGS may be set in the environment or on the gmake command line -# -CFLAGS += $(OPTIMIZER) $(OS_CFLAGS) $(DEFINES) $(INCLUDES) $(XCFLAGS) - -LDFLAGS = $(XLDFLAGS) - -ifndef NO_LIBM -LDFLAGS += -lm -endif - -# Prevent floating point errors caused by VC++ optimizations -ifeq ($(OS_ARCH),WINNT) -_MSC_VER = $(shell $(CC) 2>&1 | sed -n 's/.*Compiler Version \([0-9]*\)\.\([0-9]*\).*/\1\2/p') -ifeq (,$(filter-out 1200 1300 1310,$(_MSC_VER))) -CFLAGS += -Op -else -CFLAGS += -fp:precise -endif -endif # WINNT - -# -# Ask perl what flags it was built with, so we can build js with similar flags -# and link properly. Viva gmake. -# -ifdef JS_PERLCONNECT -DEFINES += -DPERLCONNECT -D_GNU_SOURCE - -PERLCFLAGS := $(shell perl -MExtUtils::Embed -e ccopts) -PERLLDFLAGS := $(shell perl -MExtUtils::Embed -e ldopts) - -# perl erroneously reports compiler flag -rdynamic (interpreted by ld -# as -r) when it really meant -export-dynamic. -PERLLDFLAGS := $(subst -rdynamic,-export-dynamic,$(PERLLDFLAGS)) - -CFLAGS += $(PERLCFLAGS) -#LDFLAGS += $(PERLLDFLAGS) #PH removed this assgnment -INCLUDES += -I. #needed for perlconnect/jsperl.c -endif - -# -# Server-related changes : -# -ifdef NES40 -DEFINES += -DNES40 -endif - -# -# Line editing support. -# Define JS_READLINE or JS_EDITLINE to enable line editing in the -# js command-line interpreter. -# -ifdef JS_READLINE -# For those platforms with the readline library installed. -DEFINES += -DEDITLINE -PROG_LIBS += -lreadline -ltermcap -else -ifdef JS_EDITLINE -# Use the editline library, built locally. -PREDIRS += editline -DEFINES += -DEDITLINE -PROG_LIBS += editline/$(OBJDIR)/libedit.a -endif -endif - -# For purify -PURE_CFLAGS = -DXP_UNIX $(OPTIMIZER) $(PURE_OS_CFLAGS) $(DEFINES) \ - $(INCLUDES) $(XCFLAGS) - -# -# JS file lists -# -JS_HFILES = \ - jsarray.h \ - jsatom.h \ - jsbool.h \ - jsconfig.h \ - jscntxt.h \ - jsdate.h \ - jsemit.h \ - jsexn.h \ - jsfun.h \ - jsgc.h \ - jsinterp.h \ - jslibmath.h \ - jslock.h \ - jsmath.h \ - jsnum.h \ - jsobj.h \ - jsopcode.h \ - jsparse.h \ - jsarena.h \ - jsclist.h \ - jsdhash.h \ - jsdtoa.h \ - jshash.h \ - jslong.h \ - jsosdep.h \ - jstypes.h \ - jsprvtd.h \ - jspubtd.h \ - jsregexp.h \ - jsscan.h \ - jsscope.h \ - jsscript.h \ - jsstr.h \ - jsxdrapi.h \ - jsxml.h \ - $(NULL) - -API_HFILES = \ - jsapi.h \ - jsdbgapi.h \ - $(NULL) - -OTHER_HFILES = \ - jsbit.h \ - jscompat.h \ - jscpucfg.h \ - jsotypes.h \ - jsstddef.h \ - prmjtime.h \ - resource.h \ - jsopcode.tbl \ - js.msg \ - jsshell.msg \ - $(NULL) - -ifndef PREBUILT_CPUCFG -OTHER_HFILES += $(OBJDIR)/jsautocfg.h -endif - -HFILES = $(JS_HFILES) $(API_HFILES) $(OTHER_HFILES) - -JS_CFILES = \ - jsapi.c \ - jsarena.c \ - jsarray.c \ - jsatom.c \ - jsbool.c \ - jscntxt.c \ - jsdate.c \ - jsdbgapi.c \ - jsdhash.c \ - jsdtoa.c \ - jsemit.c \ - jsexn.c \ - jsfun.c \ - jsgc.c \ - jshash.c \ - jsinterp.c \ - jslock.c \ - jslog2.c \ - jslong.c \ - jsmath.c \ - jsnum.c \ - jsobj.c \ - jsopcode.c \ - jsparse.c \ - jsprf.c \ - jsregexp.c \ - jsscan.c \ - jsscope.c \ - jsscript.c \ - jsstr.c \ - jsutil.c \ - jsxdrapi.c \ - jsxml.c \ - prmjtime.c \ - $(NULL) - -PREDIRS += fdlibm - -ifdef USE_MSVC -FDLIBM_LIBRARY = fdlibm/$(OBJDIR)/fdlibm.lib -else -FDLIBM_LIBRARY = fdlibm/$(OBJDIR)/libfdm.a -endif -JSMATH_PRELINK = $(OBJDIR)/jsmathtemp.o -# Flag for incremental linking -DASH_R = -r - -ifeq ($(OS_ARCH),QNX) -ifneq ($(OS_TARGET),NTO) -# Don't use wildcard here, because we only want this resolved at link time. -OBJS += fdlibm/*.o -endif -endif - -ifdef JS_LIVECONNECT -DIRS += liveconnect -endif - -ifdef JS_PERLCONNECT -JS_CFILES += perlconnect/jsperl.c -endif - -ifdef JS_HAS_FILE_OBJECT -JS_CFILES += jsfile.c -JS_HFILES += jsfile.h -endif - -LIB_CFILES = $(JS_CFILES) -LIB_ASFILES := $(wildcard *_$(OS_ARCH).s) -PROG_CFILES = js.c - -ifdef USE_MSVC -LIBRARY = $(OBJDIR)/js32.lib -SHARED_LIBRARY = $(OBJDIR)/js32.dll -PROGRAM = $(OBJDIR)/js.exe -else -LIBRARY = $(OBJDIR)/libjs.a -SHARED_LIBRARY = $(OBJDIR)/libjs.$(SO_SUFFIX) -PROGRAM = $(OBJDIR)/js -ifdef JS_PERLCONNECT -PROG_LIBS += $(PERLLDFLAGS) -endif -endif - -include rules.mk - -MOZ_DEPTH = ../.. -include jsconfig.mk - -nsinstall-target: - cd ../../config; $(MAKE) OBJDIR=$(OBJDIR) OBJDIR_NAME=$(OBJDIR) -ifdef USE_MSVC -$(PROGRAM): $(PROG_OBJS) $(LIBRARY) $(FDLIBM_LIBRARY) - link.exe -out:"$@" $(EXE_LINK_FLAGS) $^ -else -$(PROGRAM): $(PROG_OBJS) $(LIBRARY) $(FDLIBM_LIBRARY) - $(CC) -o $@ $(CFLAGS) $(PROG_OBJS) $(LIBRARY) $(LDFLAGS) $(OTHER_LIBS) \ - $(PROG_LIBS) -endif - -$(PROGRAM).pure: $(PROG_OBJS) $(LIBRARY) - purify $(PUREFLAGS) \ - $(CC) -o $@ $(PURE_OS_CFLAGS) $(PROG_OBJS) $(LIBRARY) $(LDFLAGS) \ - $(OTHER_LIBS) $(PROG_LIBS) - -ifndef PREBUILT_CPUCFG -$(HFILES) $(CFILES): $(OBJDIR)/jsautocfg.h - -$(OBJDIR)/jsautocfg.h: $(OBJDIR)/jscpucfg - rm -f $@ - $(OBJDIR)/jscpucfg > $@ - -$(OBJDIR)/jscpucfg: $(OBJDIR)/jscpucfg.o - $(CC) -o $@ $(OBJDIR)/jscpucfg.o - -# Look in OBJDIR to find jsautocfg.h -INCLUDES += -I$(OBJDIR) - -# Add to TARGETS for clobber rule -TARGETS += $(OBJDIR)/jsautocfg.h $(OBJDIR)/jscpucfg \ - $(OBJDIR)/jscpucfg.o $(OBJDIR)/jsmathtemp.o -endif - - -# special rule for jsmath.o since we want to incrementally link -# against fdlibm to pull in only what is needed -$(OBJDIR)/jsmath.o: jsmath.c jsmath.h jslibmath.h $(FDLIBM_LIBRARY) -ifneq (,$(filter OS2 WINNT,$(OS_ARCH))) - $(CC) -Fo$(JSMATH_PRELINK) -c $(CFLAGS) $< -else - $(CC) -o $(JSMATH_PRELINK) -c $(CFLAGS) $< -endif - -ifeq ($(OS_ARCH),QNX) -ifneq ($(OS_TARGET),NTO) - @cp $(JSMATH_PRELINK) $@ -else - $(LD) $(DASH_R) -o $@ $(JSMATH_PRELINK) $(FDLIBM_LIBRARY) -endif -else -ifdef USE_MSVC - @echo Warning: to use $(LIBRARY) must also link against $(FDLIBM_LIBRARY) - @cp $(JSMATH_PRELINK) $@ -endif - $(LD) $(DASH_R) -o $@ $(JSMATH_PRELINK) $(FDLIBM_LIBRARY) -endif - -# Note: generated headers must be built before descending -# into fdlibm directory -$(FDLIBM_LIBRARY) : - $(MAKE) -C fdlibm -f Makefile.ref $(@F) - -# -# Hardwire dependencies on jsopcode.tbl -# -jsopcode.h jsopcode.c: jsopcode.tbl - --include $(DEPENDENCIES) - -TARNAME = jsref.tar -TARFILES = files `cat files` - -SUFFIXES: .i -%.i: %.c - $(CC) -C -E $(CFLAGS) $< > $*.i diff --git a/lib/javascript/README.html b/lib/javascript/README.html deleted file mode 100644 index b2942e38..00000000 --- a/lib/javascript/README.html +++ /dev/null @@ -1,826 +0,0 @@ - - - - - - - JavaScript Reference Implementation (JSRef) README - - - -

-Table of Contents

- - - -

-Introduction

-This is the README file for the JavaScript -Reference (JSRef, now better known as SpiderMonkey) implementation. -It consists of build conventions -and instructions, source code conventions, a design walk-through, and a -brief file-by-file description of the source. -

JSRef builds a library or DLL containing the -JavaScript runtime (compiler, interpreter, decompiler, garbage collector, -atom manager, standard classes). It then compiles a small "shell" program -and links that with the library to make an interpreter that can be used -interactively and with test .js files to run scripts.  The code has -no dependencies on the rest of the Mozilla codebase. -

Quick start tip: skip to "Using the JS API" below, build the -js shell, and play with the object named "it" (start by setting 'it.noisy -= true'). -

-Build conventions (standalone JS engine and shell) -(OUT OF DATE!)

-These build directions refer only to building the standalone JavaScript -engine and shell.  To build within the browser, refer to the build -directions on the mozilla.org website. -

By default, all platforms build a version of the JS engine that is not -threadsafe.  If you require thread-safety, you must also populate -the mozilla/dist directory with NSPR -headers and libraries.  (NSPR implements a portable threading library, -among other things.  The source is downloadable via CVS -from mozilla/nsprpub.)  -Next, you must define JS_THREADSAFE when building the JS engine, -either on the command-line (gmake/nmake) or in a universal header file. -

-Windows

- -
    -
  • -Use MSVC 4.2 or 5.0.
  • - -
  • -For building from the IDE use js/src/js.mdp.  (js.mdp -is an MSVC4.2 project file, but if you load it into MSVC5, it will be converted -to the newer project file format.)  NOTE: makefile.win -is an nmake file used only for building the JS-engine in the Mozilla browser.  -Don't attempt to use it to build the standalone JS-engine.
  • - -
  • -If you prefer to build from the command-line, use 'nmake -f js.mak'
  • - -
  • -Executable shell js.exe and runtime library js32.dll -are created in either js/src/Debug or js/src/Release.
  • -
- -

-Macintosh

- -
    -
  • -Use CodeWarrior 3.x
  • - -
  • -Load the project file js:src:macbuild:JSRef.mcp and select "Make" -from the menu.
  • -
- -

-Unix

- -
    -
  • -Use 'gmake -f Makefile.ref' to build. To compile optimized code, -pass BUILD_OPT=1 on the gmake command line or preset it in the -environment or Makefile.refNOTE: -Do not attempt to use Makefile to build the standalone JavaScript engine.  -This file is used only for building the JS-engine in the Mozilla browser.
  • - -
  • -Each platform on which JS is built must have a *.mk -configuration file in the js/src/config directory.  The configuration -file specifies the compiler/linker to be used and allows for customization -of command-line options.  To date, the build system has been tested -on Solaris, AIX, HP/UX, OSF, IRIX, x86 Linux and Windows NT.
  • - -
  • -Most platforms will work with either the vendor compiler -or -gcc.  -(Except that HP builds only work using the native compiler.  gcc won't -link correctly with shared libraries on that platform.  If someone -knows a way to fix this, let us -know.)
  • - -
  • -If you define JS_LIVECONNECT, gmake will -descend into the liveconnect directory and build -LiveConnect -after building the JS engine.
  • - -
  • -To build a binary drop (a zip'ed up file of headers, libraries, binaries), -check out mozilla/config and mozilla/nsprpub/config.  -Use 'gmake -f Makefile.ref nsinstall-target all export ship'
  • -
- -

-Debugging notes

- -
    -
  • -To turn on GC instrumentation, define JS_GCMETER.
  • - -
      -
    • -To turn on GC mark-phase debugging, useful to find leaked objects by their -address, and to dump the GC heap, define GC_MARK_DEBUG. -See the code in jsgc.c around the declaration and use of -js_LiveThingToFind.
    • - -
    • -To turn on the arena package's instrumentation, define JS_ARENAMETER.
    • - -
    • -To turn on the hash table package's metering, define JS_HASHMETER.
    • -
    - -

    -Naming and coding conventions

    - -
      -
    • -Public function names begin with JS_ followed by capitalized "intercaps", -e.g. JS_NewObject.
    • - -
    • -Extern but library-private function names use a js_ prefix and -mixed case, e.g. js_SearchScope.
    • - -
    • -Most static function names have unprefixed, mixed-case names: GetChar.
    • - -
    • -But static native methods of JS objects have lowercase, underscore-separated -or intercaps names, e.g., str_indexOf.
    • - -
    • -And library-private and static data use underscores, not intercaps (but -library-private data do use a js_ prefix).
    • - -
    • -Scalar type names are lowercase and js-prefixed: jsdouble.
    • - -
    • -Aggregate type names are JS-prefixed and mixed-case: JSObject.
    • - -
    • -Macros are generally ALL_CAPS and underscored, to call out potential -side effects, multiple uses of a formal argument, etc.
    • - -
    • -Four spaces of indentation per statement nesting level.
    • - -
    • -Tabs are taken to be eight spaces, and an Emacs magic comment at the top -of each file tries to help. If you're using MSVC or similar, you'll want -to set tab width to 8, and help convert these files to be space-filled. -Do not add hard tabs to source files; do remove them -whenever possible.
    • - -
    • -DLL entry points have their return type expanded within a JS_PUBLIC_API() -macro call, to get the right Windows secret type qualifiers in the right -places for all build variants.
    • - -
    • -Callback functions that might be called from a DLL are similarly macroized -with JS_STATIC_DLL_CALLBACK (if the function otherwise would be -static to hide its name) or JS_DLL_CALLBACK (this macro takes -no type argument; it should be used after the return type and before the -function name).
    • -
    - -

    -Using the JS API

    - -

    -Starting up

    - -
        /*
    -     * Tune this to avoid wasting space for shallow stacks, while saving on
    -     * malloc overhead/fragmentation for deep or highly-variable stacks.
    -     */
    -    #define STACK_CHUNK_SIZE    8192
    -
    -    JSRuntime *rt;
    -    JSContext *cx;
    -
    -    /* You need a runtime and one or more contexts to do anything with JS. */
    -    rt = JS_NewRuntime(0x400000L);
    -    if (!rt)
    -        fail("can't create JavaScript runtime");
    -    cx = JS_NewContext(rt, STACK_CHUNK_SIZE);
    -    if (!cx)
    -        fail("can't create JavaScript context");
    -
    -    /*
    -     * The context definitely wants a global object, in order to have standard
    -     * classes and functions like Date and parseInt.  See below for details on
    -     * JS_NewObject.
    -     */
    -    JSObject *globalObj;
    -
    -    globalObj = JS_NewObject(cx, &my_global_class, 0, 0);
    -    JS_InitStandardClasses(cx, globalObj);
    - -

    -Defining objects and properties

    - -
        /* Statically initialize a class to make "one-off" objects. */
    -    JSClass my_class = {
    -        "MyClass",
    -
    -        /* All of these can be replaced with the corresponding JS_*Stub
    -           function pointers. */
    -        my_addProperty, my_delProperty, my_getProperty, my_setProperty,
    -        my_enumerate,   my_resolve,     my_convert,     my_finalize
    -    };
    -
    -    JSObject *obj;
    -
    -    /*
    -     * Define an object named in the global scope that can be enumerated by
    -     * for/in loops.  The parent object is passed as the second argument, as
    -     * with all other API calls that take an object/name pair.  The prototype
    -     * passed in is null, so the default object prototype will be used.
    -     */
    -    obj = JS_DefineObject(cx, globalObj, "myObject", &my_class, NULL,
    -                          JSPROP_ENUMERATE);
    -
    -    /*
    -     * Define a bunch of properties with a JSPropertySpec array statically
    -     * initialized and terminated with a null-name entry.  Besides its name,
    -     * each property has a "tiny" identifier (MY_COLOR, e.g.) that can be used
    -     * in switch statements (in a common my_getProperty function, for example).
    -     */
    -    enum my_tinyid {
    -        MY_COLOR, MY_HEIGHT, MY_WIDTH, MY_FUNNY, MY_ARRAY, MY_RDONLY
    -    };
    -
    -    static JSPropertySpec my_props[] = {
    -        {"color",       MY_COLOR,       JSPROP_ENUMERATE},
    -        {"height",      MY_HEIGHT,      JSPROP_ENUMERATE},
    -        {"width",       MY_WIDTH,       JSPROP_ENUMERATE},
    -        {"funny",       MY_FUNNY,       JSPROP_ENUMERATE},
    -        {"array",       MY_ARRAY,       JSPROP_ENUMERATE},
    -        {"rdonly",      MY_RDONLY,      JSPROP_READONLY},
    -        {0}
    -    };
    -
    -    JS_DefineProperties(cx, obj, my_props);
    -
    -    /*
    -     * Given the above definitions and call to JS_DefineProperties, obj will
    -     * need this sort of "getter" method in its class (my_class, above).  See
    -     * the example for the "It" class in js.c.
    -     */
    -    static JSBool
    -    my_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
    -    {
    -        if (JSVAL_IS_INT(id)) {
    -            switch (JSVAL_TO_INT(id)) {
    -              case MY_COLOR:  *vp = . . .; break;
    -              case MY_HEIGHT: *vp = . . .; break;
    -              case MY_WIDTH:  *vp = . . .; break;
    -              case MY_FUNNY:  *vp = . . .; break;
    -              case MY_ARRAY:  *vp = . . .; break;
    -              case MY_RDONLY: *vp = . . .; break;
    -            }
    -        }
    -        return JS_TRUE;
    -    }
    - -

    -Defining functions

    - -
        /* Define a bunch of native functions first: */
    -    static JSBool
    -    my_abs(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
    -    {
    -        jsdouble x, z;
    -
    -        if (!JS_ValueToNumber(cx, argv[0], &x))
    -            return JS_FALSE;
    -        z = (x < 0) ? -x : x;
    -        return JS_NewDoubleValue(cx, z, rval);
    -    }
    -
    -    . . .
    -
    -    /*
    -     * Use a JSFunctionSpec array terminated with a null name to define a
    -     * bunch of native functions.
    -     */
    -    static JSFunctionSpec my_functions[] = {
    -    /*    name          native          nargs    */
    -        {"abs",         my_abs,         1},
    -        {"acos",        my_acos,        1},
    -        {"asin",        my_asin,        1},
    -        . . .
    -        {0}
    -    };
    -
    -    /*
    -     * Pass a particular object to define methods for it alone.  If you pass
    -     * a prototype object, the methods will apply to all instances past and
    -     * future of the prototype's class (see below for classes).
    -     */
    -    JS_DefineFunctions(cx, globalObj, my_functions);
    - -

    -Defining classes

    - -
        /*
    -     * This pulls together the above API elements by defining a constructor
    -     * function, a prototype object, and properties of the prototype and of
    -     * the constructor, all with one API call.
    -     *
    -     * Initialize a class by defining its constructor function, prototype, and
    -     * per-instance and per-class properties.  The latter are called "static"
    -     * below by analogy to Java.  They are defined in the constructor object's
    -     * scope, so that 'MyClass.myStaticProp' works along with 'new MyClass()'.
    -     *
    -     * JS_InitClass takes a lot of arguments, but you can pass null for any of
    -     * the last four if there are no such properties or methods.
    -     *
    -     * Note that you do not need to call JS_InitClass to make a new instance of
    -     * that class -- otherwise there would be a chicken-and-egg problem making
    -     * the global object -- but you should call JS_InitClass if you require a
    -     * constructor function for script authors to call via new, and/or a class
    -     * prototype object ('MyClass.prototype') for authors to extend with new
    -     * properties at run-time.  In general, if you want to support multiple
    -     * instances that share behavior, use JS_InitClass.
    -     */
    -    protoObj = JS_InitClass(cx, globalObj, NULL, &my_class,
    -
    -                            /* native constructor function and min arg count */
    -                            MyClass, 0,
    -
    -                            /* prototype object properties and methods -- these
    -                               will be "inherited" by all instances through
    -                               delegation up the instance's prototype link. */
    -                            my_props, my_methods,
    -
    -                            /* class constructor properties and methods */
    -                            my_static_props, my_static_methods);
    - -

    -Running scripts

    - -
        /* These should indicate source location for diagnostics. */
    -    char *filename;
    -    uintN lineno;
    -
    -    /*
    -     * The return value comes back here -- if it could be a GC thing, you must
    -     * add it to the GC's "root set" with JS_AddRoot(cx, &thing) where thing
    -     * is a JSString *, JSObject *, or jsdouble *, and remove the root before
    -     * rval goes out of scope, or when rval is no longer needed.
    -     */
    -    jsval rval;
    -    JSBool ok;
    -
    -    /*
    -     * Some example source in a C string.  Larger, non-null-terminated buffers
    -     * can be used, if you pass the buffer length to JS_EvaluateScript.
    -     */
    -    char *source = "x * f(y)";
    -
    -    ok = JS_EvaluateScript(cx, globalObj, source, strlen(source),
    -                           filename, lineno, &rval);
    -
    -    if (ok) {
    -        /* Should get a number back from the example source. */
    -        jsdouble d;
    -
    -        ok = JS_ValueToNumber(cx, rval, &d);
    -        . . .
    -    }
    - -

    -Calling functions

    - -
        /* Call a global function named "foo" that takes no arguments. */
    -    ok = JS_CallFunctionName(cx, globalObj, "foo", 0, 0, &rval);
    -
    -    jsval argv[2];
    -
    -    /* Call a function in obj's scope named "method", passing two arguments. */
    -    argv[0] = . . .;
    -    argv[1] = . . .;
    -    ok = JS_CallFunctionName(cx, obj, "method", 2, argv, &rval);
    - -

    -Shutting down

    - -
        /* For each context you've created: */
    -    JS_DestroyContext(cx);
    -
    -    /* For each runtime: */
    -    JS_DestroyRuntime(rt);
    -
    -    /* And finally: */
    -    JS_ShutDown();
    - -

    -Debugging API

    -See the trap, untrap, watch, unwatch, line2pc, and pc2line -commands in js.c. Also the (scant) comments in jsdbgapi.h. -

    -Design walk-through

    -This section must be brief for now -- it could easily turn into a book. -

    -JS "JavaScript Proper"

    -JS modules declare and implement the JavaScript compiler, interpreter, -decompiler, GC and atom manager, and standard classes. -

    JavaScript uses untyped bytecode and runtime type tagging of data values. -The jsval type is a signed machine word that contains either a -signed integer value (if the low bit is set), or a type-tagged pointer -or boolean value (if the low bit is clear). Tagged pointers all refer to -8-byte-aligned things in the GC heap. -

    Objects consist of a possibly shared structural description, called -the map or scope; and unshared property values in a vector, called the -slots. Object properties are associated with nonnegative integers stored -in jsval's, or with atoms (unique string descriptors) if named -by an identifier or a non-integral index expression. -

    Scripts contain bytecode, source annotations, and a pool of string, -number, and identifier literals. Functions are objects that extend scripts -or native functions with formal parameters, a literal syntax, and a distinct -primitive type ("function"). -

    The compiler consists of a recursive-descent parser and a random-logic -rather than table-driven lexical scanner. Semantic and lexical feedback -are used to disambiguate hard cases such as missing semicolons, assignable -expressions ("lvalues" in C parlance), etc. The parser generates bytecode -as it parses, using fixup lists for downward branches and code buffering -and rewriting for exceptional cases such as for loops. It attempts no error -recovery. The interpreter executes the bytecode of top-level scripts, and -calls itself indirectly to interpret function bodies (which are also scripts). -All state associated with an interpreter instance is passed through formal -parameters to the interpreter entry point; most implicit state is collected -in a type named JSContext. Therefore, all API and almost all other functions -in JSRef take a JSContext pointer as their first argument. -

    The decompiler translates postfix bytecode into infix source by consulting -a separate byte-sized code, called source notes, to disambiguate bytecodes -that result from more than one grammatical production. -

    The GC is a mark-and-sweep, non-conservative (exact) collector. It -can allocate only fixed-sized things -- the current size is two machine -words. It is used to hold JS object and string descriptors (but not property -lists or string bytes), and double-precision floating point numbers. It -runs automatically only when maxbytes (as passed to JS_NewRuntime()) -bytes of GC things have been allocated and another thing-allocation request -is made. JS API users should call JS_GC() or JS_MaybeGC() -between script executions or from the branch callback, as often as necessary. -

    An important point about the GC's "exactness": you must add roots for -new objects created by your native methods if you store references to them -into a non-JS structure in the malloc heap or in static data. Also, if -you make a new object in a native method, but do not store it through the -rval -result parameter (see math_abs in the "Using the JS API" section above) -so that it is in a known root, the object is guaranteed to survive only -until another new object is created. Either lock the first new object when -making two in a row, or store it in a root you've added, or store it via -rval. -See the GC tips -document for more. -

    The atom manager consists of a hash table associating strings uniquely -with scanner/parser information such as keyword type, index in script or -function literal pool, etc. Atoms play three roles in JSRef: as literals -referred to by unaligned 16-bit immediate bytecode operands, as unique -string descriptors for efficient property name hashing, and as members -of the root GC set for exact GC. -

    Native objects and methods for arrays, booleans, dates, functions, numbers, -and strings are implemented using the JS API and certain internal interfaces -used as "fast paths". -

    In general, errors are signaled by false or unoverloaded-null return -values, and are reported using JS_ReportError() or one of its -variants by the lowest level in order to provide the most detail. Client -code can substitute its own error reporting function and suppress errors, -or reflect them into Java or some other runtime system as exceptions, GUI -dialogs, etc.. -

    -File walk-through (OUT OF DATE!)

    - -

    -jsapi.c, jsapi.h

    -The public API to be used by almost all client code.  If your client -code can't make do with jsapi.h, and must reach into a friend -or private js* file, please let us know so we can extend jsapi.h -to include what you need in a fashion that we can support over the long -run. -

    -jspubtd.h, jsprvtd.h

    -These files exist to group struct and scalar typedefs so they can be used -everywhere without dragging in struct definitions from N different files. -The jspubtd.h file contains public typedefs, and is included by -jsapi.h. -The jsprvtd.h file contains private typedefs and is included by -various .h files that need type names, but not type sizes or declarations. -

    -jsdbgapi.c, jsdbgapi.h

    -The Debugging API, still very much under development. Provided so far: -
      -
    • -Traps, with which breakpoints, single-stepping, step over, step out, and -so on can be implemented. The debugger will have to consult jsopcode.def -on its own to figure out where to plant trap instructions to implement -functions like step out, but a future jsdbgapi.h will provide convenience -interfaces to do these things. At most one trap per bytecode can be set. -When a script (JSScript) is destroyed, all traps set in its bytecode -are cleared.
    • - -
    • -Watchpoints, for intercepting set operations on properties and running -a debugger-supplied function that receives the old value and a pointer -to the new one, which it can use to modify the new value being set.
    • - -
    • -Line number to PC and back mapping functions. The line-to-PC direction -"rounds" toward the next bytecode generated from a line greater than or -equal to the input line, and may return the PC of a for-loop update part, -if given the line number of the loop body's closing brace. Any line after -the last one in a script or function maps to a PC one byte beyond the last -bytecode in the script. An example, from perfect.js:
    • - -
      14   function perfect(n)
      -15   {
      -16       print("The perfect numbers up to " +  n + " are:");
      -17
      -18       // We build sumOfDivisors[i] to hold a string expression for
      -19       // the sum of the divisors of i, excluding i itself.
      -20       var sumOfDivisors = new ExprArray(n+1,1);
      -21       for (var divisor = 2; divisor <= n; divisor++) {
      -22           for (var j = divisor + divisor; j <= n; j += divisor) {
      -23               sumOfDivisors[j] += " + " + divisor;
      -24           }
      -25           // At this point everything up to 'divisor' has its sumOfDivisors
      -26           // expression calculated, so we can determine whether it's perfect
      -27           // already by evaluating.
      -28           if (eval(sumOfDivisors[divisor]) == divisor) {
      -29               print("" + divisor + " = " + sumOfDivisors[divisor]);
      -30           }
      -31       }
      -32       delete sumOfDivisors;
      -33       print("That's all.");
      -34   }
      -The line number to PC and back mappings can be tested using the js program -with the following script: -
              load("perfect.js")
      -        print(perfect)
      -        dis(perfect)
      -
      -        print()
      -        for (var ln = 0; ln <= 40; ln++) {
      -            var pc = line2pc(perfect,ln)
      -            var ln2 = pc2line(perfect,pc)
      -            print("\tline " + ln + " => pc " + pc + " => line " + ln2)
      -        }
      -The result of the for loop over lines 0 to 40 inclusive is: -
              line 0 => pc 0 => line 16
      -        line 1 => pc 0 => line 16
      -        line 2 => pc 0 => line 16
      -        line 3 => pc 0 => line 16
      -        line 4 => pc 0 => line 16
      -        line 5 => pc 0 => line 16
      -        line 6 => pc 0 => line 16
      -        line 7 => pc 0 => line 16
      -        line 8 => pc 0 => line 16
      -        line 9 => pc 0 => line 16
      -        line 10 => pc 0 => line 16
      -        line 11 => pc 0 => line 16
      -        line 12 => pc 0 => line 16
      -        line 13 => pc 0 => line 16
      -        line 14 => pc 0 => line 16
      -        line 15 => pc 0 => line 16
      -        line 16 => pc 0 => line 16
      -        line 17 => pc 19 => line 20
      -        line 18 => pc 19 => line 20
      -        line 19 => pc 19 => line 20
      -        line 20 => pc 19 => line 20
      -        line 21 => pc 36 => line 21
      -        line 22 => pc 53 => line 22
      -        line 23 => pc 74 => line 23
      -        line 24 => pc 92 => line 22
      -        line 25 => pc 106 => line 28
      -        line 26 => pc 106 => line 28
      -        line 27 => pc 106 => line 28
      -        line 28 => pc 106 => line 28
      -        line 29 => pc 127 => line 29
      -        line 30 => pc 154 => line 21
      -        line 31 => pc 154 => line 21
      -        line 32 => pc 161 => line 32
      -        line 33 => pc 172 => line 33
      -        line 34 => pc 172 => line 33
      -        line 35 => pc 172 => line 33
      -        line 36 => pc 172 => line 33
      -        line 37 => pc 172 => line 33
      -        line 38 => pc 172 => line 33
      -        line 39 => pc 172 => line 33
      -        line 40 => pc 172 => line 33
      -
    - -

    -jsconfig.h

    -Various configuration macros defined as 0 or 1 depending on how JS_VERSION -is defined (as 10 for JavaScript 1.0, 11 for JavaScript 1.1, etc.). Not -all macros are tested around related code yet. In particular, JS 1.0 support -is missing from JSRef. JS 1.2 support will appear in a future JSRef release. -
      -

    -js.c

    -The "JS shell", a simple interpreter program that uses the JS API and more -than a few internal interfaces (some of these internal interfaces could -be replaced by jsapi.h calls). The js program built from this -source provides a test vehicle for evaluating scripts and calling functions, -trying out new debugger primitives, etc. -

    -jsarray.*, jsbool.*, jdsdate.*, jsfun.*, jsmath.*, jsnum.*, jsstr.*

    -These file pairs implement the standard classes and (where they exist) -their underlying primitive types. They have similar structure, generally -starting with class definitions and continuing with internal constructors, -finalizers, and helper functions. -

    -jsobj.*, jsscope.*

    -These two pairs declare and implement the JS object system. All of the -following happen here: -
      -
    • -creating objects by class and prototype, and finalizing objects;
    • - -
    • -defining, looking up, getting, setting, and deleting properties;
    • - -
    • -creating and destroying properties and binding names to them.
    • -
    -The details of a native object's map (scope) are mostly hidden in -jsscope.[ch]. -

    -jsatom.c, jsatom.h

    -The atom manager. Contains well-known string constants, their atoms, the -global atom hash table and related state, the js_Atomize() function that -turns a counted string of bytes into an atom, and literal pool (JSAtomMap) -methods. -

    -jsgc.c, jsgc.h

    -[TBD] -

    -jsinterp.*, jscntxt.*

    -The bytecode interpreter, and related functions such as Call and AllocStack, -live in jsinterp.c. The JSContext constructor and destructor are -factored out into jscntxt.c for minimal linking when the compiler -part of JS is split from the interpreter part into a separate program. -

    -jsemit.*, jsopcode.tbl, jsopcode.*, jsparse.*, jsscan.*, jsscript.*

    -Compiler and decompiler modules. The jsopcode.tbl file is a C preprocessor -source that defines almost everything there is to know about JS bytecodes. -See its major comment for how to use it. For now, a debugger will use it -and its dependents such as jsopcode.h directly, but over time we -intend to extend jsdbgapi.h to hide uninteresting details and provide -conveniences. The code generator is split across paragraphs of code in -jsparse.c, -and the utility methods called on JSCodeGenerator appear in jsemit.c. -Source notes generated by jsparse.c and -jsemit.c are used -in jsscript.c to map line number to program counter and back. -

    -jstypes.h, jslog2.c

    -Fundamental representation types and utility macros. This file alone among -all .h files in JSRef must be included first by .c files. It is not nested -in .h files, as other prerequisite .h files generally are, since it is -also a direct dependency of most .c files and would be over-included if -nested in addition to being directly included. The one "not-quite-a-macro -macro" is the JS_CeilingLog2() function in jslog2.c. -

    -jsarena.c, jsarena.h

    -Last-In-First-Out allocation macros that amortize malloc costs and allow -for en-masse freeing. See the paper mentioned in prarena.h's major comment. -

    -jsutil.c, jsutil.h

    -The JS_ASSERT macro is used throughout JSRef source as a proof -device to make invariants and preconditions clear to the reader, and to -hold the line during maintenance and evolution against regressions or violations -of assumptions that it would be too expensive to test unconditionally at -run-time. Certain assertions are followed by run-time tests that cope with -assertion failure, but only where I'm too smart or paranoid to believe -the assertion will never fail... -

    -jsclist.h

    -Doubly-linked circular list struct and macros. -

    -jscpucfg.c

    -This standalone program generates jscpucfg.h, a header file containing -bytes per word and other constants that depend on CPU architecture and -C compiler type model. It tries to discover most of these constants by -running its own experiments on the build host, so if you are cross-compiling, -beware. -

    -prdtoa.c, prdtoa.h

    -David Gay's portable double-precision floating point to string conversion -code, with Permission To Use notice included. -

    -prhash.c, prhash.h

    -Portable, extensible hash tables. These use multiplicative hash for strength -reduction over division hash, yet with very good key distribution over -power of two table sizes. Collisions resolve via chaining, so each entry -burns a malloc and can fragment the heap. -

    -prlong.c, prlong.h

    -64-bit integer emulation, and compatible macros that use C's long long -type where it exists (my last company mapped long long to a 128-bit type, -but no real architecture does 128-bit ints yet). -

    -jsosdep.h

    -Annoying OS dependencies rationalized into a few "feature-test" macros -such as JS_HAVE_LONG_LONG. -

    -jsprf.*

    -Portable, buffer-overrun-resistant sprintf and friends. For no good reason -save lack of time, the %e, %f, and %g formats cause your system's native -sprintf, rather than JS_dtoa(), to be used. This bug doesn't affect -JSRef, because it uses its own JS_dtoa() call in jsnum.c -to convert from double to string, but it's a bug that we'll fix later, -and one you should be aware of if you intend to use a JS_*printf()  -function with your own floating type arguments - various vendor sprintf's -mishandle NaN, +/-Inf, and some even print normal floating values inaccurately. -

    -prmjtime.c, prmjtime.h

    -Time functions. These interfaces are named in a way that makes local vs. -universal time confusion likely. Caveat emptor, and we're working on it. -To make matters worse, Java (and therefore JavaScript) uses "local" time -numbers (offsets from the epoch) in its Date class. - - -

    -Additional Resources (links, API docs, and newsgroups)

    - - - - - - diff --git a/lib/javascript/SpiderMonkey.rsp b/lib/javascript/SpiderMonkey.rsp deleted file mode 100644 index 8025c6cd..00000000 --- a/lib/javascript/SpiderMonkey.rsp +++ /dev/null @@ -1,12 +0,0 @@ -mozilla/js/src/* -mozilla/js/src/config/* -mozilla/js/src/fdlibm/* -mozilla/js/src/liveconnect/* -mozilla/js/src/liveconnect/_jni/* -mozilla/js/src/liveconnect/classes/* -mozilla/js/src/liveconnect/classes/netscape/* -mozilla/js/src/liveconnect/classes/netscape/javascript/* -mozilla/js/src/liveconnect/config/* -mozilla/js/src/liveconnect/macbuild/* -mozilla/js/src/liveconnect/macbuild/JavaSession/* -mozilla/js/src/macbuild/* diff --git a/lib/javascript/config.mk b/lib/javascript/config.mk deleted file mode 100644 index fbbd08fb..00000000 --- a/lib/javascript/config.mk +++ /dev/null @@ -1,190 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998-1999 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either of the GNU General Public License Version 2 or later (the "GPL"), -# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -ifdef JS_DIST -DIST = $(JS_DIST) -else -DIST = $(DEPTH)/../../dist -endif - -# Set os+release dependent make variables -OS_ARCH := $(subst /,_,$(shell uname -s | sed /\ /s//_/)) - -# Attempt to differentiate between SunOS 5.4 and x86 5.4 -OS_CPUARCH := $(shell uname -m) -ifeq ($(OS_CPUARCH),i86pc) -OS_RELEASE := $(shell uname -r)_$(OS_CPUARCH) -else -ifeq ($(OS_ARCH),AIX) -OS_RELEASE := $(shell uname -v).$(shell uname -r) -else -OS_RELEASE := $(shell uname -r) -endif -endif -ifeq ($(OS_ARCH),IRIX64) -OS_ARCH := IRIX -endif - -# Handle output from win32 unames other than Netscape's version -ifeq (,$(filter-out Windows_95 Windows_98 CYGWIN_95-4.0 CYGWIN_98-4.10, $(OS_ARCH))) - OS_ARCH := WIN95 -endif -ifeq ($(OS_ARCH),WIN95) - OS_ARCH := WINNT - OS_RELEASE := 4.0 -endif -ifeq ($(OS_ARCH), Windows_NT) - OS_ARCH := WINNT - OS_MINOR_RELEASE := $(shell uname -v) - ifeq ($(OS_MINOR_RELEASE),00) - OS_MINOR_RELEASE = 0 - endif - OS_RELEASE := $(OS_RELEASE).$(OS_MINOR_RELEASE) -endif -ifeq (CYGWIN_NT,$(findstring CYGWIN_NT,$(OS_ARCH))) - OS_RELEASE := $(patsubst CYGWIN_NT-%,%,$(OS_ARCH)) - OS_ARCH := WINNT -endif -ifeq ($(OS_ARCH), CYGWIN32_NT) - OS_ARCH := WINNT -endif -ifeq (MINGW32_NT,$(findstring MINGW32_NT,$(OS_ARCH))) - OS_RELEASE := $(patsubst MINGW32_NT-%,%,$(OS_ARCH)) - OS_ARCH := WINNT -endif - -# Virtually all Linux versions are identical. -# Any distinctions are handled in linux.h -ifeq ($(OS_ARCH),Linux) -OS_CONFIG := Linux_All -else -ifeq ($(OS_ARCH),dgux) -OS_CONFIG := dgux -else -ifeq ($(OS_ARCH),Darwin) -OS_CONFIG := Darwin -else -OS_CONFIG := $(OS_ARCH)$(OS_OBJTYPE)$(OS_RELEASE) -endif -endif -endif - -ASFLAGS = -DEFINES = - -ifeq ($(OS_ARCH), WINNT) -INSTALL = nsinstall -CP = cp -else -INSTALL = $(DIST)/bin/nsinstall -CP = cp -endif - -# ifdef BUILD_OPT -# OPTIMIZER = -O -# DEFINES += -UDEBUG -DNDEBUG -UDEBUG_$(USER) -# OBJDIR_TAG = _OPT -# else -# ifdef USE_MSVC -# OPTIMIZER = -Zi -# else -# OPTIMIZER = -g -# endif -# DEFINES += -DDEBUG -DDEBUG_$(USER) -# OBJDIR_TAG = _DBG -# endif - -OPTIMIZER = -O2 -fexpensive-optimizations -fomit-frame-pointer -ffast-math -fPIC - - -SO_SUFFIX = so - -NS_USE_NATIVE = 1 - -# Java stuff -CLASSDIR = $(DEPTH)/liveconnect/classes -JAVA_CLASSES = $(patsubst %.java,%.class,$(JAVA_SRCS)) -TARGETS += $(addprefix $(CLASSDIR)/$(OBJDIR)/$(JARPATH)/, $(JAVA_CLASSES)) -JAVAC = $(JDK)/bin/javac -JAVAC_FLAGS = -classpath "$(CLASSPATH)" -d $(CLASSDIR)/$(OBJDIR) -ifeq ($(OS_ARCH), WINNT) - SEP = ; -else - SEP = : -endif -CLASSPATH = $(JDK)/lib/classes.zip$(SEP)$(CLASSDIR)/$(OBJDIR) - -include $(DEPTH)/config/$(OS_CONFIG).mk - -ifndef OBJ_SUFFIX -ifdef USE_MSVC -OBJ_SUFFIX = obj -else -OBJ_SUFFIX = o -endif -endif - -ifndef HOST_BIN_SUFFIX -ifeq ($(OS_ARCH),WINNT) -HOST_BIN_SUFFIX = .exe -else -HOST_BIN_SUFFIX = -endif -endif - -# Name of the binary code directories -# ifdef BUILD_IDG -# OBJDIR = $(OS_CONFIG)$(OBJDIR_TAG).OBJD -# else -# OBJDIR = $(OS_CONFIG)$(OBJDIR_TAG).OBJ -# endif -OBJDIR = obj -VPATH = $(OBJDIR) - -# Automatic make dependencies file -DEPENDENCIES = $(OBJDIR)/.md - -LCJAR = js15lc30.jar - -# Library name -LIBDIR := lib -ifeq ($(CPU_ARCH), x86_64) -LIBDIR := lib64 -endif - diff --git a/lib/javascript/config/AIX4.1.mk b/lib/javascript/config/AIX4.1.mk deleted file mode 100644 index 09c7cb94..00000000 --- a/lib/javascript/config/AIX4.1.mk +++ /dev/null @@ -1,65 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config stuff for AIX -# - -CC = xlC_r -CCC = xlC_r - -RANLIB = ranlib - -#.c.o: -# $(CC) -c -MD $*.d $(CFLAGS) $< -ARCH := aix -CPU_ARCH = rs6000 -GFX_ARCH = x -INLINES = js_compare_and_swap:js_fast_lock1:js_fast_unlock1:js_lock_get_slot:js_lock_set_slot:js_lock_scope1 - -OS_CFLAGS = -qarch=com -qinline+$(INLINES) -DXP_UNIX -DAIX -DAIXV3 -DSYSV -DHAVE_LOCALTIME_R -OS_LIBS = -lbsd -lsvld -lm -#-lpthreads -lc_r - -MKSHLIB = $(LD) -bM:SRE -bh:4 -bnoentry -berok -XLDFLAGS += -lc - -ifdef JS_THREADSAFE -XLDFLAGS += -lsvld -endif diff --git a/lib/javascript/config/AIX4.2.mk b/lib/javascript/config/AIX4.2.mk deleted file mode 100644 index 1e3f1f18..00000000 --- a/lib/javascript/config/AIX4.2.mk +++ /dev/null @@ -1,64 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config stuff for AIX -# - -CC = xlC_r -CCC = xlC_r -CFLAGS += -qarch=com -qnoansialias -qinline+$(INLINES) -DXP_UNIX -DAIX -DAIXV3 -DSYSV -DHAVE_LOCALTIME_R - -RANLIB = ranlib - -#.c.o: -# $(CC) -c -MD $*.d $(CFLAGS) $< -ARCH := aix -CPU_ARCH = rs6000 -GFX_ARCH = x -INLINES = js_compare_and_swap:js_fast_lock1:js_fast_unlock1:js_lock_get_slot:js_lock_set_slot:js_lock_scope1 - -#-lpthreads -lc_r - -MKSHLIB = /usr/lpp/xlC/bin/makeC++SharedLib_r -p 0 -G -berok - -ifdef JS_THREADSAFE -XLDFLAGS += -ldl -endif - diff --git a/lib/javascript/config/AIX4.3.mk b/lib/javascript/config/AIX4.3.mk deleted file mode 100644 index df05d8c9..00000000 --- a/lib/javascript/config/AIX4.3.mk +++ /dev/null @@ -1,65 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config stuff for AIX -# - -CC = xlC_r -CCC = xlC_r -CFLAGS += -qarch=com -qnoansialias -qinline+$(INLINES) -DXP_UNIX -DAIX -DAIXV3 -DSYSV -DAIX4_3 -DHAVE_LOCALTIME_R - -RANLIB = ranlib - -#.c.o: -# $(CC) -c -MD $*.d $(CFLAGS) $< -ARCH := aix -CPU_ARCH = rs6000 -GFX_ARCH = x -INLINES = js_compare_and_swap:js_fast_lock1:js_fast_unlock1:js_lock_get_slot:js_lock_set_slot:js_lock_scope1 - -#-lpthreads -lc_r - -MKSHLIB_BIN = /usr/ibmcxx/bin/makeC++SharedLib_r -MKSHLIB = $(MKSHLIB_BIN) -p 0 -G -berok -bM:UR - -ifdef JS_THREADSAFE -XLDFLAGS += -ldl -endif - diff --git a/lib/javascript/config/Darwin.mk b/lib/javascript/config/Darwin.mk deleted file mode 100644 index 9b9b6ff0..00000000 --- a/lib/javascript/config/Darwin.mk +++ /dev/null @@ -1,81 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Steve Zellers (zellers@apple.com) -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config for Mac OS X as of PR3 -# Just ripped from Linux config -# - -CC = cc -CCC = g++ -CFLAGS += -Wall -Wno-format -OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DDARWIN - -RANLIB = ranlib -MKSHLIB = libtool $(XMKSHLIBOPTS) -framework System - -#.c.o: -# $(CC) -c -MD $*.d $(CFLAGS) $< - -CPU_ARCH = $(shell uname -m) -ifeq (86,$(findstring 86,$(CPU_ARCH))) -CPU_ARCH = x86 -OS_CFLAGS+= -DX86_LINUX -endif -GFX_ARCH = x - -OS_LIBS = -lc -framework System - -ASFLAGS += -x assembler-with-cpp - -ifeq ($(CPU_ARCH),alpha) - -# Ask the C compiler on alpha linux to let us work with denormalized -# double values, which are required by the ECMA spec. - -OS_CFLAGS += -mieee -endif - -# Use the editline library to provide line-editing support. -JS_EDITLINE = 1 - -# Don't allow Makefile.ref to use libmath -NO_LIBM = 1 - diff --git a/lib/javascript/config/Darwin1.3.mk b/lib/javascript/config/Darwin1.3.mk deleted file mode 100755 index 05d3767a..00000000 --- a/lib/javascript/config/Darwin1.3.mk +++ /dev/null @@ -1,81 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Steve Zellers (zellers@apple.com) -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config for Mac OS X as of PR3 -# Just ripped from Linux config -# - -CC = cc -CCC = g++ -CFLAGS += -Wall -Wno-format -OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DRHAPSODY - -RANLIB = ranlib -MKSHLIB = libtool $(XMKSHLIBOPTS) -framework System - -#.c.o: -# $(CC) -c -MD $*.d $(CFLAGS) $< - -CPU_ARCH = $(shell uname -m) -ifeq (86,$(findstring 86,$(CPU_ARCH))) -CPU_ARCH = x86 -OS_CFLAGS+= -DX86_LINUX -endif -GFX_ARCH = x - -OS_LIBS = -lc -framework System - -ASFLAGS += -x assembler-with-cpp - -ifeq ($(CPU_ARCH),alpha) - -# Ask the C compiler on alpha linux to let us work with denormalized -# double values, which are required by the ECMA spec. - -OS_CFLAGS += -mieee -endif - -# Use the editline library to provide line-editing support. -JS_EDITLINE = 1 - -# Don't allow Makefile.ref to use libmath -NO_LIBM = 1 - diff --git a/lib/javascript/config/Darwin1.4.mk b/lib/javascript/config/Darwin1.4.mk deleted file mode 100755 index f7b6af8e..00000000 --- a/lib/javascript/config/Darwin1.4.mk +++ /dev/null @@ -1,41 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mike McCabe -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -include $(DEPTH)/config/Darwin1.3.mk diff --git a/lib/javascript/config/Darwin5.2.mk b/lib/javascript/config/Darwin5.2.mk deleted file mode 100755 index 9b9b6ff0..00000000 --- a/lib/javascript/config/Darwin5.2.mk +++ /dev/null @@ -1,81 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Steve Zellers (zellers@apple.com) -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config for Mac OS X as of PR3 -# Just ripped from Linux config -# - -CC = cc -CCC = g++ -CFLAGS += -Wall -Wno-format -OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DDARWIN - -RANLIB = ranlib -MKSHLIB = libtool $(XMKSHLIBOPTS) -framework System - -#.c.o: -# $(CC) -c -MD $*.d $(CFLAGS) $< - -CPU_ARCH = $(shell uname -m) -ifeq (86,$(findstring 86,$(CPU_ARCH))) -CPU_ARCH = x86 -OS_CFLAGS+= -DX86_LINUX -endif -GFX_ARCH = x - -OS_LIBS = -lc -framework System - -ASFLAGS += -x assembler-with-cpp - -ifeq ($(CPU_ARCH),alpha) - -# Ask the C compiler on alpha linux to let us work with denormalized -# double values, which are required by the ECMA spec. - -OS_CFLAGS += -mieee -endif - -# Use the editline library to provide line-editing support. -JS_EDITLINE = 1 - -# Don't allow Makefile.ref to use libmath -NO_LIBM = 1 - diff --git a/lib/javascript/config/Darwin5.3.mk b/lib/javascript/config/Darwin5.3.mk deleted file mode 100644 index 9b9b6ff0..00000000 --- a/lib/javascript/config/Darwin5.3.mk +++ /dev/null @@ -1,81 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Steve Zellers (zellers@apple.com) -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config for Mac OS X as of PR3 -# Just ripped from Linux config -# - -CC = cc -CCC = g++ -CFLAGS += -Wall -Wno-format -OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DDARWIN - -RANLIB = ranlib -MKSHLIB = libtool $(XMKSHLIBOPTS) -framework System - -#.c.o: -# $(CC) -c -MD $*.d $(CFLAGS) $< - -CPU_ARCH = $(shell uname -m) -ifeq (86,$(findstring 86,$(CPU_ARCH))) -CPU_ARCH = x86 -OS_CFLAGS+= -DX86_LINUX -endif -GFX_ARCH = x - -OS_LIBS = -lc -framework System - -ASFLAGS += -x assembler-with-cpp - -ifeq ($(CPU_ARCH),alpha) - -# Ask the C compiler on alpha linux to let us work with denormalized -# double values, which are required by the ECMA spec. - -OS_CFLAGS += -mieee -endif - -# Use the editline library to provide line-editing support. -JS_EDITLINE = 1 - -# Don't allow Makefile.ref to use libmath -NO_LIBM = 1 - diff --git a/lib/javascript/config/HP-UXB.10.10.mk b/lib/javascript/config/HP-UXB.10.10.mk deleted file mode 100644 index 8cd9d206..00000000 --- a/lib/javascript/config/HP-UXB.10.10.mk +++ /dev/null @@ -1,77 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config stuff for HPUX -# - -# CC = gcc -# CCC = g++ -# CFLAGS += -Wall -Wno-format -fPIC - -CC = cc -Ae +Z -CCC = CC -Ae +a1 +eh +Z - -RANLIB = echo -MKSHLIB = $(LD) -b - -SO_SUFFIX = sl - -#.c.o: -# $(CC) -c -MD $*.d $(CFLAGS) $< - -CPU_ARCH = hppa -GFX_ARCH = x - -OS_CFLAGS = -DXP_UNIX -DHPUX -DSYSV -DHAVE_LOCALTIME_R -OS_LIBS = -ldld - -ifeq ($(OS_RELEASE),B.10) -PLATFORM_FLAGS += -DHPUX10 -Dhpux10 -PORT_FLAGS += -DRW_NO_OVERLOAD_SCHAR -DHAVE_MODEL_H -ifeq ($(OS_VERSION),.10) -PLATFORM_FLAGS += -DHPUX10_10 -endif -ifeq ($(OS_VERSION),.20) -PLATFORM_FLAGS += -DHPUX10_20 -endif -ifeq ($(OS_VERSION),.30) -PLATFORM_FLAGS += -DHPUX10_30 -endif -endif diff --git a/lib/javascript/config/HP-UXB.10.20.mk b/lib/javascript/config/HP-UXB.10.20.mk deleted file mode 100644 index 8cd9d206..00000000 --- a/lib/javascript/config/HP-UXB.10.20.mk +++ /dev/null @@ -1,77 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config stuff for HPUX -# - -# CC = gcc -# CCC = g++ -# CFLAGS += -Wall -Wno-format -fPIC - -CC = cc -Ae +Z -CCC = CC -Ae +a1 +eh +Z - -RANLIB = echo -MKSHLIB = $(LD) -b - -SO_SUFFIX = sl - -#.c.o: -# $(CC) -c -MD $*.d $(CFLAGS) $< - -CPU_ARCH = hppa -GFX_ARCH = x - -OS_CFLAGS = -DXP_UNIX -DHPUX -DSYSV -DHAVE_LOCALTIME_R -OS_LIBS = -ldld - -ifeq ($(OS_RELEASE),B.10) -PLATFORM_FLAGS += -DHPUX10 -Dhpux10 -PORT_FLAGS += -DRW_NO_OVERLOAD_SCHAR -DHAVE_MODEL_H -ifeq ($(OS_VERSION),.10) -PLATFORM_FLAGS += -DHPUX10_10 -endif -ifeq ($(OS_VERSION),.20) -PLATFORM_FLAGS += -DHPUX10_20 -endif -ifeq ($(OS_VERSION),.30) -PLATFORM_FLAGS += -DHPUX10_30 -endif -endif diff --git a/lib/javascript/config/HP-UXB.11.00.mk b/lib/javascript/config/HP-UXB.11.00.mk deleted file mode 100644 index 239188d6..00000000 --- a/lib/javascript/config/HP-UXB.11.00.mk +++ /dev/null @@ -1,80 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config stuff for HPUX -# - -ifdef NS_USE_NATIVE - CC = cc +Z +DAportable +DS2.0 +u4 -# LD = aCC +Z -b -Wl,+s -Wl,-B,symbolic -else - CC = gcc -Wall -Wno-format -fPIC - CCC = g++ -Wall -Wno-format -fPIC -endif - -RANLIB = echo -MKSHLIB = $(LD) -b - -SO_SUFFIX = sl - -#.c.o: -# $(CC) -c -MD $*.d $(CFLAGS) $< - -CPU_ARCH = hppa -GFX_ARCH = x - -OS_CFLAGS = -DXP_UNIX -DHPUX -DSYSV -D_HPUX -DNATIVE -D_POSIX_C_SOURCE=199506L -DHAVE_LOCALTIME_R -OS_LIBS = -ldld - -XLDFLAGS = -lpthread - -ifeq ($(OS_RELEASE),B.10) -PLATFORM_FLAGS += -DHPUX10 -Dhpux10 -PORT_FLAGS += -DRW_NO_OVERLOAD_SCHAR -DHAVE_MODEL_H -ifeq ($(OS_VERSION),.10) -PLATFORM_FLAGS += -DHPUX10_10 -endif -ifeq ($(OS_VERSION),.20) -PLATFORM_FLAGS += -DHPUX10_20 -endif -ifeq ($(OS_VERSION),.30) -PLATFORM_FLAGS += -DHPUX10_30 -endif -endif diff --git a/lib/javascript/config/IRIX.mk b/lib/javascript/config/IRIX.mk deleted file mode 100644 index 88b162f2..00000000 --- a/lib/javascript/config/IRIX.mk +++ /dev/null @@ -1,87 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config stuff for IRIX -# - -CPU_ARCH = mips -GFX_ARCH = x - -RANLIB = /bin/true - -#NS_USE_GCC = 1 - -ifndef NS_USE_NATIVE -CC = gcc -CCC = g++ -AS = $(CC) -x assembler-with-cpp -ODD_CFLAGS = -Wall -Wno-format -ifdef BUILD_OPT -OPTIMIZER = -O6 -endif -else -ifeq ($(OS_RELEASE),6.2) -CC = cc -n32 -DIRIX6_2 -endif -ifeq ($(OS_RELEASE),6.3) -CC = cc -n32 -DIRIX6_3 -endif -ifeq ($(OS_RELEASE),6.5) -CC = cc -n32 -DIRIX6_5 -endif -CCC = CC -# LD = CC -ODD_CFLAGS = -fullwarn -xansi -ifdef BUILD_OPT -OPTIMIZER += -Olimit 4000 -endif -endif - -# For purify -HAVE_PURIFY = 1 -PURE_OS_CFLAGS = $(ODD_CFLAGS) -DXP_UNIX -DSVR4 -DSW_THREADS -DIRIX -DHAVE_LOCALTIME_R - -OS_CFLAGS = $(PURE_OS_CFLAGS) -MDupdate $(DEPENDENCIES) - -BSDECHO = echo -MKSHLIB = $(LD) -n32 -shared - -# Use the editline library to provide line-editing support. -JS_EDITLINE = 1 diff --git a/lib/javascript/config/IRIX5.3.mk b/lib/javascript/config/IRIX5.3.mk deleted file mode 100644 index f38cc948..00000000 --- a/lib/javascript/config/IRIX5.3.mk +++ /dev/null @@ -1,44 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config stuff for IRIX5.3 -# - -include $(DEPTH)/config/IRIX.mk diff --git a/lib/javascript/config/IRIX6.1.mk b/lib/javascript/config/IRIX6.1.mk deleted file mode 100644 index 354f1d11..00000000 --- a/lib/javascript/config/IRIX6.1.mk +++ /dev/null @@ -1,44 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config stuff for IRIX6.3 -# - -include $(DEPTH)/config/IRIX.mk diff --git a/lib/javascript/config/IRIX6.2.mk b/lib/javascript/config/IRIX6.2.mk deleted file mode 100644 index 354f1d11..00000000 --- a/lib/javascript/config/IRIX6.2.mk +++ /dev/null @@ -1,44 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config stuff for IRIX6.3 -# - -include $(DEPTH)/config/IRIX.mk diff --git a/lib/javascript/config/IRIX6.3.mk b/lib/javascript/config/IRIX6.3.mk deleted file mode 100644 index 354f1d11..00000000 --- a/lib/javascript/config/IRIX6.3.mk +++ /dev/null @@ -1,44 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config stuff for IRIX6.3 -# - -include $(DEPTH)/config/IRIX.mk diff --git a/lib/javascript/config/IRIX6.5.mk b/lib/javascript/config/IRIX6.5.mk deleted file mode 100644 index 354f1d11..00000000 --- a/lib/javascript/config/IRIX6.5.mk +++ /dev/null @@ -1,44 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config stuff for IRIX6.3 -# - -include $(DEPTH)/config/IRIX.mk diff --git a/lib/javascript/config/Linux_All.mk b/lib/javascript/config/Linux_All.mk deleted file mode 100644 index 77f8af35..00000000 --- a/lib/javascript/config/Linux_All.mk +++ /dev/null @@ -1,103 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config for all versions of Linux -# - -CC = gcc -CCC = g++ -CFLAGS += -Wall -Wno-format -OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DHAVE_LOCALTIME_R - -RANLIB = echo -MKSHLIB = $(LD) -shared $(XMKSHLIBOPTS) - -#.c.o: -# $(CC) -c -MD $*.d $(CFLAGS) $< - -CPU_ARCH = $(shell uname -m) -# don't filter in x86-64 architecture -ifneq (x86_64,$(CPU_ARCH)) -ifeq (86,$(findstring 86,$(CPU_ARCH))) -CPU_ARCH = x86 -OS_CFLAGS+= -DX86_LINUX - -ifeq (gcc, $(CC)) -# if using gcc on x86, check version for opt bug -# (http://bugzilla.mozilla.org/show_bug.cgi?id=24892) -GCC_VERSION := $(shell gcc -v 2>&1 | grep version | awk '{ print $$3 }') -GCC_LIST:=$(sort 2.91.66 $(GCC_VERSION) ) - -ifeq (2.91.66, $(firstword $(GCC_LIST))) -CFLAGS+= -DGCC_OPT_BUG -endif -endif -endif -endif - -GFX_ARCH = x - -OS_LIBS = -lm -lc - -ASFLAGS += -x assembler-with-cpp - - -ifeq ($(CPU_ARCH),alpha) - -# Ask the C compiler on alpha linux to let us work with denormalized -# double values, which are required by the ECMA spec. - -OS_CFLAGS += -mieee -endif - -# Use the editline library to provide line-editing support. -JS_EDITLINE = 1 - -##ifeq ($(CPU_ARCH),x86_64) -# Use VA_COPY() standard macro on x86-64 -# FIXME: better use it everywhere -OS_CFLAGS += -DHAVE_VA_COPY -DVA_COPY=va_copy -##endif - -ifeq ($(CPU_ARCH),x86_64) -# We need PIC code for shared libraries -# FIXME: better patch rules.mk & fdlibm/Makefile* -OS_CFLAGS += -DPIC -fPIC -endif diff --git a/lib/javascript/config/Mac_OS10.0.mk b/lib/javascript/config/Mac_OS10.0.mk deleted file mode 100755 index 74ba151e..00000000 --- a/lib/javascript/config/Mac_OS10.0.mk +++ /dev/null @@ -1,82 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Steve Zellers (zellers@apple.com) -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config for Mac OS X as of PR3 -# Just ripped from Linux config -# - -CC = cc -CCC = g++ -CFLAGS += -Wall -Wno-format -OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE --DRHAPSODY - -RANLIB = ranlib -MKSHLIB = libtool -dynamic $(XMKSHLIBOPTS) -framework System - -#.c.o: -# $(CC) -c -MD $*.d $(CFLAGS) $< - -CPU_ARCH = $(shell uname -m) -ifeq (86,$(findstring 86,$(CPU_ARCH))) -CPU_ARCH = x86 -OS_CFLAGS+= -DX86_LINUX -endif -GFX_ARCH = x - -OS_LIBS = -lc -framework System - -ASFLAGS += -x assembler-with-cpp - -ifeq ($(CPU_ARCH),alpha) - -# Ask the C compiler on alpha linux to let us work with denormalized -# double values, which are required by the ECMA spec. - -OS_CFLAGS += -mieee -endif - -# Use the editline library to provide line-editing support. -JS_EDITLINE = 1 - -# Don't allow Makefile.ref to use libmath -NO_LIBM = 1 - diff --git a/lib/javascript/config/OSF1V4.0.mk b/lib/javascript/config/OSF1V4.0.mk deleted file mode 100644 index 337ca745..00000000 --- a/lib/javascript/config/OSF1V4.0.mk +++ /dev/null @@ -1,72 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config stuff for Data General DG/UX -# - -# -# Initial DG/UX port by Marc Fraioli (fraioli@dg-rtp.dg.com) -# - -ifndef NS_USE_NATIVE -CC = gcc -CCC = g++ -CFLAGS += -mieee -Wall -Wno-format -else -CC = cc -CCC = cxx -CFLAGS += -ieee -std -# LD = cxx -endif - -RANLIB = echo -MKSHLIB = $(LD) -shared -taso -all -expect_unresolved "*" - -# -# _DGUX_SOURCE is needed to turn on a lot of stuff in the headers if -# you're not using DG's compiler. It shouldn't hurt if you are. -# -# _POSIX4A_DRAFT10_SOURCE is needed to pick up localtime_r, used in -# prtime.c -# -OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -DDGUX -D_DGUX_SOURCE -D_POSIX4A_DRAFT10_SOURCE -DOSF1 -DHAVE_LOCALTIME_R -OS_LIBS = -lsocket -lnsl - -NOSUCHFILE = /no-such-file diff --git a/lib/javascript/config/OSF1V5.0.mk b/lib/javascript/config/OSF1V5.0.mk deleted file mode 100644 index b65738c4..00000000 --- a/lib/javascript/config/OSF1V5.0.mk +++ /dev/null @@ -1,69 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config stuff for Tru64 Unix 5.0 -# - -# -# Initial DG/UX port by Marc Fraioli (fraioli@dg-rtp.dg.com) -# - -ifndef NS_USE_NATIVE -CC = gcc -CCC = g++ -CFLAGS += -mieee -Wall -Wno-format -else -CC = cc -CCC = cxx -CFLAGS += -ieee -std -pthread -# LD = cxx -endif - -RANLIB = echo -MKSHLIB = $(LD) -shared -all -expect_unresolved "*" - -# -# _POSIX4A_DRAFT10_SOURCE is needed to pick up localtime_r, used in -# prtime.c -# -OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_POSIX4A_DRAFT10_SOURCE -DOSF1 -DHAVE_LOCALTIME_R -OS_LIBS = -lsocket -lnsl - -NOSUCHFILE = /no-such-file diff --git a/lib/javascript/config/SunOS4.1.4.mk b/lib/javascript/config/SunOS4.1.4.mk deleted file mode 100644 index 62f4815b..00000000 --- a/lib/javascript/config/SunOS4.1.4.mk +++ /dev/null @@ -1,101 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config stuff for SunOS4.1 -# - -CC = gcc -CCC = g++ -RANLIB = ranlib - -#.c.o: -# $(CC) -c -MD $*.d $(CFLAGS) $< - -CPU_ARCH = sparc -GFX_ARCH = x - -# A pile of -D's to build xfe on sunos -MOZ_CFLAGS = -DSTRINGS_ALIGNED -DNO_REGEX -DNO_ISDIR -DUSE_RE_COMP \ - -DNO_REGCOMP -DUSE_GETWD -DNO_MEMMOVE -DNO_ALLOCA \ - -DBOGUS_MB_MAX -DNO_CONST - -# Purify doesn't like -MDupdate -NOMD_OS_CFLAGS = -DXP_UNIX -Wall -Wno-format -DSW_THREADS -DSUNOS4 -DNEED_SYSCALL \ - $(MOZ_CFLAGS) - -OS_CFLAGS = $(NOMD_OS_CFLAGS) -MDupdate $(DEPENDENCIES) -OS_LIBS = -ldl -lm - -MKSHLIB = $(LD) -L$(MOTIF)/lib - -HAVE_PURIFY = 1 -MOTIF = /home/motif/usr -MOTIFLIB = -L$(MOTIF)/lib -lXm -INCLUDES += -I/usr/X11R5/include -I$(MOTIF)/include - -NOSUCHFILE = /solaris-rm-f-sucks - -LOCALE_MAP = $(DEPTH)/cmd/xfe/intl/sunos.lm - -EN_LOCALE = en_US -DE_LOCALE = de -FR_LOCALE = fr -JP_LOCALE = ja -SJIS_LOCALE = ja_JP.SJIS -KR_LOCALE = ko -CN_LOCALE = zh -TW_LOCALE = zh_TW -I2_LOCALE = i2 -IT_LOCALE = it -SV_LOCALE = sv -ES_LOCALE = es -NL_LOCALE = nl -PT_LOCALE = pt - -LOC_LIB_DIR = /usr/openwin/lib/locale - -BSDECHO = echo - -# -# These defines are for building unix plugins -# -BUILD_UNIX_PLUGINS = 1 -DSO_LDOPTS = -DSO_LDFLAGS = diff --git a/lib/javascript/config/SunOS5.3.mk b/lib/javascript/config/SunOS5.3.mk deleted file mode 100644 index bd615dee..00000000 --- a/lib/javascript/config/SunOS5.3.mk +++ /dev/null @@ -1,91 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config stuff for SunOS5.3 -# - -CC = gcc -CCC = g++ -CFLAGS += -Wall -Wno-format - -#CC = /opt/SUNWspro/SC3.0.1/bin/cc -RANLIB = echo - -#.c.o: -# $(CC) -c -MD $*.d $(CFLAGS) $< - -CPU_ARCH = sparc -GFX_ARCH = x - -OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -DSOLARIS -DHAVE_LOCALTIME_R -OS_LIBS = -lsocket -lnsl -ldl - -ASFLAGS += -P -L -K PIC -D_ASM -D__STDC__=0 - -HAVE_PURIFY = 1 - -NOSUCHFILE = /solaris-rm-f-sucks - -ifndef JS_NO_ULTRA -ULTRA_OPTIONS := -xarch=v8plus -ULTRA_OPTIONSD := -DULTRA_SPARC -else -ULTRA_OPTIONS := -xarch=v8 -ULTRA_OPTIONSD := -endif - -ifeq ($(OS_CPUARCH),sun4u) -DEFINES += $(ULTRA_OPTIONSD) -ifeq ($(findstring gcc,$(CC)),gcc) -DEFINES += -Wa,$(ULTRA_OPTIONS),$(ULTRA_OPTIONSD) -else -ASFLAGS += $(ULTRA_OPTIONS) $(ULTRA_OPTIONSD) -endif -endif - -ifeq ($(OS_CPUARCH),sun4m) -ifeq ($(findstring gcc,$(CC)),gcc) -DEFINES += -Wa,-xarch=v8 -else -ASFLAGS += -xarch=v8 -endif -endif - -MKSHLIB = $(LD) -G diff --git a/lib/javascript/config/SunOS5.4.mk b/lib/javascript/config/SunOS5.4.mk deleted file mode 100644 index de019247..00000000 --- a/lib/javascript/config/SunOS5.4.mk +++ /dev/null @@ -1,92 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config stuff for SunOS5.4 -# - -ifdef NS_USE_NATIVE -CC = cc -CCC = CC -else -CC = gcc -CCC = g++ -CFLAGS += -Wall -Wno-format -endif - -RANLIB = echo - -CPU_ARCH = sparc -GFX_ARCH = x - -OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D__svr4 -DSOLARIS -DHAVE_LOCALTIME_R -OS_LIBS = -lsocket -lnsl -ldl - -ASFLAGS += -P -L -K PIC -D_ASM -D__STDC__=0 - -HAVE_PURIFY = 1 - -NOSUCHFILE = /solaris-rm-f-sucks - -ifndef JS_NO_ULTRA -ULTRA_OPTIONS := -xarch=v8plus -ULTRA_OPTIONSD := -DULTRA_SPARC -else -ULTRA_OPTIONS := -xarch=v8 -ULTRA_OPTIONSD := -endif - -ifeq ($(OS_CPUARCH),sun4u) -DEFINES += $(ULTRA_OPTIONSD) -ifeq ($(findstring gcc,$(CC)),gcc) -DEFINES += -Wa,$(ULTRA_OPTIONS),$(ULTRA_OPTIONSD) -else -ASFLAGS += $(ULTRA_OPTIONS) $(ULTRA_OPTIONSD) -endif -endif - -ifeq ($(OS_CPUARCH),sun4m) -ifeq ($(findstring gcc,$(CC)),gcc) -DEFINES += -Wa,-xarch=v8 -else -ASFLAGS += -xarch=v8 -endif -endif - -MKSHLIB = $(LD) -G diff --git a/lib/javascript/config/SunOS5.5.1.mk b/lib/javascript/config/SunOS5.5.1.mk deleted file mode 100644 index 648f72ff..00000000 --- a/lib/javascript/config/SunOS5.5.1.mk +++ /dev/null @@ -1,44 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config stuff for SunOS5.5.1 -# - -include $(DEPTH)/config/SunOS5.5.mk diff --git a/lib/javascript/config/SunOS5.5.mk b/lib/javascript/config/SunOS5.5.mk deleted file mode 100644 index e26b3a3e..00000000 --- a/lib/javascript/config/SunOS5.5.mk +++ /dev/null @@ -1,87 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config stuff for SunOS5.5 -# - -AS = /usr/ccs/bin/as -ifndef NS_USE_NATIVE -CC = gcc -CCC = g++ -CFLAGS += -Wall -Wno-format -else -CC = cc -CCC = CC -endif - -RANLIB = echo - -#.c.o: -# $(CC) -c -MD $*.d $(CFLAGS) $< - -CPU_ARCH = sparc -GFX_ARCH = x - -OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -DSOLARIS -DHAVE_LOCALTIME_R -OS_LIBS = -lsocket -lnsl -ldl - -ASFLAGS += -P -L -K PIC -D_ASM -D__STDC__=0 - -HAVE_PURIFY = 1 - -NOSUCHFILE = /solaris-rm-f-sucks - -ifeq ($(OS_CPUARCH),sun4u) # ultra sparc? -ifeq ($(CC),gcc) # using gcc? -ifndef JS_NO_ULTRA # do we want ultra? -ifdef JS_THREADSAFE # only in thread-safe mode -DEFINES += -DULTRA_SPARC -DEFINES += -Wa,-xarch=v8plus,-DULTRA_SPARC -else -ASFLAGS += -xarch=v8plus -DULTRA_SPARC -endif -endif -endif -endif - -MKSHLIB = $(LD) -G - -# Use the editline library to provide line-editing support. -JS_EDITLINE = 1 diff --git a/lib/javascript/config/SunOS5.6.mk b/lib/javascript/config/SunOS5.6.mk deleted file mode 100644 index efe11528..00000000 --- a/lib/javascript/config/SunOS5.6.mk +++ /dev/null @@ -1,89 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config stuff for SunOS5.5 -# - -AS = /usr/ccs/bin/as -ifndef NS_USE_NATIVE - CC = gcc - CCC = g++ - CFLAGS += -Wall -Wno-format -else - CC = cc - CCC = CC - CFLAGS += -mt -KPIC -# LD = CC -endif - -RANLIB = echo - -#.c.o: -# $(CC) -c -MD $*.d $(CFLAGS) $< - -CPU_ARCH = sparc -GFX_ARCH = x - -OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -DSOLARIS -DHAVE_LOCALTIME_R -OS_LIBS = -lsocket -lnsl -ldl - -ASFLAGS += -P -L -K PIC -D_ASM -D__STDC__=0 - -HAVE_PURIFY = 1 - -NOSUCHFILE = /solaris-rm-f-sucks - -ifeq ($(OS_CPUARCH),sun4u) # ultra sparc? -ifeq ($(CC),gcc) # using gcc? -ifndef JS_NO_ULTRA # do we want ultra? -ifdef JS_THREADSAFE # only in thread-safe mode -DEFINES += -DULTRA_SPARC -DEFINES += -Wa,-xarch=v8plus,-DULTRA_SPARC -else -ASFLAGS += -xarch=v8plus -DULTRA_SPARC -endif -endif -endif -endif - -MKSHLIB = $(LD) -G - -# Use the editline library to provide line-editing support. -JS_EDITLINE = 1 diff --git a/lib/javascript/config/SunOS5.7.mk b/lib/javascript/config/SunOS5.7.mk deleted file mode 100644 index 2cb02f29..00000000 --- a/lib/javascript/config/SunOS5.7.mk +++ /dev/null @@ -1,44 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1999 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config stuff for SunOS5.7 -# - -include $(DEPTH)/config/SunOS5.5.mk diff --git a/lib/javascript/config/SunOS5.8.mk b/lib/javascript/config/SunOS5.8.mk deleted file mode 100644 index dd8a32d4..00000000 --- a/lib/javascript/config/SunOS5.8.mk +++ /dev/null @@ -1,44 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1999 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config stuff for SunOS5.8 -# - -include $(DEPTH)/config/SunOS5.5.mk diff --git a/lib/javascript/config/SunOS5.9.mk b/lib/javascript/config/SunOS5.9.mk deleted file mode 100644 index b01ec9c2..00000000 --- a/lib/javascript/config/SunOS5.9.mk +++ /dev/null @@ -1,44 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1999 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config stuff for SunOS5.9 -# - -include $(DEPTH)/config/SunOS5.5.mk diff --git a/lib/javascript/config/WINNT4.0.mk b/lib/javascript/config/WINNT4.0.mk deleted file mode 100644 index fe3fd0a5..00000000 --- a/lib/javascript/config/WINNT4.0.mk +++ /dev/null @@ -1,115 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config for Windows NT using MS Visual C++ (version?) -# - -CC = cl - -RANLIB = echo - -PDBFILE = $(basename $(@F)).pdb - -#.c.o: -# $(CC) -c -MD $*.d $(CFLAGS) $< - -CPU_ARCH = x86 # XXX fixme -GFX_ARCH = win32 - -# MSVC compiler options for both debug/optimize -# -nologo - suppress copyright message -# -W3 - Warning level 3 -# -Gm - enable minimal rebuild -# -Z7 - put debug info into the executable, not in .pdb file -# -Zi - put debug info into .pdb file -# -YX - automatic precompiled headers -# -GX - enable C++ exception support -WIN_CFLAGS = -nologo -W3 - -# MSVC compiler options for debug builds linked to MSVCRTD.DLL -# -MDd - link with MSVCRTD.LIB (Dynamically-linked, multi-threaded, debug C-runtime) -# -Od - minimal optimization -WIN_IDG_CFLAGS = -MDd -Od -Z7 - -# MSVC compiler options for debug builds linked to MSVCRT.DLL -# -MD - link with MSVCRT.LIB (Dynamically-linked, multi-threaded, debug C-runtime) -# -Od - minimal optimization -WIN_DEBUG_CFLAGS = -MD -Od -Zi -Fd$(OBJDIR)/$(PDBFILE) - -# MSVC compiler options for release (optimized) builds -# -MD - link with MSVCRT.LIB (Dynamically-linked, multi-threaded, C-runtime) -# -O2 - Optimize for speed -# -G5 - Optimize for Pentium -WIN_OPT_CFLAGS = -MD -O2 - -ifdef BUILD_OPT -OPTIMIZER = $(WIN_OPT_CFLAGS) -else -ifdef BUILD_IDG -OPTIMIZER = $(WIN_IDG_CFLAGS) -else -OPTIMIZER = $(WIN_DEBUG_CFLAGS) -endif -endif - -OS_CFLAGS = -D_X86_=1 -DXP_WIN -DXP_WIN32 -DWIN32 -D_WINDOWS -D_WIN32 $(WIN_CFLAGS) -JSDLL_CFLAGS = -DEXPORT_JS_API -OS_LIBS = -lm -lc - -PREBUILT_CPUCFG = 1 -USE_MSVC = 1 - -LIB_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ - advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib -nologo\ - -subsystem:windows -dll -debug -pdb:$(OBJDIR)/$(PDBFILE)\ - -machine:I386\ - -opt:ref -opt:noicf - -EXE_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ - advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib -nologo\ - -subsystem:console -debug -pdb:$(OBJDIR)/$(PDBFILE)\ - -machine:I386\ - -opt:ref -opt:noicf - -# CAFEDIR = t:/cafe -# JCLASSPATH = $(CAFEDIR)/Java/Lib/classes.zip -# JAVAC = $(CAFEDIR)/Bin/sj.exe -# JAVAH = $(CAFEDIR)/Java/Bin/javah.exe -# JCFLAGS = -I$(CAFEDIR)/Java/Include -I$(CAFEDIR)/Java/Include/win32 diff --git a/lib/javascript/config/WINNT5.0.mk b/lib/javascript/config/WINNT5.0.mk deleted file mode 100644 index fe3fd0a5..00000000 --- a/lib/javascript/config/WINNT5.0.mk +++ /dev/null @@ -1,115 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config for Windows NT using MS Visual C++ (version?) -# - -CC = cl - -RANLIB = echo - -PDBFILE = $(basename $(@F)).pdb - -#.c.o: -# $(CC) -c -MD $*.d $(CFLAGS) $< - -CPU_ARCH = x86 # XXX fixme -GFX_ARCH = win32 - -# MSVC compiler options for both debug/optimize -# -nologo - suppress copyright message -# -W3 - Warning level 3 -# -Gm - enable minimal rebuild -# -Z7 - put debug info into the executable, not in .pdb file -# -Zi - put debug info into .pdb file -# -YX - automatic precompiled headers -# -GX - enable C++ exception support -WIN_CFLAGS = -nologo -W3 - -# MSVC compiler options for debug builds linked to MSVCRTD.DLL -# -MDd - link with MSVCRTD.LIB (Dynamically-linked, multi-threaded, debug C-runtime) -# -Od - minimal optimization -WIN_IDG_CFLAGS = -MDd -Od -Z7 - -# MSVC compiler options for debug builds linked to MSVCRT.DLL -# -MD - link with MSVCRT.LIB (Dynamically-linked, multi-threaded, debug C-runtime) -# -Od - minimal optimization -WIN_DEBUG_CFLAGS = -MD -Od -Zi -Fd$(OBJDIR)/$(PDBFILE) - -# MSVC compiler options for release (optimized) builds -# -MD - link with MSVCRT.LIB (Dynamically-linked, multi-threaded, C-runtime) -# -O2 - Optimize for speed -# -G5 - Optimize for Pentium -WIN_OPT_CFLAGS = -MD -O2 - -ifdef BUILD_OPT -OPTIMIZER = $(WIN_OPT_CFLAGS) -else -ifdef BUILD_IDG -OPTIMIZER = $(WIN_IDG_CFLAGS) -else -OPTIMIZER = $(WIN_DEBUG_CFLAGS) -endif -endif - -OS_CFLAGS = -D_X86_=1 -DXP_WIN -DXP_WIN32 -DWIN32 -D_WINDOWS -D_WIN32 $(WIN_CFLAGS) -JSDLL_CFLAGS = -DEXPORT_JS_API -OS_LIBS = -lm -lc - -PREBUILT_CPUCFG = 1 -USE_MSVC = 1 - -LIB_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ - advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib -nologo\ - -subsystem:windows -dll -debug -pdb:$(OBJDIR)/$(PDBFILE)\ - -machine:I386\ - -opt:ref -opt:noicf - -EXE_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ - advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib -nologo\ - -subsystem:console -debug -pdb:$(OBJDIR)/$(PDBFILE)\ - -machine:I386\ - -opt:ref -opt:noicf - -# CAFEDIR = t:/cafe -# JCLASSPATH = $(CAFEDIR)/Java/Lib/classes.zip -# JAVAC = $(CAFEDIR)/Bin/sj.exe -# JAVAH = $(CAFEDIR)/Java/Bin/javah.exe -# JCFLAGS = -I$(CAFEDIR)/Java/Include -I$(CAFEDIR)/Java/Include/win32 diff --git a/lib/javascript/config/WINNT5.1.mk b/lib/javascript/config/WINNT5.1.mk deleted file mode 100644 index fe3fd0a5..00000000 --- a/lib/javascript/config/WINNT5.1.mk +++ /dev/null @@ -1,115 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config for Windows NT using MS Visual C++ (version?) -# - -CC = cl - -RANLIB = echo - -PDBFILE = $(basename $(@F)).pdb - -#.c.o: -# $(CC) -c -MD $*.d $(CFLAGS) $< - -CPU_ARCH = x86 # XXX fixme -GFX_ARCH = win32 - -# MSVC compiler options for both debug/optimize -# -nologo - suppress copyright message -# -W3 - Warning level 3 -# -Gm - enable minimal rebuild -# -Z7 - put debug info into the executable, not in .pdb file -# -Zi - put debug info into .pdb file -# -YX - automatic precompiled headers -# -GX - enable C++ exception support -WIN_CFLAGS = -nologo -W3 - -# MSVC compiler options for debug builds linked to MSVCRTD.DLL -# -MDd - link with MSVCRTD.LIB (Dynamically-linked, multi-threaded, debug C-runtime) -# -Od - minimal optimization -WIN_IDG_CFLAGS = -MDd -Od -Z7 - -# MSVC compiler options for debug builds linked to MSVCRT.DLL -# -MD - link with MSVCRT.LIB (Dynamically-linked, multi-threaded, debug C-runtime) -# -Od - minimal optimization -WIN_DEBUG_CFLAGS = -MD -Od -Zi -Fd$(OBJDIR)/$(PDBFILE) - -# MSVC compiler options for release (optimized) builds -# -MD - link with MSVCRT.LIB (Dynamically-linked, multi-threaded, C-runtime) -# -O2 - Optimize for speed -# -G5 - Optimize for Pentium -WIN_OPT_CFLAGS = -MD -O2 - -ifdef BUILD_OPT -OPTIMIZER = $(WIN_OPT_CFLAGS) -else -ifdef BUILD_IDG -OPTIMIZER = $(WIN_IDG_CFLAGS) -else -OPTIMIZER = $(WIN_DEBUG_CFLAGS) -endif -endif - -OS_CFLAGS = -D_X86_=1 -DXP_WIN -DXP_WIN32 -DWIN32 -D_WINDOWS -D_WIN32 $(WIN_CFLAGS) -JSDLL_CFLAGS = -DEXPORT_JS_API -OS_LIBS = -lm -lc - -PREBUILT_CPUCFG = 1 -USE_MSVC = 1 - -LIB_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ - advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib -nologo\ - -subsystem:windows -dll -debug -pdb:$(OBJDIR)/$(PDBFILE)\ - -machine:I386\ - -opt:ref -opt:noicf - -EXE_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ - advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib -nologo\ - -subsystem:console -debug -pdb:$(OBJDIR)/$(PDBFILE)\ - -machine:I386\ - -opt:ref -opt:noicf - -# CAFEDIR = t:/cafe -# JCLASSPATH = $(CAFEDIR)/Java/Lib/classes.zip -# JAVAC = $(CAFEDIR)/Bin/sj.exe -# JAVAH = $(CAFEDIR)/Java/Bin/javah.exe -# JCFLAGS = -I$(CAFEDIR)/Java/Include -I$(CAFEDIR)/Java/Include/win32 diff --git a/lib/javascript/config/WINNT5.2.mk b/lib/javascript/config/WINNT5.2.mk deleted file mode 100644 index fe3fd0a5..00000000 --- a/lib/javascript/config/WINNT5.2.mk +++ /dev/null @@ -1,115 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config for Windows NT using MS Visual C++ (version?) -# - -CC = cl - -RANLIB = echo - -PDBFILE = $(basename $(@F)).pdb - -#.c.o: -# $(CC) -c -MD $*.d $(CFLAGS) $< - -CPU_ARCH = x86 # XXX fixme -GFX_ARCH = win32 - -# MSVC compiler options for both debug/optimize -# -nologo - suppress copyright message -# -W3 - Warning level 3 -# -Gm - enable minimal rebuild -# -Z7 - put debug info into the executable, not in .pdb file -# -Zi - put debug info into .pdb file -# -YX - automatic precompiled headers -# -GX - enable C++ exception support -WIN_CFLAGS = -nologo -W3 - -# MSVC compiler options for debug builds linked to MSVCRTD.DLL -# -MDd - link with MSVCRTD.LIB (Dynamically-linked, multi-threaded, debug C-runtime) -# -Od - minimal optimization -WIN_IDG_CFLAGS = -MDd -Od -Z7 - -# MSVC compiler options for debug builds linked to MSVCRT.DLL -# -MD - link with MSVCRT.LIB (Dynamically-linked, multi-threaded, debug C-runtime) -# -Od - minimal optimization -WIN_DEBUG_CFLAGS = -MD -Od -Zi -Fd$(OBJDIR)/$(PDBFILE) - -# MSVC compiler options for release (optimized) builds -# -MD - link with MSVCRT.LIB (Dynamically-linked, multi-threaded, C-runtime) -# -O2 - Optimize for speed -# -G5 - Optimize for Pentium -WIN_OPT_CFLAGS = -MD -O2 - -ifdef BUILD_OPT -OPTIMIZER = $(WIN_OPT_CFLAGS) -else -ifdef BUILD_IDG -OPTIMIZER = $(WIN_IDG_CFLAGS) -else -OPTIMIZER = $(WIN_DEBUG_CFLAGS) -endif -endif - -OS_CFLAGS = -D_X86_=1 -DXP_WIN -DXP_WIN32 -DWIN32 -D_WINDOWS -D_WIN32 $(WIN_CFLAGS) -JSDLL_CFLAGS = -DEXPORT_JS_API -OS_LIBS = -lm -lc - -PREBUILT_CPUCFG = 1 -USE_MSVC = 1 - -LIB_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ - advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib -nologo\ - -subsystem:windows -dll -debug -pdb:$(OBJDIR)/$(PDBFILE)\ - -machine:I386\ - -opt:ref -opt:noicf - -EXE_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ - advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib -nologo\ - -subsystem:console -debug -pdb:$(OBJDIR)/$(PDBFILE)\ - -machine:I386\ - -opt:ref -opt:noicf - -# CAFEDIR = t:/cafe -# JCLASSPATH = $(CAFEDIR)/Java/Lib/classes.zip -# JAVAC = $(CAFEDIR)/Bin/sj.exe -# JAVAH = $(CAFEDIR)/Java/Bin/javah.exe -# JCFLAGS = -I$(CAFEDIR)/Java/Include -I$(CAFEDIR)/Java/Include/win32 diff --git a/lib/javascript/config/dgux.mk b/lib/javascript/config/dgux.mk deleted file mode 100644 index 3b5967e3..00000000 --- a/lib/javascript/config/dgux.mk +++ /dev/null @@ -1,64 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Config stuff for Data General DG/UX -# - -# -# Initial DG/UX port by Marc Fraioli (fraioli@dg-rtp.dg.com) -# - -AS = as -CC = gcc -CCC = g++ - -RANLIB = echo - -# -# _DGUX_SOURCE is needed to turn on a lot of stuff in the headers if -# you're not using DG's compiler. It shouldn't hurt if you are. -# -# _POSIX4A_DRAFT10_SOURCE is needed to pick up localtime_r, used in -# prtime.c -# -OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -DDGUX -D_DGUX_SOURCE -D_POSIX4A_DRAFT10_SOURCE -DHAVE_LOCALTIME_R -OS_LIBS = -lsocket -lnsl - -NOSUCHFILE = /no-such-file diff --git a/lib/javascript/editline/Makefile.ref b/lib/javascript/editline/Makefile.ref deleted file mode 100644 index c2b53a90..00000000 --- a/lib/javascript/editline/Makefile.ref +++ /dev/null @@ -1,144 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Simmule Turner and Rich Salz. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Copyright 1992,1993 Simmule Turner and Rich Salz. All rights reserved. -# -# This software is not subject to any license of the American Telephone -# and Telegraph Company or of the Regents of the University of California. -# -# Permission is granted to anyone to use this software for any purpose on -# any computer system, and to alter it and redistribute it freely, subject -# to the following restrictions: -# 1. The authors are not responsible for the consequences of use of this -# software, no matter how awful, even if they arise from flaws in it. -# 2. The origin of this software must not be misrepresented, either by -# explicit claim or by omission. Since few users ever read sources, -# credits must appear in the documentation. -# 3. Altered versions must be plainly marked as such, and must not be -# misrepresented as being the original software. Since few users -# ever read sources, credits must appear in the documentation. -# 4. This notice may not be removed or altered. -# - -# -# Unix makefile for editline library. -# - -## Set your options: -## -DANSI_ARROWS ANSI arrows keys work like emacs. -## -DHAVE_STDLIB Have . -## -DHAVE_TCGETATTR Have tcgetattr(), tcsetattr(). -## -DHAVE_TERMIO Have "struct termio" and -## (If neither of above two, we use and BSD ioctl's) -## -DHIDE Make static functions static (non debug). -## -DHIST_SIZE=n History size. -## -DNEED_STRDUP Don't have strdup(). -## -DUNIQUE_HISTORY Don't save command if same as last one. -## -DUSE_DIRENT Use , not ? -## -DUSE_TERMCAP Use the termcap library for terminal size -## see LDFLAGS, below, if you set this. -## -DNEED_PERROR Don't have perror() (used in testit) - -## If you have -DUSE_TERMCAP, set this as appropriate: -#LDFLAGS = -ltermlib -#LDFLAGS = -ltermcap - -DEFS = -DANSI_ARROWS -DHAVE_TCGETATTR -DHIDE -DUSE_DIRENT -DSYS_UNIX \ - -DHAVE_STDLIB -DUNIQUE_HISTORY - -DEPTH = .. - -include $(DEPTH)/config.mk - -# -# Default IEEE libm -# -CFLAGS += -DXP_UNIX $(OPTIMIZER) $(OS_CFLAGS) $(DEFINES) $(INCLUDES) \ - -DJSFILE $(XCFLAGS) $(DEFS) - -INCFILES = editline.h -.INIT: $(INCFILES) -.KEEP_STATE: -EDITLINE_CFILES = editline.c sysunix.c - -EDITLINE_OBJS = $(addprefix $(OBJDIR)/, $(EDITLINE_CFILES:.c=.o)) - -LIBRARY = $(OBJDIR)/libedit.a - -define MAKE_OBJDIR -if test ! -d $(@D); then rm -rf $(@D); mkdir $(@D); fi -endef - -all: $(LIBRARY) - -export: - -$(OBJDIR)/%: %.c - @$(MAKE_OBJDIR) - $(CC) -o $@ $(CFLAGS) $*.c $(LDFLAGS) - -$(OBJDIR)/%.o: %.c - @$(MAKE_OBJDIR) - $(CC) -o $@ -c $(CFLAGS) $*.c - -$(OBJDIR)/%.o: %.s - @$(MAKE_OBJDIR) - $(AS) -o $@ $(ASFLAGS) $*.s - -$(LIBRARY): $(EDITLINE_OBJS) - $(AR) rv $@ $? - $(RANLIB) $@ - -#libedit.a : $(EDITLINE_OBJS) -# $(AR) cru $(OBJDIR)/libedit.a $(EDITLINE_OBJS) -# $(RANLIB) $(OBJDIR)/libedit.a - -clean: - rm -rf $(EDITLINE_OBJS) - -clobber: - rm -rf $(EDITLINE_OBJS) $(LIBRARY) $(DEPENDENCIES) - -SUFFIXES: .i -%.i: %.c - $(CC) -C -E $(CFLAGS) $< > $*.i - - - diff --git a/lib/javascript/editline/README b/lib/javascript/editline/README deleted file mode 100644 index 53ec359f..00000000 --- a/lib/javascript/editline/README +++ /dev/null @@ -1,83 +0,0 @@ -The files in this directory provide simple line-editing and history -support for the standalone javascript engine, through the 'editline' -library. - -editline has only been enabled for those platforms on which it is -known to build; to try it on a different platform, define JS_EDITLINE -before building. Line editing (and js.c) is not a supported feature -of the javascript library, so your mileage my vary. - -The editline API is a compatible subset of the FSF readline API; if -you have readline installed and would like to link to that instead, -define JS_READLINE. Note that the readline library is distributed -under the GPL, so any resulting binaries are not legally -distributable. - -The editline files used here have been modified to work with the js -build system and to quiet some compiler warnings, and also to remove -filename-completion support. - -If anyone knows of a more recent version of these files, or a site on -which they are being maintained, please let me know! - -Mike McCabe, mccabe@netscape.com - - -The original README file distributed with the editline library follows. - - - -This is a line-editing library. It can be linked into almost any -program to provide command-line editing and recall. - -It is call-compatible with the FSF readline library, but it is a -fraction of the size (and offers fewer features). It does not use -standard I/O. It is distributed under a "C News-like" copyright. - -Configuration is done in the Makefile. Type "make testit" to get -a small slow shell for testing. - -An earlier version was distributed with Byron's rc. Principal -changes over that version include: - Faster. - Is eight-bit clean (thanks to brendan@cs.widener.edu) - Written in K&R C, but ANSI compliant (gcc all warnings) - Propagates EOF properly; rc trip test now passes - Doesn't need or use or provide memmove. - More robust - Calling sequence changed to be compatible with readline. - Test program, new manpage, better configuration - More system-independant; includes Unix and OS-9 support. - -This contains some changes since the posting to comp.sources.misc: - Bugfix for completion on absolute pathnames. - Better handling of M-n versus showing raw 8bit chars. - Better signal handling. - Now supports termios/termio/sgttyb ioctl's. - Add M-m command to toggle how 8bit data is displayed. - -There is one known bug: - History-searching redraws the line wrong if the text - retrieved is shorter then the prompt. - -Enjoy, - Rich $alz - - - Copyright 1992,1993 Simmule Turner and Rich Salz. All rights reserved. - - This software is not subject to any license of the American Telephone - and Telegraph Company or of the Regents of the University of California. - - Permission is granted to anyone to use this software for any purpose on - any computer system, and to alter it and redistribute it freely, subject - to the following restrictions: - 1. The authors are not responsible for the consequences of use of this - software, no matter how awful, even if they arise from flaws in it. - 2. The origin of this software must not be misrepresented, either by - explicit claim or by omission. Since few users ever read sources, - credits must appear in the documentation. - 3. Altered versions must be plainly marked as such, and must not be - misrepresented as being the original software. Since few users - ever read sources, credits must appear in the documentation. - 4. This notice may not be removed or altered. diff --git a/lib/javascript/editline/editline.3 b/lib/javascript/editline/editline.3 deleted file mode 100644 index 21a72ca3..00000000 --- a/lib/javascript/editline/editline.3 +++ /dev/null @@ -1,175 +0,0 @@ -.TH EDITLINE 3 -.SH NAME -editline \- command-line editing library with history -.SH SYNOPSIS -.nf -.B "char *" -.B "readline(prompt)" -.B " char *prompt;" - -.B "void" -.B "add_history(line)" -.B " char *line;" -.fi -.SH DESCRIPTION -.I Editline -is a library that provides an line-editing interface with text recall. -It is intended to be compatible with the -.I readline -library provided by the Free Software Foundation, but much smaller. -The bulk of this manual page describes the user interface. -.PP -The -.I readline -routine returns a line of text with the trailing newline removed. -The data is returned in a buffer allocated with -.IR malloc (3), -so the space should be released with -.IR free (3) -when the calling program is done with it. -Before accepting input from the user, the specified -.I prompt -is displayed on the terminal. -.PP -The -.I add_history -routine makes a copy of the specified -.I line -and adds it to the internal history list. -.SS "User Interface" -A program that uses this library provides a simple emacs-like editing -interface to its users. -A line may be edited before it is sent to the calling program by typing either -control characters or escape sequences. -A control character, shown as a caret followed by a letter, is typed by -holding down the ``control'' key while the letter is typed. -For example, ``^A'' is a control-A. -An escape sequence is entered by typing the ``escape'' key followed by one or -more characters. -The escape key is abbreviated as ``ESC.'' -Note that unlike control keys, case matters in escape sequences; ``ESC\ F'' -is not the same as ``ESC\ f''. -.PP -An editing command may be typed anywhere on the line, not just at the -beginning. -In addition, a return may also be typed anywhere on the line, not just at -the end. -.PP -Most editing commands may be given a repeat count, -.IR n , -where -.I n -is a number. -To enter a repeat count, type the escape key, the number, and then -the command to execute. -For example, ``ESC\ 4\ ^f'' moves forward four characters. -If a command may be given a repeat count then the text ``[n]'' is given at the -end of its description. -.PP -The following control characters are accepted: -.RS -.nf -.ta \w'ESC DEL 'u -^A Move to the beginning of the line -^B Move left (backwards) [n] -^D Delete character [n] -^E Move to end of line -^F Move right (forwards) [n] -^G Ring the bell -^H Delete character before cursor (backspace key) [n] -^I Complete filename (tab key); see below -^J Done with line (return key) -^K Kill to end of line (or column [n]) -^L Redisplay line -^M Done with line (alternate return key) -^N Get next line from history [n] -^P Get previous line from history [n] -^R Search backward (forward if [n]) through history for text; -\& must start line if text begins with an uparrow -^T Transpose characters -^V Insert next character, even if it is an edit command -^W Wipe to the mark -^X^X Exchange current location and mark -^Y Yank back last killed text -^[ Start an escape sequence (escape key) -^]c Move forward to next character ``c'' -^? Delete character before cursor (delete key) [n] -.fi -.RE -.PP -The following escape sequences are provided. -.RS -.nf -.ta \w'ESC DEL 'u -ESC\ ^H Delete previous word (backspace key) [n] -ESC\ DEL Delete previous word (delete key) [n] -ESC\ SP Set the mark (space key); see ^X^X and ^Y above -ESC\ \. Get the last (or [n]'th) word from previous line -ESC\ \? Show possible completions; see below -ESC\ < Move to start of history -ESC\ > Move to end of history -ESC\ b Move backward a word [n] -ESC\ d Delete word under cursor [n] -ESC\ f Move forward a word [n] -ESC\ l Make word lowercase [n] -ESC\ m Toggle if 8bit chars display normally or with ``M\-'' prefix -ESC\ u Make word uppercase [n] -ESC\ y Yank back last killed text -ESC\ v Show library version -ESC\ w Make area up to mark yankable -ESC\ nn Set repeat count to the number nn -ESC\ C Read from environment variable ``_C_'', where C is -\& an uppercase letter -.fi -.RE -.PP -The -.I editline -library has a small macro facility. -If you type the escape key followed by an uppercase letter, -.IR C , -then the contents of the environment variable -.I _C_ -are read in as if you had typed them at the keyboard. -For example, if the variable -.I _L_ -contains the following: -.RS -^A^Kecho '^V^[[H^V^[[2J'^M -.RE -Then typing ``ESC L'' will move to the beginning of the line, kill the -entire line, enter the echo command needed to clear the terminal (if your -terminal is like a VT-100), and send the line back to the shell. -.PP -The -.I editline -library also does filename completion. -Suppose the root directory has the following files in it: -.RS -.nf -.ta \w'core 'u -bin vmunix -core vmunix.old -.fi -.RE -If you type ``rm\ /v'' and then the tab key. -.I Editline -will then finish off as much of the name as possible by adding ``munix''. -Because the name is not unique, it will then beep. -If you type the escape key and a question mark, it will display the -two choices. -If you then type a period and a tab, the library will finish off the filename -for you: -.RS -.nf -.RI "rm /v[TAB]" munix .TAB old -.fi -.RE -The tab key is shown by ``[TAB]'' and the automatically-entered text -is shown in italics. -.SH "BUGS AND LIMITATIONS" -Cannot handle lines more than 80 columns. -.SH AUTHORS -Simmule R. Turner -and Rich $alz . -Original manual page by DaviD W. Sanderson . diff --git a/lib/javascript/editline/editline.c b/lib/javascript/editline/editline.c deleted file mode 100644 index 0f0210b3..00000000 --- a/lib/javascript/editline/editline.c +++ /dev/null @@ -1,1369 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Simmule Turner and Rich Salz. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * Copyright 1992,1993 Simmule Turner and Rich Salz. All rights reserved. - * - * This software is not subject to any license of the American Telephone - * and Telegraph Company or of the Regents of the University of California. - * - * Permission is granted to anyone to use this software for any purpose on - * any computer system, and to alter it and redistribute it freely, subject - * to the following restrictions: - * 1. The authors are not responsible for the consequences of use of this - * software, no matter how awful, even if they arise from flaws in it. - * 2. The origin of this software must not be misrepresented, either by - * explicit claim or by omission. Since few users ever read sources, - * credits must appear in the documentation. - * 3. Altered versions must be plainly marked as such, and must not be - * misrepresented as being the original software. Since few users - * ever read sources, credits must appear in the documentation. - * 4. This notice may not be removed or altered. - */ - - -/* -** Main editing routines for editline library. -*/ -#include "editline.h" -#include -#include - -/* -** Manifest constants. -*/ -#define SCREEN_WIDTH 80 -#define SCREEN_ROWS 24 -#define NO_ARG (-1) -#define DEL 127 -#define CTL(x) ((x) & 0x1F) -#define ISCTL(x) ((x) && (x) < ' ') -#define UNCTL(x) ((x) + 64) -#define META(x) ((x) | 0x80) -#define ISMETA(x) ((x) & 0x80) -#define UNMETA(x) ((x) & 0x7F) -#if !defined(HIST_SIZE) -#define HIST_SIZE 20 -#endif /* !defined(HIST_SIZE) */ - -/* -** Command status codes. -*/ -typedef enum _STATUS { - CSdone, CSeof, CSmove, CSdispatch, CSstay, CSsignal -} STATUS; - -/* -** The type of case-changing to perform. -*/ -typedef enum _CASE { - TOupper, TOlower -} CASE; - -/* -** Key to command mapping. -*/ -typedef struct _KEYMAP { - CHAR Key; - STATUS (*Function)(); -} KEYMAP; - -/* -** Command history structure. -*/ -typedef struct _HISTORY { - int Size; - int Pos; - CHAR *Lines[HIST_SIZE]; -} HISTORY; - -/* -** Globals. -*/ -int rl_eof; -int rl_erase; -int rl_intr; -int rl_kill; -int rl_quit; - -STATIC CHAR NIL[] = ""; -STATIC CONST CHAR *Input = NIL; -STATIC CHAR *Line; -STATIC CONST char *Prompt; -STATIC CHAR *Yanked; -STATIC char *Screen; -STATIC char NEWLINE[]= CRLF; -STATIC HISTORY H; -STATIC int Repeat; -STATIC int End; -STATIC int Mark; -STATIC int OldPoint; -STATIC int Point; -STATIC int PushBack; -STATIC int Pushed; -STATIC int Signal; -FORWARD KEYMAP Map[32]; -FORWARD KEYMAP MetaMap[16]; -STATIC SIZE_T Length; -STATIC SIZE_T ScreenCount; -STATIC SIZE_T ScreenSize; -STATIC char *backspace; -STATIC int TTYwidth; -STATIC int TTYrows; - -/* Display print 8-bit chars as `M-x' or as the actual 8-bit char? */ -int rl_meta_chars = 0; - -/* -** Declarations. -*/ -STATIC CHAR *editinput(); -extern int read(); -extern int write(); -#if defined(USE_TERMCAP) -extern char *getenv(); -extern char *tgetstr(); -extern int tgetent(); -#endif /* defined(USE_TERMCAP) */ - -/* -** TTY input/output functions. -*/ - -STATIC void -TTYflush() -{ - if (ScreenCount) { - (void)write(1, Screen, ScreenCount); - ScreenCount = 0; - } -} - -STATIC void -TTYput(c) - CHAR c; -{ - Screen[ScreenCount] = c; - if (++ScreenCount >= ScreenSize - 1) { - ScreenSize += SCREEN_INC; - RENEW(Screen, char, ScreenSize); - } -} - -STATIC void -TTYputs(p) - CHAR *p; -{ - while (*p) - TTYput(*p++); -} - -STATIC void -TTYshow(c) - CHAR c; -{ - if (c == DEL) { - TTYput('^'); - TTYput('?'); - } - else if (ISCTL(c)) { - TTYput('^'); - TTYput(UNCTL(c)); - } - else if (rl_meta_chars && ISMETA(c)) { - TTYput('M'); - TTYput('-'); - TTYput(UNMETA(c)); - } - else - TTYput(c); -} - -STATIC void -TTYstring(p) - CHAR *p; -{ - while (*p) - TTYshow(*p++); -} - -STATIC unsigned int -TTYget() -{ - CHAR c; - - TTYflush(); - if (Pushed) { - Pushed = 0; - return PushBack; - } - if (*Input) - return *Input++; - return read(0, &c, (SIZE_T)1) == 1 ? c : EOF; -} - -#define TTYback() (backspace ? TTYputs((CHAR *)backspace) : TTYput('\b')) - -STATIC void -TTYbackn(n) - int n; -{ - while (--n >= 0) - TTYback(); -} - -STATIC void -TTYinfo() -{ - static int init; -#if defined(USE_TERMCAP) - char *term; - char buff[2048]; - char *bp, *p; -#endif /* defined(USE_TERMCAP) */ -#if defined(TIOCGWINSZ) - struct winsize W; -#endif /* defined(TIOCGWINSZ) */ - - if (init) { -#if defined(TIOCGWINSZ) - /* Perhaps we got resized. */ - if (ioctl(0, TIOCGWINSZ, &W) >= 0 - && W.ws_col > 0 && W.ws_row > 0) { - TTYwidth = (int)W.ws_col; - TTYrows = (int)W.ws_row; - } -#endif /* defined(TIOCGWINSZ) */ - return; - } - init++; - - TTYwidth = TTYrows = 0; -#if defined(USE_TERMCAP) - bp = &buff[0]; - if ((term = getenv("TERM")) == NULL) - term = "dumb"; - if (tgetent(buff, term) < 0) { - TTYwidth = SCREEN_WIDTH; - TTYrows = SCREEN_ROWS; - return; - } - p = tgetstr("le", &bp); - backspace = p ? strdup(p) : NULL; - TTYwidth = tgetnum("co"); - TTYrows = tgetnum("li"); -#endif /* defined(USE_TERMCAP) */ - -#if defined(TIOCGWINSZ) - if (ioctl(0, TIOCGWINSZ, &W) >= 0) { - TTYwidth = (int)W.ws_col; - TTYrows = (int)W.ws_row; - } -#endif /* defined(TIOCGWINSZ) */ - - if (TTYwidth <= 0 || TTYrows <= 0) { - TTYwidth = SCREEN_WIDTH; - TTYrows = SCREEN_ROWS; - } -} - - -STATIC void -reposition() -{ - int i; - CHAR *p; - - TTYput('\r'); - TTYputs((CONST CHAR *)Prompt); - for (i = Point, p = Line; --i >= 0; p++) - TTYshow(*p); -} - -STATIC void -left(Change) - STATUS Change; -{ - TTYback(); - if (Point) { - if (ISCTL(Line[Point - 1])) - TTYback(); - else if (rl_meta_chars && ISMETA(Line[Point - 1])) { - TTYback(); - TTYback(); - } - } - if (Change == CSmove) - Point--; -} - -STATIC void -right(Change) - STATUS Change; -{ - TTYshow(Line[Point]); - if (Change == CSmove) - Point++; -} - -STATIC STATUS -ring_bell() -{ - TTYput('\07'); - TTYflush(); - return CSstay; -} - -STATIC STATUS -do_macro(c) - unsigned int c; -{ - CHAR name[4]; - - name[0] = '_'; - name[1] = c; - name[2] = '_'; - name[3] = '\0'; - - if ((Input = (CHAR *)getenv((char *)name)) == NULL) { - Input = NIL; - return ring_bell(); - } - return CSstay; -} - -STATIC STATUS -do_forward(move) - STATUS move; -{ - int i; - CHAR *p; - - i = 0; - do { - p = &Line[Point]; - for ( ; Point < End && (*p == ' ' || !isalnum(*p)); Point++, p++) - if (move == CSmove) - right(CSstay); - - for (; Point < End && isalnum(*p); Point++, p++) - if (move == CSmove) - right(CSstay); - - if (Point == End) - break; - } while (++i < Repeat); - - return CSstay; -} - -STATIC STATUS -do_case(type) - CASE type; -{ - int i; - int end; - int count; - CHAR *p; - - (void)do_forward(CSstay); - if (OldPoint != Point) { - if ((count = Point - OldPoint) < 0) - count = -count; - Point = OldPoint; - if ((end = Point + count) > End) - end = End; - for (i = Point, p = &Line[i]; i < end; i++, p++) { - if (type == TOupper) { - if (islower(*p)) - *p = toupper(*p); - } - else if (isupper(*p)) - *p = tolower(*p); - right(CSmove); - } - } - return CSstay; -} - -STATIC STATUS -case_down_word() -{ - return do_case(TOlower); -} - -STATIC STATUS -case_up_word() -{ - return do_case(TOupper); -} - -STATIC void -ceol() -{ - int extras; - int i; - CHAR *p; - - for (extras = 0, i = Point, p = &Line[i]; i <= End; i++, p++) { - TTYput(' '); - if (ISCTL(*p)) { - TTYput(' '); - extras++; - } - else if (rl_meta_chars && ISMETA(*p)) { - TTYput(' '); - TTYput(' '); - extras += 2; - } - } - - for (i += extras; i > Point; i--) - TTYback(); -} - -STATIC void -clear_line() -{ - Point = -strlen(Prompt); - TTYput('\r'); - ceol(); - Point = 0; - End = 0; - Line[0] = '\0'; -} - -STATIC STATUS -insert_string(p) - CHAR *p; -{ - SIZE_T len; - int i; - CHAR *new; - CHAR *q; - - len = strlen((char *)p); - if (End + len >= Length) { - if ((new = NEW(CHAR, Length + len + MEM_INC)) == NULL) - return CSstay; - if (Length) { - COPYFROMTO(new, Line, Length); - DISPOSE(Line); - } - Line = new; - Length += len + MEM_INC; - } - - for (q = &Line[Point], i = End - Point; --i >= 0; ) - q[len + i] = q[i]; - COPYFROMTO(&Line[Point], p, len); - End += len; - Line[End] = '\0'; - TTYstring(&Line[Point]); - Point += len; - - return Point == End ? CSstay : CSmove; -} - -STATIC STATUS -redisplay() -{ - TTYputs((CONST CHAR *)NEWLINE); - TTYputs((CONST CHAR *)Prompt); - TTYstring(Line); - return CSmove; -} - -STATIC STATUS -toggle_meta_mode() -{ - rl_meta_chars = ! rl_meta_chars; - return redisplay(); -} - - -STATIC CHAR * -next_hist() -{ - return H.Pos >= H.Size - 1 ? NULL : H.Lines[++H.Pos]; -} - -STATIC CHAR * -prev_hist() -{ - return H.Pos == 0 ? NULL : H.Lines[--H.Pos]; -} - -STATIC STATUS -do_insert_hist(p) - CHAR *p; -{ - if (p == NULL) - return ring_bell(); - Point = 0; - reposition(); - ceol(); - End = 0; - return insert_string(p); -} - -STATIC STATUS -do_hist(move) - CHAR *(*move)(); -{ - CHAR *p; - int i; - - i = 0; - do { - if ((p = (*move)()) == NULL) - return ring_bell(); - } while (++i < Repeat); - return do_insert_hist(p); -} - -STATIC STATUS -h_next() -{ - return do_hist(next_hist); -} - -STATIC STATUS -h_prev() -{ - return do_hist(prev_hist); -} - -STATIC STATUS -h_first() -{ - return do_insert_hist(H.Lines[H.Pos = 0]); -} - -STATIC STATUS -h_last() -{ - return do_insert_hist(H.Lines[H.Pos = H.Size - 1]); -} - -/* -** Return zero if pat appears as a substring in text. -*/ -STATIC int -substrcmp(text, pat, len) - char *text; - char *pat; - int len; -{ - char c; - - if ((c = *pat) == '\0') - return *text == '\0'; - for ( ; *text; text++) - if (*text == c && strncmp(text, pat, len) == 0) - return 0; - return 1; -} - -STATIC CHAR * -search_hist(search, move) - CHAR *search; - CHAR *(*move)(); -{ - static CHAR *old_search; - int len; - int pos; - int (*match)(); - char *pat; - - /* Save or get remembered search pattern. */ - if (search && *search) { - if (old_search) - DISPOSE(old_search); - old_search = (CHAR *)strdup((char *)search); - } - else { - if (old_search == NULL || *old_search == '\0') - return NULL; - search = old_search; - } - - /* Set up pattern-finder. */ - if (*search == '^') { - match = strncmp; - pat = (char *)(search + 1); - } - else { - match = substrcmp; - pat = (char *)search; - } - len = strlen(pat); - - for (pos = H.Pos; (*move)() != NULL; ) - if ((*match)((char *)H.Lines[H.Pos], pat, len) == 0) - return H.Lines[H.Pos]; - H.Pos = pos; - return NULL; -} - -STATIC STATUS -h_search() -{ - static int Searching; - CONST char *old_prompt; - CHAR *(*move)(); - CHAR *p; - - if (Searching) - return ring_bell(); - Searching = 1; - - clear_line(); - old_prompt = Prompt; - Prompt = "Search: "; - TTYputs((CONST CHAR *)Prompt); - move = Repeat == NO_ARG ? prev_hist : next_hist; - p = editinput(); - Prompt = old_prompt; - Searching = 0; - TTYputs((CONST CHAR *)Prompt); - if (p == NULL && Signal > 0) { - Signal = 0; - clear_line(); - return redisplay(); - } - p = search_hist(p, move); - clear_line(); - if (p == NULL) { - (void)ring_bell(); - return redisplay(); - } - return do_insert_hist(p); -} - -STATIC STATUS -fd_char() -{ - int i; - - i = 0; - do { - if (Point >= End) - break; - right(CSmove); - } while (++i < Repeat); - return CSstay; -} - -STATIC void -save_yank(begin, i) - int begin; - int i; -{ - if (Yanked) { - DISPOSE(Yanked); - Yanked = NULL; - } - - if (i < 1) - return; - - if ((Yanked = NEW(CHAR, (SIZE_T)i + 1)) != NULL) { - COPYFROMTO(Yanked, &Line[begin], i); - Yanked[i] = '\0'; - } -} - -STATIC STATUS -delete_string(count) - int count; -{ - int i; - CHAR *p; - - if (count <= 0 || End == Point) - return ring_bell(); - - if (count == 1 && Point == End - 1) { - /* Optimize common case of delete at end of line. */ - End--; - p = &Line[Point]; - i = 1; - TTYput(' '); - if (ISCTL(*p)) { - i = 2; - TTYput(' '); - } - else if (rl_meta_chars && ISMETA(*p)) { - i = 3; - TTYput(' '); - TTYput(' '); - } - TTYbackn(i); - *p = '\0'; - return CSmove; - } - if (Point + count > End && (count = End - Point) <= 0) - return CSstay; - - if (count > 1) - save_yank(Point, count); - - for (p = &Line[Point], i = End - (Point + count) + 1; --i >= 0; p++) - p[0] = p[count]; - ceol(); - End -= count; - TTYstring(&Line[Point]); - return CSmove; -} - -STATIC STATUS -bk_char() -{ - int i; - - i = 0; - do { - if (Point == 0) - break; - left(CSmove); - } while (++i < Repeat); - - return CSstay; -} - -STATIC STATUS -bk_del_char() -{ - int i; - - i = 0; - do { - if (Point == 0) - break; - left(CSmove); - } while (++i < Repeat); - - return delete_string(i); -} - -STATIC STATUS -kill_line() -{ - int i; - - if (Repeat != NO_ARG) { - if (Repeat < Point) { - i = Point; - Point = Repeat; - reposition(); - (void)delete_string(i - Point); - } - else if (Repeat > Point) { - right(CSmove); - (void)delete_string(Repeat - Point - 1); - } - return CSmove; - } - - save_yank(Point, End - Point); - Line[Point] = '\0'; - ceol(); - End = Point; - return CSstay; -} - -STATIC STATUS -insert_char(c) - int c; -{ - STATUS s; - CHAR buff[2]; - CHAR *p; - CHAR *q; - int i; - - if (Repeat == NO_ARG || Repeat < 2) { - buff[0] = c; - buff[1] = '\0'; - return insert_string(buff); - } - - if ((p = NEW(CHAR, Repeat + 1)) == NULL) - return CSstay; - for (i = Repeat, q = p; --i >= 0; ) - *q++ = c; - *q = '\0'; - Repeat = 0; - s = insert_string(p); - DISPOSE(p); - return s; -} - -STATIC STATUS -meta() -{ - unsigned int c; - KEYMAP *kp; - - if ((c = TTYget()) == EOF) - return CSeof; -#if defined(ANSI_ARROWS) - /* Also include VT-100 arrows. */ - if (c == '[' || c == 'O') - switch (c = TTYget()) { - default: return ring_bell(); - case EOF: return CSeof; - case 'A': return h_prev(); - case 'B': return h_next(); - case 'C': return fd_char(); - case 'D': return bk_char(); - } -#endif /* defined(ANSI_ARROWS) */ - - if (isdigit(c)) { - for (Repeat = c - '0'; (c = TTYget()) != EOF && isdigit(c); ) - Repeat = Repeat * 10 + c - '0'; - Pushed = 1; - PushBack = c; - return CSstay; - } - - if (isupper(c)) - return do_macro(c); - for (OldPoint = Point, kp = MetaMap; kp->Function; kp++) - if (kp->Key == c) - return (*kp->Function)(); - - return ring_bell(); -} - -STATIC STATUS -emacs(c) - unsigned int c; -{ - STATUS s; - KEYMAP *kp; - - if (rl_meta_chars && ISMETA(c)) { - Pushed = 1; - PushBack = UNMETA(c); - return meta(); - } - for (kp = Map; kp->Function; kp++) - if (kp->Key == c) - break; - s = kp->Function ? (*kp->Function)() : insert_char((int)c); - if (!Pushed) - /* No pushback means no repeat count; hacky, but true. */ - Repeat = NO_ARG; - return s; -} - -STATIC STATUS -TTYspecial(c) - unsigned int c; -{ - if (ISMETA(c)) - return CSdispatch; - - if (c == rl_erase || c == DEL) - return bk_del_char(); - if (c == rl_kill) { - if (Point != 0) { - Point = 0; - reposition(); - } - Repeat = NO_ARG; - return kill_line(); - } - if (c == rl_eof && Point == 0 && End == 0) - return CSeof; - if (c == rl_intr) { - Signal = SIGINT; - return CSsignal; - } - if (c == rl_quit) { - Signal = SIGQUIT; - return CSeof; - } - - return CSdispatch; -} - -STATIC CHAR * -editinput() -{ - unsigned int c; - - Repeat = NO_ARG; - OldPoint = Point = Mark = End = 0; - Line[0] = '\0'; - - Signal = -1; - while ((c = TTYget()) != EOF) - switch (TTYspecial(c)) { - case CSdone: - return Line; - case CSeof: - return NULL; - case CSsignal: - return (CHAR *)""; - case CSmove: - reposition(); - break; - case CSdispatch: - switch (emacs(c)) { - case CSdone: - return Line; - case CSeof: - return NULL; - case CSsignal: - return (CHAR *)""; - case CSmove: - reposition(); - break; - case CSdispatch: - case CSstay: - break; - } - break; - case CSstay: - break; - } - return NULL; -} - -STATIC void -hist_add(p) - CHAR *p; -{ - int i; - - if ((p = (CHAR *)strdup((char *)p)) == NULL) - return; - if (H.Size < HIST_SIZE) - H.Lines[H.Size++] = p; - else { - DISPOSE(H.Lines[0]); - for (i = 0; i < HIST_SIZE - 1; i++) - H.Lines[i] = H.Lines[i + 1]; - H.Lines[i] = p; - } - H.Pos = H.Size - 1; -} - -/* -** For compatibility with FSF readline. -*/ -/* ARGSUSED0 */ -void -rl_reset_terminal(p) - char *p; -{ -} - -void -rl_initialize() -{ -} - -char * -readline(prompt) - CONST char *prompt; -{ - CHAR *line; - int s; - - if (Line == NULL) { - Length = MEM_INC; - if ((Line = NEW(CHAR, Length)) == NULL) - return NULL; - } - - TTYinfo(); - rl_ttyset(0); - hist_add(NIL); - ScreenSize = SCREEN_INC; - Screen = NEW(char, ScreenSize); - Prompt = prompt ? prompt : (char *)NIL; - TTYputs((CONST CHAR *)Prompt); - if ((line = editinput()) != NULL) { - line = (CHAR *)strdup((char *)line); - TTYputs((CHAR *)NEWLINE); - TTYflush(); - } - rl_ttyset(1); - DISPOSE(Screen); - DISPOSE(H.Lines[--H.Size]); - if (Signal > 0) { - s = Signal; - Signal = 0; - (void)kill(getpid(), s); - } - return (char *)line; -} - -void -add_history(p) - char *p; -{ - if (p == NULL || *p == '\0') - return; - -#if defined(UNIQUE_HISTORY) - if (H.Size && strcmp(p, H.Lines[H.Size - 1]) == 0) - return; -#endif /* defined(UNIQUE_HISTORY) */ - hist_add((CHAR *)p); -} - - -STATIC STATUS -beg_line() -{ - if (Point) { - Point = 0; - return CSmove; - } - return CSstay; -} - -STATIC STATUS -del_char() -{ - return delete_string(Repeat == NO_ARG ? 1 : Repeat); -} - -STATIC STATUS -end_line() -{ - if (Point != End) { - Point = End; - return CSmove; - } - return CSstay; -} - -STATIC STATUS -accept_line() -{ - Line[End] = '\0'; - return CSdone; -} - -STATIC STATUS -transpose() -{ - CHAR c; - - if (Point) { - if (Point == End) - left(CSmove); - c = Line[Point - 1]; - left(CSstay); - Line[Point - 1] = Line[Point]; - TTYshow(Line[Point - 1]); - Line[Point++] = c; - TTYshow(c); - } - return CSstay; -} - -STATIC STATUS -quote() -{ - unsigned int c; - - return (c = TTYget()) == EOF ? CSeof : insert_char((int)c); -} - -STATIC STATUS -wipe() -{ - int i; - - if (Mark > End) - return ring_bell(); - - if (Point > Mark) { - i = Point; - Point = Mark; - Mark = i; - reposition(); - } - - return delete_string(Mark - Point); -} - -STATIC STATUS -mk_set() -{ - Mark = Point; - return CSstay; -} - -STATIC STATUS -exchange() -{ - unsigned int c; - - if ((c = TTYget()) != CTL('X')) - return c == EOF ? CSeof : ring_bell(); - - if ((c = Mark) <= End) { - Mark = Point; - Point = c; - return CSmove; - } - return CSstay; -} - -STATIC STATUS -yank() -{ - if (Yanked && *Yanked) - return insert_string(Yanked); - return CSstay; -} - -STATIC STATUS -copy_region() -{ - if (Mark > End) - return ring_bell(); - - if (Point > Mark) - save_yank(Mark, Point - Mark); - else - save_yank(Point, Mark - Point); - - return CSstay; -} - -STATIC STATUS -move_to_char() -{ - unsigned int c; - int i; - CHAR *p; - - if ((c = TTYget()) == EOF) - return CSeof; - for (i = Point + 1, p = &Line[i]; i < End; i++, p++) - if (*p == c) { - Point = i; - return CSmove; - } - return CSstay; -} - -STATIC STATUS -fd_word() -{ - return do_forward(CSmove); -} - -STATIC STATUS -fd_kill_word() -{ - int i; - - (void)do_forward(CSstay); - if (OldPoint != Point) { - i = Point - OldPoint; - Point = OldPoint; - return delete_string(i); - } - return CSstay; -} - -STATIC STATUS -bk_word() -{ - int i; - CHAR *p; - - i = 0; - do { - for (p = &Line[Point]; p > Line && !isalnum(p[-1]); p--) - left(CSmove); - - for (; p > Line && p[-1] != ' ' && isalnum(p[-1]); p--) - left(CSmove); - - if (Point == 0) - break; - } while (++i < Repeat); - - return CSstay; -} - -STATIC STATUS -bk_kill_word() -{ - (void)bk_word(); - if (OldPoint != Point) - return delete_string(OldPoint - Point); - return CSstay; -} - -STATIC int -argify(line, avp) - CHAR *line; - CHAR ***avp; -{ - CHAR *c; - CHAR **p; - CHAR **new; - int ac; - int i; - - i = MEM_INC; - if ((*avp = p = NEW(CHAR*, i))== NULL) - return 0; - - for (c = line; isspace(*c); c++) - continue; - if (*c == '\n' || *c == '\0') - return 0; - - for (ac = 0, p[ac++] = c; *c && *c != '\n'; ) { - if (isspace(*c)) { - *c++ = '\0'; - if (*c && *c != '\n') { - if (ac + 1 == i) { - new = NEW(CHAR*, i + MEM_INC); - if (new == NULL) { - p[ac] = NULL; - return ac; - } - COPYFROMTO(new, p, i * sizeof (char **)); - i += MEM_INC; - DISPOSE(p); - *avp = p = new; - } - p[ac++] = c; - } - } - else - c++; - } - *c = '\0'; - p[ac] = NULL; - return ac; -} - -STATIC STATUS -last_argument() -{ - CHAR **av; - CHAR *p; - STATUS s; - int ac; - - if (H.Size == 1 || (p = H.Lines[H.Size - 2]) == NULL) - return ring_bell(); - - if ((p = (CHAR *)strdup((char *)p)) == NULL) - return CSstay; - ac = argify(p, &av); - - if (Repeat != NO_ARG) - s = Repeat < ac ? insert_string(av[Repeat]) : ring_bell(); - else - s = ac ? insert_string(av[ac - 1]) : CSstay; - - if (ac) - DISPOSE(av); - DISPOSE(p); - return s; -} - -STATIC KEYMAP Map[32] = { - { CTL('@'), ring_bell }, - { CTL('A'), beg_line }, - { CTL('B'), bk_char }, - { CTL('D'), del_char }, - { CTL('E'), end_line }, - { CTL('F'), fd_char }, - { CTL('G'), ring_bell }, - { CTL('H'), bk_del_char }, - { CTL('J'), accept_line }, - { CTL('K'), kill_line }, - { CTL('L'), redisplay }, - { CTL('M'), accept_line }, - { CTL('N'), h_next }, - { CTL('O'), ring_bell }, - { CTL('P'), h_prev }, - { CTL('Q'), ring_bell }, - { CTL('R'), h_search }, - { CTL('S'), ring_bell }, - { CTL('T'), transpose }, - { CTL('U'), ring_bell }, - { CTL('V'), quote }, - { CTL('W'), wipe }, - { CTL('X'), exchange }, - { CTL('Y'), yank }, - { CTL('Z'), ring_bell }, - { CTL('['), meta }, - { CTL(']'), move_to_char }, - { CTL('^'), ring_bell }, - { CTL('_'), ring_bell }, - { 0, NULL } -}; - -STATIC KEYMAP MetaMap[16]= { - { CTL('H'), bk_kill_word }, - { DEL, bk_kill_word }, - { ' ', mk_set }, - { '.', last_argument }, - { '<', h_first }, - { '>', h_last }, - { 'b', bk_word }, - { 'd', fd_kill_word }, - { 'f', fd_word }, - { 'l', case_down_word }, - { 'm', toggle_meta_mode }, - { 'u', case_up_word }, - { 'y', yank }, - { 'w', copy_region }, - { 0, NULL } -}; - diff --git a/lib/javascript/editline/editline.h b/lib/javascript/editline/editline.h deleted file mode 100644 index e820049b..00000000 --- a/lib/javascript/editline/editline.h +++ /dev/null @@ -1,135 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Simmule Turner and Rich Salz. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * Copyright 1992,1993 Simmule Turner and Rich Salz. All rights reserved. - * - * This software is not subject to any license of the American Telephone - * and Telegraph Company or of the Regents of the University of California. - * - * Permission is granted to anyone to use this software for any purpose on - * any computer system, and to alter it and redistribute it freely, subject - * to the following restrictions: - * 1. The authors are not responsible for the consequences of use of this - * software, no matter how awful, even if they arise from flaws in it. - * 2. The origin of this software must not be misrepresented, either by - * explicit claim or by omission. Since few users ever read sources, - * credits must appear in the documentation. - * 3. Altered versions must be plainly marked as such, and must not be - * misrepresented as being the original software. Since few users - * ever read sources, credits must appear in the documentation. - * 4. This notice may not be removed or altered. - */ - -/* -** Internal header file for editline library. -*/ -#include -#if defined(HAVE_STDLIB) -#include -#include -#endif /* defined(HAVE_STDLIB) */ -#if defined(SYS_UNIX) -#include "unix.h" -#endif /* defined(SYS_UNIX) */ -#if defined(SYS_OS9) -#include "os9.h" -#endif /* defined(SYS_OS9) */ - -#if !defined(SIZE_T) -#define SIZE_T unsigned int -#endif /* !defined(SIZE_T) */ - -typedef unsigned char CHAR; - -#if defined(HIDE) -#define STATIC static -#else -#define STATIC /* NULL */ -#endif /* !defined(HIDE) */ - -#if !defined(CONST) -#if defined(__STDC__) -#define CONST const -#else -#define CONST -#endif /* defined(__STDC__) */ -#endif /* !defined(CONST) */ - - -#define MEM_INC 64 -#define SCREEN_INC 256 - -#define DISPOSE(p) free((char *)(p)) -#define NEW(T, c) \ - ((T *)malloc((unsigned int)(sizeof (T) * (c)))) -#define RENEW(p, T, c) \ - (p = (T *)realloc((char *)(p), (unsigned int)(sizeof (T) * (c)))) -#define COPYFROMTO(new, p, len) \ - (void)memcpy((char *)(new), (char *)(p), (int)(len)) - - -/* -** Variables and routines internal to this package. -*/ -extern int rl_eof; -extern int rl_erase; -extern int rl_intr; -extern int rl_kill; -extern int rl_quit; -extern char *rl_complete(); -extern int rl_list_possib(); -extern void rl_ttyset(); -extern void rl_add_slash(); - -#if !defined(HAVE_STDLIB) -extern char *getenv(); -extern char *malloc(); -extern char *realloc(); -extern char *memcpy(); -extern char *strcat(); -extern char *strchr(); -extern char *strrchr(); -extern char *strcpy(); -extern char *strdup(); -extern int strcmp(); -extern int strlen(); -extern int strncmp(); -#endif /* !defined(HAVE_STDLIB) */ - diff --git a/lib/javascript/editline/sysunix.c b/lib/javascript/editline/sysunix.c deleted file mode 100644 index 17227ead..00000000 --- a/lib/javascript/editline/sysunix.c +++ /dev/null @@ -1,182 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Simmule Turner and Rich Salz. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * Copyright 1992,1993 Simmule Turner and Rich Salz. All rights reserved. - * - * This software is not subject to any license of the American Telephone - * and Telegraph Company or of the Regents of the University of California. - * - * Permission is granted to anyone to use this software for any purpose on - * any computer system, and to alter it and redistribute it freely, subject - * to the following restrictions: - * 1. The authors are not responsible for the consequences of use of this - * software, no matter how awful, even if they arise from flaws in it. - * 2. The origin of this software must not be misrepresented, either by - * explicit claim or by omission. Since few users ever read sources, - * credits must appear in the documentation. - * 3. Altered versions must be plainly marked as such, and must not be - * misrepresented as being the original software. Since few users - * ever read sources, credits must appear in the documentation. - * 4. This notice may not be removed or altered. - */ - - -/* -** Unix system-dependant routines for editline library. -*/ -#include "editline.h" - -#if defined(HAVE_TCGETATTR) -#include - -void -rl_ttyset(Reset) - int Reset; -{ - static struct termios old; - struct termios new; - - if (Reset == 0) { - (void)tcgetattr(0, &old); - rl_erase = old.c_cc[VERASE]; - rl_kill = old.c_cc[VKILL]; - rl_eof = old.c_cc[VEOF]; - rl_intr = old.c_cc[VINTR]; - rl_quit = old.c_cc[VQUIT]; - - new = old; - new.c_cc[VINTR] = -1; - new.c_cc[VQUIT] = -1; - new.c_lflag &= ~(ECHO | ICANON); - new.c_iflag &= ~(ISTRIP | INPCK); - new.c_cc[VMIN] = 1; - new.c_cc[VTIME] = 0; - (void)tcsetattr(0, TCSADRAIN, &new); - } - else - (void)tcsetattr(0, TCSADRAIN, &old); -} - -#else -#if defined(HAVE_TERMIO) -#include - -void -rl_ttyset(Reset) - int Reset; -{ - static struct termio old; - struct termio new; - - if (Reset == 0) { - (void)ioctl(0, TCGETA, &old); - rl_erase = old.c_cc[VERASE]; - rl_kill = old.c_cc[VKILL]; - rl_eof = old.c_cc[VEOF]; - rl_intr = old.c_cc[VINTR]; - rl_quit = old.c_cc[VQUIT]; - - new = old; - new.c_cc[VINTR] = -1; - new.c_cc[VQUIT] = -1; - new.c_lflag &= ~(ECHO | ICANON); - new.c_iflag &= ~(ISTRIP | INPCK); - new.c_cc[VMIN] = 1; - new.c_cc[VTIME] = 0; - (void)ioctl(0, TCSETAW, &new); - } - else - (void)ioctl(0, TCSETAW, &old); -} - -#else -#include - -void -rl_ttyset(Reset) - int Reset; -{ - static struct sgttyb old_sgttyb; - static struct tchars old_tchars; - struct sgttyb new_sgttyb; - struct tchars new_tchars; - - if (Reset == 0) { - (void)ioctl(0, TIOCGETP, &old_sgttyb); - rl_erase = old_sgttyb.sg_erase; - rl_kill = old_sgttyb.sg_kill; - - (void)ioctl(0, TIOCGETC, &old_tchars); - rl_eof = old_tchars.t_eofc; - rl_intr = old_tchars.t_intrc; - rl_quit = old_tchars.t_quitc; - - new_sgttyb = old_sgttyb; - new_sgttyb.sg_flags &= ~ECHO; - new_sgttyb.sg_flags |= RAW; -#if defined(PASS8) - new_sgttyb.sg_flags |= PASS8; -#endif /* defined(PASS8) */ - (void)ioctl(0, TIOCSETP, &new_sgttyb); - - new_tchars = old_tchars; - new_tchars.t_intrc = -1; - new_tchars.t_quitc = -1; - (void)ioctl(0, TIOCSETC, &new_tchars); - } - else { - (void)ioctl(0, TIOCSETP, &old_sgttyb); - (void)ioctl(0, TIOCSETC, &old_tchars); - } -} -#endif /* defined(HAVE_TERMIO) */ -#endif /* defined(HAVE_TCGETATTR) */ - -void -rl_add_slash(path, p) - char *path; - char *p; -{ - struct stat Sb; - - if (stat(path, &Sb) >= 0) - (void)strcat(p, S_ISDIR(Sb.st_mode) ? "/" : " "); -} - diff --git a/lib/javascript/editline/unix.h b/lib/javascript/editline/unix.h deleted file mode 100644 index c99b729f..00000000 --- a/lib/javascript/editline/unix.h +++ /dev/null @@ -1,82 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Simmule Turner and Rich Salz. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * Copyright 1992,1993 Simmule Turner and Rich Salz. All rights reserved. - * - * This software is not subject to any license of the American Telephone - * and Telegraph Company or of the Regents of the University of California. - * - * Permission is granted to anyone to use this software for any purpose on - * any computer system, and to alter it and redistribute it freely, subject - * to the following restrictions: - * 1. The authors are not responsible for the consequences of use of this - * software, no matter how awful, even if they arise from flaws in it. - * 2. The origin of this software must not be misrepresented, either by - * explicit claim or by omission. Since few users ever read sources, - * credits must appear in the documentation. - * 3. Altered versions must be plainly marked as such, and must not be - * misrepresented as being the original software. Since few users - * ever read sources, credits must appear in the documentation. - * 4. This notice may not be removed or altered. - */ - - -/* -** Editline system header file for Unix. -*/ - -#define CRLF "\r\n" -#define FORWARD STATIC - -#include -#include - -#if defined(USE_DIRENT) -#include -typedef struct dirent DIRENTRY; -#else -#include -typedef struct direct DIRENTRY; -#endif /* defined(USE_DIRENT) */ - -#if !defined(S_ISDIR) -#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) -#endif /* !defined(S_ISDIR) */ - diff --git a/lib/javascript/fdlibm/.cvsignore b/lib/javascript/fdlibm/.cvsignore deleted file mode 100644 index bb5cc66e..00000000 --- a/lib/javascript/fdlibm/.cvsignore +++ /dev/null @@ -1,7 +0,0 @@ -*.pdb -*.ncb -*.opt -*.plg -Debug -Release -Makefile diff --git a/lib/javascript/fdlibm/Makefile.in b/lib/javascript/fdlibm/Makefile.in deleted file mode 100644 index fdec7b7e..00000000 --- a/lib/javascript/fdlibm/Makefile.in +++ /dev/null @@ -1,127 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either of the GNU General Public License Version 2 or later (the "GPL"), -# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -DEPTH = ../../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(DEPTH)/config/autoconf.mk - -MODULE = js -LIBRARY_NAME = fdm - -CSRCS = \ - e_acos.c \ - e_asin.c \ - e_atan2.c \ - e_exp.c \ - e_fmod.c \ - e_log.c \ - e_pow.c \ - e_rem_pio2.c \ - s_scalbn.c \ - e_sqrt.c \ - k_cos.c \ - k_sin.c \ - k_rem_pio2.c \ - k_tan.c \ - s_atan.c \ - s_ceil.c \ - s_copysign.c \ - s_cos.c \ - s_fabs.c \ - s_finite.c \ - s_floor.c \ - s_isnan.c \ - s_lib_version.c \ - s_sin.c \ - s_tan.c \ - w_acos.c \ - w_asin.c \ - w_atan2.c \ - w_exp.c \ - w_fmod.c \ - w_log.c \ - w_pow.c \ - w_sqrt.c \ - $(NULL) - -EXPORTS = fdlibm.h - -# we need to force a static lib for the linking that js/src/Makefile.in wants -# to do, and we don't really need a shared library ever, so: -FORCE_STATIC_LIB = 1 -FORCE_USE_PIC = 1 - -include $(topsrcdir)/config/rules.mk - -# -# Default IEEE libm -# -CFLAGS += -D_IEEE_LIBM - -ifeq ($(OS_ARCH),Linux) -LDFLAGS += -ldl -endif - -ifeq ($(OS_ARCH),OSF1) -LDFLAGS += -lc_r -endif - -ifeq ($(OS_ARCH),SunOS) -LDFLAGS += -lposix4 -ldl -lnsl -lsocket -ifeq ($(CPU_ARCH),sparc) - -ifndef JS_NO_ULTRA -ULTRA_OPTIONS := -xarch=v8plus,-DULTRA_SPARC -ULTRA_OPTIONSCC := -DULTRA_SPARC -else -ULTRA_OPTIONS := -xarch=v8 -ULTRA_OPTIONSCC := -endif - -ifeq ($(shell uname -m),sun4u) -ASFLAGS += -Wa,$(ULTRA_OPTIONS),-P,-L,-D_ASM,-D__STDC__=0 $(ULTRA_OPTIONSCC) -else -ASFLAGS += -Wa,-xarch=v8,-P,-L,-D_ASM,-D__STDC__=0 -endif - -endif -endif - diff --git a/lib/javascript/fdlibm/Makefile.ref b/lib/javascript/fdlibm/Makefile.ref deleted file mode 100644 index de378025..00000000 --- a/lib/javascript/fdlibm/Makefile.ref +++ /dev/null @@ -1,192 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Sun Microsystems, Inc. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either of the GNU General Public License Version 2 or later (the "GPL"), -# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# @(#)Makefile 1.4 95/01/18 -# -# ==================================================== -# Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. -# -# Developed at SunSoft, a Sun Microsystems, Inc. business. -# Permission to use, copy, modify, and distribute this -# software is freely granted, provided that this notice -# is preserved. -# ==================================================== -# -# - -# -# There are two options in making libm at fdlibm compile time: -# _IEEE_LIBM --- IEEE libm; smaller, and somewhat faster -# _MULTI_LIBM --- Support multi-standard at runtime by -# imposing wrapper functions defined in -# fdlibm.h: -# _IEEE_MODE -- IEEE -# _XOPEN_MODE -- X/OPEN -# _POSIX_MODE -- POSIX/ANSI -# _SVID3_MODE -- SVID -# -# Here is how to set up CFLAGS to create the desired libm at -# compile time: -# -# CFLAGS = -D_IEEE_LIBM ... IEEE libm (recommended) -# CFLAGS = -D_SVID3_MODE ... Multi-standard supported -# libm with SVID as the -# default standard -# CFLAGS = -D_XOPEN_MODE ... Multi-standard supported -# libm with XOPEN as the -# default standard -# CFLAGS = -D_POSIX_MODE ... Multi-standard supported -# libm with POSIX as the -# default standard -# CFLAGS = ... Multi-standard supported -# libm with IEEE as the -# default standard -# -# NOTE: if scalb's second arguement is an int, then one must -# define _SCALB_INT in CFLAGS. The default prototype of scalb -# is double scalb(double, double) -# - -DEPTH = .. - -include $(DEPTH)/config.mk - -# -# Default IEEE libm -# -CFLAGS += -DXP_UNIX $(OPTIMIZER) $(OS_CFLAGS) $(DEFINES) $(INCLUDES) \ - -DJSFILE $(XCFLAGS) -D_IEEE_LIBM - -# Need for jstypes.h and friends -INCLUDES += -I.. -INCLUDES += -I../$(OBJDIR) - -#CC = cc - -INCFILES = fdlibm.h -.INIT: $(INCFILES) -.KEEP_STATE: -FDLIBM_CFILES = \ - k_standard.c k_rem_pio2.c \ - k_cos.c k_sin.c k_tan.c \ - e_acos.c e_acosh.c e_asin.c e_atan2.c \ - e_atanh.c e_cosh.c e_exp.c e_fmod.c \ - e_gamma.c e_gamma_r.c e_hypot.c e_j0.c \ - e_j1.c e_jn.c e_lgamma.c e_lgamma_r.c \ - e_log.c e_log10.c e_pow.c e_rem_pio2.c e_remainder.c \ - e_scalb.c e_sinh.c e_sqrt.c \ - w_acos.c w_acosh.c w_asin.c w_atan2.c \ - w_atanh.c w_cosh.c w_exp.c w_fmod.c \ - w_gamma.c w_gamma_r.c w_hypot.c w_j0.c \ - w_j1.c w_jn.c w_lgamma.c w_lgamma_r.c \ - w_log.c w_log10.c w_pow.c w_remainder.c \ - w_scalb.c w_sinh.c w_sqrt.c \ - s_asinh.c s_atan.c s_cbrt.c s_ceil.c s_copysign.c \ - s_cos.c s_erf.c s_expm1.c s_fabs.c s_finite.c s_floor.c \ - s_frexp.c s_ilogb.c s_isnan.c s_ldexp.c s_lib_version.c \ - s_log1p.c s_logb.c s_matherr.c s_modf.c s_nextafter.c \ - s_rint.c s_scalbn.c s_signgam.c s_significand.c s_sin.c \ - s_tan.c s_tanh.c - -ifdef USE_MSVC -FDLIBM_OBJS = $(addprefix $(OBJDIR)/, $(FDLIBM_CFILES:.c=.obj)) -else -FDLIBM_OBJS = $(addprefix $(OBJDIR)/, $(FDLIBM_CFILES:.c=.o)) -endif - -ifdef USE_MSVC -LIBRARY = $(OBJDIR)/fdlibm.lib -else -LIBRARY = $(OBJDIR)/libfdm.a -endif - -define MAKE_OBJDIR -if test ! -d $(@D); then rm -rf $(@D); mkdir -p $(@D); fi -endef - -all: $(LIBRARY) - -export: - -$(OBJDIR)/%: %.c - @$(MAKE_OBJDIR) - $(CC) -o $@ $(CFLAGS) $*.c $(LDFLAGS) - -$(OBJDIR)/%.o: %.c - @$(MAKE_OBJDIR) - $(CC) -o $@ -c $(CFLAGS) $*.c - -$(OBJDIR)/%.o: %.s - @$(MAKE_OBJDIR) - $(AS) -o $@ $(ASFLAGS) $*.s - -# windows only -$(OBJDIR)/%.obj: %.c - @$(MAKE_OBJDIR) - $(CC) -Fo$(OBJDIR)/ -c $(CFLAGS) $*.c - -ifeq ($(OS_ARCH),OS2) -$(LIBRARY): $(FDLIBM_OBJS) - $(AR) $@ $? $(AR_OS2_SUFFIX) - $(RANLIB) $@ -else -ifdef USE_MSVC -$(LIBRARY): $(FDLIBM_OBJS) - lib.exe /out:"$@" $? -else -$(LIBRARY): $(FDLIBM_OBJS) - $(AR) rv $@ $? - $(RANLIB) $@ -endif -endif - -libfdm.a : $(FDLIBM_OBJS) - $(AR) cru $(OBJDIR)/libfdm.a $(FDLIBM_OBJS) - $(RANLIB) $(OBJDIR)/libfdm.a - -clean: - rm -rf $(FDLIBM_OBJS) - -clobber: - rm -rf $(FDLIBM_OBJS) $(LIBRARY) $(DEPENDENCIES) - -SUFFIXES: .i -%.i: %.c - $(CC) -C -E $(CFLAGS) $< > $*.i diff --git a/lib/javascript/fdlibm/e_acos.c b/lib/javascript/fdlibm/e_acos.c deleted file mode 100644 index a07c1eeb..00000000 --- a/lib/javascript/fdlibm/e_acos.c +++ /dev/null @@ -1,147 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_acos.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* __ieee754_acos(x) - * Method : - * acos(x) = pi/2 - asin(x) - * acos(-x) = pi/2 + asin(x) - * For |x|<=0.5 - * acos(x) = pi/2 - (x + x*x^2*R(x^2)) (see asin.c) - * For x>0.5 - * acos(x) = pi/2 - (pi/2 - 2asin(sqrt((1-x)/2))) - * = 2asin(sqrt((1-x)/2)) - * = 2s + 2s*z*R(z) ...z=(1-x)/2, s=sqrt(z) - * = 2f + (2c + 2s*z*R(z)) - * where f=hi part of s, and c = (z-f*f)/(s+f) is the correction term - * for f so that f+c ~ sqrt(z). - * For x<-0.5 - * acos(x) = pi - 2asin(sqrt((1-|x|)/2)) - * = pi - 0.5*(s+s*z*R(z)), where z=(1-|x|)/2,s=sqrt(z) - * - * Special cases: - * if x is NaN, return x itself; - * if |x|>1, return NaN with invalid signal. - * - * Function needed: sqrt - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -one= 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ -pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */ -pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */ -pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */ -pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */ -pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */ -pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */ -pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */ -pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */ -pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */ -qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */ -qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */ -qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */ -qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */ - -#ifdef __STDC__ - double __ieee754_acos(double x) -#else - double __ieee754_acos(x) - double x; -#endif -{ - fd_twoints u; - double df; - double z,p,q,r,w,s,c; - int hx,ix; - u.d = x; - hx = __HI(u); - ix = hx&0x7fffffff; - if(ix>=0x3ff00000) { /* |x| >= 1 */ - if(((ix-0x3ff00000)|__LO(u))==0) { /* |x|==1 */ - if(hx>0) return 0.0; /* acos(1) = 0 */ - else return pi+2.0*pio2_lo; /* acos(-1)= pi */ - } - return (x-x)/(x-x); /* acos(|x|>1) is NaN */ - } - if(ix<0x3fe00000) { /* |x| < 0.5 */ - if(ix<=0x3c600000) return pio2_hi+pio2_lo;/*if|x|<2**-57*/ - z = x*x; - p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5))))); - q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4))); - r = p/q; - return pio2_hi - (x - (pio2_lo-x*r)); - } else if (hx<0) { /* x < -0.5 */ - z = (one+x)*0.5; - p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5))))); - q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4))); - s = fd_sqrt(z); - r = p/q; - w = r*s-pio2_lo; - return pi - 2.0*(s+w); - } else { /* x > 0.5 */ - z = (one-x)*0.5; - s = fd_sqrt(z); - u.d = s; - __LO(u) = 0; - df = u.d; - c = (z-df*df)/(s+df); - p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5))))); - q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4))); - r = p/q; - w = r*s+c; - return 2.0*(df+w); - } -} diff --git a/lib/javascript/fdlibm/e_acosh.c b/lib/javascript/fdlibm/e_acosh.c deleted file mode 100644 index 725cceef..00000000 --- a/lib/javascript/fdlibm/e_acosh.c +++ /dev/null @@ -1,105 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_acosh.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -/* __ieee754_acosh(x) - * Method : - * Based on - * acosh(x) = log [ x + sqrt(x*x-1) ] - * we have - * acosh(x) := log(x)+ln2, if x is large; else - * acosh(x) := log(2x-1/(sqrt(x*x-1)+x)) if x>2; else - * acosh(x) := log1p(t+sqrt(2.0*t+t*t)); where t=x-1. - * - * Special cases: - * acosh(x) is NaN with signal if x<1. - * acosh(NaN) is NaN without signal. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -one = 1.0, -ln2 = 6.93147180559945286227e-01; /* 0x3FE62E42, 0xFEFA39EF */ - -#ifdef __STDC__ - double __ieee754_acosh(double x) -#else - double __ieee754_acosh(x) - double x; -#endif -{ - fd_twoints u; - double t; - int hx; - u.d = x; - hx = __HI(u); - if(hx<0x3ff00000) { /* x < 1 */ - return (x-x)/(x-x); - } else if(hx >=0x41b00000) { /* x > 2**28 */ - if(hx >=0x7ff00000) { /* x is inf of NaN */ - return x+x; - } else - return __ieee754_log(x)+ln2; /* acosh(huge)=log(2x) */ - } else if(((hx-0x3ff00000)|__LO(u))==0) { - return 0.0; /* acosh(1) = 0 */ - } else if (hx > 0x40000000) { /* 2**28 > x > 2 */ - t=x*x; - return __ieee754_log(2.0*x-one/(x+fd_sqrt(t-one))); - } else { /* 10.98 - * asin(x) = pi/2 - 2*(s+s*z*R(z)) - * = pio2_hi - (2*(s+s*z*R(z)) - pio2_lo) - * For x<=0.98, let pio4_hi = pio2_hi/2, then - * f = hi part of s; - * c = sqrt(z) - f = (z-f*f)/(s+f) ...f+c=sqrt(z) - * and - * asin(x) = pi/2 - 2*(s+s*z*R(z)) - * = pio4_hi+(pio4-2s)-(2s*z*R(z)-pio2_lo) - * = pio4_hi+(pio4-2f)-(2s*z*R(z)-(pio2_lo+2c)) - * - * Special cases: - * if x is NaN, return x itself; - * if |x|>1, return NaN with invalid signal. - * - */ - - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ -really_big = 1.000e+300, -pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */ -pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */ -pio4_hi = 7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */ - /* coefficient for R(x^2) */ -pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */ -pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */ -pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */ -pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */ -pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */ -pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */ -qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */ -qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */ -qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */ -qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */ - -#ifdef __STDC__ - double __ieee754_asin(double x) -#else - double __ieee754_asin(x) - double x; -#endif -{ - fd_twoints u; - double w,t,p,q,c,r,s; - int hx,ix; - u.d = x; - hx = __HI(u); - x = u.d; - ix = hx&0x7fffffff; - if(ix>= 0x3ff00000) { /* |x|>= 1 */ - if(((ix-0x3ff00000)|__LO(u))==0) - /* asin(1)=+-pi/2 with inexact */ - return x*pio2_hi+x*pio2_lo; - return (x-x)/(x-x); /* asin(|x|>1) is NaN */ - } else if (ix<0x3fe00000) { /* |x|<0.5 */ - if(ix<0x3e400000) { /* if |x| < 2**-27 */ - if(really_big+x>one) return x;/* return x with inexact if x!=0*/ - } else - t = x*x; - p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5))))); - q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4))); - w = p/q; - return x+x*w; - } - /* 1> |x|>= 0.5 */ - w = one-fd_fabs(x); - t = w*0.5; - p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5))))); - q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4))); - s = fd_sqrt(t); - if(ix>=0x3FEF3333) { /* if |x| > 0.975 */ - w = p/q; - t = pio2_hi-(2.0*(s+s*w)-pio2_lo); - } else { - u.d = s; - __LO(u) = 0; - w = u.d; - c = (t-w*w)/(s+w); - r = p/q; - p = 2.0*s*r-(pio2_lo-2.0*c); - q = pio4_hi-2.0*w; - t = pio4_hi-(p-q); - } - if(hx>0) return t; else return -t; -} diff --git a/lib/javascript/fdlibm/e_atan2.c b/lib/javascript/fdlibm/e_atan2.c deleted file mode 100644 index 9c9a2c01..00000000 --- a/lib/javascript/fdlibm/e_atan2.c +++ /dev/null @@ -1,165 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_atan2.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -/* __ieee754_atan2(y,x) - * Method : - * 1. Reduce y to positive by atan2(y,x)=-atan2(-y,x). - * 2. Reduce x to positive by (if x and y are unexceptional): - * ARG (x+iy) = arctan(y/x) ... if x > 0, - * ARG (x+iy) = pi - arctan[y/(-x)] ... if x < 0, - * - * Special cases: - * - * ATAN2((anything), NaN ) is NaN; - * ATAN2(NAN , (anything) ) is NaN; - * ATAN2(+-0, +(anything but NaN)) is +-0 ; - * ATAN2(+-0, -(anything but NaN)) is +-pi ; - * ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2; - * ATAN2(+-(anything but INF and NaN), +INF) is +-0 ; - * ATAN2(+-(anything but INF and NaN), -INF) is +-pi; - * ATAN2(+-INF,+INF ) is +-pi/4 ; - * ATAN2(+-INF,-INF ) is +-3pi/4; - * ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2; - * - * Constants: - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -tiny = 1.0e-300, -zero = 0.0, -pi_o_4 = 7.8539816339744827900E-01, /* 0x3FE921FB, 0x54442D18 */ -pi_o_2 = 1.5707963267948965580E+00, /* 0x3FF921FB, 0x54442D18 */ -pi = 3.1415926535897931160E+00, /* 0x400921FB, 0x54442D18 */ -pi_lo = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */ - -#ifdef __STDC__ - double __ieee754_atan2(double y, double x) -#else - double __ieee754_atan2(y,x) - double y,x; -#endif -{ - fd_twoints ux, uy, uz; - double z; - int k,m,hx,hy,ix,iy; - unsigned lx,ly; - - ux.d = x; uy.d = y; - hx = __HI(ux); ix = hx&0x7fffffff; - lx = __LO(ux); - hy = __HI(uy); iy = hy&0x7fffffff; - ly = __LO(uy); - if(((ix|((lx|-(int)lx)>>31))>0x7ff00000)|| - ((iy|((ly|-(int)ly)>>31))>0x7ff00000)) /* x or y is NaN */ - return x+y; - if(((hx-0x3ff00000)|lx)==0) return fd_atan(y); /* x=1.0 */ - m = ((hy>>31)&1)|((hx>>30)&2); /* 2*sign(x)+sign(y) */ - - /* when y = 0 */ - if((iy|ly)==0) { - switch(m) { - case 0: - case 1: return y; /* atan(+-0,+anything)=+-0 */ - case 2: return pi+tiny;/* atan(+0,-anything) = pi */ - case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */ - } - } - /* when x = 0 */ - if((ix|lx)==0) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny; - - /* when x is INF */ - if(ix==0x7ff00000) { - if(iy==0x7ff00000) { - switch(m) { - case 0: return pi_o_4+tiny;/* atan(+INF,+INF) */ - case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */ - case 2: return 3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/ - case 3: return -3.0*pi_o_4-tiny;/*atan(-INF,-INF)*/ - } - } else { - switch(m) { - case 0: return zero ; /* atan(+...,+INF) */ - case 1: return -zero ; /* atan(-...,+INF) */ - case 2: return pi+tiny ; /* atan(+...,-INF) */ - case 3: return -pi-tiny ; /* atan(-...,-INF) */ - } - } - } - /* when y is INF */ - if(iy==0x7ff00000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny; - - /* compute y/x */ - k = (iy-ix)>>20; - if(k > 60) z=pi_o_2+0.5*pi_lo; /* |y/x| > 2**60 */ - else if(hx<0&&k<-60) z=0.0; /* |y|/x < -2**60 */ - else z=fd_atan(fd_fabs(y/x)); /* safe to do y/x */ - switch (m) { - case 0: return z ; /* atan(+,+) */ - case 1: uz.d = z; - __HI(uz) ^= 0x80000000; - z = uz.d; - return z ; /* atan(-,+) */ - case 2: return pi-(z-pi_lo);/* atan(+,-) */ - default: /* case 3 */ - return (z-pi_lo)-pi;/* atan(-,-) */ - } -} diff --git a/lib/javascript/fdlibm/e_atanh.c b/lib/javascript/fdlibm/e_atanh.c deleted file mode 100644 index dc4a90c8..00000000 --- a/lib/javascript/fdlibm/e_atanh.c +++ /dev/null @@ -1,110 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_atanh.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -/* __ieee754_atanh(x) - * Method : - * 1.Reduced x to positive by atanh(-x) = -atanh(x) - * 2.For x>=0.5 - * 1 2x x - * atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------) - * 2 1 - x 1 - x - * - * For x<0.5 - * atanh(x) = 0.5*log1p(2x+2x*x/(1-x)) - * - * Special cases: - * atanh(x) is NaN if |x| > 1 with signal; - * atanh(NaN) is that NaN with no signal; - * atanh(+-1) is +-INF with signal. - * - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double one = 1.0, really_big = 1e300; -#else -static double one = 1.0, really_big = 1e300; -#endif - -static double zero = 0.0; - -#ifdef __STDC__ - double __ieee754_atanh(double x) -#else - double __ieee754_atanh(x) - double x; -#endif -{ - double t; - int hx,ix; - unsigned lx; - fd_twoints u; - u.d = x; - hx = __HI(u); /* high word */ - lx = __LO(u); /* low word */ - ix = hx&0x7fffffff; - if ((ix|((lx|(-(int)lx))>>31))>0x3ff00000) /* |x|>1 */ - return (x-x)/(x-x); - if(ix==0x3ff00000) - return x/zero; - if(ix<0x3e300000&&(really_big+x)>zero) return x; /* x<2**-28 */ - u.d = x; - __HI(u) = ix; /* x <- |x| */ - x = u.d; - if(ix<0x3fe00000) { /* x < 0.5 */ - t = x+x; - t = 0.5*fd_log1p(t+t*x/(one-x)); - } else - t = 0.5*fd_log1p((x+x)/(one-x)); - if(hx>=0) return t; else return -t; -} diff --git a/lib/javascript/fdlibm/e_cosh.c b/lib/javascript/fdlibm/e_cosh.c deleted file mode 100644 index 4f8d4f76..00000000 --- a/lib/javascript/fdlibm/e_cosh.c +++ /dev/null @@ -1,133 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_cosh.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* __ieee754_cosh(x) - * Method : - * mathematically cosh(x) if defined to be (exp(x)+exp(-x))/2 - * 1. Replace x by |x| (cosh(x) = cosh(-x)). - * 2. - * [ exp(x) - 1 ]^2 - * 0 <= x <= ln2/2 : cosh(x) := 1 + ------------------- - * 2*exp(x) - * - * exp(x) + 1/exp(x) - * ln2/2 <= x <= 22 : cosh(x) := ------------------- - * 2 - * 22 <= x <= lnovft : cosh(x) := exp(x)/2 - * lnovft <= x <= ln2ovft: cosh(x) := exp(x/2)/2 * exp(x/2) - * ln2ovft < x : cosh(x) := huge*huge (overflow) - * - * Special cases: - * cosh(x) is |x| if x is +INF, -INF, or NaN. - * only cosh(0)=1 is exact for finite x. - */ - -#include "fdlibm.h" - -#ifdef _WIN32 -#define huge myhuge -#endif - -#ifdef __STDC__ -static const double one = 1.0, half=0.5, really_big = 1.0e300; -#else -static double one = 1.0, half=0.5, really_big = 1.0e300; -#endif - -#ifdef __STDC__ - double __ieee754_cosh(double x) -#else - double __ieee754_cosh(x) - double x; -#endif -{ - fd_twoints u; - double t,w; - int ix; - unsigned lx; - - /* High word of |x|. */ - u.d = x; - ix = __HI(u); - ix &= 0x7fffffff; - - /* x is INF or NaN */ - if(ix>=0x7ff00000) return x*x; - - /* |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) */ - if(ix<0x3fd62e43) { - t = fd_expm1(fd_fabs(x)); - w = one+t; - if (ix<0x3c800000) return w; /* cosh(tiny) = 1 */ - return one+(t*t)/(w+w); - } - - /* |x| in [0.5*ln2,22], return (exp(|x|)+1/exp(|x|)/2; */ - if (ix < 0x40360000) { - t = __ieee754_exp(fd_fabs(x)); - return half*t+half/t; - } - - /* |x| in [22, log(maxdouble)] return half*exp(|x|) */ - if (ix < 0x40862E42) return half*__ieee754_exp(fd_fabs(x)); - - /* |x| in [log(maxdouble), overflowthresold] */ - lx = *( (((*(unsigned*)&one)>>29)) + (unsigned*)&x); - if (ix<0x408633CE || - (ix==0x408633ce)&&(lx<=(unsigned)0x8fb9f87d)) { - w = __ieee754_exp(half*fd_fabs(x)); - t = half*w; - return t*w; - } - - /* |x| > overflowthresold, cosh(x) overflow */ - return really_big*really_big; -} diff --git a/lib/javascript/fdlibm/e_exp.c b/lib/javascript/fdlibm/e_exp.c deleted file mode 100644 index ad9cec12..00000000 --- a/lib/javascript/fdlibm/e_exp.c +++ /dev/null @@ -1,202 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_exp.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* __ieee754_exp(x) - * Returns the exponential of x. - * - * Method - * 1. Argument reduction: - * Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658. - * Given x, find r and integer k such that - * - * x = k*ln2 + r, |r| <= 0.5*ln2. - * - * Here r will be represented as r = hi-lo for better - * accuracy. - * - * 2. Approximation of exp(r) by a special rational function on - * the interval [0,0.34658]: - * Write - * R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ... - * We use a special Reme algorithm on [0,0.34658] to generate - * a polynomial of degree 5 to approximate R. The maximum error - * of this polynomial approximation is bounded by 2**-59. In - * other words, - * R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5 - * (where z=r*r, and the values of P1 to P5 are listed below) - * and - * | 5 | -59 - * | 2.0+P1*z+...+P5*z - R(z) | <= 2 - * | | - * The computation of exp(r) thus becomes - * 2*r - * exp(r) = 1 + ------- - * R - r - * r*R1(r) - * = 1 + r + ----------- (for better accuracy) - * 2 - R1(r) - * where - * 2 4 10 - * R1(r) = r - (P1*r + P2*r + ... + P5*r ). - * - * 3. Scale back to obtain exp(x): - * From step 1, we have - * exp(x) = 2^k * exp(r) - * - * Special cases: - * exp(INF) is INF, exp(NaN) is NaN; - * exp(-INF) is 0, and - * for finite argument, only exp(0)=1 is exact. - * - * Accuracy: - * according to an error analysis, the error is always less than - * 1 ulp (unit in the last place). - * - * Misc. info. - * For IEEE double - * if x > 7.09782712893383973096e+02 then exp(x) overflow - * if x < -7.45133219101941108420e+02 then exp(x) underflow - * - * Constants: - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -one = 1.0, -halF[2] = {0.5,-0.5,}, -really_big = 1.0e+300, -twom1000= 9.33263618503218878990e-302, /* 2**-1000=0x01700000,0*/ -o_threshold= 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */ -u_threshold= -7.45133219101941108420e+02, /* 0xc0874910, 0xD52D3051 */ -ln2HI[2] ={ 6.93147180369123816490e-01, /* 0x3fe62e42, 0xfee00000 */ - -6.93147180369123816490e-01,},/* 0xbfe62e42, 0xfee00000 */ -ln2LO[2] ={ 1.90821492927058770002e-10, /* 0x3dea39ef, 0x35793c76 */ - -1.90821492927058770002e-10,},/* 0xbdea39ef, 0x35793c76 */ -invln2 = 1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */ -P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ -P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ -P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ -P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ -P5 = 4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */ - - -#ifdef __STDC__ - double __ieee754_exp(double x) /* default IEEE double exp */ -#else - double __ieee754_exp(x) /* default IEEE double exp */ - double x; -#endif -{ - fd_twoints u; - double y,hi,lo,c,t; - int k, xsb; - unsigned hx; - - u.d = x; - hx = __HI(u); /* high word of x */ - xsb = (hx>>31)&1; /* sign bit of x */ - hx &= 0x7fffffff; /* high word of |x| */ - - /* filter out non-finite argument */ - if(hx >= 0x40862E42) { /* if |x|>=709.78... */ - if(hx>=0x7ff00000) { - u.d = x; - if(((hx&0xfffff)|__LO(u))!=0) - return x+x; /* NaN */ - else return (xsb==0)? x:0.0; /* exp(+-inf)={inf,0} */ - } - if(x > o_threshold) return really_big*really_big; /* overflow */ - if(x < u_threshold) return twom1000*twom1000; /* underflow */ - } - - /* argument reduction */ - if(hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */ - if(hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */ - hi = x-ln2HI[xsb]; lo=ln2LO[xsb]; k = 1-xsb-xsb; - } else { - k = (int)(invln2*x+halF[xsb]); - t = k; - hi = x - t*ln2HI[0]; /* t*ln2HI is exact here */ - lo = t*ln2LO[0]; - } - x = hi - lo; - } - else if(hx < 0x3e300000) { /* when |x|<2**-28 */ - if(really_big+x>one) return one+x;/* trigger inexact */ - } - else k = 0; - - /* x is now in primary range */ - t = x*x; - c = x - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))); - if(k==0) return one-((x*c)/(c-2.0)-x); - else y = one-((lo-(x*c)/(2.0-c))-hi); - if(k >= -1021) { - u.d = y; - __HI(u) += (k<<20); /* add k to y's exponent */ - y = u.d; - return y; - } else { - u.d = y; - __HI(u) += ((k+1000)<<20);/* add k to y's exponent */ - y = u.d; - return y*twom1000; - } -} diff --git a/lib/javascript/fdlibm/e_fmod.c b/lib/javascript/fdlibm/e_fmod.c deleted file mode 100644 index 7b5ce780..00000000 --- a/lib/javascript/fdlibm/e_fmod.c +++ /dev/null @@ -1,184 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_fmod.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * __ieee754_fmod(x,y) - * Return x mod y in exact arithmetic - * Method: shift and subtract - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double one = 1.0, Zero[] = {0.0, -0.0,}; -#else -static double one = 1.0, Zero[] = {0.0, -0.0,}; -#endif - -#ifdef __STDC__ - double __ieee754_fmod(double x, double y) -#else - double __ieee754_fmod(x,y) - double x,y ; -#endif -{ - fd_twoints ux, uy; - int n,hx,hy,hz,ix,iy,sx,i; - unsigned lx,ly,lz; - - ux.d = x; uy.d = y; - hx = __HI(ux); /* high word of x */ - lx = __LO(ux); /* low word of x */ - hy = __HI(uy); /* high word of y */ - ly = __LO(uy); /* low word of y */ - sx = hx&0x80000000; /* sign of x */ - hx ^=sx; /* |x| */ - hy &= 0x7fffffff; /* |y| */ - - /* purge off exception values */ - if((hy|ly)==0||(hx>=0x7ff00000)|| /* y=0,or x not finite */ - ((hy|((ly|-(int)ly)>>31))>0x7ff00000)) /* or y is NaN */ - return (x*y)/(x*y); - if(hx<=hy) { - if((hx>31]; /* |x|=|y| return x*0*/ - } - - /* determine ix = ilogb(x) */ - if(hx<0x00100000) { /* subnormal x */ - if(hx==0) { - for (ix = -1043, i=lx; i>0; i<<=1) ix -=1; - } else { - for (ix = -1022,i=(hx<<11); i>0; i<<=1) ix -=1; - } - } else ix = (hx>>20)-1023; - - /* determine iy = ilogb(y) */ - if(hy<0x00100000) { /* subnormal y */ - if(hy==0) { - for (iy = -1043, i=ly; i>0; i<<=1) iy -=1; - } else { - for (iy = -1022,i=(hy<<11); i>0; i<<=1) iy -=1; - } - } else iy = (hy>>20)-1023; - - /* set up {hx,lx}, {hy,ly} and align y to x */ - if(ix >= -1022) - hx = 0x00100000|(0x000fffff&hx); - else { /* subnormal x, shift x to normal */ - n = -1022-ix; - if(n<=31) { - hx = (hx<>(32-n)); - lx <<= n; - } else { - hx = lx<<(n-32); - lx = 0; - } - } - if(iy >= -1022) - hy = 0x00100000|(0x000fffff&hy); - else { /* subnormal y, shift y to normal */ - n = -1022-iy; - if(n<=31) { - hy = (hy<>(32-n)); - ly <<= n; - } else { - hy = ly<<(n-32); - ly = 0; - } - } - - /* fix point fmod */ - n = ix - iy; - while(n--) { - hz=hx-hy;lz=lx-ly; if(lx>31); lx = lx+lx;} - else { - if((hz|lz)==0) /* return sign(x)*0 */ - return Zero[(unsigned)sx>>31]; - hx = hz+hz+(lz>>31); lx = lz+lz; - } - } - hz=hx-hy;lz=lx-ly; if(lx=0) {hx=hz;lx=lz;} - - /* convert back to floating value and restore the sign */ - if((hx|lx)==0) /* return sign(x)*0 */ - return Zero[(unsigned)sx>>31]; - while(hx<0x00100000) { /* normalize x */ - hx = hx+hx+(lx>>31); lx = lx+lx; - iy -= 1; - } - if(iy>= -1022) { /* normalize output */ - hx = ((hx-0x00100000)|((iy+1023)<<20)); - ux.d = x; - __HI(ux) = hx|sx; - __LO(ux) = lx; - x = ux.d; - } else { /* subnormal output */ - n = -1022 - iy; - if(n<=20) { - lx = (lx>>n)|((unsigned)hx<<(32-n)); - hx >>= n; - } else if (n<=31) { - lx = (hx<<(32-n))|(lx>>n); hx = sx; - } else { - lx = hx>>(n-32); hx = sx; - } - ux.d = x; - __HI(ux) = hx|sx; - __LO(ux) = lx; - x = ux.d; - x *= one; /* create necessary signal */ - } - return x; /* exact output */ -} diff --git a/lib/javascript/fdlibm/e_gamma.c b/lib/javascript/fdlibm/e_gamma.c deleted file mode 100644 index a34faa32..00000000 --- a/lib/javascript/fdlibm/e_gamma.c +++ /dev/null @@ -1,71 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_gamma.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -/* __ieee754_gamma(x) - * Return the logarithm of the Gamma function of x. - * - * Method: call __ieee754_gamma_r - */ - -#include "fdlibm.h" - -extern int signgam; - -#ifdef __STDC__ - double __ieee754_gamma(double x) -#else - double __ieee754_gamma(x) - double x; -#endif -{ - return __ieee754_gamma_r(x,&signgam); -} diff --git a/lib/javascript/fdlibm/e_gamma_r.c b/lib/javascript/fdlibm/e_gamma_r.c deleted file mode 100644 index f10e32e3..00000000 --- a/lib/javascript/fdlibm/e_gamma_r.c +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_gamma_r.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -/* __ieee754_gamma_r(x, signgamp) - * Reentrant version of the logarithm of the Gamma function - * with user provide pointer for the sign of Gamma(x). - * - * Method: See __ieee754_lgamma_r - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double __ieee754_gamma_r(double x, int *signgamp) -#else - double __ieee754_gamma_r(x,signgamp) - double x; int *signgamp; -#endif -{ - return __ieee754_lgamma_r(x,signgamp); -} diff --git a/lib/javascript/fdlibm/e_hypot.c b/lib/javascript/fdlibm/e_hypot.c deleted file mode 100644 index 39002308..00000000 --- a/lib/javascript/fdlibm/e_hypot.c +++ /dev/null @@ -1,173 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_hypot.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* __ieee754_hypot(x,y) - * - * Method : - * If (assume round-to-nearest) z=x*x+y*y - * has error less than sqrt(2)/2 ulp, than - * sqrt(z) has error less than 1 ulp (exercise). - * - * So, compute sqrt(x*x+y*y) with some care as - * follows to get the error below 1 ulp: - * - * Assume x>y>0; - * (if possible, set rounding to round-to-nearest) - * 1. if x > 2y use - * x1*x1+(y*y+(x2*(x+x1))) for x*x+y*y - * where x1 = x with lower 32 bits cleared, x2 = x-x1; else - * 2. if x <= 2y use - * t1*y1+((x-y)*(x-y)+(t1*y2+t2*y)) - * where t1 = 2x with lower 32 bits cleared, t2 = 2x-t1, - * y1= y with lower 32 bits chopped, y2 = y-y1. - * - * NOTE: scaling may be necessary if some argument is too - * large or too tiny - * - * Special cases: - * hypot(x,y) is INF if x or y is +INF or -INF; else - * hypot(x,y) is NAN if x or y is NAN. - * - * Accuracy: - * hypot(x,y) returns sqrt(x^2+y^2) with error less - * than 1 ulps (units in the last place) - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double __ieee754_hypot(double x, double y) -#else - double __ieee754_hypot(x,y) - double x, y; -#endif -{ - fd_twoints ux, uy; - double a=x,b=y,t1,t2,y1,y2,w; - int j,k,ha,hb; - - ux.d = x; uy.d = y; - ha = __HI(ux)&0x7fffffff; /* high word of x */ - hb = __HI(uy)&0x7fffffff; /* high word of y */ - if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;} - ux.d = a; uy.d = b; - __HI(ux) = ha; /* a <- |a| */ - __HI(uy) = hb; /* b <- |b| */ - a = ux.d; b = uy.d; - if((ha-hb)>0x3c00000) {return a+b;} /* x/y > 2**60 */ - k=0; - if(ha > 0x5f300000) { /* a>2**500 */ - if(ha >= 0x7ff00000) { /* Inf or NaN */ - w = a+b; /* for sNaN */ - ux.d = a; uy.d = b; - if(((ha&0xfffff)|__LO(ux))==0) w = a; - if(((hb^0x7ff00000)|__LO(uy))==0) w = b; - return w; - } - /* scale a and b by 2**-600 */ - ha -= 0x25800000; hb -= 0x25800000; k += 600; - ux.d = a; uy.d = b; - __HI(ux) = ha; - __HI(uy) = hb; - a = ux.d; b = uy.d; - } - if(hb < 0x20b00000) { /* b < 2**-500 */ - if(hb <= 0x000fffff) { /* subnormal b or 0 */ - uy.d = b; - if((hb|(__LO(uy)))==0) return a; - t1=0; - ux.d = t1; - __HI(ux) = 0x7fd00000; /* t1=2^1022 */ - t1 = ux.d; - b *= t1; - a *= t1; - k -= 1022; - } else { /* scale a and b by 2^600 */ - ha += 0x25800000; /* a *= 2^600 */ - hb += 0x25800000; /* b *= 2^600 */ - k -= 600; - ux.d = a; uy.d = b; - __HI(ux) = ha; - __HI(uy) = hb; - a = ux.d; b = uy.d; - } - } - /* medium size a and b */ - w = a-b; - if (w>b) { - t1 = 0; - ux.d = t1; - __HI(ux) = ha; - t1 = ux.d; - t2 = a-t1; - w = fd_sqrt(t1*t1-(b*(-b)-t2*(a+t1))); - } else { - a = a+a; - y1 = 0; - ux.d = y1; - __HI(ux) = hb; - y1 = ux.d; - y2 = b - y1; - t1 = 0; - ux.d = t1; - __HI(ux) = ha+0x00100000; - t1 = ux.d; - t2 = a - t1; - w = fd_sqrt(t1*y1-(w*(-w)-(t1*y2+t2*b))); - } - if(k!=0) { - t1 = 1.0; - ux.d = t1; - __HI(ux) += (k<<20); - t1 = ux.d; - return t1*w; - } else return w; -} diff --git a/lib/javascript/fdlibm/e_j0.c b/lib/javascript/fdlibm/e_j0.c deleted file mode 100644 index 078e0964..00000000 --- a/lib/javascript/fdlibm/e_j0.c +++ /dev/null @@ -1,524 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_j0.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* __ieee754_j0(x), __ieee754_y0(x) - * Bessel function of the first and second kinds of order zero. - * Method -- j0(x): - * 1. For tiny x, we use j0(x) = 1 - x^2/4 + x^4/64 - ... - * 2. Reduce x to |x| since j0(x)=j0(-x), and - * for x in (0,2) - * j0(x) = 1-z/4+ z^2*R0/S0, where z = x*x; - * (precision: |j0-1+z/4-z^2R0/S0 |<2**-63.67 ) - * for x in (2,inf) - * j0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)-q0(x)*sin(x0)) - * where x0 = x-pi/4. It is better to compute sin(x0),cos(x0) - * as follow: - * cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4) - * = 1/sqrt(2) * (cos(x) + sin(x)) - * sin(x0) = sin(x)cos(pi/4)-cos(x)sin(pi/4) - * = 1/sqrt(2) * (sin(x) - cos(x)) - * (To avoid cancellation, use - * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) - * to compute the worse one.) - * - * 3 Special cases - * j0(nan)= nan - * j0(0) = 1 - * j0(inf) = 0 - * - * Method -- y0(x): - * 1. For x<2. - * Since - * y0(x) = 2/pi*(j0(x)*(ln(x/2)+Euler) + x^2/4 - ...) - * therefore y0(x)-2/pi*j0(x)*ln(x) is an even function. - * We use the following function to approximate y0, - * y0(x) = U(z)/V(z) + (2/pi)*(j0(x)*ln(x)), z= x^2 - * where - * U(z) = u00 + u01*z + ... + u06*z^6 - * V(z) = 1 + v01*z + ... + v04*z^4 - * with absolute approximation error bounded by 2**-72. - * Note: For tiny x, U/V = u0 and j0(x)~1, hence - * y0(tiny) = u0 + (2/pi)*ln(tiny), (choose tiny<2**-27) - * 2. For x>=2. - * y0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)+q0(x)*sin(x0)) - * where x0 = x-pi/4. It is better to compute sin(x0),cos(x0) - * by the method mentioned above. - * 3. Special cases: y0(0)=-inf, y0(x<0)=NaN, y0(inf)=0. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static double pzero(double), qzero(double); -#else -static double pzero(), qzero(); -#endif - -#ifdef __STDC__ -static const double -#else -static double -#endif -really_big = 1e300, -one = 1.0, -invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */ -tpi = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ - /* R0/S0 on [0, 2.00] */ -R02 = 1.56249999999999947958e-02, /* 0x3F8FFFFF, 0xFFFFFFFD */ -R03 = -1.89979294238854721751e-04, /* 0xBF28E6A5, 0xB61AC6E9 */ -R04 = 1.82954049532700665670e-06, /* 0x3EBEB1D1, 0x0C503919 */ -R05 = -4.61832688532103189199e-09, /* 0xBE33D5E7, 0x73D63FCE */ -S01 = 1.56191029464890010492e-02, /* 0x3F8FFCE8, 0x82C8C2A4 */ -S02 = 1.16926784663337450260e-04, /* 0x3F1EA6D2, 0xDD57DBF4 */ -S03 = 5.13546550207318111446e-07, /* 0x3EA13B54, 0xCE84D5A9 */ -S04 = 1.16614003333790000205e-09; /* 0x3E1408BC, 0xF4745D8F */ - -static double zero = 0.0; - -#ifdef __STDC__ - double __ieee754_j0(double x) -#else - double __ieee754_j0(x) - double x; -#endif -{ - fd_twoints un; - double z, s,c,ss,cc,r,u,v; - int hx,ix; - - un.d = x; - hx = __HI(un); - ix = hx&0x7fffffff; - if(ix>=0x7ff00000) return one/(x*x); - x = fd_fabs(x); - if(ix >= 0x40000000) { /* |x| >= 2.0 */ - s = fd_sin(x); - c = fd_cos(x); - ss = s-c; - cc = s+c; - if(ix<0x7fe00000) { /* make sure x+x not overflow */ - z = -fd_cos(x+x); - if ((s*c)0x48000000) z = (invsqrtpi*cc)/fd_sqrt(x); - else { - u = pzero(x); v = qzero(x); - z = invsqrtpi*(u*cc-v*ss)/fd_sqrt(x); - } - return z; - } - if(ix<0x3f200000) { /* |x| < 2**-13 */ - if(really_big+x>one) { /* raise inexact if x != 0 */ - if(ix<0x3e400000) return one; /* |x|<2**-27 */ - else return one - 0.25*x*x; - } - } - z = x*x; - r = z*(R02+z*(R03+z*(R04+z*R05))); - s = one+z*(S01+z*(S02+z*(S03+z*S04))); - if(ix < 0x3FF00000) { /* |x| < 1.00 */ - return one + z*(-0.25+(r/s)); - } else { - u = 0.5*x; - return((one+u)*(one-u)+z*(r/s)); - } -} - -#ifdef __STDC__ -static const double -#else -static double -#endif -u00 = -7.38042951086872317523e-02, /* 0xBFB2E4D6, 0x99CBD01F */ -u01 = 1.76666452509181115538e-01, /* 0x3FC69D01, 0x9DE9E3FC */ -u02 = -1.38185671945596898896e-02, /* 0xBF8C4CE8, 0xB16CFA97 */ -u03 = 3.47453432093683650238e-04, /* 0x3F36C54D, 0x20B29B6B */ -u04 = -3.81407053724364161125e-06, /* 0xBECFFEA7, 0x73D25CAD */ -u05 = 1.95590137035022920206e-08, /* 0x3E550057, 0x3B4EABD4 */ -u06 = -3.98205194132103398453e-11, /* 0xBDC5E43D, 0x693FB3C8 */ -v01 = 1.27304834834123699328e-02, /* 0x3F8A1270, 0x91C9C71A */ -v02 = 7.60068627350353253702e-05, /* 0x3F13ECBB, 0xF578C6C1 */ -v03 = 2.59150851840457805467e-07, /* 0x3E91642D, 0x7FF202FD */ -v04 = 4.41110311332675467403e-10; /* 0x3DFE5018, 0x3BD6D9EF */ - -#ifdef __STDC__ - double __ieee754_y0(double x) -#else - double __ieee754_y0(x) - double x; -#endif -{ - fd_twoints un; - double z, s,c,ss,cc,u,v; - int hx,ix,lx; - - un.d = x; - hx = __HI(un); - ix = 0x7fffffff&hx; - lx = __LO(un); - /* Y0(NaN) is NaN, y0(-inf) is Nan, y0(inf) is 0 */ - if(ix>=0x7ff00000) return one/(x+x*x); - if((ix|lx)==0) return -one/zero; - if(hx<0) return zero/zero; - if(ix >= 0x40000000) { /* |x| >= 2.0 */ - /* y0(x) = sqrt(2/(pi*x))*(p0(x)*sin(x0)+q0(x)*cos(x0)) - * where x0 = x-pi/4 - * Better formula: - * cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4) - * = 1/sqrt(2) * (sin(x) + cos(x)) - * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) - * = 1/sqrt(2) * (sin(x) - cos(x)) - * To avoid cancellation, use - * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) - * to compute the worse one. - */ - s = fd_sin(x); - c = fd_cos(x); - ss = s-c; - cc = s+c; - /* - * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x) - * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x) - */ - if(ix<0x7fe00000) { /* make sure x+x not overflow */ - z = -fd_cos(x+x); - if ((s*c)0x48000000) z = (invsqrtpi*ss)/fd_sqrt(x); - else { - u = pzero(x); v = qzero(x); - z = invsqrtpi*(u*ss+v*cc)/fd_sqrt(x); - } - return z; - } - if(ix<=0x3e400000) { /* x < 2**-27 */ - return(u00 + tpi*__ieee754_log(x)); - } - z = x*x; - u = u00+z*(u01+z*(u02+z*(u03+z*(u04+z*(u05+z*u06))))); - v = one+z*(v01+z*(v02+z*(v03+z*v04))); - return(u/v + tpi*(__ieee754_j0(x)*__ieee754_log(x))); -} - -/* The asymptotic expansions of pzero is - * 1 - 9/128 s^2 + 11025/98304 s^4 - ..., where s = 1/x. - * For x >= 2, We approximate pzero by - * pzero(x) = 1 + (R/S) - * where R = pR0 + pR1*s^2 + pR2*s^4 + ... + pR5*s^10 - * S = 1 + pS0*s^2 + ... + pS4*s^10 - * and - * | pzero(x)-1-R/S | <= 2 ** ( -60.26) - */ -#ifdef __STDC__ -static const double pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ -#else -static double pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ -#endif - 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ - -7.03124999999900357484e-02, /* 0xBFB1FFFF, 0xFFFFFD32 */ - -8.08167041275349795626e+00, /* 0xC02029D0, 0xB44FA779 */ - -2.57063105679704847262e+02, /* 0xC0701102, 0x7B19E863 */ - -2.48521641009428822144e+03, /* 0xC0A36A6E, 0xCD4DCAFC */ - -5.25304380490729545272e+03, /* 0xC0B4850B, 0x36CC643D */ -}; -#ifdef __STDC__ -static const double pS8[5] = { -#else -static double pS8[5] = { -#endif - 1.16534364619668181717e+02, /* 0x405D2233, 0x07A96751 */ - 3.83374475364121826715e+03, /* 0x40ADF37D, 0x50596938 */ - 4.05978572648472545552e+04, /* 0x40E3D2BB, 0x6EB6B05F */ - 1.16752972564375915681e+05, /* 0x40FC810F, 0x8F9FA9BD */ - 4.76277284146730962675e+04, /* 0x40E74177, 0x4F2C49DC */ -}; - -#ifdef __STDC__ -static const double pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ -#else -static double pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ -#endif - -1.14125464691894502584e-11, /* 0xBDA918B1, 0x47E495CC */ - -7.03124940873599280078e-02, /* 0xBFB1FFFF, 0xE69AFBC6 */ - -4.15961064470587782438e+00, /* 0xC010A370, 0xF90C6BBF */ - -6.76747652265167261021e+01, /* 0xC050EB2F, 0x5A7D1783 */ - -3.31231299649172967747e+02, /* 0xC074B3B3, 0x6742CC63 */ - -3.46433388365604912451e+02, /* 0xC075A6EF, 0x28A38BD7 */ -}; -#ifdef __STDC__ -static const double pS5[5] = { -#else -static double pS5[5] = { -#endif - 6.07539382692300335975e+01, /* 0x404E6081, 0x0C98C5DE */ - 1.05125230595704579173e+03, /* 0x40906D02, 0x5C7E2864 */ - 5.97897094333855784498e+03, /* 0x40B75AF8, 0x8FBE1D60 */ - 9.62544514357774460223e+03, /* 0x40C2CCB8, 0xFA76FA38 */ - 2.40605815922939109441e+03, /* 0x40A2CC1D, 0xC70BE864 */ -}; - -#ifdef __STDC__ -static const double pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ -#else -static double pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ -#endif - -2.54704601771951915620e-09, /* 0xBE25E103, 0x6FE1AA86 */ - -7.03119616381481654654e-02, /* 0xBFB1FFF6, 0xF7C0E24B */ - -2.40903221549529611423e+00, /* 0xC00345B2, 0xAEA48074 */ - -2.19659774734883086467e+01, /* 0xC035F74A, 0x4CB94E14 */ - -5.80791704701737572236e+01, /* 0xC04D0A22, 0x420A1A45 */ - -3.14479470594888503854e+01, /* 0xC03F72AC, 0xA892D80F */ -}; -#ifdef __STDC__ -static const double pS3[5] = { -#else -static double pS3[5] = { -#endif - 3.58560338055209726349e+01, /* 0x4041ED92, 0x84077DD3 */ - 3.61513983050303863820e+02, /* 0x40769839, 0x464A7C0E */ - 1.19360783792111533330e+03, /* 0x4092A66E, 0x6D1061D6 */ - 1.12799679856907414432e+03, /* 0x40919FFC, 0xB8C39B7E */ - 1.73580930813335754692e+02, /* 0x4065B296, 0xFC379081 */ -}; - -#ifdef __STDC__ -static const double pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ -#else -static double pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ -#endif - -8.87534333032526411254e-08, /* 0xBE77D316, 0xE927026D */ - -7.03030995483624743247e-02, /* 0xBFB1FF62, 0x495E1E42 */ - -1.45073846780952986357e+00, /* 0xBFF73639, 0x8A24A843 */ - -7.63569613823527770791e+00, /* 0xC01E8AF3, 0xEDAFA7F3 */ - -1.11931668860356747786e+01, /* 0xC02662E6, 0xC5246303 */ - -3.23364579351335335033e+00, /* 0xC009DE81, 0xAF8FE70F */ -}; -#ifdef __STDC__ -static const double pS2[5] = { -#else -static double pS2[5] = { -#endif - 2.22202997532088808441e+01, /* 0x40363865, 0x908B5959 */ - 1.36206794218215208048e+02, /* 0x4061069E, 0x0EE8878F */ - 2.70470278658083486789e+02, /* 0x4070E786, 0x42EA079B */ - 1.53875394208320329881e+02, /* 0x40633C03, 0x3AB6FAFF */ - 1.46576176948256193810e+01, /* 0x402D50B3, 0x44391809 */ -}; - -#ifdef __STDC__ - static double pzero(double x) -#else - static double pzero(x) - double x; -#endif -{ -#ifdef __STDC__ - const double *p,*q; -#else - double *p,*q; -#endif - fd_twoints u; - double z,r,s; - int ix; - u.d = x; - ix = 0x7fffffff&__HI(u); - if(ix>=0x40200000) {p = pR8; q= pS8;} - else if(ix>=0x40122E8B){p = pR5; q= pS5;} - else if(ix>=0x4006DB6D){p = pR3; q= pS3;} - else if(ix>=0x40000000){p = pR2; q= pS2;} - z = one/(x*x); - r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); - s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4])))); - return one+ r/s; -} - - -/* For x >= 8, the asymptotic expansions of qzero is - * -1/8 s + 75/1024 s^3 - ..., where s = 1/x. - * We approximate pzero by - * qzero(x) = s*(-1.25 + (R/S)) - * where R = qR0 + qR1*s^2 + qR2*s^4 + ... + qR5*s^10 - * S = 1 + qS0*s^2 + ... + qS5*s^12 - * and - * | qzero(x)/s +1.25-R/S | <= 2 ** ( -61.22) - */ -#ifdef __STDC__ -static const double qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ -#else -static double qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ -#endif - 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ - 7.32421874999935051953e-02, /* 0x3FB2BFFF, 0xFFFFFE2C */ - 1.17682064682252693899e+01, /* 0x40278952, 0x5BB334D6 */ - 5.57673380256401856059e+02, /* 0x40816D63, 0x15301825 */ - 8.85919720756468632317e+03, /* 0x40C14D99, 0x3E18F46D */ - 3.70146267776887834771e+04, /* 0x40E212D4, 0x0E901566 */ -}; -#ifdef __STDC__ -static const double qS8[6] = { -#else -static double qS8[6] = { -#endif - 1.63776026895689824414e+02, /* 0x406478D5, 0x365B39BC */ - 8.09834494656449805916e+03, /* 0x40BFA258, 0x4E6B0563 */ - 1.42538291419120476348e+05, /* 0x41016652, 0x54D38C3F */ - 8.03309257119514397345e+05, /* 0x412883DA, 0x83A52B43 */ - 8.40501579819060512818e+05, /* 0x4129A66B, 0x28DE0B3D */ - -3.43899293537866615225e+05, /* 0xC114FD6D, 0x2C9530C5 */ -}; - -#ifdef __STDC__ -static const double qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ -#else -static double qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ -#endif - 1.84085963594515531381e-11, /* 0x3DB43D8F, 0x29CC8CD9 */ - 7.32421766612684765896e-02, /* 0x3FB2BFFF, 0xD172B04C */ - 5.83563508962056953777e+00, /* 0x401757B0, 0xB9953DD3 */ - 1.35111577286449829671e+02, /* 0x4060E392, 0x0A8788E9 */ - 1.02724376596164097464e+03, /* 0x40900CF9, 0x9DC8C481 */ - 1.98997785864605384631e+03, /* 0x409F17E9, 0x53C6E3A6 */ -}; -#ifdef __STDC__ -static const double qS5[6] = { -#else -static double qS5[6] = { -#endif - 8.27766102236537761883e+01, /* 0x4054B1B3, 0xFB5E1543 */ - 2.07781416421392987104e+03, /* 0x40A03BA0, 0xDA21C0CE */ - 1.88472887785718085070e+04, /* 0x40D267D2, 0x7B591E6D */ - 5.67511122894947329769e+04, /* 0x40EBB5E3, 0x97E02372 */ - 3.59767538425114471465e+04, /* 0x40E19118, 0x1F7A54A0 */ - -5.35434275601944773371e+03, /* 0xC0B4EA57, 0xBEDBC609 */ -}; - -#ifdef __STDC__ -static const double qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ -#else -static double qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ -#endif - 4.37741014089738620906e-09, /* 0x3E32CD03, 0x6ADECB82 */ - 7.32411180042911447163e-02, /* 0x3FB2BFEE, 0x0E8D0842 */ - 3.34423137516170720929e+00, /* 0x400AC0FC, 0x61149CF5 */ - 4.26218440745412650017e+01, /* 0x40454F98, 0x962DAEDD */ - 1.70808091340565596283e+02, /* 0x406559DB, 0xE25EFD1F */ - 1.66733948696651168575e+02, /* 0x4064D77C, 0x81FA21E0 */ -}; -#ifdef __STDC__ -static const double qS3[6] = { -#else -static double qS3[6] = { -#endif - 4.87588729724587182091e+01, /* 0x40486122, 0xBFE343A6 */ - 7.09689221056606015736e+02, /* 0x40862D83, 0x86544EB3 */ - 3.70414822620111362994e+03, /* 0x40ACF04B, 0xE44DFC63 */ - 6.46042516752568917582e+03, /* 0x40B93C6C, 0xD7C76A28 */ - 2.51633368920368957333e+03, /* 0x40A3A8AA, 0xD94FB1C0 */ - -1.49247451836156386662e+02, /* 0xC062A7EB, 0x201CF40F */ -}; - -#ifdef __STDC__ -static const double qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ -#else -static double qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ -#endif - 1.50444444886983272379e-07, /* 0x3E84313B, 0x54F76BDB */ - 7.32234265963079278272e-02, /* 0x3FB2BEC5, 0x3E883E34 */ - 1.99819174093815998816e+00, /* 0x3FFFF897, 0xE727779C */ - 1.44956029347885735348e+01, /* 0x402CFDBF, 0xAAF96FE5 */ - 3.16662317504781540833e+01, /* 0x403FAA8E, 0x29FBDC4A */ - 1.62527075710929267416e+01, /* 0x403040B1, 0x71814BB4 */ -}; -#ifdef __STDC__ -static const double qS2[6] = { -#else -static double qS2[6] = { -#endif - 3.03655848355219184498e+01, /* 0x403E5D96, 0xF7C07AED */ - 2.69348118608049844624e+02, /* 0x4070D591, 0xE4D14B40 */ - 8.44783757595320139444e+02, /* 0x408A6645, 0x22B3BF22 */ - 8.82935845112488550512e+02, /* 0x408B977C, 0x9C5CC214 */ - 2.12666388511798828631e+02, /* 0x406A9553, 0x0E001365 */ - -5.31095493882666946917e+00, /* 0xC0153E6A, 0xF8B32931 */ -}; - -#ifdef __STDC__ - static double qzero(double x) -#else - static double qzero(x) - double x; -#endif -{ -#ifdef __STDC__ - const double *p,*q; -#else - double *p,*q; -#endif - fd_twoints u; - double s,r,z; - int ix; - u.d = x; - ix = 0x7fffffff&__HI(u); - if(ix>=0x40200000) {p = qR8; q= qS8;} - else if(ix>=0x40122E8B){p = qR5; q= qS5;} - else if(ix>=0x4006DB6D){p = qR3; q= qS3;} - else if(ix>=0x40000000){p = qR2; q= qS2;} - z = one/(x*x); - r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); - s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5]))))); - return (-.125 + r/s)/x; -} diff --git a/lib/javascript/fdlibm/e_j1.c b/lib/javascript/fdlibm/e_j1.c deleted file mode 100644 index 8982ac86..00000000 --- a/lib/javascript/fdlibm/e_j1.c +++ /dev/null @@ -1,523 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_j1.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* __ieee754_j1(x), __ieee754_y1(x) - * Bessel function of the first and second kinds of order zero. - * Method -- j1(x): - * 1. For tiny x, we use j1(x) = x/2 - x^3/16 + x^5/384 - ... - * 2. Reduce x to |x| since j1(x)=-j1(-x), and - * for x in (0,2) - * j1(x) = x/2 + x*z*R0/S0, where z = x*x; - * (precision: |j1/x - 1/2 - R0/S0 |<2**-61.51 ) - * for x in (2,inf) - * j1(x) = sqrt(2/(pi*x))*(p1(x)*cos(x1)-q1(x)*sin(x1)) - * y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1)) - * where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1) - * as follow: - * cos(x1) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4) - * = 1/sqrt(2) * (sin(x) - cos(x)) - * sin(x1) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) - * = -1/sqrt(2) * (sin(x) + cos(x)) - * (To avoid cancellation, use - * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) - * to compute the worse one.) - * - * 3 Special cases - * j1(nan)= nan - * j1(0) = 0 - * j1(inf) = 0 - * - * Method -- y1(x): - * 1. screen out x<=0 cases: y1(0)=-inf, y1(x<0)=NaN - * 2. For x<2. - * Since - * y1(x) = 2/pi*(j1(x)*(ln(x/2)+Euler)-1/x-x/2+5/64*x^3-...) - * therefore y1(x)-2/pi*j1(x)*ln(x)-1/x is an odd function. - * We use the following function to approximate y1, - * y1(x) = x*U(z)/V(z) + (2/pi)*(j1(x)*ln(x)-1/x), z= x^2 - * where for x in [0,2] (abs err less than 2**-65.89) - * U(z) = U0[0] + U0[1]*z + ... + U0[4]*z^4 - * V(z) = 1 + v0[0]*z + ... + v0[4]*z^5 - * Note: For tiny x, 1/x dominate y1 and hence - * y1(tiny) = -2/pi/tiny, (choose tiny<2**-54) - * 3. For x>=2. - * y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1)) - * where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1) - * by method mentioned above. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static double pone(double), qone(double); -#else -static double pone(), qone(); -#endif - -#ifdef __STDC__ -static const double -#else -static double -#endif -really_big = 1e300, -one = 1.0, -invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */ -tpi = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ - /* R0/S0 on [0,2] */ -r00 = -6.25000000000000000000e-02, /* 0xBFB00000, 0x00000000 */ -r01 = 1.40705666955189706048e-03, /* 0x3F570D9F, 0x98472C61 */ -r02 = -1.59955631084035597520e-05, /* 0xBEF0C5C6, 0xBA169668 */ -r03 = 4.96727999609584448412e-08, /* 0x3E6AAAFA, 0x46CA0BD9 */ -s01 = 1.91537599538363460805e-02, /* 0x3F939D0B, 0x12637E53 */ -s02 = 1.85946785588630915560e-04, /* 0x3F285F56, 0xB9CDF664 */ -s03 = 1.17718464042623683263e-06, /* 0x3EB3BFF8, 0x333F8498 */ -s04 = 5.04636257076217042715e-09, /* 0x3E35AC88, 0xC97DFF2C */ -s05 = 1.23542274426137913908e-11; /* 0x3DAB2ACF, 0xCFB97ED8 */ - -static double zero = 0.0; - -#ifdef __STDC__ - double __ieee754_j1(double x) -#else - double __ieee754_j1(x) - double x; -#endif -{ - fd_twoints un; - double z, s,c,ss,cc,r,u,v,y; - int hx,ix; - - un.d = x; - hx = __HI(un); - ix = hx&0x7fffffff; - if(ix>=0x7ff00000) return one/x; - y = fd_fabs(x); - if(ix >= 0x40000000) { /* |x| >= 2.0 */ - s = fd_sin(y); - c = fd_cos(y); - ss = -s-c; - cc = s-c; - if(ix<0x7fe00000) { /* make sure y+y not overflow */ - z = fd_cos(y+y); - if ((s*c)>zero) cc = z/ss; - else ss = z/cc; - } - /* - * j1(x) = 1/sqrt(pi) * (P(1,x)*cc - Q(1,x)*ss) / sqrt(x) - * y1(x) = 1/sqrt(pi) * (P(1,x)*ss + Q(1,x)*cc) / sqrt(x) - */ - if(ix>0x48000000) z = (invsqrtpi*cc)/fd_sqrt(y); - else { - u = pone(y); v = qone(y); - z = invsqrtpi*(u*cc-v*ss)/fd_sqrt(y); - } - if(hx<0) return -z; - else return z; - } - if(ix<0x3e400000) { /* |x|<2**-27 */ - if(really_big+x>one) return 0.5*x;/* inexact if x!=0 necessary */ - } - z = x*x; - r = z*(r00+z*(r01+z*(r02+z*r03))); - s = one+z*(s01+z*(s02+z*(s03+z*(s04+z*s05)))); - r *= x; - return(x*0.5+r/s); -} - -#ifdef __STDC__ -static const double U0[5] = { -#else -static double U0[5] = { -#endif - -1.96057090646238940668e-01, /* 0xBFC91866, 0x143CBC8A */ - 5.04438716639811282616e-02, /* 0x3FA9D3C7, 0x76292CD1 */ - -1.91256895875763547298e-03, /* 0xBF5F55E5, 0x4844F50F */ - 2.35252600561610495928e-05, /* 0x3EF8AB03, 0x8FA6B88E */ - -9.19099158039878874504e-08, /* 0xBE78AC00, 0x569105B8 */ -}; -#ifdef __STDC__ -static const double V0[5] = { -#else -static double V0[5] = { -#endif - 1.99167318236649903973e-02, /* 0x3F94650D, 0x3F4DA9F0 */ - 2.02552581025135171496e-04, /* 0x3F2A8C89, 0x6C257764 */ - 1.35608801097516229404e-06, /* 0x3EB6C05A, 0x894E8CA6 */ - 6.22741452364621501295e-09, /* 0x3E3ABF1D, 0x5BA69A86 */ - 1.66559246207992079114e-11, /* 0x3DB25039, 0xDACA772A */ -}; - -#ifdef __STDC__ - double __ieee754_y1(double x) -#else - double __ieee754_y1(x) - double x; -#endif -{ - fd_twoints un; - double z, s,c,ss,cc,u,v; - int hx,ix,lx; - - un.d = x; - hx = __HI(un); - ix = 0x7fffffff&hx; - lx = __LO(un); - /* if Y1(NaN) is NaN, Y1(-inf) is NaN, Y1(inf) is 0 */ - if(ix>=0x7ff00000) return one/(x+x*x); - if((ix|lx)==0) return -one/zero; - if(hx<0) return zero/zero; - if(ix >= 0x40000000) { /* |x| >= 2.0 */ - s = fd_sin(x); - c = fd_cos(x); - ss = -s-c; - cc = s-c; - if(ix<0x7fe00000) { /* make sure x+x not overflow */ - z = fd_cos(x+x); - if ((s*c)>zero) cc = z/ss; - else ss = z/cc; - } - /* y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x0)+q1(x)*cos(x0)) - * where x0 = x-3pi/4 - * Better formula: - * cos(x0) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4) - * = 1/sqrt(2) * (sin(x) - cos(x)) - * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) - * = -1/sqrt(2) * (cos(x) + sin(x)) - * To avoid cancellation, use - * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) - * to compute the worse one. - */ - if(ix>0x48000000) z = (invsqrtpi*ss)/fd_sqrt(x); - else { - u = pone(x); v = qone(x); - z = invsqrtpi*(u*ss+v*cc)/fd_sqrt(x); - } - return z; - } - if(ix<=0x3c900000) { /* x < 2**-54 */ - return(-tpi/x); - } - z = x*x; - u = U0[0]+z*(U0[1]+z*(U0[2]+z*(U0[3]+z*U0[4]))); - v = one+z*(V0[0]+z*(V0[1]+z*(V0[2]+z*(V0[3]+z*V0[4])))); - return(x*(u/v) + tpi*(__ieee754_j1(x)*__ieee754_log(x)-one/x)); -} - -/* For x >= 8, the asymptotic expansions of pone is - * 1 + 15/128 s^2 - 4725/2^15 s^4 - ..., where s = 1/x. - * We approximate pone by - * pone(x) = 1 + (R/S) - * where R = pr0 + pr1*s^2 + pr2*s^4 + ... + pr5*s^10 - * S = 1 + ps0*s^2 + ... + ps4*s^10 - * and - * | pone(x)-1-R/S | <= 2 ** ( -60.06) - */ - -#ifdef __STDC__ -static const double pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ -#else -static double pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ -#endif - 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ - 1.17187499999988647970e-01, /* 0x3FBDFFFF, 0xFFFFFCCE */ - 1.32394806593073575129e+01, /* 0x402A7A9D, 0x357F7FCE */ - 4.12051854307378562225e+02, /* 0x4079C0D4, 0x652EA590 */ - 3.87474538913960532227e+03, /* 0x40AE457D, 0xA3A532CC */ - 7.91447954031891731574e+03, /* 0x40BEEA7A, 0xC32782DD */ -}; -#ifdef __STDC__ -static const double ps8[5] = { -#else -static double ps8[5] = { -#endif - 1.14207370375678408436e+02, /* 0x405C8D45, 0x8E656CAC */ - 3.65093083420853463394e+03, /* 0x40AC85DC, 0x964D274F */ - 3.69562060269033463555e+04, /* 0x40E20B86, 0x97C5BB7F */ - 9.76027935934950801311e+04, /* 0x40F7D42C, 0xB28F17BB */ - 3.08042720627888811578e+04, /* 0x40DE1511, 0x697A0B2D */ -}; - -#ifdef __STDC__ -static const double pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ -#else -static double pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ -#endif - 1.31990519556243522749e-11, /* 0x3DAD0667, 0xDAE1CA7D */ - 1.17187493190614097638e-01, /* 0x3FBDFFFF, 0xE2C10043 */ - 6.80275127868432871736e+00, /* 0x401B3604, 0x6E6315E3 */ - 1.08308182990189109773e+02, /* 0x405B13B9, 0x452602ED */ - 5.17636139533199752805e+02, /* 0x40802D16, 0xD052D649 */ - 5.28715201363337541807e+02, /* 0x408085B8, 0xBB7E0CB7 */ -}; -#ifdef __STDC__ -static const double ps5[5] = { -#else -static double ps5[5] = { -#endif - 5.92805987221131331921e+01, /* 0x404DA3EA, 0xA8AF633D */ - 9.91401418733614377743e+02, /* 0x408EFB36, 0x1B066701 */ - 5.35326695291487976647e+03, /* 0x40B4E944, 0x5706B6FB */ - 7.84469031749551231769e+03, /* 0x40BEA4B0, 0xB8A5BB15 */ - 1.50404688810361062679e+03, /* 0x40978030, 0x036F5E51 */ -}; - -#ifdef __STDC__ -static const double pr3[6] = { -#else -static double pr3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ -#endif - 3.02503916137373618024e-09, /* 0x3E29FC21, 0xA7AD9EDD */ - 1.17186865567253592491e-01, /* 0x3FBDFFF5, 0x5B21D17B */ - 3.93297750033315640650e+00, /* 0x400F76BC, 0xE85EAD8A */ - 3.51194035591636932736e+01, /* 0x40418F48, 0x9DA6D129 */ - 9.10550110750781271918e+01, /* 0x4056C385, 0x4D2C1837 */ - 4.85590685197364919645e+01, /* 0x4048478F, 0x8EA83EE5 */ -}; -#ifdef __STDC__ -static const double ps3[5] = { -#else -static double ps3[5] = { -#endif - 3.47913095001251519989e+01, /* 0x40416549, 0xA134069C */ - 3.36762458747825746741e+02, /* 0x40750C33, 0x07F1A75F */ - 1.04687139975775130551e+03, /* 0x40905B7C, 0x5037D523 */ - 8.90811346398256432622e+02, /* 0x408BD67D, 0xA32E31E9 */ - 1.03787932439639277504e+02, /* 0x4059F26D, 0x7C2EED53 */ -}; - -#ifdef __STDC__ -static const double pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ -#else -static double pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ -#endif - 1.07710830106873743082e-07, /* 0x3E7CE9D4, 0xF65544F4 */ - 1.17176219462683348094e-01, /* 0x3FBDFF42, 0xBE760D83 */ - 2.36851496667608785174e+00, /* 0x4002F2B7, 0xF98FAEC0 */ - 1.22426109148261232917e+01, /* 0x40287C37, 0x7F71A964 */ - 1.76939711271687727390e+01, /* 0x4031B1A8, 0x177F8EE2 */ - 5.07352312588818499250e+00, /* 0x40144B49, 0xA574C1FE */ -}; -#ifdef __STDC__ -static const double ps2[5] = { -#else -static double ps2[5] = { -#endif - 2.14364859363821409488e+01, /* 0x40356FBD, 0x8AD5ECDC */ - 1.25290227168402751090e+02, /* 0x405F5293, 0x14F92CD5 */ - 2.32276469057162813669e+02, /* 0x406D08D8, 0xD5A2DBD9 */ - 1.17679373287147100768e+02, /* 0x405D6B7A, 0xDA1884A9 */ - 8.36463893371618283368e+00, /* 0x4020BAB1, 0xF44E5192 */ -}; - -#ifdef __STDC__ - static double pone(double x) -#else - static double pone(x) - double x; -#endif -{ -#ifdef __STDC__ - const double *p,*q; -#else - double *p,*q; -#endif - fd_twoints un; - double z,r,s; - int ix; - un.d = x; - ix = 0x7fffffff&__HI(un); - if(ix>=0x40200000) {p = pr8; q= ps8;} - else if(ix>=0x40122E8B){p = pr5; q= ps5;} - else if(ix>=0x4006DB6D){p = pr3; q= ps3;} - else if(ix>=0x40000000){p = pr2; q= ps2;} - z = one/(x*x); - r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); - s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4])))); - return one+ r/s; -} - - -/* For x >= 8, the asymptotic expansions of qone is - * 3/8 s - 105/1024 s^3 - ..., where s = 1/x. - * We approximate pone by - * qone(x) = s*(0.375 + (R/S)) - * where R = qr1*s^2 + qr2*s^4 + ... + qr5*s^10 - * S = 1 + qs1*s^2 + ... + qs6*s^12 - * and - * | qone(x)/s -0.375-R/S | <= 2 ** ( -61.13) - */ - -#ifdef __STDC__ -static const double qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ -#else -static double qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ -#endif - 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ - -1.02539062499992714161e-01, /* 0xBFBA3FFF, 0xFFFFFDF3 */ - -1.62717534544589987888e+01, /* 0xC0304591, 0xA26779F7 */ - -7.59601722513950107896e+02, /* 0xC087BCD0, 0x53E4B576 */ - -1.18498066702429587167e+04, /* 0xC0C724E7, 0x40F87415 */ - -4.84385124285750353010e+04, /* 0xC0E7A6D0, 0x65D09C6A */ -}; -#ifdef __STDC__ -static const double qs8[6] = { -#else -static double qs8[6] = { -#endif - 1.61395369700722909556e+02, /* 0x40642CA6, 0xDE5BCDE5 */ - 7.82538599923348465381e+03, /* 0x40BE9162, 0xD0D88419 */ - 1.33875336287249578163e+05, /* 0x4100579A, 0xB0B75E98 */ - 7.19657723683240939863e+05, /* 0x4125F653, 0x72869C19 */ - 6.66601232617776375264e+05, /* 0x412457D2, 0x7719AD5C */ - -2.94490264303834643215e+05, /* 0xC111F969, 0x0EA5AA18 */ -}; - -#ifdef __STDC__ -static const double qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ -#else -static double qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ -#endif - -2.08979931141764104297e-11, /* 0xBDB6FA43, 0x1AA1A098 */ - -1.02539050241375426231e-01, /* 0xBFBA3FFF, 0xCB597FEF */ - -8.05644828123936029840e+00, /* 0xC0201CE6, 0xCA03AD4B */ - -1.83669607474888380239e+02, /* 0xC066F56D, 0x6CA7B9B0 */ - -1.37319376065508163265e+03, /* 0xC09574C6, 0x6931734F */ - -2.61244440453215656817e+03, /* 0xC0A468E3, 0x88FDA79D */ -}; -#ifdef __STDC__ -static const double qs5[6] = { -#else -static double qs5[6] = { -#endif - 8.12765501384335777857e+01, /* 0x405451B2, 0xFF5A11B2 */ - 1.99179873460485964642e+03, /* 0x409F1F31, 0xE77BF839 */ - 1.74684851924908907677e+04, /* 0x40D10F1F, 0x0D64CE29 */ - 4.98514270910352279316e+04, /* 0x40E8576D, 0xAABAD197 */ - 2.79480751638918118260e+04, /* 0x40DB4B04, 0xCF7C364B */ - -4.71918354795128470869e+03, /* 0xC0B26F2E, 0xFCFFA004 */ -}; - -#ifdef __STDC__ -static const double qr3[6] = { -#else -static double qr3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ -#endif - -5.07831226461766561369e-09, /* 0xBE35CFA9, 0xD38FC84F */ - -1.02537829820837089745e-01, /* 0xBFBA3FEB, 0x51AEED54 */ - -4.61011581139473403113e+00, /* 0xC01270C2, 0x3302D9FF */ - -5.78472216562783643212e+01, /* 0xC04CEC71, 0xC25D16DA */ - -2.28244540737631695038e+02, /* 0xC06C87D3, 0x4718D55F */ - -2.19210128478909325622e+02, /* 0xC06B66B9, 0x5F5C1BF6 */ -}; -#ifdef __STDC__ -static const double qs3[6] = { -#else -static double qs3[6] = { -#endif - 4.76651550323729509273e+01, /* 0x4047D523, 0xCCD367E4 */ - 6.73865112676699709482e+02, /* 0x40850EEB, 0xC031EE3E */ - 3.38015286679526343505e+03, /* 0x40AA684E, 0x448E7C9A */ - 5.54772909720722782367e+03, /* 0x40B5ABBA, 0xA61D54A6 */ - 1.90311919338810798763e+03, /* 0x409DBC7A, 0x0DD4DF4B */ - -1.35201191444307340817e+02, /* 0xC060E670, 0x290A311F */ -}; - -#ifdef __STDC__ -static const double qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ -#else -static double qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ -#endif - -1.78381727510958865572e-07, /* 0xBE87F126, 0x44C626D2 */ - -1.02517042607985553460e-01, /* 0xBFBA3E8E, 0x9148B010 */ - -2.75220568278187460720e+00, /* 0xC0060484, 0x69BB4EDA */ - -1.96636162643703720221e+01, /* 0xC033A9E2, 0xC168907F */ - -4.23253133372830490089e+01, /* 0xC04529A3, 0xDE104AAA */ - -2.13719211703704061733e+01, /* 0xC0355F36, 0x39CF6E52 */ -}; -#ifdef __STDC__ -static const double qs2[6] = { -#else -static double qs2[6] = { -#endif - 2.95333629060523854548e+01, /* 0x403D888A, 0x78AE64FF */ - 2.52981549982190529136e+02, /* 0x406F9F68, 0xDB821CBA */ - 7.57502834868645436472e+02, /* 0x4087AC05, 0xCE49A0F7 */ - 7.39393205320467245656e+02, /* 0x40871B25, 0x48D4C029 */ - 1.55949003336666123687e+02, /* 0x40637E5E, 0x3C3ED8D4 */ - -4.95949898822628210127e+00, /* 0xC013D686, 0xE71BE86B */ -}; - -#ifdef __STDC__ - static double qone(double x) -#else - static double qone(x) - double x; -#endif -{ -#ifdef __STDC__ - const double *p,*q; -#else - double *p,*q; -#endif - fd_twoints un; - double s,r,z; - int ix; - un.d = x; - ix = 0x7fffffff&__HI(un); - if(ix>=0x40200000) {p = qr8; q= qs8;} - else if(ix>=0x40122E8B){p = qr5; q= qs5;} - else if(ix>=0x4006DB6D){p = qr3; q= qs3;} - else if(ix>=0x40000000){p = qr2; q= qs2;} - z = one/(x*x); - r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); - s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5]))))); - return (.375 + r/s)/x; -} diff --git a/lib/javascript/fdlibm/e_jn.c b/lib/javascript/fdlibm/e_jn.c deleted file mode 100644 index 2b61b443..00000000 --- a/lib/javascript/fdlibm/e_jn.c +++ /dev/null @@ -1,315 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_jn.c 1.4 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * __ieee754_jn(n, x), __ieee754_yn(n, x) - * floating point Bessel's function of the 1st and 2nd kind - * of order n - * - * Special cases: - * y0(0)=y1(0)=yn(n,0) = -inf with division by zero signal; - * y0(-ve)=y1(-ve)=yn(n,-ve) are NaN with invalid signal. - * Note 2. About jn(n,x), yn(n,x) - * For n=0, j0(x) is called, - * for n=1, j1(x) is called, - * for nx, a continued fraction approximation to - * j(n,x)/j(n-1,x) is evaluated and then backward - * recursion is used starting from a supposed value - * for j(n,x). The resulting value of j(0,x) is - * compared with the actual value to correct the - * supposed value of j(n,x). - * - * yn(n,x) is similar in all respects, except - * that forward recursion is used for all - * values of n>1. - * - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */ -two = 2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */ -one = 1.00000000000000000000e+00; /* 0x3FF00000, 0x00000000 */ - -static double zero = 0.00000000000000000000e+00; - -#ifdef __STDC__ - double __ieee754_jn(int n, double x) -#else - double __ieee754_jn(n,x) - int n; double x; -#endif -{ - fd_twoints u; - int i,hx,ix,lx, sgn; - double a, b, temp, di; - double z, w; - - /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x) - * Thus, J(-n,x) = J(n,-x) - */ - u.d = x; - hx = __HI(u); - ix = 0x7fffffff&hx; - lx = __LO(u); - /* if J(n,NaN) is NaN */ - if((ix|((unsigned)(lx|-lx))>>31)>0x7ff00000) return x+x; - if(n<0){ - n = -n; - x = -x; - hx ^= 0x80000000; - } - if(n==0) return(__ieee754_j0(x)); - if(n==1) return(__ieee754_j1(x)); - sgn = (n&1)&(hx>>31); /* even n -- 0, odd n -- sign(x) */ - x = fd_fabs(x); - if((ix|lx)==0||ix>=0x7ff00000) /* if x is 0 or inf */ - b = zero; - else if((double)n<=x) { - /* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */ - if(ix>=0x52D00000) { /* x > 2**302 */ - /* (x >> n**2) - * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi) - * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi) - * Let s=sin(x), c=cos(x), - * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then - * - * n sin(xn)*sqt2 cos(xn)*sqt2 - * ---------------------------------- - * 0 s-c c+s - * 1 -s-c -c+s - * 2 -s+c -c-s - * 3 s+c c-s - */ - switch(n&3) { - case 0: temp = fd_cos(x)+fd_sin(x); break; - case 1: temp = -fd_cos(x)+fd_sin(x); break; - case 2: temp = -fd_cos(x)-fd_sin(x); break; - case 3: temp = fd_cos(x)-fd_sin(x); break; - } - b = invsqrtpi*temp/fd_sqrt(x); - } else { - a = __ieee754_j0(x); - b = __ieee754_j1(x); - for(i=1;i33) /* underflow */ - b = zero; - else { - temp = x*0.5; b = temp; - for (a=one,i=2;i<=n;i++) { - a *= (double)i; /* a = n! */ - b *= temp; /* b = (x/2)^n */ - } - b = b/a; - } - } else { - /* use backward recurrence */ - /* x x^2 x^2 - * J(n,x)/J(n-1,x) = ---- ------ ------ ..... - * 2n - 2(n+1) - 2(n+2) - * - * 1 1 1 - * (for large x) = ---- ------ ------ ..... - * 2n 2(n+1) 2(n+2) - * -- - ------ - ------ - - * x x x - * - * Let w = 2n/x and h=2/x, then the above quotient - * is equal to the continued fraction: - * 1 - * = ----------------------- - * 1 - * w - ----------------- - * 1 - * w+h - --------- - * w+2h - ... - * - * To determine how many terms needed, let - * Q(0) = w, Q(1) = w(w+h) - 1, - * Q(k) = (w+k*h)*Q(k-1) - Q(k-2), - * When Q(k) > 1e4 good for single - * When Q(k) > 1e9 good for double - * When Q(k) > 1e17 good for quadruple - */ - /* determine k */ - double t,v; - double q0,q1,h,tmp; int k,m; - w = (n+n)/(double)x; h = 2.0/(double)x; - q0 = w; z = w+h; q1 = w*z - 1.0; k=1; - while(q1<1.0e9) { - k += 1; z += h; - tmp = z*q1 - q0; - q0 = q1; - q1 = tmp; - } - m = n+n; - for(t=zero, i = 2*(n+k); i>=m; i -= 2) t = one/(i/x-t); - a = t; - b = one; - /* estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n) - * Hence, if n*(log(2n/x)) > ... - * single 8.8722839355e+01 - * double 7.09782712893383973096e+02 - * long double 1.1356523406294143949491931077970765006170e+04 - * then recurrent value may overflow and the result is - * likely underflow to zero - */ - tmp = n; - v = two/x; - tmp = tmp*__ieee754_log(fd_fabs(v*tmp)); - if(tmp<7.09782712893383973096e+02) { - for(i=n-1,di=(double)(i+i);i>0;i--){ - temp = b; - b *= di; - b = b/x - a; - a = temp; - di -= two; - } - } else { - for(i=n-1,di=(double)(i+i);i>0;i--){ - temp = b; - b *= di; - b = b/x - a; - a = temp; - di -= two; - /* scale b to avoid spurious overflow */ - if(b>1e100) { - a /= b; - t /= b; - b = one; - } - } - } - b = (t*__ieee754_j0(x)/b); - } - } - if(sgn==1) return -b; else return b; -} - -#ifdef __STDC__ - double __ieee754_yn(int n, double x) -#else - double __ieee754_yn(n,x) - int n; double x; -#endif -{ - fd_twoints u; - int i,hx,ix,lx; - int sign; - double a, b, temp; - - u.d = x; - hx = __HI(u); - ix = 0x7fffffff&hx; - lx = __LO(u); - /* if Y(n,NaN) is NaN */ - if((ix|((unsigned)(lx|-lx))>>31)>0x7ff00000) return x+x; - if((ix|lx)==0) return -one/zero; - if(hx<0) return zero/zero; - sign = 1; - if(n<0){ - n = -n; - sign = 1 - ((n&1)<<1); - } - if(n==0) return(__ieee754_y0(x)); - if(n==1) return(sign*__ieee754_y1(x)); - if(ix==0x7ff00000) return zero; - if(ix>=0x52D00000) { /* x > 2**302 */ - /* (x >> n**2) - * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi) - * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi) - * Let s=sin(x), c=cos(x), - * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then - * - * n sin(xn)*sqt2 cos(xn)*sqt2 - * ---------------------------------- - * 0 s-c c+s - * 1 -s-c -c+s - * 2 -s+c -c-s - * 3 s+c c-s - */ - switch(n&3) { - case 0: temp = fd_sin(x)-fd_cos(x); break; - case 1: temp = -fd_sin(x)-fd_cos(x); break; - case 2: temp = -fd_sin(x)+fd_cos(x); break; - case 3: temp = fd_sin(x)+fd_cos(x); break; - } - b = invsqrtpi*temp/fd_sqrt(x); - } else { - a = __ieee754_y0(x); - b = __ieee754_y1(x); - /* quit if b is -inf */ - u.d = b; - for(i=1;i0) return b; else return -b; -} diff --git a/lib/javascript/fdlibm/e_lgamma.c b/lib/javascript/fdlibm/e_lgamma.c deleted file mode 100644 index beb3bd93..00000000 --- a/lib/javascript/fdlibm/e_lgamma.c +++ /dev/null @@ -1,71 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_lgamma.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -/* __ieee754_lgamma(x) - * Return the logarithm of the Gamma function of x. - * - * Method: call __ieee754_lgamma_r - */ - -#include "fdlibm.h" - -extern int signgam; - -#ifdef __STDC__ - double __ieee754_lgamma(double x) -#else - double __ieee754_lgamma(x) - double x; -#endif -{ - return __ieee754_lgamma_r(x,&signgam); -} diff --git a/lib/javascript/fdlibm/e_lgamma_r.c b/lib/javascript/fdlibm/e_lgamma_r.c deleted file mode 100644 index df92e7a2..00000000 --- a/lib/javascript/fdlibm/e_lgamma_r.c +++ /dev/null @@ -1,347 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_lgamma_r.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -/* __ieee754_lgamma_r(x, signgamp) - * Reentrant version of the logarithm of the Gamma function - * with user provide pointer for the sign of Gamma(x). - * - * Method: - * 1. Argument Reduction for 0 < x <= 8 - * Since gamma(1+s)=s*gamma(s), for x in [0,8], we may - * reduce x to a number in [1.5,2.5] by - * lgamma(1+s) = log(s) + lgamma(s) - * for example, - * lgamma(7.3) = log(6.3) + lgamma(6.3) - * = log(6.3*5.3) + lgamma(5.3) - * = log(6.3*5.3*4.3*3.3*2.3) + lgamma(2.3) - * 2. Polynomial approximation of lgamma around its - * minimun ymin=1.461632144968362245 to maintain monotonicity. - * On [ymin-0.23, ymin+0.27] (i.e., [1.23164,1.73163]), use - * Let z = x-ymin; - * lgamma(x) = -1.214862905358496078218 + z^2*poly(z) - * where - * poly(z) is a 14 degree polynomial. - * 2. Rational approximation in the primary interval [2,3] - * We use the following approximation: - * s = x-2.0; - * lgamma(x) = 0.5*s + s*P(s)/Q(s) - * with accuracy - * |P/Q - (lgamma(x)-0.5s)| < 2**-61.71 - * Our algorithms are based on the following observation - * - * zeta(2)-1 2 zeta(3)-1 3 - * lgamma(2+s) = s*(1-Euler) + --------- * s - --------- * s + ... - * 2 3 - * - * where Euler = 0.5771... is the Euler constant, which is very - * close to 0.5. - * - * 3. For x>=8, we have - * lgamma(x)~(x-0.5)log(x)-x+0.5*log(2pi)+1/(12x)-1/(360x**3)+.... - * (better formula: - * lgamma(x)~(x-0.5)*(log(x)-1)-.5*(log(2pi)-1) + ...) - * Let z = 1/x, then we approximation - * f(z) = lgamma(x) - (x-0.5)(log(x)-1) - * by - * 3 5 11 - * w = w0 + w1*z + w2*z + w3*z + ... + w6*z - * where - * |w - f(z)| < 2**-58.74 - * - * 4. For negative x, since (G is gamma function) - * -x*G(-x)*G(x) = pi/sin(pi*x), - * we have - * G(x) = pi/(sin(pi*x)*(-x)*G(-x)) - * since G(-x) is positive, sign(G(x)) = sign(sin(pi*x)) for x<0 - * Hence, for x<0, signgam = sign(sin(pi*x)) and - * lgamma(x) = log(|Gamma(x)|) - * = log(pi/(|x*sin(pi*x)|)) - lgamma(-x); - * Note: one should avoid compute pi*(-x) directly in the - * computation of sin(pi*(-x)). - * - * 5. Special Cases - * lgamma(2+s) ~ s*(1-Euler) for tiny s - * lgamma(1)=lgamma(2)=0 - * lgamma(x) ~ -log(x) for tiny x - * lgamma(0) = lgamma(inf) = inf - * lgamma(-integer) = +-inf - * - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -two52= 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ -half= 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ -one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ -pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */ -a0 = 7.72156649015328655494e-02, /* 0x3FB3C467, 0xE37DB0C8 */ -a1 = 3.22467033424113591611e-01, /* 0x3FD4A34C, 0xC4A60FAD */ -a2 = 6.73523010531292681824e-02, /* 0x3FB13E00, 0x1A5562A7 */ -a3 = 2.05808084325167332806e-02, /* 0x3F951322, 0xAC92547B */ -a4 = 7.38555086081402883957e-03, /* 0x3F7E404F, 0xB68FEFE8 */ -a5 = 2.89051383673415629091e-03, /* 0x3F67ADD8, 0xCCB7926B */ -a6 = 1.19270763183362067845e-03, /* 0x3F538A94, 0x116F3F5D */ -a7 = 5.10069792153511336608e-04, /* 0x3F40B6C6, 0x89B99C00 */ -a8 = 2.20862790713908385557e-04, /* 0x3F2CF2EC, 0xED10E54D */ -a9 = 1.08011567247583939954e-04, /* 0x3F1C5088, 0x987DFB07 */ -a10 = 2.52144565451257326939e-05, /* 0x3EFA7074, 0x428CFA52 */ -a11 = 4.48640949618915160150e-05, /* 0x3F07858E, 0x90A45837 */ -tc = 1.46163214496836224576e+00, /* 0x3FF762D8, 0x6356BE3F */ -tf = -1.21486290535849611461e-01, /* 0xBFBF19B9, 0xBCC38A42 */ -/* tt = -(tail of tf) */ -tt = -3.63867699703950536541e-18, /* 0xBC50C7CA, 0xA48A971F */ -t0 = 4.83836122723810047042e-01, /* 0x3FDEF72B, 0xC8EE38A2 */ -t1 = -1.47587722994593911752e-01, /* 0xBFC2E427, 0x8DC6C509 */ -t2 = 6.46249402391333854778e-02, /* 0x3FB08B42, 0x94D5419B */ -t3 = -3.27885410759859649565e-02, /* 0xBFA0C9A8, 0xDF35B713 */ -t4 = 1.79706750811820387126e-02, /* 0x3F9266E7, 0x970AF9EC */ -t5 = -1.03142241298341437450e-02, /* 0xBF851F9F, 0xBA91EC6A */ -t6 = 6.10053870246291332635e-03, /* 0x3F78FCE0, 0xE370E344 */ -t7 = -3.68452016781138256760e-03, /* 0xBF6E2EFF, 0xB3E914D7 */ -t8 = 2.25964780900612472250e-03, /* 0x3F6282D3, 0x2E15C915 */ -t9 = -1.40346469989232843813e-03, /* 0xBF56FE8E, 0xBF2D1AF1 */ -t10 = 8.81081882437654011382e-04, /* 0x3F4CDF0C, 0xEF61A8E9 */ -t11 = -5.38595305356740546715e-04, /* 0xBF41A610, 0x9C73E0EC */ -t12 = 3.15632070903625950361e-04, /* 0x3F34AF6D, 0x6C0EBBF7 */ -t13 = -3.12754168375120860518e-04, /* 0xBF347F24, 0xECC38C38 */ -t14 = 3.35529192635519073543e-04, /* 0x3F35FD3E, 0xE8C2D3F4 */ -u0 = -7.72156649015328655494e-02, /* 0xBFB3C467, 0xE37DB0C8 */ -u1 = 6.32827064025093366517e-01, /* 0x3FE4401E, 0x8B005DFF */ -u2 = 1.45492250137234768737e+00, /* 0x3FF7475C, 0xD119BD6F */ -u3 = 9.77717527963372745603e-01, /* 0x3FEF4976, 0x44EA8450 */ -u4 = 2.28963728064692451092e-01, /* 0x3FCD4EAE, 0xF6010924 */ -u5 = 1.33810918536787660377e-02, /* 0x3F8B678B, 0xBF2BAB09 */ -v1 = 2.45597793713041134822e+00, /* 0x4003A5D7, 0xC2BD619C */ -v2 = 2.12848976379893395361e+00, /* 0x40010725, 0xA42B18F5 */ -v3 = 7.69285150456672783825e-01, /* 0x3FE89DFB, 0xE45050AF */ -v4 = 1.04222645593369134254e-01, /* 0x3FBAAE55, 0xD6537C88 */ -v5 = 3.21709242282423911810e-03, /* 0x3F6A5ABB, 0x57D0CF61 */ -s0 = -7.72156649015328655494e-02, /* 0xBFB3C467, 0xE37DB0C8 */ -s1 = 2.14982415960608852501e-01, /* 0x3FCB848B, 0x36E20878 */ -s2 = 3.25778796408930981787e-01, /* 0x3FD4D98F, 0x4F139F59 */ -s3 = 1.46350472652464452805e-01, /* 0x3FC2BB9C, 0xBEE5F2F7 */ -s4 = 2.66422703033638609560e-02, /* 0x3F9B481C, 0x7E939961 */ -s5 = 1.84028451407337715652e-03, /* 0x3F5E26B6, 0x7368F239 */ -s6 = 3.19475326584100867617e-05, /* 0x3F00BFEC, 0xDD17E945 */ -r1 = 1.39200533467621045958e+00, /* 0x3FF645A7, 0x62C4AB74 */ -r2 = 7.21935547567138069525e-01, /* 0x3FE71A18, 0x93D3DCDC */ -r3 = 1.71933865632803078993e-01, /* 0x3FC601ED, 0xCCFBDF27 */ -r4 = 1.86459191715652901344e-02, /* 0x3F9317EA, 0x742ED475 */ -r5 = 7.77942496381893596434e-04, /* 0x3F497DDA, 0xCA41A95B */ -r6 = 7.32668430744625636189e-06, /* 0x3EDEBAF7, 0xA5B38140 */ -w0 = 4.18938533204672725052e-01, /* 0x3FDACFE3, 0x90C97D69 */ -w1 = 8.33333333333329678849e-02, /* 0x3FB55555, 0x5555553B */ -w2 = -2.77777777728775536470e-03, /* 0xBF66C16C, 0x16B02E5C */ -w3 = 7.93650558643019558500e-04, /* 0x3F4A019F, 0x98CF38B6 */ -w4 = -5.95187557450339963135e-04, /* 0xBF4380CB, 0x8C0FE741 */ -w5 = 8.36339918996282139126e-04, /* 0x3F4B67BA, 0x4CDAD5D1 */ -w6 = -1.63092934096575273989e-03; /* 0xBF5AB89D, 0x0B9E43E4 */ - -static double zero= 0.00000000000000000000e+00; - -#ifdef __STDC__ - static double sin_pi(double x) -#else - static double sin_pi(x) - double x; -#endif -{ - fd_twoints u; - double y,z; - int n,ix; - - u.d = x; - ix = 0x7fffffff&__HI(u); - - if(ix<0x3fd00000) return __kernel_sin(pi*x,zero,0); - y = -x; /* x is assume negative */ - - /* - * argument reduction, make sure inexact flag not raised if input - * is an integer - */ - z = fd_floor(y); - if(z!=y) { /* inexact anyway */ - y *= 0.5; - y = 2.0*(y - fd_floor(y)); /* y = |x| mod 2.0 */ - n = (int) (y*4.0); - } else { - if(ix>=0x43400000) { - y = zero; n = 0; /* y must be even */ - } else { - if(ix<0x43300000) z = y+two52; /* exact */ - u.d = z; - n = __LO(u)&1; /* lower word of z */ - y = n; - n<<= 2; - } - } - switch (n) { - case 0: y = __kernel_sin(pi*y,zero,0); break; - case 1: - case 2: y = __kernel_cos(pi*(0.5-y),zero); break; - case 3: - case 4: y = __kernel_sin(pi*(one-y),zero,0); break; - case 5: - case 6: y = -__kernel_cos(pi*(y-1.5),zero); break; - default: y = __kernel_sin(pi*(y-2.0),zero,0); break; - } - return -y; -} - - -#ifdef __STDC__ - double __ieee754_lgamma_r(double x, int *signgamp) -#else - double __ieee754_lgamma_r(x,signgamp) - double x; int *signgamp; -#endif -{ - fd_twoints u; - double t,y,z,nadj,p,p1,p2,p3,q,r,w; - int i,hx,lx,ix; - - u.d = x; - hx = __HI(u); - lx = __LO(u); - - /* purge off +-inf, NaN, +-0, and negative arguments */ - *signgamp = 1; - ix = hx&0x7fffffff; - if(ix>=0x7ff00000) return x*x; - if((ix|lx)==0) return one/zero; - if(ix<0x3b900000) { /* |x|<2**-70, return -log(|x|) */ - if(hx<0) { - *signgamp = -1; - return -__ieee754_log(-x); - } else return -__ieee754_log(x); - } - if(hx<0) { - if(ix>=0x43300000) /* |x|>=2**52, must be -integer */ - return one/zero; - t = sin_pi(x); - if(t==zero) return one/zero; /* -integer */ - nadj = __ieee754_log(pi/fd_fabs(t*x)); - if(t=0x3FE76944) {y = one-x; i= 0;} - else if(ix>=0x3FCDA661) {y= x-(tc-one); i=1;} - else {y = x; i=2;} - } else { - r = zero; - if(ix>=0x3FFBB4C3) {y=2.0-x;i=0;} /* [1.7316,2] */ - else if(ix>=0x3FF3B4C4) {y=x-tc;i=1;} /* [1.23,1.73] */ - else {y=x-one;i=2;} - } - switch(i) { - case 0: - z = y*y; - p1 = a0+z*(a2+z*(a4+z*(a6+z*(a8+z*a10)))); - p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*a11))))); - p = y*p1+p2; - r += (p-0.5*y); break; - case 1: - z = y*y; - w = z*y; - p1 = t0+w*(t3+w*(t6+w*(t9 +w*t12))); /* parallel comp */ - p2 = t1+w*(t4+w*(t7+w*(t10+w*t13))); - p3 = t2+w*(t5+w*(t8+w*(t11+w*t14))); - p = z*p1-(tt-w*(p2+y*p3)); - r += (tf + p); break; - case 2: - p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*u5))))); - p2 = one+y*(v1+y*(v2+y*(v3+y*(v4+y*v5)))); - r += (-0.5*y + p1/p2); - } - } - else if(ix<0x40200000) { /* x < 8.0 */ - i = (int)x; - t = zero; - y = x-(double)i; - p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*s6)))))); - q = one+y*(r1+y*(r2+y*(r3+y*(r4+y*(r5+y*r6))))); - r = half*y+p/q; - z = one; /* lgamma(1+s) = log(s) + lgamma(s) */ - switch(i) { - case 7: z *= (y+6.0); /* FALLTHRU */ - case 6: z *= (y+5.0); /* FALLTHRU */ - case 5: z *= (y+4.0); /* FALLTHRU */ - case 4: z *= (y+3.0); /* FALLTHRU */ - case 3: z *= (y+2.0); /* FALLTHRU */ - r += __ieee754_log(z); break; - } - /* 8.0 <= x < 2**58 */ - } else if (ix < 0x43900000) { - t = __ieee754_log(x); - z = one/x; - y = z*z; - w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*w6))))); - r = (x-half)*(t-one)+w; - } else - /* 2**58 <= x <= inf */ - r = x*(__ieee754_log(x)-one); - if(hx<0) r = nadj - r; - return r; -} diff --git a/lib/javascript/fdlibm/e_log.c b/lib/javascript/fdlibm/e_log.c deleted file mode 100644 index 8645d6ef..00000000 --- a/lib/javascript/fdlibm/e_log.c +++ /dev/null @@ -1,184 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_log.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* __ieee754_log(x) - * Return the logrithm of x - * - * Method : - * 1. Argument Reduction: find k and f such that - * x = 2^k * (1+f), - * where sqrt(2)/2 < 1+f < sqrt(2) . - * - * 2. Approximation of log(1+f). - * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) - * = 2s + 2/3 s**3 + 2/5 s**5 + ....., - * = 2s + s*R - * We use a special Reme algorithm on [0,0.1716] to generate - * a polynomial of degree 14 to approximate R The maximum error - * of this polynomial approximation is bounded by 2**-58.45. In - * other words, - * 2 4 6 8 10 12 14 - * R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s - * (the values of Lg1 to Lg7 are listed in the program) - * and - * | 2 14 | -58.45 - * | Lg1*s +...+Lg7*s - R(z) | <= 2 - * | | - * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. - * In order to guarantee error in log below 1ulp, we compute log - * by - * log(1+f) = f - s*(f - R) (if f is not too large) - * log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy) - * - * 3. Finally, log(x) = k*ln2 + log(1+f). - * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) - * Here ln2 is split into two floating point number: - * ln2_hi + ln2_lo, - * where n*ln2_hi is always exact for |n| < 2000. - * - * Special cases: - * log(x) is NaN with signal if x < 0 (including -INF) ; - * log(+INF) is +INF; log(0) is -INF with signal; - * log(NaN) is that NaN with no signal. - * - * Accuracy: - * according to an error analysis, the error is always less than - * 1 ulp (unit in the last place). - * - * Constants: - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */ -ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */ -two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */ -Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ -Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ -Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ -Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ -Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ -Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ -Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ - -static double zero = 0.0; - -#ifdef __STDC__ - double __ieee754_log(double x) -#else - double __ieee754_log(x) - double x; -#endif -{ - fd_twoints u; - double hfsq,f,s,z,R,w,t1,t2,dk; - int k,hx,i,j; - unsigned lx; - - u.d = x; - hx = __HI(u); /* high word of x */ - lx = __LO(u); /* low word of x */ - - k=0; - if (hx < 0x00100000) { /* x < 2**-1022 */ - if (((hx&0x7fffffff)|lx)==0) - return -two54/zero; /* log(+-0)=-inf */ - if (hx<0) return (x-x)/zero; /* log(-#) = NaN */ - k -= 54; x *= two54; /* subnormal number, scale up x */ - u.d = x; - hx = __HI(u); /* high word of x */ - } - if (hx >= 0x7ff00000) return x+x; - k += (hx>>20)-1023; - hx &= 0x000fffff; - i = (hx+0x95f64)&0x100000; - u.d = x; - __HI(u) = hx|(i^0x3ff00000); /* normalize x or x/2 */ - x = u.d; - k += (i>>20); - f = x-1.0; - if((0x000fffff&(2+hx))<3) { /* |f| < 2**-20 */ - if(f==zero) { - if(k==0) return zero; else {dk=(double)k; - return dk*ln2_hi+dk*ln2_lo;} - } - R = f*f*(0.5-0.33333333333333333*f); - if(k==0) return f-R; else {dk=(double)k; - return dk*ln2_hi-((R-dk*ln2_lo)-f);} - } - s = f/(2.0+f); - dk = (double)k; - z = s*s; - i = hx-0x6147a; - w = z*z; - j = 0x6b851-hx; - t1= w*(Lg2+w*(Lg4+w*Lg6)); - t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7))); - i |= j; - R = t2+t1; - if(i>0) { - hfsq=0.5*f*f; - if(k==0) return f-(hfsq-s*(hfsq+R)); else - return dk*ln2_hi-((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f); - } else { - if(k==0) return f-s*(f-R); else - return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f); - } -} diff --git a/lib/javascript/fdlibm/e_log10.c b/lib/javascript/fdlibm/e_log10.c deleted file mode 100644 index 5f88f4b4..00000000 --- a/lib/javascript/fdlibm/e_log10.c +++ /dev/null @@ -1,134 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_log10.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* __ieee754_log10(x) - * Return the base 10 logarithm of x - * - * Method : - * Let log10_2hi = leading 40 bits of log10(2) and - * log10_2lo = log10(2) - log10_2hi, - * ivln10 = 1/log(10) rounded. - * Then - * n = ilogb(x), - * if(n<0) n = n+1; - * x = scalbn(x,-n); - * log10(x) := n*log10_2hi + (n*log10_2lo + ivln10*log(x)) - * - * Note 1: - * To guarantee log10(10**n)=n, where 10**n is normal, the rounding - * mode must set to Round-to-Nearest. - * Note 2: - * [1/log(10)] rounded to 53 bits has error .198 ulps; - * log10 is monotonic at all binary break points. - * - * Special cases: - * log10(x) is NaN with signal if x < 0; - * log10(+INF) is +INF with no signal; log10(0) is -INF with signal; - * log10(NaN) is that NaN with no signal; - * log10(10**N) = N for N=0,1,...,22. - * - * Constants: - * The hexadecimal values are the intended ones for the following constants. - * The decimal values may be used, provided that the compiler will convert - * from decimal to binary accurately enough to produce the hexadecimal values - * shown. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ -ivln10 = 4.34294481903251816668e-01, /* 0x3FDBCB7B, 0x1526E50E */ -log10_2hi = 3.01029995663611771306e-01, /* 0x3FD34413, 0x509F6000 */ -log10_2lo = 3.69423907715893078616e-13; /* 0x3D59FEF3, 0x11F12B36 */ - -static double zero = 0.0; - -#ifdef __STDC__ - double __ieee754_log10(double x) -#else - double __ieee754_log10(x) - double x; -#endif -{ - fd_twoints u; - double y,z; - int i,k,hx; - unsigned lx; - - u.d = x; - hx = __HI(u); /* high word of x */ - lx = __LO(u); /* low word of x */ - - k=0; - if (hx < 0x00100000) { /* x < 2**-1022 */ - if (((hx&0x7fffffff)|lx)==0) - return -two54/zero; /* log(+-0)=-inf */ - if (hx<0) return (x-x)/zero; /* log(-#) = NaN */ - k -= 54; x *= two54; /* subnormal number, scale up x */ - u.d = x; - hx = __HI(u); /* high word of x */ - } - if (hx >= 0x7ff00000) return x+x; - k += (hx>>20)-1023; - i = ((unsigned)k&0x80000000)>>31; - hx = (hx&0x000fffff)|((0x3ff-i)<<20); - y = (double)(k+i); - u.d = x; - __HI(u) = hx; - x = u.d; - z = y*log10_2lo + ivln10*__ieee754_log(x); - return z+y*log10_2hi; -} diff --git a/lib/javascript/fdlibm/e_pow.c b/lib/javascript/fdlibm/e_pow.c deleted file mode 100644 index 18c8d069..00000000 --- a/lib/javascript/fdlibm/e_pow.c +++ /dev/null @@ -1,386 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_pow.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* __ieee754_pow(x,y) return x**y - * - * n - * Method: Let x = 2 * (1+f) - * 1. Compute and return log2(x) in two pieces: - * log2(x) = w1 + w2, - * where w1 has 53-24 = 29 bit trailing zeros. - * 2. Perform y*log2(x) = n+y' by simulating muti-precision - * arithmetic, where |y'|<=0.5. - * 3. Return x**y = 2**n*exp(y'*log2) - * - * Special cases: - * 1. (anything) ** 0 is 1 - * 2. (anything) ** 1 is itself - * 3. (anything) ** NAN is NAN - * 4. NAN ** (anything except 0) is NAN - * 5. +-(|x| > 1) ** +INF is +INF - * 6. +-(|x| > 1) ** -INF is +0 - * 7. +-(|x| < 1) ** +INF is +0 - * 8. +-(|x| < 1) ** -INF is +INF - * 9. +-1 ** +-INF is NAN - * 10. +0 ** (+anything except 0, NAN) is +0 - * 11. -0 ** (+anything except 0, NAN, odd integer) is +0 - * 12. +0 ** (-anything except 0, NAN) is +INF - * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF - * 14. -0 ** (odd integer) = -( +0 ** (odd integer) ) - * 15. +INF ** (+anything except 0,NAN) is +INF - * 16. +INF ** (-anything except 0,NAN) is +0 - * 17. -INF ** (anything) = -0 ** (-anything) - * 18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer) - * 19. (-anything except 0 and inf) ** (non-integer) is NAN - * - * Accuracy: - * pow(x,y) returns x**y nearly rounded. In particular - * pow(integer,integer) - * always returns the correct integer provided it is - * representable. - * - * Constants : - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - */ - -#include "fdlibm.h" - -#if defined(_MSC_VER) -/* Microsoft Compiler */ -#pragma warning( disable : 4723 ) /* disables potential divide by 0 warning */ -#endif - -#ifdef __STDC__ -static const double -#else -static double -#endif -bp[] = {1.0, 1.5,}, -dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */ -dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */ -zero = 0.0, -one = 1.0, -two = 2.0, -two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */ -really_big = 1.0e300, -tiny = 1.0e-300, - /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */ -L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */ -L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */ -L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */ -L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */ -L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */ -L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */ -P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ -P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ -P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ -P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ -P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */ -lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */ -lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */ -lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */ -ovt = 8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */ -cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */ -cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */ -cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/ -ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */ -ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/ -ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/ - -#ifdef __STDC__ - double __ieee754_pow(double x, double y) -#else - double __ieee754_pow(x,y) - double x, y; -#endif -{ - fd_twoints ux, uy, uz; - double y1,t1,p_h,t,z,ax; - double z_h,z_l,p_l; - double t2,r,s,u,v,w; - int i,j,k,yisint,n; - int hx,hy,ix,iy; - unsigned lx,ly; - - ux.d = x; uy.d = y; - hx = __HI(ux); lx = __LO(ux); - hy = __HI(uy); ly = __LO(uy); - ix = hx&0x7fffffff; iy = hy&0x7fffffff; - - /* y==zero: x**0 = 1 */ - if((iy|ly)==0) return one; - - /* +-NaN return x+y */ - if(ix > 0x7ff00000 || ((ix==0x7ff00000)&&(lx!=0)) || - iy > 0x7ff00000 || ((iy==0x7ff00000)&&(ly!=0))) - return x+y; - - /* determine if y is an odd int when x < 0 - * yisint = 0 ... y is not an integer - * yisint = 1 ... y is an odd int - * yisint = 2 ... y is an even int - */ - yisint = 0; - if(hx<0) { - if(iy>=0x43400000) yisint = 2; /* even integer y */ - else if(iy>=0x3ff00000) { - k = (iy>>20)-0x3ff; /* exponent */ - if(k>20) { - j = ly>>(52-k); - if((j<<(52-k))==(int)ly) yisint = 2-(j&1); - } else if(ly==0) { - j = iy>>(20-k); - if((j<<(20-k))==iy) yisint = 2-(j&1); - } - } - } - - /* special value of y */ - if(ly==0) { - if (iy==0x7ff00000) { /* y is +-inf */ - if(((ix-0x3ff00000)|lx)==0) -#ifdef _WIN32 -/* VC++ optimizer reduces y - y to 0 */ - return y / y; -#else - return y - y; /* inf**+-1 is NaN */ -#endif - else if (ix >= 0x3ff00000)/* (|x|>1)**+-inf = inf,0 */ - return (hy>=0)? y: zero; - else /* (|x|<1)**-,+inf = inf,0 */ - return (hy<0)?-y: zero; - } - if(iy==0x3ff00000) { /* y is +-1 */ - if(hy<0) return one/x; else return x; - } - if(hy==0x40000000) return x*x; /* y is 2 */ - if(hy==0x3fe00000) { /* y is 0.5 */ - if(hx>=0) /* x >= +0 */ - return fd_sqrt(x); - } - } - - ax = fd_fabs(x); - /* special value of x */ - if(lx==0) { - if(ix==0x7ff00000||ix==0||ix==0x3ff00000){ - z = ax; /*x is +-0,+-inf,+-1*/ - if(hy<0) z = one/z; /* z = (1/|x|) */ - if(hx<0) { - if(((ix-0x3ff00000)|yisint)==0) { - z = (z-z)/(z-z); /* (-1)**non-int is NaN */ - } else if(yisint==1) { -#ifdef HPUX - uz.d = z; - __HI(uz) ^= 1<<31; /* some HPUXes cannot negate 0.. */ - z = uz.d; -#else - z = -z; /* (x<0)**odd = -(|x|**odd) */ -#endif - } - } - return z; - } - } - - /* (x<0)**(non-int) is NaN */ - if((((hx>>31)+1)|yisint)==0) return (x-x)/(x-x); - - /* |y| is really_big */ - if(iy>0x41e00000) { /* if |y| > 2**31 */ - if(iy>0x43f00000){ /* if |y| > 2**64, must o/uflow */ - if(ix<=0x3fefffff) return (hy<0)? really_big*really_big:tiny*tiny; - if(ix>=0x3ff00000) return (hy>0)? really_big*really_big:tiny*tiny; - } - /* over/underflow if x is not close to one */ - if(ix<0x3fefffff) return (hy<0)? really_big*really_big:tiny*tiny; - if(ix>0x3ff00000) return (hy>0)? really_big*really_big:tiny*tiny; - /* now |1-x| is tiny <= 2**-20, suffice to compute - log(x) by x-x^2/2+x^3/3-x^4/4 */ - t = x-1; /* t has 20 trailing zeros */ - w = (t*t)*(0.5-t*(0.3333333333333333333333-t*0.25)); - u = ivln2_h*t; /* ivln2_h has 21 sig. bits */ - v = t*ivln2_l-w*ivln2; - t1 = u+v; - uz.d = t1; - __LO(uz) = 0; - t1 = uz.d; - t2 = v-(t1-u); - } else { - double s_h,t_h; - double s2,s_l,t_l; - n = 0; - /* take care subnormal number */ - if(ix<0x00100000) - {ax *= two53; n -= 53; uz.d = ax; ix = __HI(uz); } - n += ((ix)>>20)-0x3ff; - j = ix&0x000fffff; - /* determine interval */ - ix = j|0x3ff00000; /* normalize ix */ - if(j<=0x3988E) k=0; /* |x|>1)|0x20000000)+0x00080000+(k<<18); - t_h = uz.d; - t_l = ax - (t_h-bp[k]); - s_l = v*((u-s_h*t_h)-s_h*t_l); - /* compute log(ax) */ - s2 = s*s; - r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6))))); - r += s_l*(s_h+s); - s2 = s_h*s_h; - t_h = 3.0+s2+r; - uz.d = t_h; - __LO(uz) = 0; - t_h = uz.d; - t_l = r-((t_h-3.0)-s2); - /* u+v = s*(1+...) */ - u = s_h*t_h; - v = s_l*t_h+t_l*s; - /* 2/(3log2)*(s+...) */ - p_h = u+v; - uz.d = p_h; - __LO(uz) = 0; - p_h = uz.d; - p_l = v-(p_h-u); - z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */ - z_l = cp_l*p_h+p_l*cp+dp_l[k]; - /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */ - t = (double)n; - t1 = (((z_h+z_l)+dp_h[k])+t); - uz.d = t1; - __LO(uz) = 0; - t1 = uz.d; - t2 = z_l-(((t1-t)-dp_h[k])-z_h); - } - - s = one; /* s (sign of result -ve**odd) = -1 else = 1 */ - if((((hx>>31)+1)|(yisint-1))==0) s = -one;/* (-ve)**(odd int) */ - - /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ - y1 = y; - uy.d = y1; - __LO(uy) = 0; - y1 = uy.d; - p_l = (y-y1)*t1+y*t2; - p_h = y1*t1; - z = p_l+p_h; - uz.d = z; - j = __HI(uz); - i = __LO(uz); - - if (j>=0x40900000) { /* z >= 1024 */ - if(((j-0x40900000)|i)!=0) /* if z > 1024 */ - return s*really_big*really_big; /* overflow */ - else { - if(p_l+ovt>z-p_h) return s*really_big*really_big; /* overflow */ - } - } else if((j&0x7fffffff)>=0x4090cc00 ) { /* z <= -1075 */ - if(((j-0xc090cc00)|i)!=0) /* z < -1075 */ - return s*tiny*tiny; /* underflow */ - else { - if(p_l<=z-p_h) return s*tiny*tiny; /* underflow */ - } - } - /* - * compute 2**(p_h+p_l) - */ - i = j&0x7fffffff; - k = (i>>20)-0x3ff; - n = 0; - if(i>0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */ - n = j+(0x00100000>>(k+1)); - k = ((n&0x7fffffff)>>20)-0x3ff; /* new k for n */ - t = zero; - uz.d = t; - __HI(uz) = (n&~(0x000fffff>>k)); - t = uz.d; - n = ((n&0x000fffff)|0x00100000)>>(20-k); - if(j<0) n = -n; - p_h -= t; - } - t = p_l+p_h; - uz.d = t; - __LO(uz) = 0; - t = uz.d; - u = t*lg2_h; - v = (p_l-(t-p_h))*lg2+t*lg2_l; - z = u+v; - w = v-(z-u); - t = z*z; - t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))); - r = (z*t1)/(t1-two)-(w+z*w); - z = one-(r-z); - uz.d = z; - j = __HI(uz); - j += (n<<20); - if((j>>20)<=0) z = fd_scalbn(z,n); /* subnormal output */ - else { uz.d = z; __HI(uz) += (n<<20); z = uz.d; } - return s*z; -} diff --git a/lib/javascript/fdlibm/e_rem_pio2.c b/lib/javascript/fdlibm/e_rem_pio2.c deleted file mode 100644 index c9d26187..00000000 --- a/lib/javascript/fdlibm/e_rem_pio2.c +++ /dev/null @@ -1,222 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_rem_pio2.c 1.4 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -/* __ieee754_rem_pio2(x,y) - * - * return the remainder of x rem pi/2 in y[0]+y[1] - * use __kernel_rem_pio2() - */ - -#include "fdlibm.h" - -/* - * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi - */ -#ifdef __STDC__ -static const int two_over_pi[] = { -#else -static int two_over_pi[] = { -#endif -0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, -0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, -0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, -0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41, -0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8, -0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF, -0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, -0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, -0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, -0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, -0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B, -}; - -#ifdef __STDC__ -static const int npio2_hw[] = { -#else -static int npio2_hw[] = { -#endif -0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C, -0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C, -0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A, -0x403DD85A, 0x403F6A7A, 0x40407E4C, 0x4041475C, 0x4042106C, 0x4042D97C, -0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, 0x4046C6CB, 0x40478FDB, -0x404858EB, 0x404921FB, -}; - -/* - * invpio2: 53 bits of 2/pi - * pio2_1: first 33 bit of pi/2 - * pio2_1t: pi/2 - pio2_1 - * pio2_2: second 33 bit of pi/2 - * pio2_2t: pi/2 - (pio2_1+pio2_2) - * pio2_3: third 33 bit of pi/2 - * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) - */ - -#ifdef __STDC__ -static const double -#else -static double -#endif -zero = 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ -half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ -two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */ -invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ -pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */ -pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */ -pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */ -pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */ -pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */ -pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */ - -#ifdef __STDC__ - int __ieee754_rem_pio2(double x, double *y) -#else - int __ieee754_rem_pio2(x,y) - double x,y[]; -#endif -{ - fd_twoints u, ux, uz; - double z = 0; - double w,t,r,fn; - double tx[3]; - int e0,i,j,nx,n,ix,hx; - - u.d = x; - hx = __HI(u); /* high word of x */ - ix = hx&0x7fffffff; - if(ix<=0x3fe921fb) /* |x| ~<= pi/4 , no need for reduction */ - {y[0] = x; y[1] = 0; return 0;} - if(ix<0x4002d97c) { /* |x| < 3pi/4, special case with n=+-1 */ - if(hx>0) { - z = x - pio2_1; - if(ix!=0x3ff921fb) { /* 33+53 bit pi is good enough */ - y[0] = z - pio2_1t; - y[1] = (z-y[0])-pio2_1t; - } else { /* near pi/2, use 33+33+53 bit pi */ - z -= pio2_2; - y[0] = z - pio2_2t; - y[1] = (z-y[0])-pio2_2t; - } - return 1; - } else { /* negative x */ - z = x + pio2_1; - if(ix!=0x3ff921fb) { /* 33+53 bit pi is good enough */ - y[0] = z + pio2_1t; - y[1] = (z-y[0])+pio2_1t; - } else { /* near pi/2, use 33+33+53 bit pi */ - z += pio2_2; - y[0] = z + pio2_2t; - y[1] = (z-y[0])+pio2_2t; - } - return -1; - } - } - if(ix<=0x413921fb) { /* |x| ~<= 2^19*(pi/2), medium size */ - t = fd_fabs(x); - n = (int) (t*invpio2+half); - fn = (double)n; - r = t-fn*pio2_1; - w = fn*pio2_1t; /* 1st round good to 85 bit */ - if(n<32&&ix!=npio2_hw[n-1]) { - y[0] = r-w; /* quick check no cancellation */ - } else { - j = ix>>20; - y[0] = r-w; - u.d = y[0]; - i = j-(((__HI(u))>>20)&0x7ff); - if(i>16) { /* 2nd iteration needed, good to 118 */ - t = r; - w = fn*pio2_2; - r = t-w; - w = fn*pio2_2t-((t-r)-w); - y[0] = r-w; - u.d = y[0]; - i = j-(((__HI(u))>>20)&0x7ff); - if(i>49) { /* 3rd iteration need, 151 bits acc */ - t = r; /* will cover all possible cases */ - w = fn*pio2_3; - r = t-w; - w = fn*pio2_3t-((t-r)-w); - y[0] = r-w; - } - } - } - y[1] = (r-y[0])-w; - if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;} - else return n; - } - /* - * all other (large) arguments - */ - if(ix>=0x7ff00000) { /* x is inf or NaN */ - y[0]=y[1]=x-x; return 0; - } - /* set z = scalbn(|x|,ilogb(x)-23) */ - ux.d = x; uz.d = z; - __LO(uz) = __LO(ux); - z = uz.d; - e0 = (ix>>20)-1046; /* e0 = ilogb(z)-23; */ - uz.d = z; - __HI(uz) = ix - (e0<<20); - z = uz.d; - for(i=0;i<2;i++) { - tx[i] = (double)((int)(z)); - z = (z-tx[i])*two24; - } - tx[2] = z; - nx = 3; - while(tx[nx-1]==zero) nx--; /* skip zero term */ - n = __kernel_rem_pio2(tx,y,e0,nx,2,two_over_pi); - if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;} - return n; -} diff --git a/lib/javascript/fdlibm/e_remainder.c b/lib/javascript/fdlibm/e_remainder.c deleted file mode 100644 index de40f0c2..00000000 --- a/lib/javascript/fdlibm/e_remainder.c +++ /dev/null @@ -1,120 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_remainder.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* __ieee754_remainder(x,p) - * Return : - * returns x REM p = x - [x/p]*p as if in infinite - * precise arithmetic, where [x/p] is the (infinite bit) - * integer nearest x/p (in half way case choose the even one). - * Method : - * Based on fmod() return x-[x/p]chopped*p exactlp. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double zero = 0.0; -#else -static double zero = 0.0; -#endif - - -#ifdef __STDC__ - double __ieee754_remainder(double x, double p) -#else - double __ieee754_remainder(x,p) - double x,p; -#endif -{ - fd_twoints u; - int hx,hp; - unsigned sx,lx,lp; - double p_half; - - u.d = x; - hx = __HI(u); /* high word of x */ - lx = __LO(u); /* low word of x */ - u.d = p; - hp = __HI(u); /* high word of p */ - lp = __LO(u); /* low word of p */ - sx = hx&0x80000000; - hp &= 0x7fffffff; - hx &= 0x7fffffff; - - /* purge off exception values */ - if((hp|lp)==0) return (x*p)/(x*p); /* p = 0 */ - if((hx>=0x7ff00000)|| /* x not finite */ - ((hp>=0x7ff00000)&& /* p is NaN */ - (((hp-0x7ff00000)|lp)!=0))) - return (x*p)/(x*p); - - - if (hp<=0x7fdfffff) x = __ieee754_fmod(x,p+p); /* now x < 2p */ - if (((hx-hp)|(lx-lp))==0) return zero*x; - x = fd_fabs(x); - p = fd_fabs(p); - if (hp<0x00200000) { - if(x+x>p) { - x-=p; - if(x+x>=p) x -= p; - } - } else { - p_half = 0.5*p; - if(x>p_half) { - x-=p; - if(x>=p_half) x -= p; - } - } - u.d = x; - __HI(u) ^= sx; - x = u.d; - return x; -} diff --git a/lib/javascript/fdlibm/e_scalb.c b/lib/javascript/fdlibm/e_scalb.c deleted file mode 100644 index 621704ea..00000000 --- a/lib/javascript/fdlibm/e_scalb.c +++ /dev/null @@ -1,89 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_scalb.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * __ieee754_scalb(x, fn) is provide for - * passing various standard test suite. One - * should use scalbn() instead. - */ - -#include "fdlibm.h" - -#ifdef _SCALB_INT -#ifdef __STDC__ - double __ieee754_scalb(double x, int fn) -#else - double __ieee754_scalb(x,fn) - double x; int fn; -#endif -#else -#ifdef __STDC__ - double __ieee754_scalb(double x, double fn) -#else - double __ieee754_scalb(x,fn) - double x, fn; -#endif -#endif -{ -#ifdef _SCALB_INT - return fd_scalbn(x,fn); -#else - if (fd_isnan(x)||fd_isnan(fn)) return x*fn; - if (!fd_finite(fn)) { - if(fn>0.0) return x*fn; - else return x/(-fn); - } - if (fd_rint(fn)!=fn) return (fn-fn)/(fn-fn); - if ( fn > 65000.0) return fd_scalbn(x, 65000); - if (-fn > 65000.0) return fd_scalbn(x,-65000); - return fd_scalbn(x,(int)fn); -#endif -} diff --git a/lib/javascript/fdlibm/e_sinh.c b/lib/javascript/fdlibm/e_sinh.c deleted file mode 100644 index 98ab9b5a..00000000 --- a/lib/javascript/fdlibm/e_sinh.c +++ /dev/null @@ -1,122 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_sinh.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* __ieee754_sinh(x) - * Method : - * mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2 - * 1. Replace x by |x| (sinh(-x) = -sinh(x)). - * 2. - * E + E/(E+1) - * 0 <= x <= 22 : sinh(x) := --------------, E=expm1(x) - * 2 - * - * 22 <= x <= lnovft : sinh(x) := exp(x)/2 - * lnovft <= x <= ln2ovft: sinh(x) := exp(x/2)/2 * exp(x/2) - * ln2ovft < x : sinh(x) := x*shuge (overflow) - * - * Special cases: - * sinh(x) is |x| if x is +INF, -INF, or NaN. - * only sinh(0)=0 is exact for finite x. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double one = 1.0, shuge = 1.0e307; -#else -static double one = 1.0, shuge = 1.0e307; -#endif - -#ifdef __STDC__ - double __ieee754_sinh(double x) -#else - double __ieee754_sinh(x) - double x; -#endif -{ - fd_twoints u; - double t,w,h; - int ix,jx; - unsigned lx; - - /* High word of |x|. */ - u.d = x; - jx = __HI(u); - ix = jx&0x7fffffff; - - /* x is INF or NaN */ - if(ix>=0x7ff00000) return x+x; - - h = 0.5; - if (jx<0) h = -h; - /* |x| in [0,22], return sign(x)*0.5*(E+E/(E+1))) */ - if (ix < 0x40360000) { /* |x|<22 */ - if (ix<0x3e300000) /* |x|<2**-28 */ - if(shuge+x>one) return x;/* sinh(tiny) = tiny with inexact */ - t = fd_expm1(fd_fabs(x)); - if(ix<0x3ff00000) return h*(2.0*t-t*t/(t+one)); - return h*(t+t/(t+one)); - } - - /* |x| in [22, log(maxdouble)] return 0.5*exp(|x|) */ - if (ix < 0x40862E42) return h*__ieee754_exp(fd_fabs(x)); - - /* |x| in [log(maxdouble), overflowthresold] */ - lx = *( (((*(unsigned*)&one)>>29)) + (unsigned*)&x); - if (ix<0x408633CE || (ix==0x408633ce)&&(lx<=(unsigned)0x8fb9f87d)) { - w = __ieee754_exp(0.5*fd_fabs(x)); - t = h*w; - return t*w; - } - - /* |x| > overflowthresold, sinh(x) overflow */ - return x*shuge; -} diff --git a/lib/javascript/fdlibm/e_sqrt.c b/lib/javascript/fdlibm/e_sqrt.c deleted file mode 100644 index 91802839..00000000 --- a/lib/javascript/fdlibm/e_sqrt.c +++ /dev/null @@ -1,497 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* @(#)e_sqrt.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* __ieee754_sqrt(x) - * Return correctly rounded sqrt. - * ------------------------------------------ - * | Use the hardware sqrt if you have one | - * ------------------------------------------ - * Method: - * Bit by bit method using integer arithmetic. (Slow, but portable) - * 1. Normalization - * Scale x to y in [1,4) with even powers of 2: - * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then - * sqrt(y) = 2^k * sqrt(x) - * 2. Bit by bit computation - * Let q = sqrt(y) truncated to i bit after binary point (q = 1), - * i 0 - * i+1 2 - * s = 2*q , and y = 2 * ( y - q ). (1) - * i i i i - * - * To compute q from q , one checks whether - * i+1 i - * - * -(i+1) 2 - * (q + 2 ) <= y. (2) - * i - * -(i+1) - * If (2) is false, then q = q ; otherwise q = q + 2 . - * i+1 i i+1 i - * - * With some algebric manipulation, it is not difficult to see - * that (2) is equivalent to - * -(i+1) - * s + 2 <= y (3) - * i i - * - * The advantage of (3) is that s and y can be computed by - * i i - * the following recurrence formula: - * if (3) is false - * - * s = s , y = y ; (4) - * i+1 i i+1 i - * - * otherwise, - * -i -(i+1) - * s = s + 2 , y = y - s - 2 (5) - * i+1 i i+1 i i - * - * One may easily use induction to prove (4) and (5). - * Note. Since the left hand side of (3) contain only i+2 bits, - * it does not necessary to do a full (53-bit) comparison - * in (3). - * 3. Final rounding - * After generating the 53 bits result, we compute one more bit. - * Together with the remainder, we can decide whether the - * result is exact, bigger than 1/2ulp, or less than 1/2ulp - * (it will never equal to 1/2ulp). - * The rounding mode can be detected by checking whether - * huge + tiny is equal to huge, and whether huge - tiny is - * equal to huge for some floating point number "huge" and "tiny". - * - * Special cases: - * sqrt(+-0) = +-0 ... exact - * sqrt(inf) = inf - * sqrt(-ve) = NaN ... with invalid signal - * sqrt(NaN) = NaN ... with invalid signal for signaling NaN - * - * Other methods : see the appended file at the end of the program below. - *--------------- - */ - -#include "fdlibm.h" - -#if defined(_MSC_VER) -/* Microsoft Compiler */ -#pragma warning( disable : 4723 ) /* disables potential divide by 0 warning */ -#endif - -#ifdef __STDC__ -static const double one = 1.0, tiny=1.0e-300; -#else -static double one = 1.0, tiny=1.0e-300; -#endif - -#ifdef __STDC__ - double __ieee754_sqrt(double x) -#else - double __ieee754_sqrt(x) - double x; -#endif -{ - fd_twoints u; - double z; - int sign = (int)0x80000000; - unsigned r,t1,s1,ix1,q1; - int ix0,s0,q,m,t,i; - - u.d = x; - ix0 = __HI(u); /* high word of x */ - ix1 = __LO(u); /* low word of x */ - - /* take care of Inf and NaN */ - if((ix0&0x7ff00000)==0x7ff00000) { - return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf - sqrt(-inf)=sNaN */ - } - /* take care of zero */ - if(ix0<=0) { - if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */ - else if(ix0<0) - return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ - } - /* normalize x */ - m = (ix0>>20); - if(m==0) { /* subnormal x */ - while(ix0==0) { - m -= 21; - ix0 |= (ix1>>11); ix1 <<= 21; - } - for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1; - m -= i-1; - ix0 |= (ix1>>(32-i)); - ix1 <<= i; - } - m -= 1023; /* unbias exponent */ - ix0 = (ix0&0x000fffff)|0x00100000; - if(m&1){ /* odd m, double x to make it even */ - ix0 += ix0 + ((ix1&sign)>>31); - ix1 += ix1; - } - m >>= 1; /* m = [m/2] */ - - /* generate sqrt(x) bit by bit */ - ix0 += ix0 + ((ix1&sign)>>31); - ix1 += ix1; - q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */ - r = 0x00200000; /* r = moving bit from right to left */ - - while(r!=0) { - t = s0+r; - if(t<=ix0) { - s0 = t+r; - ix0 -= t; - q += r; - } - ix0 += ix0 + ((ix1&sign)>>31); - ix1 += ix1; - r>>=1; - } - - r = sign; - while(r!=0) { - t1 = s1+r; - t = s0; - if((t>31); - ix1 += ix1; - r>>=1; - } - - /* use floating add to find out rounding direction */ - if((ix0|ix1)!=0) { - z = one-tiny; /* trigger inexact flag */ - if (z>=one) { - z = one+tiny; - if (q1==(unsigned)0xffffffff) { q1=0; q += 1;} - else if (z>one) { - if (q1==(unsigned)0xfffffffe) q+=1; - q1+=2; - } else - q1 += (q1&1); - } - } - ix0 = (q>>1)+0x3fe00000; - ix1 = q1>>1; - if ((q&1)==1) ix1 |= sign; - ix0 += (m <<20); - u.d = z; - __HI(u) = ix0; - __LO(u) = ix1; - z = u.d; - return z; -} - -/* -Other methods (use floating-point arithmetic) -------------- -(This is a copy of a drafted paper by Prof W. Kahan -and K.C. Ng, written in May, 1986) - - Two algorithms are given here to implement sqrt(x) - (IEEE double precision arithmetic) in software. - Both supply sqrt(x) correctly rounded. The first algorithm (in - Section A) uses newton iterations and involves four divisions. - The second one uses reciproot iterations to avoid division, but - requires more multiplications. Both algorithms need the ability - to chop results of arithmetic operations instead of round them, - and the INEXACT flag to indicate when an arithmetic operation - is executed exactly with no roundoff error, all part of the - standard (IEEE 754-1985). The ability to perform shift, add, - subtract and logical AND operations upon 32-bit words is needed - too, though not part of the standard. - -A. sqrt(x) by Newton Iteration - - (1) Initial approximation - - Let x0 and x1 be the leading and the trailing 32-bit words of - a floating point number x (in IEEE double format) respectively - - 1 11 52 ...widths - ------------------------------------------------------ - x: |s| e | f | - ------------------------------------------------------ - msb lsb msb lsb ...order - - - ------------------------ ------------------------ - x0: |s| e | f1 | x1: | f2 | - ------------------------ ------------------------ - - By performing shifts and subtracts on x0 and x1 (both regarded - as integers), we obtain an 8-bit approximation of sqrt(x) as - follows. - - k := (x0>>1) + 0x1ff80000; - y0 := k - T1[31&(k>>15)]. ... y ~ sqrt(x) to 8 bits - Here k is a 32-bit integer and T1[] is an integer array containing - correction terms. Now magically the floating value of y (y's - leading 32-bit word is y0, the value of its trailing word is 0) - approximates sqrt(x) to almost 8-bit. - - Value of T1: - static int T1[32]= { - 0, 1024, 3062, 5746, 9193, 13348, 18162, 23592, - 29598, 36145, 43202, 50740, 58733, 67158, 75992, 85215, - 83599, 71378, 60428, 50647, 41945, 34246, 27478, 21581, - 16499, 12183, 8588, 5674, 3403, 1742, 661, 130,}; - - (2) Iterative refinement - - Apply Heron's rule three times to y, we have y approximates - sqrt(x) to within 1 ulp (Unit in the Last Place): - - y := (y+x/y)/2 ... almost 17 sig. bits - y := (y+x/y)/2 ... almost 35 sig. bits - y := y-(y-x/y)/2 ... within 1 ulp - - - Remark 1. - Another way to improve y to within 1 ulp is: - - y := (y+x/y) ... almost 17 sig. bits to 2*sqrt(x) - y := y - 0x00100006 ... almost 18 sig. bits to sqrt(x) - - 2 - (x-y )*y - y := y + 2* ---------- ...within 1 ulp - 2 - 3y + x - - - This formula has one division fewer than the one above; however, - it requires more multiplications and additions. Also x must be - scaled in advance to avoid spurious overflow in evaluating the - expression 3y*y+x. Hence it is not recommended uless division - is slow. If division is very slow, then one should use the - reciproot algorithm given in section B. - - (3) Final adjustment - - By twiddling y's last bit it is possible to force y to be - correctly rounded according to the prevailing rounding mode - as follows. Let r and i be copies of the rounding mode and - inexact flag before entering the square root program. Also we - use the expression y+-ulp for the next representable floating - numbers (up and down) of y. Note that y+-ulp = either fixed - point y+-1, or multiply y by nextafter(1,+-inf) in chopped - mode. - - I := FALSE; ... reset INEXACT flag I - R := RZ; ... set rounding mode to round-toward-zero - z := x/y; ... chopped quotient, possibly inexact - If(not I) then { ... if the quotient is exact - if(z=y) { - I := i; ... restore inexact flag - R := r; ... restore rounded mode - return sqrt(x):=y. - } else { - z := z - ulp; ... special rounding - } - } - i := TRUE; ... sqrt(x) is inexact - If (r=RN) then z=z+ulp ... rounded-to-nearest - If (r=RP) then { ... round-toward-+inf - y = y+ulp; z=z+ulp; - } - y := y+z; ... chopped sum - y0:=y0-0x00100000; ... y := y/2 is correctly rounded. - I := i; ... restore inexact flag - R := r; ... restore rounded mode - return sqrt(x):=y. - - (4) Special cases - - Square root of +inf, +-0, or NaN is itself; - Square root of a negative number is NaN with invalid signal. - - -B. sqrt(x) by Reciproot Iteration - - (1) Initial approximation - - Let x0 and x1 be the leading and the trailing 32-bit words of - a floating point number x (in IEEE double format) respectively - (see section A). By performing shifs and subtracts on x0 and y0, - we obtain a 7.8-bit approximation of 1/sqrt(x) as follows. - - k := 0x5fe80000 - (x0>>1); - y0:= k - T2[63&(k>>14)]. ... y ~ 1/sqrt(x) to 7.8 bits - - Here k is a 32-bit integer and T2[] is an integer array - containing correction terms. Now magically the floating - value of y (y's leading 32-bit word is y0, the value of - its trailing word y1 is set to zero) approximates 1/sqrt(x) - to almost 7.8-bit. - - Value of T2: - static int T2[64]= { - 0x1500, 0x2ef8, 0x4d67, 0x6b02, 0x87be, 0xa395, 0xbe7a, 0xd866, - 0xf14a, 0x1091b,0x11fcd,0x13552,0x14999,0x15c98,0x16e34,0x17e5f, - 0x18d03,0x19a01,0x1a545,0x1ae8a,0x1b5c4,0x1bb01,0x1bfde,0x1c28d, - 0x1c2de,0x1c0db,0x1ba73,0x1b11c,0x1a4b5,0x1953d,0x18266,0x16be0, - 0x1683e,0x179d8,0x18a4d,0x19992,0x1a789,0x1b445,0x1bf61,0x1c989, - 0x1d16d,0x1d77b,0x1dddf,0x1e2ad,0x1e5bf,0x1e6e8,0x1e654,0x1e3cd, - 0x1df2a,0x1d635,0x1cb16,0x1be2c,0x1ae4e,0x19bde,0x1868e,0x16e2e, - 0x1527f,0x1334a,0x11051,0xe951, 0xbe01, 0x8e0d, 0x5924, 0x1edd,}; - - (2) Iterative refinement - - Apply Reciproot iteration three times to y and multiply the - result by x to get an approximation z that matches sqrt(x) - to about 1 ulp. To be exact, we will have - -1ulp < sqrt(x)-z<1.0625ulp. - - ... set rounding mode to Round-to-nearest - y := y*(1.5-0.5*x*y*y) ... almost 15 sig. bits to 1/sqrt(x) - y := y*((1.5-2^-30)+0.5*x*y*y)... about 29 sig. bits to 1/sqrt(x) - ... special arrangement for better accuracy - z := x*y ... 29 bits to sqrt(x), with z*y<1 - z := z + 0.5*z*(1-z*y) ... about 1 ulp to sqrt(x) - - Remark 2. The constant 1.5-2^-30 is chosen to bias the error so that - (a) the term z*y in the final iteration is always less than 1; - (b) the error in the final result is biased upward so that - -1 ulp < sqrt(x) - z < 1.0625 ulp - instead of |sqrt(x)-z|<1.03125ulp. - - (3) Final adjustment - - By twiddling y's last bit it is possible to force y to be - correctly rounded according to the prevailing rounding mode - as follows. Let r and i be copies of the rounding mode and - inexact flag before entering the square root program. Also we - use the expression y+-ulp for the next representable floating - numbers (up and down) of y. Note that y+-ulp = either fixed - point y+-1, or multiply y by nextafter(1,+-inf) in chopped - mode. - - R := RZ; ... set rounding mode to round-toward-zero - switch(r) { - case RN: ... round-to-nearest - if(x<= z*(z-ulp)...chopped) z = z - ulp; else - if(x<= z*(z+ulp)...chopped) z = z; else z = z+ulp; - break; - case RZ:case RM: ... round-to-zero or round-to--inf - R:=RP; ... reset rounding mod to round-to-+inf - if(x=(z+ulp)*(z+ulp) ...rounded up) z = z+ulp; - break; - case RP: ... round-to-+inf - if(x>(z+ulp)*(z+ulp)...chopped) z = z+2*ulp; else - if(x>z*z ...chopped) z = z+ulp; - break; - } - - Remark 3. The above comparisons can be done in fixed point. For - example, to compare x and w=z*z chopped, it suffices to compare - x1 and w1 (the trailing parts of x and w), regarding them as - two's complement integers. - - ...Is z an exact square root? - To determine whether z is an exact square root of x, let z1 be the - trailing part of z, and also let x0 and x1 be the leading and - trailing parts of x. - - If ((z1&0x03ffffff)!=0) ... not exact if trailing 26 bits of z!=0 - I := 1; ... Raise Inexact flag: z is not exact - else { - j := 1 - [(x0>>20)&1] ... j = logb(x) mod 2 - k := z1 >> 26; ... get z's 25-th and 26-th - fraction bits - I := i or (k&j) or ((k&(j+j+1))!=(x1&3)); - } - R:= r ... restore rounded mode - return sqrt(x):=z. - - If multiplication is cheaper then the foregoing red tape, the - Inexact flag can be evaluated by - - I := i; - I := (z*z!=x) or I. - - Note that z*z can overwrite I; this value must be sensed if it is - True. - - Remark 4. If z*z = x exactly, then bit 25 to bit 0 of z1 must be - zero. - - -------------------- - z1: | f2 | - -------------------- - bit 31 bit 0 - - Further more, bit 27 and 26 of z1, bit 0 and 1 of x1, and the odd - or even of logb(x) have the following relations: - - ------------------------------------------------- - bit 27,26 of z1 bit 1,0 of x1 logb(x) - ------------------------------------------------- - 00 00 odd and even - 01 01 even - 10 10 odd - 10 00 even - 11 01 even - ------------------------------------------------- - - (4) Special cases (see (4) of Section A). - - */ - diff --git a/lib/javascript/fdlibm/fdlibm.h b/lib/javascript/fdlibm/fdlibm.h deleted file mode 100644 index e623be56..00000000 --- a/lib/javascript/fdlibm/fdlibm.h +++ /dev/null @@ -1,273 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)fdlibm.h 1.5 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* Modified defines start here.. */ -#undef __LITTLE_ENDIAN - -#ifdef _WIN32 -#define huge myhuge -#define __LITTLE_ENDIAN -#endif - -#ifdef XP_OS2 -#define __LITTLE_ENDIAN -#endif - -#if defined(linux) && (defined(__i386__) || defined(__x86_64__) || defined(__ia64) || (defined(__mips) && defined(__MIPSEL__))) -#define __LITTLE_ENDIAN -#endif - -/* End here. The rest is the standard file. */ - -#ifdef SOLARIS /* special setup for Sun test regime */ -#if defined(i386) || defined(i486) || \ - defined(intel) || defined(x86) || defined(i86pc) -#define __LITTLE_ENDIAN -#endif -#endif - -typedef union { -#ifdef __LITTLE_ENDIAN - struct { int lo, hi; } ints; -#else - struct { int hi, lo; } ints; -#endif - double d; -} fd_twoints; - -#define __HI(x) x.ints.hi -#define __LO(x) x.ints.lo - -#undef __P -#ifdef __STDC__ -#define __P(p) p -#else -#define __P(p) () -#endif - -/* - * ANSI/POSIX - */ - -extern int signgam; - -#define MAXFLOAT ((float)3.40282346638528860e+38) - -enum fdversion {fdlibm_ieee = -1, fdlibm_svid, fdlibm_xopen, fdlibm_posix}; - -#define _LIB_VERSION_TYPE enum fdversion -#define _LIB_VERSION _fdlib_version - -/* if global variable _LIB_VERSION is not desirable, one may - * change the following to be a constant by: - * #define _LIB_VERSION_TYPE const enum version - * In that case, after one initializes the value _LIB_VERSION (see - * s_lib_version.c) during compile time, it cannot be modified - * in the middle of a program - */ -extern _LIB_VERSION_TYPE _LIB_VERSION; - -#define _IEEE_ fdlibm_ieee -#define _SVID_ fdlibm_svid -#define _XOPEN_ fdlibm_xopen -#define _POSIX_ fdlibm_posix - -struct exception { - int type; - char *name; - double arg1; - double arg2; - double retval; -}; - -#define HUGE MAXFLOAT - -/* - * set X_TLOSS = pi*2**52, which is possibly defined in - * (one may replace the following line by "#include ") - */ - -#define X_TLOSS 1.41484755040568800000e+16 - -#define DOMAIN 1 -#define SING 2 -#define OVERFLOW 3 -#define UNDERFLOW 4 -#define TLOSS 5 -#define PLOSS 6 - -/* - * ANSI/POSIX - */ - -extern double fd_acos __P((double)); -extern double fd_asin __P((double)); -extern double fd_atan __P((double)); -extern double fd_atan2 __P((double, double)); -extern double fd_cos __P((double)); -extern double fd_sin __P((double)); -extern double fd_tan __P((double)); - -extern double fd_cosh __P((double)); -extern double fd_sinh __P((double)); -extern double fd_tanh __P((double)); - -extern double fd_exp __P((double)); -extern double fd_frexp __P((double, int *)); -extern double fd_ldexp __P((double, int)); -extern double fd_log __P((double)); -extern double fd_log10 __P((double)); -extern double fd_modf __P((double, double *)); - -extern double fd_pow __P((double, double)); -extern double fd_sqrt __P((double)); - -extern double fd_ceil __P((double)); -extern double fd_fabs __P((double)); -extern double fd_floor __P((double)); -extern double fd_fmod __P((double, double)); - -extern double fd_erf __P((double)); -extern double fd_erfc __P((double)); -extern double fd_gamma __P((double)); -extern double fd_hypot __P((double, double)); -extern int fd_isnan __P((double)); -extern int fd_finite __P((double)); -extern double fd_j0 __P((double)); -extern double fd_j1 __P((double)); -extern double fd_jn __P((int, double)); -extern double fd_lgamma __P((double)); -extern double fd_y0 __P((double)); -extern double fd_y1 __P((double)); -extern double fd_yn __P((int, double)); - -extern double fd_acosh __P((double)); -extern double fd_asinh __P((double)); -extern double fd_atanh __P((double)); -extern double fd_cbrt __P((double)); -extern double fd_logb __P((double)); -extern double fd_nextafter __P((double, double)); -extern double fd_remainder __P((double, double)); -#ifdef _SCALB_INT -extern double fd_scalb __P((double, int)); -#else -extern double fd_scalb __P((double, double)); -#endif - -extern int fd_matherr __P((struct exception *)); - -/* - * IEEE Test Vector - */ -extern double significand __P((double)); - -/* - * Functions callable from C, intended to support IEEE arithmetic. - */ -extern double fd_copysign __P((double, double)); -extern int fd_ilogb __P((double)); -extern double fd_rint __P((double)); -extern double fd_scalbn __P((double, int)); - -/* - * BSD math library entry points - */ -extern double fd_expm1 __P((double)); -extern double fd_log1p __P((double)); - -/* - * Reentrant version of gamma & lgamma; passes signgam back by reference - * as the second argument; user must allocate space for signgam. - */ -#ifdef _REENTRANT -extern double gamma_r __P((double, int *)); -extern double lgamma_r __P((double, int *)); -#endif /* _REENTRANT */ - -/* ieee style elementary functions */ -extern double __ieee754_sqrt __P((double)); -extern double __ieee754_acos __P((double)); -extern double __ieee754_acosh __P((double)); -extern double __ieee754_log __P((double)); -extern double __ieee754_atanh __P((double)); -extern double __ieee754_asin __P((double)); -extern double __ieee754_atan2 __P((double,double)); -extern double __ieee754_exp __P((double)); -extern double __ieee754_cosh __P((double)); -extern double __ieee754_fmod __P((double,double)); -extern double __ieee754_pow __P((double,double)); -extern double __ieee754_lgamma_r __P((double,int *)); -extern double __ieee754_gamma_r __P((double,int *)); -extern double __ieee754_lgamma __P((double)); -extern double __ieee754_gamma __P((double)); -extern double __ieee754_log10 __P((double)); -extern double __ieee754_sinh __P((double)); -extern double __ieee754_hypot __P((double,double)); -extern double __ieee754_j0 __P((double)); -extern double __ieee754_j1 __P((double)); -extern double __ieee754_y0 __P((double)); -extern double __ieee754_y1 __P((double)); -extern double __ieee754_jn __P((int,double)); -extern double __ieee754_yn __P((int,double)); -extern double __ieee754_remainder __P((double,double)); -extern int __ieee754_rem_pio2 __P((double,double*)); -#ifdef _SCALB_INT -extern double __ieee754_scalb __P((double,int)); -#else -extern double __ieee754_scalb __P((double,double)); -#endif - -/* fdlibm kernel function */ -extern double __kernel_standard __P((double,double,int,int*)); -extern double __kernel_sin __P((double,double,int)); -extern double __kernel_cos __P((double,double)); -extern double __kernel_tan __P((double,double,int)); -extern int __kernel_rem_pio2 __P((double*,double*,int,int,int,const int*)); diff --git a/lib/javascript/fdlibm/fdlibm.mak b/lib/javascript/fdlibm/fdlibm.mak deleted file mode 100644 index 436c1c45..00000000 --- a/lib/javascript/fdlibm/fdlibm.mak +++ /dev/null @@ -1,1453 +0,0 @@ -# Microsoft Developer Studio Generated NMAKE File, Format Version 4.20 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Static Library" 0x0104 - -!IF "$(CFG)" == "" -CFG=fdlibm - Win32 Debug -!MESSAGE No configuration specified. Defaulting to fdlibm - Win32 Debug. -!ENDIF - -!IF "$(CFG)" != "fdlibm - Win32 Release" && "$(CFG)" != "fdlibm - Win32 Debug" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE on this makefile -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "fdlibm.mak" CFG="fdlibm - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "fdlibm - Win32 Release" (based on "Win32 (x86) Static Library") -!MESSAGE "fdlibm - Win32 Debug" (based on "Win32 (x86) Static Library") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -!IF "$(OS)" == "Windows_NT" -NULL= -!ELSE -NULL=nul -!ENDIF -################################################################################ -# Begin Project -CPP=cl.exe - -!IF "$(CFG)" == "fdlibm - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "fdlibm__" -# PROP BASE Intermediate_Dir "fdlibm__" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "fdlibm__" -# PROP Intermediate_Dir "fdlibm__" -# PROP Target_Dir "" -OUTDIR=.\fdlibm__ -INTDIR=.\fdlibm__ - -ALL : "$(OUTDIR)\fdlibm.lib" - -CLEAN : - -@erase "$(INTDIR)\e_acos.obj" - -@erase "$(INTDIR)\e_acosh.obj" - -@erase "$(INTDIR)\e_asin.obj" - -@erase "$(INTDIR)\e_atan2.obj" - -@erase "$(INTDIR)\e_atanh.obj" - -@erase "$(INTDIR)\e_cosh.obj" - -@erase "$(INTDIR)\e_exp.obj" - -@erase "$(INTDIR)\e_fmod.obj" - -@erase "$(INTDIR)\e_gamma.obj" - -@erase "$(INTDIR)\e_gamma_r.obj" - -@erase "$(INTDIR)\e_hypot.obj" - -@erase "$(INTDIR)\e_j0.obj" - -@erase "$(INTDIR)\e_j1.obj" - -@erase "$(INTDIR)\e_jn.obj" - -@erase "$(INTDIR)\e_lgamma.obj" - -@erase "$(INTDIR)\e_lgamma_r.obj" - -@erase "$(INTDIR)\e_log.obj" - -@erase "$(INTDIR)\e_log10.obj" - -@erase "$(INTDIR)\e_pow.obj" - -@erase "$(INTDIR)\e_rem_pio2.obj" - -@erase "$(INTDIR)\e_remainder.obj" - -@erase "$(INTDIR)\e_scalb.obj" - -@erase "$(INTDIR)\e_sinh.obj" - -@erase "$(INTDIR)\e_sqrt.obj" - -@erase "$(INTDIR)\k_cos.obj" - -@erase "$(INTDIR)\k_rem_pio2.obj" - -@erase "$(INTDIR)\k_sin.obj" - -@erase "$(INTDIR)\k_standard.obj" - -@erase "$(INTDIR)\k_tan.obj" - -@erase "$(INTDIR)\s_asinh.obj" - -@erase "$(INTDIR)\s_atan.obj" - -@erase "$(INTDIR)\s_cbrt.obj" - -@erase "$(INTDIR)\s_ceil.obj" - -@erase "$(INTDIR)\s_copysign.obj" - -@erase "$(INTDIR)\s_cos.obj" - -@erase "$(INTDIR)\s_erf.obj" - -@erase "$(INTDIR)\s_expm1.obj" - -@erase "$(INTDIR)\s_fabs.obj" - -@erase "$(INTDIR)\s_finite.obj" - -@erase "$(INTDIR)\s_floor.obj" - -@erase "$(INTDIR)\s_frexp.obj" - -@erase "$(INTDIR)\s_ilogb.obj" - -@erase "$(INTDIR)\s_isnan.obj" - -@erase "$(INTDIR)\s_ldexp.obj" - -@erase "$(INTDIR)\s_lib_version.obj" - -@erase "$(INTDIR)\s_log1p.obj" - -@erase "$(INTDIR)\s_logb.obj" - -@erase "$(INTDIR)\s_matherr.obj" - -@erase "$(INTDIR)\s_modf.obj" - -@erase "$(INTDIR)\s_nextafter.obj" - -@erase "$(INTDIR)\s_rint.obj" - -@erase "$(INTDIR)\s_scalbn.obj" - -@erase "$(INTDIR)\s_signgam.obj" - -@erase "$(INTDIR)\s_significand.obj" - -@erase "$(INTDIR)\s_sin.obj" - -@erase "$(INTDIR)\s_tan.obj" - -@erase "$(INTDIR)\s_tanh.obj" - -@erase "$(INTDIR)\w_acos.obj" - -@erase "$(INTDIR)\w_acosh.obj" - -@erase "$(INTDIR)\w_asin.obj" - -@erase "$(INTDIR)\w_atan2.obj" - -@erase "$(INTDIR)\w_atanh.obj" - -@erase "$(INTDIR)\w_cosh.obj" - -@erase "$(INTDIR)\w_exp.obj" - -@erase "$(INTDIR)\w_fmod.obj" - -@erase "$(INTDIR)\w_gamma.obj" - -@erase "$(INTDIR)\w_gamma_r.obj" - -@erase "$(INTDIR)\w_hypot.obj" - -@erase "$(INTDIR)\w_j0.obj" - -@erase "$(INTDIR)\w_j1.obj" - -@erase "$(INTDIR)\w_jn.obj" - -@erase "$(INTDIR)\w_lgamma.obj" - -@erase "$(INTDIR)\w_lgamma_r.obj" - -@erase "$(INTDIR)\w_log.obj" - -@erase "$(INTDIR)\w_log10.obj" - -@erase "$(INTDIR)\w_pow.obj" - -@erase "$(INTDIR)\w_remainder.obj" - -@erase "$(INTDIR)\w_scalb.obj" - -@erase "$(INTDIR)\w_sinh.obj" - -@erase "$(INTDIR)\w_sqrt.obj" - -@erase "$(OUTDIR)\fdlibm.lib" - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c -# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c -CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\ - /Fp"$(INTDIR)/fdlibm.pch" /YX /Fo"$(INTDIR)/" /c -CPP_OBJS=.\fdlibm__/ -CPP_SBRS=.\. -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o"$(OUTDIR)/fdlibm.bsc" -BSC32_SBRS= \ - -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo -LIB32_FLAGS=/nologo /out:"$(OUTDIR)/fdlibm.lib" -LIB32_OBJS= \ - "$(INTDIR)\e_acos.obj" \ - "$(INTDIR)\e_acosh.obj" \ - "$(INTDIR)\e_asin.obj" \ - "$(INTDIR)\e_atan2.obj" \ - "$(INTDIR)\e_atanh.obj" \ - "$(INTDIR)\e_cosh.obj" \ - "$(INTDIR)\e_exp.obj" \ - "$(INTDIR)\e_fmod.obj" \ - "$(INTDIR)\e_gamma.obj" \ - "$(INTDIR)\e_gamma_r.obj" \ - "$(INTDIR)\e_hypot.obj" \ - "$(INTDIR)\e_j0.obj" \ - "$(INTDIR)\e_j1.obj" \ - "$(INTDIR)\e_jn.obj" \ - "$(INTDIR)\e_lgamma.obj" \ - "$(INTDIR)\e_lgamma_r.obj" \ - "$(INTDIR)\e_log.obj" \ - "$(INTDIR)\e_log10.obj" \ - "$(INTDIR)\e_pow.obj" \ - "$(INTDIR)\e_rem_pio2.obj" \ - "$(INTDIR)\e_remainder.obj" \ - "$(INTDIR)\e_scalb.obj" \ - "$(INTDIR)\e_sinh.obj" \ - "$(INTDIR)\e_sqrt.obj" \ - "$(INTDIR)\k_cos.obj" \ - "$(INTDIR)\k_rem_pio2.obj" \ - "$(INTDIR)\k_sin.obj" \ - "$(INTDIR)\k_standard.obj" \ - "$(INTDIR)\k_tan.obj" \ - "$(INTDIR)\s_asinh.obj" \ - "$(INTDIR)\s_atan.obj" \ - "$(INTDIR)\s_cbrt.obj" \ - "$(INTDIR)\s_ceil.obj" \ - "$(INTDIR)\s_copysign.obj" \ - "$(INTDIR)\s_cos.obj" \ - "$(INTDIR)\s_erf.obj" \ - "$(INTDIR)\s_expm1.obj" \ - "$(INTDIR)\s_fabs.obj" \ - "$(INTDIR)\s_finite.obj" \ - "$(INTDIR)\s_floor.obj" \ - "$(INTDIR)\s_frexp.obj" \ - "$(INTDIR)\s_ilogb.obj" \ - "$(INTDIR)\s_isnan.obj" \ - "$(INTDIR)\s_ldexp.obj" \ - "$(INTDIR)\s_lib_version.obj" \ - "$(INTDIR)\s_log1p.obj" \ - "$(INTDIR)\s_logb.obj" \ - "$(INTDIR)\s_matherr.obj" \ - "$(INTDIR)\s_modf.obj" \ - "$(INTDIR)\s_nextafter.obj" \ - "$(INTDIR)\s_rint.obj" \ - "$(INTDIR)\s_scalbn.obj" \ - "$(INTDIR)\s_signgam.obj" \ - "$(INTDIR)\s_significand.obj" \ - "$(INTDIR)\s_sin.obj" \ - "$(INTDIR)\s_tan.obj" \ - "$(INTDIR)\s_tanh.obj" \ - "$(INTDIR)\w_acos.obj" \ - "$(INTDIR)\w_acosh.obj" \ - "$(INTDIR)\w_asin.obj" \ - "$(INTDIR)\w_atan2.obj" \ - "$(INTDIR)\w_atanh.obj" \ - "$(INTDIR)\w_cosh.obj" \ - "$(INTDIR)\w_exp.obj" \ - "$(INTDIR)\w_fmod.obj" \ - "$(INTDIR)\w_gamma.obj" \ - "$(INTDIR)\w_gamma_r.obj" \ - "$(INTDIR)\w_hypot.obj" \ - "$(INTDIR)\w_j0.obj" \ - "$(INTDIR)\w_j1.obj" \ - "$(INTDIR)\w_jn.obj" \ - "$(INTDIR)\w_lgamma.obj" \ - "$(INTDIR)\w_lgamma_r.obj" \ - "$(INTDIR)\w_log.obj" \ - "$(INTDIR)\w_log10.obj" \ - "$(INTDIR)\w_pow.obj" \ - "$(INTDIR)\w_remainder.obj" \ - "$(INTDIR)\w_scalb.obj" \ - "$(INTDIR)\w_sinh.obj" \ - "$(INTDIR)\w_sqrt.obj" - -"$(OUTDIR)\fdlibm.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS) - $(LIB32) @<< - $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS) -<< - -!ELSEIF "$(CFG)" == "fdlibm - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "fdlibm_0" -# PROP BASE Intermediate_Dir "fdlibm_0" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "fdlibm_0" -# PROP Intermediate_Dir "fdlibm_0" -# PROP Target_Dir "" -OUTDIR=.\fdlibm_0 -INTDIR=.\fdlibm_0 - -ALL : "$(OUTDIR)\fdlibm.lib" - -CLEAN : - -@erase "$(INTDIR)\e_acos.obj" - -@erase "$(INTDIR)\e_acosh.obj" - -@erase "$(INTDIR)\e_asin.obj" - -@erase "$(INTDIR)\e_atan2.obj" - -@erase "$(INTDIR)\e_atanh.obj" - -@erase "$(INTDIR)\e_cosh.obj" - -@erase "$(INTDIR)\e_exp.obj" - -@erase "$(INTDIR)\e_fmod.obj" - -@erase "$(INTDIR)\e_gamma.obj" - -@erase "$(INTDIR)\e_gamma_r.obj" - -@erase "$(INTDIR)\e_hypot.obj" - -@erase "$(INTDIR)\e_j0.obj" - -@erase "$(INTDIR)\e_j1.obj" - -@erase "$(INTDIR)\e_jn.obj" - -@erase "$(INTDIR)\e_lgamma.obj" - -@erase "$(INTDIR)\e_lgamma_r.obj" - -@erase "$(INTDIR)\e_log.obj" - -@erase "$(INTDIR)\e_log10.obj" - -@erase "$(INTDIR)\e_pow.obj" - -@erase "$(INTDIR)\e_rem_pio2.obj" - -@erase "$(INTDIR)\e_remainder.obj" - -@erase "$(INTDIR)\e_scalb.obj" - -@erase "$(INTDIR)\e_sinh.obj" - -@erase "$(INTDIR)\e_sqrt.obj" - -@erase "$(INTDIR)\k_cos.obj" - -@erase "$(INTDIR)\k_rem_pio2.obj" - -@erase "$(INTDIR)\k_sin.obj" - -@erase "$(INTDIR)\k_standard.obj" - -@erase "$(INTDIR)\k_tan.obj" - -@erase "$(INTDIR)\s_asinh.obj" - -@erase "$(INTDIR)\s_atan.obj" - -@erase "$(INTDIR)\s_cbrt.obj" - -@erase "$(INTDIR)\s_ceil.obj" - -@erase "$(INTDIR)\s_copysign.obj" - -@erase "$(INTDIR)\s_cos.obj" - -@erase "$(INTDIR)\s_erf.obj" - -@erase "$(INTDIR)\s_expm1.obj" - -@erase "$(INTDIR)\s_fabs.obj" - -@erase "$(INTDIR)\s_finite.obj" - -@erase "$(INTDIR)\s_floor.obj" - -@erase "$(INTDIR)\s_frexp.obj" - -@erase "$(INTDIR)\s_ilogb.obj" - -@erase "$(INTDIR)\s_isnan.obj" - -@erase "$(INTDIR)\s_ldexp.obj" - -@erase "$(INTDIR)\s_lib_version.obj" - -@erase "$(INTDIR)\s_log1p.obj" - -@erase "$(INTDIR)\s_logb.obj" - -@erase "$(INTDIR)\s_matherr.obj" - -@erase "$(INTDIR)\s_modf.obj" - -@erase "$(INTDIR)\s_nextafter.obj" - -@erase "$(INTDIR)\s_rint.obj" - -@erase "$(INTDIR)\s_scalbn.obj" - -@erase "$(INTDIR)\s_signgam.obj" - -@erase "$(INTDIR)\s_significand.obj" - -@erase "$(INTDIR)\s_sin.obj" - -@erase "$(INTDIR)\s_tan.obj" - -@erase "$(INTDIR)\s_tanh.obj" - -@erase "$(INTDIR)\w_acos.obj" - -@erase "$(INTDIR)\w_acosh.obj" - -@erase "$(INTDIR)\w_asin.obj" - -@erase "$(INTDIR)\w_atan2.obj" - -@erase "$(INTDIR)\w_atanh.obj" - -@erase "$(INTDIR)\w_cosh.obj" - -@erase "$(INTDIR)\w_exp.obj" - -@erase "$(INTDIR)\w_fmod.obj" - -@erase "$(INTDIR)\w_gamma.obj" - -@erase "$(INTDIR)\w_gamma_r.obj" - -@erase "$(INTDIR)\w_hypot.obj" - -@erase "$(INTDIR)\w_j0.obj" - -@erase "$(INTDIR)\w_j1.obj" - -@erase "$(INTDIR)\w_jn.obj" - -@erase "$(INTDIR)\w_lgamma.obj" - -@erase "$(INTDIR)\w_lgamma_r.obj" - -@erase "$(INTDIR)\w_log.obj" - -@erase "$(INTDIR)\w_log10.obj" - -@erase "$(INTDIR)\w_pow.obj" - -@erase "$(INTDIR)\w_remainder.obj" - -@erase "$(INTDIR)\w_scalb.obj" - -@erase "$(INTDIR)\w_sinh.obj" - -@erase "$(INTDIR)\w_sqrt.obj" - -@erase "$(OUTDIR)\fdlibm.lib" - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c -# ADD CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c -CPP_PROJ=/nologo /MLd /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS"\ - /Fp"$(INTDIR)/fdlibm.pch" /YX /Fo"$(INTDIR)/" /c -CPP_OBJS=.\fdlibm_0/ -CPP_SBRS=.\. -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o"$(OUTDIR)/fdlibm.bsc" -BSC32_SBRS= \ - -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo -LIB32_FLAGS=/nologo /out:"$(OUTDIR)/fdlibm.lib" -LIB32_OBJS= \ - "$(INTDIR)\e_acos.obj" \ - "$(INTDIR)\e_acosh.obj" \ - "$(INTDIR)\e_asin.obj" \ - "$(INTDIR)\e_atan2.obj" \ - "$(INTDIR)\e_atanh.obj" \ - "$(INTDIR)\e_cosh.obj" \ - "$(INTDIR)\e_exp.obj" \ - "$(INTDIR)\e_fmod.obj" \ - "$(INTDIR)\e_gamma.obj" \ - "$(INTDIR)\e_gamma_r.obj" \ - "$(INTDIR)\e_hypot.obj" \ - "$(INTDIR)\e_j0.obj" \ - "$(INTDIR)\e_j1.obj" \ - "$(INTDIR)\e_jn.obj" \ - "$(INTDIR)\e_lgamma.obj" \ - "$(INTDIR)\e_lgamma_r.obj" \ - "$(INTDIR)\e_log.obj" \ - "$(INTDIR)\e_log10.obj" \ - "$(INTDIR)\e_pow.obj" \ - "$(INTDIR)\e_rem_pio2.obj" \ - "$(INTDIR)\e_remainder.obj" \ - "$(INTDIR)\e_scalb.obj" \ - "$(INTDIR)\e_sinh.obj" \ - "$(INTDIR)\e_sqrt.obj" \ - "$(INTDIR)\k_cos.obj" \ - "$(INTDIR)\k_rem_pio2.obj" \ - "$(INTDIR)\k_sin.obj" \ - "$(INTDIR)\k_standard.obj" \ - "$(INTDIR)\k_tan.obj" \ - "$(INTDIR)\s_asinh.obj" \ - "$(INTDIR)\s_atan.obj" \ - "$(INTDIR)\s_cbrt.obj" \ - "$(INTDIR)\s_ceil.obj" \ - "$(INTDIR)\s_copysign.obj" \ - "$(INTDIR)\s_cos.obj" \ - "$(INTDIR)\s_erf.obj" \ - "$(INTDIR)\s_expm1.obj" \ - "$(INTDIR)\s_fabs.obj" \ - "$(INTDIR)\s_finite.obj" \ - "$(INTDIR)\s_floor.obj" \ - "$(INTDIR)\s_frexp.obj" \ - "$(INTDIR)\s_ilogb.obj" \ - "$(INTDIR)\s_isnan.obj" \ - "$(INTDIR)\s_ldexp.obj" \ - "$(INTDIR)\s_lib_version.obj" \ - "$(INTDIR)\s_log1p.obj" \ - "$(INTDIR)\s_logb.obj" \ - "$(INTDIR)\s_matherr.obj" \ - "$(INTDIR)\s_modf.obj" \ - "$(INTDIR)\s_nextafter.obj" \ - "$(INTDIR)\s_rint.obj" \ - "$(INTDIR)\s_scalbn.obj" \ - "$(INTDIR)\s_signgam.obj" \ - "$(INTDIR)\s_significand.obj" \ - "$(INTDIR)\s_sin.obj" \ - "$(INTDIR)\s_tan.obj" \ - "$(INTDIR)\s_tanh.obj" \ - "$(INTDIR)\w_acos.obj" \ - "$(INTDIR)\w_acosh.obj" \ - "$(INTDIR)\w_asin.obj" \ - "$(INTDIR)\w_atan2.obj" \ - "$(INTDIR)\w_atanh.obj" \ - "$(INTDIR)\w_cosh.obj" \ - "$(INTDIR)\w_exp.obj" \ - "$(INTDIR)\w_fmod.obj" \ - "$(INTDIR)\w_gamma.obj" \ - "$(INTDIR)\w_gamma_r.obj" \ - "$(INTDIR)\w_hypot.obj" \ - "$(INTDIR)\w_j0.obj" \ - "$(INTDIR)\w_j1.obj" \ - "$(INTDIR)\w_jn.obj" \ - "$(INTDIR)\w_lgamma.obj" \ - "$(INTDIR)\w_lgamma_r.obj" \ - "$(INTDIR)\w_log.obj" \ - "$(INTDIR)\w_log10.obj" \ - "$(INTDIR)\w_pow.obj" \ - "$(INTDIR)\w_remainder.obj" \ - "$(INTDIR)\w_scalb.obj" \ - "$(INTDIR)\w_sinh.obj" \ - "$(INTDIR)\w_sqrt.obj" - -"$(OUTDIR)\fdlibm.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS) - $(LIB32) @<< - $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS) -<< - -!ENDIF - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.c{$(CPP_SBRS)}.sbr: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_SBRS)}.sbr: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_SBRS)}.sbr: - $(CPP) $(CPP_PROJ) $< - -################################################################################ -# Begin Target - -# Name "fdlibm - Win32 Release" -# Name "fdlibm - Win32 Debug" - -!IF "$(CFG)" == "fdlibm - Win32 Release" - -!ELSEIF "$(CFG)" == "fdlibm - Win32 Debug" - -!ENDIF - -################################################################################ -# Begin Source File - -SOURCE=.\w_sqrt.c -DEP_CPP_W_SQR=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_sqrt.obj" : $(SOURCE) $(DEP_CPP_W_SQR) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_acosh.c -DEP_CPP_E_ACO=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_acosh.obj" : $(SOURCE) $(DEP_CPP_E_ACO) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_asin.c -DEP_CPP_E_ASI=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_asin.obj" : $(SOURCE) $(DEP_CPP_E_ASI) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_atan2.c -DEP_CPP_E_ATA=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_atan2.obj" : $(SOURCE) $(DEP_CPP_E_ATA) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_atanh.c -DEP_CPP_E_ATAN=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_atanh.obj" : $(SOURCE) $(DEP_CPP_E_ATAN) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_cosh.c -DEP_CPP_E_COS=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_cosh.obj" : $(SOURCE) $(DEP_CPP_E_COS) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_exp.c -DEP_CPP_E_EXP=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_exp.obj" : $(SOURCE) $(DEP_CPP_E_EXP) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_fmod.c -DEP_CPP_E_FMO=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_fmod.obj" : $(SOURCE) $(DEP_CPP_E_FMO) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_gamma.c -DEP_CPP_E_GAM=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_gamma.obj" : $(SOURCE) $(DEP_CPP_E_GAM) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_gamma_r.c -DEP_CPP_E_GAMM=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_gamma_r.obj" : $(SOURCE) $(DEP_CPP_E_GAMM) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_hypot.c -DEP_CPP_E_HYP=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_hypot.obj" : $(SOURCE) $(DEP_CPP_E_HYP) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_j0.c -DEP_CPP_E_J0_=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_j0.obj" : $(SOURCE) $(DEP_CPP_E_J0_) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_j1.c -DEP_CPP_E_J1_=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_j1.obj" : $(SOURCE) $(DEP_CPP_E_J1_) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_jn.c -DEP_CPP_E_JN_=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_jn.obj" : $(SOURCE) $(DEP_CPP_E_JN_) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_lgamma.c -DEP_CPP_E_LGA=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_lgamma.obj" : $(SOURCE) $(DEP_CPP_E_LGA) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_lgamma_r.c -DEP_CPP_E_LGAM=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_lgamma_r.obj" : $(SOURCE) $(DEP_CPP_E_LGAM) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_log.c -DEP_CPP_E_LOG=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_log.obj" : $(SOURCE) $(DEP_CPP_E_LOG) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_log10.c -DEP_CPP_E_LOG1=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_log10.obj" : $(SOURCE) $(DEP_CPP_E_LOG1) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_pow.c -DEP_CPP_E_POW=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_pow.obj" : $(SOURCE) $(DEP_CPP_E_POW) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_rem_pio2.c -DEP_CPP_E_REM=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_rem_pio2.obj" : $(SOURCE) $(DEP_CPP_E_REM) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_remainder.c -DEP_CPP_E_REMA=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_remainder.obj" : $(SOURCE) $(DEP_CPP_E_REMA) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_scalb.c -DEP_CPP_E_SCA=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_scalb.obj" : $(SOURCE) $(DEP_CPP_E_SCA) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_sinh.c -DEP_CPP_E_SIN=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_sinh.obj" : $(SOURCE) $(DEP_CPP_E_SIN) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_sqrt.c -DEP_CPP_E_SQR=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_sqrt.obj" : $(SOURCE) $(DEP_CPP_E_SQR) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\fdlibm.h - -!IF "$(CFG)" == "fdlibm - Win32 Release" - -!ELSEIF "$(CFG)" == "fdlibm - Win32 Debug" - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\k_cos.c -DEP_CPP_K_COS=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\k_cos.obj" : $(SOURCE) $(DEP_CPP_K_COS) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\k_rem_pio2.c -DEP_CPP_K_REM=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\k_rem_pio2.obj" : $(SOURCE) $(DEP_CPP_K_REM) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\k_sin.c -DEP_CPP_K_SIN=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\k_sin.obj" : $(SOURCE) $(DEP_CPP_K_SIN) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\k_standard.c -DEP_CPP_K_STA=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\k_standard.obj" : $(SOURCE) $(DEP_CPP_K_STA) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\k_tan.c -DEP_CPP_K_TAN=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\k_tan.obj" : $(SOURCE) $(DEP_CPP_K_TAN) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_asinh.c -DEP_CPP_S_ASI=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_asinh.obj" : $(SOURCE) $(DEP_CPP_S_ASI) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_atan.c -DEP_CPP_S_ATA=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_atan.obj" : $(SOURCE) $(DEP_CPP_S_ATA) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_cbrt.c -DEP_CPP_S_CBR=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_cbrt.obj" : $(SOURCE) $(DEP_CPP_S_CBR) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_ceil.c -DEP_CPP_S_CEI=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_ceil.obj" : $(SOURCE) $(DEP_CPP_S_CEI) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_copysign.c -DEP_CPP_S_COP=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_copysign.obj" : $(SOURCE) $(DEP_CPP_S_COP) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_cos.c -DEP_CPP_S_COS=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_cos.obj" : $(SOURCE) $(DEP_CPP_S_COS) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_erf.c -DEP_CPP_S_ERF=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_erf.obj" : $(SOURCE) $(DEP_CPP_S_ERF) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_expm1.c -DEP_CPP_S_EXP=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_expm1.obj" : $(SOURCE) $(DEP_CPP_S_EXP) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_fabs.c -DEP_CPP_S_FAB=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_fabs.obj" : $(SOURCE) $(DEP_CPP_S_FAB) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_finite.c -DEP_CPP_S_FIN=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_finite.obj" : $(SOURCE) $(DEP_CPP_S_FIN) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_floor.c -DEP_CPP_S_FLO=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_floor.obj" : $(SOURCE) $(DEP_CPP_S_FLO) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_frexp.c -DEP_CPP_S_FRE=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_frexp.obj" : $(SOURCE) $(DEP_CPP_S_FRE) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_ilogb.c -DEP_CPP_S_ILO=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_ilogb.obj" : $(SOURCE) $(DEP_CPP_S_ILO) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_isnan.c -DEP_CPP_S_ISN=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_isnan.obj" : $(SOURCE) $(DEP_CPP_S_ISN) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_ldexp.c -DEP_CPP_S_LDE=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_ldexp.obj" : $(SOURCE) $(DEP_CPP_S_LDE) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_lib_version.c -DEP_CPP_S_LIB=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_lib_version.obj" : $(SOURCE) $(DEP_CPP_S_LIB) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_log1p.c -DEP_CPP_S_LOG=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_log1p.obj" : $(SOURCE) $(DEP_CPP_S_LOG) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_logb.c -DEP_CPP_S_LOGB=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_logb.obj" : $(SOURCE) $(DEP_CPP_S_LOGB) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_matherr.c -DEP_CPP_S_MAT=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_matherr.obj" : $(SOURCE) $(DEP_CPP_S_MAT) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_modf.c -DEP_CPP_S_MOD=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_modf.obj" : $(SOURCE) $(DEP_CPP_S_MOD) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_nextafter.c -DEP_CPP_S_NEX=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_nextafter.obj" : $(SOURCE) $(DEP_CPP_S_NEX) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_rint.c -DEP_CPP_S_RIN=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_rint.obj" : $(SOURCE) $(DEP_CPP_S_RIN) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_scalbn.c -DEP_CPP_S_SCA=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_scalbn.obj" : $(SOURCE) $(DEP_CPP_S_SCA) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_signgam.c -DEP_CPP_S_SIG=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_signgam.obj" : $(SOURCE) $(DEP_CPP_S_SIG) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_significand.c -DEP_CPP_S_SIGN=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_significand.obj" : $(SOURCE) $(DEP_CPP_S_SIGN) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_sin.c -DEP_CPP_S_SIN=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_sin.obj" : $(SOURCE) $(DEP_CPP_S_SIN) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_tan.c -DEP_CPP_S_TAN=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_tan.obj" : $(SOURCE) $(DEP_CPP_S_TAN) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_tanh.c -DEP_CPP_S_TANH=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_tanh.obj" : $(SOURCE) $(DEP_CPP_S_TANH) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_acos.c -DEP_CPP_W_ACO=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_acos.obj" : $(SOURCE) $(DEP_CPP_W_ACO) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_acosh.c -DEP_CPP_W_ACOS=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_acosh.obj" : $(SOURCE) $(DEP_CPP_W_ACOS) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_asin.c -DEP_CPP_W_ASI=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_asin.obj" : $(SOURCE) $(DEP_CPP_W_ASI) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_atan2.c -DEP_CPP_W_ATA=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_atan2.obj" : $(SOURCE) $(DEP_CPP_W_ATA) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_atanh.c -DEP_CPP_W_ATAN=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_atanh.obj" : $(SOURCE) $(DEP_CPP_W_ATAN) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_cosh.c -DEP_CPP_W_COS=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_cosh.obj" : $(SOURCE) $(DEP_CPP_W_COS) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_exp.c -DEP_CPP_W_EXP=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_exp.obj" : $(SOURCE) $(DEP_CPP_W_EXP) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_fmod.c -DEP_CPP_W_FMO=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_fmod.obj" : $(SOURCE) $(DEP_CPP_W_FMO) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_gamma.c -DEP_CPP_W_GAM=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_gamma.obj" : $(SOURCE) $(DEP_CPP_W_GAM) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_gamma_r.c -DEP_CPP_W_GAMM=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_gamma_r.obj" : $(SOURCE) $(DEP_CPP_W_GAMM) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_hypot.c -DEP_CPP_W_HYP=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_hypot.obj" : $(SOURCE) $(DEP_CPP_W_HYP) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_j0.c -DEP_CPP_W_J0_=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_j0.obj" : $(SOURCE) $(DEP_CPP_W_J0_) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_j1.c -DEP_CPP_W_J1_=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_j1.obj" : $(SOURCE) $(DEP_CPP_W_J1_) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_jn.c -DEP_CPP_W_JN_=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_jn.obj" : $(SOURCE) $(DEP_CPP_W_JN_) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_lgamma.c -DEP_CPP_W_LGA=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_lgamma.obj" : $(SOURCE) $(DEP_CPP_W_LGA) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_lgamma_r.c -DEP_CPP_W_LGAM=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_lgamma_r.obj" : $(SOURCE) $(DEP_CPP_W_LGAM) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_log.c -DEP_CPP_W_LOG=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_log.obj" : $(SOURCE) $(DEP_CPP_W_LOG) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_log10.c -DEP_CPP_W_LOG1=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_log10.obj" : $(SOURCE) $(DEP_CPP_W_LOG1) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_pow.c -DEP_CPP_W_POW=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_pow.obj" : $(SOURCE) $(DEP_CPP_W_POW) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_remainder.c -DEP_CPP_W_REM=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_remainder.obj" : $(SOURCE) $(DEP_CPP_W_REM) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_scalb.c -DEP_CPP_W_SCA=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_scalb.obj" : $(SOURCE) $(DEP_CPP_W_SCA) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_sinh.c -DEP_CPP_W_SIN=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_sinh.obj" : $(SOURCE) $(DEP_CPP_W_SIN) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_acos.c -DEP_CPP_E_ACOS=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_acos.obj" : $(SOURCE) $(DEP_CPP_E_ACOS) "$(INTDIR)" - - -# End Source File -# End Target -# End Project -################################################################################ diff --git a/lib/javascript/fdlibm/fdlibm.mdp b/lib/javascript/fdlibm/fdlibm.mdp deleted file mode 100644 index 5904c494..00000000 Binary files a/lib/javascript/fdlibm/fdlibm.mdp and /dev/null differ diff --git a/lib/javascript/fdlibm/k_cos.c b/lib/javascript/fdlibm/k_cos.c deleted file mode 100644 index 1d18c803..00000000 --- a/lib/javascript/fdlibm/k_cos.c +++ /dev/null @@ -1,135 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)k_cos.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * __kernel_cos( x, y ) - * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164 - * Input x is assumed to be bounded by ~pi/4 in magnitude. - * Input y is the tail of x. - * - * Algorithm - * 1. Since cos(-x) = cos(x), we need only to consider positive x. - * 2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0. - * 3. cos(x) is approximated by a polynomial of degree 14 on - * [0,pi/4] - * 4 14 - * cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x - * where the remez error is - * - * | 2 4 6 8 10 12 14 | -58 - * |cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x +C6*x )| <= 2 - * | | - * - * 4 6 8 10 12 14 - * 4. let r = C1*x +C2*x +C3*x +C4*x +C5*x +C6*x , then - * cos(x) = 1 - x*x/2 + r - * since cos(x+y) ~ cos(x) - sin(x)*y - * ~ cos(x) - x*y, - * a correction term is necessary in cos(x) and hence - * cos(x+y) = 1 - (x*x/2 - (r - x*y)) - * For better accuracy when x > 0.3, let qx = |x|/4 with - * the last 32 bits mask off, and if x > 0.78125, let qx = 0.28125. - * Then - * cos(x+y) = (1-qx) - ((x*x/2-qx) - (r-x*y)). - * Note that 1-qx and (x*x/2-qx) is EXACT here, and the - * magnitude of the latter is at least a quarter of x*x/2, - * thus, reducing the rounding error in the subtraction. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ -C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */ -C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */ -C3 = 2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */ -C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */ -C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */ -C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */ - -#ifdef __STDC__ - double __kernel_cos(double x, double y) -#else - double __kernel_cos(x, y) - double x,y; -#endif -{ - fd_twoints u; - double qx = 0; - double a,hz,z,r; - int ix; - u.d = x; - ix = __HI(u)&0x7fffffff; /* ix = |x|'s high word*/ - if(ix<0x3e400000) { /* if x < 2**27 */ - if(((int)x)==0) return one; /* generate inexact */ - } - z = x*x; - r = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6))))); - if(ix < 0x3FD33333) /* if |x| < 0.3 */ - return one - (0.5*z - (z*r - x*y)); - else { - if(ix > 0x3fe90000) { /* x > 0.78125 */ - qx = 0.28125; - } else { - u.d = qx; - __HI(u) = ix-0x00200000; /* x/4 */ - __LO(u) = 0; - qx = u.d; - } - hz = 0.5*z-qx; - a = one-qx; - return a - (hz - (z*r-x*y)); - } -} diff --git a/lib/javascript/fdlibm/k_rem_pio2.c b/lib/javascript/fdlibm/k_rem_pio2.c deleted file mode 100644 index d261e190..00000000 --- a/lib/javascript/fdlibm/k_rem_pio2.c +++ /dev/null @@ -1,354 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)k_rem_pio2.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * __kernel_rem_pio2(x,y,e0,nx,prec,ipio2) - * double x[],y[]; int e0,nx,prec; int ipio2[]; - * - * __kernel_rem_pio2 return the last three digits of N with - * y = x - N*pi/2 - * so that |y| < pi/2. - * - * The method is to compute the integer (mod 8) and fraction parts of - * (2/pi)*x without doing the full multiplication. In general we - * skip the part of the product that are known to be a huge integer ( - * more accurately, = 0 mod 8 ). Thus the number of operations are - * independent of the exponent of the input. - * - * (2/pi) is represented by an array of 24-bit integers in ipio2[]. - * - * Input parameters: - * x[] The input value (must be positive) is broken into nx - * pieces of 24-bit integers in double precision format. - * x[i] will be the i-th 24 bit of x. The scaled exponent - * of x[0] is given in input parameter e0 (i.e., x[0]*2^e0 - * match x's up to 24 bits. - * - * Example of breaking a double positive z into x[0]+x[1]+x[2]: - * e0 = ilogb(z)-23 - * z = scalbn(z,-e0) - * for i = 0,1,2 - * x[i] = floor(z) - * z = (z-x[i])*2**24 - * - * - * y[] ouput result in an array of double precision numbers. - * The dimension of y[] is: - * 24-bit precision 1 - * 53-bit precision 2 - * 64-bit precision 2 - * 113-bit precision 3 - * The actual value is the sum of them. Thus for 113-bit - * precison, one may have to do something like: - * - * long double t,w,r_head, r_tail; - * t = (long double)y[2] + (long double)y[1]; - * w = (long double)y[0]; - * r_head = t+w; - * r_tail = w - (r_head - t); - * - * e0 The exponent of x[0] - * - * nx dimension of x[] - * - * prec an integer indicating the precision: - * 0 24 bits (single) - * 1 53 bits (double) - * 2 64 bits (extended) - * 3 113 bits (quad) - * - * ipio2[] - * integer array, contains the (24*i)-th to (24*i+23)-th - * bit of 2/pi after binary point. The corresponding - * floating value is - * - * ipio2[i] * 2^(-24(i+1)). - * - * External function: - * double scalbn(), floor(); - * - * - * Here is the description of some local variables: - * - * jk jk+1 is the initial number of terms of ipio2[] needed - * in the computation. The recommended value is 2,3,4, - * 6 for single, double, extended,and quad. - * - * jz local integer variable indicating the number of - * terms of ipio2[] used. - * - * jx nx - 1 - * - * jv index for pointing to the suitable ipio2[] for the - * computation. In general, we want - * ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8 - * is an integer. Thus - * e0-3-24*jv >= 0 or (e0-3)/24 >= jv - * Hence jv = max(0,(e0-3)/24). - * - * jp jp+1 is the number of terms in PIo2[] needed, jp = jk. - * - * q[] double array with integral value, representing the - * 24-bits chunk of the product of x and 2/pi. - * - * q0 the corresponding exponent of q[0]. Note that the - * exponent for q[i] would be q0-24*i. - * - * PIo2[] double precision array, obtained by cutting pi/2 - * into 24 bits chunks. - * - * f[] ipio2[] in floating point - * - * iq[] integer array by breaking up q[] in 24-bits chunk. - * - * fq[] final product of x*(2/pi) in fq[0],..,fq[jk] - * - * ih integer. If >0 it indicates q[] is >= 0.5, hence - * it also indicates the *sign* of the result. - * - */ - - -/* - * Constants: - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const int init_jk[] = {2,3,4,6}; /* initial value for jk */ -#else -static int init_jk[] = {2,3,4,6}; -#endif - -#ifdef __STDC__ -static const double PIo2[] = { -#else -static double PIo2[] = { -#endif - 1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */ - 7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */ - 5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */ - 3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */ - 1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */ - 1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */ - 2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */ - 2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */ -}; - -#ifdef __STDC__ -static const double -#else -static double -#endif -zero = 0.0, -one = 1.0, -two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */ -twon24 = 5.96046447753906250000e-08; /* 0x3E700000, 0x00000000 */ - -#ifdef __STDC__ - int __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec, const int *ipio2) -#else - int __kernel_rem_pio2(x,y,e0,nx,prec,ipio2) - double x[], y[]; int e0,nx,prec; int ipio2[]; -#endif -{ - int jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih; - double z,fw,f[20],fq[20],q[20]; - - /* initialize jk*/ - jk = init_jk[prec]; - jp = jk; - - /* determine jx,jv,q0, note that 3>q0 */ - jx = nx-1; - jv = (e0-3)/24; if(jv<0) jv=0; - q0 = e0-24*(jv+1); - - /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */ - j = jv-jx; m = jx+jk; - for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (double) ipio2[j]; - - /* compute q[0],q[1],...q[jk] */ - for (i=0;i<=jk;i++) { - for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw; - } - - jz = jk; -recompute: - /* distill q[] into iq[] reversingly */ - for(i=0,j=jz,z=q[jz];j>0;i++,j--) { - fw = (double)((int)(twon24* z)); - iq[i] = (int)(z-two24*fw); - z = q[j-1]+fw; - } - - /* compute n */ - z = fd_scalbn(z,q0); /* actual value of z */ - z -= 8.0*fd_floor(z*0.125); /* trim off integer >= 8 */ - n = (int) z; - z -= (double)n; - ih = 0; - if(q0>0) { /* need iq[jz-1] to determine n */ - i = (iq[jz-1]>>(24-q0)); n += i; - iq[jz-1] -= i<<(24-q0); - ih = iq[jz-1]>>(23-q0); - } - else if(q0==0) ih = iq[jz-1]>>23; - else if(z>=0.5) ih=2; - - if(ih>0) { /* q > 0.5 */ - n += 1; carry = 0; - for(i=0;i0) { /* rare case: chance is 1 in 12 */ - switch(q0) { - case 1: - iq[jz-1] &= 0x7fffff; break; - case 2: - iq[jz-1] &= 0x3fffff; break; - } - } - if(ih==2) { - z = one - z; - if(carry!=0) z -= fd_scalbn(one,q0); - } - } - - /* check if recomputation is needed */ - if(z==zero) { - j = 0; - for (i=jz-1;i>=jk;i--) j |= iq[i]; - if(j==0) { /* need recomputation */ - for(k=1;iq[jk-k]==0;k++); /* k = no. of terms needed */ - - for(i=jz+1;i<=jz+k;i++) { /* add q[jz+1] to q[jz+k] */ - f[jx+i] = (double) ipio2[jv+i]; - for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; - q[i] = fw; - } - jz += k; - goto recompute; - } - } - - /* chop off zero terms */ - if(z==0.0) { - jz -= 1; q0 -= 24; - while(iq[jz]==0) { jz--; q0-=24;} - } else { /* break z into 24-bit if necessary */ - z = fd_scalbn(z,-q0); - if(z>=two24) { - fw = (double)((int)(twon24*z)); - iq[jz] = (int)(z-two24*fw); - jz += 1; q0 += 24; - iq[jz] = (int) fw; - } else iq[jz] = (int) z ; - } - - /* convert integer "bit" chunk to floating-point value */ - fw = fd_scalbn(one,q0); - for(i=jz;i>=0;i--) { - q[i] = fw*(double)iq[i]; fw*=twon24; - } - - /* compute PIo2[0,...,jp]*q[jz,...,0] */ - for(i=jz;i>=0;i--) { - for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k]; - fq[jz-i] = fw; - } - - /* compress fq[] into y[] */ - switch(prec) { - case 0: - fw = 0.0; - for (i=jz;i>=0;i--) fw += fq[i]; - y[0] = (ih==0)? fw: -fw; - break; - case 1: - case 2: - fw = 0.0; - for (i=jz;i>=0;i--) fw += fq[i]; - y[0] = (ih==0)? fw: -fw; - fw = fq[0]-fw; - for (i=1;i<=jz;i++) fw += fq[i]; - y[1] = (ih==0)? fw: -fw; - break; - case 3: /* painful */ - for (i=jz;i>0;i--) { - fw = fq[i-1]+fq[i]; - fq[i] += fq[i-1]-fw; - fq[i-1] = fw; - } - for (i=jz;i>1;i--) { - fw = fq[i-1]+fq[i]; - fq[i] += fq[i-1]-fw; - fq[i-1] = fw; - } - for (fw=0.0,i=jz;i>=2;i--) fw += fq[i]; - if(ih==0) { - y[0] = fq[0]; y[1] = fq[1]; y[2] = fw; - } else { - y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw; - } - } - return n&7; -} diff --git a/lib/javascript/fdlibm/k_sin.c b/lib/javascript/fdlibm/k_sin.c deleted file mode 100644 index d2bdabd6..00000000 --- a/lib/javascript/fdlibm/k_sin.c +++ /dev/null @@ -1,114 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)k_sin.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* __kernel_sin( x, y, iy) - * kernel sin function on [-pi/4, pi/4], pi/4 ~ 0.7854 - * Input x is assumed to be bounded by ~pi/4 in magnitude. - * Input y is the tail of x. - * Input iy indicates whether y is 0. (if iy=0, y assume to be 0). - * - * Algorithm - * 1. Since sin(-x) = -sin(x), we need only to consider positive x. - * 2. if x < 2^-27 (hx<0x3e400000 0), return x with inexact if x!=0. - * 3. sin(x) is approximated by a polynomial of degree 13 on - * [0,pi/4] - * 3 13 - * sin(x) ~ x + S1*x + ... + S6*x - * where - * - * |sin(x) 2 4 6 8 10 12 | -58 - * |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2 - * | x | - * - * 4. sin(x+y) = sin(x) + sin'(x')*y - * ~ sin(x) + (1-x*x/2)*y - * For better accuracy, let - * 3 2 2 2 2 - * r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6)))) - * then 3 2 - * sin(x) = x + (S1*x + (x *(r-y/2)+y)) - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ -S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */ -S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */ -S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */ -S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */ -S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */ -S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */ - -#ifdef __STDC__ - double __kernel_sin(double x, double y, int iy) -#else - double __kernel_sin(x, y, iy) - double x,y; int iy; /* iy=0 if y is zero */ -#endif -{ - fd_twoints u; - double z,r,v; - int ix; - u.d = x; - ix = __HI(u)&0x7fffffff; /* high word of x */ - if(ix<0x3e400000) /* |x| < 2**-27 */ - {if((int)x==0) return x;} /* generate inexact */ - z = x*x; - v = z*x; - r = S2+z*(S3+z*(S4+z*(S5+z*S6))); - if(iy==0) return x+v*(S1+z*r); - else return x-((z*(half*y-v*r)-y)-v*S1); -} diff --git a/lib/javascript/fdlibm/k_standard.c b/lib/javascript/fdlibm/k_standard.c deleted file mode 100644 index 720109c9..00000000 --- a/lib/javascript/fdlibm/k_standard.c +++ /dev/null @@ -1,785 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)k_standard.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -#include "fdlibm.h" - -/* XXX ugly hack to get msvc to link without error. */ -#if _LIB_VERSION == _IEEE_ && !(defined(DARWIN) || defined(XP_MACOSX)) - int errno; -# define EDOM 0 -# define ERANGE 0 -#else -# include -#endif - - -#ifndef _USE_WRITE -#include /* fputs(), stderr */ -#define WRITE2(u,v) fputs(u, stderr) -#else /* !defined(_USE_WRITE) */ -#include /* write */ -#define WRITE2(u,v) write(2, u, v) -#undef fflush -#endif /* !defined(_USE_WRITE) */ - -static double zero = 0.0; /* used as const */ - -/* - * Standard conformance (non-IEEE) on exception cases. - * Mapping: - * 1 -- acos(|x|>1) - * 2 -- asin(|x|>1) - * 3 -- atan2(+-0,+-0) - * 4 -- hypot overflow - * 5 -- cosh overflow - * 6 -- exp overflow - * 7 -- exp underflow - * 8 -- y0(0) - * 9 -- y0(-ve) - * 10-- y1(0) - * 11-- y1(-ve) - * 12-- yn(0) - * 13-- yn(-ve) - * 14-- lgamma(finite) overflow - * 15-- lgamma(-integer) - * 16-- log(0) - * 17-- log(x<0) - * 18-- log10(0) - * 19-- log10(x<0) - * 20-- pow(0.0,0.0) - * 21-- pow(x,y) overflow - * 22-- pow(x,y) underflow - * 23-- pow(0,negative) - * 24-- pow(neg,non-integral) - * 25-- sinh(finite) overflow - * 26-- sqrt(negative) - * 27-- fmod(x,0) - * 28-- remainder(x,0) - * 29-- acosh(x<1) - * 30-- atanh(|x|>1) - * 31-- atanh(|x|=1) - * 32-- scalb overflow - * 33-- scalb underflow - * 34-- j0(|x|>X_TLOSS) - * 35-- y0(x>X_TLOSS) - * 36-- j1(|x|>X_TLOSS) - * 37-- y1(x>X_TLOSS) - * 38-- jn(|x|>X_TLOSS, n) - * 39-- yn(x>X_TLOSS, n) - * 40-- gamma(finite) overflow - * 41-- gamma(-integer) - * 42-- pow(NaN,0.0) - */ - - -#ifdef __STDC__ - double __kernel_standard(double x, double y, int type, int *err) -#else - double __kernel_standard(x,y,type, err) - double x,y; int type;int *err; -#endif -{ - struct exception exc; -#ifndef HUGE_VAL /* this is the only routine that uses HUGE_VAL */ -#define HUGE_VAL inf - double inf = 0.0; - fd_twoints u; - - u.d = inf; - __HI(u) = 0x7ff00000; /* set inf to infinite */ - inf = u.d; -#endif - - *err = 0; - -#ifdef _USE_WRITE - (void) fflush(stdout); -#endif - exc.arg1 = x; - exc.arg2 = y; - switch(type) { - case 1: - /* acos(|x|>1) */ - exc.type = DOMAIN; - exc.name = "acos"; - exc.retval = zero; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if(_LIB_VERSION == _SVID_) { - (void) WRITE2("acos: DOMAIN error\n", 19); - } - *err = EDOM; - } - break; - case 2: - /* asin(|x|>1) */ - exc.type = DOMAIN; - exc.name = "asin"; - exc.retval = zero; - if(_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if(_LIB_VERSION == _SVID_) { - (void) WRITE2("asin: DOMAIN error\n", 19); - } - *err = EDOM; - } - break; - case 3: - /* atan2(+-0,+-0) */ - exc.arg1 = y; - exc.arg2 = x; - exc.type = DOMAIN; - exc.name = "atan2"; - exc.retval = zero; - if(_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if(_LIB_VERSION == _SVID_) { - (void) WRITE2("atan2: DOMAIN error\n", 20); - } - *err = EDOM; - } - break; - case 4: - /* hypot(finite,finite) overflow */ - exc.type = OVERFLOW; - exc.name = "hypot"; - if (_LIB_VERSION == _SVID_) - exc.retval = HUGE; - else - exc.retval = HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - *err = ERANGE; - } - break; - case 5: - /* cosh(finite) overflow */ - exc.type = OVERFLOW; - exc.name = "cosh"; - if (_LIB_VERSION == _SVID_) - exc.retval = HUGE; - else - exc.retval = HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - *err = ERANGE; - } - break; - case 6: - /* exp(finite) overflow */ - exc.type = OVERFLOW; - exc.name = "exp"; - if (_LIB_VERSION == _SVID_) - exc.retval = HUGE; - else - exc.retval = HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - *err = ERANGE; - } - break; - case 7: - /* exp(finite) underflow */ - exc.type = UNDERFLOW; - exc.name = "exp"; - exc.retval = zero; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - *err = ERANGE; - } - break; - case 8: - /* y0(0) = -inf */ - exc.type = DOMAIN; /* should be SING for IEEE */ - exc.name = "y0"; - if (_LIB_VERSION == _SVID_) - exc.retval = -HUGE; - else - exc.retval = -HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("y0: DOMAIN error\n", 17); - } - *err = EDOM; - } - break; - case 9: - /* y0(x<0) = NaN */ - exc.type = DOMAIN; - exc.name = "y0"; - if (_LIB_VERSION == _SVID_) - exc.retval = -HUGE; - else - exc.retval = -HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("y0: DOMAIN error\n", 17); - } - *err = EDOM; - } - break; - case 10: - /* y1(0) = -inf */ - exc.type = DOMAIN; /* should be SING for IEEE */ - exc.name = "y1"; - if (_LIB_VERSION == _SVID_) - exc.retval = -HUGE; - else - exc.retval = -HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("y1: DOMAIN error\n", 17); - } - *err = EDOM; - } - break; - case 11: - /* y1(x<0) = NaN */ - exc.type = DOMAIN; - exc.name = "y1"; - if (_LIB_VERSION == _SVID_) - exc.retval = -HUGE; - else - exc.retval = -HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("y1: DOMAIN error\n", 17); - } - *err = EDOM; - } - break; - case 12: - /* yn(n,0) = -inf */ - exc.type = DOMAIN; /* should be SING for IEEE */ - exc.name = "yn"; - if (_LIB_VERSION == _SVID_) - exc.retval = -HUGE; - else - exc.retval = -HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("yn: DOMAIN error\n", 17); - } - *err = EDOM; - } - break; - case 13: - /* yn(x<0) = NaN */ - exc.type = DOMAIN; - exc.name = "yn"; - if (_LIB_VERSION == _SVID_) - exc.retval = -HUGE; - else - exc.retval = -HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("yn: DOMAIN error\n", 17); - } - *err = EDOM; - } - break; - case 14: - /* lgamma(finite) overflow */ - exc.type = OVERFLOW; - exc.name = "lgamma"; - if (_LIB_VERSION == _SVID_) - exc.retval = HUGE; - else - exc.retval = HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - *err = ERANGE; - } - break; - case 15: - /* lgamma(-integer) or lgamma(0) */ - exc.type = SING; - exc.name = "lgamma"; - if (_LIB_VERSION == _SVID_) - exc.retval = HUGE; - else - exc.retval = HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("lgamma: SING error\n", 19); - } - *err = EDOM; - } - break; - case 16: - /* log(0) */ - exc.type = SING; - exc.name = "log"; - if (_LIB_VERSION == _SVID_) - exc.retval = -HUGE; - else - exc.retval = -HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("log: SING error\n", 16); - } - *err = EDOM; - } - break; - case 17: - /* log(x<0) */ - exc.type = DOMAIN; - exc.name = "log"; - if (_LIB_VERSION == _SVID_) - exc.retval = -HUGE; - else - exc.retval = -HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("log: DOMAIN error\n", 18); - } - *err = EDOM; - } - break; - case 18: - /* log10(0) */ - exc.type = SING; - exc.name = "log10"; - if (_LIB_VERSION == _SVID_) - exc.retval = -HUGE; - else - exc.retval = -HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("log10: SING error\n", 18); - } - *err = EDOM; - } - break; - case 19: - /* log10(x<0) */ - exc.type = DOMAIN; - exc.name = "log10"; - if (_LIB_VERSION == _SVID_) - exc.retval = -HUGE; - else - exc.retval = -HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("log10: DOMAIN error\n", 20); - } - *err = EDOM; - } - break; - case 20: - /* pow(0.0,0.0) */ - /* error only if _LIB_VERSION == _SVID_ */ - exc.type = DOMAIN; - exc.name = "pow"; - exc.retval = zero; - if (_LIB_VERSION != _SVID_) exc.retval = 1.0; - else if (!fd_matherr(&exc)) { - (void) WRITE2("pow(0,0): DOMAIN error\n", 23); - *err = EDOM; - } - break; - case 21: - /* pow(x,y) overflow */ - exc.type = OVERFLOW; - exc.name = "pow"; - if (_LIB_VERSION == _SVID_) { - exc.retval = HUGE; - y *= 0.5; - if(xzero) ? HUGE : -HUGE); - else - exc.retval = ( (x>zero) ? HUGE_VAL : -HUGE_VAL); - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - *err = ERANGE; - } - break; - case 26: - /* sqrt(x<0) */ - exc.type = DOMAIN; - exc.name = "sqrt"; - if (_LIB_VERSION == _SVID_) - exc.retval = zero; - else - exc.retval = zero/zero; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("sqrt: DOMAIN error\n", 19); - } - *err = EDOM; - } - break; - case 27: - /* fmod(x,0) */ - exc.type = DOMAIN; - exc.name = "fmod"; - if (_LIB_VERSION == _SVID_) - exc.retval = x; - else - exc.retval = zero/zero; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("fmod: DOMAIN error\n", 20); - } - *err = EDOM; - } - break; - case 28: - /* remainder(x,0) */ - exc.type = DOMAIN; - exc.name = "remainder"; - exc.retval = zero/zero; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("remainder: DOMAIN error\n", 24); - } - *err = EDOM; - } - break; - case 29: - /* acosh(x<1) */ - exc.type = DOMAIN; - exc.name = "acosh"; - exc.retval = zero/zero; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("acosh: DOMAIN error\n", 20); - } - *err = EDOM; - } - break; - case 30: - /* atanh(|x|>1) */ - exc.type = DOMAIN; - exc.name = "atanh"; - exc.retval = zero/zero; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("atanh: DOMAIN error\n", 20); - } - *err = EDOM; - } - break; - case 31: - /* atanh(|x|=1) */ - exc.type = SING; - exc.name = "atanh"; - exc.retval = x/zero; /* sign(x)*inf */ - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("atanh: SING error\n", 18); - } - *err = EDOM; - } - break; - case 32: - /* scalb overflow; SVID also returns +-HUGE_VAL */ - exc.type = OVERFLOW; - exc.name = "scalb"; - exc.retval = x > zero ? HUGE_VAL : -HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - *err = ERANGE; - } - break; - case 33: - /* scalb underflow */ - exc.type = UNDERFLOW; - exc.name = "scalb"; - exc.retval = fd_copysign(zero,x); - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - *err = ERANGE; - } - break; - case 34: - /* j0(|x|>X_TLOSS) */ - exc.type = TLOSS; - exc.name = "j0"; - exc.retval = zero; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2(exc.name, 2); - (void) WRITE2(": TLOSS error\n", 14); - } - *err = ERANGE; - } - break; - case 35: - /* y0(x>X_TLOSS) */ - exc.type = TLOSS; - exc.name = "y0"; - exc.retval = zero; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2(exc.name, 2); - (void) WRITE2(": TLOSS error\n", 14); - } - *err = ERANGE; - } - break; - case 36: - /* j1(|x|>X_TLOSS) */ - exc.type = TLOSS; - exc.name = "j1"; - exc.retval = zero; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2(exc.name, 2); - (void) WRITE2(": TLOSS error\n", 14); - } - *err = ERANGE; - } - break; - case 37: - /* y1(x>X_TLOSS) */ - exc.type = TLOSS; - exc.name = "y1"; - exc.retval = zero; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2(exc.name, 2); - (void) WRITE2(": TLOSS error\n", 14); - } - *err = ERANGE; - } - break; - case 38: - /* jn(|x|>X_TLOSS) */ - exc.type = TLOSS; - exc.name = "jn"; - exc.retval = zero; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2(exc.name, 2); - (void) WRITE2(": TLOSS error\n", 14); - } - *err = ERANGE; - } - break; - case 39: - /* yn(x>X_TLOSS) */ - exc.type = TLOSS; - exc.name = "yn"; - exc.retval = zero; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2(exc.name, 2); - (void) WRITE2(": TLOSS error\n", 14); - } - *err = ERANGE; - } - break; - case 40: - /* gamma(finite) overflow */ - exc.type = OVERFLOW; - exc.name = "gamma"; - if (_LIB_VERSION == _SVID_) - exc.retval = HUGE; - else - exc.retval = HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - *err = ERANGE; - } - break; - case 41: - /* gamma(-integer) or gamma(0) */ - exc.type = SING; - exc.name = "gamma"; - if (_LIB_VERSION == _SVID_) - exc.retval = HUGE; - else - exc.retval = HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("gamma: SING error\n", 18); - } - *err = EDOM; - } - break; - case 42: - /* pow(NaN,0.0) */ - /* error only if _LIB_VERSION == _SVID_ & _XOPEN_ */ - exc.type = DOMAIN; - exc.name = "pow"; - exc.retval = x; - if (_LIB_VERSION == _IEEE_ || - _LIB_VERSION == _POSIX_) exc.retval = 1.0; - else if (!fd_matherr(&exc)) { - *err = EDOM; - } - break; - } - return exc.retval; -} diff --git a/lib/javascript/fdlibm/k_tan.c b/lib/javascript/fdlibm/k_tan.c deleted file mode 100644 index 1e7681b8..00000000 --- a/lib/javascript/fdlibm/k_tan.c +++ /dev/null @@ -1,170 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)k_tan.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* __kernel_tan( x, y, k ) - * kernel tan function on [-pi/4, pi/4], pi/4 ~ 0.7854 - * Input x is assumed to be bounded by ~pi/4 in magnitude. - * Input y is the tail of x. - * Input k indicates whether tan (if k=1) or - * -1/tan (if k= -1) is returned. - * - * Algorithm - * 1. Since tan(-x) = -tan(x), we need only to consider positive x. - * 2. if x < 2^-28 (hx<0x3e300000 0), return x with inexact if x!=0. - * 3. tan(x) is approximated by a odd polynomial of degree 27 on - * [0,0.67434] - * 3 27 - * tan(x) ~ x + T1*x + ... + T13*x - * where - * - * |tan(x) 2 4 26 | -59.2 - * |----- - (1+T1*x +T2*x +.... +T13*x )| <= 2 - * | x | - * - * Note: tan(x+y) = tan(x) + tan'(x)*y - * ~ tan(x) + (1+x*x)*y - * Therefore, for better accuracy in computing tan(x+y), let - * 3 2 2 2 2 - * r = x *(T2+x *(T3+x *(...+x *(T12+x *T13)))) - * then - * 3 2 - * tan(x+y) = x + (T1*x + (x *(r+y)+y)) - * - * 4. For x in [0.67434,pi/4], let y = pi/4 - x, then - * tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y)) - * = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y))) - */ - -#include "fdlibm.h" -#ifdef __STDC__ -static const double -#else -static double -#endif -one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ -pio4 = 7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */ -pio4lo= 3.06161699786838301793e-17, /* 0x3C81A626, 0x33145C07 */ -T[] = { - 3.33333333333334091986e-01, /* 0x3FD55555, 0x55555563 */ - 1.33333333333201242699e-01, /* 0x3FC11111, 0x1110FE7A */ - 5.39682539762260521377e-02, /* 0x3FABA1BA, 0x1BB341FE */ - 2.18694882948595424599e-02, /* 0x3F9664F4, 0x8406D637 */ - 8.86323982359930005737e-03, /* 0x3F8226E3, 0xE96E8493 */ - 3.59207910759131235356e-03, /* 0x3F6D6D22, 0xC9560328 */ - 1.45620945432529025516e-03, /* 0x3F57DBC8, 0xFEE08315 */ - 5.88041240820264096874e-04, /* 0x3F4344D8, 0xF2F26501 */ - 2.46463134818469906812e-04, /* 0x3F3026F7, 0x1A8D1068 */ - 7.81794442939557092300e-05, /* 0x3F147E88, 0xA03792A6 */ - 7.14072491382608190305e-05, /* 0x3F12B80F, 0x32F0A7E9 */ - -1.85586374855275456654e-05, /* 0xBEF375CB, 0xDB605373 */ - 2.59073051863633712884e-05, /* 0x3EFB2A70, 0x74BF7AD4 */ -}; - -#ifdef __STDC__ - double __kernel_tan(double x, double y, int iy) -#else - double __kernel_tan(x, y, iy) - double x,y; int iy; -#endif -{ - fd_twoints u; - double z,r,v,w,s; - int ix,hx; - u.d = x; - hx = __HI(u); /* high word of x */ - ix = hx&0x7fffffff; /* high word of |x| */ - if(ix<0x3e300000) /* x < 2**-28 */ - {if((int)x==0) { /* generate inexact */ - u.d =x; - if(((ix|__LO(u))|(iy+1))==0) return one/fd_fabs(x); - else return (iy==1)? x: -one/x; - } - } - if(ix>=0x3FE59428) { /* |x|>=0.6744 */ - if(hx<0) {x = -x; y = -y;} - z = pio4-x; - w = pio4lo-y; - x = z+w; y = 0.0; - } - z = x*x; - w = z*z; - /* Break x^5*(T[1]+x^2*T[2]+...) into - * x^5(T[1]+x^4*T[3]+...+x^20*T[11]) + - * x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12])) - */ - r = T[1]+w*(T[3]+w*(T[5]+w*(T[7]+w*(T[9]+w*T[11])))); - v = z*(T[2]+w*(T[4]+w*(T[6]+w*(T[8]+w*(T[10]+w*T[12]))))); - s = z*x; - r = y + z*(s*(r+v)+y); - r += T[0]*s; - w = x+r; - if(ix>=0x3FE59428) { - v = (double)iy; - return (double)(1-((hx>>30)&2))*(v-2.0*(x-(w*w/(w+v)-r))); - } - if(iy==1) return w; - else { /* if allow error up to 2 ulp, - simply return -1.0/(x+r) here */ - /* compute -1.0/(x+r) accurately */ - double a,t; - z = w; - u.d = z; - __LO(u) = 0; - z = u.d; - v = r-(z - x); /* z+v = r+x */ - t = a = -1.0/w; /* a = -1.0/w */ - u.d = t; - __LO(u) = 0; - t = u.d; - s = 1.0+t*z; - return t+a*(s+t*v); - } -} diff --git a/lib/javascript/fdlibm/s_asinh.c b/lib/javascript/fdlibm/s_asinh.c deleted file mode 100644 index fdf70a91..00000000 --- a/lib/javascript/fdlibm/s_asinh.c +++ /dev/null @@ -1,101 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_asinh.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* asinh(x) - * Method : - * Based on - * asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ] - * we have - * asinh(x) := x if 1+x*x=1, - * := sign(x)*(log(x)+ln2)) for large |x|, else - * := sign(x)*log(2|x|+1/(|x|+sqrt(x*x+1))) if|x|>2, else - * := sign(x)*log1p(|x| + x^2/(1 + sqrt(1+x^2))) - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ -ln2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */ -really_big= 1.00000000000000000000e+300; - -#ifdef __STDC__ - double fd_asinh(double x) -#else - double fd_asinh(x) - double x; -#endif -{ - fd_twoints u; - double t,w; - int hx,ix; - u.d = x; - hx = __HI(u); - ix = hx&0x7fffffff; - if(ix>=0x7ff00000) return x+x; /* x is inf or NaN */ - if(ix< 0x3e300000) { /* |x|<2**-28 */ - if(really_big+x>one) return x; /* return x inexact except 0 */ - } - if(ix>0x41b00000) { /* |x| > 2**28 */ - w = __ieee754_log(fd_fabs(x))+ln2; - } else if (ix>0x40000000) { /* 2**28 > |x| > 2.0 */ - t = fd_fabs(x); - w = __ieee754_log(2.0*t+one/(fd_sqrt(x*x+one)+t)); - } else { /* 2.0 > |x| > 2**-28 */ - t = x*x; - w =fd_log1p(fd_fabs(x)+t/(one+fd_sqrt(one+t))); - } - if(hx>0) return w; else return -w; -} diff --git a/lib/javascript/fdlibm/s_atan.c b/lib/javascript/fdlibm/s_atan.c deleted file mode 100644 index 99a00c68..00000000 --- a/lib/javascript/fdlibm/s_atan.c +++ /dev/null @@ -1,175 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_atan.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -/* atan(x) - * Method - * 1. Reduce x to positive by atan(x) = -atan(-x). - * 2. According to the integer k=4t+0.25 chopped, t=x, the argument - * is further reduced to one of the following intervals and the - * arctangent of t is evaluated by the corresponding formula: - * - * [0,7/16] atan(x) = t-t^3*(a1+t^2*(a2+...(a10+t^2*a11)...) - * [7/16,11/16] atan(x) = atan(1/2) + atan( (t-0.5)/(1+t/2) ) - * [11/16.19/16] atan(x) = atan( 1 ) + atan( (t-1)/(1+t) ) - * [19/16,39/16] atan(x) = atan(3/2) + atan( (t-1.5)/(1+1.5t) ) - * [39/16,INF] atan(x) = atan(INF) + atan( -1/t ) - * - * Constants: - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double atanhi[] = { -#else -static double atanhi[] = { -#endif - 4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */ - 7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */ - 9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */ - 1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */ -}; - -#ifdef __STDC__ -static const double atanlo[] = { -#else -static double atanlo[] = { -#endif - 2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */ - 3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */ - 1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */ - 6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */ -}; - -#ifdef __STDC__ -static const double aT[] = { -#else -static double aT[] = { -#endif - 3.33333333333329318027e-01, /* 0x3FD55555, 0x5555550D */ - -1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */ - 1.42857142725034663711e-01, /* 0x3FC24924, 0x920083FF */ - -1.11111104054623557880e-01, /* 0xBFBC71C6, 0xFE231671 */ - 9.09088713343650656196e-02, /* 0x3FB745CD, 0xC54C206E */ - -7.69187620504482999495e-02, /* 0xBFB3B0F2, 0xAF749A6D */ - 6.66107313738753120669e-02, /* 0x3FB10D66, 0xA0D03D51 */ - -5.83357013379057348645e-02, /* 0xBFADDE2D, 0x52DEFD9A */ - 4.97687799461593236017e-02, /* 0x3FA97B4B, 0x24760DEB */ - -3.65315727442169155270e-02, /* 0xBFA2B444, 0x2C6A6C2F */ - 1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */ -}; - -#ifdef __STDC__ - static const double -#else - static double -#endif -one = 1.0, -really_big = 1.0e300; - -#ifdef __STDC__ - double fd_atan(double x) -#else - double fd_atan(x) - double x; -#endif -{ - fd_twoints u; - double w,s1,s2,z; - int ix,hx,id; - - u.d = x; - hx = __HI(u); - ix = hx&0x7fffffff; - if(ix>=0x44100000) { /* if |x| >= 2^66 */ - u.d = x; - if(ix>0x7ff00000|| - (ix==0x7ff00000&&(__LO(u)!=0))) - return x+x; /* NaN */ - if(hx>0) return atanhi[3]+atanlo[3]; - else return -atanhi[3]-atanlo[3]; - } if (ix < 0x3fdc0000) { /* |x| < 0.4375 */ - if (ix < 0x3e200000) { /* |x| < 2^-29 */ - if(really_big+x>one) return x; /* raise inexact */ - } - id = -1; - } else { - x = fd_fabs(x); - if (ix < 0x3ff30000) { /* |x| < 1.1875 */ - if (ix < 0x3fe60000) { /* 7/16 <=|x|<11/16 */ - id = 0; x = (2.0*x-one)/(2.0+x); - } else { /* 11/16<=|x|< 19/16 */ - id = 1; x = (x-one)/(x+one); - } - } else { - if (ix < 0x40038000) { /* |x| < 2.4375 */ - id = 2; x = (x-1.5)/(one+1.5*x); - } else { /* 2.4375 <= |x| < 2^66 */ - id = 3; x = -1.0/x; - } - }} - /* end of argument reduction */ - z = x*x; - w = z*z; - /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */ - s1 = z*(aT[0]+w*(aT[2]+w*(aT[4]+w*(aT[6]+w*(aT[8]+w*aT[10]))))); - s2 = w*(aT[1]+w*(aT[3]+w*(aT[5]+w*(aT[7]+w*aT[9])))); - if (id<0) return x - x*(s1+s2); - else { - z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x); - return (hx<0)? -z:z; - } -} diff --git a/lib/javascript/fdlibm/s_cbrt.c b/lib/javascript/fdlibm/s_cbrt.c deleted file mode 100644 index 4aed19b1..00000000 --- a/lib/javascript/fdlibm/s_cbrt.c +++ /dev/null @@ -1,133 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_cbrt.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -#include "fdlibm.h" - -/* cbrt(x) - * Return cube root of x - */ -#ifdef __STDC__ -static const unsigned -#else -static unsigned -#endif - B1 = 715094163, /* B1 = (682-0.03306235651)*2**20 */ - B2 = 696219795; /* B2 = (664-0.03306235651)*2**20 */ - -#ifdef __STDC__ -static const double -#else -static double -#endif -C = 5.42857142857142815906e-01, /* 19/35 = 0x3FE15F15, 0xF15F15F1 */ -D = -7.05306122448979611050e-01, /* -864/1225 = 0xBFE691DE, 0x2532C834 */ -E = 1.41428571428571436819e+00, /* 99/70 = 0x3FF6A0EA, 0x0EA0EA0F */ -F = 1.60714285714285720630e+00, /* 45/28 = 0x3FF9B6DB, 0x6DB6DB6E */ -G = 3.57142857142857150787e-01; /* 5/14 = 0x3FD6DB6D, 0xB6DB6DB7 */ - -#ifdef __STDC__ - double fd_cbrt(double x) -#else - double fd_cbrt(x) - double x; -#endif -{ - fd_twoints u; - int hx; - double r,s,t=0.0,w; - unsigned sign; - - u.d = x; - hx = __HI(u); /* high word of x */ - sign=hx&0x80000000; /* sign= sign(x) */ - hx ^=sign; - if(hx>=0x7ff00000) return(x+x); /* cbrt(NaN,INF) is itself */ - if((hx|__LO(u))==0) { - x = u.d; - return(x); /* cbrt(0) is itself */ - } - u.d = x; - __HI(u) = hx; /* x <- |x| */ - x = u.d; - /* rough cbrt to 5 bits */ - if(hx<0x00100000) /* subnormal number */ - {u.d = t; __HI(u)=0x43500000; t=u.d; /* set t= 2**54 */ - t*=x; __HI(u)=__HI(u)/3+B2; - } - else { - u.d = t; __HI(u)=hx/3+B1; t = u.d; - } - - - /* new cbrt to 23 bits, may be implemented in single precision */ - r=t*t/x; - s=C+r*t; - t*=G+F/(s+E+D/s); - - /* chopped to 20 bits and make it larger than cbrt(x) */ - u.d = t; - __LO(u)=0; __HI(u)+=0x00000001; - t = u.d; - - /* one step newton iteration to 53 bits with error less than 0.667 ulps */ - s=t*t; /* t*t is exact */ - r=x/s; - w=t+t; - r=(r-t)/(w+r); /* r-s is exact */ - t=t+t*r; - - /* retore the sign bit */ - u.d = t; - __HI(u) |= sign; - t = u.d; - return(t); -} diff --git a/lib/javascript/fdlibm/s_ceil.c b/lib/javascript/fdlibm/s_ceil.c deleted file mode 100644 index 826bcac6..00000000 --- a/lib/javascript/fdlibm/s_ceil.c +++ /dev/null @@ -1,120 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_ceil.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * ceil(x) - * Return x rounded toward -inf to integral value - * Method: - * Bit twiddling. - * Exception: - * Inexact flag raised if x not equal to ceil(x). - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double really_big = 1.0e300; -#else -static double really_big = 1.0e300; -#endif - -#ifdef __STDC__ - double fd_ceil(double x) -#else - double fd_ceil(x) - double x; -#endif -{ - fd_twoints u; - int i0,i1,j0; - unsigned i,j; - u.d = x; - i0 = __HI(u); - i1 = __LO(u); - j0 = ((i0>>20)&0x7ff)-0x3ff; - if(j0<20) { - if(j0<0) { /* raise inexact if x != 0 */ - if(really_big+x>0.0) {/* return 0*sign(x) if |x|<1 */ - if(i0<0) {i0=0x80000000;i1=0;} - else if((i0|i1)!=0) { i0=0x3ff00000;i1=0;} - } - } else { - i = (0x000fffff)>>j0; - if(((i0&i)|i1)==0) return x; /* x is integral */ - if(really_big+x>0.0) { /* raise inexact flag */ - if(i0>0) i0 += (0x00100000)>>j0; - i0 &= (~i); i1=0; - } - } - } else if (j0>51) { - if(j0==0x400) return x+x; /* inf or NaN */ - else return x; /* x is integral */ - } else { - i = ((unsigned)(0xffffffff))>>(j0-20); - if((i1&i)==0) return x; /* x is integral */ - if(really_big+x>0.0) { /* raise inexact flag */ - if(i0>0) { - if(j0==20) i0+=1; - else { - j = i1 + (1<<(52-j0)); - if((int)j=0x7ff00000) return x-x; - - /* argument reduction needed */ - else { - n = __ieee754_rem_pio2(x,y); - switch(n&3) { - case 0: return __kernel_cos(y[0],y[1]); - case 1: return -__kernel_sin(y[0],y[1],1); - case 2: return -__kernel_cos(y[0],y[1]); - default: - return __kernel_sin(y[0],y[1],1); - } - } -} diff --git a/lib/javascript/fdlibm/s_erf.c b/lib/javascript/fdlibm/s_erf.c deleted file mode 100644 index 6eae8de3..00000000 --- a/lib/javascript/fdlibm/s_erf.c +++ /dev/null @@ -1,356 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_erf.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* double erf(double x) - * double erfc(double x) - * x - * 2 |\ - * erf(x) = --------- | exp(-t*t)dt - * sqrt(pi) \| - * 0 - * - * erfc(x) = 1-erf(x) - * Note that - * erf(-x) = -erf(x) - * erfc(-x) = 2 - erfc(x) - * - * Method: - * 1. For |x| in [0, 0.84375] - * erf(x) = x + x*R(x^2) - * erfc(x) = 1 - erf(x) if x in [-.84375,0.25] - * = 0.5 + ((0.5-x)-x*R) if x in [0.25,0.84375] - * where R = P/Q where P is an odd poly of degree 8 and - * Q is an odd poly of degree 10. - * -57.90 - * | R - (erf(x)-x)/x | <= 2 - * - * - * Remark. The formula is derived by noting - * erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....) - * and that - * 2/sqrt(pi) = 1.128379167095512573896158903121545171688 - * is close to one. The interval is chosen because the fix - * point of erf(x) is near 0.6174 (i.e., erf(x)=x when x is - * near 0.6174), and by some experiment, 0.84375 is chosen to - * guarantee the error is less than one ulp for erf. - * - * 2. For |x| in [0.84375,1.25], let s = |x| - 1, and - * c = 0.84506291151 rounded to single (24 bits) - * erf(x) = sign(x) * (c + P1(s)/Q1(s)) - * erfc(x) = (1-c) - P1(s)/Q1(s) if x > 0 - * 1+(c+P1(s)/Q1(s)) if x < 0 - * |P1/Q1 - (erf(|x|)-c)| <= 2**-59.06 - * Remark: here we use the taylor series expansion at x=1. - * erf(1+s) = erf(1) + s*Poly(s) - * = 0.845.. + P1(s)/Q1(s) - * That is, we use rational approximation to approximate - * erf(1+s) - (c = (single)0.84506291151) - * Note that |P1/Q1|< 0.078 for x in [0.84375,1.25] - * where - * P1(s) = degree 6 poly in s - * Q1(s) = degree 6 poly in s - * - * 3. For x in [1.25,1/0.35(~2.857143)], - * erfc(x) = (1/x)*exp(-x*x-0.5625+R1/S1) - * erf(x) = 1 - erfc(x) - * where - * R1(z) = degree 7 poly in z, (z=1/x^2) - * S1(z) = degree 8 poly in z - * - * 4. For x in [1/0.35,28] - * erfc(x) = (1/x)*exp(-x*x-0.5625+R2/S2) if x > 0 - * = 2.0 - (1/x)*exp(-x*x-0.5625+R2/S2) if -6 x >= 28 - * erf(x) = sign(x) *(1 - tiny) (raise inexact) - * erfc(x) = tiny*tiny (raise underflow) if x > 0 - * = 2 - tiny if x<0 - * - * 7. Special case: - * erf(0) = 0, erf(inf) = 1, erf(-inf) = -1, - * erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2, - * erfc/erf(NaN) is NaN - */ - - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -tiny = 1e-300, -half= 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ -one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ -two = 2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */ - /* c = (float)0.84506291151 */ -erx = 8.45062911510467529297e-01, /* 0x3FEB0AC1, 0x60000000 */ -/* - * Coefficients for approximation to erf on [0,0.84375] - */ -efx = 1.28379167095512586316e-01, /* 0x3FC06EBA, 0x8214DB69 */ -efx8= 1.02703333676410069053e+00, /* 0x3FF06EBA, 0x8214DB69 */ -pp0 = 1.28379167095512558561e-01, /* 0x3FC06EBA, 0x8214DB68 */ -pp1 = -3.25042107247001499370e-01, /* 0xBFD4CD7D, 0x691CB913 */ -pp2 = -2.84817495755985104766e-02, /* 0xBF9D2A51, 0xDBD7194F */ -pp3 = -5.77027029648944159157e-03, /* 0xBF77A291, 0x236668E4 */ -pp4 = -2.37630166566501626084e-05, /* 0xBEF8EAD6, 0x120016AC */ -qq1 = 3.97917223959155352819e-01, /* 0x3FD97779, 0xCDDADC09 */ -qq2 = 6.50222499887672944485e-02, /* 0x3FB0A54C, 0x5536CEBA */ -qq3 = 5.08130628187576562776e-03, /* 0x3F74D022, 0xC4D36B0F */ -qq4 = 1.32494738004321644526e-04, /* 0x3F215DC9, 0x221C1A10 */ -qq5 = -3.96022827877536812320e-06, /* 0xBED09C43, 0x42A26120 */ -/* - * Coefficients for approximation to erf in [0.84375,1.25] - */ -pa0 = -2.36211856075265944077e-03, /* 0xBF6359B8, 0xBEF77538 */ -pa1 = 4.14856118683748331666e-01, /* 0x3FDA8D00, 0xAD92B34D */ -pa2 = -3.72207876035701323847e-01, /* 0xBFD7D240, 0xFBB8C3F1 */ -pa3 = 3.18346619901161753674e-01, /* 0x3FD45FCA, 0x805120E4 */ -pa4 = -1.10894694282396677476e-01, /* 0xBFBC6398, 0x3D3E28EC */ -pa5 = 3.54783043256182359371e-02, /* 0x3FA22A36, 0x599795EB */ -pa6 = -2.16637559486879084300e-03, /* 0xBF61BF38, 0x0A96073F */ -qa1 = 1.06420880400844228286e-01, /* 0x3FBB3E66, 0x18EEE323 */ -qa2 = 5.40397917702171048937e-01, /* 0x3FE14AF0, 0x92EB6F33 */ -qa3 = 7.18286544141962662868e-02, /* 0x3FB2635C, 0xD99FE9A7 */ -qa4 = 1.26171219808761642112e-01, /* 0x3FC02660, 0xE763351F */ -qa5 = 1.36370839120290507362e-02, /* 0x3F8BEDC2, 0x6B51DD1C */ -qa6 = 1.19844998467991074170e-02, /* 0x3F888B54, 0x5735151D */ -/* - * Coefficients for approximation to erfc in [1.25,1/0.35] - */ -ra0 = -9.86494403484714822705e-03, /* 0xBF843412, 0x600D6435 */ -ra1 = -6.93858572707181764372e-01, /* 0xBFE63416, 0xE4BA7360 */ -ra2 = -1.05586262253232909814e+01, /* 0xC0251E04, 0x41B0E726 */ -ra3 = -6.23753324503260060396e+01, /* 0xC04F300A, 0xE4CBA38D */ -ra4 = -1.62396669462573470355e+02, /* 0xC0644CB1, 0x84282266 */ -ra5 = -1.84605092906711035994e+02, /* 0xC067135C, 0xEBCCABB2 */ -ra6 = -8.12874355063065934246e+01, /* 0xC0545265, 0x57E4D2F2 */ -ra7 = -9.81432934416914548592e+00, /* 0xC023A0EF, 0xC69AC25C */ -sa1 = 1.96512716674392571292e+01, /* 0x4033A6B9, 0xBD707687 */ -sa2 = 1.37657754143519042600e+02, /* 0x4061350C, 0x526AE721 */ -sa3 = 4.34565877475229228821e+02, /* 0x407B290D, 0xD58A1A71 */ -sa4 = 6.45387271733267880336e+02, /* 0x40842B19, 0x21EC2868 */ -sa5 = 4.29008140027567833386e+02, /* 0x407AD021, 0x57700314 */ -sa6 = 1.08635005541779435134e+02, /* 0x405B28A3, 0xEE48AE2C */ -sa7 = 6.57024977031928170135e+00, /* 0x401A47EF, 0x8E484A93 */ -sa8 = -6.04244152148580987438e-02, /* 0xBFAEEFF2, 0xEE749A62 */ -/* - * Coefficients for approximation to erfc in [1/.35,28] - */ -rb0 = -9.86494292470009928597e-03, /* 0xBF843412, 0x39E86F4A */ -rb1 = -7.99283237680523006574e-01, /* 0xBFE993BA, 0x70C285DE */ -rb2 = -1.77579549177547519889e+01, /* 0xC031C209, 0x555F995A */ -rb3 = -1.60636384855821916062e+02, /* 0xC064145D, 0x43C5ED98 */ -rb4 = -6.37566443368389627722e+02, /* 0xC083EC88, 0x1375F228 */ -rb5 = -1.02509513161107724954e+03, /* 0xC0900461, 0x6A2E5992 */ -rb6 = -4.83519191608651397019e+02, /* 0xC07E384E, 0x9BDC383F */ -sb1 = 3.03380607434824582924e+01, /* 0x403E568B, 0x261D5190 */ -sb2 = 3.25792512996573918826e+02, /* 0x40745CAE, 0x221B9F0A */ -sb3 = 1.53672958608443695994e+03, /* 0x409802EB, 0x189D5118 */ -sb4 = 3.19985821950859553908e+03, /* 0x40A8FFB7, 0x688C246A */ -sb5 = 2.55305040643316442583e+03, /* 0x40A3F219, 0xCEDF3BE6 */ -sb6 = 4.74528541206955367215e+02, /* 0x407DA874, 0xE79FE763 */ -sb7 = -2.24409524465858183362e+01; /* 0xC03670E2, 0x42712D62 */ - -#ifdef __STDC__ - double fd_erf(double x) -#else - double fd_erf(x) - double x; -#endif -{ - fd_twoints u; - int hx,ix,i; - double R,S,P,Q,s,y,z,r; - u.d = x; - hx = __HI(u); - ix = hx&0x7fffffff; - if(ix>=0x7ff00000) { /* erf(nan)=nan */ - i = ((unsigned)hx>>31)<<1; - return (double)(1-i)+one/x; /* erf(+-inf)=+-1 */ - } - - if(ix < 0x3feb0000) { /* |x|<0.84375 */ - if(ix < 0x3e300000) { /* |x|<2**-28 */ - if (ix < 0x00800000) - return 0.125*(8.0*x+efx8*x); /*avoid underflow */ - return x + efx*x; - } - z = x*x; - r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4))); - s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5)))); - y = r/s; - return x + x*y; - } - if(ix < 0x3ff40000) { /* 0.84375 <= |x| < 1.25 */ - s = fd_fabs(x)-one; - P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6))))); - Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6))))); - if(hx>=0) return erx + P/Q; else return -erx - P/Q; - } - if (ix >= 0x40180000) { /* inf>|x|>=6 */ - if(hx>=0) return one-tiny; else return tiny-one; - } - x = fd_fabs(x); - s = one/(x*x); - if(ix< 0x4006DB6E) { /* |x| < 1/0.35 */ - R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*( - ra5+s*(ra6+s*ra7)))))); - S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*( - sa5+s*(sa6+s*(sa7+s*sa8))))))); - } else { /* |x| >= 1/0.35 */ - R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*( - rb5+s*rb6))))); - S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*( - sb5+s*(sb6+s*sb7)))))); - } - z = x; - u.d = z; - __LO(u) = 0; - z = u.d; - r = __ieee754_exp(-z*z-0.5625)*__ieee754_exp((z-x)*(z+x)+R/S); - if(hx>=0) return one-r/x; else return r/x-one; -} - -#ifdef __STDC__ - double erfc(double x) -#else - double erfc(x) - double x; -#endif -{ - fd_twoints u; - int hx,ix; - double R,S,P,Q,s,y,z,r; - u.d = x; - hx = __HI(u); - ix = hx&0x7fffffff; - if(ix>=0x7ff00000) { /* erfc(nan)=nan */ - /* erfc(+-inf)=0,2 */ - return (double)(((unsigned)hx>>31)<<1)+one/x; - } - - if(ix < 0x3feb0000) { /* |x|<0.84375 */ - if(ix < 0x3c700000) /* |x|<2**-56 */ - return one-x; - z = x*x; - r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4))); - s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5)))); - y = r/s; - if(hx < 0x3fd00000) { /* x<1/4 */ - return one-(x+x*y); - } else { - r = x*y; - r += (x-half); - return half - r ; - } - } - if(ix < 0x3ff40000) { /* 0.84375 <= |x| < 1.25 */ - s = fd_fabs(x)-one; - P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6))))); - Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6))))); - if(hx>=0) { - z = one-erx; return z - P/Q; - } else { - z = erx+P/Q; return one+z; - } - } - if (ix < 0x403c0000) { /* |x|<28 */ - x = fd_fabs(x); - s = one/(x*x); - if(ix< 0x4006DB6D) { /* |x| < 1/.35 ~ 2.857143*/ - R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*( - ra5+s*(ra6+s*ra7)))))); - S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*( - sa5+s*(sa6+s*(sa7+s*sa8))))))); - } else { /* |x| >= 1/.35 ~ 2.857143 */ - if(hx<0&&ix>=0x40180000) return two-tiny;/* x < -6 */ - R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*( - rb5+s*rb6))))); - S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*( - sb5+s*(sb6+s*sb7)))))); - } - z = x; - u.d = z; - __LO(u) = 0; - z = u.d; - r = __ieee754_exp(-z*z-0.5625)* - __ieee754_exp((z-x)*(z+x)+R/S); - if(hx>0) return r/x; else return two-r/x; - } else { - if(hx>0) return tiny*tiny; else return two-tiny; - } -} diff --git a/lib/javascript/fdlibm/s_expm1.c b/lib/javascript/fdlibm/s_expm1.c deleted file mode 100644 index 578d2e14..00000000 --- a/lib/javascript/fdlibm/s_expm1.c +++ /dev/null @@ -1,267 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_expm1.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* expm1(x) - * Returns exp(x)-1, the exponential of x minus 1. - * - * Method - * 1. Argument reduction: - * Given x, find r and integer k such that - * - * x = k*ln2 + r, |r| <= 0.5*ln2 ~ 0.34658 - * - * Here a correction term c will be computed to compensate - * the error in r when rounded to a floating-point number. - * - * 2. Approximating expm1(r) by a special rational function on - * the interval [0,0.34658]: - * Since - * r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 - r^4/360 + ... - * we define R1(r*r) by - * r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 * R1(r*r) - * That is, - * R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r) - * = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r)) - * = 1 - r^2/60 + r^4/2520 - r^6/100800 + ... - * We use a special Reme algorithm on [0,0.347] to generate - * a polynomial of degree 5 in r*r to approximate R1. The - * maximum error of this polynomial approximation is bounded - * by 2**-61. In other words, - * R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5 - * where Q1 = -1.6666666666666567384E-2, - * Q2 = 3.9682539681370365873E-4, - * Q3 = -9.9206344733435987357E-6, - * Q4 = 2.5051361420808517002E-7, - * Q5 = -6.2843505682382617102E-9; - * (where z=r*r, and the values of Q1 to Q5 are listed below) - * with error bounded by - * | 5 | -61 - * | 1.0+Q1*z+...+Q5*z - R1(z) | <= 2 - * | | - * - * expm1(r) = exp(r)-1 is then computed by the following - * specific way which minimize the accumulation rounding error: - * 2 3 - * r r [ 3 - (R1 + R1*r/2) ] - * expm1(r) = r + --- + --- * [--------------------] - * 2 2 [ 6 - r*(3 - R1*r/2) ] - * - * To compensate the error in the argument reduction, we use - * expm1(r+c) = expm1(r) + c + expm1(r)*c - * ~ expm1(r) + c + r*c - * Thus c+r*c will be added in as the correction terms for - * expm1(r+c). Now rearrange the term to avoid optimization - * screw up: - * ( 2 2 ) - * ({ ( r [ R1 - (3 - R1*r/2) ] ) } r ) - * expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- ) - * ({ ( 2 [ 6 - r*(3 - R1*r/2) ] ) } 2 ) - * ( ) - * - * = r - E - * 3. Scale back to obtain expm1(x): - * From step 1, we have - * expm1(x) = either 2^k*[expm1(r)+1] - 1 - * = or 2^k*[expm1(r) + (1-2^-k)] - * 4. Implementation notes: - * (A). To save one multiplication, we scale the coefficient Qi - * to Qi*2^i, and replace z by (x^2)/2. - * (B). To achieve maximum accuracy, we compute expm1(x) by - * (i) if x < -56*ln2, return -1.0, (raise inexact if x!=inf) - * (ii) if k=0, return r-E - * (iii) if k=-1, return 0.5*(r-E)-0.5 - * (iv) if k=1 if r < -0.25, return 2*((r+0.5)- E) - * else return 1.0+2.0*(r-E); - * (v) if (k<-2||k>56) return 2^k(1-(E-r)) - 1 (or exp(x)-1) - * (vi) if k <= 20, return 2^k((1-2^-k)-(E-r)), else - * (vii) return 2^k(1-((E+2^-k)-r)) - * - * Special cases: - * expm1(INF) is INF, expm1(NaN) is NaN; - * expm1(-INF) is -1, and - * for finite argument, only expm1(0)=0 is exact. - * - * Accuracy: - * according to an error analysis, the error is always less than - * 1 ulp (unit in the last place). - * - * Misc. info. - * For IEEE double - * if x > 7.09782712893383973096e+02 then expm1(x) overflow - * - * Constants: - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -one = 1.0, -really_big = 1.0e+300, -tiny = 1.0e-300, -o_threshold = 7.09782712893383973096e+02,/* 0x40862E42, 0xFEFA39EF */ -ln2_hi = 6.93147180369123816490e-01,/* 0x3fe62e42, 0xfee00000 */ -ln2_lo = 1.90821492927058770002e-10,/* 0x3dea39ef, 0x35793c76 */ -invln2 = 1.44269504088896338700e+00,/* 0x3ff71547, 0x652b82fe */ - /* scaled coefficients related to expm1 */ -Q1 = -3.33333333333331316428e-02, /* BFA11111 111110F4 */ -Q2 = 1.58730158725481460165e-03, /* 3F5A01A0 19FE5585 */ -Q3 = -7.93650757867487942473e-05, /* BF14CE19 9EAADBB7 */ -Q4 = 4.00821782732936239552e-06, /* 3ED0CFCA 86E65239 */ -Q5 = -2.01099218183624371326e-07; /* BE8AFDB7 6E09C32D */ - -#ifdef __STDC__ - double fd_expm1(double x) -#else - double fd_expm1(x) - double x; -#endif -{ - fd_twoints u; - double y,hi,lo,c,t,e,hxs,hfx,r1; - int k,xsb; - unsigned hx; - - u.d = x; - hx = __HI(u); /* high word of x */ - xsb = hx&0x80000000; /* sign bit of x */ - if(xsb==0) y=x; else y= -x; /* y = |x| */ - hx &= 0x7fffffff; /* high word of |x| */ - - /* filter out huge and non-finite argument */ - if(hx >= 0x4043687A) { /* if |x|>=56*ln2 */ - if(hx >= 0x40862E42) { /* if |x|>=709.78... */ - if(hx>=0x7ff00000) { - u.d = x; - if(((hx&0xfffff)|__LO(u))!=0) - return x+x; /* NaN */ - else return (xsb==0)? x:-1.0;/* exp(+-inf)={inf,-1} */ - } - if(x > o_threshold) return really_big*really_big; /* overflow */ - } - if(xsb!=0) { /* x < -56*ln2, return -1.0 with inexact */ - if(x+tiny<0.0) /* raise inexact */ - return tiny-one; /* return -1 */ - } - } - - /* argument reduction */ - if(hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */ - if(hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */ - if(xsb==0) - {hi = x - ln2_hi; lo = ln2_lo; k = 1;} - else - {hi = x + ln2_hi; lo = -ln2_lo; k = -1;} - } else { - k = (int)(invln2*x+((xsb==0)?0.5:-0.5)); - t = k; - hi = x - t*ln2_hi; /* t*ln2_hi is exact here */ - lo = t*ln2_lo; - } - x = hi - lo; - c = (hi-x)-lo; - } - else if(hx < 0x3c900000) { /* when |x|<2**-54, return x */ - t = really_big+x; /* return x with inexact flags when x!=0 */ - return x - (t-(really_big+x)); - } - else k = 0; - - /* x is now in primary range */ - hfx = 0.5*x; - hxs = x*hfx; - r1 = one+hxs*(Q1+hxs*(Q2+hxs*(Q3+hxs*(Q4+hxs*Q5)))); - t = 3.0-r1*hfx; - e = hxs*((r1-t)/(6.0 - x*t)); - if(k==0) return x - (x*e-hxs); /* c is 0 */ - else { - e = (x*(e-c)-c); - e -= hxs; - if(k== -1) return 0.5*(x-e)-0.5; - if(k==1) - if(x < -0.25) return -2.0*(e-(x+0.5)); - else return one+2.0*(x-e); - if (k <= -2 || k>56) { /* suffice to return exp(x)-1 */ - y = one-(e-x); - u.d = y; - __HI(u) += (k<<20); /* add k to y's exponent */ - y = u.d; - return y-one; - } - t = one; - if(k<20) { - u.d = t; - __HI(u) = 0x3ff00000 - (0x200000>>k); /* t=1-2^-k */ - t = u.d; - y = t-(e-x); - u.d = y; - __HI(u) += (k<<20); /* add k to y's exponent */ - y = u.d; - } else { - u.d = t; - __HI(u) = ((0x3ff-k)<<20); /* 2^-k */ - t = u.d; - y = x-(e+t); - y += one; - u.d = y; - __HI(u) += (k<<20); /* add k to y's exponent */ - y = u.d; - } - } - return y; -} diff --git a/lib/javascript/fdlibm/s_fabs.c b/lib/javascript/fdlibm/s_fabs.c deleted file mode 100644 index 6b029da1..00000000 --- a/lib/javascript/fdlibm/s_fabs.c +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_fabs.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * fabs(x) returns the absolute value of x. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double fd_fabs(double x) -#else - double fd_fabs(x) - double x; -#endif -{ - fd_twoints u; - u.d = x; - __HI(u) &= 0x7fffffff; - x = u.d; - return x; -} diff --git a/lib/javascript/fdlibm/s_finite.c b/lib/javascript/fdlibm/s_finite.c deleted file mode 100644 index 4a0a4d3c..00000000 --- a/lib/javascript/fdlibm/s_finite.c +++ /dev/null @@ -1,71 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_finite.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * finite(x) returns 1 is x is finite, else 0; - * no branching! - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - int fd_finite(double x) -#else - int fd_finite(x) - double x; -#endif -{ - fd_twoints u; - int hx; - u.d = x; - hx = __HI(u); - return (unsigned)((hx&0x7fffffff)-0x7ff00000)>>31; -} diff --git a/lib/javascript/fdlibm/s_floor.c b/lib/javascript/fdlibm/s_floor.c deleted file mode 100644 index 6c23495f..00000000 --- a/lib/javascript/fdlibm/s_floor.c +++ /dev/null @@ -1,121 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_floor.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * floor(x) - * Return x rounded toward -inf to integral value - * Method: - * Bit twiddling. - * Exception: - * Inexact flag raised if x not equal to floor(x). - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double really_big = 1.0e300; -#else -static double really_big = 1.0e300; -#endif - -#ifdef __STDC__ - double fd_floor(double x) -#else - double fd_floor(x) - double x; -#endif -{ - fd_twoints u; - int i0,i1,j0; - unsigned i,j; - u.d = x; - i0 = __HI(u); - i1 = __LO(u); - j0 = ((i0>>20)&0x7ff)-0x3ff; - if(j0<20) { - if(j0<0) { /* raise inexact if x != 0 */ - if(really_big+x>0.0) {/* return 0*sign(x) if |x|<1 */ - if(i0>=0) {i0=i1=0;} - else if(((i0&0x7fffffff)|i1)!=0) - { i0=0xbff00000;i1=0;} - } - } else { - i = (0x000fffff)>>j0; - if(((i0&i)|i1)==0) return x; /* x is integral */ - if(really_big+x>0.0) { /* raise inexact flag */ - if(i0<0) i0 += (0x00100000)>>j0; - i0 &= (~i); i1=0; - } - } - } else if (j0>51) { - if(j0==0x400) return x+x; /* inf or NaN */ - else return x; /* x is integral */ - } else { - i = ((unsigned)(0xffffffff))>>(j0-20); - if((i1&i)==0) return x; /* x is integral */ - if(really_big+x>0.0) { /* raise inexact flag */ - if(i0<0) { - if(j0==20) i0+=1; - else { - j = i1+(1<<(52-j0)); - if((int)j=0x7ff00000||((ix|lx)==0)) return x; /* 0,inf,nan */ - if (ix<0x00100000) { /* subnormal */ - x *= two54; - u.d = x; - hx = __HI(u); - ix = hx&0x7fffffff; - *eptr = -54; - } - *eptr += (ix>>20)-1022; - hx = (hx&0x800fffff)|0x3fe00000; - u.d = x; - __HI(u) = hx; - x = u.d; - return x; -} diff --git a/lib/javascript/fdlibm/s_ilogb.c b/lib/javascript/fdlibm/s_ilogb.c deleted file mode 100644 index f769781a..00000000 --- a/lib/javascript/fdlibm/s_ilogb.c +++ /dev/null @@ -1,85 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_ilogb.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* ilogb(double x) - * return the binary exponent of non-zero x - * ilogb(0) = 0x80000001 - * ilogb(inf/NaN) = 0x7fffffff (no signal is raised) - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - int fd_ilogb(double x) -#else - int fd_ilogb(x) - double x; -#endif -{ - int hx,lx,ix; - fd_twoints u; - u.d = x; - hx = (__HI(u))&0x7fffffff; /* high word of x */ - if(hx<0x00100000) { - lx = __LO(u); - if((hx|lx)==0) - return 0x80000001; /* ilogb(0) = 0x80000001 */ - else /* subnormal x */ - if(hx==0) { - for (ix = -1043; lx>0; lx<<=1) ix -=1; - } else { - for (ix = -1022,hx<<=11; hx>0; hx<<=1) ix -=1; - } - return ix; - } - else if (hx<0x7ff00000) return (hx>>20)-1023; - else return 0x7fffffff; -} diff --git a/lib/javascript/fdlibm/s_isnan.c b/lib/javascript/fdlibm/s_isnan.c deleted file mode 100644 index 52f8759c..00000000 --- a/lib/javascript/fdlibm/s_isnan.c +++ /dev/null @@ -1,74 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_isnan.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * isnan(x) returns 1 is x is nan, else 0; - * no branching! - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - int fd_isnan(double x) -#else - int fd_isnan(x) - double x; -#endif -{ - fd_twoints u; - int hx,lx; - u.d = x; - hx = (__HI(u)&0x7fffffff); - lx = __LO(u); - hx |= (unsigned)(lx|(-lx))>>31; - hx = 0x7ff00000 - hx; - return ((unsigned)(hx))>>31; -} diff --git a/lib/javascript/fdlibm/s_ldexp.c b/lib/javascript/fdlibm/s_ldexp.c deleted file mode 100644 index 9475520d..00000000 --- a/lib/javascript/fdlibm/s_ldexp.c +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_ldexp.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#include "fdlibm.h" -#include - -#ifdef __STDC__ - double fd_ldexp(double value, int exp) -#else - double fd_ldexp(value, exp) - double value; int exp; -#endif -{ - if(!fd_finite(value)||value==0.0) return value; - value = fd_scalbn(value,exp); - if(!fd_finite(value)||value==0.0) errno = ERANGE; - return value; -} diff --git a/lib/javascript/fdlibm/s_lib_version.c b/lib/javascript/fdlibm/s_lib_version.c deleted file mode 100644 index 2ccf67d5..00000000 --- a/lib/javascript/fdlibm/s_lib_version.c +++ /dev/null @@ -1,73 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_lib_version.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * MACRO for standards - */ - -#include "fdlibm.h" - -/* - * define and initialize _LIB_VERSION - */ -#ifdef _POSIX_MODE -_LIB_VERSION_TYPE _LIB_VERSION = _POSIX_; -#else -#ifdef _XOPEN_MODE -_LIB_VERSION_TYPE _LIB_VERSION = _XOPEN_; -#else -#ifdef _SVID3_MODE -_LIB_VERSION_TYPE _LIB_VERSION = _SVID_; -#else /* default _IEEE_MODE */ -_LIB_VERSION_TYPE _LIB_VERSION = _IEEE_; -#endif -#endif -#endif diff --git a/lib/javascript/fdlibm/s_log1p.c b/lib/javascript/fdlibm/s_log1p.c deleted file mode 100644 index 1840156b..00000000 --- a/lib/javascript/fdlibm/s_log1p.c +++ /dev/null @@ -1,211 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_log1p.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* double log1p(double x) - * - * Method : - * 1. Argument Reduction: find k and f such that - * 1+x = 2^k * (1+f), - * where sqrt(2)/2 < 1+f < sqrt(2) . - * - * Note. If k=0, then f=x is exact. However, if k!=0, then f - * may not be representable exactly. In that case, a correction - * term is need. Let u=1+x rounded. Let c = (1+x)-u, then - * log(1+x) - log(u) ~ c/u. Thus, we proceed to compute log(u), - * and add back the correction term c/u. - * (Note: when x > 2**53, one can simply return log(x)) - * - * 2. Approximation of log1p(f). - * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) - * = 2s + 2/3 s**3 + 2/5 s**5 + ....., - * = 2s + s*R - * We use a special Reme algorithm on [0,0.1716] to generate - * a polynomial of degree 14 to approximate R The maximum error - * of this polynomial approximation is bounded by 2**-58.45. In - * other words, - * 2 4 6 8 10 12 14 - * R(z) ~ Lp1*s +Lp2*s +Lp3*s +Lp4*s +Lp5*s +Lp6*s +Lp7*s - * (the values of Lp1 to Lp7 are listed in the program) - * and - * | 2 14 | -58.45 - * | Lp1*s +...+Lp7*s - R(z) | <= 2 - * | | - * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. - * In order to guarantee error in log below 1ulp, we compute log - * by - * log1p(f) = f - (hfsq - s*(hfsq+R)). - * - * 3. Finally, log1p(x) = k*ln2 + log1p(f). - * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) - * Here ln2 is split into two floating point number: - * ln2_hi + ln2_lo, - * where n*ln2_hi is always exact for |n| < 2000. - * - * Special cases: - * log1p(x) is NaN with signal if x < -1 (including -INF) ; - * log1p(+INF) is +INF; log1p(-1) is -INF with signal; - * log1p(NaN) is that NaN with no signal. - * - * Accuracy: - * according to an error analysis, the error is always less than - * 1 ulp (unit in the last place). - * - * Constants: - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - * - * Note: Assuming log() return accurate answer, the following - * algorithm can be used to compute log1p(x) to within a few ULP: - * - * u = 1+x; - * if(u==1.0) return x ; else - * return log(u)*(x/(u-1.0)); - * - * See HP-15C Advanced Functions Handbook, p.193. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */ -ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */ -two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */ -Lp1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ -Lp2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ -Lp3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ -Lp4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ -Lp5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ -Lp6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ -Lp7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ - -static double zero = 0.0; - -#ifdef __STDC__ - double fd_log1p(double x) -#else - double fd_log1p(x) - double x; -#endif -{ - double hfsq,f,c,s,z,R,u; - int k,hx,hu,ax; - fd_twoints un; - - un.d = x; - hx = __HI(un); /* high word of x */ - ax = hx&0x7fffffff; - - k = 1; - if (hx < 0x3FDA827A) { /* x < 0.41422 */ - if(ax>=0x3ff00000) { /* x <= -1.0 */ - if(x==-1.0) return -two54/zero; /* log1p(-1)=+inf */ - else return (x-x)/(x-x); /* log1p(x<-1)=NaN */ - } - if(ax<0x3e200000) { /* |x| < 2**-29 */ - if(two54+x>zero /* raise inexact */ - &&ax<0x3c900000) /* |x| < 2**-54 */ - return x; - else - return x - x*x*0.5; - } - if(hx>0||hx<=((int)0xbfd2bec3)) { - k=0;f=x;hu=1;} /* -0.2929= 0x7ff00000) return x+x; - if(k!=0) { - if(hx<0x43400000) { - u = 1.0+x; - un.d = u; - hu = __HI(un); /* high word of u */ - k = (hu>>20)-1023; - c = (k>0)? 1.0-(u-x):x-(u-1.0);/* correction term */ - c /= u; - } else { - u = x; - un.d = u; - hu = __HI(un); /* high word of u */ - k = (hu>>20)-1023; - c = 0; - } - hu &= 0x000fffff; - if(hu<0x6a09e) { - un.d = u; - __HI(un) = hu|0x3ff00000; /* normalize u */ - u = un.d; - } else { - k += 1; - un.d = u; - __HI(un) = hu|0x3fe00000; /* normalize u/2 */ - u = un.d; - hu = (0x00100000-hu)>>2; - } - f = u-1.0; - } - hfsq=0.5*f*f; - if(hu==0) { /* |f| < 2**-20 */ - if(f==zero) if(k==0) return zero; - else {c += k*ln2_lo; return k*ln2_hi+c;} - R = hfsq*(1.0-0.66666666666666666*f); - if(k==0) return f-R; else - return k*ln2_hi-((R-(k*ln2_lo+c))-f); - } - s = f/(2.0+f); - z = s*s; - R = z*(Lp1+z*(Lp2+z*(Lp3+z*(Lp4+z*(Lp5+z*(Lp6+z*Lp7)))))); - if(k==0) return f-(hfsq-s*(hfsq+R)); else - return k*ln2_hi-((hfsq-(s*(hfsq+R)+(k*ln2_lo+c)))-f); -} diff --git a/lib/javascript/fdlibm/s_logb.c b/lib/javascript/fdlibm/s_logb.c deleted file mode 100644 index f885c4dc..00000000 --- a/lib/javascript/fdlibm/s_logb.c +++ /dev/null @@ -1,79 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_logb.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * double logb(x) - * IEEE 754 logb. Included to pass IEEE test suite. Not recommend. - * Use ilogb instead. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double fd_logb(double x) -#else - double fd_logb(x) - double x; -#endif -{ - int lx,ix; - fd_twoints u; - - u.d = x; - ix = (__HI(u))&0x7fffffff; /* high |x| */ - lx = __LO(u); /* low x */ - if((ix|lx)==0) return -1.0/fd_fabs(x); - if(ix>=0x7ff00000) return x*x; - if((ix>>=20)==0) /* IEEE 754 logb */ - return -1022.0; - else - return (double) (ix-1023); -} diff --git a/lib/javascript/fdlibm/s_matherr.c b/lib/javascript/fdlibm/s_matherr.c deleted file mode 100644 index cd99ca88..00000000 --- a/lib/javascript/fdlibm/s_matherr.c +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_matherr.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - int fd_matherr(struct exception *x) -#else - int fd_matherr(x) - struct exception *x; -#endif -{ - int n=0; - if(x->arg1!=x->arg1) return 0; - return n; -} diff --git a/lib/javascript/fdlibm/s_modf.c b/lib/javascript/fdlibm/s_modf.c deleted file mode 100644 index 3b182bd3..00000000 --- a/lib/javascript/fdlibm/s_modf.c +++ /dev/null @@ -1,132 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_modf.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * modf(double x, double *iptr) - * return fraction part of x, and return x's integral part in *iptr. - * Method: - * Bit twiddling. - * - * Exception: - * No exception. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double one = 1.0; -#else -static double one = 1.0; -#endif - -#ifdef __STDC__ - double fd_modf(double x, double *iptr) -#else - double fd_modf(x, iptr) - double x,*iptr; -#endif -{ - int i0,i1,j0; - unsigned i; - fd_twoints u; - u.d = x; - i0 = __HI(u); /* high x */ - i1 = __LO(u); /* low x */ - j0 = ((i0>>20)&0x7ff)-0x3ff; /* exponent of x */ - if(j0<20) { /* integer part in high x */ - if(j0<0) { /* |x|<1 */ - u.d = *iptr; - __HI(u) = i0&0x80000000; - __LO(u) = 0; /* *iptr = +-0 */ - *iptr = u.d; - return x; - } else { - i = (0x000fffff)>>j0; - if(((i0&i)|i1)==0) { /* x is integral */ - *iptr = x; - u.d = x; - __HI(u) &= 0x80000000; - __LO(u) = 0; /* return +-0 */ - x = u.d; - return x; - } else { - u.d = *iptr; - __HI(u) = i0&(~i); - __LO(u) = 0; - *iptr = u.d; - return x - *iptr; - } - } - } else if (j0>51) { /* no fraction part */ - *iptr = x*one; - u.d = x; - __HI(u) &= 0x80000000; - __LO(u) = 0; /* return +-0 */ - x = u.d; - return x; - } else { /* fraction part in low x */ - i = ((unsigned)(0xffffffff))>>(j0-20); - if((i1&i)==0) { /* x is integral */ - *iptr = x; - u.d = x; - __HI(u) &= 0x80000000; - __LO(u) = 0; /* return +-0 */ - x = u.d; - return x; - } else { - u.d = *iptr; - __HI(u) = i0; - __LO(u) = i1&(~i); - *iptr = u.d; - return x - *iptr; - } - } -} diff --git a/lib/javascript/fdlibm/s_nextafter.c b/lib/javascript/fdlibm/s_nextafter.c deleted file mode 100644 index f71c5c83..00000000 --- a/lib/javascript/fdlibm/s_nextafter.c +++ /dev/null @@ -1,124 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_nextafter.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* IEEE functions - * nextafter(x,y) - * return the next machine floating-point number of x in the - * direction toward y. - * Special cases: - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double fd_nextafter(double x, double y) -#else - double fd_nextafter(x,y) - double x,y; -#endif -{ - int hx,hy,ix,iy; - unsigned lx,ly; - fd_twoints ux, uy; - - ux.d = x; uy.d = y; - hx = __HI(ux); /* high word of x */ - lx = __LO(ux); /* low word of x */ - hy = __HI(uy); /* high word of y */ - ly = __LO(uy); /* low word of y */ - ix = hx&0x7fffffff; /* |x| */ - iy = hy&0x7fffffff; /* |y| */ - - if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || /* x is nan */ - ((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0)) /* y is nan */ - return x+y; - if(x==y) return x; /* x=y, return x */ - if((ix|lx)==0) { /* x == 0 */ - ux.d = x; - __HI(ux) = hy&0x80000000; /* return +-minsubnormal */ - __LO(ux) = 1; - x = ux.d; - y = x*x; - if(y==x) return y; else return x; /* raise underflow flag */ - } - if(hx>=0) { /* x > 0 */ - if(hx>hy||((hx==hy)&&(lx>ly))) { /* x > y, x -= ulp */ - if(lx==0) hx -= 1; - lx -= 1; - } else { /* x < y, x += ulp */ - lx += 1; - if(lx==0) hx += 1; - } - } else { /* x < 0 */ - if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){/* x < y, x -= ulp */ - if(lx==0) hx -= 1; - lx -= 1; - } else { /* x > y, x += ulp */ - lx += 1; - if(lx==0) hx += 1; - } - } - hy = hx&0x7ff00000; - if(hy>=0x7ff00000) return x+x; /* overflow */ - if(hy<0x00100000) { /* underflow */ - y = x*x; - if(y!=x) { /* raise underflow flag */ - uy.d = y; - __HI(uy) = hx; __LO(uy) = lx; - y = uy.d; - return y; - } - } - ux.d = x; - __HI(ux) = hx; __LO(ux) = lx; - x = ux.d; - return x; -} diff --git a/lib/javascript/fdlibm/s_rint.c b/lib/javascript/fdlibm/s_rint.c deleted file mode 100644 index 3c4fab6d..00000000 --- a/lib/javascript/fdlibm/s_rint.c +++ /dev/null @@ -1,131 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_rint.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * rint(x) - * Return x rounded to integral value according to the prevailing - * rounding mode. - * Method: - * Using floating addition. - * Exception: - * Inexact flag raised if x not equal to rint(x). - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -TWO52[2]={ - 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ - -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ -}; - -#ifdef __STDC__ - double fd_rint(double x) -#else - double fd_rint(x) - double x; -#endif -{ - int i0,j0,sx; - unsigned i,i1; - double w,t; - fd_twoints u; - - u.d = x; - i0 = __HI(u); - sx = (i0>>31)&1; - i1 = __LO(u); - j0 = ((i0>>20)&0x7ff)-0x3ff; - if(j0<20) { - if(j0<0) { - if(((i0&0x7fffffff)|i1)==0) return x; - i1 |= (i0&0x0fffff); - i0 &= 0xfffe0000; - i0 |= ((i1|-(int)i1)>>12)&0x80000; - u.d = x; - __HI(u)=i0; - x = u.d; - w = TWO52[sx]+x; - t = w-TWO52[sx]; - u.d = t; - i0 = __HI(u); - __HI(u) = (i0&0x7fffffff)|(sx<<31); - t = u.d; - return t; - } else { - i = (0x000fffff)>>j0; - if(((i0&i)|i1)==0) return x; /* x is integral */ - i>>=1; - if(((i0&i)|i1)!=0) { - if(j0==19) i1 = 0x40000000; else - i0 = (i0&(~i))|((0x20000)>>j0); - } - } - } else if (j0>51) { - if(j0==0x400) return x+x; /* inf or NaN */ - else return x; /* x is integral */ - } else { - i = ((unsigned)(0xffffffff))>>(j0-20); - if((i1&i)==0) return x; /* x is integral */ - i>>=1; - if((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(j0-20)); - } - u.d = x; - __HI(u) = i0; - __LO(u) = i1; - x = u.d; - w = TWO52[sx]+x; - return w-TWO52[sx]; -} diff --git a/lib/javascript/fdlibm/s_scalbn.c b/lib/javascript/fdlibm/s_scalbn.c deleted file mode 100644 index 3deeaa30..00000000 --- a/lib/javascript/fdlibm/s_scalbn.c +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_scalbn.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * scalbn (double x, int n) - * scalbn(x,n) returns x* 2**n computed by exponent - * manipulation rather than by actually performing an - * exponentiation or a multiplication. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ -twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */ -really_big = 1.0e+300, -tiny = 1.0e-300; - -#ifdef __STDC__ - double fd_scalbn (double x, int n) -#else - double fd_scalbn (x,n) - double x; int n; -#endif -{ - fd_twoints u; - int k,hx,lx; - u.d = x; - hx = __HI(u); - lx = __LO(u); - k = (hx&0x7ff00000)>>20; /* extract exponent */ - if (k==0) { /* 0 or subnormal x */ - if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */ - x *= two54; - u.d = x; - hx = __HI(u); - k = ((hx&0x7ff00000)>>20) - 54; - if (n< -50000) return tiny*x; /*underflow*/ - } - if (k==0x7ff) return x+x; /* NaN or Inf */ - k = k+n; - if (k > 0x7fe) return really_big*fd_copysign(really_big,x); /* overflow */ - if (k > 0) /* normal result */ - {u.d = x; __HI(u) = (hx&0x800fffff)|(k<<20); x = u.d; return x;} - if (k <= -54) { - if (n > 50000) /* in case integer overflow in n+k */ - return really_big*fd_copysign(really_big,x); /*overflow*/ - else return tiny*fd_copysign(tiny,x); /*underflow*/ - } - k += 54; /* subnormal result */ - u.d = x; - __HI(u) = (hx&0x800fffff)|(k<<20); - x = u.d; - return x*twom54; -} diff --git a/lib/javascript/fdlibm/s_signgam.c b/lib/javascript/fdlibm/s_signgam.c deleted file mode 100644 index 4eb8ce72..00000000 --- a/lib/javascript/fdlibm/s_signgam.c +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -#include "fdlibm.h" -int signgam = 0; diff --git a/lib/javascript/fdlibm/s_significand.c b/lib/javascript/fdlibm/s_significand.c deleted file mode 100644 index 2e1c0b28..00000000 --- a/lib/javascript/fdlibm/s_significand.c +++ /dev/null @@ -1,68 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_significand.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * significand(x) computes just - * scalb(x, (double) -ilogb(x)), - * for exercising the fraction-part(F) IEEE 754-1985 test vector. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double fd_significand(double x) -#else - double fd_significand(x) - double x; -#endif -{ - return __ieee754_scalb(x,(double) -fd_ilogb(x)); -} diff --git a/lib/javascript/fdlibm/s_sin.c b/lib/javascript/fdlibm/s_sin.c deleted file mode 100644 index 8bbc5c62..00000000 --- a/lib/javascript/fdlibm/s_sin.c +++ /dev/null @@ -1,118 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_sin.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* sin(x) - * Return sine function of x. - * - * kernel function: - * __kernel_sin ... sine function on [-pi/4,pi/4] - * __kernel_cos ... cose function on [-pi/4,pi/4] - * __ieee754_rem_pio2 ... argument reduction routine - * - * Method. - * Let S,C and T denote the sin, cos and tan respectively on - * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 - * in [-pi/4 , +pi/4], and let n = k mod 4. - * We have - * - * n sin(x) cos(x) tan(x) - * ---------------------------------------------------------- - * 0 S C T - * 1 C -S -1/T - * 2 -S -C T - * 3 -C S -1/T - * ---------------------------------------------------------- - * - * Special cases: - * Let trig be any of sin, cos, or tan. - * trig(+-INF) is NaN, with signals; - * trig(NaN) is that NaN; - * - * Accuracy: - * TRIG(x) returns trig(x) nearly rounded - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double fd_sin(double x) -#else - double fd_sin(x) - double x; -#endif -{ - fd_twoints u; - double y[2],z=0.0; - int n, ix; - - /* High word of x. */ - u.d = x; - ix = __HI(u); - - /* |x| ~< pi/4 */ - ix &= 0x7fffffff; - if(ix <= 0x3fe921fb) return __kernel_sin(x,z,0); - - /* sin(Inf or NaN) is NaN */ - else if (ix>=0x7ff00000) return x-x; - - /* argument reduction needed */ - else { - n = __ieee754_rem_pio2(x,y); - switch(n&3) { - case 0: return __kernel_sin(y[0],y[1],1); - case 1: return __kernel_cos(y[0],y[1]); - case 2: return -__kernel_sin(y[0],y[1],1); - default: - return -__kernel_cos(y[0],y[1]); - } - } -} diff --git a/lib/javascript/fdlibm/s_tan.c b/lib/javascript/fdlibm/s_tan.c deleted file mode 100644 index ded36c1d..00000000 --- a/lib/javascript/fdlibm/s_tan.c +++ /dev/null @@ -1,112 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_tan.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* tan(x) - * Return tangent function of x. - * - * kernel function: - * __kernel_tan ... tangent function on [-pi/4,pi/4] - * __ieee754_rem_pio2 ... argument reduction routine - * - * Method. - * Let S,C and T denote the sin, cos and tan respectively on - * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 - * in [-pi/4 , +pi/4], and let n = k mod 4. - * We have - * - * n sin(x) cos(x) tan(x) - * ---------------------------------------------------------- - * 0 S C T - * 1 C -S -1/T - * 2 -S -C T - * 3 -C S -1/T - * ---------------------------------------------------------- - * - * Special cases: - * Let trig be any of sin, cos, or tan. - * trig(+-INF) is NaN, with signals; - * trig(NaN) is that NaN; - * - * Accuracy: - * TRIG(x) returns trig(x) nearly rounded - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double fd_tan(double x) -#else - double fd_tan(x) - double x; -#endif -{ - fd_twoints u; - double y[2],z=0.0; - int n, ix; - - /* High word of x. */ - u.d = x; - ix = __HI(u); - - /* |x| ~< pi/4 */ - ix &= 0x7fffffff; - if(ix <= 0x3fe921fb) return __kernel_tan(x,z,1); - - /* tan(Inf or NaN) is NaN */ - else if (ix>=0x7ff00000) return x-x; /* NaN */ - - /* argument reduction needed */ - else { - n = __ieee754_rem_pio2(x,y); - return __kernel_tan(y[0],y[1],1-((n&1)<<1)); /* 1 -- n even - -1 -- n odd */ - } -} diff --git a/lib/javascript/fdlibm/s_tanh.c b/lib/javascript/fdlibm/s_tanh.c deleted file mode 100644 index aa6809f8..00000000 --- a/lib/javascript/fdlibm/s_tanh.c +++ /dev/null @@ -1,122 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_tanh.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* Tanh(x) - * Return the Hyperbolic Tangent of x - * - * Method : - * x -x - * e - e - * 0. tanh(x) is defined to be ----------- - * x -x - * e + e - * 1. reduce x to non-negative by tanh(-x) = -tanh(x). - * 2. 0 <= x <= 2**-55 : tanh(x) := x*(one+x) - * -t - * 2**-55 < x <= 1 : tanh(x) := -----; t = expm1(-2x) - * t + 2 - * 2 - * 1 <= x <= 22.0 : tanh(x) := 1- ----- ; t=expm1(2x) - * t + 2 - * 22.0 < x <= INF : tanh(x) := 1. - * - * Special cases: - * tanh(NaN) is NaN; - * only tanh(0)=0 is exact for finite argument. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double one=1.0, two=2.0, tiny = 1.0e-300; -#else -static double one=1.0, two=2.0, tiny = 1.0e-300; -#endif - -#ifdef __STDC__ - double fd_tanh(double x) -#else - double fd_tanh(x) - double x; -#endif -{ - double t,z; - int jx,ix; - fd_twoints u; - - /* High word of |x|. */ - u.d = x; - jx = __HI(u); - ix = jx&0x7fffffff; - - /* x is INF or NaN */ - if(ix>=0x7ff00000) { - if (jx>=0) return one/x+one; /* tanh(+-inf)=+-1 */ - else return one/x-one; /* tanh(NaN) = NaN */ - } - - /* |x| < 22 */ - if (ix < 0x40360000) { /* |x|<22 */ - if (ix<0x3c800000) /* |x|<2**-55 */ - return x*(one+x); /* tanh(small) = small */ - if (ix>=0x3ff00000) { /* |x|>=1 */ - t = fd_expm1(two*fd_fabs(x)); - z = one - two/(t+two); - } else { - t = fd_expm1(-two*fd_fabs(x)); - z= -t/(t+two); - } - /* |x| > 22, return +-1 */ - } else { - z = one - tiny; /* raised inexact flag */ - } - return (jx>=0)? z: -z; -} diff --git a/lib/javascript/fdlibm/w_acos.c b/lib/javascript/fdlibm/w_acos.c deleted file mode 100644 index 872c81d2..00000000 --- a/lib/javascript/fdlibm/w_acos.c +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_acos.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * wrap_acos(x) - */ - -#include "fdlibm.h" - - -#ifdef __STDC__ - double fd_acos(double x) /* wrapper acos */ -#else - double fd_acos(x) /* wrapper acos */ - double x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_acos(x); -#else - double z; - z = __ieee754_acos(x); - if(_LIB_VERSION == _IEEE_ || fd_isnan(x)) return z; - if(fd_fabs(x)>1.0) { - int err; - return __kernel_standard(x,x,1,&err); /* acos(|x|>1) */ - } else - return z; -#endif -} diff --git a/lib/javascript/fdlibm/w_acosh.c b/lib/javascript/fdlibm/w_acosh.c deleted file mode 100644 index 745d402e..00000000 --- a/lib/javascript/fdlibm/w_acosh.c +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_acosh.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -/* - * wrapper acosh(x) - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double fd_acosh(double x) /* wrapper acosh */ -#else - double fd_acosh(x) /* wrapper acosh */ - double x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_acosh(x); -#else - double z; - z = __ieee754_acosh(x); - if(_LIB_VERSION == _IEEE_ || fd_isnan(x)) return z; - if(x<1.0) { - int err; - return __kernel_standard(x,x,29,&err); /* acosh(x<1) */ - } else - return z; -#endif -} diff --git a/lib/javascript/fdlibm/w_asin.c b/lib/javascript/fdlibm/w_asin.c deleted file mode 100644 index 18aaefde..00000000 --- a/lib/javascript/fdlibm/w_asin.c +++ /dev/null @@ -1,80 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_asin.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -/* - * wrapper asin(x) - */ - - -#include "fdlibm.h" - - -#ifdef __STDC__ - double fd_asin(double x) /* wrapper asin */ -#else - double fd_asin(x) /* wrapper asin */ - double x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_asin(x); -#else - double z; - z = __ieee754_asin(x); - if(_LIB_VERSION == _IEEE_ || fd_isnan(x)) return z; - if(fd_fabs(x)>1.0) { - int err; - return __kernel_standard(x,x,2,&err); /* asin(|x|>1) */ - } else - return z; -#endif -} diff --git a/lib/javascript/fdlibm/w_atan2.c b/lib/javascript/fdlibm/w_atan2.c deleted file mode 100644 index 8cfa4bbb..00000000 --- a/lib/javascript/fdlibm/w_atan2.c +++ /dev/null @@ -1,79 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_atan2.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -/* - * wrapper atan2(y,x) - */ - -#include "fdlibm.h" - - -#ifdef __STDC__ - double fd_atan2(double y, double x) /* wrapper atan2 */ -#else - double fd_atan2(y,x) /* wrapper atan2 */ - double y,x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_atan2(y,x); -#else - double z; - z = __ieee754_atan2(y,x); - if(_LIB_VERSION == _IEEE_||fd_isnan(x)||fd_isnan(y)) return z; - if(x==0.0&&y==0.0) { - int err; - return __kernel_standard(y,x,3,&err); /* atan2(+-0,+-0) */ - } else - return z; -#endif -} diff --git a/lib/javascript/fdlibm/w_atanh.c b/lib/javascript/fdlibm/w_atanh.c deleted file mode 100644 index 6ba52d1e..00000000 --- a/lib/javascript/fdlibm/w_atanh.c +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_atanh.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* - * wrapper atanh(x) - */ - -#include "fdlibm.h" - - -#ifdef __STDC__ - double fd_atanh(double x) /* wrapper atanh */ -#else - double fd_atanh(x) /* wrapper atanh */ - double x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_atanh(x); -#else - double z,y; - z = __ieee754_atanh(x); - if(_LIB_VERSION == _IEEE_ || fd_isnan(x)) return z; - y = fd_fabs(x); - if(y>=1.0) { - int err; - if(y>1.0) - return __kernel_standard(x,x,30,&err); /* atanh(|x|>1) */ - else - return __kernel_standard(x,x,31,&err); /* atanh(|x|==1) */ - } else - return z; -#endif -} diff --git a/lib/javascript/fdlibm/w_cosh.c b/lib/javascript/fdlibm/w_cosh.c deleted file mode 100644 index 146449e0..00000000 --- a/lib/javascript/fdlibm/w_cosh.c +++ /dev/null @@ -1,77 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_cosh.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * wrapper cosh(x) - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double fd_cosh(double x) /* wrapper cosh */ -#else - double fd_cosh(x) /* wrapper cosh */ - double x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_cosh(x); -#else - double z; - z = __ieee754_cosh(x); - if(_LIB_VERSION == _IEEE_ || fd_isnan(x)) return z; - if(fd_fabs(x)>7.10475860073943863426e+02) { - int err; - return __kernel_standard(x,x,5,&err); /* cosh overflow */ - } else - return z; -#endif -} diff --git a/lib/javascript/fdlibm/w_exp.c b/lib/javascript/fdlibm/w_exp.c deleted file mode 100644 index f5dea0b0..00000000 --- a/lib/javascript/fdlibm/w_exp.c +++ /dev/null @@ -1,88 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_exp.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * wrapper exp(x) - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -o_threshold= 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */ -u_threshold= -7.45133219101941108420e+02; /* 0xc0874910, 0xD52D3051 */ - -#ifdef __STDC__ - double fd_exp(double x) /* wrapper exp */ -#else - double fd_exp(x) /* wrapper exp */ - double x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_exp(x); -#else - double z; - z = __ieee754_exp(x); - if(_LIB_VERSION == _IEEE_) return z; - if(fd_finite(x)) { - int err; - if(x>o_threshold) - return __kernel_standard(x,x,6,&err); /* exp overflow */ - else if(xX_TLOSS) { - int err; - return __kernel_standard(x,x,34,&err); /* j0(|x|>X_TLOSS) */ - } else - return z; -#endif -} - -#ifdef __STDC__ - double y0(double x) /* wrapper y0 */ -#else - double y0(x) /* wrapper y0 */ - double x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_y0(x); -#else - double z; - int err; - z = __ieee754_y0(x); - if(_LIB_VERSION == _IEEE_ || fd_isnan(x) ) return z; - if(x <= 0.0){ - if(x==0.0) - /* d= -one/(x-x); */ - return __kernel_standard(x,x,8,&err); - else - /* d = zero/(x-x); */ - return __kernel_standard(x,x,9,&err); - } - if(x>X_TLOSS) { - return __kernel_standard(x,x,35,&err); /* y0(x>X_TLOSS) */ - } else - return z; -#endif -} diff --git a/lib/javascript/fdlibm/w_j1.c b/lib/javascript/fdlibm/w_j1.c deleted file mode 100644 index 86a506bc..00000000 --- a/lib/javascript/fdlibm/w_j1.c +++ /dev/null @@ -1,106 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_j1.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * wrapper of j1,y1 - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double fd_j1(double x) /* wrapper j1 */ -#else - double fd_j1(x) /* wrapper j1 */ - double x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_j1(x); -#else - double z; - z = __ieee754_j1(x); - if(_LIB_VERSION == _IEEE_ || fd_isnan(x) ) return z; - if(fd_fabs(x)>X_TLOSS) { - int err; - return __kernel_standard(x,x,36,&err); /* j1(|x|>X_TLOSS) */ - } else - return z; -#endif -} - -#ifdef __STDC__ - double y1(double x) /* wrapper y1 */ -#else - double y1(x) /* wrapper y1 */ - double x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_y1(x); -#else - double z; - int err; - z = __ieee754_y1(x); - if(_LIB_VERSION == _IEEE_ || fd_isnan(x) ) return z; - if(x <= 0.0){ - if(x==0.0) - /* d= -one/(x-x); */ - return __kernel_standard(x,x,10,&err); - else - /* d = zero/(x-x); */ - return __kernel_standard(x,x,11,&err); - } - if(x>X_TLOSS) { - return __kernel_standard(x,x,37,&err); /* y1(x>X_TLOSS) */ - } else - return z; -#endif -} diff --git a/lib/javascript/fdlibm/w_jn.c b/lib/javascript/fdlibm/w_jn.c deleted file mode 100644 index 6926b0da..00000000 --- a/lib/javascript/fdlibm/w_jn.c +++ /dev/null @@ -1,128 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_jn.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * wrapper jn(int n, double x), yn(int n, double x) - * floating point Bessel's function of the 1st and 2nd kind - * of order n - * - * Special cases: - * y0(0)=y1(0)=yn(n,0) = -inf with division by zero signal; - * y0(-ve)=y1(-ve)=yn(n,-ve) are NaN with invalid signal. - * Note 2. About jn(n,x), yn(n,x) - * For n=0, j0(x) is called, - * for n=1, j1(x) is called, - * for nx, a continued fraction approximation to - * j(n,x)/j(n-1,x) is evaluated and then backward - * recursion is used starting from a supposed value - * for j(n,x). The resulting value of j(0,x) is - * compared with the actual value to correct the - * supposed value of j(n,x). - * - * yn(n,x) is similar in all respects, except - * that forward recursion is used for all - * values of n>1. - * - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double fd_jn(int n, double x) /* wrapper jn */ -#else - double fd_jn(n,x) /* wrapper jn */ - double x; int n; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_jn(n,x); -#else - double z; - z = __ieee754_jn(n,x); - if(_LIB_VERSION == _IEEE_ || fd_isnan(x) ) return z; - if(fd_fabs(x)>X_TLOSS) { - int err; - return __kernel_standard((double)n,x,38,&err); /* jn(|x|>X_TLOSS,n) */ - } else - return z; -#endif -} - -#ifdef __STDC__ - double yn(int n, double x) /* wrapper yn */ -#else - double yn(n,x) /* wrapper yn */ - double x; int n; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_yn(n,x); -#else - double z; - int err; - z = __ieee754_yn(n,x); - if(_LIB_VERSION == _IEEE_ || fd_isnan(x) ) return z; - if(x <= 0.0){ - if(x==0.0) - /* d= -one/(x-x); */ - return __kernel_standard((double)n,x,12,&err); - else - /* d = zero/(x-x); */ - return __kernel_standard((double)n,x,13,&err); - } - if(x>X_TLOSS) { - return __kernel_standard((double)n,x,39,&err); /* yn(x>X_TLOSS,n) */ - } else - return z; -#endif -} diff --git a/lib/javascript/fdlibm/w_lgamma.c b/lib/javascript/fdlibm/w_lgamma.c deleted file mode 100644 index f7576e89..00000000 --- a/lib/javascript/fdlibm/w_lgamma.c +++ /dev/null @@ -1,85 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_lgamma.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -/* double lgamma(double x) - * Return the logarithm of the Gamma function of x. - * - * Method: call __ieee754_lgamma_r - */ - -#include "fdlibm.h" - -extern int signgam; - -#ifdef __STDC__ - double fd_lgamma(double x) -#else - double fd_lgamma(x) - double x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_lgamma_r(x,&signgam); -#else - double y; - y = __ieee754_lgamma_r(x,&signgam); - if(_LIB_VERSION == _IEEE_) return y; - if(!fd_finite(y)&&fd_finite(x)) { - int err; - if(fd_floor(x)==x&&x<=0.0) - return __kernel_standard(x,x,15,&err); /* lgamma pole */ - else - return __kernel_standard(x,x,14,&err); /* lgamma overflow */ - } else - return y; -#endif -} diff --git a/lib/javascript/fdlibm/w_lgamma_r.c b/lib/javascript/fdlibm/w_lgamma_r.c deleted file mode 100644 index ba2ad593..00000000 --- a/lib/javascript/fdlibm/w_lgamma_r.c +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_lgamma_r.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * wrapper double lgamma_r(double x, int *signgamp) - */ - -#include "fdlibm.h" - - -#ifdef __STDC__ - double fd_lgamma_r(double x, int *signgamp) /* wrapper lgamma_r */ -#else - double fd_lgamma_r(x,signgamp) /* wrapper lgamma_r */ - double x; int *signgamp; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_lgamma_r(x,signgamp); -#else - double y; - y = __ieee754_lgamma_r(x,signgamp); - if(_LIB_VERSION == _IEEE_) return y; - if(!fd_finite(y)&&fd_finite(x)) { - int err; - if(fd_floor(x)==x&&x<=0.0) - return __kernel_standard(x,x,15,&err); /* lgamma pole */ - else - return __kernel_standard(x,x,14,&err); /* lgamma overflow */ - } else - return y; -#endif -} diff --git a/lib/javascript/fdlibm/w_log.c b/lib/javascript/fdlibm/w_log.c deleted file mode 100644 index 7e358fcf..00000000 --- a/lib/javascript/fdlibm/w_log.c +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_log.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * wrapper log(x) - */ - -#include "fdlibm.h" - - -#ifdef __STDC__ - double fd_log(double x) /* wrapper log */ -#else - double fd_log(x) /* wrapper log */ - double x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_log(x); -#else - double z; - int err; - z = __ieee754_log(x); - if(_LIB_VERSION == _IEEE_ || fd_isnan(x) || x > 0.0) return z; - if(x==0.0) - return __kernel_standard(x,x,16,&err); /* log(0) */ - else - return __kernel_standard(x,x,17,&err); /* log(x<0) */ -#endif -} diff --git a/lib/javascript/fdlibm/w_log10.c b/lib/javascript/fdlibm/w_log10.c deleted file mode 100644 index 6b298b23..00000000 --- a/lib/javascript/fdlibm/w_log10.c +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_log10.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * wrapper log10(X) - */ - -#include "fdlibm.h" - - -#ifdef __STDC__ - double fd_log10(double x) /* wrapper log10 */ -#else - double fd_log10(x) /* wrapper log10 */ - double x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_log10(x); -#else - double z; - z = __ieee754_log10(x); - if(_LIB_VERSION == _IEEE_ || fd_isnan(x)) return z; - if(x<=0.0) { - int err; - if(x==0.0) - return __kernel_standard(x,x,18,&err); /* log10(0) */ - else - return __kernel_standard(x,x,19,&err); /* log10(x<0) */ - } else - return z; -#endif -} diff --git a/lib/javascript/fdlibm/w_pow.c b/lib/javascript/fdlibm/w_pow.c deleted file mode 100644 index 3d2c15ad..00000000 --- a/lib/javascript/fdlibm/w_pow.c +++ /dev/null @@ -1,99 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - - -/* @(#)w_pow.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * wrapper pow(x,y) return x**y - */ - -#include "fdlibm.h" - - -#ifdef __STDC__ - double fd_pow(double x, double y) /* wrapper pow */ -#else - double fd_pow(x,y) /* wrapper pow */ - double x,y; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_pow(x,y); -#else - double z; - int err; - z=__ieee754_pow(x,y); - if(_LIB_VERSION == _IEEE_|| fd_isnan(y)) return z; - if(fd_isnan(x)) { - if(y==0.0) - return __kernel_standard(x,y,42,&err); /* pow(NaN,0.0) */ - else - return z; - } - if(x==0.0){ - if(y==0.0) - return __kernel_standard(x,y,20,&err); /* pow(0.0,0.0) */ - if(fd_finite(y)&&y<0.0) - return __kernel_standard(x,y,23,&err); /* pow(0.0,negative) */ - return z; - } - if(!fd_finite(z)) { - if(fd_finite(x)&&fd_finite(y)) { - if(fd_isnan(z)) - return __kernel_standard(x,y,24,&err); /* pow neg**non-int */ - else - return __kernel_standard(x,y,21,&err); /* pow overflow */ - } - } - if(z==0.0&&fd_finite(x)&&fd_finite(y)) - return __kernel_standard(x,y,22,&err); /* pow underflow */ - return z; -#endif -} diff --git a/lib/javascript/fdlibm/w_remainder.c b/lib/javascript/fdlibm/w_remainder.c deleted file mode 100644 index 25d1ba17..00000000 --- a/lib/javascript/fdlibm/w_remainder.c +++ /dev/null @@ -1,77 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_remainder.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * wrapper remainder(x,p) - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double fd_remainder(double x, double y) /* wrapper remainder */ -#else - double fd_remainder(x,y) /* wrapper remainder */ - double x,y; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_remainder(x,y); -#else - double z; - z = __ieee754_remainder(x,y); - if(_LIB_VERSION == _IEEE_ || fd_isnan(y)) return z; - if(y==0.0) { - int err; - return __kernel_standard(x,y,28,&err); /* remainder(x,0) */ - } else - return z; -#endif -} diff --git a/lib/javascript/fdlibm/w_scalb.c b/lib/javascript/fdlibm/w_scalb.c deleted file mode 100644 index 35c16a50..00000000 --- a/lib/javascript/fdlibm/w_scalb.c +++ /dev/null @@ -1,95 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_scalb.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * wrapper scalb(double x, double fn) is provide for - * passing various standard test suite. One - * should use scalbn() instead. - */ - -#include "fdlibm.h" - -#include - -#ifdef __STDC__ -#ifdef _SCALB_INT - double fd_scalb(double x, int fn) /* wrapper scalb */ -#else - double fd_scalb(double x, double fn) /* wrapper scalb */ -#endif -#else - double fd_scalb(x,fn) /* wrapper scalb */ -#ifdef _SCALB_INT - double x; int fn; -#else - double x,fn; -#endif -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_scalb(x,fn); -#else - double z; - int err; - z = __ieee754_scalb(x,fn); - if(_LIB_VERSION == _IEEE_) return z; - if(!(fd_finite(z)||fd_isnan(z))&&fd_finite(x)) { - return __kernel_standard(x,(double)fn,32,&err); /* scalb overflow */ - } - if(z==0.0&&z!=x) { - return __kernel_standard(x,(double)fn,33,&err); /* scalb underflow */ - } -#ifndef _SCALB_INT - if(!fd_finite(fn)) errno = ERANGE; -#endif - return z; -#endif -} diff --git a/lib/javascript/fdlibm/w_sinh.c b/lib/javascript/fdlibm/w_sinh.c deleted file mode 100644 index 8b04ecb7..00000000 --- a/lib/javascript/fdlibm/w_sinh.c +++ /dev/null @@ -1,77 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_sinh.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * wrapper sinh(x) - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double fd_sinh(double x) /* wrapper sinh */ -#else - double fd_sinh(x) /* wrapper sinh */ - double x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_sinh(x); -#else - double z; - z = __ieee754_sinh(x); - if(_LIB_VERSION == _IEEE_) return z; - if(!fd_finite(z)&&fd_finite(x)) { - int err; - return __kernel_standard(x,x,25,&err); /* sinh overflow */ - } else - return z; -#endif -} diff --git a/lib/javascript/fdlibm/w_sqrt.c b/lib/javascript/fdlibm/w_sqrt.c deleted file mode 100644 index 462d776f..00000000 --- a/lib/javascript/fdlibm/w_sqrt.c +++ /dev/null @@ -1,77 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_sqrt.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * wrapper sqrt(x) - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double fd_sqrt(double x) /* wrapper sqrt */ -#else - double fd_sqrt(x) /* wrapper sqrt */ - double x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_sqrt(x); -#else - double z; - z = __ieee754_sqrt(x); - if(_LIB_VERSION == _IEEE_ || fd_isnan(x)) return z; - if(x<0.0) { - int err; - return __kernel_standard(x,x,26,&err); /* sqrt(negative) */ - } else - return z; -#endif -} diff --git a/lib/javascript/js.c b/lib/javascript/js.c deleted file mode 100644 index b3961667..00000000 --- a/lib/javascript/js.c +++ /dev/null @@ -1,2632 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sw=4 et tw=80: - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JS shell. - */ -#include "jsstddef.h" -#include -#include -#include -#include -#include "jstypes.h" -#include "jsarena.h" -#include "jsutil.h" -#include "jsprf.h" -#include "jsapi.h" -#include "jsatom.h" -#include "jscntxt.h" -#include "jsdbgapi.h" -#include "jsemit.h" -#include "jsfun.h" -#include "jsgc.h" -#include "jslock.h" -#include "jsobj.h" -#include "jsparse.h" -#include "jsscope.h" -#include "jsscript.h" - -#ifdef PERLCONNECT -#include "perlconnect/jsperl.h" -#endif - -#ifdef LIVECONNECT -#include "jsjava.h" -#endif - -#ifdef JSDEBUGGER -#include "jsdebug.h" -#ifdef JSDEBUGGER_JAVA_UI -#include "jsdjava.h" -#endif /* JSDEBUGGER_JAVA_UI */ -#ifdef JSDEBUGGER_C_UI -#include "jsdb.h" -#endif /* JSDEBUGGER_C_UI */ -#endif /* JSDEBUGGER */ - -#ifdef XP_UNIX -#include -#include -#include -#endif - -#if defined(XP_WIN) || defined(XP_OS2) -#include /* for isatty() */ -#endif - -typedef enum JSShellExitCode { - EXITCODE_RUNTIME_ERROR = 3, - EXITCODE_FILE_NOT_FOUND = 4, - EXITCODE_OUT_OF_MEMORY = 5 -} JSShellExitCode; - -size_t gStackChunkSize = 8192; -static size_t gMaxStackSize = 0; -static jsuword gStackBase; -int gExitCode = 0; -JSBool gQuitting = JS_FALSE; -FILE *gErrFile = NULL; -FILE *gOutFile = NULL; - -#ifdef JSDEBUGGER -static JSDContext *_jsdc; -#ifdef JSDEBUGGER_JAVA_UI -static JSDJContext *_jsdjc; -#endif /* JSDEBUGGER_JAVA_UI */ -#endif /* JSDEBUGGER */ - -static JSBool reportWarnings = JS_TRUE; -static JSBool compileOnly = JS_FALSE; - -typedef enum JSShellErrNum { -#define MSG_DEF(name, number, count, exception, format) \ - name = number, -#include "jsshell.msg" -#undef MSG_DEF - JSShellErr_Limit -#undef MSGDEF -} JSShellErrNum; - -static const JSErrorFormatString * -my_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber); - -#ifdef EDITLINE -extern char *readline(const char *prompt); -extern void add_history(char *line); -#endif - -static JSBool -GetLine(JSContext *cx, char *bufp, FILE *file, const char *prompt) { -#ifdef EDITLINE - /* - * Use readline only if file is stdin, because there's no way to specify - * another handle. Are other filehandles interactive? - */ - if (file == stdin) { - char *linep = readline(prompt); - if (!linep) - return JS_FALSE; - if (linep[0] != '\0') - add_history(linep); - strcpy(bufp, linep); - JS_free(cx, linep); - bufp += strlen(bufp); - *bufp++ = '\n'; - *bufp = '\0'; - } else -#endif - { - char line[256]; - fprintf(gOutFile, prompt); - fflush(gOutFile); - if (!fgets(line, sizeof line, file)) - return JS_FALSE; - strcpy(bufp, line); - } - return JS_TRUE; -} - -static void -Process(JSContext *cx, JSObject *obj, char *filename) -{ - JSBool ok, hitEOF; - JSScript *script; - jsval result; - JSString *str; - char buffer[4096]; - char *bufp; - int lineno; - int startline; - FILE *file; - jsuword stackLimit; - - if (!filename || strcmp(filename, "-") == 0) { - file = stdin; - } else { - file = fopen(filename, "r"); - if (!file) { - JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, - JSSMSG_CANT_OPEN, filename, strerror(errno)); - gExitCode = EXITCODE_FILE_NOT_FOUND; - return; - } - } - - if (gMaxStackSize == 0) { - /* - * Disable checking for stack overflow if limit is zero. - */ - stackLimit = 0; - } else { -#if JS_STACK_GROWTH_DIRECTION > 0 - stackLimit = gStackBase + gMaxStackSize; -#else - stackLimit = gStackBase - gMaxStackSize; -#endif - } - JS_SetThreadStackLimit(cx, stackLimit); - - if (!isatty(fileno(file))) { - /* - * It's not interactive - just execute it. - * - * Support the UNIX #! shell hack; gobble the first line if it starts - * with '#'. TODO - this isn't quite compatible with sharp variables, - * as a legal js program (using sharp variables) might start with '#'. - * But that would require multi-character lookahead. - */ - int ch = fgetc(file); - if (ch == '#') { - while((ch = fgetc(file)) != EOF) { - if (ch == '\n' || ch == '\r') - break; - } - } - ungetc(ch, file); - script = JS_CompileFileHandle(cx, obj, filename, file); - if (script) { - if (!compileOnly) - (void)JS_ExecuteScript(cx, obj, script, &result); - JS_DestroyScript(cx, script); - } - return; - } - - /* It's an interactive filehandle; drop into read-eval-print loop. */ - lineno = 1; - hitEOF = JS_FALSE; - do { - bufp = buffer; - *bufp = '\0'; - - /* - * Accumulate lines until we get a 'compilable unit' - one that either - * generates an error (before running out of source) or that compiles - * cleanly. This should be whenever we get a complete statement that - * coincides with the end of a line. - */ - startline = lineno; - do { - if (!GetLine(cx, bufp, file, startline == lineno ? "js> " : "")) { - hitEOF = JS_TRUE; - break; - } - bufp += strlen(bufp); - lineno++; - } while (!JS_BufferIsCompilableUnit(cx, obj, buffer, strlen(buffer))); - - /* Clear any pending exception from previous failed compiles. */ - JS_ClearPendingException(cx); - script = JS_CompileScript(cx, obj, buffer, strlen(buffer), "typein", - startline); - if (script) { - if (!compileOnly) { - ok = JS_ExecuteScript(cx, obj, script, &result); - if (ok && result != JSVAL_VOID) { - str = JS_ValueToString(cx, result); - if (str) - fprintf(gOutFile, "%s\n", JS_GetStringBytes(str)); - else - ok = JS_FALSE; - } - } - JS_DestroyScript(cx, script); - } - } while (!hitEOF && !gQuitting); - fprintf(gOutFile, "\n"); - return; -} - -static int -usage(void) -{ - fprintf(gErrFile, "%s\n", JS_GetImplementationVersion()); - fprintf(gErrFile, "usage: js [-PswWxC] [-b branchlimit] [-c stackchunksize] [-v version] [-f scriptfile] [-e script] [-S maxstacksize] [scriptfile] [scriptarg...]\n"); - return 2; -} - -static uint32 gBranchCount; -static uint32 gBranchLimit; - -static JSBool -my_BranchCallback(JSContext *cx, JSScript *script) -{ - if (++gBranchCount == gBranchLimit) { - if (script) { - if (script->filename) - fprintf(gErrFile, "%s:", script->filename); - fprintf(gErrFile, "%u: script branch callback (%u callbacks)\n", - script->lineno, gBranchLimit); - } else { - fprintf(gErrFile, "native branch callback (%u callbacks)\n", - gBranchLimit); - } - gBranchCount = 0; - return JS_FALSE; - } - if ((gBranchCount & 0x3fff) == 1) - JS_MaybeGC(cx); - return JS_TRUE; -} - -extern JSClass global_class; - -static int -ProcessArgs(JSContext *cx, JSObject *obj, char **argv, int argc) -{ - int i, j, length; - JSObject *argsObj; - char *filename = NULL; - JSBool isInteractive = JS_TRUE; - - /* - * Scan past all optional arguments so we can create the arguments object - * before processing any -f options, which must interleave properly with - * -v and -w options. This requires two passes, and without getopt, we'll - * have to keep the option logic here and in the second for loop in sync. - */ - for (i = 0; i < argc; i++) { - if (argv[i][0] != '-' || argv[i][1] == '\0') { - ++i; - break; - } - switch (argv[i][1]) { - case 'b': - case 'c': - case 'f': - case 'e': - case 'v': - case 'S': - ++i; - break; - default:; - } - } - - /* - * Create arguments early and define it to root it, so it's safe from any - * GC calls nested below, and so it is available to -f arguments. - */ - argsObj = JS_NewArrayObject(cx, 0, NULL); - if (!argsObj) - return 1; - if (!JS_DefineProperty(cx, obj, "arguments", OBJECT_TO_JSVAL(argsObj), - NULL, NULL, 0)) { - return 1; - } - - length = argc - i; - for (j = 0; j < length; j++) { - JSString *str = JS_NewStringCopyZ(cx, argv[i++]); - if (!str) - return 1; - if (!JS_DefineElement(cx, argsObj, j, STRING_TO_JSVAL(str), - NULL, NULL, JSPROP_ENUMERATE)) { - return 1; - } - } - - for (i = 0; i < argc; i++) { - if (argv[i][0] != '-' || argv[i][1] == '\0') { - filename = argv[i++]; - isInteractive = JS_FALSE; - break; - } - - switch (argv[i][1]) { - case 'v': - if (++i == argc) { - return usage(); - } - JS_SetVersion(cx, (JSVersion) atoi(argv[i])); - break; - - case 'w': - reportWarnings = JS_TRUE; - break; - - case 'W': - reportWarnings = JS_FALSE; - break; - - case 's': - JS_ToggleOptions(cx, JSOPTION_STRICT); - break; - - case 'x': - JS_ToggleOptions(cx, JSOPTION_XML); - break; - - case 'P': - if (JS_GET_CLASS(cx, JS_GetPrototype(cx, obj)) != &global_class) { - JSObject *gobj; - - if (!JS_SealObject(cx, obj, JS_TRUE)) - return JS_FALSE; - gobj = JS_NewObject(cx, &global_class, NULL, NULL); - if (!gobj) - return JS_FALSE; - if (!JS_SetPrototype(cx, gobj, obj)) - return JS_FALSE; - JS_SetParent(cx, gobj, NULL); - JS_SetGlobalObject(cx, gobj); - obj = gobj; - } - break; - - case 'b': - gBranchLimit = atoi(argv[++i]); - JS_SetBranchCallback(cx, my_BranchCallback); - JS_ToggleOptions(cx, JSOPTION_NATIVE_BRANCH_CALLBACK); - break; - - case 'c': - /* set stack chunk size */ - gStackChunkSize = atoi(argv[++i]); - break; - - case 'f': - if (++i == argc) { - return usage(); - } - Process(cx, obj, argv[i]); - /* - * XXX: js -f foo.js should interpret foo.js and then - * drop into interactive mode, but that breaks the test - * harness. Just execute foo.js for now. - */ - isInteractive = JS_FALSE; - break; - - case 'e': - { - jsval rval; - - if (++i == argc) { - return usage(); - } - - /* Pass a filename of -e to imitate PERL */ - JS_EvaluateScript(cx, obj, argv[i], strlen(argv[i]), - "-e", 1, &rval); - - isInteractive = JS_FALSE; - break; - - } - case 'C': - compileOnly = JS_TRUE; - isInteractive = JS_FALSE; - break; - - case 'S': - if (++i == argc) { - return usage(); - } - /* Set maximum stack size. */ - gMaxStackSize = atoi(argv[i]); - break; - - default: - return usage(); - } - } - - if (filename || isInteractive) - Process(cx, obj, filename); - return gExitCode; -} - - -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, (JSVersion) JSVAL_TO_INT(argv[0]))); - else - *rval = INT_TO_JSVAL(JS_GetVersion(cx)); - return JS_TRUE; -} - -static struct { - const char *name; - uint32 flag; -} js_options[] = { - {"strict", JSOPTION_STRICT}, - {"werror", JSOPTION_WERROR}, - {"atline", JSOPTION_ATLINE}, - {"xml", JSOPTION_XML}, - {0, 0} -}; - -static JSBool -Options(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - uint32 optset, flag; - uintN i, j, found; - JSString *str; - const char *opt; - char *names; - - optset = 0; - for (i = 0; i < argc; i++) { - str = JS_ValueToString(cx, argv[i]); - if (!str) - return JS_FALSE; - opt = JS_GetStringBytes(str); - for (j = 0; js_options[j].name; j++) { - if (strcmp(js_options[j].name, opt) == 0) { - optset |= js_options[j].flag; - break; - } - } - } - optset = JS_ToggleOptions(cx, optset); - - names = NULL; - found = 0; - while (optset != 0) { - flag = optset; - optset &= optset - 1; - flag &= ~optset; - for (j = 0; js_options[j].name; j++) { - if (js_options[j].flag == flag) { - names = JS_sprintf_append(names, "%s%s", - names ? "," : "", js_options[j].name); - found++; - break; - } - } - } - if (!found) - names = strdup(""); - if (!names) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - - str = JS_NewString(cx, names, strlen(names)); - if (!str) { - free(names); - return JS_FALSE; - } - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -static void -my_LoadErrorReporter(JSContext *cx, const char *message, JSErrorReport *report); - -static void -my_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report); - -static 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; - JSErrorReporter older; - uint32 oldopts; - - 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); - errno = 0; - older = JS_SetErrorReporter(cx, my_LoadErrorReporter); - oldopts = JS_GetOptions(cx); - JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO); - script = JS_CompileFile(cx, obj, filename); - if (!script) { - ok = JS_FALSE; - } else { - ok = !compileOnly - ? JS_ExecuteScript(cx, obj, script, &result) - : JS_TRUE; - JS_DestroyScript(cx, script); - } - JS_SetOptions(cx, oldopts); - JS_SetErrorReporter(cx, older); - if (!ok) - return JS_FALSE; - } - - return JS_TRUE; -} - -/* - * function readline() - * Provides a hook for scripts to read a line from stdin. - */ -static JSBool -ReadLine(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ -#define BUFSIZE 256 - FILE *from; - char *buf, *tmp; - size_t bufsize, buflength, gotlength; - JSString *str; - - from = stdin; - buflength = 0; - bufsize = BUFSIZE; - buf = JS_malloc(cx, bufsize); - if (!buf) - return JS_FALSE; - - while ((gotlength = - js_fgets(buf + buflength, bufsize - buflength, from)) > 0) { - buflength += gotlength; - - /* Are we done? */ - if (buf[buflength - 1] == '\n') { - buf[buflength - 1] = '\0'; - break; - } - - /* Else, grow our buffer for another pass. */ - tmp = JS_realloc(cx, buf, bufsize * 2); - if (!tmp) { - JS_free(cx, buf); - return JS_FALSE; - } - - bufsize *= 2; - buf = tmp; - } - - /* Treat the empty string specially. */ - if (buflength == 0) { - *rval = JS_GetEmptyStringValue(cx); - JS_free(cx, buf); - return JS_TRUE; - } - - /* Shrink the buffer to the real size. */ - tmp = JS_realloc(cx, buf, buflength); - if (!tmp) { - JS_free(cx, buf); - return JS_FALSE; - } - - buf = tmp; - - /* - * Turn buf into a JSString. Note that buflength includes the trailing null - * character. - */ - str = JS_NewString(cx, buf, buflength - 1); - if (!str) { - JS_free(cx, buf); - return JS_FALSE; - } - - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -static JSBool -Print(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - uintN i, n; - JSString *str; - - for (i = n = 0; i < argc; i++) { - str = JS_ValueToString(cx, argv[i]); - if (!str) - return JS_FALSE; - fprintf(gOutFile, "%s%s", i ? " " : "", JS_GetStringBytes(str)); - } - n++; - if (n) - fputc('\n', gOutFile); - return JS_TRUE; -} - -static JSBool -Help(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); - -static JSBool -Quit(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ -#ifdef LIVECONNECT - JSJ_SimpleShutdown(); -#endif - - JS_ConvertArguments(cx, argc, argv,"/ i", &gExitCode); - - gQuitting = JS_TRUE; - return JS_FALSE; -} - -static JSBool -GC(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSRuntime *rt; - uint32 preBytes; - - rt = cx->runtime; - preBytes = rt->gcBytes; -#ifdef GC_MARK_DEBUG - if (argc && JSVAL_IS_STRING(argv[0])) { - char *name = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])); - FILE *file = fopen(name, "w"); - if (!file) { - fprintf(gErrFile, "gc: can't open %s: %s\n", strerror(errno)); - return JS_FALSE; - } - js_DumpGCHeap = file; - } else { - js_DumpGCHeap = stdout; - } -#endif - JS_GC(cx); -#ifdef GC_MARK_DEBUG - if (js_DumpGCHeap != stdout) - fclose(js_DumpGCHeap); - js_DumpGCHeap = NULL; -#endif - fprintf(gOutFile, "before %lu, after %lu, break %08lx\n", - (unsigned long)preBytes, (unsigned long)rt->gcBytes, -#ifdef XP_UNIX - (unsigned long)sbrk(0) -#else - 0 -#endif - ); -#ifdef JS_GCMETER - js_DumpGCStats(rt, stdout); -#endif - return JS_TRUE; -} - -static JSScript * -ValueToScript(JSContext *cx, jsval v) -{ - JSScript *script; - JSFunction *fun; - - if (!JSVAL_IS_PRIMITIVE(v) && - JS_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_ScriptClass) { - script = (JSScript *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v)); - } else { - fun = JS_ValueToFunction(cx, v); - if (!fun) - return NULL; - script = FUN_SCRIPT(fun); - } - return script; -} - -static JSBool -GetTrapArgs(JSContext *cx, uintN argc, jsval *argv, JSScript **scriptp, - int32 *ip) -{ - jsval v; - uintN intarg; - JSScript *script; - - *scriptp = cx->fp->down->script; - *ip = 0; - if (argc != 0) { - v = argv[0]; - intarg = 0; - if (!JSVAL_IS_PRIMITIVE(v) && - (JS_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_FunctionClass || - JS_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_ScriptClass)) { - script = ValueToScript(cx, v); - if (!script) - return JS_FALSE; - *scriptp = script; - intarg++; - } - if (argc > intarg) { - if (!JS_ValueToInt32(cx, argv[intarg], ip)) - return JS_FALSE; - } - } - return JS_TRUE; -} - -static JSTrapStatus -TrapHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval, - void *closure) -{ - JSString *str; - JSStackFrame *caller; - - str = (JSString *) closure; - caller = JS_GetScriptedCaller(cx, NULL); - if (!JS_EvaluateScript(cx, caller->scopeChain, - JS_GetStringBytes(str), JS_GetStringLength(str), - caller->script->filename, caller->script->lineno, - rval)) { - return JSTRAP_ERROR; - } - if (*rval != JSVAL_VOID) - return JSTRAP_RETURN; - return JSTRAP_CONTINUE; -} - -static JSBool -Trap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSString *str; - JSScript *script; - int32 i; - - if (argc == 0) { - JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_TRAP_USAGE); - return JS_FALSE; - } - argc--; - str = JS_ValueToString(cx, argv[argc]); - if (!str) - return JS_FALSE; - argv[argc] = STRING_TO_JSVAL(str); - if (!GetTrapArgs(cx, argc, argv, &script, &i)) - return JS_FALSE; - return JS_SetTrap(cx, script, script->code + i, TrapHandler, str); -} - -static JSBool -Untrap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSScript *script; - int32 i; - - if (!GetTrapArgs(cx, argc, argv, &script, &i)) - return JS_FALSE; - JS_ClearTrap(cx, script, script->code + i, NULL, NULL); - return JS_TRUE; -} - -static JSBool -LineToPC(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSScript *script; - int32 i; - uintN lineno; - jsbytecode *pc; - - if (argc == 0) { - JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_LINE2PC_USAGE); - return JS_FALSE; - } - script = cx->fp->down->script; - if (!GetTrapArgs(cx, argc, argv, &script, &i)) - return JS_FALSE; - lineno = (i == 0) ? script->lineno : (uintN)i; - pc = JS_LineNumberToPC(cx, script, lineno); - if (!pc) - return JS_FALSE; - *rval = INT_TO_JSVAL(PTRDIFF(pc, script->code, jsbytecode)); - return JS_TRUE; -} - -static JSBool -PCToLine(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSScript *script; - int32 i; - uintN lineno; - - if (!GetTrapArgs(cx, argc, argv, &script, &i)) - return JS_FALSE; - lineno = JS_PCToLineNumber(cx, script, script->code + i); - if (!lineno) - return JS_FALSE; - *rval = INT_TO_JSVAL(lineno); - return JS_TRUE; -} - -#ifdef DEBUG - -static void -SrcNotes(JSContext *cx, JSScript *script) -{ - uintN offset, delta, caseOff; - jssrcnote *notes, *sn; - JSSrcNoteType type; - jsatomid atomIndex; - JSAtom *atom; - - fprintf(gOutFile, "\nSource notes:\n"); - offset = 0; - notes = SCRIPT_NOTES(script); - for (sn = notes; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) { - delta = SN_DELTA(sn); - offset += delta; - fprintf(gOutFile, "%3u: %5u [%4u] %-8s", - PTRDIFF(sn, notes, jssrcnote), offset, delta, - js_SrcNoteSpec[SN_TYPE(sn)].name); - type = (JSSrcNoteType) SN_TYPE(sn); - switch (type) { - case SRC_SETLINE: - fprintf(gOutFile, " lineno %u", (uintN) js_GetSrcNoteOffset(sn, 0)); - break; - case SRC_FOR: - fprintf(gOutFile, " cond %u update %u tail %u", - (uintN) js_GetSrcNoteOffset(sn, 0), - (uintN) js_GetSrcNoteOffset(sn, 1), - (uintN) js_GetSrcNoteOffset(sn, 2)); - break; - case SRC_COND: - case SRC_IF_ELSE: - case SRC_WHILE: - case SRC_PCBASE: - case SRC_PCDELTA: - fprintf(gOutFile, " offset %u", (uintN) js_GetSrcNoteOffset(sn, 0)); - break; - case SRC_LABEL: - case SRC_LABELBRACE: - case SRC_BREAK2LABEL: - case SRC_CONT2LABEL: - case SRC_FUNCDEF: { - const char *bytes; - JSFunction *fun; - JSString *str; - - atomIndex = (jsatomid) js_GetSrcNoteOffset(sn, 0); - atom = js_GetAtom(cx, &script->atomMap, atomIndex); - if (type != SRC_FUNCDEF) { - bytes = js_AtomToPrintableString(cx, atom); - } else { - fun = (JSFunction *) - JS_GetPrivate(cx, ATOM_TO_OBJECT(atom)); - str = JS_DecompileFunction(cx, fun, JS_DONT_PRETTY_PRINT); - bytes = str ? JS_GetStringBytes(str) : "N/A"; - } - fprintf(gOutFile, " atom %u (%s)", (uintN)atomIndex, bytes); - break; - } - case SRC_SWITCH: - fprintf(gOutFile, " length %u", (uintN) js_GetSrcNoteOffset(sn, 0)); - caseOff = (uintN) js_GetSrcNoteOffset(sn, 1); - if (caseOff) - fprintf(gOutFile, " first case offset %u", caseOff); - break; - case SRC_CATCH: - delta = (uintN) js_GetSrcNoteOffset(sn, 0); - if (delta) - fprintf(gOutFile, " guard size %u", delta); - break; - default:; - } - fputc('\n', gOutFile); - } -} - -static JSBool -Notes(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - uintN i; - JSScript *script; - - for (i = 0; i < argc; i++) { - script = ValueToScript(cx, argv[i]); - if (!script) - continue; - - SrcNotes(cx, script); - } - return JS_TRUE; -} - -static JSBool -TryNotes(JSContext *cx, JSScript *script) -{ - JSTryNote *tn = script->trynotes; - - if (!tn) - return JS_TRUE; - fprintf(gOutFile, "\nException table:\nstart\tend\tcatch\n"); - while (tn->start && tn->catchStart) { - fprintf(gOutFile, " %d\t%d\t%d\n", - tn->start, tn->start + tn->length, tn->catchStart); - tn++; - } - return JS_TRUE; -} - -static JSBool -Disassemble(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSBool lines; - uintN i; - JSScript *script; - - if (argc > 0 && - JSVAL_IS_STRING(argv[0]) && - !strcmp(JS_GetStringBytes(JSVAL_TO_STRING(argv[0])), "-l")) { - lines = JS_TRUE; - argv++, argc--; - } else { - lines = JS_FALSE; - } - for (i = 0; i < argc; i++) { - script = ValueToScript(cx, argv[i]); - if (!script) - continue; - - if (JSVAL_IS_FUNCTION(cx, argv[i])) { - JSFunction *fun = JS_ValueToFunction(cx, argv[i]); - if (fun && (fun->flags & JSFUN_FLAGS_MASK)) { - uint8 flags = fun->flags; - fputs("flags:", stdout); - -#define SHOW_FLAG(flag) if (flags & JSFUN_##flag) fputs(" " #flag, stdout); - - SHOW_FLAG(LAMBDA); - SHOW_FLAG(SETTER); - SHOW_FLAG(GETTER); - SHOW_FLAG(BOUND_METHOD); - SHOW_FLAG(HEAVYWEIGHT); - -#undef SHOW_FLAG - putchar('\n'); - } - } - - if (!js_Disassemble(cx, script, lines, stdout)) - return JS_FALSE; - SrcNotes(cx, script); - TryNotes(cx, script); - } - return JS_TRUE; -} - -static JSBool -DisassWithSrc(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ -#define LINE_BUF_LEN 512 - uintN i, len, line1, line2, bupline; - JSScript *script; - FILE *file; - char linebuf[LINE_BUF_LEN]; - jsbytecode *pc, *end; - static char sep[] = ";-------------------------"; - - for (i = 0; i < argc; i++) { - script = ValueToScript(cx, argv[i]); - if (!script) - continue; - - if (!script || !script->filename) { - JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, - JSSMSG_FILE_SCRIPTS_ONLY); - return JS_FALSE; - } - - file = fopen(script->filename, "r"); - if (!file) { - JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, - JSSMSG_CANT_OPEN, - script->filename, strerror(errno)); - return JS_FALSE; - } - - pc = script->code; - end = pc + script->length; - - /* burn the leading lines */ - line2 = JS_PCToLineNumber(cx, script, pc); - for (line1 = 0; line1 < line2 - 1; line1++) - fgets(linebuf, LINE_BUF_LEN, file); - - bupline = 0; - while (pc < end) { - line2 = JS_PCToLineNumber(cx, script, pc); - - if (line2 < line1) { - if (bupline != line2) { - bupline = line2; - fprintf(gOutFile, "%s %3u: BACKUP\n", sep, line2); - } - } else { - if (bupline && line1 == line2) - fprintf(gOutFile, "%s %3u: RESTORE\n", sep, line2); - bupline = 0; - while (line1 < line2) { - if (!fgets(linebuf, LINE_BUF_LEN, file)) { - JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, - JSSMSG_UNEXPECTED_EOF, - script->filename); - goto bail; - } - line1++; - fprintf(gOutFile, "%s %3u: %s", sep, line1, linebuf); - } - } - - len = js_Disassemble1(cx, script, pc, - PTRDIFF(pc, script->code, jsbytecode), - JS_TRUE, stdout); - if (!len) - return JS_FALSE; - pc += len; - } - - bail: - fclose(file); - } - return JS_TRUE; -#undef LINE_BUF_LEN -} - -static JSBool -Tracing(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSBool bval; - JSString *str; - - if (argc == 0) { - *rval = BOOLEAN_TO_JSVAL(cx->tracefp != 0); - return JS_TRUE; - } - - switch (JS_TypeOfValue(cx, argv[0])) { - case JSTYPE_NUMBER: - bval = JSVAL_IS_INT(argv[0]) - ? JSVAL_TO_INT(argv[0]) - : (jsint) *JSVAL_TO_DOUBLE(argv[0]); - break; - case JSTYPE_BOOLEAN: - bval = JSVAL_TO_BOOLEAN(argv[0]); - break; - default: - str = JS_ValueToString(cx, argv[0]); - if (!str) - return JS_FALSE; - fprintf(gErrFile, "tracing: illegal argument %s\n", - JS_GetStringBytes(str)); - return JS_TRUE; - } - cx->tracefp = bval ? stderr : NULL; - return JS_TRUE; -} - -typedef struct DumpAtomArgs { - JSContext *cx; - FILE *fp; -} DumpAtomArgs; - -static int -DumpAtom(JSHashEntry *he, int i, void *arg) -{ - DumpAtomArgs *args = (DumpAtomArgs *)arg; - FILE *fp = args->fp; - JSAtom *atom = (JSAtom *)he; - - fprintf(fp, "%3d %08x %5lu ", - i, (uintN)he->keyHash, (unsigned long)atom->number); - if (ATOM_IS_STRING(atom)) - fprintf(fp, "\"%s\"\n", js_AtomToPrintableString(args->cx, atom)); - else if (ATOM_IS_INT(atom)) - fprintf(fp, "%ld\n", (long)ATOM_TO_INT(atom)); - else - fprintf(fp, "%.16g\n", *ATOM_TO_DOUBLE(atom)); - return HT_ENUMERATE_NEXT; -} - -static void -DumpScope(JSContext *cx, JSObject *obj, FILE *fp) -{ - uintN i; - JSScope *scope; - JSScopeProperty *sprop; - - i = 0; - scope = OBJ_SCOPE(obj); - for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) { - if (SCOPE_HAD_MIDDLE_DELETE(scope) && !SCOPE_HAS_PROPERTY(scope, sprop)) - continue; - fprintf(fp, "%3u %p", i, sprop); - if (JSID_IS_INT(sprop->id)) { - fprintf(fp, " [%ld]", (long)JSVAL_TO_INT(sprop->id)); - } else if (JSID_IS_ATOM(sprop->id)) { - JSAtom *atom = JSID_TO_ATOM(sprop->id); - fprintf(fp, " \"%s\"", js_AtomToPrintableString(cx, atom)); - } else { - jsval v = OBJECT_TO_JSVAL(JSID_TO_OBJECT(sprop->id)); - fprintf(fp, " \"%s\"", js_ValueToPrintableString(cx, v)); - } - -#define DUMP_ATTR(name) if (sprop->attrs & JSPROP_##name) fputs(" " #name, fp) - DUMP_ATTR(ENUMERATE); - DUMP_ATTR(READONLY); - DUMP_ATTR(PERMANENT); - DUMP_ATTR(EXPORTED); - DUMP_ATTR(GETTER); - DUMP_ATTR(SETTER); -#undef DUMP_ATTR - - fprintf(fp, " slot %lu flags %x shortid %d\n", - sprop->slot, sprop->flags, sprop->shortid); - } -} - -static JSBool -DumpStats(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - uintN i; - JSString *str; - const char *bytes; - JSAtom *atom; - JSObject *obj2; - JSProperty *prop; - jsval value; - - for (i = 0; i < argc; i++) { - str = JS_ValueToString(cx, argv[i]); - if (!str) - return JS_FALSE; - bytes = JS_GetStringBytes(str); - if (strcmp(bytes, "arena") == 0) { -#ifdef JS_ARENAMETER - JS_DumpArenaStats(stdout); -#endif - } else if (strcmp(bytes, "atom") == 0) { - DumpAtomArgs args; - - fprintf(gOutFile, "\natom table contents:\n"); - args.cx = cx; - args.fp = stdout; - JS_HashTableEnumerateEntries(cx->runtime->atomState.table, - DumpAtom, - &args); -#ifdef HASHMETER - JS_HashTableDumpMeter(cx->runtime->atomState.table, - DumpAtom, - stdout); -#endif - } else if (strcmp(bytes, "global") == 0) { - DumpScope(cx, cx->globalObject, stdout); - } else { - atom = js_Atomize(cx, bytes, JS_GetStringLength(str), 0); - if (!atom) - return JS_FALSE; - if (!js_FindProperty(cx, ATOM_TO_JSID(atom), &obj, &obj2, &prop)) - return JS_FALSE; - if (prop) { - OBJ_DROP_PROPERTY(cx, obj2, prop); - if (!OBJ_GET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &value)) - return JS_FALSE; - } - if (!prop || !JSVAL_IS_OBJECT(value)) { - fprintf(gErrFile, "js: invalid stats argument %s\n", - bytes); - continue; - } - obj = JSVAL_TO_OBJECT(value); - if (obj) - DumpScope(cx, obj, stdout); - } - } - return JS_TRUE; -} - -#endif /* DEBUG */ - -#ifdef TEST_EXPORT -static JSBool -DoExport(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSAtom *atom; - JSObject *obj2; - JSProperty *prop; - JSBool ok; - uintN attrs; - - if (argc != 2) { - JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_DOEXP_USAGE); - return JS_FALSE; - } - if (!JS_ValueToObject(cx, argv[0], &obj)) - return JS_FALSE; - argv[0] = OBJECT_TO_JSVAL(obj); - atom = js_ValueToStringAtom(cx, argv[1]); - if (!atom) - return JS_FALSE; - if (!OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &obj2, &prop)) - return JS_FALSE; - if (!prop) { - ok = OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID, NULL, NULL, - JSPROP_EXPORTED, NULL); - } else { - ok = OBJ_GET_ATTRIBUTES(cx, obj, ATOM_TO_JSID(atom), prop, &attrs); - if (ok) { - attrs |= JSPROP_EXPORTED; - ok = OBJ_SET_ATTRIBUTES(cx, obj, ATOM_TO_JSID(atom), prop, &attrs); - } - OBJ_DROP_PROPERTY(cx, obj2, prop); - } - return ok; -} -#endif - -#ifdef TEST_CVTARGS -#include - -static const char * -EscapeWideString(jschar *w) -{ - static char enuf[80]; - static char hex[] = "0123456789abcdef"; - jschar u; - unsigned char b, c; - int i, j; - - if (!w) - return ""; - for (i = j = 0; i < sizeof enuf - 1; i++, j++) { - u = w[j]; - if (u == 0) - break; - b = (unsigned char)(u >> 8); - c = (unsigned char)(u); - if (b) { - if (i >= sizeof enuf - 6) - break; - enuf[i++] = '\\'; - enuf[i++] = 'u'; - enuf[i++] = hex[b >> 4]; - enuf[i++] = hex[b & 15]; - enuf[i++] = hex[c >> 4]; - enuf[i] = hex[c & 15]; - } else if (!isprint(c)) { - if (i >= sizeof enuf - 4) - break; - enuf[i++] = '\\'; - enuf[i++] = 'x'; - enuf[i++] = hex[c >> 4]; - enuf[i] = hex[c & 15]; - } else { - enuf[i] = (char)c; - } - } - enuf[i] = 0; - return enuf; -} - -#include - -static JSBool -ZZ_formatter(JSContext *cx, const char *format, JSBool fromJS, jsval **vpp, - va_list *app) -{ - jsval *vp; - va_list ap; - jsdouble re, im; - - printf("entering ZZ_formatter"); - vp = *vpp; - ap = *app; - if (fromJS) { - if (!JS_ValueToNumber(cx, vp[0], &re)) - return JS_FALSE; - if (!JS_ValueToNumber(cx, vp[1], &im)) - return JS_FALSE; - *va_arg(ap, jsdouble *) = re; - *va_arg(ap, jsdouble *) = im; - } else { - re = va_arg(ap, jsdouble); - im = va_arg(ap, jsdouble); - if (!JS_NewNumberValue(cx, re, &vp[0])) - return JS_FALSE; - if (!JS_NewNumberValue(cx, im, &vp[1])) - return JS_FALSE; - } - *vpp = vp + 2; - *app = ap; - printf("leaving ZZ_formatter"); - return JS_TRUE; -} - -static JSBool -ConvertArgs(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSBool b = JS_FALSE; - jschar c = 0; - int32 i = 0, j = 0; - uint32 u = 0; - jsdouble d = 0, I = 0, re = 0, im = 0; - char *s = NULL; - JSString *str = NULL; - jschar *w = NULL; - JSObject *obj2 = NULL; - JSFunction *fun = NULL; - jsval v = JSVAL_VOID; - JSBool ok; - - if (!JS_AddArgumentFormatter(cx, "ZZ", ZZ_formatter)) - return JS_FALSE;; - ok = JS_ConvertArguments(cx, argc, argv, "b/ciujdIsSWofvZZ*", - &b, &c, &i, &u, &j, &d, &I, &s, &str, &w, &obj2, - &fun, &v, &re, &im); - JS_RemoveArgumentFormatter(cx, "ZZ"); - if (!ok) - return JS_FALSE; - fprintf(gOutFile, - "b %u, c %x (%c), i %ld, u %lu, j %ld\n", - b, c, (char)c, i, u, j); - fprintf(gOutFile, - "d %g, I %g, s %s, S %s, W %s, obj %s, fun %s\n" - "v %s, re %g, im %g\n", - d, I, s, str ? JS_GetStringBytes(str) : "", EscapeWideString(w), - JS_GetStringBytes(JS_ValueToString(cx, OBJECT_TO_JSVAL(obj2))), - fun ? JS_GetStringBytes(JS_DecompileFunction(cx, fun, 4)) : "", - JS_GetStringBytes(JS_ValueToString(cx, v)), re, im); - return JS_TRUE; -} -#endif - -static JSBool -BuildDate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - fprintf(gOutFile, "built on %s at %s\n", __DATE__, __TIME__); - return JS_TRUE; -} - -static JSBool -Clear(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - if (argc != 0 && !JS_ValueToObject(cx, argv[0], &obj)) - return JS_FALSE; - JS_ClearScope(cx, obj); - return JS_TRUE; -} - -static JSBool -Intern(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSString *str; - - str = JS_ValueToString(cx, argv[0]); - if (!str) - return JS_FALSE; - if (!JS_InternUCStringN(cx, JS_GetStringChars(str), - JS_GetStringLength(str))) { - return JS_FALSE; - } - return JS_TRUE; -} - -static JSBool -Clone(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSFunction *fun; - JSObject *funobj, *parent, *clone; - - fun = JS_ValueToFunction(cx, argv[0]); - if (!fun) - return JS_FALSE; - funobj = JS_GetFunctionObject(fun); - if (argc > 1) { - if (!JS_ValueToObject(cx, argv[1], &parent)) - return JS_FALSE; - } else { - parent = JS_GetParent(cx, funobj); - } - clone = JS_CloneFunctionObject(cx, funobj, parent); - if (!clone) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(clone); - return JS_TRUE; -} - -static JSBool -Seal(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSObject *target; - JSBool deep = JS_FALSE; - - if (!JS_ConvertArguments(cx, argc, argv, "o/b", &target, &deep)) - return JS_FALSE; - if (!target) - return JS_TRUE; - return JS_SealObject(cx, target, deep); -} - -static JSBool -GetPDA(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSObject *vobj, *aobj, *pdobj; - JSBool ok; - JSPropertyDescArray pda; - JSPropertyDesc *pd; - uint32 i; - jsval v; - - if (!JS_ValueToObject(cx, argv[0], &vobj)) - return JS_FALSE; - if (!vobj) - return JS_TRUE; - - aobj = JS_NewArrayObject(cx, 0, NULL); - if (!aobj) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(aobj); - - ok = JS_GetPropertyDescArray(cx, vobj, &pda); - if (!ok) - return JS_FALSE; - pd = pda.array; - for (i = 0; i < pda.length; i++) { - pdobj = JS_NewObject(cx, NULL, NULL, NULL); - if (!pdobj) { - ok = JS_FALSE; - break; - } - - ok = JS_SetProperty(cx, pdobj, "id", &pd->id) && - JS_SetProperty(cx, pdobj, "value", &pd->value) && - (v = INT_TO_JSVAL(pd->flags), - JS_SetProperty(cx, pdobj, "flags", &v)) && - (v = INT_TO_JSVAL(pd->slot), - JS_SetProperty(cx, pdobj, "slot", &v)) && - JS_SetProperty(cx, pdobj, "alias", &pd->alias); - if (!ok) - break; - - v = OBJECT_TO_JSVAL(pdobj); - ok = JS_SetElement(cx, aobj, i, &v); - if (!ok) - break; - } - JS_PutPropertyDescArray(cx, &pda); - return ok; -} - -static JSBool -GetSLX(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSScript *script; - - script = ValueToScript(cx, argv[0]); - if (!script) - return JS_FALSE; - *rval = INT_TO_JSVAL(js_GetScriptLineExtent(script)); - return JS_TRUE; -} - -static JSBool -ToInt32(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - int32 i; - - if (!JS_ValueToInt32(cx, argv[0], &i)) - return JS_FALSE; - return JS_NewNumberValue(cx, i, rval); -} - -static JSBool -StringsAreUtf8(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - *rval = JS_StringsAreUTF8 () ? JSVAL_TRUE : JSVAL_FALSE; - return JS_TRUE; -} - -static const char* badUtf8 = "...\xC0..."; -static const char* bigUtf8 = "...\xFB\xBF\xBF\xBF\xBF..."; -static const jschar badSurrogate[] = { 'A', 'B', 'C', 0xDEEE, 'D', 'E', 0 }; - -static JSBool -TestUtf8(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - intN mode = 1; - jschar chars[20]; - size_t charsLength = 5; - char bytes[20]; - size_t bytesLength = 20; - if (argc && !JS_ValueToInt32(cx, *argv, &mode)) - return JS_FALSE; - - /* The following throw errors if compiled with UTF-8. */ - switch (mode) { - /* mode 1: malformed UTF-8 string. */ - case 1: - JS_NewStringCopyZ(cx, badUtf8); - break; - /* mode 2: big UTF-8 character. */ - case 2: - JS_NewStringCopyZ(cx, bigUtf8); - break; - /* mode 3: bad surrogate character. */ - case 3: - JS_EncodeCharacters(cx, badSurrogate, 6, bytes, &bytesLength); - break; - /* mode 4: use a too small buffer. */ - case 4: - JS_DecodeBytes(cx, "1234567890", 10, chars, &charsLength); - break; - default: - JS_ReportError(cx, "invalid mode parameter"); - return JS_FALSE; - } - return !JS_IsExceptionPending (cx); -} - -static JSFunctionSpec shell_functions[] = { - {"version", Version, 0}, - {"options", Options, 0}, - {"load", Load, 1}, - {"readline", ReadLine, 0}, - {"print", Print, 0}, - {"help", Help, 0}, - {"quit", Quit, 0}, - {"gc", GC, 0}, - {"trap", Trap, 3}, - {"untrap", Untrap, 2}, - {"line2pc", LineToPC, 0}, - {"pc2line", PCToLine, 0}, - {"stringsAreUtf8", StringsAreUtf8, 0}, - {"testUtf8", TestUtf8, 1}, -#ifdef DEBUG - {"dis", Disassemble, 1}, - {"dissrc", DisassWithSrc, 1}, - {"notes", Notes, 1}, - {"tracing", Tracing, 0}, - {"stats", DumpStats, 1}, -#endif -#ifdef TEST_EXPORT - {"xport", DoExport, 2}, -#endif -#ifdef TEST_CVTARGS - {"cvtargs", ConvertArgs, 0, 0, 12}, -#endif - {"build", BuildDate, 0}, - {"clear", Clear, 0}, - {"intern", Intern, 1}, - {"clone", Clone, 1}, - {"seal", Seal, 1, 0, 1}, - {"getpda", GetPDA, 1}, - {"getslx", GetSLX, 1}, - {"toint32", ToInt32, 1}, - {0} -}; - -/* NOTE: These must be kept in sync with the above. */ - -static char *shell_help_messages[] = { - "version([number]) Get or set JavaScript version number", - "options([option ...]) Get or toggle JavaScript options", - "load(['foo.js' ...]) Load files named by string arguments", - "readline() Read a single line from stdin", - "print([exp ...]) Evaluate and print expressions", - "help([name ...]) Display usage and help messages", - "quit() Quit the shell", - "gc() Run the garbage collector", - "trap([fun, [pc,]] exp) Trap bytecode execution", - "untrap(fun[, pc]) Remove a trap", - "line2pc([fun,] line) Map line number to PC", - "pc2line(fun[, pc]) Map PC to line number", - "stringsAreUTF8() Check if strings are UTF-8 encoded", - "testUTF8(mode) Perform UTF-8 tests (modes are 1 to 4)", -#ifdef DEBUG - "dis([fun]) Disassemble functions into bytecodes", - "dissrc([fun]) Disassemble functions with source lines", - "notes([fun]) Show source notes for functions", - "tracing([toggle]) Turn tracing on or off", - "stats([string ...]) Dump 'arena', 'atom', 'global' stats", -#endif -#ifdef TEST_EXPORT - "xport(obj, id) Export identified property from object", -#endif -#ifdef TEST_CVTARGS - "cvtargs(b, c, ...) Test JS_ConvertArguments", -#endif - "build() Show build date and time", - "clear([obj]) Clear properties of object", - "intern(str) Internalize str in the atom table", - "clone(fun[, scope]) Clone function object", - "seal(obj[, deep]) Seal object, or object graph if deep", - "getpda(obj) Get the property descriptors for obj", - "getslx(obj) Get script line extent", - "toint32(n) Testing hook for JS_ValueToInt32", - 0 -}; - -static void -ShowHelpHeader(void) -{ - fprintf(gOutFile, "%-14s %-22s %s\n", "Command", "Usage", "Description"); - fprintf(gOutFile, "%-14s %-22s %s\n", "=======", "=====", "==========="); -} - -static void -ShowHelpForCommand(uintN n) -{ - fprintf(gOutFile, "%-14.14s %s\n", shell_functions[n].name, shell_help_messages[n]); -} - -static JSBool -Help(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - uintN i, j; - int did_header, did_something; - JSType type; - JSFunction *fun; - JSString *str; - const char *bytes; - - fprintf(gOutFile, "%s\n", JS_GetImplementationVersion()); - if (argc == 0) { - ShowHelpHeader(); - for (i = 0; shell_functions[i].name; i++) - ShowHelpForCommand(i); - } else { - did_header = 0; - for (i = 0; i < argc; i++) { - did_something = 0; - type = JS_TypeOfValue(cx, argv[i]); - if (type == JSTYPE_FUNCTION) { - fun = JS_ValueToFunction(cx, argv[i]); - str = fun->atom ? ATOM_TO_STRING(fun->atom) : NULL; - } else if (type == JSTYPE_STRING) { - str = JSVAL_TO_STRING(argv[i]); - } else { - str = NULL; - } - if (str) { - bytes = JS_GetStringBytes(str); - for (j = 0; shell_functions[j].name; j++) { - if (!strcmp(bytes, shell_functions[j].name)) { - if (!did_header) { - did_header = 1; - ShowHelpHeader(); - } - did_something = 1; - ShowHelpForCommand(j); - break; - } - } - } - if (!did_something) { - str = JS_ValueToString(cx, argv[i]); - if (!str) - return JS_FALSE; - fprintf(gErrFile, "Sorry, no help for %s\n", - JS_GetStringBytes(str)); - } - } - } - return JS_TRUE; -} - -/* - * Define a JS object called "it". Give it class operations that printf why - * they're being called for tutorial purposes. - */ -enum its_tinyid { - ITS_COLOR, ITS_HEIGHT, ITS_WIDTH, ITS_FUNNY, ITS_ARRAY, ITS_RDONLY -}; - -static JSPropertySpec its_props[] = { - {"color", ITS_COLOR, JSPROP_ENUMERATE}, - {"height", ITS_HEIGHT, JSPROP_ENUMERATE}, - {"width", ITS_WIDTH, JSPROP_ENUMERATE}, - {"funny", ITS_FUNNY, JSPROP_ENUMERATE}, - {"array", ITS_ARRAY, JSPROP_ENUMERATE}, - {"rdonly", ITS_RDONLY, JSPROP_READONLY}, - {0} -}; - -static JSBool -its_item(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - *rval = OBJECT_TO_JSVAL(obj); - if (argc != 0) - JS_SetCallReturnValue2(cx, argv[0]); - return JS_TRUE; -} - -static JSBool -its_bindMethod(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - char *name; - JSObject *method; - - if (!JS_ConvertArguments(cx, argc, argv, "so", &name, &method)) - return JS_FALSE; - - *rval = OBJECT_TO_JSVAL(method); - - if (JS_TypeOfValue(cx, *rval) != JSTYPE_FUNCTION) { - JSString *valstr = JS_ValueToString(cx, *rval); - if (valstr) { - JS_ReportError(cx, "can't bind method %s to non-callable object %s", - name, JS_GetStringBytes(valstr)); - } - return JS_FALSE; - } - - if (!JS_DefineProperty(cx, obj, name, *rval, NULL, NULL, JSPROP_ENUMERATE)) - return JS_FALSE; - - return JS_SetParent(cx, method, obj); -} - -static JSFunctionSpec its_methods[] = { - {"item", its_item, 0}, - {"bindMethod", its_bindMethod, 2}, - {0} -}; - -#ifdef JSD_LOWLEVEL_SOURCE -/* - * This facilitates sending source to JSD (the debugger system) in the shell - * where the source is loaded using the JSFILE hack in jsscan. The function - * below is used as a callback for the jsdbgapi JS_SetSourceHandler hook. - * A more normal embedding (e.g. mozilla) loads source itself and can send - * source directly to JSD without using this hook scheme. - */ -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 its_noisy; /* whether to be noisy when finalizing it */ - -static JSBool -its_addProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - if (its_noisy) { - fprintf(gOutFile, "adding its property %s,", - JS_GetStringBytes(JS_ValueToString(cx, id))); - fprintf(gOutFile, " initial value %s\n", - JS_GetStringBytes(JS_ValueToString(cx, *vp))); - } - return JS_TRUE; -} - -static JSBool -its_delProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - if (its_noisy) { - fprintf(gOutFile, "deleting its property %s,", - JS_GetStringBytes(JS_ValueToString(cx, id))); - fprintf(gOutFile, " current value %s\n", - JS_GetStringBytes(JS_ValueToString(cx, *vp))); - } - return JS_TRUE; -} - -static JSBool -its_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - if (its_noisy) { - fprintf(gOutFile, "getting its property %s,", - JS_GetStringBytes(JS_ValueToString(cx, id))); - fprintf(gOutFile, " current value %s\n", - JS_GetStringBytes(JS_ValueToString(cx, *vp))); - } - return JS_TRUE; -} - -static JSBool -its_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - if (its_noisy) { - fprintf(gOutFile, "setting its property %s,", - JS_GetStringBytes(JS_ValueToString(cx, id))); - fprintf(gOutFile, " new value %s\n", - JS_GetStringBytes(JS_ValueToString(cx, *vp))); - } - if (JSVAL_IS_STRING(id) && - !strcmp(JS_GetStringBytes(JSVAL_TO_STRING(id)), "noisy")) { - return JS_ValueToBoolean(cx, *vp, &its_noisy); - } - return JS_TRUE; -} - -static JSBool -its_enumerate(JSContext *cx, JSObject *obj) -{ - if (its_noisy) - fprintf(gOutFile, "enumerate its properties\n"); - return JS_TRUE; -} - -static JSBool -its_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, - JSObject **objp) -{ - if (its_noisy) { - fprintf(gOutFile, "resolving its property %s, flags {%s,%s,%s}\n", - JS_GetStringBytes(JS_ValueToString(cx, id)), - (flags & JSRESOLVE_QUALIFIED) ? "qualified" : "", - (flags & JSRESOLVE_ASSIGNING) ? "assigning" : "", - (flags & JSRESOLVE_DETECTING) ? "detecting" : ""); - } - return JS_TRUE; -} - -static JSBool -its_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp) -{ - if (its_noisy) - fprintf(gOutFile, "converting it to %s type\n", JS_GetTypeName(cx, type)); - return JS_TRUE; -} - -static void -its_finalize(JSContext *cx, JSObject *obj) -{ - if (its_noisy) - fprintf(gOutFile, "finalizing it\n"); -} - -static JSClass its_class = { - "It", JSCLASS_NEW_RESOLVE, - its_addProperty, its_delProperty, its_getProperty, its_setProperty, - its_enumerate, (JSResolveOp)its_resolve, - its_convert, its_finalize -}; - -JSErrorFormatString jsShell_ErrorFormatString[JSErr_Limit] = { -#if JS_HAS_DFLT_MSG_STRINGS -#define MSG_DEF(name, number, count, exception, format) \ - { format, count } , -#else -#define MSG_DEF(name, number, count, exception, format) \ - { NULL, count } , -#endif -#include "jsshell.msg" -#undef MSG_DEF -}; - -static const JSErrorFormatString * -my_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber) -{ - if ((errorNumber > 0) && (errorNumber < JSShellErr_Limit)) - return &jsShell_ErrorFormatString[errorNumber]; - return NULL; -} - -static void -my_LoadErrorReporter(JSContext *cx, const char *message, JSErrorReport *report) -{ - if (!report) { - fprintf(gErrFile, "%s\n", message); - return; - } - - /* Ignore any exceptions */ - if (JSREPORT_IS_EXCEPTION(report->flags)) - return; - - /* Otherwise, fall back to the ordinary error reporter. */ - my_ErrorReporter(cx, message, report); -} - -static void -my_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report) -{ - int i, j, k, n; - char *prefix, *tmp; - const char *ctmp; - - if (!report) { - fprintf(gErrFile, "%s\n", message); - return; - } - - /* Conditionally ignore reported warnings. */ - if (JSREPORT_IS_WARNING(report->flags) && !reportWarnings) - return; - - prefix = NULL; - if (report->filename) - prefix = JS_smprintf("%s:", report->filename); - if (report->lineno) { - tmp = prefix; - prefix = JS_smprintf("%s%u: ", tmp ? tmp : "", report->lineno); - JS_free(cx, tmp); - } - if (JSREPORT_IS_WARNING(report->flags)) { - tmp = prefix; - prefix = JS_smprintf("%s%swarning: ", - tmp ? tmp : "", - JSREPORT_IS_STRICT(report->flags) ? "strict " : ""); - JS_free(cx, tmp); - } - - /* embedded newlines -- argh! */ - while ((ctmp = strchr(message, '\n')) != 0) { - ctmp++; - if (prefix) - fputs(prefix, gErrFile); - fwrite(message, 1, ctmp - message, gErrFile); - message = ctmp; - } - - /* If there were no filename or lineno, the prefix might be empty */ - if (prefix) - fputs(prefix, gErrFile); - fputs(message, gErrFile); - - if (!report->linebuf) { - fputc('\n', gErrFile); - goto out; - } - - /* report->linebuf usually ends with a newline. */ - n = strlen(report->linebuf); - fprintf(gErrFile, ":\n%s%s%s%s", - prefix, - report->linebuf, - (n > 0 && report->linebuf[n-1] == '\n') ? "" : "\n", - prefix); - n = PTRDIFF(report->tokenptr, report->linebuf, char); - for (i = j = 0; i < n; i++) { - if (report->linebuf[i] == '\t') { - for (k = (j + 8) & ~7; j < k; j++) { - fputc('.', gErrFile); - } - continue; - } - fputc('.', gErrFile); - j++; - } - fputs("^\n", gErrFile); - out: - if (!JSREPORT_IS_WARNING(report->flags)) { - if (report->errorNumber == JSMSG_OUT_OF_MEMORY) { - gExitCode = EXITCODE_OUT_OF_MEMORY; - } else { - gExitCode = EXITCODE_RUNTIME_ERROR; - } - } - JS_free(cx, prefix); -} - -#if defined(SHELL_HACK) && defined(DEBUG) && defined(XP_UNIX) -static JSBool -Exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSFunction *fun; - const char *name, **nargv; - uintN i, nargc; - JSString *str; - pid_t pid; - int status; - - fun = JS_ValueToFunction(cx, argv[-2]); - if (!fun) - return JS_FALSE; - if (!fun->atom) - return JS_TRUE; - name = JS_GetStringBytes(ATOM_TO_STRING(fun->atom)); - nargc = 1 + argc; - nargv = JS_malloc(cx, (nargc + 1) * sizeof(char *)); - if (!nargv) - return JS_FALSE; - nargv[0] = name; - for (i = 1; i < nargc; i++) { - str = JS_ValueToString(cx, argv[i-1]); - if (!str) { - JS_free(cx, nargv); - return JS_FALSE; - } - nargv[i] = JS_GetStringBytes(str); - } - nargv[nargc] = 0; - pid = fork(); - switch (pid) { - case -1: - perror("js"); - break; - case 0: - (void) execvp(name, (char **)nargv); - perror("js"); - exit(127); - default: - while (waitpid(pid, &status, 0) < 0 && errno == EINTR) - continue; - break; - } - JS_free(cx, nargv); - return JS_TRUE; -} -#endif - -#define LAZY_STANDARD_CLASSES - -static JSBool -global_enumerate(JSContext *cx, JSObject *obj) -{ -#ifdef LAZY_STANDARD_CLASSES - return JS_EnumerateStandardClasses(cx, obj); -#else - return JS_TRUE; -#endif -} - -static JSBool -global_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, - JSObject **objp) -{ -#ifdef LAZY_STANDARD_CLASSES - if ((flags & JSRESOLVE_ASSIGNING) == 0) { - JSBool resolved; - - if (!JS_ResolveStandardClass(cx, obj, id, &resolved)) - return JS_FALSE; - if (resolved) { - *objp = obj; - return JS_TRUE; - } - } -#endif - -#if defined(SHELL_HACK) && defined(DEBUG) && defined(XP_UNIX) - if ((flags & (JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING)) == 0) { - /* - * Do this expensive hack only for unoptimized Unix builds, which are - * not used for benchmarking. - */ - char *path, *comp, *full; - const char *name; - JSBool ok, found; - JSFunction *fun; - - if (!JSVAL_IS_STRING(id)) - return JS_TRUE; - path = getenv("PATH"); - if (!path) - return JS_TRUE; - path = JS_strdup(cx, path); - if (!path) - return JS_FALSE; - name = JS_GetStringBytes(JSVAL_TO_STRING(id)); - ok = JS_TRUE; - for (comp = strtok(path, ":"); comp; comp = strtok(NULL, ":")) { - if (*comp != '\0') { - full = JS_smprintf("%s/%s", comp, name); - if (!full) { - JS_ReportOutOfMemory(cx); - ok = JS_FALSE; - break; - } - } else { - full = (char *)name; - } - found = (access(full, X_OK) == 0); - if (*comp != '\0') - free(full); - if (found) { - fun = JS_DefineFunction(cx, obj, name, Exec, 0, - JSPROP_ENUMERATE); - ok = (fun != NULL); - if (ok) - *objp = obj; - break; - } - } - JS_free(cx, path); - return ok; - } -#else - return JS_TRUE; -#endif -} - -JSClass global_class = { - "global", JSCLASS_NEW_RESOLVE, - JS_PropertyStub, JS_PropertyStub, - JS_PropertyStub, JS_PropertyStub, - global_enumerate, (JSResolveOp) global_resolve, - JS_ConvertStub, JS_FinalizeStub -}; - -static JSBool -env_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ -/* XXX porting may be easy, but these don't seem to supply setenv by default */ -#if !defined XP_BEOS && !defined XP_OS2 && !defined SOLARIS - JSString *idstr, *valstr; - const char *name, *value; - int rv; - - idstr = JS_ValueToString(cx, id); - valstr = JS_ValueToString(cx, *vp); - if (!idstr || !valstr) - return JS_FALSE; - name = JS_GetStringBytes(idstr); - value = JS_GetStringBytes(valstr); -#if defined XP_WIN || defined HPUX || defined OSF1 || defined IRIX - { - char *waste = JS_smprintf("%s=%s", name, value); - if (!waste) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - rv = putenv(waste); -#ifdef XP_WIN - /* - * HPUX9 at least still has the bad old non-copying putenv. - * - * Per mail from , OSF1 also has a putenv - * that will crash if you pass it an auto char array (so it must place - * its argument directly in the char *environ[] array). - */ - free(waste); -#endif - } -#else - rv = setenv(name, value, 1); -#endif - if (rv < 0) { - JS_ReportError(cx, "can't set envariable %s to %s", name, value); - return JS_FALSE; - } - *vp = STRING_TO_JSVAL(valstr); -#endif /* !defined XP_BEOS && !defined XP_OS2 && !defined SOLARIS */ - return JS_TRUE; -} - -static JSBool -env_enumerate(JSContext *cx, JSObject *obj) -{ - static JSBool reflected; - char **evp, *name, *value; - JSString *valstr; - JSBool ok; - - if (reflected) - return JS_TRUE; - - for (evp = (char **)JS_GetPrivate(cx, obj); (name = *evp) != NULL; evp++) { - value = strchr(name, '='); - if (!value) - continue; - *value++ = '\0'; - valstr = JS_NewStringCopyZ(cx, value); - if (!valstr) { - ok = JS_FALSE; - } else { - ok = JS_DefineProperty(cx, obj, name, STRING_TO_JSVAL(valstr), - NULL, NULL, JSPROP_ENUMERATE); - } - value[-1] = '='; - if (!ok) - return JS_FALSE; - } - - reflected = JS_TRUE; - return JS_TRUE; -} - -static JSBool -env_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, - JSObject **objp) -{ - JSString *idstr, *valstr; - const char *name, *value; - - if (flags & JSRESOLVE_ASSIGNING) - return JS_TRUE; - - idstr = JS_ValueToString(cx, id); - if (!idstr) - return JS_FALSE; - name = JS_GetStringBytes(idstr); - value = getenv(name); - if (value) { - valstr = JS_NewStringCopyZ(cx, value); - if (!valstr) - return JS_FALSE; - if (!JS_DefineProperty(cx, obj, name, STRING_TO_JSVAL(valstr), - NULL, NULL, JSPROP_ENUMERATE)) { - return JS_FALSE; - } - *objp = obj; - } - return JS_TRUE; -} - -static JSClass env_class = { - "environment", JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE, - JS_PropertyStub, JS_PropertyStub, - JS_PropertyStub, env_setProperty, - env_enumerate, (JSResolveOp) env_resolve, - JS_ConvertStub, JS_FinalizeStub -}; - -#ifdef NARCISSUS - -static JSBool -defineProperty(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSString *str; - jsval value; - JSBool dontDelete, readOnly, dontEnum; - const jschar *chars; - size_t length; - uintN attrs; - - dontDelete = readOnly = dontEnum = JS_FALSE; - if (!JS_ConvertArguments(cx, argc, argv, "Sv/bbb", - &str, &value, &dontDelete, &readOnly, &dontEnum)) { - return JS_FALSE; - } - chars = JS_GetStringChars(str); - length = JS_GetStringLength(str); - attrs = dontEnum ? 0 : JSPROP_ENUMERATE; - if (dontDelete) - attrs |= JSPROP_PERMANENT; - if (readOnly) - attrs |= JSPROP_READONLY; - return JS_DefineUCProperty(cx, obj, chars, length, value, NULL, NULL, - attrs); -} - -static JSBool -Evaluate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - /* function evaluate(source, filename, lineno) { ... } */ - JSString *source; - const char *filename = ""; - jsuint lineno = 0; - uint32 oldopts; - JSBool ok; - - if (argc == 0) { - *rval = JSVAL_VOID; - return JS_TRUE; - } - - if (!JS_ConvertArguments(cx, argc, argv, "S/su", - &source, &filename, &lineno)) { - return JS_FALSE; - } - - oldopts = JS_GetOptions(cx); - JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO); - ok = JS_EvaluateUCScript(cx, obj, JS_GetStringChars(source), - JS_GetStringLength(source), filename, - lineno, rval); - JS_SetOptions(cx, oldopts); - - return ok; -} - -#include -#include - -/* - * Returns a JS_malloc'd string (that the caller needs to JS_free) - * containing the directory (non-leaf) part of |from| prepended to |leaf|. - * If |from| is empty or a leaf, MakeAbsolutePathname returns a copy of leaf. - * Returns NULL to indicate an error. - */ -static char * -MakeAbsolutePathname(JSContext *cx, const char *from, const char *leaf) -{ - size_t dirlen; - char *dir; - const char *slash = NULL, *cp; - - cp = from; - while (*cp) { - if (*cp == '/' -#ifdef XP_WIN - || *cp == '\\' -#endif - ) { - slash = cp; - } - - ++cp; - } - - if (!slash) { - /* We were given a leaf or |from| was empty. */ - return JS_strdup(cx, leaf); - } - - /* Else, we were given a real pathname, return that + the leaf. */ - dirlen = slash - from + 1; - dir = JS_malloc(cx, dirlen + strlen(leaf) + 1); - if (!dir) - return NULL; - - strncpy(dir, from, dirlen); - strcpy(dir + dirlen, leaf); /* Note: we can't use strcat here. */ - - return dir; -} - -static JSBool -snarf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSString *str; - const char *filename; - char *pathname; - JSStackFrame *fp; - int fd, cc; - JSBool ok; - size_t len; - char *buf; - struct stat sb; - - str = JS_ValueToString(cx, argv[0]); - if (!str) - return JS_FALSE; - filename = JS_GetStringBytes(str); - - /* Get the currently executing script's name. */ - fp = JS_GetScriptedCaller(cx, NULL); - JS_ASSERT(fp && fp->script->filename); - pathname = MakeAbsolutePathname(cx, fp->script->filename, filename); - if (!pathname) - return JS_FALSE; - - fd = open(pathname, O_RDONLY); - ok = JS_TRUE; - len = 0; - buf = NULL; - if (fd < 0) { - JS_ReportError(cx, "can't open %s: %s", pathname, strerror(errno)); - ok = JS_FALSE; - } else if (fstat(fd, &sb) < 0) { - JS_ReportError(cx, "can't stat %s", pathname); - ok = JS_FALSE; - } else { - len = sb.st_size; - buf = JS_malloc(cx, len + 1); - if (!buf) { - ok = JS_FALSE; - } else if ((cc = read(fd, buf, len)) != len) { - JS_free(cx, buf); - JS_ReportError(cx, "can't read %s: %s", pathname, - (cc < 0) ? strerror(errno) : "short read"); - ok = JS_FALSE; - } - } - close(fd); - JS_free(cx, pathname); - if (!ok) - return ok; - buf[len] = '\0'; - str = JS_NewString(cx, buf, len); - if (!str) { - JS_free(cx, buf); - return JS_FALSE; - } - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -#endif /* NARCISSUS */ - -int -main(int argc, char **argv, char **envp) -{ - int stackDummy; - JSRuntime *rt; - JSContext *cx; - JSObject *glob, *it, *envobj; - int result; -#ifdef LIVECONNECT - JavaVM *java_vm = NULL; -#endif -#ifdef JSDEBUGGER_JAVA_UI - JNIEnv *java_env; -#endif - - gStackBase = (jsuword)&stackDummy; - -#ifdef XP_OS2 - /* these streams are normally line buffered on OS/2 and need a \n, * - * so we need to unbuffer then to get a reasonable prompt */ - setbuf(stdout,0); - setbuf(stderr,0); -#endif - - gErrFile = stderr; - gOutFile = stdout; - - argc--; - argv++; - - rt = JS_NewRuntime(64L * 1024L * 1024L); - if (!rt) - return 1; - - cx = JS_NewContext(rt, gStackChunkSize); - if (!cx) - return 1; - JS_SetErrorReporter(cx, my_ErrorReporter); - - glob = JS_NewObject(cx, &global_class, NULL, NULL); - if (!glob) - return 1; -#ifdef LAZY_STANDARD_CLASSES - JS_SetGlobalObject(cx, glob); -#else - if (!JS_InitStandardClasses(cx, glob)) - return 1; -#endif - if (!JS_DefineFunctions(cx, glob, shell_functions)) - return 1; - - it = JS_DefineObject(cx, glob, "it", &its_class, NULL, 0); - if (!it) - return 1; - if (!JS_DefineProperties(cx, it, its_props)) - return 1; - if (!JS_DefineFunctions(cx, it, its_methods)) - return 1; - -#ifdef PERLCONNECT - if (!JS_InitPerlClass(cx, glob)) - return 1; -#endif - -#ifdef JSDEBUGGER - /* - * XXX A command line option to enable debugging (or not) would be good - */ - _jsdc = JSD_DebuggerOnForUser(rt, NULL, NULL); - if (!_jsdc) - return 1; - JSD_JSContextInUse(_jsdc, cx); -#ifdef JSD_LOWLEVEL_SOURCE - JS_SetSourceHandler(rt, SendSourceToJSDebugger, _jsdc); -#endif /* JSD_LOWLEVEL_SOURCE */ -#ifdef JSDEBUGGER_JAVA_UI - _jsdjc = JSDJ_CreateContext(); - if (! _jsdjc) - return 1; - JSDJ_SetJSDContext(_jsdjc, _jsdc); - java_env = JSDJ_CreateJavaVMAndStartDebugger(_jsdjc); -#ifdef LIVECONNECT - if (java_env) - (*java_env)->GetJavaVM(java_env, &java_vm); -#endif - /* - * XXX This would be the place to wait for the debugger to start. - * Waiting would be nice in general, but especially when a js file - * is passed on the cmd line. - */ -#endif /* JSDEBUGGER_JAVA_UI */ -#ifdef JSDEBUGGER_C_UI - JSDB_InitDebugger(rt, _jsdc, 0); -#endif /* JSDEBUGGER_C_UI */ -#endif /* JSDEBUGGER */ - -#ifdef LIVECONNECT - if (!JSJ_SimpleInit(cx, glob, java_vm, getenv("CLASSPATH"))) - return 1; -#endif - - envobj = JS_DefineObject(cx, glob, "environment", &env_class, NULL, 0); - if (!envobj || !JS_SetPrivate(cx, envobj, envp)) - return 1; - -#ifdef NARCISSUS - { - jsval v; - static const char Object_prototype[] = "Object.prototype"; - - if (!JS_DefineFunction(cx, glob, "snarf", snarf, 1, 0)) - return 1; - if (!JS_DefineFunction(cx, glob, "evaluate", Evaluate, 3, 0)) - return 1; - - if (!JS_EvaluateScript(cx, glob, - Object_prototype, sizeof Object_prototype - 1, - NULL, 0, &v)) { - return 1; - } - if (!JS_DefineFunction(cx, JSVAL_TO_OBJECT(v), "__defineProperty__", - defineProperty, 5, 0)) { - return 1; - } - } -#endif - - result = ProcessArgs(cx, glob, argv, argc); - -#ifdef JSDEBUGGER - if (_jsdc) - JSD_DebuggerOff(_jsdc); -#endif /* JSDEBUGGER */ - - JS_DestroyContext(cx); - JS_DestroyRuntime(rt); - JS_ShutDown(); - return result; -} diff --git a/lib/javascript/js.mak b/lib/javascript/js.mak deleted file mode 100644 index dfcfdeab..00000000 --- a/lib/javascript/js.mak +++ /dev/null @@ -1,4115 +0,0 @@ -# Microsoft Developer Studio Generated NMAKE File, Format Version 4.20 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 -# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 -# TARGTYPE "Win32 (x86) Static Library" 0x0104 - -!IF "$(CFG)" == "" -CFG=jsshell - Win32 Debug -!MESSAGE No configuration specified. Defaulting to jsshell - Win32 Debug. -!ENDIF - -!IF "$(CFG)" != "js - Win32 Release" && "$(CFG)" != "js - Win32 Debug" &&\ - "$(CFG)" != "jsshell - Win32 Release" && "$(CFG)" != "jsshell - Win32 Debug" &&\ - "$(CFG)" != "fdlibm - Win32 Release" && "$(CFG)" != "fdlibm - Win32 Debug" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE on this makefile -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "js.mak" CFG="jsshell - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "js - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "js - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "jsshell - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "jsshell - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE "fdlibm - Win32 Release" (based on "Win32 (x86) Static Library") -!MESSAGE "fdlibm - Win32 Debug" (based on "Win32 (x86) Static Library") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -!IF "$(OS)" == "Windows_NT" -NULL= -!ELSE -NULL=nul -!ENDIF -################################################################################ -# Begin Project -# PROP Target_Last_Scanned "jsshell - Win32 Debug" - -!IF "$(CFG)" == "js - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "js___Wi1" -# PROP BASE Intermediate_Dir "js___Wi1" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Target_Dir "" -OUTDIR=.\Release -INTDIR=.\Release - -ALL : "fdlibm - Win32 Release" "$(OUTDIR)\js32.dll" - -CLEAN : - -@erase "$(INTDIR)\jsapi.obj" - -@erase "$(INTDIR)\jsarena.obj" - -@erase "$(INTDIR)\jsarray.obj" - -@erase "$(INTDIR)\jsatom.obj" - -@erase "$(INTDIR)\jsbool.obj" - -@erase "$(INTDIR)\jscntxt.obj" - -@erase "$(INTDIR)\jsdate.obj" - -@erase "$(INTDIR)\jsdbgapi.obj" - -@erase "$(INTDIR)\jsdhash.obj" - -@erase "$(INTDIR)\jsdtoa.obj" - -@erase "$(INTDIR)\jsemit.obj" - -@erase "$(INTDIR)\jsexn.obj" - -@erase "$(INTDIR)\jsfun.obj" - -@erase "$(INTDIR)\jsgc.obj" - -@erase "$(INTDIR)\jshash.obj" - -@erase "$(INTDIR)\jsinterp.obj" - -@erase "$(INTDIR)\jslock.obj" - -@erase "$(INTDIR)\jslog2.obj" - -@erase "$(INTDIR)\jslong.obj" - -@erase "$(INTDIR)\jsmath.obj" - -@erase "$(INTDIR)\jsnum.obj" - -@erase "$(INTDIR)\jsobj.obj" - -@erase "$(INTDIR)\jsopcode.obj" - -@erase "$(INTDIR)\jsparse.obj" - -@erase "$(INTDIR)\jsprf.obj" - -@erase "$(INTDIR)\jsregexp.obj" - -@erase "$(INTDIR)\jsscan.obj" - -@erase "$(INTDIR)\jsscope.obj" - -@erase "$(INTDIR)\jsscript.obj" - -@erase "$(INTDIR)\jsstr.obj" - -@erase "$(INTDIR)\jsutil.obj" - -@erase "$(INTDIR)\jsxdrapi.obj" - -@erase "$(INTDIR)\jsxml.obj" - -@erase "$(INTDIR)\prmjtime.obj" - -@erase "$(OUTDIR)\js32.dll" - -@erase "$(OUTDIR)\js32.exp" - -@erase "$(OUTDIR)\js32.lib" - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -CPP=cl.exe -# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D _X86_=1 /D "_WINDOWS" /YX /c -# ADD CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D _X86_=1 /D "_WINDOWS" /D "WIN32" /D "XP_WIN" /D "JSFILE" /D "EXPORT_JS_API" /YX /c -CPP_PROJ=/nologo /MD /W3 /GX /O2 /D "NDEBUG" /D _X86_=1 /D "_WINDOWS" /D "WIN32" /D\ - "XP_WIN" /D "JSFILE" /D "EXPORT_JS_API" /Fp"$(INTDIR)/js.pch" /YX\ - /Fo"$(INTDIR)/" /c -CPP_OBJS=.\Release/ -CPP_SBRS=.\. - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.c{$(CPP_SBRS)}.sbr: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_SBRS)}.sbr: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_SBRS)}.sbr: - $(CPP) $(CPP_PROJ) $< - -MTL=mktyplib.exe -# ADD BASE MTL /nologo /D "NDEBUG" /win32 -# ADD MTL /nologo /D "NDEBUG" /win32 -MTL_PROJ=/nologo /D "NDEBUG" /win32 -RSC=rc.exe -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o"$(OUTDIR)/js.bsc" -BSC32_SBRS= \ - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /out:"Release/js32.dll" -# SUBTRACT LINK32 /nodefaultlib -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ - advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\ - odbccp32.lib /nologo /subsystem:windows /dll /incremental:no\ - /pdb:"$(OUTDIR)/js32.pdb" /machine:I386 /out:"$(OUTDIR)/js32.dll"\ - /implib:"$(OUTDIR)/js32.lib" /opt:ref /opt:noicf -LINK32_OBJS= \ - "$(INTDIR)\jsapi.obj" \ - "$(INTDIR)\jsarena.obj" \ - "$(INTDIR)\jsarray.obj" \ - "$(INTDIR)\jsatom.obj" \ - "$(INTDIR)\jsbool.obj" \ - "$(INTDIR)\jscntxt.obj" \ - "$(INTDIR)\jsdate.obj" \ - "$(INTDIR)\jsdbgapi.obj" \ - "$(INTDIR)\jsdhash.obj" \ - "$(INTDIR)\jsdtoa.obj" \ - "$(INTDIR)\jsemit.obj" \ - "$(INTDIR)\jsexn.obj" \ - "$(INTDIR)\jsfun.obj" \ - "$(INTDIR)\jsgc.obj" \ - "$(INTDIR)\jshash.obj" \ - "$(INTDIR)\jsinterp.obj" \ - "$(INTDIR)\jslock.obj" \ - "$(INTDIR)\jslog2.obj" \ - "$(INTDIR)\jslong.obj" \ - "$(INTDIR)\jsmath.obj" \ - "$(INTDIR)\jsnum.obj" \ - "$(INTDIR)\jsobj.obj" \ - "$(INTDIR)\jsopcode.obj" \ - "$(INTDIR)\jsparse.obj" \ - "$(INTDIR)\jsprf.obj" \ - "$(INTDIR)\jsregexp.obj" \ - "$(INTDIR)\jsscan.obj" \ - "$(INTDIR)\jsscope.obj" \ - "$(INTDIR)\jsscript.obj" \ - "$(INTDIR)\jsstr.obj" \ - "$(INTDIR)\jsutil.obj" \ - "$(INTDIR)\jsxdrapi.obj" \ - "$(INTDIR)\jsxml.obj" \ - "$(INTDIR)\prmjtime.obj" \ - "$(OUTDIR)\fdlibm.lib" - -"$(OUTDIR)\js32.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "js___Wi2" -# PROP BASE Intermediate_Dir "js___Wi2" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Target_Dir "" -OUTDIR=.\Debug -INTDIR=.\Debug - -ALL : "fdlibm - Win32 Debug" "$(OUTDIR)\js32.dll" - -CLEAN : - -@erase "$(INTDIR)\jsapi.obj" - -@erase "$(INTDIR)\jsarena.obj" - -@erase "$(INTDIR)\jsarray.obj" - -@erase "$(INTDIR)\jsatom.obj" - -@erase "$(INTDIR)\jsbool.obj" - -@erase "$(INTDIR)\jscntxt.obj" - -@erase "$(INTDIR)\jsdate.obj" - -@erase "$(INTDIR)\jsdbgapi.obj" - -@erase "$(INTDIR)\jsdhash.obj" - -@erase "$(INTDIR)\jsdtoa.obj" - -@erase "$(INTDIR)\jsemit.obj" - -@erase "$(INTDIR)\jsexn.obj" - -@erase "$(INTDIR)\jsfun.obj" - -@erase "$(INTDIR)\jsgc.obj" - -@erase "$(INTDIR)\jshash.obj" - -@erase "$(INTDIR)\jsinterp.obj" - -@erase "$(INTDIR)\jslock.obj" - -@erase "$(INTDIR)\jslog2.obj" - -@erase "$(INTDIR)\jslong.obj" - -@erase "$(INTDIR)\jsmath.obj" - -@erase "$(INTDIR)\jsnum.obj" - -@erase "$(INTDIR)\jsobj.obj" - -@erase "$(INTDIR)\jsopcode.obj" - -@erase "$(INTDIR)\jsparse.obj" - -@erase "$(INTDIR)\jsprf.obj" - -@erase "$(INTDIR)\jsregexp.obj" - -@erase "$(INTDIR)\jsscan.obj" - -@erase "$(INTDIR)\jsscope.obj" - -@erase "$(INTDIR)\jsscript.obj" - -@erase "$(INTDIR)\jsstr.obj" - -@erase "$(INTDIR)\jsutil.obj" - -@erase "$(INTDIR)\jsxdrapi.obj" - -@erase "$(INTDIR)\jsxml.obj" - -@erase "$(INTDIR)\prmjtime.obj" - -@erase "$(OUTDIR)\js32.dll" - -@erase "$(OUTDIR)\js32.exp" - -@erase "$(OUTDIR)\js32.ilk" - -@erase "$(OUTDIR)\js32.lib" - -@erase "$(OUTDIR)\js32.pdb" - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -CPP=cl.exe -# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D _X86_=1 /D "_WINDOWS" /YX /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "DEBUG" /D _X86_=1 /D "_WINDOWS" /D "WIN32" /D "XP_WIN" /D "JSFILE" /D "EXPORT_JS_API" /YX /c -CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "DEBUG" /D _X86_=1 /D "_WINDOWS"\ - /D "WIN32" /D "XP_WIN" /D "JSFILE" /D "EXPORT_JS_API" /Fp"$(INTDIR)/js.pch" /YX\ - /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c -CPP_OBJS=.\Debug/ -CPP_SBRS=.\. - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.c{$(CPP_SBRS)}.sbr: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_SBRS)}.sbr: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_SBRS)}.sbr: - $(CPP) $(CPP_PROJ) $< - -MTL=mktyplib.exe -# ADD BASE MTL /nologo /D "_DEBUG" /win32 -# ADD MTL /nologo /D "_DEBUG" /win32 -MTL_PROJ=/nologo /D "_DEBUG" /win32 -RSC=rc.exe -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o"$(OUTDIR)/js.bsc" -BSC32_SBRS= \ - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"Debug/js32.dll" -# SUBTRACT LINK32 /nodefaultlib -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ - advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\ - odbccp32.lib /nologo /subsystem:windows /dll /incremental:yes\ - /pdb:"$(OUTDIR)/js32.pdb" /debug /machine:I386 /out:"$(OUTDIR)/js32.dll"\ - /implib:"$(OUTDIR)/js32.lib" -LINK32_OBJS= \ - "$(INTDIR)\jsapi.obj" \ - "$(INTDIR)\jsarena.obj" \ - "$(INTDIR)\jsarray.obj" \ - "$(INTDIR)\jsatom.obj" \ - "$(INTDIR)\jsbool.obj" \ - "$(INTDIR)\jscntxt.obj" \ - "$(INTDIR)\jsdate.obj" \ - "$(INTDIR)\jsdbgapi.obj" \ - "$(INTDIR)\jsdhash.obj" \ - "$(INTDIR)\jsdtoa.obj" \ - "$(INTDIR)\jsemit.obj" \ - "$(INTDIR)\jsexn.obj" \ - "$(INTDIR)\jsfun.obj" \ - "$(INTDIR)\jsgc.obj" \ - "$(INTDIR)\jshash.obj" \ - "$(INTDIR)\jsinterp.obj" \ - "$(INTDIR)\jslock.obj" \ - "$(INTDIR)\jslog2.obj" \ - "$(INTDIR)\jslong.obj" \ - "$(INTDIR)\jsmath.obj" \ - "$(INTDIR)\jsnum.obj" \ - "$(INTDIR)\jsobj.obj" \ - "$(INTDIR)\jsopcode.obj" \ - "$(INTDIR)\jsparse.obj" \ - "$(INTDIR)\jsprf.obj" \ - "$(INTDIR)\jsregexp.obj" \ - "$(INTDIR)\jsscan.obj" \ - "$(INTDIR)\jsscope.obj" \ - "$(INTDIR)\jsscript.obj" \ - "$(INTDIR)\jsstr.obj" \ - "$(INTDIR)\jsutil.obj" \ - "$(INTDIR)\jsxdrapi.obj" \ - "$(INTDIR)\jsxml.obj" \ - "$(INTDIR)\prmjtime.obj" \ - "$(OUTDIR)\fdlibm.lib" - -"$(OUTDIR)\js32.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "jsshell - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "jsshell\Release" -# PROP BASE Intermediate_Dir "jsshell\Release" -# PROP BASE Target_Dir "jsshell" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Target_Dir "jsshell" -OUTDIR=.\Release -INTDIR=.\Release - -ALL : "js - Win32 Release" "$(OUTDIR)\jsshell.exe" - -CLEAN : - -@erase "$(INTDIR)\js.obj" - -@erase "$(OUTDIR)\jsshell.exe" - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -CPP=cl.exe -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c -# ADD CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "_CONSOLE" /D "WIN32" /D "XP_WIN" /D "JSFILE" /YX /c -CPP_PROJ=/nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "_CONSOLE" /D "WIN32" /D\ - "XP_WIN" /D "JSFILE" /Fp"$(INTDIR)/jsshell.pch" /YX /Fo"$(INTDIR)/" /c -CPP_OBJS=.\Release/ -CPP_SBRS=.\. - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.c{$(CPP_SBRS)}.sbr: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_SBRS)}.sbr: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_SBRS)}.sbr: - $(CPP) $(CPP_PROJ) $< - -RSC=rc.exe -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o"$(OUTDIR)/jsshell.bsc" -BSC32_SBRS= \ - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ - advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\ - odbccp32.lib /nologo /subsystem:console /incremental:no\ - /pdb:"$(OUTDIR)/jsshell.pdb" /machine:I386 /out:"$(OUTDIR)/jsshell.exe" -LINK32_OBJS= \ - "$(INTDIR)\js.obj" \ - "$(OUTDIR)\js32.lib" - -"$(OUTDIR)\jsshell.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "jsshell - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "jsshell\jsshell_" -# PROP BASE Intermediate_Dir "jsshell\jsshell_" -# PROP BASE Target_Dir "jsshell" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Target_Dir "jsshell" -OUTDIR=.\Debug -INTDIR=.\Debug - -ALL : "js - Win32 Debug" "$(OUTDIR)\jsshell.exe" - -CLEAN : - -@erase "$(INTDIR)\js.obj" - -@erase "$(OUTDIR)\jsshell.exe" - -@erase "$(OUTDIR)\jsshell.ilk" - -@erase "$(OUTDIR)\jsshell.pdb" - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -CPP=cl.exe -# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "_CONSOLE" /D "_DEBUG" /D "WIN32" /D "XP_WIN" /D "JSFILE" /D "DEBUG" /YX /c -CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /D "_CONSOLE" /D "_DEBUG" /D "WIN32"\ - /D "XP_WIN" /D "JSFILE" /D "DEBUG" /Fp"$(INTDIR)/jsshell.pch" /YX\ - /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c -CPP_OBJS=.\Debug/ -CPP_SBRS=.\. - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.c{$(CPP_SBRS)}.sbr: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_SBRS)}.sbr: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_SBRS)}.sbr: - $(CPP) $(CPP_PROJ) $< - -RSC=rc.exe -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o"$(OUTDIR)/jsshell.bsc" -BSC32_SBRS= \ - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ - advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\ - odbccp32.lib /nologo /subsystem:console /incremental:yes\ - /pdb:"$(OUTDIR)/jsshell.pdb" /debug /machine:I386 /out:"$(OUTDIR)/jsshell.exe" -LINK32_OBJS= \ - "$(INTDIR)\js.obj" \ - "$(OUTDIR)\js32.lib" - -"$(OUTDIR)\jsshell.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "fdlibm - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "fdlibm\Release" -# PROP BASE Intermediate_Dir "fdlibm\Release" -# PROP BASE Target_Dir "fdlibm" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Target_Dir "fdlibm" -OUTDIR=.\Release -INTDIR=.\Release - -ALL : "$(OUTDIR)\fdlibm.lib" - -CLEAN : - -@erase "$(INTDIR)\e_atan2.obj" - -@erase "$(INTDIR)\e_pow.obj" - -@erase "$(INTDIR)\e_sqrt.obj" - -@erase "$(INTDIR)\k_standard.obj" - -@erase "$(INTDIR)\s_atan.obj" - -@erase "$(INTDIR)\s_copysign.obj" - -@erase "$(INTDIR)\s_fabs.obj" - -@erase "$(INTDIR)\s_finite.obj" - -@erase "$(INTDIR)\s_isnan.obj" - -@erase "$(INTDIR)\s_matherr.obj" - -@erase "$(INTDIR)\s_rint.obj" - -@erase "$(INTDIR)\s_scalbn.obj" - -@erase "$(INTDIR)\w_atan2.obj" - -@erase "$(INTDIR)\w_pow.obj" - -@erase "$(INTDIR)\w_sqrt.obj" - -@erase "$(OUTDIR)\fdlibm.lib" - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -CPP=cl.exe -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D _X86_=1 /D "_WINDOWS" /YX /c -# ADD CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D _X86_=1 /D "_WINDOWS" /D "_IEEE_LIBM" /YX /c -CPP_PROJ=/nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D _X86_=1 /D "_WINDOWS" /D\ - "_IEEE_LIBM" /D "XP_WIN" /I .\ /Fp"$(INTDIR)/fdlibm.pch" /YX /Fo"$(INTDIR)/" /c -CPP_OBJS=.\Release/ -CPP_SBRS=.\. - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.c{$(CPP_SBRS)}.sbr: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_SBRS)}.sbr: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_SBRS)}.sbr: - $(CPP) $(CPP_PROJ) $< - -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o"$(OUTDIR)/fdlibm.bsc" -BSC32_SBRS= \ - -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo -LIB32_FLAGS=/nologo /out:"$(OUTDIR)/fdlibm.lib" -LIB32_OBJS= \ - "$(INTDIR)\e_atan2.obj" \ - "$(INTDIR)\e_pow.obj" \ - "$(INTDIR)\e_sqrt.obj" \ - "$(INTDIR)\k_standard.obj" \ - "$(INTDIR)\s_atan.obj" \ - "$(INTDIR)\s_copysign.obj" \ - "$(INTDIR)\s_fabs.obj" \ - "$(INTDIR)\s_finite.obj" \ - "$(INTDIR)\s_isnan.obj" \ - "$(INTDIR)\s_matherr.obj" \ - "$(INTDIR)\s_rint.obj" \ - "$(INTDIR)\s_scalbn.obj" \ - "$(INTDIR)\w_atan2.obj" \ - "$(INTDIR)\w_pow.obj" \ - "$(INTDIR)\w_sqrt.obj" - -"$(OUTDIR)\fdlibm.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS) - $(LIB32) @<< - $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS) -<< - -!ELSEIF "$(CFG)" == "fdlibm - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "fdlibm\Debug" -# PROP BASE Intermediate_Dir "fdlibm\Debug" -# PROP BASE Target_Dir "fdlibm" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Target_Dir "fdlibm" -OUTDIR=.\Debug -INTDIR=.\Debug - -ALL : "$(OUTDIR)\fdlibm.lib" - -CLEAN : - -@erase "$(INTDIR)\e_atan2.obj" - -@erase "$(INTDIR)\e_pow.obj" - -@erase "$(INTDIR)\e_sqrt.obj" - -@erase "$(INTDIR)\k_standard.obj" - -@erase "$(INTDIR)\s_atan.obj" - -@erase "$(INTDIR)\s_copysign.obj" - -@erase "$(INTDIR)\s_fabs.obj" - -@erase "$(INTDIR)\s_finite.obj" - -@erase "$(INTDIR)\s_isnan.obj" - -@erase "$(INTDIR)\s_matherr.obj" - -@erase "$(INTDIR)\s_rint.obj" - -@erase "$(INTDIR)\s_scalbn.obj" - -@erase "$(INTDIR)\w_atan2.obj" - -@erase "$(INTDIR)\w_pow.obj" - -@erase "$(INTDIR)\w_sqrt.obj" - -@erase "$(OUTDIR)\fdlibm.lib" - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -CPP=cl.exe -# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D _X86_=1 /D "_WINDOWS" /YX /c -# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /D "_DEBUG" /D "WIN32" /D _X86_=1 /D "_WINDOWS" /D "_IEEE_LIBM" /YX /c -CPP_PROJ=/nologo /MDd /W3 /GX /Z7 /Od /D "_DEBUG" /D "WIN32" /D _X86_=1 /D "_WINDOWS" /D\ - "_IEEE_LIBM" /D "XP_WIN" -I .\ /Fp"$(INTDIR)/fdlibm.pch" /YX /Fo"$(INTDIR)/" /c -CPP_OBJS=.\Debug/ -CPP_SBRS=.\. - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.c{$(CPP_SBRS)}.sbr: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_SBRS)}.sbr: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_SBRS)}.sbr: - $(CPP) $(CPP_PROJ) $< - -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o"$(OUTDIR)/fdlibm.bsc" -BSC32_SBRS= \ - -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo -LIB32_FLAGS=/nologo /out:"$(OUTDIR)/fdlibm.lib" -LIB32_OBJS= \ - "$(INTDIR)\e_atan2.obj" \ - "$(INTDIR)\e_pow.obj" \ - "$(INTDIR)\e_sqrt.obj" \ - "$(INTDIR)\k_standard.obj" \ - "$(INTDIR)\s_atan.obj" \ - "$(INTDIR)\s_copysign.obj" \ - "$(INTDIR)\s_fabs.obj" \ - "$(INTDIR)\s_finite.obj" \ - "$(INTDIR)\s_isnan.obj" \ - "$(INTDIR)\s_matherr.obj" \ - "$(INTDIR)\s_rint.obj" \ - "$(INTDIR)\s_scalbn.obj" \ - "$(INTDIR)\w_atan2.obj" \ - "$(INTDIR)\w_pow.obj" \ - "$(INTDIR)\w_sqrt.obj" - -"$(OUTDIR)\fdlibm.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS) - $(LIB32) @<< - $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS) -<< - -!ENDIF - -################################################################################ -# Begin Target - -# Name "js - Win32 Release" -# Name "js - Win32 Debug" - -!IF "$(CFG)" == "js - Win32 Release" - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -!ENDIF - -################################################################################ -# Begin Source File - -SOURCE=.\jsapi.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSAPI=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsarray.h"\ - ".\jsatom.h"\ - ".\jsbool.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsdate.h"\ - ".\jsemit.h"\ - ".\jsexn.h"\ - ".\jsfile.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsmath.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsparse.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscan.h"\ - ".\jsscope.h"\ - ".\jsscript.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - ".\jsxml.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSAPI=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsapi.obj" : $(SOURCE) $(DEP_CPP_JSAPI) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSAPI=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsarray.h"\ - ".\jsatom.h"\ - ".\jsbool.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsdate.h"\ - ".\jsemit.h"\ - ".\jsexn.h"\ - ".\jsfile.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsmath.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsparse.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscan.h"\ - ".\jsscope.h"\ - ".\jsscript.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - ".\jsxml.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSAPI=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsapi.obj" : $(SOURCE) $(DEP_CPP_JSAPI) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jsarena.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSARE=\ - ".\jsarena.h"\ - ".\jsbit.h"\ - ".\jscompat.h"\ - ".\jscpucfg.h"\ - ".\jslong.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsstddef.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSARE=\ - ".\jsautocfg.h"\ - - -"$(INTDIR)\jsarena.obj" : $(SOURCE) $(DEP_CPP_JSARE) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSARE=\ - ".\jsarena.h"\ - ".\jsbit.h"\ - ".\jscompat.h"\ - ".\jscpucfg.h"\ - ".\jslong.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsstddef.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSARE=\ - ".\jsautocfg.h"\ - - -"$(INTDIR)\jsarena.obj" : $(SOURCE) $(DEP_CPP_JSARE) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jsarray.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSARR=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsarray.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSARR=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsarray.obj" : $(SOURCE) $(DEP_CPP_JSARR) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSARR=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsarray.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSARR=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsarray.obj" : $(SOURCE) $(DEP_CPP_JSARR) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jsatom.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSATO=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSATO=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsatom.obj" : $(SOURCE) $(DEP_CPP_JSATO) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSATO=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSATO=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsatom.obj" : $(SOURCE) $(DEP_CPP_JSATO) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jsbool.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSBOO=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsbool.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSBOO=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsbool.obj" : $(SOURCE) $(DEP_CPP_JSBOO) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSBOO=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsbool.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSBOO=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsbool.obj" : $(SOURCE) $(DEP_CPP_JSBOO) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jscntxt.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSCNT=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsdbgapi.h"\ - ".\jsexn.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscan.h"\ - ".\jsscope.h"\ - ".\jsscript.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSCNT=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jscntxt.obj" : $(SOURCE) $(DEP_CPP_JSCNT) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSCNT=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsdbgapi.h"\ - ".\jsexn.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscan.h"\ - ".\jsscope.h"\ - ".\jsscript.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSCNT=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jscntxt.obj" : $(SOURCE) $(DEP_CPP_JSCNT) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jsdate.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSDAT=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsdate.h"\ - ".\jsdtoa.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - ".\prmjtime.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSDAT=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsdate.obj" : $(SOURCE) $(DEP_CPP_JSDAT) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSDAT=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsdate.h"\ - ".\jsdtoa.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - ".\prmjtime.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSDAT=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsdate.obj" : $(SOURCE) $(DEP_CPP_JSDAT) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jsdbgapi.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSDBG=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsdbgapi.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsscript.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSDBG=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsdbgapi.obj" : $(SOURCE) $(DEP_CPP_JSDBG) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSDBG=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsdbgapi.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsscript.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSDBG=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsdbgapi.obj" : $(SOURCE) $(DEP_CPP_JSDBG) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jsdhash.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSDHA=\ - ".\jsbit.h"\ - ".\jscompat.h"\ - ".\jscpucfg.h"\ - ".\jsdhash.h"\ - ".\jslong.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSDHA=\ - ".\jsautocfg.h"\ - - -"$(INTDIR)\jsdhash.obj" : $(SOURCE) $(DEP_CPP_JSDHA) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSDHA=\ - ".\jsbit.h"\ - ".\jscompat.h"\ - ".\jscpucfg.h"\ - ".\jsdhash.h"\ - ".\jslong.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSDHA=\ - ".\jsautocfg.h"\ - - -"$(INTDIR)\jsdhash.obj" : $(SOURCE) $(DEP_CPP_JSDHA) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jsdtoa.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSDTO=\ - ".\jscompat.h"\ - ".\jscpucfg.h"\ - ".\jsdtoa.h"\ - ".\jslong.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsstddef.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSDTO=\ - ".\jsautocfg.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsdtoa.obj" : $(SOURCE) $(DEP_CPP_JSDTO) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSDTO=\ - ".\jscompat.h"\ - ".\jscpucfg.h"\ - ".\jsdtoa.h"\ - ".\jslong.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsstddef.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSDTO=\ - ".\jsautocfg.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsdtoa.obj" : $(SOURCE) $(DEP_CPP_JSDTO) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jsemit.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSEMI=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsemit.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsparse.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscan.h"\ - ".\jsscope.h"\ - ".\jsscript.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSEMI=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsemit.obj" : $(SOURCE) $(DEP_CPP_JSEMI) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSEMI=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsemit.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsparse.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscan.h"\ - ".\jsscope.h"\ - ".\jsscript.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSEMI=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsemit.obj" : $(SOURCE) $(DEP_CPP_JSEMI) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jsexn.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSEXN=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsexn.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsobj.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSEXN=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsexn.obj" : $(SOURCE) $(DEP_CPP_JSEXN) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSEXN=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsexn.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsobj.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSEXN=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsexn.obj" : $(SOURCE) $(DEP_CPP_JSEXN) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jsfun.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSFUN=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsarray.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsparse.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscan.h"\ - ".\jsscope.h"\ - ".\jsscript.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - ".\jsxdrapi.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSFUN=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsfun.obj" : $(SOURCE) $(DEP_CPP_JSFUN) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSFUN=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsarray.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsparse.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscan.h"\ - ".\jsscope.h"\ - ".\jsscript.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - ".\jsxdrapi.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSFUN=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsfun.obj" : $(SOURCE) $(DEP_CPP_JSFUN) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jsgc.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSGC_=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsscript.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - ".\jsxml.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSGC_=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsgc.obj" : $(SOURCE) $(DEP_CPP_JSGC_) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSGC_=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsscript.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - ".\jsxml.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSGC_=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsgc.obj" : $(SOURCE) $(DEP_CPP_JSGC_) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jshash.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSHAS=\ - ".\jsbit.h"\ - ".\jscompat.h"\ - ".\jscpucfg.h"\ - ".\jshash.h"\ - ".\jslong.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSHAS=\ - ".\jsautocfg.h"\ - - -"$(INTDIR)\jshash.obj" : $(SOURCE) $(DEP_CPP_JSHAS) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSHAS=\ - ".\jsbit.h"\ - ".\jscompat.h"\ - ".\jscpucfg.h"\ - ".\jshash.h"\ - ".\jslong.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSHAS=\ - ".\jsautocfg.h"\ - - -"$(INTDIR)\jshash.obj" : $(SOURCE) $(DEP_CPP_JSHAS) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jsinterp.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSINT=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsarray.h"\ - ".\jsatom.h"\ - ".\jsbool.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsdbgapi.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsscript.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - ".\jsxml.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSINT=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsinterp.obj" : $(SOURCE) $(DEP_CPP_JSINT) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSINT=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsarray.h"\ - ".\jsatom.h"\ - ".\jsbool.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsdbgapi.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsscript.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - ".\jsxml.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSINT=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsinterp.obj" : $(SOURCE) $(DEP_CPP_JSINT) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jslock.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSLOC=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsobj.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSLOC=\ - ".\jsautocfg.h"\ - ".\pratom.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - ".\prthread.h"\ - - -"$(INTDIR)\jslock.obj" : $(SOURCE) $(DEP_CPP_JSLOC) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSLOC=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsobj.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSLOC=\ - ".\jsautocfg.h"\ - ".\pratom.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - ".\prthread.h"\ - - -"$(INTDIR)\jslock.obj" : $(SOURCE) $(DEP_CPP_JSLOC) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jslog2.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSLOG=\ - ".\jsbit.h"\ - ".\jscpucfg.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jstypes.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSLOG=\ - ".\jsautocfg.h"\ - - -"$(INTDIR)\jslog2.obj" : $(SOURCE) $(DEP_CPP_JSLOG) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSLOG=\ - ".\jsbit.h"\ - ".\jscpucfg.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jstypes.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSLOG=\ - ".\jsautocfg.h"\ - - -"$(INTDIR)\jslog2.obj" : $(SOURCE) $(DEP_CPP_JSLOG) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jslong.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSLON=\ - ".\jscpucfg.h"\ - ".\jslong.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jstypes.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSLON=\ - ".\jsautocfg.h"\ - - -"$(INTDIR)\jslong.obj" : $(SOURCE) $(DEP_CPP_JSLON) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSLON=\ - ".\jscpucfg.h"\ - ".\jslong.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jstypes.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSLON=\ - ".\jsautocfg.h"\ - - -"$(INTDIR)\jslong.obj" : $(SOURCE) $(DEP_CPP_JSLON) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jsmath.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSMAT=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslibmath.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsmath.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\prmjtime.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSMAT=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsmath.obj" : $(SOURCE) $(DEP_CPP_JSMAT) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSMAT=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslibmath.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsmath.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\prmjtime.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSMAT=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsmath.obj" : $(SOURCE) $(DEP_CPP_JSMAT) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jsnum.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSNUM=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsdtoa.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSNUM=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsnum.obj" : $(SOURCE) $(DEP_CPP_JSNUM) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSNUM=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsdtoa.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSNUM=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsnum.obj" : $(SOURCE) $(DEP_CPP_JSNUM) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jsobj.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSOBJ=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsbool.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsdbgapi.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsscript.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - ".\jsxdrapi.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSOBJ=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsobj.obj" : $(SOURCE) $(DEP_CPP_JSOBJ) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSOBJ=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsbool.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsdbgapi.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsscript.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - ".\jsxdrapi.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSOBJ=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsobj.obj" : $(SOURCE) $(DEP_CPP_JSOBJ) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jsopcode.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSOPC=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsarray.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsdbgapi.h"\ - ".\jsdtoa.h"\ - ".\jsemit.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsscript.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSOPC=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsopcode.obj" : $(SOURCE) $(DEP_CPP_JSOPC) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSOPC=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsarray.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsdbgapi.h"\ - ".\jsdtoa.h"\ - ".\jsemit.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsscript.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSOPC=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsopcode.obj" : $(SOURCE) $(DEP_CPP_JSOPC) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jsparse.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSPAR=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsemit.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsparse.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscan.h"\ - ".\jsscope.h"\ - ".\jsscript.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSPAR=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsparse.obj" : $(SOURCE) $(DEP_CPP_JSPAR) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSPAR=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsemit.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsparse.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscan.h"\ - ".\jsscope.h"\ - ".\jsscript.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSPAR=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsparse.obj" : $(SOURCE) $(DEP_CPP_JSPAR) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jsprf.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSPRF=\ - ".\jscpucfg.h"\ - ".\jslong.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSPRF=\ - ".\jsautocfg.h"\ - - -"$(INTDIR)\jsprf.obj" : $(SOURCE) $(DEP_CPP_JSPRF) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSPRF=\ - ".\jscpucfg.h"\ - ".\jslong.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSPRF=\ - ".\jsautocfg.h"\ - - -"$(INTDIR)\jsprf.obj" : $(SOURCE) $(DEP_CPP_JSPRF) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jsregexp.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSREG=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsarray.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - ".\jsxdrapi.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSREG=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsregexp.obj" : $(SOURCE) $(DEP_CPP_JSREG) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSREG=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsarray.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - ".\jsxdrapi.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSREG=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsregexp.obj" : $(SOURCE) $(DEP_CPP_JSREG) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jsscan.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSSCA=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsdtoa.h"\ - ".\jsexn.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscan.h"\ - ".\jsscope.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - ".\jsxml.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSSCA=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsscan.obj" : $(SOURCE) $(DEP_CPP_JSSCA) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSSCA=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsdtoa.h"\ - ".\jsexn.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscan.h"\ - ".\jsscope.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - ".\jsxml.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSSCA=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsscan.obj" : $(SOURCE) $(DEP_CPP_JSSCA) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jsscope.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSSCO=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSSCO=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsscope.obj" : $(SOURCE) $(DEP_CPP_JSSCO) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSSCO=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSSCO=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsscope.obj" : $(SOURCE) $(DEP_CPP_JSSCO) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jsscript.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSSCR=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsdbgapi.h"\ - ".\jsemit.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsscript.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - ".\jsxdrapi.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSSCR=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsscript.obj" : $(SOURCE) $(DEP_CPP_JSSCR) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSSCR=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsdbgapi.h"\ - ".\jsemit.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsscript.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - ".\jsxdrapi.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSSCR=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsscript.obj" : $(SOURCE) $(DEP_CPP_JSSCR) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jsstr.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSSTR=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsarray.h"\ - ".\jsatom.h"\ - ".\jsbool.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSSTR=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsstr.obj" : $(SOURCE) $(DEP_CPP_JSSTR) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSSTR=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsarray.h"\ - ".\jsatom.h"\ - ".\jsbool.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSSTR=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsstr.obj" : $(SOURCE) $(DEP_CPP_JSSTR) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jsutil.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSUTI=\ - ".\jscpucfg.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSUTI=\ - ".\jsautocfg.h"\ - - -"$(INTDIR)\jsutil.obj" : $(SOURCE) $(DEP_CPP_JSUTI) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSUTI=\ - ".\jscpucfg.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSUTI=\ - ".\jsautocfg.h"\ - - -"$(INTDIR)\jsutil.obj" : $(SOURCE) $(DEP_CPP_JSUTI) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jsxdrapi.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSXDR=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsobj.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - ".\jsxdrapi.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSXDR=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsxdrapi.obj" : $(SOURCE) $(DEP_CPP_JSXDR) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSXDR=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsobj.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscope.h"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - ".\jsxdrapi.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSXDR=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsxdrapi.obj" : $(SOURCE) $(DEP_CPP_JSXDR) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\jsxml.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_JSXML=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarray.h"\ - ".\jsatom.h"\ - ".\jsbit.h"\ - ".\jsbool.h"\ - ".\jscntxt.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsparse.h"\ - ".\jsprf.h"\ - ".\jsscan.h"\ - ".\jsscope.h"\ - ".\jsscript.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - ".\jsxml.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSXML=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsxml.obj" : $(SOURCE) $(DEP_CPP_JSXML) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_JSXML=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarray.h"\ - ".\jsatom.h"\ - ".\jsbit.h"\ - ".\jsbool.h"\ - ".\jscntxt.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jsnum.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsparse.h"\ - ".\jsscan.h"\ - ".\jsscope.h"\ - ".\jsscript.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - ".\jsxml.h"\ - ".\jsprf.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JSXML=\ - ".\jsautocfg.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\jsxml.obj" : $(SOURCE) $(DEP_CPP_JSXML) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\prmjtime.c - -!IF "$(CFG)" == "js - Win32 Release" - -DEP_CPP_PRMJT=\ - ".\jscompat.h"\ - ".\jscpucfg.h"\ - ".\jslong.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jstypes.h"\ - ".\prmjtime.h"\ - {$(INCLUDE)}"\sys\TIMEB.H"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_PRMJT=\ - ".\jsautocfg.h"\ - - -"$(INTDIR)\prmjtime.obj" : $(SOURCE) $(DEP_CPP_PRMJT) "$(INTDIR)" - - -!ELSEIF "$(CFG)" == "js - Win32 Debug" - -DEP_CPP_PRMJT=\ - ".\jscompat.h"\ - ".\jscpucfg.h"\ - ".\jslong.h"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsprf.h"\ - ".\jstypes.h"\ - ".\prmjtime.h"\ - {$(INCLUDE)}"\sys\TIMEB.H"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_PRMJT=\ - ".\jsautocfg.h"\ - - -"$(INTDIR)\prmjtime.obj" : $(SOURCE) $(DEP_CPP_PRMJT) "$(INTDIR)" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Project Dependency - -# Project_Dep_Name "fdlibm" - -!IF "$(CFG)" == "js - Win32 Debug" - -"fdlibm - Win32 Debug" : - $(MAKE) /$(MAKEFLAGS) /F ".\js.mak" CFG="fdlibm - Win32 Debug" - -!ELSEIF "$(CFG)" == "js - Win32 Release" - -"fdlibm - Win32 Release" : - $(MAKE) /$(MAKEFLAGS) /F ".\js.mak" CFG="fdlibm - Win32 Release" - -!ENDIF - -# End Project Dependency -# End Target -################################################################################ -# Begin Target - -# Name "jsshell - Win32 Release" -# Name "jsshell - Win32 Debug" - -!IF "$(CFG)" == "jsshell - Win32 Release" - -!ELSEIF "$(CFG)" == "jsshell - Win32 Debug" - -!ENDIF - -################################################################################ -# Begin Source File - -SOURCE=.\js.c -DEP_CPP_JS_C42=\ - ".\js.msg"\ - ".\jsapi.h"\ - ".\jsarena.h"\ - ".\jsatom.h"\ - ".\jsclist.h"\ - ".\jscntxt.h"\ - ".\jscompat.h"\ - ".\jsconfig.h"\ - ".\jscpucfg.h"\ - ".\jsdbgapi.h"\ - ".\jsemit.h"\ - ".\jsfun.h"\ - ".\jsgc.h"\ - ".\jshash.h"\ - ".\jsinterp.h"\ - ".\jslock.h"\ - ".\jslong.h"\ - ".\jsobj.h"\ - ".\jsopcode.h"\ - ".\jsopcode.tbl"\ - ".\jsosdep.h"\ - ".\jsotypes.h"\ - ".\jsparse.h"\ - ".\jsprf.h"\ - ".\jsprvtd.h"\ - ".\jspubtd.h"\ - ".\jsregexp.h"\ - ".\jsscan.h"\ - ".\jsscope.h"\ - ".\jsscript.h"\ - ".\jsshell.msg"\ - ".\jsstddef.h"\ - ".\jsstr.h"\ - ".\jstypes.h"\ - ".\jsutil.h"\ - {$(INCLUDE)}"\sys\types.h"\ - -NODEP_CPP_JS_C42=\ - ".\jsautocfg.h"\ - ".\jsdb.h"\ - ".\jsdebug.h"\ - ".\jsdjava.h"\ - ".\jsjava.h"\ - ".\jsperl.h"\ - ".\prcvar.h"\ - ".\prlock.h"\ - - -"$(INTDIR)\js.obj" : $(SOURCE) $(DEP_CPP_JS_C42) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Project Dependency - -# Project_Dep_Name "js" - -!IF "$(CFG)" == "jsshell - Win32 Release" - -"js - Win32 Release" : - $(MAKE) /$(MAKEFLAGS) /F ".\js.mak" CFG="js - Win32 Release" - -!ELSEIF "$(CFG)" == "jsshell - Win32 Debug" - -"js - Win32 Debug" : - $(MAKE) /$(MAKEFLAGS) /F ".\js.mak" CFG="js - Win32 Debug" - -!ENDIF - -# End Project Dependency -# End Target -################################################################################ -# Begin Target - -# Name "fdlibm - Win32 Release" -# Name "fdlibm - Win32 Debug" - -!IF "$(CFG)" == "fdlibm - Win32 Release" - -!ELSEIF "$(CFG)" == "fdlibm - Win32 Debug" - -!ENDIF - -################################################################################ -# Begin Source File - -SOURCE=.\fdlibm\w_atan2.c - -!IF "$(CFG)" == "fdlibm - Win32 Release" - -DEP_CPP_W_ATA=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\w_atan2.obj" : $(SOURCE) $(DEP_CPP_W_ATA) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ELSEIF "$(CFG)" == "fdlibm - Win32 Debug" - -DEP_CPP_W_ATA=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\w_atan2.obj" : $(SOURCE) $(DEP_CPP_W_ATA) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\fdlibm\s_copysign.c - -!IF "$(CFG)" == "fdlibm - Win32 Release" - -DEP_CPP_S_COP=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\s_copysign.obj" : $(SOURCE) $(DEP_CPP_S_COP) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ELSEIF "$(CFG)" == "fdlibm - Win32 Debug" - -DEP_CPP_S_COP=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\s_copysign.obj" : $(SOURCE) $(DEP_CPP_S_COP) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\fdlibm\w_pow.c - -!IF "$(CFG)" == "fdlibm - Win32 Release" - -DEP_CPP_W_POW=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\w_pow.obj" : $(SOURCE) $(DEP_CPP_W_POW) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ELSEIF "$(CFG)" == "fdlibm - Win32 Debug" - -DEP_CPP_W_POW=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\w_pow.obj" : $(SOURCE) $(DEP_CPP_W_POW) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\fdlibm\e_pow.c - -!IF "$(CFG)" == "fdlibm - Win32 Release" - -DEP_CPP_E_POW=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\e_pow.obj" : $(SOURCE) $(DEP_CPP_E_POW) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ELSEIF "$(CFG)" == "fdlibm - Win32 Debug" - -DEP_CPP_E_POW=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\e_pow.obj" : $(SOURCE) $(DEP_CPP_E_POW) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\fdlibm\k_standard.c - -!IF "$(CFG)" == "fdlibm - Win32 Release" - -DEP_CPP_K_STA=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\k_standard.obj" : $(SOURCE) $(DEP_CPP_K_STA) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ELSEIF "$(CFG)" == "fdlibm - Win32 Debug" - -DEP_CPP_K_STA=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\k_standard.obj" : $(SOURCE) $(DEP_CPP_K_STA) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\fdlibm\e_atan2.c - -!IF "$(CFG)" == "fdlibm - Win32 Release" - -DEP_CPP_E_ATA=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\e_atan2.obj" : $(SOURCE) $(DEP_CPP_E_ATA) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ELSEIF "$(CFG)" == "fdlibm - Win32 Debug" - -DEP_CPP_E_ATA=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\e_atan2.obj" : $(SOURCE) $(DEP_CPP_E_ATA) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\fdlibm\s_isnan.c - -!IF "$(CFG)" == "fdlibm - Win32 Release" - -DEP_CPP_S_ISN=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\s_isnan.obj" : $(SOURCE) $(DEP_CPP_S_ISN) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ELSEIF "$(CFG)" == "fdlibm - Win32 Debug" - -DEP_CPP_S_ISN=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\s_isnan.obj" : $(SOURCE) $(DEP_CPP_S_ISN) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\fdlibm\s_fabs.c - -!IF "$(CFG)" == "fdlibm - Win32 Release" - -DEP_CPP_S_FAB=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\s_fabs.obj" : $(SOURCE) $(DEP_CPP_S_FAB) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ELSEIF "$(CFG)" == "fdlibm - Win32 Debug" - -DEP_CPP_S_FAB=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\s_fabs.obj" : $(SOURCE) $(DEP_CPP_S_FAB) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\fdlibm\w_sqrt.c - -!IF "$(CFG)" == "fdlibm - Win32 Release" - -DEP_CPP_W_SQR=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\w_sqrt.obj" : $(SOURCE) $(DEP_CPP_W_SQR) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ELSEIF "$(CFG)" == "fdlibm - Win32 Debug" - -DEP_CPP_W_SQR=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\w_sqrt.obj" : $(SOURCE) $(DEP_CPP_W_SQR) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\fdlibm\s_scalbn.c - -!IF "$(CFG)" == "fdlibm - Win32 Release" - -DEP_CPP_S_SCA=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\s_scalbn.obj" : $(SOURCE) $(DEP_CPP_S_SCA) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ELSEIF "$(CFG)" == "fdlibm - Win32 Debug" - -DEP_CPP_S_SCA=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\s_scalbn.obj" : $(SOURCE) $(DEP_CPP_S_SCA) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\fdlibm\e_sqrt.c - -!IF "$(CFG)" == "fdlibm - Win32 Release" - -DEP_CPP_E_SQR=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\e_sqrt.obj" : $(SOURCE) $(DEP_CPP_E_SQR) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ELSEIF "$(CFG)" == "fdlibm - Win32 Debug" - -DEP_CPP_E_SQR=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\e_sqrt.obj" : $(SOURCE) $(DEP_CPP_E_SQR) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\fdlibm\s_rint.c - -!IF "$(CFG)" == "fdlibm - Win32 Release" - -DEP_CPP_S_RIN=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\s_rint.obj" : $(SOURCE) $(DEP_CPP_S_RIN) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ELSEIF "$(CFG)" == "fdlibm - Win32 Debug" - -DEP_CPP_S_RIN=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\s_rint.obj" : $(SOURCE) $(DEP_CPP_S_RIN) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\fdlibm\s_atan.c - -!IF "$(CFG)" == "fdlibm - Win32 Release" - -DEP_CPP_S_ATA=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\s_atan.obj" : $(SOURCE) $(DEP_CPP_S_ATA) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ELSEIF "$(CFG)" == "fdlibm - Win32 Debug" - -DEP_CPP_S_ATA=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\s_atan.obj" : $(SOURCE) $(DEP_CPP_S_ATA) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\fdlibm\s_finite.c - -!IF "$(CFG)" == "fdlibm - Win32 Release" - -DEP_CPP_S_FIN=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\s_finite.obj" : $(SOURCE) $(DEP_CPP_S_FIN) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ELSEIF "$(CFG)" == "fdlibm - Win32 Debug" - -DEP_CPP_S_FIN=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\s_finite.obj" : $(SOURCE) $(DEP_CPP_S_FIN) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\fdlibm\s_matherr.c - -!IF "$(CFG)" == "fdlibm - Win32 Release" - -DEP_CPP_S_MAT=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\s_matherr.obj" : $(SOURCE) $(DEP_CPP_S_MAT) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ELSEIF "$(CFG)" == "fdlibm - Win32 Debug" - -DEP_CPP_S_MAT=\ - ".\fdlibm\fdlibm.h"\ - - -"$(INTDIR)\s_matherr.obj" : $(SOURCE) $(DEP_CPP_S_MAT) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - - -!ENDIF - -# End Source File -# End Target -# End Project -################################################################################ diff --git a/lib/javascript/js.mdp b/lib/javascript/js.mdp deleted file mode 100644 index 8da64fb6..00000000 Binary files a/lib/javascript/js.mdp and /dev/null differ diff --git a/lib/javascript/js.msg b/lib/javascript/js.msg deleted file mode 100644 index 5df1ead9..00000000 --- a/lib/javascript/js.msg +++ /dev/null @@ -1,290 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * This is the JavaScript error message file. - * - * The format for each JS error message is: - * - * MSG_DEF(, , , , - * ) - * - * where ; - * is a legal C identifer that will be used in the - * JS engine source. - * - * is an unique integral value identifying this error. - * - * is an integer literal specifying the total number of - * replaceable arguments in the following format string. - * - * is an exception index from the enum in jsexn.c; - * JSEXN_NONE for none. The given exception index will be raised by the - * engine when the corresponding error occurs. - * - * is a string literal, optionally containing sequences - * {X} where X is an integer representing the argument number that will - * be replaced with a string value when the error is reported. - * - * e.g. - * - * MSG_DEF(JSMSG_NOT_A_SUBSPECIES, 73, JSEXN_NONE, 2, - * "{0} is not a member of the {1} family") - * - * can be used: - * - * JS_ReportErrorNumber(JSMSG_NOT_A_SUBSPECIES, "Rhino", "Monkey"); - * - * to report: - * - * "Rhino is not a member of the Monkey family" - * - * Before adding a new MSG_DEF at the end, look for JSMSG_UNUSED free - * index placeholders in the middle of the list. - */ - -MSG_DEF(JSMSG_NOT_AN_ERROR, 0, 0, JSEXN_NONE, "") -MSG_DEF(JSMSG_NOT_DEFINED, 1, 1, JSEXN_REFERENCEERR, "{0} is not defined") -MSG_DEF(JSMSG_NO_REG_EXPS, 2, 1, JSEXN_INTERNALERR, "sorry, regular expression are not supported") -MSG_DEF(JSMSG_MORE_ARGS_NEEDED, 3, 3, JSEXN_NONE, "{0} requires more than {1} argument{2}") -MSG_DEF(JSMSG_BAD_CHAR, 4, 1, JSEXN_NONE, "invalid format character {0}") -MSG_DEF(JSMSG_BAD_TYPE, 5, 1, JSEXN_NONE, "unknown type {0}") -MSG_DEF(JSMSG_CANT_LOCK, 6, 0, JSEXN_NONE, "can't lock memory") -MSG_DEF(JSMSG_CANT_UNLOCK, 7, 0, JSEXN_NONE, "can't unlock memory") -MSG_DEF(JSMSG_INCOMPATIBLE_PROTO, 8, 3, JSEXN_TYPEERR, "{0}.prototype.{1} called on incompatible {2}") -MSG_DEF(JSMSG_NO_CONSTRUCTOR, 9, 1, JSEXN_NONE, "{0} has no constructor") -MSG_DEF(JSMSG_CANT_ALIAS, 10, 3, JSEXN_NONE, "can't alias {0} to {1} in class {2}") -MSG_DEF(JSMSG_NOT_SCRIPTED_FUNCTION, 11, 1, JSEXN_TYPEERR, "{0} is not a scripted function") -MSG_DEF(JSMSG_BAD_SORT_ARG, 12, 0, JSEXN_TYPEERR, "invalid Array.prototype.sort argument") -MSG_DEF(JSMSG_BAD_ATOMIC_NUMBER, 13, 1, JSEXN_INTERNALERR, "internal error: no index for atom {0}") -MSG_DEF(JSMSG_TOO_MANY_LITERALS, 14, 0, JSEXN_INTERNALERR, "too many literals") -MSG_DEF(JSMSG_CANT_WATCH, 15, 1, JSEXN_NONE, "can't watch non-native objects of class {0}") -MSG_DEF(JSMSG_STACK_UNDERFLOW, 16, 2, JSEXN_INTERNALERR, "internal error compiling {0}: stack underflow at pc {1}") -MSG_DEF(JSMSG_NEED_DIET, 17, 1, JSEXN_INTERNALERR, "{0} too large") -MSG_DEF(JSMSG_TOO_MANY_LOCAL_ROOTS, 18, 0, JSEXN_ERR, "out of local root space") -MSG_DEF(JSMSG_READ_ONLY, 19, 1, JSEXN_ERR, "{0} is read-only") -MSG_DEF(JSMSG_BAD_FORMAL, 20, 0, JSEXN_SYNTAXERR, "malformed formal parameter") -MSG_DEF(JSMSG_SAME_FORMAL, 21, 1, JSEXN_NONE, "duplicate formal argument {0}") -MSG_DEF(JSMSG_NOT_FUNCTION, 22, 1, JSEXN_TYPEERR, "{0} is not a function") -MSG_DEF(JSMSG_NOT_CONSTRUCTOR, 23, 1, JSEXN_TYPEERR, "{0} is not a constructor") -MSG_DEF(JSMSG_STACK_OVERFLOW, 24, 1, JSEXN_INTERNALERR, "stack overflow in {0}") -MSG_DEF(JSMSG_NOT_EXPORTED, 25, 1, JSEXN_NONE, "{0} is not exported") -MSG_DEF(JSMSG_OVER_RECURSED, 26, 0, JSEXN_INTERNALERR, "too much recursion") -MSG_DEF(JSMSG_IN_NOT_OBJECT, 27, 1, JSEXN_TYPEERR, "invalid 'in' operand {0}") -MSG_DEF(JSMSG_BAD_NEW_RESULT, 28, 1, JSEXN_NONE, "invalid new expression result {0}") -MSG_DEF(JSMSG_BAD_SHARP_DEF, 29, 1, JSEXN_ERR, "invalid sharp variable definition #{0}=") -MSG_DEF(JSMSG_BAD_SHARP_USE, 30, 1, JSEXN_ERR, "invalid sharp variable use #{0}#") -MSG_DEF(JSMSG_BAD_INSTANCEOF_RHS, 31, 1, JSEXN_TYPEERR, "invalid 'instanceof' operand {0}") -MSG_DEF(JSMSG_BAD_BYTECODE, 32, 1, JSEXN_INTERNALERR, "unimplemented JavaScript bytecode {0}") -MSG_DEF(JSMSG_BAD_RADIX, 33, 1, JSEXN_ERR, "illegal radix {0}") -MSG_DEF(JSMSG_NAN, 34, 1, JSEXN_ERR, "{0} is not a number") -MSG_DEF(JSMSG_CANT_CONVERT, 35, 1, JSEXN_NONE, "can't convert {0} to an integer") -MSG_DEF(JSMSG_CYCLIC_VALUE, 36, 1, JSEXN_ERR, "cyclic {0} value") -MSG_DEF(JSMSG_PERMANENT, 37, 1, JSEXN_ERR, "{0} is permanent") -MSG_DEF(JSMSG_CANT_CONVERT_TO, 38, 2, JSEXN_TYPEERR, "can't convert {0} to {1}") -MSG_DEF(JSMSG_NO_PROPERTIES, 39, 1, JSEXN_TYPEERR, "{0} has no properties") -MSG_DEF(JSMSG_CANT_FIND_CLASS, 40, 1, JSEXN_NONE, "can't find class id {0}") -MSG_DEF(JSMSG_CANT_XDR_CLASS, 41, 1, JSEXN_NONE, "can't XDR class {0}") -MSG_DEF(JSMSG_BYTECODE_TOO_BIG, 42, 2, JSEXN_INTERNALERR, "bytecode {0} too large (limit {1})") -MSG_DEF(JSMSG_UNKNOWN_FORMAT, 43, 1, JSEXN_INTERNALERR, "unknown bytecode format {0}") -MSG_DEF(JSMSG_TOO_MANY_CON_ARGS, 44, 0, JSEXN_SYNTAXERR, "too many constructor arguments") -MSG_DEF(JSMSG_TOO_MANY_FUN_ARGS, 45, 0, JSEXN_SYNTAXERR, "too many function arguments") -MSG_DEF(JSMSG_BAD_QUANTIFIER, 46, 1, JSEXN_SYNTAXERR, "invalid quantifier {0}") -MSG_DEF(JSMSG_MIN_TOO_BIG, 47, 1, JSEXN_SYNTAXERR, "overlarge minimum {0}") -MSG_DEF(JSMSG_MAX_TOO_BIG, 48, 1, JSEXN_SYNTAXERR, "overlarge maximum {0}") -MSG_DEF(JSMSG_OUT_OF_ORDER, 49, 1, JSEXN_SYNTAXERR, "maximum {0} less than minimum") -MSG_DEF(JSMSG_ZERO_QUANTIFIER, 50, 1, JSEXN_SYNTAXERR, "zero quantifier {0}") -MSG_DEF(JSMSG_UNTERM_QUANTIFIER, 51, 1, JSEXN_SYNTAXERR, "unterminated quantifier {0}") -MSG_DEF(JSMSG_EMPTY_BEFORE_STAR, 52, 0, JSEXN_SYNTAXERR, "regular expression before * could be empty") -MSG_DEF(JSMSG_EMPTY_BEFORE_PLUS, 53, 0, JSEXN_SYNTAXERR, "regular expression before + could be empty") -MSG_DEF(JSMSG_MISSING_PAREN, 54, 0, JSEXN_SYNTAXERR, "unterminated parenthetical") -MSG_DEF(JSMSG_UNTERM_CLASS, 55, 1, JSEXN_SYNTAXERR, "unterminated character class {0}") -MSG_DEF(JSMSG_TRAILING_SLASH, 56, 0, JSEXN_SYNTAXERR, "trailing \\ in regular expression") -MSG_DEF(JSMSG_BAD_CLASS_RANGE, 57, 0, JSEXN_SYNTAXERR, "invalid range in character class") -MSG_DEF(JSMSG_BAD_FLAG, 58, 1, JSEXN_SYNTAXERR, "invalid regular expression flag {0}") -MSG_DEF(JSMSG_NO_INPUT, 59, 3, JSEXN_SYNTAXERR, "no input for /{0}/{1}{2}") -MSG_DEF(JSMSG_CANT_OPEN, 60, 2, JSEXN_NONE, "can't open {0}: {1}") -MSG_DEF(JSMSG_BAD_STRING_MASK, 61, 1, JSEXN_ERR, "invalid string escape mask {0}") -MSG_DEF(JSMSG_UNMATCHED_RIGHT_PAREN, 62, 0, JSEXN_SYNTAXERR, "unmatched ) in regular expression") -MSG_DEF(JSMSG_END_OF_DATA, 63, 0, JSEXN_NONE, "unexpected end of data") -MSG_DEF(JSMSG_SEEK_BEYOND_START, 64, 0, JSEXN_NONE, "illegal seek beyond start") -MSG_DEF(JSMSG_SEEK_BEYOND_END, 65, 0, JSEXN_NONE, "illegal seek beyond end") -MSG_DEF(JSMSG_END_SEEK, 66, 0, JSEXN_NONE, "illegal end-based seek") -MSG_DEF(JSMSG_WHITHER_WHENCE, 67, 1, JSEXN_NONE, "unknown seek whence: {0}") -MSG_DEF(JSMSG_BAD_SCRIPT_MAGIC, 68, 0, JSEXN_NONE, "bad script XDR magic number") -MSG_DEF(JSMSG_PAREN_BEFORE_FORMAL, 69, 0, JSEXN_SYNTAXERR, "missing ( before formal parameters") -MSG_DEF(JSMSG_MISSING_FORMAL, 70, 0, JSEXN_SYNTAXERR, "missing formal parameter") -MSG_DEF(JSMSG_PAREN_AFTER_FORMAL, 71, 0, JSEXN_SYNTAXERR, "missing ) after formal parameters") -MSG_DEF(JSMSG_CURLY_BEFORE_BODY, 72, 0, JSEXN_SYNTAXERR, "missing { before function body") -MSG_DEF(JSMSG_CURLY_AFTER_BODY, 73, 0, JSEXN_SYNTAXERR, "missing } after function body") -MSG_DEF(JSMSG_PAREN_BEFORE_COND, 74, 0, JSEXN_SYNTAXERR, "missing ( before condition") -MSG_DEF(JSMSG_PAREN_AFTER_COND, 75, 0, JSEXN_SYNTAXERR, "missing ) after condition") -MSG_DEF(JSMSG_NO_IMPORT_NAME, 76, 0, JSEXN_SYNTAXERR, "missing name in import statement") -MSG_DEF(JSMSG_NAME_AFTER_DOT, 77, 0, JSEXN_SYNTAXERR, "missing name after . operator") -MSG_DEF(JSMSG_BRACKET_IN_INDEX, 78, 0, JSEXN_SYNTAXERR, "missing ] in index expression") -MSG_DEF(JSMSG_NO_EXPORT_NAME, 79, 0, JSEXN_SYNTAXERR, "missing name in export statement") -MSG_DEF(JSMSG_PAREN_BEFORE_SWITCH, 80, 0, JSEXN_SYNTAXERR, "missing ( before switch expression") -MSG_DEF(JSMSG_PAREN_AFTER_SWITCH, 81, 0, JSEXN_SYNTAXERR, "missing ) after switch expression") -MSG_DEF(JSMSG_CURLY_BEFORE_SWITCH, 82, 0, JSEXN_SYNTAXERR, "missing { before switch body") -MSG_DEF(JSMSG_COLON_AFTER_CASE, 83, 0, JSEXN_SYNTAXERR, "missing : after case label") -MSG_DEF(JSMSG_WHILE_AFTER_DO, 84, 0, JSEXN_SYNTAXERR, "missing while after do-loop body") -MSG_DEF(JSMSG_PAREN_AFTER_FOR, 85, 0, JSEXN_SYNTAXERR, "missing ( after for") -MSG_DEF(JSMSG_SEMI_AFTER_FOR_INIT, 86, 0, JSEXN_SYNTAXERR, "missing ; after for-loop initializer") -MSG_DEF(JSMSG_SEMI_AFTER_FOR_COND, 87, 0, JSEXN_SYNTAXERR, "missing ; after for-loop condition") -MSG_DEF(JSMSG_PAREN_AFTER_FOR_CTRL, 88, 0, JSEXN_SYNTAXERR, "missing ) after for-loop control") -MSG_DEF(JSMSG_CURLY_BEFORE_TRY, 89, 0, JSEXN_SYNTAXERR, "missing { before try block") -MSG_DEF(JSMSG_CURLY_AFTER_TRY, 90, 0, JSEXN_SYNTAXERR, "missing } after try block") -MSG_DEF(JSMSG_PAREN_BEFORE_CATCH, 91, 0, JSEXN_SYNTAXERR, "missing ( before catch") -MSG_DEF(JSMSG_CATCH_IDENTIFIER, 92, 0, JSEXN_SYNTAXERR, "missing identifier in catch") -MSG_DEF(JSMSG_PAREN_AFTER_CATCH, 93, 0, JSEXN_SYNTAXERR, "missing ) after catch") -MSG_DEF(JSMSG_CURLY_BEFORE_CATCH, 94, 0, JSEXN_SYNTAXERR, "missing { before catch block") -MSG_DEF(JSMSG_CURLY_AFTER_CATCH, 95, 0, JSEXN_SYNTAXERR, "missing } after catch block") -MSG_DEF(JSMSG_CURLY_BEFORE_FINALLY, 96, 0, JSEXN_SYNTAXERR, "missing { before finally block") -MSG_DEF(JSMSG_CURLY_AFTER_FINALLY, 97, 0, JSEXN_SYNTAXERR, "missing } after finally block") -MSG_DEF(JSMSG_CATCH_OR_FINALLY, 98, 0, JSEXN_SYNTAXERR, "missing catch or finally after try") -MSG_DEF(JSMSG_PAREN_BEFORE_WITH, 99, 0, JSEXN_SYNTAXERR, "missing ( before with-statement object") -MSG_DEF(JSMSG_PAREN_AFTER_WITH, 100, 0, JSEXN_SYNTAXERR, "missing ) after with-statement object") -MSG_DEF(JSMSG_CURLY_IN_COMPOUND, 101, 0, JSEXN_SYNTAXERR, "missing } in compound statement") -MSG_DEF(JSMSG_NO_VARIABLE_NAME, 102, 0, JSEXN_SYNTAXERR, "missing variable name") -MSG_DEF(JSMSG_COLON_IN_COND, 103, 0, JSEXN_SYNTAXERR, "missing : in conditional expression") -MSG_DEF(JSMSG_PAREN_AFTER_ARGS, 104, 0, JSEXN_SYNTAXERR, "missing ) after argument list") -MSG_DEF(JSMSG_BRACKET_AFTER_LIST, 105, 0, JSEXN_SYNTAXERR, "missing ] after element list") -MSG_DEF(JSMSG_COLON_AFTER_ID, 106, 0, JSEXN_SYNTAXERR, "missing : after property id") -MSG_DEF(JSMSG_CURLY_AFTER_LIST, 107, 0, JSEXN_SYNTAXERR, "missing } after property list") -MSG_DEF(JSMSG_PAREN_IN_PAREN, 108, 0, JSEXN_SYNTAXERR, "missing ) in parenthetical") -MSG_DEF(JSMSG_SEMI_BEFORE_STMNT, 109, 0, JSEXN_SYNTAXERR, "missing ; before statement") -MSG_DEF(JSMSG_NO_RETURN_VALUE, 110, 1, JSEXN_TYPEERR, "function {0} does not always return a value") -MSG_DEF(JSMSG_DUPLICATE_FORMAL, 111, 1, JSEXN_TYPEERR, "duplicate formal argument {0}") -MSG_DEF(JSMSG_EQUAL_AS_ASSIGN, 112, 1, JSEXN_NONE, "test for equality (==) mistyped as assignment (=)?{0}") -MSG_DEF(JSMSG_BAD_IMPORT, 113, 0, JSEXN_SYNTAXERR, "invalid import expression") -MSG_DEF(JSMSG_TOO_MANY_DEFAULTS, 114, 0, JSEXN_SYNTAXERR, "more than one switch default") -MSG_DEF(JSMSG_TOO_MANY_CASES, 115, 0, JSEXN_INTERNALERR, "too many switch cases") -MSG_DEF(JSMSG_BAD_SWITCH, 116, 0, JSEXN_SYNTAXERR, "invalid switch statement") -MSG_DEF(JSMSG_BAD_FOR_LEFTSIDE, 117, 0, JSEXN_SYNTAXERR, "invalid for/in left-hand side") -MSG_DEF(JSMSG_CATCH_AFTER_GENERAL, 118, 0, JSEXN_SYNTAXERR, "catch after unconditional catch") -MSG_DEF(JSMSG_CATCH_WITHOUT_TRY, 119, 0, JSEXN_SYNTAXERR, "catch without try") -MSG_DEF(JSMSG_FINALLY_WITHOUT_TRY, 120, 0, JSEXN_SYNTAXERR, "finally without try") -MSG_DEF(JSMSG_LABEL_NOT_FOUND, 121, 0, JSEXN_SYNTAXERR, "label not found") -MSG_DEF(JSMSG_TOUGH_BREAK, 122, 0, JSEXN_SYNTAXERR, "invalid break") -MSG_DEF(JSMSG_BAD_CONTINUE, 123, 0, JSEXN_SYNTAXERR, "invalid continue") -MSG_DEF(JSMSG_BAD_RETURN, 124, 0, JSEXN_SYNTAXERR, "invalid return") -MSG_DEF(JSMSG_BAD_LABEL, 125, 0, JSEXN_SYNTAXERR, "invalid label") -MSG_DEF(JSMSG_DUPLICATE_LABEL, 126, 0, JSEXN_SYNTAXERR, "duplicate label") -MSG_DEF(JSMSG_VAR_HIDES_ARG, 127, 1, JSEXN_TYPEERR, "variable {0} hides argument") -MSG_DEF(JSMSG_BAD_VAR_INIT, 128, 0, JSEXN_SYNTAXERR, "invalid variable initialization") -MSG_DEF(JSMSG_BAD_LEFTSIDE_OF_ASS, 129, 0, JSEXN_SYNTAXERR, "invalid assignment left-hand side") -MSG_DEF(JSMSG_BAD_OPERAND, 130, 1, JSEXN_SYNTAXERR, "invalid {0} operand") -MSG_DEF(JSMSG_BAD_PROP_ID, 131, 0, JSEXN_SYNTAXERR, "invalid property id") -MSG_DEF(JSMSG_RESERVED_ID, 132, 1, JSEXN_SYNTAXERR, "{0} is a reserved identifier") -MSG_DEF(JSMSG_SYNTAX_ERROR, 133, 0, JSEXN_SYNTAXERR, "syntax error") -MSG_DEF(JSMSG_BAD_SHARP_VAR_DEF, 134, 0, JSEXN_SYNTAXERR, "invalid sharp variable definition") -MSG_DEF(JSMSG_BAD_PROTOTYPE, 135, 1, JSEXN_TYPEERR, "'prototype' property of {0} is not an object") -MSG_DEF(JSMSG_MISSING_EXPONENT, 136, 0, JSEXN_SYNTAXERR, "missing exponent") -MSG_DEF(JSMSG_OUT_OF_MEMORY, 137, 0, JSEXN_ERR, "out of memory") -MSG_DEF(JSMSG_UNTERMINATED_STRING, 138, 0, JSEXN_SYNTAXERR, "unterminated string literal") -MSG_DEF(JSMSG_TOO_MANY_PARENS, 139, 0, JSEXN_INTERNALERR, "too many parentheses in regular expression") -MSG_DEF(JSMSG_UNTERMINATED_COMMENT, 140, 0, JSEXN_SYNTAXERR, "unterminated comment") -MSG_DEF(JSMSG_UNTERMINATED_REGEXP, 141, 0, JSEXN_SYNTAXERR, "unterminated regular expression literal") -MSG_DEF(JSMSG_BAD_REGEXP_FLAG, 142, 0, JSEXN_SYNTAXERR, "invalid flag after regular expression") -MSG_DEF(JSMSG_SHARPVAR_TOO_BIG, 143, 0, JSEXN_SYNTAXERR, "overlarge sharp variable number") -MSG_DEF(JSMSG_ILLEGAL_CHARACTER, 144, 0, JSEXN_SYNTAXERR, "illegal character") -MSG_DEF(JSMSG_BAD_OCTAL, 145, 1, JSEXN_SYNTAXERR, "{0} is not a legal ECMA-262 octal constant") -MSG_DEF(JSMSG_BAD_INDIRECT_CALL, 146, 1, JSEXN_EVALERR, "function {0} must be called directly, and not by way of a function of another name") -MSG_DEF(JSMSG_UNCAUGHT_EXCEPTION, 147, 1, JSEXN_NONE, "uncaught exception: {0}") -MSG_DEF(JSMSG_INVALID_BACKREF, 148, 0, JSEXN_SYNTAXERR, "non-octal digit in an escape sequence that doesn't match a back-reference") -MSG_DEF(JSMSG_BAD_BACKREF, 149, 0, JSEXN_SYNTAXERR, "back-reference exceeds number of capturing parentheses") -MSG_DEF(JSMSG_PRECISION_RANGE, 150, 1, JSEXN_RANGEERR, "precision {0} out of range") -MSG_DEF(JSMSG_BAD_GETTER_OR_SETTER, 151, 1, JSEXN_SYNTAXERR, "invalid {0} usage") -MSG_DEF(JSMSG_BAD_ARRAY_LENGTH, 152, 0, JSEXN_RANGEERR, "invalid array length") -MSG_DEF(JSMSG_CANT_DESCRIBE_PROPS, 153, 1, JSEXN_NONE, "can't describe non-native properties of class {0}") -MSG_DEF(JSMSG_BAD_APPLY_ARGS, 154, 0, JSEXN_TYPEERR, "second argument to Function.prototype.apply must be an array") -MSG_DEF(JSMSG_REDECLARED_VAR, 155, 2, JSEXN_TYPEERR, "redeclaration of {0} {1}") -MSG_DEF(JSMSG_UNDECLARED_VAR, 156, 1, JSEXN_TYPEERR, "assignment to undeclared variable {0}") -MSG_DEF(JSMSG_ANON_NO_RETURN_VALUE, 157, 0, JSEXN_TYPEERR, "anonymous function does not always return a value") -MSG_DEF(JSMSG_DEPRECATED_USAGE, 158, 1, JSEXN_REFERENCEERR, "deprecated {0} usage") -MSG_DEF(JSMSG_BAD_URI, 159, 0, JSEXN_URIERR, "malformed URI sequence") -MSG_DEF(JSMSG_GETTER_ONLY, 160, 0, JSEXN_TYPEERR, "setting a property that has only a getter") -MSG_DEF(JSMSG_TRAILING_COMMA, 161, 0, JSEXN_SYNTAXERR, "trailing comma is not legal in ECMA-262 object initializers") -MSG_DEF(JSMSG_UNDEFINED_PROP, 162, 1, JSEXN_TYPEERR, "reference to undefined property {0}") -MSG_DEF(JSMSG_USELESS_EXPR, 163, 0, JSEXN_TYPEERR, "useless expression") -MSG_DEF(JSMSG_REDECLARED_PARAM, 164, 1, JSEXN_TYPEERR, "redeclaration of formal parameter {0}") -MSG_DEF(JSMSG_NEWREGEXP_FLAGGED, 165, 0, JSEXN_TYPEERR, "can't supply flags when constructing one RegExp from another") -MSG_DEF(JSMSG_RESERVED_SLOT_RANGE, 166, 0, JSEXN_RANGEERR, "reserved slot index out of range") -MSG_DEF(JSMSG_CANT_DECODE_PRINCIPALS, 167, 0, JSEXN_INTERNALERR, "can't decode JSPrincipals") -MSG_DEF(JSMSG_CANT_SEAL_OBJECT, 168, 1, JSEXN_ERR, "can't seal {0} objects") -MSG_DEF(JSMSG_CANT_UNSEAL_OBJECT, 169, 1, JSEXN_ERR, "can't unseal {0} objects") -MSG_DEF(JSMSG_BAD_XML_MARKUP, 170, 0, JSEXN_SYNTAXERR, "invalid XML markup") -MSG_DEF(JSMSG_BAD_XML_CHARACTER, 171, 0, JSEXN_SYNTAXERR, "illegal XML character") -MSG_DEF(JSMSG_BAD_DEFAULT_XML_NAMESPACE,172,0,JSEXN_SYNTAXERR, "invalid default XML namespace") -MSG_DEF(JSMSG_BAD_XML_NAME_SYNTAX, 173, 0, JSEXN_SYNTAXERR, "invalid XML name") -MSG_DEF(JSMSG_BRACKET_AFTER_ATTR_EXPR,174, 0, JSEXN_SYNTAXERR, "missing ] after attribute expression") -MSG_DEF(JSMSG_NAME_AFTER_DBLDOT, 175, 0, JSEXN_SYNTAXERR, "missing name after .. operator") -MSG_DEF(JSMSG_CURLY_IN_XML_EXPR, 176, 0, JSEXN_SYNTAXERR, "missing } in XML expression") -MSG_DEF(JSMSG_BAD_XML_NAMESPACE, 177, 1, JSEXN_TYPEERR, "invalid XML namespace {0}") -MSG_DEF(JSMSG_BAD_XML_ATTR_NAME, 178, 1, JSEXN_TYPEERR, "invalid XML attribute name {0}") -MSG_DEF(JSMSG_BAD_XML_NAME, 179, 1, JSEXN_TYPEERR, "invalid XML name {0}") -MSG_DEF(JSMSG_BAD_XML_CONVERSION, 180, 1, JSEXN_TYPEERR, "can't convert {0} to XML") -MSG_DEF(JSMSG_BAD_XMLLIST_CONVERSION, 181, 1, JSEXN_TYPEERR, "can't convert {0} to XMLList") -MSG_DEF(JSMSG_IS_NOT_XML_OBJECT, 182, 1, JSEXN_TYPEERR, "{0} is not an XML object") -MSG_DEF(JSMSG_NO_ASSIGN_IN_XML_ATTR, 183, 0, JSEXN_SYNTAXERR, "missing = in XML attribute") -MSG_DEF(JSMSG_BAD_XML_ATTR_VALUE, 184, 0, JSEXN_SYNTAXERR, "invalid XML attribute value") -MSG_DEF(JSMSG_XML_TAG_NAME_MISMATCH, 185, 0, JSEXN_SYNTAXERR, "XML tag name mismatch") -MSG_DEF(JSMSG_BAD_XML_TAG_SYNTAX, 186, 0, JSEXN_SYNTAXERR, "invalid XML tag syntax") -MSG_DEF(JSMSG_BAD_XML_LIST_SYNTAX, 187, 0, JSEXN_SYNTAXERR, "invalid XML list syntax") -MSG_DEF(JSMSG_INCOMPATIBLE_METHOD, 188, 3, JSEXN_TYPEERR, "{0} {1} called on incompatible {2}") -MSG_DEF(JSMSG_CANT_SET_XML_ATTRS, 189, 0, JSEXN_INTERNALERR, "can't set XML property attributes") -MSG_DEF(JSMSG_END_OF_XML_SOURCE, 190, 0, JSEXN_SYNTAXERR, "unexpected end of XML source") -MSG_DEF(JSMSG_END_OF_XML_ENTITY, 191, 0, JSEXN_SYNTAXERR, "unexpected end of XML entity") -MSG_DEF(JSMSG_BAD_XML_QNAME, 192, 0, JSEXN_SYNTAXERR, "invalid XML qualified name") -MSG_DEF(JSMSG_BAD_FOR_EACH_LOOP, 193, 0, JSEXN_SYNTAXERR, "invalid for each loop") -MSG_DEF(JSMSG_BAD_XMLLIST_PUT, 194, 1, JSEXN_TYPEERR, "can't set property {0} in XMLList") -MSG_DEF(JSMSG_UNKNOWN_XML_ENTITY, 195, 1, JSEXN_TYPEERR, "unknown XML entity {0}") -MSG_DEF(JSMSG_BAD_XML_NCR, 196, 1, JSEXN_TYPEERR, "malformed XML character {0}") -MSG_DEF(JSMSG_UNDEFINED_XML_NAME, 197, 1, JSEXN_REFERENCEERR, "reference to undefined XML name {0}") -MSG_DEF(JSMSG_DUPLICATE_XML_ATTR, 198, 1, JSEXN_TYPEERR, "duplicate XML attribute {0}") -MSG_DEF(JSMSG_TOO_MANY_FUN_VARS, 199, 0, JSEXN_SYNTAXERR, "too many local variables") -MSG_DEF(JSMSG_ARRAY_INIT_TOO_BIG, 200, 0, JSEXN_INTERNALERR, "array initialiser too large") -MSG_DEF(JSMSG_REGEXP_TOO_COMPLEX, 201, 0, JSEXN_INTERNALERR, "regular expression too complex") -MSG_DEF(JSMSG_WRONG_CONSTRUCTOR, 202, 1, JSEXN_TYPEERR, "wrong construtor called for {0}") -MSG_DEF(JSMSG_SELF_MODIFYING_SCRIPT, 203, 0, JSEXN_TYPEERR, "self-modifying script detected") -MSG_DEF(JSMSG_BUFFER_TOO_SMALL, 204, 0, JSEXN_INTERNALERR, "buffer too small") -MSG_DEF(JSMSG_BAD_SURROGATE_CHAR, 205, 1, JSEXN_TYPEERR, "bad surrogate character {0}") -MSG_DEF(JSMSG_UTF8_CHAR_TOO_LARGE, 206, 1, JSEXN_TYPEERR, "UTF-8 character {0} too large") -MSG_DEF(JSMSG_MALFORMED_UTF8_CHAR, 207, 1, JSEXN_TYPEERR, "malformed UTF-8 character sequence at offset {0}") -MSG_DEF(JSMSG_USER_DEFINED_ERROR, 208, 0, JSEXN_ERR, "JS_ReportError was called") diff --git a/lib/javascript/js.pkg b/lib/javascript/js.pkg deleted file mode 100644 index 93185a92..00000000 --- a/lib/javascript/js.pkg +++ /dev/null @@ -1,2 +0,0 @@ -[gecko xpi-bootstrap] -dist/bin/@SHARED_LIBRARY@ diff --git a/lib/javascript/js3240.rc b/lib/javascript/js3240.rc deleted file mode 100644 index 1a9f62c0..00000000 --- a/lib/javascript/js3240.rc +++ /dev/null @@ -1,79 +0,0 @@ -//Microsoft Developer Studio generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "winver.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 4,0,0,0 - PRODUCTVERSION 4,0,0,0 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x10004L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904e4" - BEGIN - VALUE "CompanyName", "Netscape Communications Corporation\0" - VALUE "FileDescription", "Netscape 32-bit JavaScript Module\0" - VALUE "FileVersion", "4.0\0" - VALUE "InternalName", "JS3240\0" - VALUE "LegalCopyright", "Copyright Netscape Communications. 1994-96\0" - VALUE "LegalTrademarks", "Netscape, Mozilla\0" - VALUE "OriginalFilename", "js3240.dll\0" - VALUE "ProductName", "NETSCAPE\0" - VALUE "ProductVersion", "4.0\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1252 - END -END - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE DISCARDABLE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE DISCARDABLE -BEGIN - "#include ""winver.h""\r\n" - "\0" -END - -3 TEXTINCLUDE DISCARDABLE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - -///////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/lib/javascript/jsOS240.def b/lib/javascript/jsOS240.def deleted file mode 100644 index 8f27d649..00000000 --- a/lib/javascript/jsOS240.def +++ /dev/null @@ -1,654 +0,0 @@ -; ***** BEGIN LICENSE BLOCK ***** -; Version: MPL 1.1/GPL 2.0/LGPL 2.1 -; -; The contents of this file are subject to the Mozilla Public License Version -; 1.1 (the "License"); you may not use this file except in compliance with -; the License. You may obtain a copy of the License at -; http://www.mozilla.org/MPL/ -; -; Software distributed under the License is distributed on an "AS IS" basis, -; WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -; for the specific language governing rights and limitations under the -; License. -; -; The Original Code is Mozilla Communicator client code, released -; March 31, 1998. -; -; The Initial Developer of the Original Code is -; Netscape Communications Corporation. -; Portions created by the Initial Developer are Copyright (C) 1998 -; the Initial Developer. All Rights Reserved. -; -; Contributor(s): -; -; Alternatively, the contents of this file may be used under the terms of -; either of the GNU General Public License Version 2 or later (the "GPL"), -; or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -; in which case the provisions of the GPL or the LGPL are applicable instead -; of those above. If you wish to allow use of your version of this file only -; under the terms of either the GPL or the LGPL, and not to allow others to -; use your version of this file under the terms of the MPL, indicate your -; decision by deleting the provisions above and replace them with the notice -; and other provisions required by the GPL or the LGPL. If you do not delete -; the provisions above, a recipient may use your version of this file under -; the terms of any one of the MPL, the GPL or the LGPL. -; -; ***** END LICENSE BLOCK ***** - -LIBRARY JS3240 INITINSTANCE TERMINSTANCE -PROTMODE - -DESCRIPTION 'Netscape OS/2 JavaScript Library' - - -CODE LOADONCALL MOVEABLE DISCARDABLE -DATA PRELOAD MOVEABLE MULTIPLE NONSHARED - - -EXPORTS -;====================== win16 exports these at least... =========== -; JS_Init = JS_Init @2 -; JS_Finish = JS_Finish @3 -; JS_GetNaNValue -; JS_GetNegativeInfinityValue -; JS_GetPositiveInfinityValue -; JS_GetEmptyStringValue -; JS_ConvertValue -; JS_ValueToObject -; JS_ValueToFunction -; JS_ValueToString -; JS_ValueToNumber -; JS_ValueToBoolean -; JS_TypeOfValue -; JS_GetTypeName -; JS_Lock -; JS_Unlock -; JS_NewContext -; JS_DestroyContext -; JS_ContextIterator -; JS_GetGlobalObject -; JS_SetGlobalObject -; JS_InitStandardClasses -;; JS_GetStaticLink -; JS_malloc -; JS_realloc -; JS_free -; JS_strdup -; JS_NewDouble -; JS_NewDoubleValue -; JS_AddRoot -; JS_RemoveRoot -; JS_LockGCThing -; JS_UnlockGCThing -; JS_GC -; JS_PropertyStub -; JS_EnumerateStub -; JS_ResolveStub -; JS_ConvertStub -; JS_FinalizeStub -; JS_InitClass -; JS_GetClass -; JS_InstanceOf -; JS_GetPrivate -; JS_SetPrivate -; JS_GetInstancePrivate -; JS_GetPrototype -; JS_GetParent -; JS_SetParent -; JS_GetConstructor -; JS_NewObject -; JS_DefineObject -; JS_DefineConstDoubles -; JS_DefineProperties -; JS_DefineProperty -; JS_DefinePropertyWithTinyId -; JS_AliasProperty -; JS_LookupProperty -; JS_GetProperty -; JS_SetProperty -; JS_DeleteProperty -; JS_NewArrayObject -; JS_DefineElement -; JS_AliasElement -; JS_LookupElement -; JS_GetElement -; JS_SetElement -; JS_DeleteElement -; JS_ClearScope -; JS_NewFunction -; JS_GetFunctionObject -; JS_GetFunctionName -; JS_DefineFunctions -; JS_DefineFunction -; JS_CompileScript -; JS_DestroyScript -; JS_CompileFunction -; JS_DecompileScript -; JS_DecompileFunction -; JS_DecompileFunctionBody -; JS_ExecuteScript -; JS_EvaluateScript -; JS_CallFunction -; JS_CallFunctionName -; JS_CallFunctionValue -; JS_SetBranchCallback -; JS_IsRunning -; JS_IsConstructing -; JS_SetCallReturnValue2 -; JS_NewString -; JS_NewStringCopyN -; JS_NewStringCopyZ -; JS_InternString -; JS_GetStringBytes -; JS_GetStringLength -; JS_CompareStrings -; JS_ReportError -; JS_ReportOutOfMemory -; JS_SetErrorReporter -; JS_NewRegExpObject -; JS_SetRegExpInput -; JS_ClearRegExpStatics -;================================================= - - -;00001:jsstr (OFFSET:0x00002e17, SIZE:0x0000ae17): -; - Public Definitions: -; js_EmptySubString -; js_CompareStrings -; js_HashString -; js_ValueToString -; js_StringToObject -; js_FinalizeString -; js_NewStringCopyZ -; js_NewString -; js_InitStringClass -; js_NewStringCopyN -; js_BoyerMooreHorspool -; -; -;00002:jsscript (OFFSET:0x0000dc2e, SIZE:0x00003abb): -; - Public Definitions: -; js_LineNumberToPC -; js_PCToLineNumber -; js_GetSrcNote -; js_DestroyScript -; js_NewScript -; -; -;00003:jsscope (OFFSET:0x000116e9, SIZE:0x00004f82): -; - Public Definitions: -; js_hash_scope_ops -; js_list_scope_ops -; js_DestroyProperty -; js_NewProperty -; js_IdToValue -; js_HashValue -; js_DestroyScope -; js_MutateScope -; js_DropScope -; js_HoldScope -; js_NewScope -; js_GetMutableScope -; js_HoldProperty -; js_DropProperty -; -; -;00004:jsscan (OFFSET:0x0001666b, SIZE:0x00008890): -; - Public Definitions: -; js_MatchToken -; js_FlushNewlines -; js_PeekTokenSameLine -; js_UngetToken -; js_GetToken -; js_PeekToken -; js_ReportCompileError - js_CloseTokenStream - js_NewBufferTokenStream -; js_NewTokenStream -; js_InitScanner -; -; -;00005:jsregexp (OFFSET:0x0001eefb, SIZE:0x0000eee4): -; - Public Definitions: -; js_RegExpClass -; reopsize -; js_NewRegExpObject -; js_InitRegExpClass -; js_FreeRegExpStatics -; js_InitRegExpStatics -; js_ExecuteRegExp -; js_NewRegExpOpt -; js_DestroyRegExp -; js_NewRegExp -; -; -;00006:jsparse (OFFSET:0x0002dddf, SIZE:0x00010b71): -; - Public Definitions: -; js_ParseFunctionBody - js_Parse -; -; -;00007:jsopcode (OFFSET:0x0003e950, SIZE:0x0000d362): -; - Public Definitions: -; js_EscapeMap -; js_NumCodeSpecs -; js_CodeSpec -; js_incop_str -; js_true_str -; js_false_str -; js_this_str -; js_null_str -; js_void_str -; js_typeof_str -; js_delete_str -; js_new_str -; js_ValueToSource -; js_DecompileScript -; js_DecompileCode -; js_DecompileFunction -; js_puts -; js_printf -; js_GetPrinterOutput -; js_DestroyPrinter -; js_NewPrinter -; js_EscapeString -; js_Disassemble1 -; js_Disassemble -; -;00008:jsobj (OFFSET:0x0004bcb2, SIZE:0x000090a4): -; - Public Definitions: -; js_WithClass -; js_ObjectClass -; js_TryValueOf -; js_ValueToNonNullObject -; js_TryMethod -; js_ObjectToString -; js_SetClassPrototype -; js_DeleteProperty2 -; js_DeleteProperty -; js_SetProperty -; js_GetProperty -; js_FindVariableScope -; js_FindVariable -; js_FindProperty -; js_LookupProperty -; js_DefineProperty -; js_FreeSlot -; js_AllocSlot -; js_FinalizeObject -; js_GetClassPrototype -; js_NewObject -; js_InitObjectClass -; js_ValueToObject -; js_obj_toString -; js_SetSlot -; js_GetSlot -; -; -;00009:jsnum (OFFSET:0x00054d56, SIZE:0x00004f29): -; - Public Definitions: -; js_ValueToInt32 -; js_NumberToObject -; js_FinalizeDouble -; js_InitNumberClass -; js_NumberToString -; js_NewDoubleValue -; js_NewDouble -; js_ValueToNumber -; -; -;00010:jsmath (OFFSET:0x00059c7f, SIZE:0x000054b6): -; - Public Definitions: -; js_InitMathClass -; -; -;00011:jsjava (OFFSET:0x0005f135, SIZE:0x00022aad): -; - Public Definitions: -; js_Hooks -; MojaSrcLog -; finalizeTask - JSJ_FindCurrentJSContext -; JSJ_GetPrincipals - JSJ_IsSafeMethod - JSJ_InitContext - JSJ_Init - js_JSErrorToJException - js_JavaErrorReporter - js_RemoveReflection - js_ReflectJObjectToJSObject - js_convertJObjectToJSValue - js_convertJSValueToJObject - js_ReflectJSObjectToJObject -; js_ReflectJClassToJSObject - JSJ_ExitJS - JSJ_EnterJS - JSJ_CurrentContext - JSJ_IsEnabled -;added in GA code - DSR70297 - JSJ_Finish - JSJ_IsCalledFromJava - js_GetJSPrincipalsFromJavaCaller - -; -; -;00012:jsinterp (OFFSET:0x00081be2, SIZE:0x00012274): -; - Public Definitions: -; js_Call -; js_Interpret -; js_SetLocalVariable -; js_GetLocalVariable -; js_SetArgument -; js_GetArgument -; js_FlushPropertyCacheByProp -; js_FlushPropertyCache -; -; -;00013:jsgc (OFFSET:0x00093e56, SIZE:0x00004f8d): -; - Public Definitions: -; js_ForceGC -; js_UnlockGCThing -; js_LockGCThing -; js_GC -; js_AllocGCThing -; js_RemoveRoot -; js_AddRoot -; js_FinishGC -; js_InitGC -; -; -;00014:jsfun (OFFSET:0x00098de3, SIZE:0x0000977c): -; - Public Definitions: -; js_FunctionClass -; js_ClosureClass -; js_CallClass -; js_DefineFunction -; js_NewFunction -; js_InitCallAndClosureClasses -; js_InitFunctionClass -; js_ValueToFunction -; js_SetCallVariable -; js_GetCallVariable -; js_PutCallObject -; js_GetCallObject -; -; -;00015:jsemit (OFFSET:0x000a255f, SIZE:0x000077be): -; - Public Definitions: -; js_SrcNoteName -; js_SrcNoteArity - js_FinishTakingSrcNotes -; js_MoveSrcNotes -; js_GetSrcNoteOffset -; js_BumpSrcNoteDelta -; js_NewSrcNote3 -; js_NewSrcNote2 -; js_PopStatement -; js_EmitContinue -; js_EmitBreak -; js_SetSrcNoteOffset -; js_NewSrcNote -; js_PushStatement -; js_MoveCode -; js_SetJumpOffset -; js_Emit3 -; js_Emit2 -; js_Emit1 -; js_UpdateDepth -; js_SrcNoteLength -; js_CancelLastOpcode - js_InitCodeGenerator -; -; -;00016:jsdbgapi (OFFSET:0x000a9d1d, SIZE:0x000057db): -; - Public Definitions: -; js_watchpoint_list -; js_trap_list -; JS_SetAnnotationInFrame -; JS_GetAnnotationFromFrame -; JS_GetJSPrincipalArrayFromFrame -; JS_NextJSFrame -; JS_InitJSFrameIterator - JS_LineNumberToPC - JS_PCToLineNumber - JS_ClearAllWatchPoints - JS_ClearWatchPoint - JS_SetWatchPoint - JS_HandleTrap - JS_ClearAllTraps - JS_ClearScriptTraps - JS_ClearTrap - JS_GetTrapOpcode - JS_SetTrap -;DSR070297 - added in GA code - JS_FrameIterator - JS_GetFrameAnnotation - JS_GetFramePrincipalArray - JS_GetFrameScript - JS_GetScriptFilename - JS_SetFrameAnnotation - JS_GetFramePC - JS_GetFunctionScript - -; -; -;00017:jsdate (OFFSET:0x000af4f8, SIZE:0x00009a8e): -; - Public Definitions: - js_DateGetSeconds - js_DateGetMinutes - js_DateGetHours - js_DateGetDate - js_DateGetMonth - js_DateGetYear - js_NewDateObject -; js_InitDateClass -; -; -;00018:jscntxt (OFFSET:0x000b8f86, SIZE:0x00003732): -; - Public Definitions: -; js_InterpreterHooks -; js_ReportIsNotDefined -; js_ReportErrorAgain -; js_ReportErrorVA -; js_ContextIterator -; js_DestroyContext -; js_NewContext -; js_SetInterpreterHooks -; -; -;00019:jsbool (OFFSET:0x000bc6b8, SIZE:0x00003375): -; - Public Definitions: -; js_BooleanToString -; js_BooleanToObject -; js_InitBooleanClass -; js_ValueToBoolean -; -; -;00020:jsatom (OFFSET:0x000bfa2d, SIZE:0x000058d0): -; - Public Definitions: -; js_valueOf_str -; js_toString_str -; js_length_str -; js_eval_str -; js_constructor_str -; js_class_prototype_str -; js_assign_str -; js_anonymous_str -; js_Object_str -; js_Array_str -; js_type_str -; js_DropUnmappedAtoms - js_FreeAtomMap - js_InitAtomMap -; js_GetAtom -; js_DropAtom -; js_IndexAtom -; js_ValueToStringAtom -; js_AtomizeString -; js_AtomizeDouble -; js_AtomizeInt -; js_AtomizeBoolean -; js_AtomizeObject -; js_HoldAtom -; js_MarkAtomState -; js_FreeAtomState -; js_Atomize -; js_InitAtomState -; -; -;00021:jsarray (OFFSET:0x000c52fd, SIZE:0x00007c86): -; - Public Definitions: -; js_ArrayClass -; js_SetArrayLength -; js_GetArrayLength -; js_InitArrayClass -; js_NewArrayObject -; PR_qsort -; -; -;00022:jsapi (OFFSET:0x000ccf83, SIZE:0x0000de8c): -; - Public Definitions: - JS_ClearRegExpStatics - JS_SetRegExpInput - JS_NewRegExpObject - JS_SetErrorReporter - JS_CompareStrings - JS_GetStringLength - JS_GetStringBytes - JS_InternString - JS_NewStringCopyZ - JS_NewStringCopyN - JS_NewString - JS_IsRunning - JS_SetBranchCallback - JS_CallFunctionValue - JS_CallFunctionName - JS_CallFunction - JS_EvaluateScriptForPrincipals - JS_EvaluateScript - JS_ExecuteScript - JS_DecompileFunctionBody - JS_DecompileFunction - JS_DecompileScript - JS_CompileFunctionForPrincipals - JS_CompileFunction - JS_DestroyScript - JS_CompileScriptForPrincipals - JS_CompileScript - JS_DefineFunction - JS_GetFunctionName - JS_GetFunctionObject - JS_NewFunction - JS_ClearScope - JS_DeleteElement - JS_SetElement - JS_GetElement - JS_LookupElement - JS_AliasElement - JS_DefineElement - JS_SetArrayLength - JS_GetArrayLength - JS_NewArrayObject - JS_DeleteProperty - JS_SetProperty - JS_GetProperty - JS_LookupProperty - JS_AliasProperty - JS_DefinePropertyWithTinyId - JS_DefineProperty - JS_DefineConstDoubles - JS_DefineObject - JS_NewObject - JS_GetConstructor - JS_SetParent - JS_GetParent - JS_SetPrototype - JS_GetPrototype - JS_GetInstancePrivate - JS_SetPrivate - JS_GetPrivate - JS_InstanceOf - JS_GetClass - JS_DefineFunctions - JS_DefineProperties - JS_InitClass - JS_FinalizeStub - JS_ConvertStub - JS_ResolveStub - JS_EnumerateStub - JS_PropertyStub - JS_GC - JS_UnlockGCThing - JS_LockGCThing - JS_RemoveRoot - JS_AddRoot - JS_NewDoubleValue - JS_NewDouble - JS_strdup - JS_free - JS_realloc - JS_ReportOutOfMemory - JS_malloc - JS_GetScopeChain - JS_InitStandardClasses - JS_SetGlobalObject - JS_GetGlobalObject - JS_SetVersion - JS_GetVersion - JS_ContextIterator - JS_GetTaskState - JS_DestroyContext - JS_NewContext - JS_Unlock - JS_Lock - JS_Finish - JS_Init - JS_GetTypeName - JS_TypeOfValue - JS_ValueToBoolean - JS_ValueToInt32 - JS_ValueToNumber - JS_ValueToString - JS_ValueToFunction - JS_ValueToObject - JS_ReportError - JS_ConvertValue - JS_GetEmptyStringValue - JS_GetPositiveInfinityValue - JS_GetNegativeInfinityValue - JS_GetNaNValue -;DSR062897 - added for GA code - JS_MaybeGC - JS_GetScriptPrincipals - JS_IsAssigning - JS_SetCharSetInfo -;brendan@mozilla.org, 2-Sept-2000 - JS_SetCallReturnValue2 - JS_SetGCCallback - JS_SetGCCallbackRT - JS_AddExternalStringFinalizer - JS_RemoveExternalStringFinalizer - JS_NewExternalString -; -; -;00023:prmjtime (OFFSET:0x000dae0f, SIZE:0x00008986): -; - Public Definitions: - PRMJ_FormatTimeUSEnglish - PRMJ_gmtime - PRMJ_FormatTime - PRMJ_mktime - PRMJ_ComputeTime - PRMJ_localtime - PRMJ_ExplodeTime - PRMJ_ToLocal - PRMJ_ToGMT - PRMJ_NowLocal - PRMJ_DSTOffset - PRMJ_NowS - PRMJ_NowMS - PRMJ_Now - PRMJ_ToExtendedTime - PRMJ_ToBaseTime - PRMJ_setDST - PRMJ_LocalGMTDifference - - diff --git a/lib/javascript/jsapi.c b/lib/javascript/jsapi.c deleted file mode 100644 index 344fc246..00000000 --- a/lib/javascript/jsapi.c +++ /dev/null @@ -1,4847 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sw=4 et tw=80: - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JavaScript API. - */ -#include "jsstddef.h" -#include -#include -#include -#include -#include "jstypes.h" -#include "jsarena.h" /* Added by JSIFY */ -#include "jsutil.h" /* Added by JSIFY */ -#include "jsclist.h" -#include "jsdhash.h" -#include "jsprf.h" -#include "jsapi.h" -#include "jsarray.h" -#include "jsatom.h" -#include "jsbool.h" -#include "jscntxt.h" -#include "jsconfig.h" -#include "jsdate.h" -#include "jsdtoa.h" -#include "jsemit.h" -#include "jsexn.h" -#include "jsfun.h" -#include "jsgc.h" -#include "jsinterp.h" -#include "jslock.h" -#include "jsmath.h" -#include "jsnum.h" -#include "jsobj.h" -#include "jsopcode.h" -#include "jsparse.h" -#include "jsregexp.h" -#include "jsscan.h" -#include "jsscope.h" -#include "jsscript.h" -#include "jsstr.h" -#include "prmjtime.h" - -#if JS_HAS_FILE_OBJECT -#include "jsfile.h" -#endif - -#if JS_HAS_XML_SUPPORT -#include "jsxml.h" -#endif - -#ifdef HAVE_VA_LIST_AS_ARRAY -#define JS_ADDRESSOF_VA_LIST(ap) ((va_list *)(ap)) -#else -#define JS_ADDRESSOF_VA_LIST(ap) (&(ap)) -#endif - -#if defined(JS_PARANOID_REQUEST) && defined(JS_THREADSAFE) -#define CHECK_REQUEST(cx) JS_ASSERT(cx->requestDepth) -#else -#define CHECK_REQUEST(cx) ((void)0) -#endif - -JS_PUBLIC_API(int64) -JS_Now() -{ - return PRMJ_Now(); -} - -JS_PUBLIC_API(jsval) -JS_GetNaNValue(JSContext *cx) -{ - return DOUBLE_TO_JSVAL(cx->runtime->jsNaN); -} - -JS_PUBLIC_API(jsval) -JS_GetNegativeInfinityValue(JSContext *cx) -{ - return DOUBLE_TO_JSVAL(cx->runtime->jsNegativeInfinity); -} - -JS_PUBLIC_API(jsval) -JS_GetPositiveInfinityValue(JSContext *cx) -{ - return DOUBLE_TO_JSVAL(cx->runtime->jsPositiveInfinity); -} - -JS_PUBLIC_API(jsval) -JS_GetEmptyStringValue(JSContext *cx) -{ - return STRING_TO_JSVAL(cx->runtime->emptyString); -} - -static JSBool -TryArgumentFormatter(JSContext *cx, const char **formatp, JSBool fromJS, - jsval **vpp, va_list *app) -{ - const char *format; - JSArgumentFormatMap *map; - - format = *formatp; - for (map = cx->argumentFormatMap; map; map = map->next) { - if (!strncmp(format, map->format, map->length)) { - *formatp = format + map->length; - return map->formatter(cx, format, fromJS, vpp, app); - } - } - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CHAR, format); - return JS_FALSE; -} - -JS_PUBLIC_API(JSBool) -JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format, - ...) -{ - va_list ap; - JSBool ok; - - va_start(ap, format); - ok = JS_ConvertArgumentsVA(cx, argc, argv, format, ap); - va_end(ap); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_ConvertArgumentsVA(JSContext *cx, uintN argc, jsval *argv, - const char *format, va_list ap) -{ - jsval *sp; - JSBool required; - char c; - JSFunction *fun; - jsdouble d; - JSString *str; - JSObject *obj; - - CHECK_REQUEST(cx); - sp = argv; - required = JS_TRUE; - while ((c = *format++) != '\0') { - if (isspace(c)) - continue; - if (c == '/') { - required = JS_FALSE; - continue; - } - if (sp == argv + argc) { - if (required) { - fun = js_ValueToFunction(cx, &argv[-2], 0); - if (fun) { - char numBuf[12]; - JS_snprintf(numBuf, sizeof numBuf, "%u", argc); - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_MORE_ARGS_NEEDED, - JS_GetFunctionName(fun), numBuf, - (argc == 1) ? "" : "s"); - } - return JS_FALSE; - } - break; - } - switch (c) { - case 'b': - if (!js_ValueToBoolean(cx, *sp, va_arg(ap, JSBool *))) - return JS_FALSE; - break; - case 'c': - if (!js_ValueToUint16(cx, *sp, va_arg(ap, uint16 *))) - return JS_FALSE; - break; - case 'i': - if (!js_ValueToECMAInt32(cx, *sp, va_arg(ap, int32 *))) - return JS_FALSE; - break; - case 'u': - if (!js_ValueToECMAUint32(cx, *sp, va_arg(ap, uint32 *))) - return JS_FALSE; - break; - case 'j': - if (!js_ValueToInt32(cx, *sp, va_arg(ap, int32 *))) - return JS_FALSE; - break; - case 'd': - if (!js_ValueToNumber(cx, *sp, va_arg(ap, jsdouble *))) - return JS_FALSE; - break; - case 'I': - if (!js_ValueToNumber(cx, *sp, &d)) - return JS_FALSE; - *va_arg(ap, jsdouble *) = js_DoubleToInteger(d); - break; - case 's': - case 'S': - case 'W': - str = js_ValueToString(cx, *sp); - if (!str) - return JS_FALSE; - *sp = STRING_TO_JSVAL(str); - if (c == 's') - *va_arg(ap, char **) = JS_GetStringBytes(str); - else if (c == 'W') - *va_arg(ap, jschar **) = JS_GetStringChars(str); - else - *va_arg(ap, JSString **) = str; - break; - case 'o': - if (!js_ValueToObject(cx, *sp, &obj)) - return JS_FALSE; - *sp = OBJECT_TO_JSVAL(obj); - *va_arg(ap, JSObject **) = obj; - break; - case 'f': - obj = js_ValueToFunctionObject(cx, sp, 0); - if (!obj) - return JS_FALSE; - *va_arg(ap, JSFunction **) = (JSFunction *) JS_GetPrivate(cx, obj); - break; - case 'v': - *va_arg(ap, jsval *) = *sp; - break; - case '*': - break; - default: - format--; - if (!TryArgumentFormatter(cx, &format, JS_TRUE, &sp, - JS_ADDRESSOF_VA_LIST(ap))) { - return JS_FALSE; - } - /* NB: the formatter already updated sp, so we continue here. */ - continue; - } - sp++; - } - return JS_TRUE; -} - -JS_PUBLIC_API(jsval *) -JS_PushArguments(JSContext *cx, void **markp, const char *format, ...) -{ - va_list ap; - jsval *argv; - - va_start(ap, format); - argv = JS_PushArgumentsVA(cx, markp, format, ap); - va_end(ap); - return argv; -} - -JS_PUBLIC_API(jsval *) -JS_PushArgumentsVA(JSContext *cx, void **markp, const char *format, va_list ap) -{ - uintN argc; - jsval *argv, *sp; - char c; - const char *cp; - JSString *str; - JSFunction *fun; - JSStackHeader *sh; - - CHECK_REQUEST(cx); - *markp = NULL; - argc = 0; - for (cp = format; (c = *cp) != '\0'; cp++) { - /* - * Count non-space non-star characters as individual jsval arguments. - * This may over-allocate stack, but we'll fix below. - */ - if (isspace(c) || c == '*') - continue; - argc++; - } - sp = js_AllocStack(cx, argc, markp); - if (!sp) - return NULL; - argv = sp; - while ((c = *format++) != '\0') { - if (isspace(c) || c == '*') - continue; - switch (c) { - case 'b': - *sp = BOOLEAN_TO_JSVAL((JSBool) va_arg(ap, int)); - break; - case 'c': - *sp = INT_TO_JSVAL((uint16) va_arg(ap, unsigned int)); - break; - case 'i': - case 'j': - if (!js_NewNumberValue(cx, (jsdouble) va_arg(ap, int32), sp)) - goto bad; - break; - case 'u': - if (!js_NewNumberValue(cx, (jsdouble) va_arg(ap, uint32), sp)) - goto bad; - break; - case 'd': - case 'I': - if (!js_NewDoubleValue(cx, va_arg(ap, jsdouble), sp)) - goto bad; - break; - case 's': - str = JS_NewStringCopyZ(cx, va_arg(ap, char *)); - if (!str) - goto bad; - *sp = STRING_TO_JSVAL(str); - break; - case 'W': - str = JS_NewUCStringCopyZ(cx, va_arg(ap, jschar *)); - if (!str) - goto bad; - *sp = STRING_TO_JSVAL(str); - break; - case 'S': - str = va_arg(ap, JSString *); - *sp = STRING_TO_JSVAL(str); - break; - case 'o': - *sp = OBJECT_TO_JSVAL(va_arg(ap, JSObject *)); - break; - case 'f': - fun = va_arg(ap, JSFunction *); - *sp = fun ? OBJECT_TO_JSVAL(fun->object) : JSVAL_NULL; - break; - case 'v': - *sp = va_arg(ap, jsval); - break; - default: - format--; - if (!TryArgumentFormatter(cx, &format, JS_FALSE, &sp, - JS_ADDRESSOF_VA_LIST(ap))) { - goto bad; - } - /* NB: the formatter already updated sp, so we continue here. */ - continue; - } - sp++; - } - - /* - * We may have overallocated stack due to a multi-character format code - * handled by a JSArgumentFormatter. Give back that stack space! - */ - JS_ASSERT(sp <= argv + argc); - if (sp < argv + argc) { - /* Return slots not pushed to the current stack arena. */ - cx->stackPool.current->avail = (jsuword)sp; - - /* Reduce the count of slots the GC will scan in this stack segment. */ - sh = cx->stackHeaders; - JS_ASSERT(JS_STACK_SEGMENT(sh) + sh->nslots == argv + argc); - sh->nslots -= argc - (sp - argv); - } - return argv; - -bad: - js_FreeStack(cx, *markp); - return NULL; -} - -JS_PUBLIC_API(void) -JS_PopArguments(JSContext *cx, void *mark) -{ - CHECK_REQUEST(cx); - js_FreeStack(cx, mark); -} - -JS_PUBLIC_API(JSBool) -JS_AddArgumentFormatter(JSContext *cx, const char *format, - JSArgumentFormatter formatter) -{ - size_t length; - JSArgumentFormatMap **mpp, *map; - - length = strlen(format); - mpp = &cx->argumentFormatMap; - while ((map = *mpp) != NULL) { - /* Insert before any shorter string to match before prefixes. */ - if (map->length < length) - break; - if (map->length == length && !strcmp(map->format, format)) - goto out; - mpp = &map->next; - } - map = (JSArgumentFormatMap *) JS_malloc(cx, sizeof *map); - if (!map) - return JS_FALSE; - map->format = format; - map->length = length; - map->next = *mpp; - *mpp = map; -out: - map->formatter = formatter; - return JS_TRUE; -} - -JS_PUBLIC_API(void) -JS_RemoveArgumentFormatter(JSContext *cx, const char *format) -{ - size_t length; - JSArgumentFormatMap **mpp, *map; - - length = strlen(format); - mpp = &cx->argumentFormatMap; - while ((map = *mpp) != NULL) { - if (map->length == length && !strcmp(map->format, format)) { - *mpp = map->next; - JS_free(cx, map); - return; - } - mpp = &map->next; - } -} - -JS_PUBLIC_API(JSBool) -JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp) -{ - JSBool ok, b; - JSObject *obj; - JSString *str; - jsdouble d, *dp; - - CHECK_REQUEST(cx); - switch (type) { - case JSTYPE_VOID: - *vp = JSVAL_VOID; - ok = JS_TRUE; - break; - case JSTYPE_OBJECT: - ok = js_ValueToObject(cx, v, &obj); - if (ok) - *vp = OBJECT_TO_JSVAL(obj); - break; - case JSTYPE_FUNCTION: - *vp = v; - obj = js_ValueToFunctionObject(cx, vp, JSV2F_SEARCH_STACK); - ok = (obj != NULL); - break; - case JSTYPE_STRING: - str = js_ValueToString(cx, v); - ok = (str != NULL); - if (ok) - *vp = STRING_TO_JSVAL(str); - break; - case JSTYPE_NUMBER: - ok = js_ValueToNumber(cx, v, &d); - if (ok) { - dp = js_NewDouble(cx, d, 0); - ok = (dp != NULL); - if (ok) - *vp = DOUBLE_TO_JSVAL(dp); - } - break; - case JSTYPE_BOOLEAN: - ok = js_ValueToBoolean(cx, v, &b); - if (ok) - *vp = BOOLEAN_TO_JSVAL(b); - break; - default: { - char numBuf[12]; - JS_snprintf(numBuf, sizeof numBuf, "%d", (int)type); - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_TYPE, - numBuf); - ok = JS_FALSE; - break; - } - } - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_ValueToObject(JSContext *cx, jsval v, JSObject **objp) -{ - CHECK_REQUEST(cx); - return js_ValueToObject(cx, v, objp); -} - -JS_PUBLIC_API(JSFunction *) -JS_ValueToFunction(JSContext *cx, jsval v) -{ - CHECK_REQUEST(cx); - return js_ValueToFunction(cx, &v, JSV2F_SEARCH_STACK); -} - -JS_PUBLIC_API(JSFunction *) -JS_ValueToConstructor(JSContext *cx, jsval v) -{ - CHECK_REQUEST(cx); - return js_ValueToFunction(cx, &v, JSV2F_SEARCH_STACK); -} - -JS_PUBLIC_API(JSString *) -JS_ValueToString(JSContext *cx, jsval v) -{ - CHECK_REQUEST(cx); - return js_ValueToString(cx, v); -} - -JS_PUBLIC_API(JSBool) -JS_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp) -{ - CHECK_REQUEST(cx); - return js_ValueToNumber(cx, v, dp); -} - -JS_PUBLIC_API(JSBool) -JS_ValueToECMAInt32(JSContext *cx, jsval v, int32 *ip) -{ - CHECK_REQUEST(cx); - return js_ValueToECMAInt32(cx, v, ip); -} - -JS_PUBLIC_API(JSBool) -JS_ValueToECMAUint32(JSContext *cx, jsval v, uint32 *ip) -{ - CHECK_REQUEST(cx); - return js_ValueToECMAUint32(cx, v, ip); -} - -JS_PUBLIC_API(JSBool) -JS_ValueToInt32(JSContext *cx, jsval v, int32 *ip) -{ - CHECK_REQUEST(cx); - return js_ValueToInt32(cx, v, ip); -} - -JS_PUBLIC_API(JSBool) -JS_ValueToUint16(JSContext *cx, jsval v, uint16 *ip) -{ - CHECK_REQUEST(cx); - return js_ValueToUint16(cx, v, ip); -} - -JS_PUBLIC_API(JSBool) -JS_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp) -{ - CHECK_REQUEST(cx); - return js_ValueToBoolean(cx, v, bp); -} - -JS_PUBLIC_API(JSType) -JS_TypeOfValue(JSContext *cx, jsval v) -{ - JSType type; - JSObject *obj; - JSObjectOps *ops; - JSClass *clasp; - - CHECK_REQUEST(cx); - if (JSVAL_IS_OBJECT(v)) { - type = JSTYPE_OBJECT; /* XXXbe JSTYPE_NULL for JS2 */ - obj = JSVAL_TO_OBJECT(v); - if (obj) { - ops = obj->map->ops; -#if JS_HAS_XML_SUPPORT - if (ops == &js_XMLObjectOps.base) { - type = JSTYPE_XML; - } else -#endif - { - /* - * ECMA 262, 11.4.3 says that any native object that implements - * [[Call]] should be of type "function". Note that RegExp and - * Script are both of type "function" for compatibility with - * older SpiderMonkeys. - */ - clasp = OBJ_GET_CLASS(cx, obj); - if ((ops == &js_ObjectOps) - ? (clasp->call - ? (clasp == &js_RegExpClass || clasp == &js_ScriptClass) - : clasp == &js_FunctionClass) - : ops->call != NULL) { - type = JSTYPE_FUNCTION; - } else { -#ifdef NARCISSUS - if (!OBJ_GET_PROPERTY(cx, obj, - ATOM_TO_JSID(cx->runtime->atomState - .callAtom), - &v)) { - JS_ClearPendingException(cx); - } else if (JSVAL_IS_FUNCTION(cx, v)) { - type = JSTYPE_FUNCTION; - } -#endif - } - } - } - } else if (JSVAL_IS_NUMBER(v)) { - type = JSTYPE_NUMBER; - } else if (JSVAL_IS_STRING(v)) { - type = JSTYPE_STRING; - } else if (JSVAL_IS_BOOLEAN(v)) { - type = JSTYPE_BOOLEAN; - } else { - type = JSTYPE_VOID; - } - return type; -} - -JS_PUBLIC_API(const char *) -JS_GetTypeName(JSContext *cx, JSType type) -{ - if ((uintN)type >= (uintN)JSTYPE_LIMIT) - return NULL; - return js_type_str[type]; -} - -/************************************************************************/ - -JS_PUBLIC_API(JSRuntime *) -JS_NewRuntime(uint32 maxbytes) -{ - JSRuntime *rt; - -#ifdef DEBUG - JS_BEGIN_MACRO - /* - * This code asserts that the numbers associated with the error names in - * jsmsg.def are monotonically increasing. It uses values for the error - * names enumerated in jscntxt.c. It's not a compiletime check, but it's - * better than nothing. - */ - int errorNumber = 0; -#define MSG_DEF(name, number, count, exception, format) \ - JS_ASSERT(name == errorNumber++); -#include "js.msg" -#undef MSG_DEF - JS_END_MACRO; -#endif /* DEBUG */ - - if (!js_InitStringGlobals()) - return NULL; - rt = (JSRuntime *) malloc(sizeof(JSRuntime)); - if (!rt) - return NULL; - - /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */ - memset(rt, 0, sizeof(JSRuntime)); - JS_INIT_CLIST(&rt->contextList); - JS_INIT_CLIST(&rt->trapList); - JS_INIT_CLIST(&rt->watchPointList); - - if (!js_InitGC(rt, maxbytes)) - goto bad; -#ifdef JS_THREADSAFE - rt->gcLock = JS_NEW_LOCK(); - if (!rt->gcLock) - goto bad; - rt->gcDone = JS_NEW_CONDVAR(rt->gcLock); - if (!rt->gcDone) - goto bad; - rt->requestDone = JS_NEW_CONDVAR(rt->gcLock); - if (!rt->requestDone) - goto bad; - /* this is asymmetric with JS_ShutDown: */ - if (!js_SetupLocks(8, 16)) - goto bad; - rt->rtLock = JS_NEW_LOCK(); - if (!rt->rtLock) - goto bad; - rt->stateChange = JS_NEW_CONDVAR(rt->gcLock); - if (!rt->stateChange) - goto bad; - rt->setSlotLock = JS_NEW_LOCK(); - if (!rt->setSlotLock) - goto bad; - rt->setSlotDone = JS_NEW_CONDVAR(rt->setSlotLock); - if (!rt->setSlotDone) - goto bad; - rt->scopeSharingDone = JS_NEW_CONDVAR(rt->gcLock); - if (!rt->scopeSharingDone) - goto bad; - rt->scopeSharingTodo = NO_SCOPE_SHARING_TODO; -#endif - rt->propertyCache.empty = JS_TRUE; - if (!js_InitPropertyTree(rt)) - goto bad; - return rt; - -bad: - JS_DestroyRuntime(rt); - return NULL; -} - -JS_PUBLIC_API(void) -JS_DestroyRuntime(JSRuntime *rt) -{ -#ifdef DEBUG - /* Don't hurt everyone in leaky ol' Mozilla with a fatal JS_ASSERT! */ - if (!JS_CLIST_IS_EMPTY(&rt->contextList)) { - JSContext *cx, *iter = NULL; - uintN cxcount = 0; - while ((cx = js_ContextIterator(rt, JS_TRUE, &iter)) != NULL) - cxcount++; - fprintf(stderr, -"JS API usage error: %u contexts left in runtime upon JS_DestroyRuntime.\n", - cxcount); - } -#endif - - js_FreeRuntimeScriptState(rt); - js_FinishAtomState(&rt->atomState); - js_FinishGC(rt); -#ifdef JS_THREADSAFE - if (rt->gcLock) - JS_DESTROY_LOCK(rt->gcLock); - if (rt->gcDone) - JS_DESTROY_CONDVAR(rt->gcDone); - if (rt->requestDone) - JS_DESTROY_CONDVAR(rt->requestDone); - if (rt->rtLock) - JS_DESTROY_LOCK(rt->rtLock); - if (rt->stateChange) - JS_DESTROY_CONDVAR(rt->stateChange); - if (rt->setSlotLock) - JS_DESTROY_LOCK(rt->setSlotLock); - if (rt->setSlotDone) - JS_DESTROY_CONDVAR(rt->setSlotDone); - if (rt->scopeSharingDone) - JS_DESTROY_CONDVAR(rt->scopeSharingDone); -#endif - js_FinishPropertyTree(rt); - free(rt); -} - -JS_PUBLIC_API(void) -JS_ShutDown(void) -{ - JS_ArenaShutDown(); - js_FinishDtoa(); - js_FreeStringGlobals(); -#ifdef JS_THREADSAFE - js_CleanupLocks(); -#endif -} - -JS_PUBLIC_API(void *) -JS_GetRuntimePrivate(JSRuntime *rt) -{ - return rt->data; -} - -JS_PUBLIC_API(void) -JS_SetRuntimePrivate(JSRuntime *rt, void *data) -{ - rt->data = data; -} - -#ifdef JS_THREADSAFE - -JS_PUBLIC_API(void) -JS_BeginRequest(JSContext *cx) -{ - JSRuntime *rt; - - JS_ASSERT(cx->thread); - if (!cx->requestDepth) { - /* Wait until the GC is finished. */ - rt = cx->runtime; - JS_LOCK_GC(rt); - - /* NB: we use cx->thread here, not js_CurrentThreadId(). */ - if (rt->gcThread != cx->thread) { - while (rt->gcLevel > 0) - JS_AWAIT_GC_DONE(rt); - } - - /* Indicate that a request is running. */ - rt->requestCount++; - cx->requestDepth = 1; - JS_UNLOCK_GC(rt); - return; - } - cx->requestDepth++; -} - -JS_PUBLIC_API(void) -JS_EndRequest(JSContext *cx) -{ - JSRuntime *rt; - JSScope *scope, **todop; - uintN nshares; - - CHECK_REQUEST(cx); - JS_ASSERT(cx->requestDepth > 0); - if (cx->requestDepth == 1) { - /* Lock before clearing to interlock with ClaimScope, in jslock.c. */ - rt = cx->runtime; - JS_LOCK_GC(rt); - cx->requestDepth = 0; - - /* See whether cx has any single-threaded scopes to start sharing. */ - todop = &rt->scopeSharingTodo; - nshares = 0; - while ((scope = *todop) != NO_SCOPE_SHARING_TODO) { - if (scope->ownercx != cx) { - todop = &scope->u.link; - continue; - } - *todop = scope->u.link; - scope->u.link = NULL; /* null u.link for sanity ASAP */ - - /* - * If js_DropObjectMap returns null, we held the last ref to scope. - * The waiting thread(s) must have been killed, after which the GC - * collected the object that held this scope. Unlikely, because it - * requires that the GC ran (e.g., from a branch callback) during - * this request, but possible. - */ - if (js_DropObjectMap(cx, &scope->map, NULL)) { - js_InitLock(&scope->lock); - scope->u.count = 0; /* NULL may not pun as 0 */ - js_FinishSharingScope(rt, scope); /* set ownercx = NULL */ - nshares++; - } - } - if (nshares) - JS_NOTIFY_ALL_CONDVAR(rt->scopeSharingDone); - - /* Give the GC a chance to run if this was the last request running. */ - JS_ASSERT(rt->requestCount > 0); - rt->requestCount--; - if (rt->requestCount == 0) - JS_NOTIFY_REQUEST_DONE(rt); - - JS_UNLOCK_GC(rt); - return; - } - - cx->requestDepth--; -} - -/* Yield to pending GC operations, regardless of request depth */ -JS_PUBLIC_API(void) -JS_YieldRequest(JSContext *cx) -{ - JSRuntime *rt; - - JS_ASSERT(cx->thread); - CHECK_REQUEST(cx); - - rt = cx->runtime; - JS_LOCK_GC(rt); - JS_ASSERT(rt->requestCount > 0); - rt->requestCount--; - if (rt->requestCount == 0) - JS_NOTIFY_REQUEST_DONE(rt); - JS_UNLOCK_GC(rt); - /* XXXbe give the GC or another request calling it a chance to run here? - Assumes FIFO scheduling */ - JS_LOCK_GC(rt); - rt->requestCount++; - JS_UNLOCK_GC(rt); -} - -JS_PUBLIC_API(jsrefcount) -JS_SuspendRequest(JSContext *cx) -{ - jsrefcount saveDepth = cx->requestDepth; - - while (cx->requestDepth) - JS_EndRequest(cx); - return saveDepth; -} - -JS_PUBLIC_API(void) -JS_ResumeRequest(JSContext *cx, jsrefcount saveDepth) -{ - JS_ASSERT(!cx->requestDepth); - while (--saveDepth >= 0) - JS_BeginRequest(cx); -} - -#endif /* JS_THREADSAFE */ - -JS_PUBLIC_API(void) -JS_Lock(JSRuntime *rt) -{ - JS_LOCK_RUNTIME(rt); -} - -JS_PUBLIC_API(void) -JS_Unlock(JSRuntime *rt) -{ - JS_UNLOCK_RUNTIME(rt); -} - -JS_PUBLIC_API(JSContext *) -JS_NewContext(JSRuntime *rt, size_t stackChunkSize) -{ - return js_NewContext(rt, stackChunkSize); -} - -JS_PUBLIC_API(void) -JS_DestroyContext(JSContext *cx) -{ - js_DestroyContext(cx, JS_FORCE_GC); -} - -JS_PUBLIC_API(void) -JS_DestroyContextNoGC(JSContext *cx) -{ - js_DestroyContext(cx, JS_NO_GC); -} - -JS_PUBLIC_API(void) -JS_DestroyContextMaybeGC(JSContext *cx) -{ - js_DestroyContext(cx, JS_MAYBE_GC); -} - -JS_PUBLIC_API(void *) -JS_GetContextPrivate(JSContext *cx) -{ - return cx->data; -} - -JS_PUBLIC_API(void) -JS_SetContextPrivate(JSContext *cx, void *data) -{ - cx->data = data; -} - -JS_PUBLIC_API(JSRuntime *) -JS_GetRuntime(JSContext *cx) -{ - return cx->runtime; -} - -JS_PUBLIC_API(JSContext *) -JS_ContextIterator(JSRuntime *rt, JSContext **iterp) -{ - return js_ContextIterator(rt, JS_TRUE, iterp); -} - -JS_PUBLIC_API(JSVersion) -JS_GetVersion(JSContext *cx) -{ - return cx->version & JSVERSION_MASK; -} - -JS_PUBLIC_API(JSVersion) -JS_SetVersion(JSContext *cx, JSVersion version) -{ - JSVersion oldVersion; - - JS_ASSERT(version != JSVERSION_UNKNOWN); - JS_ASSERT((version & ~JSVERSION_MASK) == 0); - - oldVersion = cx->version & JSVERSION_MASK; - if (version == oldVersion) - return oldVersion; - - cx->version = (cx->version & ~JSVERSION_MASK) | version; - js_OnVersionChange(cx); - return oldVersion; -} - -static struct v2smap { - JSVersion version; - const char *string; -} v2smap[] = { - {JSVERSION_1_0, "1.0"}, - {JSVERSION_1_1, "1.1"}, - {JSVERSION_1_2, "1.2"}, - {JSVERSION_1_3, "1.3"}, - {JSVERSION_1_4, "1.4"}, - {JSVERSION_ECMA_3, "ECMAv3"}, - {JSVERSION_1_5, "1.5"}, - {JSVERSION_1_6, "1.6"}, - {JSVERSION_DEFAULT, js_default_str}, - {JSVERSION_UNKNOWN, NULL}, /* must be last, NULL is sentinel */ -}; - -JS_PUBLIC_API(const char *) -JS_VersionToString(JSVersion version) -{ - int i; - - for (i = 0; v2smap[i].string; i++) - if (v2smap[i].version == version) - return v2smap[i].string; - return "unknown"; -} - -JS_PUBLIC_API(JSVersion) -JS_StringToVersion(const char *string) -{ - int i; - - for (i = 0; v2smap[i].string; i++) - if (strcmp(v2smap[i].string, string) == 0) - return v2smap[i].version; - return JSVERSION_UNKNOWN; -} - -JS_PUBLIC_API(uint32) -JS_GetOptions(JSContext *cx) -{ - return cx->options; -} - -#define SYNC_OPTIONS_TO_VERSION(cx) \ - JS_BEGIN_MACRO \ - if ((cx)->options & JSOPTION_XML) \ - (cx)->version |= JSVERSION_HAS_XML; \ - else \ - (cx)->version &= ~JSVERSION_HAS_XML; \ - JS_END_MACRO - -JS_PUBLIC_API(uint32) -JS_SetOptions(JSContext *cx, uint32 options) -{ - uint32 oldopts = cx->options; - cx->options = options; - SYNC_OPTIONS_TO_VERSION(cx); - return oldopts; -} - -JS_PUBLIC_API(uint32) -JS_ToggleOptions(JSContext *cx, uint32 options) -{ - uint32 oldopts = cx->options; - cx->options ^= options; - SYNC_OPTIONS_TO_VERSION(cx); - return oldopts; -} - -JS_PUBLIC_API(const char *) -JS_GetImplementationVersion(void) -{ - return "JavaScript-C 1.6 2006-11-19"; -} - - -JS_PUBLIC_API(JSObject *) -JS_GetGlobalObject(JSContext *cx) -{ - return cx->globalObject; -} - -JS_PUBLIC_API(void) -JS_SetGlobalObject(JSContext *cx, JSObject *obj) -{ - cx->globalObject = obj; -#if JS_HAS_XML_SUPPORT - cx->xmlSettingFlags = 0; -#endif -} - -static JSObject * -InitFunctionAndObjectClasses(JSContext *cx, JSObject *obj) -{ - JSDHashTable *table; - JSBool resolving; - JSRuntime *rt; - JSResolvingKey key; - JSResolvingEntry *entry; - JSObject *fun_proto, *obj_proto; - - /* If cx has no global object, use obj so prototypes can be found. */ - if (!cx->globalObject) - JS_SetGlobalObject(cx, obj); - - /* Record Function and Object in cx->resolvingTable, if we are resolving. */ - table = cx->resolvingTable; - resolving = (table && table->entryCount); - if (resolving) { - rt = cx->runtime; - key.obj = obj; - key.id = ATOM_TO_JSID(rt->atomState.FunctionAtom); - entry = (JSResolvingEntry *) - JS_DHashTableOperate(table, &key, JS_DHASH_ADD); - if (entry && entry->key.obj && (entry->flags & JSRESFLAG_LOOKUP)) { - /* Already resolving Function, record Object too. */ - JS_ASSERT(entry->key.obj == obj); - key.id = ATOM_TO_JSID(rt->atomState.ObjectAtom); - entry = (JSResolvingEntry *) - JS_DHashTableOperate(table, &key, JS_DHASH_ADD); - } - if (!entry) { - JS_ReportOutOfMemory(cx); - return NULL; - } - JS_ASSERT(!entry->key.obj && entry->flags == 0); - entry->key = key; - entry->flags = JSRESFLAG_LOOKUP; - } - - /* Initialize the function class first so constructors can be made. */ - fun_proto = js_InitFunctionClass(cx, obj); - if (!fun_proto) - goto out; - - /* Initialize the object class next so Object.prototype works. */ - obj_proto = js_InitObjectClass(cx, obj); - if (!obj_proto) { - fun_proto = NULL; - goto out; - } - - /* Function.prototype and the global object delegate to Object.prototype. */ - OBJ_SET_PROTO(cx, fun_proto, obj_proto); - if (!OBJ_GET_PROTO(cx, obj)) - OBJ_SET_PROTO(cx, obj, obj_proto); - -out: - /* If resolving, remove the other entry (Object or Function) from table. */ - if (resolving) - JS_DHashTableOperate(table, &key, JS_DHASH_REMOVE); - return fun_proto; -} - -JS_PUBLIC_API(JSBool) -JS_InitStandardClasses(JSContext *cx, JSObject *obj) -{ - CHECK_REQUEST(cx); - -#if JS_HAS_UNDEFINED -{ - /* Define a top-level property 'undefined' with the undefined value. */ - JSAtom *atom = cx->runtime->atomState.typeAtoms[JSTYPE_VOID]; - if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID, - NULL, NULL, JSPROP_PERMANENT, NULL)) { - return JS_FALSE; - } -} -#endif - - /* Function and Object require cooperative bootstrapping magic. */ - if (!InitFunctionAndObjectClasses(cx, obj)) - return JS_FALSE; - - /* Initialize the rest of the standard objects and functions. */ - return js_InitArrayClass(cx, obj) && - js_InitBooleanClass(cx, obj) && - js_InitMathClass(cx, obj) && - js_InitNumberClass(cx, obj) && - js_InitStringClass(cx, obj) && -#if JS_HAS_CALL_OBJECT - js_InitCallClass(cx, obj) && -#endif -#if JS_HAS_REGEXPS - js_InitRegExpClass(cx, obj) && -#endif -#if JS_HAS_SCRIPT_OBJECT - js_InitScriptClass(cx, obj) && -#endif -#if JS_HAS_ERROR_EXCEPTIONS - js_InitExceptionClasses(cx, obj) && -#endif -#if JS_HAS_XML_SUPPORT - js_InitXMLClasses(cx, obj) && -#endif -#if JS_HAS_FILE_OBJECT - js_InitFileClass(cx, obj) && -#endif - js_InitDateClass(cx, obj); -} - -#define ATOM_OFFSET(name) offsetof(JSAtomState, name##Atom) -#define OFFSET_TO_ATOM(rt,off) (*(JSAtom **)((char*)&(rt)->atomState + (off))) - -/* - * Table of class initializers and their atom offsets in rt->atomState. - * If you add a "standard" class, remember to update this table. - */ -static struct { - JSObjectOp init; - size_t atomOffset; -} standard_class_atoms[] = { - {InitFunctionAndObjectClasses, ATOM_OFFSET(Function)}, - {InitFunctionAndObjectClasses, ATOM_OFFSET(Object)}, - {js_InitArrayClass, ATOM_OFFSET(Array)}, - {js_InitBooleanClass, ATOM_OFFSET(Boolean)}, - {js_InitDateClass, ATOM_OFFSET(Date)}, - {js_InitMathClass, ATOM_OFFSET(Math)}, - {js_InitNumberClass, ATOM_OFFSET(Number)}, - {js_InitStringClass, ATOM_OFFSET(String)}, -#if JS_HAS_CALL_OBJECT - {js_InitCallClass, ATOM_OFFSET(Call)}, -#endif -#if JS_HAS_ERROR_EXCEPTIONS - {js_InitExceptionClasses, ATOM_OFFSET(Error)}, -#endif -#if JS_HAS_REGEXPS - {js_InitRegExpClass, ATOM_OFFSET(RegExp)}, -#endif -#if JS_HAS_SCRIPT_OBJECT - {js_InitScriptClass, ATOM_OFFSET(Script)}, -#endif -#if JS_HAS_XML_SUPPORT - {js_InitXMLClass, ATOM_OFFSET(XML)}, - {js_InitNamespaceClass, ATOM_OFFSET(Namespace)}, - {js_InitQNameClass, ATOM_OFFSET(QName)}, -#endif -#if JS_HAS_FILE_OBJECT - {js_InitFileClass, ATOM_OFFSET(File)}, -#endif - {NULL, 0} -}; - -/* - * Table of top-level function and constant names and their init functions. - * If you add a "standard" global function or property, remember to update - * this table. - */ -typedef struct JSStdName { - JSObjectOp init; - size_t atomOffset; /* offset of atom pointer in JSAtomState */ - const char *name; /* null if atom is pre-pinned, else name */ -} JSStdName; - -static JSAtom * -StdNameToAtom(JSContext *cx, JSStdName *stdn) -{ - size_t offset; - JSAtom *atom; - const char *name; - - offset = stdn->atomOffset; - atom = OFFSET_TO_ATOM(cx->runtime, offset); - if (!atom) { - name = stdn->name; - if (name) { - atom = js_Atomize(cx, name, strlen(name), ATOM_PINNED); - OFFSET_TO_ATOM(cx->runtime, offset) = atom; - } - } - return atom; -} - -#define EAGERLY_PINNED_ATOM(name) ATOM_OFFSET(name), NULL -#define LAZILY_PINNED_ATOM(name) ATOM_OFFSET(lazy.name), js_##name##_str - -static JSStdName standard_class_names[] = { - /* ECMA requires that eval be a direct property of the global object. */ - {js_InitObjectClass, EAGERLY_PINNED_ATOM(eval)}, - - /* Global properties and functions defined by the Number class. */ - {js_InitNumberClass, LAZILY_PINNED_ATOM(NaN)}, - {js_InitNumberClass, LAZILY_PINNED_ATOM(Infinity)}, - {js_InitNumberClass, LAZILY_PINNED_ATOM(isNaN)}, - {js_InitNumberClass, LAZILY_PINNED_ATOM(isFinite)}, - {js_InitNumberClass, LAZILY_PINNED_ATOM(parseFloat)}, - {js_InitNumberClass, LAZILY_PINNED_ATOM(parseInt)}, - - /* String global functions. */ - {js_InitStringClass, LAZILY_PINNED_ATOM(escape)}, - {js_InitStringClass, LAZILY_PINNED_ATOM(unescape)}, - {js_InitStringClass, LAZILY_PINNED_ATOM(decodeURI)}, - {js_InitStringClass, LAZILY_PINNED_ATOM(encodeURI)}, - {js_InitStringClass, LAZILY_PINNED_ATOM(decodeURIComponent)}, - {js_InitStringClass, LAZILY_PINNED_ATOM(encodeURIComponent)}, -#if JS_HAS_UNEVAL - {js_InitStringClass, LAZILY_PINNED_ATOM(uneval)}, -#endif - - /* Exception constructors. */ -#if JS_HAS_ERROR_EXCEPTIONS - {js_InitExceptionClasses, EAGERLY_PINNED_ATOM(Error)}, - {js_InitExceptionClasses, LAZILY_PINNED_ATOM(InternalError)}, - {js_InitExceptionClasses, LAZILY_PINNED_ATOM(EvalError)}, - {js_InitExceptionClasses, LAZILY_PINNED_ATOM(RangeError)}, - {js_InitExceptionClasses, LAZILY_PINNED_ATOM(ReferenceError)}, - {js_InitExceptionClasses, LAZILY_PINNED_ATOM(SyntaxError)}, - {js_InitExceptionClasses, LAZILY_PINNED_ATOM(TypeError)}, - {js_InitExceptionClasses, LAZILY_PINNED_ATOM(URIError)}, -#endif - -#if JS_HAS_XML_SUPPORT - {js_InitAnyNameClass, LAZILY_PINNED_ATOM(AnyName)}, - {js_InitAttributeNameClass, LAZILY_PINNED_ATOM(AttributeName)}, - {js_InitXMLClass, LAZILY_PINNED_ATOM(XMLList)}, - {js_InitXMLClass, LAZILY_PINNED_ATOM(isXMLName)}, -#endif - - {NULL, 0, NULL} -}; - -static JSStdName object_prototype_names[] = { - /* Object.prototype properties (global delegates to Object.prototype). */ - {js_InitObjectClass, EAGERLY_PINNED_ATOM(proto)}, - {js_InitObjectClass, EAGERLY_PINNED_ATOM(parent)}, - {js_InitObjectClass, EAGERLY_PINNED_ATOM(count)}, -#if JS_HAS_TOSOURCE - {js_InitObjectClass, EAGERLY_PINNED_ATOM(toSource)}, -#endif - {js_InitObjectClass, EAGERLY_PINNED_ATOM(toString)}, - {js_InitObjectClass, EAGERLY_PINNED_ATOM(toLocaleString)}, - {js_InitObjectClass, EAGERLY_PINNED_ATOM(valueOf)}, -#if JS_HAS_OBJ_WATCHPOINT - {js_InitObjectClass, LAZILY_PINNED_ATOM(watch)}, - {js_InitObjectClass, LAZILY_PINNED_ATOM(unwatch)}, -#endif -#if JS_HAS_NEW_OBJ_METHODS - {js_InitObjectClass, LAZILY_PINNED_ATOM(hasOwnProperty)}, - {js_InitObjectClass, LAZILY_PINNED_ATOM(isPrototypeOf)}, - {js_InitObjectClass, LAZILY_PINNED_ATOM(propertyIsEnumerable)}, -#endif -#if JS_HAS_GETTER_SETTER - {js_InitObjectClass, LAZILY_PINNED_ATOM(defineGetter)}, - {js_InitObjectClass, LAZILY_PINNED_ATOM(defineSetter)}, - {js_InitObjectClass, LAZILY_PINNED_ATOM(lookupGetter)}, - {js_InitObjectClass, LAZILY_PINNED_ATOM(lookupSetter)}, -#endif - - {NULL, 0, NULL} -}; - -#undef EAGERLY_PINNED_ATOM -#undef LAZILY_PINNED_ATOM - -JS_PUBLIC_API(JSBool) -JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsval id, - JSBool *resolved) -{ - JSString *idstr; - JSRuntime *rt; - JSAtom *atom; - JSObjectOp init; - uintN i; - - CHECK_REQUEST(cx); - *resolved = JS_FALSE; - - if (!JSVAL_IS_STRING(id)) - return JS_TRUE; - idstr = JSVAL_TO_STRING(id); - rt = cx->runtime; - -#if JS_HAS_UNDEFINED - /* Check whether we're resolving 'undefined', and define it if so. */ - atom = rt->atomState.typeAtoms[JSTYPE_VOID]; - if (idstr == ATOM_TO_STRING(atom)) { - *resolved = JS_TRUE; - return OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID, - NULL, NULL, JSPROP_PERMANENT, NULL); - } -#endif - - /* Try for class constructors/prototypes named by well-known atoms. */ - init = NULL; - for (i = 0; standard_class_atoms[i].init; i++) { - atom = OFFSET_TO_ATOM(rt, standard_class_atoms[i].atomOffset); - if (idstr == ATOM_TO_STRING(atom)) { - init = standard_class_atoms[i].init; - break; - } - } - - if (!init) { - /* Try less frequently used top-level functions and constants. */ - for (i = 0; standard_class_names[i].init; i++) { - atom = StdNameToAtom(cx, &standard_class_names[i]); - if (!atom) - return JS_FALSE; - if (idstr == ATOM_TO_STRING(atom)) { - init = standard_class_names[i].init; - break; - } - } - - if (!init && !OBJ_GET_PROTO(cx, obj)) { - /* - * Try even less frequently used names delegated from the global - * object to Object.prototype, but only if the Object class hasn't - * yet been initialized. - */ - for (i = 0; object_prototype_names[i].init; i++) { - atom = StdNameToAtom(cx, &object_prototype_names[i]); - if (!atom) - return JS_FALSE; - if (idstr == ATOM_TO_STRING(atom)) { - init = standard_class_names[i].init; - break; - } - } - } - } - - if (init) { - if (!init(cx, obj)) - return JS_FALSE; - *resolved = JS_TRUE; - } - return JS_TRUE; -} - -static JSBool -AlreadyHasOwnProperty(JSObject *obj, JSAtom *atom) -{ - JS_ASSERT(OBJ_IS_NATIVE(obj)); - return SCOPE_GET_PROPERTY(OBJ_SCOPE(obj), ATOM_TO_JSID(atom)) != NULL; -} - -JS_PUBLIC_API(JSBool) -JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj) -{ - JSRuntime *rt; - JSAtom *atom; - uintN i; - - CHECK_REQUEST(cx); - rt = cx->runtime; - -#if JS_HAS_UNDEFINED - /* Check whether we need to bind 'undefined' and define it if so. */ - atom = rt->atomState.typeAtoms[JSTYPE_VOID]; - if (!AlreadyHasOwnProperty(obj, atom) && - !OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID, - NULL, NULL, JSPROP_PERMANENT, NULL)) { - return JS_FALSE; - } -#endif - - /* Initialize any classes that have not been resolved yet. */ - for (i = 0; standard_class_atoms[i].init; i++) { - atom = OFFSET_TO_ATOM(rt, standard_class_atoms[i].atomOffset); - if (!AlreadyHasOwnProperty(obj, atom) && - !standard_class_atoms[i].init(cx, obj)) { - return JS_FALSE; - } - } - - return JS_TRUE; -} - -static JSIdArray * -AddAtomToArray(JSContext *cx, JSAtom *atom, JSIdArray *ida, jsint *ip) -{ - jsint i, length; - - i = *ip; - length = ida->length; - if (i >= length) { - ida = js_SetIdArrayLength(cx, ida, JS_MAX(length * 2, 8)); - if (!ida) - return NULL; - JS_ASSERT(i < ida->length); - } - ida->vector[i] = ATOM_TO_JSID(atom); - *ip = i + 1; - return ida; -} - -static JSIdArray * -EnumerateIfResolved(JSContext *cx, JSObject *obj, JSAtom *atom, JSIdArray *ida, - jsint *ip, JSBool *foundp) -{ - *foundp = AlreadyHasOwnProperty(obj, atom); - if (*foundp) - ida = AddAtomToArray(cx, atom, ida, ip); - return ida; -} - -JS_PUBLIC_API(JSIdArray *) -JS_EnumerateResolvedStandardClasses(JSContext *cx, JSObject *obj, - JSIdArray *ida) -{ - JSRuntime *rt; - jsint i, j, k; - JSAtom *atom; - JSBool found; - JSObjectOp init; - - CHECK_REQUEST(cx); - rt = cx->runtime; - if (ida) { - i = ida->length; - } else { - ida = js_NewIdArray(cx, 8); - if (!ida) - return NULL; - i = 0; - } - -#if JS_HAS_UNDEFINED - /* Check whether 'undefined' has been resolved and enumerate it if so. */ - atom = rt->atomState.typeAtoms[JSTYPE_VOID]; - ida = EnumerateIfResolved(cx, obj, atom, ida, &i, &found); - if (!ida) - return NULL; -#endif - - /* Enumerate only classes that *have* been resolved. */ - for (j = 0; standard_class_atoms[j].init; j++) { - atom = OFFSET_TO_ATOM(rt, standard_class_atoms[j].atomOffset); - ida = EnumerateIfResolved(cx, obj, atom, ida, &i, &found); - if (!ida) - return NULL; - - if (found) { - init = standard_class_atoms[j].init; - - for (k = 0; standard_class_names[k].init; k++) { - if (standard_class_names[k].init == init) { - atom = StdNameToAtom(cx, &standard_class_names[k]); - ida = AddAtomToArray(cx, atom, ida, &i); - if (!ida) - return NULL; - } - } - - if (init == js_InitObjectClass) { - for (k = 0; object_prototype_names[k].init; k++) { - atom = StdNameToAtom(cx, &object_prototype_names[k]); - ida = AddAtomToArray(cx, atom, ida, &i); - if (!ida) - return NULL; - } - } - } - } - - /* Trim to exact length via js_SetIdArrayLength. */ - return js_SetIdArrayLength(cx, ida, i); -} - -#undef ATOM_OFFSET -#undef OFFSET_TO_ATOM - -JS_PUBLIC_API(JSObject *) -JS_GetScopeChain(JSContext *cx) -{ - return cx->fp ? cx->fp->scopeChain : NULL; -} - -JS_PUBLIC_API(void *) -JS_malloc(JSContext *cx, size_t nbytes) -{ - void *p; - - JS_ASSERT(nbytes != 0); - if (nbytes == 0) - nbytes = 1; - cx->runtime->gcMallocBytes += nbytes; - p = malloc(nbytes); - if (!p) - JS_ReportOutOfMemory(cx); - return p; -} - -JS_PUBLIC_API(void *) -JS_realloc(JSContext *cx, void *p, size_t nbytes) -{ - p = realloc(p, nbytes); - if (!p) - JS_ReportOutOfMemory(cx); - return p; -} - -JS_PUBLIC_API(void) -JS_free(JSContext *cx, void *p) -{ - if (p) - free(p); -} - -JS_PUBLIC_API(char *) -JS_strdup(JSContext *cx, const char *s) -{ - size_t n; - void *p; - - n = strlen(s) + 1; - p = JS_malloc(cx, n); - if (!p) - return NULL; - return (char *)memcpy(p, s, n); -} - -JS_PUBLIC_API(jsdouble *) -JS_NewDouble(JSContext *cx, jsdouble d) -{ - CHECK_REQUEST(cx); - return js_NewDouble(cx, d, 0); -} - -JS_PUBLIC_API(JSBool) -JS_NewDoubleValue(JSContext *cx, jsdouble d, jsval *rval) -{ - CHECK_REQUEST(cx); - return js_NewDoubleValue(cx, d, rval); -} - -JS_PUBLIC_API(JSBool) -JS_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval) -{ - CHECK_REQUEST(cx); - return js_NewNumberValue(cx, d, rval); -} - -#undef JS_AddRoot -JS_PUBLIC_API(JSBool) -JS_AddRoot(JSContext *cx, void *rp) -{ - CHECK_REQUEST(cx); - return js_AddRoot(cx, rp, NULL); -} - -JS_PUBLIC_API(JSBool) -JS_AddNamedRootRT(JSRuntime *rt, void *rp, const char *name) -{ - return js_AddRootRT(rt, rp, name); -} - -JS_PUBLIC_API(JSBool) -JS_RemoveRoot(JSContext *cx, void *rp) -{ - CHECK_REQUEST(cx); - return js_RemoveRoot(cx->runtime, rp); -} - -JS_PUBLIC_API(JSBool) -JS_RemoveRootRT(JSRuntime *rt, void *rp) -{ - return js_RemoveRoot(rt, rp); -} - -JS_PUBLIC_API(JSBool) -JS_AddNamedRoot(JSContext *cx, void *rp, const char *name) -{ - CHECK_REQUEST(cx); - return js_AddRoot(cx, rp, name); -} - -JS_PUBLIC_API(void) -JS_ClearNewbornRoots(JSContext *cx) -{ - uintN i; - - for (i = 0; i < GCX_NTYPES; i++) - cx->newborn[i] = NULL; - cx->lastAtom = NULL; - cx->lastInternalResult = JSVAL_NULL; -} - -JS_PUBLIC_API(JSBool) -JS_EnterLocalRootScope(JSContext *cx) -{ - CHECK_REQUEST(cx); - return js_EnterLocalRootScope(cx); -} - -JS_PUBLIC_API(void) -JS_LeaveLocalRootScope(JSContext *cx) -{ - CHECK_REQUEST(cx); - js_LeaveLocalRootScope(cx); -} - -JS_PUBLIC_API(void) -JS_ForgetLocalRoot(JSContext *cx, void *thing) -{ - CHECK_REQUEST(cx); - js_ForgetLocalRoot(cx, (jsval) thing); -} - -#include "jshash.h" /* Added by JSIFY */ - -#ifdef DEBUG - -typedef struct NamedRootDumpArgs { - void (*dump)(const char *name, void *rp, void *data); - void *data; -} NamedRootDumpArgs; - -JS_STATIC_DLL_CALLBACK(JSDHashOperator) -js_named_root_dumper(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number, - void *arg) -{ - NamedRootDumpArgs *args = (NamedRootDumpArgs *) arg; - JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr; - - if (rhe->name) - args->dump(rhe->name, rhe->root, args->data); - return JS_DHASH_NEXT; -} - -JS_PUBLIC_API(void) -JS_DumpNamedRoots(JSRuntime *rt, - void (*dump)(const char *name, void *rp, void *data), - void *data) -{ - NamedRootDumpArgs args; - - args.dump = dump; - args.data = data; - JS_DHashTableEnumerate(&rt->gcRootsHash, js_named_root_dumper, &args); -} - -#endif /* DEBUG */ - -typedef struct GCRootMapArgs { - JSGCRootMapFun map; - void *data; -} GCRootMapArgs; - -JS_STATIC_DLL_CALLBACK(JSDHashOperator) -js_gcroot_mapper(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number, - void *arg) -{ - GCRootMapArgs *args = (GCRootMapArgs *) arg; - JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr; - intN mapflags; - JSDHashOperator op; - - mapflags = args->map(rhe->root, rhe->name, args->data); - -#if JS_MAP_GCROOT_NEXT == JS_DHASH_NEXT && \ - JS_MAP_GCROOT_STOP == JS_DHASH_STOP && \ - JS_MAP_GCROOT_REMOVE == JS_DHASH_REMOVE - op = (JSDHashOperator)mapflags; -#else - op = JS_DHASH_NEXT; - if (mapflags & JS_MAP_GCROOT_STOP) - op |= JS_DHASH_STOP; - if (mapflags & JS_MAP_GCROOT_REMOVE) - op |= JS_DHASH_REMOVE; -#endif - - return op; -} - -JS_PUBLIC_API(uint32) -JS_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data) -{ - GCRootMapArgs args; - uint32 rv; - - args.map = map; - args.data = data; - JS_LOCK_GC(rt); - rv = JS_DHashTableEnumerate(&rt->gcRootsHash, js_gcroot_mapper, &args); - JS_UNLOCK_GC(rt); - return rv; -} - -JS_PUBLIC_API(JSBool) -JS_LockGCThing(JSContext *cx, void *thing) -{ - JSBool ok; - - CHECK_REQUEST(cx); - ok = js_LockGCThing(cx, thing); - if (!ok) - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_LOCK); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_LockGCThingRT(JSRuntime *rt, void *thing) -{ - return js_LockGCThingRT(rt, thing); -} - -JS_PUBLIC_API(JSBool) -JS_UnlockGCThing(JSContext *cx, void *thing) -{ - JSBool ok; - - CHECK_REQUEST(cx); - ok = js_UnlockGCThingRT(cx->runtime, thing); - if (!ok) - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_UNLOCK); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_UnlockGCThingRT(JSRuntime *rt, void *thing) -{ - return js_UnlockGCThingRT(rt, thing); -} - -JS_PUBLIC_API(void) -JS_MarkGCThing(JSContext *cx, void *thing, const char *name, void *arg) -{ - JS_ASSERT(cx->runtime->gcLevel > 0); -#ifdef JS_THREADSAFE - JS_ASSERT(cx->runtime->gcThread == js_CurrentThreadId()); -#endif - - GC_MARK(cx, thing, name, arg); -} - -JS_PUBLIC_API(void) -JS_GC(JSContext *cx) -{ - /* Don't nuke active arenas if executing or compiling. */ - if (cx->stackPool.current == &cx->stackPool.first) - JS_FinishArenaPool(&cx->stackPool); - if (cx->tempPool.current == &cx->tempPool.first) - JS_FinishArenaPool(&cx->tempPool); - js_ForceGC(cx, 0); -} - -JS_PUBLIC_API(void) -JS_MaybeGC(JSContext *cx) -{ -#ifdef WAY_TOO_MUCH_GC - JS_GC(cx); -#else - JSRuntime *rt; - uint32 bytes, lastBytes; - - rt = cx->runtime; - bytes = rt->gcBytes; - lastBytes = rt->gcLastBytes; - if ((bytes > 8192 && bytes > lastBytes + lastBytes / 2) || - rt->gcMallocBytes > rt->gcMaxMallocBytes) { - /* - * Run the GC if we have half again as many bytes of GC-things as - * the last time we GC'd, or if we have malloc'd more bytes through - * JS_malloc than we were told to allocate by JS_NewRuntime. - */ - JS_GC(cx); - } -#endif -} - -JS_PUBLIC_API(JSGCCallback) -JS_SetGCCallback(JSContext *cx, JSGCCallback cb) -{ - return JS_SetGCCallbackRT(cx->runtime, cb); -} - -JS_PUBLIC_API(JSGCCallback) -JS_SetGCCallbackRT(JSRuntime *rt, JSGCCallback cb) -{ - JSGCCallback oldcb; - - oldcb = rt->gcCallback; - rt->gcCallback = cb; - return oldcb; -} - -JS_PUBLIC_API(JSBool) -JS_IsAboutToBeFinalized(JSContext *cx, void *thing) -{ - JS_ASSERT(thing); - return js_IsAboutToBeFinalized(cx, thing); -} - -JS_PUBLIC_API(void) -JS_SetGCParameter(JSRuntime *rt, JSGCParamKey key, uint32 value) -{ - switch (key) { - case JSGC_MAX_BYTES: - rt->gcMaxBytes = value; - break; - case JSGC_MAX_MALLOC_BYTES: - rt->gcMaxMallocBytes = value; - break; - } -} - -JS_PUBLIC_API(intN) -JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer) -{ - return js_ChangeExternalStringFinalizer(NULL, finalizer); -} - -JS_PUBLIC_API(intN) -JS_RemoveExternalStringFinalizer(JSStringFinalizeOp finalizer) -{ - return js_ChangeExternalStringFinalizer(finalizer, NULL); -} - -JS_PUBLIC_API(JSString *) -JS_NewExternalString(JSContext *cx, jschar *chars, size_t length, intN type) -{ - JSString *str; - - CHECK_REQUEST(cx); - JS_ASSERT(GCX_EXTERNAL_STRING <= type && type < (intN) GCX_NTYPES); - - str = (JSString *) js_NewGCThing(cx, (uintN) type, sizeof(JSString)); - if (!str) - return NULL; - str->length = length; - str->chars = chars; - return str; -} - -JS_PUBLIC_API(intN) -JS_GetExternalStringGCType(JSRuntime *rt, JSString *str) -{ - uint8 type = (uint8) (*js_GetGCThingFlags(str) & GCF_TYPEMASK); - - if (type >= GCX_EXTERNAL_STRING) - return (intN)type; - JS_ASSERT(type == GCX_STRING || type == GCX_MUTABLE_STRING); - return -1; -} - -JS_PUBLIC_API(void) -JS_SetThreadStackLimit(JSContext *cx, jsuword limitAddr) -{ -#if JS_STACK_GROWTH_DIRECTION > 0 - if (limitAddr == 0) - limitAddr = (jsuword)-1; -#endif - cx->stackLimit = limitAddr; -} - -/************************************************************************/ - -JS_PUBLIC_API(void) -JS_DestroyIdArray(JSContext *cx, JSIdArray *ida) -{ - JS_free(cx, ida); -} - -JS_PUBLIC_API(JSBool) -JS_ValueToId(JSContext *cx, jsval v, jsid *idp) -{ - JSAtom *atom; - - CHECK_REQUEST(cx); - if (JSVAL_IS_INT(v)) { - *idp = v; - } else { - atom = js_ValueToStringAtom(cx, v); - if (!atom) - return JS_FALSE; - *idp = ATOM_TO_JSID(atom); - } - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_IdToValue(JSContext *cx, jsid id, jsval *vp) -{ - CHECK_REQUEST(cx); - *vp = ID_TO_VALUE(id); - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_PropertyStub(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_EnumerateStub(JSContext *cx, JSObject *obj) -{ - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_ResolveStub(JSContext *cx, JSObject *obj, jsval id) -{ - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_ConvertStub(JSContext *cx, JSObject *obj, JSType type, jsval *vp) -{ -#if JS_BUG_EAGER_TOSTRING - if (type == JSTYPE_STRING) - return JS_TRUE; -#endif - js_TryValueOf(cx, obj, type, vp); - return JS_TRUE; -} - -JS_PUBLIC_API(void) -JS_FinalizeStub(JSContext *cx, JSObject *obj) -{ -} - -JS_PUBLIC_API(JSObject *) -JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto, - JSClass *clasp, JSNative constructor, uintN nargs, - JSPropertySpec *ps, JSFunctionSpec *fs, - JSPropertySpec *static_ps, JSFunctionSpec *static_fs) -{ - JSAtom *atom; - JSObject *proto, *ctor; - JSTempValueRooter tvr; - jsval cval, rval; - JSBool named; - JSFunction *fun; - - CHECK_REQUEST(cx); - atom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0); - if (!atom) - return NULL; - - /* Create a prototype object for this class. */ - proto = js_NewObject(cx, clasp, parent_proto, obj); - if (!proto) - return NULL; - - /* After this point, control must exit via label bad or out. */ - JS_PUSH_SINGLE_TEMP_ROOT(cx, OBJECT_TO_JSVAL(proto), &tvr); - - if (!constructor) { - /* Lacking a constructor, name the prototype (e.g., Math). */ - named = OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), - OBJECT_TO_JSVAL(proto), - NULL, NULL, 0, NULL); - if (!named) - goto bad; - ctor = proto; - } else { - /* Define the constructor function in obj's scope. */ - fun = js_DefineFunction(cx, obj, atom, constructor, nargs, 0); - named = (fun != NULL); - if (!fun) - goto bad; - - /* - * Remember the class this function is a constructor for so that - * we know to create an object of this class when we call the - * constructor. - */ - fun->clasp = clasp; - - /* - * Optionally construct the prototype object, before the class has - * been fully initialized. Allow the ctor to replace proto with a - * different object, as is done for operator new -- and as at least - * XML support requires. - */ - ctor = fun->object; - if (clasp->flags & JSCLASS_CONSTRUCT_PROTOTYPE) { - cval = OBJECT_TO_JSVAL(ctor); - if (!js_InternalConstruct(cx, proto, cval, 0, NULL, &rval)) - goto bad; - if (!JSVAL_IS_PRIMITIVE(rval) && JSVAL_TO_OBJECT(rval) != proto) - proto = JSVAL_TO_OBJECT(rval); - } - - /* Connect constructor and prototype by named properties. */ - if (!js_SetClassPrototype(cx, ctor, proto, - JSPROP_READONLY | JSPROP_PERMANENT)) { - goto bad; - } - - /* Bootstrap Function.prototype (see also JS_InitStandardClasses). */ - if (OBJ_GET_CLASS(cx, ctor) == clasp) { - /* XXXMLM - this fails in framesets that are writing over - * themselves! - * JS_ASSERT(!OBJ_GET_PROTO(cx, ctor)); - */ - OBJ_SET_PROTO(cx, ctor, proto); - } - } - - /* Add properties and methods to the prototype and the constructor. */ - if ((ps && !JS_DefineProperties(cx, proto, ps)) || - (fs && !JS_DefineFunctions(cx, proto, fs)) || - (static_ps && !JS_DefineProperties(cx, ctor, static_ps)) || - (static_fs && !JS_DefineFunctions(cx, ctor, static_fs))) { - goto bad; - } - -out: - JS_POP_TEMP_ROOT(cx, &tvr); - return proto; - -bad: - if (named) - (void) OBJ_DELETE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &rval); - proto = NULL; - goto out; -} - -#ifdef JS_THREADSAFE -JS_PUBLIC_API(JSClass *) -JS_GetClass(JSContext *cx, JSObject *obj) -{ - return (JSClass *) - JSVAL_TO_PRIVATE(GC_AWARE_GET_SLOT(cx, obj, JSSLOT_CLASS)); -} -#else -JS_PUBLIC_API(JSClass *) -JS_GetClass(JSObject *obj) -{ - return LOCKED_OBJ_GET_CLASS(obj); -} -#endif - -JS_PUBLIC_API(JSBool) -JS_InstanceOf(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv) -{ - JSFunction *fun; - - CHECK_REQUEST(cx); - if (OBJ_GET_CLASS(cx, obj) == clasp) - return JS_TRUE; - if (argv) { - fun = js_ValueToFunction(cx, &argv[-2], 0); - if (fun) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_INCOMPATIBLE_PROTO, - clasp->name, JS_GetFunctionName(fun), - OBJ_GET_CLASS(cx, obj)->name); - } - } - return JS_FALSE; -} - -JS_PUBLIC_API(JSBool) -JS_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp) -{ - return js_HasInstance(cx, obj, v, bp); -} - -JS_PUBLIC_API(void *) -JS_GetPrivate(JSContext *cx, JSObject *obj) -{ - jsval v; - - JS_ASSERT(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_HAS_PRIVATE); - v = GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PRIVATE); - if (!JSVAL_IS_INT(v)) - return NULL; - return JSVAL_TO_PRIVATE(v); -} - -JS_PUBLIC_API(JSBool) -JS_SetPrivate(JSContext *cx, JSObject *obj, void *data) -{ - JS_ASSERT(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_HAS_PRIVATE); - OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(data)); - return JS_TRUE; -} - -JS_PUBLIC_API(void *) -JS_GetInstancePrivate(JSContext *cx, JSObject *obj, JSClass *clasp, - jsval *argv) -{ - if (!JS_InstanceOf(cx, obj, clasp, argv)) - return NULL; - return JS_GetPrivate(cx, obj); -} - -JS_PUBLIC_API(JSObject *) -JS_GetPrototype(JSContext *cx, JSObject *obj) -{ - JSObject *proto; - - CHECK_REQUEST(cx); - proto = JSVAL_TO_OBJECT(GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PROTO)); - - /* Beware ref to dead object (we may be called from obj's finalizer). */ - return proto && proto->map ? proto : NULL; -} - -JS_PUBLIC_API(JSBool) -JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto) -{ - CHECK_REQUEST(cx); - if (obj->map->ops->setProto) - return obj->map->ops->setProto(cx, obj, JSSLOT_PROTO, proto); - OBJ_SET_SLOT(cx, obj, JSSLOT_PROTO, OBJECT_TO_JSVAL(proto)); - return JS_TRUE; -} - -JS_PUBLIC_API(JSObject *) -JS_GetParent(JSContext *cx, JSObject *obj) -{ - JSObject *parent; - - parent = JSVAL_TO_OBJECT(GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PARENT)); - - /* Beware ref to dead object (we may be called from obj's finalizer). */ - return parent && parent->map ? parent : NULL; -} - -JS_PUBLIC_API(JSBool) -JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent) -{ - CHECK_REQUEST(cx); - if (obj->map->ops->setParent) - return obj->map->ops->setParent(cx, obj, JSSLOT_PARENT, parent); - OBJ_SET_SLOT(cx, obj, JSSLOT_PARENT, OBJECT_TO_JSVAL(parent)); - return JS_TRUE; -} - -JS_PUBLIC_API(JSObject *) -JS_GetConstructor(JSContext *cx, JSObject *proto) -{ - jsval cval; - - CHECK_REQUEST(cx); - if (!OBJ_GET_PROPERTY(cx, proto, - ATOM_TO_JSID(cx->runtime->atomState.constructorAtom), - &cval)) { - return NULL; - } - if (!JSVAL_IS_FUNCTION(cx, cval)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_CONSTRUCTOR, - OBJ_GET_CLASS(cx, proto)->name); - return NULL; - } - return JSVAL_TO_OBJECT(cval); -} - -JS_PUBLIC_API(JSBool) -JS_GetObjectId(JSContext *cx, JSObject *obj, jsid *idp) -{ - JS_ASSERT(((jsid)obj & JSID_TAGMASK) == 0); - *idp = OBJECT_TO_JSID(obj); - return JS_TRUE; -} - -JS_PUBLIC_API(JSObject *) -JS_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent) -{ - CHECK_REQUEST(cx); - if (!clasp) - clasp = &js_ObjectClass; /* default class is Object */ - return js_NewObject(cx, clasp, proto, parent); -} - -JS_PUBLIC_API(JSBool) -JS_SealObject(JSContext *cx, JSObject *obj, JSBool deep) -{ - JSScope *scope; - JSIdArray *ida; - uint32 nslots; - jsval v, *vp, *end; - - if (!OBJ_IS_NATIVE(obj)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_CANT_SEAL_OBJECT, - OBJ_GET_CLASS(cx, obj)->name); - return JS_FALSE; - } - - scope = OBJ_SCOPE(obj); - -#if defined JS_THREADSAFE && defined DEBUG - /* Insist on scope being used exclusively by cx's thread. */ - if (scope->ownercx != cx) { - JS_LOCK_OBJ(cx, obj); - JS_ASSERT(OBJ_SCOPE(obj) == scope); - JS_ASSERT(scope->ownercx == cx); - JS_UNLOCK_SCOPE(cx, scope); - } -#endif - - /* Nothing to do if obj's scope is already sealed. */ - if (SCOPE_IS_SEALED(scope)) - return JS_TRUE; - - /* XXX Enumerate lazy properties now, as they can't be added later. */ - ida = JS_Enumerate(cx, obj); - if (!ida) - return JS_FALSE; - JS_DestroyIdArray(cx, ida); - - /* Ensure that obj has its own, mutable scope, and seal that scope. */ - JS_LOCK_OBJ(cx, obj); - scope = js_GetMutableScope(cx, obj); - if (scope) - SCOPE_SET_SEALED(scope); - JS_UNLOCK_SCOPE(cx, scope); - if (!scope) - return JS_FALSE; - - /* If we are not sealing an entire object graph, we're done. */ - if (!deep) - return JS_TRUE; - - /* Walk obj->slots and if any value is a non-null object, seal it. */ - nslots = JS_MIN(scope->map.freeslot, scope->map.nslots); - for (vp = obj->slots, end = vp + nslots; vp < end; vp++) { - v = *vp; - if (JSVAL_IS_PRIMITIVE(v)) - continue; - if (!JS_SealObject(cx, JSVAL_TO_OBJECT(v), deep)) - return JS_FALSE; - } - return JS_TRUE; -} - -JS_PUBLIC_API(JSObject *) -JS_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto, - JSObject *parent) -{ - CHECK_REQUEST(cx); - if (!clasp) - clasp = &js_ObjectClass; /* default class is Object */ - return js_ConstructObject(cx, clasp, proto, parent, 0, NULL); -} - -JS_PUBLIC_API(JSObject *) -JS_ConstructObjectWithArguments(JSContext *cx, JSClass *clasp, JSObject *proto, - JSObject *parent, uintN argc, jsval *argv) -{ - CHECK_REQUEST(cx); - if (!clasp) - clasp = &js_ObjectClass; /* default class is Object */ - return js_ConstructObject(cx, clasp, proto, parent, argc, argv); -} - -static JSBool -DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value, - JSPropertyOp getter, JSPropertyOp setter, uintN attrs, - uintN flags, intN tinyid) -{ - jsid id; - JSAtom *atom; - - if (attrs & JSPROP_INDEX) { - id = INT_TO_JSID(JS_PTR_TO_INT32(name)); - atom = NULL; - attrs &= ~JSPROP_INDEX; - } else { - atom = js_Atomize(cx, name, strlen(name), 0); - if (!atom) - return JS_FALSE; - id = ATOM_TO_JSID(atom); - } - if (flags != 0 && OBJ_IS_NATIVE(obj)) { - return js_DefineNativeProperty(cx, obj, id, value, getter, setter, - attrs, flags, tinyid, NULL); - } - return OBJ_DEFINE_PROPERTY(cx, obj, id, value, getter, setter, attrs, - NULL); -} - -#define AUTO_NAMELEN(s,n) (((n) == (size_t)-1) ? js_strlen(s) : (n)) - -static JSBool -DefineUCProperty(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, jsval value, - JSPropertyOp getter, JSPropertyOp setter, uintN attrs, - uintN flags, intN tinyid) -{ - JSAtom *atom; - - atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0); - if (!atom) - return JS_FALSE; - if (flags != 0 && OBJ_IS_NATIVE(obj)) { - return js_DefineNativeProperty(cx, obj, ATOM_TO_JSID(atom), value, - getter, setter, attrs, flags, tinyid, - NULL); - } - return OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), value, - getter, setter, attrs, NULL); -} - -JS_PUBLIC_API(JSObject *) -JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *clasp, - JSObject *proto, uintN attrs) -{ - JSObject *nobj; - - CHECK_REQUEST(cx); - if (!clasp) - clasp = &js_ObjectClass; /* default class is Object */ - nobj = js_NewObject(cx, clasp, proto, obj); - if (!nobj) - return NULL; - if (!DefineProperty(cx, obj, name, OBJECT_TO_JSVAL(nobj), NULL, NULL, attrs, - 0, 0)) { - cx->newborn[GCX_OBJECT] = NULL; - return NULL; - } - return nobj; -} - -JS_PUBLIC_API(JSBool) -JS_DefineConstDoubles(JSContext *cx, JSObject *obj, JSConstDoubleSpec *cds) -{ - JSBool ok; - jsval value; - uintN flags; - - CHECK_REQUEST(cx); - for (ok = JS_TRUE; cds->name; cds++) { - ok = js_NewNumberValue(cx, cds->dval, &value); - if (!ok) - break; - flags = cds->flags; - if (!flags) - flags = JSPROP_READONLY | JSPROP_PERMANENT; - ok = DefineProperty(cx, obj, cds->name, value, NULL, NULL, flags, 0, 0); - if (!ok) - break; - } - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_DefineProperties(JSContext *cx, JSObject *obj, JSPropertySpec *ps) -{ - JSBool ok; - - CHECK_REQUEST(cx); - for (ok = JS_TRUE; ps->name; ps++) { - ok = DefineProperty(cx, obj, ps->name, JSVAL_VOID, - ps->getter, ps->setter, ps->flags, - SPROP_HAS_SHORTID, ps->tinyid); - if (!ok) - break; - } - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value, - JSPropertyOp getter, JSPropertyOp setter, uintN attrs) -{ - CHECK_REQUEST(cx); - return DefineProperty(cx, obj, name, value, getter, setter, attrs, 0, 0); -} - -JS_PUBLIC_API(JSBool) -JS_DefinePropertyWithTinyId(JSContext *cx, JSObject *obj, const char *name, - int8 tinyid, jsval value, - JSPropertyOp getter, JSPropertyOp setter, - uintN attrs) -{ - CHECK_REQUEST(cx); - return DefineProperty(cx, obj, name, value, getter, setter, attrs, - SPROP_HAS_SHORTID, tinyid); -} - -static JSBool -LookupProperty(JSContext *cx, JSObject *obj, const char *name, JSObject **objp, - JSProperty **propp) -{ - JSAtom *atom; - - atom = js_Atomize(cx, name, strlen(name), 0); - if (!atom) - return JS_FALSE; - return OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), objp, propp); -} - -static JSBool -LookupUCProperty(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, - JSObject **objp, JSProperty **propp) -{ - JSAtom *atom; - - atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0); - if (!atom) - return JS_FALSE; - return OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), objp, propp); -} - -JS_PUBLIC_API(JSBool) -JS_AliasProperty(JSContext *cx, JSObject *obj, const char *name, - const char *alias) -{ - JSObject *obj2; - JSProperty *prop; - JSAtom *atom; - JSBool ok; - JSScopeProperty *sprop; - - CHECK_REQUEST(cx); - if (!LookupProperty(cx, obj, name, &obj2, &prop)) - return JS_FALSE; - if (!prop) { - js_ReportIsNotDefined(cx, name); - return JS_FALSE; - } - if (obj2 != obj || !OBJ_IS_NATIVE(obj)) { - OBJ_DROP_PROPERTY(cx, obj2, prop); - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_ALIAS, - alias, name, OBJ_GET_CLASS(cx, obj2)->name); - return JS_FALSE; - } - atom = js_Atomize(cx, alias, strlen(alias), 0); - if (!atom) { - ok = JS_FALSE; - } else { - sprop = (JSScopeProperty *)prop; - ok = (js_AddNativeProperty(cx, obj, ATOM_TO_JSID(atom), - sprop->getter, sprop->setter, sprop->slot, - sprop->attrs, sprop->flags | SPROP_IS_ALIAS, - sprop->shortid) - != NULL); - } - OBJ_DROP_PROPERTY(cx, obj, prop); - return ok; -} - -static jsval -LookupResult(JSContext *cx, JSObject *obj, JSObject *obj2, JSProperty *prop) -{ - JSScopeProperty *sprop; - jsval rval; - - if (!prop) { - /* XXX bad API: no way to tell "not defined" from "void value" */ - return JSVAL_VOID; - } - if (OBJ_IS_NATIVE(obj2)) { - /* Peek at the native property's slot value, without doing a Get. */ - sprop = (JSScopeProperty *)prop; - rval = SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj2)) - ? LOCKED_OBJ_GET_SLOT(obj2, sprop->slot) - : JSVAL_TRUE; - } else { - /* XXX bad API: no way to return "defined but value unknown" */ - rval = JSVAL_TRUE; - } - OBJ_DROP_PROPERTY(cx, obj2, prop); - return rval; -} - -static JSBool -GetPropertyAttributes(JSContext *cx, JSObject *obj, JSAtom *atom, - uintN *attrsp, JSBool *foundp, - JSPropertyOp *getterp, JSPropertyOp *setterp) -{ - JSObject *obj2; - JSProperty *prop; - JSBool ok; - - if (!atom) - return JS_FALSE; - if (!OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &obj2, &prop)) - return JS_FALSE; - - if (!prop || obj != obj2) { - *attrsp = 0; - *foundp = JS_FALSE; - if (getterp) - *getterp = NULL; - if (setterp) - *setterp = NULL; - if (prop) - OBJ_DROP_PROPERTY(cx, obj2, prop); - return JS_TRUE; - } - - *foundp = JS_TRUE; - ok = OBJ_GET_ATTRIBUTES(cx, obj, ATOM_TO_JSID(atom), prop, attrsp); - if (ok && OBJ_IS_NATIVE(obj)) { - JSScopeProperty *sprop = (JSScopeProperty *) prop; - - if (getterp) - *getterp = sprop->getter; - if (setterp) - *setterp = sprop->setter; - } - OBJ_DROP_PROPERTY(cx, obj, prop); - return ok; -} - -static JSBool -SetPropertyAttributes(JSContext *cx, JSObject *obj, JSAtom *atom, - uintN attrs, JSBool *foundp) -{ - JSObject *obj2; - JSProperty *prop; - JSBool ok; - - if (!atom) - return JS_FALSE; - if (!OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &obj2, &prop)) - return JS_FALSE; - if (!prop || obj != obj2) { - *foundp = JS_FALSE; - if (prop) - OBJ_DROP_PROPERTY(cx, obj2, prop); - return JS_TRUE; - } - - *foundp = JS_TRUE; - ok = OBJ_SET_ATTRIBUTES(cx, obj, ATOM_TO_JSID(atom), prop, &attrs); - OBJ_DROP_PROPERTY(cx, obj, prop); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_GetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name, - uintN *attrsp, JSBool *foundp) -{ - CHECK_REQUEST(cx); - return GetPropertyAttributes(cx, obj, - js_Atomize(cx, name, strlen(name), 0), - attrsp, foundp, NULL, NULL); -} - -JS_PUBLIC_API(JSBool) -JS_GetPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj, - const char *name, - uintN *attrsp, JSBool *foundp, - JSPropertyOp *getterp, - JSPropertyOp *setterp) -{ - CHECK_REQUEST(cx); - return GetPropertyAttributes(cx, obj, - js_Atomize(cx, name, strlen(name), 0), - attrsp, foundp, getterp, setterp); -} - -JS_PUBLIC_API(JSBool) -JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name, - uintN attrs, JSBool *foundp) -{ - CHECK_REQUEST(cx); - return SetPropertyAttributes(cx, obj, - js_Atomize(cx, name, strlen(name), 0), - attrs, foundp); -} - -JS_PUBLIC_API(JSBool) -JS_HasProperty(JSContext *cx, JSObject *obj, const char *name, JSBool *foundp) -{ - JSBool ok; - JSObject *obj2; - JSProperty *prop; - - CHECK_REQUEST(cx); - ok = LookupProperty(cx, obj, name, &obj2, &prop); - if (ok) { - *foundp = (prop != NULL); - if (prop) - OBJ_DROP_PROPERTY(cx, obj2, prop); - } - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_LookupProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp) -{ - JSBool ok; - JSObject *obj2; - JSProperty *prop; - - CHECK_REQUEST(cx); - ok = LookupProperty(cx, obj, name, &obj2, &prop); - if (ok) - *vp = LookupResult(cx, obj, obj2, prop); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, const char *name, - uintN flags, jsval *vp) -{ - JSAtom *atom; - JSBool ok; - JSObject *obj2; - JSProperty *prop; - - CHECK_REQUEST(cx); - atom = js_Atomize(cx, name, strlen(name), 0); - if (!atom) - return JS_FALSE; - ok = OBJ_IS_NATIVE(obj) - ? js_LookupPropertyWithFlags(cx, obj, ATOM_TO_JSID(atom), flags, - &obj2, &prop) - : OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &obj2, &prop); - if (ok) - *vp = LookupResult(cx, obj, obj2, prop); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_GetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp) -{ - JSAtom *atom; - - CHECK_REQUEST(cx); - atom = js_Atomize(cx, name, strlen(name), 0); - if (!atom) - return JS_FALSE; - return OBJ_GET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp); -} - -JS_PUBLIC_API(JSBool) -JS_GetMethod(JSContext *cx, JSObject *obj, const char *name, JSObject **objp, - jsval *vp) -{ - JSAtom *atom; - jsid id; - - CHECK_REQUEST(cx); - atom = js_Atomize(cx, name, strlen(name), 0); - if (!atom) - return JS_FALSE; - id = ATOM_TO_JSID(atom); - -#if JS_HAS_XML_SUPPORT - if (OBJECT_IS_XML(cx, obj)) { - JSXMLObjectOps *ops; - - ops = (JSXMLObjectOps *) obj->map->ops; - obj = ops->getMethod(cx, obj, id, vp); - if (!obj) - return JS_FALSE; - } else -#endif - { - if (!OBJ_GET_PROPERTY(cx, obj, id, vp)) - return JS_FALSE; - } - - *objp = obj; - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_SetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp) -{ - JSAtom *atom; - - CHECK_REQUEST(cx); - atom = js_Atomize(cx, name, strlen(name), 0); - if (!atom) - return JS_FALSE; - return OBJ_SET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp); -} - -JS_PUBLIC_API(JSBool) -JS_DeleteProperty(JSContext *cx, JSObject *obj, const char *name) -{ - jsval junk; - - CHECK_REQUEST(cx); - return JS_DeleteProperty2(cx, obj, name, &junk); -} - -JS_PUBLIC_API(JSBool) -JS_DeleteProperty2(JSContext *cx, JSObject *obj, const char *name, - jsval *rval) -{ - JSAtom *atom; - - CHECK_REQUEST(cx); - atom = js_Atomize(cx, name, strlen(name), 0); - if (!atom) - return JS_FALSE; - return OBJ_DELETE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), rval); -} - -JS_PUBLIC_API(JSBool) -JS_DefineUCProperty(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, jsval value, - JSPropertyOp getter, JSPropertyOp setter, - uintN attrs) -{ - CHECK_REQUEST(cx); - return DefineUCProperty(cx, obj, name, namelen, value, getter, setter, - attrs, 0, 0); -} - -JS_PUBLIC_API(JSBool) -JS_GetUCPropertyAttributes(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, - uintN *attrsp, JSBool *foundp) -{ - CHECK_REQUEST(cx); - return GetPropertyAttributes(cx, obj, - js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0), - attrsp, foundp, NULL, NULL); -} - -JS_PUBLIC_API(JSBool) -JS_GetUCPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, - uintN *attrsp, JSBool *foundp, - JSPropertyOp *getterp, - JSPropertyOp *setterp) -{ - CHECK_REQUEST(cx); - return GetPropertyAttributes(cx, obj, - js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0), - attrsp, foundp, getterp, setterp); -} - -JS_PUBLIC_API(JSBool) -JS_SetUCPropertyAttributes(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, - uintN attrs, JSBool *foundp) -{ - CHECK_REQUEST(cx); - return SetPropertyAttributes(cx, obj, - js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0), - attrs, foundp); -} - -JS_PUBLIC_API(JSBool) -JS_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, - int8 tinyid, jsval value, - JSPropertyOp getter, JSPropertyOp setter, - uintN attrs) -{ - CHECK_REQUEST(cx); - return DefineUCProperty(cx, obj, name, namelen, value, getter, setter, - attrs, SPROP_HAS_SHORTID, tinyid); -} - -JS_PUBLIC_API(JSBool) -JS_HasUCProperty(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, - JSBool *vp) -{ - JSBool ok; - JSObject *obj2; - JSProperty *prop; - - CHECK_REQUEST(cx); - ok = LookupUCProperty(cx, obj, name, namelen, &obj2, &prop); - if (ok) { - *vp = (prop != NULL); - if (prop) - OBJ_DROP_PROPERTY(cx, obj2, prop); - } - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_LookupUCProperty(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, - jsval *vp) -{ - JSBool ok; - JSObject *obj2; - JSProperty *prop; - - CHECK_REQUEST(cx); - ok = LookupUCProperty(cx, obj, name, namelen, &obj2, &prop); - if (ok) - *vp = LookupResult(cx, obj, obj2, prop); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_GetUCProperty(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, - jsval *vp) -{ - JSAtom *atom; - - CHECK_REQUEST(cx); - atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0); - if (!atom) - return JS_FALSE; - return OBJ_GET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp); -} - -JS_PUBLIC_API(JSBool) -JS_SetUCProperty(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, - jsval *vp) -{ - JSAtom *atom; - - CHECK_REQUEST(cx); - atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0); - if (!atom) - return JS_FALSE; - return OBJ_SET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp); -} - -JS_PUBLIC_API(JSBool) -JS_DeleteUCProperty2(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, - jsval *rval) -{ - JSAtom *atom; - - CHECK_REQUEST(cx); - atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0); - if (!atom) - return JS_FALSE; - return OBJ_DELETE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), rval); -} - -JS_PUBLIC_API(JSObject *) -JS_NewArrayObject(JSContext *cx, jsint length, jsval *vector) -{ - CHECK_REQUEST(cx); - /* NB: jsuint cast does ToUint32. */ - return js_NewArrayObject(cx, (jsuint)length, vector); -} - -JS_PUBLIC_API(JSBool) -JS_IsArrayObject(JSContext *cx, JSObject *obj) -{ - return OBJ_GET_CLASS(cx, obj) == &js_ArrayClass; -} - -JS_PUBLIC_API(JSBool) -JS_GetArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp) -{ - CHECK_REQUEST(cx); - return js_GetLengthProperty(cx, obj, lengthp); -} - -JS_PUBLIC_API(JSBool) -JS_SetArrayLength(JSContext *cx, JSObject *obj, jsuint length) -{ - CHECK_REQUEST(cx); - return js_SetLengthProperty(cx, obj, length); -} - -JS_PUBLIC_API(JSBool) -JS_HasArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp) -{ - CHECK_REQUEST(cx); - return js_HasLengthProperty(cx, obj, lengthp); -} - -JS_PUBLIC_API(JSBool) -JS_DefineElement(JSContext *cx, JSObject *obj, jsint index, jsval value, - JSPropertyOp getter, JSPropertyOp setter, uintN attrs) -{ - CHECK_REQUEST(cx); - return OBJ_DEFINE_PROPERTY(cx, obj, INT_TO_JSID(index), value, - getter, setter, attrs, NULL); -} - -JS_PUBLIC_API(JSBool) -JS_AliasElement(JSContext *cx, JSObject *obj, const char *name, jsint alias) -{ - JSObject *obj2; - JSProperty *prop; - JSScopeProperty *sprop; - JSBool ok; - - CHECK_REQUEST(cx); - if (!LookupProperty(cx, obj, name, &obj2, &prop)) - return JS_FALSE; - if (!prop) { - js_ReportIsNotDefined(cx, name); - return JS_FALSE; - } - if (obj2 != obj || !OBJ_IS_NATIVE(obj)) { - char numBuf[12]; - OBJ_DROP_PROPERTY(cx, obj2, prop); - JS_snprintf(numBuf, sizeof numBuf, "%ld", (long)alias); - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_ALIAS, - numBuf, name, OBJ_GET_CLASS(cx, obj2)->name); - return JS_FALSE; - } - sprop = (JSScopeProperty *)prop; - ok = (js_AddNativeProperty(cx, obj, INT_TO_JSID(alias), - sprop->getter, sprop->setter, sprop->slot, - sprop->attrs, sprop->flags | SPROP_IS_ALIAS, - sprop->shortid) - != NULL); - OBJ_DROP_PROPERTY(cx, obj, prop); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_HasElement(JSContext *cx, JSObject *obj, jsint index, JSBool *foundp) -{ - JSBool ok; - JSObject *obj2; - JSProperty *prop; - - CHECK_REQUEST(cx); - ok = OBJ_LOOKUP_PROPERTY(cx, obj, INT_TO_JSID(index), &obj2, &prop); - if (ok) { - *foundp = (prop != NULL); - if (prop) - OBJ_DROP_PROPERTY(cx, obj2, prop); - } - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_LookupElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp) -{ - JSBool ok; - JSObject *obj2; - JSProperty *prop; - - CHECK_REQUEST(cx); - ok = OBJ_LOOKUP_PROPERTY(cx, obj, INT_TO_JSID(index), &obj2, &prop); - if (ok) - *vp = LookupResult(cx, obj, obj2, prop); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_GetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp) -{ - CHECK_REQUEST(cx); - return OBJ_GET_PROPERTY(cx, obj, INT_TO_JSID(index), vp); -} - -JS_PUBLIC_API(JSBool) -JS_SetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp) -{ - CHECK_REQUEST(cx); - return OBJ_SET_PROPERTY(cx, obj, INT_TO_JSID(index), vp); -} - -JS_PUBLIC_API(JSBool) -JS_DeleteElement(JSContext *cx, JSObject *obj, jsint index) -{ - jsval junk; - - CHECK_REQUEST(cx); - return JS_DeleteElement2(cx, obj, index, &junk); -} - -JS_PUBLIC_API(JSBool) -JS_DeleteElement2(JSContext *cx, JSObject *obj, jsint index, jsval *rval) -{ - CHECK_REQUEST(cx); - return OBJ_DELETE_PROPERTY(cx, obj, INT_TO_JSID(index), rval); -} - -JS_PUBLIC_API(void) -JS_ClearScope(JSContext *cx, JSObject *obj) -{ - CHECK_REQUEST(cx); - - if (obj->map->ops->clear) - obj->map->ops->clear(cx, obj); -} - -JS_PUBLIC_API(JSIdArray *) -JS_Enumerate(JSContext *cx, JSObject *obj) -{ - jsint i, n; - jsval iter_state, num_properties; - jsid id; - JSIdArray *ida; - jsval *vector; - - CHECK_REQUEST(cx); - - ida = NULL; - iter_state = JSVAL_NULL; - - /* Get the number of properties to enumerate. */ - if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &iter_state, &num_properties)) - goto error; - if (!JSVAL_IS_INT(num_properties)) { - JS_ASSERT(0); - goto error; - } - - /* Grow as needed if we don't know the exact amount ahead of time. */ - n = JSVAL_TO_INT(num_properties); - if (n <= 0) - n = 8; - - /* Create an array of jsids large enough to hold all the properties */ - ida = js_NewIdArray(cx, n); - if (!ida) - goto error; - - i = 0; - vector = &ida->vector[0]; - for (;;) { - if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_NEXT, &iter_state, &id)) - goto error; - - /* No more jsid's to enumerate ? */ - if (iter_state == JSVAL_NULL) - break; - - if (i == ida->length) { - ida = js_SetIdArrayLength(cx, ida, ida->length * 2); - if (!ida) - goto error; - vector = &ida->vector[0]; - } - vector[i++] = id; - } - return js_SetIdArrayLength(cx, ida, i); - -error: - if (iter_state != JSVAL_NULL) - OBJ_ENUMERATE(cx, obj, JSENUMERATE_DESTROY, &iter_state, 0); - if (ida) - JS_DestroyIdArray(cx, ida); - return NULL; -} - -/* - * XXX reverse iterator for properties, unreverse and meld with jsinterp.c's - * prop_iterator_class somehow... - * + preserve the OBJ_ENUMERATE API while optimizing the native object case - * + native case here uses a JSScopeProperty *, but that iterates in reverse! - * + so we make non-native match, by reverse-iterating after JS_Enumerating - */ -#define JSSLOT_ITER_INDEX (JSSLOT_PRIVATE + 1) - -#if JSSLOT_ITER_INDEX >= JS_INITIAL_NSLOTS -# error "JSSLOT_ITER_INDEX botch!" -#endif - -static void -prop_iter_finalize(JSContext *cx, JSObject *obj) -{ - jsval v; - jsint i; - JSIdArray *ida; - - v = GC_AWARE_GET_SLOT(cx, obj, JSSLOT_ITER_INDEX); - if (JSVAL_IS_VOID(v)) - return; - - i = JSVAL_TO_INT(v); - if (i >= 0) { - /* Non-native case: destroy the ida enumerated when obj was created. */ - ida = (JSIdArray *) JS_GetPrivate(cx, obj); - if (ida) - JS_DestroyIdArray(cx, ida); - } -} - -static uint32 -prop_iter_mark(JSContext *cx, JSObject *obj, void *arg) -{ - jsval v; - jsint i, n; - JSScopeProperty *sprop; - JSIdArray *ida; - jsid id; - - v = GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PRIVATE); - JS_ASSERT(!JSVAL_IS_VOID(v)); - - i = JSVAL_TO_INT(OBJ_GET_SLOT(cx, obj, JSSLOT_ITER_INDEX)); - if (i < 0) { - /* Native case: just mark the next property to visit. */ - sprop = (JSScopeProperty *) JSVAL_TO_PRIVATE(v); - if (sprop) - MARK_SCOPE_PROPERTY(sprop); - } else { - /* Non-native case: mark each id in the JSIdArray private. */ - ida = (JSIdArray *) JSVAL_TO_PRIVATE(v); - for (i = 0, n = ida->length; i < n; i++) { - id = ida->vector[i]; - if (JSID_IS_ATOM(id)) - GC_MARK_ATOM(cx, JSID_TO_ATOM(id), arg); - else if (JSID_IS_OBJECT(id)) - GC_MARK(cx, JSID_TO_OBJECT(id), "id", arg); - } - } - return 0; -} - -static JSClass prop_iter_class = { - "PropertyIterator", - JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1), - JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, prop_iter_finalize, - NULL, NULL, NULL, NULL, - NULL, NULL, prop_iter_mark, NULL -}; - -JS_PUBLIC_API(JSObject *) -JS_NewPropertyIterator(JSContext *cx, JSObject *obj) -{ - JSObject *iterobj; - JSScope *scope; - void *pdata; - jsint index; - JSIdArray *ida; - - CHECK_REQUEST(cx); - iterobj = js_NewObject(cx, &prop_iter_class, NULL, obj); - if (!iterobj) - return NULL; - - if (OBJ_IS_NATIVE(obj)) { - /* Native case: start with the last property in obj's own scope. */ - scope = OBJ_SCOPE(obj); - pdata = (scope->object == obj) ? scope->lastProp : NULL; - index = -1; - } else { - JSTempValueRooter tvr; - - /* - * Non-native case: enumerate a JSIdArray and keep it via private. - * - * Note: we have to make sure that we root obj around the call to - * JS_Enumerate to protect against multiple allocations under it. - */ - JS_PUSH_SINGLE_TEMP_ROOT(cx, OBJECT_TO_JSVAL(iterobj), &tvr); - ida = JS_Enumerate(cx, obj); - JS_POP_TEMP_ROOT(cx, &tvr); - if (!ida) - goto bad; - pdata = ida; - index = ida->length; - } - - /* iterobj can not escape to other threads here. */ - iterobj->slots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(pdata); - iterobj->slots[JSSLOT_ITER_INDEX] = INT_TO_JSVAL(index); - return iterobj; - -bad: - cx->newborn[GCX_OBJECT] = NULL; - return NULL; -} - -JS_PUBLIC_API(JSBool) -JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp) -{ - jsint i; - JSObject *obj; - JSScope *scope; - JSScopeProperty *sprop; - JSIdArray *ida; - - CHECK_REQUEST(cx); - i = JSVAL_TO_INT(OBJ_GET_SLOT(cx, iterobj, JSSLOT_ITER_INDEX)); - if (i < 0) { - /* Native case: private data is a property tree node pointer. */ - obj = OBJ_GET_PARENT(cx, iterobj); - JS_ASSERT(OBJ_IS_NATIVE(obj)); - scope = OBJ_SCOPE(obj); - JS_ASSERT(scope->object == obj); - sprop = (JSScopeProperty *) JS_GetPrivate(cx, iterobj); - - /* - * If the next property mapped by scope in the property tree ancestor - * line is not enumerable, or it's an alias, or one or more properties - * were deleted from the "middle" of the scope-mapped ancestor line - * and the next property was among those deleted, skip it and keep on - * trying to find an enumerable property that is still in scope. - */ - while (sprop && - (!(sprop->attrs & JSPROP_ENUMERATE) || - (sprop->flags & SPROP_IS_ALIAS) || - (SCOPE_HAD_MIDDLE_DELETE(scope) && - !SCOPE_HAS_PROPERTY(scope, sprop)))) { - sprop = sprop->parent; - } - - if (!sprop) { - *idp = JSVAL_VOID; - } else { - if (!JS_SetPrivate(cx, iterobj, sprop->parent)) - return JS_FALSE; - *idp = sprop->id; - } - } else { - /* Non-native case: use the ida enumerated when iterobj was created. */ - ida = (JSIdArray *) JS_GetPrivate(cx, iterobj); - JS_ASSERT(i <= ida->length); - if (i == 0) { - *idp = JSVAL_VOID; - } else { - *idp = ida->vector[--i]; - OBJ_SET_SLOT(cx, iterobj, JSSLOT_ITER_INDEX, INT_TO_JSVAL(i)); - } - } - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode, - jsval *vp, uintN *attrsp) -{ - CHECK_REQUEST(cx); - return OBJ_CHECK_ACCESS(cx, obj, id, mode, vp, attrsp); -} - -JS_PUBLIC_API(JSCheckAccessOp) -JS_SetCheckObjectAccessCallback(JSRuntime *rt, JSCheckAccessOp acb) -{ - JSCheckAccessOp oldacb; - - oldacb = rt->checkObjectAccess; - rt->checkObjectAccess = acb; - return oldacb; -} - -static JSBool -ReservedSlotIndexOK(JSContext *cx, JSObject *obj, JSClass *clasp, - uint32 index, uint32 limit) -{ - /* Check the computed, possibly per-instance, upper bound. */ - if (clasp->reserveSlots) - JS_LOCK_OBJ_VOID(cx, obj, limit += clasp->reserveSlots(cx, obj)); - if (index >= limit) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_RESERVED_SLOT_RANGE); - return JS_FALSE; - } - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval *vp) -{ - JSClass *clasp; - uint32 limit, slot; - - CHECK_REQUEST(cx); - clasp = OBJ_GET_CLASS(cx, obj); - limit = JSCLASS_RESERVED_SLOTS(clasp); - if (index >= limit && !ReservedSlotIndexOK(cx, obj, clasp, index, limit)) - return JS_FALSE; - slot = JSSLOT_START(clasp) + index; - *vp = OBJ_GET_REQUIRED_SLOT(cx, obj, slot); - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval v) -{ - JSClass *clasp; - uint32 limit, slot; - - CHECK_REQUEST(cx); - clasp = OBJ_GET_CLASS(cx, obj); - limit = JSCLASS_RESERVED_SLOTS(clasp); - if (index >= limit && !ReservedSlotIndexOK(cx, obj, clasp, index, limit)) - return JS_FALSE; - slot = JSSLOT_START(clasp) + index; - return OBJ_SET_REQUIRED_SLOT(cx, obj, slot, v); -} - -#ifdef JS_THREADSAFE -JS_PUBLIC_API(jsrefcount) -JS_HoldPrincipals(JSContext *cx, JSPrincipals *principals) -{ - return JS_ATOMIC_INCREMENT(&principals->refcount); -} - -JS_PUBLIC_API(jsrefcount) -JS_DropPrincipals(JSContext *cx, JSPrincipals *principals) -{ - jsrefcount rc = JS_ATOMIC_DECREMENT(&principals->refcount); - if (rc == 0) - principals->destroy(cx, principals); - return rc; -} -#endif - -JS_PUBLIC_API(JSPrincipalsTranscoder) -JS_SetPrincipalsTranscoder(JSRuntime *rt, JSPrincipalsTranscoder px) -{ - JSPrincipalsTranscoder oldpx; - - oldpx = rt->principalsTranscoder; - rt->principalsTranscoder = px; - return oldpx; -} - -JS_PUBLIC_API(JSObjectPrincipalsFinder) -JS_SetObjectPrincipalsFinder(JSRuntime *rt, JSObjectPrincipalsFinder fop) -{ - JSObjectPrincipalsFinder oldfop; - - oldfop = rt->findObjectPrincipals; - rt->findObjectPrincipals = fop; - return oldfop; -} - -JS_PUBLIC_API(JSFunction *) -JS_NewFunction(JSContext *cx, JSNative native, uintN nargs, uintN flags, - JSObject *parent, const char *name) -{ - JSAtom *atom; - - CHECK_REQUEST(cx); - - if (!name) { - atom = NULL; - } else { - atom = js_Atomize(cx, name, strlen(name), 0); - if (!atom) - return NULL; - } - return js_NewFunction(cx, NULL, native, nargs, flags, parent, atom); -} - -JS_PUBLIC_API(JSObject *) -JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent) -{ - CHECK_REQUEST(cx); - if (OBJ_GET_CLASS(cx, funobj) != &js_FunctionClass) { - /* Indicate we cannot clone this object. */ - return funobj; - } - return js_CloneFunctionObject(cx, funobj, parent); -} - -JS_PUBLIC_API(JSObject *) -JS_GetFunctionObject(JSFunction *fun) -{ - return fun->object; -} - -JS_PUBLIC_API(const char *) -JS_GetFunctionName(JSFunction *fun) -{ - return fun->atom - ? JS_GetStringBytes(ATOM_TO_STRING(fun->atom)) - : js_anonymous_str; -} - -JS_PUBLIC_API(JSString *) -JS_GetFunctionId(JSFunction *fun) -{ - return fun->atom ? ATOM_TO_STRING(fun->atom) : NULL; -} - -JS_PUBLIC_API(uintN) -JS_GetFunctionFlags(JSFunction *fun) -{ - return fun->flags; -} - -JS_PUBLIC_API(uint16) -JS_GetFunctionArity(JSFunction *fun) -{ - return fun->nargs; -} - -JS_PUBLIC_API(JSBool) -JS_ObjectIsFunction(JSContext *cx, JSObject *obj) -{ - return OBJ_GET_CLASS(cx, obj) == &js_FunctionClass; -} - -JS_STATIC_DLL_CALLBACK(JSBool) -js_generic_native_method_dispatcher(JSContext *cx, JSObject *obj, - uintN argc, jsval *argv, jsval *rval) -{ - jsval fsv; - JSFunctionSpec *fs; - JSObject *tmp; - - if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(argv[-2]), 0, &fsv)) - return JS_FALSE; - fs = (JSFunctionSpec *) JSVAL_TO_PRIVATE(fsv); - - /* - * We know that argv[0] is valid because JS_DefineFunctions, which is our - * only (indirect) referrer, defined us as requiring at least one argument - * (notice how it passes fs->nargs + 1 as the next-to-last argument to - * JS_DefineFunction). - */ - if (JSVAL_IS_PRIMITIVE(argv[0])) { - /* - * Make sure that this is an object or null, as required by the generic - * functions. - */ - if (!js_ValueToObject(cx, argv[0], &tmp)) - return JS_FALSE; - argv[0] = OBJECT_TO_JSVAL(tmp); - } - - /* - * Copy all actual (argc) and required but missing (fs->nargs + 1 - argc) - * args down over our |this| parameter, argv[-1], which is almost always - * the class constructor object, e.g. Array. Then call the corresponding - * prototype native method with our first argument passed as |this|. - */ - memmove(argv - 1, argv, JS_MAX(fs->nargs + 1U, argc) * sizeof(jsval)); - - /* - * Follow Function.prototype.apply and .call by using the global object as - * the 'this' param if no args. - */ - JS_ASSERT(cx->fp->argv == argv); - if (!js_ComputeThis(cx, JSVAL_TO_OBJECT(argv[-1]), cx->fp)) - return JS_FALSE; - - /* - * Protect against argc - 1 underflowing below. By calling js_ComputeThis, - * we made it as if the static was called with one parameter. - */ - if (argc == 0) - argc = 1; - - return fs->call(cx, JSVAL_TO_OBJECT(argv[-1]), argc - 1, argv, rval); -} - -JS_PUBLIC_API(JSBool) -JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs) -{ - uintN flags; - JSObject *ctor; - JSFunction *fun; - - CHECK_REQUEST(cx); - ctor = NULL; - for (; fs->name; fs++) { - flags = fs->flags; - - /* - * Define a generic arity N+1 static method for the arity N prototype - * method if flags contains JSFUN_GENERIC_NATIVE. - */ - if (flags & JSFUN_GENERIC_NATIVE) { - if (!ctor) { - ctor = JS_GetConstructor(cx, obj); - if (!ctor) - return JS_FALSE; - } - - flags &= ~JSFUN_GENERIC_NATIVE; - fun = JS_DefineFunction(cx, ctor, fs->name, - js_generic_native_method_dispatcher, - fs->nargs + 1, flags); - if (!fun) - return JS_FALSE; - fun->extra = fs->extra; - - /* - * As jsapi.h notes, fs must point to storage that lives as long - * as fun->object lives. - */ - if (!JS_SetReservedSlot(cx, fun->object, 0, PRIVATE_TO_JSVAL(fs))) - return JS_FALSE; - } - - fun = JS_DefineFunction(cx, obj, fs->name, fs->call, fs->nargs, flags); - if (!fun) - return JS_FALSE; - fun->extra = fs->extra; - } - return JS_TRUE; -} - -JS_PUBLIC_API(JSFunction *) -JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call, - uintN nargs, uintN attrs) -{ - JSAtom *atom; - - CHECK_REQUEST(cx); - atom = js_Atomize(cx, name, strlen(name), 0); - if (!atom) - return NULL; - return js_DefineFunction(cx, obj, atom, call, nargs, attrs); -} - -JS_PUBLIC_API(JSFunction *) -JS_DefineUCFunction(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, JSNative call, - uintN nargs, uintN attrs) -{ - JSAtom *atom; - - atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0); - if (!atom) - return NULL; - return js_DefineFunction(cx, obj, atom, call, nargs, attrs); -} - -static JSScript * -CompileTokenStream(JSContext *cx, JSObject *obj, JSTokenStream *ts, - void *tempMark, JSBool *eofp) -{ - JSBool eof; - JSArenaPool codePool, notePool; - JSCodeGenerator cg; - JSScript *script; - - CHECK_REQUEST(cx); - eof = JS_FALSE; - JS_InitArenaPool(&codePool, "code", 1024, sizeof(jsbytecode)); - JS_InitArenaPool(¬ePool, "note", 1024, sizeof(jssrcnote)); - if (!js_InitCodeGenerator(cx, &cg, &codePool, ¬ePool, - ts->filename, ts->lineno, - ts->principals)) { - script = NULL; - } else if (!js_CompileTokenStream(cx, obj, ts, &cg)) { - script = NULL; - eof = (ts->flags & TSF_EOF) != 0; - } else { - script = js_NewScriptFromCG(cx, &cg, NULL); - } - if (eofp) - *eofp = eof; - if (!js_CloseTokenStream(cx, ts)) { - if (script) - js_DestroyScript(cx, script); - script = NULL; - } - cg.tempMark = tempMark; - js_FinishCodeGenerator(cx, &cg); - JS_FinishArenaPool(&codePool); - JS_FinishArenaPool(¬ePool); - return script; -} - -JS_PUBLIC_API(JSScript *) -JS_CompileScript(JSContext *cx, JSObject *obj, - const char *bytes, size_t length, - const char *filename, uintN lineno) -{ - jschar *chars; - JSScript *script; - - CHECK_REQUEST(cx); - chars = js_InflateString(cx, bytes, &length); - if (!chars) - return NULL; - script = JS_CompileUCScript(cx, obj, chars, length, filename, lineno); - JS_free(cx, chars); - return script; -} - -JS_PUBLIC_API(JSScript *) -JS_CompileScriptForPrincipals(JSContext *cx, JSObject *obj, - JSPrincipals *principals, - const char *bytes, size_t length, - const char *filename, uintN lineno) -{ - jschar *chars; - JSScript *script; - - CHECK_REQUEST(cx); - chars = js_InflateString(cx, bytes, &length); - if (!chars) - return NULL; - script = JS_CompileUCScriptForPrincipals(cx, obj, principals, - chars, length, filename, lineno); - JS_free(cx, chars); - return script; -} - -JS_PUBLIC_API(JSScript *) -JS_CompileUCScript(JSContext *cx, JSObject *obj, - const jschar *chars, size_t length, - const char *filename, uintN lineno) -{ - CHECK_REQUEST(cx); - return JS_CompileUCScriptForPrincipals(cx, obj, NULL, chars, length, - filename, lineno); -} - -#if JS_HAS_EXCEPTIONS -# define LAST_FRAME_EXCEPTION_CHECK(cx,result) \ - JS_BEGIN_MACRO \ - if (!(result)) \ - js_ReportUncaughtException(cx); \ - JS_END_MACRO -#else -# define LAST_FRAME_EXCEPTION_CHECK(cx,result) /* nothing */ -#endif - -#define LAST_FRAME_CHECKS(cx,result) \ - JS_BEGIN_MACRO \ - if (!(cx)->fp) { \ - (cx)->lastInternalResult = JSVAL_NULL; \ - LAST_FRAME_EXCEPTION_CHECK(cx, result); \ - } \ - JS_END_MACRO - -JS_PUBLIC_API(JSScript *) -JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *obj, - JSPrincipals *principals, - const jschar *chars, size_t length, - const char *filename, uintN lineno) -{ - void *mark; - JSTokenStream *ts; - JSScript *script; - - CHECK_REQUEST(cx); - mark = JS_ARENA_MARK(&cx->tempPool); - ts = js_NewTokenStream(cx, chars, length, filename, lineno, principals); - if (!ts) - return NULL; - script = CompileTokenStream(cx, obj, ts, mark, NULL); - LAST_FRAME_CHECKS(cx, script); - return script; -} - -JS_PUBLIC_API(JSBool) -JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj, - const char *bytes, size_t length) -{ - jschar *chars; - JSBool result; - JSExceptionState *exnState; - void *tempMark; - JSTokenStream *ts; - JSErrorReporter older; - - CHECK_REQUEST(cx); - chars = js_InflateString(cx, bytes, &length); - if (!chars) - return JS_TRUE; - - /* - * Return true on any out-of-memory error, so our caller doesn't try to - * collect more buffered source. - */ - result = JS_TRUE; - exnState = JS_SaveExceptionState(cx); - tempMark = JS_ARENA_MARK(&cx->tempPool); - ts = js_NewTokenStream(cx, chars, length, NULL, 0, NULL); - if (ts) { - older = JS_SetErrorReporter(cx, NULL); - if (!js_ParseTokenStream(cx, obj, ts) && - (ts->flags & TSF_UNEXPECTED_EOF)) { - /* - * We ran into an error. If it was because we ran out of source, - * we return false, so our caller will know to try to collect more - * buffered source. - */ - result = JS_FALSE; - } - - JS_SetErrorReporter(cx, older); - js_CloseTokenStream(cx, ts); - JS_ARENA_RELEASE(&cx->tempPool, tempMark); - } - - JS_free(cx, chars); - JS_RestoreExceptionState(cx, exnState); - return result; -} - -JS_PUBLIC_API(JSScript *) -JS_CompileFile(JSContext *cx, JSObject *obj, const char *filename) -{ - void *mark; - JSTokenStream *ts; - JSScript *script; - - CHECK_REQUEST(cx); - mark = JS_ARENA_MARK(&cx->tempPool); - ts = js_NewFileTokenStream(cx, filename, stdin); - if (!ts) - return NULL; - script = CompileTokenStream(cx, obj, ts, mark, NULL); - LAST_FRAME_CHECKS(cx, script); - return script; -} - -JS_PUBLIC_API(JSScript *) -JS_CompileFileHandle(JSContext *cx, JSObject *obj, const char *filename, - FILE *file) -{ - return JS_CompileFileHandleForPrincipals(cx, obj, filename, file, NULL); -} - -JS_PUBLIC_API(JSScript *) -JS_CompileFileHandleForPrincipals(JSContext *cx, JSObject *obj, - const char *filename, FILE *file, - JSPrincipals *principals) -{ - void *mark; - JSTokenStream *ts; - JSScript *script; - - CHECK_REQUEST(cx); - mark = JS_ARENA_MARK(&cx->tempPool); - ts = js_NewFileTokenStream(cx, NULL, file); - if (!ts) - return NULL; - ts->filename = filename; - /* XXXshaver js_NewFileTokenStream should do this, because it drops */ - if (principals) { - ts->principals = principals; - JSPRINCIPALS_HOLD(cx, ts->principals); - } - script = CompileTokenStream(cx, obj, ts, mark, NULL); - LAST_FRAME_CHECKS(cx, script); - return script; -} - -JS_PUBLIC_API(JSObject *) -JS_NewScriptObject(JSContext *cx, JSScript *script) -{ - JSObject *obj; - - obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL); - if (!obj) - return NULL; - - if (script) { - if (!JS_SetPrivate(cx, obj, script)) - return NULL; - script->object = obj; - } - return obj; -} - -JS_PUBLIC_API(JSObject *) -JS_GetScriptObject(JSScript *script) -{ - return script->object; -} - -JS_PUBLIC_API(void) -JS_DestroyScript(JSContext *cx, JSScript *script) -{ - CHECK_REQUEST(cx); - js_DestroyScript(cx, script); -} - -JS_PUBLIC_API(JSFunction *) -JS_CompileFunction(JSContext *cx, JSObject *obj, const char *name, - uintN nargs, const char **argnames, - const char *bytes, size_t length, - const char *filename, uintN lineno) -{ - jschar *chars; - JSFunction *fun; - - CHECK_REQUEST(cx); - chars = js_InflateString(cx, bytes, &length); - if (!chars) - return NULL; - fun = JS_CompileUCFunction(cx, obj, name, nargs, argnames, chars, length, - filename, lineno); - JS_free(cx, chars); - return fun; -} - -JS_PUBLIC_API(JSFunction *) -JS_CompileFunctionForPrincipals(JSContext *cx, JSObject *obj, - JSPrincipals *principals, const char *name, - uintN nargs, const char **argnames, - const char *bytes, size_t length, - const char *filename, uintN lineno) -{ - jschar *chars; - JSFunction *fun; - - CHECK_REQUEST(cx); - chars = js_InflateString(cx, bytes, &length); - if (!chars) - return NULL; - fun = JS_CompileUCFunctionForPrincipals(cx, obj, principals, name, - nargs, argnames, chars, length, - filename, lineno); - JS_free(cx, chars); - return fun; -} - -JS_PUBLIC_API(JSFunction *) -JS_CompileUCFunction(JSContext *cx, JSObject *obj, const char *name, - uintN nargs, const char **argnames, - const jschar *chars, size_t length, - const char *filename, uintN lineno) -{ - CHECK_REQUEST(cx); - return JS_CompileUCFunctionForPrincipals(cx, obj, NULL, name, - nargs, argnames, - chars, length, - filename, lineno); -} - -JS_PUBLIC_API(JSFunction *) -JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj, - JSPrincipals *principals, const char *name, - uintN nargs, const char **argnames, - const jschar *chars, size_t length, - const char *filename, uintN lineno) -{ - void *mark; - JSTokenStream *ts; - JSFunction *fun; - JSAtom *funAtom, *argAtom; - uintN i; - - CHECK_REQUEST(cx); - mark = JS_ARENA_MARK(&cx->tempPool); - ts = js_NewTokenStream(cx, chars, length, filename, lineno, principals); - if (!ts) { - fun = NULL; - goto out; - } - if (!name) { - funAtom = NULL; - } else { - funAtom = js_Atomize(cx, name, strlen(name), 0); - if (!funAtom) { - fun = NULL; - goto out; - } - } - fun = js_NewFunction(cx, NULL, NULL, nargs, 0, obj, funAtom); - if (!fun) - goto out; - if (nargs) { - for (i = 0; i < nargs; i++) { - argAtom = js_Atomize(cx, argnames[i], strlen(argnames[i]), 0); - if (!argAtom) - break; - if (!js_AddHiddenProperty(cx, fun->object, ATOM_TO_JSID(argAtom), - js_GetArgument, js_SetArgument, - SPROP_INVALID_SLOT, - JSPROP_PERMANENT | JSPROP_SHARED, - SPROP_HAS_SHORTID, i)) { - break; - } - } - if (i < nargs) { - fun = NULL; - goto out; - } - } - if (!js_CompileFunctionBody(cx, ts, fun)) { - fun = NULL; - goto out; - } - if (obj && funAtom) { - if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(funAtom), - OBJECT_TO_JSVAL(fun->object), - NULL, NULL, JSPROP_ENUMERATE, NULL)) { - return NULL; - } - } -out: - if (ts) - js_CloseTokenStream(cx, ts); - JS_ARENA_RELEASE(&cx->tempPool, mark); - LAST_FRAME_CHECKS(cx, fun); - return fun; -} - -JS_PUBLIC_API(JSString *) -JS_DecompileScript(JSContext *cx, JSScript *script, const char *name, - uintN indent) -{ - JSPrinter *jp; - JSString *str; - - CHECK_REQUEST(cx); - jp = js_NewPrinter(cx, name, - indent & ~JS_DONT_PRETTY_PRINT, - !(indent & JS_DONT_PRETTY_PRINT)); - if (!jp) - return NULL; - if (js_DecompileScript(jp, script)) - str = js_GetPrinterOutput(jp); - else - str = NULL; - js_DestroyPrinter(jp); - return str; -} - -JS_PUBLIC_API(JSString *) -JS_DecompileFunction(JSContext *cx, JSFunction *fun, uintN indent) -{ - JSPrinter *jp; - JSString *str; - - CHECK_REQUEST(cx); - jp = js_NewPrinter(cx, JS_GetFunctionName(fun), - indent & ~JS_DONT_PRETTY_PRINT, - !(indent & JS_DONT_PRETTY_PRINT)); - if (!jp) - return NULL; - if (js_DecompileFunction(jp, fun)) - str = js_GetPrinterOutput(jp); - else - str = NULL; - js_DestroyPrinter(jp); - return str; -} - -JS_PUBLIC_API(JSString *) -JS_DecompileFunctionBody(JSContext *cx, JSFunction *fun, uintN indent) -{ - JSPrinter *jp; - JSString *str; - - CHECK_REQUEST(cx); - jp = js_NewPrinter(cx, JS_GetFunctionName(fun), - indent & ~JS_DONT_PRETTY_PRINT, - !(indent & JS_DONT_PRETTY_PRINT)); - if (!jp) - return NULL; - if (js_DecompileFunctionBody(jp, fun)) - str = js_GetPrinterOutput(jp); - else - str = NULL; - js_DestroyPrinter(jp); - return str; -} - -JS_PUBLIC_API(JSBool) -JS_ExecuteScript(JSContext *cx, JSObject *obj, JSScript *script, jsval *rval) -{ - JSBool ok; - - CHECK_REQUEST(cx); - ok = js_Execute(cx, obj, script, NULL, 0, rval); - LAST_FRAME_CHECKS(cx, ok); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_ExecuteScriptPart(JSContext *cx, JSObject *obj, JSScript *script, - JSExecPart part, jsval *rval) -{ - JSScript tmp; - JSRuntime *rt; - JSBool ok; - - /* Make a temporary copy of the JSScript structure and farble it a bit. */ - tmp = *script; - if (part == JSEXEC_PROLOG) { - tmp.length = PTRDIFF(tmp.main, tmp.code, jsbytecode); - } else { - tmp.length -= PTRDIFF(tmp.main, tmp.code, jsbytecode); - tmp.code = tmp.main; - } - - /* Tell the debugger about our temporary copy of the script structure. */ - rt = cx->runtime; - if (rt->newScriptHook) { - rt->newScriptHook(cx, tmp.filename, tmp.lineno, &tmp, NULL, - rt->newScriptHookData); - } - - /* Execute the farbled struct and tell the debugger to forget about it. */ - ok = JS_ExecuteScript(cx, obj, &tmp, rval); - if (rt->destroyScriptHook) - rt->destroyScriptHook(cx, &tmp, rt->destroyScriptHookData); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_EvaluateScript(JSContext *cx, JSObject *obj, - const char *bytes, uintN nbytes, - const char *filename, uintN lineno, - jsval *rval) -{ - size_t length = nbytes; - jschar *chars; - JSBool ok; - - CHECK_REQUEST(cx); - chars = js_InflateString(cx, bytes, &length); - if (!chars) - return JS_FALSE; - ok = JS_EvaluateUCScript(cx, obj, chars, length, filename, lineno, rval); - JS_free(cx, chars); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_EvaluateScriptForPrincipals(JSContext *cx, JSObject *obj, - JSPrincipals *principals, - const char *bytes, uintN nbytes, - const char *filename, uintN lineno, - jsval *rval) -{ - size_t length = nbytes; - jschar *chars; - JSBool ok; - - CHECK_REQUEST(cx); - chars = js_InflateString(cx, bytes, &length); - if (!chars) - return JS_FALSE; - ok = JS_EvaluateUCScriptForPrincipals(cx, obj, principals, chars, length, - filename, lineno, rval); - JS_free(cx, chars); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_EvaluateUCScript(JSContext *cx, JSObject *obj, - const jschar *chars, uintN length, - const char *filename, uintN lineno, - jsval *rval) -{ - CHECK_REQUEST(cx); - return JS_EvaluateUCScriptForPrincipals(cx, obj, NULL, chars, length, - filename, lineno, rval); -} - -JS_PUBLIC_API(JSBool) -JS_EvaluateUCScriptForPrincipals(JSContext *cx, JSObject *obj, - JSPrincipals *principals, - const jschar *chars, uintN length, - const char *filename, uintN lineno, - jsval *rval) -{ - uint32 options; - JSScript *script; - JSBool ok; - - CHECK_REQUEST(cx); - options = cx->options; - cx->options = options | JSOPTION_COMPILE_N_GO; - script = JS_CompileUCScriptForPrincipals(cx, obj, principals, chars, length, - filename, lineno); - cx->options = options; - if (!script) - return JS_FALSE; - ok = js_Execute(cx, obj, script, NULL, 0, rval); - LAST_FRAME_CHECKS(cx, ok); - JS_DestroyScript(cx, script); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, uintN argc, - jsval *argv, jsval *rval) -{ - JSBool ok; - - CHECK_REQUEST(cx); - ok = js_InternalCall(cx, obj, OBJECT_TO_JSVAL(fun->object), argc, argv, - rval); - LAST_FRAME_CHECKS(cx, ok); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_CallFunctionName(JSContext *cx, JSObject *obj, const char *name, uintN argc, - jsval *argv, jsval *rval) -{ - JSBool ok; - jsval fval; - - CHECK_REQUEST(cx); -#if JS_HAS_XML_SUPPORT - if (OBJECT_IS_XML(cx, obj)) { - JSXMLObjectOps *ops; - JSAtom *atom; - - ops = (JSXMLObjectOps *) obj->map->ops; - atom = js_Atomize(cx, name, strlen(name), 0); - if (!atom) - return JS_FALSE; - obj = ops->getMethod(cx, obj, ATOM_TO_JSID(atom), &fval); - if (!obj) - return JS_FALSE; - } else -#endif - if (!JS_GetProperty(cx, obj, name, &fval)) - return JS_FALSE; - ok = js_InternalCall(cx, obj, fval, argc, argv, rval); - LAST_FRAME_CHECKS(cx, ok); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, uintN argc, - jsval *argv, jsval *rval) -{ - JSBool ok; - - CHECK_REQUEST(cx); - ok = js_InternalCall(cx, obj, fval, argc, argv, rval); - LAST_FRAME_CHECKS(cx, ok); - return ok; -} - -JS_PUBLIC_API(JSBranchCallback) -JS_SetBranchCallback(JSContext *cx, JSBranchCallback cb) -{ - JSBranchCallback oldcb; - - oldcb = cx->branchCallback; - cx->branchCallback = cb; - return oldcb; -} - -JS_PUBLIC_API(JSBool) -JS_IsRunning(JSContext *cx) -{ - return cx->fp != NULL; -} - -JS_PUBLIC_API(JSBool) -JS_IsConstructing(JSContext *cx) -{ - return cx->fp && (cx->fp->flags & JSFRAME_CONSTRUCTING); -} - -JS_FRIEND_API(JSBool) -JS_IsAssigning(JSContext *cx) -{ - JSStackFrame *fp; - jsbytecode *pc; - - for (fp = cx->fp; fp && !fp->script; fp = fp->down) - continue; - if (!fp || !(pc = fp->pc)) - return JS_FALSE; - return (js_CodeSpec[*pc].format & JOF_ASSIGNING) != 0; -} - -JS_PUBLIC_API(void) -JS_SetCallReturnValue2(JSContext *cx, jsval v) -{ -#if JS_HAS_LVALUE_RETURN - cx->rval2 = v; - cx->rval2set = JS_TRUE; -#endif -} - -/************************************************************************/ - -JS_PUBLIC_API(JSString *) -JS_NewString(JSContext *cx, char *bytes, size_t length) -{ - jschar *chars; - JSString *str; - size_t charsLength = length; - - CHECK_REQUEST(cx); - /* Make a Unicode vector from the 8-bit char codes in bytes. */ - chars = js_InflateString(cx, bytes, &charsLength); - if (!chars) - return NULL; - - /* Free chars (but not bytes, which caller frees on error) if we fail. */ - str = js_NewString(cx, chars, charsLength, 0); - if (!str) { - JS_free(cx, chars); - return NULL; - } - - /* Hand off bytes to the deflated string cache, if possible. */ - if (!js_SetStringBytes(str, bytes, length)) - JS_free(cx, bytes); - return str; -} - -JS_PUBLIC_API(JSString *) -JS_NewStringCopyN(JSContext *cx, const char *s, size_t n) -{ - jschar *js; - JSString *str; - - CHECK_REQUEST(cx); - js = js_InflateString(cx, s, &n); - if (!js) - return NULL; - str = js_NewString(cx, js, n, 0); - if (!str) - JS_free(cx, js); - return str; -} - -JS_PUBLIC_API(JSString *) -JS_NewStringCopyZ(JSContext *cx, const char *s) -{ - size_t n; - jschar *js; - JSString *str; - - CHECK_REQUEST(cx); - if (!s) - return cx->runtime->emptyString; - n = strlen(s); - js = js_InflateString(cx, s, &n); - if (!js) - return NULL; - str = js_NewString(cx, js, n, 0); - if (!str) - JS_free(cx, js); - return str; -} - -JS_PUBLIC_API(JSString *) -JS_InternString(JSContext *cx, const char *s) -{ - JSAtom *atom; - - CHECK_REQUEST(cx); - atom = js_Atomize(cx, s, strlen(s), ATOM_INTERNED); - if (!atom) - return NULL; - return ATOM_TO_STRING(atom); -} - -JS_PUBLIC_API(JSString *) -JS_NewUCString(JSContext *cx, jschar *chars, size_t length) -{ - CHECK_REQUEST(cx); - return js_NewString(cx, chars, length, 0); -} - -JS_PUBLIC_API(JSString *) -JS_NewUCStringCopyN(JSContext *cx, const jschar *s, size_t n) -{ - CHECK_REQUEST(cx); - return js_NewStringCopyN(cx, s, n, 0); -} - -JS_PUBLIC_API(JSString *) -JS_NewUCStringCopyZ(JSContext *cx, const jschar *s) -{ - CHECK_REQUEST(cx); - if (!s) - return cx->runtime->emptyString; - return js_NewStringCopyZ(cx, s, 0); -} - -JS_PUBLIC_API(JSString *) -JS_InternUCStringN(JSContext *cx, const jschar *s, size_t length) -{ - JSAtom *atom; - - CHECK_REQUEST(cx); - atom = js_AtomizeChars(cx, s, length, ATOM_INTERNED); - if (!atom) - return NULL; - return ATOM_TO_STRING(atom); -} - -JS_PUBLIC_API(JSString *) -JS_InternUCString(JSContext *cx, const jschar *s) -{ - return JS_InternUCStringN(cx, s, js_strlen(s)); -} - -JS_PUBLIC_API(char *) -JS_GetStringBytes(JSString *str) -{ - char *bytes; - - bytes = js_GetStringBytes(str); - return bytes ? bytes : ""; -} - -JS_PUBLIC_API(jschar *) -JS_GetStringChars(JSString *str) -{ - /* - * API botch (again, shades of JS_GetStringBytes): we have no cx to pass - * to js_UndependString (called by js_GetStringChars) for out-of-memory - * error reports, so js_UndependString passes NULL and suppresses errors. - * If it fails to convert a dependent string into an independent one, our - * caller will not be guaranteed a \u0000 terminator as a backstop. This - * may break some clients who already misbehave on embedded NULs. - * - * The gain of dependent strings, which cure quadratic and cubic growth - * rate bugs in string concatenation, is worth this slight loss in API - * compatibility. - */ - jschar *chars; - - chars = js_GetStringChars(str); - return chars ? chars : JSSTRING_CHARS(str); -} - -JS_PUBLIC_API(size_t) -JS_GetStringLength(JSString *str) -{ - return JSSTRING_LENGTH(str); -} - -JS_PUBLIC_API(intN) -JS_CompareStrings(JSString *str1, JSString *str2) -{ - return js_CompareStrings(str1, str2); -} - -JS_PUBLIC_API(JSString *) -JS_NewGrowableString(JSContext *cx, jschar *chars, size_t length) -{ - CHECK_REQUEST(cx); - return js_NewString(cx, chars, length, GCF_MUTABLE); -} - -JS_PUBLIC_API(JSString *) -JS_NewDependentString(JSContext *cx, JSString *str, size_t start, - size_t length) -{ - CHECK_REQUEST(cx); - return js_NewDependentString(cx, str, start, length, 0); -} - -JS_PUBLIC_API(JSString *) -JS_ConcatStrings(JSContext *cx, JSString *left, JSString *right) -{ - CHECK_REQUEST(cx); - return js_ConcatStrings(cx, left, right); -} - -JS_PUBLIC_API(const jschar *) -JS_UndependString(JSContext *cx, JSString *str) -{ - CHECK_REQUEST(cx); - return js_UndependString(cx, str); -} - -JS_PUBLIC_API(JSBool) -JS_MakeStringImmutable(JSContext *cx, JSString *str) -{ - CHECK_REQUEST(cx); - if (!js_UndependString(cx, str)) - return JS_FALSE; - - *js_GetGCThingFlags(str) &= ~GCF_MUTABLE; - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_EncodeCharacters(JSContext *cx, const jschar *src, size_t srclen, char *dst, - size_t *dstlenp) -{ - return js_DeflateStringToBuffer(cx, src, srclen, dst, dstlenp); -} - -JS_PUBLIC_API(JSBool) -JS_DecodeBytes(JSContext *cx, const char *src, size_t srclen, jschar *dst, - size_t *dstlenp) -{ - return js_InflateStringToBuffer(cx, src, srclen, dst, dstlenp); -} - -JS_PUBLIC_API(JSBool) -JS_StringsAreUTF8 () -{ -#ifdef JS_C_STRINGS_ARE_UTF8 - return JS_TRUE; -#else - return JS_FALSE; -#endif -} - -/************************************************************************/ - -JS_PUBLIC_API(void) -JS_ReportError(JSContext *cx, const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - js_ReportErrorVA(cx, JSREPORT_ERROR, format, ap); - va_end(ap); -} - -JS_PUBLIC_API(void) -JS_ReportErrorNumber(JSContext *cx, JSErrorCallback errorCallback, - void *userRef, const uintN errorNumber, ...) -{ - va_list ap; - - va_start(ap, errorNumber); - js_ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef, - errorNumber, JS_TRUE, ap); - va_end(ap); -} - -JS_PUBLIC_API(void) -JS_ReportErrorNumberUC(JSContext *cx, JSErrorCallback errorCallback, - void *userRef, const uintN errorNumber, ...) -{ - va_list ap; - - va_start(ap, errorNumber); - js_ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef, - errorNumber, JS_FALSE, ap); - va_end(ap); -} - -JS_PUBLIC_API(JSBool) -JS_ReportWarning(JSContext *cx, const char *format, ...) -{ - va_list ap; - JSBool ok; - - va_start(ap, format); - ok = js_ReportErrorVA(cx, JSREPORT_WARNING, format, ap); - va_end(ap); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_ReportErrorFlagsAndNumber(JSContext *cx, uintN flags, - JSErrorCallback errorCallback, void *userRef, - const uintN errorNumber, ...) -{ - va_list ap; - JSBool ok; - - va_start(ap, errorNumber); - ok = js_ReportErrorNumberVA(cx, flags, errorCallback, userRef, - errorNumber, JS_TRUE, ap); - va_end(ap); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_ReportErrorFlagsAndNumberUC(JSContext *cx, uintN flags, - JSErrorCallback errorCallback, void *userRef, - const uintN errorNumber, ...) -{ - va_list ap; - JSBool ok; - - va_start(ap, errorNumber); - ok = js_ReportErrorNumberVA(cx, flags, errorCallback, userRef, - errorNumber, JS_FALSE, ap); - va_end(ap); - return ok; -} - -JS_PUBLIC_API(void) -JS_ReportOutOfMemory(JSContext *cx) -{ - js_ReportOutOfMemory(cx, js_GetErrorMessage); -} - -JS_PUBLIC_API(JSErrorReporter) -JS_SetErrorReporter(JSContext *cx, JSErrorReporter er) -{ - JSErrorReporter older; - - older = cx->errorReporter; - cx->errorReporter = er; - return older; -} - -/************************************************************************/ - -/* - * Regular Expressions. - */ -JS_PUBLIC_API(JSObject *) -JS_NewRegExpObject(JSContext *cx, char *bytes, size_t length, uintN flags) -{ -#if JS_HAS_REGEXPS - jschar *chars; - JSObject *obj; - - CHECK_REQUEST(cx); - chars = js_InflateString(cx, bytes, &length); - if (!chars) - return NULL; - obj = js_NewRegExpObject(cx, NULL, chars, length, flags); - JS_free(cx, chars); - return obj; -#else - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_REG_EXPS); - return NULL; -#endif -} - -JS_PUBLIC_API(JSObject *) -JS_NewUCRegExpObject(JSContext *cx, jschar *chars, size_t length, uintN flags) -{ - CHECK_REQUEST(cx); -#if JS_HAS_REGEXPS - return js_NewRegExpObject(cx, NULL, chars, length, flags); -#else - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_REG_EXPS); - return NULL; -#endif -} - -JS_PUBLIC_API(void) -JS_SetRegExpInput(JSContext *cx, JSString *input, JSBool multiline) -{ - JSRegExpStatics *res; - - CHECK_REQUEST(cx); - /* No locking required, cx is thread-private and input must be live. */ - res = &cx->regExpStatics; - res->input = input; - res->multiline = multiline; - cx->runtime->gcPoke = JS_TRUE; -} - -JS_PUBLIC_API(void) -JS_ClearRegExpStatics(JSContext *cx) -{ - JSRegExpStatics *res; - - /* No locking required, cx is thread-private and input must be live. */ - res = &cx->regExpStatics; - res->input = NULL; - res->multiline = JS_FALSE; - res->parenCount = 0; - res->lastMatch = res->lastParen = js_EmptySubString; - res->leftContext = res->rightContext = js_EmptySubString; - cx->runtime->gcPoke = JS_TRUE; -} - -JS_PUBLIC_API(void) -JS_ClearRegExpRoots(JSContext *cx) -{ - JSRegExpStatics *res; - - /* No locking required, cx is thread-private and input must be live. */ - res = &cx->regExpStatics; - res->input = NULL; - cx->runtime->gcPoke = JS_TRUE; -} - -/* TODO: compile, execute, get/set other statics... */ - -/************************************************************************/ - -JS_PUBLIC_API(void) -JS_SetLocaleCallbacks(JSContext *cx, JSLocaleCallbacks *callbacks) -{ - cx->localeCallbacks = callbacks; -} - -JS_PUBLIC_API(JSLocaleCallbacks *) -JS_GetLocaleCallbacks(JSContext *cx) -{ - return cx->localeCallbacks; -} - -/************************************************************************/ - -JS_PUBLIC_API(JSBool) -JS_IsExceptionPending(JSContext *cx) -{ -#if JS_HAS_EXCEPTIONS - return (JSBool) cx->throwing; -#else - return JS_FALSE; -#endif -} - -JS_PUBLIC_API(JSBool) -JS_GetPendingException(JSContext *cx, jsval *vp) -{ -#if JS_HAS_EXCEPTIONS - CHECK_REQUEST(cx); - if (!cx->throwing) - return JS_FALSE; - *vp = cx->exception; - return JS_TRUE; -#else - return JS_FALSE; -#endif -} - -JS_PUBLIC_API(void) -JS_SetPendingException(JSContext *cx, jsval v) -{ - CHECK_REQUEST(cx); -#if JS_HAS_EXCEPTIONS - cx->throwing = JS_TRUE; - cx->exception = v; -#endif -} - -JS_PUBLIC_API(void) -JS_ClearPendingException(JSContext *cx) -{ -#if JS_HAS_EXCEPTIONS - cx->throwing = JS_FALSE; - cx->exception = JSVAL_VOID; -#endif -} - -JS_PUBLIC_API(JSBool) -JS_ReportPendingException(JSContext *cx) -{ -#if JS_HAS_EXCEPTIONS - JSBool save, ok; - - CHECK_REQUEST(cx); - - /* - * Set cx->creatingException to suppress the standard error-to-exception - * conversion done by all {js,JS}_Report* functions except for OOM. The - * cx->creatingException flag was added to suppress recursive divergence - * under js_ErrorToException, but it serves for our purposes here too. - */ - save = cx->creatingException; - cx->creatingException = JS_TRUE; - ok = js_ReportUncaughtException(cx); - cx->creatingException = save; - return ok; -#else - return JS_TRUE; -#endif -} - -#if JS_HAS_EXCEPTIONS -struct JSExceptionState { - JSBool throwing; - jsval exception; -}; -#endif - -JS_PUBLIC_API(JSExceptionState *) -JS_SaveExceptionState(JSContext *cx) -{ -#if JS_HAS_EXCEPTIONS - JSExceptionState *state; - - CHECK_REQUEST(cx); - state = (JSExceptionState *) JS_malloc(cx, sizeof(JSExceptionState)); - if (state) { - state->throwing = JS_GetPendingException(cx, &state->exception); - if (state->throwing && JSVAL_IS_GCTHING(state->exception)) - js_AddRoot(cx, &state->exception, "JSExceptionState.exception"); - } - return state; -#else - return NULL; -#endif -} - -JS_PUBLIC_API(void) -JS_RestoreExceptionState(JSContext *cx, JSExceptionState *state) -{ -#if JS_HAS_EXCEPTIONS - CHECK_REQUEST(cx); - if (state) { - if (state->throwing) - JS_SetPendingException(cx, state->exception); - else - JS_ClearPendingException(cx); - JS_DropExceptionState(cx, state); - } -#endif -} - -JS_PUBLIC_API(void) -JS_DropExceptionState(JSContext *cx, JSExceptionState *state) -{ -#if JS_HAS_EXCEPTIONS - CHECK_REQUEST(cx); - if (state) { - if (state->throwing && JSVAL_IS_GCTHING(state->exception)) - JS_RemoveRoot(cx, &state->exception); - JS_free(cx, state); - } -#endif -} - -JS_PUBLIC_API(JSErrorReport *) -JS_ErrorFromException(JSContext *cx, jsval v) -{ -#if JS_HAS_ERROR_EXCEPTIONS - CHECK_REQUEST(cx); - return js_ErrorFromException(cx, v); -#else - return NULL; -#endif -} - -JS_PUBLIC_API(JSBool) -JS_ThrowReportedError(JSContext *cx, const char *message, - JSErrorReport *reportp) -{ - return js_ErrorToException(cx, message, reportp); -} - -#ifdef JS_THREADSAFE -JS_PUBLIC_API(jsword) -JS_GetContextThread(JSContext *cx) -{ - return cx->thread; -} - -JS_PUBLIC_API(jsword) -JS_SetContextThread(JSContext *cx) -{ - jsword old = cx->thread; - cx->thread = js_CurrentThreadId(); - return old; -} - -JS_PUBLIC_API(jsword) -JS_ClearContextThread(JSContext *cx) -{ - jsword old = cx->thread; - cx->thread = 0; - return old; -} -#endif - -/************************************************************************/ - -#if defined(XP_WIN) -#include -/* - * Initialization routine for the JS DLL... - */ - -/* - * Global Instance handle... - * In Win32 this is the module handle of the DLL. - * - * In Win16 this is the instance handle of the application - * which loaded the DLL. - */ - -#ifdef _WIN32 -BOOL WINAPI DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved) -{ - return TRUE; -} - -#else /* !_WIN32 */ - -int CALLBACK LibMain( HINSTANCE hInst, WORD wDataSeg, - WORD cbHeapSize, LPSTR lpszCmdLine ) -{ - return TRUE; -} - -BOOL CALLBACK __loadds WEP(BOOL fSystemExit) -{ - return TRUE; -} - -#endif /* !_WIN32 */ -#endif /* XP_WIN */ diff --git a/lib/javascript/jsapi.h b/lib/javascript/jsapi.h deleted file mode 100644 index 9fe07ac6..00000000 --- a/lib/javascript/jsapi.h +++ /dev/null @@ -1,2027 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jsapi_h___ -#define jsapi_h___ -/* - * JavaScript API. - */ -#include -#include -#include "jspubtd.h" - -JS_BEGIN_EXTERN_C - -/* - * Type tags stored in the low bits of a jsval. - */ -#define JSVAL_OBJECT 0x0 /* untagged reference to object */ -#define JSVAL_INT 0x1 /* tagged 31-bit integer value */ -#define JSVAL_DOUBLE 0x2 /* tagged reference to double */ -#define JSVAL_STRING 0x4 /* tagged reference to string */ -#define JSVAL_BOOLEAN 0x6 /* tagged boolean value */ - -/* Type tag bitfield length and derived macros. */ -#define JSVAL_TAGBITS 3 -#define JSVAL_TAGMASK JS_BITMASK(JSVAL_TAGBITS) -#define JSVAL_TAG(v) ((v) & JSVAL_TAGMASK) -#define JSVAL_SETTAG(v,t) ((v) | (t)) -#define JSVAL_CLRTAG(v) ((v) & ~(jsval)JSVAL_TAGMASK) -#define JSVAL_ALIGN JS_BIT(JSVAL_TAGBITS) - -/* Predicates for type testing. */ -#define JSVAL_IS_OBJECT(v) (JSVAL_TAG(v) == JSVAL_OBJECT) -#define JSVAL_IS_NUMBER(v) (JSVAL_IS_INT(v) || JSVAL_IS_DOUBLE(v)) -#define JSVAL_IS_INT(v) (((v) & JSVAL_INT) && (v) != JSVAL_VOID) -#define JSVAL_IS_DOUBLE(v) (JSVAL_TAG(v) == JSVAL_DOUBLE) -#define JSVAL_IS_STRING(v) (JSVAL_TAG(v) == JSVAL_STRING) -#define JSVAL_IS_BOOLEAN(v) (JSVAL_TAG(v) == JSVAL_BOOLEAN) -#define JSVAL_IS_NULL(v) ((v) == JSVAL_NULL) -#define JSVAL_IS_VOID(v) ((v) == JSVAL_VOID) -#define JSVAL_IS_PRIMITIVE(v) (!JSVAL_IS_OBJECT(v) || JSVAL_IS_NULL(v)) - -/* Objects, strings, and doubles are GC'ed. */ -#define JSVAL_IS_GCTHING(v) (!((v) & JSVAL_INT) && !JSVAL_IS_BOOLEAN(v)) -#define JSVAL_TO_GCTHING(v) ((void *)JSVAL_CLRTAG(v)) -#define JSVAL_TO_OBJECT(v) ((JSObject *)JSVAL_TO_GCTHING(v)) -#define JSVAL_TO_DOUBLE(v) ((jsdouble *)JSVAL_TO_GCTHING(v)) -#define JSVAL_TO_STRING(v) ((JSString *)JSVAL_TO_GCTHING(v)) -#define OBJECT_TO_JSVAL(obj) ((jsval)(obj)) -#define DOUBLE_TO_JSVAL(dp) JSVAL_SETTAG((jsval)(dp), JSVAL_DOUBLE) -#define STRING_TO_JSVAL(str) JSVAL_SETTAG((jsval)(str), JSVAL_STRING) - -/* Lock and unlock the GC thing held by a jsval. */ -#define JSVAL_LOCK(cx,v) (JSVAL_IS_GCTHING(v) \ - ? JS_LockGCThing(cx, JSVAL_TO_GCTHING(v)) \ - : JS_TRUE) -#define JSVAL_UNLOCK(cx,v) (JSVAL_IS_GCTHING(v) \ - ? JS_UnlockGCThing(cx, JSVAL_TO_GCTHING(v)) \ - : JS_TRUE) - -/* Domain limits for the jsval int type. */ -#define JSVAL_INT_BITS 31 -#define JSVAL_INT_POW2(n) ((jsval)1 << (n)) -#define JSVAL_INT_MIN ((jsval)1 - JSVAL_INT_POW2(30)) -#define JSVAL_INT_MAX (JSVAL_INT_POW2(30) - 1) -#define INT_FITS_IN_JSVAL(i) ((jsuint)((i)+JSVAL_INT_MAX) <= 2*JSVAL_INT_MAX) -#define JSVAL_TO_INT(v) ((jsint)(v) >> 1) -#define INT_TO_JSVAL(i) (((jsval)(i) << 1) | JSVAL_INT) - -/* Convert between boolean and jsval. */ -#define JSVAL_TO_BOOLEAN(v) ((JSBool)((v) >> JSVAL_TAGBITS)) -#define BOOLEAN_TO_JSVAL(b) JSVAL_SETTAG((jsval)(b) << JSVAL_TAGBITS, \ - JSVAL_BOOLEAN) - -/* A private data pointer (2-byte-aligned) can be stored as an int jsval. */ -#define JSVAL_TO_PRIVATE(v) ((void *)((v) & ~JSVAL_INT)) -#define PRIVATE_TO_JSVAL(p) ((jsval)(p) | JSVAL_INT) - -/* Property attributes, set in JSPropertySpec and passed to API functions. */ -#define JSPROP_ENUMERATE 0x01 /* property is visible to for/in loop */ -#define JSPROP_READONLY 0x02 /* not settable: assignment is no-op */ -#define JSPROP_PERMANENT 0x04 /* property cannot be deleted */ -#define JSPROP_EXPORTED 0x08 /* property is exported from object */ -#define JSPROP_GETTER 0x10 /* property holds getter function */ -#define JSPROP_SETTER 0x20 /* property holds setter function */ -#define JSPROP_SHARED 0x40 /* don't allocate a value slot for this - property; don't copy the property on - set of the same-named property in an - object that delegates to a prototype - containing this property */ -#define JSPROP_INDEX 0x80 /* name is actually (jsint) index */ - -/* Function flags, set in JSFunctionSpec and passed to JS_NewFunction etc. */ -#define JSFUN_LAMBDA 0x08 /* expressed, not declared, function */ -#define JSFUN_GETTER JSPROP_GETTER -#define JSFUN_SETTER JSPROP_SETTER -#define JSFUN_BOUND_METHOD 0x40 /* bind this to fun->object's parent */ -#define JSFUN_HEAVYWEIGHT 0x80 /* activation requires a Call object */ -#define JSFUN_FLAGS_MASK 0xf8 /* overlay JSFUN_* attributes */ - -/* - * Re-use JSFUN_LAMBDA, which applies only to scripted functions, for use in - * JSFunctionSpec arrays that specify generic native prototype methods, i.e., - * methods of a class prototype that are exposed as static methods taking an - * extra leading argument: the generic |this| parameter. - * - * If you set this flag in a JSFunctionSpec struct's flags initializer, then - * that struct must live at least as long as the native static method object - * created due to this flag by JS_DefineFunctions or JS_InitClass. Typically - * JSFunctionSpec structs are allocated in static arrays. - */ -#define JSFUN_GENERIC_NATIVE JSFUN_LAMBDA - -/* - * Well-known JS values. The extern'd variables are initialized when the - * first JSContext is created by JS_NewContext (see below). - */ -#define JSVAL_VOID INT_TO_JSVAL(0 - JSVAL_INT_POW2(30)) -#define JSVAL_NULL OBJECT_TO_JSVAL(0) -#define JSVAL_ZERO INT_TO_JSVAL(0) -#define JSVAL_ONE INT_TO_JSVAL(1) -#define JSVAL_FALSE BOOLEAN_TO_JSVAL(JS_FALSE) -#define JSVAL_TRUE BOOLEAN_TO_JSVAL(JS_TRUE) - -/* - * Microseconds since the epoch, midnight, January 1, 1970 UTC. See the - * comment in jstypes.h regarding safe int64 usage. - */ -extern JS_PUBLIC_API(int64) -JS_Now(); - -/* Don't want to export data, so provide accessors for non-inline jsvals. */ -extern JS_PUBLIC_API(jsval) -JS_GetNaNValue(JSContext *cx); - -extern JS_PUBLIC_API(jsval) -JS_GetNegativeInfinityValue(JSContext *cx); - -extern JS_PUBLIC_API(jsval) -JS_GetPositiveInfinityValue(JSContext *cx); - -extern JS_PUBLIC_API(jsval) -JS_GetEmptyStringValue(JSContext *cx); - -/* - * Format is a string of the following characters (spaces are insignificant), - * specifying the tabulated type conversions: - * - * b JSBool Boolean - * c uint16/jschar ECMA uint16, Unicode char - * i int32 ECMA int32 - * u uint32 ECMA uint32 - * j int32 Rounded int32 (coordinate) - * d jsdouble IEEE double - * I jsdouble Integral IEEE double - * s char * C string - * S JSString * Unicode string, accessed by a JSString pointer - * W jschar * Unicode character vector, 0-terminated (W for wide) - * o JSObject * Object reference - * f JSFunction * Function private - * v jsval Argument value (no conversion) - * * N/A Skip this argument (no vararg) - * / N/A End of required arguments - * - * The variable argument list after format must consist of &b, &c, &s, e.g., - * where those variables have the types given above. For the pointer types - * char *, JSString *, and JSObject *, the pointed-at memory returned belongs - * to the JS runtime, not to the calling native code. The runtime promises - * to keep this memory valid so long as argv refers to allocated stack space - * (so long as the native function is active). - * - * Fewer arguments than format specifies may be passed only if there is a / - * in format after the last required argument specifier and argc is at least - * the number of required arguments. More arguments than format specifies - * may be passed without error; it is up to the caller to deal with trailing - * unconverted arguments. - */ -extern JS_PUBLIC_API(JSBool) -JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format, - ...); - -#ifdef va_start -extern JS_PUBLIC_API(JSBool) -JS_ConvertArgumentsVA(JSContext *cx, uintN argc, jsval *argv, - const char *format, va_list ap); -#endif - -/* - * Inverse of JS_ConvertArguments: scan format and convert trailing arguments - * into jsvals, GC-rooted if necessary by the JS stack. Return null on error, - * and a pointer to the new argument vector on success. Also return a stack - * mark on success via *markp, in which case the caller must eventually clean - * up by calling JS_PopArguments. - * - * Note that the number of actual arguments supplied is specified exclusively - * by format, so there is no argc parameter. - */ -extern JS_PUBLIC_API(jsval *) -JS_PushArguments(JSContext *cx, void **markp, const char *format, ...); - -#ifdef va_start -extern JS_PUBLIC_API(jsval *) -JS_PushArgumentsVA(JSContext *cx, void **markp, const char *format, va_list ap); -#endif - -extern JS_PUBLIC_API(void) -JS_PopArguments(JSContext *cx, void *mark); - -#ifdef JS_ARGUMENT_FORMATTER_DEFINED - -/* - * Add and remove a format string handler for JS_{Convert,Push}Arguments{,VA}. - * The handler function has this signature (see jspubtd.h): - * - * JSBool MyArgumentFormatter(JSContext *cx, const char *format, - * JSBool fromJS, jsval **vpp, va_list *app); - * - * It should return true on success, and return false after reporting an error - * or detecting an already-reported error. - * - * For a given format string, for example "AA", the formatter is called from - * JS_ConvertArgumentsVA like so: - * - * formatter(cx, "AA...", JS_TRUE, &sp, &ap); - * - * sp points into the arguments array on the JS stack, while ap points into - * the stdarg.h va_list on the C stack. The JS_TRUE passed for fromJS tells - * the formatter to convert zero or more jsvals at sp to zero or more C values - * accessed via pointers-to-values at ap, updating both sp (via *vpp) and ap - * (via *app) to point past the converted arguments and their result pointers - * on the C stack. - * - * When called from JS_PushArgumentsVA, the formatter is invoked thus: - * - * formatter(cx, "AA...", JS_FALSE, &sp, &ap); - * - * where JS_FALSE for fromJS means to wrap the C values at ap according to the - * format specifier and store them at sp, updating ap and sp appropriately. - * - * The "..." after "AA" is the rest of the format string that was passed into - * JS_{Convert,Push}Arguments{,VA}. The actual format trailing substring used - * in each Convert or PushArguments call is passed to the formatter, so that - * one such function may implement several formats, in order to share code. - * - * Remove just forgets about any handler associated with format. Add does not - * copy format, it points at the string storage allocated by the caller, which - * is typically a string constant. If format is in dynamic storage, it is up - * to the caller to keep the string alive until Remove is called. - */ -extern JS_PUBLIC_API(JSBool) -JS_AddArgumentFormatter(JSContext *cx, const char *format, - JSArgumentFormatter formatter); - -extern JS_PUBLIC_API(void) -JS_RemoveArgumentFormatter(JSContext *cx, const char *format); - -#endif /* JS_ARGUMENT_FORMATTER_DEFINED */ - -extern JS_PUBLIC_API(JSBool) -JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp); - -extern JS_PUBLIC_API(JSBool) -JS_ValueToObject(JSContext *cx, jsval v, JSObject **objp); - -extern JS_PUBLIC_API(JSFunction *) -JS_ValueToFunction(JSContext *cx, jsval v); - -extern JS_PUBLIC_API(JSFunction *) -JS_ValueToConstructor(JSContext *cx, jsval v); - -extern JS_PUBLIC_API(JSString *) -JS_ValueToString(JSContext *cx, jsval v); - -extern JS_PUBLIC_API(JSBool) -JS_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp); - -/* - * Convert a value to a number, then to an int32, according to the ECMA rules - * for ToInt32. - */ -extern JS_PUBLIC_API(JSBool) -JS_ValueToECMAInt32(JSContext *cx, jsval v, int32 *ip); - -/* - * Convert a value to a number, then to a uint32, according to the ECMA rules - * for ToUint32. - */ -extern JS_PUBLIC_API(JSBool) -JS_ValueToECMAUint32(JSContext *cx, jsval v, uint32 *ip); - -/* - * Convert a value to a number, then to an int32 if it fits by rounding to - * nearest; but failing with an error report if the double is out of range - * or unordered. - */ -extern JS_PUBLIC_API(JSBool) -JS_ValueToInt32(JSContext *cx, jsval v, int32 *ip); - -/* - * ECMA ToUint16, for mapping a jsval to a Unicode point. - */ -extern JS_PUBLIC_API(JSBool) -JS_ValueToUint16(JSContext *cx, jsval v, uint16 *ip); - -extern JS_PUBLIC_API(JSBool) -JS_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp); - -extern JS_PUBLIC_API(JSType) -JS_TypeOfValue(JSContext *cx, jsval v); - -extern JS_PUBLIC_API(const char *) -JS_GetTypeName(JSContext *cx, JSType type); - -/************************************************************************/ - -/* - * Initialization, locking, contexts, and memory allocation. - */ -#define JS_NewRuntime JS_Init -#define JS_DestroyRuntime JS_Finish -#define JS_LockRuntime JS_Lock -#define JS_UnlockRuntime JS_Unlock - -extern JS_PUBLIC_API(JSRuntime *) -JS_NewRuntime(uint32 maxbytes); - -extern JS_PUBLIC_API(void) -JS_DestroyRuntime(JSRuntime *rt); - -extern JS_PUBLIC_API(void) -JS_ShutDown(void); - -JS_PUBLIC_API(void *) -JS_GetRuntimePrivate(JSRuntime *rt); - -JS_PUBLIC_API(void) -JS_SetRuntimePrivate(JSRuntime *rt, void *data); - -#ifdef JS_THREADSAFE - -extern JS_PUBLIC_API(void) -JS_BeginRequest(JSContext *cx); - -extern JS_PUBLIC_API(void) -JS_EndRequest(JSContext *cx); - -/* Yield to pending GC operations, regardless of request depth */ -extern JS_PUBLIC_API(void) -JS_YieldRequest(JSContext *cx); - -extern JS_PUBLIC_API(jsrefcount) -JS_SuspendRequest(JSContext *cx); - -extern JS_PUBLIC_API(void) -JS_ResumeRequest(JSContext *cx, jsrefcount saveDepth); - -#endif /* JS_THREADSAFE */ - -extern JS_PUBLIC_API(void) -JS_Lock(JSRuntime *rt); - -extern JS_PUBLIC_API(void) -JS_Unlock(JSRuntime *rt); - -extern JS_PUBLIC_API(JSContext *) -JS_NewContext(JSRuntime *rt, size_t stackChunkSize); - -extern JS_PUBLIC_API(void) -JS_DestroyContext(JSContext *cx); - -extern JS_PUBLIC_API(void) -JS_DestroyContextNoGC(JSContext *cx); - -extern JS_PUBLIC_API(void) -JS_DestroyContextMaybeGC(JSContext *cx); - -extern JS_PUBLIC_API(void *) -JS_GetContextPrivate(JSContext *cx); - -extern JS_PUBLIC_API(void) -JS_SetContextPrivate(JSContext *cx, void *data); - -extern JS_PUBLIC_API(JSRuntime *) -JS_GetRuntime(JSContext *cx); - -extern JS_PUBLIC_API(JSContext *) -JS_ContextIterator(JSRuntime *rt, JSContext **iterp); - -extern JS_PUBLIC_API(JSVersion) -JS_GetVersion(JSContext *cx); - -extern JS_PUBLIC_API(JSVersion) -JS_SetVersion(JSContext *cx, JSVersion version); - -extern JS_PUBLIC_API(const char *) -JS_VersionToString(JSVersion version); - -extern JS_PUBLIC_API(JSVersion) -JS_StringToVersion(const char *string); - -/* - * JS options are orthogonal to version, and may be freely composed with one - * another as well as with version. - * - * JSOPTION_VAROBJFIX is recommended -- see the comments associated with the - * prototypes for JS_ExecuteScript, JS_EvaluateScript, etc. - */ -#define JSOPTION_STRICT JS_BIT(0) /* warn on dubious practice */ -#define JSOPTION_WERROR JS_BIT(1) /* convert warning to error */ -#define JSOPTION_VAROBJFIX JS_BIT(2) /* make JS_EvaluateScript use - the last object on its 'obj' - param's scope chain as the - ECMA 'variables object' */ -#define JSOPTION_PRIVATE_IS_NSISUPPORTS \ - JS_BIT(3) /* context private data points - to an nsISupports subclass */ -#define JSOPTION_COMPILE_N_GO JS_BIT(4) /* caller of JS_Compile*Script - promises to execute compiled - script once only; enables - compile-time scope chain - resolution of consts. */ -#define JSOPTION_ATLINE JS_BIT(5) /* //@line number ["filename"] - option supported for the - XUL preprocessor and kindred - beasts. */ -#define JSOPTION_XML JS_BIT(6) /* EMCAScript for XML support: - parse as a token, - not backward compatible with - the comment-hiding hack used - in HTML script tags. */ -#define JSOPTION_NATIVE_BRANCH_CALLBACK \ - JS_BIT(7) /* the branch callback set by - JS_SetBranchCallback may be - called with a null script - parameter, by native code - that loops intensively */ - -extern JS_PUBLIC_API(uint32) -JS_GetOptions(JSContext *cx); - -extern JS_PUBLIC_API(uint32) -JS_SetOptions(JSContext *cx, uint32 options); - -extern JS_PUBLIC_API(uint32) -JS_ToggleOptions(JSContext *cx, uint32 options); - -extern JS_PUBLIC_API(const char *) -JS_GetImplementationVersion(void); - -extern JS_PUBLIC_API(JSObject *) -JS_GetGlobalObject(JSContext *cx); - -extern JS_PUBLIC_API(void) -JS_SetGlobalObject(JSContext *cx, JSObject *obj); - -/* - * Initialize standard JS class constructors, prototypes, and any top-level - * functions and constants associated with the standard classes (e.g. isNaN - * for Number). - * - * NB: This sets cx's global object to obj if it was null. - */ -extern JS_PUBLIC_API(JSBool) -JS_InitStandardClasses(JSContext *cx, JSObject *obj); - -/* - * Resolve id, which must contain either a string or an int, to a standard - * class name in obj if possible, defining the class's constructor and/or - * prototype and storing true in *resolved. If id does not name a standard - * class or a top-level property induced by initializing a standard class, - * store false in *resolved and just return true. Return false on error, - * as usual for JSBool result-typed API entry points. - * - * This API can be called directly from a global object class's resolve op, - * to define standard classes lazily. The class's enumerate op should call - * JS_EnumerateStandardClasses(cx, obj), to define eagerly during for..in - * loops any classes not yet resolved lazily. - */ -extern JS_PUBLIC_API(JSBool) -JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsval id, - JSBool *resolved); - -extern JS_PUBLIC_API(JSBool) -JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj); - -/* - * Enumerate any already-resolved standard class ids into ida, or into a new - * JSIdArray if ida is null. Return the augmented array on success, null on - * failure with ida (if it was non-null on entry) destroyed. - */ -extern JS_PUBLIC_API(JSIdArray *) -JS_EnumerateResolvedStandardClasses(JSContext *cx, JSObject *obj, - JSIdArray *ida); - -extern JS_PUBLIC_API(JSObject *) -JS_GetScopeChain(JSContext *cx); - -extern JS_PUBLIC_API(void *) -JS_malloc(JSContext *cx, size_t nbytes); - -extern JS_PUBLIC_API(void *) -JS_realloc(JSContext *cx, void *p, size_t nbytes); - -extern JS_PUBLIC_API(void) -JS_free(JSContext *cx, void *p); - -extern JS_PUBLIC_API(char *) -JS_strdup(JSContext *cx, const char *s); - -extern JS_PUBLIC_API(jsdouble *) -JS_NewDouble(JSContext *cx, jsdouble d); - -extern JS_PUBLIC_API(JSBool) -JS_NewDoubleValue(JSContext *cx, jsdouble d, jsval *rval); - -extern JS_PUBLIC_API(JSBool) -JS_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval); - -/* - * A JS GC root is a pointer to a JSObject *, JSString *, or jsdouble * that - * itself points into the GC heap (more recently, we support this extension: - * a root may be a pointer to a jsval v for which JSVAL_IS_GCTHING(v) is true). - * - * Therefore, you never pass JSObject *obj to JS_AddRoot(cx, obj). You always - * call JS_AddRoot(cx, &obj), passing obj by reference. And later, before obj - * or the structure it is embedded within goes out of scope or is freed, you - * must call JS_RemoveRoot(cx, &obj). - * - * Also, use JS_AddNamedRoot(cx, &structPtr->memberObj, "structPtr->memberObj") - * in preference to JS_AddRoot(cx, &structPtr->memberObj), in order to identify - * roots by their source callsites. This way, you can find the callsite while - * debugging if you should fail to do JS_RemoveRoot(cx, &structPtr->memberObj) - * before freeing structPtr's memory. - */ -extern JS_PUBLIC_API(JSBool) -JS_AddRoot(JSContext *cx, void *rp); - -#ifdef NAME_ALL_GC_ROOTS -#define JS_DEFINE_TO_TOKEN(def) #def -#define JS_DEFINE_TO_STRING(def) JS_DEFINE_TO_TOKEN(def) -#define JS_AddRoot(cx,rp) JS_AddNamedRoot((cx), (rp), (__FILE__ ":" JS_TOKEN_TO_STRING(__LINE__)) -#endif - -extern JS_PUBLIC_API(JSBool) -JS_AddNamedRoot(JSContext *cx, void *rp, const char *name); - -extern JS_PUBLIC_API(JSBool) -JS_AddNamedRootRT(JSRuntime *rt, void *rp, const char *name); - -extern JS_PUBLIC_API(JSBool) -JS_RemoveRoot(JSContext *cx, void *rp); - -extern JS_PUBLIC_API(JSBool) -JS_RemoveRootRT(JSRuntime *rt, void *rp); - -/* - * The last GC thing of each type (object, string, double, external string - * types) created on a given context is kept alive until another thing of the - * same type is created, using a newborn root in the context. These newborn - * roots help native code protect newly-created GC-things from GC invocations - * activated before those things can be rooted using local or global roots. - * - * However, the newborn roots can also entrain great gobs of garbage, so the - * JS_GC entry point clears them for the context on which GC is being forced. - * Embeddings may need to do likewise for all contexts. - * - * See the scoped local root API immediately below for a better way to manage - * newborns in cases where native hooks (functions, getters, setters, etc.) - * create many GC-things, potentially without connecting them to predefined - * local roots such as *rval or argv[i] in an active native function. Using - * JS_EnterLocalRootScope disables updating of the context's per-gc-thing-type - * newborn roots, until control flow unwinds and leaves the outermost nesting - * local root scope. - */ -extern JS_PUBLIC_API(void) -JS_ClearNewbornRoots(JSContext *cx); - -/* - * Scoped local root management allows native functions, getter/setters, etc. - * to avoid worrying about the newborn root pigeon-holes, overloading local - * roots allocated in argv and *rval, or ending up having to call JS_Add*Root - * and JS_RemoveRoot to manage global roots temporarily. - * - * Instead, calling JS_EnterLocalRootScope and JS_LeaveLocalRootScope around - * the body of the native hook causes the engine to allocate a local root for - * each newborn created in between the two API calls, using a local root stack - * associated with cx. For example: - * - * JSBool - * my_GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) - * { - * JSBool ok; - * - * if (!JS_EnterLocalRootScope(cx)) - * return JS_FALSE; - * ok = my_GetPropertyBody(cx, obj, id, vp); - * JS_LeaveLocalRootScope(cx); - * return ok; - * } - * - * NB: JS_LeaveLocalRootScope must be called once for every prior successful - * call to JS_EnterLocalRootScope. If JS_EnterLocalRootScope fails, you must - * not make the matching JS_LeaveLocalRootScope call. - * - * In case a native hook allocates many objects or other GC-things, but the - * native protects some of those GC-things by storing them as property values - * in an object that is itself protected, the hook can call JS_ForgetLocalRoot - * to free the local root automatically pushed for the now-protected GC-thing. - * - * JS_ForgetLocalRoot works on any GC-thing allocated in the current local - * root scope, but it's more time-efficient when called on references to more - * recently created GC-things. Calling it successively on other than the most - * recently allocated GC-thing will tend to average the time inefficiency, and - * may risk O(n^2) growth rate, but in any event, you shouldn't allocate too - * many local roots if you can root as you go (build a tree of objects from - * the top down, forgetting each latest-allocated GC-thing immediately upon - * linking it to its parent). - */ -extern JS_PUBLIC_API(JSBool) -JS_EnterLocalRootScope(JSContext *cx); - -extern JS_PUBLIC_API(void) -JS_LeaveLocalRootScope(JSContext *cx); - -extern JS_PUBLIC_API(void) -JS_ForgetLocalRoot(JSContext *cx, void *thing); - -#ifdef DEBUG -extern JS_PUBLIC_API(void) -JS_DumpNamedRoots(JSRuntime *rt, - void (*dump)(const char *name, void *rp, void *data), - void *data); -#endif - -/* - * Call JS_MapGCRoots to map the GC's roots table using map(rp, name, data). - * The root is pointed at by rp; if the root is unnamed, name is null; data is - * supplied from the third parameter to JS_MapGCRoots. - * - * The map function should return JS_MAP_GCROOT_REMOVE to cause the currently - * enumerated root to be removed. To stop enumeration, set JS_MAP_GCROOT_STOP - * in the return value. To keep on mapping, return JS_MAP_GCROOT_NEXT. These - * constants are flags; you can OR them together. - * - * This function acquires and releases rt's GC lock around the mapping of the - * roots table, so the map function should run to completion in as few cycles - * as possible. Of course, map cannot call JS_GC, JS_MaybeGC, JS_BeginRequest, - * or any JS API entry point that acquires locks, without double-tripping or - * deadlocking on the GC lock. - * - * JS_MapGCRoots returns the count of roots that were successfully mapped. - */ -#define JS_MAP_GCROOT_NEXT 0 /* continue mapping entries */ -#define JS_MAP_GCROOT_STOP 1 /* stop mapping entries */ -#define JS_MAP_GCROOT_REMOVE 2 /* remove and free the current entry */ - -typedef intN -(* JS_DLL_CALLBACK JSGCRootMapFun)(void *rp, const char *name, void *data); - -extern JS_PUBLIC_API(uint32) -JS_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data); - -extern JS_PUBLIC_API(JSBool) -JS_LockGCThing(JSContext *cx, void *thing); - -extern JS_PUBLIC_API(JSBool) -JS_LockGCThingRT(JSRuntime *rt, void *thing); - -extern JS_PUBLIC_API(JSBool) -JS_UnlockGCThing(JSContext *cx, void *thing); - -extern JS_PUBLIC_API(JSBool) -JS_UnlockGCThingRT(JSRuntime *rt, void *thing); - -/* - * For implementors of JSObjectOps.mark, to mark a GC-thing reachable via a - * property or other strong ref identified for debugging purposes by name. - * The name argument's storage needs to live only as long as the call to - * this routine. - * - * The final arg is used by GC_MARK_DEBUG code to build a ref path through - * the GC's live thing graph. Implementors of JSObjectOps.mark should pass - * its final arg through to this function when marking all GC-things that are - * directly reachable from the object being marked. - * - * See the JSMarkOp typedef in jspubtd.h, and the JSObjectOps struct below. - */ -extern JS_PUBLIC_API(void) -JS_MarkGCThing(JSContext *cx, void *thing, const char *name, void *arg); - -extern JS_PUBLIC_API(void) -JS_GC(JSContext *cx); - -extern JS_PUBLIC_API(void) -JS_MaybeGC(JSContext *cx); - -extern JS_PUBLIC_API(JSGCCallback) -JS_SetGCCallback(JSContext *cx, JSGCCallback cb); - -extern JS_PUBLIC_API(JSGCCallback) -JS_SetGCCallbackRT(JSRuntime *rt, JSGCCallback cb); - -extern JS_PUBLIC_API(JSBool) -JS_IsAboutToBeFinalized(JSContext *cx, void *thing); - -typedef enum JSGCParamKey { - JSGC_MAX_BYTES = 0, /* maximum nominal heap before last ditch GC */ - JSGC_MAX_MALLOC_BYTES = 1 /* # of JS_malloc bytes before last ditch GC */ -} JSGCParamKey; - -extern JS_PUBLIC_API(void) -JS_SetGCParameter(JSRuntime *rt, JSGCParamKey key, uint32 value); - -/* - * Add a finalizer for external strings created by JS_NewExternalString (see - * below) using a type-code returned from this function, and that understands - * how to free or release the memory pointed at by JS_GetStringChars(str). - * - * Return a nonnegative type index if there is room for finalizer in the - * global GC finalizers table, else return -1. If the engine is compiled - * JS_THREADSAFE and used in a multi-threaded environment, this function must - * be invoked on the primordial thread only, at startup -- or else the entire - * program must single-thread itself while loading a module that calls this - * function. - */ -extern JS_PUBLIC_API(intN) -JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer); - -/* - * Remove finalizer from the global GC finalizers table, returning its type - * code if found, -1 if not found. - * - * As with JS_AddExternalStringFinalizer, there is a threading restriction - * if you compile the engine JS_THREADSAFE: this function may be called for a - * given finalizer pointer on only one thread; different threads may call to - * remove distinct finalizers safely. - * - * You must ensure that all strings with finalizer's type have been collected - * before calling this function. Otherwise, string data will be leaked by the - * GC, for want of a finalizer to call. - */ -extern JS_PUBLIC_API(intN) -JS_RemoveExternalStringFinalizer(JSStringFinalizeOp finalizer); - -/* - * Create a new JSString whose chars member refers to external memory, i.e., - * memory requiring special, type-specific finalization. The type code must - * be a nonnegative return value from JS_AddExternalStringFinalizer. - */ -extern JS_PUBLIC_API(JSString *) -JS_NewExternalString(JSContext *cx, jschar *chars, size_t length, intN type); - -/* - * Returns the external-string finalizer index for this string, or -1 if it is - * an "internal" (native to JS engine) string. - */ -extern JS_PUBLIC_API(intN) -JS_GetExternalStringGCType(JSRuntime *rt, JSString *str); - -/* - * Sets maximum (if stack grows upward) or minimum (downward) legal stack byte - * address in limitAddr for the thread or process stack used by cx. To disable - * stack size checking, pass 0 for limitAddr. - */ -extern JS_PUBLIC_API(void) -JS_SetThreadStackLimit(JSContext *cx, jsuword limitAddr); - -/************************************************************************/ - -/* - * Classes, objects, and properties. - */ - -/* For detailed comments on the function pointer types, see jspubtd.h. */ -struct JSClass { - const char *name; - uint32 flags; - - /* Mandatory non-null function pointer members. */ - JSPropertyOp addProperty; - JSPropertyOp delProperty; - JSPropertyOp getProperty; - JSPropertyOp setProperty; - JSEnumerateOp enumerate; - JSResolveOp resolve; - JSConvertOp convert; - JSFinalizeOp finalize; - - /* Optionally non-null members start here. */ - JSGetObjectOps getObjectOps; - JSCheckAccessOp checkAccess; - JSNative call; - JSNative construct; - JSXDRObjectOp xdrObject; - JSHasInstanceOp hasInstance; - JSMarkOp mark; - JSReserveSlotsOp reserveSlots; -}; - -struct JSExtendedClass { - JSClass base; - JSEqualityOp equality; - JSObjectOp outerObject; - JSObjectOp innerObject; - jsword reserved0; - jsword reserved1; - jsword reserved2; - jsword reserved3; - jsword reserved4; -}; - -#define JSCLASS_HAS_PRIVATE (1<<0) /* objects have private slot */ -#define JSCLASS_NEW_ENUMERATE (1<<1) /* has JSNewEnumerateOp hook */ -#define JSCLASS_NEW_RESOLVE (1<<2) /* has JSNewResolveOp hook */ -#define JSCLASS_PRIVATE_IS_NSISUPPORTS (1<<3) /* private is (nsISupports *) */ -#define JSCLASS_SHARE_ALL_PROPERTIES (1<<4) /* all properties are SHARED */ -#define JSCLASS_NEW_RESOLVE_GETS_START (1<<5) /* JSNewResolveOp gets starting - object in prototype chain - passed in via *objp in/out - parameter */ -#define JSCLASS_CONSTRUCT_PROTOTYPE (1<<6) /* call constructor on class - prototype */ -#define JSCLASS_DOCUMENT_OBSERVER (1<<7) /* DOM document observer */ - -/* - * To reserve slots fetched and stored via JS_Get/SetReservedSlot, bitwise-or - * JSCLASS_HAS_RESERVED_SLOTS(n) into the initializer for JSClass.flags, where - * n is a constant in [1, 255]. Reserved slots are indexed from 0 to n-1. - */ -#define JSCLASS_RESERVED_SLOTS_SHIFT 8 /* room for 8 flags below */ -#define JSCLASS_RESERVED_SLOTS_WIDTH 8 /* and 16 above this field */ -#define JSCLASS_RESERVED_SLOTS_MASK JS_BITMASK(JSCLASS_RESERVED_SLOTS_WIDTH) -#define JSCLASS_HAS_RESERVED_SLOTS(n) (((n) & JSCLASS_RESERVED_SLOTS_MASK) \ - << JSCLASS_RESERVED_SLOTS_SHIFT) -#define JSCLASS_RESERVED_SLOTS(clasp) (((clasp)->flags \ - >> JSCLASS_RESERVED_SLOTS_SHIFT) \ - & JSCLASS_RESERVED_SLOTS_MASK) - -#define JSCLASS_HIGH_FLAGS_SHIFT (JSCLASS_RESERVED_SLOTS_SHIFT + \ - JSCLASS_RESERVED_SLOTS_WIDTH) - -/* True if JSClass is really a JSExtendedClass. */ -#define JSCLASS_IS_EXTENDED (1<<(JSCLASS_HIGH_FLAGS_SHIFT+0)) - -/* Initializer for unused members of statically initialized JSClass structs. */ -#define JSCLASS_NO_OPTIONAL_MEMBERS 0,0,0,0,0,0,0,0 -#define JSCLASS_NO_RESERVED_MEMBERS 0,0,0,0,0 - -/* For detailed comments on these function pointer types, see jspubtd.h. */ -struct JSObjectOps { - /* Mandatory non-null function pointer members. */ - JSNewObjectMapOp newObjectMap; - JSObjectMapOp destroyObjectMap; - JSLookupPropOp lookupProperty; - JSDefinePropOp defineProperty; - JSPropertyIdOp getProperty; - JSPropertyIdOp setProperty; - JSAttributesOp getAttributes; - JSAttributesOp setAttributes; - JSPropertyIdOp deleteProperty; - JSConvertOp defaultValue; - JSNewEnumerateOp enumerate; - JSCheckAccessIdOp checkAccess; - - /* Optionally non-null members start here. */ - JSObjectOp thisObject; - JSPropertyRefOp dropProperty; - JSNative call; - JSNative construct; - JSXDRObjectOp xdrObject; - JSHasInstanceOp hasInstance; - JSSetObjectSlotOp setProto; - JSSetObjectSlotOp setParent; - JSMarkOp mark; - JSFinalizeOp clear; - JSGetRequiredSlotOp getRequiredSlot; - JSSetRequiredSlotOp setRequiredSlot; -}; - -struct JSXMLObjectOps { - JSObjectOps base; - JSGetMethodOp getMethod; - JSSetMethodOp setMethod; - JSEnumerateValuesOp enumerateValues; - JSEqualityOp equality; - JSConcatenateOp concatenate; -}; - -/* - * Classes that expose JSObjectOps via a non-null getObjectOps class hook may - * derive a property structure from this struct, return a pointer to it from - * lookupProperty and defineProperty, and use the pointer to avoid rehashing - * in getAttributes and setAttributes. - * - * The jsid type contains either an int jsval (see JSVAL_IS_INT above), or an - * internal pointer that is opaque to users of this API, but which users may - * convert from and to a jsval using JS_ValueToId and JS_IdToValue. - */ -struct JSProperty { - jsid id; -}; - -struct JSIdArray { - jsint length; - jsid vector[1]; /* actually, length jsid words */ -}; - -extern JS_PUBLIC_API(void) -JS_DestroyIdArray(JSContext *cx, JSIdArray *ida); - -extern JS_PUBLIC_API(JSBool) -JS_ValueToId(JSContext *cx, jsval v, jsid *idp); - -extern JS_PUBLIC_API(JSBool) -JS_IdToValue(JSContext *cx, jsid id, jsval *vp); - -/* - * The magic XML namespace id is int-tagged, but not a valid integer jsval. - * Global object classes in embeddings that enable JS_HAS_XML_SUPPORT (E4X) - * should handle this id specially before converting id via JSVAL_TO_INT. - */ -#define JS_DEFAULT_XML_NAMESPACE_ID ((jsid) JSVAL_VOID) - -/* - * JSNewResolveOp flag bits. - */ -#define JSRESOLVE_QUALIFIED 0x01 /* resolve a qualified property id */ -#define JSRESOLVE_ASSIGNING 0x02 /* resolve on the left of assignment */ -#define JSRESOLVE_DETECTING 0x04 /* 'if (o.p)...' or '(o.p) ?...:...' */ -#define JSRESOLVE_DECLARING 0x08 /* var, const, or function prolog op */ -#define JSRESOLVE_CLASSNAME 0x10 /* class name used when constructing */ - -extern JS_PUBLIC_API(JSBool) -JS_PropertyStub(JSContext *cx, JSObject *obj, jsval id, jsval *vp); - -extern JS_PUBLIC_API(JSBool) -JS_EnumerateStub(JSContext *cx, JSObject *obj); - -extern JS_PUBLIC_API(JSBool) -JS_ResolveStub(JSContext *cx, JSObject *obj, jsval id); - -extern JS_PUBLIC_API(JSBool) -JS_ConvertStub(JSContext *cx, JSObject *obj, JSType type, jsval *vp); - -extern JS_PUBLIC_API(void) -JS_FinalizeStub(JSContext *cx, JSObject *obj); - -struct JSConstDoubleSpec { - jsdouble dval; - const char *name; - uint8 flags; - uint8 spare[3]; -}; - -/* - * To define an array element rather than a named property member, cast the - * element's index to (const char *) and initialize name with it, and set the - * JSPROP_INDEX bit in flags. - */ -struct JSPropertySpec { - const char *name; - int8 tinyid; - uint8 flags; - JSPropertyOp getter; - JSPropertyOp setter; -}; - -struct JSFunctionSpec { - const char *name; - JSNative call; - uint8 nargs; - uint8 flags; - uint16 extra; /* number of arg slots for local GC roots */ -}; - -extern JS_PUBLIC_API(JSObject *) -JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto, - JSClass *clasp, JSNative constructor, uintN nargs, - JSPropertySpec *ps, JSFunctionSpec *fs, - JSPropertySpec *static_ps, JSFunctionSpec *static_fs); - -#ifdef JS_THREADSAFE -extern JS_PUBLIC_API(JSClass *) -JS_GetClass(JSContext *cx, JSObject *obj); - -#define JS_GET_CLASS(cx,obj) JS_GetClass(cx, obj) -#else -extern JS_PUBLIC_API(JSClass *) -JS_GetClass(JSObject *obj); - -#define JS_GET_CLASS(cx,obj) JS_GetClass(obj) -#endif - -extern JS_PUBLIC_API(JSBool) -JS_InstanceOf(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv); - -extern JS_PUBLIC_API(JSBool) -JS_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp); - -extern JS_PUBLIC_API(void *) -JS_GetPrivate(JSContext *cx, JSObject *obj); - -extern JS_PUBLIC_API(JSBool) -JS_SetPrivate(JSContext *cx, JSObject *obj, void *data); - -extern JS_PUBLIC_API(void *) -JS_GetInstancePrivate(JSContext *cx, JSObject *obj, JSClass *clasp, - jsval *argv); - -extern JS_PUBLIC_API(JSObject *) -JS_GetPrototype(JSContext *cx, JSObject *obj); - -extern JS_PUBLIC_API(JSBool) -JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto); - -extern JS_PUBLIC_API(JSObject *) -JS_GetParent(JSContext *cx, JSObject *obj); - -extern JS_PUBLIC_API(JSBool) -JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent); - -extern JS_PUBLIC_API(JSObject *) -JS_GetConstructor(JSContext *cx, JSObject *proto); - -/* - * Get a unique identifier for obj, good for the lifetime of obj (even if it - * is moved by a copying GC). Return false on failure (likely out of memory), - * and true with *idp containing the unique id on success. - */ -extern JS_PUBLIC_API(JSBool) -JS_GetObjectId(JSContext *cx, JSObject *obj, jsid *idp); - -extern JS_PUBLIC_API(JSObject *) -JS_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent); - -extern JS_PUBLIC_API(JSBool) -JS_SealObject(JSContext *cx, JSObject *obj, JSBool deep); - -extern JS_PUBLIC_API(JSObject *) -JS_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto, - JSObject *parent); - -extern JS_PUBLIC_API(JSObject *) -JS_ConstructObjectWithArguments(JSContext *cx, JSClass *clasp, JSObject *proto, - JSObject *parent, uintN argc, jsval *argv); - -extern JS_PUBLIC_API(JSObject *) -JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *clasp, - JSObject *proto, uintN attrs); - -extern JS_PUBLIC_API(JSBool) -JS_DefineConstDoubles(JSContext *cx, JSObject *obj, JSConstDoubleSpec *cds); - -extern JS_PUBLIC_API(JSBool) -JS_DefineProperties(JSContext *cx, JSObject *obj, JSPropertySpec *ps); - -extern JS_PUBLIC_API(JSBool) -JS_DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value, - JSPropertyOp getter, JSPropertyOp setter, uintN attrs); - -/* - * Determine the attributes (JSPROP_* flags) of a property on a given object. - * - * If the object does not have a property by that name, *foundp will be - * JS_FALSE and the value of *attrsp is undefined. - */ -extern JS_PUBLIC_API(JSBool) -JS_GetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name, - uintN *attrsp, JSBool *foundp); - -/* - * The same, but if the property is native, return its getter and setter via - * *getterp and *setterp, respectively (and only if the out parameter pointer - * is not null). - */ -extern JS_PUBLIC_API(JSBool) -JS_GetPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj, - const char *name, - uintN *attrsp, JSBool *foundp, - JSPropertyOp *getterp, - JSPropertyOp *setterp); - -/* - * Set the attributes of a property on a given object. - * - * If the object does not have a property by that name, *foundp will be - * JS_FALSE and nothing will be altered. - */ -extern JS_PUBLIC_API(JSBool) -JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name, - uintN attrs, JSBool *foundp); - -extern JS_PUBLIC_API(JSBool) -JS_DefinePropertyWithTinyId(JSContext *cx, JSObject *obj, const char *name, - int8 tinyid, jsval value, - JSPropertyOp getter, JSPropertyOp setter, - uintN attrs); - -extern JS_PUBLIC_API(JSBool) -JS_AliasProperty(JSContext *cx, JSObject *obj, const char *name, - const char *alias); - -extern JS_PUBLIC_API(JSBool) -JS_HasProperty(JSContext *cx, JSObject *obj, const char *name, JSBool *foundp); - -extern JS_PUBLIC_API(JSBool) -JS_LookupProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp); - -extern JS_PUBLIC_API(JSBool) -JS_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, const char *name, - uintN flags, jsval *vp); - -extern JS_PUBLIC_API(JSBool) -JS_GetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp); - -extern JS_PUBLIC_API(JSBool) -JS_GetMethod(JSContext *cx, JSObject *obj, const char *name, JSObject **objp, - jsval *vp); - -extern JS_PUBLIC_API(JSBool) -JS_SetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp); - -extern JS_PUBLIC_API(JSBool) -JS_DeleteProperty(JSContext *cx, JSObject *obj, const char *name); - -extern JS_PUBLIC_API(JSBool) -JS_DeleteProperty2(JSContext *cx, JSObject *obj, const char *name, - jsval *rval); - -extern JS_PUBLIC_API(JSBool) -JS_DefineUCProperty(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, jsval value, - JSPropertyOp getter, JSPropertyOp setter, - uintN attrs); - -/* - * Determine the attributes (JSPROP_* flags) of a property on a given object. - * - * If the object does not have a property by that name, *foundp will be - * JS_FALSE and the value of *attrsp is undefined. - */ -extern JS_PUBLIC_API(JSBool) -JS_GetUCPropertyAttributes(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, - uintN *attrsp, JSBool *foundp); - -/* - * The same, but if the property is native, return its getter and setter via - * *getterp and *setterp, respectively (and only if the out parameter pointer - * is not null). - */ -extern JS_PUBLIC_API(JSBool) -JS_GetUCPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, - uintN *attrsp, JSBool *foundp, - JSPropertyOp *getterp, - JSPropertyOp *setterp); - -/* - * Set the attributes of a property on a given object. - * - * If the object does not have a property by that name, *foundp will be - * JS_FALSE and nothing will be altered. - */ -extern JS_PUBLIC_API(JSBool) -JS_SetUCPropertyAttributes(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, - uintN attrs, JSBool *foundp); - - -extern JS_PUBLIC_API(JSBool) -JS_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, - int8 tinyid, jsval value, - JSPropertyOp getter, JSPropertyOp setter, - uintN attrs); - -extern JS_PUBLIC_API(JSBool) -JS_HasUCProperty(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, - JSBool *vp); - -extern JS_PUBLIC_API(JSBool) -JS_LookupUCProperty(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, - jsval *vp); - -extern JS_PUBLIC_API(JSBool) -JS_GetUCProperty(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, - jsval *vp); - -extern JS_PUBLIC_API(JSBool) -JS_SetUCProperty(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, - jsval *vp); - -extern JS_PUBLIC_API(JSBool) -JS_DeleteUCProperty2(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, - jsval *rval); - -extern JS_PUBLIC_API(JSObject *) -JS_NewArrayObject(JSContext *cx, jsint length, jsval *vector); - -extern JS_PUBLIC_API(JSBool) -JS_IsArrayObject(JSContext *cx, JSObject *obj); - -extern JS_PUBLIC_API(JSBool) -JS_GetArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp); - -extern JS_PUBLIC_API(JSBool) -JS_SetArrayLength(JSContext *cx, JSObject *obj, jsuint length); - -extern JS_PUBLIC_API(JSBool) -JS_HasArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp); - -extern JS_PUBLIC_API(JSBool) -JS_DefineElement(JSContext *cx, JSObject *obj, jsint index, jsval value, - JSPropertyOp getter, JSPropertyOp setter, uintN attrs); - -extern JS_PUBLIC_API(JSBool) -JS_AliasElement(JSContext *cx, JSObject *obj, const char *name, jsint alias); - -extern JS_PUBLIC_API(JSBool) -JS_HasElement(JSContext *cx, JSObject *obj, jsint index, JSBool *foundp); - -extern JS_PUBLIC_API(JSBool) -JS_LookupElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp); - -extern JS_PUBLIC_API(JSBool) -JS_GetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp); - -extern JS_PUBLIC_API(JSBool) -JS_SetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp); - -extern JS_PUBLIC_API(JSBool) -JS_DeleteElement(JSContext *cx, JSObject *obj, jsint index); - -extern JS_PUBLIC_API(JSBool) -JS_DeleteElement2(JSContext *cx, JSObject *obj, jsint index, jsval *rval); - -extern JS_PUBLIC_API(void) -JS_ClearScope(JSContext *cx, JSObject *obj); - -extern JS_PUBLIC_API(JSIdArray *) -JS_Enumerate(JSContext *cx, JSObject *obj); - -/* - * Create an object to iterate over enumerable properties of obj, in arbitrary - * property definition order. NB: This differs from longstanding for..in loop - * order, which uses order of property definition in obj. - */ -extern JS_PUBLIC_API(JSObject *) -JS_NewPropertyIterator(JSContext *cx, JSObject *obj); - -/* - * Return true on success with *idp containing the id of the next enumerable - * property to visit using iterobj, or JSVAL_VOID if there is no such property - * left to visit. Return false on error. - */ -extern JS_PUBLIC_API(JSBool) -JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp); - -extern JS_PUBLIC_API(JSBool) -JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode, - jsval *vp, uintN *attrsp); - -extern JS_PUBLIC_API(JSCheckAccessOp) -JS_SetCheckObjectAccessCallback(JSRuntime *rt, JSCheckAccessOp acb); - -extern JS_PUBLIC_API(JSBool) -JS_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval *vp); - -extern JS_PUBLIC_API(JSBool) -JS_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval v); - -/************************************************************************/ - -/* - * Security protocol. - */ -struct JSPrincipals { - char *codebase; - - /* XXX unspecified and unused by Mozilla code -- can we remove these? */ - void * (* JS_DLL_CALLBACK getPrincipalArray)(JSContext *cx, JSPrincipals *); - JSBool (* JS_DLL_CALLBACK globalPrivilegesEnabled)(JSContext *cx, JSPrincipals *); - - /* Don't call "destroy"; use reference counting macros below. */ - jsrefcount refcount; - - void (* JS_DLL_CALLBACK destroy)(JSContext *cx, JSPrincipals *); - JSBool (* JS_DLL_CALLBACK subsume)(JSPrincipals *, JSPrincipals *); -}; - -#ifdef JS_THREADSAFE -#define JSPRINCIPALS_HOLD(cx, principals) JS_HoldPrincipals(cx,principals) -#define JSPRINCIPALS_DROP(cx, principals) JS_DropPrincipals(cx,principals) - -extern JS_PUBLIC_API(jsrefcount) -JS_HoldPrincipals(JSContext *cx, JSPrincipals *principals); - -extern JS_PUBLIC_API(jsrefcount) -JS_DropPrincipals(JSContext *cx, JSPrincipals *principals); - -#else -#define JSPRINCIPALS_HOLD(cx, principals) (++(principals)->refcount) -#define JSPRINCIPALS_DROP(cx, principals) \ - ((--(principals)->refcount == 0) \ - ? ((*(principals)->destroy)((cx), (principals)), 0) \ - : (principals)->refcount) -#endif - -extern JS_PUBLIC_API(JSPrincipalsTranscoder) -JS_SetPrincipalsTranscoder(JSRuntime *rt, JSPrincipalsTranscoder px); - -extern JS_PUBLIC_API(JSObjectPrincipalsFinder) -JS_SetObjectPrincipalsFinder(JSRuntime *rt, JSObjectPrincipalsFinder fop); - -/************************************************************************/ - -/* - * Functions and scripts. - */ -extern JS_PUBLIC_API(JSFunction *) -JS_NewFunction(JSContext *cx, JSNative call, uintN nargs, uintN flags, - JSObject *parent, const char *name); - -extern JS_PUBLIC_API(JSObject *) -JS_GetFunctionObject(JSFunction *fun); - -/* - * Deprecated, useful only for diagnostics. Use JS_GetFunctionId instead for - * anonymous vs. "anonymous" disambiguation and Unicode fidelity. - */ -extern JS_PUBLIC_API(const char *) -JS_GetFunctionName(JSFunction *fun); - -/* - * Return the function's identifier as a JSString, or null if fun is unnamed. - * The returned string lives as long as fun, so you don't need to root a saved - * reference to it if fun is well-connected or rooted, and provided you bound - * the use of the saved reference by fun's lifetime. - * - * Prefer JS_GetFunctionId over JS_GetFunctionName because it returns null for - * truly anonymous functions, and because it doesn't chop to ISO-Latin-1 chars - * from UTF-16-ish jschars. - */ -extern JS_PUBLIC_API(JSString *) -JS_GetFunctionId(JSFunction *fun); - -/* - * Return JSFUN_* flags for fun. - */ -extern JS_PUBLIC_API(uintN) -JS_GetFunctionFlags(JSFunction *fun); - -/* - * Return the arity (length) of fun. - */ -extern JS_PUBLIC_API(uint16) -JS_GetFunctionArity(JSFunction *fun); - -/* - * Infallible predicate to test whether obj is a function object (faster than - * comparing obj's class name to "Function", but equivalent unless someone has - * overwritten the "Function" identifier with a different constructor and then - * created instances using that constructor that might be passed in as obj). - */ -extern JS_PUBLIC_API(JSBool) -JS_ObjectIsFunction(JSContext *cx, JSObject *obj); - -extern JS_PUBLIC_API(JSBool) -JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs); - -extern JS_PUBLIC_API(JSFunction *) -JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call, - uintN nargs, uintN attrs); - -extern JS_PUBLIC_API(JSFunction *) -JS_DefineUCFunction(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, JSNative call, - uintN nargs, uintN attrs); - -extern JS_PUBLIC_API(JSObject *) -JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent); - -/* - * Given a buffer, return JS_FALSE if the buffer might become a valid - * javascript statement with the addition of more lines. Otherwise return - * JS_TRUE. The intent is to support interactive compilation - accumulate - * lines in a buffer until JS_BufferIsCompilableUnit is true, then pass it to - * the compiler. - */ -extern JS_PUBLIC_API(JSBool) -JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj, - const char *bytes, size_t length); - -/* - * The JSScript objects returned by the following functions refer to string and - * other kinds of literals, including doubles and RegExp objects. These - * literals are vulnerable to garbage collection; to root script objects and - * prevent literals from being collected, create a rootable object using - * JS_NewScriptObject, and root the resulting object using JS_Add[Named]Root. - */ -extern JS_PUBLIC_API(JSScript *) -JS_CompileScript(JSContext *cx, JSObject *obj, - const char *bytes, size_t length, - const char *filename, uintN lineno); - -extern JS_PUBLIC_API(JSScript *) -JS_CompileScriptForPrincipals(JSContext *cx, JSObject *obj, - JSPrincipals *principals, - const char *bytes, size_t length, - const char *filename, uintN lineno); - -extern JS_PUBLIC_API(JSScript *) -JS_CompileUCScript(JSContext *cx, JSObject *obj, - const jschar *chars, size_t length, - const char *filename, uintN lineno); - -extern JS_PUBLIC_API(JSScript *) -JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *obj, - JSPrincipals *principals, - const jschar *chars, size_t length, - const char *filename, uintN lineno); - -extern JS_PUBLIC_API(JSScript *) -JS_CompileFile(JSContext *cx, JSObject *obj, const char *filename); - -extern JS_PUBLIC_API(JSScript *) -JS_CompileFileHandle(JSContext *cx, JSObject *obj, const char *filename, - FILE *fh); - -extern JS_PUBLIC_API(JSScript *) -JS_CompileFileHandleForPrincipals(JSContext *cx, JSObject *obj, - const char *filename, FILE *fh, - JSPrincipals *principals); - -/* - * NB: you must use JS_NewScriptObject and root a pointer to its return value - * in order to keep a JSScript and its atoms safe from garbage collection after - * creating the script via JS_Compile* and before a JS_ExecuteScript* call. - * E.g., and without error checks: - * - * JSScript *script = JS_CompileFile(cx, global, filename); - * JSObject *scrobj = JS_NewScriptObject(cx, script); - * JS_AddNamedRoot(cx, &scrobj, "scrobj"); - * do { - * jsval result; - * JS_ExecuteScript(cx, global, script, &result); - * JS_GC(); - * } while (!JSVAL_IS_BOOLEAN(result) || JSVAL_TO_BOOLEAN(result)); - * JS_RemoveRoot(cx, &scrobj); - */ -extern JS_PUBLIC_API(JSObject *) -JS_NewScriptObject(JSContext *cx, JSScript *script); - -/* - * Infallible getter for a script's object. If JS_NewScriptObject has not been - * called on script yet, the return value will be null. - */ -extern JS_PUBLIC_API(JSObject *) -JS_GetScriptObject(JSScript *script); - -extern JS_PUBLIC_API(void) -JS_DestroyScript(JSContext *cx, JSScript *script); - -extern JS_PUBLIC_API(JSFunction *) -JS_CompileFunction(JSContext *cx, JSObject *obj, const char *name, - uintN nargs, const char **argnames, - const char *bytes, size_t length, - const char *filename, uintN lineno); - -extern JS_PUBLIC_API(JSFunction *) -JS_CompileFunctionForPrincipals(JSContext *cx, JSObject *obj, - JSPrincipals *principals, const char *name, - uintN nargs, const char **argnames, - const char *bytes, size_t length, - const char *filename, uintN lineno); - -extern JS_PUBLIC_API(JSFunction *) -JS_CompileUCFunction(JSContext *cx, JSObject *obj, const char *name, - uintN nargs, const char **argnames, - const jschar *chars, size_t length, - const char *filename, uintN lineno); - -extern JS_PUBLIC_API(JSFunction *) -JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj, - JSPrincipals *principals, const char *name, - uintN nargs, const char **argnames, - const jschar *chars, size_t length, - const char *filename, uintN lineno); - -extern JS_PUBLIC_API(JSString *) -JS_DecompileScript(JSContext *cx, JSScript *script, const char *name, - uintN indent); - -/* - * API extension: OR this into indent to avoid pretty-printing the decompiled - * source resulting from JS_DecompileFunction{,Body}. - */ -#define JS_DONT_PRETTY_PRINT ((uintN)0x8000) - -extern JS_PUBLIC_API(JSString *) -JS_DecompileFunction(JSContext *cx, JSFunction *fun, uintN indent); - -extern JS_PUBLIC_API(JSString *) -JS_DecompileFunctionBody(JSContext *cx, JSFunction *fun, uintN indent); - -/* - * NB: JS_ExecuteScript, JS_ExecuteScriptPart, and the JS_Evaluate*Script* - * quadruplets all use the obj parameter as the initial scope chain header, - * the 'this' keyword value, and the variables object (ECMA parlance for where - * 'var' and 'function' bind names) of the execution context for script. - * - * Using obj as the variables object is problematic if obj's parent (which is - * the scope chain link; see JS_SetParent and JS_NewObject) is not null: in - * this case, variables created by 'var x = 0', e.g., go in obj, but variables - * created by assignment to an unbound id, 'x = 0', go in the last object on - * the scope chain linked by parent. - * - * ECMA calls that last scoping object the "global object", but note that many - * embeddings have several such objects. ECMA requires that "global code" be - * executed with the variables object equal to this global object. But these - * JS API entry points provide freedom to execute code against a "sub-global", - * i.e., a parented or scoped object, in which case the variables object will - * differ from the last object on the scope chain, resulting in confusing and - * non-ECMA explicit vs. implicit variable creation. - * - * Caveat embedders: unless you already depend on this buggy variables object - * binding behavior, you should call JS_SetOptions(cx, JSOPTION_VAROBJFIX) or - * JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_VAROBJFIX) -- the latter if - * someone may have set other options on cx already -- for each context in the - * application, if you pass parented objects as the obj parameter, or may ever - * pass such objects in the future. - * - * Why a runtime option? The alternative is to add six or so new API entry - * points with signatures matching the following six, and that doesn't seem - * worth the code bloat cost. Such new entry points would probably have less - * obvious names, too, so would not tend to be used. The JS_SetOption call, - * OTOH, can be more easily hacked into existing code that does not depend on - * the bug; such code can continue to use the familiar JS_EvaluateScript, - * etc., entry points. - */ -extern JS_PUBLIC_API(JSBool) -JS_ExecuteScript(JSContext *cx, JSObject *obj, JSScript *script, jsval *rval); - -/* - * Execute either the function-defining prolog of a script, or the script's - * main body, but not both. - */ -typedef enum JSExecPart { JSEXEC_PROLOG, JSEXEC_MAIN } JSExecPart; - -extern JS_PUBLIC_API(JSBool) -JS_ExecuteScriptPart(JSContext *cx, JSObject *obj, JSScript *script, - JSExecPart part, jsval *rval); - -extern JS_PUBLIC_API(JSBool) -JS_EvaluateScript(JSContext *cx, JSObject *obj, - const char *bytes, uintN length, - const char *filename, uintN lineno, - jsval *rval); - -extern JS_PUBLIC_API(JSBool) -JS_EvaluateScriptForPrincipals(JSContext *cx, JSObject *obj, - JSPrincipals *principals, - const char *bytes, uintN length, - const char *filename, uintN lineno, - jsval *rval); - -extern JS_PUBLIC_API(JSBool) -JS_EvaluateUCScript(JSContext *cx, JSObject *obj, - const jschar *chars, uintN length, - const char *filename, uintN lineno, - jsval *rval); - -extern JS_PUBLIC_API(JSBool) -JS_EvaluateUCScriptForPrincipals(JSContext *cx, JSObject *obj, - JSPrincipals *principals, - const jschar *chars, uintN length, - const char *filename, uintN lineno, - jsval *rval); - -extern JS_PUBLIC_API(JSBool) -JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, uintN argc, - jsval *argv, jsval *rval); - -extern JS_PUBLIC_API(JSBool) -JS_CallFunctionName(JSContext *cx, JSObject *obj, const char *name, uintN argc, - jsval *argv, jsval *rval); - -extern JS_PUBLIC_API(JSBool) -JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, uintN argc, - jsval *argv, jsval *rval); - -extern JS_PUBLIC_API(JSBranchCallback) -JS_SetBranchCallback(JSContext *cx, JSBranchCallback cb); - -extern JS_PUBLIC_API(JSBool) -JS_IsRunning(JSContext *cx); - -extern JS_PUBLIC_API(JSBool) -JS_IsConstructing(JSContext *cx); - -/* - * Returns true if a script is executing and its current bytecode is a set - * (assignment) operation, even if there are native (no script) stack frames - * between the script and the caller to JS_IsAssigning. - */ -extern JS_FRIEND_API(JSBool) -JS_IsAssigning(JSContext *cx); - -/* - * Set the second return value, which should be a string or int jsval that - * identifies a property in the returned object, to form an ECMA reference - * type value (obj, id). Only native methods can return reference types, - * and if the returned value is used on the left-hand side of an assignment - * op, the identified property will be set. If the return value is in an - * r-value, the interpreter just gets obj[id]'s value. - */ -extern JS_PUBLIC_API(void) -JS_SetCallReturnValue2(JSContext *cx, jsval v); - -/************************************************************************/ - -/* - * Strings. - * - * NB: JS_NewString takes ownership of bytes on success, avoiding a copy; but - * on error (signified by null return), it leaves bytes owned by the caller. - * So the caller must free bytes in the error case, if it has no use for them. - * In contrast, all the JS_New*StringCopy* functions do not take ownership of - * the character memory passed to them -- they copy it. - */ -extern JS_PUBLIC_API(JSString *) -JS_NewString(JSContext *cx, char *bytes, size_t length); - -extern JS_PUBLIC_API(JSString *) -JS_NewStringCopyN(JSContext *cx, const char *s, size_t n); - -extern JS_PUBLIC_API(JSString *) -JS_NewStringCopyZ(JSContext *cx, const char *s); - -extern JS_PUBLIC_API(JSString *) -JS_InternString(JSContext *cx, const char *s); - -extern JS_PUBLIC_API(JSString *) -JS_NewUCString(JSContext *cx, jschar *chars, size_t length); - -extern JS_PUBLIC_API(JSString *) -JS_NewUCStringCopyN(JSContext *cx, const jschar *s, size_t n); - -extern JS_PUBLIC_API(JSString *) -JS_NewUCStringCopyZ(JSContext *cx, const jschar *s); - -extern JS_PUBLIC_API(JSString *) -JS_InternUCStringN(JSContext *cx, const jschar *s, size_t length); - -extern JS_PUBLIC_API(JSString *) -JS_InternUCString(JSContext *cx, const jschar *s); - -extern JS_PUBLIC_API(char *) -JS_GetStringBytes(JSString *str); - -extern JS_PUBLIC_API(jschar *) -JS_GetStringChars(JSString *str); - -extern JS_PUBLIC_API(size_t) -JS_GetStringLength(JSString *str); - -extern JS_PUBLIC_API(intN) -JS_CompareStrings(JSString *str1, JSString *str2); - -/* - * Mutable string support. A string's characters are never mutable in this JS - * implementation, but a growable string has a buffer that can be reallocated, - * and a dependent string is a substring of another (growable, dependent, or - * immutable) string. The direct data members of the (opaque to API clients) - * JSString struct may be changed in a single-threaded way for growable and - * dependent strings. - * - * Therefore mutable strings cannot be used by more than one thread at a time. - * You may call JS_MakeStringImmutable to convert the string from a mutable - * (growable or dependent) string to an immutable (and therefore thread-safe) - * string. The engine takes care of converting growable and dependent strings - * to immutable for you if you store strings in multi-threaded objects using - * JS_SetProperty or kindred API entry points. - * - * If you store a JSString pointer in a native data structure that is (safely) - * accessible to multiple threads, you must call JS_MakeStringImmutable before - * retiring the store. - */ -extern JS_PUBLIC_API(JSString *) -JS_NewGrowableString(JSContext *cx, jschar *chars, size_t length); - -/* - * Create a dependent string, i.e., a string that owns no character storage, - * but that refers to a slice of another string's chars. Dependent strings - * are mutable by definition, so the thread safety comments above apply. - */ -extern JS_PUBLIC_API(JSString *) -JS_NewDependentString(JSContext *cx, JSString *str, size_t start, - size_t length); - -/* - * Concatenate two strings, resulting in a new growable string. If you create - * the left string and pass it to JS_ConcatStrings on a single thread, try to - * use JS_NewGrowableString to create the left string -- doing so helps Concat - * avoid allocating a new buffer for the result and copying left's chars into - * the new buffer. See above for thread safety comments. - */ -extern JS_PUBLIC_API(JSString *) -JS_ConcatStrings(JSContext *cx, JSString *left, JSString *right); - -/* - * Convert a dependent string into an independent one. This function does not - * change the string's mutability, so the thread safety comments above apply. - */ -extern JS_PUBLIC_API(const jschar *) -JS_UndependString(JSContext *cx, JSString *str); - -/* - * Convert a mutable string (either growable or dependent) into an immutable, - * thread-safe one. - */ -extern JS_PUBLIC_API(JSBool) -JS_MakeStringImmutable(JSContext *cx, JSString *str); - -/* - * Return JS_TRUE if C (char []) strings passed via the API and internally - * are UTF-8. The source must be compiled with JS_C_STRINGS_ARE_UTF8 defined - * to get UTF-8 support. - */ -JS_PUBLIC_API(JSBool) -JS_StringsAreUTF8(); - -/* - * Character encoding support. - * - * For both JS_EncodeCharacters and JS_DecodeBytes, set *dstlenp to the size - * of the destination buffer before the call; on return, *dstlenp contains the - * number of bytes (JS_EncodeCharacters) or jschars (JS_DecodeBytes) actually - * stored. To determine the necessary destination buffer size, make a sizing - * call that passes NULL for dst. - * - * On errors, the functions report the error. In that case, *dstlenp contains - * the number of characters or bytes transferred so far. If cx is NULL, no - * error is reported on failure, and the functions simply return JS_FALSE. - * - * NB: Neither function stores an additional zero byte or jschar after the - * transcoded string. - * - * If the source has been compiled with the #define JS_C_STRINGS_ARE_UTF8 to - * enable UTF-8 interpretation of C char[] strings, then JS_EncodeCharacters - * encodes to UTF-8, and JS_DecodeBytes decodes from UTF-8, which may create - * addititional errors if the character sequence is malformed. If UTF-8 - * support is disabled, the functions deflate and inflate, respectively. - */ -JS_PUBLIC_API(JSBool) -JS_EncodeCharacters(JSContext *cx, const jschar *src, size_t srclen, char *dst, - size_t *dstlenp); - -JS_PUBLIC_API(JSBool) -JS_DecodeBytes(JSContext *cx, const char *src, size_t srclen, jschar *dst, - size_t *dstlenp); - -/************************************************************************/ - -/* - * Locale specific string conversion callback. - */ -struct JSLocaleCallbacks { - JSLocaleToUpperCase localeToUpperCase; - JSLocaleToLowerCase localeToLowerCase; - JSLocaleCompare localeCompare; - JSLocaleToUnicode localeToUnicode; -}; - -/* - * Establish locale callbacks. The pointer must persist as long as the - * JSContext. Passing NULL restores the default behaviour. - */ -extern JS_PUBLIC_API(void) -JS_SetLocaleCallbacks(JSContext *cx, JSLocaleCallbacks *callbacks); - -/* - * Return the address of the current locale callbacks struct, which may - * be NULL. - */ -extern JS_PUBLIC_API(JSLocaleCallbacks *) -JS_GetLocaleCallbacks(JSContext *cx); - -/************************************************************************/ - -/* - * Error reporting. - */ - -/* - * Report an exception represented by the sprintf-like conversion of format - * and its arguments. This exception message string is passed to a pre-set - * JSErrorReporter function (set by JS_SetErrorReporter; see jspubtd.h for - * the JSErrorReporter typedef). - */ -extern JS_PUBLIC_API(void) -JS_ReportError(JSContext *cx, const char *format, ...); - -/* - * Use an errorNumber to retrieve the format string, args are char * - */ -extern JS_PUBLIC_API(void) -JS_ReportErrorNumber(JSContext *cx, JSErrorCallback errorCallback, - void *userRef, const uintN errorNumber, ...); - -/* - * Use an errorNumber to retrieve the format string, args are jschar * - */ -extern JS_PUBLIC_API(void) -JS_ReportErrorNumberUC(JSContext *cx, JSErrorCallback errorCallback, - void *userRef, const uintN errorNumber, ...); - -/* - * As above, but report a warning instead (JSREPORT_IS_WARNING(report.flags)). - * Return true if there was no error trying to issue the warning, and if the - * warning was not converted into an error due to the JSOPTION_WERROR option - * being set, false otherwise. - */ -extern JS_PUBLIC_API(JSBool) -JS_ReportWarning(JSContext *cx, const char *format, ...); - -extern JS_PUBLIC_API(JSBool) -JS_ReportErrorFlagsAndNumber(JSContext *cx, uintN flags, - JSErrorCallback errorCallback, void *userRef, - const uintN errorNumber, ...); - -extern JS_PUBLIC_API(JSBool) -JS_ReportErrorFlagsAndNumberUC(JSContext *cx, uintN flags, - JSErrorCallback errorCallback, void *userRef, - const uintN errorNumber, ...); - -/* - * Complain when out of memory. - */ -extern JS_PUBLIC_API(void) -JS_ReportOutOfMemory(JSContext *cx); - -struct JSErrorReport { - const char *filename; /* source file name, URL, etc., or null */ - uintN lineno; /* source line number */ - const char *linebuf; /* offending source line without final \n */ - const char *tokenptr; /* pointer to error token in linebuf */ - const jschar *uclinebuf; /* unicode (original) line buffer */ - const jschar *uctokenptr; /* unicode (original) token pointer */ - uintN flags; /* error/warning, etc. */ - uintN errorNumber; /* the error number, e.g. see js.msg */ - const jschar *ucmessage; /* the (default) error message */ - const jschar **messageArgs; /* arguments for the error message */ -}; - -/* - * JSErrorReport flag values. These may be freely composed. - */ -#define JSREPORT_ERROR 0x0 /* pseudo-flag for default case */ -#define JSREPORT_WARNING 0x1 /* reported via JS_ReportWarning */ -#define JSREPORT_EXCEPTION 0x2 /* exception was thrown */ -#define JSREPORT_STRICT 0x4 /* error or warning due to strict option */ - -/* - * If JSREPORT_EXCEPTION is set, then a JavaScript-catchable exception - * has been thrown for this runtime error, and the host should ignore it. - * Exception-aware hosts should also check for JS_IsExceptionPending if - * JS_ExecuteScript returns failure, and signal or propagate the exception, as - * appropriate. - */ -#define JSREPORT_IS_WARNING(flags) (((flags) & JSREPORT_WARNING) != 0) -#define JSREPORT_IS_EXCEPTION(flags) (((flags) & JSREPORT_EXCEPTION) != 0) -#define JSREPORT_IS_STRICT(flags) (((flags) & JSREPORT_STRICT) != 0) - -extern JS_PUBLIC_API(JSErrorReporter) -JS_SetErrorReporter(JSContext *cx, JSErrorReporter er); - -/************************************************************************/ - -/* - * Regular Expressions. - */ -#define JSREG_FOLD 0x01 /* fold uppercase to lowercase */ -#define JSREG_GLOB 0x02 /* global exec, creates array of matches */ -#define JSREG_MULTILINE 0x04 /* treat ^ and $ as begin and end of line */ - -extern JS_PUBLIC_API(JSObject *) -JS_NewRegExpObject(JSContext *cx, char *bytes, size_t length, uintN flags); - -extern JS_PUBLIC_API(JSObject *) -JS_NewUCRegExpObject(JSContext *cx, jschar *chars, size_t length, uintN flags); - -extern JS_PUBLIC_API(void) -JS_SetRegExpInput(JSContext *cx, JSString *input, JSBool multiline); - -extern JS_PUBLIC_API(void) -JS_ClearRegExpStatics(JSContext *cx); - -extern JS_PUBLIC_API(void) -JS_ClearRegExpRoots(JSContext *cx); - -/* TODO: compile, exec, get/set other statics... */ - -/************************************************************************/ - -extern JS_PUBLIC_API(JSBool) -JS_IsExceptionPending(JSContext *cx); - -extern JS_PUBLIC_API(JSBool) -JS_GetPendingException(JSContext *cx, jsval *vp); - -extern JS_PUBLIC_API(void) -JS_SetPendingException(JSContext *cx, jsval v); - -extern JS_PUBLIC_API(void) -JS_ClearPendingException(JSContext *cx); - -extern JS_PUBLIC_API(JSBool) -JS_ReportPendingException(JSContext *cx); - -/* - * Save the current exception state. This takes a snapshot of cx's current - * exception state without making any change to that state. - * - * The returned state pointer MUST be passed later to JS_RestoreExceptionState - * (to restore that saved state, overriding any more recent state) or else to - * JS_DropExceptionState (to free the state struct in case it is not correct - * or desirable to restore it). Both Restore and Drop free the state struct, - * so callers must stop using the pointer returned from Save after calling the - * Release or Drop API. - */ -extern JS_PUBLIC_API(JSExceptionState *) -JS_SaveExceptionState(JSContext *cx); - -extern JS_PUBLIC_API(void) -JS_RestoreExceptionState(JSContext *cx, JSExceptionState *state); - -extern JS_PUBLIC_API(void) -JS_DropExceptionState(JSContext *cx, JSExceptionState *state); - -/* - * If the given value is an exception object that originated from an error, - * the exception will contain an error report struct, and this API will return - * the address of that struct. Otherwise, it returns NULL. The lifetime of - * the error report struct that might be returned is the same as the lifetime - * of the exception object. - */ -extern JS_PUBLIC_API(JSErrorReport *) -JS_ErrorFromException(JSContext *cx, jsval v); - -/* - * Given a reported error's message and JSErrorReport struct pointer, throw - * the corresponding exception on cx. - */ -extern JS_PUBLIC_API(JSBool) -JS_ThrowReportedError(JSContext *cx, const char *message, - JSErrorReport *reportp); - -#ifdef JS_THREADSAFE - -/* - * Associate the current thread with the given context. This is done - * implicitly by JS_NewContext. - * - * Returns the old thread id for this context, which should be treated as - * an opaque value. This value is provided for comparison to 0, which - * indicates that ClearContextThread has been called on this context - * since the last SetContextThread, or non-0, which indicates the opposite. - */ -extern JS_PUBLIC_API(jsword) -JS_GetContextThread(JSContext *cx); - -extern JS_PUBLIC_API(jsword) -JS_SetContextThread(JSContext *cx); - -extern JS_PUBLIC_API(jsword) -JS_ClearContextThread(JSContext *cx); - -#endif /* JS_THREADSAFE */ - -/************************************************************************/ - -JS_END_EXTERN_C - -#endif /* jsapi_h___ */ diff --git a/lib/javascript/jsarena.c b/lib/javascript/jsarena.c deleted file mode 100644 index 8b2c8a54..00000000 --- a/lib/javascript/jsarena.c +++ /dev/null @@ -1,579 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * Lifetime-based fast allocation, inspired by much prior art, including - * "Fast Allocation and Deallocation of Memory Based on Object Lifetimes" - * David R. Hanson, Software -- Practice and Experience, Vol. 20(1). - */ -#include "jsstddef.h" -#include -#include -#include "jstypes.h" -#include "jsbit.h" -#include "jsarena.h" /* Added by JSIFY */ -#include "jsutil.h" /* Added by JSIFY */ -#include "jslock.h" - -static JSArena *arena_freelist; - -#ifdef JS_THREADSAFE -static JSLock *arena_freelist_lock; -#endif - -#ifdef JS_ARENAMETER -static JSArenaStats *arena_stats_list; - -#define COUNT(pool,what) (pool)->stats.what++ -#else -#define COUNT(pool,what) /* nothing */ -#endif - -#define JS_ARENA_DEFAULT_ALIGN sizeof(double) - -JS_PUBLIC_API(void) -JS_InitArenaPool(JSArenaPool *pool, const char *name, size_t size, size_t align) -{ -#ifdef JS_THREADSAFE - /* Must come through here once in primordial thread to init safely! */ - if (!arena_freelist_lock) { - arena_freelist_lock = JS_NEW_LOCK(); - JS_ASSERT(arena_freelist_lock); - } -#endif - if (align == 0) - align = JS_ARENA_DEFAULT_ALIGN; - pool->mask = JS_BITMASK(JS_CeilingLog2(align)); - pool->first.next = NULL; - pool->first.base = pool->first.avail = pool->first.limit = - JS_ARENA_ALIGN(pool, &pool->first + 1); - pool->current = &pool->first; - pool->arenasize = size; -#ifdef JS_ARENAMETER - memset(&pool->stats, 0, sizeof pool->stats); - pool->stats.name = strdup(name); - pool->stats.next = arena_stats_list; - arena_stats_list = &pool->stats; -#endif -} - -/* - * An allocation that consumes more than pool->arenasize also has a header - * pointing back to its previous arena's next member. This header is not - * included in [a->base, a->limit), so its space can't be wrongly claimed. - * - * As the header is a pointer, it must be well-aligned. If pool->mask is - * greater than or equal to POINTER_MASK, the header just preceding a->base - * for an oversized arena a is well-aligned, because a->base is well-aligned. - * However, we may need to add more space to pad the JSArena ** back-pointer - * so that it lies just behind a->base, because a might not be aligned such - * that (jsuword)(a + 1) is on a pointer boundary. - * - * By how much must we pad? Let M be the alignment modulus for pool and P - * the modulus for a pointer. Given M >= P, the greatest distance between a - * pointer aligned on an M boundary and one aligned on a P boundary is M-P. - * If M and P are powers of two, then M-P = (pool->mask - POINTER_MASK). - * - * How much extra padding might spill over unused into the remainder of the - * allocation, in the worst case (where M > P)? - * - * If we add M-P to the nominal back-pointer address and then round down to - * align on a P boundary, we will use at most M-P bytes of padding, and at - * least P (M > P => M >= 2P; M == 2P gives the least padding, P). So if we - * use P bytes of padding, then we will overallocate a by P+M-1 bytes, as we - * also add M-1 to the estimated size in case malloc returns an odd pointer. - * a->limit must include this overestimation to satisfy a->avail in [a->base, - * a->limit]. - * - * Similarly, if pool->mask is less than POINTER_MASK, we must include enough - * space in the header size to align the back-pointer on a P boundary so that - * it can be found by subtracting P from a->base. This means a->base must be - * on a P boundary, even though subsequent allocations from a may be aligned - * on a lesser (M) boundary. Given powers of two M and P as above, the extra - * space needed when P > M is P-M or POINTER_MASK - pool->mask. - * - * The size of a header including padding is given by the HEADER_SIZE macro, - * below, for any pool (for any value of M). - * - * The mask to align a->base for any pool is (pool->mask | POINTER_MASK), or - * HEADER_BASE_MASK(pool). - * - * PTR_TO_HEADER computes the address of the back-pointer, given an oversized - * allocation at p. By definition, p must be a->base for the arena a that - * contains p. GET_HEADER and SET_HEADER operate on an oversized arena a, in - * the case of SET_HEADER with back-pointer ap. - */ -#define POINTER_MASK ((jsuword)(JS_ALIGN_OF_POINTER - 1)) -#define HEADER_SIZE(pool) (sizeof(JSArena **) \ - + (((pool)->mask < POINTER_MASK) \ - ? POINTER_MASK - (pool)->mask \ - : (pool)->mask - POINTER_MASK)) -#define HEADER_BASE_MASK(pool) ((pool)->mask | POINTER_MASK) -#define PTR_TO_HEADER(pool,p) (JS_ASSERT(((jsuword)(p) \ - & HEADER_BASE_MASK(pool)) \ - == 0), \ - (JSArena ***)(p) - 1) -#define GET_HEADER(pool,a) (*PTR_TO_HEADER(pool, (a)->base)) -#define SET_HEADER(pool,a,ap) (*PTR_TO_HEADER(pool, (a)->base) = (ap)) - -JS_PUBLIC_API(void *) -JS_ArenaAllocate(JSArenaPool *pool, size_t nb) -{ - JSArena **ap, **bp, *a, *b; - jsuword extra, hdrsz, gross, sz; - void *p; - - /* - * Search pool from current forward till we find or make enough space. - * - * NB: subtract nb from a->limit in the loop condition, instead of adding - * nb to a->avail, to avoid overflowing a 32-bit address space (possible - * when running a 32-bit program on a 64-bit system where the kernel maps - * the heap up against the top of the 32-bit address space). - * - * Thanks to Juergen Kreileder , who brought this up in - * https://bugzilla.mozilla.org/show_bug.cgi?id=279273. - */ - JS_ASSERT((nb & pool->mask) == 0); - for (a = pool->current; nb > a->limit || a->avail > a->limit - nb; - pool->current = a) { - ap = &a->next; - if (!*ap) { - /* Not enough space in pool -- try to reclaim a free arena. */ - extra = (nb > pool->arenasize) ? HEADER_SIZE(pool) : 0; - hdrsz = sizeof *a + extra + pool->mask; - gross = hdrsz + JS_MAX(nb, pool->arenasize); - if (gross < nb) - return NULL; - - bp = &arena_freelist; - JS_ACQUIRE_LOCK(arena_freelist_lock); - while ((b = *bp) != NULL) { - /* - * Insist on exact arenasize match to avoid leaving alloc'able - * space after an oversized allocation as it grows. - */ - sz = JS_UPTRDIFF(b->limit, b); - if (sz == gross) { - *bp = b->next; - JS_RELEASE_LOCK(arena_freelist_lock); - b->next = NULL; - COUNT(pool, nreclaims); - goto claim; - } - bp = &b->next; - } - - /* Nothing big enough on the freelist, so we must malloc. */ - JS_RELEASE_LOCK(arena_freelist_lock); - b = (JSArena *) malloc(gross); - if (!b) - return NULL; - b->next = NULL; - b->limit = (jsuword)b + gross; - JS_COUNT_ARENA(pool,++); - COUNT(pool, nmallocs); - - claim: - /* If oversized, store ap in the header, just before a->base. */ - *ap = a = b; - JS_ASSERT(gross <= JS_UPTRDIFF(a->limit, a)); - if (extra) { - a->base = a->avail = - ((jsuword)a + hdrsz) & ~HEADER_BASE_MASK(pool); - SET_HEADER(pool, a, ap); - } else { - a->base = a->avail = JS_ARENA_ALIGN(pool, a + 1); - } - continue; - } - a = *ap; /* move to next arena */ - } - - p = (void *)a->avail; - a->avail += nb; - JS_ASSERT(a->base <= a->avail && a->avail <= a->limit); - return p; -} - -JS_PUBLIC_API(void *) -JS_ArenaRealloc(JSArenaPool *pool, void *p, size_t size, size_t incr) -{ - JSArena **ap, *a, *b; - jsuword boff, aoff, extra, hdrsz, gross; - - /* - * Use the oversized-single-allocation header to avoid searching for ap. - * See JS_ArenaAllocate, the SET_HEADER call. - */ - if (size > pool->arenasize) { - ap = *PTR_TO_HEADER(pool, p); - a = *ap; - } else { - ap = &pool->first.next; - while ((a = *ap) != pool->current) - ap = &a->next; - } - - JS_ASSERT(a->base == (jsuword)p); - boff = JS_UPTRDIFF(a->base, a); - aoff = size + incr; - JS_ASSERT(aoff > pool->arenasize); - extra = HEADER_SIZE(pool); /* oversized header holds ap */ - hdrsz = sizeof *a + extra + pool->mask; /* header and alignment slop */ - gross = hdrsz + aoff; - JS_ASSERT(gross > aoff); - a = (JSArena *) realloc(a, gross); - if (!a) - return NULL; -#ifdef JS_ARENAMETER - pool->stats.nreallocs++; -#endif - - if (a != *ap) { - /* Oops, realloc moved the allocation: update other pointers to a. */ - if (pool->current == *ap) - pool->current = a; - b = a->next; - if (b && b->avail - b->base > pool->arenasize) { - JS_ASSERT(GET_HEADER(pool, b) == &(*ap)->next); - SET_HEADER(pool, b, &a->next); - } - - /* Now update *ap, the next link of the arena before a. */ - *ap = a; - } - - a->base = ((jsuword)a + hdrsz) & ~HEADER_BASE_MASK(pool); - a->limit = (jsuword)a + gross; - a->avail = JS_ARENA_ALIGN(pool, a->base + aoff); - JS_ASSERT(a->base <= a->avail && a->avail <= a->limit); - - /* Check whether realloc aligned differently, and copy if necessary. */ - if (boff != JS_UPTRDIFF(a->base, a)) - memmove((void *)a->base, (char *)a + boff, size); - - /* Store ap in the oversized-load arena header. */ - SET_HEADER(pool, a, ap); - return (void *)a->base; -} - -JS_PUBLIC_API(void *) -JS_ArenaGrow(JSArenaPool *pool, void *p, size_t size, size_t incr) -{ - void *newp; - - /* - * If p points to an oversized allocation, it owns an entire arena, so we - * can simply realloc the arena. - */ - if (size > pool->arenasize) - return JS_ArenaRealloc(pool, p, size, incr); - - JS_ARENA_ALLOCATE(newp, pool, size + incr); - if (newp) - memcpy(newp, p, size); - return newp; -} - -/* - * Free tail arenas linked after head, which may not be the true list head. - * Reset pool->current to point to head in case it pointed at a tail arena. - */ -static void -FreeArenaList(JSArenaPool *pool, JSArena *head, JSBool reallyFree) -{ - JSArena **ap, *a; - - ap = &head->next; - a = *ap; - if (!a) - return; - -#ifdef DEBUG - do { - JS_ASSERT(a->base <= a->avail && a->avail <= a->limit); - a->avail = a->base; - JS_CLEAR_UNUSED(a); - } while ((a = a->next) != NULL); - a = *ap; -#endif - - if (reallyFree) { - do { - *ap = a->next; - JS_CLEAR_ARENA(a); - JS_COUNT_ARENA(pool,--); - free(a); - } while ((a = *ap) != NULL); - } else { - /* Insert the whole arena chain at the front of the freelist. */ - do { - ap = &(*ap)->next; - } while (*ap); - JS_ACQUIRE_LOCK(arena_freelist_lock); - *ap = arena_freelist; - arena_freelist = a; - JS_RELEASE_LOCK(arena_freelist_lock); - head->next = NULL; - } - - pool->current = head; -} - -JS_PUBLIC_API(void) -JS_ArenaRelease(JSArenaPool *pool, char *mark) -{ - JSArena *a; - - for (a = &pool->first; a; a = a->next) { - JS_ASSERT(a->base <= a->avail && a->avail <= a->limit); - - if (JS_UPTRDIFF(mark, a->base) <= JS_UPTRDIFF(a->avail, a->base)) { - a->avail = JS_ARENA_ALIGN(pool, mark); - JS_ASSERT(a->avail <= a->limit); - FreeArenaList(pool, a, JS_TRUE); - return; - } - } -} - -JS_PUBLIC_API(void) -JS_ArenaFreeAllocation(JSArenaPool *pool, void *p, size_t size) -{ - JSArena **ap, *a, *b; - jsuword q; - - /* - * If the allocation is oversized, it consumes an entire arena, and it has - * a header just before the allocation pointing back to its predecessor's - * next member. Otherwise, we have to search pool for a. - */ - if (size > pool->arenasize) { - ap = *PTR_TO_HEADER(pool, p); - a = *ap; - } else { - q = (jsuword)p + size; - q = JS_ARENA_ALIGN(pool, q); - ap = &pool->first.next; - while ((a = *ap) != NULL) { - JS_ASSERT(a->base <= a->avail && a->avail <= a->limit); - - if (a->avail == q) { - /* - * If a is consumed by the allocation at p, we can free it to - * the malloc heap. - */ - if (a->base == (jsuword)p) - break; - - /* - * We can't free a, but we can "retract" its avail cursor -- - * whether there are others after it in pool. - */ - a->avail = (jsuword)p; - return; - } - ap = &a->next; - } - } - - /* - * At this point, a is doomed, so ensure that pool->current doesn't point - * at it. We must preserve LIFO order of mark/release cursors, so we use - * the oversized-allocation arena's back pointer (or if not oversized, we - * use the result of searching the entire pool) to compute the address of - * the arena that precedes a. - */ - if (pool->current == a) - pool->current = (JSArena *) ((char *)ap - offsetof(JSArena, next)); - - /* - * This is a non-LIFO deallocation, so take care to fix up a->next's back - * pointer in its header, if a->next is oversized. - */ - *ap = b = a->next; - if (b && b->avail - b->base > pool->arenasize) { - JS_ASSERT(GET_HEADER(pool, b) == &a->next); - SET_HEADER(pool, b, ap); - } - JS_CLEAR_ARENA(a); - JS_COUNT_ARENA(pool,--); - free(a); -} - -JS_PUBLIC_API(void) -JS_FreeArenaPool(JSArenaPool *pool) -{ - FreeArenaList(pool, &pool->first, JS_FALSE); - COUNT(pool, ndeallocs); -} - -JS_PUBLIC_API(void) -JS_FinishArenaPool(JSArenaPool *pool) -{ - FreeArenaList(pool, &pool->first, JS_TRUE); -#ifdef JS_ARENAMETER - { - JSArenaStats *stats, **statsp; - - if (pool->stats.name) - free(pool->stats.name); - for (statsp = &arena_stats_list; (stats = *statsp) != 0; - statsp = &stats->next) { - if (stats == &pool->stats) { - *statsp = stats->next; - return; - } - } - } -#endif -} - -JS_PUBLIC_API(void) -JS_ArenaFinish() -{ - JSArena *a, *next; - - JS_ACQUIRE_LOCK(arena_freelist_lock); - a = arena_freelist; - arena_freelist = NULL; - JS_RELEASE_LOCK(arena_freelist_lock); - for (; a; a = next) { - next = a->next; - free(a); - } -} - -JS_PUBLIC_API(void) -JS_ArenaShutDown(void) -{ -#ifdef JS_THREADSAFE - /* Must come through here once in the process's last thread! */ - if (arena_freelist_lock) { - JS_DESTROY_LOCK(arena_freelist_lock); - arena_freelist_lock = NULL; - } -#endif -} - -#ifdef JS_ARENAMETER -JS_PUBLIC_API(void) -JS_ArenaCountAllocation(JSArenaPool *pool, size_t nb) -{ - pool->stats.nallocs++; - pool->stats.nbytes += nb; - if (nb > pool->stats.maxalloc) - pool->stats.maxalloc = nb; - pool->stats.variance += nb * nb; -} - -JS_PUBLIC_API(void) -JS_ArenaCountInplaceGrowth(JSArenaPool *pool, size_t size, size_t incr) -{ - pool->stats.ninplace++; -} - -JS_PUBLIC_API(void) -JS_ArenaCountGrowth(JSArenaPool *pool, size_t size, size_t incr) -{ - pool->stats.ngrows++; - pool->stats.nbytes += incr; - pool->stats.variance -= size * size; - size += incr; - if (size > pool->stats.maxalloc) - pool->stats.maxalloc = size; - pool->stats.variance += size * size; -} - -JS_PUBLIC_API(void) -JS_ArenaCountRelease(JSArenaPool *pool, char *mark) -{ - pool->stats.nreleases++; -} - -JS_PUBLIC_API(void) -JS_ArenaCountRetract(JSArenaPool *pool, char *mark) -{ - pool->stats.nfastrels++; -} - -#include -#include - -JS_PUBLIC_API(void) -JS_DumpArenaStats(FILE *fp) -{ - JSArenaStats *stats; - uint32 nallocs, nbytes; - double mean, variance, sigma; - - for (stats = arena_stats_list; stats; stats = stats->next) { - nallocs = stats->nallocs; - if (nallocs != 0) { - nbytes = stats->nbytes; - mean = (double)nbytes / nallocs; - variance = stats->variance * nallocs - nbytes * nbytes; - if (variance < 0 || nallocs == 1) - variance = 0; - else - variance /= nallocs * (nallocs - 1); - sigma = sqrt(variance); - } else { - mean = variance = sigma = 0; - } - - fprintf(fp, "\n%s allocation statistics:\n", stats->name); - fprintf(fp, " number of arenas: %u\n", stats->narenas); - fprintf(fp, " number of allocations: %u\n", stats->nallocs); - fprintf(fp, " number of free arena reclaims: %u\n", stats->nreclaims); - fprintf(fp, " number of malloc calls: %u\n", stats->nmallocs); - fprintf(fp, " number of deallocations: %u\n", stats->ndeallocs); - fprintf(fp, " number of allocation growths: %u\n", stats->ngrows); - fprintf(fp, " number of in-place growths: %u\n", stats->ninplace); - fprintf(fp, " number of realloc'ing growths: %u\n", stats->nreallocs); - fprintf(fp, "number of released allocations: %u\n", stats->nreleases); - fprintf(fp, " number of fast releases: %u\n", stats->nfastrels); - fprintf(fp, " total bytes allocated: %u\n", stats->nbytes); - fprintf(fp, " mean allocation size: %g\n", mean); - fprintf(fp, " standard deviation: %g\n", sigma); - fprintf(fp, " maximum allocation size: %u\n", stats->maxalloc); - } -} -#endif /* JS_ARENAMETER */ diff --git a/lib/javascript/jsarena.h b/lib/javascript/jsarena.h deleted file mode 100644 index 5370f8f8..00000000 --- a/lib/javascript/jsarena.h +++ /dev/null @@ -1,313 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jsarena_h___ -#define jsarena_h___ -/* - * Lifetime-based fast allocation, inspired by much prior art, including - * "Fast Allocation and Deallocation of Memory Based on Object Lifetimes" - * David R. Hanson, Software -- Practice and Experience, Vol. 20(1). - * - * Also supports LIFO allocation (JS_ARENA_MARK/JS_ARENA_RELEASE). - */ -#include -#include "jstypes.h" -#include "jscompat.h" - -JS_BEGIN_EXTERN_C - -typedef struct JSArena JSArena; -typedef struct JSArenaPool JSArenaPool; - -struct JSArena { - JSArena *next; /* next arena for this lifetime */ - jsuword base; /* aligned base address, follows this header */ - jsuword limit; /* one beyond last byte in arena */ - jsuword avail; /* points to next available byte */ -}; - -#ifdef JS_ARENAMETER -typedef struct JSArenaStats JSArenaStats; - -struct JSArenaStats { - JSArenaStats *next; /* next in arenaStats list */ - char *name; /* name for debugging */ - uint32 narenas; /* number of arenas in pool */ - uint32 nallocs; /* number of JS_ARENA_ALLOCATE() calls */ - uint32 nreclaims; /* number of reclaims from freeArenas */ - uint32 nmallocs; /* number of malloc() calls */ - uint32 ndeallocs; /* number of lifetime deallocations */ - uint32 ngrows; /* number of JS_ARENA_GROW() calls */ - uint32 ninplace; /* number of in-place growths */ - uint32 nreallocs; /* number of arena grow extending reallocs */ - uint32 nreleases; /* number of JS_ARENA_RELEASE() calls */ - uint32 nfastrels; /* number of "fast path" releases */ - size_t nbytes; /* total bytes allocated */ - size_t maxalloc; /* maximum allocation size in bytes */ - double variance; /* size variance accumulator */ -}; -#endif - -struct JSArenaPool { - JSArena first; /* first arena in pool list */ - JSArena *current; /* arena from which to allocate space */ - size_t arenasize; /* net exact size of a new arena */ - jsuword mask; /* alignment mask (power-of-2 - 1) */ -#ifdef JS_ARENAMETER - JSArenaStats stats; -#endif -}; - -/* - * If the including .c file uses only one power-of-2 alignment, it may define - * JS_ARENA_CONST_ALIGN_MASK to the alignment mask and save a few instructions - * per ALLOCATE and GROW. - */ -#ifdef JS_ARENA_CONST_ALIGN_MASK -#define JS_ARENA_ALIGN(pool, n) (((jsuword)(n) + JS_ARENA_CONST_ALIGN_MASK) \ - & ~(jsuword)JS_ARENA_CONST_ALIGN_MASK) - -#define JS_INIT_ARENA_POOL(pool, name, size) \ - JS_InitArenaPool(pool, name, size, JS_ARENA_CONST_ALIGN_MASK + 1) -#else -#define JS_ARENA_ALIGN(pool, n) (((jsuword)(n) + (pool)->mask) & ~(pool)->mask) -#endif - -#define JS_ARENA_ALLOCATE(p, pool, nb) \ - JS_ARENA_ALLOCATE_CAST(p, void *, pool, nb) - -#define JS_ARENA_ALLOCATE_TYPE(p, type, pool) \ - JS_ARENA_ALLOCATE_COMMON(p, type *, pool, sizeof(type), 0) - -#define JS_ARENA_ALLOCATE_CAST(p, type, pool, nb) \ - JS_ARENA_ALLOCATE_COMMON(p, type, pool, nb, _nb > _a->limit) - -/* - * NB: In JS_ARENA_ALLOCATE_CAST and JS_ARENA_GROW_CAST, always subtract _nb - * from a->limit rather than adding _nb to _p, to avoid overflowing a 32-bit - * address space (possible when running a 32-bit program on a 64-bit system - * where the kernel maps the heap up against the top of the 32-bit address - * space). - * - * Thanks to Juergen Kreileder , who brought this up in - * https://bugzilla.mozilla.org/show_bug.cgi?id=279273. - */ -#define JS_ARENA_ALLOCATE_COMMON(p, type, pool, nb, guard) \ - JS_BEGIN_MACRO \ - JSArena *_a = (pool)->current; \ - size_t _nb = JS_ARENA_ALIGN(pool, nb); \ - jsuword _p = _a->avail; \ - if ((guard) || _p > _a->limit - _nb) \ - _p = (jsuword)JS_ArenaAllocate(pool, _nb); \ - else \ - _a->avail = _p + _nb; \ - p = (type) _p; \ - JS_ArenaCountAllocation(pool, nb); \ - JS_END_MACRO - -#define JS_ARENA_GROW(p, pool, size, incr) \ - JS_ARENA_GROW_CAST(p, void *, pool, size, incr) - -#define JS_ARENA_GROW_CAST(p, type, pool, size, incr) \ - JS_BEGIN_MACRO \ - JSArena *_a = (pool)->current; \ - if (_a->avail == (jsuword)(p) + JS_ARENA_ALIGN(pool, size)) { \ - size_t _nb = (size) + (incr); \ - _nb = JS_ARENA_ALIGN(pool, _nb); \ - if (_a->limit >= _nb && (jsuword)(p) <= _a->limit - _nb) { \ - _a->avail = (jsuword)(p) + _nb; \ - JS_ArenaCountInplaceGrowth(pool, size, incr); \ - } else if ((jsuword)(p) == _a->base) { \ - p = (type) JS_ArenaRealloc(pool, p, size, incr); \ - } else { \ - p = (type) JS_ArenaGrow(pool, p, size, incr); \ - } \ - } else { \ - p = (type) JS_ArenaGrow(pool, p, size, incr); \ - } \ - JS_ArenaCountGrowth(pool, size, incr); \ - JS_END_MACRO - -#define JS_ARENA_MARK(pool) ((void *) (pool)->current->avail) -#define JS_UPTRDIFF(p,q) ((jsuword)(p) - (jsuword)(q)) - -#ifdef DEBUG -#define JS_FREE_PATTERN 0xDA -#define JS_CLEAR_UNUSED(a) (JS_ASSERT((a)->avail <= (a)->limit), \ - memset((void*)(a)->avail, JS_FREE_PATTERN, \ - (a)->limit - (a)->avail)) -#define JS_CLEAR_ARENA(a) memset((void*)(a), JS_FREE_PATTERN, \ - (a)->limit - (jsuword)(a)) -#else -#define JS_CLEAR_UNUSED(a) /* nothing */ -#define JS_CLEAR_ARENA(a) /* nothing */ -#endif - -#define JS_ARENA_RELEASE(pool, mark) \ - JS_BEGIN_MACRO \ - char *_m = (char *)(mark); \ - JSArena *_a = (pool)->current; \ - if (_a != &(pool)->first && \ - JS_UPTRDIFF(_m, _a->base) <= JS_UPTRDIFF(_a->avail, _a->base)) { \ - _a->avail = (jsuword)JS_ARENA_ALIGN(pool, _m); \ - JS_ASSERT(_a->avail <= _a->limit); \ - JS_CLEAR_UNUSED(_a); \ - JS_ArenaCountRetract(pool, _m); \ - } else { \ - JS_ArenaRelease(pool, _m); \ - } \ - JS_ArenaCountRelease(pool, _m); \ - JS_END_MACRO - -#ifdef JS_ARENAMETER -#define JS_COUNT_ARENA(pool,op) ((pool)->stats.narenas op) -#else -#define JS_COUNT_ARENA(pool,op) -#endif - -#define JS_ARENA_DESTROY(pool, a, pnext) \ - JS_BEGIN_MACRO \ - JS_COUNT_ARENA(pool,--); \ - if ((pool)->current == (a)) (pool)->current = &(pool)->first; \ - *(pnext) = (a)->next; \ - JS_CLEAR_ARENA(a); \ - free(a); \ - (a) = NULL; \ - JS_END_MACRO - -/* - * Initialize an arena pool with the given name for debugging and metering, - * with a minimum size per arena of size bytes. - */ -extern JS_PUBLIC_API(void) -JS_InitArenaPool(JSArenaPool *pool, const char *name, size_t size, - size_t align); - -/* - * Free the arenas in pool. The user may continue to allocate from pool - * after calling this function. There is no need to call JS_InitArenaPool() - * again unless JS_FinishArenaPool(pool) has been called. - */ -extern JS_PUBLIC_API(void) -JS_FreeArenaPool(JSArenaPool *pool); - -/* - * Free the arenas in pool and finish using it altogether. - */ -extern JS_PUBLIC_API(void) -JS_FinishArenaPool(JSArenaPool *pool); - -/* - * Finish using arenas, freeing all memory associated with them except for - * any locks needed for thread safety. - */ -extern JS_PUBLIC_API(void) -JS_ArenaFinish(void); - -/* - * Free any locks or other memory needed for thread safety, just before - * shutting down. At that point, we must be called by a single thread. - * - * After shutting down, the next thread to call JS_InitArenaPool must not - * race with any other thread. Once a pool has been initialized, threads - * may safely call jsarena.c functions on thread-local pools. The upshot - * is that pools are per-thread, but the underlying global freelist is - * thread-safe, provided that both the first pool initialization and the - * shut-down call are single-threaded. - */ -extern JS_PUBLIC_API(void) -JS_ArenaShutDown(void); - -/* - * Friend functions used by the JS_ARENA_*() macros. - */ -extern JS_PUBLIC_API(void *) -JS_ArenaAllocate(JSArenaPool *pool, size_t nb); - -extern JS_PUBLIC_API(void *) -JS_ArenaRealloc(JSArenaPool *pool, void *p, size_t size, size_t incr); - -extern JS_PUBLIC_API(void *) -JS_ArenaGrow(JSArenaPool *pool, void *p, size_t size, size_t incr); - -extern JS_PUBLIC_API(void) -JS_ArenaRelease(JSArenaPool *pool, char *mark); - -/* - * Function to be used directly when an allocation has likely grown to consume - * an entire JSArena, in which case the arena is returned to the malloc heap. - */ -extern JS_PUBLIC_API(void) -JS_ArenaFreeAllocation(JSArenaPool *pool, void *p, size_t size); - -#ifdef JS_ARENAMETER - -#include - -extern JS_PUBLIC_API(void) -JS_ArenaCountAllocation(JSArenaPool *pool, size_t nb); - -extern JS_PUBLIC_API(void) -JS_ArenaCountInplaceGrowth(JSArenaPool *pool, size_t size, size_t incr); - -extern JS_PUBLIC_API(void) -JS_ArenaCountGrowth(JSArenaPool *pool, size_t size, size_t incr); - -extern JS_PUBLIC_API(void) -JS_ArenaCountRelease(JSArenaPool *pool, char *mark); - -extern JS_PUBLIC_API(void) -JS_ArenaCountRetract(JSArenaPool *pool, char *mark); - -extern JS_PUBLIC_API(void) -JS_DumpArenaStats(FILE *fp); - -#else /* !JS_ARENAMETER */ - -#define JS_ArenaCountAllocation(ap, nb) /* nothing */ -#define JS_ArenaCountInplaceGrowth(ap, size, incr) /* nothing */ -#define JS_ArenaCountGrowth(ap, size, incr) /* nothing */ -#define JS_ArenaCountRelease(ap, mark) /* nothing */ -#define JS_ArenaCountRetract(ap, mark) /* nothing */ - -#endif /* !JS_ARENAMETER */ - -JS_END_EXTERN_C - -#endif /* jsarena_h___ */ diff --git a/lib/javascript/jsarray.c b/lib/javascript/jsarray.c deleted file mode 100644 index ef94be4e..00000000 --- a/lib/javascript/jsarray.c +++ /dev/null @@ -1,1901 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set sw=4 ts=8 et tw=80: - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JS array class. - */ -#include "jsstddef.h" -#include -#include -#include "jstypes.h" -#include "jsutil.h" /* Added by JSIFY */ -#include "jsapi.h" -#include "jsarray.h" -#include "jsatom.h" -#include "jsbool.h" -#include "jscntxt.h" -#include "jsconfig.h" -#include "jsfun.h" -#include "jsgc.h" -#include "jsinterp.h" -#include "jslock.h" -#include "jsnum.h" -#include "jsobj.h" -#include "jsstr.h" - -/* 2^32 - 1 as a number and a string */ -#define MAXINDEX 4294967295u -#define MAXSTR "4294967295" - -/* - * Determine if the id represents an array index or an XML property index. - * - * An id is an array index according to ECMA by (15.4): - * - * "Array objects give special treatment to a certain class of property names. - * A property name P (in the form of a string value) is an array index if and - * only if ToString(ToUint32(P)) is equal to P and ToUint32(P) is not equal - * to 2^32-1." - * - * In our implementation, it would be sufficient to check for JSVAL_IS_INT(id) - * except that by using signed 32-bit integers we miss the top half of the - * valid range. This function checks the string representation itself; note - * that calling a standard conversion routine might allow strings such as - * "08" or "4.0" as array indices, which they are not. - */ -JSBool -js_IdIsIndex(jsval id, jsuint *indexp) -{ - JSString *str; - jschar *cp; - - if (JSVAL_IS_INT(id)) { - jsint i; - i = JSVAL_TO_INT(id); - if (i < 0) - return JS_FALSE; - *indexp = (jsuint)i; - return JS_TRUE; - } - - /* NB: id should be a string, but jsxml.c may call us with an object id. */ - if (!JSVAL_IS_STRING(id)) - return JS_FALSE; - - str = JSVAL_TO_STRING(id); - cp = JSSTRING_CHARS(str); - if (JS7_ISDEC(*cp) && JSSTRING_LENGTH(str) < sizeof(MAXSTR)) { - jsuint index = JS7_UNDEC(*cp++); - jsuint oldIndex = 0; - jsuint c = 0; - if (index != 0) { - while (JS7_ISDEC(*cp)) { - oldIndex = index; - c = JS7_UNDEC(*cp); - index = 10*index + c; - cp++; - } - } - - /* Ensure that all characters were consumed and we didn't overflow. */ - if (*cp == 0 && - (oldIndex < (MAXINDEX / 10) || - (oldIndex == (MAXINDEX / 10) && c < (MAXINDEX % 10)))) - { - *indexp = index; - return JS_TRUE; - } - } - return JS_FALSE; -} - -static JSBool -ValueIsLength(JSContext *cx, jsval v, jsuint *lengthp) -{ - jsint i; - jsdouble d; - - if (JSVAL_IS_INT(v)) { - i = JSVAL_TO_INT(v); - if (i < 0) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_ARRAY_LENGTH); - return JS_FALSE; - } - *lengthp = (jsuint) i; - return JS_TRUE; - } - - if (!js_ValueToNumber(cx, v, &d)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_ARRAY_LENGTH); - return JS_FALSE; - } - if (!js_DoubleToECMAUint32(cx, d, (uint32 *)lengthp)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_ARRAY_LENGTH); - return JS_FALSE; - } - if (JSDOUBLE_IS_NaN(d) || d != *lengthp) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_ARRAY_LENGTH); - return JS_FALSE; - } - return JS_TRUE; -} - -JSBool -js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp) -{ - JSTempValueRooter tvr; - jsid id; - JSBool ok; - jsint i; - - JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr); - id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom); - ok = OBJ_GET_PROPERTY(cx, obj, id, &tvr.u.value); - if (ok) { - /* - * Short-circuit, because js_ValueToECMAUint32 fails when called - * during init time. - */ - if (JSVAL_IS_INT(tvr.u.value)) { - i = JSVAL_TO_INT(tvr.u.value); - *lengthp = (jsuint)i; /* jsuint cast does ToUint32 */ - } else { - ok = js_ValueToECMAUint32(cx, tvr.u.value, (uint32 *)lengthp); - } - } - JS_POP_TEMP_ROOT(cx, &tvr); - return ok; -} - -static JSBool -IndexToValue(JSContext *cx, jsuint index, jsval *vp) -{ - if (index <= JSVAL_INT_MAX) { - *vp = INT_TO_JSVAL(index); - return JS_TRUE; - } - return js_NewDoubleValue(cx, (jsdouble)index, vp); -} - -static JSBool -IndexToId(JSContext *cx, jsuint index, jsid *idp) -{ - JSString *str; - JSAtom *atom; - - if (index <= JSVAL_INT_MAX) { - *idp = INT_TO_JSID(index); - } else { - str = js_NumberToString(cx, (jsdouble)index); - if (!str) - return JS_FALSE; - atom = js_AtomizeString(cx, str, 0); - if (!atom) - return JS_FALSE; - *idp = ATOM_TO_JSID(atom); - - } - return JS_TRUE; -} - -static JSBool -PropertyExists(JSContext *cx, JSObject *obj, jsid id, JSBool *foundp) -{ - JSObject *obj2; - JSProperty *prop; - - if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop)) - return JS_FALSE; - - *foundp = prop != NULL; - if (*foundp) { - OBJ_DROP_PROPERTY(cx, obj2, prop); - } - - return JS_TRUE; -} - -#define JSID_HOLE JSVAL_NULL - -static JSBool -IndexToExistingId(JSContext *cx, JSObject *obj, jsuint index, jsid *idp) -{ - JSBool exists; - - if (!IndexToId(cx, index, idp)) - return JS_FALSE; - if (!PropertyExists(cx, obj, *idp, &exists)) - return JS_FALSE; - if (!exists) - *idp = JSID_HOLE; - return JS_TRUE; -} - -JSBool -js_SetLengthProperty(JSContext *cx, JSObject *obj, jsuint length) -{ - jsval v; - jsid id; - - if (!IndexToValue(cx, length, &v)) - return JS_FALSE; - id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom); - return OBJ_SET_PROPERTY(cx, obj, id, &v); -} - -JSBool -js_HasLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp) -{ - JSErrorReporter older; - JSTempValueRooter tvr; - jsid id; - JSBool ok; - - older = JS_SetErrorReporter(cx, NULL); - JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr); - id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom); - ok = OBJ_GET_PROPERTY(cx, obj, id, &tvr.u.value); - JS_SetErrorReporter(cx, older); - if (ok) - ok = ValueIsLength(cx, tvr.u.value, lengthp); - JS_POP_TEMP_ROOT(cx, &tvr); - return ok; -} - -/* - * This get function is specific to Array.prototype.length and other array - * instance length properties. It calls back through the class get function - * in case some magic happens there (see call_getProperty in jsfun.c). - */ -static JSBool -array_length_getter(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - return OBJ_GET_CLASS(cx, obj)->getProperty(cx, obj, id, vp); -} - -static JSBool -array_length_setter(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - jsuint newlen, oldlen, slot; - jsid id2; - jsval junk; - - if (!ValueIsLength(cx, *vp, &newlen)) - return JS_FALSE; - if (!js_GetLengthProperty(cx, obj, &oldlen)) - return JS_FALSE; - slot = oldlen; - while (slot > newlen) { - --slot; - if (!IndexToId(cx, slot, &id2)) - return JS_FALSE; - if (!OBJ_DELETE_PROPERTY(cx, obj, id2, &junk)) - return JS_FALSE; - } - return IndexToValue(cx, newlen, vp); -} - -static JSBool -array_addProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - jsuint index, length; - - if (!js_IdIsIndex(id, &index)) - return JS_TRUE; - if (!js_GetLengthProperty(cx, obj, &length)) - return JS_FALSE; - if (index >= length) { - length = index + 1; - return js_SetLengthProperty(cx, obj, length); - } - return JS_TRUE; -} - -static JSBool -array_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp) -{ - jsuint length; - - if (JS_VERSION_IS_1_2(cx)) { - if (!js_GetLengthProperty(cx, obj, &length)) - return JS_FALSE; - switch (type) { - case JSTYPE_NUMBER: - return IndexToValue(cx, length, vp); - case JSTYPE_BOOLEAN: - *vp = BOOLEAN_TO_JSVAL(length > 0); - return JS_TRUE; - default: - return JS_TRUE; - } - } - return js_TryValueOf(cx, obj, type, vp); -} - -JSClass js_ArrayClass = { - "Array", - 0, - array_addProperty, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, - JS_EnumerateStub, JS_ResolveStub, array_convert, JS_FinalizeStub, - JSCLASS_NO_OPTIONAL_MEMBERS -}; - -static JSBool -array_join_sub(JSContext *cx, JSObject *obj, JSString *sep, JSBool literalize, - jsval *rval, JSBool localeString) -{ - JSBool ok; - jsuint length, index; - jschar *chars, *ochars; - size_t nchars, growth, seplen, tmplen; - const jschar *sepstr; - JSString *str; - JSHashEntry *he; - JSTempValueRooter tvr; - JSAtom *atom; - int stackDummy; - - if (!JS_CHECK_STACK_SIZE(cx, stackDummy)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_OVER_RECURSED); - return JS_FALSE; - } - - ok = js_GetLengthProperty(cx, obj, &length); - if (!ok) - return JS_FALSE; - - he = js_EnterSharpObject(cx, obj, NULL, &chars); - if (!he) - return JS_FALSE; - if (literalize) { - if (IS_SHARP(he)) { -#if JS_HAS_SHARP_VARS - nchars = js_strlen(chars); -#else - chars[0] = '['; - chars[1] = ']'; - chars[2] = 0; - nchars = 2; -#endif - goto make_string; - } - - /* - * Allocate 1 + 3 + 1 for "[", the worst-case closing ", ]", and the - * terminating 0. - */ - growth = (1 + 3 + 1) * sizeof(jschar); - if (!chars) { - nchars = 0; - chars = (jschar *) malloc(growth); - if (!chars) - goto done; - } else { - MAKE_SHARP(he); - nchars = js_strlen(chars); - chars = (jschar *) - realloc((ochars = chars), nchars * sizeof(jschar) + growth); - if (!chars) { - free(ochars); - goto done; - } - } - chars[nchars++] = '['; - } else { - /* - * Free any sharp variable definition in chars. Normally, we would - * MAKE_SHARP(he) so that only the first sharp variable annotation is - * a definition, and all the rest are references, but in the current - * case of (!literalize), we don't need chars at all. - */ - if (chars) - JS_free(cx, chars); - chars = NULL; - nchars = 0; - - /* Return the empty string on a cycle as well as on empty join. */ - if (IS_BUSY(he) || length == 0) { - js_LeaveSharpObject(cx, NULL); - *rval = JS_GetEmptyStringValue(cx); - return ok; - } - - /* Flag he as BUSY so we can distinguish a cycle from a join-point. */ - MAKE_BUSY(he); - } - sepstr = NULL; - seplen = JSSTRING_LENGTH(sep); - - /* Use rval to locally root each element value as we loop and convert. */ -#define v (*rval) - - v = JSVAL_NULL; - for (index = 0; index < length; index++) { - ok = JS_GetElement(cx, obj, index, &v); - if (!ok) - goto done; - - if ((!literalize || JS_VERSION_IS_1_2(cx)) && - (JSVAL_IS_VOID(v) || JSVAL_IS_NULL(v))) { - str = cx->runtime->emptyString; - } else { - if (localeString) { - atom = cx->runtime->atomState.toLocaleStringAtom; - JS_PUSH_TEMP_ROOT_OBJECT(cx, NULL, &tvr); - ok = js_ValueToObject(cx, v, &tvr.u.object) && - js_TryMethod(cx, tvr.u.object, atom, 0, NULL, &v); - JS_POP_TEMP_ROOT(cx, &tvr); - if (!ok) - goto done; - str = js_ValueToString(cx, v); - } else { - str = (literalize ? js_ValueToSource : js_ValueToString)(cx, v); - } - if (!str) { - ok = JS_FALSE; - goto done; - } - } - - /* Allocate 3 + 1 at end for ", ", closing bracket, and zero. */ - tmplen = JSSTRING_LENGTH(str); - growth = (nchars + (sepstr ? seplen : 0) + tmplen + 3 + 1); - if (nchars > growth || tmplen > growth || - growth > (size_t)-1 / sizeof(jschar)) { - if (chars) { - free(chars); - chars = NULL; - } - JS_ReportOutOfMemory(cx); - goto done; - } - growth *= sizeof(jschar); - if (!chars) { - chars = (jschar *) malloc(growth); - if (!chars) - goto done; - } else { - chars = (jschar *) realloc((ochars = chars), growth); - if (!chars) { - free(ochars); - goto done; - } - } - - if (sepstr) { - js_strncpy(&chars[nchars], sepstr, seplen); - nchars += seplen; - } - sepstr = JSSTRING_CHARS(sep); - - js_strncpy(&chars[nchars], JSSTRING_CHARS(str), tmplen); - nchars += tmplen; - } - - done: - if (literalize) { - if (chars) { - if (JSVAL_IS_VOID(v)) { - chars[nchars++] = ','; - chars[nchars++] = ' '; - } - chars[nchars++] = ']'; - } - } else { - CLEAR_BUSY(he); - } - js_LeaveSharpObject(cx, NULL); - if (!ok) { - if (chars) - free(chars); - return ok; - } - -#undef v - - make_string: - if (!chars) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - chars[nchars] = 0; - str = js_NewString(cx, chars, nchars, 0); - if (!str) { - free(chars); - return JS_FALSE; - } - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -static jschar comma_space_ucstr[] = {',', ' ', 0}; -static jschar comma_ucstr[] = {',', 0}; -static JSString comma_space = {2, comma_space_ucstr}; -static JSString comma = {1, comma_ucstr}; - -#if JS_HAS_TOSOURCE -static JSBool -array_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - return array_join_sub(cx, obj, &comma_space, JS_TRUE, rval, JS_FALSE); -} -#endif - -static JSBool -array_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSBool literalize; - - /* - * JS1.2 arrays convert to array literals, with a comma followed by a space - * between each element. - */ - literalize = JS_VERSION_IS_1_2(cx); - return array_join_sub(cx, obj, literalize ? &comma_space : &comma, - literalize, rval, JS_FALSE); -} - -static JSBool -array_toLocaleString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - /* - * Passing comma here as the separator. Need a way to get a - * locale-specific version. - */ - return array_join_sub(cx, obj, &comma, JS_FALSE, rval, JS_TRUE); -} - -static JSBool -InitArrayElements(JSContext *cx, JSObject *obj, jsuint length, jsval *vector) -{ - jsuint index; - jsid id; - - for (index = 0; index < length; index++) { - JS_ASSERT(vector[index] != JSVAL_HOLE); - - if (!IndexToId(cx, index, &id)) - return JS_FALSE; - if (!OBJ_SET_PROPERTY(cx, obj, id, &vector[index])) - return JS_FALSE; - } - return JS_TRUE; -} - -static JSBool -InitArrayObject(JSContext *cx, JSObject *obj, jsuint length, jsval *vector) -{ - jsval v; - jsid id; - - if (!IndexToValue(cx, length, &v)) - return JS_FALSE; - id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom); - if (!OBJ_DEFINE_PROPERTY(cx, obj, id, v, - array_length_getter, array_length_setter, - JSPROP_PERMANENT, - NULL)) { - return JS_FALSE; - } - if (!vector) - return JS_TRUE; - return InitArrayElements(cx, obj, length, vector); -} - -#if JS_HAS_SOME_PERL_FUN -/* - * Perl-inspired join, reverse, and sort. - */ -static JSBool -array_join(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSString *str; - - if (JSVAL_IS_VOID(argv[0])) - return array_join_sub(cx, obj, &comma, JS_FALSE, rval, JS_FALSE); - str = js_ValueToString(cx, argv[0]); - if (!str) - return JS_FALSE; - argv[0] = STRING_TO_JSVAL(str); - return array_join_sub(cx, obj, str, JS_FALSE, rval, JS_FALSE); -} - -static JSBool -array_reverse(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jsuint len, half, i; - jsid id, id2; - jsval *tmproot, *tmproot2; - JSBool idexists, id2exists, ok; - - if (!js_GetLengthProperty(cx, obj, &len)) - return JS_FALSE; - - /* - * When len > JSVAL_INT_MAX + 1 the loop below accesses indexes greater - * than JSVAL_INT_MAX. For such indexes the corresponding ids are atoms. - * We use JS_KEEP_ATOMS to protect them against GC since OBJ_GET_PROPERTY - * can potentially execute an arbitrary script. See bug 341956. - * - * After this point control must flow through label out: to exit. - */ - if (len > JSVAL_INT_MAX + 1) - JS_KEEP_ATOMS(cx->runtime); - - /* - * Use argv[argc] and argv[argc + 1] as local roots to hold temporarily - * array elements for GC-safe swap. - */ - tmproot = argv + argc; - tmproot2 = argv + argc + 1; - half = len / 2; - for (i = 0; i < half; i++) { - /* - * Get both values while checking for holes to make sure they don't - * get filled. - */ - if (!IndexToId(cx, i, &id)) - goto bad; - if (!PropertyExists(cx, obj, id, &idexists)) - goto bad; - if (idexists && !OBJ_GET_PROPERTY(cx, obj, id, tmproot)) - goto bad; - - if (!IndexToId(cx, len - i - 1, &id2)) - goto bad; - if (!PropertyExists(cx, obj, id2, &id2exists)) - goto bad; - if (id2exists && !OBJ_GET_PROPERTY(cx, obj, id2, tmproot2)) - goto bad; - - /* Exchange the values. */ - if (idexists) { - if (!OBJ_SET_PROPERTY(cx, obj, id2, tmproot)) - goto bad; - } else { - if (!OBJ_DELETE_PROPERTY(cx, obj, id2, tmproot)) - goto bad; - } - if (id2exists) { - if (!OBJ_SET_PROPERTY(cx, obj, id, tmproot2)) - goto bad; - } else { - if (!OBJ_DELETE_PROPERTY(cx, obj, id, tmproot2)) - goto bad; - } - } - ok = JS_TRUE; - - out: - if (len > JSVAL_INT_MAX + 1) - JS_UNKEEP_ATOMS(cx->runtime); - *rval = OBJECT_TO_JSVAL(obj); - return ok; - - bad: - ok = JS_FALSE; - goto out; -} - -typedef struct HSortArgs { - void *vec; - size_t elsize; - void *pivot; - JSComparator cmp; - void *arg; - JSBool fastcopy; -} HSortArgs; - -static int -sort_compare(const void *a, const void *b, void *arg); - -static int -sort_compare_strings(const void *a, const void *b, void *arg); - -static void -HeapSortHelper(JSBool building, HSortArgs *hsa, size_t lo, size_t hi) -{ - void *pivot, *vec, *vec2, *arg, *a, *b; - size_t elsize; - JSComparator cmp; - JSBool fastcopy; - size_t j, hiDiv2; - - pivot = hsa->pivot; - vec = hsa->vec; - elsize = hsa->elsize; - vec2 = (char *)vec - 2 * elsize; - cmp = hsa->cmp; - arg = hsa->arg; - - fastcopy = hsa->fastcopy; -#define MEMCPY(p,q,n) \ - (fastcopy ? (void)(*(jsval*)(p) = *(jsval*)(q)) : (void)memcpy(p, q, n)) - - if (lo == 1) { - j = 2; - b = (char *)vec + elsize; - if (j < hi && cmp(vec, b, arg) < 0) - j++; - a = (char *)vec + (hi - 1) * elsize; - b = (char *)vec2 + j * elsize; - - /* - * During sorting phase b points to a member of heap that cannot be - * bigger then biggest of vec[0] and vec[1], and cmp(a, b, arg) <= 0 - * always holds. - */ - if ((building || hi == 2) && cmp(a, b, arg) >= 0) - return; - - MEMCPY(pivot, a, elsize); - MEMCPY(a, b, elsize); - lo = j; - } else { - a = (char *)vec2 + lo * elsize; - MEMCPY(pivot, a, elsize); - } - - hiDiv2 = hi/2; - while (lo <= hiDiv2) { - j = lo + lo; - a = (char *)vec2 + j * elsize; - b = (char *)vec + (j - 1) * elsize; - if (j < hi && cmp(a, b, arg) < 0) - j++; - b = (char *)vec2 + j * elsize; - if (cmp(pivot, b, arg) >= 0) - break; - - a = (char *)vec2 + lo * elsize; - MEMCPY(a, b, elsize); - lo = j; - } - - a = (char *)vec2 + lo * elsize; - MEMCPY(a, pivot, elsize); -#undef MEMCPY -} - -void -js_HeapSort(void *vec, size_t nel, void *pivot, size_t elsize, - JSComparator cmp, void *arg) -{ - HSortArgs hsa; - size_t i; - - hsa.vec = vec; - hsa.elsize = elsize; - hsa.pivot = pivot; - hsa.cmp = cmp; - hsa.arg = arg; - hsa.fastcopy = (cmp == sort_compare || cmp == sort_compare_strings); - - for (i = nel/2; i != 0; i--) - HeapSortHelper(JS_TRUE, &hsa, i, nel); - while (nel > 2) - HeapSortHelper(JS_FALSE, &hsa, 1, --nel); -} - -typedef struct CompareArgs { - JSContext *context; - jsval fval; - jsval *localroot; /* need one local root, for sort_compare */ - JSBool status; -} CompareArgs; - -static int -sort_compare(const void *a, const void *b, void *arg) -{ - jsval av = *(const jsval *)a, bv = *(const jsval *)b; - CompareArgs *ca = (CompareArgs *) arg; - JSContext *cx = ca->context; - jsdouble cmp = -1; - jsval fval, argv[2], special; - JSBool ok; - - fval = ca->fval; - - /* - * By ECMA 262, 15.4.4.11, existence of the property with value undefined - * takes precedence over an undefined property (which we call a "hole"). - */ - if (av == JSVAL_HOLE || bv == JSVAL_HOLE) - special = JSVAL_HOLE; - else if (av == JSVAL_VOID || bv == JSVAL_VOID) - special = JSVAL_VOID; - else - special = JSVAL_NULL; - - if (special != JSVAL_NULL) { - if (av == bv) - cmp = 0; - else if (av != special) - cmp = -1; - else - cmp = 1; - } else if (fval == JSVAL_NULL) { - JSString *astr, *bstr; - - if (av == bv) { - cmp = 0; - } else { - /* - * Set our local root to astr in case the second js_ValueToString - * displaces the newborn root in cx, and the GC nests under that - * call. Don't bother guarding the local root store with an astr - * non-null test. If we tag null as a string, the GC will untag, - * null-test, and avoid dereferencing null. - */ - astr = js_ValueToString(cx, av); - *ca->localroot = STRING_TO_JSVAL(astr); - if (astr && (bstr = js_ValueToString(cx, bv))) - cmp = js_CompareStrings(astr, bstr); - else - ca->status = JS_FALSE; - } - } else { - argv[0] = av; - argv[1] = bv; - ok = js_InternalCall(cx, - OBJ_GET_PARENT(cx, JSVAL_TO_OBJECT(fval)), - fval, 2, argv, ca->localroot); - if (ok) { - ok = js_ValueToNumber(cx, *ca->localroot, &cmp); - - /* Clamp cmp to -1, 0, 1. */ - if (ok) { - if (JSDOUBLE_IS_NaN(cmp)) { - /* - * XXX report some kind of error here? ECMA talks about - * 'consistent compare functions' that don't return NaN, - * but is silent about what the result should be. So we - * currently ignore it. - */ - cmp = 0; - } else if (cmp != 0) { - cmp = cmp > 0 ? 1 : -1; - } - } - } - if (!ok) - ca->status = ok; - } - return (int)cmp; -} - -static int -sort_compare_strings(const void *a, const void *b, void *arg) -{ - jsval av = *(const jsval *)a, bv = *(const jsval *)b; - - return (int) js_CompareStrings(JSVAL_TO_STRING(av), JSVAL_TO_STRING(bv)); -} - -static JSBool -array_sort(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsval fval, *vec, *pivotroot; - CompareArgs ca; - jsuint len, newlen, i; - JSStackFrame *fp; - jsid id; - size_t nbytes; - - /* - * Optimize the default compare function case if all of obj's elements - * have values of type string. - */ - JSBool all_strings; - - if (argc > 0) { - if (JSVAL_IS_PRIMITIVE(argv[0])) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_SORT_ARG); - return JS_FALSE; - } - fval = argv[0]; - all_strings = JS_FALSE; /* non-default compare function */ - } else { - fval = JSVAL_NULL; - all_strings = JS_TRUE; /* check for all string values */ - } - - if (!js_GetLengthProperty(cx, obj, &len)) - return JS_FALSE; - if (len == 0) { - *rval = OBJECT_TO_JSVAL(obj); - return JS_TRUE; - } - - /* - * We need a temporary array of len jsvals to hold elements of the array. - * Check that its size does not overflow size_t, which would allow for - * indexing beyond the end of the malloc'd vector. - */ - if (len > ((size_t) -1) / sizeof(jsval)) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - nbytes = ((size_t) len) * sizeof(jsval); - - vec = (jsval *) JS_malloc(cx, nbytes); - if (!vec) - return JS_FALSE; - - /* Root vec, clearing it first in case a GC nests while we're filling it. */ - memset(vec, 0, nbytes); - fp = cx->fp; - fp->vars = vec; - fp->nvars = len; - - newlen = 0; - for (i = 0; i < len; i++) { - ca.status = IndexToExistingId(cx, obj, i, &id); - if (!ca.status) - goto out; - - if (id == JSID_HOLE) { - vec[i] = JSVAL_HOLE; - all_strings = JS_FALSE; - continue; - } - newlen++; - - ca.status = OBJ_GET_PROPERTY(cx, obj, id, &vec[i]); - if (!ca.status) - goto out; - - /* We know JSVAL_IS_STRING yields 0 or 1, so avoid a branch via &=. */ - all_strings &= JSVAL_IS_STRING(vec[i]); - } - - ca.context = cx; - ca.fval = fval; - ca.localroot = argv + argc; /* local GC root for temporary string */ - pivotroot = argv + argc + 1; /* local GC root for pivot val */ - ca.status = JS_TRUE; - js_HeapSort(vec, (size_t) len, pivotroot, sizeof(jsval), - all_strings ? sort_compare_strings : sort_compare, - &ca); - - if (ca.status) { - ca.status = InitArrayElements(cx, obj, newlen, vec); - if (ca.status) - *rval = OBJECT_TO_JSVAL(obj); - - /* Re-create any holes that sorted to the end of the array. */ - while (len > newlen) { - jsval junk; - - if (!IndexToId(cx, --len, &id)) - return JS_FALSE; - if (!OBJ_DELETE_PROPERTY(cx, obj, id, &junk)) - return JS_FALSE; - } - } - -out: - if (vec) - JS_free(cx, vec); - return ca.status; -} -#endif /* JS_HAS_SOME_PERL_FUN */ - -#if JS_HAS_MORE_PERL_FUN -/* - * Perl-inspired push, pop, shift, unshift, and splice methods. - */ -static JSBool -array_push(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsuint length; - uintN i; - jsid id; - - if (!js_GetLengthProperty(cx, obj, &length)) - return JS_FALSE; - for (i = 0; i < argc; i++) { - if (!IndexToId(cx, length + i, &id)) - return JS_FALSE; - if (!OBJ_SET_PROPERTY(cx, obj, id, &argv[i])) - return JS_FALSE; - } - - /* - * If JS1.2, follow Perl4 by returning the last thing pushed. Otherwise, - * return the new array length. - */ - length += argc; - if (JS_VERSION_IS_1_2(cx)) { - *rval = argc ? argv[argc-1] : JSVAL_VOID; - } else { - if (!IndexToValue(cx, length, rval)) - return JS_FALSE; - } - return js_SetLengthProperty(cx, obj, length); -} - -static JSBool -array_pop(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsuint index; - jsid id; - JSBool ok; - jsval junk; - - if (!js_GetLengthProperty(cx, obj, &index)) - return JS_FALSE; - if (index > 0) { - index--; - - /* Get the to-be-deleted property's value into rval. */ - if (!IndexToId(cx, index, &id)) - return JS_FALSE; - - /* See comments in array_reverse. */ - if (index > JSVAL_INT_MAX) - JS_KEEP_ATOMS(cx->runtime); - ok = OBJ_GET_PROPERTY(cx, obj, id, rval) && - OBJ_DELETE_PROPERTY(cx, obj, id, &junk); - if (index > JSVAL_INT_MAX) - JS_UNKEEP_ATOMS(cx->runtime); - if (!ok) - return JS_FALSE; - } - return js_SetLengthProperty(cx, obj, index); -} - -static JSBool -array_shift(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsuint length, i; - jsid id, id2; - jsval junk; - - if (!js_GetLengthProperty(cx, obj, &length)) - return JS_FALSE; - if (length > 0) { - length--; - id = JSVAL_ZERO; - - /* Get the to-be-deleted property's value into rval ASAP. */ - if (!OBJ_GET_PROPERTY(cx, obj, id, rval)) - return JS_FALSE; - - /* - * Slide down the array above the first element. - */ - if (length > 0) { - for (i = 1; i <= length; i++) { - if (!IndexToId(cx, i, &id)) - return JS_FALSE; - if (!OBJ_GET_PROPERTY(cx, obj, id, &argv[0])) - return JS_FALSE; - - /* Get id after value to avoid nested GC hazards. */ - if (!IndexToId(cx, i - 1, &id2)) - return JS_FALSE; - if (!OBJ_SET_PROPERTY(cx, obj, id2, &argv[0])) - return JS_FALSE; - } - } - - /* - * Delete the only or the last element. We recreate id when it is an - * atom to protect against a nested GC during the last iteration. - */ - if (length > JSVAL_INT_MAX && !IndexToId(cx, length, &id)) - return JS_FALSE; - if (!OBJ_DELETE_PROPERTY(cx, obj, id, &junk)) - return JS_FALSE; - } - return js_SetLengthProperty(cx, obj, length); -} - -static JSBool -array_unshift(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jsuint length, last; - uintN i; - jsid id, id2; - jsval *vp, junk; - - if (!js_GetLengthProperty(cx, obj, &length)) - return JS_FALSE; - if (argc > 0) { - /* Slide up the array to make room for argc at the bottom. */ - if (length > 0) { - last = length; - vp = argv + argc; - while (last--) { - if (!IndexToExistingId(cx, obj, last, &id)) - return JS_FALSE; - if (id != JSID_HOLE) { - if (!OBJ_GET_PROPERTY(cx, obj, id, vp)) - return JS_FALSE; - } - - /* Get id after value to avoid nested GC hazards. */ - if (!IndexToId(cx, last + argc, &id2)) - return JS_FALSE; - if (id == JSID_HOLE) { - if (!OBJ_DELETE_PROPERTY(cx, obj, id2, &junk)) - return JS_FALSE; - } else { - if (!OBJ_SET_PROPERTY(cx, obj, id2, vp)) - return JS_FALSE; - } - } - } - - /* Copy from argv to the bottom of the array. */ - for (i = 0; i < argc; i++) { - if (!IndexToId(cx, i, &id)) - return JS_FALSE; - if (!OBJ_SET_PROPERTY(cx, obj, id, &argv[i])) - return JS_FALSE; - } - - /* Follow Perl by returning the new array length. */ - length += argc; - if (!js_SetLengthProperty(cx, obj, length)) - return JS_FALSE; - } - return IndexToValue(cx, length, rval); -} - -static JSBool -array_splice(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsval *vp, junk; - jsuint length, begin, end, count, delta, last; - jsdouble d; - jsid id, id2; - JSObject *obj2; - uintN i; - - /* - * Nothing to do if no args. Otherwise point vp at our one explicit local - * root and get length. - */ - if (argc == 0) - return JS_TRUE; - vp = argv + argc; - if (!js_GetLengthProperty(cx, obj, &length)) - return JS_FALSE; - - /* Convert the first argument into a starting index. */ - if (!js_ValueToNumber(cx, *argv, &d)) - return JS_FALSE; - d = js_DoubleToInteger(d); - if (d < 0) { - d += length; - if (d < 0) - d = 0; - } else if (d > length) { - d = length; - } - begin = (jsuint)d; /* d has been clamped to uint32 */ - argc--; - argv++; - - /* Convert the second argument from a count into a fencepost index. */ - delta = length - begin; - if (argc == 0) { - count = delta; - end = length; - } else { - if (!js_ValueToNumber(cx, *argv, &d)) - return JS_FALSE; - d = js_DoubleToInteger(d); - if (d < 0) - d = 0; - else if (d > delta) - d = delta; - count = (jsuint)d; - end = begin + count; - argc--; - argv++; - } - - if (count == 1 && JS_VERSION_IS_1_2(cx)) { - /* - * JS lacks "list context", whereby in Perl one turns the single - * scalar that's spliced out into an array just by assigning it to - * @single instead of $single, or by using it as Perl push's first - * argument, for instance. - * - * JS1.2 emulated Perl too closely and returned a non-Array for - * the single-splice-out case, requiring callers to test and wrap - * in [] if necessary. So JS1.3, default, and other versions all - * return an array of length 1 for uniformity. - */ - if (!IndexToId(cx, begin, &id)) - return JS_FALSE; - if (!OBJ_GET_PROPERTY(cx, obj, id, rval)) - return JS_FALSE; - } else { - if (!JS_VERSION_IS_1_2(cx) || count > 0) { - /* - * Create a new array value to return. Our ECMA v2 proposal specs - * that splice always returns an array value, even when given no - * arguments. We think this is best because it eliminates the need - * for callers to do an extra test to handle the empty splice case. - */ - obj2 = js_NewArrayObject(cx, 0, NULL); - if (!obj2) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(obj2); - - /* If there are elements to remove, put them into the return value. */ - if (count > 0) { - for (last = begin; last < end; last++) { - if (!IndexToExistingId(cx, obj, last, &id)) - return JS_FALSE; - if (id == JSID_HOLE) - continue; /* don't fill holes in the new array */ - if (!OBJ_GET_PROPERTY(cx, obj, id, vp)) - return JS_FALSE; - - /* Get id after value to avoid nested GC hazards. */ - if (!IndexToId(cx, last - begin, &id2)) - return JS_FALSE; - if (!OBJ_SET_PROPERTY(cx, obj2, id2, vp)) - return JS_FALSE; - } - - if (!js_SetLengthProperty(cx, obj2, end - begin)) - return JS_FALSE; - } - } - } - - /* Find the direction (up or down) to copy and make way for argv. */ - if (argc > count) { - delta = (jsuint)argc - count; - last = length; - /* (uint) end could be 0, so can't use vanilla >= test */ - while (last-- > end) { - if (!IndexToExistingId(cx, obj, last, &id)) - return JS_FALSE; - if (id != JSID_HOLE) { - if (!OBJ_GET_PROPERTY(cx, obj, id, vp)) - return JS_FALSE; - } - - /* Get id after value to avoid nested GC hazards. */ - if (!IndexToId(cx, last + delta, &id2)) - return JS_FALSE; - if (id != JSID_HOLE) { - if (!OBJ_SET_PROPERTY(cx, obj, id2, vp)) - return JS_FALSE; - } else { - if (!OBJ_DELETE_PROPERTY(cx, obj, id2, &junk)) - return JS_FALSE; - } - } - length += delta; - } else if (argc < count) { - delta = count - (jsuint)argc; - for (last = end; last < length; last++) { - if (!IndexToExistingId(cx, obj, last, &id)) - return JS_FALSE; - if (id != JSID_HOLE) { - if (!OBJ_GET_PROPERTY(cx, obj, id, vp)) - return JS_FALSE; - } - - /* Get id after value to avoid nested GC hazards. */ - if (!IndexToId(cx, last - delta, &id2)) - return JS_FALSE; - if (id != JSID_HOLE) { - if (!OBJ_SET_PROPERTY(cx, obj, id2, vp)) - return JS_FALSE; - } else { - if (!OBJ_DELETE_PROPERTY(cx, obj, id2, &junk)) - return JS_FALSE; - } - } - length -= delta; - } - - /* Copy from argv into the hole to complete the splice. */ - for (i = 0; i < argc; i++) { - if (!IndexToId(cx, begin + i, &id)) - return JS_FALSE; - if (!OBJ_SET_PROPERTY(cx, obj, id, &argv[i])) - return JS_FALSE; - } - - /* Update length in case we deleted elements from the end. */ - return js_SetLengthProperty(cx, obj, length); -} -#endif /* JS_HAS_MORE_PERL_FUN */ - -#if JS_HAS_SEQUENCE_OPS -/* - * Python-esque sequence operations. - */ -static JSBool -array_concat(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsval *vp, v; - JSObject *nobj, *aobj; - jsuint length, alength, slot; - uintN i; - jsid id, id2; - - /* Hoist the explicit local root address computation. */ - vp = argv + argc; - - /* Treat obj as the first argument; see ECMA 15.4.4.4. */ - --argv; - JS_ASSERT(obj == JSVAL_TO_OBJECT(argv[0])); - - /* Create a new Array object and store it in the rval local root. */ - nobj = js_NewArrayObject(cx, 0, NULL); - if (!nobj) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(nobj); - - /* Loop over [0, argc] to concat args into nobj, expanding all Arrays. */ - length = 0; - for (i = 0; i <= argc; i++) { - v = argv[i]; - if (JSVAL_IS_OBJECT(v)) { - aobj = JSVAL_TO_OBJECT(v); - if (aobj && OBJ_GET_CLASS(cx, aobj) == &js_ArrayClass) { - if (!OBJ_GET_PROPERTY(cx, aobj, - ATOM_TO_JSID(cx->runtime->atomState - .lengthAtom), - vp)) { - return JS_FALSE; - } - if (!ValueIsLength(cx, *vp, &alength)) - return JS_FALSE; - for (slot = 0; slot < alength; slot++) { - if (!IndexToExistingId(cx, aobj, slot, &id)) - return JS_FALSE; - if (id == JSID_HOLE) { - /* - * Per ECMA 262, 15.4.4.4, step 9, ignore non-existent - * properties. - */ - continue; - } - if (!OBJ_GET_PROPERTY(cx, aobj, id, vp)) - return JS_FALSE; - - /* Get id after value to avoid nested GC hazards. */ - if (!IndexToId(cx, length + slot, &id2)) - return JS_FALSE; - if (!OBJ_SET_PROPERTY(cx, nobj, id2, vp)) - return JS_FALSE; - } - length += alength; - continue; - } - } - - *vp = v; - if (!IndexToId(cx, length, &id)) - return JS_FALSE; - if (!OBJ_SET_PROPERTY(cx, nobj, id, vp)) - return JS_FALSE; - length++; - } - - return js_SetLengthProperty(cx, nobj, length); -} - -static JSBool -array_slice(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsval *vp; - JSObject *nobj; - jsuint length, begin, end, slot; - jsdouble d; - jsid id, id2; - - /* Hoist the explicit local root address computation. */ - vp = argv + argc; - - /* Create a new Array object and store it in the rval local root. */ - nobj = js_NewArrayObject(cx, 0, NULL); - if (!nobj) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(nobj); - - if (!js_GetLengthProperty(cx, obj, &length)) - return JS_FALSE; - begin = 0; - end = length; - - if (argc > 0) { - if (!js_ValueToNumber(cx, argv[0], &d)) - return JS_FALSE; - d = js_DoubleToInteger(d); - if (d < 0) { - d += length; - if (d < 0) - d = 0; - } else if (d > length) { - d = length; - } - begin = (jsuint)d; - - if (argc > 1) { - if (!js_ValueToNumber(cx, argv[1], &d)) - return JS_FALSE; - d = js_DoubleToInteger(d); - if (d < 0) { - d += length; - if (d < 0) - d = 0; - } else if (d > length) { - d = length; - } - end = (jsuint)d; - } - } - - if (begin > end) - begin = end; - - for (slot = begin; slot < end; slot++) { - if (!IndexToExistingId(cx, obj, slot, &id)) - return JS_FALSE; - if (id == JSID_HOLE) - continue; - if (!OBJ_GET_PROPERTY(cx, obj, id, vp)) - return JS_FALSE; - - /* Get id after value to avoid nested GC hazards. */ - if (!IndexToId(cx, slot - begin, &id2)) - return JS_FALSE; - if (!OBJ_SET_PROPERTY(cx, nobj, id2, vp)) - return JS_FALSE; - } - return js_SetLengthProperty(cx, nobj, end - begin); -} -#endif /* JS_HAS_SEQUENCE_OPS */ - -#if JS_HAS_ARRAY_EXTRAS - -static JSBool -array_indexOfHelper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval, JSBool isLast) -{ - jsuint length, i, stop; - jsint direction; - - if (!js_GetLengthProperty(cx, obj, &length)) - return JS_FALSE; - if (length == 0) - goto not_found; - - if (argc <= 1) { - i = isLast ? length - 1 : 0; - } else { - jsdouble start; - - if (!js_ValueToNumber(cx, argv[1], &start)) - return JS_FALSE; - start = js_DoubleToInteger(start); - if (start < 0) { - start += length; - i = (start < 0) ? 0 : (jsuint)start; - } else if (start >= length) { - i = length - 1; - } else { - i = (jsuint)start; - } - } - - if (isLast) { - stop = 0; - direction = -1; - } else { - stop = length - 1; - direction = 1; - } - - for (;;) { - jsid id; - jsval v; - - if (!IndexToExistingId(cx, obj, (jsuint)i, &id)) - return JS_FALSE; - if (id != JSID_HOLE) { - if (!OBJ_GET_PROPERTY(cx, obj, id, &v)) - return JS_FALSE; - if (js_StrictlyEqual(v, argv[0])) - return js_NewNumberValue(cx, i, rval); - } - - if (i == stop) - goto not_found; - i += direction; - } - - not_found: - *rval = INT_TO_JSVAL(-1); - return JS_TRUE; -} - -static JSBool -array_indexOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - return array_indexOfHelper(cx, obj, argc, argv, rval, JS_FALSE); -} - -static JSBool -array_lastIndexOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - return array_indexOfHelper(cx, obj, argc, argv, rval, JS_TRUE); -} - -/* Order is important; extras that use a caller's predicate must follow MAP. */ -typedef enum ArrayExtraMode { - FOREACH, - MAP, - FILTER, - SOME, - EVERY -} ArrayExtraMode; - -static JSBool -array_extra(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval, - ArrayExtraMode mode) -{ - jsval *vp, *sp, *origsp, *oldsp; - jsuint length, newlen, i; - JSObject *callable, *thisp, *newarr; - void *mark; - JSStackFrame *fp; - JSBool ok, b; - - /* Hoist the explicit local root address computation. */ - vp = argv + argc; - - if (!js_GetLengthProperty(cx, obj, &length)) - return JS_FALSE; - - /* - * First, get or compute our callee, so that we error out consistently - * when passed a non-callable object. - */ - callable = js_ValueToCallableObject(cx, &argv[0], 0); - if (!callable) - return JS_FALSE; - - /* - * Set our initial return condition, used for zero-length array cases - * (and pre-size our map return to match our known length, for all cases). - */ -#ifdef __GNUC__ /* quell GCC overwarning */ - newlen = 0; - newarr = NULL; - ok = JS_TRUE; -#endif - switch (mode) { - case MAP: - case FILTER: - newlen = (mode == MAP) ? length : 0; - newarr = js_NewArrayObject(cx, newlen, NULL); - if (!newarr) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(newarr); - break; - case SOME: - *rval = JSVAL_FALSE; - break; - case EVERY: - *rval = JSVAL_TRUE; - break; - case FOREACH: - break; - } - - if (length == 0) - return JS_TRUE; - - if (argc > 1) { - if (!js_ValueToObject(cx, argv[1], &thisp)) - return JS_FALSE; - argv[1] = OBJECT_TO_JSVAL(thisp); - } else { - thisp = NULL; - } - - /* We call with 3 args (value, index, array), plus room for rval. */ - origsp = js_AllocStack(cx, 2 + 3 + 1, &mark); - if (!origsp) - return JS_FALSE; - - /* Lift current frame to include our args. */ - fp = cx->fp; - oldsp = fp->sp; - - for (i = 0; i < length; i++) { - jsid id; - jsval rval2; - - ok = IndexToExistingId(cx, obj, i, &id); - if (!ok) - break; - if (id == JSID_HOLE) - continue; - ok = OBJ_GET_PROPERTY(cx, obj, id, vp); - if (!ok) - break; - - /* - * Push callable and 'this', then args. We must do this for every - * iteration around the loop since js_Invoke uses origsp[0] for rval - * storage and some native functions use origsp[1] for local rooting. - */ - sp = origsp; - *sp++ = OBJECT_TO_JSVAL(callable); - *sp++ = OBJECT_TO_JSVAL(thisp); - *sp++ = *vp; - *sp++ = INT_TO_JSVAL(i); - *sp++ = OBJECT_TO_JSVAL(obj); - - /* Do the call. */ - fp->sp = sp; - ok = js_Invoke(cx, 3, JSINVOKE_INTERNAL); - rval2 = fp->sp[-1]; - fp->sp = oldsp; - if (!ok) - break; - - if (mode > MAP) { - if (rval2 == JSVAL_NULL) { - b = JS_FALSE; - } else if (JSVAL_IS_BOOLEAN(rval2)) { - b = JSVAL_TO_BOOLEAN(rval2); - } else { - ok = js_ValueToBoolean(cx, rval2, &b); - if (!ok) - goto out; - } - } - - switch (mode) { - case FOREACH: - break; - case MAP: - /* - * We reconstruct id once again when it is a GC thing since scripts - * can trigger GC that collects it. See bug 341956. - */ - if (i > JSVAL_INT_MAX) { - ok = IndexToId(cx, i, &id); - if (!ok) - goto out; - } - ok = OBJ_SET_PROPERTY(cx, newarr, id, &rval2); - if (!ok) - goto out; - break; - case FILTER: - if (!b) - break; - /* Filter passed *vp, push as result. */ - ok = IndexToId(cx, newlen++, &id); - if (!ok) - goto out; - ok = OBJ_SET_PROPERTY(cx, newarr, id, vp); - if (!ok) - goto out; - break; - case SOME: - if (b) { - *rval = JSVAL_TRUE; - goto out; - } - break; - case EVERY: - if (!b) { - *rval = JSVAL_FALSE; - goto out; - } - break; - } - } - - out: - js_FreeStack(cx, mark); - if (ok && mode == FILTER) - ok = js_SetLengthProperty(cx, newarr, newlen); - return ok; -} - -static JSBool -array_forEach(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - return array_extra(cx, obj, argc, argv, rval, FOREACH); -} - -static JSBool -array_map(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - return array_extra(cx, obj, argc, argv, rval, MAP); -} - -static JSBool -array_filter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - return array_extra(cx, obj, argc, argv, rval, FILTER); -} - -static JSBool -array_some(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - return array_extra(cx, obj, argc, argv, rval, SOME); -} - -static JSBool -array_every(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - return array_extra(cx, obj, argc, argv, rval, EVERY); -} -#endif - -static JSFunctionSpec array_methods[] = { -#if JS_HAS_TOSOURCE - {js_toSource_str, array_toSource, 0,0,0}, -#endif - {js_toString_str, array_toString, 0,0,0}, - {js_toLocaleString_str, array_toLocaleString, 0,0,0}, - - /* Perl-ish methods. */ -#if JS_HAS_SOME_PERL_FUN - {"join", array_join, 1,JSFUN_GENERIC_NATIVE,0}, - {"reverse", array_reverse, 0,JSFUN_GENERIC_NATIVE,2}, - {"sort", array_sort, 1,JSFUN_GENERIC_NATIVE,2}, -#endif -#if JS_HAS_MORE_PERL_FUN - {"push", array_push, 1,JSFUN_GENERIC_NATIVE,0}, - {"pop", array_pop, 0,JSFUN_GENERIC_NATIVE,0}, - {"shift", array_shift, 0,JSFUN_GENERIC_NATIVE,1}, - {"unshift", array_unshift, 1,JSFUN_GENERIC_NATIVE,1}, - {"splice", array_splice, 2,JSFUN_GENERIC_NATIVE,1}, -#endif - - /* Python-esque sequence methods. */ -#if JS_HAS_SEQUENCE_OPS - {"concat", array_concat, 1,JSFUN_GENERIC_NATIVE,1}, - {"slice", array_slice, 2,JSFUN_GENERIC_NATIVE,1}, -#endif - -#if JS_HAS_ARRAY_EXTRAS - {"indexOf", array_indexOf, 1,JSFUN_GENERIC_NATIVE,0}, - {"lastIndexOf", array_lastIndexOf, 1,JSFUN_GENERIC_NATIVE,0}, - {"forEach", array_forEach, 1,JSFUN_GENERIC_NATIVE,1}, - {"map", array_map, 1,JSFUN_GENERIC_NATIVE,1}, - {"filter", array_filter, 1,JSFUN_GENERIC_NATIVE,1}, - {"some", array_some, 1,JSFUN_GENERIC_NATIVE,1}, - {"every", array_every, 1,JSFUN_GENERIC_NATIVE,1}, -#endif - - {0,0,0,0,0} -}; - -static JSBool -Array(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsuint length; - jsval *vector; - - /* If called without new, replace obj with a new Array object. */ - if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) { - obj = js_NewObject(cx, &js_ArrayClass, NULL, NULL); - if (!obj) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(obj); - } - - if (argc == 0) { - length = 0; - vector = NULL; - } else if (JS_VERSION_IS_1_2(cx)) { - length = (jsuint) argc; - vector = argv; - } else if (argc > 1) { - length = (jsuint) argc; - vector = argv; - } else if (!JSVAL_IS_NUMBER(argv[0])) { - length = 1; - vector = argv; - } else { - if (!ValueIsLength(cx, argv[0], &length)) - return JS_FALSE; - vector = NULL; - } - return InitArrayObject(cx, obj, length, vector); -} - -JSObject * -js_InitArrayClass(JSContext *cx, JSObject *obj) -{ - JSObject *proto; - - proto = JS_InitClass(cx, obj, NULL, &js_ArrayClass, Array, 1, - NULL, array_methods, NULL, NULL); - - /* Initialize the Array prototype object so it gets a length property. */ - if (!proto || !InitArrayObject(cx, proto, 0, NULL)) - return NULL; - return proto; -} - -JSObject * -js_NewArrayObject(JSContext *cx, jsuint length, jsval *vector) -{ - JSObject *obj; - - obj = js_NewObject(cx, &js_ArrayClass, NULL, NULL); - if (!obj) - return NULL; - if (!InitArrayObject(cx, obj, length, vector)) { - cx->newborn[GCX_OBJECT] = NULL; - return NULL; - } - return obj; -} diff --git a/lib/javascript/jsarray.h b/lib/javascript/jsarray.h deleted file mode 100644 index 0f43bee0..00000000 --- a/lib/javascript/jsarray.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jsarray_h___ -#define jsarray_h___ -/* - * JS Array interface. - */ -#include "jsprvtd.h" -#include "jspubtd.h" - -JS_BEGIN_EXTERN_C - -extern JSBool -js_IdIsIndex(jsval id, jsuint *indexp); - -extern JSClass js_ArrayClass; - -extern JSObject * -js_InitArrayClass(JSContext *cx, JSObject *obj); - -extern JSObject * -js_NewArrayObject(JSContext *cx, jsuint length, jsval *vector); - -extern JSBool -js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp); - -extern JSBool -js_SetLengthProperty(JSContext *cx, JSObject *obj, jsuint length); - -extern JSBool -js_HasLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp); - -/* - * JS-specific heap sort function. - */ -typedef int (*JSComparator)(const void *a, const void *b, void *arg); - -extern void -js_HeapSort(void *vec, size_t nel, void *pivot, size_t elsize, - JSComparator cmp, void *arg); - -JS_END_EXTERN_C - -#endif /* jsarray_h___ */ diff --git a/lib/javascript/jsatom.c b/lib/javascript/jsatom.c deleted file mode 100644 index 6de628ae..00000000 --- a/lib/javascript/jsatom.c +++ /dev/null @@ -1,980 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JS atom table. - */ -#include "jsstddef.h" -#include -#include -#include "jstypes.h" -#include "jsutil.h" /* Added by JSIFY */ -#include "jshash.h" /* Added by JSIFY */ -#include "jsprf.h" -#include "jsapi.h" -#include "jsatom.h" -#include "jscntxt.h" -#include "jsconfig.h" -#include "jsgc.h" -#include "jslock.h" -#include "jsnum.h" -#include "jsopcode.h" -#include "jsstr.h" - -JS_FRIEND_API(const char *) -js_AtomToPrintableString(JSContext *cx, JSAtom *atom) -{ - return js_ValueToPrintableString(cx, ATOM_KEY(atom)); -} - -#if JS_HAS_ERROR_EXCEPTIONS -extern const char js_Error_str[]; /* trivial, from jsexn.h */ -#endif - -/* - * Keep this in sync with jspubtd.h -- an assertion below will insist that - * its length match the JSType enum's JSTYPE_LIMIT limit value. - */ -const char *js_type_str[] = { - "undefined", - js_object_str, - "function", - "string", - "number", - "boolean", - "null", - "xml", -}; - -const char *js_boolean_str[] = { - js_false_str, - js_true_str -}; - -const char js_Arguments_str[] = "Arguments"; -const char js_Array_str[] = "Array"; -const char js_Boolean_str[] = "Boolean"; -const char js_Call_str[] = "Call"; -const char js_Date_str[] = "Date"; -const char js_Function_str[] = "Function"; -const char js_Math_str[] = "Math"; -const char js_Namespace_str[] = "Namespace"; -const char js_Number_str[] = "Number"; -const char js_Object_str[] = "Object"; -const char js_QName_str[] = "QName"; -const char js_RegExp_str[] = "RegExp"; -const char js_Script_str[] = "Script"; -const char js_String_str[] = "String"; -const char js_XML_str[] = "XML"; -const char js_File_str[] = "File"; -const char js_anonymous_str[] = "anonymous"; -const char js_arguments_str[] = "arguments"; -const char js_arity_str[] = "arity"; -const char js_callee_str[] = "callee"; -const char js_caller_str[] = "caller"; -const char js_class_prototype_str[] = "prototype"; -const char js_constructor_str[] = "constructor"; -const char js_count_str[] = "__count__"; -const char js_each_str[] = "each"; -const char js_eval_str[] = "eval"; -const char js_getter_str[] = "getter"; -const char js_get_str[] = "get"; -const char js_index_str[] = "index"; -const char js_input_str[] = "input"; -const char js_length_str[] = "length"; -const char js_name_str[] = "name"; -const char js_noSuchMethod_str[] = "__noSuchMethod__"; -const char js_object_str[] = "object"; -const char js_parent_str[] = "__parent__"; -const char js_private_str[] = "private"; -const char js_proto_str[] = "__proto__"; -const char js_setter_str[] = "setter"; -const char js_set_str[] = "set"; -const char js_toSource_str[] = "toSource"; -const char js_toString_str[] = "toString"; -const char js_toLocaleString_str[] = "toLocaleString"; -const char js_valueOf_str[] = "valueOf"; - -#if JS_HAS_XML_SUPPORT -const char js_etago_str[] = ""; -const char js_qualifier_str[] = "::"; -const char js_space_str[] = " "; -const char js_stago_str[] = "<"; -const char js_star_str[] = "*"; -const char js_starQualifier_str[] = "*::"; -const char js_tagc_str[] = ">"; -const char js_xml_str[] = "xml"; -#endif - -#ifdef NARCISSUS -const char js_call_str[] = "__call__"; -const char js_construct_str[] = "__construct__"; -const char js_hasInstance_str[] = "__hasInstance__"; -const char js_ExecutionContext_str[] = "ExecutionContext"; -const char js_current_str[] = "current"; -#endif - -#define HASH_OBJECT(o) (JS_PTR_TO_UINT32(o) >> JSVAL_TAGBITS) -#define HASH_INT(i) ((JSHashNumber)(i)) -#define HASH_DOUBLE(dp) ((JSDOUBLE_HI32(*dp) ^ JSDOUBLE_LO32(*dp))) -#define HASH_BOOLEAN(b) ((JSHashNumber)(b)) - -JS_STATIC_DLL_CALLBACK(JSHashNumber) -js_hash_atom_key(const void *key) -{ - jsval v; - jsdouble *dp; - - /* Order JSVAL_IS_* tests by likelihood of success. */ - v = (jsval)key; - if (JSVAL_IS_STRING(v)) - return js_HashString(JSVAL_TO_STRING(v)); - if (JSVAL_IS_INT(v)) - return HASH_INT(JSVAL_TO_INT(v)); - if (JSVAL_IS_DOUBLE(v)) { - dp = JSVAL_TO_DOUBLE(v); - return HASH_DOUBLE(dp); - } - if (JSVAL_IS_OBJECT(v)) - return HASH_OBJECT(JSVAL_TO_OBJECT(v)); - if (JSVAL_IS_BOOLEAN(v)) - return HASH_BOOLEAN(JSVAL_TO_BOOLEAN(v)); - return (JSHashNumber)v; -} - -JS_STATIC_DLL_CALLBACK(intN) -js_compare_atom_keys(const void *k1, const void *k2) -{ - jsval v1, v2; - - v1 = (jsval)k1, v2 = (jsval)k2; - if (JSVAL_IS_STRING(v1) && JSVAL_IS_STRING(v2)) - return !js_CompareStrings(JSVAL_TO_STRING(v1), JSVAL_TO_STRING(v2)); - if (JSVAL_IS_DOUBLE(v1) && JSVAL_IS_DOUBLE(v2)) { - double d1 = *JSVAL_TO_DOUBLE(v1); - double d2 = *JSVAL_TO_DOUBLE(v2); - if (JSDOUBLE_IS_NaN(d1)) - return JSDOUBLE_IS_NaN(d2); -#if defined(XP_WIN) - /* XXX MSVC miscompiles such that (NaN == 0) */ - if (JSDOUBLE_IS_NaN(d2)) - return JS_FALSE; -#endif - return d1 == d2; - } - return v1 == v2; -} - -JS_STATIC_DLL_CALLBACK(int) -js_compare_stub(const void *v1, const void *v2) -{ - return 1; -} - -/* These next two are exported to jsscript.c and used similarly there. */ -void * JS_DLL_CALLBACK -js_alloc_table_space(void *priv, size_t size) -{ - return malloc(size); -} - -void JS_DLL_CALLBACK -js_free_table_space(void *priv, void *item) -{ - free(item); -} - -JS_STATIC_DLL_CALLBACK(JSHashEntry *) -js_alloc_atom(void *priv, const void *key) -{ - JSAtomState *state = (JSAtomState *) priv; - JSAtom *atom; - - atom = (JSAtom *) malloc(sizeof(JSAtom)); - if (!atom) - return NULL; -#ifdef JS_THREADSAFE - state->tablegen++; -#endif - atom->entry.key = key; - atom->entry.value = NULL; - atom->flags = 0; - atom->number = state->number++; - return &atom->entry; -} - -JS_STATIC_DLL_CALLBACK(void) -js_free_atom(void *priv, JSHashEntry *he, uintN flag) -{ - if (flag != HT_FREE_ENTRY) - return; -#ifdef JS_THREADSAFE - ((JSAtomState *)priv)->tablegen++; -#endif - free(he); -} - -static JSHashAllocOps atom_alloc_ops = { - js_alloc_table_space, js_free_table_space, - js_alloc_atom, js_free_atom -}; - -#define JS_ATOM_HASH_SIZE 1024 - -JSBool -js_InitAtomState(JSContext *cx, JSAtomState *state) -{ - state->table = JS_NewHashTable(JS_ATOM_HASH_SIZE, js_hash_atom_key, - js_compare_atom_keys, js_compare_stub, - &atom_alloc_ops, state); - if (!state->table) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - - state->runtime = cx->runtime; -#ifdef JS_THREADSAFE - js_InitLock(&state->lock); - state->tablegen = 0; -#endif - - if (!js_InitPinnedAtoms(cx, state)) { - js_FreeAtomState(cx, state); - return JS_FALSE; - } - return JS_TRUE; -} - -JSBool -js_InitPinnedAtoms(JSContext *cx, JSAtomState *state) -{ - uintN i; - -#define FROB(lval,str) \ - JS_BEGIN_MACRO \ - if (!(state->lval = js_Atomize(cx, str, strlen(str), ATOM_PINNED))) \ - return JS_FALSE; \ - JS_END_MACRO - - JS_ASSERT(sizeof js_type_str / sizeof js_type_str[0] == JSTYPE_LIMIT); - for (i = 0; i < JSTYPE_LIMIT; i++) - FROB(typeAtoms[i], js_type_str[i]); - - FROB(booleanAtoms[0], js_false_str); - FROB(booleanAtoms[1], js_true_str); - FROB(nullAtom, js_null_str); - - FROB(ArgumentsAtom, js_Arguments_str); - FROB(ArrayAtom, js_Array_str); - FROB(BooleanAtom, js_Boolean_str); - FROB(CallAtom, js_Call_str); - FROB(DateAtom, js_Date_str); -#if JS_HAS_ERROR_EXCEPTIONS - FROB(ErrorAtom, js_Error_str); -#endif - FROB(FunctionAtom, js_Function_str); - FROB(MathAtom, js_Math_str); - FROB(NamespaceAtom, js_Namespace_str); - FROB(NumberAtom, js_Number_str); - FROB(ObjectAtom, js_Object_str); - FROB(QNameAtom, js_QName_str); - FROB(RegExpAtom, js_RegExp_str); - FROB(ScriptAtom, js_Script_str); - FROB(StringAtom, js_String_str); - FROB(XMLAtom, js_XML_str); - FROB(FileAtom, js_File_str); - FROB(anonymousAtom, js_anonymous_str); - FROB(argumentsAtom, js_arguments_str); - FROB(arityAtom, js_arity_str); - FROB(calleeAtom, js_callee_str); - FROB(callerAtom, js_caller_str); - FROB(classPrototypeAtom, js_class_prototype_str); - FROB(constructorAtom, js_constructor_str); - FROB(countAtom, js_count_str); - FROB(eachAtom, js_each_str); - FROB(evalAtom, js_eval_str); - FROB(getAtom, js_get_str); - FROB(getterAtom, js_getter_str); - FROB(indexAtom, js_index_str); - FROB(inputAtom, js_input_str); - FROB(lengthAtom, js_length_str); - FROB(nameAtom, js_name_str); - FROB(noSuchMethodAtom, js_noSuchMethod_str); - FROB(parentAtom, js_parent_str); - FROB(protoAtom, js_proto_str); - FROB(setAtom, js_set_str); - FROB(setterAtom, js_setter_str); - FROB(toSourceAtom, js_toSource_str); - FROB(toStringAtom, js_toString_str); - FROB(toLocaleStringAtom, js_toLocaleString_str); - FROB(valueOfAtom, js_valueOf_str); - -#if JS_HAS_XML_SUPPORT - FROB(etagoAtom, js_etago_str); - FROB(namespaceAtom, js_namespace_str); - FROB(ptagcAtom, js_ptagc_str); - FROB(qualifierAtom, js_qualifier_str); - FROB(spaceAtom, js_space_str); - FROB(stagoAtom, js_stago_str); - FROB(starAtom, js_star_str); - FROB(starQualifierAtom, js_starQualifier_str); - FROB(tagcAtom, js_tagc_str); - FROB(xmlAtom, js_xml_str); -#endif - -#ifdef NARCISSUS - FROB(callAtom, js_call_str); - FROB(constructAtom, js_construct_str); - FROB(hasInstanceAtom, js_hasInstance_str); - FROB(ExecutionContextAtom, js_ExecutionContext_str); - FROB(currentAtom, js_current_str); -#endif - -#undef FROB - - memset(&state->lazy, 0, sizeof state->lazy); - return JS_TRUE; -} - -/* NB: cx unused; js_FinishAtomState calls us with null cx. */ -void -js_FreeAtomState(JSContext *cx, JSAtomState *state) -{ - if (state->table) - JS_HashTableDestroy(state->table); -#ifdef JS_THREADSAFE - js_FinishLock(&state->lock); -#endif - memset(state, 0, sizeof *state); -} - -typedef struct UninternArgs { - JSRuntime *rt; - jsatomid leaks; -} UninternArgs; - -JS_STATIC_DLL_CALLBACK(intN) -js_atom_uninterner(JSHashEntry *he, intN i, void *arg) -{ - JSAtom *atom; - UninternArgs *args; - - atom = (JSAtom *)he; - args = (UninternArgs *)arg; - if (ATOM_IS_STRING(atom)) - js_FinalizeStringRT(args->rt, ATOM_TO_STRING(atom)); - else if (ATOM_IS_OBJECT(atom)) - args->leaks++; - return HT_ENUMERATE_NEXT; -} - -void -js_FinishAtomState(JSAtomState *state) -{ - UninternArgs args; - - if (!state->table) - return; - args.rt = state->runtime; - args.leaks = 0; - JS_HashTableEnumerateEntries(state->table, js_atom_uninterner, &args); -#ifdef DEBUG - if (args.leaks != 0) { - fprintf(stderr, -"JS engine warning: %lu atoms remain after destroying the JSRuntime.\n" -" These atoms may point to freed memory. Things reachable\n" -" through them have not been finalized.\n", - (unsigned long) args.leaks); - } -#endif - js_FreeAtomState(NULL, state); -} - -typedef struct MarkArgs { - uintN gcflags; - JSGCThingMarker mark; - void *data; -} MarkArgs; - -JS_STATIC_DLL_CALLBACK(intN) -js_atom_marker(JSHashEntry *he, intN i, void *arg) -{ - JSAtom *atom; - MarkArgs *args; - jsval key; - - atom = (JSAtom *)he; - args = (MarkArgs *)arg; - if ((atom->flags & (ATOM_PINNED | ATOM_INTERNED)) || - (args->gcflags & GC_KEEP_ATOMS)) { - atom->flags |= ATOM_MARK; - key = ATOM_KEY(atom); - if (JSVAL_IS_GCTHING(key)) - args->mark(JSVAL_TO_GCTHING(key), args->data); - } - return HT_ENUMERATE_NEXT; -} - -void -js_MarkAtomState(JSAtomState *state, uintN gcflags, JSGCThingMarker mark, - void *data) -{ - MarkArgs args; - - if (!state->table) - return; - args.gcflags = gcflags; - args.mark = mark; - args.data = data; - JS_HashTableEnumerateEntries(state->table, js_atom_marker, &args); -} - -JS_STATIC_DLL_CALLBACK(intN) -js_atom_sweeper(JSHashEntry *he, intN i, void *arg) -{ - JSAtom *atom; - JSAtomState *state; - - atom = (JSAtom *)he; - if (atom->flags & ATOM_MARK) { - atom->flags &= ~ATOM_MARK; - state = (JSAtomState *)arg; - state->liveAtoms++; - return HT_ENUMERATE_NEXT; - } - JS_ASSERT((atom->flags & (ATOM_PINNED | ATOM_INTERNED)) == 0); - atom->entry.key = atom->entry.value = NULL; - atom->flags = 0; - return HT_ENUMERATE_REMOVE; -} - -void -js_SweepAtomState(JSAtomState *state) -{ - state->liveAtoms = 0; - if (state->table) - JS_HashTableEnumerateEntries(state->table, js_atom_sweeper, state); -} - -JS_STATIC_DLL_CALLBACK(intN) -js_atom_unpinner(JSHashEntry *he, intN i, void *arg) -{ - JSAtom *atom; - - atom = (JSAtom *)he; - atom->flags &= ~ATOM_PINNED; - return HT_ENUMERATE_NEXT; -} - -void -js_UnpinPinnedAtoms(JSAtomState *state) -{ - if (state->table) - JS_HashTableEnumerateEntries(state->table, js_atom_unpinner, NULL); -} - -static JSAtom * -js_AtomizeHashedKey(JSContext *cx, jsval key, JSHashNumber keyHash, uintN flags) -{ - JSAtomState *state; - JSHashTable *table; - JSHashEntry *he, **hep; - JSAtom *atom; - - state = &cx->runtime->atomState; - JS_LOCK(&state->lock, cx); - table = state->table; - hep = JS_HashTableRawLookup(table, keyHash, (void *)key); - if ((he = *hep) == NULL) { - he = JS_HashTableRawAdd(table, hep, keyHash, (void *)key, NULL); - if (!he) { - JS_ReportOutOfMemory(cx); - atom = NULL; - goto out; - } - } - - atom = (JSAtom *)he; - atom->flags |= flags; - cx->lastAtom = atom; -out: - JS_UNLOCK(&state->lock,cx); - return atom; -} - -JSAtom * -js_AtomizeObject(JSContext *cx, JSObject *obj, uintN flags) -{ - jsval key; - JSHashNumber keyHash; - - /* XXX must be set in the following order or MSVC1.52 will crash */ - keyHash = HASH_OBJECT(obj); - key = OBJECT_TO_JSVAL(obj); - return js_AtomizeHashedKey(cx, key, keyHash, flags); -} - -JSAtom * -js_AtomizeBoolean(JSContext *cx, JSBool b, uintN flags) -{ - jsval key; - JSHashNumber keyHash; - - key = BOOLEAN_TO_JSVAL(b); - keyHash = HASH_BOOLEAN(b); - return js_AtomizeHashedKey(cx, key, keyHash, flags); -} - -JSAtom * -js_AtomizeInt(JSContext *cx, jsint i, uintN flags) -{ - jsval key; - JSHashNumber keyHash; - - key = INT_TO_JSVAL(i); - keyHash = HASH_INT(i); - return js_AtomizeHashedKey(cx, key, keyHash, flags); -} - -/* Worst-case alignment grain and aligning macro for 2x-sized buffer. */ -#define ALIGNMENT(t) JS_MAX(JSVAL_ALIGN, sizeof(t)) -#define ALIGN(b,t) ((t*) &(b)[ALIGNMENT(t) - (jsuword)(b) % ALIGNMENT(t)]) - -JSAtom * -js_AtomizeDouble(JSContext *cx, jsdouble d, uintN flags) -{ - jsdouble *dp; - JSHashNumber keyHash; - jsval key; - JSAtomState *state; - JSHashTable *table; - JSHashEntry *he, **hep; - JSAtom *atom; - char buf[2 * ALIGNMENT(double)]; - - dp = ALIGN(buf, double); - *dp = d; - keyHash = HASH_DOUBLE(dp); - key = DOUBLE_TO_JSVAL(dp); - state = &cx->runtime->atomState; - JS_LOCK(&state->lock, cx); - table = state->table; - hep = JS_HashTableRawLookup(table, keyHash, (void *)key); - if ((he = *hep) == NULL) { -#ifdef JS_THREADSAFE - uint32 gen = state->tablegen; -#endif - JS_UNLOCK(&state->lock,cx); - if (!js_NewDoubleValue(cx, d, &key)) - return NULL; - JS_LOCK(&state->lock, cx); -#ifdef JS_THREADSAFE - if (state->tablegen != gen) { - hep = JS_HashTableRawLookup(table, keyHash, (void *)key); - if ((he = *hep) != NULL) { - atom = (JSAtom *)he; - goto out; - } - } -#endif - he = JS_HashTableRawAdd(table, hep, keyHash, (void *)key, NULL); - if (!he) { - JS_ReportOutOfMemory(cx); - atom = NULL; - goto out; - } - } - - atom = (JSAtom *)he; - atom->flags |= flags; - cx->lastAtom = atom; -out: - JS_UNLOCK(&state->lock,cx); - return atom; -} - -/* - * To put an atom into the hidden subspace. XOR its keyHash with this value, - * which is (sqrt(2)-1) in 32-bit fixed point. - */ -#define HIDDEN_ATOM_SUBSPACE_KEYHASH 0x6A09E667 - -JSAtom * -js_AtomizeString(JSContext *cx, JSString *str, uintN flags) -{ - JSHashNumber keyHash; - jsval key; - JSAtomState *state; - JSHashTable *table; - JSHashEntry *he, **hep; - JSAtom *atom; - - keyHash = js_HashString(str); - if (flags & ATOM_HIDDEN) - keyHash ^= HIDDEN_ATOM_SUBSPACE_KEYHASH; - key = STRING_TO_JSVAL(str); - state = &cx->runtime->atomState; - JS_LOCK(&state->lock, cx); - table = state->table; - hep = JS_HashTableRawLookup(table, keyHash, (void *)key); - if ((he = *hep) == NULL) { -#ifdef JS_THREADSAFE - uint32 gen = state->tablegen; - JS_UNLOCK(&state->lock, cx); -#endif - - if (flags & ATOM_TMPSTR) { - str = (flags & ATOM_NOCOPY) - ? js_NewString(cx, str->chars, str->length, 0) - : js_NewStringCopyN(cx, str->chars, str->length, 0); - if (!str) - return NULL; - key = STRING_TO_JSVAL(str); - } else { - if (!JS_MakeStringImmutable(cx, str)) - return NULL; - } - -#ifdef JS_THREADSAFE - JS_LOCK(&state->lock, cx); - if (state->tablegen != gen) { - hep = JS_HashTableRawLookup(table, keyHash, (void *)key); - if ((he = *hep) != NULL) { - atom = (JSAtom *)he; - if (flags & ATOM_NOCOPY) - str->chars = NULL; - goto out; - } - } -#endif - - he = JS_HashTableRawAdd(table, hep, keyHash, (void *)key, NULL); - if (!he) { - JS_ReportOutOfMemory(cx); - atom = NULL; - goto out; - } - } - - atom = (JSAtom *)he; - atom->flags |= flags & (ATOM_PINNED | ATOM_INTERNED | ATOM_HIDDEN); - cx->lastAtom = atom; -out: - JS_UNLOCK(&state->lock,cx); - return atom; -} - -JS_FRIEND_API(JSAtom *) -js_Atomize(JSContext *cx, const char *bytes, size_t length, uintN flags) -{ - jschar *chars; - JSString *str; - JSAtom *atom; - char buf[2 * ALIGNMENT(JSString)]; - - /* - * Avoiding the malloc in js_InflateString on shorter strings saves us - * over 20,000 malloc calls on mozilla browser startup. This compares to - * only 131 calls where the string is longer than a 31 char (net) buffer. - * The vast majority of atomized strings are already in the hashtable. So - * js_AtomizeString rarely has to copy the temp string we make. - */ -#define ATOMIZE_BUF_MAX 32 - jschar inflated[ATOMIZE_BUF_MAX]; - size_t inflatedLength = ATOMIZE_BUF_MAX - 1; - - if (length < ATOMIZE_BUF_MAX) { - js_InflateStringToBuffer(cx, bytes, length, inflated, &inflatedLength); - inflated[inflatedLength] = 0; - chars = inflated; - } else { - inflatedLength = length; - chars = js_InflateString(cx, bytes, &inflatedLength); - if (!chars) - return NULL; - flags |= ATOM_NOCOPY; - } - - str = ALIGN(buf, JSString); - - str->chars = chars; - str->length = inflatedLength; - atom = js_AtomizeString(cx, str, ATOM_TMPSTR | flags); - if (chars != inflated && (!atom || ATOM_TO_STRING(atom)->chars != chars)) - JS_free(cx, chars); - return atom; -} - -JS_FRIEND_API(JSAtom *) -js_AtomizeChars(JSContext *cx, const jschar *chars, size_t length, uintN flags) -{ - JSString *str; - char buf[2 * ALIGNMENT(JSString)]; - - str = ALIGN(buf, JSString); - str->chars = (jschar *)chars; - str->length = length; - return js_AtomizeString(cx, str, ATOM_TMPSTR | flags); -} - -JSAtom * -js_AtomizeValue(JSContext *cx, jsval value, uintN flags) -{ - if (JSVAL_IS_STRING(value)) - return js_AtomizeString(cx, JSVAL_TO_STRING(value), flags); - if (JSVAL_IS_INT(value)) - return js_AtomizeInt(cx, JSVAL_TO_INT(value), flags); - if (JSVAL_IS_DOUBLE(value)) - return js_AtomizeDouble(cx, *JSVAL_TO_DOUBLE(value), flags); - if (JSVAL_IS_OBJECT(value)) - return js_AtomizeObject(cx, JSVAL_TO_OBJECT(value), flags); - if (JSVAL_IS_BOOLEAN(value)) - return js_AtomizeBoolean(cx, JSVAL_TO_BOOLEAN(value), flags); - return js_AtomizeHashedKey(cx, value, (JSHashNumber)value, flags); -} - -JSAtom * -js_ValueToStringAtom(JSContext *cx, jsval v) -{ - JSString *str; - - str = js_ValueToString(cx, v); - if (!str) - return NULL; - return js_AtomizeString(cx, str, 0); -} - -JS_STATIC_DLL_CALLBACK(JSHashNumber) -js_hash_atom_ptr(const void *key) -{ - const JSAtom *atom = key; - return atom->number; -} - -JS_STATIC_DLL_CALLBACK(void *) -js_alloc_temp_space(void *priv, size_t size) -{ - JSContext *cx = priv; - void *space; - - JS_ARENA_ALLOCATE(space, &cx->tempPool, size); - if (!space) - JS_ReportOutOfMemory(cx); - return space; -} - -JS_STATIC_DLL_CALLBACK(void) -js_free_temp_space(void *priv, void *item) -{ -} - -JS_STATIC_DLL_CALLBACK(JSHashEntry *) -js_alloc_temp_entry(void *priv, const void *key) -{ - JSContext *cx = priv; - JSAtomListElement *ale; - - JS_ARENA_ALLOCATE_TYPE(ale, JSAtomListElement, &cx->tempPool); - if (!ale) { - JS_ReportOutOfMemory(cx); - return NULL; - } - return &ale->entry; -} - -JS_STATIC_DLL_CALLBACK(void) -js_free_temp_entry(void *priv, JSHashEntry *he, uintN flag) -{ -} - -static JSHashAllocOps temp_alloc_ops = { - js_alloc_temp_space, js_free_temp_space, - js_alloc_temp_entry, js_free_temp_entry -}; - -JSAtomListElement * -js_IndexAtom(JSContext *cx, JSAtom *atom, JSAtomList *al) -{ - JSAtomListElement *ale, *ale2, *next; - JSHashEntry **hep; - - ATOM_LIST_LOOKUP(ale, hep, al, atom); - if (!ale) { - if (al->count < 10) { - /* Few enough for linear search, no hash table needed. */ - JS_ASSERT(!al->table); - ale = (JSAtomListElement *)js_alloc_temp_entry(cx, atom); - if (!ale) - return NULL; - ALE_SET_ATOM(ale, atom); - ALE_SET_NEXT(ale, al->list); - al->list = ale; - } else { - /* We want to hash. Have we already made a hash table? */ - if (!al->table) { - /* No hash table yet, so hep had better be null! */ - JS_ASSERT(!hep); - al->table = JS_NewHashTable(al->count + 1, js_hash_atom_ptr, - JS_CompareValues, JS_CompareValues, - &temp_alloc_ops, cx); - if (!al->table) - return NULL; - - /* - * Set ht->nentries explicitly, because we are moving entries - * from al to ht, not calling JS_HashTable(Raw|)Add. - */ - al->table->nentries = al->count; - - /* Insert each ale on al->list into the new hash table. */ - for (ale2 = al->list; ale2; ale2 = next) { - next = ALE_NEXT(ale2); - ale2->entry.keyHash = ALE_ATOM(ale2)->number; - hep = JS_HashTableRawLookup(al->table, ale2->entry.keyHash, - ale2->entry.key); - ALE_SET_NEXT(ale2, *hep); - *hep = &ale2->entry; - } - al->list = NULL; - - /* Set hep for insertion of atom's ale, immediately below. */ - hep = JS_HashTableRawLookup(al->table, atom->number, atom); - } - - /* Finally, add an entry for atom into the hash bucket at hep. */ - ale = (JSAtomListElement *) - JS_HashTableRawAdd(al->table, hep, atom->number, atom, NULL); - if (!ale) - return NULL; - } - - ALE_SET_INDEX(ale, al->count++); - } - return ale; -} - -JS_FRIEND_API(JSAtom *) -js_GetAtom(JSContext *cx, JSAtomMap *map, jsatomid i) -{ - JSAtom *atom; - static JSAtom dummy; - - JS_ASSERT(map->vector && i < map->length); - if (!map->vector || i >= map->length) { - char numBuf[12]; - JS_snprintf(numBuf, sizeof numBuf, "%lu", (unsigned long)i); - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_ATOMIC_NUMBER, numBuf); - return &dummy; - } - atom = map->vector[i]; - JS_ASSERT(atom); - return atom; -} - -JS_STATIC_DLL_CALLBACK(intN) -js_map_atom(JSHashEntry *he, intN i, void *arg) -{ - JSAtomListElement *ale = (JSAtomListElement *)he; - JSAtom **vector = arg; - - vector[ALE_INDEX(ale)] = ALE_ATOM(ale); - return HT_ENUMERATE_NEXT; -} - -#ifdef DEBUG -jsrefcount js_atom_map_count; -jsrefcount js_atom_map_hash_table_count; -#endif - -JS_FRIEND_API(JSBool) -js_InitAtomMap(JSContext *cx, JSAtomMap *map, JSAtomList *al) -{ - JSAtom **vector; - JSAtomListElement *ale; - uint32 count; - -#ifdef DEBUG - JS_ATOMIC_INCREMENT(&js_atom_map_count); -#endif - ale = al->list; - if (!ale && !al->table) { - map->vector = NULL; - map->length = 0; - return JS_TRUE; - } - - count = al->count; - if (count >= ATOM_INDEX_LIMIT) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_TOO_MANY_LITERALS); - return JS_FALSE; - } - vector = (JSAtom **) JS_malloc(cx, (size_t) count * sizeof *vector); - if (!vector) - return JS_FALSE; - - if (al->table) { -#ifdef DEBUG - JS_ATOMIC_INCREMENT(&js_atom_map_hash_table_count); -#endif - JS_HashTableEnumerateEntries(al->table, js_map_atom, vector); - } else { - do { - vector[ALE_INDEX(ale)] = ALE_ATOM(ale); - } while ((ale = ALE_NEXT(ale)) != NULL); - } - ATOM_LIST_INIT(al); - - map->vector = vector; - map->length = (jsatomid)count; - return JS_TRUE; -} - -JS_FRIEND_API(void) -js_FreeAtomMap(JSContext *cx, JSAtomMap *map) -{ - if (map->vector) { - JS_free(cx, map->vector); - map->vector = NULL; - } - map->length = 0; -} diff --git a/lib/javascript/jsatom.h b/lib/javascript/jsatom.h deleted file mode 100644 index f8ce3f90..00000000 --- a/lib/javascript/jsatom.h +++ /dev/null @@ -1,468 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jsatom_h___ -#define jsatom_h___ -/* - * JS atom table. - */ -#include -#include "jstypes.h" -#include "jshash.h" /* Added by JSIFY */ -#include "jsapi.h" -#include "jsprvtd.h" -#include "jspubtd.h" - -#ifdef JS_THREADSAFE -#include "jslock.h" -#endif - -JS_BEGIN_EXTERN_C - -#define ATOM_PINNED 0x01 /* atom is pinned against GC */ -#define ATOM_INTERNED 0x02 /* pinned variant for JS_Intern* API */ -#define ATOM_MARK 0x04 /* atom is reachable via GC */ -#define ATOM_HIDDEN 0x08 /* atom is in special hidden subspace */ -#define ATOM_NOCOPY 0x40 /* don't copy atom string bytes */ -#define ATOM_TMPSTR 0x80 /* internal, to avoid extra string */ - -struct JSAtom { - JSHashEntry entry; /* key is jsval, value keyword info or - unhidden atom if ATOM_HIDDEN */ - uint32 flags; /* pinned, interned, and mark flags */ - jsatomid number; /* atom serial number and hash code */ -}; - -#define ATOM_KEY(atom) ((jsval)(atom)->entry.key) -#define ATOM_IS_OBJECT(atom) JSVAL_IS_OBJECT(ATOM_KEY(atom)) -#define ATOM_TO_OBJECT(atom) JSVAL_TO_OBJECT(ATOM_KEY(atom)) -#define ATOM_IS_INT(atom) JSVAL_IS_INT(ATOM_KEY(atom)) -#define ATOM_TO_INT(atom) JSVAL_TO_INT(ATOM_KEY(atom)) -#define ATOM_IS_DOUBLE(atom) JSVAL_IS_DOUBLE(ATOM_KEY(atom)) -#define ATOM_TO_DOUBLE(atom) JSVAL_TO_DOUBLE(ATOM_KEY(atom)) -#define ATOM_IS_STRING(atom) JSVAL_IS_STRING(ATOM_KEY(atom)) -#define ATOM_TO_STRING(atom) JSVAL_TO_STRING(ATOM_KEY(atom)) -#define ATOM_IS_BOOLEAN(atom) JSVAL_IS_BOOLEAN(ATOM_KEY(atom)) -#define ATOM_TO_BOOLEAN(atom) JSVAL_TO_BOOLEAN(ATOM_KEY(atom)) - -/* - * Return a printable, lossless char[] representation of a string-type atom. - * The lifetime of the result extends at least until the next GC activation, - * longer if cx's string newborn root is not overwritten. - */ -extern JS_FRIEND_API(const char *) -js_AtomToPrintableString(JSContext *cx, JSAtom *atom); - -#define ATOM_KEYWORD(atom) ((struct keyword *)(atom)->entry.value) -#define ATOM_SET_KEYWORD(atom,kw) ((atom)->entry.value = (kw)) - -struct JSAtomListElement { - JSHashEntry entry; -}; - -#define ALE_ATOM(ale) ((JSAtom *) (ale)->entry.key) -#define ALE_INDEX(ale) ((jsatomid) JS_PTR_TO_UINT32((ale)->entry.value)) -#define ALE_JSOP(ale) ((JSOp) (ale)->entry.value) -#define ALE_VALUE(ale) ((jsval) (ale)->entry.value) -#define ALE_NEXT(ale) ((JSAtomListElement *) (ale)->entry.next) - -#define ALE_SET_ATOM(ale,atom) ((ale)->entry.key = (const void *)(atom)) -#define ALE_SET_INDEX(ale,index)((ale)->entry.value = JS_UINT32_TO_PTR(index)) -#define ALE_SET_JSOP(ale,op) ((ale)->entry.value = JS_UINT32_TO_PTR(op)) -#define ALE_SET_VALUE(ale,val) ((ale)->entry.value = (JSHashEntry *)(val)) -#define ALE_SET_NEXT(ale,link) ((ale)->entry.next = (JSHashEntry *)(link)) - -struct JSAtomList { - JSAtomListElement *list; /* literals indexed for mapping */ - JSHashTable *table; /* hash table if list gets too long */ - jsuint count; /* count of indexed literals */ -}; - -#define ATOM_LIST_INIT(al) ((al)->list = NULL, (al)->table = NULL, \ - (al)->count = 0) - -#define ATOM_LIST_SEARCH(_ale,_al,_atom) \ - JS_BEGIN_MACRO \ - JSHashEntry **_hep; \ - ATOM_LIST_LOOKUP(_ale, _hep, _al, _atom); \ - JS_END_MACRO - -#define ATOM_LIST_LOOKUP(_ale,_hep,_al,_atom) \ - JS_BEGIN_MACRO \ - if ((_al)->table) { \ - _hep = JS_HashTableRawLookup((_al)->table, _atom->number, _atom); \ - _ale = *_hep ? (JSAtomListElement *) *_hep : NULL; \ - } else { \ - JSAtomListElement **_alep = &(_al)->list; \ - _hep = NULL; \ - while ((_ale = *_alep) != NULL) { \ - if (ALE_ATOM(_ale) == (_atom)) { \ - /* Hit, move atom's element to the front of the list. */ \ - *_alep = ALE_NEXT(_ale); \ - ALE_SET_NEXT(_ale, (_al)->list); \ - (_al)->list = _ale; \ - break; \ - } \ - _alep = (JSAtomListElement **)&_ale->entry.next; \ - } \ - } \ - JS_END_MACRO - -struct JSAtomMap { - JSAtom **vector; /* array of ptrs to indexed atoms */ - jsatomid length; /* count of (to-be-)indexed atoms */ -}; - -struct JSAtomState { - JSRuntime *runtime; /* runtime that owns us */ - JSHashTable *table; /* hash table containing all atoms */ - jsatomid number; /* one beyond greatest atom number */ - jsatomid liveAtoms; /* number of live atoms after last GC */ - - /* The rt->emptyString atom, see jsstr.c's js_InitRuntimeStringState. */ - JSAtom *emptyAtom; - - /* Type names and value literals. */ - JSAtom *typeAtoms[JSTYPE_LIMIT]; - JSAtom *booleanAtoms[2]; - JSAtom *nullAtom; - - /* Various built-in or commonly-used atoms, pinned on first context. */ - JSAtom *ArgumentsAtom; - JSAtom *ArrayAtom; - JSAtom *BooleanAtom; - JSAtom *CallAtom; - JSAtom *DateAtom; - JSAtom *ErrorAtom; - JSAtom *FunctionAtom; - JSAtom *MathAtom; - JSAtom *NamespaceAtom; - JSAtom *NumberAtom; - JSAtom *ObjectAtom; - JSAtom *QNameAtom; - JSAtom *RegExpAtom; - JSAtom *ScriptAtom; - JSAtom *StringAtom; - JSAtom *XMLAtom; - JSAtom *FileAtom; - JSAtom *anonymousAtom; - JSAtom *argumentsAtom; - JSAtom *arityAtom; - JSAtom *calleeAtom; - JSAtom *callerAtom; - JSAtom *classPrototypeAtom; - JSAtom *constructorAtom; - JSAtom *countAtom; - JSAtom *eachAtom; - JSAtom *etagoAtom; - JSAtom *evalAtom; - JSAtom *getAtom; - JSAtom *getterAtom; - JSAtom *indexAtom; - JSAtom *inputAtom; - JSAtom *lengthAtom; - JSAtom *nameAtom; - JSAtom *namespaceAtom; - JSAtom *noSuchMethodAtom; - JSAtom *parentAtom; - JSAtom *protoAtom; - JSAtom *ptagcAtom; - JSAtom *qualifierAtom; - JSAtom *setAtom; - JSAtom *setterAtom; - JSAtom *spaceAtom; - JSAtom *stagoAtom; - JSAtom *starAtom; - JSAtom *starQualifierAtom; - JSAtom *tagcAtom; - JSAtom *toLocaleStringAtom; - JSAtom *toSourceAtom; - JSAtom *toStringAtom; - JSAtom *valueOfAtom; - JSAtom *xmlAtom; - - /* Less frequently used atoms, pinned lazily by JS_ResolveStandardClass. */ - struct { - JSAtom *AnyNameAtom; - JSAtom *AttributeNameAtom; - JSAtom *EvalErrorAtom; - JSAtom *InfinityAtom; - JSAtom *InternalErrorAtom; - JSAtom *NaNAtom; - JSAtom *RangeErrorAtom; - JSAtom *ReferenceErrorAtom; - JSAtom *SyntaxErrorAtom; - JSAtom *TypeErrorAtom; - JSAtom *URIErrorAtom; - JSAtom *XMLListAtom; - JSAtom *decodeURIAtom; - JSAtom *decodeURIComponentAtom; - JSAtom *defineGetterAtom; - JSAtom *defineSetterAtom; - JSAtom *encodeURIAtom; - JSAtom *encodeURIComponentAtom; - JSAtom *escapeAtom; - JSAtom *functionNamespaceURIAtom; - JSAtom *hasOwnPropertyAtom; - JSAtom *isFiniteAtom; - JSAtom *isNaNAtom; - JSAtom *isPrototypeOfAtom; - JSAtom *isXMLNameAtom; - JSAtom *lookupGetterAtom; - JSAtom *lookupSetterAtom; - JSAtom *parseFloatAtom; - JSAtom *parseIntAtom; - JSAtom *propertyIsEnumerableAtom; - JSAtom *unescapeAtom; - JSAtom *unevalAtom; - JSAtom *unwatchAtom; - JSAtom *watchAtom; - } lazy; - -#ifdef JS_THREADSAFE - JSThinLock lock; - volatile uint32 tablegen; -#endif -#ifdef NARCISSUS - JSAtom *callAtom; - JSAtom *constructAtom; - JSAtom *hasInstanceAtom; - JSAtom *ExecutionContextAtom; - JSAtom *currentAtom; -#endif -}; - -/* Well-known predefined strings and their atoms. */ -extern const char *js_type_str[]; -extern const char *js_boolean_str[]; - -extern const char js_Arguments_str[]; -extern const char js_Array_str[]; -extern const char js_Boolean_str[]; -extern const char js_Call_str[]; -extern const char js_Date_str[]; -extern const char js_Function_str[]; -extern const char js_Math_str[]; -extern const char js_Namespace_str[]; -extern const char js_Number_str[]; -extern const char js_Object_str[]; -extern const char js_QName_str[]; -extern const char js_RegExp_str[]; -extern const char js_Script_str[]; -extern const char js_String_str[]; -extern const char js_XML_str[]; -extern const char js_File_str[]; -extern const char js_anonymous_str[]; -extern const char js_arguments_str[]; -extern const char js_arity_str[]; -extern const char js_callee_str[]; -extern const char js_caller_str[]; -extern const char js_class_prototype_str[]; -extern const char js_constructor_str[]; -extern const char js_count_str[]; -extern const char js_etago_str[]; -extern const char js_each_str[]; -extern const char js_eval_str[]; -extern const char js_getter_str[]; -extern const char js_get_str[]; -extern const char js_index_str[]; -extern const char js_input_str[]; -extern const char js_length_str[]; -extern const char js_name_str[]; -extern const char js_namespace_str[]; -extern const char js_noSuchMethod_str[]; -extern const char js_object_str[]; -extern const char js_parent_str[]; -extern const char js_private_str[]; -extern const char js_proto_str[]; -extern const char js_ptagc_str[]; -extern const char js_qualifier_str[]; -extern const char js_setter_str[]; -extern const char js_set_str[]; -extern const char js_space_str[]; -extern const char js_stago_str[]; -extern const char js_star_str[]; -extern const char js_starQualifier_str[]; -extern const char js_tagc_str[]; -extern const char js_toSource_str[]; -extern const char js_toString_str[]; -extern const char js_toLocaleString_str[]; -extern const char js_valueOf_str[]; -extern const char js_xml_str[]; - -#ifdef NARCISSUS -extern const char js_call_str[]; -extern const char js_construct_str[]; -extern const char js_hasInstance_str[]; -extern const char js_ExecutionContext_str[]; -extern const char js_current_str[]; -#endif - -/* - * Initialize atom state. Return true on success, false with an out of - * memory error report on failure. - */ -extern JSBool -js_InitAtomState(JSContext *cx, JSAtomState *state); - -/* - * Free and clear atom state (except for any interned string atoms). - */ -extern void -js_FreeAtomState(JSContext *cx, JSAtomState *state); - -/* - * Interned strings are atoms that live until state's runtime is destroyed. - * This function frees all interned string atoms, and then frees and clears - * state's members (just as js_FreeAtomState does), unless there aren't any - * interned strings in state -- in which case state must be "free" already. - * - * NB: js_FreeAtomState is called for each "last" context being destroyed in - * a runtime, where there may yet be another context created in the runtime; - * whereas js_FinishAtomState is called from JS_DestroyRuntime, when we know - * that no more contexts will be created. Thus we minimize garbage during - * context-free episodes on a runtime, while preserving atoms created by the - * JS_Intern*String APIs for the life of the runtime. - */ -extern void -js_FinishAtomState(JSAtomState *state); - -/* - * Atom garbage collection hooks. - */ -typedef void -(*JSGCThingMarker)(void *thing, void *data); - -extern void -js_MarkAtomState(JSAtomState *state, uintN gcflags, JSGCThingMarker mark, - void *data); - -extern void -js_SweepAtomState(JSAtomState *state); - -extern JSBool -js_InitPinnedAtoms(JSContext *cx, JSAtomState *state); - -extern void -js_UnpinPinnedAtoms(JSAtomState *state); - -/* - * Find or create the atom for an object. If we create a new atom, give it the - * type indicated in flags. Return 0 on failure to allocate memory. - */ -extern JSAtom * -js_AtomizeObject(JSContext *cx, JSObject *obj, uintN flags); - -/* - * Find or create the atom for a Boolean value. If we create a new atom, give - * it the type indicated in flags. Return 0 on failure to allocate memory. - */ -extern JSAtom * -js_AtomizeBoolean(JSContext *cx, JSBool b, uintN flags); - -/* - * Find or create the atom for an integer value. If we create a new atom, give - * it the type indicated in flags. Return 0 on failure to allocate memory. - */ -extern JSAtom * -js_AtomizeInt(JSContext *cx, jsint i, uintN flags); - -/* - * Find or create the atom for a double value. If we create a new atom, give - * it the type indicated in flags. Return 0 on failure to allocate memory. - */ -extern JSAtom * -js_AtomizeDouble(JSContext *cx, jsdouble d, uintN flags); - -/* - * Find or create the atom for a string. If we create a new atom, give it the - * type indicated in flags. Return 0 on failure to allocate memory. - */ -extern JSAtom * -js_AtomizeString(JSContext *cx, JSString *str, uintN flags); - -extern JS_FRIEND_API(JSAtom *) -js_Atomize(JSContext *cx, const char *bytes, size_t length, uintN flags); - -extern JS_FRIEND_API(JSAtom *) -js_AtomizeChars(JSContext *cx, const jschar *chars, size_t length, uintN flags); - -/* - * This variant handles all value tag types. - */ -extern JSAtom * -js_AtomizeValue(JSContext *cx, jsval value, uintN flags); - -/* - * Convert v to an atomized string. - */ -extern JSAtom * -js_ValueToStringAtom(JSContext *cx, jsval v); - -/* - * Assign atom an index and insert it on al. - */ -extern JSAtomListElement * -js_IndexAtom(JSContext *cx, JSAtom *atom, JSAtomList *al); - -/* - * Get the atom with index i from map. - */ -extern JS_FRIEND_API(JSAtom *) -js_GetAtom(JSContext *cx, JSAtomMap *map, jsatomid i); - -/* - * For all unmapped atoms recorded in al, add a mapping from the atom's index - * to its address. The GC must not run until all indexed atoms in atomLists - * have been mapped by scripts connected to live objects (Function and Script - * class objects have scripts as/in their private data -- the GC knows about - * these two classes). - */ -extern JS_FRIEND_API(JSBool) -js_InitAtomMap(JSContext *cx, JSAtomMap *map, JSAtomList *al); - -/* - * Free map->vector and clear map. - */ -extern JS_FRIEND_API(void) -js_FreeAtomMap(JSContext *cx, JSAtomMap *map); - -JS_END_EXTERN_C - -#endif /* jsatom_h___ */ diff --git a/lib/javascript/jsbit.h b/lib/javascript/jsbit.h deleted file mode 100644 index db41acf9..00000000 --- a/lib/javascript/jsbit.h +++ /dev/null @@ -1,113 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jsbit_h___ -#define jsbit_h___ - -#include "jstypes.h" -JS_BEGIN_EXTERN_C - -/* -** A jsbitmap_t is a long integer that can be used for bitmaps -*/ -typedef JSUword jsbitmap_t; /* NSPR name, a la Unix system types */ -typedef jsbitmap_t jsbitmap; /* JS-style scalar typedef name */ - -#define JS_TEST_BIT(_map,_bit) \ - ((_map)[(_bit)>>JS_BITS_PER_WORD_LOG2] & (1L << ((_bit) & (JS_BITS_PER_WORD-1)))) -#define JS_SET_BIT(_map,_bit) \ - ((_map)[(_bit)>>JS_BITS_PER_WORD_LOG2] |= (1L << ((_bit) & (JS_BITS_PER_WORD-1)))) -#define JS_CLEAR_BIT(_map,_bit) \ - ((_map)[(_bit)>>JS_BITS_PER_WORD_LOG2] &= ~(1L << ((_bit) & (JS_BITS_PER_WORD-1)))) - -/* -** Compute the log of the least power of 2 greater than or equal to n -*/ -extern JS_PUBLIC_API(JSIntn) JS_CeilingLog2(JSUint32 i); - -/* -** Compute the log of the greatest power of 2 less than or equal to n -*/ -extern JS_PUBLIC_API(JSIntn) JS_FloorLog2(JSUint32 i); - -/* -** Macro version of JS_CeilingLog2: Compute the log of the least power of -** 2 greater than or equal to _n. The result is returned in _log2. -*/ -#define JS_CEILING_LOG2(_log2,_n) \ - JS_BEGIN_MACRO \ - JSUint32 j_ = (JSUint32)(_n); \ - (_log2) = 0; \ - if ((j_) & ((j_)-1)) \ - (_log2) += 1; \ - if ((j_) >> 16) \ - (_log2) += 16, (j_) >>= 16; \ - if ((j_) >> 8) \ - (_log2) += 8, (j_) >>= 8; \ - if ((j_) >> 4) \ - (_log2) += 4, (j_) >>= 4; \ - if ((j_) >> 2) \ - (_log2) += 2, (j_) >>= 2; \ - if ((j_) >> 1) \ - (_log2) += 1; \ - JS_END_MACRO - -/* -** Macro version of JS_FloorLog2: Compute the log of the greatest power of -** 2 less than or equal to _n. The result is returned in _log2. -** -** This is equivalent to finding the highest set bit in the word. -*/ -#define JS_FLOOR_LOG2(_log2,_n) \ - JS_BEGIN_MACRO \ - JSUint32 j_ = (JSUint32)(_n); \ - (_log2) = 0; \ - if ((j_) >> 16) \ - (_log2) += 16, (j_) >>= 16; \ - if ((j_) >> 8) \ - (_log2) += 8, (j_) >>= 8; \ - if ((j_) >> 4) \ - (_log2) += 4, (j_) >>= 4; \ - if ((j_) >> 2) \ - (_log2) += 2, (j_) >>= 2; \ - if ((j_) >> 1) \ - (_log2) += 1; \ - JS_END_MACRO - -JS_END_EXTERN_C -#endif /* jsbit_h___ */ diff --git a/lib/javascript/jsbool.c b/lib/javascript/jsbool.c deleted file mode 100644 index 33d5c507..00000000 --- a/lib/javascript/jsbool.c +++ /dev/null @@ -1,215 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JS boolean implementation. - */ -#include "jsstddef.h" -#include "jstypes.h" -#include "jsutil.h" /* Added by JSIFY */ -#include "jsapi.h" -#include "jsatom.h" -#include "jsbool.h" -#include "jscntxt.h" -#include "jsconfig.h" -#include "jsinterp.h" -#include "jslock.h" -#include "jsnum.h" -#include "jsobj.h" -#include "jsstr.h" - -JSClass js_BooleanClass = { - "Boolean", - JSCLASS_HAS_PRIVATE, - JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, - JSCLASS_NO_OPTIONAL_MEMBERS -}; - -#if JS_HAS_TOSOURCE -#include "jsprf.h" - -static JSBool -bool_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jsval v; - char buf[32]; - JSString *str; - - if (!JS_InstanceOf(cx, obj, &js_BooleanClass, argv)) - return JS_FALSE; - v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE); - if (!JSVAL_IS_BOOLEAN(v)) - return js_obj_toSource(cx, obj, argc, argv, rval); - JS_snprintf(buf, sizeof buf, "(new %s(%s))", - js_BooleanClass.name, - js_boolean_str[JSVAL_TO_BOOLEAN(v) ? 1 : 0]); - str = JS_NewStringCopyZ(cx, buf); - if (!str) - return JS_FALSE; - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} -#endif - -static JSBool -bool_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jsval v; - JSAtom *atom; - JSString *str; - - if (!JS_InstanceOf(cx, obj, &js_BooleanClass, argv)) - return JS_FALSE; - v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE); - if (!JSVAL_IS_BOOLEAN(v)) - return js_obj_toString(cx, obj, argc, argv, rval); - atom = cx->runtime->atomState.booleanAtoms[JSVAL_TO_BOOLEAN(v) ? 1 : 0]; - str = ATOM_TO_STRING(atom); - if (!str) - return JS_FALSE; - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -static JSBool -bool_valueOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - if (!JS_InstanceOf(cx, obj, &js_BooleanClass, argv)) - return JS_FALSE; - *rval = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE); - return JS_TRUE; -} - -static JSFunctionSpec boolean_methods[] = { -#if JS_HAS_TOSOURCE - {js_toSource_str, bool_toSource, 0,0,0}, -#endif - {js_toString_str, bool_toString, 0,0,0}, - {js_valueOf_str, bool_valueOf, 0,0,0}, - {0,0,0,0,0} -}; - -static JSBool -Boolean(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSBool b; - jsval bval; - - if (argc != 0) { - if (!js_ValueToBoolean(cx, argv[0], &b)) - return JS_FALSE; - bval = BOOLEAN_TO_JSVAL(b); - } else { - bval = JSVAL_FALSE; - } - if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) { - *rval = bval; - return JS_TRUE; - } - OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, bval); - return JS_TRUE; -} - -JSObject * -js_InitBooleanClass(JSContext *cx, JSObject *obj) -{ - JSObject *proto; - - proto = JS_InitClass(cx, obj, NULL, &js_BooleanClass, Boolean, 1, - NULL, boolean_methods, NULL, NULL); - if (!proto) - return NULL; - OBJ_SET_SLOT(cx, proto, JSSLOT_PRIVATE, JSVAL_FALSE); - return proto; -} - -JSObject * -js_BooleanToObject(JSContext *cx, JSBool b) -{ - JSObject *obj; - - obj = js_NewObject(cx, &js_BooleanClass, NULL, NULL); - if (!obj) - return NULL; - OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, BOOLEAN_TO_JSVAL(b)); - return obj; -} - -JSString * -js_BooleanToString(JSContext *cx, JSBool b) -{ - return ATOM_TO_STRING(cx->runtime->atomState.booleanAtoms[b ? 1 : 0]); -} - -JSBool -js_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp) -{ - JSBool b; - jsdouble d; - - if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) { - b = JS_FALSE; - } else if (JSVAL_IS_OBJECT(v)) { - if (!JS_VERSION_IS_ECMA(cx)) { - if (!OBJ_DEFAULT_VALUE(cx, JSVAL_TO_OBJECT(v), JSTYPE_BOOLEAN, &v)) - return JS_FALSE; - if (!JSVAL_IS_BOOLEAN(v)) - v = JSVAL_TRUE; /* non-null object is true */ - b = JSVAL_TO_BOOLEAN(v); - } else { - b = JS_TRUE; - } - } else if (JSVAL_IS_STRING(v)) { - b = JSSTRING_LENGTH(JSVAL_TO_STRING(v)) ? JS_TRUE : JS_FALSE; - } else if (JSVAL_IS_INT(v)) { - b = JSVAL_TO_INT(v) ? JS_TRUE : JS_FALSE; - } else if (JSVAL_IS_DOUBLE(v)) { - d = *JSVAL_TO_DOUBLE(v); - b = (!JSDOUBLE_IS_NaN(d) && d != 0) ? JS_TRUE : JS_FALSE; - } else { - JS_ASSERT(JSVAL_IS_BOOLEAN(v)); - b = JSVAL_TO_BOOLEAN(v); - } - - *bp = b; - return JS_TRUE; -} diff --git a/lib/javascript/jsbool.h b/lib/javascript/jsbool.h deleted file mode 100644 index 770b94c6..00000000 --- a/lib/javascript/jsbool.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jsbool_h___ -#define jsbool_h___ -/* - * JS boolean interface. - */ - -JS_BEGIN_EXTERN_C - -/* - * Crypto-booleans, not visible to script but used internally by the engine. - * - * JSVAL_HOLE is a useful value for identifying a hole in an array. It's also - * used in the interpreter to represent "no exception pending". In general it - * can be used to represent "no value". - */ -#define JSVAL_HOLE BOOLEAN_TO_JSVAL(2) - -extern JSClass js_BooleanClass; - -extern JSObject * -js_InitBooleanClass(JSContext *cx, JSObject *obj); - -extern JSObject * -js_BooleanToObject(JSContext *cx, JSBool b); - -extern JSString * -js_BooleanToString(JSContext *cx, JSBool b); - -extern JSBool -js_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp); - -JS_END_EXTERN_C - -#endif /* jsbool_h___ */ diff --git a/lib/javascript/jsclist.h b/lib/javascript/jsclist.h deleted file mode 100644 index 604ec0ec..00000000 --- a/lib/javascript/jsclist.h +++ /dev/null @@ -1,139 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jsclist_h___ -#define jsclist_h___ - -#include "jstypes.h" - -/* -** Circular linked list -*/ -typedef struct JSCListStr { - struct JSCListStr *next; - struct JSCListStr *prev; -} JSCList; - -/* -** Insert element "_e" into the list, before "_l". -*/ -#define JS_INSERT_BEFORE(_e,_l) \ - JS_BEGIN_MACRO \ - (_e)->next = (_l); \ - (_e)->prev = (_l)->prev; \ - (_l)->prev->next = (_e); \ - (_l)->prev = (_e); \ - JS_END_MACRO - -/* -** Insert element "_e" into the list, after "_l". -*/ -#define JS_INSERT_AFTER(_e,_l) \ - JS_BEGIN_MACRO \ - (_e)->next = (_l)->next; \ - (_e)->prev = (_l); \ - (_l)->next->prev = (_e); \ - (_l)->next = (_e); \ - JS_END_MACRO - -/* -** Return the element following element "_e" -*/ -#define JS_NEXT_LINK(_e) \ - ((_e)->next) -/* -** Return the element preceding element "_e" -*/ -#define JS_PREV_LINK(_e) \ - ((_e)->prev) - -/* -** Append an element "_e" to the end of the list "_l" -*/ -#define JS_APPEND_LINK(_e,_l) JS_INSERT_BEFORE(_e,_l) - -/* -** Insert an element "_e" at the head of the list "_l" -*/ -#define JS_INSERT_LINK(_e,_l) JS_INSERT_AFTER(_e,_l) - -/* Return the head/tail of the list */ -#define JS_LIST_HEAD(_l) (_l)->next -#define JS_LIST_TAIL(_l) (_l)->prev - -/* -** Remove the element "_e" from it's circular list. -*/ -#define JS_REMOVE_LINK(_e) \ - JS_BEGIN_MACRO \ - (_e)->prev->next = (_e)->next; \ - (_e)->next->prev = (_e)->prev; \ - JS_END_MACRO - -/* -** Remove the element "_e" from it's circular list. Also initializes the -** linkage. -*/ -#define JS_REMOVE_AND_INIT_LINK(_e) \ - JS_BEGIN_MACRO \ - (_e)->prev->next = (_e)->next; \ - (_e)->next->prev = (_e)->prev; \ - (_e)->next = (_e); \ - (_e)->prev = (_e); \ - JS_END_MACRO - -/* -** Return non-zero if the given circular list "_l" is empty, zero if the -** circular list is not empty -*/ -#define JS_CLIST_IS_EMPTY(_l) \ - ((_l)->next == (_l)) - -/* -** Initialize a circular list -*/ -#define JS_INIT_CLIST(_l) \ - JS_BEGIN_MACRO \ - (_l)->next = (_l); \ - (_l)->prev = (_l); \ - JS_END_MACRO - -#define JS_INIT_STATIC_CLIST(_l) \ - {(_l), (_l)} - -#endif /* jsclist_h___ */ diff --git a/lib/javascript/jscntxt.c b/lib/javascript/jscntxt.c deleted file mode 100644 index 43041f97..00000000 --- a/lib/javascript/jscntxt.c +++ /dev/null @@ -1,1073 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JS execution context. - */ -#include "jsstddef.h" -#include -#include -#include -#include "jstypes.h" -#include "jsarena.h" /* Added by JSIFY */ -#include "jsutil.h" /* Added by JSIFY */ -#include "jsclist.h" -#include "jsprf.h" -#include "jsatom.h" -#include "jscntxt.h" -#include "jsconfig.h" -#include "jsdbgapi.h" -#include "jsexn.h" -#include "jsgc.h" -#include "jslock.h" -#include "jsnum.h" -#include "jsobj.h" -#include "jsopcode.h" -#include "jsscan.h" -#include "jsscript.h" -#include "jsstr.h" - -void -js_OnVersionChange(JSContext *cx) -{ -#if !JS_BUG_FALLIBLE_EQOPS - if (JS_VERSION_IS_1_2(cx)) { - cx->jsop_eq = JSOP_NEW_EQ; - cx->jsop_ne = JSOP_NEW_NE; - } else { - cx->jsop_eq = JSOP_EQ; - cx->jsop_ne = JSOP_NE; - } -#endif /* !JS_BUG_FALLIBLE_EQOPS */ -} - -void -js_SetVersion(JSContext *cx, JSVersion version) -{ - cx->version = version; - js_OnVersionChange(cx); -} - -JSContext * -js_NewContext(JSRuntime *rt, size_t stackChunkSize) -{ - JSContext *cx; - JSBool ok, first; - - cx = (JSContext *) malloc(sizeof *cx); - if (!cx) - return NULL; - memset(cx, 0, sizeof *cx); - - cx->runtime = rt; -#if JS_STACK_GROWTH_DIRECTION > 0 - cx->stackLimit = (jsuword)-1; -#endif -#ifdef JS_THREADSAFE - js_InitContextForLocking(cx); -#endif - - JS_LOCK_GC(rt); - for (;;) { - first = (rt->contextList.next == &rt->contextList); - if (rt->state == JSRTS_UP) { - JS_ASSERT(!first); - break; - } - if (rt->state == JSRTS_DOWN) { - JS_ASSERT(first); - rt->state = JSRTS_LAUNCHING; - break; - } - JS_WAIT_CONDVAR(rt->stateChange, JS_NO_TIMEOUT); - } - JS_APPEND_LINK(&cx->links, &rt->contextList); - JS_UNLOCK_GC(rt); - - /* - * First we do the infallible, every-time per-context initializations. - * Should a later, fallible initialization (js_InitRegExpStatics, e.g., - * or the stuff under 'if (first)' below) fail, at least the version - * and arena-pools will be valid and safe to use (say, from the last GC - * done by js_DestroyContext). - */ - cx->version = JSVERSION_DEFAULT; - cx->jsop_eq = JSOP_EQ; - cx->jsop_ne = JSOP_NE; - JS_InitArenaPool(&cx->stackPool, "stack", stackChunkSize, sizeof(jsval)); - JS_InitArenaPool(&cx->tempPool, "temp", 1024, sizeof(jsdouble)); - -#if JS_HAS_REGEXPS - if (!js_InitRegExpStatics(cx, &cx->regExpStatics)) { - js_DestroyContext(cx, JS_NO_GC); - return NULL; - } -#endif -#if JS_HAS_EXCEPTIONS - cx->throwing = JS_FALSE; -#endif - - /* - * If cx is the first context on this runtime, initialize well-known atoms, - * keywords, numbers, and strings. If one of these steps should fail, the - * runtime will be left in a partially initialized state, with zeroes and - * nulls stored in the default-initialized remainder of the struct. We'll - * clean the runtime up under js_DestroyContext, because cx will be "last" - * as well as "first". - */ - if (first) { - /* - * Both atomState and the scriptFilenameTable may be left over from a - * previous episode of non-zero contexts alive in rt, so don't re-init - * either table if it's not necessary. Just repopulate atomState with - * well-known internal atoms, and with the reserved identifiers added - * by the scanner. - */ - ok = (rt->atomState.liveAtoms == 0) - ? js_InitAtomState(cx, &rt->atomState) - : js_InitPinnedAtoms(cx, &rt->atomState); - if (ok) - ok = js_InitScanner(cx); - if (ok && !rt->scriptFilenameTable) - ok = js_InitRuntimeScriptState(rt); - if (ok) - ok = js_InitRuntimeNumberState(cx); - if (ok) - ok = js_InitRuntimeStringState(cx); - if (!ok) { - js_DestroyContext(cx, JS_NO_GC); - return NULL; - } - - JS_LOCK_GC(rt); - rt->state = JSRTS_UP; - JS_NOTIFY_ALL_CONDVAR(rt->stateChange); - JS_UNLOCK_GC(rt); - } - - return cx; -} - -void -js_DestroyContext(JSContext *cx, JSGCMode gcmode) -{ - JSRuntime *rt; - JSBool last; - JSArgumentFormatMap *map; - JSLocalRootStack *lrs; - JSLocalRootChunk *lrc; - - rt = cx->runtime; - - /* Remove cx from context list first. */ - JS_LOCK_GC(rt); - JS_ASSERT(rt->state == JSRTS_UP || rt->state == JSRTS_LAUNCHING); - JS_REMOVE_LINK(&cx->links); - last = (rt->contextList.next == &rt->contextList); - if (last) - rt->state = JSRTS_LANDING; - JS_UNLOCK_GC(rt); - - if (last) { -#ifdef JS_THREADSAFE - /* - * If cx is not in a request already, begin one now so that we wait - * for any racing GC started on a not-last context to finish, before - * we plow ahead and unpin atoms. Note that even though we begin a - * request here if necessary, we end all requests on cx below before - * forcing a final GC. This lets any not-last context destruction - * racing in another thread try to force or maybe run the GC, but by - * that point, rt->state will not be JSRTS_UP, and that GC attempt - * will return early. - */ - if (cx->requestDepth == 0) - JS_BeginRequest(cx); -#endif - - /* Unpin all pinned atoms before final GC. */ - js_UnpinPinnedAtoms(&rt->atomState); - - /* Unlock and clear GC things held by runtime pointers. */ - js_FinishRuntimeNumberState(cx); - js_FinishRuntimeStringState(cx); - - /* Clear debugging state to remove GC roots. */ - JS_ClearAllTraps(cx); - JS_ClearAllWatchPoints(cx); - } - -#if JS_HAS_REGEXPS - /* - * Remove more GC roots in regExpStatics, then collect garbage. - * XXX anti-modularity alert: we rely on the call to js_RemoveRoot within - * XXX this function call to wait for any racing GC to complete, in the - * XXX case where JS_DestroyContext is called outside of a request on cx - */ - js_FreeRegExpStatics(cx, &cx->regExpStatics); -#endif - -#ifdef JS_THREADSAFE - /* - * Destroying a context implicitly calls JS_EndRequest(). Also, we must - * end our request here in case we are "last" -- in that event, another - * js_DestroyContext that was not last might be waiting in the GC for our - * request to end. We'll let it run below, just before we do the truly - * final GC and then free atom state. - * - * At this point, cx must be inaccessible to other threads. It's off the - * rt->contextList, and it should not be reachable via any object private - * data structure. - */ - while (cx->requestDepth != 0) - JS_EndRequest(cx); -#endif - - if (last) { - /* Always force, so we wait for any racing GC to finish. */ - js_ForceGC(cx, GC_LAST_CONTEXT); - - /* Iterate until no finalizer removes a GC root or lock. */ - while (rt->gcPoke) - js_GC(cx, GC_LAST_CONTEXT); - - /* Try to free atom state, now that no unrooted scripts survive. */ - if (rt->atomState.liveAtoms == 0) - js_FreeAtomState(cx, &rt->atomState); - - /* Also free the script filename table if it exists and is empty. */ - if (rt->scriptFilenameTable && rt->scriptFilenameTable->nentries == 0) - js_FinishRuntimeScriptState(rt); - - /* Take the runtime down, now that it has no contexts or atoms. */ - JS_LOCK_GC(rt); - rt->state = JSRTS_DOWN; - JS_NOTIFY_ALL_CONDVAR(rt->stateChange); - JS_UNLOCK_GC(rt); - } else { - if (gcmode == JS_FORCE_GC) - js_ForceGC(cx, 0); - else if (gcmode == JS_MAYBE_GC) - JS_MaybeGC(cx); - } - - /* Free the stuff hanging off of cx. */ - JS_FinishArenaPool(&cx->stackPool); - JS_FinishArenaPool(&cx->tempPool); - if (cx->lastMessage) - free(cx->lastMessage); - - /* Remove any argument formatters. */ - map = cx->argumentFormatMap; - while (map) { - JSArgumentFormatMap *temp = map; - map = map->next; - JS_free(cx, temp); - } - - /* Destroy the resolve recursion damper. */ - if (cx->resolvingTable) { - JS_DHashTableDestroy(cx->resolvingTable); - cx->resolvingTable = NULL; - } - - lrs = cx->localRootStack; - if (lrs) { - while ((lrc = lrs->topChunk) != &lrs->firstChunk) { - lrs->topChunk = lrc->down; - JS_free(cx, lrc); - } - JS_free(cx, lrs); - } - - /* Finally, free cx itself. */ - free(cx); -} - -JSBool -js_ValidContextPointer(JSRuntime *rt, JSContext *cx) -{ - JSCList *cl; - - for (cl = rt->contextList.next; cl != &rt->contextList; cl = cl->next) { - if (cl == &cx->links) - return JS_TRUE; - } - JS_RUNTIME_METER(rt, deadContexts); - return JS_FALSE; -} - -JSContext * -js_ContextIterator(JSRuntime *rt, JSBool unlocked, JSContext **iterp) -{ - JSContext *cx = *iterp; - - if (unlocked) - JS_LOCK_GC(rt); - if (!cx) - cx = (JSContext *)&rt->contextList; - cx = (JSContext *)cx->links.next; - if (&cx->links == &rt->contextList) - cx = NULL; - *iterp = cx; - if (unlocked) - JS_UNLOCK_GC(rt); - return cx; -} - -JS_STATIC_DLL_CALLBACK(const void *) -resolving_GetKey(JSDHashTable *table, JSDHashEntryHdr *hdr) -{ - JSResolvingEntry *entry = (JSResolvingEntry *)hdr; - - return &entry->key; -} - -JS_STATIC_DLL_CALLBACK(JSDHashNumber) -resolving_HashKey(JSDHashTable *table, const void *ptr) -{ - const JSResolvingKey *key = (const JSResolvingKey *)ptr; - - return ((JSDHashNumber)JS_PTR_TO_UINT32(key->obj) >> JSVAL_TAGBITS) ^ key->id; -} - -JS_PUBLIC_API(JSBool) -resolving_MatchEntry(JSDHashTable *table, - const JSDHashEntryHdr *hdr, - const void *ptr) -{ - const JSResolvingEntry *entry = (const JSResolvingEntry *)hdr; - const JSResolvingKey *key = (const JSResolvingKey *)ptr; - - return entry->key.obj == key->obj && entry->key.id == key->id; -} - -static const JSDHashTableOps resolving_dhash_ops = { - JS_DHashAllocTable, - JS_DHashFreeTable, - resolving_GetKey, - resolving_HashKey, - resolving_MatchEntry, - JS_DHashMoveEntryStub, - JS_DHashClearEntryStub, - JS_DHashFinalizeStub, - NULL -}; - -JSBool -js_StartResolving(JSContext *cx, JSResolvingKey *key, uint32 flag, - JSResolvingEntry **entryp) -{ - JSDHashTable *table; - JSResolvingEntry *entry; - - table = cx->resolvingTable; - if (!table) { - table = JS_NewDHashTable(&resolving_dhash_ops, NULL, - sizeof(JSResolvingEntry), - JS_DHASH_MIN_SIZE); - if (!table) - goto outofmem; - cx->resolvingTable = table; - } - - entry = (JSResolvingEntry *) - JS_DHashTableOperate(table, key, JS_DHASH_ADD); - if (!entry) - goto outofmem; - - if (entry->flags & flag) { - /* An entry for (key, flag) exists already -- dampen recursion. */ - entry = NULL; - } else { - /* Fill in key if we were the first to add entry, then set flag. */ - if (!entry->key.obj) - entry->key = *key; - entry->flags |= flag; - } - *entryp = entry; - return JS_TRUE; - -outofmem: - JS_ReportOutOfMemory(cx); - return JS_FALSE; -} - -void -js_StopResolving(JSContext *cx, JSResolvingKey *key, uint32 flag, - JSResolvingEntry *entry, uint32 generation) -{ - JSDHashTable *table; - - /* - * Clear flag from entry->flags and return early if other flags remain. - * We must take care to re-lookup entry if the table has changed since - * it was found by js_StartResolving. - */ - table = cx->resolvingTable; - if (!entry || table->generation != generation) { - entry = (JSResolvingEntry *) - JS_DHashTableOperate(table, key, JS_DHASH_LOOKUP); - } - JS_ASSERT(JS_DHASH_ENTRY_IS_BUSY(&entry->hdr)); - entry->flags &= ~flag; - if (entry->flags) - return; - - /* - * Do a raw remove only if fewer entries were removed than would cause - * alpha to be less than .5 (alpha is at most .75). Otherwise, we just - * call JS_DHashTableOperate to re-lookup the key and remove its entry, - * compressing or shrinking the table as needed. - */ - if (table->removedCount < JS_DHASH_TABLE_SIZE(table) >> 2) - JS_DHashTableRawRemove(table, &entry->hdr); - else - JS_DHashTableOperate(table, key, JS_DHASH_REMOVE); -} - -JSBool -js_EnterLocalRootScope(JSContext *cx) -{ - JSLocalRootStack *lrs; - int mark; - - lrs = cx->localRootStack; - if (!lrs) { - lrs = (JSLocalRootStack *) JS_malloc(cx, sizeof *lrs); - if (!lrs) - return JS_FALSE; - lrs->scopeMark = JSLRS_NULL_MARK; - lrs->rootCount = 0; - lrs->topChunk = &lrs->firstChunk; - lrs->firstChunk.down = NULL; - cx->localRootStack = lrs; - } - - /* Push lrs->scopeMark to save it for restore when leaving. */ - mark = js_PushLocalRoot(cx, lrs, INT_TO_JSVAL(lrs->scopeMark)); - if (mark < 0) - return JS_FALSE; - lrs->scopeMark = (uint32) mark; - return JS_TRUE; -} - -void -js_LeaveLocalRootScope(JSContext *cx) -{ - JSLocalRootStack *lrs; - unsigned mark, m, n; - JSLocalRootChunk *lrc; - - /* Defend against buggy native callers. */ - lrs = cx->localRootStack; - JS_ASSERT(lrs && lrs->rootCount != 0); - if (!lrs || lrs->rootCount == 0) - return; - - mark = lrs->scopeMark; - JS_ASSERT(mark != JSLRS_NULL_MARK); - if (mark == JSLRS_NULL_MARK) - return; - - /* Free any chunks being popped by this leave operation. */ - m = mark >> JSLRS_CHUNK_SHIFT; - n = (lrs->rootCount - 1) >> JSLRS_CHUNK_SHIFT; - while (n > m) { - lrc = lrs->topChunk; - JS_ASSERT(lrc != &lrs->firstChunk); - lrs->topChunk = lrc->down; - JS_free(cx, lrc); - --n; - } - - /* Pop the scope, restoring lrs->scopeMark. */ - lrc = lrs->topChunk; - m = mark & JSLRS_CHUNK_MASK; - lrs->scopeMark = (uint32) JSVAL_TO_INT(lrc->roots[m]); - lrc->roots[m] = JSVAL_NULL; - lrs->rootCount = (uint32) mark; - - /* - * Free the stack eagerly, risking malloc churn. The alternative would - * require an lrs->entryCount member, maintained by Enter and Leave, and - * tested by the GC in addition to the cx->localRootStack non-null test. - * - * That approach would risk hoarding 264 bytes (net) per context. Right - * now it seems better to give fresh (dirty in CPU write-back cache, and - * the data is no longer needed) memory back to the malloc heap. - */ - if (mark == 0) { - cx->localRootStack = NULL; - JS_free(cx, lrs); - } else if (m == 0) { - lrs->topChunk = lrc->down; - JS_free(cx, lrc); - } -} - -void -js_ForgetLocalRoot(JSContext *cx, jsval v) -{ - JSLocalRootStack *lrs; - unsigned i, j, m, n, mark; - JSLocalRootChunk *lrc, *lrc2; - jsval top; - - lrs = cx->localRootStack; - JS_ASSERT(lrs && lrs->rootCount); - if (!lrs || lrs->rootCount == 0) - return; - - /* Prepare to pop the top-most value from the stack. */ - n = lrs->rootCount - 1; - m = n & JSLRS_CHUNK_MASK; - lrc = lrs->topChunk; - top = lrc->roots[m]; - - /* Be paranoid about calls on an empty scope. */ - mark = lrs->scopeMark; - JS_ASSERT(mark < n); - if (mark >= n) - return; - - /* If v was not the last root pushed in the top scope, find it. */ - if (top != v) { - /* Search downward in case v was recently pushed. */ - i = n; - j = m; - lrc2 = lrc; - while (--i > mark) { - if (j == 0) - lrc2 = lrc2->down; - j = i & JSLRS_CHUNK_MASK; - if (lrc2->roots[j] == v) - break; - } - - /* If we didn't find v in this scope, assert and bail out. */ - JS_ASSERT(i != mark); - if (i == mark) - return; - - /* Swap top and v so common tail code can pop v. */ - lrc2->roots[j] = top; - } - - /* Pop the last value from the stack. */ - lrc->roots[m] = JSVAL_NULL; - lrs->rootCount = n; - if (m == 0) { - JS_ASSERT(n != 0); - JS_ASSERT(lrc != &lrs->firstChunk); - lrs->topChunk = lrc->down; - JS_free(cx, lrc); - } -} - -int -js_PushLocalRoot(JSContext *cx, JSLocalRootStack *lrs, jsval v) -{ - unsigned n, m; - JSLocalRootChunk *lrc; - - n = lrs->rootCount; - m = n & JSLRS_CHUNK_MASK; - if (n == 0 || m != 0) { - /* - * At start of first chunk, or not at start of a non-first top chunk. - * Check for lrs->rootCount overflow. - */ - if ((uint32)(n + 1) == 0) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_TOO_MANY_LOCAL_ROOTS); - return -1; - } - lrc = lrs->topChunk; - JS_ASSERT(n != 0 || lrc == &lrs->firstChunk); - } else { - /* - * After lrs->firstChunk, trying to index at a power-of-two chunk - * boundary: need a new chunk. - */ - lrc = (JSLocalRootChunk *) JS_malloc(cx, sizeof *lrc); - if (!lrc) - return -1; - lrc->down = lrs->topChunk; - lrs->topChunk = lrc; - } - lrs->rootCount = n + 1; - lrc->roots[m] = v; - return (int) n; -} - -void -js_MarkLocalRoots(JSContext *cx, JSLocalRootStack *lrs) -{ - unsigned n, m, mark; - JSLocalRootChunk *lrc; - - n = lrs->rootCount; - if (n == 0) - return; - - mark = lrs->scopeMark; - lrc = lrs->topChunk; - do { - while (--n > mark) { -#ifdef GC_MARK_DEBUG - char name[22]; - JS_snprintf(name, sizeof name, "", n); -#else - const char *name = NULL; -#endif - m = n & JSLRS_CHUNK_MASK; - JS_ASSERT(JSVAL_IS_GCTHING(lrc->roots[m])); - JS_MarkGCThing(cx, JSVAL_TO_GCTHING(lrc->roots[m]), name, NULL); - if (m == 0) - lrc = lrc->down; - } - m = n & JSLRS_CHUNK_MASK; - mark = JSVAL_TO_INT(lrc->roots[m]); - if (m == 0) - lrc = lrc->down; - } while (n != 0); - JS_ASSERT(!lrc); -} - -static void -ReportError(JSContext *cx, const char *message, JSErrorReport *reportp) -{ - /* - * Check the error report, and set a JavaScript-catchable exception - * if the error is defined to have an associated exception. If an - * exception is thrown, then the JSREPORT_EXCEPTION flag will be set - * on the error report, and exception-aware hosts should ignore it. - */ - if (reportp && reportp->errorNumber == JSMSG_UNCAUGHT_EXCEPTION) - reportp->flags |= JSREPORT_EXCEPTION; - -#if JS_HAS_ERROR_EXCEPTIONS - /* - * Call the error reporter only if an exception wasn't raised. - * - * If an exception was raised, then we call the debugErrorHook - * (if present) to give it a chance to see the error before it - * propagates out of scope. This is needed for compatability - * with the old scheme. - */ - if (!js_ErrorToException(cx, message, reportp)) { - js_ReportErrorAgain(cx, message, reportp); - } else if (cx->runtime->debugErrorHook && cx->errorReporter) { - JSDebugErrorHook hook = cx->runtime->debugErrorHook; - /* test local in case debugErrorHook changed on another thread */ - if (hook) - hook(cx, message, reportp, cx->runtime->debugErrorHookData); - } -#else - js_ReportErrorAgain(cx, message, reportp); -#endif -} - -/* - * We don't post an exception in this case, since doing so runs into - * complications of pre-allocating an exception object which required - * running the Exception class initializer early etc. - * Instead we just invoke the errorReporter with an "Out Of Memory" - * type message, and then hope the process ends swiftly. - */ -void -js_ReportOutOfMemory(JSContext *cx, JSErrorCallback callback) -{ - JSStackFrame *fp; - JSErrorReport report; - JSErrorReporter onError = cx->errorReporter; - - /* Get the message for this error, but we won't expand any arguments. */ - const JSErrorFormatString *efs = callback(NULL, NULL, JSMSG_OUT_OF_MEMORY); - const char *msg = efs ? efs->format : "Out of memory"; - - /* Fill out the report, but don't do anything that requires allocation. */ - memset(&report, 0, sizeof (struct JSErrorReport)); - report.flags = JSREPORT_ERROR; - report.errorNumber = JSMSG_OUT_OF_MEMORY; - - /* - * Walk stack until we find a frame that is associated with some script - * rather than a native frame. - */ - for (fp = cx->fp; fp; fp = fp->down) { - if (fp->script && fp->pc) { - report.filename = fp->script->filename; - report.lineno = js_PCToLineNumber(cx, fp->script, fp->pc); - break; - } - } - - /* - * If debugErrorHook is present then we give it a chance to veto - * sending the error on to the regular ErrorReporter. - */ - if (onError) { - JSDebugErrorHook hook = cx->runtime->debugErrorHook; - if (hook && - !hook(cx, msg, &report, cx->runtime->debugErrorHookData)) { - onError = NULL; - } - } - - if (onError) - onError(cx, msg, &report); -} - -JSBool -js_ReportErrorVA(JSContext *cx, uintN flags, const char *format, va_list ap) -{ - char *last; - JSStackFrame *fp; - JSErrorReport report; - JSBool warning; - - if ((flags & JSREPORT_STRICT) && !JS_HAS_STRICT_OPTION(cx)) - return JS_TRUE; - - last = JS_vsmprintf(format, ap); - if (!last) - return JS_FALSE; - - memset(&report, 0, sizeof (struct JSErrorReport)); - report.flags = flags; - - /* Find the top-most active script frame, for best line number blame. */ - for (fp = cx->fp; fp; fp = fp->down) { - if (fp->script && fp->pc) { - report.filename = fp->script->filename; - report.lineno = js_PCToLineNumber(cx, fp->script, fp->pc); - break; - } - } - - warning = JSREPORT_IS_WARNING(report.flags); - if (warning && JS_HAS_WERROR_OPTION(cx)) { - report.flags &= ~JSREPORT_WARNING; - warning = JS_FALSE; - } - - ReportError(cx, last, &report); - free(last); - return warning; -} - -/* - * The arguments from ap need to be packaged up into an array and stored - * into the report struct. - * - * The format string addressed by the error number may contain operands - * identified by the format {N}, where N is a decimal digit. Each of these - * is to be replaced by the Nth argument from the va_list. The complete - * message is placed into reportp->ucmessage converted to a JSString. - * - * Returns true if the expansion succeeds (can fail if out of memory). - */ -JSBool -js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback, - void *userRef, const uintN errorNumber, - char **messagep, JSErrorReport *reportp, - JSBool *warningp, JSBool charArgs, va_list ap) -{ - const JSErrorFormatString *efs; - int i; - int argCount; - - *warningp = JSREPORT_IS_WARNING(reportp->flags); - if (*warningp && JS_HAS_WERROR_OPTION(cx)) { - reportp->flags &= ~JSREPORT_WARNING; - *warningp = JS_FALSE; - } - - *messagep = NULL; - if (callback) { - efs = callback(userRef, NULL, errorNumber); - if (efs) { - size_t totalArgsLength = 0; - size_t argLengths[10]; /* only {0} thru {9} supported */ - argCount = efs->argCount; - JS_ASSERT(argCount <= 10); - if (argCount > 0) { - /* - * Gather the arguments into an array, and accumulate - * their sizes. We allocate 1 more than necessary and - * null it out to act as the caboose when we free the - * pointers later. - */ - reportp->messageArgs = (const jschar **) - JS_malloc(cx, sizeof(jschar *) * (argCount + 1)); - if (!reportp->messageArgs) - return JS_FALSE; - reportp->messageArgs[argCount] = NULL; - for (i = 0; i < argCount; i++) { - if (charArgs) { - char *charArg = va_arg(ap, char *); - size_t charArgLength = strlen(charArg); - reportp->messageArgs[i] - = js_InflateString(cx, charArg, &charArgLength); - if (!reportp->messageArgs[i]) - goto error; - } - else - reportp->messageArgs[i] = va_arg(ap, jschar *); - argLengths[i] = js_strlen(reportp->messageArgs[i]); - totalArgsLength += argLengths[i]; - } - /* NULL-terminate for easy copying. */ - reportp->messageArgs[i] = NULL; - } - /* - * Parse the error format, substituting the argument X - * for {X} in the format. - */ - if (argCount > 0) { - if (efs->format) { - jschar *buffer, *fmt, *out; - const jschar *arg; - int expandedArgs = 0; - size_t expandedLength; - size_t len = strlen (efs->format); - buffer = fmt = js_InflateString (cx, efs->format, &len); - if (!buffer) - goto error; - expandedLength - = len - - (3 * argCount) /* exclude the {n} */ - + totalArgsLength; - /* - * Note - the above calculation assumes that each argument - * is used once and only once in the expansion !!! - */ - reportp->ucmessage = out = (jschar *) - JS_malloc(cx, (expandedLength + 1) * sizeof(jschar)); - if (!out) { - JS_free (cx, buffer); - goto error; - } - while (*fmt) { - if (*fmt == '{') { - if (isdigit(fmt[1])) { - int d = JS7_UNDEC(fmt[1]); - JS_ASSERT(d < argCount); - arg = reportp->messageArgs[d]; - js_strncpy(out, arg, argLengths[d]); - out += argLengths[d]; - fmt += 3; - expandedArgs++; - continue; - } - } - *out++ = *fmt++; - } - JS_ASSERT(expandedArgs == argCount); - *out = 0; - JS_free (cx, buffer); - *messagep = - js_DeflateString(cx, reportp->ucmessage, - (size_t)(out - reportp->ucmessage)); - if (!*messagep) - goto error; - } - } else { - /* - * Zero arguments: the format string (if it exists) is the - * entire message. - */ - if (efs->format) { - size_t len; - *messagep = JS_strdup(cx, efs->format); - if (!*messagep) - goto error; - len = strlen(*messagep); - reportp->ucmessage - = js_InflateString(cx, *messagep, &len); - if (!reportp->ucmessage) - goto error; - } - } - } - } - if (*messagep == NULL) { - /* where's the right place for this ??? */ - const char *defaultErrorMessage - = "No error message available for error number %d"; - size_t nbytes = strlen(defaultErrorMessage) + 16; - *messagep = (char *)JS_malloc(cx, nbytes); - if (!*messagep) - goto error; - JS_snprintf(*messagep, nbytes, defaultErrorMessage, errorNumber); - } - return JS_TRUE; - -error: - if (reportp->messageArgs) { - i = 0; - while (reportp->messageArgs[i]) - JS_free(cx, (void *)reportp->messageArgs[i++]); - JS_free(cx, (void *)reportp->messageArgs); - reportp->messageArgs = NULL; - } - if (reportp->ucmessage) { - JS_free(cx, (void *)reportp->ucmessage); - reportp->ucmessage = NULL; - } - if (*messagep) { - JS_free(cx, (void *)*messagep); - *messagep = NULL; - } - return JS_FALSE; -} - -JSBool -js_ReportErrorNumberVA(JSContext *cx, uintN flags, JSErrorCallback callback, - void *userRef, const uintN errorNumber, - JSBool charArgs, va_list ap) -{ - JSStackFrame *fp; - JSErrorReport report; - char *message; - JSBool warning; - - if ((flags & JSREPORT_STRICT) && !JS_HAS_STRICT_OPTION(cx)) - return JS_TRUE; - - memset(&report, 0, sizeof (struct JSErrorReport)); - report.flags = flags; - report.errorNumber = errorNumber; - - /* - * If we can't find out where the error was based on the current frame, - * see if the next frame has a script/pc combo we can use. - */ - for (fp = cx->fp; fp; fp = fp->down) { - if (fp->script && fp->pc) { - report.filename = fp->script->filename; - report.lineno = js_PCToLineNumber(cx, fp->script, fp->pc); - break; - } - } - - if (!js_ExpandErrorArguments(cx, callback, userRef, errorNumber, - &message, &report, &warning, charArgs, ap)) { - return JS_FALSE; - } - - ReportError(cx, message, &report); - - if (message) - JS_free(cx, message); - if (report.messageArgs) { - int i = 0; - while (report.messageArgs[i]) - JS_free(cx, (void *)report.messageArgs[i++]); - JS_free(cx, (void *)report.messageArgs); - } - if (report.ucmessage) - JS_free(cx, (void *)report.ucmessage); - - return warning; -} - -JS_FRIEND_API(void) -js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *reportp) -{ - JSErrorReporter onError; - - if (!message) - return; - - if (cx->lastMessage) - free(cx->lastMessage); - cx->lastMessage = JS_strdup(cx, message); - if (!cx->lastMessage) - return; - onError = cx->errorReporter; - - /* - * If debugErrorHook is present then we give it a chance to veto - * sending the error on to the regular ErrorReporter. - */ - if (onError) { - JSDebugErrorHook hook = cx->runtime->debugErrorHook; - if (hook && - !hook(cx, cx->lastMessage, reportp, - cx->runtime->debugErrorHookData)) { - onError = NULL; - } - } - if (onError) - onError(cx, cx->lastMessage, reportp); -} - -void -js_ReportIsNotDefined(JSContext *cx, const char *name) -{ - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_DEFINED, name); -} - -#if defined DEBUG && defined XP_UNIX -/* For gdb usage. */ -void js_traceon(JSContext *cx) { cx->tracefp = stderr; } -void js_traceoff(JSContext *cx) { cx->tracefp = NULL; } -#endif - -JSErrorFormatString js_ErrorFormatString[JSErr_Limit] = { -#if JS_HAS_DFLT_MSG_STRINGS -#define MSG_DEF(name, number, count, exception, format) \ - { format, count } , -#else -#define MSG_DEF(name, number, count, exception, format) \ - { NULL, count } , -#endif -#include "js.msg" -#undef MSG_DEF -}; - -const JSErrorFormatString * -js_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber) -{ - if ((errorNumber > 0) && (errorNumber < JSErr_Limit)) - return &js_ErrorFormatString[errorNumber]; - return NULL; -} diff --git a/lib/javascript/jscntxt.h b/lib/javascript/jscntxt.h deleted file mode 100644 index 49ca4384..00000000 --- a/lib/javascript/jscntxt.h +++ /dev/null @@ -1,803 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jscntxt_h___ -#define jscntxt_h___ -/* - * JS execution context. - */ -#include "jsarena.h" /* Added by JSIFY */ -#include "jsclist.h" -#include "jslong.h" -#include "jsatom.h" -#include "jsconfig.h" -#include "jsdhash.h" -#include "jsgc.h" -#include "jsinterp.h" -#include "jsobj.h" -#include "jsprvtd.h" -#include "jspubtd.h" -#include "jsregexp.h" -#include "jsutil.h" - -JS_BEGIN_EXTERN_C - -typedef enum JSGCMode { JS_NO_GC, JS_MAYBE_GC, JS_FORCE_GC } JSGCMode; - -typedef enum JSRuntimeState { - JSRTS_DOWN, - JSRTS_LAUNCHING, - JSRTS_UP, - JSRTS_LANDING -} JSRuntimeState; - -typedef struct JSPropertyTreeEntry { - JSDHashEntryHdr hdr; - JSScopeProperty *child; -} JSPropertyTreeEntry; - -/* - * Forward declaration for opaque JSRuntime.nativeIteratorStates. - */ -typedef struct JSNativeIteratorState JSNativeIteratorState; - -struct JSRuntime { - /* Runtime state, synchronized by the stateChange/gcLock condvar/lock. */ - JSRuntimeState state; - - /* Garbage collector state, used by jsgc.c. */ - JSArenaPool gcArenaPool[GC_NUM_FREELISTS]; - JSGCThing *gcFreeList[GC_NUM_FREELISTS]; - JSDHashTable gcRootsHash; - JSDHashTable *gcLocksHash; - jsrefcount gcKeepAtoms; - uint32 gcBytes; - uint32 gcLastBytes; - uint32 gcMaxBytes; - uint32 gcMaxMallocBytes; - uint32 gcLevel; - uint32 gcNumber; - JSPackedBool gcPoke; - JSPackedBool gcRunning; - JSGCCallback gcCallback; - uint32 gcMallocBytes; - - /* - * API compatibility requires keeping GCX_PRIVATE bytes separate from the - * original GC types' byte tally. Otherwise embeddings that configure a - * good limit for pre-GCX_PRIVATE versions of the engine will see memory - * over-pressure too often, possibly leading to failed last-ditch GCs. - * - * The new XML GC-thing types do add to gcBytes, and they're larger than - * the original GC-thing type size (8 bytes on most architectures). So a - * user who enables E4X may want to increase the maxbytes value passed to - * JS_NewRuntime. TODO: Note this in the API docs. - */ - uint32 gcPrivateBytes; - -#if JS_HAS_XML_SUPPORT - /* Lists of JSXML private data structures to be finalized. */ - JSXMLNamespace *gcDoomedNamespaces; - JSXMLQName *gcDoomedQNames; - JSXML *gcDoomedXML; -#endif -#ifdef JS_GCMETER - JSGCStats gcStats; -#endif - - /* Literal table maintained by jsatom.c functions. */ - JSAtomState atomState; - - /* Random number generator state, used by jsmath.c. */ - JSBool rngInitialized; - int64 rngMultiplier; - int64 rngAddend; - int64 rngMask; - int64 rngSeed; - jsdouble rngDscale; - - /* Well-known numbers held for use by this runtime's contexts. */ - jsdouble *jsNaN; - jsdouble *jsNegativeInfinity; - jsdouble *jsPositiveInfinity; - - /* Empty string held for use by this runtime's contexts. */ - JSString *emptyString; - - /* List of active contexts sharing this runtime; protected by gcLock. */ - JSCList contextList; - - /* These are used for debugging -- see jsprvtd.h and jsdbgapi.h. */ - JSTrapHandler interruptHandler; - void *interruptHandlerData; - JSNewScriptHook newScriptHook; - void *newScriptHookData; - JSDestroyScriptHook destroyScriptHook; - void *destroyScriptHookData; - JSTrapHandler debuggerHandler; - void *debuggerHandlerData; - JSSourceHandler sourceHandler; - void *sourceHandlerData; - JSInterpreterHook executeHook; - void *executeHookData; - JSInterpreterHook callHook; - void *callHookData; - JSObjectHook objectHook; - void *objectHookData; - JSTrapHandler throwHook; - void *throwHookData; - JSDebugErrorHook debugErrorHook; - void *debugErrorHookData; - - /* More debugging state, see jsdbgapi.c. */ - JSCList trapList; - JSCList watchPointList; - - /* Weak links to properties, indexed by quickened get/set opcodes. */ - /* XXX must come after JSCLists or MSVC alignment bug bites empty lists */ - JSPropertyCache propertyCache; - - /* Client opaque pointer */ - void *data; - -#ifdef JS_THREADSAFE - /* These combine to interlock the GC and new requests. */ - PRLock *gcLock; - PRCondVar *gcDone; - PRCondVar *requestDone; - uint32 requestCount; - jsword gcThread; - - /* Lock and owning thread pointer for JS_LOCK_RUNTIME. */ - PRLock *rtLock; -#ifdef DEBUG - jsword rtLockOwner; -#endif - - /* Used to synchronize down/up state change; protected by gcLock. */ - PRCondVar *stateChange; - - /* Used to serialize cycle checks when setting __proto__ or __parent__. */ - PRLock *setSlotLock; - PRCondVar *setSlotDone; - JSBool setSlotBusy; - JSScope *setSlotScope; /* deadlock avoidance, see jslock.c */ - - /* - * State for sharing single-threaded scopes, once a second thread tries to - * lock a scope. The scopeSharingDone condvar is protected by rt->gcLock, - * to minimize number of locks taken in JS_EndRequest. - * - * The scopeSharingTodo linked list is likewise "global" per runtime, not - * one-list-per-context, to conserve space over all contexts, optimizing - * for the likely case that scopes become shared rarely, and among a very - * small set of threads (contexts). - */ - PRCondVar *scopeSharingDone; - JSScope *scopeSharingTodo; - -/* - * Magic terminator for the rt->scopeSharingTodo linked list, threaded through - * scope->u.link. This hack allows us to test whether a scope is on the list - * by asking whether scope->u.link is non-null. We use a large, likely bogus - * pointer here to distinguish this value from any valid u.count (small int) - * value. - */ -#define NO_SCOPE_SHARING_TODO ((JSScope *) 0xfeedbeef) -#endif /* JS_THREADSAFE */ - - /* - * Check property accessibility for objects of arbitrary class. Used at - * present to check f.caller accessibility for any function object f. - */ - JSCheckAccessOp checkObjectAccess; - - /* Security principals serialization support. */ - JSPrincipalsTranscoder principalsTranscoder; - - /* Optional hook to find principals for an object in this runtime. */ - JSObjectPrincipalsFinder findObjectPrincipals; - - /* Shared scope property tree, and allocator for its nodes. */ - JSDHashTable propertyTreeHash; - JSScopeProperty *propertyFreeList; - JSArenaPool propertyArenaPool; - - /* Script filename table. */ - struct JSHashTable *scriptFilenameTable; - JSCList scriptFilenamePrefixes; -#ifdef JS_THREADSAFE - PRLock *scriptFilenameTableLock; -#endif - - /* Number localization, used by jsnum.c */ - const char *thousandsSeparator; - const char *decimalSeparator; - const char *numGrouping; - - /* - * Weak references to lazily-created, well-known XML singletons. - * - * NB: Singleton objects must be carefully disconnected from the rest of - * the object graph usually associated with a JSContext's global object, - * including the set of standard class objects. See jsxml.c for details. - */ - JSObject *anynameObject; - JSObject *functionNamespaceObject; - - /* - * A helper list for the GC, so it can mark native iterator states. See - * js_MarkNativeIteratorStates for details. - */ - JSNativeIteratorState *nativeIteratorStates; - -#ifdef DEBUG - /* Function invocation metering. */ - jsrefcount inlineCalls; - jsrefcount nativeCalls; - jsrefcount nonInlineCalls; - jsrefcount constructs; - - /* Scope lock and property metering. */ - jsrefcount claimAttempts; - jsrefcount claimedScopes; - jsrefcount deadContexts; - jsrefcount deadlocksAvoided; - jsrefcount liveScopes; - jsrefcount sharedScopes; - jsrefcount totalScopes; - jsrefcount badUndependStrings; - jsrefcount liveScopeProps; - jsrefcount totalScopeProps; - jsrefcount livePropTreeNodes; - jsrefcount duplicatePropTreeNodes; - jsrefcount totalPropTreeNodes; - jsrefcount propTreeKidsChunks; - jsrefcount middleDeleteFixups; - - /* String instrumentation. */ - jsrefcount liveStrings; - jsrefcount totalStrings; - jsrefcount liveDependentStrings; - jsrefcount totalDependentStrings; - double lengthSum; - double lengthSquaredSum; - double strdepLengthSum; - double strdepLengthSquaredSum; -#endif -}; - -#ifdef DEBUG -# define JS_RUNTIME_METER(rt, which) JS_ATOMIC_INCREMENT(&(rt)->which) -# define JS_RUNTIME_UNMETER(rt, which) JS_ATOMIC_DECREMENT(&(rt)->which) -#else -# define JS_RUNTIME_METER(rt, which) /* nothing */ -# define JS_RUNTIME_UNMETER(rt, which) /* nothing */ -#endif - -#define JS_KEEP_ATOMS(rt) JS_ATOMIC_INCREMENT(&(rt)->gcKeepAtoms); -#define JS_UNKEEP_ATOMS(rt) JS_ATOMIC_DECREMENT(&(rt)->gcKeepAtoms); - -#ifdef JS_ARGUMENT_FORMATTER_DEFINED -/* - * Linked list mapping format strings for JS_{Convert,Push}Arguments{,VA} to - * formatter functions. Elements are sorted in non-increasing format string - * length order. - */ -struct JSArgumentFormatMap { - const char *format; - size_t length; - JSArgumentFormatter formatter; - JSArgumentFormatMap *next; -}; -#endif - -struct JSStackHeader { - uintN nslots; - JSStackHeader *down; -}; - -#define JS_STACK_SEGMENT(sh) ((jsval *)(sh) + 2) - -/* - * Key and entry types for the JSContext.resolvingTable hash table, typedef'd - * here because all consumers need to see these declarations (and not just the - * typedef names, as would be the case for an opaque pointer-to-typedef'd-type - * declaration), along with cx->resolvingTable. - */ -typedef struct JSResolvingKey { - JSObject *obj; - jsid id; -} JSResolvingKey; - -typedef struct JSResolvingEntry { - JSDHashEntryHdr hdr; - JSResolvingKey key; - uint32 flags; -} JSResolvingEntry; - -#define JSRESFLAG_LOOKUP 0x1 /* resolving id from lookup */ -#define JSRESFLAG_WATCH 0x2 /* resolving id from watch */ - -typedef struct JSLocalRootChunk JSLocalRootChunk; - -#define JSLRS_CHUNK_SHIFT 8 -#define JSLRS_CHUNK_SIZE JS_BIT(JSLRS_CHUNK_SHIFT) -#define JSLRS_CHUNK_MASK JS_BITMASK(JSLRS_CHUNK_SHIFT) - -struct JSLocalRootChunk { - jsval roots[JSLRS_CHUNK_SIZE]; - JSLocalRootChunk *down; -}; - -typedef struct JSLocalRootStack { - uint32 scopeMark; - uint32 rootCount; - JSLocalRootChunk *topChunk; - JSLocalRootChunk firstChunk; -} JSLocalRootStack; - -#define JSLRS_NULL_MARK ((uint32) -1) - -typedef struct JSTempValueRooter JSTempValueRooter; -typedef void -(* JS_DLL_CALLBACK JSTempValueMarker)(JSContext *cx, JSTempValueRooter *tvr); - -typedef union JSTempValueUnion { - jsval value; - JSObject *object; - JSTempValueMarker marker; - jsval *array; -} JSTempValueUnion; - -/* - * Context-linked stack of temporary GC roots. - * - * If count is -1, then u.value contains the single value to root. - * If count is -2, then u.marker holds a mark hook that is executed to mark - * the values. - * If count >= 0, then u.array points to a stack-allocated vector of jsvals. - * - * To root a single GC-thing pointer, which need not be tagged and stored as a - * jsval, use JS_PUSH_SINGLE_TEMP_ROOT. The (jsval)(val) cast works because a - * GC-thing is aligned on a 0 mod 8 boundary, and object has the 0 jsval tag. - * So any GC-thing may be tagged as if it were an object and untagged, if it's - * then used only as an opaque pointer until discriminated by other means than - * tag bits (this is how the GC mark function uses its |thing| parameter -- it - * consults GC-thing flags stored separately from the thing to decide the type - * of thing). - * - * Alternatively, if a single pointer to rooted JSObject * is required, use - * JS_PUSH_TEMP_ROOT_OBJECT(cx, NULL, &tvr). Then &tvr.u.object gives the - * necessary pointer, which puns tvr.u.value safely because object tag bits - * are all zeroes. - * - * If you need to protect a result value that flows out of a C function across - * several layers of other functions, use the js_LeaveLocalRootScopeWithResult - * internal API (see further below) instead. - */ -struct JSTempValueRooter { - JSTempValueRooter *down; - ptrdiff_t count; - JSTempValueUnion u; -}; - -#define JS_PUSH_TEMP_ROOT_COMMON(cx,tvr) \ - JS_BEGIN_MACRO \ - JS_ASSERT((cx)->tempValueRooters != (tvr)); \ - (tvr)->down = (cx)->tempValueRooters; \ - (cx)->tempValueRooters = (tvr); \ - JS_END_MACRO - -#define JS_PUSH_SINGLE_TEMP_ROOT(cx,val,tvr) \ - JS_BEGIN_MACRO \ - JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ - (tvr)->count = -1; \ - (tvr)->u.value = (val); \ - JS_END_MACRO - -#define JS_PUSH_TEMP_ROOT(cx,cnt,arr,tvr) \ - JS_BEGIN_MACRO \ - JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ - JS_ASSERT((ptrdiff_t)(cnt) >= 0); \ - (tvr)->count = (ptrdiff_t)(cnt); \ - (tvr)->u.array = (arr); \ - JS_END_MACRO - -#define JS_PUSH_TEMP_ROOT_MARKER(cx,marker_,tvr) \ - JS_BEGIN_MACRO \ - JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ - (tvr)->count = -2; \ - (tvr)->u.marker = (marker_); \ - JS_END_MACRO - -#define JS_PUSH_TEMP_ROOT_OBJECT(cx,obj,tvr) \ - JS_BEGIN_MACRO \ - JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ - (tvr)->count = -1; \ - (tvr)->u.object = (obj); \ - JS_END_MACRO - -#define JS_POP_TEMP_ROOT(cx,tvr) \ - JS_BEGIN_MACRO \ - JS_ASSERT((cx)->tempValueRooters == (tvr)); \ - (cx)->tempValueRooters = (tvr)->down; \ - JS_END_MACRO - -#define JS_TEMP_ROOT_EVAL(cx,cnt,val,expr) \ - JS_BEGIN_MACRO \ - JSTempValueRooter tvr; \ - JS_PUSH_TEMP_ROOT(cx, cnt, val, &tvr); \ - (expr); \ - JS_POP_TEMP_ROOT(cx, &tvr); \ - JS_END_MACRO - -struct JSContext { - JSCList links; - - /* Interpreter activation count. */ - uintN interpLevel; - - /* Limit pointer for checking stack consumption during recursion. */ - jsuword stackLimit; - - /* Runtime version control identifier and equality operators. */ - uint16 version; - jsbytecode jsop_eq; - jsbytecode jsop_ne; - - /* Data shared by threads in an address space. */ - JSRuntime *runtime; - - /* Stack arena pool and frame pointer register. */ - JSArenaPool stackPool; - JSStackFrame *fp; - - /* Temporary arena pool used while compiling and decompiling. */ - JSArenaPool tempPool; - - /* Top-level object and pointer to top stack frame's scope chain. */ - JSObject *globalObject; - - /* Most recently created things by type, members of the GC's root set. */ - JSGCThing *newborn[GCX_NTYPES]; - - /* Atom root for the last-looked-up atom on this context. */ - JSAtom *lastAtom; - - /* Root for the result of the most recent js_InternalInvoke call. */ - jsval lastInternalResult; - - /* Regular expression class statics (XXX not shared globally). */ - JSRegExpStatics regExpStatics; - - /* State for object and array toSource conversion. */ - JSSharpObjectMap sharpObjectMap; - - /* Argument formatter support for JS_{Convert,Push}Arguments{,VA}. */ - JSArgumentFormatMap *argumentFormatMap; - - /* Last message string and trace file for debugging. */ - char *lastMessage; -#ifdef DEBUG - void *tracefp; -#endif - - /* Per-context optional user callbacks. */ - JSBranchCallback branchCallback; - JSErrorReporter errorReporter; - - /* Client opaque pointer */ - void *data; - - /* GC and thread-safe state. */ - JSStackFrame *dormantFrameChain; /* dormant stack frame to scan */ -#ifdef JS_THREADSAFE - jsword thread; - jsrefcount requestDepth; - JSScope *scopeToShare; /* weak reference, see jslock.c */ - JSScope *lockedSealedScope; /* weak ref, for low-cost sealed - scope locking */ -#endif - -#if JS_HAS_LVALUE_RETURN - /* - * Secondary return value from native method called on the left-hand side - * of an assignment operator. The native should store the object in which - * to set a property in *rval, and return the property's id expressed as a - * jsval by calling JS_SetCallReturnValue2(cx, idval). - */ - jsval rval2; - JSPackedBool rval2set; -#endif - -#if JS_HAS_XML_SUPPORT - /* - * Bit-set formed from binary exponentials of the XML_* tiny-ids defined - * for boolean settings in jsxml.c, plus an XSF_CACHE_VALID bit. Together - * these act as a cache of the boolean XML.ignore* and XML.prettyPrinting - * property values associated with this context's global object. - */ - uint8 xmlSettingFlags; -#endif - - /* - * True if creating an exception object, to prevent runaway recursion. - * NB: creatingException packs with rval2set, #if JS_HAS_LVALUE_RETURN; - * with xmlSettingFlags, #if JS_HAS_XML_SUPPORT; and with throwing below. - */ - JSPackedBool creatingException; - - /* - * Exception state -- the exception member is a GC root by definition. - * NB: throwing packs with creatingException and rval2set, above. - */ - JSPackedBool throwing; /* is there a pending exception? */ - jsval exception; /* most-recently-thrown exception */ - - /* Per-context options. */ - uint32 options; /* see jsapi.h for JSOPTION_* */ - - /* Locale specific callbacks for string conversion. */ - JSLocaleCallbacks *localeCallbacks; - - /* - * cx->resolvingTable is non-null and non-empty if we are initializing - * standard classes lazily, or if we are otherwise recursing indirectly - * from js_LookupProperty through a JSClass.resolve hook. It is used to - * limit runaway recursion (see jsapi.c and jsobj.c). - */ - JSDHashTable *resolvingTable; - - /* PDL of stack headers describing stack slots not rooted by argv, etc. */ - JSStackHeader *stackHeaders; - - /* Optional stack of heap-allocated scoped local GC roots. */ - JSLocalRootStack *localRootStack; - - /* Stack of thread-stack-allocated temporary GC roots. */ - JSTempValueRooter *tempValueRooters; -}; - -#ifdef __cplusplus -/* FIXME(bug 332648): Move this into a public header. */ -class JSAutoTempValueRooter -{ - public: - JSAutoTempValueRooter(JSContext *cx, size_t len, jsval *vec) - : mContext(cx) { - JS_PUSH_TEMP_ROOT(mContext, len, vec, &mTvr); - } - JSAutoTempValueRooter(JSContext *cx, jsval v) - : mContext(cx) { - JS_PUSH_SINGLE_TEMP_ROOT(mContext, v, &mTvr); - } - - ~JSAutoTempValueRooter() { - JS_POP_TEMP_ROOT(mContext, &mTvr); - } - - private: - // static void *operator new(size_t) { return 0; } - // static void operator delete(void *, size_t) { } - - JSContext *mContext; - JSTempValueRooter mTvr; -}; -#endif - -/* - * Slightly more readable macros for testing per-context option settings (also - * to hide bitset implementation detail). - * - * JSOPTION_XML must be handled specially in order to propagate from compile- - * to run-time (from cx->options to script->version/cx->version). To do that, - * we copy JSOPTION_XML from cx->options into cx->version as JSVERSION_HAS_XML - * whenever options are set, and preserve this XML flag across version number - * changes done via the JS_SetVersion API. - * - * But when executing a script or scripted function, the interpreter changes - * cx->version, including the XML flag, to script->version. Thus JSOPTION_XML - * is a compile-time option that causes a run-time version change during each - * activation of the compiled script. That version change has the effect of - * changing JS_HAS_XML_OPTION, so that any compiling done via eval enables XML - * support. If an XML-enabled script or function calls a non-XML function, - * the flag bit will be cleared during the callee's activation. - * - * Note that JS_SetVersion API calls never pass JSVERSION_HAS_XML or'd into - * that API's version parameter. - * - * Note also that script->version must contain this XML option flag in order - * for XDR'ed scripts to serialize and deserialize with that option preserved - * for detection at run-time. We can't copy other compile-time options into - * script->version because that would break backward compatibility (certain - * other options, e.g. JSOPTION_VAROBJFIX, are analogous to JSOPTION_XML). - */ -#define JS_HAS_OPTION(cx,option) (((cx)->options & (option)) != 0) -#define JS_HAS_STRICT_OPTION(cx) JS_HAS_OPTION(cx, JSOPTION_STRICT) -#define JS_HAS_WERROR_OPTION(cx) JS_HAS_OPTION(cx, JSOPTION_WERROR) -#define JS_HAS_COMPILE_N_GO_OPTION(cx) JS_HAS_OPTION(cx, JSOPTION_COMPILE_N_GO) -#define JS_HAS_ATLINE_OPTION(cx) JS_HAS_OPTION(cx, JSOPTION_ATLINE) - -#define JSVERSION_MASK 0x0FFF /* see JSVersion in jspubtd.h */ -#define JSVERSION_HAS_XML 0x1000 /* flag induced by XML option */ - -#define JSVERSION_NUMBER(cx) ((cx)->version & JSVERSION_MASK) -#define JS_HAS_XML_OPTION(cx) ((cx)->version & JSVERSION_HAS_XML || \ - JSVERSION_NUMBER(cx) >= JSVERSION_1_6) - -#define JS_HAS_NATIVE_BRANCH_CALLBACK_OPTION(cx) \ - JS_HAS_OPTION(cx, JSOPTION_NATIVE_BRANCH_CALLBACK) - -/* - * Wrappers for the JSVERSION_IS_* macros from jspubtd.h taking JSContext *cx - * and masking off the XML flag and any other high order bits. - */ -#define JS_VERSION_IS_ECMA(cx) JSVERSION_IS_ECMA(JSVERSION_NUMBER(cx)) -#define JS_VERSION_IS_1_2(cx) (JSVERSION_NUMBER(cx) == JSVERSION_1_2) - -/* - * Common subroutine of JS_SetVersion and js_SetVersion, to update per-context - * data that depends on version. - */ -extern void -js_OnVersionChange(JSContext *cx); - -/* - * Unlike the JS_SetVersion API, this function stores JSVERSION_HAS_XML and - * any future non-version-number flags induced by compiler options. - */ -extern void -js_SetVersion(JSContext *cx, JSVersion version); - -/* - * Create and destroy functions for JSContext, which is manually allocated - * and exclusively owned. - */ -extern JSContext * -js_NewContext(JSRuntime *rt, size_t stackChunkSize); - -extern void -js_DestroyContext(JSContext *cx, JSGCMode gcmode); - -/* - * Return true if cx points to a context in rt->contextList, else return false. - * NB: the caller (see jslock.c:ClaimScope) must hold rt->gcLock. - */ -extern JSBool -js_ValidContextPointer(JSRuntime *rt, JSContext *cx); - -/* - * If unlocked, acquire and release rt->gcLock around *iterp update; otherwise - * the caller must be holding rt->gcLock. - */ -extern JSContext * -js_ContextIterator(JSRuntime *rt, JSBool unlocked, JSContext **iterp); - -/* - * JSClass.resolve and watchpoint recursion damping machinery. - */ -extern JSBool -js_StartResolving(JSContext *cx, JSResolvingKey *key, uint32 flag, - JSResolvingEntry **entryp); - -extern void -js_StopResolving(JSContext *cx, JSResolvingKey *key, uint32 flag, - JSResolvingEntry *entry, uint32 generation); - -/* - * Local root set management. - */ -extern JSBool -js_EnterLocalRootScope(JSContext *cx); - -extern void -js_LeaveLocalRootScope(JSContext *cx); - -extern void -js_ForgetLocalRoot(JSContext *cx, jsval v); - -extern int -js_PushLocalRoot(JSContext *cx, JSLocalRootStack *lrs, jsval v); - -extern void -js_MarkLocalRoots(JSContext *cx, JSLocalRootStack *lrs); - -/* - * Report an exception, which is currently realized as a printf-style format - * string and its arguments. - */ -typedef enum JSErrNum { -#define MSG_DEF(name, number, count, exception, format) \ - name = number, -#include "js.msg" -#undef MSG_DEF - JSErr_Limit -} JSErrNum; - -extern const JSErrorFormatString * -js_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber); - -#ifdef va_start -extern JSBool -js_ReportErrorVA(JSContext *cx, uintN flags, const char *format, va_list ap); - -extern JSBool -js_ReportErrorNumberVA(JSContext *cx, uintN flags, JSErrorCallback callback, - void *userRef, const uintN errorNumber, - JSBool charArgs, va_list ap); - -extern JSBool -js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback, - void *userRef, const uintN errorNumber, - char **message, JSErrorReport *reportp, - JSBool *warningp, JSBool charArgs, va_list ap); -#endif - -extern void -js_ReportOutOfMemory(JSContext *cx, JSErrorCallback errorCallback); - -/* - * Report an exception using a previously composed JSErrorReport. - * XXXbe remove from "friend" API - */ -extern JS_FRIEND_API(void) -js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *report); - -extern void -js_ReportIsNotDefined(JSContext *cx, const char *name); - -extern JSErrorFormatString js_ErrorFormatString[JSErr_Limit]; - -/* - * See JS_SetThreadStackLimit in jsapi.c, where we check that the stack grows - * in the expected direction. On Unix-y systems, JS_STACK_GROWTH_DIRECTION is - * computed on the build host by jscpucfg.c and written into jsautocfg.h. The - * macro is hardcoded in jscpucfg.h on Windows and Mac systems (for historical - * reasons pre-dating autoconf usage). - */ -#if JS_STACK_GROWTH_DIRECTION > 0 -# define JS_CHECK_STACK_SIZE(cx, lval) ((jsuword)&(lval) < (cx)->stackLimit) -#else -# define JS_CHECK_STACK_SIZE(cx, lval) ((jsuword)&(lval) > (cx)->stackLimit) -#endif - -JS_END_EXTERN_C - -#endif /* jscntxt_h___ */ diff --git a/lib/javascript/jscompat.h b/lib/javascript/jscompat.h deleted file mode 100644 index 6ba036a5..00000000 --- a/lib/javascript/jscompat.h +++ /dev/null @@ -1,57 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* -*- Mode: C; tab-width: 8 -*- - * Copyright © 1996-1999 Netscape Communications Corporation, All Rights Reserved. - */ -#ifndef jscompat_h___ -#define jscompat_h___ -/* - * Compatibility glue for various NSPR versions. We must always define int8, - * int16, jsword, and so on to minimize differences with js/ref, no matter what - * the NSPR typedef names may be. - */ -#include "jstypes.h" -#include "jslong.h" - -typedef JSIntn intN; -typedef JSUintn uintN; -typedef JSUword jsuword; -typedef JSWord jsword; -typedef float float32; -#define allocPriv allocPool -#endif /* jscompat_h___ */ diff --git a/lib/javascript/jsconfig.h b/lib/javascript/jsconfig.h deleted file mode 100644 index 5902499f..00000000 --- a/lib/javascript/jsconfig.h +++ /dev/null @@ -1,563 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JS configuration macros. - */ -#ifndef JS_VERSION -#define JS_VERSION 160 -#endif - -/* - * Compile-time JS version configuration. The JS version numbers lie on the - * number line like so: - * - * 1.0 1.1 1.2 1.3 1.4 ECMAv3 1.5 1.6 - * ^ ^ - * | | - * basis for ECMAv1 close to ECMAv2 - * - * where ECMAv3 stands for ECMA-262 Edition 3. See the runtime version enum - * JSVersion in jspubtd.h. Code in the engine can therefore count on version - * <= JSVERSION_1_4 to mean "before the Third Edition of ECMA-262" and version - * > JSVERSION_1_4 to mean "at or after the Third Edition". - * - * In the unlikely event that SpiderMonkey ever implements JavaScript 2.0, or - * ECMA-262 Edition 4 (JS2 without certain extensions), the version number to - * use would be near 200, or greater. - * - * The JS_VERSION_ECMA_3 version is the minimal configuration conforming to - * the ECMA-262 Edition 3 specification. Use it for minimal embeddings, where - * you're sure you don't need any of the extensions disabled in this version. - * In order to facilitate testing, JS_HAS_OBJ_PROTO_PROP is defined as part of - * the JS_VERSION_ECMA_3_TEST version. - */ -#define JS_VERSION_ECMA_3 148 -#define JS_VERSION_ECMA_3_TEST 149 - -#if JS_VERSION == JS_VERSION_ECMA_3 || \ - JS_VERSION == JS_VERSION_ECMA_3_TEST - -#define JS_BUG_NULL_INDEX_PROPS 0 /* o[0] defaults to null, not void */ -#define JS_BUG_EMPTY_INDEX_ZERO 0 /* o[""] is equivalent to o[0] */ -#define JS_BUG_EAGER_TOSTRING 0 /* o.toString() trumps o.valueOf() */ -#define JS_BUG_VOID_TOSTRING 0 /* void 0 + 0 == "undefined0" */ -#define JS_BUG_EVAL_THIS_FUN 0 /* eval('this') in function f is f */ -#define JS_BUG_EVAL_THIS_SCOPE 0 /* Math.eval('sin(x)') vs. local x */ -#define JS_BUG_FALLIBLE_EQOPS 0 /* fallible/intransitive equality ops */ -#define JS_BUG_FALLIBLE_TONUM 0 /* fallible ValueToNumber primitive */ -#define JS_BUG_WITH_CLOSURE 0 /* with(o)function f(){} sets o.f */ - -#define JS_HAS_PROP_DELETE 1 /* delete o.p removes p from o */ -#define JS_HAS_CALL_OBJECT 1 /* fun.caller is stack frame obj */ -#define JS_HAS_LABEL_STATEMENT 1 /* has break/continue to label: */ -#define JS_HAS_DO_WHILE_LOOP 1 /* has do {...} while (b) */ -#define JS_HAS_SWITCH_STATEMENT 1 /* has switch (v) {case c: ...} */ -#define JS_HAS_SOME_PERL_FUN 1 /* has array.join/reverse/sort */ -#define JS_HAS_MORE_PERL_FUN 1 /* has array.push, array.pop, etc */ -#define JS_HAS_STR_HTML_HELPERS 0 /* has str.anchor, str.bold, etc. */ -#define JS_HAS_PERL_SUBSTR 0 /* has str.substr */ -#define JS_HAS_VALUEOF_HINT 1 /* valueOf(hint) where hint is typeof */ -#define JS_HAS_LEXICAL_CLOSURE 1 /* nested functions, lexically closed */ -#define JS_HAS_APPLY_FUNCTION 1 /* has fun.apply(obj, argArray) */ -#define JS_HAS_CALL_FUNCTION 1 /* has fun.call(obj, arg1, ... argN) */ -#if JS_VERSION == JS_VERSION_ECMA_3_TEST -#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */ -#else -#define JS_HAS_OBJ_PROTO_PROP 0 /* has o.__proto__ etc. */ -#endif -#define JS_HAS_REGEXPS 1 /* has perl r.e.s via RegExp, /pat/ */ -#define JS_HAS_SEQUENCE_OPS 1 /* has array.slice, string.concat */ -#define JS_HAS_INITIALIZERS 1 /* has var o = {'foo': 42, 'bar':3} */ -#define JS_HAS_OBJ_WATCHPOINT 0 /* has o.watch and o.unwatch */ -#define JS_HAS_EXPORT_IMPORT 0 /* has export fun; import obj.fun */ -#define JS_HAS_EVAL_THIS_SCOPE 0 /* Math.eval is same as with (Math) */ -#define JS_HAS_TRIPLE_EQOPS 1 /* has === and !== identity eqops */ -#define JS_HAS_SHARP_VARS 0 /* has #n=, #n# for object literals */ -#define JS_HAS_REPLACE_LAMBDA 1 /* has string.replace(re, lambda) */ -#define JS_HAS_SCRIPT_OBJECT 0 /* has (new Script("x++")).exec() */ -#define JS_HAS_XDR 0 /* has XDR API and internal support */ -#define JS_HAS_XDR_FREEZE_THAW 0 /* has XDR freeze/thaw script methods */ -#define JS_HAS_EXCEPTIONS 1 /* has exception handling */ -#define JS_HAS_UNDEFINED 1 /* has global "undefined" property */ -#define JS_HAS_TOSOURCE 0 /* has Object/Array toSource method */ -#define JS_HAS_IN_OPERATOR 1 /* has in operator ('p' in {p:1}) */ -#define JS_HAS_INSTANCEOF 1 /* has {p:1} instanceof Object */ -#define JS_HAS_ARGS_OBJECT 1 /* has minimal ECMA arguments object */ -#define JS_HAS_DEBUGGER_KEYWORD 0 /* has hook for debugger keyword */ -#define JS_HAS_ERROR_EXCEPTIONS 1 /* has error object hierarchy */ -#define JS_HAS_CATCH_GUARD 0 /* has exception handling catch guard */ -#define JS_HAS_NEW_OBJ_METHODS 1 /* has Object.prototype query methods */ -#define JS_HAS_SPARSE_ARRAYS 0 /* array methods preserve empty elems */ -#define JS_HAS_DFLT_MSG_STRINGS 1 /* provides English error messages */ -#define JS_HAS_NUMBER_FORMATS 1 /* numbers have formatting methods */ -#define JS_HAS_GETTER_SETTER 0 /* has JS2 getter/setter functions */ -#define JS_HAS_UNEVAL 0 /* has uneval() top-level function */ -#define JS_HAS_CONST 0 /* has JS2 const as alternative var */ -#define JS_HAS_FUN_EXPR_STMT 0 /* has function expression statement */ -#define JS_HAS_LVALUE_RETURN 1 /* has o.item(i) = j; for native item */ -#define JS_HAS_NO_SUCH_METHOD 0 /* has o.__noSuchMethod__ handler */ -#define JS_HAS_XML_SUPPORT 0 /* has ECMAScript for XML support */ -#define JS_HAS_ARRAY_EXTRAS 0 /* has indexOf and Lispy extras */ - -#elif JS_VERSION == 100 - -#define JS_BUG_NULL_INDEX_PROPS 1 /* o[0] defaults to null, not void */ -#define JS_BUG_EMPTY_INDEX_ZERO 1 /* o[""] is equivalent to o[0] */ -#define JS_BUG_EAGER_TOSTRING 1 /* o.toString() trumps o.valueOf() */ -#define JS_BUG_VOID_TOSTRING 0 /* void 0 + 0 == "undefined0" */ -#define JS_BUG_EVAL_THIS_FUN 0 /* eval('this') in function f is f */ -#define JS_BUG_EVAL_THIS_SCOPE 0 /* Math.eval('sin(x)') vs. local x */ -#define JS_BUG_FALLIBLE_EQOPS 1 /* fallible/intransitive equality ops */ -#define JS_BUG_FALLIBLE_TONUM 1 /* fallible ValueToNumber primitive */ -#define JS_BUG_WITH_CLOSURE 0 /* with(o)function f(){} sets o.f */ - -#define JS_HAS_PROP_DELETE 0 /* delete o.p removes p from o */ -#define JS_HAS_CALL_OBJECT 0 /* fun.caller is stack frame obj */ -#define JS_HAS_LABEL_STATEMENT 0 /* has break/continue to label: */ -#define JS_HAS_DO_WHILE_LOOP 0 /* has do {...} while (b) */ -#define JS_HAS_SWITCH_STATEMENT 0 /* has switch (v) {case c: ...} */ -#define JS_HAS_SOME_PERL_FUN 0 /* has array.join/reverse/sort */ -#define JS_HAS_MORE_PERL_FUN 0 /* has array.push, str.substr, etc */ -#define JS_HAS_STR_HTML_HELPERS 1 /* has str.anchor, str.bold, etc. */ -#define JS_HAS_PERL_SUBSTR 0 /* has str.substr */ -#define JS_HAS_VALUEOF_HINT 0 /* valueOf(hint) where hint is typeof */ -#define JS_HAS_LEXICAL_CLOSURE 0 /* nested functions, lexically closed */ -#define JS_HAS_APPLY_FUNCTION 0 /* has fun.apply(obj, argArray) */ -#define JS_HAS_CALL_FUNCTION 0 /* has fun.call(obj, arg1, ... argN) */ -#define JS_HAS_OBJ_PROTO_PROP 0 /* has o.__proto__ etc. */ -#define JS_HAS_REGEXPS 0 /* has perl r.e.s via RegExp, /pat/ */ -#define JS_HAS_SEQUENCE_OPS 0 /* has array.slice, string.concat */ -#define JS_HAS_INITIALIZERS 0 /* has var o = {'foo': 42, 'bar':3} */ -#define JS_HAS_OBJ_WATCHPOINT 0 /* has o.watch and o.unwatch */ -#define JS_HAS_EXPORT_IMPORT 0 /* has export fun; import obj.fun */ -#define JS_HAS_EVAL_THIS_SCOPE 0 /* Math.eval is same as with (Math) */ -#define JS_HAS_TRIPLE_EQOPS 0 /* has === and !== identity eqops */ -#define JS_HAS_SHARP_VARS 0 /* has #n=, #n# for object literals */ -#define JS_HAS_REPLACE_LAMBDA 0 /* has string.replace(re, lambda) */ -#define JS_HAS_SCRIPT_OBJECT 0 /* has (new Script("x++")).exec() */ -#define JS_HAS_XDR 0 /* has XDR API and internal support */ -#define JS_HAS_XDR_FREEZE_THAW 0 /* has XDR freeze/thaw script methods */ -#define JS_HAS_EXCEPTIONS 0 /* has exception handling */ -#define JS_HAS_UNDEFINED 0 /* has global "undefined" property */ -#define JS_HAS_TOSOURCE 0 /* has Object/Array toSource method */ -#define JS_HAS_IN_OPERATOR 0 /* has in operator ('p' in {p:1}) */ -#define JS_HAS_INSTANCEOF 0 /* has {p:1} instanceof Object */ -#define JS_HAS_ARGS_OBJECT 0 /* has minimal ECMA arguments object */ -#define JS_HAS_DEBUGGER_KEYWORD 0 /* has hook for debugger keyword */ -#define JS_HAS_ERROR_EXCEPTIONS 0 /* has error object hierarchy */ -#define JS_HAS_CATCH_GUARD 0 /* has exception handling catch guard */ -#define JS_HAS_NEW_OBJ_METHODS 0 /* has Object.prototype query methods */ -#define JS_HAS_SPARSE_ARRAYS 0 /* array methods preserve empty elems */ -#define JS_HAS_DFLT_MSG_STRINGS 1 /* provides English error messages */ -#define JS_HAS_NUMBER_FORMATS 0 /* numbers have formatting methods */ -#define JS_HAS_GETTER_SETTER 0 /* has JS2 getter/setter functions */ -#define JS_HAS_UNEVAL 0 /* has uneval() top-level function */ -#define JS_HAS_CONST 0 /* has JS2 const as alternative var */ -#define JS_HAS_FUN_EXPR_STMT 0 /* has function expression statement */ -#define JS_HAS_LVALUE_RETURN 0 /* has o.item(i) = j; for native item */ -#define JS_HAS_NO_SUCH_METHOD 0 /* has o.__noSuchMethod__ handler */ -#define JS_HAS_XML_SUPPORT 0 /* has ECMAScript for XML support */ -#define JS_HAS_ARRAY_EXTRAS 0 /* has indexOf and Lispy extras */ - -#elif JS_VERSION == 110 - -#define JS_BUG_NULL_INDEX_PROPS 1 /* o[0] defaults to null, not void */ -#define JS_BUG_EMPTY_INDEX_ZERO 1 /* o[""] is equivalent to o[0] */ -#define JS_BUG_EAGER_TOSTRING 1 /* o.toString() trumps o.valueOf() */ -#define JS_BUG_VOID_TOSTRING 0 /* void 0 + 0 == "undefined0" */ -#define JS_BUG_EVAL_THIS_FUN 1 /* eval('this') in function f is f */ -#define JS_BUG_EVAL_THIS_SCOPE 1 /* Math.eval('sin(x)') vs. local x */ -#define JS_BUG_FALLIBLE_EQOPS 1 /* fallible/intransitive equality ops */ -#define JS_BUG_FALLIBLE_TONUM 1 /* fallible ValueToNumber primitive */ -#define JS_BUG_WITH_CLOSURE 0 /* with(o)function f(){} sets o.f */ - -#define JS_HAS_PROP_DELETE 0 /* delete o.p removes p from o */ -#define JS_HAS_CALL_OBJECT 0 /* fun.caller is stack frame obj */ -#define JS_HAS_LABEL_STATEMENT 0 /* has break/continue to label: */ -#define JS_HAS_DO_WHILE_LOOP 0 /* has do {...} while (b) */ -#define JS_HAS_SWITCH_STATEMENT 0 /* has switch (v) {case c: ...} */ -#define JS_HAS_SOME_PERL_FUN 1 /* has array.join/reverse/sort */ -#define JS_HAS_MORE_PERL_FUN 0 /* has array.push, str.substr, etc */ -#define JS_HAS_STR_HTML_HELPERS 1 /* has str.anchor, str.bold, etc. */ -#define JS_HAS_PERL_SUBSTR 0 /* has str.substr */ -#define JS_HAS_VALUEOF_HINT 0 /* valueOf(hint) where hint is typeof */ -#define JS_HAS_LEXICAL_CLOSURE 0 /* nested functions, lexically closed */ -#define JS_HAS_APPLY_FUNCTION 0 /* has apply(fun, arg1, ... argN) */ -#define JS_HAS_CALL_FUNCTION 0 /* has fun.call(obj, arg1, ... argN) */ -#define JS_HAS_OBJ_PROTO_PROP 0 /* has o.__proto__ etc. */ -#define JS_HAS_REGEXPS 0 /* has perl r.e.s via RegExp, /pat/ */ -#define JS_HAS_SEQUENCE_OPS 0 /* has array.slice, string.concat */ -#define JS_HAS_INITIALIZERS 0 /* has var o = {'foo': 42, 'bar':3} */ -#define JS_HAS_OBJ_WATCHPOINT 0 /* has o.watch and o.unwatch */ -#define JS_HAS_EXPORT_IMPORT 0 /* has export fun; import obj.fun */ -#define JS_HAS_EVAL_THIS_SCOPE 0 /* Math.eval is same as with (Math) */ -#define JS_HAS_TRIPLE_EQOPS 0 /* has === and !== identity eqops */ -#define JS_HAS_SHARP_VARS 0 /* has #n=, #n# for object literals */ -#define JS_HAS_REPLACE_LAMBDA 0 /* has string.replace(re, lambda) */ -#define JS_HAS_SCRIPT_OBJECT 0 /* has (new Script("x++")).exec() */ -#define JS_HAS_XDR 0 /* has XDR API and internal support */ -#define JS_HAS_XDR_FREEZE_THAW 0 /* has XDR freeze/thaw script methods */ -#define JS_HAS_EXCEPTIONS 0 /* has exception handling */ -#define JS_HAS_UNDEFINED 0 /* has global "undefined" property */ -#define JS_HAS_TOSOURCE 0 /* has Object/Array toSource method */ -#define JS_HAS_IN_OPERATOR 0 /* has in operator ('p' in {p:1}) */ -#define JS_HAS_INSTANCEOF 0 /* has {p:1} instanceof Object */ -#define JS_HAS_ARGS_OBJECT 0 /* has minimal ECMA arguments object */ -#define JS_HAS_DEBUGGER_KEYWORD 0 /* has hook for debugger keyword */ -#define JS_HAS_ERROR_EXCEPTIONS 0 /* has error object hierarchy */ -#define JS_HAS_CATCH_GUARD 0 /* has exception handling catch guard */ -#define JS_HAS_NEW_OBJ_METHODS 0 /* has Object.prototype query methods */ -#define JS_HAS_SPARSE_ARRAYS 0 /* array methods preserve empty elems */ -#define JS_HAS_DFLT_MSG_STRINGS 1 /* provides English error messages */ -#define JS_HAS_NUMBER_FORMATS 0 /* numbers have formatting methods */ -#define JS_HAS_GETTER_SETTER 0 /* has JS2 getter/setter functions */ -#define JS_HAS_UNEVAL 0 /* has uneval() top-level function */ -#define JS_HAS_CONST 0 /* has JS2 const as alternative var */ -#define JS_HAS_FUN_EXPR_STMT 0 /* has function expression statement */ -#define JS_HAS_LVALUE_RETURN 0 /* has o.item(i) = j; for native item */ -#define JS_HAS_NO_SUCH_METHOD 0 /* has o.__noSuchMethod__ handler */ -#define JS_HAS_XML_SUPPORT 0 /* has ECMAScript for XML support */ -#define JS_HAS_ARRAY_EXTRAS 0 /* has indexOf and Lispy extras */ - -#elif JS_VERSION == 120 - -#define JS_BUG_NULL_INDEX_PROPS 0 /* o[0] defaults to null, not void */ -#define JS_BUG_EMPTY_INDEX_ZERO 0 /* o[""] is equivalent to o[0] */ -#define JS_BUG_EAGER_TOSTRING 0 /* o.toString() trumps o.valueOf() */ -#define JS_BUG_VOID_TOSTRING 1 /* void 0 + 0 == "undefined0" */ -#define JS_BUG_EVAL_THIS_FUN 0 /* eval('this') in function f is f */ -#define JS_BUG_EVAL_THIS_SCOPE 0 /* Math.eval('sin(x)') vs. local x */ -#define JS_BUG_FALLIBLE_EQOPS 0 /* fallible/intransitive equality ops */ -#define JS_BUG_FALLIBLE_TONUM 0 /* fallible ValueToNumber primitive */ -#define JS_BUG_WITH_CLOSURE 1 /* with(o)function f(){} sets o.f */ - -#define JS_HAS_PROP_DELETE 1 /* delete o.p removes p from o */ -#define JS_HAS_CALL_OBJECT 1 /* fun.caller is stack frame obj */ -#define JS_HAS_LABEL_STATEMENT 1 /* has break/continue to label: */ -#define JS_HAS_DO_WHILE_LOOP 1 /* has do {...} while (b) */ -#define JS_HAS_SWITCH_STATEMENT 1 /* has switch (v) {case c: ...} */ -#define JS_HAS_SOME_PERL_FUN 1 /* has array.join/reverse/sort */ -#define JS_HAS_MORE_PERL_FUN 1 /* has array.push, str.substr, etc */ -#define JS_HAS_STR_HTML_HELPERS 1 /* has str.anchor, str.bold, etc. */ -#define JS_HAS_PERL_SUBSTR 1 /* has str.substr */ -#define JS_HAS_VALUEOF_HINT 1 /* valueOf(hint) where hint is typeof */ -#define JS_HAS_LEXICAL_CLOSURE 1 /* nested functions, lexically closed */ -#define JS_HAS_APPLY_FUNCTION 1 /* has apply(fun, arg1, ... argN) */ -#define JS_HAS_CALL_FUNCTION 0 /* has fun.call(obj, arg1, ... argN) */ -#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */ -#define JS_HAS_REGEXPS 1 /* has perl r.e.s via RegExp, /pat/ */ -#define JS_HAS_SEQUENCE_OPS 1 /* has array.slice, string.concat */ -#define JS_HAS_INITIALIZERS 1 /* has var o = {'foo': 42, 'bar':3} */ -#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */ -#define JS_HAS_EXPORT_IMPORT 1 /* has export fun; import obj.fun */ -#define JS_HAS_EVAL_THIS_SCOPE 1 /* Math.eval is same as with (Math) */ -#define JS_HAS_TRIPLE_EQOPS 0 /* has === and !== identity eqops */ -#define JS_HAS_SHARP_VARS 0 /* has #n=, #n# for object literals */ -#define JS_HAS_REPLACE_LAMBDA 0 /* has string.replace(re, lambda) */ -#define JS_HAS_SCRIPT_OBJECT 0 /* has (new Script("x++")).exec() */ -#define JS_HAS_XDR 0 /* has XDR API and internal support */ -#define JS_HAS_XDR_FREEZE_THAW 0 /* has XDR freeze/thaw script methods */ -#define JS_HAS_EXCEPTIONS 0 /* has exception handling */ -#define JS_HAS_UNDEFINED 0 /* has global "undefined" property */ -#define JS_HAS_TOSOURCE 0 /* has Object/Array toSource method */ -#define JS_HAS_IN_OPERATOR 0 /* has in operator ('p' in {p:1}) */ -#define JS_HAS_INSTANCEOF 0 /* has {p:1} instanceof Object */ -#define JS_HAS_ARGS_OBJECT 0 /* has minimal ECMA arguments object */ -#define JS_HAS_DEBUGGER_KEYWORD 0 /* has hook for debugger keyword */ -#define JS_HAS_ERROR_EXCEPTIONS 0 /* has error object hierarchy */ -#define JS_HAS_CATCH_GUARD 0 /* has exception handling catch guard */ -#define JS_HAS_NEW_OBJ_METHODS 0 /* has Object.prototype query methods */ -#define JS_HAS_SPARSE_ARRAYS 0 /* array methods preserve empty elems */ -#define JS_HAS_DFLT_MSG_STRINGS 1 /* provides English error messages */ -#define JS_HAS_NUMBER_FORMATS 0 /* numbers have formatting methods */ -#define JS_HAS_GETTER_SETTER 0 /* has JS2 getter/setter functions */ -#define JS_HAS_UNEVAL 0 /* has uneval() top-level function */ -#define JS_HAS_CONST 0 /* has JS2 const as alternative var */ -#define JS_HAS_FUN_EXPR_STMT 0 /* has function expression statement */ -#define JS_HAS_LVALUE_RETURN 0 /* has o.item(i) = j; for native item */ -#define JS_HAS_NO_SUCH_METHOD 0 /* has o.__noSuchMethod__ handler */ -#define JS_HAS_XML_SUPPORT 0 /* has ECMAScript for XML support */ -#define JS_HAS_ARRAY_EXTRAS 0 /* has indexOf and Lispy extras */ - -#elif JS_VERSION == 130 - -#define JS_BUG_NULL_INDEX_PROPS 0 /* o[0] defaults to null, not void */ -#define JS_BUG_EMPTY_INDEX_ZERO 0 /* o[""] is equivalent to o[0] */ -#define JS_BUG_EAGER_TOSTRING 0 /* o.toString() trumps o.valueOf() */ -#define JS_BUG_VOID_TOSTRING 0 /* void 0 + 0 == "undefined0" */ -#define JS_BUG_EVAL_THIS_FUN 0 /* eval('this') in function f is f */ -#define JS_BUG_EVAL_THIS_SCOPE 0 /* Math.eval('sin(x)') vs. local x */ -#define JS_BUG_FALLIBLE_EQOPS 0 /* fallible/intransitive equality ops */ -#define JS_BUG_FALLIBLE_TONUM 0 /* fallible ValueToNumber primitive */ -#define JS_BUG_WITH_CLOSURE 1 /* with(o)function f(){} sets o.f */ - -#define JS_HAS_PROP_DELETE 1 /* delete o.p removes p from o */ -#define JS_HAS_CALL_OBJECT 1 /* fun.caller is stack frame obj */ -#define JS_HAS_LABEL_STATEMENT 1 /* has break/continue to label: */ -#define JS_HAS_DO_WHILE_LOOP 1 /* has do {...} while (b) */ -#define JS_HAS_SWITCH_STATEMENT 1 /* has switch (v) {case c: ...} */ -#define JS_HAS_SOME_PERL_FUN 1 /* has array.join/reverse/sort */ -#define JS_HAS_MORE_PERL_FUN 1 /* has array.push, str.substr, etc */ -#define JS_HAS_STR_HTML_HELPERS 1 /* has str.anchor, str.bold, etc. */ -#define JS_HAS_PERL_SUBSTR 1 /* has str.substr */ -#define JS_HAS_VALUEOF_HINT 1 /* valueOf(hint) where hint is typeof */ -#define JS_HAS_LEXICAL_CLOSURE 1 /* nested functions, lexically closed */ -#define JS_HAS_APPLY_FUNCTION 1 /* has apply(fun, arg1, ... argN) */ -#define JS_HAS_CALL_FUNCTION 1 /* has fun.call(obj, arg1, ... argN) */ -#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */ -#define JS_HAS_REGEXPS 1 /* has perl r.e.s via RegExp, /pat/ */ -#define JS_HAS_SEQUENCE_OPS 1 /* has array.slice, string.concat */ -#define JS_HAS_INITIALIZERS 1 /* has var o = {'foo': 42, 'bar':3} */ -#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */ -#define JS_HAS_EXPORT_IMPORT 1 /* has export fun; import obj.fun */ -#define JS_HAS_EVAL_THIS_SCOPE 1 /* Math.eval is same as with (Math) */ -#define JS_HAS_TRIPLE_EQOPS 1 /* has === and !== identity eqops */ -#define JS_HAS_SHARP_VARS 1 /* has #n=, #n# for object literals */ -#define JS_HAS_REPLACE_LAMBDA 1 /* has string.replace(re, lambda) */ -#define JS_HAS_SCRIPT_OBJECT 1 /* has (new Script("x++")).exec() */ -#define JS_HAS_XDR 1 /* has XDR API and internal support */ -#define JS_HAS_XDR_FREEZE_THAW 0 /* has XDR freeze/thaw script methods */ -#define JS_HAS_EXCEPTIONS 0 /* has exception handling */ -#define JS_HAS_UNDEFINED 1 /* has global "undefined" property */ -#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */ -#define JS_HAS_IN_OPERATOR 0 /* has in operator ('p' in {p:1}) */ -#define JS_HAS_INSTANCEOF 0 /* has {p:1} instanceof Object */ -#define JS_HAS_ARGS_OBJECT 1 /* has minimal ECMA arguments object */ -#define JS_HAS_DEBUGGER_KEYWORD 1 /* has hook for debugger keyword */ -#define JS_HAS_ERROR_EXCEPTIONS 0 /* has error object hierarchy */ -#define JS_HAS_CATCH_GUARD 0 /* has exception handling catch guard */ -#define JS_HAS_NEW_OBJ_METHODS 0 /* has Object.prototype query methods */ -#define JS_HAS_SPARSE_ARRAYS 0 /* array methods preserve empty elems */ -#define JS_HAS_DFLT_MSG_STRINGS 1 /* provides English error messages */ -#define JS_HAS_NUMBER_FORMATS 0 /* numbers have formatting methods */ -#define JS_HAS_GETTER_SETTER 0 /* has JS2 getter/setter functions */ -#define JS_HAS_UNEVAL 0 /* has uneval() top-level function */ -#define JS_HAS_CONST 0 /* has JS2 const as alternative var */ -#define JS_HAS_FUN_EXPR_STMT 0 /* has function expression statement */ -#define JS_HAS_LVALUE_RETURN 0 /* has o.item(i) = j; for native item */ -#define JS_HAS_NO_SUCH_METHOD 0 /* has o.__noSuchMethod__ handler */ -#define JS_HAS_XML_SUPPORT 0 /* has ECMAScript for XML support */ -#define JS_HAS_ARRAY_EXTRAS 0 /* has indexOf and Lispy extras */ - -#elif JS_VERSION == 140 - -#define JS_BUG_NULL_INDEX_PROPS 0 /* o[0] defaults to null, not void */ -#define JS_BUG_EMPTY_INDEX_ZERO 0 /* o[""] is equivalent to o[0] */ -#define JS_BUG_EAGER_TOSTRING 0 /* o.toString() trumps o.valueOf() */ -#define JS_BUG_VOID_TOSTRING 0 /* void 0 + 0 == "undefined0" */ -#define JS_BUG_EVAL_THIS_FUN 0 /* eval('this') in function f is f */ -#define JS_BUG_EVAL_THIS_SCOPE 0 /* Math.eval('sin(x)') vs. local x */ -#define JS_BUG_FALLIBLE_EQOPS 0 /* fallible/intransitive equality ops */ -#define JS_BUG_FALLIBLE_TONUM 0 /* fallible ValueToNumber primitive */ -#define JS_BUG_WITH_CLOSURE 1 /* with(o)function f(){} sets o.f */ - -#define JS_HAS_PROP_DELETE 1 /* delete o.p removes p from o */ -#define JS_HAS_CALL_OBJECT 1 /* fun.caller is stack frame obj */ -#define JS_HAS_LABEL_STATEMENT 1 /* has break/continue to label: */ -#define JS_HAS_DO_WHILE_LOOP 1 /* has do {...} while (b) */ -#define JS_HAS_SWITCH_STATEMENT 1 /* has switch (v) {case c: ...} */ -#define JS_HAS_SOME_PERL_FUN 1 /* has array.join/reverse/sort */ -#define JS_HAS_MORE_PERL_FUN 1 /* has array.push, str.substr, etc */ -#define JS_HAS_STR_HTML_HELPERS 1 /* has str.anchor, str.bold, etc. */ -#define JS_HAS_PERL_SUBSTR 1 /* has str.substr */ -#define JS_HAS_VALUEOF_HINT 1 /* valueOf(hint) where hint is typeof */ -#define JS_HAS_LEXICAL_CLOSURE 1 /* nested functions, lexically closed */ -#define JS_HAS_APPLY_FUNCTION 1 /* has apply(fun, arg1, ... argN) */ -#define JS_HAS_CALL_FUNCTION 1 /* has fun.call(obj, arg1, ... argN) */ -#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */ -#define JS_HAS_REGEXPS 1 /* has perl r.e.s via RegExp, /pat/ */ -#define JS_HAS_SEQUENCE_OPS 1 /* has array.slice, string.concat */ -#define JS_HAS_INITIALIZERS 1 /* has var o = {'foo': 42, 'bar':3} */ -#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */ -#define JS_HAS_EXPORT_IMPORT 1 /* has export fun; import obj.fun */ -#define JS_HAS_EVAL_THIS_SCOPE 1 /* Math.eval is same as with (Math) */ -#define JS_HAS_TRIPLE_EQOPS 1 /* has === and !== identity eqops */ -#define JS_HAS_SHARP_VARS 1 /* has #n=, #n# for object literals */ -#define JS_HAS_REPLACE_LAMBDA 1 /* has string.replace(re, lambda) */ -#define JS_HAS_SCRIPT_OBJECT 1 /* has (new Script("x++")).exec() */ -#define JS_HAS_XDR 1 /* has XDR API and internal support */ -#define JS_HAS_XDR_FREEZE_THAW 0 /* has XDR freeze/thaw script methods */ -#define JS_HAS_EXCEPTIONS 1 /* has exception handling */ -#define JS_HAS_UNDEFINED 1 /* has global "undefined" property */ -#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */ -#define JS_HAS_IN_OPERATOR 1 /* has in operator ('p' in {p:1}) */ -#define JS_HAS_INSTANCEOF 1 /* has {p:1} instanceof Object */ -#define JS_HAS_ARGS_OBJECT 1 /* has minimal ECMA arguments object */ -#define JS_HAS_DEBUGGER_KEYWORD 1 /* has hook for debugger keyword */ -#define JS_HAS_ERROR_EXCEPTIONS 0 /* rt errors reflected as exceptions */ -#define JS_HAS_CATCH_GUARD 0 /* has exception handling catch guard */ -#define JS_HAS_NEW_OBJ_METHODS 0 /* has Object.prototype query methods */ -#define JS_HAS_SPARSE_ARRAYS 0 /* array methods preserve empty elems */ -#define JS_HAS_DFLT_MSG_STRINGS 1 /* provides English error messages */ -#define JS_HAS_NUMBER_FORMATS 0 /* numbers have formatting methods */ -#define JS_HAS_GETTER_SETTER 0 /* has JS2 getter/setter functions */ -#define JS_HAS_UNEVAL 0 /* has uneval() top-level function */ -#define JS_HAS_CONST 0 /* has JS2 const as alternative var */ -#define JS_HAS_FUN_EXPR_STMT 0 /* has function expression statement */ -#define JS_HAS_LVALUE_RETURN 0 /* has o.item(i) = j; for native item */ -#define JS_HAS_NO_SUCH_METHOD 0 /* has o.__noSuchMethod__ handler */ -#define JS_HAS_XML_SUPPORT 0 /* has ECMAScript for XML support */ -#define JS_HAS_ARRAY_EXTRAS 0 /* has indexOf and Lispy extras */ - -#elif JS_VERSION == 150 - -#define JS_BUG_NULL_INDEX_PROPS 0 /* o[0] defaults to null, not void */ -#define JS_BUG_EMPTY_INDEX_ZERO 0 /* o[""] is equivalent to o[0] */ -#define JS_BUG_EAGER_TOSTRING 0 /* o.toString() trumps o.valueOf() */ -#define JS_BUG_VOID_TOSTRING 0 /* void 0 + 0 == "undefined0" */ -#define JS_BUG_EVAL_THIS_FUN 0 /* eval('this') in function f is f */ -#define JS_BUG_EVAL_THIS_SCOPE 0 /* Math.eval('sin(x)') vs. local x */ -#define JS_BUG_FALLIBLE_EQOPS 0 /* fallible/intransitive equality ops */ -#define JS_BUG_FALLIBLE_TONUM 0 /* fallible ValueToNumber primitive */ -#define JS_BUG_WITH_CLOSURE 0 /* with(o)function f(){} sets o.f */ - -#define JS_HAS_PROP_DELETE 1 /* delete o.p removes p from o */ -#define JS_HAS_CALL_OBJECT 1 /* fun.caller is stack frame obj */ -#define JS_HAS_LABEL_STATEMENT 1 /* has break/continue to label: */ -#define JS_HAS_DO_WHILE_LOOP 1 /* has do {...} while (b) */ -#define JS_HAS_SWITCH_STATEMENT 1 /* has switch (v) {case c: ...} */ -#define JS_HAS_SOME_PERL_FUN 1 /* has array.join/reverse/sort */ -#define JS_HAS_MORE_PERL_FUN 1 /* has array.push, str.substr, etc */ -#define JS_HAS_STR_HTML_HELPERS 1 /* has str.anchor, str.bold, etc. */ -#define JS_HAS_PERL_SUBSTR 1 /* has str.substr */ -#define JS_HAS_VALUEOF_HINT 1 /* valueOf(hint) where hint is typeof */ -#define JS_HAS_LEXICAL_CLOSURE 1 /* nested functions, lexically closed */ -#define JS_HAS_APPLY_FUNCTION 1 /* has apply(fun, arg1, ... argN) */ -#define JS_HAS_CALL_FUNCTION 1 /* has fun.call(obj, arg1, ... argN) */ -#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */ -#define JS_HAS_REGEXPS 1 /* has perl r.e.s via RegExp, /pat/ */ -#define JS_HAS_SEQUENCE_OPS 1 /* has array.slice, string.concat */ -#define JS_HAS_INITIALIZERS 1 /* has var o = {'foo': 42, 'bar':3} */ -#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */ -#define JS_HAS_EXPORT_IMPORT 1 /* has export fun; import obj.fun */ -#define JS_HAS_EVAL_THIS_SCOPE 1 /* Math.eval is same as with (Math) */ -#define JS_HAS_TRIPLE_EQOPS 1 /* has === and !== identity eqops */ -#define JS_HAS_SHARP_VARS 1 /* has #n=, #n# for object literals */ -#define JS_HAS_REPLACE_LAMBDA 1 /* has string.replace(re, lambda) */ -#define JS_HAS_SCRIPT_OBJECT 1 /* has (new Script("x++")).exec() */ -#define JS_HAS_XDR 1 /* has XDR API and internal support */ -#define JS_HAS_XDR_FREEZE_THAW 0 /* has XDR freeze/thaw script methods */ -#define JS_HAS_EXCEPTIONS 1 /* has exception handling */ -#define JS_HAS_UNDEFINED 1 /* has global "undefined" property */ -#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */ -#define JS_HAS_IN_OPERATOR 1 /* has in operator ('p' in {p:1}) */ -#define JS_HAS_INSTANCEOF 1 /* has {p:1} instanceof Object */ -#define JS_HAS_ARGS_OBJECT 1 /* has minimal ECMA arguments object */ -#define JS_HAS_DEBUGGER_KEYWORD 1 /* has hook for debugger keyword */ -#define JS_HAS_ERROR_EXCEPTIONS 1 /* rt errors reflected as exceptions */ -#define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */ -#define JS_HAS_NEW_OBJ_METHODS 1 /* has Object.prototype query methods */ -#define JS_HAS_SPARSE_ARRAYS 0 /* array methods preserve empty elems */ -#define JS_HAS_DFLT_MSG_STRINGS 1 /* provides English error messages */ -#define JS_HAS_NUMBER_FORMATS 1 /* numbers have formatting methods */ -#define JS_HAS_GETTER_SETTER 1 /* has JS2 getter/setter functions */ -#define JS_HAS_UNEVAL 1 /* has uneval() top-level function */ -#define JS_HAS_CONST 1 /* has JS2 const as alternative var */ -#define JS_HAS_FUN_EXPR_STMT 1 /* has function expression statement */ -#define JS_HAS_LVALUE_RETURN 1 /* has o.item(i) = j; for native item */ -#define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */ -#define JS_HAS_XML_SUPPORT 0 /* has ECMAScript for XML support */ -#define JS_HAS_ARRAY_EXTRAS 0 /* has indexOf and Lispy extras */ - -#elif JS_VERSION == 160 - -#define JS_BUG_NULL_INDEX_PROPS 0 /* o[0] defaults to null, not void */ -#define JS_BUG_EMPTY_INDEX_ZERO 0 /* o[""] is equivalent to o[0] */ -#define JS_BUG_EAGER_TOSTRING 0 /* o.toString() trumps o.valueOf() */ -#define JS_BUG_VOID_TOSTRING 0 /* void 0 + 0 == "undefined0" */ -#define JS_BUG_EVAL_THIS_FUN 0 /* eval('this') in function f is f */ -#define JS_BUG_EVAL_THIS_SCOPE 0 /* Math.eval('sin(x)') vs. local x */ -#define JS_BUG_FALLIBLE_EQOPS 0 /* fallible/intransitive equality ops */ -#define JS_BUG_FALLIBLE_TONUM 0 /* fallible ValueToNumber primitive */ -#define JS_BUG_WITH_CLOSURE 0 /* with(o)function f(){} sets o.f */ - -#define JS_HAS_PROP_DELETE 1 /* delete o.p removes p from o */ -#define JS_HAS_CALL_OBJECT 1 /* fun.caller is stack frame obj */ -#define JS_HAS_LABEL_STATEMENT 1 /* has break/continue to label: */ -#define JS_HAS_DO_WHILE_LOOP 1 /* has do {...} while (b) */ -#define JS_HAS_SWITCH_STATEMENT 1 /* has switch (v) {case c: ...} */ -#define JS_HAS_SOME_PERL_FUN 1 /* has array.join/reverse/sort */ -#define JS_HAS_MORE_PERL_FUN 1 /* has array.push, str.substr, etc */ -#define JS_HAS_STR_HTML_HELPERS 1 /* has str.anchor, str.bold, etc. */ -#define JS_HAS_PERL_SUBSTR 1 /* has str.substr */ -#define JS_HAS_VALUEOF_HINT 1 /* valueOf(hint) where hint is typeof */ -#define JS_HAS_LEXICAL_CLOSURE 1 /* nested functions, lexically closed */ -#define JS_HAS_APPLY_FUNCTION 1 /* has apply(fun, arg1, ... argN) */ -#define JS_HAS_CALL_FUNCTION 1 /* has fun.call(obj, arg1, ... argN) */ -#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */ -#define JS_HAS_REGEXPS 1 /* has perl r.e.s via RegExp, /pat/ */ -#define JS_HAS_SEQUENCE_OPS 1 /* has array.slice, string.concat */ -#define JS_HAS_INITIALIZERS 1 /* has var o = {'foo': 42, 'bar':3} */ -#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */ -#define JS_HAS_EXPORT_IMPORT 1 /* has export fun; import obj.fun */ -#define JS_HAS_EVAL_THIS_SCOPE 1 /* Math.eval is same as with (Math) */ -#define JS_HAS_TRIPLE_EQOPS 1 /* has === and !== identity eqops */ -#define JS_HAS_SHARP_VARS 1 /* has #n=, #n# for object literals */ -#define JS_HAS_REPLACE_LAMBDA 1 /* has string.replace(re, lambda) */ -#define JS_HAS_SCRIPT_OBJECT 1 /* has (new Script("x++")).exec() */ -#define JS_HAS_XDR 1 /* has XDR API and internal support */ -#define JS_HAS_XDR_FREEZE_THAW 0 /* has XDR freeze/thaw script methods */ -#define JS_HAS_EXCEPTIONS 1 /* has exception handling */ -#define JS_HAS_UNDEFINED 1 /* has global "undefined" property */ -#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */ -#define JS_HAS_IN_OPERATOR 1 /* has in operator ('p' in {p:1}) */ -#define JS_HAS_INSTANCEOF 1 /* has {p:1} instanceof Object */ -#define JS_HAS_ARGS_OBJECT 1 /* has minimal ECMA arguments object */ -#define JS_HAS_DEBUGGER_KEYWORD 1 /* has hook for debugger keyword */ -#define JS_HAS_ERROR_EXCEPTIONS 1 /* rt errors reflected as exceptions */ -#define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */ -#define JS_HAS_NEW_OBJ_METHODS 1 /* has Object.prototype query methods */ -#define JS_HAS_SPARSE_ARRAYS 0 /* array methods preserve empty elems */ -#define JS_HAS_DFLT_MSG_STRINGS 1 /* provides English error messages */ -#define JS_HAS_NUMBER_FORMATS 1 /* numbers have formatting methods */ -#define JS_HAS_GETTER_SETTER 1 /* has JS2 getter/setter functions */ -#define JS_HAS_UNEVAL 1 /* has uneval() top-level function */ -#define JS_HAS_CONST 1 /* has JS2 const as alternative var */ -#define JS_HAS_FUN_EXPR_STMT 1 /* has function expression statement */ -#define JS_HAS_LVALUE_RETURN 1 /* has o.item(i) = j; for native item */ -#define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */ -#define JS_HAS_XML_SUPPORT 1 /* has ECMAScript for XML support */ -#define JS_HAS_ARRAY_EXTRAS 1 /* has indexOf and Lispy extras */ - -#else - -#error "unknown JS_VERSION" - -#endif diff --git a/lib/javascript/jsconfig.mk b/lib/javascript/jsconfig.mk deleted file mode 100644 index a3b88673..00000000 --- a/lib/javascript/jsconfig.mk +++ /dev/null @@ -1,181 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998-1999 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either of the GNU General Public License Version 2 or later (the "GPL"), -# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -ifndef OBJDIR - ifdef OBJDIR_NAME - OBJDIR = $(OBJDIR_NAME) - endif -endif - -NSPR_VERSION = v4.0 -NSPR_LIBSUFFIX = 4 - -NSPR_LOCAL = $(MOZ_DEPTH)/dist/$(OBJDIR)/nspr -NSPR_DIST = $(MOZ_DEPTH)/dist/$(OBJDIR) -NSPR_OBJDIR = $(OBJDIR) -ifeq ($(OS_ARCH), SunOS) - NSPR_OBJDIR := $(subst _sparc,,$(NSPR_OBJDIR)) -endif -ifeq ($(OS_ARCH), Linux) - LINUX_REL := $(shell uname -r) - ifneq (,$(findstring 2.0,$(LINUX_REL))) - NSPR_OBJDIR := $(subst _All,2.0_x86_glibc_PTH,$(NSPR_OBJDIR)) - else - NSPR_OBJDIR := $(subst _All,2.2_x86_glibc_PTH,$(NSPR_OBJDIR)) - endif -endif -ifeq ($(OS_ARCH), AIX) - NSPR_OBJDIR := $(subst 4.1,4.2,$(NSPR_OBJDIR)) -endif -ifeq ($(OS_CONFIG), IRIX6.2) - NSPR_OBJDIR := $(subst 6.2,6.2_n32_PTH,$(NSPR_OBJDIR)) -endif -ifeq ($(OS_CONFIG), IRIX6.5) - NSPR_OBJDIR := $(subst 6.5,6.5_n32_PTH,$(NSPR_OBJDIR)) -endif -ifeq ($(OS_ARCH), WINNT) - ifeq ($(OBJDIR), WIN32_D.OBJ) - NSPR_OBJDIR = WINNT4.0_DBG.OBJ - endif - ifeq ($(OBJDIR), WIN32_O.OBJ) - NSPR_OBJDIR = WINNT4.0_OPT.OBJ - endif -endif -NSPR_SHARED = /share/builds/components/nspr20/$(NSPR_VERSION)/$(NSPR_OBJDIR) -ifeq ($(OS_ARCH), WINNT) - NSPR_SHARED = nspr20/$(NSPR_VERSION)/$(NSPR_OBJDIR) -endif -NSPR_VERSIONFILE = $(NSPR_LOCAL)/Version -NSPR_CURVERSION := $(shell cat $(NSPR_VERSIONFILE)) - -get_nspr: - @echo "Grabbing NSPR component..." -ifeq ($(NSPR_VERSION), $(NSPR_CURVERSION)) - @echo "No need, NSPR is up to date in this tree (ver=$(NSPR_VERSION))." -else - mkdir -p $(NSPR_LOCAL) - mkdir -p $(NSPR_DIST) - ifneq ($(OS_ARCH), WINNT) - cp $(NSPR_SHARED)/*.jar $(NSPR_LOCAL) - else - sh $(MOZ_DEPTH)/../reltools/compftp.sh $(NSPR_SHARED) $(NSPR_LOCAL) *.jar - endif - unzip -o $(NSPR_LOCAL)/mdbinary.jar -d $(NSPR_DIST) - mkdir -p $(NSPR_DIST)/include - unzip -o $(NSPR_LOCAL)/mdheader.jar -d $(NSPR_DIST)/include - rm -rf $(NSPR_DIST)/META-INF - rm -rf $(NSPR_DIST)/include/META-INF - echo $(NSPR_VERSION) > $(NSPR_VERSIONFILE) -endif - -SHIP_DIST = $(MOZ_DEPTH)/dist/$(OBJDIR) -SHIP_DIR = $(SHIP_DIST)/SHIP - -SHIP_LIBS = libjs.$(SO_SUFFIX) libjs.a -ifdef JS_LIVECONNECT - SHIP_LIBS += libjsj.$(SO_SUFFIX) libjsj.a -endif -ifeq ($(OS_ARCH), WINNT) - SHIP_LIBS = js32.dll js32.lib - ifdef JS_LIVECONNECT - SHIP_LIBS += jsj.dll jsj.lib - endif -endif -SHIP_LIBS += $(LCJAR) -SHIP_LIBS := $(addprefix $(SHIP_DIST)/lib/, $(SHIP_LIBS)) - -SHIP_INCS = js*.h prmjtime.h resource.h *.msg *.tbl -ifdef JS_LIVECONNECT - SHIP_INCS += netscape*.h nsC*.h nsI*.h -endif -SHIP_INCS := $(addprefix $(SHIP_DIST)/include/, $(SHIP_INCS)) - -SHIP_BINS = js -ifdef JS_LIVECONNECT - SHIP_BINS += lcshell -endif -ifeq ($(OS_ARCH), WINNT) - SHIP_BINS := $(addsuffix .exe, $(SHIP_BINS)) -endif -SHIP_BINS := $(addprefix $(SHIP_DIST)/bin/, $(SHIP_BINS)) - -ifdef BUILD_OPT - JSREFJAR = jsref_opt.jar -else -ifdef BUILD_IDG - JSREFJAR = jsref_idg.jar -else - JSREFJAR = jsref_dbg.jar -endif -endif - -ship: - mkdir -p $(SHIP_DIR)/$(LIBDIR) - mkdir -p $(SHIP_DIR)/include - mkdir -p $(SHIP_DIR)/bin - cp $(SHIP_LIBS) $(SHIP_DIR)/$(LIBDIR) - cp $(SHIP_INCS) $(SHIP_DIR)/include - cp $(SHIP_BINS) $(SHIP_DIR)/bin - cd $(SHIP_DIR); \ - zip -r $(JSREFJAR) bin lib include -ifdef BUILD_SHIP - cp $(SHIP_DIR)/$(JSREFJAR) $(BUILD_SHIP) -endif - -CWD = $(shell pwd) -shipSource: $(SHIP_DIR)/jsref_src.lst .FORCE - mkdir -p $(SHIP_DIR) - cd $(MOZ_DEPTH)/.. ; \ - zip $(CWD)/$(SHIP_DIR)/jsref_src.jar -@ < $(CWD)/$(SHIP_DIR)/jsref_src.lst -ifdef BUILD_SHIP - cp $(SHIP_DIR)/jsref_src.jar $(BUILD_SHIP) -endif - -JSREFSRCDIRS := $(shell cat $(DEPTH)/SpiderMonkey.rsp) -$(SHIP_DIR)/jsref_src.lst: .FORCE - mkdir -p $(SHIP_DIR) - rm -f $@ - touch $@ - for d in $(JSREFSRCDIRS); do \ - cd $(MOZ_DEPTH)/..; \ - ls -1 -d $$d | grep -v CVS | grep -v \.OBJ >> $(CWD)/$@; \ - cd $(CWD); \ - done - -.FORCE: diff --git a/lib/javascript/jscpucfg.c b/lib/javascript/jscpucfg.c deleted file mode 100644 index e02f3361..00000000 --- a/lib/javascript/jscpucfg.c +++ /dev/null @@ -1,375 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Roland Mainz - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * Generate CPU-specific bit-size and similar #defines. - */ -#include -#include - -#ifdef CROSS_COMPILE -#include -#define INT64 PRInt64 -#else - -/************************************************************************/ - -/* Generate cpucfg.h */ - -#if defined(XP_WIN) || defined(XP_OS2) -#ifdef WIN32 -#if defined(__GNUC__) -#define INT64 long long -#else -#define INT64 _int64 -#endif /* __GNUC__ */ -#else -#define INT64 long -#endif -#else -#if defined(HPUX) || defined(__QNX__) || defined(_SCO_DS) || defined(UNIXWARE) -#define INT64 long -#else -#define INT64 long long -#endif -#endif - -#endif /* CROSS_COMPILE */ - -#ifdef __GNUC__ -#define NS_NEVER_INLINE __attribute__((noinline)) -#else -#define NS_NEVER_INLINE -#endif - -typedef void *prword; - -struct align_short { - char c; - short a; -}; -struct align_int { - char c; - int a; -}; -struct align_long { - char c; - long a; -}; -struct align_int64 { - char c; - INT64 a; -}; -struct align_fakelonglong { - char c; - struct { - long hi, lo; - } a; -}; -struct align_float { - char c; - float a; -}; -struct align_double { - char c; - double a; -}; -struct align_pointer { - char c; - void *a; -}; -struct align_prword { - char c; - prword a; -}; - -#define ALIGN_OF(type) \ - (((char*)&(((struct align_##type *)0)->a)) - ((char*)0)) - -unsigned int bpb; - -static int Log2(unsigned int n) -{ - int log2 = 0; - - if (n & (n-1)) - log2++; - if (n >> 16) - log2 += 16, n >>= 16; - if (n >> 8) - log2 += 8, n >>= 8; - if (n >> 4) - log2 += 4, n >>= 4; - if (n >> 2) - log2 += 2, n >>= 2; - if (n >> 1) - log2++; - return log2; -} - -/* - * Conceivably this could actually be used, but there is lots of code out - * there with ands and shifts in it that assumes a byte is exactly 8 bits, - * so forget about porting THIS code to all those non 8 bit byte machines. - */ -static void BitsPerByte(void) -{ - bpb = 8; -} - -static int NS_NEVER_INLINE StackGrowthDirection(int *dummy1addr) -{ - int dummy2; - - return (&dummy2 < dummy1addr) ? -1 : 1; -} - -int main(int argc, char **argv) -{ - int sizeof_char, sizeof_short, sizeof_int, sizeof_int64, sizeof_long, - sizeof_float, sizeof_double, sizeof_word, sizeof_dword; - int bits_per_int64_log2, align_of_short, align_of_int, align_of_long, - align_of_int64, align_of_float, align_of_double, align_of_pointer, - align_of_word; - int dummy1; - - BitsPerByte(); - - printf("#ifndef js_cpucfg___\n"); - printf("#define js_cpucfg___\n\n"); - - printf("/* AUTOMATICALLY GENERATED - DO NOT EDIT */\n\n"); - -#ifdef CROSS_COMPILE -#if defined(IS_LITTLE_ENDIAN) - printf("#define IS_LITTLE_ENDIAN 1\n"); - printf("#undef IS_BIG_ENDIAN\n\n"); -#elif defined(IS_BIG_ENDIAN) - printf("#undef IS_LITTLE_ENDIAN\n"); - printf("#define IS_BIG_ENDIAN 1\n\n"); -#else -#error "Endianess not defined." -#endif - - sizeof_char = PR_BYTES_PER_BYTE; - sizeof_short = PR_BYTES_PER_SHORT; - sizeof_int = PR_BYTES_PER_INT; - sizeof_int64 = PR_BYTES_PER_INT64; - sizeof_long = PR_BYTES_PER_LONG; - sizeof_float = PR_BYTES_PER_FLOAT; - sizeof_double = PR_BYTES_PER_DOUBLE; - sizeof_word = PR_BYTES_PER_WORD; - sizeof_dword = PR_BYTES_PER_DWORD; - - bits_per_int64_log2 = PR_BITS_PER_INT64_LOG2; - - align_of_short = PR_ALIGN_OF_SHORT; - align_of_int = PR_ALIGN_OF_INT; - align_of_long = PR_ALIGN_OF_LONG; - align_of_int64 = PR_ALIGN_OF_INT64; - align_of_float = PR_ALIGN_OF_FLOAT; - align_of_double = PR_ALIGN_OF_DOUBLE; - align_of_pointer = PR_ALIGN_OF_POINTER; - align_of_word = PR_ALIGN_OF_WORD; - -#else /* !CROSS_COMPILE */ - - /* - * We don't handle PDP-endian or similar orders: if a short is big-endian, - * so must int and long be big-endian for us to generate the IS_BIG_ENDIAN - * #define and the IS_LITTLE_ENDIAN #undef. - */ - { - int big_endian = 0, little_endian = 0, ntests = 0; - - if (sizeof(short) == 2) { - /* force |volatile| here to get rid of any compiler optimisations - * (var in register etc.) which may be appiled to |auto| vars - - * even those in |union|s... - * (|static| is used to get the same functionality for compilers - * which do not honor |volatile|...). - */ - volatile static union { - short i; - char c[2]; - } u; - - u.i = 0x0102; - big_endian += (u.c[0] == 0x01 && u.c[1] == 0x02); - little_endian += (u.c[0] == 0x02 && u.c[1] == 0x01); - ntests++; - } - - if (sizeof(int) == 4) { - /* force |volatile| here ... */ - volatile static union { - int i; - char c[4]; - } u; - - u.i = 0x01020304; - big_endian += (u.c[0] == 0x01 && u.c[1] == 0x02 && - u.c[2] == 0x03 && u.c[3] == 0x04); - little_endian += (u.c[0] == 0x04 && u.c[1] == 0x03 && - u.c[2] == 0x02 && u.c[3] == 0x01); - ntests++; - } - - if (sizeof(long) == 8) { - /* force |volatile| here ... */ - volatile static union { - long i; - char c[8]; - } u; - - /* - * Write this as portably as possible: avoid 0x0102030405060708L - * and <<= 32. - */ - u.i = 0x01020304; - u.i <<= 16, u.i <<= 16; - u.i |= 0x05060708; - big_endian += (u.c[0] == 0x01 && u.c[1] == 0x02 && - u.c[2] == 0x03 && u.c[3] == 0x04 && - u.c[4] == 0x05 && u.c[5] == 0x06 && - u.c[6] == 0x07 && u.c[7] == 0x08); - little_endian += (u.c[0] == 0x08 && u.c[1] == 0x07 && - u.c[2] == 0x06 && u.c[3] == 0x05 && - u.c[4] == 0x04 && u.c[5] == 0x03 && - u.c[6] == 0x02 && u.c[7] == 0x01); - ntests++; - } - - if (big_endian && big_endian == ntests) { - printf("#undef IS_LITTLE_ENDIAN\n"); - printf("#define IS_BIG_ENDIAN 1\n\n"); - } else if (little_endian && little_endian == ntests) { - printf("#define IS_LITTLE_ENDIAN 1\n"); - printf("#undef IS_BIG_ENDIAN\n\n"); - } else { - fprintf(stderr, "%s: unknown byte order" - "(big_endian=%d, little_endian=%d, ntests=%d)!\n", - argv[0], big_endian, little_endian, ntests); - return EXIT_FAILURE; - } - } - - sizeof_char = sizeof(char); - sizeof_short = sizeof(short); - sizeof_int = sizeof(int); - sizeof_int64 = 8; - sizeof_long = sizeof(long); - sizeof_float = sizeof(float); - sizeof_double = sizeof(double); - sizeof_word = sizeof(prword); - sizeof_dword = 8; - - bits_per_int64_log2 = 6; - - align_of_short = ALIGN_OF(short); - align_of_int = ALIGN_OF(int); - align_of_long = ALIGN_OF(long); - if (sizeof(INT64) < 8) { - /* this machine doesn't actually support int64's */ - align_of_int64 = ALIGN_OF(fakelonglong); - } else { - align_of_int64 = ALIGN_OF(int64); - } - align_of_float = ALIGN_OF(float); - align_of_double = ALIGN_OF(double); - align_of_pointer = ALIGN_OF(pointer); - align_of_word = ALIGN_OF(prword); - -#endif /* CROSS_COMPILE */ - - printf("#define JS_BYTES_PER_BYTE %dL\n", sizeof_char); - printf("#define JS_BYTES_PER_SHORT %dL\n", sizeof_short); - printf("#define JS_BYTES_PER_INT %dL\n", sizeof_int); - printf("#define JS_BYTES_PER_INT64 %dL\n", sizeof_int64); - printf("#define JS_BYTES_PER_LONG %dL\n", sizeof_long); - printf("#define JS_BYTES_PER_FLOAT %dL\n", sizeof_float); - printf("#define JS_BYTES_PER_DOUBLE %dL\n", sizeof_double); - printf("#define JS_BYTES_PER_WORD %dL\n", sizeof_word); - printf("#define JS_BYTES_PER_DWORD %dL\n", sizeof_dword); - printf("\n"); - - printf("#define JS_BITS_PER_BYTE %dL\n", bpb); - printf("#define JS_BITS_PER_SHORT %dL\n", bpb * sizeof_short); - printf("#define JS_BITS_PER_INT %dL\n", bpb * sizeof_int); - printf("#define JS_BITS_PER_INT64 %dL\n", bpb * sizeof_int64); - printf("#define JS_BITS_PER_LONG %dL\n", bpb * sizeof_long); - printf("#define JS_BITS_PER_FLOAT %dL\n", bpb * sizeof_float); - printf("#define JS_BITS_PER_DOUBLE %dL\n", bpb * sizeof_double); - printf("#define JS_BITS_PER_WORD %dL\n", bpb * sizeof_word); - printf("\n"); - - printf("#define JS_BITS_PER_BYTE_LOG2 %dL\n", Log2(bpb)); - printf("#define JS_BITS_PER_SHORT_LOG2 %dL\n", Log2(bpb * sizeof_short)); - printf("#define JS_BITS_PER_INT_LOG2 %dL\n", Log2(bpb * sizeof_int)); - printf("#define JS_BITS_PER_INT64_LOG2 %dL\n", bits_per_int64_log2); - printf("#define JS_BITS_PER_LONG_LOG2 %dL\n", Log2(bpb * sizeof_long)); - printf("#define JS_BITS_PER_FLOAT_LOG2 %dL\n", Log2(bpb * sizeof_float)); - printf("#define JS_BITS_PER_DOUBLE_LOG2 %dL\n", Log2(bpb * sizeof_double)); - printf("#define JS_BITS_PER_WORD_LOG2 %dL\n", Log2(bpb * sizeof_word)); - printf("\n"); - - printf("#define JS_ALIGN_OF_SHORT %dL\n", align_of_short); - printf("#define JS_ALIGN_OF_INT %dL\n", align_of_int); - printf("#define JS_ALIGN_OF_LONG %dL\n", align_of_long); - printf("#define JS_ALIGN_OF_INT64 %dL\n", align_of_int64); - printf("#define JS_ALIGN_OF_FLOAT %dL\n", align_of_float); - printf("#define JS_ALIGN_OF_DOUBLE %dL\n", align_of_double); - printf("#define JS_ALIGN_OF_POINTER %dL\n", align_of_pointer); - printf("#define JS_ALIGN_OF_WORD %dL\n", align_of_word); - printf("\n"); - - printf("#define JS_BYTES_PER_WORD_LOG2 %dL\n", Log2(sizeof_word)); - printf("#define JS_BYTES_PER_DWORD_LOG2 %dL\n", Log2(sizeof_dword)); - printf("#define JS_WORDS_PER_DWORD_LOG2 %dL\n", Log2(sizeof_dword/sizeof_word)); - printf("\n"); - - printf("#define JS_STACK_GROWTH_DIRECTION (%d)\n", StackGrowthDirection(&dummy1)); - printf("\n"); - - printf("#endif /* js_cpucfg___ */\n"); - - return EXIT_SUCCESS; -} - diff --git a/lib/javascript/jscpucfg.h b/lib/javascript/jscpucfg.h deleted file mode 100644 index 7b8b2add..00000000 --- a/lib/javascript/jscpucfg.h +++ /dev/null @@ -1,159 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef js_cpucfg___ -#define js_cpucfg___ - -#include "jsosdep.h" - -#if defined(XP_WIN) || defined(XP_OS2) || defined(WINCE) - -#ifdef __WATCOMC__ -#define HAVE_VA_LIST_AS_ARRAY -#endif - -#if defined(_WIN32) || defined(XP_OS2) || defined(WINCE) -#define IS_LITTLE_ENDIAN 1 -#undef IS_BIG_ENDIAN - -#define JS_BYTES_PER_BYTE 1L -#define JS_BYTES_PER_SHORT 2L -#define JS_BYTES_PER_INT 4L -#define JS_BYTES_PER_INT64 8L -#define JS_BYTES_PER_LONG 4L -#define JS_BYTES_PER_FLOAT 4L -#define JS_BYTES_PER_DOUBLE 8L -#define JS_BYTES_PER_WORD 4L -#define JS_BYTES_PER_DWORD 8L - -#define JS_BITS_PER_BYTE 8L -#define JS_BITS_PER_SHORT 16L -#define JS_BITS_PER_INT 32L -#define JS_BITS_PER_INT64 64L -#define JS_BITS_PER_LONG 32L -#define JS_BITS_PER_FLOAT 32L -#define JS_BITS_PER_DOUBLE 64L -#define JS_BITS_PER_WORD 32L - -#define JS_BITS_PER_BYTE_LOG2 3L -#define JS_BITS_PER_SHORT_LOG2 4L -#define JS_BITS_PER_INT_LOG2 5L -#define JS_BITS_PER_INT64_LOG2 6L -#define JS_BITS_PER_LONG_LOG2 5L -#define JS_BITS_PER_FLOAT_LOG2 5L -#define JS_BITS_PER_DOUBLE_LOG2 6L -#define JS_BITS_PER_WORD_LOG2 5L - -#define JS_ALIGN_OF_SHORT 2L -#define JS_ALIGN_OF_INT 4L -#define JS_ALIGN_OF_LONG 4L -#define JS_ALIGN_OF_INT64 8L -#define JS_ALIGN_OF_FLOAT 4L -#define JS_ALIGN_OF_DOUBLE 4L -#define JS_ALIGN_OF_POINTER 4L -#define JS_ALIGN_OF_WORD 4L - -#define JS_BYTES_PER_WORD_LOG2 2L -#define JS_BYTES_PER_DWORD_LOG2 3L -#define PR_WORDS_PER_DWORD_LOG2 1L -#endif /* _WIN32 || XP_OS2 || WINCE*/ - -#if defined(_WINDOWS) && !defined(_WIN32) /* WIN16 */ -#define IS_LITTLE_ENDIAN 1 -#undef IS_BIG_ENDIAN - -#define JS_BYTES_PER_BYTE 1L -#define JS_BYTES_PER_SHORT 2L -#define JS_BYTES_PER_INT 2L -#define JS_BYTES_PER_INT64 8L -#define JS_BYTES_PER_LONG 4L -#define JS_BYTES_PER_FLOAT 4L -#define JS_BYTES_PER_DOUBLE 8L -#define JS_BYTES_PER_WORD 4L -#define JS_BYTES_PER_DWORD 8L - -#define JS_BITS_PER_BYTE 8L -#define JS_BITS_PER_SHORT 16L -#define JS_BITS_PER_INT 16L -#define JS_BITS_PER_INT64 64L -#define JS_BITS_PER_LONG 32L -#define JS_BITS_PER_FLOAT 32L -#define JS_BITS_PER_DOUBLE 64L -#define JS_BITS_PER_WORD 32L - -#define JS_BITS_PER_BYTE_LOG2 3L -#define JS_BITS_PER_SHORT_LOG2 4L -#define JS_BITS_PER_INT_LOG2 4L -#define JS_BITS_PER_INT64_LOG2 6L -#define JS_BITS_PER_LONG_LOG2 5L -#define JS_BITS_PER_FLOAT_LOG2 5L -#define JS_BITS_PER_DOUBLE_LOG2 6L -#define JS_BITS_PER_WORD_LOG2 5L - -#define JS_ALIGN_OF_SHORT 2L -#define JS_ALIGN_OF_INT 2L -#define JS_ALIGN_OF_LONG 2L -#define JS_ALIGN_OF_INT64 2L -#define JS_ALIGN_OF_FLOAT 2L -#define JS_ALIGN_OF_DOUBLE 2L -#define JS_ALIGN_OF_POINTER 2L -#define JS_ALIGN_OF_WORD 2L - -#define JS_BYTES_PER_WORD_LOG2 2L -#define JS_BYTES_PER_DWORD_LOG2 3L -#define PR_WORDS_PER_DWORD_LOG2 1L -#endif /* defined(_WINDOWS) && !defined(_WIN32) */ - -#elif defined(XP_UNIX) || defined(XP_BEOS) - -#error "This file is supposed to be auto-generated on UNIX platforms, but the" -#error "static version for Mac and Windows platforms is being used." -#error "Something's probably wrong with paths/headers/dependencies/Makefiles." - -#else - -#error "Must define one of XP_BEOS, XP_OS2, XP_WIN, or XP_UNIX" - -#endif - -#ifndef JS_STACK_GROWTH_DIRECTION -#define JS_STACK_GROWTH_DIRECTION (-1) -#endif - -#endif /* js_cpucfg___ */ diff --git a/lib/javascript/jsdate.c b/lib/javascript/jsdate.c deleted file mode 100644 index a76502c3..00000000 --- a/lib/javascript/jsdate.c +++ /dev/null @@ -1,2386 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JS date methods. - */ - -/* - * "For example, OS/360 devotes 26 bytes of the permanently - * resident date-turnover routine to the proper handling of - * December 31 on leap years (when it is Day 366). That - * might have been left to the operator." - * - * Frederick Brooks, 'The Second-System Effect'. - */ - -#include "jsstddef.h" -#include -#include -#include -#include -#include -#include "jstypes.h" -#include "jsprf.h" -#include "prmjtime.h" -#include "jsutil.h" /* Added by JSIFY */ -#include "jsapi.h" -#include "jsconfig.h" -#include "jscntxt.h" -#include "jsdate.h" -#include "jsinterp.h" -#include "jsnum.h" -#include "jsobj.h" -#include "jsstr.h" - -/* - * The JS 'Date' object is patterned after the Java 'Date' object. - * Here is an script: - * - * today = new Date(); - * - * print(today.toLocaleString()); - * - * weekDay = today.getDay(); - * - * - * These Java (and ECMA-262) methods are supported: - * - * UTC - * getDate (getUTCDate) - * getDay (getUTCDay) - * getHours (getUTCHours) - * getMinutes (getUTCMinutes) - * getMonth (getUTCMonth) - * getSeconds (getUTCSeconds) - * getMilliseconds (getUTCMilliseconds) - * getTime - * getTimezoneOffset - * getYear - * getFullYear (getUTCFullYear) - * parse - * setDate (setUTCDate) - * setHours (setUTCHours) - * setMinutes (setUTCMinutes) - * setMonth (setUTCMonth) - * setSeconds (setUTCSeconds) - * setMilliseconds (setUTCMilliseconds) - * setTime - * setYear (setFullYear, setUTCFullYear) - * toGMTString (toUTCString) - * toLocaleString - * toString - * - * - * These Java methods are not supported - * - * setDay - * before - * after - * equals - * hashCode - */ - -/* - * 11/97 - jsdate.c has been rewritten to conform to the ECMA-262 language - * definition and reduce dependence on NSPR. NSPR is used to get the current - * time in milliseconds, the time zone offset, and the daylight savings time - * offset for a given time. NSPR is also used for Date.toLocaleString(), for - * locale-specific formatting, and to get a string representing the timezone. - * (Which turns out to be platform-dependent.) - * - * To do: - * (I did some performance tests by timing how long it took to run what - * I had of the js ECMA conformance tests.) - * - * - look at saving results across multiple calls to supporting - * functions; the toString functions compute some of the same values - * multiple times. Although - I took a quick stab at this, and I lost - * rather than gained. (Fractionally.) Hard to tell what compilers/processors - * are doing these days. - * - * - look at tweaking function return types to return double instead - * of int; this seems to make things run slightly faster sometimes. - * (though it could be architecture-dependent.) It'd be good to see - * how this does on win32. (Tried it on irix.) Types could use a - * general going-over. - */ - -/* - * Supporting functions - ECMA 15.9.1.* - */ - -#define HalfTimeDomain 8.64e15 -#define HoursPerDay 24.0 -#define MinutesPerDay (HoursPerDay * MinutesPerHour) -#define MinutesPerHour 60.0 -#define SecondsPerDay (MinutesPerDay * SecondsPerMinute) -#define SecondsPerHour (MinutesPerHour * SecondsPerMinute) -#define SecondsPerMinute 60.0 - -#if defined(XP_WIN) || defined(XP_OS2) -/* Work around msvc double optimization bug by making these runtime values; if - * they're available at compile time, msvc optimizes division by them by - * computing the reciprocal and multiplying instead of dividing - this loses - * when the reciprocal isn't representable in a double. - */ -static jsdouble msPerSecond = 1000.0; -static jsdouble msPerDay = SecondsPerDay * 1000.0; -static jsdouble msPerHour = SecondsPerHour * 1000.0; -static jsdouble msPerMinute = SecondsPerMinute * 1000.0; -#else -#define msPerDay (SecondsPerDay * msPerSecond) -#define msPerHour (SecondsPerHour * msPerSecond) -#define msPerMinute (SecondsPerMinute * msPerSecond) -#define msPerSecond 1000.0 -#endif - -#define Day(t) floor((t) / msPerDay) - -static jsdouble -TimeWithinDay(jsdouble t) -{ - jsdouble result; - result = fmod(t, msPerDay); - if (result < 0) - result += msPerDay; - return result; -} - -#define DaysInYear(y) ((y) % 4 == 0 && ((y) % 100 || ((y) % 400 == 0)) \ - ? 366 : 365) - -/* math here has to be f.p, because we need - * floor((1968 - 1969) / 4) == -1 - */ -#define DayFromYear(y) (365 * ((y)-1970) + floor(((y)-1969)/4.0) \ - - floor(((y)-1901)/100.0) + floor(((y)-1601)/400.0)) -#define TimeFromYear(y) (DayFromYear(y) * msPerDay) - -static jsint -YearFromTime(jsdouble t) -{ - jsint y = (jsint) floor(t /(msPerDay*365.2425)) + 1970; - jsdouble t2 = (jsdouble) TimeFromYear(y); - - if (t2 > t) { - y--; - } else { - if (t2 + msPerDay * DaysInYear(y) <= t) - y++; - } - return y; -} - -#define InLeapYear(t) (JSBool) (DaysInYear(YearFromTime(t)) == 366) - -#define DayWithinYear(t, year) ((intN) (Day(t) - DayFromYear(year))) - -/* - * The following array contains the day of year for the first day of - * each month, where index 0 is January, and day 0 is January 1. - */ -static jsdouble firstDayOfMonth[2][12] = { - {0.0, 31.0, 59.0, 90.0, 120.0, 151.0, 181.0, 212.0, 243.0, 273.0, 304.0, 334.0}, - {0.0, 31.0, 60.0, 91.0, 121.0, 152.0, 182.0, 213.0, 244.0, 274.0, 305.0, 335.0} -}; - -#define DayFromMonth(m, leap) firstDayOfMonth[leap][(intN)m]; - -static intN -MonthFromTime(jsdouble t) -{ - intN d, step; - jsint year = YearFromTime(t); - d = DayWithinYear(t, year); - - if (d < (step = 31)) - return 0; - step += (InLeapYear(t) ? 29 : 28); - if (d < step) - return 1; - if (d < (step += 31)) - return 2; - if (d < (step += 30)) - return 3; - if (d < (step += 31)) - return 4; - if (d < (step += 30)) - return 5; - if (d < (step += 31)) - return 6; - if (d < (step += 31)) - return 7; - if (d < (step += 30)) - return 8; - if (d < (step += 31)) - return 9; - if (d < (step += 30)) - return 10; - return 11; -} - -static intN -DateFromTime(jsdouble t) -{ - intN d, step, next; - jsint year = YearFromTime(t); - d = DayWithinYear(t, year); - - if (d <= (next = 30)) - return d + 1; - step = next; - next += (InLeapYear(t) ? 29 : 28); - if (d <= next) - return d - step; - step = next; - if (d <= (next += 31)) - return d - step; - step = next; - if (d <= (next += 30)) - return d - step; - step = next; - if (d <= (next += 31)) - return d - step; - step = next; - if (d <= (next += 30)) - return d - step; - step = next; - if (d <= (next += 31)) - return d - step; - step = next; - if (d <= (next += 31)) - return d - step; - step = next; - if (d <= (next += 30)) - return d - step; - step = next; - if (d <= (next += 31)) - return d - step; - step = next; - if (d <= (next += 30)) - return d - step; - step = next; - return d - step; -} - -static intN -WeekDay(jsdouble t) -{ - jsint result; - result = (jsint) Day(t) + 4; - result = result % 7; - if (result < 0) - result += 7; - return (intN) result; -} - -#define MakeTime(hour, min, sec, ms) \ -((((hour) * MinutesPerHour + (min)) * SecondsPerMinute + (sec)) * msPerSecond + (ms)) - -static jsdouble -MakeDay(jsdouble year, jsdouble month, jsdouble date) -{ - JSBool leap; - jsdouble yearday; - jsdouble monthday; - - year += floor(month / 12); - - month = fmod(month, 12.0); - if (month < 0) - month += 12; - - leap = (DaysInYear((jsint) year) == 366); - - yearday = floor(TimeFromYear(year) / msPerDay); - monthday = DayFromMonth(month, leap); - - return yearday + monthday + date - 1; -} - -#define MakeDate(day, time) ((day) * msPerDay + (time)) - -/* - * Years and leap years on which Jan 1 is a Sunday, Monday, etc. - * - * yearStartingWith[0][i] is an example non-leap year where - * Jan 1 appears on Sunday (i == 0), Monday (i == 1), etc. - * - * yearStartingWith[1][i] is an example leap year where - * Jan 1 appears on Sunday (i == 0), Monday (i == 1), etc. - */ -static jsint yearStartingWith[2][7] = { - {1978, 1973, 1974, 1975, 1981, 1971, 1977}, - {1984, 1996, 1980, 1992, 1976, 1988, 1972} -}; - -/* - * Find a year for which any given date will fall on the same weekday. - * - * This function should be used with caution when used other than - * for determining DST; it hasn't been proven not to produce an - * incorrect year for times near year boundaries. - */ -static jsint -EquivalentYearForDST(jsint year) { - jsint day; - JSBool isLeapYear; - - day = (jsint) DayFromYear(year) + 4; - day = day % 7; - if (day < 0) - day += 7; - - isLeapYear = (DaysInYear(year) == 366); - - return yearStartingWith[isLeapYear][day]; -} - -/* LocalTZA gets set by js_InitDateClass() */ -static jsdouble LocalTZA; - -static jsdouble -DaylightSavingTA(jsdouble t) -{ - volatile int64 PR_t; - int64 ms2us; - int64 offset; - jsdouble result; - - /* abort if NaN */ - if (JSDOUBLE_IS_NaN(t)) - return t; - - /* - * If earlier than 1970 or after 2038, potentially beyond the ken of - * many OSes, map it to an equivalent year before asking. - */ - if (t < 0.0 || t > 2145916800000.0) { - jsint year; - jsdouble day; - - year = EquivalentYearForDST(YearFromTime(t)); - day = MakeDay(year, MonthFromTime(t), DateFromTime(t)); - t = MakeDate(day, TimeWithinDay(t)); - } - - /* put our t in an LL, and map it to usec for prtime */ - JSLL_D2L(PR_t, t); - JSLL_I2L(ms2us, PRMJ_USEC_PER_MSEC); - JSLL_MUL(PR_t, PR_t, ms2us); - - offset = PRMJ_DSTOffset(PR_t); - - JSLL_DIV(offset, offset, ms2us); - JSLL_L2D(result, offset); - return result; -} - - -#define AdjustTime(t) fmod(LocalTZA + DaylightSavingTA(t), msPerDay) - -#define LocalTime(t) ((t) + AdjustTime(t)) - -static jsdouble -UTC(jsdouble t) -{ - return t - AdjustTime(t - LocalTZA); -} - -static intN -HourFromTime(jsdouble t) -{ - intN result = (intN) fmod(floor(t/msPerHour), HoursPerDay); - if (result < 0) - result += (intN)HoursPerDay; - return result; -} - -static intN -MinFromTime(jsdouble t) -{ - intN result = (intN) fmod(floor(t / msPerMinute), MinutesPerHour); - if (result < 0) - result += (intN)MinutesPerHour; - return result; -} - -static intN -SecFromTime(jsdouble t) -{ - intN result = (intN) fmod(floor(t / msPerSecond), SecondsPerMinute); - if (result < 0) - result += (intN)SecondsPerMinute; - return result; -} - -static intN -msFromTime(jsdouble t) -{ - intN result = (intN) fmod(t, msPerSecond); - if (result < 0) - result += (intN)msPerSecond; - return result; -} - -#define TIMECLIP(d) ((JSDOUBLE_IS_FINITE(d) \ - && !((d < 0 ? -d : d) > HalfTimeDomain)) \ - ? js_DoubleToInteger(d + (+0.)) : *cx->runtime->jsNaN) - -/** - * end of ECMA 'support' functions - */ - -/* - * Other Support routines and definitions - */ - -static JSClass date_class = { - js_Date_str, - JSCLASS_HAS_PRIVATE, - JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, - JSCLASS_NO_OPTIONAL_MEMBERS -}; - -/* for use by date_parse */ - -static const char* wtb[] = { - "am", "pm", - "monday", "tuesday", "wednesday", "thursday", "friday", - "saturday", "sunday", - "january", "february", "march", "april", "may", "june", - "july", "august", "september", "october", "november", "december", - "gmt", "ut", "utc", - "est", "edt", - "cst", "cdt", - "mst", "mdt", - "pst", "pdt" - /* time zone table needs to be expanded */ -}; - -static int ttb[] = { - -1, -2, 0, 0, 0, 0, 0, 0, 0, /* AM/PM */ - 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 10000 + 0, 10000 + 0, 10000 + 0, /* GMT/UT/UTC */ - 10000 + 5 * 60, 10000 + 4 * 60, /* EST/EDT */ - 10000 + 6 * 60, 10000 + 5 * 60, /* CST/CDT */ - 10000 + 7 * 60, 10000 + 6 * 60, /* MST/MDT */ - 10000 + 8 * 60, 10000 + 7 * 60 /* PST/PDT */ -}; - -/* helper for date_parse */ -static JSBool -date_regionMatches(const char* s1, int s1off, const jschar* s2, int s2off, - int count, int ignoreCase) -{ - JSBool result = JS_FALSE; - /* return true if matches, otherwise, false */ - - while (count > 0 && s1[s1off] && s2[s2off]) { - if (ignoreCase) { - if (JS_TOLOWER((jschar)s1[s1off]) != JS_TOLOWER(s2[s2off])) { - break; - } - } else { - if ((jschar)s1[s1off] != s2[s2off]) { - break; - } - } - s1off++; - s2off++; - count--; - } - - if (count == 0) { - result = JS_TRUE; - } - - return result; -} - -/* find UTC time from given date... no 1900 correction! */ -static jsdouble -date_msecFromDate(jsdouble year, jsdouble mon, jsdouble mday, jsdouble hour, - jsdouble min, jsdouble sec, jsdouble msec) -{ - jsdouble day; - jsdouble msec_time; - jsdouble result; - - day = MakeDay(year, mon, mday); - msec_time = MakeTime(hour, min, sec, msec); - result = MakeDate(day, msec_time); - return result; -} - -/* - * See ECMA 15.9.4.[3-10]; - */ -/* XXX this function must be above date_parseString to avoid a - horrid bug in the Win16 1.52 compiler */ -#define MAXARGS 7 -static JSBool -date_UTC(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsdouble array[MAXARGS]; - uintN loop; - jsdouble d; - - for (loop = 0; loop < MAXARGS; loop++) { - if (loop < argc) { - if (!js_ValueToNumber(cx, argv[loop], &d)) - return JS_FALSE; - /* return NaN if any arg is NaN */ - if (!JSDOUBLE_IS_FINITE(d)) { - return js_NewNumberValue(cx, d, rval); - } - array[loop] = floor(d); - } else { - array[loop] = 0; - } - } - - /* adjust 2-digit years into the 20th century */ - if (array[0] >= 0 && array[0] <= 99) - array[0] += 1900; - - /* if we got a 0 for 'date' (which is out of range) - * pretend it's a 1. (So Date.UTC(1972, 5) works) */ - if (array[2] < 1) - array[2] = 1; - - d = date_msecFromDate(array[0], array[1], array[2], - array[3], array[4], array[5], array[6]); - d = TIMECLIP(d); - - return js_NewNumberValue(cx, d, rval); -} - -static JSBool -date_parseString(JSString *str, jsdouble *result) -{ - jsdouble msec; - - const jschar *s = JSSTRING_CHARS(str); - size_t limit = JSSTRING_LENGTH(str); - size_t i = 0; - int year = -1; - int mon = -1; - int mday = -1; - int hour = -1; - int min = -1; - int sec = -1; - int c = -1; - int n = -1; - jsdouble tzoffset = -1; /* was an int, overflowed on win16!!! */ - int prevc = 0; - JSBool seenplusminus = JS_FALSE; - int temp; - JSBool seenmonthname = JS_FALSE; - - if (limit == 0) - goto syntax; - while (i < limit) { - c = s[i]; - i++; - if (c <= ' ' || c == ',' || c == '-') { - if (c == '-' && '0' <= s[i] && s[i] <= '9') { - prevc = c; - } - continue; - } - if (c == '(') { /* comments) */ - int depth = 1; - while (i < limit) { - c = s[i]; - i++; - if (c == '(') depth++; - else if (c == ')') - if (--depth <= 0) - break; - } - continue; - } - if ('0' <= c && c <= '9') { - n = c - '0'; - while (i < limit && '0' <= (c = s[i]) && c <= '9') { - n = n * 10 + c - '0'; - i++; - } - - /* allow TZA before the year, so - * 'Wed Nov 05 21:49:11 GMT-0800 1997' - * works */ - - /* uses of seenplusminus allow : in TZA, so Java - * no-timezone style of GMT+4:30 works - */ - - if ((prevc == '+' || prevc == '-')/* && year>=0 */) { - /* make ':' case below change tzoffset */ - seenplusminus = JS_TRUE; - - /* offset */ - if (n < 24) - n = n * 60; /* EG. "GMT-3" */ - else - n = n % 100 + n / 100 * 60; /* eg "GMT-0430" */ - if (prevc == '+') /* plus means east of GMT */ - n = -n; - if (tzoffset != 0 && tzoffset != -1) - goto syntax; - tzoffset = n; - } else if (prevc == '/' && mon >= 0 && mday >= 0 && year < 0) { - if (c <= ' ' || c == ',' || c == '/' || i >= limit) - year = n; - else - goto syntax; - } else if (c == ':') { - if (hour < 0) - hour = /*byte*/ n; - else if (min < 0) - min = /*byte*/ n; - else - goto syntax; - } else if (c == '/') { - /* until it is determined that mon is the actual - month, keep it as 1-based rather than 0-based */ - if (mon < 0) - mon = /*byte*/ n; - else if (mday < 0) - mday = /*byte*/ n; - else - goto syntax; - } else if (i < limit && c != ',' && c > ' ' && c != '-' && c != '(') { - goto syntax; - } else if (seenplusminus && n < 60) { /* handle GMT-3:30 */ - if (tzoffset < 0) - tzoffset -= n; - else - tzoffset += n; - } else if (hour >= 0 && min < 0) { - min = /*byte*/ n; - } else if (prevc == ':' && min >= 0 && sec < 0) { - sec = /*byte*/ n; - } else if (mon < 0) { - mon = /*byte*/n; - } else if (mon >= 0 && mday < 0) { - mday = /*byte*/ n; - } else if (mon >= 0 && mday >= 0 && year < 0) { - year = n; - } else { - goto syntax; - } - prevc = 0; - } else if (c == '/' || c == ':' || c == '+' || c == '-') { - prevc = c; - } else { - size_t st = i - 1; - int k; - while (i < limit) { - c = s[i]; - if (!(('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'))) - break; - i++; - } - if (i <= st + 1) - goto syntax; - for (k = (sizeof(wtb)/sizeof(char*)); --k >= 0;) - if (date_regionMatches(wtb[k], 0, s, st, i-st, 1)) { - int action = ttb[k]; - if (action != 0) { - if (action < 0) { - /* - * AM/PM. Count 12:30 AM as 00:30, 12:30 PM as - * 12:30, instead of blindly adding 12 if PM. - */ - JS_ASSERT(action == -1 || action == -2); - if (hour > 12 || hour < 0) { - goto syntax; - } else { - if (action == -1 && hour == 12) { /* am */ - hour = 0; - } else if (action == -2 && hour != 12) { /* pm */ - hour += 12; - } - } - } else if (action <= 13) { /* month! */ - /* Adjust mon to be 1-based until the final values - for mon, mday and year are adjusted below */ - if (seenmonthname) { - goto syntax; - } - seenmonthname = JS_TRUE; - temp = /*byte*/ (action - 2) + 1; - - if (mon < 0) { - mon = temp; - } else if (mday < 0) { - mday = mon; - mon = temp; - } else if (year < 0) { - year = mon; - mon = temp; - } else { - goto syntax; - } - } else { - tzoffset = action - 10000; - } - } - break; - } - if (k < 0) - goto syntax; - prevc = 0; - } - } - if (year < 0 || mon < 0 || mday < 0) - goto syntax; - /* - Case 1. The input string contains an English month name. - The form of the string can be month f l, or f month l, or - f l month which each evaluate to the same date. - If f and l are both greater than or equal to 70, or - both less than 70, the date is invalid. - The year is taken to be the greater of the values f, l. - If the year is greater than or equal to 70 and less than 100, - it is considered to be the number of years after 1900. - Case 2. The input string is of the form "f/m/l" where f, m and l are - integers, e.g. 7/16/45. - Adjust the mon, mday and year values to achieve 100% MSIE - compatibility. - a. If 0 <= f < 70, f/m/l is interpreted as month/day/year. - i. If year < 100, it is the number of years after 1900 - ii. If year >= 100, it is the number of years after 0. - b. If 70 <= f < 100 - i. If m < 70, f/m/l is interpreted as - year/month/day where year is the number of years after - 1900. - ii. If m >= 70, the date is invalid. - c. If f >= 100 - i. If m < 70, f/m/l is interpreted as - year/month/day where year is the number of years after 0. - ii. If m >= 70, the date is invalid. - */ - if (seenmonthname) { - if ((mday >= 70 && year >= 70) || (mday < 70 && year < 70)) { - goto syntax; - } - if (mday > year) { - temp = year; - year = mday; - mday = temp; - } - if (year >= 70 && year < 100) { - year += 1900; - } - } else if (mon < 70) { /* (a) month/day/year */ - if (year < 100) { - year += 1900; - } - } else if (mon < 100) { /* (b) year/month/day */ - if (mday < 70) { - temp = year; - year = mon + 1900; - mon = mday; - mday = temp; - } else { - goto syntax; - } - } else { /* (c) year/month/day */ - if (mday < 70) { - temp = year; - year = mon; - mon = mday; - mday = temp; - } else { - goto syntax; - } - } - mon -= 1; /* convert month to 0-based */ - if (sec < 0) - sec = 0; - if (min < 0) - min = 0; - if (hour < 0) - hour = 0; - if (tzoffset == -1) { /* no time zone specified, have to use local */ - jsdouble msec_time; - msec_time = date_msecFromDate(year, mon, mday, hour, min, sec, 0); - - *result = UTC(msec_time); - return JS_TRUE; - } - - msec = date_msecFromDate(year, mon, mday, hour, min, sec, 0); - msec += tzoffset * msPerMinute; - *result = msec; - return JS_TRUE; - -syntax: - /* syntax error */ - *result = 0; - return JS_FALSE; -} - -static JSBool -date_parse(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSString *str; - jsdouble result; - - str = js_ValueToString(cx, argv[0]); - if (!str) - return JS_FALSE; - if (!date_parseString(str, &result)) { - *rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN); - return JS_TRUE; - } - - result = TIMECLIP(result); - return js_NewNumberValue(cx, result, rval); -} - -static JSBool -date_now(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - int64 us, ms, us2ms; - jsdouble msec_time; - - us = PRMJ_Now(); - JSLL_UI2L(us2ms, PRMJ_USEC_PER_MSEC); - JSLL_DIV(ms, us, us2ms); - JSLL_L2D(msec_time, ms); - - return js_NewDoubleValue(cx, msec_time, rval); -} - -/* - * Check that obj is an object of class Date, and get the date value. - * Return NULL on failure. - */ -static jsdouble * -date_getProlog(JSContext *cx, JSObject *obj, jsval *argv) -{ - if (!JS_InstanceOf(cx, obj, &date_class, argv)) - return NULL; - return JSVAL_TO_DOUBLE(OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE)); -} - -/* - * See ECMA 15.9.5.4 thru 15.9.5.23 - */ -static JSBool -date_getTime(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsdouble *date = date_getProlog(cx, obj, argv); - if (!date) - return JS_FALSE; - - return js_NewNumberValue(cx, *date, rval); -} - -static JSBool -date_getYear(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsdouble *date; - jsdouble result; - JSVersion version; - - date = date_getProlog(cx, obj, argv); - if (!date) - return JS_FALSE; - - result = *date; - if (!JSDOUBLE_IS_FINITE(result)) - return js_NewNumberValue(cx, result, rval); - - result = YearFromTime(LocalTime(result)); - - /* - * During the great date rewrite of 1.3, we tried to track the evolving ECMA - * standard, which then had a definition of getYear which always subtracted - * 1900. Which we implemented, not realizing that it was incompatible with - * the old behavior... now, rather than thrash the behavior yet again, - * we've decided to leave it with the - 1900 behavior and point people to - * the getFullYear method. But we try to protect existing scripts that - * have specified a version... - */ - version = cx->version & JSVERSION_MASK; - if (version == JSVERSION_1_0 || - version == JSVERSION_1_1 || - version == JSVERSION_1_2) - { - if (result >= 1900 && result < 2000) - result -= 1900; - } else { - result -= 1900; - } - return js_NewNumberValue(cx, result, rval); -} - -static JSBool -date_getFullYear(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jsdouble result; - jsdouble *date = date_getProlog(cx, obj, argv); - if (!date) - return JS_FALSE; - result = *date; - - if (!JSDOUBLE_IS_FINITE(result)) - return js_NewNumberValue(cx, result, rval); - - result = YearFromTime(LocalTime(result)); - return js_NewNumberValue(cx, result, rval); -} - -static JSBool -date_getUTCFullYear(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jsdouble result; - jsdouble *date = date_getProlog(cx, obj, argv); - if (!date) - return JS_FALSE; - result = *date; - - if (!JSDOUBLE_IS_FINITE(result)) - return js_NewNumberValue(cx, result, rval); - - result = YearFromTime(result); - return js_NewNumberValue(cx, result, rval); -} - -static JSBool -date_getMonth(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jsdouble result; - jsdouble *date = date_getProlog(cx, obj, argv); - if (!date) - return JS_FALSE; - result = *date; - - if (!JSDOUBLE_IS_FINITE(result)) - return js_NewNumberValue(cx, result, rval); - - result = MonthFromTime(LocalTime(result)); - return js_NewNumberValue(cx, result, rval); -} - -static JSBool -date_getUTCMonth(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jsdouble result; - jsdouble *date = date_getProlog(cx, obj, argv); - if (!date) - return JS_FALSE; - result = *date; - - if (!JSDOUBLE_IS_FINITE(result)) - return js_NewNumberValue(cx, result, rval); - - result = MonthFromTime(result); - return js_NewNumberValue(cx, result, rval); -} - -static JSBool -date_getDate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsdouble result; - jsdouble *date = date_getProlog(cx, obj, argv); - if (!date) - return JS_FALSE; - result = *date; - - if (!JSDOUBLE_IS_FINITE(result)) - return js_NewNumberValue(cx, result, rval); - - result = LocalTime(result); - result = DateFromTime(result); - return js_NewNumberValue(cx, result, rval); -} - -static JSBool -date_getUTCDate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jsdouble result; - jsdouble *date = date_getProlog(cx, obj, argv); - if (!date) - return JS_FALSE; - result = *date; - - if (!JSDOUBLE_IS_FINITE(result)) - return js_NewNumberValue(cx, result, rval); - - result = DateFromTime(result); - return js_NewNumberValue(cx, result, rval); -} - -static JSBool -date_getDay(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsdouble result; - jsdouble *date = date_getProlog(cx, obj, argv); - if (!date) - return JS_FALSE; - result = *date; - - if (!JSDOUBLE_IS_FINITE(result)) - return js_NewNumberValue(cx, result, rval); - - result = LocalTime(result); - result = WeekDay(result); - return js_NewNumberValue(cx, result, rval); -} - -static JSBool -date_getUTCDay(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jsdouble result; - jsdouble *date = date_getProlog(cx, obj, argv); - if (!date) - return JS_FALSE; - result = *date; - - if (!JSDOUBLE_IS_FINITE(result)) - return js_NewNumberValue(cx, result, rval); - - result = WeekDay(result); - return js_NewNumberValue(cx, result, rval); -} - -static JSBool -date_getHours(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jsdouble result; - jsdouble *date = date_getProlog(cx, obj, argv); - if (!date) - return JS_FALSE; - result = *date; - - if (!JSDOUBLE_IS_FINITE(result)) - return js_NewNumberValue(cx, result, rval); - - result = HourFromTime(LocalTime(result)); - return js_NewNumberValue(cx, result, rval); -} - -static JSBool -date_getUTCHours(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jsdouble result; - jsdouble *date = date_getProlog(cx, obj, argv); - if (!date) - return JS_FALSE; - result = *date; - - if (!JSDOUBLE_IS_FINITE(result)) - return js_NewNumberValue(cx, result, rval); - - result = HourFromTime(result); - return js_NewNumberValue(cx, result, rval); -} - -static JSBool -date_getMinutes(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jsdouble result; - jsdouble *date = date_getProlog(cx, obj, argv); - if (!date) - return JS_FALSE; - result = *date; - - if (!JSDOUBLE_IS_FINITE(result)) - return js_NewNumberValue(cx, result, rval); - - result = MinFromTime(LocalTime(result)); - return js_NewNumberValue(cx, result, rval); -} - -static JSBool -date_getUTCMinutes(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jsdouble result; - jsdouble *date = date_getProlog(cx, obj, argv); - if (!date) - return JS_FALSE; - result = *date; - - if (!JSDOUBLE_IS_FINITE(result)) - return js_NewNumberValue(cx, result, rval); - - result = MinFromTime(result); - return js_NewNumberValue(cx, result, rval); -} - -/* Date.getSeconds is mapped to getUTCSeconds */ - -static JSBool -date_getUTCSeconds(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jsdouble result; - jsdouble *date = date_getProlog(cx, obj, argv); - if (!date) - return JS_FALSE; - result = *date; - - if (!JSDOUBLE_IS_FINITE(result)) - return js_NewNumberValue(cx, result, rval); - - result = SecFromTime(result); - return js_NewNumberValue(cx, result, rval); -} - -/* Date.getMilliseconds is mapped to getUTCMilliseconds */ - -static JSBool -date_getUTCMilliseconds(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jsdouble result; - jsdouble *date = date_getProlog(cx, obj, argv); - if (!date) - return JS_FALSE; - result = *date; - - if (!JSDOUBLE_IS_FINITE(result)) - return js_NewNumberValue(cx, result, rval); - - result = msFromTime(result); - return js_NewNumberValue(cx, result, rval); -} - -static JSBool -date_getTimezoneOffset(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jsdouble result; - jsdouble *date = date_getProlog(cx, obj, argv); - if (!date) - return JS_FALSE; - result = *date; - - /* - * Return the time zone offset in minutes for the current locale - * that is appropriate for this time. This value would be a - * constant except for daylight savings time. - */ - result = (result - LocalTime(result)) / msPerMinute; - return js_NewNumberValue(cx, result, rval); -} - -static JSBool -date_setTime(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsdouble result; - jsdouble *date = date_getProlog(cx, obj, argv); - if (!date) - return JS_FALSE; - - if (!js_ValueToNumber(cx, argv[0], &result)) - return JS_FALSE; - - result = TIMECLIP(result); - - *date = result; - return js_NewNumberValue(cx, result, rval); -} - -static JSBool -date_makeTime(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - uintN maxargs, JSBool local, jsval *rval) -{ - uintN i; - jsdouble args[4], *argp, *stop; - jsdouble hour, min, sec, msec; - jsdouble lorutime; /* Local or UTC version of *date */ - - jsdouble msec_time; - jsdouble result; - - jsdouble *date = date_getProlog(cx, obj, argv); - if (!date) - return JS_FALSE; - - result = *date; - - /* just return NaN if the date is already NaN */ - if (!JSDOUBLE_IS_FINITE(result)) - return js_NewNumberValue(cx, result, rval); - - /* Satisfy the ECMA rule that if a function is called with - * fewer arguments than the specified formal arguments, the - * remaining arguments are set to undefined. Seems like all - * the Date.setWhatever functions in ECMA are only varargs - * beyond the first argument; this should be set to undefined - * if it's not given. This means that "d = new Date(); - * d.setMilliseconds()" returns NaN. Blech. - */ - if (argc == 0) - argc = 1; /* should be safe, because length of all setters is 1 */ - else if (argc > maxargs) - argc = maxargs; /* clamp argc */ - - for (i = 0; i < argc; i++) { - if (!js_ValueToNumber(cx, argv[i], &args[i])) - return JS_FALSE; - if (!JSDOUBLE_IS_FINITE(args[i])) { - *date = *cx->runtime->jsNaN; - return js_NewNumberValue(cx, *date, rval); - } - args[i] = js_DoubleToInteger(args[i]); - } - - if (local) - lorutime = LocalTime(result); - else - lorutime = result; - - argp = args; - stop = argp + argc; - if (maxargs >= 4 && argp < stop) - hour = *argp++; - else - hour = HourFromTime(lorutime); - - if (maxargs >= 3 && argp < stop) - min = *argp++; - else - min = MinFromTime(lorutime); - - if (maxargs >= 2 && argp < stop) - sec = *argp++; - else - sec = SecFromTime(lorutime); - - if (maxargs >= 1 && argp < stop) - msec = *argp; - else - msec = msFromTime(lorutime); - - msec_time = MakeTime(hour, min, sec, msec); - result = MakeDate(Day(lorutime), msec_time); - -/* fprintf(stderr, "%f\n", result); */ - - if (local) - result = UTC(result); - -/* fprintf(stderr, "%f\n", result); */ - - *date = TIMECLIP(result); - return js_NewNumberValue(cx, *date, rval); -} - -static JSBool -date_setMilliseconds(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval) -{ - return date_makeTime(cx, obj, argc, argv, 1, JS_TRUE, rval); -} - -static JSBool -date_setUTCMilliseconds(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval) -{ - return date_makeTime(cx, obj, argc, argv, 1, JS_FALSE, rval); -} - -static JSBool -date_setSeconds(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval) -{ - return date_makeTime(cx, obj, argc, argv, 2, JS_TRUE, rval); -} - -static JSBool -date_setUTCSeconds(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval) -{ - return date_makeTime(cx, obj, argc, argv, 2, JS_FALSE, rval); -} - -static JSBool -date_setMinutes(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval) -{ - return date_makeTime(cx, obj, argc, argv, 3, JS_TRUE, rval); -} - -static JSBool -date_setUTCMinutes(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval) -{ - return date_makeTime(cx, obj, argc, argv, 3, JS_FALSE, rval); -} - -static JSBool -date_setHours(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval) -{ - return date_makeTime(cx, obj, argc, argv, 4, JS_TRUE, rval); -} - -static JSBool -date_setUTCHours(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval) -{ - return date_makeTime(cx, obj, argc, argv, 4, JS_FALSE, rval); -} - -static JSBool -date_makeDate(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, uintN maxargs, JSBool local, jsval *rval) -{ - uintN i; - jsdouble lorutime; /* local or UTC version of *date */ - jsdouble args[3], *argp, *stop; - jsdouble year, month, day; - jsdouble result; - - jsdouble *date = date_getProlog(cx, obj, argv); - if (!date) - return JS_FALSE; - - result = *date; - - /* see complaint about ECMA in date_MakeTime */ - if (argc == 0) - argc = 1; /* should be safe, because length of all setters is 1 */ - else if (argc > maxargs) - argc = maxargs; /* clamp argc */ - - for (i = 0; i < argc; i++) { - if (!js_ValueToNumber(cx, argv[i], &args[i])) - return JS_FALSE; - if (!JSDOUBLE_IS_FINITE(args[i])) { - *date = *cx->runtime->jsNaN; - return js_NewNumberValue(cx, *date, rval); - } - args[i] = js_DoubleToInteger(args[i]); - } - - /* return NaN if date is NaN and we're not setting the year, - * If we are, use 0 as the time. */ - if (!(JSDOUBLE_IS_FINITE(result))) { - if (argc < 3) - return js_NewNumberValue(cx, result, rval); - else - lorutime = +0.; - } else { - if (local) - lorutime = LocalTime(result); - else - lorutime = result; - } - - argp = args; - stop = argp + argc; - if (maxargs >= 3 && argp < stop) - year = *argp++; - else - year = YearFromTime(lorutime); - - if (maxargs >= 2 && argp < stop) - month = *argp++; - else - month = MonthFromTime(lorutime); - - if (maxargs >= 1 && argp < stop) - day = *argp++; - else - day = DateFromTime(lorutime); - - day = MakeDay(year, month, day); /* day within year */ - result = MakeDate(day, TimeWithinDay(lorutime)); - - if (local) - result = UTC(result); - - *date = TIMECLIP(result); - return js_NewNumberValue(cx, *date, rval); -} - -static JSBool -date_setDate(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval) -{ - return date_makeDate(cx, obj, argc, argv, 1, JS_TRUE, rval); -} - -static JSBool -date_setUTCDate(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval) -{ - return date_makeDate(cx, obj, argc, argv, 1, JS_FALSE, rval); -} - -static JSBool -date_setMonth(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval) -{ - return date_makeDate(cx, obj, argc, argv, 2, JS_TRUE, rval); -} - -static JSBool -date_setUTCMonth(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval) -{ - return date_makeDate(cx, obj, argc, argv, 2, JS_FALSE, rval); -} - -static JSBool -date_setFullYear(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval) -{ - return date_makeDate(cx, obj, argc, argv, 3, JS_TRUE, rval); -} - -static JSBool -date_setUTCFullYear(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval) -{ - return date_makeDate(cx, obj, argc, argv, 3, JS_FALSE, rval); -} - -static JSBool -date_setYear(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval) -{ - jsdouble t; - jsdouble year; - jsdouble day; - jsdouble result; - - jsdouble *date = date_getProlog(cx, obj, argv); - if (!date) - return JS_FALSE; - - result = *date; - - if (!js_ValueToNumber(cx, argv[0], &year)) - return JS_FALSE; - if (!JSDOUBLE_IS_FINITE(year)) { - *date = *cx->runtime->jsNaN; - return js_NewNumberValue(cx, *date, rval); - } - - year = js_DoubleToInteger(year); - - if (!JSDOUBLE_IS_FINITE(result)) { - t = +0.0; - } else { - t = LocalTime(result); - } - - if (year >= 0 && year <= 99) - year += 1900; - - day = MakeDay(year, MonthFromTime(t), DateFromTime(t)); - result = MakeDate(day, TimeWithinDay(t)); - result = UTC(result); - - *date = TIMECLIP(result); - return js_NewNumberValue(cx, *date, rval); -} - -/* constants for toString, toUTCString */ -static char js_NaN_date_str[] = "Invalid Date"; -static const char* days[] = -{ - "Sun","Mon","Tue","Wed","Thu","Fri","Sat" -}; -static const char* months[] = -{ - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; - -static JSBool -date_toGMTString(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval) -{ - char buf[100]; - JSString *str; - jsdouble *date = date_getProlog(cx, obj, argv); - if (!date) - return JS_FALSE; - - if (!JSDOUBLE_IS_FINITE(*date)) { - JS_snprintf(buf, sizeof buf, js_NaN_date_str); - } else { - jsdouble temp = *date; - - /* Avoid dependence on PRMJ_FormatTimeUSEnglish, because it - * requires a PRMJTime... which only has 16-bit years. Sub-ECMA. - */ - JS_snprintf(buf, sizeof buf, "%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT", - days[WeekDay(temp)], - DateFromTime(temp), - months[MonthFromTime(temp)], - YearFromTime(temp), - HourFromTime(temp), - MinFromTime(temp), - SecFromTime(temp)); - } - str = JS_NewStringCopyZ(cx, buf); - if (!str) - return JS_FALSE; - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -/* for Date.toLocaleString; interface to PRMJTime date struct. - * If findEquivalent is true, then try to map the year to an equivalent year - * that's in range. - */ -static void -new_explode(jsdouble timeval, PRMJTime *split, JSBool findEquivalent) -{ - jsint year = YearFromTime(timeval); - int16 adjustedYear; - - /* If the year doesn't fit in a PRMJTime, find something to do about it. */ - if (year > 32767 || year < -32768) { - if (findEquivalent) { - /* We're really just trying to get a timezone string; map the year - * to some equivalent year in the range 0 to 2800. Borrowed from - * A. D. Olsen. - */ - jsint cycles; -#define CYCLE_YEARS 2800L - cycles = (year >= 0) ? year / CYCLE_YEARS - : -1 - (-1 - year) / CYCLE_YEARS; - adjustedYear = (int16)(year - cycles * CYCLE_YEARS); - } else { - /* Clamp it to the nearest representable year. */ - adjustedYear = (int16)((year > 0) ? 32767 : - 32768); - } - } else { - adjustedYear = (int16)year; - } - - split->tm_usec = (int32) msFromTime(timeval) * 1000; - split->tm_sec = (int8) SecFromTime(timeval); - split->tm_min = (int8) MinFromTime(timeval); - split->tm_hour = (int8) HourFromTime(timeval); - split->tm_mday = (int8) DateFromTime(timeval); - split->tm_mon = (int8) MonthFromTime(timeval); - split->tm_wday = (int8) WeekDay(timeval); - split->tm_year = (int16) adjustedYear; - split->tm_yday = (int16) DayWithinYear(timeval, year); - - /* not sure how this affects things, but it doesn't seem - to matter. */ - split->tm_isdst = (DaylightSavingTA(timeval) != 0); -} - -typedef enum formatspec { - FORMATSPEC_FULL, FORMATSPEC_DATE, FORMATSPEC_TIME -} formatspec; - -/* helper function */ -static JSBool -date_format(JSContext *cx, jsdouble date, formatspec format, jsval *rval) -{ - char buf[100]; - JSString *str; - char tzbuf[100]; - JSBool usetz; - size_t i, tzlen; - PRMJTime split; - - if (!JSDOUBLE_IS_FINITE(date)) { - JS_snprintf(buf, sizeof buf, js_NaN_date_str); - } else { - jsdouble local = LocalTime(date); - - /* offset from GMT in minutes. The offset includes daylight savings, - if it applies. */ - jsint minutes = (jsint) floor(AdjustTime(date) / msPerMinute); - - /* map 510 minutes to 0830 hours */ - intN offset = (minutes / 60) * 100 + minutes % 60; - - /* print as "Wed Nov 05 19:38:03 GMT-0800 (PST) 1997" The TZA is - * printed as 'GMT-0800' rather than as 'PST' to avoid - * operating-system dependence on strftime (which - * PRMJ_FormatTimeUSEnglish calls, for %Z only.) win32 prints - * PST as 'Pacific Standard Time.' This way we always know - * what we're getting, and can parse it if we produce it. - * The OS TZA string is included as a comment. - */ - - /* get a timezone string from the OS to include as a - comment. */ - new_explode(date, &split, JS_TRUE); - if (PRMJ_FormatTime(tzbuf, sizeof tzbuf, "(%Z)", &split) != 0) { - - /* Decide whether to use the resulting timezone string. - * - * Reject it if it contains any non-ASCII, non-alphanumeric - * characters. It's then likely in some other character - * encoding, and we probably won't display it correctly. - */ - usetz = JS_TRUE; - tzlen = strlen(tzbuf); - if (tzlen > 100) { - usetz = JS_FALSE; - } else { - for (i = 0; i < tzlen; i++) { - jschar c = tzbuf[i]; - if (c > 127 || - !(isalpha(c) || isdigit(c) || - c == ' ' || c == '(' || c == ')')) { - usetz = JS_FALSE; - } - } - } - - /* Also reject it if it's not parenthesized or if it's '()'. */ - if (tzbuf[0] != '(' || tzbuf[1] == ')') - usetz = JS_FALSE; - } else - usetz = JS_FALSE; - - switch (format) { - case FORMATSPEC_FULL: - /* - * Avoid dependence on PRMJ_FormatTimeUSEnglish, because it - * requires a PRMJTime... which only has 16-bit years. Sub-ECMA. - */ - /* Tue Oct 31 2000 09:41:40 GMT-0800 (PST) */ - JS_snprintf(buf, sizeof buf, - "%s %s %.2d %.4d %.2d:%.2d:%.2d GMT%+.4d%s%s", - days[WeekDay(local)], - months[MonthFromTime(local)], - DateFromTime(local), - YearFromTime(local), - HourFromTime(local), - MinFromTime(local), - SecFromTime(local), - offset, - usetz ? " " : "", - usetz ? tzbuf : ""); - break; - case FORMATSPEC_DATE: - /* Tue Oct 31 2000 */ - JS_snprintf(buf, sizeof buf, - "%s %s %.2d %.4d", - days[WeekDay(local)], - months[MonthFromTime(local)], - DateFromTime(local), - YearFromTime(local)); - break; - case FORMATSPEC_TIME: - /* 09:41:40 GMT-0800 (PST) */ - JS_snprintf(buf, sizeof buf, - "%.2d:%.2d:%.2d GMT%+.4d%s%s", - HourFromTime(local), - MinFromTime(local), - SecFromTime(local), - offset, - usetz ? " " : "", - usetz ? tzbuf : ""); - break; - } - } - - str = JS_NewStringCopyZ(cx, buf); - if (!str) - return JS_FALSE; - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -static JSBool -date_toLocaleHelper(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval, char *format) -{ - char buf[100]; - JSString *str; - PRMJTime split; - jsdouble *date = date_getProlog(cx, obj, argv); - if (!date) - return JS_FALSE; - - if (!JSDOUBLE_IS_FINITE(*date)) { - JS_snprintf(buf, sizeof buf, js_NaN_date_str); - } else { - intN result_len; - jsdouble local = LocalTime(*date); - new_explode(local, &split, JS_FALSE); - - /* let PRMJTime format it. */ - result_len = PRMJ_FormatTime(buf, sizeof buf, format, &split); - - /* If it failed, default to toString. */ - if (result_len == 0) - return date_format(cx, *date, FORMATSPEC_FULL, rval); - - /* Hacked check against undesired 2-digit year 00/00/00 form. */ - if (buf[result_len - 3] == '/' && - isdigit(buf[result_len - 2]) && isdigit(buf[result_len - 1])) { - JS_snprintf(buf + (result_len - 2), (sizeof buf) - (result_len - 2), - "%d", js_DateGetYear(cx, obj)); - } - - } - - if (cx->localeCallbacks && cx->localeCallbacks->localeToUnicode) - return cx->localeCallbacks->localeToUnicode(cx, buf, rval); - - str = JS_NewStringCopyZ(cx, buf); - if (!str) - return JS_FALSE; - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -static JSBool -date_toLocaleString(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval) -{ - /* Use '%#c' for windows, because '%c' is - * backward-compatible and non-y2k with msvc; '%#c' requests that a - * full year be used in the result string. - */ - return date_toLocaleHelper(cx, obj, argc, argv, rval, -#if defined(_WIN32) && !defined(__MWERKS__) - "%#c" -#else - "%c" -#endif - ); -} - -static JSBool -date_toLocaleDateString(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval) -{ - /* Use '%#x' for windows, because '%x' is - * backward-compatible and non-y2k with msvc; '%#x' requests that a - * full year be used in the result string. - */ - return date_toLocaleHelper(cx, obj, argc, argv, rval, -#if defined(_WIN32) && !defined(__MWERKS__) - "%#x" -#else - "%x" -#endif - ); -} - -static JSBool -date_toLocaleTimeString(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval) -{ - return date_toLocaleHelper(cx, obj, argc, argv, rval, "%X"); -} - -static JSBool -date_toLocaleFormat(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSString *fmt; - - if (argc == 0) - return date_toLocaleString(cx, obj, argc, argv, rval); - - fmt = JS_ValueToString(cx, argv[0]); - if (!fmt) - return JS_FALSE; - - return date_toLocaleHelper(cx, obj, argc, argv, rval, - JS_GetStringBytes(fmt)); -} - -static JSBool -date_toTimeString(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval) -{ - jsdouble *date = date_getProlog(cx, obj, argv); - if (!date) - return JS_FALSE; - return date_format(cx, *date, FORMATSPEC_TIME, rval); -} - -static JSBool -date_toDateString(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval) -{ - jsdouble *date = date_getProlog(cx, obj, argv); - if (!date) - return JS_FALSE; - return date_format(cx, *date, FORMATSPEC_DATE, rval); -} - -#if JS_HAS_TOSOURCE -#include -#include "jsdtoa.h" - -static JSBool -date_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jsdouble *date; - char buf[DTOSTR_STANDARD_BUFFER_SIZE], *numStr, *bytes; - JSString *str; - - date = date_getProlog(cx, obj, argv); - if (!date) - return JS_FALSE; - - numStr = JS_dtostr(buf, sizeof buf, DTOSTR_STANDARD, 0, *date); - if (!numStr) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - - bytes = JS_smprintf("(new %s(%s))", date_class.name, numStr); - if (!bytes) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - - str = JS_NewString(cx, bytes, strlen(bytes)); - if (!str) { - free(bytes); - return JS_FALSE; - } - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} -#endif - -static JSBool -date_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jsdouble *date = date_getProlog(cx, obj, argv); - if (!date) - return JS_FALSE; - return date_format(cx, *date, FORMATSPEC_FULL, rval); -} - -#if JS_HAS_VALUEOF_HINT -static JSBool -date_valueOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - /* It is an error to call date_valueOf on a non-date object, but we don't - * need to check for that explicitly here because every path calls - * date_getProlog, which does the check. - */ - - /* If called directly with no arguments, convert to a time number. */ - if (argc == 0) - return date_getTime(cx, obj, argc, argv, rval); - - /* Convert to number only if the hint was given, otherwise favor string. */ - if (argc == 1) { - JSString *str, *str2; - - str = js_ValueToString(cx, argv[0]); - if (!str) - return JS_FALSE; - str2 = ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_NUMBER]); - if (!js_CompareStrings(str, str2)) - return date_getTime(cx, obj, argc, argv, rval); - } - return date_toString(cx, obj, argc, argv, rval); -} -#else -#define date_valueOf date_getTime -#endif - - -/* - * creation and destruction - */ - -static JSFunctionSpec date_static_methods[] = { - {"UTC", date_UTC, MAXARGS,0,0 }, - {"parse", date_parse, 1,0,0 }, - {"now", date_now, 0,0,0 }, - {0,0,0,0,0} -}; - -static JSFunctionSpec date_methods[] = { - {"getTime", date_getTime, 0,0,0 }, - {"getTimezoneOffset", date_getTimezoneOffset, 0,0,0 }, - {"getYear", date_getYear, 0,0,0 }, - {"getFullYear", date_getFullYear, 0,0,0 }, - {"getUTCFullYear", date_getUTCFullYear, 0,0,0 }, - {"getMonth", date_getMonth, 0,0,0 }, - {"getUTCMonth", date_getUTCMonth, 0,0,0 }, - {"getDate", date_getDate, 0,0,0 }, - {"getUTCDate", date_getUTCDate, 0,0,0 }, - {"getDay", date_getDay, 0,0,0 }, - {"getUTCDay", date_getUTCDay, 0,0,0 }, - {"getHours", date_getHours, 0,0,0 }, - {"getUTCHours", date_getUTCHours, 0,0,0 }, - {"getMinutes", date_getMinutes, 0,0,0 }, - {"getUTCMinutes", date_getUTCMinutes, 0,0,0 }, - {"getSeconds", date_getUTCSeconds, 0,0,0 }, - {"getUTCSeconds", date_getUTCSeconds, 0,0,0 }, - {"getMilliseconds", date_getUTCMilliseconds,0,0,0 }, - {"getUTCMilliseconds", date_getUTCMilliseconds,0,0,0 }, - {"setTime", date_setTime, 1,0,0 }, - {"setYear", date_setYear, 1,0,0 }, - {"setFullYear", date_setFullYear, 3,0,0 }, - {"setUTCFullYear", date_setUTCFullYear, 3,0,0 }, - {"setMonth", date_setMonth, 2,0,0 }, - {"setUTCMonth", date_setUTCMonth, 2,0,0 }, - {"setDate", date_setDate, 1,0,0 }, - {"setUTCDate", date_setUTCDate, 1,0,0 }, - {"setHours", date_setHours, 4,0,0 }, - {"setUTCHours", date_setUTCHours, 4,0,0 }, - {"setMinutes", date_setMinutes, 3,0,0 }, - {"setUTCMinutes", date_setUTCMinutes, 3,0,0 }, - {"setSeconds", date_setSeconds, 2,0,0 }, - {"setUTCSeconds", date_setUTCSeconds, 2,0,0 }, - {"setMilliseconds", date_setMilliseconds, 1,0,0 }, - {"setUTCMilliseconds", date_setUTCMilliseconds,1,0,0 }, - {"toUTCString", date_toGMTString, 0,0,0 }, - {js_toLocaleString_str, date_toLocaleString, 0,0,0 }, - {"toLocaleDateString", date_toLocaleDateString,0,0,0 }, - {"toLocaleTimeString", date_toLocaleTimeString,0,0,0 }, - {"toLocaleFormat", date_toLocaleFormat, 1,0,0 }, - {"toDateString", date_toDateString, 0,0,0 }, - {"toTimeString", date_toTimeString, 0,0,0 }, -#if JS_HAS_TOSOURCE - {js_toSource_str, date_toSource, 0,0,0 }, -#endif - {js_toString_str, date_toString, 0,0,0 }, - {js_valueOf_str, date_valueOf, 0,0,0 }, - {0,0,0,0,0} -}; - -static jsdouble * -date_constructor(JSContext *cx, JSObject* obj) -{ - jsdouble *date; - - date = js_NewDouble(cx, 0.0, 0); - if (!date) - return NULL; - OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, DOUBLE_TO_JSVAL(date)); - return date; -} - -static JSBool -Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsdouble *date; - JSString *str; - jsdouble d; - - /* Date called as function. */ - if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) { - int64 us, ms, us2ms; - jsdouble msec_time; - - /* NSPR 2.0 docs say 'We do not support PRMJ_NowMS and PRMJ_NowS', - * so compute ms from PRMJ_Now. - */ - us = PRMJ_Now(); - JSLL_UI2L(us2ms, PRMJ_USEC_PER_MSEC); - JSLL_DIV(ms, us, us2ms); - JSLL_L2D(msec_time, ms); - - return date_format(cx, msec_time, FORMATSPEC_FULL, rval); - } - - /* Date called as constructor. */ - if (argc == 0) { - int64 us, ms, us2ms; - jsdouble msec_time; - - date = date_constructor(cx, obj); - if (!date) - return JS_FALSE; - - us = PRMJ_Now(); - JSLL_UI2L(us2ms, PRMJ_USEC_PER_MSEC); - JSLL_DIV(ms, us, us2ms); - JSLL_L2D(msec_time, ms); - - *date = msec_time; - } else if (argc == 1) { - if (!JSVAL_IS_STRING(argv[0])) { - /* the argument is a millisecond number */ - if (!js_ValueToNumber(cx, argv[0], &d)) - return JS_FALSE; - date = date_constructor(cx, obj); - if (!date) - return JS_FALSE; - *date = TIMECLIP(d); - } else { - /* the argument is a string; parse it. */ - date = date_constructor(cx, obj); - if (!date) - return JS_FALSE; - - str = js_ValueToString(cx, argv[0]); - if (!str) - return JS_FALSE; - - if (!date_parseString(str, date)) - *date = *cx->runtime->jsNaN; - *date = TIMECLIP(*date); - } - } else { - jsdouble array[MAXARGS]; - uintN loop; - jsdouble double_arg; - jsdouble day; - jsdouble msec_time; - - for (loop = 0; loop < MAXARGS; loop++) { - if (loop < argc) { - if (!js_ValueToNumber(cx, argv[loop], &double_arg)) - return JS_FALSE; - /* if any arg is NaN, make a NaN date object - and return */ - if (!JSDOUBLE_IS_FINITE(double_arg)) { - date = date_constructor(cx, obj); - if (!date) - return JS_FALSE; - *date = *cx->runtime->jsNaN; - return JS_TRUE; - } - array[loop] = js_DoubleToInteger(double_arg); - } else { - if (loop == 2) { - array[loop] = 1; /* Default the date argument to 1. */ - } else { - array[loop] = 0; - } - } - } - - date = date_constructor(cx, obj); - if (!date) - return JS_FALSE; - - /* adjust 2-digit years into the 20th century */ - if (array[0] >= 0 && array[0] <= 99) - array[0] += 1900; - - day = MakeDay(array[0], array[1], array[2]); - msec_time = MakeTime(array[3], array[4], array[5], array[6]); - msec_time = MakeDate(day, msec_time); - msec_time = UTC(msec_time); - *date = TIMECLIP(msec_time); - } - return JS_TRUE; -} - -JSObject * -js_InitDateClass(JSContext *cx, JSObject *obj) -{ - JSObject *proto; - jsdouble *proto_date; - - /* set static LocalTZA */ - LocalTZA = -(PRMJ_LocalGMTDifference() * msPerSecond); - proto = JS_InitClass(cx, obj, NULL, &date_class, Date, MAXARGS, - NULL, date_methods, NULL, date_static_methods); - if (!proto) - return NULL; - - /* Alias toUTCString with toGMTString. (ECMA B.2.6) */ - if (!JS_AliasProperty(cx, proto, "toUTCString", "toGMTString")) - return NULL; - - /* Set the value of the Date.prototype date to NaN */ - proto_date = date_constructor(cx, proto); - if (!proto_date) - return NULL; - *proto_date = *cx->runtime->jsNaN; - - return proto; -} - -JS_FRIEND_API(JSObject *) -js_NewDateObjectMsec(JSContext *cx, jsdouble msec_time) -{ - JSObject *obj; - jsdouble *date; - - obj = js_NewObject(cx, &date_class, NULL, NULL); - if (!obj) - return NULL; - - date = date_constructor(cx, obj); - if (!date) - return NULL; - - *date = msec_time; - return obj; -} - -JS_FRIEND_API(JSObject *) -js_NewDateObject(JSContext* cx, int year, int mon, int mday, - int hour, int min, int sec) -{ - JSObject *obj; - jsdouble msec_time; - - msec_time = date_msecFromDate(year, mon, mday, hour, min, sec, 0); - obj = js_NewDateObjectMsec(cx, UTC(msec_time)); - return obj; -} - -JS_FRIEND_API(JSBool) -js_DateIsValid(JSContext *cx, JSObject* obj) -{ - jsdouble *date = date_getProlog(cx, obj, NULL); - - if (!date || JSDOUBLE_IS_NaN(*date)) - return JS_FALSE; - else - return JS_TRUE; -} - -JS_FRIEND_API(int) -js_DateGetYear(JSContext *cx, JSObject* obj) -{ - jsdouble *date = date_getProlog(cx, obj, NULL); - - /* Preserve legacy API behavior of returning 0 for invalid dates. */ - if (!date || JSDOUBLE_IS_NaN(*date)) - return 0; - return (int) YearFromTime(LocalTime(*date)); -} - -JS_FRIEND_API(int) -js_DateGetMonth(JSContext *cx, JSObject* obj) -{ - jsdouble *date = date_getProlog(cx, obj, NULL); - - if (!date || JSDOUBLE_IS_NaN(*date)) - return 0; - return (int) MonthFromTime(LocalTime(*date)); -} - -JS_FRIEND_API(int) -js_DateGetDate(JSContext *cx, JSObject* obj) -{ - jsdouble *date = date_getProlog(cx, obj, NULL); - - if (!date || JSDOUBLE_IS_NaN(*date)) - return 0; - return (int) DateFromTime(LocalTime(*date)); -} - -JS_FRIEND_API(int) -js_DateGetHours(JSContext *cx, JSObject* obj) -{ - jsdouble *date = date_getProlog(cx, obj, NULL); - - if (!date || JSDOUBLE_IS_NaN(*date)) - return 0; - return (int) HourFromTime(LocalTime(*date)); -} - -JS_FRIEND_API(int) -js_DateGetMinutes(JSContext *cx, JSObject* obj) -{ - jsdouble *date = date_getProlog(cx, obj, NULL); - - if (!date || JSDOUBLE_IS_NaN(*date)) - return 0; - return (int) MinFromTime(LocalTime(*date)); -} - -JS_FRIEND_API(int) -js_DateGetSeconds(JSContext *cx, JSObject* obj) -{ - jsdouble *date = date_getProlog(cx, obj, NULL); - - if (!date || JSDOUBLE_IS_NaN(*date)) - return 0; - return (int) SecFromTime(*date); -} - -JS_FRIEND_API(void) -js_DateSetYear(JSContext *cx, JSObject *obj, int year) -{ - jsdouble local; - jsdouble *date = date_getProlog(cx, obj, NULL); - if (!date) - return; - local = LocalTime(*date); - /* reset date if it was NaN */ - if (JSDOUBLE_IS_NaN(local)) - local = 0; - local = date_msecFromDate(year, - MonthFromTime(local), - DateFromTime(local), - HourFromTime(local), - MinFromTime(local), - SecFromTime(local), - msFromTime(local)); - *date = UTC(local); -} - -JS_FRIEND_API(void) -js_DateSetMonth(JSContext *cx, JSObject *obj, int month) -{ - jsdouble local; - jsdouble *date = date_getProlog(cx, obj, NULL); - if (!date) - return; - local = LocalTime(*date); - /* bail if date was NaN */ - if (JSDOUBLE_IS_NaN(local)) - return; - local = date_msecFromDate(YearFromTime(local), - month, - DateFromTime(local), - HourFromTime(local), - MinFromTime(local), - SecFromTime(local), - msFromTime(local)); - *date = UTC(local); -} - -JS_FRIEND_API(void) -js_DateSetDate(JSContext *cx, JSObject *obj, int date) -{ - jsdouble local; - jsdouble *datep = date_getProlog(cx, obj, NULL); - if (!datep) - return; - local = LocalTime(*datep); - if (JSDOUBLE_IS_NaN(local)) - return; - local = date_msecFromDate(YearFromTime(local), - MonthFromTime(local), - date, - HourFromTime(local), - MinFromTime(local), - SecFromTime(local), - msFromTime(local)); - *datep = UTC(local); -} - -JS_FRIEND_API(void) -js_DateSetHours(JSContext *cx, JSObject *obj, int hours) -{ - jsdouble local; - jsdouble *date = date_getProlog(cx, obj, NULL); - if (!date) - return; - local = LocalTime(*date); - if (JSDOUBLE_IS_NaN(local)) - return; - local = date_msecFromDate(YearFromTime(local), - MonthFromTime(local), - DateFromTime(local), - hours, - MinFromTime(local), - SecFromTime(local), - msFromTime(local)); - *date = UTC(local); -} - -JS_FRIEND_API(void) -js_DateSetMinutes(JSContext *cx, JSObject *obj, int minutes) -{ - jsdouble local; - jsdouble *date = date_getProlog(cx, obj, NULL); - if (!date) - return; - local = LocalTime(*date); - if (JSDOUBLE_IS_NaN(local)) - return; - local = date_msecFromDate(YearFromTime(local), - MonthFromTime(local), - DateFromTime(local), - HourFromTime(local), - minutes, - SecFromTime(local), - msFromTime(local)); - *date = UTC(local); -} - -JS_FRIEND_API(void) -js_DateSetSeconds(JSContext *cx, JSObject *obj, int seconds) -{ - jsdouble local; - jsdouble *date = date_getProlog(cx, obj, NULL); - if (!date) - return; - local = LocalTime(*date); - if (JSDOUBLE_IS_NaN(local)) - return; - local = date_msecFromDate(YearFromTime(local), - MonthFromTime(local), - DateFromTime(local), - HourFromTime(local), - MinFromTime(local), - seconds, - msFromTime(local)); - *date = UTC(local); -} - -JS_FRIEND_API(jsdouble) -js_DateGetMsecSinceEpoch(JSContext *cx, JSObject *obj) -{ - jsdouble *date = date_getProlog(cx, obj, NULL); - if (!date || JSDOUBLE_IS_NaN(*date)) - return 0; - return (*date); -} diff --git a/lib/javascript/jsdate.h b/lib/javascript/jsdate.h deleted file mode 100644 index 343314fa..00000000 --- a/lib/javascript/jsdate.h +++ /dev/null @@ -1,118 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JS Date class interface. - */ - -#ifndef jsdate_h___ -#define jsdate_h___ - -JS_BEGIN_EXTERN_C - -extern JSObject * -js_InitDateClass(JSContext *cx, JSObject *obj); - -/* - * These functions provide a C interface to the date/time object - */ - -/* - * Construct a new Date Object from a time value given in milliseconds UTC - * since the epoch. - */ -extern JS_FRIEND_API(JSObject*) -js_NewDateObjectMsec(JSContext* cx, jsdouble msec_time); - -/* - * Construct a new Date Object from an exploded local time value. - */ -extern JS_FRIEND_API(JSObject*) -js_NewDateObject(JSContext* cx, int year, int mon, int mday, - int hour, int min, int sec); - -/* - * Detect whether the internal date value is NaN. (Because failure is - * out-of-band for js_DateGet*) - */ -extern JS_FRIEND_API(JSBool) -js_DateIsValid(JSContext *cx, JSObject* obj); - -extern JS_FRIEND_API(int) -js_DateGetYear(JSContext *cx, JSObject* obj); - -extern JS_FRIEND_API(int) -js_DateGetMonth(JSContext *cx, JSObject* obj); - -extern JS_FRIEND_API(int) -js_DateGetDate(JSContext *cx, JSObject* obj); - -extern JS_FRIEND_API(int) -js_DateGetHours(JSContext *cx, JSObject* obj); - -extern JS_FRIEND_API(int) -js_DateGetMinutes(JSContext *cx, JSObject* obj); - -extern JS_FRIEND_API(int) -js_DateGetSeconds(JSContext *cx, JSObject* obj); - -extern JS_FRIEND_API(void) -js_DateSetYear(JSContext *cx, JSObject *obj, int year); - -extern JS_FRIEND_API(void) -js_DateSetMonth(JSContext *cx, JSObject *obj, int year); - -extern JS_FRIEND_API(void) -js_DateSetDate(JSContext *cx, JSObject *obj, int date); - -extern JS_FRIEND_API(void) -js_DateSetHours(JSContext *cx, JSObject *obj, int hours); - -extern JS_FRIEND_API(void) -js_DateSetMinutes(JSContext *cx, JSObject *obj, int minutes); - -extern JS_FRIEND_API(void) -js_DateSetSeconds(JSContext *cx, JSObject *obj, int seconds); - -extern JS_FRIEND_API(jsdouble) -js_DateGetMsecSinceEpoch(JSContext *cx, JSObject *obj); - -JS_END_EXTERN_C - -#endif /* jsdate_h___ */ diff --git a/lib/javascript/jsdbgapi.c b/lib/javascript/jsdbgapi.c deleted file mode 100644 index cddbd480..00000000 --- a/lib/javascript/jsdbgapi.c +++ /dev/null @@ -1,1405 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JS debugging API. - */ -#include "jsstddef.h" -#include -#include "jstypes.h" -#include "jsutil.h" /* Added by JSIFY */ -#include "jsclist.h" -#include "jsapi.h" -#include "jscntxt.h" -#include "jsconfig.h" -#include "jsdbgapi.h" -#include "jsfun.h" -#include "jsgc.h" -#include "jsinterp.h" -#include "jslock.h" -#include "jsobj.h" -#include "jsopcode.h" -#include "jsscope.h" -#include "jsscript.h" -#include "jsstr.h" - -typedef struct JSTrap { - JSCList links; - JSScript *script; - jsbytecode *pc; - JSOp op; - JSTrapHandler handler; - void *closure; -} JSTrap; - -static JSTrap * -FindTrap(JSRuntime *rt, JSScript *script, jsbytecode *pc) -{ - JSTrap *trap; - - for (trap = (JSTrap *)rt->trapList.next; - trap != (JSTrap *)&rt->trapList; - trap = (JSTrap *)trap->links.next) { - if (trap->script == script && trap->pc == pc) - return trap; - } - return NULL; -} - -void -js_PatchOpcode(JSContext *cx, JSScript *script, jsbytecode *pc, JSOp op) -{ - JSTrap *trap; - - trap = FindTrap(cx->runtime, script, pc); - if (trap) - trap->op = op; - else - *pc = (jsbytecode)op; -} - -JS_PUBLIC_API(JSBool) -JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc, - JSTrapHandler handler, void *closure) -{ - JSRuntime *rt; - JSTrap *trap; - - rt = cx->runtime; - trap = FindTrap(rt, script, pc); - if (trap) { - JS_ASSERT(trap->script == script && trap->pc == pc); - JS_ASSERT(*pc == JSOP_TRAP); - } else { - trap = (JSTrap *) JS_malloc(cx, sizeof *trap); - if (!trap || !js_AddRoot(cx, &trap->closure, "trap->closure")) { - if (trap) - JS_free(cx, trap); - return JS_FALSE; - } - JS_APPEND_LINK(&trap->links, &rt->trapList); - trap->script = script; - trap->pc = pc; - trap->op = (JSOp)*pc; - *pc = JSOP_TRAP; - } - trap->handler = handler; - trap->closure = closure; - return JS_TRUE; -} - -JS_PUBLIC_API(JSOp) -JS_GetTrapOpcode(JSContext *cx, JSScript *script, jsbytecode *pc) -{ - JSTrap *trap; - - trap = FindTrap(cx->runtime, script, pc); - if (!trap) { - JS_ASSERT(0); /* XXX can't happen */ - return JSOP_LIMIT; - } - return trap->op; -} - -static void -DestroyTrap(JSContext *cx, JSTrap *trap) -{ - JS_REMOVE_LINK(&trap->links); - *trap->pc = (jsbytecode)trap->op; - js_RemoveRoot(cx->runtime, &trap->closure); - JS_free(cx, trap); -} - -JS_PUBLIC_API(void) -JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc, - JSTrapHandler *handlerp, void **closurep) -{ - JSTrap *trap; - - trap = FindTrap(cx->runtime, script, pc); - if (handlerp) - *handlerp = trap ? trap->handler : NULL; - if (closurep) - *closurep = trap ? trap->closure : NULL; - if (trap) - DestroyTrap(cx, trap); -} - -JS_PUBLIC_API(void) -JS_ClearScriptTraps(JSContext *cx, JSScript *script) -{ - JSRuntime *rt; - JSTrap *trap, *next; - - rt = cx->runtime; - for (trap = (JSTrap *)rt->trapList.next; - trap != (JSTrap *)&rt->trapList; - trap = next) { - next = (JSTrap *)trap->links.next; - if (trap->script == script) - DestroyTrap(cx, trap); - } -} - -JS_PUBLIC_API(void) -JS_ClearAllTraps(JSContext *cx) -{ - JSRuntime *rt; - JSTrap *trap, *next; - - rt = cx->runtime; - for (trap = (JSTrap *)rt->trapList.next; - trap != (JSTrap *)&rt->trapList; - trap = next) { - next = (JSTrap *)trap->links.next; - DestroyTrap(cx, trap); - } -} - -JS_PUBLIC_API(JSTrapStatus) -JS_HandleTrap(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval) -{ - JSTrap *trap; - JSTrapStatus status; - jsint op; - - trap = FindTrap(cx->runtime, script, pc); - if (!trap) { - JS_ASSERT(0); /* XXX can't happen */ - return JSTRAP_ERROR; - } - /* - * It's important that we not use 'trap->' after calling the callback -- - * the callback might remove the trap! - */ - op = (jsint)trap->op; - status = trap->handler(cx, script, pc, rval, trap->closure); - if (status == JSTRAP_CONTINUE) { - /* By convention, return the true op to the interpreter in rval. */ - *rval = INT_TO_JSVAL(op); - } - return status; -} - -JS_PUBLIC_API(JSBool) -JS_SetInterrupt(JSRuntime *rt, JSTrapHandler handler, void *closure) -{ - rt->interruptHandler = handler; - rt->interruptHandlerData = closure; - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_ClearInterrupt(JSRuntime *rt, JSTrapHandler *handlerp, void **closurep) -{ - if (handlerp) - *handlerp = (JSTrapHandler)rt->interruptHandler; - if (closurep) - *closurep = rt->interruptHandlerData; - rt->interruptHandler = 0; - rt->interruptHandlerData = 0; - return JS_TRUE; -} - -/************************************************************************/ - -typedef struct JSWatchPoint { - JSCList links; - JSObject *object; /* weak link, see js_FinalizeObject */ - JSScopeProperty *sprop; - JSPropertyOp setter; - JSWatchPointHandler handler; - void *closure; - jsrefcount nrefs; -} JSWatchPoint; - -#define HoldWatchPoint(wp) ((wp)->nrefs++) - -static JSBool -DropWatchPoint(JSContext *cx, JSWatchPoint *wp) -{ - JSScopeProperty *sprop; - - if (--wp->nrefs != 0) - return JS_TRUE; - - /* - * Remove wp from the list, then if there are no other watchpoints for - * wp->sprop in any scope, restore wp->sprop->setter from wp. - */ - JS_REMOVE_LINK(&wp->links); - sprop = wp->sprop; - if (!js_GetWatchedSetter(cx->runtime, NULL, sprop)) { - sprop = js_ChangeNativePropertyAttrs(cx, wp->object, sprop, - 0, sprop->attrs, - sprop->getter, wp->setter); - if (!sprop) - return JS_FALSE; - } - js_RemoveRoot(cx->runtime, &wp->closure); - JS_free(cx, wp); - return JS_TRUE; -} - -void -js_MarkWatchPoints(JSContext *cx) -{ - JSRuntime *rt; - JSWatchPoint *wp; - - rt = cx->runtime; - for (wp = (JSWatchPoint *)rt->watchPointList.next; - wp != (JSWatchPoint *)&rt->watchPointList; - wp = (JSWatchPoint *)wp->links.next) { - MARK_SCOPE_PROPERTY(wp->sprop); - if (wp->sprop->attrs & JSPROP_SETTER) - JS_MarkGCThing(cx, wp->setter, "wp->setter", NULL); - } -} - -static JSWatchPoint * -FindWatchPoint(JSRuntime *rt, JSScope *scope, jsid id) -{ - JSWatchPoint *wp; - - for (wp = (JSWatchPoint *)rt->watchPointList.next; - wp != (JSWatchPoint *)&rt->watchPointList; - wp = (JSWatchPoint *)wp->links.next) { - if (wp->object == scope->object && wp->sprop->id == id) - return wp; - } - return NULL; -} - -JSScopeProperty * -js_FindWatchPoint(JSRuntime *rt, JSScope *scope, jsid id) -{ - JSWatchPoint *wp; - - wp = FindWatchPoint(rt, scope, id); - if (!wp) - return NULL; - return wp->sprop; -} - -JSPropertyOp -js_GetWatchedSetter(JSRuntime *rt, JSScope *scope, - const JSScopeProperty *sprop) -{ - JSWatchPoint *wp; - - for (wp = (JSWatchPoint *)rt->watchPointList.next; - wp != (JSWatchPoint *)&rt->watchPointList; - wp = (JSWatchPoint *)wp->links.next) { - if ((!scope || wp->object == scope->object) && wp->sprop == sprop) - return wp->setter; - } - return NULL; -} - -JSBool JS_DLL_CALLBACK -js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - JSRuntime *rt; - JSWatchPoint *wp; - JSScopeProperty *sprop; - jsval propid, userid; - JSScope *scope; - JSBool ok; - - rt = cx->runtime; - for (wp = (JSWatchPoint *)rt->watchPointList.next; - wp != (JSWatchPoint *)&rt->watchPointList; - wp = (JSWatchPoint *)wp->links.next) { - sprop = wp->sprop; - if (wp->object == obj && SPROP_USERID(sprop) == id) { - JS_LOCK_OBJ(cx, obj); - propid = ID_TO_VALUE(sprop->id); - userid = (sprop->flags & SPROP_HAS_SHORTID) - ? INT_TO_JSVAL(sprop->shortid) - : propid; - scope = OBJ_SCOPE(obj); - JS_UNLOCK_OBJ(cx, obj); - HoldWatchPoint(wp); - ok = wp->handler(cx, obj, propid, - SPROP_HAS_VALID_SLOT(sprop, scope) - ? OBJ_GET_SLOT(cx, obj, wp->sprop->slot) - : JSVAL_VOID, - vp, wp->closure); - if (ok) { - /* - * Create pseudo-frame for call to setter so that any - * stack-walking security code in the setter will correctly - * identify the guilty party. - */ - JSObject *closure; - JSClass *clasp; - JSFunction *fun; - JSScript *script; - uintN nslots; - jsval smallv[5]; - jsval *argv; - JSStackFrame frame; - - closure = (JSObject *) wp->closure; - clasp = OBJ_GET_CLASS(cx, closure); - if (clasp == &js_FunctionClass) { - fun = (JSFunction *) JS_GetPrivate(cx, closure); - script = FUN_SCRIPT(fun); - } else if (clasp == &js_ScriptClass) { - fun = NULL; - script = (JSScript *) JS_GetPrivate(cx, closure); - } else { - fun = NULL; - script = NULL; - } - - nslots = 2; - if (fun) { - nslots += fun->nargs; - if (FUN_NATIVE(fun)) - nslots += fun->extra; - } - - if (nslots <= sizeof (smallv) / sizeof (smallv[0])) { - argv = smallv; - } else { - argv = JS_malloc(cx, nslots * sizeof(jsval)); - if (!argv) { - DropWatchPoint(cx, wp); - return JS_FALSE; - } - } - - argv[0] = OBJECT_TO_JSVAL(closure); - argv[1] = JSVAL_NULL; - memset(argv + 2, 0, (nslots - 2) * sizeof(jsval)); - - memset(&frame, 0, sizeof(frame)); - frame.script = script; - if (script) - frame.pc = script->code; - frame.fun = fun; - frame.argv = argv + 2; - frame.down = cx->fp; - frame.scopeChain = OBJ_GET_PARENT(cx, closure); - - cx->fp = &frame; - ok = !wp->setter || - ((sprop->attrs & JSPROP_SETTER) - ? js_InternalCall(cx, obj, OBJECT_TO_JSVAL(wp->setter), - 1, vp, vp) - : wp->setter(cx, OBJ_THIS_OBJECT(cx, obj), userid, vp)); - cx->fp = frame.down; - if (argv != smallv) - JS_free(cx, argv); - } - return DropWatchPoint(cx, wp); - } - } - JS_ASSERT(0); /* XXX can't happen */ - return JS_FALSE; -} - -JSBool JS_DLL_CALLBACK -js_watch_set_wrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSObject *funobj; - JSFunction *wrapper; - jsval userid; - - funobj = JSVAL_TO_OBJECT(argv[-2]); - JS_ASSERT(OBJ_GET_CLASS(cx, funobj) == &js_FunctionClass); - wrapper = (JSFunction *) JS_GetPrivate(cx, funobj); - userid = ATOM_KEY(wrapper->atom); - *rval = argv[0]; - return js_watch_set(cx, obj, userid, rval); -} - -JSPropertyOp -js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter) -{ - JSAtom *atom; - JSFunction *wrapper; - - if (!(attrs & JSPROP_SETTER)) - return &js_watch_set; /* & to silence schoolmarmish MSVC */ - - if (JSID_IS_ATOM(id)) { - atom = JSID_TO_ATOM(id); - } else if (JSID_IS_INT(id)) { - atom = js_AtomizeInt(cx, JSID_TO_INT(id), 0); - if (!atom) - return NULL; - } else { - atom = NULL; - } - wrapper = js_NewFunction(cx, NULL, js_watch_set_wrapper, 1, 0, - OBJ_GET_PARENT(cx, (JSObject *)setter), - atom); - if (!wrapper) - return NULL; - return (JSPropertyOp) wrapper->object; -} - -JS_PUBLIC_API(JSBool) -JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval id, - JSWatchPointHandler handler, void *closure) -{ - JSAtom *atom; - jsid propid; - JSObject *pobj; - JSProperty *prop; - JSScopeProperty *sprop; - JSRuntime *rt; - JSBool ok; - JSWatchPoint *wp; - JSPropertyOp watcher; - - if (!OBJ_IS_NATIVE(obj)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_WATCH, - OBJ_GET_CLASS(cx, obj)->name); - return JS_FALSE; - } - - if (JSVAL_IS_INT(id)) { - propid = INT_JSVAL_TO_JSID(id); - atom = NULL; - } else { - atom = js_ValueToStringAtom(cx, id); - if (!atom) - return JS_FALSE; - propid = ATOM_TO_JSID(atom); - } - - if (!js_LookupProperty(cx, obj, propid, &pobj, &prop)) - return JS_FALSE; - sprop = (JSScopeProperty *) prop; - rt = cx->runtime; - if (!sprop) { - /* Check for a deleted symbol watchpoint, which holds its property. */ - sprop = js_FindWatchPoint(rt, OBJ_SCOPE(obj), propid); - if (!sprop) { - /* Make a new property in obj so we can watch for the first set. */ - if (!js_DefineProperty(cx, obj, propid, JSVAL_VOID, - NULL, NULL, JSPROP_ENUMERATE, - &prop)) { - return JS_FALSE; - } - sprop = (JSScopeProperty *) prop; - } - } else if (pobj != obj) { - /* Clone the prototype property so we can watch the right object. */ - jsval value; - JSPropertyOp getter, setter; - uintN attrs, flags; - intN shortid; - - if (OBJ_IS_NATIVE(pobj)) { - value = SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(pobj)) - ? LOCKED_OBJ_GET_SLOT(pobj, sprop->slot) - : JSVAL_VOID; - getter = sprop->getter; - setter = sprop->setter; - attrs = sprop->attrs; - flags = sprop->flags; - shortid = sprop->shortid; - } else { - if (!OBJ_GET_PROPERTY(cx, pobj, id, &value) || - !OBJ_GET_ATTRIBUTES(cx, pobj, id, prop, &attrs)) { - OBJ_DROP_PROPERTY(cx, pobj, prop); - return JS_FALSE; - } - getter = setter = NULL; - flags = 0; - shortid = 0; - } - OBJ_DROP_PROPERTY(cx, pobj, prop); - - /* Recall that obj is native, whether or not pobj is native. */ - if (!js_DefineNativeProperty(cx, obj, propid, value, getter, setter, - attrs, flags, shortid, &prop)) { - return JS_FALSE; - } - sprop = (JSScopeProperty *) prop; - } - - /* - * At this point, prop/sprop exists in obj, obj is locked, and we must - * OBJ_DROP_PROPERTY(cx, obj, prop) before returning. - */ - ok = JS_TRUE; - wp = FindWatchPoint(rt, OBJ_SCOPE(obj), propid); - if (!wp) { - watcher = js_WrapWatchedSetter(cx, propid, sprop->attrs, sprop->setter); - if (!watcher) { - ok = JS_FALSE; - goto out; - } - - wp = (JSWatchPoint *) JS_malloc(cx, sizeof *wp); - if (!wp) { - ok = JS_FALSE; - goto out; - } - wp->handler = NULL; - wp->closure = NULL; - ok = js_AddRoot(cx, &wp->closure, "wp->closure"); - if (!ok) { - JS_free(cx, wp); - goto out; - } - wp->object = obj; - JS_ASSERT(sprop->setter != js_watch_set || pobj != obj); - wp->setter = sprop->setter; - wp->nrefs = 1; - - /* XXXbe nest in obj lock here */ - sprop = js_ChangeNativePropertyAttrs(cx, obj, sprop, 0, sprop->attrs, - sprop->getter, watcher); - if (!sprop) { - /* Self-link wp->links so DropWatchPoint can JS_REMOVE_LINK it. */ - JS_INIT_CLIST(&wp->links); - DropWatchPoint(cx, wp); - ok = JS_FALSE; - goto out; - } - wp->sprop = sprop; - - /* Now that wp is fully initialized, append it to rt's wp list. */ - JS_APPEND_LINK(&wp->links, &rt->watchPointList); - } - wp->handler = handler; - wp->closure = closure; - -out: - OBJ_DROP_PROPERTY(cx, obj, prop); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_ClearWatchPoint(JSContext *cx, JSObject *obj, jsval id, - JSWatchPointHandler *handlerp, void **closurep) -{ - JSRuntime *rt; - JSWatchPoint *wp; - - rt = cx->runtime; - for (wp = (JSWatchPoint *)rt->watchPointList.next; - wp != (JSWatchPoint *)&rt->watchPointList; - wp = (JSWatchPoint *)wp->links.next) { - if (wp->object == obj && SPROP_USERID(wp->sprop) == id) { - if (handlerp) - *handlerp = wp->handler; - if (closurep) - *closurep = wp->closure; - return DropWatchPoint(cx, wp); - } - } - if (handlerp) - *handlerp = NULL; - if (closurep) - *closurep = NULL; - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_ClearWatchPointsForObject(JSContext *cx, JSObject *obj) -{ - JSRuntime *rt; - JSWatchPoint *wp, *next; - - rt = cx->runtime; - for (wp = (JSWatchPoint *)rt->watchPointList.next; - wp != (JSWatchPoint *)&rt->watchPointList; - wp = next) { - next = (JSWatchPoint *)wp->links.next; - if (wp->object == obj && !DropWatchPoint(cx, wp)) - return JS_FALSE; - } - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_ClearAllWatchPoints(JSContext *cx) -{ - JSRuntime *rt; - JSWatchPoint *wp, *next; - - rt = cx->runtime; - for (wp = (JSWatchPoint *)rt->watchPointList.next; - wp != (JSWatchPoint *)&rt->watchPointList; - wp = next) { - next = (JSWatchPoint *)wp->links.next; - if (!DropWatchPoint(cx, wp)) - return JS_FALSE; - } - return JS_TRUE; -} - -/************************************************************************/ - -JS_PUBLIC_API(uintN) -JS_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc) -{ - return js_PCToLineNumber(cx, script, pc); -} - -JS_PUBLIC_API(jsbytecode *) -JS_LineNumberToPC(JSContext *cx, JSScript *script, uintN lineno) -{ - return js_LineNumberToPC(script, lineno); -} - -JS_PUBLIC_API(JSScript *) -JS_GetFunctionScript(JSContext *cx, JSFunction *fun) -{ - return FUN_SCRIPT(fun); -} - -JS_PUBLIC_API(JSNative) -JS_GetFunctionNative(JSContext *cx, JSFunction *fun) -{ - return FUN_NATIVE(fun); -} - -JS_PUBLIC_API(JSPrincipals *) -JS_GetScriptPrincipals(JSContext *cx, JSScript *script) -{ - return script->principals; -} - -/************************************************************************/ - -/* - * Stack Frame Iterator - */ -JS_PUBLIC_API(JSStackFrame *) -JS_FrameIterator(JSContext *cx, JSStackFrame **iteratorp) -{ - *iteratorp = (*iteratorp == NULL) ? cx->fp : (*iteratorp)->down; - return *iteratorp; -} - -JS_PUBLIC_API(JSScript *) -JS_GetFrameScript(JSContext *cx, JSStackFrame *fp) -{ - return fp->script; -} - -JS_PUBLIC_API(jsbytecode *) -JS_GetFramePC(JSContext *cx, JSStackFrame *fp) -{ - return fp->pc; -} - -JS_PUBLIC_API(JSStackFrame *) -JS_GetScriptedCaller(JSContext *cx, JSStackFrame *fp) -{ - if (!fp) - fp = cx->fp; - while ((fp = fp->down) != NULL) { - if (fp->script) - return fp; - } - return NULL; -} - -JS_PUBLIC_API(JSPrincipals *) -JS_StackFramePrincipals(JSContext *cx, JSStackFrame *fp) -{ - if (fp->fun) { - JSRuntime *rt = cx->runtime; - - if (rt->findObjectPrincipals) { - JSObject *callee = JSVAL_TO_OBJECT(fp->argv[-2]); - - if (fp->fun->object != callee) - return rt->findObjectPrincipals(cx, callee); - /* FALL THROUGH */ - } - } - if (fp->script) - return fp->script->principals; - return NULL; -} - -JS_PUBLIC_API(JSPrincipals *) -JS_EvalFramePrincipals(JSContext *cx, JSStackFrame *fp, JSStackFrame *caller) -{ - JSRuntime *rt; - JSObject *callee; - JSPrincipals *principals, *callerPrincipals; - - rt = cx->runtime; - if (rt->findObjectPrincipals) { - callee = JSVAL_TO_OBJECT(fp->argv[-2]); - principals = rt->findObjectPrincipals(cx, callee); - } else { - principals = NULL; - } - if (!caller) - return principals; - callerPrincipals = JS_StackFramePrincipals(cx, caller); - return (callerPrincipals && principals && - callerPrincipals->subsume(callerPrincipals, principals)) - ? principals - : callerPrincipals; -} - -JS_PUBLIC_API(void *) -JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fp) -{ - if (fp->annotation && fp->script) { - JSPrincipals *principals = JS_StackFramePrincipals(cx, fp); - - if (principals && principals->globalPrivilegesEnabled(cx, principals)) { - /* - * Give out an annotation only if privileges have not been revoked - * or disabled globally. - */ - return fp->annotation; - } - } - - return NULL; -} - -JS_PUBLIC_API(void) -JS_SetFrameAnnotation(JSContext *cx, JSStackFrame *fp, void *annotation) -{ - fp->annotation = annotation; -} - -JS_PUBLIC_API(void *) -JS_GetFramePrincipalArray(JSContext *cx, JSStackFrame *fp) -{ - JSPrincipals *principals; - - principals = JS_StackFramePrincipals(cx, fp); - if (!principals) - return NULL; - return principals->getPrincipalArray(cx, principals); -} - -JS_PUBLIC_API(JSBool) -JS_IsNativeFrame(JSContext *cx, JSStackFrame *fp) -{ - return !fp->script; -} - -/* this is deprecated, use JS_GetFrameScopeChain instead */ -JS_PUBLIC_API(JSObject *) -JS_GetFrameObject(JSContext *cx, JSStackFrame *fp) -{ - return fp->scopeChain; -} - -JS_PUBLIC_API(JSObject *) -JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fp) -{ - /* Force creation of argument and call objects if not yet created */ - (void) JS_GetFrameCallObject(cx, fp); - return fp->scopeChain; -} - -JS_PUBLIC_API(JSObject *) -JS_GetFrameCallObject(JSContext *cx, JSStackFrame *fp) -{ - if (! fp->fun) - return NULL; -#if JS_HAS_ARGS_OBJECT - /* Force creation of argument object if not yet created */ - (void) js_GetArgsObject(cx, fp); -#endif -#if JS_HAS_CALL_OBJECT - /* - * XXX ill-defined: null return here means error was reported, unlike a - * null returned above or in the #else - */ - return js_GetCallObject(cx, fp, NULL); -#else - return NULL; -#endif /* JS_HAS_CALL_OBJECT */ -} - - -JS_PUBLIC_API(JSObject *) -JS_GetFrameThis(JSContext *cx, JSStackFrame *fp) -{ - return fp->thisp; -} - -JS_PUBLIC_API(JSFunction *) -JS_GetFrameFunction(JSContext *cx, JSStackFrame *fp) -{ - return fp->fun; -} - -JS_PUBLIC_API(JSObject *) -JS_GetFrameFunctionObject(JSContext *cx, JSStackFrame *fp) -{ - return fp->argv && fp->fun ? JSVAL_TO_OBJECT(fp->argv[-2]) : NULL; -} - -JS_PUBLIC_API(JSBool) -JS_IsConstructorFrame(JSContext *cx, JSStackFrame *fp) -{ - return (fp->flags & JSFRAME_CONSTRUCTING) != 0; -} - -JS_PUBLIC_API(JSObject *) -JS_GetFrameCalleeObject(JSContext *cx, JSStackFrame *fp) -{ - return fp->argv ? JSVAL_TO_OBJECT(fp->argv[-2]) : NULL; -} - -JS_PUBLIC_API(JSBool) -JS_IsDebuggerFrame(JSContext *cx, JSStackFrame *fp) -{ - return (fp->flags & JSFRAME_DEBUGGER) != 0; -} - -JS_PUBLIC_API(jsval) -JS_GetFrameReturnValue(JSContext *cx, JSStackFrame *fp) -{ - return fp->rval; -} - -JS_PUBLIC_API(void) -JS_SetFrameReturnValue(JSContext *cx, JSStackFrame *fp, jsval rval) -{ - fp->rval = rval; -} - -/************************************************************************/ - -JS_PUBLIC_API(const char *) -JS_GetScriptFilename(JSContext *cx, JSScript *script) -{ - return script->filename; -} - -JS_PUBLIC_API(uintN) -JS_GetScriptBaseLineNumber(JSContext *cx, JSScript *script) -{ - return script->lineno; -} - -JS_PUBLIC_API(uintN) -JS_GetScriptLineExtent(JSContext *cx, JSScript *script) -{ - return js_GetScriptLineExtent(script); -} - -JS_PUBLIC_API(JSVersion) -JS_GetScriptVersion(JSContext *cx, JSScript *script) -{ - return script->version & JSVERSION_MASK; -} - -/***************************************************************************/ - -JS_PUBLIC_API(void) -JS_SetNewScriptHook(JSRuntime *rt, JSNewScriptHook hook, void *callerdata) -{ - rt->newScriptHook = hook; - rt->newScriptHookData = callerdata; -} - -JS_PUBLIC_API(void) -JS_SetDestroyScriptHook(JSRuntime *rt, JSDestroyScriptHook hook, - void *callerdata) -{ - rt->destroyScriptHook = hook; - rt->destroyScriptHookData = callerdata; -} - -/***************************************************************************/ - -JS_PUBLIC_API(JSBool) -JS_EvaluateUCInStackFrame(JSContext *cx, JSStackFrame *fp, - const jschar *bytes, uintN length, - const char *filename, uintN lineno, - jsval *rval) -{ - uint32 flags, options; - JSScript *script; - JSBool ok; - - /* - * XXX Hack around ancient compiler API to propagate the JSFRAME_SPECIAL - * flags to the code generator (see js_EmitTree's TOK_SEMI case). - */ - flags = fp->flags; - fp->flags |= JSFRAME_DEBUGGER | JSFRAME_EVAL; - options = cx->options; - cx->options = options | JSOPTION_COMPILE_N_GO; - script = JS_CompileUCScriptForPrincipals(cx, fp->scopeChain, - JS_StackFramePrincipals(cx, fp), - bytes, length, filename, lineno); - fp->flags = flags; - cx->options = options; - if (!script) - return JS_FALSE; - - ok = js_Execute(cx, fp->scopeChain, script, fp, - JSFRAME_DEBUGGER | JSFRAME_EVAL, rval); - js_DestroyScript(cx, script); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_EvaluateInStackFrame(JSContext *cx, JSStackFrame *fp, - const char *bytes, uintN nbytes, - const char *filename, uintN lineno, - jsval *rval) -{ - size_t length = nbytes; - jschar *chars; - JSBool ok; - - chars = js_InflateString(cx, bytes, &length); - if (!chars) - return JS_FALSE; - ok = JS_EvaluateUCInStackFrame(cx, fp, chars, length, filename, lineno, - rval); - JS_free(cx, chars); - - return ok; -} - -/************************************************************************/ - -/* XXXbe this all needs to be reworked to avoid requiring JSScope types. */ - -JS_PUBLIC_API(JSScopeProperty *) -JS_PropertyIterator(JSObject *obj, JSScopeProperty **iteratorp) -{ - JSScopeProperty *sprop; - JSScope *scope; - - sprop = *iteratorp; - scope = OBJ_SCOPE(obj); - - /* XXXbe minor(?) incompatibility: iterate in reverse definition order */ - if (!sprop) { - sprop = SCOPE_LAST_PROP(scope); - } else { - while ((sprop = sprop->parent) != NULL) { - if (!SCOPE_HAD_MIDDLE_DELETE(scope)) - break; - if (SCOPE_HAS_PROPERTY(scope, sprop)) - break; - } - } - *iteratorp = sprop; - return sprop; -} - -JS_PUBLIC_API(JSBool) -JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop, - JSPropertyDesc *pd) -{ - JSPropertyOp getter; - JSScope *scope; - JSScopeProperty *aprop; - jsval lastException; - JSBool wasThrowing; - - pd->id = ID_TO_VALUE(sprop->id); - - wasThrowing = cx->throwing; - if (wasThrowing) { - lastException = cx->exception; - if (JSVAL_IS_GCTHING(lastException) && - !js_AddRoot(cx, &lastException, "lastException")) { - return JS_FALSE; - } - cx->throwing = JS_FALSE; - } - - if (!js_GetProperty(cx, obj, sprop->id, &pd->value)) { - if (!cx->throwing) { - pd->flags = JSPD_ERROR; - pd->value = JSVAL_VOID; - } else { - pd->flags = JSPD_EXCEPTION; - pd->value = cx->exception; - } - } else { - pd->flags = 0; - } - - cx->throwing = wasThrowing; - if (wasThrowing) { - cx->exception = lastException; - if (JSVAL_IS_GCTHING(lastException)) - js_RemoveRoot(cx->runtime, &lastException); - } - - getter = sprop->getter; - pd->flags |= ((sprop->attrs & JSPROP_ENUMERATE) ? JSPD_ENUMERATE : 0) - | ((sprop->attrs & JSPROP_READONLY) ? JSPD_READONLY : 0) - | ((sprop->attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0) -#if JS_HAS_CALL_OBJECT - | ((getter == js_GetCallVariable) ? JSPD_VARIABLE : 0) -#endif /* JS_HAS_CALL_OBJECT */ - | ((getter == js_GetArgument) ? JSPD_ARGUMENT : 0) - | ((getter == js_GetLocalVariable) ? JSPD_VARIABLE : 0); -#if JS_HAS_CALL_OBJECT - /* for Call Object 'real' getter isn't passed in to us */ - if (OBJ_GET_CLASS(cx, obj) == &js_CallClass && - getter == js_CallClass.getProperty) { - /* - * Property of a heavyweight function's variable object having the - * class-default getter. It's either an argument if permanent, or a - * nested function if impermanent. Local variables have a special - * getter (js_GetCallVariable, tested above) and setter, and not the - * class default. - */ - pd->flags |= (sprop->attrs & JSPROP_PERMANENT) - ? JSPD_ARGUMENT - : JSPD_VARIABLE; - } -#endif /* JS_HAS_CALL_OBJECT */ - pd->spare = 0; - pd->slot = (pd->flags & (JSPD_ARGUMENT | JSPD_VARIABLE)) - ? sprop->shortid - : 0; - pd->alias = JSVAL_VOID; - scope = OBJ_SCOPE(obj); - if (SPROP_HAS_VALID_SLOT(sprop, scope)) { - for (aprop = SCOPE_LAST_PROP(scope); aprop; aprop = aprop->parent) { - if (aprop != sprop && aprop->slot == sprop->slot) { - pd->alias = ID_TO_VALUE(aprop->id); - break; - } - } - } - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda) -{ - JSClass *clasp; - JSScope *scope; - uint32 i, n; - JSPropertyDesc *pd; - JSScopeProperty *sprop; - - clasp = OBJ_GET_CLASS(cx, obj); - if (!OBJ_IS_NATIVE(obj) || (clasp->flags & JSCLASS_NEW_ENUMERATE)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_CANT_DESCRIBE_PROPS, clasp->name); - return JS_FALSE; - } - if (!clasp->enumerate(cx, obj)) - return JS_FALSE; - - /* have no props, or object's scope has not mutated from that of proto */ - scope = OBJ_SCOPE(obj); - if (scope->object != obj || scope->entryCount == 0) { - pda->length = 0; - pda->array = NULL; - return JS_TRUE; - } - - n = scope->entryCount; - if (n > scope->map.nslots) - n = scope->map.nslots; - pd = (JSPropertyDesc *) JS_malloc(cx, (size_t)n * sizeof(JSPropertyDesc)); - if (!pd) - return JS_FALSE; - i = 0; - for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) { - if (SCOPE_HAD_MIDDLE_DELETE(scope) && !SCOPE_HAS_PROPERTY(scope, sprop)) - continue; - if (!js_AddRoot(cx, &pd[i].id, NULL)) - goto bad; - if (!js_AddRoot(cx, &pd[i].value, NULL)) - goto bad; - if (!JS_GetPropertyDesc(cx, obj, sprop, &pd[i])) - goto bad; - if ((pd[i].flags & JSPD_ALIAS) && !js_AddRoot(cx, &pd[i].alias, NULL)) - goto bad; - if (++i == n) - break; - } - pda->length = i; - pda->array = pd; - return JS_TRUE; - -bad: - pda->length = i + 1; - pda->array = pd; - JS_PutPropertyDescArray(cx, pda); - return JS_FALSE; -} - -JS_PUBLIC_API(void) -JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda) -{ - JSPropertyDesc *pd; - uint32 i; - - pd = pda->array; - for (i = 0; i < pda->length; i++) { - js_RemoveRoot(cx->runtime, &pd[i].id); - js_RemoveRoot(cx->runtime, &pd[i].value); - if (pd[i].flags & JSPD_ALIAS) - js_RemoveRoot(cx->runtime, &pd[i].alias); - } - JS_free(cx, pd); -} - -/************************************************************************/ - -JS_PUBLIC_API(JSBool) -JS_SetDebuggerHandler(JSRuntime *rt, JSTrapHandler handler, void *closure) -{ - rt->debuggerHandler = handler; - rt->debuggerHandlerData = closure; - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_SetSourceHandler(JSRuntime *rt, JSSourceHandler handler, void *closure) -{ - rt->sourceHandler = handler; - rt->sourceHandlerData = closure; - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_SetExecuteHook(JSRuntime *rt, JSInterpreterHook hook, void *closure) -{ - rt->executeHook = hook; - rt->executeHookData = closure; - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_SetCallHook(JSRuntime *rt, JSInterpreterHook hook, void *closure) -{ - rt->callHook = hook; - rt->callHookData = closure; - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_SetObjectHook(JSRuntime *rt, JSObjectHook hook, void *closure) -{ - rt->objectHook = hook; - rt->objectHookData = closure; - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_SetThrowHook(JSRuntime *rt, JSTrapHandler hook, void *closure) -{ - rt->throwHook = hook; - rt->throwHookData = closure; - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_SetDebugErrorHook(JSRuntime *rt, JSDebugErrorHook hook, void *closure) -{ - rt->debugErrorHook = hook; - rt->debugErrorHookData = closure; - return JS_TRUE; -} - -/************************************************************************/ - -JS_PUBLIC_API(size_t) -JS_GetObjectTotalSize(JSContext *cx, JSObject *obj) -{ - size_t nbytes; - JSScope *scope; - - nbytes = sizeof *obj + obj->map->nslots * sizeof obj->slots[0]; - if (OBJ_IS_NATIVE(obj)) { - scope = OBJ_SCOPE(obj); - if (scope->object == obj) { - nbytes += sizeof *scope; - nbytes += SCOPE_CAPACITY(scope) * sizeof(JSScopeProperty *); - } - } - return nbytes; -} - -static size_t -GetAtomTotalSize(JSContext *cx, JSAtom *atom) -{ - size_t nbytes; - - nbytes = sizeof *atom; - if (ATOM_IS_STRING(atom)) { - nbytes += sizeof(JSString); - nbytes += (ATOM_TO_STRING(atom)->length + 1) * sizeof(jschar); - } else if (ATOM_IS_DOUBLE(atom)) { - nbytes += sizeof(jsdouble); - } else if (ATOM_IS_OBJECT(atom)) { - nbytes += JS_GetObjectTotalSize(cx, ATOM_TO_OBJECT(atom)); - } - return nbytes; -} - -JS_PUBLIC_API(size_t) -JS_GetFunctionTotalSize(JSContext *cx, JSFunction *fun) -{ - size_t nbytes, obytes; - JSObject *obj; - JSAtom *atom; - - nbytes = sizeof *fun; - JS_ASSERT(fun->nrefs); - obj = fun->object; - if (obj) { - obytes = JS_GetObjectTotalSize(cx, obj); - if (fun->nrefs > 1) - obytes = JS_HOWMANY(obytes, fun->nrefs); - nbytes += obytes; - } - if (fun->interpreted) - nbytes += JS_GetScriptTotalSize(cx, fun->u.script); - atom = fun->atom; - if (atom) - nbytes += GetAtomTotalSize(cx, atom); - return nbytes; -} - -#include "jsemit.h" - -JS_PUBLIC_API(size_t) -JS_GetScriptTotalSize(JSContext *cx, JSScript *script) -{ - size_t nbytes, pbytes; - JSObject *obj; - jsatomid i; - jssrcnote *sn, *notes; - JSTryNote *tn, *tnotes; - JSPrincipals *principals; - - nbytes = sizeof *script; - obj = script->object; - if (obj) - nbytes += JS_GetObjectTotalSize(cx, obj); - - nbytes += script->length * sizeof script->code[0]; - nbytes += script->atomMap.length * sizeof script->atomMap.vector[0]; - for (i = 0; i < script->atomMap.length; i++) - nbytes += GetAtomTotalSize(cx, script->atomMap.vector[i]); - - if (script->filename) - nbytes += strlen(script->filename) + 1; - - notes = SCRIPT_NOTES(script); - for (sn = notes; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) - continue; - nbytes += (sn - notes + 1) * sizeof *sn; - - tnotes = script->trynotes; - if (tnotes) { - for (tn = tnotes; tn->catchStart; tn++) - continue; - nbytes += (tn - tnotes + 1) * sizeof *tn; - } - - principals = script->principals; - if (principals) { - JS_ASSERT(principals->refcount); - pbytes = sizeof *principals; - if (principals->refcount > 1) - pbytes = JS_HOWMANY(pbytes, principals->refcount); - nbytes += pbytes; - } - - return nbytes; -} - -JS_PUBLIC_API(uint32) -JS_GetTopScriptFilenameFlags(JSContext *cx, JSStackFrame *fp) -{ - if (!fp) - fp = cx->fp; - while (fp) { - if (fp->script) { - return JS_GetScriptFilenameFlags(fp->script); - } - fp = fp->down; - } - return 0; - } - -JS_PUBLIC_API(uint32) -JS_GetScriptFilenameFlags(JSScript *script) -{ - JS_ASSERT(script); - if (!script->filename) - return JSFILENAME_NULL; - return js_GetScriptFilenameFlags(script->filename); -} - -JS_PUBLIC_API(JSBool) -JS_FlagScriptFilenamePrefix(JSRuntime *rt, const char *prefix, uint32 flags) -{ - if (!js_SaveScriptFilenameRT(rt, prefix, flags)) - return JS_FALSE; - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_IsSystemObject(JSContext *cx, JSObject *obj) -{ - return (*js_GetGCThingFlags(obj) & GCF_SYSTEM) != 0; -} - -JS_PUBLIC_API(void) -JS_FlagSystemObject(JSContext *cx, JSObject *obj) -{ - uint8 *flagp; - - flagp = js_GetGCThingFlags(obj); - *flagp |= GCF_SYSTEM; -} diff --git a/lib/javascript/jsdbgapi.h b/lib/javascript/jsdbgapi.h deleted file mode 100644 index d1b13d9d..00000000 --- a/lib/javascript/jsdbgapi.h +++ /dev/null @@ -1,406 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jsdbgapi_h___ -#define jsdbgapi_h___ -/* - * JS debugger API. - */ -#include "jsapi.h" -#include "jsopcode.h" -#include "jsprvtd.h" - -JS_BEGIN_EXTERN_C - -extern void -js_PatchOpcode(JSContext *cx, JSScript *script, jsbytecode *pc, JSOp op); - -extern JS_PUBLIC_API(JSBool) -JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc, - JSTrapHandler handler, void *closure); - -extern JS_PUBLIC_API(JSOp) -JS_GetTrapOpcode(JSContext *cx, JSScript *script, jsbytecode *pc); - -extern JS_PUBLIC_API(void) -JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc, - JSTrapHandler *handlerp, void **closurep); - -extern JS_PUBLIC_API(void) -JS_ClearScriptTraps(JSContext *cx, JSScript *script); - -extern JS_PUBLIC_API(void) -JS_ClearAllTraps(JSContext *cx); - -extern JS_PUBLIC_API(JSTrapStatus) -JS_HandleTrap(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval); - -extern JS_PUBLIC_API(JSBool) -JS_SetInterrupt(JSRuntime *rt, JSTrapHandler handler, void *closure); - -extern JS_PUBLIC_API(JSBool) -JS_ClearInterrupt(JSRuntime *rt, JSTrapHandler *handlerp, void **closurep); - -/************************************************************************/ - -extern JS_PUBLIC_API(JSBool) -JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval id, - JSWatchPointHandler handler, void *closure); - -extern JS_PUBLIC_API(JSBool) -JS_ClearWatchPoint(JSContext *cx, JSObject *obj, jsval id, - JSWatchPointHandler *handlerp, void **closurep); - -extern JS_PUBLIC_API(JSBool) -JS_ClearWatchPointsForObject(JSContext *cx, JSObject *obj); - -extern JS_PUBLIC_API(JSBool) -JS_ClearAllWatchPoints(JSContext *cx); - -#ifdef JS_HAS_OBJ_WATCHPOINT -/* - * Hide these non-API function prototypes by testing whether the internal - * header file "jsconfig.h" has been included. - */ -extern void -js_MarkWatchPoints(JSContext *cx); - -extern JSScopeProperty * -js_FindWatchPoint(JSRuntime *rt, JSScope *scope, jsid id); - -extern JSPropertyOp -js_GetWatchedSetter(JSRuntime *rt, JSScope *scope, - const JSScopeProperty *sprop); - -extern JSBool JS_DLL_CALLBACK -js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp); - -extern JSBool JS_DLL_CALLBACK -js_watch_set_wrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval); - -extern JSPropertyOp -js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter); - -#endif /* JS_HAS_OBJ_WATCHPOINT */ - -/************************************************************************/ - -extern JS_PUBLIC_API(uintN) -JS_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc); - -extern JS_PUBLIC_API(jsbytecode *) -JS_LineNumberToPC(JSContext *cx, JSScript *script, uintN lineno); - -extern JS_PUBLIC_API(JSScript *) -JS_GetFunctionScript(JSContext *cx, JSFunction *fun); - -extern JS_PUBLIC_API(JSNative) -JS_GetFunctionNative(JSContext *cx, JSFunction *fun); - -extern JS_PUBLIC_API(JSPrincipals *) -JS_GetScriptPrincipals(JSContext *cx, JSScript *script); - -/* - * Stack Frame Iterator - * - * Used to iterate through the JS stack frames to extract - * information from the frames. - */ - -extern JS_PUBLIC_API(JSStackFrame *) -JS_FrameIterator(JSContext *cx, JSStackFrame **iteratorp); - -extern JS_PUBLIC_API(JSScript *) -JS_GetFrameScript(JSContext *cx, JSStackFrame *fp); - -extern JS_PUBLIC_API(jsbytecode *) -JS_GetFramePC(JSContext *cx, JSStackFrame *fp); - -/* - * Get the closest scripted frame below fp. If fp is null, start from cx->fp. - */ -extern JS_PUBLIC_API(JSStackFrame *) -JS_GetScriptedCaller(JSContext *cx, JSStackFrame *fp); - -/* - * Return a weak reference to fp's principals. A null return does not denote - * an error, it means there are no principals. - */ -extern JS_PUBLIC_API(JSPrincipals *) -JS_StackFramePrincipals(JSContext *cx, JSStackFrame *fp); - -/* - * This API is like JS_StackFramePrincipals(cx, caller), except that if - * cx->runtime->findObjectPrincipals is non-null, it returns the weaker of - * the caller's principals and the object principals of fp's callee function - * object (fp->argv[-2]), which is eval, Function, or a similar eval-like - * method. The caller parameter should be JS_GetScriptedCaller(cx, fp). - * - * All eval-like methods must use JS_EvalFramePrincipals to acquire a weak - * reference to the correct principals for the eval call to be secure, given - * an embedding that calls JS_SetObjectPrincipalsFinder (see jsapi.h). - */ -extern JS_PUBLIC_API(JSPrincipals *) -JS_EvalFramePrincipals(JSContext *cx, JSStackFrame *fp, JSStackFrame *caller); - -extern JS_PUBLIC_API(void *) -JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fp); - -extern JS_PUBLIC_API(void) -JS_SetFrameAnnotation(JSContext *cx, JSStackFrame *fp, void *annotation); - -extern JS_PUBLIC_API(void *) -JS_GetFramePrincipalArray(JSContext *cx, JSStackFrame *fp); - -extern JS_PUBLIC_API(JSBool) -JS_IsNativeFrame(JSContext *cx, JSStackFrame *fp); - -/* this is deprecated, use JS_GetFrameScopeChain instead */ -extern JS_PUBLIC_API(JSObject *) -JS_GetFrameObject(JSContext *cx, JSStackFrame *fp); - -extern JS_PUBLIC_API(JSObject *) -JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fp); - -extern JS_PUBLIC_API(JSObject *) -JS_GetFrameCallObject(JSContext *cx, JSStackFrame *fp); - -extern JS_PUBLIC_API(JSObject *) -JS_GetFrameThis(JSContext *cx, JSStackFrame *fp); - -extern JS_PUBLIC_API(JSFunction *) -JS_GetFrameFunction(JSContext *cx, JSStackFrame *fp); - -extern JS_PUBLIC_API(JSObject *) -JS_GetFrameFunctionObject(JSContext *cx, JSStackFrame *fp); - -/* XXXrginda Initially published with typo */ -#define JS_IsContructorFrame JS_IsConstructorFrame -extern JS_PUBLIC_API(JSBool) -JS_IsConstructorFrame(JSContext *cx, JSStackFrame *fp); - -extern JS_PUBLIC_API(JSBool) -JS_IsDebuggerFrame(JSContext *cx, JSStackFrame *fp); - -extern JS_PUBLIC_API(jsval) -JS_GetFrameReturnValue(JSContext *cx, JSStackFrame *fp); - -extern JS_PUBLIC_API(void) -JS_SetFrameReturnValue(JSContext *cx, JSStackFrame *fp, jsval rval); - -/** - * Return fp's callee function object (fp->argv[-2]) if it has one. - */ -extern JS_PUBLIC_API(JSObject *) -JS_GetFrameCalleeObject(JSContext *cx, JSStackFrame *fp); - -/************************************************************************/ - -extern JS_PUBLIC_API(const char *) -JS_GetScriptFilename(JSContext *cx, JSScript *script); - -extern JS_PUBLIC_API(uintN) -JS_GetScriptBaseLineNumber(JSContext *cx, JSScript *script); - -extern JS_PUBLIC_API(uintN) -JS_GetScriptLineExtent(JSContext *cx, JSScript *script); - -extern JS_PUBLIC_API(JSVersion) -JS_GetScriptVersion(JSContext *cx, JSScript *script); - -/************************************************************************/ - -/* - * Hook setters for script creation and destruction, see jsprvtd.h for the - * typedefs. These macros provide binary compatibility and newer, shorter - * synonyms. - */ -#define JS_SetNewScriptHook JS_SetNewScriptHookProc -#define JS_SetDestroyScriptHook JS_SetDestroyScriptHookProc - -extern JS_PUBLIC_API(void) -JS_SetNewScriptHook(JSRuntime *rt, JSNewScriptHook hook, void *callerdata); - -extern JS_PUBLIC_API(void) -JS_SetDestroyScriptHook(JSRuntime *rt, JSDestroyScriptHook hook, - void *callerdata); - -/************************************************************************/ - -extern JS_PUBLIC_API(JSBool) -JS_EvaluateUCInStackFrame(JSContext *cx, JSStackFrame *fp, - const jschar *bytes, uintN length, - const char *filename, uintN lineno, - jsval *rval); - -extern JS_PUBLIC_API(JSBool) -JS_EvaluateInStackFrame(JSContext *cx, JSStackFrame *fp, - const char *bytes, uintN length, - const char *filename, uintN lineno, - jsval *rval); - -/************************************************************************/ - -typedef struct JSPropertyDesc { - jsval id; /* primary id, a string or int */ - jsval value; /* property value */ - uint8 flags; /* flags, see below */ - uint8 spare; /* unused */ - uint16 slot; /* argument/variable slot */ - jsval alias; /* alias id if JSPD_ALIAS flag */ -} JSPropertyDesc; - -#define JSPD_ENUMERATE 0x01 /* visible to for/in loop */ -#define JSPD_READONLY 0x02 /* assignment is error */ -#define JSPD_PERMANENT 0x04 /* property cannot be deleted */ -#define JSPD_ALIAS 0x08 /* property has an alias id */ -#define JSPD_ARGUMENT 0x10 /* argument to function */ -#define JSPD_VARIABLE 0x20 /* local variable in function */ -#define JSPD_EXCEPTION 0x40 /* exception occurred fetching the property, */ - /* value is exception */ -#define JSPD_ERROR 0x80 /* native getter returned JS_FALSE without */ - /* throwing an exception */ - -typedef struct JSPropertyDescArray { - uint32 length; /* number of elements in array */ - JSPropertyDesc *array; /* alloc'd by Get, freed by Put */ -} JSPropertyDescArray; - -extern JS_PUBLIC_API(JSScopeProperty *) -JS_PropertyIterator(JSObject *obj, JSScopeProperty **iteratorp); - -extern JS_PUBLIC_API(JSBool) -JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop, - JSPropertyDesc *pd); - -extern JS_PUBLIC_API(JSBool) -JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda); - -extern JS_PUBLIC_API(void) -JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda); - -/************************************************************************/ - -extern JS_PUBLIC_API(JSBool) -JS_SetDebuggerHandler(JSRuntime *rt, JSTrapHandler handler, void *closure); - -extern JS_PUBLIC_API(JSBool) -JS_SetSourceHandler(JSRuntime *rt, JSSourceHandler handler, void *closure); - -extern JS_PUBLIC_API(JSBool) -JS_SetExecuteHook(JSRuntime *rt, JSInterpreterHook hook, void *closure); - -extern JS_PUBLIC_API(JSBool) -JS_SetCallHook(JSRuntime *rt, JSInterpreterHook hook, void *closure); - -extern JS_PUBLIC_API(JSBool) -JS_SetObjectHook(JSRuntime *rt, JSObjectHook hook, void *closure); - -extern JS_PUBLIC_API(JSBool) -JS_SetThrowHook(JSRuntime *rt, JSTrapHandler hook, void *closure); - -extern JS_PUBLIC_API(JSBool) -JS_SetDebugErrorHook(JSRuntime *rt, JSDebugErrorHook hook, void *closure); - -/************************************************************************/ - -extern JS_PUBLIC_API(size_t) -JS_GetObjectTotalSize(JSContext *cx, JSObject *obj); - -extern JS_PUBLIC_API(size_t) -JS_GetFunctionTotalSize(JSContext *cx, JSFunction *fun); - -extern JS_PUBLIC_API(size_t) -JS_GetScriptTotalSize(JSContext *cx, JSScript *script); - -/* - * Get the top-most running script on cx starting from fp, or from the top of - * cx's frame stack if fp is null, and return its script filename flags. If - * the script has a null filename member, return JSFILENAME_NULL. - */ -extern JS_PUBLIC_API(uint32) -JS_GetTopScriptFilenameFlags(JSContext *cx, JSStackFrame *fp); - -/* - * Get the script filename flags for the script. If the script - * doesn't have a filename, return JSFILENAME_NULL. - */ -extern JS_PUBLIC_API(uint32) -JS_GetScriptFilenameFlags(JSScript *script); - -/* - * Associate flags with a script filename prefix in rt, so that any subsequent - * script compilation will inherit those flags if the script's filename is the - * same as prefix, or if prefix is a substring of the script's filename. - * - * The API defines only one flag bit, JSFILENAME_SYSTEM, leaving the remaining - * 31 bits up to the API client to define. The union of all 32 bits must not - * be a legal combination, however, in order to preserve JSFILENAME_NULL as a - * unique value. API clients may depend on JSFILENAME_SYSTEM being a set bit - * in JSFILENAME_NULL -- a script with a null filename member is presumed to - * be a "system" script. - */ -extern JS_PUBLIC_API(JSBool) -JS_FlagScriptFilenamePrefix(JSRuntime *rt, const char *prefix, uint32 flags); - -#define JSFILENAME_NULL 0xffffffff /* null script filename */ -#define JSFILENAME_SYSTEM 0x00000001 /* "system" script, see below */ - -/* - * Return true if obj is a "system" object, that is, one flagged by a prior - * call to JS_FlagSystemObject(cx, obj). What "system" means is up to the API - * client, but it can be used to coordinate access control policies based on - * script filenames and their prefixes, using JS_FlagScriptFilenamePrefix and - * JS_GetTopScriptFilenameFlags. - */ -extern JS_PUBLIC_API(JSBool) -JS_IsSystemObject(JSContext *cx, JSObject *obj); - -/* - * Flag obj as a "system" object. The API client can flag system objects to - * optimize access control checks. The engine stores but does not interpret - * the per-object flag set by this call. - */ -extern JS_PUBLIC_API(void) -JS_FlagSystemObject(JSContext *cx, JSObject *obj); - -JS_END_EXTERN_C - -#endif /* jsdbgapi_h___ */ diff --git a/lib/javascript/jsdhash.c b/lib/javascript/jsdhash.c deleted file mode 100644 index cd300668..00000000 --- a/lib/javascript/jsdhash.c +++ /dev/null @@ -1,767 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla JavaScript code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1999-2001 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Brendan Eich (Original Author) - * Chris Waterson - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * Double hashing implementation. - */ -#include -#include -#include -#include "jsbit.h" -#include "jsdhash.h" -#include "jsutil.h" /* for JS_ASSERT */ - -#ifdef JS_DHASHMETER -# if defined MOZILLA_CLIENT && defined DEBUG_XXXbrendan -# include "nsTraceMalloc.h" -# endif -# define METER(x) x -#else -# define METER(x) /* nothing */ -#endif - -JS_PUBLIC_API(void *) -JS_DHashAllocTable(JSDHashTable *table, uint32 nbytes) -{ - return malloc(nbytes); -} - -JS_PUBLIC_API(void) -JS_DHashFreeTable(JSDHashTable *table, void *ptr) -{ - free(ptr); -} - -JS_PUBLIC_API(JSDHashNumber) -JS_DHashStringKey(JSDHashTable *table, const void *key) -{ - JSDHashNumber h; - const unsigned char *s; - - h = 0; - for (s = key; *s != '\0'; s++) - h = (h >> (JS_DHASH_BITS - 4)) ^ (h << 4) ^ *s; - return h; -} - -JS_PUBLIC_API(const void *) -JS_DHashGetKeyStub(JSDHashTable *table, JSDHashEntryHdr *entry) -{ - JSDHashEntryStub *stub = (JSDHashEntryStub *)entry; - - return stub->key; -} - -JS_PUBLIC_API(JSDHashNumber) -JS_DHashVoidPtrKeyStub(JSDHashTable *table, const void *key) -{ - return (JSDHashNumber)(unsigned long)key >> 2; -} - -JS_PUBLIC_API(JSBool) -JS_DHashMatchEntryStub(JSDHashTable *table, - const JSDHashEntryHdr *entry, - const void *key) -{ - const JSDHashEntryStub *stub = (const JSDHashEntryStub *)entry; - - return stub->key == key; -} - -JS_PUBLIC_API(JSBool) -JS_DHashMatchStringKey(JSDHashTable *table, - const JSDHashEntryHdr *entry, - const void *key) -{ - const JSDHashEntryStub *stub = (const JSDHashEntryStub *)entry; - - /* XXX tolerate null keys on account of sloppy Mozilla callers. */ - return stub->key == key || - (stub->key && key && strcmp(stub->key, key) == 0); -} - -JS_PUBLIC_API(void) -JS_DHashMoveEntryStub(JSDHashTable *table, - const JSDHashEntryHdr *from, - JSDHashEntryHdr *to) -{ - memcpy(to, from, table->entrySize); -} - -JS_PUBLIC_API(void) -JS_DHashClearEntryStub(JSDHashTable *table, JSDHashEntryHdr *entry) -{ - memset(entry, 0, table->entrySize); -} - -JS_PUBLIC_API(void) -JS_DHashFreeStringKey(JSDHashTable *table, JSDHashEntryHdr *entry) -{ - const JSDHashEntryStub *stub = (const JSDHashEntryStub *)entry; - - free((void *) stub->key); - memset(entry, 0, table->entrySize); -} - -JS_PUBLIC_API(void) -JS_DHashFinalizeStub(JSDHashTable *table) -{ -} - -static const JSDHashTableOps stub_ops = { - JS_DHashAllocTable, - JS_DHashFreeTable, - JS_DHashGetKeyStub, - JS_DHashVoidPtrKeyStub, - JS_DHashMatchEntryStub, - JS_DHashMoveEntryStub, - JS_DHashClearEntryStub, - JS_DHashFinalizeStub, - NULL -}; - -JS_PUBLIC_API(const JSDHashTableOps *) -JS_DHashGetStubOps(void) -{ - return &stub_ops; -} - -JS_PUBLIC_API(JSDHashTable *) -JS_NewDHashTable(const JSDHashTableOps *ops, void *data, uint32 entrySize, - uint32 capacity) -{ - JSDHashTable *table; - - table = (JSDHashTable *) malloc(sizeof *table); - if (!table) - return NULL; - if (!JS_DHashTableInit(table, ops, data, entrySize, capacity)) { - free(table); - return NULL; - } - return table; -} - -JS_PUBLIC_API(void) -JS_DHashTableDestroy(JSDHashTable *table) -{ - JS_DHashTableFinish(table); - free(table); -} - -JS_PUBLIC_API(JSBool) -JS_DHashTableInit(JSDHashTable *table, const JSDHashTableOps *ops, void *data, - uint32 entrySize, uint32 capacity) -{ - int log2; - uint32 nbytes; - -#ifdef DEBUG - if (entrySize > 10 * sizeof(void *)) { - fprintf(stderr, - "jsdhash: for the table at address %p, the given entrySize" - " of %lu %s favors chaining over double hashing.\n", - (void *)table, - (unsigned long) entrySize, - (entrySize > 16 * sizeof(void*)) ? "definitely" : "probably"); - } -#endif - - table->ops = ops; - table->data = data; - if (capacity < JS_DHASH_MIN_SIZE) - capacity = JS_DHASH_MIN_SIZE; - - JS_CEILING_LOG2(log2, capacity); - - capacity = JS_BIT(log2); - if (capacity >= JS_DHASH_SIZE_LIMIT) - return JS_FALSE; - table->hashShift = JS_DHASH_BITS - log2; - table->maxAlphaFrac = 0xC0; /* .75 */ - table->minAlphaFrac = 0x40; /* .25 */ - table->entrySize = entrySize; - table->entryCount = table->removedCount = 0; - table->generation = 0; - nbytes = capacity * entrySize; - - table->entryStore = ops->allocTable(table, nbytes); - if (!table->entryStore) - return JS_FALSE; - memset(table->entryStore, 0, nbytes); - METER(memset(&table->stats, 0, sizeof table->stats)); - return JS_TRUE; -} - -/* - * Compute max and min load numbers (entry counts) from table params. - */ -#define MAX_LOAD(table, size) (((table)->maxAlphaFrac * (size)) >> 8) -#define MIN_LOAD(table, size) (((table)->minAlphaFrac * (size)) >> 8) - -JS_PUBLIC_API(void) -JS_DHashTableSetAlphaBounds(JSDHashTable *table, - float maxAlpha, - float minAlpha) -{ - uint32 size; - - /* - * Reject obviously insane bounds, rather than trying to guess what the - * buggy caller intended. - */ - JS_ASSERT(0.5 <= maxAlpha && maxAlpha < 1 && 0 <= minAlpha); - if (maxAlpha < 0.5 || 1 <= maxAlpha || minAlpha < 0) - return; - - /* - * Ensure that at least one entry will always be free. If maxAlpha at - * minimum size leaves no entries free, reduce maxAlpha based on minimum - * size and the precision limit of maxAlphaFrac's fixed point format. - */ - JS_ASSERT(JS_DHASH_MIN_SIZE - (maxAlpha * JS_DHASH_MIN_SIZE) >= 1); - if (JS_DHASH_MIN_SIZE - (maxAlpha * JS_DHASH_MIN_SIZE) < 1) { - maxAlpha = (float) - (JS_DHASH_MIN_SIZE - JS_MAX(JS_DHASH_MIN_SIZE / 256, 1)) - / JS_DHASH_MIN_SIZE; - } - - /* - * Ensure that minAlpha is strictly less than half maxAlpha. Take care - * not to truncate an entry's worth of alpha when storing in minAlphaFrac - * (8-bit fixed point format). - */ - JS_ASSERT(minAlpha < maxAlpha / 2); - if (minAlpha >= maxAlpha / 2) { - size = JS_DHASH_TABLE_SIZE(table); - minAlpha = (size * maxAlpha - JS_MAX(size / 256, 1)) / (2 * size); - } - - table->maxAlphaFrac = (uint8)(maxAlpha * 256); - table->minAlphaFrac = (uint8)(minAlpha * 256); -} - -/* - * Double hashing needs the second hash code to be relatively prime to table - * size, so we simply make hash2 odd. - */ -#define HASH1(hash0, shift) ((hash0) >> (shift)) -#define HASH2(hash0,log2,shift) ((((hash0) << (log2)) >> (shift)) | 1) - -/* - * Reserve keyHash 0 for free entries and 1 for removed-entry sentinels. Note - * that a removed-entry sentinel need be stored only if the removed entry had - * a colliding entry added after it. Therefore we can use 1 as the collision - * flag in addition to the removed-entry sentinel value. Multiplicative hash - * uses the high order bits of keyHash, so this least-significant reservation - * should not hurt the hash function's effectiveness much. - * - * If you change any of these magic numbers, also update JS_DHASH_ENTRY_IS_LIVE - * in jsdhash.h. It used to be private to jsdhash.c, but then became public to - * assist iterator writers who inspect table->entryStore directly. - */ -#define COLLISION_FLAG ((JSDHashNumber) 1) -#define MARK_ENTRY_FREE(entry) ((entry)->keyHash = 0) -#define MARK_ENTRY_REMOVED(entry) ((entry)->keyHash = 1) -#define ENTRY_IS_REMOVED(entry) ((entry)->keyHash == 1) -#define ENTRY_IS_LIVE(entry) JS_DHASH_ENTRY_IS_LIVE(entry) -#define ENSURE_LIVE_KEYHASH(hash0) if (hash0 < 2) hash0 -= 2; else (void)0 - -/* Match an entry's keyHash against an unstored one computed from a key. */ -#define MATCH_ENTRY_KEYHASH(entry,hash0) \ - (((entry)->keyHash & ~COLLISION_FLAG) == (hash0)) - -/* Compute the address of the indexed entry in table. */ -#define ADDRESS_ENTRY(table, index) \ - ((JSDHashEntryHdr *)((table)->entryStore + (index) * (table)->entrySize)) - -JS_PUBLIC_API(void) -JS_DHashTableFinish(JSDHashTable *table) -{ - char *entryAddr, *entryLimit; - uint32 entrySize; - JSDHashEntryHdr *entry; - -#ifdef DEBUG_XXXbrendan - static FILE *dumpfp = NULL; - if (!dumpfp) dumpfp = fopen("/tmp/jsdhash.bigdump", "w"); - if (dumpfp) { -#ifdef MOZILLA_CLIENT - NS_TraceStack(1, dumpfp); -#endif - JS_DHashTableDumpMeter(table, NULL, dumpfp); - fputc('\n', dumpfp); - } -#endif - - /* Call finalize before clearing entries, so it can enumerate them. */ - table->ops->finalize(table); - - /* Clear any remaining live entries. */ - entryAddr = table->entryStore; - entrySize = table->entrySize; - entryLimit = entryAddr + JS_DHASH_TABLE_SIZE(table) * entrySize; - while (entryAddr < entryLimit) { - entry = (JSDHashEntryHdr *)entryAddr; - if (ENTRY_IS_LIVE(entry)) { - METER(table->stats.removeEnums++); - table->ops->clearEntry(table, entry); - } - entryAddr += entrySize; - } - - /* Free entry storage last. */ - table->ops->freeTable(table, table->entryStore); -} - -static JSDHashEntryHdr * JS_DHASH_FASTCALL -SearchTable(JSDHashTable *table, const void *key, JSDHashNumber keyHash, - JSDHashOperator op) -{ - JSDHashNumber hash1, hash2; - int hashShift, sizeLog2; - JSDHashEntryHdr *entry, *firstRemoved; - JSDHashMatchEntry matchEntry; - uint32 sizeMask; - - METER(table->stats.searches++); - JS_ASSERT(!(keyHash & COLLISION_FLAG)); - - /* Compute the primary hash address. */ - hashShift = table->hashShift; - hash1 = HASH1(keyHash, hashShift); - entry = ADDRESS_ENTRY(table, hash1); - - /* Miss: return space for a new entry. */ - if (JS_DHASH_ENTRY_IS_FREE(entry)) { - METER(table->stats.misses++); - return entry; - } - - /* Hit: return entry. */ - matchEntry = table->ops->matchEntry; - if (MATCH_ENTRY_KEYHASH(entry, keyHash) && matchEntry(table, entry, key)) { - METER(table->stats.hits++); - return entry; - } - - /* Collision: double hash. */ - sizeLog2 = JS_DHASH_BITS - table->hashShift; - hash2 = HASH2(keyHash, sizeLog2, hashShift); - sizeMask = JS_BITMASK(sizeLog2); - - /* Save the first removed entry pointer so JS_DHASH_ADD can recycle it. */ - if (ENTRY_IS_REMOVED(entry)) { - firstRemoved = entry; - } else { - firstRemoved = NULL; - if (op == JS_DHASH_ADD) - entry->keyHash |= COLLISION_FLAG; - } - - for (;;) { - METER(table->stats.steps++); - hash1 -= hash2; - hash1 &= sizeMask; - - entry = ADDRESS_ENTRY(table, hash1); - if (JS_DHASH_ENTRY_IS_FREE(entry)) { - METER(table->stats.misses++); - return (firstRemoved && op == JS_DHASH_ADD) ? firstRemoved : entry; - } - - if (MATCH_ENTRY_KEYHASH(entry, keyHash) && - matchEntry(table, entry, key)) { - METER(table->stats.hits++); - return entry; - } - - if (ENTRY_IS_REMOVED(entry)) { - if (!firstRemoved) - firstRemoved = entry; - } else { - if (op == JS_DHASH_ADD) - entry->keyHash |= COLLISION_FLAG; - } - } - - /* NOTREACHED */ - return NULL; -} - -static JSBool -ChangeTable(JSDHashTable *table, int deltaLog2) -{ - int oldLog2, newLog2; - uint32 oldCapacity, newCapacity; - char *newEntryStore, *oldEntryStore, *oldEntryAddr; - uint32 entrySize, i, nbytes; - JSDHashEntryHdr *oldEntry, *newEntry; - JSDHashGetKey getKey; - JSDHashMoveEntry moveEntry; - - /* Look, but don't touch, until we succeed in getting new entry store. */ - oldLog2 = JS_DHASH_BITS - table->hashShift; - newLog2 = oldLog2 + deltaLog2; - oldCapacity = JS_BIT(oldLog2); - newCapacity = JS_BIT(newLog2); - if (newCapacity >= JS_DHASH_SIZE_LIMIT) - return JS_FALSE; - entrySize = table->entrySize; - nbytes = newCapacity * entrySize; - - newEntryStore = table->ops->allocTable(table, nbytes); - if (!newEntryStore) - return JS_FALSE; - - /* We can't fail from here on, so update table parameters. */ - table->hashShift = JS_DHASH_BITS - newLog2; - table->removedCount = 0; - table->generation++; - - /* Assign the new entry store to table. */ - memset(newEntryStore, 0, nbytes); - oldEntryAddr = oldEntryStore = table->entryStore; - table->entryStore = newEntryStore; - getKey = table->ops->getKey; - moveEntry = table->ops->moveEntry; - - /* Copy only live entries, leaving removed ones behind. */ - for (i = 0; i < oldCapacity; i++) { - oldEntry = (JSDHashEntryHdr *)oldEntryAddr; - if (ENTRY_IS_LIVE(oldEntry)) { - oldEntry->keyHash &= ~COLLISION_FLAG; - newEntry = SearchTable(table, getKey(table, oldEntry), - oldEntry->keyHash, JS_DHASH_ADD); - JS_ASSERT(JS_DHASH_ENTRY_IS_FREE(newEntry)); - moveEntry(table, oldEntry, newEntry); - newEntry->keyHash = oldEntry->keyHash; - } - oldEntryAddr += entrySize; - } - - table->ops->freeTable(table, oldEntryStore); - return JS_TRUE; -} - -JS_PUBLIC_API(JSDHashEntryHdr *) JS_DHASH_FASTCALL -JS_DHashTableOperate(JSDHashTable *table, const void *key, JSDHashOperator op) -{ - JSDHashNumber keyHash; - JSDHashEntryHdr *entry; - uint32 size; - int deltaLog2; - - keyHash = table->ops->hashKey(table, key); - keyHash *= JS_DHASH_GOLDEN_RATIO; - - /* Avoid 0 and 1 hash codes, they indicate free and removed entries. */ - ENSURE_LIVE_KEYHASH(keyHash); - keyHash &= ~COLLISION_FLAG; - - switch (op) { - case JS_DHASH_LOOKUP: - METER(table->stats.lookups++); - entry = SearchTable(table, key, keyHash, op); - break; - - case JS_DHASH_ADD: - /* - * If alpha is >= .75, grow or compress the table. If key is already - * in the table, we may grow once more than necessary, but only if we - * are on the edge of being overloaded. - */ - size = JS_DHASH_TABLE_SIZE(table); - if (table->entryCount + table->removedCount >= MAX_LOAD(table, size)) { - /* Compress if a quarter or more of all entries are removed. */ - if (table->removedCount >= size >> 2) { - METER(table->stats.compresses++); - deltaLog2 = 0; - } else { - METER(table->stats.grows++); - deltaLog2 = 1; - } - - /* - * Grow or compress table, returning null if ChangeTable fails and - * falling through might claim the last free entry. - */ - if (!ChangeTable(table, deltaLog2) && - table->entryCount + table->removedCount == size - 1) { - METER(table->stats.addFailures++); - return NULL; - } - } - - /* - * Look for entry after possibly growing, so we don't have to add it, - * then skip it while growing the table and re-add it after. - */ - entry = SearchTable(table, key, keyHash, op); - if (!ENTRY_IS_LIVE(entry)) { - /* Initialize the entry, indicating that it's no longer free. */ - METER(table->stats.addMisses++); - if (ENTRY_IS_REMOVED(entry)) { - METER(table->stats.addOverRemoved++); - table->removedCount--; - keyHash |= COLLISION_FLAG; - } - if (table->ops->initEntry && - !table->ops->initEntry(table, entry, key)) { - /* We haven't claimed entry yet; fail with null return. */ - memset(entry + 1, 0, table->entrySize - sizeof *entry); - return NULL; - } - entry->keyHash = keyHash; - table->entryCount++; - } - METER(else table->stats.addHits++); - break; - - case JS_DHASH_REMOVE: - entry = SearchTable(table, key, keyHash, op); - if (ENTRY_IS_LIVE(entry)) { - /* Clear this entry and mark it as "removed". */ - METER(table->stats.removeHits++); - JS_DHashTableRawRemove(table, entry); - - /* Shrink if alpha is <= .25 and table isn't too small already. */ - size = JS_DHASH_TABLE_SIZE(table); - if (size > JS_DHASH_MIN_SIZE && - table->entryCount <= MIN_LOAD(table, size)) { - METER(table->stats.shrinks++); - (void) ChangeTable(table, -1); - } - } - METER(else table->stats.removeMisses++); - entry = NULL; - break; - - default: - JS_ASSERT(0); - entry = NULL; - } - - return entry; -} - -JS_PUBLIC_API(void) -JS_DHashTableRawRemove(JSDHashTable *table, JSDHashEntryHdr *entry) -{ - JSDHashNumber keyHash; /* load first in case clearEntry goofs it */ - - JS_ASSERT(JS_DHASH_ENTRY_IS_LIVE(entry)); - keyHash = entry->keyHash; - table->ops->clearEntry(table, entry); - if (keyHash & COLLISION_FLAG) { - MARK_ENTRY_REMOVED(entry); - table->removedCount++; - } else { - METER(table->stats.removeFrees++); - MARK_ENTRY_FREE(entry); - } - table->entryCount--; -} - -JS_PUBLIC_API(uint32) -JS_DHashTableEnumerate(JSDHashTable *table, JSDHashEnumerator etor, void *arg) -{ - char *entryAddr, *entryLimit; - uint32 i, capacity, entrySize, ceiling; - JSBool didRemove; - JSDHashEntryHdr *entry; - JSDHashOperator op; - - entryAddr = table->entryStore; - entrySize = table->entrySize; - capacity = JS_DHASH_TABLE_SIZE(table); - entryLimit = entryAddr + capacity * entrySize; - i = 0; - didRemove = JS_FALSE; - while (entryAddr < entryLimit) { - entry = (JSDHashEntryHdr *)entryAddr; - if (ENTRY_IS_LIVE(entry)) { - op = etor(table, entry, i++, arg); - if (op & JS_DHASH_REMOVE) { - METER(table->stats.removeEnums++); - JS_DHashTableRawRemove(table, entry); - didRemove = JS_TRUE; - } - if (op & JS_DHASH_STOP) - break; - } - entryAddr += entrySize; - } - - /* - * Shrink or compress if a quarter or more of all entries are removed, or - * if the table is underloaded according to the configured minimum alpha, - * and is not minimal-size already. Do this only if we removed above, so - * non-removing enumerations can count on stable table->entryStore until - * the next non-lookup-Operate or removing-Enumerate. - */ - if (didRemove && - (table->removedCount >= capacity >> 2 || - (capacity > JS_DHASH_MIN_SIZE && - table->entryCount <= MIN_LOAD(table, capacity)))) { - METER(table->stats.enumShrinks++); - capacity = table->entryCount; - capacity += capacity >> 1; - if (capacity < JS_DHASH_MIN_SIZE) - capacity = JS_DHASH_MIN_SIZE; - - JS_CEILING_LOG2(ceiling, capacity); - ceiling -= JS_DHASH_BITS - table->hashShift; - - (void) ChangeTable(table, ceiling); - } - return i; -} - -#ifdef JS_DHASHMETER -#include - -JS_PUBLIC_API(void) -JS_DHashTableDumpMeter(JSDHashTable *table, JSDHashEnumerator dump, FILE *fp) -{ - char *entryAddr; - uint32 entrySize, entryCount; - int hashShift, sizeLog2; - uint32 i, tableSize, sizeMask, chainLen, maxChainLen, chainCount; - JSDHashNumber hash1, hash2, saveHash1, maxChainHash1, maxChainHash2; - double sqsum, mean, variance, sigma; - JSDHashEntryHdr *entry, *probe; - - entryAddr = table->entryStore; - entrySize = table->entrySize; - hashShift = table->hashShift; - sizeLog2 = JS_DHASH_BITS - hashShift; - tableSize = JS_DHASH_TABLE_SIZE(table); - sizeMask = JS_BITMASK(sizeLog2); - chainCount = maxChainLen = 0; - hash2 = 0; - sqsum = 0; - - for (i = 0; i < tableSize; i++) { - entry = (JSDHashEntryHdr *)entryAddr; - entryAddr += entrySize; - if (!ENTRY_IS_LIVE(entry)) - continue; - hash1 = HASH1(entry->keyHash & ~COLLISION_FLAG, hashShift); - saveHash1 = hash1; - probe = ADDRESS_ENTRY(table, hash1); - chainLen = 1; - if (probe == entry) { - /* Start of a (possibly unit-length) chain. */ - chainCount++; - } else { - hash2 = HASH2(entry->keyHash & ~COLLISION_FLAG, sizeLog2, - hashShift); - do { - chainLen++; - hash1 -= hash2; - hash1 &= sizeMask; - probe = ADDRESS_ENTRY(table, hash1); - } while (probe != entry); - } - sqsum += chainLen * chainLen; - if (chainLen > maxChainLen) { - maxChainLen = chainLen; - maxChainHash1 = saveHash1; - maxChainHash2 = hash2; - } - } - - entryCount = table->entryCount; - if (entryCount && chainCount) { - mean = (double)entryCount / chainCount; - variance = chainCount * sqsum - entryCount * entryCount; - if (variance < 0 || chainCount == 1) - variance = 0; - else - variance /= chainCount * (chainCount - 1); - sigma = sqrt(variance); - } else { - mean = sigma = 0; - } - - fprintf(fp, "Double hashing statistics:\n"); - fprintf(fp, " table size (in entries): %u\n", tableSize); - fprintf(fp, " number of entries: %u\n", table->entryCount); - fprintf(fp, " number of removed entries: %u\n", table->removedCount); - fprintf(fp, " number of searches: %u\n", table->stats.searches); - fprintf(fp, " number of hits: %u\n", table->stats.hits); - fprintf(fp, " number of misses: %u\n", table->stats.misses); - fprintf(fp, " mean steps per search: %g\n", table->stats.searches ? - (double)table->stats.steps - / table->stats.searches : - 0.); - fprintf(fp, " mean hash chain length: %g\n", mean); - fprintf(fp, " standard deviation: %g\n", sigma); - fprintf(fp, " maximum hash chain length: %u\n", maxChainLen); - fprintf(fp, " number of lookups: %u\n", table->stats.lookups); - fprintf(fp, " adds that made a new entry: %u\n", table->stats.addMisses); - fprintf(fp, "adds that recycled removeds: %u\n", table->stats.addOverRemoved); - fprintf(fp, " adds that found an entry: %u\n", table->stats.addHits); - fprintf(fp, " add failures: %u\n", table->stats.addFailures); - fprintf(fp, " useful removes: %u\n", table->stats.removeHits); - fprintf(fp, " useless removes: %u\n", table->stats.removeMisses); - fprintf(fp, "removes that freed an entry: %u\n", table->stats.removeFrees); - fprintf(fp, " removes while enumerating: %u\n", table->stats.removeEnums); - fprintf(fp, " number of grows: %u\n", table->stats.grows); - fprintf(fp, " number of shrinks: %u\n", table->stats.shrinks); - fprintf(fp, " number of compresses: %u\n", table->stats.compresses); - fprintf(fp, "number of enumerate shrinks: %u\n", table->stats.enumShrinks); - - if (dump && maxChainLen && hash2) { - fputs("Maximum hash chain:\n", fp); - hash1 = maxChainHash1; - hash2 = maxChainHash2; - entry = ADDRESS_ENTRY(table, hash1); - i = 0; - do { - if (dump(table, entry, i++, fp) != JS_DHASH_NEXT) - break; - hash1 -= hash2; - hash1 &= sizeMask; - entry = ADDRESS_ENTRY(table, hash1); - } while (JS_DHASH_ENTRY_IS_BUSY(entry)); - } -} -#endif /* JS_DHASHMETER */ diff --git a/lib/javascript/jsdhash.h b/lib/javascript/jsdhash.h deleted file mode 100644 index 6beecadd..00000000 --- a/lib/javascript/jsdhash.h +++ /dev/null @@ -1,579 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla JavaScript code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1999-2001 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Brendan Eich (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jsdhash_h___ -#define jsdhash_h___ -/* - * Double hashing, a la Knuth 6. - */ -#include "jstypes.h" - -JS_BEGIN_EXTERN_C - -#if defined(__GNUC__) && defined(__i386__) && (__GNUC__ >= 3) && !defined(XP_OS2) -#define JS_DHASH_FASTCALL __attribute__ ((regparm (3),stdcall)) -#else -#define JS_DHASH_FASTCALL -#endif - -#ifdef DEBUG_XXXbrendan -#define JS_DHASHMETER 1 -#endif - -/* Table size limit, do not equal or exceed (see min&maxAlphaFrac, below). */ -#undef JS_DHASH_SIZE_LIMIT -#define JS_DHASH_SIZE_LIMIT JS_BIT(24) - -/* Minimum table size, or gross entry count (net is at most .75 loaded). */ -#ifndef JS_DHASH_MIN_SIZE -#define JS_DHASH_MIN_SIZE 16 -#elif (JS_DHASH_MIN_SIZE & (JS_DHASH_MIN_SIZE - 1)) != 0 -#error "JS_DHASH_MIN_SIZE must be a power of two!" -#endif - -/* - * Multiplicative hash uses an unsigned 32 bit integer and the golden ratio, - * expressed as a fixed-point 32-bit fraction. - */ -#define JS_DHASH_BITS 32 -#define JS_DHASH_GOLDEN_RATIO 0x9E3779B9U - -/* Primitive and forward-struct typedefs. */ -typedef uint32 JSDHashNumber; -typedef struct JSDHashEntryHdr JSDHashEntryHdr; -typedef struct JSDHashEntryStub JSDHashEntryStub; -typedef struct JSDHashTable JSDHashTable; -typedef struct JSDHashTableOps JSDHashTableOps; - -/* - * Table entry header structure. - * - * In order to allow in-line allocation of key and value, we do not declare - * either here. Instead, the API uses const void *key as a formal parameter, - * and asks each entry for its key when necessary via a getKey callback, used - * when growing or shrinking the table. Other callback types are defined - * below and grouped into the JSDHashTableOps structure, for single static - * initialization per hash table sub-type. - * - * Each hash table sub-type should nest the JSDHashEntryHdr structure at the - * front of its particular entry type. The keyHash member contains the result - * of multiplying the hash code returned from the hashKey callback (see below) - * by JS_DHASH_GOLDEN_RATIO, then constraining the result to avoid the magic 0 - * and 1 values. The stored keyHash value is table size invariant, and it is - * maintained automatically by JS_DHashTableOperate -- users should never set - * it, and its only uses should be via the entry macros below. - * - * The JS_DHASH_ENTRY_IS_LIVE macro tests whether entry is neither free nor - * removed. An entry may be either busy or free; if busy, it may be live or - * removed. Consumers of this API should not access members of entries that - * are not live. - * - * However, use JS_DHASH_ENTRY_IS_BUSY for faster liveness testing of entries - * returned by JS_DHashTableOperate, as JS_DHashTableOperate never returns a - * non-live, busy (i.e., removed) entry pointer to its caller. See below for - * more details on JS_DHashTableOperate's calling rules. - */ -struct JSDHashEntryHdr { - JSDHashNumber keyHash; /* every entry must begin like this */ -}; - -#define JS_DHASH_ENTRY_IS_FREE(entry) ((entry)->keyHash == 0) -#define JS_DHASH_ENTRY_IS_BUSY(entry) (!JS_DHASH_ENTRY_IS_FREE(entry)) -#define JS_DHASH_ENTRY_IS_LIVE(entry) ((entry)->keyHash >= 2) - -/* - * A JSDHashTable is currently 8 words (without the JS_DHASHMETER overhead) - * on most architectures, and may be allocated on the stack or within another - * structure or class (see below for the Init and Finish functions to use). - * - * To decide whether to use double hashing vs. chaining, we need to develop a - * trade-off relation, as follows: - * - * Let alpha be the load factor, esize the entry size in words, count the - * entry count, and pow2 the power-of-two table size in entries. - * - * (JSDHashTable overhead) > (JSHashTable overhead) - * (unused table entry space) > (malloc and .next overhead per entry) + - * (buckets overhead) - * (1 - alpha) * esize * pow2 > 2 * count + pow2 - * - * Notice that alpha is by definition (count / pow2): - * - * (1 - alpha) * esize * pow2 > 2 * alpha * pow2 + pow2 - * (1 - alpha) * esize > 2 * alpha + 1 - * - * esize > (1 + 2 * alpha) / (1 - alpha) - * - * This assumes both tables must keep keyHash, key, and value for each entry, - * where key and value point to separately allocated strings or structures. - * If key and value can be combined into one pointer, then the trade-off is: - * - * esize > (1 + 3 * alpha) / (1 - alpha) - * - * If the entry value can be a subtype of JSDHashEntryHdr, rather than a type - * that must be allocated separately and referenced by an entry.value pointer - * member, and provided key's allocation can be fused with its entry's, then - * k (the words wasted per entry with chaining) is 4. - * - * To see these curves, feed gnuplot input like so: - * - * gnuplot> f(x,k) = (1 + k * x) / (1 - x) - * gnuplot> plot [0:.75] f(x,2), f(x,3), f(x,4) - * - * For k of 2 and a well-loaded table (alpha > .5), esize must be more than 4 - * words for chaining to be more space-efficient than double hashing. - * - * Solving for alpha helps us decide when to shrink an underloaded table: - * - * esize > (1 + k * alpha) / (1 - alpha) - * esize - alpha * esize > 1 + k * alpha - * esize - 1 > (k + esize) * alpha - * (esize - 1) / (k + esize) > alpha - * - * alpha < (esize - 1) / (esize + k) - * - * Therefore double hashing should keep alpha >= (esize - 1) / (esize + k), - * assuming esize is not too large (in which case, chaining should probably be - * used for any alpha). For esize=2 and k=3, we want alpha >= .2; for esize=3 - * and k=2, we want alpha >= .4. For k=4, esize could be 6, and alpha >= .5 - * would still obtain. See the JS_DHASH_MIN_ALPHA macro further below. - * - * The current implementation uses a configurable lower bound on alpha, which - * defaults to .25, when deciding to shrink the table (while still respecting - * JS_DHASH_MIN_SIZE). - * - * Note a qualitative difference between chaining and double hashing: under - * chaining, entry addresses are stable across table shrinks and grows. With - * double hashing, you can't safely hold an entry pointer and use it after an - * ADD or REMOVE operation, unless you sample table->generation before adding - * or removing, and compare the sample after, dereferencing the entry pointer - * only if table->generation has not changed. - * - * The moral of this story: there is no one-size-fits-all hash table scheme, - * but for small table entry size, and assuming entry address stability is not - * required, double hashing wins. - */ -struct JSDHashTable { - const JSDHashTableOps *ops; /* virtual operations, see below */ - void *data; /* ops- and instance-specific data */ - int16 hashShift; /* multiplicative hash shift */ - uint8 maxAlphaFrac; /* 8-bit fixed point max alpha */ - uint8 minAlphaFrac; /* 8-bit fixed point min alpha */ - uint32 entrySize; /* number of bytes in an entry */ - uint32 entryCount; /* number of entries in table */ - uint32 removedCount; /* removed entry sentinels in table */ - uint32 generation; /* entry storage generation number */ - char *entryStore; /* entry storage */ -#ifdef JS_DHASHMETER - struct JSDHashStats { - uint32 searches; /* total number of table searches */ - uint32 steps; /* hash chain links traversed */ - uint32 hits; /* searches that found key */ - uint32 misses; /* searches that didn't find key */ - uint32 lookups; /* number of JS_DHASH_LOOKUPs */ - uint32 addMisses; /* adds that miss, and do work */ - uint32 addOverRemoved; /* adds that recycled a removed entry */ - uint32 addHits; /* adds that hit an existing entry */ - uint32 addFailures; /* out-of-memory during add growth */ - uint32 removeHits; /* removes that hit, and do work */ - uint32 removeMisses; /* useless removes that miss */ - uint32 removeFrees; /* removes that freed entry directly */ - uint32 removeEnums; /* removes done by Enumerate */ - uint32 grows; /* table expansions */ - uint32 shrinks; /* table contractions */ - uint32 compresses; /* table compressions */ - uint32 enumShrinks; /* contractions after Enumerate */ - } stats; -#endif -}; - -/* - * Size in entries (gross, not net of free and removed sentinels) for table. - * We store hashShift rather than sizeLog2 to optimize the collision-free case - * in SearchTable. - */ -#define JS_DHASH_TABLE_SIZE(table) JS_BIT(JS_DHASH_BITS - (table)->hashShift) - -/* - * Table space at entryStore is allocated and freed using these callbacks. - * The allocator should return null on error only (not if called with nbytes - * equal to 0; but note that jsdhash.c code will never call with 0 nbytes). - */ -typedef void * -(* JS_DLL_CALLBACK JSDHashAllocTable)(JSDHashTable *table, uint32 nbytes); - -typedef void -(* JS_DLL_CALLBACK JSDHashFreeTable) (JSDHashTable *table, void *ptr); - -/* - * When a table grows or shrinks, each entry is queried for its key using this - * callback. NB: in that event, entry is not in table any longer; it's in the - * old entryStore vector, which is due to be freed once all entries have been - * moved via moveEntry callbacks. - */ -typedef const void * -(* JS_DLL_CALLBACK JSDHashGetKey) (JSDHashTable *table, - JSDHashEntryHdr *entry); - -/* - * Compute the hash code for a given key to be looked up, added, or removed - * from table. A hash code may have any JSDHashNumber value. - */ -typedef JSDHashNumber -(* JS_DLL_CALLBACK JSDHashHashKey) (JSDHashTable *table, const void *key); - -/* - * Compare the key identifying entry in table with the provided key parameter. - * Return JS_TRUE if keys match, JS_FALSE otherwise. - */ -typedef JSBool -(* JS_DLL_CALLBACK JSDHashMatchEntry)(JSDHashTable *table, - const JSDHashEntryHdr *entry, - const void *key); - -/* - * Copy the data starting at from to the new entry storage at to. Do not add - * reference counts for any strong references in the entry, however, as this - * is a "move" operation: the old entry storage at from will be freed without - * any reference-decrementing callback shortly. - */ -typedef void -(* JS_DLL_CALLBACK JSDHashMoveEntry)(JSDHashTable *table, - const JSDHashEntryHdr *from, - JSDHashEntryHdr *to); - -/* - * Clear the entry and drop any strong references it holds. This callback is - * invoked during a JS_DHASH_REMOVE operation (see below for operation codes), - * but only if the given key is found in the table. - */ -typedef void -(* JS_DLL_CALLBACK JSDHashClearEntry)(JSDHashTable *table, - JSDHashEntryHdr *entry); - -/* - * Called when a table (whether allocated dynamically by itself, or nested in - * a larger structure, or allocated on the stack) is finished. This callback - * allows table->ops-specific code to finalize table->data. - */ -typedef void -(* JS_DLL_CALLBACK JSDHashFinalize) (JSDHashTable *table); - -/* - * Initialize a new entry, apart from keyHash. This function is called when - * JS_DHashTableOperate's JS_DHASH_ADD case finds no existing entry for the - * given key, and must add a new one. At that point, entry->keyHash is not - * set yet, to avoid claiming the last free entry in a severely overloaded - * table. - */ -typedef JSBool -(* JS_DLL_CALLBACK JSDHashInitEntry)(JSDHashTable *table, - JSDHashEntryHdr *entry, - const void *key); - -/* - * Finally, the "vtable" structure for JSDHashTable. The first eight hooks - * must be provided by implementations; they're called unconditionally by the - * generic jsdhash.c code. Hooks after these may be null. - * - * Summary of allocation-related hook usage with C++ placement new emphasis: - * allocTable Allocate raw bytes with malloc, no ctors run. - * freeTable Free raw bytes with free, no dtors run. - * initEntry Call placement new using default key-based ctor. - * Return JS_TRUE on success, JS_FALSE on error. - * moveEntry Call placement new using copy ctor, run dtor on old - * entry storage. - * clearEntry Run dtor on entry. - * finalize Stub unless table->data was initialized and needs to - * be finalized. - * - * Note the reason why initEntry is optional: the default hooks (stubs) clear - * entry storage: On successful JS_DHashTableOperate(tbl, key, JS_DHASH_ADD), - * the returned entry pointer addresses an entry struct whose keyHash member - * has been set non-zero, but all other entry members are still clear (null). - * JS_DHASH_ADD callers can test such members to see whether the entry was - * newly created by the JS_DHASH_ADD call that just succeeded. If placement - * new or similar initialization is required, define an initEntry hook. Of - * course, the clearEntry hook must zero or null appropriately. - * - * XXX assumes 0 is null for pointer types. - */ -struct JSDHashTableOps { - /* Mandatory hooks. All implementations must provide these. */ - JSDHashAllocTable allocTable; - JSDHashFreeTable freeTable; - JSDHashGetKey getKey; - JSDHashHashKey hashKey; - JSDHashMatchEntry matchEntry; - JSDHashMoveEntry moveEntry; - JSDHashClearEntry clearEntry; - JSDHashFinalize finalize; - - /* Optional hooks start here. If null, these are not called. */ - JSDHashInitEntry initEntry; -}; - -/* - * Default implementations for the above ops. - */ -extern JS_PUBLIC_API(void *) -JS_DHashAllocTable(JSDHashTable *table, uint32 nbytes); - -extern JS_PUBLIC_API(void) -JS_DHashFreeTable(JSDHashTable *table, void *ptr); - -extern JS_PUBLIC_API(JSDHashNumber) -JS_DHashStringKey(JSDHashTable *table, const void *key); - -/* A minimal entry contains a keyHash header and a void key pointer. */ -struct JSDHashEntryStub { - JSDHashEntryHdr hdr; - const void *key; -}; - -extern JS_PUBLIC_API(const void *) -JS_DHashGetKeyStub(JSDHashTable *table, JSDHashEntryHdr *entry); - -extern JS_PUBLIC_API(JSDHashNumber) -JS_DHashVoidPtrKeyStub(JSDHashTable *table, const void *key); - -extern JS_PUBLIC_API(JSBool) -JS_DHashMatchEntryStub(JSDHashTable *table, - const JSDHashEntryHdr *entry, - const void *key); - -extern JS_PUBLIC_API(JSBool) -JS_DHashMatchStringKey(JSDHashTable *table, - const JSDHashEntryHdr *entry, - const void *key); - -extern JS_PUBLIC_API(void) -JS_DHashMoveEntryStub(JSDHashTable *table, - const JSDHashEntryHdr *from, - JSDHashEntryHdr *to); - -extern JS_PUBLIC_API(void) -JS_DHashClearEntryStub(JSDHashTable *table, JSDHashEntryHdr *entry); - -extern JS_PUBLIC_API(void) -JS_DHashFreeStringKey(JSDHashTable *table, JSDHashEntryHdr *entry); - -extern JS_PUBLIC_API(void) -JS_DHashFinalizeStub(JSDHashTable *table); - -/* - * If you use JSDHashEntryStub or a subclass of it as your entry struct, and - * if your entries move via memcpy and clear via memset(0), you can use these - * stub operations. - */ -extern JS_PUBLIC_API(const JSDHashTableOps *) -JS_DHashGetStubOps(void); - -/* - * Dynamically allocate a new JSDHashTable using malloc, initialize it using - * JS_DHashTableInit, and return its address. Return null on malloc failure. - * Note that the entry storage at table->entryStore will be allocated using - * the ops->allocTable callback. - */ -extern JS_PUBLIC_API(JSDHashTable *) -JS_NewDHashTable(const JSDHashTableOps *ops, void *data, uint32 entrySize, - uint32 capacity); - -/* - * Finalize table's data, free its entry storage (via table->ops->freeTable), - * and return the memory starting at table to the malloc heap. - */ -extern JS_PUBLIC_API(void) -JS_DHashTableDestroy(JSDHashTable *table); - -/* - * Initialize table with ops, data, entrySize, and capacity. Capacity is a - * guess for the smallest table size at which the table will usually be less - * than 75% loaded (the table will grow or shrink as needed; capacity serves - * only to avoid inevitable early growth from JS_DHASH_MIN_SIZE). - */ -extern JS_PUBLIC_API(JSBool) -JS_DHashTableInit(JSDHashTable *table, const JSDHashTableOps *ops, void *data, - uint32 entrySize, uint32 capacity); - -/* - * Set maximum and minimum alpha for table. The defaults are 0.75 and .25. - * maxAlpha must be in [0.5, 0.9375] for the default JS_DHASH_MIN_SIZE; or if - * MinSize=JS_DHASH_MIN_SIZE <= 256, in [0.5, (float)(MinSize-1)/MinSize]; or - * else in [0.5, 255.0/256]. minAlpha must be in [0, maxAlpha / 2), so that - * we don't shrink on the very next remove after growing a table upon adding - * an entry that brings entryCount past maxAlpha * tableSize. - */ -extern JS_PUBLIC_API(void) -JS_DHashTableSetAlphaBounds(JSDHashTable *table, - float maxAlpha, - float minAlpha); - -/* - * Call this macro with k, the number of pointer-sized words wasted per entry - * under chaining, to compute the minimum alpha at which double hashing still - * beats chaining. - */ -#define JS_DHASH_MIN_ALPHA(table, k) \ - ((float)((table)->entrySize / sizeof(void *) - 1) \ - / ((table)->entrySize / sizeof(void *) + (k))) - -/* - * Finalize table's data, free its entry storage using table->ops->freeTable, - * and leave its members unchanged from their last live values (which leaves - * pointers dangling). If you want to burn cycles clearing table, it's up to - * your code to call memset. - */ -extern JS_PUBLIC_API(void) -JS_DHashTableFinish(JSDHashTable *table); - -/* - * To consolidate keyHash computation and table grow/shrink code, we use a - * single entry point for lookup, add, and remove operations. The operation - * codes are declared here, along with codes returned by JSDHashEnumerator - * functions, which control JS_DHashTableEnumerate's behavior. - */ -typedef enum JSDHashOperator { - JS_DHASH_LOOKUP = 0, /* lookup entry */ - JS_DHASH_ADD = 1, /* add entry */ - JS_DHASH_REMOVE = 2, /* remove entry, or enumerator says remove */ - JS_DHASH_NEXT = 0, /* enumerator says continue */ - JS_DHASH_STOP = 1 /* enumerator says stop */ -} JSDHashOperator; - -/* - * To lookup a key in table, call: - * - * entry = JS_DHashTableOperate(table, key, JS_DHASH_LOOKUP); - * - * If JS_DHASH_ENTRY_IS_BUSY(entry) is true, key was found and it identifies - * entry. If JS_DHASH_ENTRY_IS_FREE(entry) is true, key was not found. - * - * To add an entry identified by key to table, call: - * - * entry = JS_DHashTableOperate(table, key, JS_DHASH_ADD); - * - * If entry is null upon return, then either the table is severely overloaded, - * and memory can't be allocated for entry storage via table->ops->allocTable; - * Or if table->ops->initEntry is non-null, the table->ops->initEntry op may - * have returned false. - * - * Otherwise, entry->keyHash has been set so that JS_DHASH_ENTRY_IS_BUSY(entry) - * is true, and it is up to the caller to initialize the key and value parts - * of the entry sub-type, if they have not been set already (i.e. if entry was - * not already in the table, and if the optional initEntry hook was not used). - * - * To remove an entry identified by key from table, call: - * - * (void) JS_DHashTableOperate(table, key, JS_DHASH_REMOVE); - * - * If key's entry is found, it is cleared (via table->ops->clearEntry) and - * the entry is marked so that JS_DHASH_ENTRY_IS_FREE(entry). This operation - * returns null unconditionally; you should ignore its return value. - */ -extern JS_PUBLIC_API(JSDHashEntryHdr *) JS_DHASH_FASTCALL -JS_DHashTableOperate(JSDHashTable *table, const void *key, JSDHashOperator op); - -/* - * Remove an entry already accessed via LOOKUP or ADD. - * - * NB: this is a "raw" or low-level routine, intended to be used only where - * the inefficiency of a full JS_DHashTableOperate (which rehashes in order - * to find the entry given its key) is not tolerable. This function does not - * shrink the table if it is underloaded. It does not update stats #ifdef - * JS_DHASHMETER, either. - */ -extern JS_PUBLIC_API(void) -JS_DHashTableRawRemove(JSDHashTable *table, JSDHashEntryHdr *entry); - -/* - * Enumerate entries in table using etor: - * - * count = JS_DHashTableEnumerate(table, etor, arg); - * - * JS_DHashTableEnumerate calls etor like so: - * - * op = etor(table, entry, number, arg); - * - * where number is a zero-based ordinal assigned to live entries according to - * their order in table->entryStore. - * - * The return value, op, is treated as a set of flags. If op is JS_DHASH_NEXT, - * then continue enumerating. If op contains JS_DHASH_REMOVE, then clear (via - * table->ops->clearEntry) and free entry. Then we check whether op contains - * JS_DHASH_STOP; if so, stop enumerating and return the number of live entries - * that were enumerated so far. Return the total number of live entries when - * enumeration completes normally. - * - * If etor calls JS_DHashTableOperate on table with op != JS_DHASH_LOOKUP, it - * must return JS_DHASH_STOP; otherwise undefined behavior results. - * - * If any enumerator returns JS_DHASH_REMOVE, table->entryStore may be shrunk - * or compressed after enumeration, but before JS_DHashTableEnumerate returns. - * Such an enumerator therefore can't safely set aside entry pointers, but an - * enumerator that never returns JS_DHASH_REMOVE can set pointers to entries - * aside, e.g., to avoid copying live entries into an array of the entry type. - * Copying entry pointers is cheaper, and safe so long as the caller of such a - * "stable" Enumerate doesn't use the set-aside pointers after any call either - * to PL_DHashTableOperate, or to an "unstable" form of Enumerate, which might - * grow or shrink entryStore. - * - * If your enumerator wants to remove certain entries, but set aside pointers - * to other entries that it retains, it can use JS_DHashTableRawRemove on the - * entries to be removed, returning JS_DHASH_NEXT to skip them. Likewise, if - * you want to remove entries, but for some reason you do not want entryStore - * to be shrunk or compressed, you can call JS_DHashTableRawRemove safely on - * the entry being enumerated, rather than returning JS_DHASH_REMOVE. - */ -typedef JSDHashOperator -(* JS_DLL_CALLBACK JSDHashEnumerator)(JSDHashTable *table, JSDHashEntryHdr *hdr, - uint32 number, void *arg); - -extern JS_PUBLIC_API(uint32) -JS_DHashTableEnumerate(JSDHashTable *table, JSDHashEnumerator etor, void *arg); - -#ifdef JS_DHASHMETER -#include - -extern JS_PUBLIC_API(void) -JS_DHashTableDumpMeter(JSDHashTable *table, JSDHashEnumerator dump, FILE *fp); -#endif - -JS_END_EXTERN_C - -#endif /* jsdhash_h___ */ diff --git a/lib/javascript/jsdtoa.c b/lib/javascript/jsdtoa.c deleted file mode 100644 index ff6731bf..00000000 --- a/lib/javascript/jsdtoa.c +++ /dev/null @@ -1,3126 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * Portable double to alphanumeric string and back converters. - */ -#include "jsstddef.h" -#include "jslibmath.h" -#include "jstypes.h" -#include "jsdtoa.h" -#include "jsprf.h" -#include "jsutil.h" /* Added by JSIFY */ -#include "jspubtd.h" -#include "jsnum.h" - -#ifdef JS_THREADSAFE -#include "prlock.h" -#endif - -/**************************************************************** - * - * The author of this software is David M. Gay. - * - * Copyright (c) 1991 by Lucent Technologies. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY - * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - * - ***************************************************************/ - -/* Please send bug reports to - David M. Gay - Bell Laboratories, Room 2C-463 - 600 Mountain Avenue - Murray Hill, NJ 07974-0636 - U.S.A. - dmg@bell-labs.com - */ - -/* On a machine with IEEE extended-precision registers, it is - * necessary to specify double-precision (53-bit) rounding precision - * before invoking strtod or dtoa. If the machine uses (the equivalent - * of) Intel 80x87 arithmetic, the call - * _control87(PC_53, MCW_PC); - * does this with many compilers. Whether this or another call is - * appropriate depends on the compiler; for this to work, it may be - * necessary to #include "float.h" or another system-dependent header - * file. - */ - -/* strtod for IEEE-arithmetic machines. - * - * This strtod returns a nearest machine number to the input decimal - * string (or sets err to JS_DTOA_ERANGE or JS_DTOA_ENOMEM). With IEEE - * arithmetic, ties are broken by the IEEE round-even rule. Otherwise - * ties are broken by biased rounding (add half and chop). - * - * Inspired loosely by William D. Clinger's paper "How to Read Floating - * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101]. - * - * Modifications: - * - * 1. We only require IEEE double-precision - * arithmetic (not IEEE double-extended). - * 2. We get by with floating-point arithmetic in a case that - * Clinger missed -- when we're computing d * 10^n - * for a small integer d and the integer n is not too - * much larger than 22 (the maximum integer k for which - * we can represent 10^k exactly), we may be able to - * compute (d*10^k) * 10^(e-k) with just one roundoff. - * 3. Rather than a bit-at-a-time adjustment of the binary - * result in the hard case, we use floating-point - * arithmetic to determine the adjustment to within - * one bit; only in really hard cases do we need to - * compute a second residual. - * 4. Because of 3., we don't need a large table of powers of 10 - * for ten-to-e (just some small tables, e.g. of 10^k - * for 0 <= k <= 22). - */ - -/* - * #define IEEE_8087 for IEEE-arithmetic machines where the least - * significant byte has the lowest address. - * #define IEEE_MC68k for IEEE-arithmetic machines where the most - * significant byte has the lowest address. - * #define Long int on machines with 32-bit ints and 64-bit longs. - * #define Sudden_Underflow for IEEE-format machines without gradual - * underflow (i.e., that flush to zero on underflow). - * #define No_leftright to omit left-right logic in fast floating-point - * computation of js_dtoa. - * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3. - * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines - * that use extended-precision instructions to compute rounded - * products and quotients) with IBM. - * #define ROUND_BIASED for IEEE-format with biased rounding. - * #define Inaccurate_Divide for IEEE-format with correctly rounded - * products but inaccurate quotients, e.g., for Intel i860. - * #define JS_HAVE_LONG_LONG on machines that have a "long long" - * integer type (of >= 64 bits). If long long is available and the name is - * something other than "long long", #define Llong to be the name, - * and if "unsigned Llong" does not work as an unsigned version of - * Llong, #define #ULLong to be the corresponding unsigned type. - * #define Bad_float_h if your system lacks a float.h or if it does not - * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP, - * FLT_RADIX, FLT_ROUNDS, and DBL_MAX. - * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n) - * if memory is available and otherwise does something you deem - * appropriate. If MALLOC is undefined, malloc will be invoked - * directly -- and assumed always to succeed. - * #define Omit_Private_Memory to omit logic (added Jan. 1998) for making - * memory allocations from a private pool of memory when possible. - * When used, the private pool is PRIVATE_MEM bytes long: 2000 bytes, - * unless #defined to be a different length. This default length - * suffices to get rid of MALLOC calls except for unusual cases, - * such as decimal-to-binary conversion of a very long string of - * digits. - * #define INFNAN_CHECK on IEEE systems to cause strtod to check for - * Infinity and NaN (case insensitively). On some systems (e.g., - * some HP systems), it may be necessary to #define NAN_WORD0 - * appropriately -- to the most significant word of a quiet NaN. - * (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.) - * #define MULTIPLE_THREADS if the system offers preemptively scheduled - * multiple threads. In this case, you must provide (or suitably - * #define) two locks, acquired by ACQUIRE_DTOA_LOCK() and released - * by RELEASE_DTOA_LOCK(). (The second lock, accessed - * in pow5mult, ensures lazy evaluation of only one copy of high - * powers of 5; omitting this lock would introduce a small - * probability of wasting memory, but would otherwise be harmless.) - * You must also invoke freedtoa(s) to free the value s returned by - * dtoa. You may do so whether or not MULTIPLE_THREADS is #defined. - * #define NO_IEEE_Scale to disable new (Feb. 1997) logic in strtod that - * avoids underflows on inputs whose result does not underflow. - */ -#ifdef IS_LITTLE_ENDIAN -#define IEEE_8087 -#else -#define IEEE_MC68k -#endif - -#ifndef Long -#define Long int32 -#endif - -#ifndef ULong -#define ULong uint32 -#endif - -#define Bug(errorMessageString) JS_ASSERT(!errorMessageString) - -#include "stdlib.h" -#include "string.h" - -#ifdef MALLOC -extern void *MALLOC(size_t); -#else -#define MALLOC malloc -#endif - -#define Omit_Private_Memory -/* Private memory currently doesn't work with JS_THREADSAFE */ -#ifndef Omit_Private_Memory -#ifndef PRIVATE_MEM -#define PRIVATE_MEM 2000 -#endif -#define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double)) -static double private_mem[PRIVATE_mem], *pmem_next = private_mem; -#endif - -#ifdef Bad_float_h -#undef __STDC__ - -#define DBL_DIG 15 -#define DBL_MAX_10_EXP 308 -#define DBL_MAX_EXP 1024 -#define FLT_RADIX 2 -#define FLT_ROUNDS 1 -#define DBL_MAX 1.7976931348623157e+308 - - - -#ifndef LONG_MAX -#define LONG_MAX 2147483647 -#endif - -#else /* ifndef Bad_float_h */ -#include "float.h" -#endif /* Bad_float_h */ - -#ifndef __MATH_H__ -#include "math.h" -#endif - -#ifndef CONST -#define CONST const -#endif - -#if defined(IEEE_8087) + defined(IEEE_MC68k) != 1 -Exactly one of IEEE_8087 or IEEE_MC68k should be defined. -#endif - -#define word0(x) JSDOUBLE_HI32(x) -#define set_word0(x, y) JSDOUBLE_SET_HI32(x, y) -#define word1(x) JSDOUBLE_LO32(x) -#define set_word1(x, y) JSDOUBLE_SET_LO32(x, y) - -#define Storeinc(a,b,c) (*(a)++ = (b) << 16 | (c) & 0xffff) - -/* #define P DBL_MANT_DIG */ -/* Ten_pmax = floor(P*log(2)/log(5)) */ -/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */ -/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */ -/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */ - -#define Exp_shift 20 -#define Exp_shift1 20 -#define Exp_msk1 0x100000 -#define Exp_msk11 0x100000 -#define Exp_mask 0x7ff00000 -#define P 53 -#define Bias 1023 -#define Emin (-1022) -#define Exp_1 0x3ff00000 -#define Exp_11 0x3ff00000 -#define Ebits 11 -#define Frac_mask 0xfffff -#define Frac_mask1 0xfffff -#define Ten_pmax 22 -#define Bletch 0x10 -#define Bndry_mask 0xfffff -#define Bndry_mask1 0xfffff -#define LSB 1 -#define Sign_bit 0x80000000 -#define Log2P 1 -#define Tiny0 0 -#define Tiny1 1 -#define Quick_max 14 -#define Int_max 14 -#define Infinite(x) (word0(x) == 0x7ff00000) /* sufficient test for here */ -#ifndef NO_IEEE_Scale -#define Avoid_Underflow -#endif - - - -#ifdef RND_PRODQUOT -#define rounded_product(a,b) a = rnd_prod(a, b) -#define rounded_quotient(a,b) a = rnd_quot(a, b) -extern double rnd_prod(double, double), rnd_quot(double, double); -#else -#define rounded_product(a,b) a *= b -#define rounded_quotient(a,b) a /= b -#endif - -#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1)) -#define Big1 0xffffffff - -#ifndef JS_HAVE_LONG_LONG -#undef ULLong -#else /* long long available */ -#ifndef Llong -#define Llong JSInt64 -#endif -#ifndef ULLong -#define ULLong JSUint64 -#endif -#endif /* JS_HAVE_LONG_LONG */ - -#ifdef JS_THREADSAFE -#define MULTIPLE_THREADS -static PRLock *freelist_lock; -#define ACQUIRE_DTOA_LOCK() \ - JS_BEGIN_MACRO \ - if (!initialized) \ - InitDtoa(); \ - PR_Lock(freelist_lock); \ - JS_END_MACRO -#define RELEASE_DTOA_LOCK() PR_Unlock(freelist_lock) -#else -#undef MULTIPLE_THREADS -#define ACQUIRE_DTOA_LOCK() /*nothing*/ -#define RELEASE_DTOA_LOCK() /*nothing*/ -#endif - -#define Kmax 15 - -struct Bigint { - struct Bigint *next; /* Free list link */ - int32 k; /* lg2(maxwds) */ - int32 maxwds; /* Number of words allocated for x */ - int32 sign; /* Zero if positive, 1 if negative. Ignored by most Bigint routines! */ - int32 wds; /* Actual number of words. If value is nonzero, the most significant word must be nonzero. */ - ULong x[1]; /* wds words of number in little endian order */ -}; - -#ifdef ENABLE_OOM_TESTING -/* Out-of-memory testing. Use a good testcase (over and over) and then use - * these routines to cause a memory failure on every possible Balloc allocation, - * to make sure that all out-of-memory paths can be followed. See bug 14044. - */ - -static int allocationNum; /* which allocation is next? */ -static int desiredFailure; /* which allocation should fail? */ - -/** - * js_BigintTestingReset - * - * Call at the beginning of a test run to set the allocation failure position. - * (Set to 0 to just have the engine count allocations without failing.) - */ -JS_PUBLIC_API(void) -js_BigintTestingReset(int newFailure) -{ - allocationNum = 0; - desiredFailure = newFailure; -} - -/** - * js_BigintTestingWhere - * - * Report the current allocation position. This is really only useful when you - * want to learn how many allocations a test run has. - */ -JS_PUBLIC_API(int) -js_BigintTestingWhere() -{ - return allocationNum; -} - - -/* - * So here's what you do: Set up a fantastic test case that exercises the - * elements of the code you wish. Set the failure point at 0 and run the test, - * then get the allocation position. This number is the number of allocations - * your test makes. Now loop from 1 to that number, setting the failure point - * at each loop count, and run the test over and over, causing failures at each - * step. Any memory failure *should* cause a Out-Of-Memory exception; if it - * doesn't, then there's still an error here. - */ -#endif - -typedef struct Bigint Bigint; - -static Bigint *freelist[Kmax+1]; - -/* - * Allocate a Bigint with 2^k words. - * This is not threadsafe. The caller must use thread locks - */ -static Bigint *Balloc(int32 k) -{ - int32 x; - Bigint *rv; -#ifndef Omit_Private_Memory - uint32 len; -#endif - -#ifdef ENABLE_OOM_TESTING - if (++allocationNum == desiredFailure) { - printf("Forced Failing Allocation number %d\n", allocationNum); - return NULL; - } -#endif - - if ((rv = freelist[k]) != NULL) - freelist[k] = rv->next; - if (rv == NULL) { - x = 1 << k; -#ifdef Omit_Private_Memory - rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong)); -#else - len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1) - /sizeof(double); - if (pmem_next - private_mem + len <= PRIVATE_mem) { - rv = (Bigint*)pmem_next; - pmem_next += len; - } - else - rv = (Bigint*)MALLOC(len*sizeof(double)); -#endif - if (!rv) - return NULL; - rv->k = k; - rv->maxwds = x; - } - rv->sign = rv->wds = 0; - return rv; -} - -static void Bfree(Bigint *v) -{ - if (v) { - v->next = freelist[v->k]; - freelist[v->k] = v; - } -} - -#define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \ - y->wds*sizeof(Long) + 2*sizeof(int32)) - -/* Return b*m + a. Deallocate the old b. Both a and m must be between 0 and - * 65535 inclusive. NOTE: old b is deallocated on memory failure. - */ -static Bigint *multadd(Bigint *b, int32 m, int32 a) -{ - int32 i, wds; -#ifdef ULLong - ULong *x; - ULLong carry, y; -#else - ULong carry, *x, y; - ULong xi, z; -#endif - Bigint *b1; - -#ifdef ENABLE_OOM_TESTING - if (++allocationNum == desiredFailure) { - /* Faux allocation, because I'm not getting all of the failure paths - * without it. - */ - printf("Forced Failing Allocation number %d\n", allocationNum); - Bfree(b); - return NULL; - } -#endif - - wds = b->wds; - x = b->x; - i = 0; - carry = a; - do { -#ifdef ULLong - y = *x * (ULLong)m + carry; - carry = y >> 32; - *x++ = (ULong)(y & 0xffffffffUL); -#else - xi = *x; - y = (xi & 0xffff) * m + carry; - z = (xi >> 16) * m + (y >> 16); - carry = z >> 16; - *x++ = (z << 16) + (y & 0xffff); -#endif - } - while(++i < wds); - if (carry) { - if (wds >= b->maxwds) { - b1 = Balloc(b->k+1); - if (!b1) { - Bfree(b); - return NULL; - } - Bcopy(b1, b); - Bfree(b); - b = b1; - } - b->x[wds++] = (ULong)carry; - b->wds = wds; - } - return b; -} - -static Bigint *s2b(CONST char *s, int32 nd0, int32 nd, ULong y9) -{ - Bigint *b; - int32 i, k; - Long x, y; - - x = (nd + 8) / 9; - for(k = 0, y = 1; x > y; y <<= 1, k++) ; - b = Balloc(k); - if (!b) - return NULL; - b->x[0] = y9; - b->wds = 1; - - i = 9; - if (9 < nd0) { - s += 9; - do { - b = multadd(b, 10, *s++ - '0'); - if (!b) - return NULL; - } while(++i < nd0); - s++; - } - else - s += 10; - for(; i < nd; i++) { - b = multadd(b, 10, *s++ - '0'); - if (!b) - return NULL; - } - return b; -} - - -/* Return the number (0 through 32) of most significant zero bits in x. */ -static int32 hi0bits(register ULong x) -{ - register int32 k = 0; - - if (!(x & 0xffff0000)) { - k = 16; - x <<= 16; - } - if (!(x & 0xff000000)) { - k += 8; - x <<= 8; - } - if (!(x & 0xf0000000)) { - k += 4; - x <<= 4; - } - if (!(x & 0xc0000000)) { - k += 2; - x <<= 2; - } - if (!(x & 0x80000000)) { - k++; - if (!(x & 0x40000000)) - return 32; - } - return k; -} - - -/* Return the number (0 through 32) of least significant zero bits in y. - * Also shift y to the right past these 0 through 32 zeros so that y's - * least significant bit will be set unless y was originally zero. */ -static int32 lo0bits(ULong *y) -{ - register int32 k; - register ULong x = *y; - - if (x & 7) { - if (x & 1) - return 0; - if (x & 2) { - *y = x >> 1; - return 1; - } - *y = x >> 2; - return 2; - } - k = 0; - if (!(x & 0xffff)) { - k = 16; - x >>= 16; - } - if (!(x & 0xff)) { - k += 8; - x >>= 8; - } - if (!(x & 0xf)) { - k += 4; - x >>= 4; - } - if (!(x & 0x3)) { - k += 2; - x >>= 2; - } - if (!(x & 1)) { - k++; - x >>= 1; - if (!x & 1) - return 32; - } - *y = x; - return k; -} - -/* Return a new Bigint with the given integer value, which must be nonnegative. */ -static Bigint *i2b(int32 i) -{ - Bigint *b; - - b = Balloc(1); - if (!b) - return NULL; - b->x[0] = i; - b->wds = 1; - return b; -} - -/* Return a newly allocated product of a and b. */ -static Bigint *mult(CONST Bigint *a, CONST Bigint *b) -{ - CONST Bigint *t; - Bigint *c; - int32 k, wa, wb, wc; - ULong y; - ULong *xc, *xc0, *xce; - CONST ULong *x, *xa, *xae, *xb, *xbe; -#ifdef ULLong - ULLong carry, z; -#else - ULong carry, z; - ULong z2; -#endif - - if (a->wds < b->wds) { - t = a; - a = b; - b = t; - } - k = a->k; - wa = a->wds; - wb = b->wds; - wc = wa + wb; - if (wc > a->maxwds) - k++; - c = Balloc(k); - if (!c) - return NULL; - for(xc = c->x, xce = xc + wc; xc < xce; xc++) - *xc = 0; - xa = a->x; - xae = xa + wa; - xb = b->x; - xbe = xb + wb; - xc0 = c->x; -#ifdef ULLong - for(; xb < xbe; xc0++) { - if ((y = *xb++) != 0) { - x = xa; - xc = xc0; - carry = 0; - do { - z = *x++ * (ULLong)y + *xc + carry; - carry = z >> 32; - *xc++ = (ULong)(z & 0xffffffffUL); - } - while(x < xae); - *xc = (ULong)carry; - } - } -#else - for(; xb < xbe; xb++, xc0++) { - if ((y = *xb & 0xffff) != 0) { - x = xa; - xc = xc0; - carry = 0; - do { - z = (*x & 0xffff) * y + (*xc & 0xffff) + carry; - carry = z >> 16; - z2 = (*x++ >> 16) * y + (*xc >> 16) + carry; - carry = z2 >> 16; - Storeinc(xc, z2, z); - } - while(x < xae); - *xc = carry; - } - if ((y = *xb >> 16) != 0) { - x = xa; - xc = xc0; - carry = 0; - z2 = *xc; - do { - z = (*x & 0xffff) * y + (*xc >> 16) + carry; - carry = z >> 16; - Storeinc(xc, z, z2); - z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry; - carry = z2 >> 16; - } - while(x < xae); - *xc = z2; - } - } -#endif - for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ; - c->wds = wc; - return c; -} - -/* - * 'p5s' points to a linked list of Bigints that are powers of 5. - * This list grows on demand, and it can only grow: it won't change - * in any other way. So if we read 'p5s' or the 'next' field of - * some Bigint on the list, and it is not NULL, we know it won't - * change to NULL or some other value. Only when the value of - * 'p5s' or 'next' is NULL do we need to acquire the lock and add - * a new Bigint to the list. - */ - -static Bigint *p5s; - -#ifdef JS_THREADSAFE -static PRLock *p5s_lock; -#endif - -/* Return b * 5^k. Deallocate the old b. k must be nonnegative. */ -/* NOTE: old b is deallocated on memory failure. */ -static Bigint *pow5mult(Bigint *b, int32 k) -{ - Bigint *b1, *p5, *p51; - int32 i; - static CONST int32 p05[3] = { 5, 25, 125 }; - - if ((i = k & 3) != 0) { - b = multadd(b, p05[i-1], 0); - if (!b) - return NULL; - } - - if (!(k >>= 2)) - return b; - if (!(p5 = p5s)) { -#ifdef JS_THREADSAFE - /* - * We take great care to not call i2b() and Bfree() - * while holding the lock. - */ - Bigint *wasted_effort = NULL; - p5 = i2b(625); - if (!p5) { - Bfree(b); - return NULL; - } - /* lock and check again */ - PR_Lock(p5s_lock); - if (!p5s) { - /* first time */ - p5s = p5; - p5->next = 0; - } else { - /* some other thread just beat us */ - wasted_effort = p5; - p5 = p5s; - } - PR_Unlock(p5s_lock); - if (wasted_effort) { - Bfree(wasted_effort); - } -#else - /* first time */ - p5 = p5s = i2b(625); - if (!p5) { - Bfree(b); - return NULL; - } - p5->next = 0; -#endif - } - for(;;) { - if (k & 1) { - b1 = mult(b, p5); - Bfree(b); - if (!b1) - return NULL; - b = b1; - } - if (!(k >>= 1)) - break; - if (!(p51 = p5->next)) { -#ifdef JS_THREADSAFE - Bigint *wasted_effort = NULL; - p51 = mult(p5, p5); - if (!p51) { - Bfree(b); - return NULL; - } - PR_Lock(p5s_lock); - if (!p5->next) { - p5->next = p51; - p51->next = 0; - } else { - wasted_effort = p51; - p51 = p5->next; - } - PR_Unlock(p5s_lock); - if (wasted_effort) { - Bfree(wasted_effort); - } -#else - p51 = mult(p5,p5); - if (!p51) { - Bfree(b); - return NULL; - } - p51->next = 0; - p5->next = p51; -#endif - } - p5 = p51; - } - return b; -} - -/* Return b * 2^k. Deallocate the old b. k must be nonnegative. - * NOTE: on memory failure, old b is deallocated. */ -static Bigint *lshift(Bigint *b, int32 k) -{ - int32 i, k1, n, n1; - Bigint *b1; - ULong *x, *x1, *xe, z; - - n = k >> 5; - k1 = b->k; - n1 = n + b->wds + 1; - for(i = b->maxwds; n1 > i; i <<= 1) - k1++; - b1 = Balloc(k1); - if (!b1) - goto done; - x1 = b1->x; - for(i = 0; i < n; i++) - *x1++ = 0; - x = b->x; - xe = x + b->wds; - if (k &= 0x1f) { - k1 = 32 - k; - z = 0; - do { - *x1++ = *x << k | z; - z = *x++ >> k1; - } - while(x < xe); - if ((*x1 = z) != 0) - ++n1; - } - else do - *x1++ = *x++; - while(x < xe); - b1->wds = n1 - 1; -done: - Bfree(b); - return b1; -} - -/* Return -1, 0, or 1 depending on whether ab, respectively. */ -static int32 cmp(Bigint *a, Bigint *b) -{ - ULong *xa, *xa0, *xb, *xb0; - int32 i, j; - - i = a->wds; - j = b->wds; -#ifdef DEBUG - if (i > 1 && !a->x[i-1]) - Bug("cmp called with a->x[a->wds-1] == 0"); - if (j > 1 && !b->x[j-1]) - Bug("cmp called with b->x[b->wds-1] == 0"); -#endif - if (i -= j) - return i; - xa0 = a->x; - xa = xa0 + j; - xb0 = b->x; - xb = xb0 + j; - for(;;) { - if (*--xa != *--xb) - return *xa < *xb ? -1 : 1; - if (xa <= xa0) - break; - } - return 0; -} - -static Bigint *diff(Bigint *a, Bigint *b) -{ - Bigint *c; - int32 i, wa, wb; - ULong *xa, *xae, *xb, *xbe, *xc; -#ifdef ULLong - ULLong borrow, y; -#else - ULong borrow, y; - ULong z; -#endif - - i = cmp(a,b); - if (!i) { - c = Balloc(0); - if (!c) - return NULL; - c->wds = 1; - c->x[0] = 0; - return c; - } - if (i < 0) { - c = a; - a = b; - b = c; - i = 1; - } - else - i = 0; - c = Balloc(a->k); - if (!c) - return NULL; - c->sign = i; - wa = a->wds; - xa = a->x; - xae = xa + wa; - wb = b->wds; - xb = b->x; - xbe = xb + wb; - xc = c->x; - borrow = 0; -#ifdef ULLong - do { - y = (ULLong)*xa++ - *xb++ - borrow; - borrow = y >> 32 & 1UL; - *xc++ = (ULong)(y & 0xffffffffUL); - } - while(xb < xbe); - while(xa < xae) { - y = *xa++ - borrow; - borrow = y >> 32 & 1UL; - *xc++ = (ULong)(y & 0xffffffffUL); - } -#else - do { - y = (*xa & 0xffff) - (*xb & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - z = (*xa++ >> 16) - (*xb++ >> 16) - borrow; - borrow = (z & 0x10000) >> 16; - Storeinc(xc, z, y); - } - while(xb < xbe); - while(xa < xae) { - y = (*xa & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - z = (*xa++ >> 16) - borrow; - borrow = (z & 0x10000) >> 16; - Storeinc(xc, z, y); - } -#endif - while(!*--xc) - wa--; - c->wds = wa; - return c; -} - -/* Return the absolute difference between x and the adjacent greater-magnitude double number (ignoring exponent overflows). */ -static double ulp(double x) -{ - register Long L; - double a = 0; - - L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1; -#ifndef Sudden_Underflow - if (L > 0) { -#endif - set_word0(a, L); - set_word1(a, 0); -#ifndef Sudden_Underflow - } - else { - L = -L >> Exp_shift; - if (L < Exp_shift) { - set_word0(a, 0x80000 >> L); - set_word1(a, 0); - } - else { - set_word0(a, 0); - L -= Exp_shift; - set_word1(a, L >= 31 ? 1 : 1 << (31 - L)); - } - } -#endif - return a; -} - - -static double b2d(Bigint *a, int32 *e) -{ - ULong *xa, *xa0, w, y, z; - int32 k; - double d = 0; -#define d0 word0(d) -#define d1 word1(d) -#define set_d0(x) set_word0(d, x) -#define set_d1(x) set_word1(d, x) - - xa0 = a->x; - xa = xa0 + a->wds; - y = *--xa; -#ifdef DEBUG - if (!y) Bug("zero y in b2d"); -#endif - k = hi0bits(y); - *e = 32 - k; - if (k < Ebits) { - set_d0(Exp_1 | y >> (Ebits - k)); - w = xa > xa0 ? *--xa : 0; - set_d1(y << (32-Ebits + k) | w >> (Ebits - k)); - goto ret_d; - } - z = xa > xa0 ? *--xa : 0; - if (k -= Ebits) { - set_d0(Exp_1 | y << k | z >> (32 - k)); - y = xa > xa0 ? *--xa : 0; - set_d1(z << k | y >> (32 - k)); - } - else { - set_d0(Exp_1 | y); - set_d1(z); - } - ret_d: -#undef d0 -#undef d1 -#undef set_d0 -#undef set_d1 - return d; -} - - -/* Convert d into the form b*2^e, where b is an odd integer. b is the returned - * Bigint and e is the returned binary exponent. Return the number of significant - * bits in b in bits. d must be finite and nonzero. */ -static Bigint *d2b(double d, int32 *e, int32 *bits) -{ - Bigint *b; - int32 de, i, k; - ULong *x, y, z; -#define d0 word0(d) -#define d1 word1(d) -#define set_d0(x) set_word0(d, x) -#define set_d1(x) set_word1(d, x) - - b = Balloc(1); - if (!b) - return NULL; - x = b->x; - - z = d0 & Frac_mask; - set_d0(d0 & 0x7fffffff); /* clear sign bit, which we ignore */ -#ifdef Sudden_Underflow - de = (int32)(d0 >> Exp_shift); - z |= Exp_msk11; -#else - if ((de = (int32)(d0 >> Exp_shift)) != 0) - z |= Exp_msk1; -#endif - if ((y = d1) != 0) { - if ((k = lo0bits(&y)) != 0) { - x[0] = y | z << (32 - k); - z >>= k; - } - else - x[0] = y; - i = b->wds = (x[1] = z) ? 2 : 1; - } - else { - JS_ASSERT(z); - k = lo0bits(&z); - x[0] = z; - i = b->wds = 1; - k += 32; - } -#ifndef Sudden_Underflow - if (de) { -#endif - *e = de - Bias - (P-1) + k; - *bits = P - k; -#ifndef Sudden_Underflow - } - else { - *e = de - Bias - (P-1) + 1 + k; - *bits = 32*i - hi0bits(x[i-1]); - } -#endif - return b; -} -#undef d0 -#undef d1 -#undef set_d0 -#undef set_d1 - - -static double ratio(Bigint *a, Bigint *b) -{ - double da, db; - int32 k, ka, kb; - - da = b2d(a, &ka); - db = b2d(b, &kb); - k = ka - kb + 32*(a->wds - b->wds); - if (k > 0) - set_word0(da, word0(da) + k*Exp_msk1); - else { - k = -k; - set_word0(db, word0(db) + k*Exp_msk1); - } - return da / db; -} - -static CONST double -tens[] = { - 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, - 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, - 1e20, 1e21, 1e22 -}; - -static CONST double bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 }; -static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, -#ifdef Avoid_Underflow - 9007199254740992.e-256 -#else - 1e-256 -#endif - }; -/* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */ -/* flag unnecessarily. It leads to a song and dance at the end of strtod. */ -#define Scale_Bit 0x10 -#define n_bigtens 5 - - -#ifdef INFNAN_CHECK - -#ifndef NAN_WORD0 -#define NAN_WORD0 0x7ff80000 -#endif - -#ifndef NAN_WORD1 -#define NAN_WORD1 0 -#endif - -static int match(CONST char **sp, char *t) -{ - int c, d; - CONST char *s = *sp; - - while(d = *t++) { - if ((c = *++s) >= 'A' && c <= 'Z') - c += 'a' - 'A'; - if (c != d) - return 0; - } - *sp = s + 1; - return 1; - } -#endif /* INFNAN_CHECK */ - - -#ifdef JS_THREADSAFE -static JSBool initialized = JS_FALSE; - -/* hacked replica of nspr _PR_InitDtoa */ -static void InitDtoa(void) -{ - freelist_lock = PR_NewLock(); - p5s_lock = PR_NewLock(); - initialized = JS_TRUE; -} -#endif - -void js_FinishDtoa(void) -{ - int count; - Bigint *temp; - -#ifdef JS_THREADSAFE - if (initialized == JS_TRUE) { - PR_DestroyLock(freelist_lock); - PR_DestroyLock(p5s_lock); - initialized = JS_FALSE; - } -#endif - - /* clear down the freelist array and p5s */ - - /* static Bigint *freelist[Kmax+1]; */ - for (count = 0; count <= Kmax; count++) { - Bigint **listp = &freelist[count]; - while ((temp = *listp) != NULL) { - *listp = temp->next; - free(temp); - } - freelist[count] = NULL; - } - - /* static Bigint *p5s; */ - while (p5s) { - temp = p5s; - p5s = p5s->next; - free(temp); - } -} - -/* nspr2 watcom bug ifdef omitted */ - -JS_FRIEND_API(double) -JS_strtod(CONST char *s00, char **se, int *err) -{ - int32 scale; - int32 bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign, - e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign; - CONST char *s, *s0, *s1; - double aadj, aadj1, adj, rv, rv0; - Long L; - ULong y, z; - Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; - - *err = 0; - - bb = bd = bs = delta = NULL; - sign = nz0 = nz = 0; - rv = 0.; - - /* Locking for Balloc's shared buffers that will be used in this block */ - ACQUIRE_DTOA_LOCK(); - - for(s = s00;;s++) switch(*s) { - case '-': - sign = 1; - /* no break */ - case '+': - if (*++s) - goto break2; - /* no break */ - case 0: - s = s00; - goto ret; - case '\t': - case '\n': - case '\v': - case '\f': - case '\r': - case ' ': - continue; - default: - goto break2; - } -break2: - - if (*s == '0') { - nz0 = 1; - while(*++s == '0') ; - if (!*s) - goto ret; - } - s0 = s; - y = z = 0; - for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++) - if (nd < 9) - y = 10*y + c - '0'; - else if (nd < 16) - z = 10*z + c - '0'; - nd0 = nd; - if (c == '.') { - c = *++s; - if (!nd) { - for(; c == '0'; c = *++s) - nz++; - if (c > '0' && c <= '9') { - s0 = s; - nf += nz; - nz = 0; - goto have_dig; - } - goto dig_done; - } - for(; c >= '0' && c <= '9'; c = *++s) { - have_dig: - nz++; - if (c -= '0') { - nf += nz; - for(i = 1; i < nz; i++) - if (nd++ < 9) - y *= 10; - else if (nd <= DBL_DIG + 1) - z *= 10; - if (nd++ < 9) - y = 10*y + c; - else if (nd <= DBL_DIG + 1) - z = 10*z + c; - nz = 0; - } - } - } -dig_done: - e = 0; - if (c == 'e' || c == 'E') { - if (!nd && !nz && !nz0) { - s = s00; - goto ret; - } - s00 = s; - esign = 0; - switch(c = *++s) { - case '-': - esign = 1; - case '+': - c = *++s; - } - if (c >= '0' && c <= '9') { - while(c == '0') - c = *++s; - if (c > '0' && c <= '9') { - L = c - '0'; - s1 = s; - while((c = *++s) >= '0' && c <= '9') - L = 10*L + c - '0'; - if (s - s1 > 8 || L > 19999) - /* Avoid confusion from exponents - * so large that e might overflow. - */ - e = 19999; /* safe for 16 bit ints */ - else - e = (int32)L; - if (esign) - e = -e; - } - else - e = 0; - } - else - s = s00; - } - if (!nd) { - if (!nz && !nz0) { -#ifdef INFNAN_CHECK - /* Check for Nan and Infinity */ - switch(c) { - case 'i': - case 'I': - if (match(&s,"nfinity")) { - word0(rv) = 0x7ff00000; - word1(rv) = 0; - goto ret; - } - break; - case 'n': - case 'N': - if (match(&s, "an")) { - word0(rv) = NAN_WORD0; - word1(rv) = NAN_WORD1; - goto ret; - } - } -#endif /* INFNAN_CHECK */ - s = s00; - } - goto ret; - } - e1 = e -= nf; - - /* Now we have nd0 digits, starting at s0, followed by a - * decimal point, followed by nd-nd0 digits. The number we're - * after is the integer represented by those digits times - * 10**e */ - - if (!nd0) - nd0 = nd; - k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; - rv = y; - if (k > 9) - rv = tens[k - 9] * rv + z; - bd0 = 0; - if (nd <= DBL_DIG -#ifndef RND_PRODQUOT - && FLT_ROUNDS == 1 -#endif - ) { - if (!e) - goto ret; - if (e > 0) { - if (e <= Ten_pmax) { - /* rv = */ rounded_product(rv, tens[e]); - goto ret; - } - i = DBL_DIG - nd; - if (e <= Ten_pmax + i) { - /* A fancier test would sometimes let us do - * this for larger i values. - */ - e -= i; - rv *= tens[i]; - /* rv = */ rounded_product(rv, tens[e]); - goto ret; - } - } -#ifndef Inaccurate_Divide - else if (e >= -Ten_pmax) { - /* rv = */ rounded_quotient(rv, tens[-e]); - goto ret; - } -#endif - } - e1 += nd - k; - - scale = 0; - - /* Get starting approximation = rv * 10**e1 */ - - if (e1 > 0) { - if ((i = e1 & 15) != 0) - rv *= tens[i]; - if (e1 &= ~15) { - if (e1 > DBL_MAX_10_EXP) { - ovfl: - *err = JS_DTOA_ERANGE; -#ifdef __STDC__ - rv = HUGE_VAL; -#else - /* Can't trust HUGE_VAL */ - word0(rv) = Exp_mask; - word1(rv) = 0; -#endif - if (bd0) - goto retfree; - goto ret; - } - e1 >>= 4; - for(j = 0; e1 > 1; j++, e1 >>= 1) - if (e1 & 1) - rv *= bigtens[j]; - /* The last multiplication could overflow. */ - set_word0(rv, word0(rv) - P*Exp_msk1); - rv *= bigtens[j]; - if ((z = word0(rv) & Exp_mask) > Exp_msk1*(DBL_MAX_EXP+Bias-P)) - goto ovfl; - if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) { - /* set to largest number */ - /* (Can't trust DBL_MAX) */ - set_word0(rv, Big0); - set_word1(rv, Big1); - } - else - set_word0(rv, word0(rv) + P*Exp_msk1); - } - } - else if (e1 < 0) { - e1 = -e1; - if ((i = e1 & 15) != 0) - rv /= tens[i]; - if (e1 &= ~15) { - e1 >>= 4; - if (e1 >= 1 << n_bigtens) - goto undfl; -#ifdef Avoid_Underflow - if (e1 & Scale_Bit) - scale = P; - for(j = 0; e1 > 0; j++, e1 >>= 1) - if (e1 & 1) - rv *= tinytens[j]; - if (scale && (j = P + 1 - ((word0(rv) & Exp_mask) - >> Exp_shift)) > 0) { - /* scaled rv is denormal; zap j low bits */ - if (j >= 32) { - set_word1(rv, 0); - set_word0(rv, word0(rv) & (0xffffffff << (j-32))); - if (!word0(rv)) - set_word0(rv, 1); - } - else - set_word1(rv, word1(rv) & (0xffffffff << j)); - } -#else - for(j = 0; e1 > 1; j++, e1 >>= 1) - if (e1 & 1) - rv *= tinytens[j]; - /* The last multiplication could underflow. */ - rv0 = rv; - rv *= tinytens[j]; - if (!rv) { - rv = 2.*rv0; - rv *= tinytens[j]; -#endif - if (!rv) { - undfl: - rv = 0.; - *err = JS_DTOA_ERANGE; - if (bd0) - goto retfree; - goto ret; - } -#ifndef Avoid_Underflow - set_word0(rv, Tiny0); - set_word1(rv, Tiny1); - /* The refinement below will clean - * this approximation up. - */ - } -#endif - } - } - - /* Now the hard part -- adjusting rv to the correct value.*/ - - /* Put digits into bd: true value = bd * 10^e */ - - bd0 = s2b(s0, nd0, nd, y); - if (!bd0) - goto nomem; - - for(;;) { - bd = Balloc(bd0->k); - if (!bd) - goto nomem; - Bcopy(bd, bd0); - bb = d2b(rv, &bbe, &bbbits); /* rv = bb * 2^bbe */ - if (!bb) - goto nomem; - bs = i2b(1); - if (!bs) - goto nomem; - - if (e >= 0) { - bb2 = bb5 = 0; - bd2 = bd5 = e; - } - else { - bb2 = bb5 = -e; - bd2 = bd5 = 0; - } - if (bbe >= 0) - bb2 += bbe; - else - bd2 -= bbe; - bs2 = bb2; -#ifdef Sudden_Underflow - j = P + 1 - bbbits; -#else -#ifdef Avoid_Underflow - j = bbe - scale; -#else - j = bbe; -#endif - i = j + bbbits - 1; /* logb(rv) */ - if (i < Emin) /* denormal */ - j += P - Emin; - else - j = P + 1 - bbbits; -#endif - bb2 += j; - bd2 += j; -#ifdef Avoid_Underflow - bd2 += scale; -#endif - i = bb2 < bd2 ? bb2 : bd2; - if (i > bs2) - i = bs2; - if (i > 0) { - bb2 -= i; - bd2 -= i; - bs2 -= i; - } - if (bb5 > 0) { - bs = pow5mult(bs, bb5); - if (!bs) - goto nomem; - bb1 = mult(bs, bb); - if (!bb1) - goto nomem; - Bfree(bb); - bb = bb1; - } - if (bb2 > 0) { - bb = lshift(bb, bb2); - if (!bb) - goto nomem; - } - if (bd5 > 0) { - bd = pow5mult(bd, bd5); - if (!bd) - goto nomem; - } - if (bd2 > 0) { - bd = lshift(bd, bd2); - if (!bd) - goto nomem; - } - if (bs2 > 0) { - bs = lshift(bs, bs2); - if (!bs) - goto nomem; - } - delta = diff(bb, bd); - if (!delta) - goto nomem; - dsign = delta->sign; - delta->sign = 0; - i = cmp(delta, bs); - if (i < 0) { - /* Error is less than half an ulp -- check for - * special case of mantissa a power of two. - */ - if (dsign || word1(rv) || word0(rv) & Bndry_mask -#ifdef Avoid_Underflow - || (word0(rv) & Exp_mask) <= Exp_msk1 + P*Exp_msk1 -#else - || (word0(rv) & Exp_mask) <= Exp_msk1 -#endif - ) { -#ifdef Avoid_Underflow - if (!delta->x[0] && delta->wds == 1) - dsign = 2; -#endif - break; - } - delta = lshift(delta,Log2P); - if (!delta) - goto nomem; - if (cmp(delta, bs) > 0) - goto drop_down; - break; - } - if (i == 0) { - /* exactly half-way between */ - if (dsign) { - if ((word0(rv) & Bndry_mask1) == Bndry_mask1 - && word1(rv) == 0xffffffff) { - /*boundary case -- increment exponent*/ - set_word0(rv, (word0(rv) & Exp_mask) + Exp_msk1); - set_word1(rv, 0); -#ifdef Avoid_Underflow - dsign = 0; -#endif - break; - } - } - else if (!(word0(rv) & Bndry_mask) && !word1(rv)) { -#ifdef Avoid_Underflow - dsign = 2; -#endif - drop_down: - /* boundary case -- decrement exponent */ -#ifdef Sudden_Underflow - L = word0(rv) & Exp_mask; - if (L <= Exp_msk1) - goto undfl; - L -= Exp_msk1; -#else - L = (word0(rv) & Exp_mask) - Exp_msk1; -#endif - set_word0(rv, L | Bndry_mask1); - set_word1(rv, 0xffffffff); - break; - } -#ifndef ROUND_BIASED - if (!(word1(rv) & LSB)) - break; -#endif - if (dsign) - rv += ulp(rv); -#ifndef ROUND_BIASED - else { - rv -= ulp(rv); -#ifndef Sudden_Underflow - if (!rv) - goto undfl; -#endif - } -#ifdef Avoid_Underflow - dsign = 1 - dsign; -#endif -#endif - break; - } - if ((aadj = ratio(delta, bs)) <= 2.) { - if (dsign) - aadj = aadj1 = 1.; - else if (word1(rv) || word0(rv) & Bndry_mask) { -#ifndef Sudden_Underflow - if (word1(rv) == Tiny1 && !word0(rv)) - goto undfl; -#endif - aadj = 1.; - aadj1 = -1.; - } - else { - /* special case -- power of FLT_RADIX to be */ - /* rounded down... */ - - if (aadj < 2./FLT_RADIX) - aadj = 1./FLT_RADIX; - else - aadj *= 0.5; - aadj1 = -aadj; - } - } - else { - aadj *= 0.5; - aadj1 = dsign ? aadj : -aadj; -#ifdef Check_FLT_ROUNDS - switch(FLT_ROUNDS) { - case 2: /* towards +infinity */ - aadj1 -= 0.5; - break; - case 0: /* towards 0 */ - case 3: /* towards -infinity */ - aadj1 += 0.5; - } -#else - if (FLT_ROUNDS == 0) - aadj1 += 0.5; -#endif - } - y = word0(rv) & Exp_mask; - - /* Check for overflow */ - - if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) { - rv0 = rv; - set_word0(rv, word0(rv) - P*Exp_msk1); - adj = aadj1 * ulp(rv); - rv += adj; - if ((word0(rv) & Exp_mask) >= - Exp_msk1*(DBL_MAX_EXP+Bias-P)) { - if (word0(rv0) == Big0 && word1(rv0) == Big1) - goto ovfl; - set_word0(rv, Big0); - set_word1(rv, Big1); - goto cont; - } - else - set_word0(rv, word0(rv) + P*Exp_msk1); - } - else { -#ifdef Sudden_Underflow - if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { - rv0 = rv; - set_word0(rv, word0(rv) + P*Exp_msk1); - adj = aadj1 * ulp(rv); - rv += adj; - if ((word0(rv) & Exp_mask) <= P*Exp_msk1) - { - if (word0(rv0) == Tiny0 - && word1(rv0) == Tiny1) - goto undfl; - set_word0(rv, Tiny0); - set_word1(rv, Tiny1); - goto cont; - } - else - set_word0(rv, word0(rv) - P*Exp_msk1); - } - else { - adj = aadj1 * ulp(rv); - rv += adj; - } -#else - /* Compute adj so that the IEEE rounding rules will - * correctly round rv + adj in some half-way cases. - * If rv * ulp(rv) is denormalized (i.e., - * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid - * trouble from bits lost to denormalization; - * example: 1.2e-307 . - */ -#ifdef Avoid_Underflow - if (y <= P*Exp_msk1 && aadj > 1.) -#else - if (y <= (P-1)*Exp_msk1 && aadj > 1.) -#endif - { - aadj1 = (double)(int32)(aadj + 0.5); - if (!dsign) - aadj1 = -aadj1; - } -#ifdef Avoid_Underflow - if (scale && y <= P*Exp_msk1) - set_word0(aadj1, word0(aadj1) + (P+1)*Exp_msk1 - y); -#endif - adj = aadj1 * ulp(rv); - rv += adj; -#endif - } - z = word0(rv) & Exp_mask; -#ifdef Avoid_Underflow - if (!scale) -#endif - if (y == z) { - /* Can we stop now? */ - L = (Long)aadj; - aadj -= L; - /* The tolerances below are conservative. */ - if (dsign || word1(rv) || word0(rv) & Bndry_mask) { - if (aadj < .4999999 || aadj > .5000001) - break; - } - else if (aadj < .4999999/FLT_RADIX) - break; - } - cont: - Bfree(bb); - Bfree(bd); - Bfree(bs); - Bfree(delta); - bb = bd = bs = delta = NULL; - } -#ifdef Avoid_Underflow - if (scale) { - set_word0(rv0, Exp_1 - P*Exp_msk1); - set_word1(rv0, 0); - if ((word0(rv) & Exp_mask) <= P*Exp_msk1 - && word1(rv) & 1 - && dsign != 2) { - if (dsign) { -#ifdef Sudden_Underflow - /* rv will be 0, but this would give the */ - /* right result if only rv *= rv0 worked. */ - set_word0(rv, word0(rv) + P*Exp_msk1); - set_word0(rv0, Exp_1 - 2*P*Exp_msk1); -#endif - rv += ulp(rv); - } - else - set_word1(rv, word1(rv) & ~1); - } - rv *= rv0; - } -#endif /* Avoid_Underflow */ -retfree: - Bfree(bb); - Bfree(bd); - Bfree(bs); - Bfree(bd0); - Bfree(delta); -ret: - RELEASE_DTOA_LOCK(); - if (se) - *se = (char *)s; - return sign ? -rv : rv; - -nomem: - Bfree(bb); - Bfree(bd); - Bfree(bs); - Bfree(bd0); - Bfree(delta); - *err = JS_DTOA_ENOMEM; - return 0; -} - - -/* Return floor(b/2^k) and set b to be the remainder. The returned quotient must be less than 2^32. */ -static uint32 quorem2(Bigint *b, int32 k) -{ - ULong mask; - ULong result; - ULong *bx, *bxe; - int32 w; - int32 n = k >> 5; - k &= 0x1F; - mask = (1<wds - n; - if (w <= 0) - return 0; - JS_ASSERT(w <= 2); - bx = b->x; - bxe = bx + n; - result = *bxe >> k; - *bxe &= mask; - if (w == 2) { - JS_ASSERT(!(bxe[1] & ~mask)); - if (k) - result |= bxe[1] << (32 - k); - } - n++; - while (!*bxe && bxe != bx) { - n--; - bxe--; - } - b->wds = n; - return result; -} - -/* Return floor(b/S) and set b to be the remainder. As added restrictions, b must not have - * more words than S, the most significant word of S must not start with a 1 bit, and the - * returned quotient must be less than 36. */ -static int32 quorem(Bigint *b, Bigint *S) -{ - int32 n; - ULong *bx, *bxe, q, *sx, *sxe; -#ifdef ULLong - ULLong borrow, carry, y, ys; -#else - ULong borrow, carry, y, ys; - ULong si, z, zs; -#endif - - n = S->wds; - JS_ASSERT(b->wds <= n); - if (b->wds < n) - return 0; - sx = S->x; - sxe = sx + --n; - bx = b->x; - bxe = bx + n; - JS_ASSERT(*sxe <= 0x7FFFFFFF); - q = *bxe / (*sxe + 1); /* ensure q <= true quotient */ - JS_ASSERT(q < 36); - if (q) { - borrow = 0; - carry = 0; - do { -#ifdef ULLong - ys = *sx++ * (ULLong)q + carry; - carry = ys >> 32; - y = *bx - (ys & 0xffffffffUL) - borrow; - borrow = y >> 32 & 1UL; - *bx++ = (ULong)(y & 0xffffffffUL); -#else - si = *sx++; - ys = (si & 0xffff) * q + carry; - zs = (si >> 16) * q + (ys >> 16); - carry = zs >> 16; - y = (*bx & 0xffff) - (ys & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - z = (*bx >> 16) - (zs & 0xffff) - borrow; - borrow = (z & 0x10000) >> 16; - Storeinc(bx, z, y); -#endif - } - while(sx <= sxe); - if (!*bxe) { - bx = b->x; - while(--bxe > bx && !*bxe) - --n; - b->wds = n; - } - } - if (cmp(b, S) >= 0) { - q++; - borrow = 0; - carry = 0; - bx = b->x; - sx = S->x; - do { -#ifdef ULLong - ys = *sx++ + carry; - carry = ys >> 32; - y = *bx - (ys & 0xffffffffUL) - borrow; - borrow = y >> 32 & 1UL; - *bx++ = (ULong)(y & 0xffffffffUL); -#else - si = *sx++; - ys = (si & 0xffff) + carry; - zs = (si >> 16) + (ys >> 16); - carry = zs >> 16; - y = (*bx & 0xffff) - (ys & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - z = (*bx >> 16) - (zs & 0xffff) - borrow; - borrow = (z & 0x10000) >> 16; - Storeinc(bx, z, y); -#endif - } while(sx <= sxe); - bx = b->x; - bxe = bx + n; - if (!*bxe) { - while(--bxe > bx && !*bxe) - --n; - b->wds = n; - } - } - return (int32)q; -} - -/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string. - * - * Inspired by "How to Print Floating-Point Numbers Accurately" by - * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101]. - * - * Modifications: - * 1. Rather than iterating, we use a simple numeric overestimate - * to determine k = floor(log10(d)). We scale relevant - * quantities using O(log2(k)) rather than O(k) multiplications. - * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't - * try to generate digits strictly left to right. Instead, we - * compute with fewer bits and propagate the carry if necessary - * when rounding the final digit up. This is often faster. - * 3. Under the assumption that input will be rounded nearest, - * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22. - * That is, we allow equality in stopping tests when the - * round-nearest rule will give the same floating-point value - * as would satisfaction of the stopping test with strict - * inequality. - * 4. We remove common factors of powers of 2 from relevant - * quantities. - * 5. When converting floating-point integers less than 1e16, - * we use floating-point arithmetic rather than resorting - * to multiple-precision integers. - * 6. When asked to produce fewer than 15 digits, we first try - * to get by with floating-point arithmetic; we resort to - * multiple-precision integer arithmetic only if we cannot - * guarantee that the floating-point calculation has given - * the correctly rounded result. For k requested digits and - * "uniformly" distributed input, the probability is - * something like 10^(k-15) that we must resort to the Long - * calculation. - */ - -/* Always emits at least one digit. */ -/* If biasUp is set, then rounding in modes 2 and 3 will round away from zero - * when the number is exactly halfway between two representable values. For example, - * rounding 2.5 to zero digits after the decimal point will return 3 and not 2. - * 2.49 will still round to 2, and 2.51 will still round to 3. */ -/* bufsize should be at least 20 for modes 0 and 1. For the other modes, - * bufsize should be two greater than the maximum number of output characters expected. */ -static JSBool -js_dtoa(double d, int mode, JSBool biasUp, int ndigits, - int *decpt, int *sign, char **rve, char *buf, size_t bufsize) -{ - /* Arguments ndigits, decpt, sign are similar to those - of ecvt and fcvt; trailing zeros are suppressed from - the returned string. If not null, *rve is set to point - to the end of the return value. If d is +-Infinity or NaN, - then *decpt is set to 9999. - - mode: - 0 ==> shortest string that yields d when read in - and rounded to nearest. - 1 ==> like 0, but with Steele & White stopping rule; - e.g. with IEEE P754 arithmetic , mode 0 gives - 1e23 whereas mode 1 gives 9.999999999999999e22. - 2 ==> max(1,ndigits) significant digits. This gives a - return value similar to that of ecvt, except - that trailing zeros are suppressed. - 3 ==> through ndigits past the decimal point. This - gives a return value similar to that from fcvt, - except that trailing zeros are suppressed, and - ndigits can be negative. - 4-9 should give the same return values as 2-3, i.e., - 4 <= mode <= 9 ==> same return as mode - 2 + (mode & 1). These modes are mainly for - debugging; often they run slower but sometimes - faster than modes 2-3. - 4,5,8,9 ==> left-to-right digit generation. - 6-9 ==> don't try fast floating-point estimate - (if applicable). - - Values of mode other than 0-9 are treated as mode 0. - - Sufficient space is allocated to the return value - to hold the suppressed trailing zeros. - */ - - int32 bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1, - j, j1, k, k0, k_check, leftright, m2, m5, s2, s5, - spec_case, try_quick; - Long L; -#ifndef Sudden_Underflow - int32 denorm; - ULong x; -#endif - Bigint *b, *b1, *delta, *mlo, *mhi, *S; - double d2, ds, eps; - char *s; - - if (word0(d) & Sign_bit) { - /* set sign for everything, including 0's and NaNs */ - *sign = 1; - set_word0(d, word0(d) & ~Sign_bit); /* clear sign bit */ - } - else - *sign = 0; - - if ((word0(d) & Exp_mask) == Exp_mask) { - /* Infinity or NaN */ - *decpt = 9999; - s = !word1(d) && !(word0(d) & Frac_mask) ? "Infinity" : "NaN"; - if ((s[0] == 'I' && bufsize < 9) || (s[0] == 'N' && bufsize < 4)) { - JS_ASSERT(JS_FALSE); -/* JS_SetError(JS_BUFFER_OVERFLOW_ERROR, 0); */ - return JS_FALSE; - } - strcpy(buf, s); - if (rve) { - *rve = buf[3] ? buf + 8 : buf + 3; - JS_ASSERT(**rve == '\0'); - } - return JS_TRUE; - } - - b = NULL; /* initialize for abort protection */ - S = NULL; - mlo = mhi = NULL; - - if (!d) { - no_digits: - *decpt = 1; - if (bufsize < 2) { - JS_ASSERT(JS_FALSE); -/* JS_SetError(JS_BUFFER_OVERFLOW_ERROR, 0); */ - return JS_FALSE; - } - buf[0] = '0'; buf[1] = '\0'; /* copy "0" to buffer */ - if (rve) - *rve = buf + 1; - /* We might have jumped to "no_digits" from below, so we need - * to be sure to free the potentially allocated Bigints to avoid - * memory leaks. */ - Bfree(b); - Bfree(S); - if (mlo != mhi) - Bfree(mlo); - Bfree(mhi); - return JS_TRUE; - } - - b = d2b(d, &be, &bbits); - if (!b) - goto nomem; -#ifdef Sudden_Underflow - i = (int32)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)); -#else - if ((i = (int32)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) != 0) { -#endif - d2 = d; - set_word0(d2, word0(d2) & Frac_mask1); - set_word0(d2, word0(d2) | Exp_11); - - /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 - * log10(x) = log(x) / log(10) - * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) - * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2) - * - * This suggests computing an approximation k to log10(d) by - * - * k = (i - Bias)*0.301029995663981 - * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 ); - * - * We want k to be too large rather than too small. - * The error in the first-order Taylor series approximation - * is in our favor, so we just round up the constant enough - * to compensate for any error in the multiplication of - * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077, - * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14, - * adding 1e-13 to the constant term more than suffices. - * Hence we adjust the constant term to 0.1760912590558. - * (We could get a more accurate k by invoking log10, - * but this is probably not worthwhile.) - */ - - i -= Bias; -#ifndef Sudden_Underflow - denorm = 0; - } - else { - /* d is denormalized */ - - i = bbits + be + (Bias + (P-1) - 1); - x = i > 32 ? word0(d) << (64 - i) | word1(d) >> (i - 32) : word1(d) << (32 - i); - d2 = x; - set_word0(d2, word0(d2) - 31*Exp_msk1); /* adjust exponent */ - i -= (Bias + (P-1) - 1) + 1; - denorm = 1; - } -#endif - /* At this point d = f*2^i, where 1 <= f < 2. d2 is an approximation of f. */ - ds = (d2-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; - k = (int32)ds; - if (ds < 0. && ds != k) - k--; /* want k = floor(ds) */ - k_check = 1; - if (k >= 0 && k <= Ten_pmax) { - if (d < tens[k]) - k--; - k_check = 0; - } - /* At this point floor(log10(d)) <= k <= floor(log10(d))+1. - If k_check is zero, we're guaranteed that k = floor(log10(d)). */ - j = bbits - i - 1; - /* At this point d = b/2^j, where b is an odd integer. */ - if (j >= 0) { - b2 = 0; - s2 = j; - } - else { - b2 = -j; - s2 = 0; - } - if (k >= 0) { - b5 = 0; - s5 = k; - s2 += k; - } - else { - b2 -= k; - b5 = -k; - s5 = 0; - } - /* At this point d/10^k = (b * 2^b2 * 5^b5) / (2^s2 * 5^s5), where b is an odd integer, - b2 >= 0, b5 >= 0, s2 >= 0, and s5 >= 0. */ - if (mode < 0 || mode > 9) - mode = 0; - try_quick = 1; - if (mode > 5) { - mode -= 4; - try_quick = 0; - } - leftright = 1; - ilim = ilim1 = 0; - switch(mode) { - case 0: - case 1: - ilim = ilim1 = -1; - i = 18; - ndigits = 0; - break; - case 2: - leftright = 0; - /* no break */ - case 4: - if (ndigits <= 0) - ndigits = 1; - ilim = ilim1 = i = ndigits; - break; - case 3: - leftright = 0; - /* no break */ - case 5: - i = ndigits + k + 1; - ilim = i; - ilim1 = i - 1; - if (i <= 0) - i = 1; - } - /* ilim is the maximum number of significant digits we want, based on k and ndigits. */ - /* ilim1 is the maximum number of significant digits we want, based on k and ndigits, - when it turns out that k was computed too high by one. */ - - /* Ensure space for at least i+1 characters, including trailing null. */ - if (bufsize <= (size_t)i) { - Bfree(b); - JS_ASSERT(JS_FALSE); - return JS_FALSE; - } - s = buf; - - if (ilim >= 0 && ilim <= Quick_max && try_quick) { - - /* Try to get by with floating-point arithmetic. */ - - i = 0; - d2 = d; - k0 = k; - ilim0 = ilim; - ieps = 2; /* conservative */ - /* Divide d by 10^k, keeping track of the roundoff error and avoiding overflows. */ - if (k > 0) { - ds = tens[k&0xf]; - j = k >> 4; - if (j & Bletch) { - /* prevent overflows */ - j &= Bletch - 1; - d /= bigtens[n_bigtens-1]; - ieps++; - } - for(; j; j >>= 1, i++) - if (j & 1) { - ieps++; - ds *= bigtens[i]; - } - d /= ds; - } - else if ((j1 = -k) != 0) { - d *= tens[j1 & 0xf]; - for(j = j1 >> 4; j; j >>= 1, i++) - if (j & 1) { - ieps++; - d *= bigtens[i]; - } - } - /* Check that k was computed correctly. */ - if (k_check && d < 1. && ilim > 0) { - if (ilim1 <= 0) - goto fast_failed; - ilim = ilim1; - k--; - d *= 10.; - ieps++; - } - /* eps bounds the cumulative error. */ - eps = ieps*d + 7.; - set_word0(eps, word0(eps) - (P-1)*Exp_msk1); - if (ilim == 0) { - S = mhi = 0; - d -= 5.; - if (d > eps) - goto one_digit; - if (d < -eps) - goto no_digits; - goto fast_failed; - } -#ifndef No_leftright - if (leftright) { - /* Use Steele & White method of only - * generating digits needed. - */ - eps = 0.5/tens[ilim-1] - eps; - for(i = 0;;) { - L = (Long)d; - d -= L; - *s++ = '0' + (char)L; - if (d < eps) - goto ret1; - if (1. - d < eps) - goto bump_up; - if (++i >= ilim) - break; - eps *= 10.; - d *= 10.; - } - } - else { -#endif - /* Generate ilim digits, then fix them up. */ - eps *= tens[ilim-1]; - for(i = 1;; i++, d *= 10.) { - L = (Long)d; - d -= L; - *s++ = '0' + (char)L; - if (i == ilim) { - if (d > 0.5 + eps) - goto bump_up; - else if (d < 0.5 - eps) { - while(*--s == '0') ; - s++; - goto ret1; - } - break; - } - } -#ifndef No_leftright - } -#endif - fast_failed: - s = buf; - d = d2; - k = k0; - ilim = ilim0; - } - - /* Do we have a "small" integer? */ - - if (be >= 0 && k <= Int_max) { - /* Yes. */ - ds = tens[k]; - if (ndigits < 0 && ilim <= 0) { - S = mhi = 0; - if (ilim < 0 || d < 5*ds || (!biasUp && d == 5*ds)) - goto no_digits; - goto one_digit; - } - - /* Use true number of digits to limit looping. */ - for(i = 1; i<=k+1; i++) { - L = (Long) (d / ds); - d -= L*ds; -#ifdef Check_FLT_ROUNDS - /* If FLT_ROUNDS == 2, L will usually be high by 1 */ - if (d < 0) { - L--; - d += ds; - } -#endif - *s++ = '0' + (char)L; - if (i == ilim) { - d += d; - if ((d > ds) || (d == ds && (L & 1 || biasUp))) { - bump_up: - while(*--s == '9') - if (s == buf) { - k++; - *s = '0'; - break; - } - ++*s++; - } - break; - } - d *= 10.; - } - goto ret1; - } - - m2 = b2; - m5 = b5; - if (leftright) { - if (mode < 2) { - i = -#ifndef Sudden_Underflow - denorm ? be + (Bias + (P-1) - 1 + 1) : -#endif - 1 + P - bbits; - /* i is 1 plus the number of trailing zero bits in d's significand. Thus, - (2^m2 * 5^m5) / (2^(s2+i) * 5^s5) = (1/2 lsb of d)/10^k. */ - } - else { - j = ilim - 1; - if (m5 >= j) - m5 -= j; - else { - s5 += j -= m5; - b5 += j; - m5 = 0; - } - if ((i = ilim) < 0) { - m2 -= i; - i = 0; - } - /* (2^m2 * 5^m5) / (2^(s2+i) * 5^s5) = (1/2 * 10^(1-ilim))/10^k. */ - } - b2 += i; - s2 += i; - mhi = i2b(1); - if (!mhi) - goto nomem; - /* (mhi * 2^m2 * 5^m5) / (2^s2 * 5^s5) = one-half of last printed (when mode >= 2) or - input (when mode < 2) significant digit, divided by 10^k. */ - } - /* We still have d/10^k = (b * 2^b2 * 5^b5) / (2^s2 * 5^s5). Reduce common factors in - b2, m2, and s2 without changing the equalities. */ - if (m2 > 0 && s2 > 0) { - i = m2 < s2 ? m2 : s2; - b2 -= i; - m2 -= i; - s2 -= i; - } - - /* Fold b5 into b and m5 into mhi. */ - if (b5 > 0) { - if (leftright) { - if (m5 > 0) { - mhi = pow5mult(mhi, m5); - if (!mhi) - goto nomem; - b1 = mult(mhi, b); - if (!b1) - goto nomem; - Bfree(b); - b = b1; - } - if ((j = b5 - m5) != 0) { - b = pow5mult(b, j); - if (!b) - goto nomem; - } - } - else { - b = pow5mult(b, b5); - if (!b) - goto nomem; - } - } - /* Now we have d/10^k = (b * 2^b2) / (2^s2 * 5^s5) and - (mhi * 2^m2) / (2^s2 * 5^s5) = one-half of last printed or input significant digit, divided by 10^k. */ - - S = i2b(1); - if (!S) - goto nomem; - if (s5 > 0) { - S = pow5mult(S, s5); - if (!S) - goto nomem; - } - /* Now we have d/10^k = (b * 2^b2) / (S * 2^s2) and - (mhi * 2^m2) / (S * 2^s2) = one-half of last printed or input significant digit, divided by 10^k. */ - - /* Check for special case that d is a normalized power of 2. */ - spec_case = 0; - if (mode < 2) { - if (!word1(d) && !(word0(d) & Bndry_mask) -#ifndef Sudden_Underflow - && word0(d) & (Exp_mask & Exp_mask << 1) -#endif - ) { - /* The special case. Here we want to be within a quarter of the last input - significant digit instead of one half of it when the decimal output string's value is less than d. */ - b2 += Log2P; - s2 += Log2P; - spec_case = 1; - } - } - - /* Arrange for convenient computation of quotients: - * shift left if necessary so divisor has 4 leading 0 bits. - * - * Perhaps we should just compute leading 28 bits of S once - * and for all and pass them and a shift to quorem, so it - * can do shifts and ors to compute the numerator for q. - */ - if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f) != 0) - i = 32 - i; - /* i is the number of leading zero bits in the most significant word of S*2^s2. */ - if (i > 4) { - i -= 4; - b2 += i; - m2 += i; - s2 += i; - } - else if (i < 4) { - i += 28; - b2 += i; - m2 += i; - s2 += i; - } - /* Now S*2^s2 has exactly four leading zero bits in its most significant word. */ - if (b2 > 0) { - b = lshift(b, b2); - if (!b) - goto nomem; - } - if (s2 > 0) { - S = lshift(S, s2); - if (!S) - goto nomem; - } - /* Now we have d/10^k = b/S and - (mhi * 2^m2) / S = maximum acceptable error, divided by 10^k. */ - if (k_check) { - if (cmp(b,S) < 0) { - k--; - b = multadd(b, 10, 0); /* we botched the k estimate */ - if (!b) - goto nomem; - if (leftright) { - mhi = multadd(mhi, 10, 0); - if (!mhi) - goto nomem; - } - ilim = ilim1; - } - } - /* At this point 1 <= d/10^k = b/S < 10. */ - - if (ilim <= 0 && mode > 2) { - /* We're doing fixed-mode output and d is less than the minimum nonzero output in this mode. - Output either zero or the minimum nonzero output depending on which is closer to d. */ - if (ilim < 0) - goto no_digits; - S = multadd(S,5,0); - if (!S) - goto nomem; - i = cmp(b,S); - if (i < 0 || (i == 0 && !biasUp)) { - /* Always emit at least one digit. If the number appears to be zero - using the current mode, then emit one '0' digit and set decpt to 1. */ - /*no_digits: - k = -1 - ndigits; - goto ret; */ - goto no_digits; - } - one_digit: - *s++ = '1'; - k++; - goto ret; - } - if (leftright) { - if (m2 > 0) { - mhi = lshift(mhi, m2); - if (!mhi) - goto nomem; - } - - /* Compute mlo -- check for special case - * that d is a normalized power of 2. - */ - - mlo = mhi; - if (spec_case) { - mhi = Balloc(mhi->k); - if (!mhi) - goto nomem; - Bcopy(mhi, mlo); - mhi = lshift(mhi, Log2P); - if (!mhi) - goto nomem; - } - /* mlo/S = maximum acceptable error, divided by 10^k, if the output is less than d. */ - /* mhi/S = maximum acceptable error, divided by 10^k, if the output is greater than d. */ - - for(i = 1;;i++) { - dig = quorem(b,S) + '0'; - /* Do we yet have the shortest decimal string - * that will round to d? - */ - j = cmp(b, mlo); - /* j is b/S compared with mlo/S. */ - delta = diff(S, mhi); - if (!delta) - goto nomem; - j1 = delta->sign ? 1 : cmp(b, delta); - Bfree(delta); - /* j1 is b/S compared with 1 - mhi/S. */ -#ifndef ROUND_BIASED - if (j1 == 0 && !mode && !(word1(d) & 1)) { - if (dig == '9') - goto round_9_up; - if (j > 0) - dig++; - *s++ = (char)dig; - goto ret; - } -#endif - if ((j < 0) || (j == 0 && !mode -#ifndef ROUND_BIASED - && !(word1(d) & 1) -#endif - )) { - if (j1 > 0) { - /* Either dig or dig+1 would work here as the least significant decimal digit. - Use whichever would produce a decimal value closer to d. */ - b = lshift(b, 1); - if (!b) - goto nomem; - j1 = cmp(b, S); - if (((j1 > 0) || (j1 == 0 && (dig & 1 || biasUp))) - && (dig++ == '9')) - goto round_9_up; - } - *s++ = (char)dig; - goto ret; - } - if (j1 > 0) { - if (dig == '9') { /* possible if i == 1 */ - round_9_up: - *s++ = '9'; - goto roundoff; - } - *s++ = (char)dig + 1; - goto ret; - } - *s++ = (char)dig; - if (i == ilim) - break; - b = multadd(b, 10, 0); - if (!b) - goto nomem; - if (mlo == mhi) { - mlo = mhi = multadd(mhi, 10, 0); - if (!mhi) - goto nomem; - } - else { - mlo = multadd(mlo, 10, 0); - if (!mlo) - goto nomem; - mhi = multadd(mhi, 10, 0); - if (!mhi) - goto nomem; - } - } - } - else - for(i = 1;; i++) { - *s++ = (char)(dig = quorem(b,S) + '0'); - if (i >= ilim) - break; - b = multadd(b, 10, 0); - if (!b) - goto nomem; - } - - /* Round off last digit */ - - b = lshift(b, 1); - if (!b) - goto nomem; - j = cmp(b, S); - if ((j > 0) || (j == 0 && (dig & 1 || biasUp))) { - roundoff: - while(*--s == '9') - if (s == buf) { - k++; - *s++ = '1'; - goto ret; - } - ++*s++; - } - else { - /* Strip trailing zeros */ - while(*--s == '0') ; - s++; - } - ret: - Bfree(S); - if (mhi) { - if (mlo && mlo != mhi) - Bfree(mlo); - Bfree(mhi); - } - ret1: - Bfree(b); - JS_ASSERT(s < buf + bufsize); - *s = '\0'; - if (rve) - *rve = s; - *decpt = k + 1; - return JS_TRUE; - -nomem: - Bfree(S); - if (mhi) { - if (mlo && mlo != mhi) - Bfree(mlo); - Bfree(mhi); - } - Bfree(b); - return JS_FALSE; -} - - -/* Mapping of JSDToStrMode -> js_dtoa mode */ -static const int dtoaModes[] = { - 0, /* DTOSTR_STANDARD */ - 0, /* DTOSTR_STANDARD_EXPONENTIAL, */ - 3, /* DTOSTR_FIXED, */ - 2, /* DTOSTR_EXPONENTIAL, */ - 2}; /* DTOSTR_PRECISION */ - -JS_FRIEND_API(char *) -JS_dtostr(char *buffer, size_t bufferSize, JSDToStrMode mode, int precision, double d) -{ - int decPt; /* Position of decimal point relative to first digit returned by js_dtoa */ - int sign; /* Nonzero if the sign bit was set in d */ - int nDigits; /* Number of significand digits returned by js_dtoa */ - char *numBegin = buffer+2; /* Pointer to the digits returned by js_dtoa; the +2 leaves space for */ - /* the sign and/or decimal point */ - char *numEnd; /* Pointer past the digits returned by js_dtoa */ - JSBool dtoaRet; - - JS_ASSERT(bufferSize >= (size_t)(mode <= DTOSTR_STANDARD_EXPONENTIAL ? DTOSTR_STANDARD_BUFFER_SIZE : - DTOSTR_VARIABLE_BUFFER_SIZE(precision))); - - if (mode == DTOSTR_FIXED && (d >= 1e21 || d <= -1e21)) - mode = DTOSTR_STANDARD; /* Change mode here rather than below because the buffer may not be large enough to hold a large integer. */ - - /* Locking for Balloc's shared buffers */ - ACQUIRE_DTOA_LOCK(); - dtoaRet = js_dtoa(d, dtoaModes[mode], mode >= DTOSTR_FIXED, precision, &decPt, &sign, &numEnd, numBegin, bufferSize-2); - RELEASE_DTOA_LOCK(); - if (!dtoaRet) - return 0; - - nDigits = numEnd - numBegin; - - /* If Infinity, -Infinity, or NaN, return the string regardless of the mode. */ - if (decPt != 9999) { - JSBool exponentialNotation = JS_FALSE; - int minNDigits = 0; /* Minimum number of significand digits required by mode and precision */ - char *p; - char *q; - - switch (mode) { - case DTOSTR_STANDARD: - if (decPt < -5 || decPt > 21) - exponentialNotation = JS_TRUE; - else - minNDigits = decPt; - break; - - case DTOSTR_FIXED: - if (precision >= 0) - minNDigits = decPt + precision; - else - minNDigits = decPt; - break; - - case DTOSTR_EXPONENTIAL: - JS_ASSERT(precision > 0); - minNDigits = precision; - /* Fall through */ - case DTOSTR_STANDARD_EXPONENTIAL: - exponentialNotation = JS_TRUE; - break; - - case DTOSTR_PRECISION: - JS_ASSERT(precision > 0); - minNDigits = precision; - if (decPt < -5 || decPt > precision) - exponentialNotation = JS_TRUE; - break; - } - - /* If the number has fewer than minNDigits, pad it with zeros at the end */ - if (nDigits < minNDigits) { - p = numBegin + minNDigits; - nDigits = minNDigits; - do { - *numEnd++ = '0'; - } while (numEnd != p); - *numEnd = '\0'; - } - - if (exponentialNotation) { - /* Insert a decimal point if more than one significand digit */ - if (nDigits != 1) { - numBegin--; - numBegin[0] = numBegin[1]; - numBegin[1] = '.'; - } - JS_snprintf(numEnd, bufferSize - (numEnd - buffer), "e%+d", decPt-1); - } else if (decPt != nDigits) { - /* Some kind of a fraction in fixed notation */ - JS_ASSERT(decPt <= nDigits); - if (decPt > 0) { - /* dd...dd . dd...dd */ - p = --numBegin; - do { - *p = p[1]; - p++; - } while (--decPt); - *p = '.'; - } else { - /* 0 . 00...00dd...dd */ - p = numEnd; - numEnd += 1 - decPt; - q = numEnd; - JS_ASSERT(numEnd < buffer + bufferSize); - *numEnd = '\0'; - while (p != numBegin) - *--q = *--p; - for (p = numBegin + 1; p != q; p++) - *p = '0'; - *numBegin = '.'; - *--numBegin = '0'; - } - } - } - - /* If negative and neither -0.0 nor NaN, output a leading '-'. */ - if (sign && - !(word0(d) == Sign_bit && word1(d) == 0) && - !((word0(d) & Exp_mask) == Exp_mask && - (word1(d) || (word0(d) & Frac_mask)))) { - *--numBegin = '-'; - } - return numBegin; -} - - -/* Let b = floor(b / divisor), and return the remainder. b must be nonnegative. - * divisor must be between 1 and 65536. - * This function cannot run out of memory. */ -static uint32 -divrem(Bigint *b, uint32 divisor) -{ - int32 n = b->wds; - uint32 remainder = 0; - ULong *bx; - ULong *bp; - - JS_ASSERT(divisor > 0 && divisor <= 65536); - - if (!n) - return 0; /* b is zero */ - bx = b->x; - bp = bx + n; - do { - ULong a = *--bp; - ULong dividend = remainder << 16 | a >> 16; - ULong quotientHi = dividend / divisor; - ULong quotientLo; - - remainder = dividend - quotientHi*divisor; - JS_ASSERT(quotientHi <= 0xFFFF && remainder < divisor); - dividend = remainder << 16 | (a & 0xFFFF); - quotientLo = dividend / divisor; - remainder = dividend - quotientLo*divisor; - JS_ASSERT(quotientLo <= 0xFFFF && remainder < divisor); - *bp = quotientHi << 16 | quotientLo; - } while (bp != bx); - /* Decrease the size of the number if its most significant word is now zero. */ - if (bx[n-1] == 0) - b->wds--; - return remainder; -} - - -/* "-0.0000...(1073 zeros after decimal point)...0001\0" is the longest string that we could produce, - * which occurs when printing -5e-324 in binary. We could compute a better estimate of the size of - * the output string and malloc fewer bytes depending on d and base, but why bother? */ -#define DTOBASESTR_BUFFER_SIZE 1078 -#define BASEDIGIT(digit) ((char)(((digit) >= 10) ? 'a' - 10 + (digit) : '0' + (digit))) - -JS_FRIEND_API(char *) -JS_dtobasestr(int base, double d) -{ - char *buffer; /* The output string */ - char *p; /* Pointer to current position in the buffer */ - char *pInt; /* Pointer to the beginning of the integer part of the string */ - char *q; - uint32 digit; - double di; /* d truncated to an integer */ - double df; /* The fractional part of d */ - - JS_ASSERT(base >= 2 && base <= 36); - - buffer = (char*) malloc(DTOBASESTR_BUFFER_SIZE); - if (buffer) { - p = buffer; - if (d < 0.0 -#if defined(XP_WIN) || defined(XP_OS2) - && !((word0(d) & Exp_mask) == Exp_mask && ((word0(d) & Frac_mask) || word1(d))) /* Visual C++ doesn't know how to compare against NaN */ -#endif - ) { - *p++ = '-'; - d = -d; - } - - /* Check for Infinity and NaN */ - if ((word0(d) & Exp_mask) == Exp_mask) { - strcpy(p, !word1(d) && !(word0(d) & Frac_mask) ? "Infinity" : "NaN"); - return buffer; - } - - /* Locking for Balloc's shared buffers */ - ACQUIRE_DTOA_LOCK(); - - /* Output the integer part of d with the digits in reverse order. */ - pInt = p; - di = fd_floor(d); - if (di <= 4294967295.0) { - uint32 n = (uint32)di; - if (n) - do { - uint32 m = n / base; - digit = n - m*base; - n = m; - JS_ASSERT(digit < (uint32)base); - *p++ = BASEDIGIT(digit); - } while (n); - else *p++ = '0'; - } else { - int32 e; - int32 bits; /* Number of significant bits in di; not used. */ - Bigint *b = d2b(di, &e, &bits); - if (!b) - goto nomem1; - b = lshift(b, e); - if (!b) { - nomem1: - Bfree(b); - return NULL; - } - do { - digit = divrem(b, base); - JS_ASSERT(digit < (uint32)base); - *p++ = BASEDIGIT(digit); - } while (b->wds); - Bfree(b); - } - /* Reverse the digits of the integer part of d. */ - q = p-1; - while (q > pInt) { - char ch = *pInt; - *pInt++ = *q; - *q-- = ch; - } - - df = d - di; - if (df != 0.0) { - /* We have a fraction. */ - int32 e, bbits, s2, done; - Bigint *b, *s, *mlo, *mhi; - - b = s = mlo = mhi = NULL; - - *p++ = '.'; - b = d2b(df, &e, &bbits); - if (!b) { - nomem2: - Bfree(b); - Bfree(s); - if (mlo != mhi) - Bfree(mlo); - Bfree(mhi); - return NULL; - } - JS_ASSERT(e < 0); - /* At this point df = b * 2^e. e must be less than zero because 0 < df < 1. */ - - s2 = -(int32)(word0(d) >> Exp_shift1 & Exp_mask>>Exp_shift1); -#ifndef Sudden_Underflow - if (!s2) - s2 = -1; -#endif - s2 += Bias + P; - /* 1/2^s2 = (nextDouble(d) - d)/2 */ - JS_ASSERT(-s2 < e); - mlo = i2b(1); - if (!mlo) - goto nomem2; - mhi = mlo; - if (!word1(d) && !(word0(d) & Bndry_mask) -#ifndef Sudden_Underflow - && word0(d) & (Exp_mask & Exp_mask << 1) -#endif - ) { - /* The special case. Here we want to be within a quarter of the last input - significant digit instead of one half of it when the output string's value is less than d. */ - s2 += Log2P; - mhi = i2b(1< df = b/2^s2 > 0; - * (d - prevDouble(d))/2 = mlo/2^s2; - * (nextDouble(d) - d)/2 = mhi/2^s2. */ - - done = JS_FALSE; - do { - int32 j, j1; - Bigint *delta; - - b = multadd(b, base, 0); - if (!b) - goto nomem2; - digit = quorem2(b, s2); - if (mlo == mhi) { - mlo = mhi = multadd(mlo, base, 0); - if (!mhi) - goto nomem2; - } - else { - mlo = multadd(mlo, base, 0); - if (!mlo) - goto nomem2; - mhi = multadd(mhi, base, 0); - if (!mhi) - goto nomem2; - } - - /* Do we yet have the shortest string that will round to d? */ - j = cmp(b, mlo); - /* j is b/2^s2 compared with mlo/2^s2. */ - delta = diff(s, mhi); - if (!delta) - goto nomem2; - j1 = delta->sign ? 1 : cmp(b, delta); - Bfree(delta); - /* j1 is b/2^s2 compared with 1 - mhi/2^s2. */ - -#ifndef ROUND_BIASED - if (j1 == 0 && !(word1(d) & 1)) { - if (j > 0) - digit++; - done = JS_TRUE; - } else -#endif - if (j < 0 || (j == 0 -#ifndef ROUND_BIASED - && !(word1(d) & 1) -#endif - )) { - if (j1 > 0) { - /* Either dig or dig+1 would work here as the least significant digit. - Use whichever would produce an output value closer to d. */ - b = lshift(b, 1); - if (!b) - goto nomem2; - j1 = cmp(b, s); - if (j1 > 0) /* The even test (|| (j1 == 0 && (digit & 1))) is not here because it messes up odd base output - * such as 3.5 in base 3. */ - digit++; - } - done = JS_TRUE; - } else if (j1 > 0) { - digit++; - done = JS_TRUE; - } - JS_ASSERT(digit < (uint32)base); - *p++ = BASEDIGIT(digit); - } while (!done); - Bfree(b); - Bfree(s); - if (mlo != mhi) - Bfree(mlo); - Bfree(mhi); - } - JS_ASSERT(p < buffer + DTOBASESTR_BUFFER_SIZE); - *p = '\0'; - RELEASE_DTOA_LOCK(); - } - return buffer; -} diff --git a/lib/javascript/jsdtoa.h b/lib/javascript/jsdtoa.h deleted file mode 100644 index 409f4545..00000000 --- a/lib/javascript/jsdtoa.h +++ /dev/null @@ -1,130 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jsdtoa_h___ -#define jsdtoa_h___ -/* - * Public interface to portable double-precision floating point to string - * and back conversion package. - */ - -#include "jscompat.h" - -JS_BEGIN_EXTERN_C - -/* - * JS_strtod() returns as a double-precision floating-point number - * the value represented by the character string pointed to by - * s00. The string is scanned up to the first unrecognized - * character. - * If the value of se is not (char **)NULL, a pointer to - * the character terminating the scan is returned in the location pointed - * to by se. If no number can be formed, se is set to s00r, and - * zero is returned. - * - * *err is set to zero on success; it's set to JS_DTOA_ERANGE on range - * errors and JS_DTOA_ENOMEM on memory failure. - */ -#define JS_DTOA_ERANGE 1 -#define JS_DTOA_ENOMEM 2 -JS_FRIEND_API(double) -JS_strtod(const char *s00, char **se, int *err); - -/* - * Modes for converting floating-point numbers to strings. - * - * Some of the modes can round-trip; this means that if the number is converted to - * a string using one of these mode and then converted back to a number, the result - * will be identical to the original number (except that, due to ECMA, -0 will get converted - * to +0). These round-trip modes return the minimum number of significand digits that - * permit the round trip. - * - * Some of the modes take an integer parameter . - */ -/* NB: Keep this in sync with number_constants[]. */ -typedef enum JSDToStrMode { - DTOSTR_STANDARD, /* Either fixed or exponential format; round-trip */ - DTOSTR_STANDARD_EXPONENTIAL, /* Always exponential format; round-trip */ - DTOSTR_FIXED, /* Round to digits after the decimal point; exponential if number is large */ - DTOSTR_EXPONENTIAL, /* Always exponential format; significant digits */ - DTOSTR_PRECISION /* Either fixed or exponential format; significant digits */ -} JSDToStrMode; - - -/* Maximum number of characters (including trailing null) that a DTOSTR_STANDARD or DTOSTR_STANDARD_EXPONENTIAL - * conversion can produce. This maximum is reached for a number like -0.0000012345678901234567. */ -#define DTOSTR_STANDARD_BUFFER_SIZE 26 - -/* Maximum number of characters (including trailing null) that one of the other conversions - * can produce. This maximum is reached for TO_FIXED, which can generate up to 21 digits before the decimal point. */ -#define DTOSTR_VARIABLE_BUFFER_SIZE(precision) ((precision)+24 > DTOSTR_STANDARD_BUFFER_SIZE ? (precision)+24 : DTOSTR_STANDARD_BUFFER_SIZE) - -/* - * Convert dval according to the given mode and return a pointer to the resulting ASCII string. - * The result is held somewhere in buffer, but not necessarily at the beginning. The size of - * buffer is given in bufferSize, and must be at least as large as given by the above macros. - * - * Return NULL if out of memory. - */ -JS_FRIEND_API(char *) -JS_dtostr(char *buffer, size_t bufferSize, JSDToStrMode mode, int precision, double dval); - -/* - * Convert d to a string in the given base. The integral part of d will be printed exactly - * in that base, regardless of how large it is, because there is no exponential notation for non-base-ten - * numbers. The fractional part will be rounded to as few digits as possible while still preserving - * the round-trip property (analogous to that of printing decimal numbers). In other words, if one were - * to read the resulting string in via a hypothetical base-number-reading routine that rounds to the nearest - * IEEE double (and to an even significand if there are two equally near doubles), then the result would - * equal d (except for -0.0, which converts to "0", and NaN, which is not equal to itself). - * - * Return NULL if out of memory. If the result is not NULL, it must be released via free(). - */ -JS_FRIEND_API(char *) -JS_dtobasestr(int base, double d); - -/* - * Clean up any persistent RAM allocated during the execution of DtoA - * routines, and remove any locks that might have been created. - */ -extern void js_FinishDtoa(void); - -JS_END_EXTERN_C - -#endif /* jsdtoa_h___ */ diff --git a/lib/javascript/jsemit.c b/lib/javascript/jsemit.c deleted file mode 100644 index c7e32f20..00000000 --- a/lib/javascript/jsemit.c +++ /dev/null @@ -1,5399 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sw=4 et tw=80: - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JS bytecode generation. - */ -#include "jsstddef.h" -#ifdef HAVE_MEMORY_H -#include -#endif -#include -#include "jstypes.h" -#include "jsarena.h" /* Added by JSIFY */ -#include "jsutil.h" /* Added by JSIFY */ -#include "jsbit.h" -#include "jsprf.h" -#include "jsapi.h" -#include "jsatom.h" -#include "jscntxt.h" -#include "jsconfig.h" -#include "jsemit.h" -#include "jsfun.h" -#include "jsnum.h" -#include "jsopcode.h" -#include "jsparse.h" -#include "jsregexp.h" -#include "jsscan.h" -#include "jsscope.h" -#include "jsscript.h" - -/* Allocation chunk counts, must be powers of two in general. */ -#define BYTECODE_CHUNK 256 /* code allocation increment */ -#define SRCNOTE_CHUNK 64 /* initial srcnote allocation increment */ -#define TRYNOTE_CHUNK 64 /* trynote allocation increment */ - -/* Macros to compute byte sizes from typed element counts. */ -#define BYTECODE_SIZE(n) ((n) * sizeof(jsbytecode)) -#define SRCNOTE_SIZE(n) ((n) * sizeof(jssrcnote)) -#define TRYNOTE_SIZE(n) ((n) * sizeof(JSTryNote)) - -JS_FRIEND_API(JSBool) -js_InitCodeGenerator(JSContext *cx, JSCodeGenerator *cg, - JSArenaPool *codePool, JSArenaPool *notePool, - const char *filename, uintN lineno, - JSPrincipals *principals) -{ - memset(cg, 0, sizeof *cg); - TREE_CONTEXT_INIT(&cg->treeContext); - cg->treeContext.flags |= TCF_COMPILING; - cg->codePool = codePool; - cg->notePool = notePool; - cg->codeMark = JS_ARENA_MARK(codePool); - cg->noteMark = JS_ARENA_MARK(notePool); - cg->tempMark = JS_ARENA_MARK(&cx->tempPool); - cg->current = &cg->main; - cg->filename = filename; - cg->firstLine = cg->prolog.currentLine = cg->main.currentLine = lineno; - cg->principals = principals; - ATOM_LIST_INIT(&cg->atomList); - cg->prolog.noteMask = cg->main.noteMask = SRCNOTE_CHUNK - 1; - ATOM_LIST_INIT(&cg->constList); - return JS_TRUE; -} - -JS_FRIEND_API(void) -js_FinishCodeGenerator(JSContext *cx, JSCodeGenerator *cg) -{ - TREE_CONTEXT_FINISH(&cg->treeContext); - JS_ARENA_RELEASE(cg->codePool, cg->codeMark); - JS_ARENA_RELEASE(cg->notePool, cg->noteMark); - JS_ARENA_RELEASE(&cx->tempPool, cg->tempMark); -} - -static ptrdiff_t -EmitCheck(JSContext *cx, JSCodeGenerator *cg, JSOp op, ptrdiff_t delta) -{ - jsbytecode *base, *limit, *next; - ptrdiff_t offset, length; - size_t incr, size; - - base = CG_BASE(cg); - next = CG_NEXT(cg); - limit = CG_LIMIT(cg); - offset = PTRDIFF(next, base, jsbytecode); - if (next + delta > limit) { - length = offset + delta; - length = (length <= BYTECODE_CHUNK) - ? BYTECODE_CHUNK - : JS_BIT(JS_CeilingLog2(length)); - incr = BYTECODE_SIZE(length); - if (!base) { - JS_ARENA_ALLOCATE_CAST(base, jsbytecode *, cg->codePool, incr); - } else { - size = BYTECODE_SIZE(PTRDIFF(limit, base, jsbytecode)); - incr -= size; - JS_ARENA_GROW_CAST(base, jsbytecode *, cg->codePool, size, incr); - } - if (!base) { - JS_ReportOutOfMemory(cx); - return -1; - } - CG_BASE(cg) = base; - CG_LIMIT(cg) = base + length; - CG_NEXT(cg) = base + offset; - } - return offset; -} - -static void -UpdateDepth(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t target) -{ - jsbytecode *pc; - const JSCodeSpec *cs; - intN nuses; - - pc = CG_CODE(cg, target); - cs = &js_CodeSpec[pc[0]]; - nuses = cs->nuses; - if (nuses < 0) - nuses = 2 + GET_ARGC(pc); /* stack: fun, this, [argc arguments] */ - cg->stackDepth -= nuses; - JS_ASSERT(cg->stackDepth >= 0); - if (cg->stackDepth < 0) { - char numBuf[12]; - JS_snprintf(numBuf, sizeof numBuf, "%d", target); - JS_ReportErrorFlagsAndNumber(cx, JSREPORT_WARNING, - js_GetErrorMessage, NULL, - JSMSG_STACK_UNDERFLOW, - cg->filename ? cg->filename : "stdin", - numBuf); - } - cg->stackDepth += cs->ndefs; - if ((uintN)cg->stackDepth > cg->maxStackDepth) - cg->maxStackDepth = cg->stackDepth; -} - -ptrdiff_t -js_Emit1(JSContext *cx, JSCodeGenerator *cg, JSOp op) -{ - ptrdiff_t offset = EmitCheck(cx, cg, op, 1); - - if (offset >= 0) { - *CG_NEXT(cg)++ = (jsbytecode)op; - UpdateDepth(cx, cg, offset); - } - return offset; -} - -ptrdiff_t -js_Emit2(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1) -{ - ptrdiff_t offset = EmitCheck(cx, cg, op, 2); - - if (offset >= 0) { - jsbytecode *next = CG_NEXT(cg); - next[0] = (jsbytecode)op; - next[1] = op1; - CG_NEXT(cg) = next + 2; - UpdateDepth(cx, cg, offset); - } - return offset; -} - -ptrdiff_t -js_Emit3(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1, - jsbytecode op2) -{ - ptrdiff_t offset = EmitCheck(cx, cg, op, 3); - - if (offset >= 0) { - jsbytecode *next = CG_NEXT(cg); - next[0] = (jsbytecode)op; - next[1] = op1; - next[2] = op2; - CG_NEXT(cg) = next + 3; - UpdateDepth(cx, cg, offset); - } - return offset; -} - -ptrdiff_t -js_EmitN(JSContext *cx, JSCodeGenerator *cg, JSOp op, size_t extra) -{ - ptrdiff_t length = 1 + (ptrdiff_t)extra; - ptrdiff_t offset = EmitCheck(cx, cg, op, length); - - if (offset >= 0) { - jsbytecode *next = CG_NEXT(cg); - *next = (jsbytecode)op; - memset(next + 1, 0, BYTECODE_SIZE(extra)); - CG_NEXT(cg) = next + length; - UpdateDepth(cx, cg, offset); - } - return offset; -} - -/* XXX too many "... statement" L10N gaffes below -- fix via js.msg! */ -const char js_with_statement_str[] = "with statement"; -const char js_script_str[] = "script"; - -static const char *statementName[] = { - "block", /* BLOCK */ - "label statement", /* LABEL */ - "if statement", /* IF */ - "else statement", /* ELSE */ - "switch statement", /* SWITCH */ - js_with_statement_str, /* WITH */ - "try statement", /* TRY */ - "catch block", /* CATCH */ - "finally statement", /* FINALLY */ - "do loop", /* DO_LOOP */ - "for loop", /* FOR_LOOP */ - "for/in loop", /* FOR_IN_LOOP */ - "while loop", /* WHILE_LOOP */ -}; - -static const char * -StatementName(JSCodeGenerator *cg) -{ - if (!cg->treeContext.topStmt) - return js_script_str; - return statementName[cg->treeContext.topStmt->type]; -} - -static void -ReportStatementTooLarge(JSContext *cx, JSCodeGenerator *cg) -{ - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NEED_DIET, - StatementName(cg)); -} - -/** - Span-dependent instructions in JS bytecode consist of the jump (JOF_JUMP) - and switch (JOF_LOOKUPSWITCH, JOF_TABLESWITCH) format opcodes, subdivided - into unconditional (gotos and gosubs), and conditional jumps or branches - (which pop a value, test it, and jump depending on its value). Most jumps - have just one immediate operand, a signed offset from the jump opcode's pc - to the target bytecode. The lookup and table switch opcodes may contain - many jump offsets. - - Mozilla bug #80981 (http://bugzilla.mozilla.org/show_bug.cgi?id=80981) was - fixed by adding extended "X" counterparts to the opcodes/formats (NB: X is - suffixed to prefer JSOP_ORX thereby avoiding a JSOP_XOR name collision for - the extended form of the JSOP_OR branch opcode). The unextended or short - formats have 16-bit signed immediate offset operands, the extended or long - formats have 32-bit signed immediates. The span-dependency problem consists - of selecting as few long instructions as possible, or about as few -- since - jumps can span other jumps, extending one jump may cause another to need to - be extended. - - Most JS scripts are short, so need no extended jumps. We optimize for this - case by generating short jumps until we know a long jump is needed. After - that point, we keep generating short jumps, but each jump's 16-bit immediate - offset operand is actually an unsigned index into cg->spanDeps, an array of - JSSpanDep structs. Each struct tells the top offset in the script of the - opcode, the "before" offset of the jump (which will be the same as top for - simplex jumps, but which will index further into the bytecode array for a - non-initial jump offset in a lookup or table switch), the after "offset" - adjusted during span-dependent instruction selection (initially the same - value as the "before" offset), and the jump target (more below). - - Since we generate cg->spanDeps lazily, from within js_SetJumpOffset, we must - ensure that all bytecode generated so far can be inspected to discover where - the jump offset immediate operands lie within CG_CODE(cg). But the bonus is - that we generate span-dependency records sorted by their offsets, so we can - binary-search when trying to find a JSSpanDep for a given bytecode offset, - or the nearest JSSpanDep at or above a given pc. - - To avoid limiting scripts to 64K jumps, if the cg->spanDeps index overflows - 65534, we store SPANDEP_INDEX_HUGE in the jump's immediate operand. This - tells us that we need to binary-search for the cg->spanDeps entry by the - jump opcode's bytecode offset (sd->before). - - Jump targets need to be maintained in a data structure that lets us look - up an already-known target by its address (jumps may have a common target), - and that also lets us update the addresses (script-relative, a.k.a. absolute - offsets) of targets that come after a jump target (for when a jump below - that target needs to be extended). We use an AVL tree, implemented using - recursion, but with some tricky optimizations to its height-balancing code - (see http://www.cmcrossroads.com/bradapp/ftp/src/libs/C++/AvlTrees.html). - - A final wrinkle: backpatch chains are linked by jump-to-jump offsets with - positive sign, even though they link "backward" (i.e., toward lower bytecode - address). We don't want to waste space and search time in the AVL tree for - such temporary backpatch deltas, so we use a single-bit wildcard scheme to - tag true JSJumpTarget pointers and encode untagged, signed (positive) deltas - in JSSpanDep.target pointers, depending on whether the JSSpanDep has a known - target, or is still awaiting backpatching. - - Note that backpatch chains would present a problem for BuildSpanDepTable, - which inspects bytecode to build cg->spanDeps on demand, when the first - short jump offset overflows. To solve this temporary problem, we emit a - proxy bytecode (JSOP_BACKPATCH; JSOP_BACKPATCH_POP for branch ops) whose - nuses/ndefs counts help keep the stack balanced, but whose opcode format - distinguishes its backpatch delta immediate operand from a normal jump - offset. - */ -static int -BalanceJumpTargets(JSJumpTarget **jtp) -{ - JSJumpTarget *jt, *jt2, *root; - int dir, otherDir, heightChanged; - JSBool doubleRotate; - - jt = *jtp; - JS_ASSERT(jt->balance != 0); - - if (jt->balance < -1) { - dir = JT_RIGHT; - doubleRotate = (jt->kids[JT_LEFT]->balance > 0); - } else if (jt->balance > 1) { - dir = JT_LEFT; - doubleRotate = (jt->kids[JT_RIGHT]->balance < 0); - } else { - return 0; - } - - otherDir = JT_OTHER_DIR(dir); - if (doubleRotate) { - jt2 = jt->kids[otherDir]; - *jtp = root = jt2->kids[dir]; - - jt->kids[otherDir] = root->kids[dir]; - root->kids[dir] = jt; - - jt2->kids[dir] = root->kids[otherDir]; - root->kids[otherDir] = jt2; - - heightChanged = 1; - root->kids[JT_LEFT]->balance = -JS_MAX(root->balance, 0); - root->kids[JT_RIGHT]->balance = -JS_MIN(root->balance, 0); - root->balance = 0; - } else { - *jtp = root = jt->kids[otherDir]; - jt->kids[otherDir] = root->kids[dir]; - root->kids[dir] = jt; - - heightChanged = (root->balance != 0); - jt->balance = -((dir == JT_LEFT) ? --root->balance : ++root->balance); - } - - return heightChanged; -} - -typedef struct AddJumpTargetArgs { - JSContext *cx; - JSCodeGenerator *cg; - ptrdiff_t offset; - JSJumpTarget *node; -} AddJumpTargetArgs; - -static int -AddJumpTarget(AddJumpTargetArgs *args, JSJumpTarget **jtp) -{ - JSJumpTarget *jt; - int balanceDelta; - - jt = *jtp; - if (!jt) { - JSCodeGenerator *cg = args->cg; - - jt = cg->jtFreeList; - if (jt) { - cg->jtFreeList = jt->kids[JT_LEFT]; - } else { - JS_ARENA_ALLOCATE_CAST(jt, JSJumpTarget *, &args->cx->tempPool, - sizeof *jt); - if (!jt) { - JS_ReportOutOfMemory(args->cx); - return 0; - } - } - jt->offset = args->offset; - jt->balance = 0; - jt->kids[JT_LEFT] = jt->kids[JT_RIGHT] = NULL; - cg->numJumpTargets++; - args->node = jt; - *jtp = jt; - return 1; - } - - if (jt->offset == args->offset) { - args->node = jt; - return 0; - } - - if (args->offset < jt->offset) - balanceDelta = -AddJumpTarget(args, &jt->kids[JT_LEFT]); - else - balanceDelta = AddJumpTarget(args, &jt->kids[JT_RIGHT]); - if (!args->node) - return 0; - - jt->balance += balanceDelta; - return (balanceDelta && jt->balance) - ? 1 - BalanceJumpTargets(jtp) - : 0; -} - -#ifdef DEBUG_brendan -static int AVLCheck(JSJumpTarget *jt) -{ - int lh, rh; - - if (!jt) return 0; - JS_ASSERT(-1 <= jt->balance && jt->balance <= 1); - lh = AVLCheck(jt->kids[JT_LEFT]); - rh = AVLCheck(jt->kids[JT_RIGHT]); - JS_ASSERT(jt->balance == rh - lh); - return 1 + JS_MAX(lh, rh); -} -#endif - -static JSBool -SetSpanDepTarget(JSContext *cx, JSCodeGenerator *cg, JSSpanDep *sd, - ptrdiff_t off) -{ - AddJumpTargetArgs args; - - if (off < JUMPX_OFFSET_MIN || JUMPX_OFFSET_MAX < off) { - ReportStatementTooLarge(cx, cg); - return JS_FALSE; - } - - args.cx = cx; - args.cg = cg; - args.offset = sd->top + off; - args.node = NULL; - AddJumpTarget(&args, &cg->jumpTargets); - if (!args.node) - return JS_FALSE; - -#ifdef DEBUG_brendan - AVLCheck(cg->jumpTargets); -#endif - - SD_SET_TARGET(sd, args.node); - return JS_TRUE; -} - -#define SPANDEPS_MIN 256 -#define SPANDEPS_SIZE(n) ((n) * sizeof(JSSpanDep)) -#define SPANDEPS_SIZE_MIN SPANDEPS_SIZE(SPANDEPS_MIN) - -static JSBool -AddSpanDep(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc, jsbytecode *pc2, - ptrdiff_t off) -{ - uintN index; - JSSpanDep *sdbase, *sd; - size_t size; - - index = cg->numSpanDeps; - if (index + 1 == 0) { - ReportStatementTooLarge(cx, cg); - return JS_FALSE; - } - - if ((index & (index - 1)) == 0 && - (!(sdbase = cg->spanDeps) || index >= SPANDEPS_MIN)) { - if (!sdbase) { - size = SPANDEPS_SIZE_MIN; - JS_ARENA_ALLOCATE_CAST(sdbase, JSSpanDep *, &cx->tempPool, size); - } else { - size = SPANDEPS_SIZE(index); - JS_ARENA_GROW_CAST(sdbase, JSSpanDep *, &cx->tempPool, size, size); - } - if (!sdbase) - return JS_FALSE; - cg->spanDeps = sdbase; - } - - cg->numSpanDeps = index + 1; - sd = cg->spanDeps + index; - sd->top = PTRDIFF(pc, CG_BASE(cg), jsbytecode); - sd->offset = sd->before = PTRDIFF(pc2, CG_BASE(cg), jsbytecode); - - if (js_CodeSpec[*pc].format & JOF_BACKPATCH) { - /* Jump offset will be backpatched if off is a non-zero "bpdelta". */ - if (off != 0) { - JS_ASSERT(off >= 1 + JUMP_OFFSET_LEN); - if (off > BPDELTA_MAX) { - ReportStatementTooLarge(cx, cg); - return JS_FALSE; - } - } - SD_SET_BPDELTA(sd, off); - } else if (off == 0) { - /* Jump offset will be patched directly, without backpatch chaining. */ - SD_SET_TARGET(sd, NULL); - } else { - /* The jump offset in off is non-zero, therefore it's already known. */ - if (!SetSpanDepTarget(cx, cg, sd, off)) - return JS_FALSE; - } - - if (index > SPANDEP_INDEX_MAX) - index = SPANDEP_INDEX_HUGE; - SET_SPANDEP_INDEX(pc2, index); - return JS_TRUE; -} - -static JSBool -BuildSpanDepTable(JSContext *cx, JSCodeGenerator *cg) -{ - jsbytecode *pc, *end; - JSOp op; - const JSCodeSpec *cs; - ptrdiff_t len, off; - - pc = CG_BASE(cg) + cg->spanDepTodo; - end = CG_NEXT(cg); - while (pc < end) { - op = (JSOp)*pc; - cs = &js_CodeSpec[op]; - len = (ptrdiff_t)cs->length; - - switch (cs->format & JOF_TYPEMASK) { - case JOF_JUMP: - off = GET_JUMP_OFFSET(pc); - if (!AddSpanDep(cx, cg, pc, pc, off)) - return JS_FALSE; - break; - -#if JS_HAS_SWITCH_STATEMENT - case JOF_TABLESWITCH: - { - jsbytecode *pc2; - jsint i, low, high; - - pc2 = pc; - off = GET_JUMP_OFFSET(pc2); - if (!AddSpanDep(cx, cg, pc, pc2, off)) - return JS_FALSE; - pc2 += JUMP_OFFSET_LEN; - low = GET_JUMP_OFFSET(pc2); - pc2 += JUMP_OFFSET_LEN; - high = GET_JUMP_OFFSET(pc2); - pc2 += JUMP_OFFSET_LEN; - for (i = low; i <= high; i++) { - off = GET_JUMP_OFFSET(pc2); - if (!AddSpanDep(cx, cg, pc, pc2, off)) - return JS_FALSE; - pc2 += JUMP_OFFSET_LEN; - } - len = 1 + pc2 - pc; - break; - } - - case JOF_LOOKUPSWITCH: - { - jsbytecode *pc2; - jsint npairs; - - pc2 = pc; - off = GET_JUMP_OFFSET(pc2); - if (!AddSpanDep(cx, cg, pc, pc2, off)) - return JS_FALSE; - pc2 += JUMP_OFFSET_LEN; - npairs = (jsint) GET_ATOM_INDEX(pc2); - pc2 += ATOM_INDEX_LEN; - while (npairs) { - pc2 += ATOM_INDEX_LEN; - off = GET_JUMP_OFFSET(pc2); - if (!AddSpanDep(cx, cg, pc, pc2, off)) - return JS_FALSE; - pc2 += JUMP_OFFSET_LEN; - npairs--; - } - len = 1 + pc2 - pc; - break; - } -#endif /* JS_HAS_SWITCH_STATEMENT */ - } - - JS_ASSERT(len > 0); - pc += len; - } - - return JS_TRUE; -} - -static JSSpanDep * -GetSpanDep(JSCodeGenerator *cg, jsbytecode *pc) -{ - uintN index; - ptrdiff_t offset; - int lo, hi, mid; - JSSpanDep *sd; - - index = GET_SPANDEP_INDEX(pc); - if (index != SPANDEP_INDEX_HUGE) - return cg->spanDeps + index; - - offset = PTRDIFF(pc, CG_BASE(cg), jsbytecode); - lo = 0; - hi = cg->numSpanDeps - 1; - while (lo <= hi) { - mid = (lo + hi) / 2; - sd = cg->spanDeps + mid; - if (sd->before == offset) - return sd; - if (sd->before < offset) - lo = mid + 1; - else - hi = mid - 1; - } - - JS_ASSERT(0); - return NULL; -} - -static JSBool -SetBackPatchDelta(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc, - ptrdiff_t delta) -{ - JSSpanDep *sd; - - JS_ASSERT(delta >= 1 + JUMP_OFFSET_LEN); - if (!cg->spanDeps && delta < JUMP_OFFSET_MAX) { - SET_JUMP_OFFSET(pc, delta); - return JS_TRUE; - } - - if (delta > BPDELTA_MAX) { - ReportStatementTooLarge(cx, cg); - return JS_FALSE; - } - - if (!cg->spanDeps && !BuildSpanDepTable(cx, cg)) - return JS_FALSE; - - sd = GetSpanDep(cg, pc); - JS_ASSERT(SD_GET_BPDELTA(sd) == 0); - SD_SET_BPDELTA(sd, delta); - return JS_TRUE; -} - -static void -UpdateJumpTargets(JSJumpTarget *jt, ptrdiff_t pivot, ptrdiff_t delta) -{ - if (jt->offset > pivot) { - jt->offset += delta; - if (jt->kids[JT_LEFT]) - UpdateJumpTargets(jt->kids[JT_LEFT], pivot, delta); - } - if (jt->kids[JT_RIGHT]) - UpdateJumpTargets(jt->kids[JT_RIGHT], pivot, delta); -} - -static JSSpanDep * -FindNearestSpanDep(JSCodeGenerator *cg, ptrdiff_t offset, int lo, - JSSpanDep *guard) -{ - int num, hi, mid; - JSSpanDep *sdbase, *sd; - - num = cg->numSpanDeps; - JS_ASSERT(num > 0); - hi = num - 1; - sdbase = cg->spanDeps; - while (lo <= hi) { - mid = (lo + hi) / 2; - sd = sdbase + mid; - if (sd->before == offset) - return sd; - if (sd->before < offset) - lo = mid + 1; - else - hi = mid - 1; - } - if (lo == num) - return guard; - sd = sdbase + lo; - JS_ASSERT(sd->before >= offset && (lo == 0 || sd[-1].before < offset)); - return sd; -} - -static void -FreeJumpTargets(JSCodeGenerator *cg, JSJumpTarget *jt) -{ - if (jt->kids[JT_LEFT]) - FreeJumpTargets(cg, jt->kids[JT_LEFT]); - if (jt->kids[JT_RIGHT]) - FreeJumpTargets(cg, jt->kids[JT_RIGHT]); - jt->kids[JT_LEFT] = cg->jtFreeList; - cg->jtFreeList = jt; -} - -static JSBool -OptimizeSpanDeps(JSContext *cx, JSCodeGenerator *cg) -{ - jsbytecode *pc, *oldpc, *base, *limit, *next; - JSSpanDep *sd, *sd2, *sdbase, *sdlimit, *sdtop, guard; - ptrdiff_t offset, growth, delta, top, pivot, span, length, target; - JSBool done; - JSOp op; - uint32 type; - size_t size, incr; - jssrcnote *sn, *snlimit; - JSSrcNoteSpec *spec; - uintN i, n, noteIndex; - JSTryNote *tn, *tnlimit; -#ifdef DEBUG_brendan - int passes = 0; -#endif - - base = CG_BASE(cg); - sdbase = cg->spanDeps; - sdlimit = sdbase + cg->numSpanDeps; - offset = CG_OFFSET(cg); - growth = 0; - - do { - done = JS_TRUE; - delta = 0; - top = pivot = -1; - sdtop = NULL; - pc = NULL; - op = JSOP_NOP; - type = 0; -#ifdef DEBUG_brendan - passes++; -#endif - - for (sd = sdbase; sd < sdlimit; sd++) { - JS_ASSERT(JT_HAS_TAG(sd->target)); - sd->offset += delta; - - if (sd->top != top) { - sdtop = sd; - top = sd->top; - JS_ASSERT(top == sd->before); - pivot = sd->offset; - pc = base + top; - op = (JSOp) *pc; - type = (js_CodeSpec[op].format & JOF_TYPEMASK); - if (JOF_TYPE_IS_EXTENDED_JUMP(type)) { - /* - * We already extended all the jump offset operands for - * the opcode at sd->top. Jumps and branches have only - * one jump offset operand, but switches have many, all - * of which are adjacent in cg->spanDeps. - */ - continue; - } - - JS_ASSERT(type == JOF_JUMP || - type == JOF_TABLESWITCH || - type == JOF_LOOKUPSWITCH); - } - - if (!JOF_TYPE_IS_EXTENDED_JUMP(type)) { - span = SD_SPAN(sd, pivot); - if (span < JUMP_OFFSET_MIN || JUMP_OFFSET_MAX < span) { - ptrdiff_t deltaFromTop = 0; - - done = JS_FALSE; - - switch (op) { - case JSOP_GOTO: op = JSOP_GOTOX; break; - case JSOP_IFEQ: op = JSOP_IFEQX; break; - case JSOP_IFNE: op = JSOP_IFNEX; break; - case JSOP_OR: op = JSOP_ORX; break; - case JSOP_AND: op = JSOP_ANDX; break; - case JSOP_GOSUB: op = JSOP_GOSUBX; break; - case JSOP_CASE: op = JSOP_CASEX; break; - case JSOP_DEFAULT: op = JSOP_DEFAULTX; break; - case JSOP_TABLESWITCH: op = JSOP_TABLESWITCHX; break; - case JSOP_LOOKUPSWITCH: op = JSOP_LOOKUPSWITCHX; break; - default: JS_ASSERT(0); - } - *pc = (jsbytecode) op; - - for (sd2 = sdtop; sd2 < sdlimit && sd2->top == top; sd2++) { - if (sd2 <= sd) { - /* - * sd2->offset already includes delta as it stood - * before we entered this loop, but it must also - * include the delta relative to top due to all the - * extended jump offset immediates for the opcode - * starting at top, which we extend in this loop. - * - * If there is only one extended jump offset, then - * sd2->offset won't change and this for loop will - * iterate once only. - */ - sd2->offset += deltaFromTop; - deltaFromTop += JUMPX_OFFSET_LEN - JUMP_OFFSET_LEN; - } else { - /* - * sd2 comes after sd, and won't be revisited by - * the outer for loop, so we have to increase its - * offset by delta, not merely by deltaFromTop. - */ - sd2->offset += delta; - } - - delta += JUMPX_OFFSET_LEN - JUMP_OFFSET_LEN; - UpdateJumpTargets(cg->jumpTargets, sd2->offset, - JUMPX_OFFSET_LEN - JUMP_OFFSET_LEN); - } - sd = sd2 - 1; - } - } - } - - growth += delta; - } while (!done); - - if (growth) { -#ifdef DEBUG_brendan - printf("%s:%u: %u/%u jumps extended in %d passes (%d=%d+%d)\n", - cg->filename ? cg->filename : "stdin", cg->firstLine, - growth / (JUMPX_OFFSET_LEN - JUMP_OFFSET_LEN), cg->numSpanDeps, - passes, offset + growth, offset, growth); -#endif - - /* - * Ensure that we have room for the extended jumps, but don't round up - * to a power of two -- we're done generating code, so we cut to fit. - */ - limit = CG_LIMIT(cg); - length = offset + growth; - next = base + length; - if (next > limit) { - JS_ASSERT(length > BYTECODE_CHUNK); - size = BYTECODE_SIZE(PTRDIFF(limit, base, jsbytecode)); - incr = BYTECODE_SIZE(length) - size; - JS_ARENA_GROW_CAST(base, jsbytecode *, cg->codePool, size, incr); - if (!base) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - CG_BASE(cg) = base; - CG_LIMIT(cg) = next = base + length; - } - CG_NEXT(cg) = next; - - /* - * Set up a fake span dependency record to guard the end of the code - * being generated. This guard record is returned as a fencepost by - * FindNearestSpanDep if there is no real spandep at or above a given - * unextended code offset. - */ - guard.top = -1; - guard.offset = offset + growth; - guard.before = offset; - guard.target = NULL; - } - - /* - * Now work backwards through the span dependencies, copying chunks of - * bytecode between each extended jump toward the end of the grown code - * space, and restoring immediate offset operands for all jump bytecodes. - * The first chunk of bytecodes, starting at base and ending at the first - * extended jump offset (NB: this chunk includes the operation bytecode - * just before that immediate jump offset), doesn't need to be copied. - */ - JS_ASSERT(sd == sdlimit); - top = -1; - while (--sd >= sdbase) { - if (sd->top != top) { - top = sd->top; - op = (JSOp) base[top]; - type = (js_CodeSpec[op].format & JOF_TYPEMASK); - - for (sd2 = sd - 1; sd2 >= sdbase && sd2->top == top; sd2--) - continue; - sd2++; - pivot = sd2->offset; - JS_ASSERT(top == sd2->before); - } - - oldpc = base + sd->before; - span = SD_SPAN(sd, pivot); - - /* - * If this jump didn't need to be extended, restore its span immediate - * offset operand now, overwriting the index of sd within cg->spanDeps - * that was stored temporarily after *pc when BuildSpanDepTable ran. - * - * Note that span might fit in 16 bits even for an extended jump op, - * if the op has multiple span operands, not all of which overflowed - * (e.g. JSOP_LOOKUPSWITCH or JSOP_TABLESWITCH where some cases are in - * range for a short jump, but others are not). - */ - if (!JOF_TYPE_IS_EXTENDED_JUMP(type)) { - JS_ASSERT(JUMP_OFFSET_MIN <= span && span <= JUMP_OFFSET_MAX); - SET_JUMP_OFFSET(oldpc, span); - continue; - } - - /* - * Set up parameters needed to copy the next run of bytecode starting - * at offset (which is a cursor into the unextended, original bytecode - * vector), down to sd->before (a cursor of the same scale as offset, - * it's the index of the original jump pc). Reuse delta to count the - * nominal number of bytes to copy. - */ - pc = base + sd->offset; - delta = offset - sd->before; - JS_ASSERT(delta >= 1 + JUMP_OFFSET_LEN); - - /* - * Don't bother copying the jump offset we're about to reset, but do - * copy the bytecode at oldpc (which comes just before its immediate - * jump offset operand), on the next iteration through the loop, by - * including it in offset's new value. - */ - offset = sd->before + 1; - size = BYTECODE_SIZE(delta - (1 + JUMP_OFFSET_LEN)); - if (size) { - memmove(pc + 1 + JUMPX_OFFSET_LEN, - oldpc + 1 + JUMP_OFFSET_LEN, - size); - } - - SET_JUMPX_OFFSET(pc, span); - } - - if (growth) { - /* - * Fix source note deltas. Don't hardwire the delta fixup adjustment, - * even though currently it must be JUMPX_OFFSET_LEN - JUMP_OFFSET_LEN - * at each sd that moved. The future may bring different offset sizes - * for span-dependent instruction operands. However, we fix only main - * notes here, not prolog notes -- we know that prolog opcodes are not - * span-dependent, and aren't likely ever to be. - */ - offset = growth = 0; - sd = sdbase; - for (sn = cg->main.notes, snlimit = sn + cg->main.noteCount; - sn < snlimit; - sn = SN_NEXT(sn)) { - /* - * Recall that the offset of a given note includes its delta, and - * tells the offset of the annotated bytecode from the main entry - * point of the script. - */ - offset += SN_DELTA(sn); - while (sd < sdlimit && sd->before < offset) { - /* - * To compute the delta to add to sn, we need to look at the - * spandep after sd, whose offset - (before + growth) tells by - * how many bytes sd's instruction grew. - */ - sd2 = sd + 1; - if (sd2 == sdlimit) - sd2 = &guard; - delta = sd2->offset - (sd2->before + growth); - if (delta > 0) { - JS_ASSERT(delta == JUMPX_OFFSET_LEN - JUMP_OFFSET_LEN); - sn = js_AddToSrcNoteDelta(cx, cg, sn, delta); - if (!sn) - return JS_FALSE; - snlimit = cg->main.notes + cg->main.noteCount; - growth += delta; - } - sd++; - } - - /* - * If sn has span-dependent offset operands, check whether each - * covers further span-dependencies, and increase those operands - * accordingly. Some source notes measure offset not from the - * annotated pc, but from that pc plus some small bias. NB: we - * assume that spec->offsetBias can't itself span span-dependent - * instructions! - */ - spec = &js_SrcNoteSpec[SN_TYPE(sn)]; - if (spec->isSpanDep) { - pivot = offset + spec->offsetBias; - n = spec->arity; - for (i = 0; i < n; i++) { - span = js_GetSrcNoteOffset(sn, i); - if (span == 0) - continue; - target = pivot + span * spec->isSpanDep; - sd2 = FindNearestSpanDep(cg, target, - (target >= pivot) - ? sd - sdbase - : 0, - &guard); - - /* - * Increase target by sd2's before-vs-after offset delta, - * which is absolute (i.e., relative to start of script, - * as is target). Recompute the span by subtracting its - * adjusted pivot from target. - */ - target += sd2->offset - sd2->before; - span = target - (pivot + growth); - span *= spec->isSpanDep; - noteIndex = sn - cg->main.notes; - if (!js_SetSrcNoteOffset(cx, cg, noteIndex, i, span)) - return JS_FALSE; - sn = cg->main.notes + noteIndex; - snlimit = cg->main.notes + cg->main.noteCount; - } - } - } - cg->main.lastNoteOffset += growth; - - /* - * Fix try/catch notes (O(numTryNotes * log2(numSpanDeps)), but it's - * not clear how we can beat that). - */ - for (tn = cg->tryBase, tnlimit = cg->tryNext; tn < tnlimit; tn++) { - /* - * First, look for the nearest span dependency at/above tn->start. - * There may not be any such spandep, in which case the guard will - * be returned. - */ - offset = tn->start; - sd = FindNearestSpanDep(cg, offset, 0, &guard); - delta = sd->offset - sd->before; - tn->start = offset + delta; - - /* - * Next, find the nearest spandep at/above tn->start + tn->length. - * Use its delta minus tn->start's delta to increase tn->length. - */ - length = tn->length; - sd2 = FindNearestSpanDep(cg, offset + length, sd - sdbase, &guard); - if (sd2 != sd) - tn->length = length + sd2->offset - sd2->before - delta; - - /* - * Finally, adjust tn->catchStart upward only if it is non-zero, - * and provided there are spandeps below it that grew. - */ - offset = tn->catchStart; - if (offset != 0) { - sd = FindNearestSpanDep(cg, offset, sd2 - sdbase, &guard); - tn->catchStart = offset + sd->offset - sd->before; - } - } - } - -#ifdef DEBUG_brendan - { - uintN bigspans = 0; - top = -1; - for (sd = sdbase; sd < sdlimit; sd++) { - offset = sd->offset; - - /* NB: sd->top cursors into the original, unextended bytecode vector. */ - if (sd->top != top) { - JS_ASSERT(top == -1 || - !JOF_TYPE_IS_EXTENDED_JUMP(type) || - bigspans != 0); - bigspans = 0; - top = sd->top; - JS_ASSERT(top == sd->before); - op = (JSOp) base[offset]; - type = (js_CodeSpec[op].format & JOF_TYPEMASK); - JS_ASSERT(type == JOF_JUMP || - type == JOF_JUMPX || - type == JOF_TABLESWITCH || - type == JOF_TABLESWITCHX || - type == JOF_LOOKUPSWITCH || - type == JOF_LOOKUPSWITCHX); - pivot = offset; - } - - pc = base + offset; - if (JOF_TYPE_IS_EXTENDED_JUMP(type)) { - span = GET_JUMPX_OFFSET(pc); - if (span < JUMP_OFFSET_MIN || JUMP_OFFSET_MAX < span) { - bigspans++; - } else { - JS_ASSERT(type == JOF_TABLESWITCHX || - type == JOF_LOOKUPSWITCHX); - } - } else { - span = GET_JUMP_OFFSET(pc); - } - JS_ASSERT(SD_SPAN(sd, pivot) == span); - } - JS_ASSERT(!JOF_TYPE_IS_EXTENDED_JUMP(type) || bigspans != 0); - } -#endif - - /* - * Reset so we optimize at most once -- cg may be used for further code - * generation of successive, independent, top-level statements. No jump - * can span top-level statements, because JS lacks goto. - */ - size = SPANDEPS_SIZE(JS_BIT(JS_CeilingLog2(cg->numSpanDeps))); - JS_ArenaFreeAllocation(&cx->tempPool, cg->spanDeps, - JS_MAX(size, SPANDEPS_SIZE_MIN)); - cg->spanDeps = NULL; - FreeJumpTargets(cg, cg->jumpTargets); - cg->jumpTargets = NULL; - cg->numSpanDeps = cg->numJumpTargets = 0; - cg->spanDepTodo = CG_OFFSET(cg); - return JS_TRUE; -} - -static JSBool -EmitJump(JSContext *cx, JSCodeGenerator *cg, JSOp op, ptrdiff_t off) -{ - JSBool extend; - ptrdiff_t jmp; - jsbytecode *pc; - - extend = off < JUMP_OFFSET_MIN || JUMP_OFFSET_MAX < off; - if (extend && !cg->spanDeps && !BuildSpanDepTable(cx, cg)) - return JS_FALSE; - - jmp = js_Emit3(cx, cg, op, JUMP_OFFSET_HI(off), JUMP_OFFSET_LO(off)); - if (jmp >= 0 && (extend || cg->spanDeps)) { - pc = CG_CODE(cg, jmp); - if (!AddSpanDep(cx, cg, pc, pc, off)) - return JS_FALSE; - } - return jmp; -} - -static ptrdiff_t -GetJumpOffset(JSCodeGenerator *cg, jsbytecode *pc) -{ - JSSpanDep *sd; - JSJumpTarget *jt; - ptrdiff_t top; - - if (!cg->spanDeps) - return GET_JUMP_OFFSET(pc); - - sd = GetSpanDep(cg, pc); - jt = sd->target; - if (!JT_HAS_TAG(jt)) - return JT_TO_BPDELTA(jt); - - top = sd->top; - while (--sd >= cg->spanDeps && sd->top == top) - continue; - sd++; - return JT_CLR_TAG(jt)->offset - sd->offset; -} - -JSBool -js_SetJumpOffset(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc, - ptrdiff_t off) -{ - if (!cg->spanDeps) { - if (JUMP_OFFSET_MIN <= off && off <= JUMP_OFFSET_MAX) { - SET_JUMP_OFFSET(pc, off); - return JS_TRUE; - } - - if (!BuildSpanDepTable(cx, cg)) - return JS_FALSE; - } - - return SetSpanDepTarget(cx, cg, GetSpanDep(cg, pc), off); -} - -JSBool -js_InWithStatement(JSTreeContext *tc) -{ - JSStmtInfo *stmt; - - for (stmt = tc->topStmt; stmt; stmt = stmt->down) { - if (stmt->type == STMT_WITH) - return JS_TRUE; - } - return JS_FALSE; -} - -JSBool -js_InCatchBlock(JSTreeContext *tc, JSAtom *atom) -{ - JSStmtInfo *stmt; - - for (stmt = tc->topStmt; stmt; stmt = stmt->down) { - if (stmt->type == STMT_CATCH && stmt->label == atom) - return JS_TRUE; - } - return JS_FALSE; -} - -void -js_PushStatement(JSTreeContext *tc, JSStmtInfo *stmt, JSStmtType type, - ptrdiff_t top) -{ - stmt->type = type; - SET_STATEMENT_TOP(stmt, top); - stmt->label = NULL; - stmt->down = tc->topStmt; - tc->topStmt = stmt; -} - -/* - * Emit a backpatch op with offset pointing to the previous jump of this type, - * so that we can walk back up the chain fixing up the op and jump offset. - */ -static ptrdiff_t -EmitBackPatchOp(JSContext *cx, JSCodeGenerator *cg, JSOp op, ptrdiff_t *lastp) -{ - ptrdiff_t offset, delta; - - offset = CG_OFFSET(cg); - delta = offset - *lastp; - *lastp = offset; - JS_ASSERT(delta > 0); - return EmitJump(cx, cg, op, delta); -} - -/* Emit additional bytecode(s) for non-local jumps. */ -static JSBool -EmitNonLocalJumpFixup(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *toStmt, - JSOp *returnop) -{ - intN depth; - JSStmtInfo *stmt; - ptrdiff_t jmp; - - /* - * Return from within a try block that has a finally clause must be split - * into two ops: JSOP_SETRVAL, to pop the r.v. and store it in fp->rval; - * and JSOP_RETRVAL, which makes control flow go back to the caller, who - * picks up fp->rval as usual. Otherwise, the stack will be unbalanced - * when executing the finally clause. - * - * We mutate *returnop once only if we find an enclosing try-block (viz, - * STMT_FINALLY) to ensure that we emit just one JSOP_SETRVAL before one - * or more JSOP_GOSUBs and other fixup opcodes emitted by this function. - * Our caller (the TOK_RETURN case of js_EmitTree) then emits *returnop. - * The fixup opcodes and gosubs must interleave in the proper order, from - * inner statement to outer, so that finally clauses run at the correct - * stack depth. - */ - if (returnop) { - JS_ASSERT(*returnop == JSOP_RETURN); - for (stmt = cg->treeContext.topStmt; stmt != toStmt; - stmt = stmt->down) { - if (stmt->type == STMT_FINALLY) { - if (js_Emit1(cx, cg, JSOP_SETRVAL) < 0) - return JS_FALSE; - *returnop = JSOP_RETRVAL; - break; - } - } - - /* - * If there are no try-with-finally blocks open around this return - * statement, we can generate a return forthwith and skip generating - * any fixup code. - */ - if (*returnop == JSOP_RETURN) - return JS_TRUE; - } - - /* - * The non-local jump fixup we emit will unbalance cg->stackDepth, because - * the fixup replicates balanced code such as JSOP_LEAVEWITH emitted at the - * end of a with statement, so we save cg->stackDepth here and restore it - * just before a successful return. - */ - depth = cg->stackDepth; - for (stmt = cg->treeContext.topStmt; stmt != toStmt; stmt = stmt->down) { - switch (stmt->type) { - case STMT_FINALLY: - if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0) - return JS_FALSE; - jmp = EmitBackPatchOp(cx, cg, JSOP_BACKPATCH, &stmt->gosub); - if (jmp < 0) - return JS_FALSE; - break; - - case STMT_WITH: - case STMT_CATCH: - /* There's a With object on the stack that we need to pop. */ - if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0) - return JS_FALSE; - if (js_Emit1(cx, cg, JSOP_LEAVEWITH) < 0) - return JS_FALSE; - break; - - case STMT_FOR_IN_LOOP: - /* - * The iterator and the object being iterated need to be popped. - * JSOP_POP2 isn't decompiled, so it doesn't need to be HIDDEN. - */ - if (js_Emit1(cx, cg, JSOP_POP2) < 0) - return JS_FALSE; - break; - - case STMT_SUBROUTINE: - /* - * There's a [exception or hole, retsub pc-index] pair on the - * stack that we need to pop. - */ - if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0) - return JS_FALSE; - if (js_Emit1(cx, cg, JSOP_POP2) < 0) - return JS_FALSE; - break; - - default:; - } - } - - cg->stackDepth = depth; - return JS_TRUE; -} - -static ptrdiff_t -EmitGoto(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *toStmt, - ptrdiff_t *lastp, JSAtomListElement *label, JSSrcNoteType noteType) -{ - intN index; - - if (!EmitNonLocalJumpFixup(cx, cg, toStmt, NULL)) - return -1; - - if (label) { - index = js_NewSrcNote(cx, cg, noteType); - if (index < 0) - return -1; - if (!js_SetSrcNoteOffset(cx, cg, (uintN)index, 0, - (ptrdiff_t) ALE_INDEX(label))) { - return -1; - } - } else if (noteType != SRC_NULL) { - if (js_NewSrcNote(cx, cg, noteType) < 0) - return -1; - } - - return EmitBackPatchOp(cx, cg, JSOP_BACKPATCH, lastp); -} - -static JSBool -BackPatch(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t last, - jsbytecode *target, jsbytecode op) -{ - jsbytecode *pc, *stop; - ptrdiff_t delta, span; - - pc = CG_CODE(cg, last); - stop = CG_CODE(cg, -1); - while (pc != stop) { - delta = GetJumpOffset(cg, pc); - span = PTRDIFF(target, pc, jsbytecode); - CHECK_AND_SET_JUMP_OFFSET(cx, cg, pc, span); - - /* - * Set *pc after jump offset in case bpdelta didn't overflow, but span - * does (if so, CHECK_AND_SET_JUMP_OFFSET might call BuildSpanDepTable - * and need to see the JSOP_BACKPATCH* op at *pc). - */ - *pc = op; - pc -= delta; - } - return JS_TRUE; -} - -void -js_PopStatement(JSTreeContext *tc) -{ - tc->topStmt = tc->topStmt->down; -} - -JSBool -js_PopStatementCG(JSContext *cx, JSCodeGenerator *cg) -{ - JSStmtInfo *stmt; - - stmt = cg->treeContext.topStmt; - if (!BackPatch(cx, cg, stmt->breaks, CG_NEXT(cg), JSOP_GOTO) || - !BackPatch(cx, cg, stmt->continues, CG_CODE(cg, stmt->update), - JSOP_GOTO)) { - return JS_FALSE; - } - js_PopStatement(&cg->treeContext); - return JS_TRUE; -} - -JSBool -js_DefineCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom, - JSParseNode *pn) -{ - jsdouble dval; - jsint ival; - JSAtom *valueAtom; - JSAtomListElement *ale; - - /* XXX just do numbers for now */ - if (pn->pn_type == TOK_NUMBER) { - dval = pn->pn_dval; - valueAtom = (JSDOUBLE_IS_INT(dval, ival) && INT_FITS_IN_JSVAL(ival)) - ? js_AtomizeInt(cx, ival, 0) - : js_AtomizeDouble(cx, dval, 0); - if (!valueAtom) - return JS_FALSE; - ale = js_IndexAtom(cx, atom, &cg->constList); - if (!ale) - return JS_FALSE; - ALE_SET_VALUE(ale, ATOM_KEY(valueAtom)); - } - return JS_TRUE; -} - -JSBool -js_LookupCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom, - jsval *vp) -{ - JSBool ok; - JSStackFrame *fp; - JSAtomListElement *ale; - JSObject *obj, *pobj; - JSProperty *prop; - uintN attrs; - - /* - * fp chases cg down the stack, but only until we reach the outermost cg. - * This enables propagating consts from top-level into switch cases in a - * function compiled along with the top-level script. All stack frames - * with matching code generators should be flagged with JSFRAME_COMPILING; - * we check sanity here. - */ - *vp = JSVAL_VOID; - ok = JS_TRUE; - fp = cx->fp; - do { - JS_ASSERT(fp->flags & JSFRAME_COMPILING); - - obj = fp->varobj; - if (obj == fp->scopeChain && - !js_InWithStatement(&cg->treeContext) && - !js_InCatchBlock(&cg->treeContext, atom)) { - ATOM_LIST_SEARCH(ale, &cg->constList, atom); - if (ale) { - *vp = ALE_VALUE(ale); - return JS_TRUE; - } - - /* - * Try looking in the variable object for a direct property that - * is readonly and permanent. We know such a property can't be - * shadowed by another property on obj's prototype chain, or a - * with object or catch variable; nor can prop's value be changed, - * nor can prop be deleted. - */ - prop = NULL; - if (OBJ_IS_NATIVE(obj)) { - ok = js_LookupHiddenProperty(cx, obj, ATOM_TO_JSID(atom), - &pobj, &prop); - if (!ok) - break; - if (prop) { - /* - * Any hidden property must be a formal arg or local var, - * which will shadow a global const of the same name. - */ - OBJ_DROP_PROPERTY(cx, pobj, prop); - break; - } - } - - ok = OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &pobj, &prop); - if (ok) { - if (pobj == obj && - (fp->flags & (JSFRAME_EVAL | JSFRAME_COMPILE_N_GO))) { - /* - * We're compiling code that will be executed immediately, - * not re-executed against a different scope chain and/or - * variable object. Therefore we can get constant values - * from our variable object here. - */ - ok = OBJ_GET_ATTRIBUTES(cx, obj, ATOM_TO_JSID(atom), prop, - &attrs); - if (ok && !(~attrs & (JSPROP_READONLY | JSPROP_PERMANENT))) - ok = OBJ_GET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp); - } - if (prop) - OBJ_DROP_PROPERTY(cx, pobj, prop); - } - if (!ok || prop) - break; - } - fp = fp->down; - } while ((cg = cg->parent) != NULL); - return ok; -} - -/* - * Allocate an index invariant for all activations of the code being compiled - * in cg, that can be used to store and fetch a reference to a cloned RegExp - * object that shares the same JSRegExp private data created for the object - * literal in pn->pn_atom. We need clones to hold lastIndex and other direct - * properties that should not be shared among threads sharing a precompiled - * function or script. - * - * If the code being compiled is function code, allocate a reserved slot in - * the cloned function object that shares its precompiled script with other - * cloned function objects and with the compiler-created clone-parent. There - * are fun->nregexps such reserved slots in each function object cloned from - * fun->object. NB: during compilation, funobj slots must never be allocated, - * because js_AllocSlot could hand out one of the slots that should be given - * to a regexp clone. - * - * If the code being compiled is global code, reserve the fp->vars slot at - * ALE_INDEX(ale), by ensuring that cg->treeContext.numGlobalVars is at least - * one more than this index. For global code, fp->vars is parallel to the - * global script->atomMap.vector array, but possibly shorter for the common - * case (where var declarations and regexp literals cluster toward the front - * of the script or function body). - * - * Global variable name literals in script->atomMap have fast-global slot - * numbers (stored as int-tagged jsvals) in the corresponding fp->vars array - * element. The atomIndex for a regexp object literal thus also addresses an - * fp->vars element that is not used by any optimized global variable, so we - * use that GC-scanned element to keep the regexp object clone alive, as well - * as to lazily create and find it at run-time for the JSOP_REGEXP bytecode. - * - * In no case can cx->fp->varobj be a Call object here, because that implies - * we are compiling eval code, in which case (cx->fp->flags & JSFRAME_EVAL) - * is true, and js_GetToken will have already selected JSOP_OBJECT instead of - * JSOP_REGEXP, to avoid all this RegExp object cloning business. - * - * Why clone regexp objects? ECMA specifies that when a regular expression - * literal is scanned, a RegExp object is created. In the spec, compilation - * and execution happen indivisibly, but in this implementation and many of - * its embeddings, code is precompiled early and re-executed in multiple - * threads, or using multiple global objects, or both, for efficiency. - * - * In such cases, naively following ECMA leads to wrongful sharing of RegExp - * objects, which makes for collisions on the lastIndex property (especially - * for global regexps) and on any ad-hoc properties. Also, __proto__ and - * __parent__ refer to the pre-compilation prototype and global objects, a - * pigeon-hole problem for instanceof tests. - */ -static JSBool -IndexRegExpClone(JSContext *cx, JSParseNode *pn, JSAtomListElement *ale, - JSCodeGenerator *cg) -{ - JSObject *varobj, *reobj; - JSClass *clasp; - JSFunction *fun; - JSRegExp *re; - uint16 *countPtr; - uintN cloneIndex; - - JS_ASSERT(!(cx->fp->flags & (JSFRAME_EVAL | JSFRAME_COMPILE_N_GO))); - - varobj = cx->fp->varobj; - clasp = OBJ_GET_CLASS(cx, varobj); - if (clasp == &js_FunctionClass) { - fun = (JSFunction *) JS_GetPrivate(cx, varobj); - countPtr = &fun->nregexps; - cloneIndex = *countPtr; - } else { - JS_ASSERT(clasp != &js_CallClass); - countPtr = &cg->treeContext.numGlobalVars; - cloneIndex = ALE_INDEX(ale); - } - - if ((cloneIndex + 1) >> 16) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_NEED_DIET, js_script_str); - return JS_FALSE; - } - if (cloneIndex >= *countPtr) - *countPtr = cloneIndex + 1; - - reobj = ATOM_TO_OBJECT(pn->pn_atom); - JS_ASSERT(OBJ_GET_CLASS(cx, reobj) == &js_RegExpClass); - re = (JSRegExp *) JS_GetPrivate(cx, reobj); - re->cloneIndex = cloneIndex; - return JS_TRUE; -} - -/* - * Macro to emit a bytecode followed by a uint16 immediate operand stored in - * big-endian order, used for arg and var numbers as well as for atomIndexes. - * NB: We use cx and cg from our caller's lexical environment, and return - * false on error. - */ -#define EMIT_UINT16_IMM_OP(op, i) \ - JS_BEGIN_MACRO \ - if (js_Emit3(cx, cg, op, ATOM_INDEX_HI(i), ATOM_INDEX_LO(i)) < 0) \ - return JS_FALSE; \ - JS_END_MACRO - -/* - * Emit a bytecode and its 2-byte constant (atom) index immediate operand. - * If the atomIndex requires more than 2 bytes, emit a prefix op whose 24-bit - * immediate operand indexes the atom in script->atomMap. - * - * If op has JOF_NAME mode, emit JSOP_FINDNAME to find and push the object in - * the scope chain in which the literal name was found, followed by the name - * as a string. This enables us to use the JOF_ELEM counterpart to op. - * - * Otherwise, if op has JOF_PROP mode, emit JSOP_LITERAL before op, to push - * the atom's value key. For JOF_PROP ops, the object being operated on has - * already been pushed, and JSOP_LITERAL will push the id, leaving the stack - * in the proper state for a JOF_ELEM counterpart. - * - * Otherwise, emit JSOP_LITOPX to push the atom index, then perform a special - * dispatch on op, but getting op's atom index from the stack instead of from - * an unsigned 16-bit immediate operand. - */ -static JSBool -EmitAtomIndexOp(JSContext *cx, JSOp op, jsatomid atomIndex, JSCodeGenerator *cg) -{ - uint32 mode; - JSOp prefixOp; - ptrdiff_t off; - jsbytecode *pc; - - if (atomIndex >= JS_BIT(16)) { - mode = (js_CodeSpec[op].format & JOF_MODEMASK); - if (op != JSOP_SETNAME) { - prefixOp = (mode == JOF_NAME) - ? JSOP_FINDNAME - : (mode == JOF_PROP) - ? JSOP_LITERAL - : JSOP_LITOPX; - off = js_EmitN(cx, cg, prefixOp, 3); - if (off < 0) - return JS_FALSE; - pc = CG_CODE(cg, off); - SET_LITERAL_INDEX(pc, atomIndex); - } - - switch (op) { - case JSOP_DECNAME: op = JSOP_DECELEM; break; - case JSOP_DECPROP: op = JSOP_DECELEM; break; - case JSOP_DELNAME: op = JSOP_DELELEM; break; - case JSOP_DELPROP: op = JSOP_DELELEM; break; - case JSOP_FORNAME: op = JSOP_FORELEM; break; - case JSOP_FORPROP: op = JSOP_FORELEM; break; - case JSOP_GETPROP: op = JSOP_GETELEM; break; - case JSOP_IMPORTPROP: op = JSOP_IMPORTELEM; break; - case JSOP_INCNAME: op = JSOP_INCELEM; break; - case JSOP_INCPROP: op = JSOP_INCELEM; break; - case JSOP_INITPROP: op = JSOP_INITELEM; break; - case JSOP_NAME: op = JSOP_GETELEM; break; - case JSOP_NAMEDEC: op = JSOP_ELEMDEC; break; - case JSOP_NAMEINC: op = JSOP_ELEMINC; break; - case JSOP_PROPDEC: op = JSOP_ELEMDEC; break; - case JSOP_PROPINC: op = JSOP_ELEMINC; break; - case JSOP_BINDNAME: return JS_TRUE; - case JSOP_SETNAME: op = JSOP_SETELEM; break; - case JSOP_SETPROP: op = JSOP_SETELEM; break; - default: JS_ASSERT(mode == 0); break; - } - - return js_Emit1(cx, cg, op) >= 0; - } - - EMIT_UINT16_IMM_OP(op, atomIndex); - return JS_TRUE; -} - -/* - * Slight sugar for EmitAtomIndexOp, again accessing cx and cg from the macro - * caller's lexical environment, and embedding a false return on error. - * XXXbe hey, who checks for fun->nvars and fun->nargs overflow?! - */ -#define EMIT_ATOM_INDEX_OP(op, atomIndex) \ - JS_BEGIN_MACRO \ - if (!EmitAtomIndexOp(cx, op, atomIndex, cg)) \ - return JS_FALSE; \ - JS_END_MACRO - -static JSBool -EmitAtomOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg) -{ - JSAtomListElement *ale; - - ale = js_IndexAtom(cx, pn->pn_atom, &cg->atomList); - if (!ale) - return JS_FALSE; - if (op == JSOP_REGEXP && !IndexRegExpClone(cx, pn, ale, cg)) - return JS_FALSE; - return EmitAtomIndexOp(cx, op, ALE_INDEX(ale), cg); -} - -/* - * This routine tries to optimize name gets and sets to stack slot loads and - * stores, given the variables object and scope chain in cx's top frame, the - * compile-time context in tc, and a TOK_NAME node pn. It returns false on - * error, true on success. - * - * The caller can inspect pn->pn_slot for a non-negative slot number to tell - * whether optimization occurred, in which case LookupArgOrVar also updated - * pn->pn_op. If pn->pn_slot is still -1 on return, pn->pn_op nevertheless - * may have been optimized, e.g., from JSOP_NAME to JSOP_ARGUMENTS. Whether - * or not pn->pn_op was modified, if this function finds an argument or local - * variable name, pn->pn_attrs will contain the property's attributes after a - * successful return. - */ -static JSBool -LookupArgOrVar(JSContext *cx, JSTreeContext *tc, JSParseNode *pn) -{ - JSStackFrame *fp; - JSObject *obj, *pobj; - JSClass *clasp; - JSBool optimizeGlobals; - JSAtom *atom; - JSProperty *prop; - JSScopeProperty *sprop; - JSOp op; - JSPropertyOp getter; - uintN attrs; - jsint slot; - JSAtomListElement *ale; - - JS_ASSERT(pn->pn_type == TOK_NAME); - if (pn->pn_slot >= 0 || pn->pn_op == JSOP_ARGUMENTS) - return JS_TRUE; - - /* QNAME references can never be optimized to use arg/var storage. */ - if (pn->pn_op == JSOP_QNAMEPART) - return JS_TRUE; - - /* - * A Script object can be used to split an eval into a compile step done - * at construction time, and an execute step done separately, possibly in - * a different scope altogether. We therefore cannot do any name-to-slot - * optimizations, but must lookup names at runtime. Note that script_exec - * ensures that its caller's frame has a Call object, so arg and var name - * lookups will succeed. - */ - if (cx->fp->flags & JSFRAME_SCRIPT_OBJECT) - return JS_TRUE; - - /* - * We can't optimize if var and closure (a local function not in a larger - * expression and not at top-level within another's body) collide. - * XXX suboptimal: keep track of colliding names and deoptimize only those - */ - if (tc->flags & TCF_FUN_CLOSURE_VS_VAR) - return JS_TRUE; - - /* - * We can't optimize if we're not compiling a function body, whether via - * eval, or directly when compiling a function statement or expression. - */ - fp = cx->fp; - obj = fp->varobj; - clasp = OBJ_GET_CLASS(cx, obj); - if (clasp != &js_FunctionClass && clasp != &js_CallClass) { - /* - * Optimize global variable accesses if there are at least 100 uses - * in unambiguous contexts, or failing that, if least half of all the - * uses of global vars/consts/functions are in loops. - */ - optimizeGlobals = (tc->globalUses >= 100 || - (tc->loopyGlobalUses && - tc->loopyGlobalUses >= tc->globalUses / 2)); - if (!optimizeGlobals) - return JS_TRUE; - } else { - optimizeGlobals = JS_FALSE; - } - - /* - * We can't optimize if we're in an eval called inside a with statement, - * or we're compiling a with statement and its body, or we're in a catch - * block whose exception variable has the same name as pn. - */ - atom = pn->pn_atom; - if (fp->scopeChain != obj || - js_InWithStatement(tc) || - js_InCatchBlock(tc, atom)) { - return JS_TRUE; - } - - op = pn->pn_op; - getter = NULL; -#ifdef __GNUC__ - attrs = slot = 0; /* quell GCC overwarning */ -#endif - if (optimizeGlobals) { - /* - * We are optimizing global variables, and there is no pre-existing - * global property named atom. If atom was declared via const or var, - * optimize pn to access fp->vars using the appropriate JOF_QVAR op. - */ - ATOM_LIST_SEARCH(ale, &tc->decls, atom); - if (!ale) { - /* Use precedes declaration, or name is never declared. */ - return JS_TRUE; - } - - attrs = (ALE_JSOP(ale) == JSOP_DEFCONST) - ? JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT - : JSPROP_ENUMERATE | JSPROP_PERMANENT; - - /* Index atom so we can map fast global number to name. */ - JS_ASSERT(tc->flags & TCF_COMPILING); - ale = js_IndexAtom(cx, atom, &((JSCodeGenerator *) tc)->atomList); - if (!ale) - return JS_FALSE; - - /* Defend against tc->numGlobalVars 16-bit overflow. */ - slot = ALE_INDEX(ale); - if ((slot + 1) >> 16) - return JS_TRUE; - - if ((uint16)(slot + 1) > tc->numGlobalVars) - tc->numGlobalVars = (uint16)(slot + 1); - } else { - /* - * We may be able to optimize name to stack slot. Look for an argument - * or variable property in the function, or its call object, not found - * in any prototype object. Rewrite pn_op and update pn accordingly. - * NB: We know that JSOP_DELNAME on an argument or variable evaluates - * to false, due to JSPROP_PERMANENT. - */ - if (!js_LookupHiddenProperty(cx, obj, ATOM_TO_JSID(atom), &pobj, &prop)) - return JS_FALSE; - sprop = (JSScopeProperty *) prop; - if (sprop) { - if (pobj == obj) { - getter = sprop->getter; - attrs = sprop->attrs; - slot = (sprop->flags & SPROP_HAS_SHORTID) ? sprop->shortid : -1; - } - OBJ_DROP_PROPERTY(cx, pobj, prop); - } - } - - if (optimizeGlobals || getter) { - if (optimizeGlobals) { - switch (op) { - case JSOP_NAME: op = JSOP_GETGVAR; break; - case JSOP_SETNAME: op = JSOP_SETGVAR; break; - case JSOP_SETCONST: /* NB: no change */ break; - case JSOP_INCNAME: op = JSOP_INCGVAR; break; - case JSOP_NAMEINC: op = JSOP_GVARINC; break; - case JSOP_DECNAME: op = JSOP_DECGVAR; break; - case JSOP_NAMEDEC: op = JSOP_GVARDEC; break; - case JSOP_FORNAME: /* NB: no change */ break; - case JSOP_DELNAME: /* NB: no change */ break; - default: JS_ASSERT(0); - } - } else if (getter == js_GetLocalVariable || - getter == js_GetCallVariable) { - switch (op) { - case JSOP_NAME: op = JSOP_GETVAR; break; - case JSOP_SETNAME: op = JSOP_SETVAR; break; - case JSOP_SETCONST: op = JSOP_SETVAR; break; - case JSOP_INCNAME: op = JSOP_INCVAR; break; - case JSOP_NAMEINC: op = JSOP_VARINC; break; - case JSOP_DECNAME: op = JSOP_DECVAR; break; - case JSOP_NAMEDEC: op = JSOP_VARDEC; break; - case JSOP_FORNAME: op = JSOP_FORVAR; break; - case JSOP_DELNAME: op = JSOP_FALSE; break; - default: JS_ASSERT(0); - } - } else if (getter == js_GetArgument || - (getter == js_CallClass.getProperty && - fp->fun && (uintN) slot < fp->fun->nargs)) { - switch (op) { - case JSOP_NAME: op = JSOP_GETARG; break; - case JSOP_SETNAME: op = JSOP_SETARG; break; - case JSOP_INCNAME: op = JSOP_INCARG; break; - case JSOP_NAMEINC: op = JSOP_ARGINC; break; - case JSOP_DECNAME: op = JSOP_DECARG; break; - case JSOP_NAMEDEC: op = JSOP_ARGDEC; break; - case JSOP_FORNAME: op = JSOP_FORARG; break; - case JSOP_DELNAME: op = JSOP_FALSE; break; - default: JS_ASSERT(0); - } - } - if (op != pn->pn_op) { - pn->pn_op = op; - pn->pn_slot = slot; - } - pn->pn_attrs = attrs; - } - - if (pn->pn_slot < 0) { - /* - * We couldn't optimize pn, so it's not a global or local slot name. - * Now we must check for the predefined arguments variable. It may be - * overridden by assignment, in which case the function is heavyweight - * and the interpreter will look up 'arguments' in the function's call - * object. - */ - if (pn->pn_op == JSOP_NAME && - atom == cx->runtime->atomState.argumentsAtom) { - pn->pn_op = JSOP_ARGUMENTS; - return JS_TRUE; - } - - tc->flags |= TCF_FUN_USES_NONLOCALS; - } - return JS_TRUE; -} - -/* - * If pn contains a useful expression, return true with *answer set to true. - * If pn contains a useless expression, return true with *answer set to false. - * Return false on error. - * - * The caller should initialize *answer to false and invoke this function on - * an expression statement or similar subtree to decide whether the tree could - * produce code that has any side effects. For an expression statement, we - * define useless code as code with no side effects, because the main effect, - * the value left on the stack after the code executes, will be discarded by a - * pop bytecode. - */ -static JSBool -CheckSideEffects(JSContext *cx, JSTreeContext *tc, JSParseNode *pn, - JSBool *answer) -{ - JSBool ok; - JSFunction *fun; - JSParseNode *pn2; - - ok = JS_TRUE; - if (!pn || *answer) - return ok; - - switch (pn->pn_arity) { - case PN_FUNC: - /* - * A named function is presumed useful: we can't yet know that it is - * not called. The side effects are the creation of a scope object - * to parent this function object, and the binding of the function's - * name in that scope object. See comments at case JSOP_NAMEDFUNOBJ: - * in jsinterp.c. - */ - fun = (JSFunction *) JS_GetPrivate(cx, ATOM_TO_OBJECT(pn->pn_funAtom)); - if (fun->atom) - *answer = JS_TRUE; - break; - - case PN_LIST: - if (pn->pn_type == TOK_NEW || - pn->pn_type == TOK_LP || - pn->pn_type == TOK_LB) { - /* - * All invocation operations (construct: TOK_NEW, call: TOK_LP) - * are presumed to be useful, because they may have side effects - * even if their main effect (their return value) is discarded. - * - * TOK_LB binary trees of 3 or more nodes are flattened into lists - * to avoid too much recursion. All such lists must be presumed - * to be useful because each index operation could invoke a getter - * (the JSOP_ARGUMENTS special case below, in the PN_BINARY case, - * does not apply here: arguments[i][j] might invoke a getter). - */ - *answer = JS_TRUE; - } else { - for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) - ok &= CheckSideEffects(cx, tc, pn2, answer); - } - break; - - case PN_TERNARY: - ok = CheckSideEffects(cx, tc, pn->pn_kid1, answer) && - CheckSideEffects(cx, tc, pn->pn_kid2, answer) && - CheckSideEffects(cx, tc, pn->pn_kid3, answer); - break; - - case PN_BINARY: - if (pn->pn_type == TOK_ASSIGN) { - /* - * Assignment is presumed to be useful, even if the next operation - * is another assignment overwriting this one's ostensible effect, - * because the left operand may be a property with a setter that - * has side effects. - */ - *answer = JS_TRUE; - } else { - if (pn->pn_type == TOK_LB) { - pn2 = pn->pn_left; - if (pn2->pn_type == TOK_NAME && !LookupArgOrVar(cx, tc, pn2)) - return JS_FALSE; - if (pn2->pn_op != JSOP_ARGUMENTS) { - /* - * Any indexed property reference could call a getter with - * side effects, except for arguments[i] where arguments is - * unambiguous. - */ - *answer = JS_TRUE; - } - } - ok = CheckSideEffects(cx, tc, pn->pn_left, answer) && - CheckSideEffects(cx, tc, pn->pn_right, answer); - } - break; - - case PN_UNARY: - if (pn->pn_type == TOK_INC || pn->pn_type == TOK_DEC || - pn->pn_type == TOK_DELETE || - pn->pn_type == TOK_THROW || - pn->pn_type == TOK_DEFSHARP) { - /* All these operations have effects that we must commit. */ - *answer = JS_TRUE; - } else { - ok = CheckSideEffects(cx, tc, pn->pn_kid, answer); - } - break; - - case PN_NAME: - if (pn->pn_type == TOK_NAME) { - if (!LookupArgOrVar(cx, tc, pn)) - return JS_FALSE; - if (pn->pn_slot < 0 && pn->pn_op != JSOP_ARGUMENTS) { - /* - * Not an argument or local variable use, so this expression - * could invoke a getter that has side effects. - */ - *answer = JS_TRUE; - } - } - pn2 = pn->pn_expr; - if (pn->pn_type == TOK_DOT && pn2->pn_type == TOK_NAME) { - if (!LookupArgOrVar(cx, tc, pn2)) - return JS_FALSE; - if (!(pn2->pn_op == JSOP_ARGUMENTS && - pn->pn_atom == cx->runtime->atomState.lengthAtom)) { - /* - * Any dotted property reference could call a getter, except - * for arguments.length where arguments is unambiguous. - */ - *answer = JS_TRUE; - } - } - ok = CheckSideEffects(cx, tc, pn2, answer); - break; - - case PN_NULLARY: - if (pn->pn_type == TOK_DEBUGGER) - *answer = JS_TRUE; - break; - } - return ok; -} - -/* - * Secret handshake with js_EmitTree's TOK_LP/TOK_NEW case logic, to flag all - * uses of JSOP_GETMETHOD that implicitly qualify the method-property name with - * a function:: prefix. All other JSOP_GETMETHOD and JSOP_SETMETHOD uses must - * be explicit, so need a distinct source note (SRC_PCDELTA rather than PCBASE) - * for round-tripping through the beloved decompiler. - */ -#define JSPROP_IMPLICIT_FUNCTION_NAMESPACE 0x100 - -static jssrcnote -SrcNoteForPropOp(JSParseNode *pn, JSOp op) -{ - return ((op == JSOP_GETMETHOD && - !(pn->pn_attrs & JSPROP_IMPLICIT_FUNCTION_NAMESPACE)) || - op == JSOP_SETMETHOD) - ? SRC_PCDELTA - : SRC_PCBASE; -} - -static JSBool -EmitPropOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg) -{ - JSParseNode *pn2, *pndot, *pnup, *pndown; - ptrdiff_t top; - - pn2 = pn->pn_expr; - if (op == JSOP_GETPROP && - pn->pn_type == TOK_DOT && - pn2->pn_type == TOK_NAME) { - /* Try to optimize arguments.length into JSOP_ARGCNT. */ - if (!LookupArgOrVar(cx, &cg->treeContext, pn2)) - return JS_FALSE; - if (pn2->pn_op == JSOP_ARGUMENTS && - pn->pn_atom == cx->runtime->atomState.lengthAtom) { - return js_Emit1(cx, cg, JSOP_ARGCNT) >= 0; - } - } - - /* - * If the object operand is also a dotted property reference, reverse the - * list linked via pn_expr temporarily so we can iterate over it from the - * bottom up (reversing again as we go), to avoid excessive recursion. - */ - if (pn2->pn_type == TOK_DOT) { - pndot = pn2; - pnup = NULL; - top = CG_OFFSET(cg); - for (;;) { - /* Reverse pndot->pn_expr to point up, not down. */ - pndot->pn_offset = top; - pndown = pndot->pn_expr; - pndot->pn_expr = pnup; - if (pndown->pn_type != TOK_DOT) - break; - pnup = pndot; - pndot = pndown; - } - - /* pndown is a primary expression, not a dotted property reference. */ - if (!js_EmitTree(cx, cg, pndown)) - return JS_FALSE; - - do { - /* Walk back up the list, emitting annotated name ops. */ - if (js_NewSrcNote2(cx, cg, SrcNoteForPropOp(pndot, pndot->pn_op), - CG_OFFSET(cg) - pndown->pn_offset) < 0) { - return JS_FALSE; - } - if (!EmitAtomOp(cx, pndot, pndot->pn_op, cg)) - return JS_FALSE; - - /* Reverse the pn_expr link again. */ - pnup = pndot->pn_expr; - pndot->pn_expr = pndown; - pndown = pndot; - } while ((pndot = pnup) != NULL); - } else { - if (!js_EmitTree(cx, cg, pn2)) - return JS_FALSE; - } - - if (js_NewSrcNote2(cx, cg, SrcNoteForPropOp(pn, op), - CG_OFFSET(cg) - pn2->pn_offset) < 0) { - return JS_FALSE; - } - if (!pn->pn_atom) { - JS_ASSERT(op == JSOP_IMPORTALL); - if (js_Emit1(cx, cg, op) < 0) - return JS_FALSE; - } else { - if (!EmitAtomOp(cx, pn, op, cg)) - return JS_FALSE; - } - return JS_TRUE; -} - -static JSBool -EmitElemOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg) -{ - ptrdiff_t top; - JSParseNode *left, *right, *next, temp; - jsint slot; - - top = CG_OFFSET(cg); - if (pn->pn_arity == PN_LIST) { - /* Left-associative operator chain to avoid too much recursion. */ - JS_ASSERT(pn->pn_op == JSOP_GETELEM); - JS_ASSERT(pn->pn_count >= 3); - left = pn->pn_head; - right = PN_LAST(pn); - next = left->pn_next; - JS_ASSERT(next != right); - - /* - * Try to optimize arguments[0][j]... into JSOP_ARGSUB<0> followed by - * one or more index expression and JSOP_GETELEM op pairs. - */ - if (left->pn_type == TOK_NAME && next->pn_type == TOK_NUMBER) { - if (!LookupArgOrVar(cx, &cg->treeContext, left)) - return JS_FALSE; - if (left->pn_op == JSOP_ARGUMENTS && - JSDOUBLE_IS_INT(next->pn_dval, slot) && - (jsuint)slot < JS_BIT(16)) { - left->pn_offset = next->pn_offset = top; - EMIT_UINT16_IMM_OP(JSOP_ARGSUB, (jsatomid)slot); - left = next; - next = left->pn_next; - } - } - - /* - * Check whether we generated JSOP_ARGSUB, just above, and have only - * one more index expression to emit. Given arguments[0][j], we must - * skip the while loop altogether, falling through to emit code for j - * (in the subtree referenced by right), followed by the annotated op, - * at the bottom of this function. - */ - JS_ASSERT(next != right || pn->pn_count == 3); - if (left == pn->pn_head) { - if (!js_EmitTree(cx, cg, left)) - return JS_FALSE; - } - while (next != right) { - if (!js_EmitTree(cx, cg, next)) - return JS_FALSE; - if (js_NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - top) < 0) - return JS_FALSE; - if (js_Emit1(cx, cg, JSOP_GETELEM) < 0) - return JS_FALSE; - next = next->pn_next; - } - } else { - if (pn->pn_arity == PN_NAME) { - /* - * Set left and right so pn appears to be a TOK_LB node, instead - * of a TOK_DOT node (see the TOK_FOR/IN case in js_EmitTree). - */ - left = pn->pn_expr; - right = &temp; - right->pn_type = TOK_STRING; - right->pn_arity = PN_NULLARY; - right->pn_op = JSOP_STRING; - right->pn_atom = pn->pn_atom; - } else { - JS_ASSERT(pn->pn_arity == PN_BINARY); - left = pn->pn_left; - right = pn->pn_right; - } - - /* Try to optimize arguments[0] (e.g.) into JSOP_ARGSUB<0>. */ - if (op == JSOP_GETELEM && - left->pn_type == TOK_NAME && - right->pn_type == TOK_NUMBER) { - if (!LookupArgOrVar(cx, &cg->treeContext, left)) - return JS_FALSE; - if (left->pn_op == JSOP_ARGUMENTS && - JSDOUBLE_IS_INT(right->pn_dval, slot) && - (jsuint)slot < JS_BIT(16)) { - left->pn_offset = right->pn_offset = top; - EMIT_UINT16_IMM_OP(JSOP_ARGSUB, (jsatomid)slot); - return JS_TRUE; - } - } - - if (!js_EmitTree(cx, cg, left)) - return JS_FALSE; - } - if (!js_EmitTree(cx, cg, right)) - return JS_FALSE; - if (js_NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - top) < 0) - return JS_FALSE; - return js_Emit1(cx, cg, op) >= 0; -} - -static JSBool -EmitNumberOp(JSContext *cx, jsdouble dval, JSCodeGenerator *cg) -{ - jsint ival; - jsatomid atomIndex; - ptrdiff_t off; - jsbytecode *pc; - JSAtom *atom; - JSAtomListElement *ale; - - if (JSDOUBLE_IS_INT(dval, ival) && INT_FITS_IN_JSVAL(ival)) { - if (ival == 0) - return js_Emit1(cx, cg, JSOP_ZERO) >= 0; - if (ival == 1) - return js_Emit1(cx, cg, JSOP_ONE) >= 0; - - atomIndex = (jsatomid)ival; - if (atomIndex < JS_BIT(16)) { - EMIT_UINT16_IMM_OP(JSOP_UINT16, atomIndex); - return JS_TRUE; - } - - if (atomIndex < JS_BIT(24)) { - off = js_EmitN(cx, cg, JSOP_UINT24, 3); - if (off < 0) - return JS_FALSE; - pc = CG_CODE(cg, off); - SET_LITERAL_INDEX(pc, atomIndex); - return JS_TRUE; - } - - atom = js_AtomizeInt(cx, ival, 0); - } else { - atom = js_AtomizeDouble(cx, dval, 0); - } - if (!atom) - return JS_FALSE; - - ale = js_IndexAtom(cx, atom, &cg->atomList); - if (!ale) - return JS_FALSE; - return EmitAtomIndexOp(cx, JSOP_NUMBER, ALE_INDEX(ale), cg); -} - -#if JS_HAS_SWITCH_STATEMENT -static JSBool -EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, - JSStmtInfo *stmtInfo) -{ - JSOp switchOp; - JSBool ok, hasDefault, constPropagated; - ptrdiff_t top, off, defaultOffset; - JSParseNode *pn2, *pn3, *pn4; - uint32 caseCount, tableLength; - JSParseNode **table; - jsdouble d; - jsint i, low, high; - jsval v; - JSAtom *atom; - JSAtomListElement *ale; - intN noteIndex; - size_t switchSize, tableSize; - jsbytecode *pc, *savepc; - - /* Try for most optimal, fall back if not dense ints, and per ECMAv2. */ - switchOp = JSOP_TABLESWITCH; - ok = JS_TRUE; - hasDefault = constPropagated = JS_FALSE; - defaultOffset = -1; - - /* Emit code for the discriminant first. */ - if (!js_EmitTree(cx, cg, pn->pn_kid1)) - return JS_FALSE; - - /* Switch bytecodes run from here till end of final case. */ - top = CG_OFFSET(cg); - js_PushStatement(&cg->treeContext, stmtInfo, STMT_SWITCH, top); - - pn2 = pn->pn_kid2; - caseCount = pn2->pn_count; - tableLength = 0; - table = NULL; - - if (caseCount == 0 || - (caseCount == 1 && - (hasDefault = (pn2->pn_head->pn_type == TOK_DEFAULT)))) { - caseCount = 0; - low = 0; - high = -1; - } else { -#define INTMAP_LENGTH 256 - jsbitmap intmap_space[INTMAP_LENGTH]; - jsbitmap *intmap = NULL; - int32 intmap_bitlen = 0; - - low = JSVAL_INT_MAX; - high = JSVAL_INT_MIN; - - for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) { - if (pn3->pn_type == TOK_DEFAULT) { - hasDefault = JS_TRUE; - caseCount--; /* one of the "cases" was the default */ - continue; - } - - JS_ASSERT(pn3->pn_type == TOK_CASE); - if (switchOp == JSOP_CONDSWITCH) - continue; - - pn4 = pn3->pn_left; - switch (pn4->pn_type) { - case TOK_NUMBER: - d = pn4->pn_dval; - if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i)) { - pn3->pn_val = INT_TO_JSVAL(i); - } else { - atom = js_AtomizeDouble(cx, d, 0); - if (!atom) { - ok = JS_FALSE; - goto release; - } - pn3->pn_val = ATOM_KEY(atom); - } - break; - case TOK_STRING: - pn3->pn_val = ATOM_KEY(pn4->pn_atom); - break; - case TOK_NAME: - if (!pn4->pn_expr) { - ok = js_LookupCompileTimeConstant(cx, cg, pn4->pn_atom, &v); - if (!ok) - goto release; - if (!JSVAL_IS_VOID(v)) { - pn3->pn_val = v; - constPropagated = JS_TRUE; - break; - } - } - /* FALL THROUGH */ - case TOK_PRIMARY: - if (pn4->pn_op == JSOP_TRUE) { - pn3->pn_val = JSVAL_TRUE; - break; - } - if (pn4->pn_op == JSOP_FALSE) { - pn3->pn_val = JSVAL_FALSE; - break; - } - /* FALL THROUGH */ - default: - switchOp = JSOP_CONDSWITCH; - continue; - } - - JS_ASSERT(JSVAL_IS_NUMBER(pn3->pn_val) || - JSVAL_IS_STRING(pn3->pn_val) || - JSVAL_IS_BOOLEAN(pn3->pn_val)); - - if (switchOp != JSOP_TABLESWITCH) - continue; - if (!JSVAL_IS_INT(pn3->pn_val)) { - switchOp = JSOP_LOOKUPSWITCH; - continue; - } - i = JSVAL_TO_INT(pn3->pn_val); - if ((jsuint)(i + (jsint)JS_BIT(15)) >= (jsuint)JS_BIT(16)) { - switchOp = JSOP_LOOKUPSWITCH; - continue; - } - if (i < low) - low = i; - if (high < i) - high = i; - - /* - * Check for duplicates, which require a JSOP_LOOKUPSWITCH. - * We bias i by 65536 if it's negative, and hope that's a rare - * case (because it requires a malloc'd bitmap). - */ - if (i < 0) - i += JS_BIT(16); - if (i >= intmap_bitlen) { - if (!intmap && - i < (INTMAP_LENGTH << JS_BITS_PER_WORD_LOG2)) { - intmap = intmap_space; - intmap_bitlen = INTMAP_LENGTH << JS_BITS_PER_WORD_LOG2; - } else { - /* Just grab 8K for the worst-case bitmap. */ - intmap_bitlen = JS_BIT(16); - intmap = (jsbitmap *) - JS_malloc(cx, - (JS_BIT(16) >> JS_BITS_PER_WORD_LOG2) - * sizeof(jsbitmap)); - if (!intmap) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - } - memset(intmap, 0, intmap_bitlen >> JS_BITS_PER_BYTE_LOG2); - } - if (JS_TEST_BIT(intmap, i)) { - switchOp = JSOP_LOOKUPSWITCH; - continue; - } - JS_SET_BIT(intmap, i); - } - - release: - if (intmap && intmap != intmap_space) - JS_free(cx, intmap); - if (!ok) - return JS_FALSE; - - /* - * Compute table length and select lookup instead if overlarge or - * more than half-sparse. - */ - if (switchOp == JSOP_TABLESWITCH) { - tableLength = (uint32)(high - low + 1); - if (tableLength >= JS_BIT(16) || tableLength > 2 * caseCount) - switchOp = JSOP_LOOKUPSWITCH; - } - } - - /* - * Emit a note with two offsets: first tells total switch code length, - * second tells offset to first JSOP_CASE if condswitch. - */ - noteIndex = js_NewSrcNote3(cx, cg, SRC_SWITCH, 0, 0); - if (noteIndex < 0) - return JS_FALSE; - - if (switchOp == JSOP_CONDSWITCH) { - /* - * 0 bytes of immediate for unoptimized ECMAv2 switch. - */ - switchSize = 0; - } else if (switchOp == JSOP_TABLESWITCH) { - /* - * 3 offsets (len, low, high) before the table, 1 per entry. - */ - switchSize = (size_t)(JUMP_OFFSET_LEN * (3 + tableLength)); - } else { - /* - * JSOP_LOOKUPSWITCH: - * 1 offset (len) and 1 atom index (npairs) before the table, - * 1 atom index and 1 jump offset per entry. - */ - switchSize = (size_t)(JUMP_OFFSET_LEN + ATOM_INDEX_LEN + - (ATOM_INDEX_LEN + JUMP_OFFSET_LEN) * caseCount); - } - - /* - * Emit switchOp followed by switchSize bytes of jump or lookup table. - * - * If switchOp is JSOP_LOOKUPSWITCH or JSOP_TABLESWITCH, it is crucial - * to emit the immediate operand(s) by which bytecode readers such as - * BuildSpanDepTable discover the length of the switch opcode *before* - * calling js_SetJumpOffset (which may call BuildSpanDepTable). It's - * also important to zero all unknown jump offset immediate operands, - * so they can be converted to span dependencies with null targets to - * be computed later (js_EmitN zeros switchSize bytes after switchOp). - */ - if (js_EmitN(cx, cg, switchOp, switchSize) < 0) - return JS_FALSE; - - off = -1; - if (switchOp == JSOP_CONDSWITCH) { - intN caseNoteIndex = -1; - JSBool beforeCases = JS_TRUE; - - /* Emit code for evaluating cases and jumping to case statements. */ - for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) { - pn4 = pn3->pn_left; - if (pn4 && !js_EmitTree(cx, cg, pn4)) - return JS_FALSE; - if (caseNoteIndex >= 0) { - /* off is the previous JSOP_CASE's bytecode offset. */ - if (!js_SetSrcNoteOffset(cx, cg, (uintN)caseNoteIndex, 0, - CG_OFFSET(cg) - off)) { - return JS_FALSE; - } - } - if (!pn4) { - JS_ASSERT(pn3->pn_type == TOK_DEFAULT); - continue; - } - caseNoteIndex = js_NewSrcNote2(cx, cg, SRC_PCDELTA, 0); - if (caseNoteIndex < 0) - return JS_FALSE; - off = EmitJump(cx, cg, JSOP_CASE, 0); - if (off < 0) - return JS_FALSE; - pn3->pn_offset = off; - if (beforeCases) { - /* Switch note's second offset is to first JSOP_CASE. */ - if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 1, - off - top)) { - return JS_FALSE; - } - beforeCases = JS_FALSE; - } - } - - /* Emit default even if no explicit default statement. */ - defaultOffset = EmitJump(cx, cg, JSOP_DEFAULT, 0); - if (defaultOffset < 0) - return JS_FALSE; - } else { - pc = CG_CODE(cg, top + JUMP_OFFSET_LEN); - - if (switchOp == JSOP_TABLESWITCH) { - /* Fill in switch bounds, which we know fit in 16-bit offsets. */ - SET_JUMP_OFFSET(pc, low); - pc += JUMP_OFFSET_LEN; - SET_JUMP_OFFSET(pc, high); - pc += JUMP_OFFSET_LEN; - - /* - * Use malloc to avoid arena bloat for programs with many switches. - * We free table if non-null at label out, so all control flow must - * exit this function through goto out or goto bad. - */ - if (tableLength != 0) { - tableSize = (size_t)tableLength * sizeof *table; - table = (JSParseNode **) JS_malloc(cx, tableSize); - if (!table) - return JS_FALSE; - memset(table, 0, tableSize); - for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) { - if (pn3->pn_type == TOK_DEFAULT) - continue; - i = JSVAL_TO_INT(pn3->pn_val); - i -= low; - JS_ASSERT((uint32)i < tableLength); - table[i] = pn3; - } - } - } else { - JS_ASSERT(switchOp == JSOP_LOOKUPSWITCH); - - /* Fill in the number of cases. */ - SET_ATOM_INDEX(pc, caseCount); - pc += ATOM_INDEX_LEN; - } - - /* - * After this point, all control flow involving JSOP_TABLESWITCH - * must set ok and goto out to exit this function. To keep things - * simple, all switchOp cases exit that way. - */ - if (constPropagated) { - /* - * Skip switchOp, as we are not setting jump offsets in the two - * for loops below. We'll restore CG_NEXT(cg) from savepc after, - * unless there was an error. - */ - savepc = CG_NEXT(cg); - CG_NEXT(cg) = pc + 1; - if (switchOp == JSOP_TABLESWITCH) { - for (i = 0; i < (jsint)tableLength; i++) { - pn3 = table[i]; - if (pn3 && - (pn4 = pn3->pn_left) != NULL && - pn4->pn_type == TOK_NAME) { - /* Note a propagated constant with the const's name. */ - JS_ASSERT(!pn4->pn_expr); - ale = js_IndexAtom(cx, pn4->pn_atom, &cg->atomList); - if (!ale) - goto bad; - CG_NEXT(cg) = pc; - if (js_NewSrcNote2(cx, cg, SRC_LABEL, (ptrdiff_t) - ALE_INDEX(ale)) < 0) { - goto bad; - } - } - pc += JUMP_OFFSET_LEN; - } - } else { - for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) { - pn4 = pn3->pn_left; - if (pn4 && pn4->pn_type == TOK_NAME) { - /* Note a propagated constant with the const's name. */ - JS_ASSERT(!pn4->pn_expr); - ale = js_IndexAtom(cx, pn4->pn_atom, &cg->atomList); - if (!ale) - goto bad; - CG_NEXT(cg) = pc; - if (js_NewSrcNote2(cx, cg, SRC_LABEL, (ptrdiff_t) - ALE_INDEX(ale)) < 0) { - goto bad; - } - } - pc += ATOM_INDEX_LEN + JUMP_OFFSET_LEN; - } - } - CG_NEXT(cg) = savepc; - } - } - - /* Emit code for each case's statements, copying pn_offset up to pn3. */ - for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) { - if (switchOp == JSOP_CONDSWITCH && pn3->pn_type != TOK_DEFAULT) - CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, pn3->pn_offset); - pn4 = pn3->pn_right; - ok = js_EmitTree(cx, cg, pn4); - if (!ok) - goto out; - pn3->pn_offset = pn4->pn_offset; - if (pn3->pn_type == TOK_DEFAULT) - off = pn3->pn_offset - top; - } - - if (!hasDefault) { - /* If no default case, offset for default is to end of switch. */ - off = CG_OFFSET(cg) - top; - } - - /* We better have set "off" by now. */ - JS_ASSERT(off != -1); - - /* Set the default offset (to end of switch if no default). */ - if (switchOp == JSOP_CONDSWITCH) { - pc = NULL; - JS_ASSERT(defaultOffset != -1); - ok = js_SetJumpOffset(cx, cg, CG_CODE(cg, defaultOffset), - off - (defaultOffset - top)); - if (!ok) - goto out; - } else { - pc = CG_CODE(cg, top); - ok = js_SetJumpOffset(cx, cg, pc, off); - if (!ok) - goto out; - pc += JUMP_OFFSET_LEN; - } - - /* Set the SRC_SWITCH note's offset operand to tell end of switch. */ - off = CG_OFFSET(cg) - top; - ok = js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, off); - if (!ok) - goto out; - - if (switchOp == JSOP_TABLESWITCH) { - /* Skip over the already-initialized switch bounds. */ - pc += 2 * JUMP_OFFSET_LEN; - - /* Fill in the jump table, if there is one. */ - for (i = 0; i < (jsint)tableLength; i++) { - pn3 = table[i]; - off = pn3 ? pn3->pn_offset - top : 0; - ok = js_SetJumpOffset(cx, cg, pc, off); - if (!ok) - goto out; - pc += JUMP_OFFSET_LEN; - } - } else if (switchOp == JSOP_LOOKUPSWITCH) { - /* Skip over the already-initialized number of cases. */ - pc += ATOM_INDEX_LEN; - - for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) { - if (pn3->pn_type == TOK_DEFAULT) - continue; - atom = js_AtomizeValue(cx, pn3->pn_val, 0); - if (!atom) - goto bad; - ale = js_IndexAtom(cx, atom, &cg->atomList); - if (!ale) - goto bad; - SET_ATOM_INDEX(pc, ALE_INDEX(ale)); - pc += ATOM_INDEX_LEN; - - off = pn3->pn_offset - top; - ok = js_SetJumpOffset(cx, cg, pc, off); - if (!ok) - goto out; - pc += JUMP_OFFSET_LEN; - } - } - -out: - if (table) - JS_free(cx, table); - return ok && js_PopStatementCG(cx, cg); - -bad: - ok = JS_FALSE; - goto out; -} -#endif /* JS_HAS_SWITCH_STATEMENT */ - -JSBool -js_EmitFunctionBody(JSContext *cx, JSCodeGenerator *cg, JSParseNode *body, - JSFunction *fun) -{ - JSStackFrame *fp, frame; - JSObject *funobj; - JSBool ok; - - if (!js_AllocTryNotes(cx, cg)) - return JS_FALSE; - - fp = cx->fp; - funobj = fun->object; - JS_ASSERT(!fp || (fp->fun != fun && fp->varobj != funobj && - fp->scopeChain != funobj)); - memset(&frame, 0, sizeof frame); - frame.fun = fun; - frame.varobj = frame.scopeChain = funobj; - frame.down = fp; - frame.flags = JS_HAS_COMPILE_N_GO_OPTION(cx) - ? JSFRAME_COMPILING | JSFRAME_COMPILE_N_GO - : JSFRAME_COMPILING; - cx->fp = &frame; - ok = js_EmitTree(cx, cg, body); - cx->fp = fp; - if (!ok) - return JS_FALSE; - - fun->u.script = js_NewScriptFromCG(cx, cg, fun); - if (!fun->u.script) - return JS_FALSE; - JS_ASSERT(fun->interpreted); - if (cg->treeContext.flags & TCF_FUN_HEAVYWEIGHT) - fun->flags |= JSFUN_HEAVYWEIGHT; - return JS_TRUE; -} - -/* A macro for inlining at the top of js_EmitTree (whence it came). */ -#define UPDATE_LINE_NUMBER_NOTES(cx, cg, pn) \ - JS_BEGIN_MACRO \ - uintN line_ = (pn)->pn_pos.begin.lineno; \ - uintN delta_ = line_ - CG_CURRENT_LINE(cg); \ - if (delta_ != 0) { \ - /* \ - * Encode any change in the current source line number by using \ - * either several SRC_NEWLINE notes or just one SRC_SETLINE note, \ - * whichever consumes less space. \ - * \ - * NB: We handle backward line number deltas (possible with for \ - * loops where the update part is emitted after the body, but its \ - * line number is <= any line number in the body) here by letting \ - * unsigned delta_ wrap to a very large number, which triggers a \ - * SRC_SETLINE. \ - */ \ - CG_CURRENT_LINE(cg) = line_; \ - if (delta_ >= (uintN)(2 + ((line_ > SN_3BYTE_OFFSET_MASK)<<1))) { \ - if (js_NewSrcNote2(cx, cg, SRC_SETLINE, (ptrdiff_t)line_) < 0)\ - return JS_FALSE; \ - } else { \ - do { \ - if (js_NewSrcNote(cx, cg, SRC_NEWLINE) < 0) \ - return JS_FALSE; \ - } while (--delta_ != 0); \ - } \ - } \ - JS_END_MACRO - -/* A function, so that we avoid macro-bloating all the other callsites. */ -static JSBool -UpdateLineNumberNotes(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) -{ - UPDATE_LINE_NUMBER_NOTES(cx, cg, pn); - return JS_TRUE; -} - -JSBool -js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) -{ - JSBool ok, useful, wantval; - JSStmtInfo *stmt, stmtInfo; - ptrdiff_t top, off, tmp, beq, jmp; - JSParseNode *pn2, *pn3; - JSAtom *atom; - JSAtomListElement *ale; - jsatomid atomIndex; - ptrdiff_t noteIndex; - JSSrcNoteType noteType; - jsbytecode *pc; - JSOp op; - uint32 argc; - int stackDummy; - - if (!JS_CHECK_STACK_SIZE(cx, stackDummy)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_OVER_RECURSED); - return JS_FALSE; - } - - ok = JS_TRUE; - cg->emitLevel++; - pn->pn_offset = top = CG_OFFSET(cg); - - /* Emit notes to tell the current bytecode's source line number. */ - UPDATE_LINE_NUMBER_NOTES(cx, cg, pn); - - switch (pn->pn_type) { - case TOK_FUNCTION: - { - void *cg2mark; - JSCodeGenerator *cg2; - JSFunction *fun; - -#if JS_HAS_XML_SUPPORT - if (pn->pn_arity == PN_NULLARY) { - if (js_Emit1(cx, cg, JSOP_GETFUNNS) < 0) - return JS_FALSE; - break; - } -#endif - - /* Generate code for the function's body. */ - cg2mark = JS_ARENA_MARK(&cx->tempPool); - JS_ARENA_ALLOCATE_TYPE(cg2, JSCodeGenerator, &cx->tempPool); - if (!cg2) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - if (!js_InitCodeGenerator(cx, cg2, cg->codePool, cg->notePool, - cg->filename, pn->pn_pos.begin.lineno, - cg->principals)) { - return JS_FALSE; - } - cg2->treeContext.flags = (uint16) (pn->pn_flags | TCF_IN_FUNCTION); - cg2->treeContext.tryCount = pn->pn_tryCount; - cg2->parent = cg; - fun = (JSFunction *) JS_GetPrivate(cx, ATOM_TO_OBJECT(pn->pn_funAtom)); - if (!js_EmitFunctionBody(cx, cg2, pn->pn_body, fun)) - return JS_FALSE; - - /* - * We need an activation object if an inner peeks out, or if such - * inner-peeking caused one of our inners to become heavyweight. - */ - if (cg2->treeContext.flags & - (TCF_FUN_USES_NONLOCALS | TCF_FUN_HEAVYWEIGHT)) { - cg->treeContext.flags |= TCF_FUN_HEAVYWEIGHT; - } - js_FinishCodeGenerator(cx, cg2); - JS_ARENA_RELEASE(&cx->tempPool, cg2mark); - - /* Make the function object a literal in the outer script's pool. */ - ale = js_IndexAtom(cx, pn->pn_funAtom, &cg->atomList); - if (!ale) - return JS_FALSE; - atomIndex = ALE_INDEX(ale); - -#if JS_HAS_LEXICAL_CLOSURE - /* Emit a bytecode pointing to the closure object in its immediate. */ - if (pn->pn_op != JSOP_NOP) { - EMIT_ATOM_INDEX_OP(pn->pn_op, atomIndex); - break; - } -#endif - - /* Top-level named functions need a nop for decompilation. */ - noteIndex = js_NewSrcNote2(cx, cg, SRC_FUNCDEF, (ptrdiff_t)atomIndex); - if (noteIndex < 0 || - js_Emit1(cx, cg, JSOP_NOP) < 0) { - return JS_FALSE; - } - - /* - * Top-levels also need a prolog op to predefine their names in the - * variable object, or if local, to fill their stack slots. - */ - CG_SWITCH_TO_PROLOG(cg); - -#if JS_HAS_LEXICAL_CLOSURE - if (cg->treeContext.flags & TCF_IN_FUNCTION) { - JSObject *obj, *pobj; - JSProperty *prop; - JSScopeProperty *sprop; - uintN slot; - - obj = OBJ_GET_PARENT(cx, fun->object); - if (!js_LookupHiddenProperty(cx, obj, ATOM_TO_JSID(fun->atom), - &pobj, &prop)) { - return JS_FALSE; - } - - JS_ASSERT(prop && pobj == obj); - sprop = (JSScopeProperty *) prop; - JS_ASSERT(sprop->getter == js_GetLocalVariable); - slot = sprop->shortid; - OBJ_DROP_PROPERTY(cx, pobj, prop); - - if (atomIndex >= JS_BIT(16)) { - /* - * Lots of literals in the outer function, so we have to emit - * [JSOP_LITOPX, atomIndex, JSOP_DEFLOCALFUN, var slot]. - */ - off = js_EmitN(cx, cg, JSOP_LITOPX, 3); - if (off < 0) - return JS_FALSE; - pc = CG_CODE(cg, off); - SET_LITERAL_INDEX(pc, atomIndex); - EMIT_UINT16_IMM_OP(JSOP_DEFLOCALFUN, slot); - } else { - /* Emit [JSOP_DEFLOCALFUN, var slot, atomIndex]. */ - off = js_EmitN(cx, cg, JSOP_DEFLOCALFUN, - VARNO_LEN + ATOM_INDEX_LEN); - if (off < 0) - return JS_FALSE; - pc = CG_CODE(cg, off); - SET_VARNO(pc, slot); - pc += VARNO_LEN; - SET_ATOM_INDEX(pc, atomIndex); - } - } else -#endif - EMIT_ATOM_INDEX_OP(JSOP_DEFFUN, atomIndex); - - CG_SWITCH_TO_MAIN(cg); - break; - } - -#if JS_HAS_EXPORT_IMPORT - case TOK_EXPORT: - pn2 = pn->pn_head; - if (pn2->pn_type == TOK_STAR) { - /* - * 'export *' must have no other elements in the list (what would - * be the point?). - */ - if (js_Emit1(cx, cg, JSOP_EXPORTALL) < 0) - return JS_FALSE; - } else { - /* - * If not 'export *', the list consists of NAME nodes identifying - * properties of the variables object to flag as exported. - */ - do { - ale = js_IndexAtom(cx, pn2->pn_atom, &cg->atomList); - if (!ale) - return JS_FALSE; - EMIT_ATOM_INDEX_OP(JSOP_EXPORTNAME, ALE_INDEX(ale)); - } while ((pn2 = pn2->pn_next) != NULL); - } - break; - - case TOK_IMPORT: - for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) { - /* - * Each subtree on an import list is rooted by a DOT or LB node. - * A DOT may have a null pn_atom member, in which case pn_op must - * be JSOP_IMPORTALL -- see EmitPropOp above. - */ - if (!js_EmitTree(cx, cg, pn2)) - return JS_FALSE; - } - break; -#endif /* JS_HAS_EXPORT_IMPORT */ - - case TOK_IF: - /* Initialize so we can detect else-if chains and avoid recursion. */ - stmtInfo.type = STMT_IF; - beq = jmp = -1; - noteIndex = -1; - - if_again: - /* Emit code for the condition before pushing stmtInfo. */ - if (!js_EmitTree(cx, cg, pn->pn_kid1)) - return JS_FALSE; - if (stmtInfo.type == STMT_IF) { - js_PushStatement(&cg->treeContext, &stmtInfo, STMT_IF, - CG_OFFSET(cg)); - } else { - /* - * We came here from the goto further below that detects else-if - * chains, so we must mutate stmtInfo back into a STMT_IF record. - * Also (see below for why) we need a note offset for SRC_IF_ELSE - * to help the decompiler. - */ - JS_ASSERT(stmtInfo.type == STMT_ELSE); - stmtInfo.type = STMT_IF; - if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, jmp - beq)) - return JS_FALSE; - } - - /* Emit an annotated branch-if-false around the then part. */ - pn3 = pn->pn_kid3; - noteIndex = js_NewSrcNote(cx, cg, pn3 ? SRC_IF_ELSE : SRC_IF); - if (noteIndex < 0) - return JS_FALSE; - beq = EmitJump(cx, cg, JSOP_IFEQ, 0); - if (beq < 0) - return JS_FALSE; - - /* Emit code for the then and optional else parts. */ - if (!js_EmitTree(cx, cg, pn->pn_kid2)) - return JS_FALSE; - if (pn3) { - /* Modify stmtInfo so we know we're in the else part. */ - stmtInfo.type = STMT_ELSE; - - /* - * Emit a JSOP_BACKPATCH op to jump from the end of our then part - * around the else part. The js_PopStatementCG call at the bottom - * of this switch case will fix up the backpatch chain linked from - * stmtInfo.breaks. - */ - jmp = EmitGoto(cx, cg, &stmtInfo, &stmtInfo.breaks, NULL, SRC_NULL); - if (jmp < 0) - return JS_FALSE; - - /* Ensure the branch-if-false comes here, then emit the else. */ - CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, beq); - if (pn3->pn_type == TOK_IF) { - pn = pn3; - goto if_again; - } - - if (!js_EmitTree(cx, cg, pn3)) - return JS_FALSE; - - /* - * Annotate SRC_IF_ELSE with the offset from branch to jump, for - * the decompiler's benefit. We can't just "back up" from the pc - * of the else clause, because we don't know whether an extended - * jump was required to leap from the end of the then clause over - * the else clause. - */ - if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, jmp - beq)) - return JS_FALSE; - } else { - /* No else part, fixup the branch-if-false to come here. */ - CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, beq); - } - ok = js_PopStatementCG(cx, cg); - break; - -#if JS_HAS_SWITCH_STATEMENT - case TOK_SWITCH: - /* Out of line to avoid bloating js_EmitTree's stack frame size. */ - ok = EmitSwitch(cx, cg, pn, &stmtInfo); - break; -#endif /* JS_HAS_SWITCH_STATEMENT */ - - case TOK_WHILE: - js_PushStatement(&cg->treeContext, &stmtInfo, STMT_WHILE_LOOP, top); - if (!js_EmitTree(cx, cg, pn->pn_left)) - return JS_FALSE; - noteIndex = js_NewSrcNote(cx, cg, SRC_WHILE); - if (noteIndex < 0) - return JS_FALSE; - beq = EmitJump(cx, cg, JSOP_IFEQ, 0); - if (beq < 0) - return JS_FALSE; - if (!js_EmitTree(cx, cg, pn->pn_right)) - return JS_FALSE; - jmp = EmitJump(cx, cg, JSOP_GOTO, top - CG_OFFSET(cg)); - if (jmp < 0) - return JS_FALSE; - CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, beq); - if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, jmp - beq)) - return JS_FALSE; - ok = js_PopStatementCG(cx, cg); - break; - -#if JS_HAS_DO_WHILE_LOOP - case TOK_DO: - /* Emit an annotated nop so we know to decompile a 'do' keyword. */ - if (js_NewSrcNote(cx, cg, SRC_WHILE) < 0 || - js_Emit1(cx, cg, JSOP_NOP) < 0) { - return JS_FALSE; - } - - /* Compile the loop body. */ - top = CG_OFFSET(cg); - js_PushStatement(&cg->treeContext, &stmtInfo, STMT_DO_LOOP, top); - if (!js_EmitTree(cx, cg, pn->pn_left)) - return JS_FALSE; - - /* Set loop and enclosing label update offsets, for continue. */ - stmt = &stmtInfo; - do { - stmt->update = CG_OFFSET(cg); - } while ((stmt = stmt->down) != NULL && stmt->type == STMT_LABEL); - - /* Compile the loop condition, now that continues know where to go. */ - if (!js_EmitTree(cx, cg, pn->pn_right)) - return JS_FALSE; - - /* - * No source note needed, because JSOP_IFNE is used only for do-while. - * If we ever use JSOP_IFNE for other purposes, we can still avoid yet - * another note here, by storing (jmp - top) in the SRC_WHILE note's - * offset, and fetching that delta in order to decompile recursively. - */ - if (EmitJump(cx, cg, JSOP_IFNE, top - CG_OFFSET(cg)) < 0) - return JS_FALSE; - ok = js_PopStatementCG(cx, cg); - break; -#endif /* JS_HAS_DO_WHILE_LOOP */ - - case TOK_FOR: - beq = 0; /* suppress gcc warnings */ - pn2 = pn->pn_left; - js_PushStatement(&cg->treeContext, &stmtInfo, STMT_FOR_LOOP, top); - - if (pn2->pn_type == TOK_IN) { - JSBool emitIFEQ; - - /* Set stmtInfo type for later testing. */ - stmtInfo.type = STMT_FOR_IN_LOOP; - noteIndex = -1; - - /* - * If the left part is 'var x', emit code to define x if necessary - * using a prolog opcode, but do not emit a pop. If the left part - * is 'var x = i', emit prolog code to define x if necessary; then - * emit code to evaluate i, assign the result to x, and pop the - * result off the stack. - * - * All the logic to do this is implemented in the outer switch's - * TOK_VAR case, conditioned on pn_extra flags set by the parser. - * - * In the 'for (var x = i in o) ...' case, the js_EmitTree(...pn3) - * called here will generate the SRC_VAR note for the assignment - * op that sets x = i, hoisting the initialized var declaration - * out of the loop: 'var x = i; for (x in o) ...'. - * - * In the 'for (var x in o) ...' case, nothing but the prolog op - * (if needed) should be generated here, we must emit the SRC_VAR - * just before the JSOP_FOR* opcode in the switch on pn3->pn_type - * a bit below, so nothing is hoisted: 'for (var x in o) ...'. - */ - pn3 = pn2->pn_left; - if (pn3->pn_type == TOK_VAR && !js_EmitTree(cx, cg, pn3)) - return JS_FALSE; - - /* Emit a push to allocate the iterator. */ - if (js_Emit1(cx, cg, JSOP_PUSH) < 0) - return JS_FALSE; - - /* Compile the object expression to the right of 'in'. */ - if (!js_EmitTree(cx, cg, pn2->pn_right)) - return JS_FALSE; - if (js_Emit1(cx, cg, JSOP_TOOBJECT) < 0) - return JS_FALSE; - - top = CG_OFFSET(cg); - SET_STATEMENT_TOP(&stmtInfo, top); - -#if JS_HAS_XML_SUPPORT - /* Emit a prefix opcode if 'for each (... in ...)' was used. */ - if (pn->pn_op != JSOP_NOP && js_Emit1(cx, cg, pn->pn_op) < 0) - return JS_FALSE; -#endif - - /* Compile a JSOP_FOR* bytecode based on the left hand side. */ - emitIFEQ = JS_TRUE; - switch (pn3->pn_type) { - case TOK_VAR: - pn3 = pn3->pn_head; - JS_ASSERT(pn3->pn_type == TOK_NAME); - if (!pn3->pn_expr && js_NewSrcNote(cx, cg, SRC_VAR) < 0) - return JS_FALSE; - /* FALL THROUGH */ - case TOK_NAME: - if (pn3->pn_slot >= 0) { - op = pn3->pn_op; - switch (op) { - case JSOP_GETARG: /* FALL THROUGH */ - case JSOP_SETARG: op = JSOP_FORARG; break; - case JSOP_GETVAR: /* FALL THROUGH */ - case JSOP_SETVAR: op = JSOP_FORVAR; break; - case JSOP_GETGVAR: - case JSOP_SETGVAR: op = JSOP_FORNAME; break; - default: JS_ASSERT(0); - } - } else { - pn3->pn_op = JSOP_FORNAME; - if (!LookupArgOrVar(cx, &cg->treeContext, pn3)) - return JS_FALSE; - op = pn3->pn_op; - } - if (pn3->pn_slot >= 0) { - if (pn3->pn_attrs & JSPROP_READONLY) - op = JSOP_GETVAR; - atomIndex = (jsatomid) pn3->pn_slot; - EMIT_UINT16_IMM_OP(op, atomIndex); - } else { - if (!EmitAtomOp(cx, pn3, op, cg)) - return JS_FALSE; - } - break; - - case TOK_DOT: - useful = JS_TRUE; - if (!CheckSideEffects(cx, &cg->treeContext, pn3->pn_expr, - &useful)) { - return JS_FALSE; - } - if (!useful) { - if (!EmitPropOp(cx, pn3, JSOP_FORPROP, cg)) - return JS_FALSE; - break; - } - /* FALL THROUGH */ - -#if JS_HAS_XML_SUPPORT - case TOK_UNARYOP: -#endif -#if JS_HAS_LVALUE_RETURN - case TOK_LP: -#endif - case TOK_LB: - /* - * We separate the first/next bytecode from the enumerator - * variable binding to avoid any side-effects in the index - * expression (e.g., for (x[i++] in {}) should not bind x[i] - * or increment i at all). - */ - emitIFEQ = JS_FALSE; - if (!js_Emit1(cx, cg, JSOP_FORELEM)) - return JS_FALSE; - - /* - * Emit a SRC_WHILE note with offset telling the distance to - * the loop-closing jump (we can't reckon from the branch at - * the top of the loop, because the loop-closing jump might - * need to be an extended jump, independent of whether the - * branch is short or long). - */ - noteIndex = js_NewSrcNote(cx, cg, SRC_WHILE); - if (noteIndex < 0) - return JS_FALSE; - beq = EmitJump(cx, cg, JSOP_IFEQ, 0); - if (beq < 0) - return JS_FALSE; - -#if JS_HAS_LVALUE_RETURN - if (pn3->pn_type == TOK_LP) { - JS_ASSERT(pn3->pn_op == JSOP_SETCALL); - if (!js_EmitTree(cx, cg, pn3)) - return JS_FALSE; - if (!js_Emit1(cx, cg, JSOP_ENUMELEM)) - return JS_FALSE; - break; - } -#endif -#if JS_HAS_XML_SUPPORT - if (pn3->pn_type == TOK_UNARYOP) { - JS_ASSERT(pn3->pn_op == JSOP_BINDXMLNAME); - if (!js_EmitTree(cx, cg, pn3)) - return JS_FALSE; - if (!js_Emit1(cx, cg, JSOP_ENUMELEM)) - return JS_FALSE; - break; - } -#endif - - /* Now that we're safely past the IFEQ, commit side effects. */ - if (!EmitElemOp(cx, pn3, JSOP_ENUMELEM, cg)) - return JS_FALSE; - break; - - default: - JS_ASSERT(0); - } - - if (emitIFEQ) { - /* Annotate so the decompiler can find the loop-closing jump. */ - noteIndex = js_NewSrcNote(cx, cg, SRC_WHILE); - if (noteIndex < 0) - return JS_FALSE; - - /* Pop and test the loop condition generated by JSOP_FOR*. */ - beq = EmitJump(cx, cg, JSOP_IFEQ, 0); - if (beq < 0) - return JS_FALSE; - } - } else { - if (!pn2->pn_kid1) { - /* No initializer: emit an annotated nop for the decompiler. */ - op = JSOP_NOP; - } else { - if (!js_EmitTree(cx, cg, pn2->pn_kid1)) - return JS_FALSE; - op = JSOP_POP; - } - noteIndex = js_NewSrcNote(cx, cg, SRC_FOR); - if (noteIndex < 0 || - js_Emit1(cx, cg, op) < 0) { - return JS_FALSE; - } - - top = CG_OFFSET(cg); - SET_STATEMENT_TOP(&stmtInfo, top); - if (!pn2->pn_kid2) { - /* No loop condition: flag this fact in the source notes. */ - if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, 0)) - return JS_FALSE; - } else { - if (!js_EmitTree(cx, cg, pn2->pn_kid2)) - return JS_FALSE; - if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, - CG_OFFSET(cg) - top)) { - return JS_FALSE; - } - beq = EmitJump(cx, cg, JSOP_IFEQ, 0); - if (beq < 0) - return JS_FALSE; - } - - /* Set pn3 (used below) here to avoid spurious gcc warnings. */ - pn3 = pn2->pn_kid3; - } - - /* Emit code for the loop body. */ - if (!js_EmitTree(cx, cg, pn->pn_right)) - return JS_FALSE; - - if (pn2->pn_type != TOK_IN) { - /* Set the second note offset so we can find the update part. */ - JS_ASSERT(noteIndex != -1); - if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 1, - CG_OFFSET(cg) - top)) { - return JS_FALSE; - } - - if (pn3) { - /* Set loop and enclosing "update" offsets, for continue. */ - stmt = &stmtInfo; - do { - stmt->update = CG_OFFSET(cg); - } while ((stmt = stmt->down) != NULL && - stmt->type == STMT_LABEL); - - if (!js_EmitTree(cx, cg, pn3)) - return JS_FALSE; - if (js_Emit1(cx, cg, JSOP_POP) < 0) - return JS_FALSE; - - /* Restore the absolute line number for source note readers. */ - off = (ptrdiff_t) pn->pn_pos.end.lineno; - if (CG_CURRENT_LINE(cg) != (uintN) off) { - if (js_NewSrcNote2(cx, cg, SRC_SETLINE, off) < 0) - return JS_FALSE; - CG_CURRENT_LINE(cg) = (uintN) off; - } - } - - /* The third note offset helps us find the loop-closing jump. */ - if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 2, - CG_OFFSET(cg) - top)) { - return JS_FALSE; - } - } - - /* Emit the loop-closing jump and fixup all jump offsets. */ - jmp = EmitJump(cx, cg, JSOP_GOTO, top - CG_OFFSET(cg)); - if (jmp < 0) - return JS_FALSE; - if (beq > 0) - CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, beq); - if (pn2->pn_type == TOK_IN) { - /* Set the SRC_WHILE note offset so we can find the closing jump. */ - JS_ASSERT(noteIndex != -1); - if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, jmp - beq)) - return JS_FALSE; - } - - /* Now fixup all breaks and continues (before for/in's final POP2). */ - if (!js_PopStatementCG(cx, cg)) - return JS_FALSE; - - if (pn2->pn_type == TOK_IN) { - if (js_Emit1(cx, cg, JSOP_POP2) < 0) - return JS_FALSE; - } - break; - - case TOK_BREAK: - stmt = cg->treeContext.topStmt; - atom = pn->pn_atom; - if (atom) { - ale = js_IndexAtom(cx, atom, &cg->atomList); - if (!ale) - return JS_FALSE; - while (stmt->type != STMT_LABEL || stmt->label != atom) - stmt = stmt->down; - noteType = SRC_BREAK2LABEL; - } else { - ale = NULL; - while (!STMT_IS_LOOP(stmt) && stmt->type != STMT_SWITCH) - stmt = stmt->down; - noteType = SRC_NULL; - } - - if (EmitGoto(cx, cg, stmt, &stmt->breaks, ale, noteType) < 0) - return JS_FALSE; - break; - - case TOK_CONTINUE: - stmt = cg->treeContext.topStmt; - atom = pn->pn_atom; - if (atom) { - /* Find the loop statement enclosed by the matching label. */ - JSStmtInfo *loop = NULL; - ale = js_IndexAtom(cx, atom, &cg->atomList); - if (!ale) - return JS_FALSE; - while (stmt->type != STMT_LABEL || stmt->label != atom) { - if (STMT_IS_LOOP(stmt)) - loop = stmt; - stmt = stmt->down; - } - stmt = loop; - noteType = SRC_CONT2LABEL; - } else { - ale = NULL; - while (!STMT_IS_LOOP(stmt)) - stmt = stmt->down; - noteType = SRC_CONTINUE; - } - - if (EmitGoto(cx, cg, stmt, &stmt->continues, ale, noteType) < 0) - return JS_FALSE; - break; - - case TOK_WITH: - if (!js_EmitTree(cx, cg, pn->pn_left)) - return JS_FALSE; - js_PushStatement(&cg->treeContext, &stmtInfo, STMT_WITH, CG_OFFSET(cg)); - if (js_Emit1(cx, cg, JSOP_ENTERWITH) < 0) - return JS_FALSE; - if (!js_EmitTree(cx, cg, pn->pn_right)) - return JS_FALSE; - if (js_Emit1(cx, cg, JSOP_LEAVEWITH) < 0) - return JS_FALSE; - ok = js_PopStatementCG(cx, cg); - break; - -#if JS_HAS_EXCEPTIONS - - case TOK_TRY: - { - ptrdiff_t start, end, catchStart, finallyCatch, catchJump; - JSParseNode *iter; - intN depth; - - /* Quell GCC overwarnings. */ - end = catchStart = finallyCatch = catchJump = -1; - - /* - * Push stmtInfo to track jumps-over-catches and gosubs-to-finally - * for later fixup. - * - * When a finally block is `active' (STMT_FINALLY on the treeContext), - * non-local jumps (including jumps-over-catches) result in a GOSUB - * being written into the bytecode stream and fixed-up later (c.f. - * EmitBackPatchOp and BackPatch). - */ - js_PushStatement(&cg->treeContext, &stmtInfo, - pn->pn_kid3 ? STMT_FINALLY : STMT_BLOCK, - CG_OFFSET(cg)); - - /* - * About JSOP_SETSP: an exception can be thrown while the stack is in - * an unbalanced state, and this imbalance causes problems with things - * like function invocation later on. - * - * To fix this, we compute the `balanced' stack depth upon try entry, - * and then restore the stack to this depth when we hit the first catch - * or finally block. We can't just zero the stack, because things like - * for/in and with that are active upon entry to the block keep state - * variables on the stack. - */ - depth = cg->stackDepth; - - /* Mark try location for decompilation, then emit try block. */ - if (js_Emit1(cx, cg, JSOP_TRY) < 0) - return JS_FALSE; - start = CG_OFFSET(cg); - if (!js_EmitTree(cx, cg, pn->pn_kid1)) - return JS_FALSE; - - /* GOSUB to finally, if present. */ - if (pn->pn_kid3) { - if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0) - return JS_FALSE; - jmp = EmitBackPatchOp(cx, cg, JSOP_BACKPATCH, &stmtInfo.gosub); - if (jmp < 0) - return JS_FALSE; - } - - /* Emit (hidden) jump over catch and/or finally. */ - if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0) - return JS_FALSE; - jmp = EmitBackPatchOp(cx, cg, JSOP_BACKPATCH, &stmtInfo.catchJump); - if (jmp < 0) - return JS_FALSE; - - end = CG_OFFSET(cg); - - /* If this try has a catch block, emit it. */ - iter = pn->pn_kid2; - if (iter) { - catchStart = end; - - /* - * The emitted code for a catch block looks like: - * - * [ popscope ] only if 2nd+ catch block - * name Object - * pushobj - * newinit - * exception - * initcatchvar - * enterwith - * [< catchguard code >] if there's a catchguard - * [ifeq ] " " - * < catch block contents > - * leavewith - * goto non-local; finally applies - * - * If there's no catch block without a catchguard, the last - * points to rethrow code. This - * code will [gosub] to the finally code if appropriate, and is - * also used for the catch-all trynote for capturing exceptions - * thrown from catch{} blocks. - */ - for (;;) { - JSStmtInfo stmtInfo2; - JSParseNode *disc; - ptrdiff_t guardnote; - - if (!UpdateLineNumberNotes(cx, cg, iter)) - return JS_FALSE; - - if (catchJump != -1) { - JS_ASSERT(cg->stackDepth == depth); - - /* Fix up and clean up previous catch block. */ - CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, catchJump); - - /* Set cx->throwing to protect cx->exception from the GC. */ - if (!js_Emit1(cx, cg, JSOP_THROWING) < 0) - return JS_FALSE; - - /* Compensate for the [leavewith]. */ - cg->stackDepth++; - JS_ASSERT((uintN) cg->stackDepth <= cg->maxStackDepth); - - if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0 || - js_Emit1(cx, cg, JSOP_LEAVEWITH) < 0) { - return JS_FALSE; - } - } else { - /* Set stack to original depth (see SETSP comment above). */ - EMIT_UINT16_IMM_OP(JSOP_SETSP, (jsatomid)depth); - cg->stackDepth = depth; - } - - /* Non-negative guardnote offset is length of catchguard. */ - guardnote = js_NewSrcNote2(cx, cg, SRC_CATCH, 0); - if (guardnote < 0 || - js_Emit1(cx, cg, JSOP_NOP) < 0) { - return JS_FALSE; - } - - /* Construct the scope holder and push it on. */ - ale = js_IndexAtom(cx, cx->runtime->atomState.ObjectAtom, - &cg->atomList); - if (!ale) - return JS_FALSE; - EMIT_ATOM_INDEX_OP(JSOP_NAME, ALE_INDEX(ale)); - - if (js_Emit1(cx, cg, JSOP_PUSHOBJ) < 0 || - js_Emit1(cx, cg, JSOP_NEWINIT) < 0 || - js_Emit1(cx, cg, JSOP_EXCEPTION) < 0) { - return JS_FALSE; - } - - /* initcatchvar */ - disc = iter->pn_kid1; - ale = js_IndexAtom(cx, disc->pn_atom, &cg->atomList); - if (!ale) - return JS_FALSE; - - EMIT_ATOM_INDEX_OP(JSOP_INITCATCHVAR, ALE_INDEX(ale)); - if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0 || - js_Emit1(cx, cg, JSOP_ENTERWITH) < 0) { - return JS_FALSE; - } - - /* boolean_expr */ - if (disc->pn_expr) { - ptrdiff_t guardstart = CG_OFFSET(cg); - if (!js_EmitTree(cx, cg, disc->pn_expr)) - return JS_FALSE; - if (!js_SetSrcNoteOffset(cx, cg, guardnote, 0, - CG_OFFSET(cg) - guardstart)) { - return JS_FALSE; - } - /* ifeq */ - catchJump = EmitJump(cx, cg, JSOP_IFEQ, 0); - if (catchJump < 0) - return JS_FALSE; - } - - /* Emit catch block. */ - js_PushStatement(&cg->treeContext, &stmtInfo2, STMT_CATCH, - CG_OFFSET(cg)); - stmtInfo2.label = disc->pn_atom; - if (!js_EmitTree(cx, cg, iter->pn_kid3)) - return JS_FALSE; - js_PopStatementCG(cx, cg); - - /* - * Jump over the remaining catch blocks. - * This counts as a non-local jump, so do the finally thing. - */ - - /* leavewith, annotated so the decompiler knows to pop */ - off = cg->stackDepth - 1; - if (js_NewSrcNote2(cx, cg, SRC_CATCH, off) < 0 || - js_Emit1(cx, cg, JSOP_LEAVEWITH) < 0) { - return JS_FALSE; - } - - /* gosub , if required */ - if (pn->pn_kid3) { - jmp = EmitBackPatchOp(cx, cg, JSOP_BACKPATCH, - &stmtInfo.gosub); - if (jmp < 0) - return JS_FALSE; - JS_ASSERT(cg->stackDepth == depth); - } - - /* This will get fixed up to jump to after catch/finally. */ - if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0) - return JS_FALSE; - jmp = EmitBackPatchOp(cx, cg, JSOP_BACKPATCH, - &stmtInfo.catchJump); - if (jmp < 0) - return JS_FALSE; - if (!iter->pn_kid2) /* leave iter at last catch */ - break; - iter = iter->pn_kid2; - } - } - - /* - * We emit a [setsp][gosub] sequence for running finally code while - * letting an uncaught exception pass thrown from within the try in a - * try-finally. The [gosub] and [retsub] opcodes will take care of - * stacking and rethrowing any exception pending across the finally. - * - * For rethrowing after a try-catch(guard)-finally, we have a problem: - * all the guards have mismatched, leaving cx->exception still set but - * cx->throwing clear, so that no exception appears to be pending for - * [gosub] to stack and [retsub] to rethrow. We must emit a special - * [throwing] opcode in front of the [setsp][gosub]; this opcode will - * restore cx->throwing to true before running the finally. - * - * For rethrowing after a try-catch(guard) without a finally, we emit - * [setsp][exception][throw]. - */ - if (pn->pn_kid3 || - (catchJump != -1 && iter->pn_kid1->pn_expr)) { - /* - * Last discriminant jumps to the rethrow code sequence if no - * discriminants match. Target catchJump at the beginning of the - * rethrow sequence, just in case a guard expression throws and - * leaves the stack unbalanced. - */ - if (catchJump != -1 && iter->pn_kid1->pn_expr) { - CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, catchJump); - if (pn->pn_kid3 && !js_Emit1(cx, cg, JSOP_THROWING) < 0) - return JS_FALSE; - } - - /* - * Emit another stack fixup, because the catch could itself - * throw an exception in an unbalanced state, and the finally - * may need to call functions. If there is no finally, only - * guarded catches, the rethrow code below nevertheless needs - * stack fixup. - */ - finallyCatch = CG_OFFSET(cg); - EMIT_UINT16_IMM_OP(JSOP_SETSP, (jsatomid)depth); - cg->stackDepth = depth; - - if (pn->pn_kid3) { - jmp = EmitBackPatchOp(cx, cg, JSOP_BACKPATCH, &stmtInfo.gosub); - if (jmp < 0) - return JS_FALSE; - - JS_ASSERT(cg->stackDepth == depth); - JS_ASSERT((uintN)depth <= cg->maxStackDepth); - } else { - if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0 || - js_Emit1(cx, cg, JSOP_EXCEPTION) < 0 || - js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0 || - js_Emit1(cx, cg, JSOP_THROW) < 0) { - return JS_FALSE; - } - } - } - - /* - * If we have a finally, it belongs here, and we have to fix up the - * gosubs that might have been emitted before non-local jumps. - */ - if (pn->pn_kid3) { - if (!BackPatch(cx, cg, stmtInfo.gosub, CG_NEXT(cg), JSOP_GOSUB)) - return JS_FALSE; - - /* - * The stack budget must be balanced at this point. All [gosub] - * calls emitted before this point will push two stack slots, one - * for the pending exception (or JSVAL_HOLE if there is no pending - * exception) and one for the [retsub] pc-index. - */ - JS_ASSERT(cg->stackDepth == depth); - cg->stackDepth += 2; - if ((uintN)cg->stackDepth > cg->maxStackDepth) - cg->maxStackDepth = cg->stackDepth; - - /* Now indicate that we're emitting a subroutine body. */ - stmtInfo.type = STMT_SUBROUTINE; - if (!UpdateLineNumberNotes(cx, cg, pn->pn_kid3)) - return JS_FALSE; - if (js_Emit1(cx, cg, JSOP_FINALLY) < 0 || - !js_EmitTree(cx, cg, pn->pn_kid3) || - js_Emit1(cx, cg, JSOP_RETSUB) < 0) { - return JS_FALSE; - } - - /* Restore stack depth budget to its balanced state. */ - JS_ASSERT(cg->stackDepth == depth + 2); - cg->stackDepth = depth; - } - if (!js_PopStatementCG(cx, cg)) - return JS_FALSE; - - if (js_NewSrcNote(cx, cg, SRC_ENDBRACE) < 0 || - js_Emit1(cx, cg, JSOP_NOP) < 0) { - return JS_FALSE; - } - - /* Fix up the end-of-try/catch jumps to come here. */ - if (!BackPatch(cx, cg, stmtInfo.catchJump, CG_NEXT(cg), JSOP_GOTO)) - return JS_FALSE; - - /* - * Add the try note last, to let post-order give us the right ordering - * (first to last for a given nesting level, inner to outer by level). - */ - if (pn->pn_kid2) { - JS_ASSERT(end != -1 && catchStart != -1); - if (!js_NewTryNote(cx, cg, start, end, catchStart)) - return JS_FALSE; - } - - /* - * If we've got a finally, mark try+catch region with additional - * trynote to catch exceptions (re)thrown from a catch block or - * for the try{}finally{} case. - */ - if (pn->pn_kid3) { - JS_ASSERT(finallyCatch != -1); - if (!js_NewTryNote(cx, cg, start, finallyCatch, finallyCatch)) - return JS_FALSE; - } - break; - } - -#endif /* JS_HAS_EXCEPTIONS */ - - case TOK_VAR: - off = noteIndex = -1; - for (pn2 = pn->pn_head; ; pn2 = pn2->pn_next) { - JS_ASSERT(pn2->pn_type == TOK_NAME); - if (!LookupArgOrVar(cx, &cg->treeContext, pn2)) - return JS_FALSE; - op = pn2->pn_op; - if (op == JSOP_ARGUMENTS) { - JS_ASSERT(!pn2->pn_expr); /* JSOP_ARGUMENTS => no initializer */ -#ifdef __GNUC__ - atomIndex = 0; /* quell GCC overwarning */ -#endif - } else { - if (pn2->pn_slot >= 0) { - atomIndex = (jsatomid) pn2->pn_slot; - } else { - ale = js_IndexAtom(cx, pn2->pn_atom, &cg->atomList); - if (!ale) - return JS_FALSE; - atomIndex = ALE_INDEX(ale); - } - - if ((js_CodeSpec[op].format & JOF_TYPEMASK) == JOF_CONST && - (!(cg->treeContext.flags & TCF_IN_FUNCTION) || - (cg->treeContext.flags & TCF_FUN_HEAVYWEIGHT))) { - /* Emit a prolog bytecode to predefine the variable. */ - CG_SWITCH_TO_PROLOG(cg); - if (!UpdateLineNumberNotes(cx, cg, pn2)) - return JS_FALSE; - EMIT_ATOM_INDEX_OP(pn->pn_op, atomIndex); - CG_SWITCH_TO_MAIN(cg); - } - - if (pn2->pn_expr) { - if (op == JSOP_SETNAME) - EMIT_ATOM_INDEX_OP(JSOP_BINDNAME, atomIndex); - pn3 = pn2->pn_expr; - if (pn->pn_op == JSOP_DEFCONST && - !js_DefineCompileTimeConstant(cx, cg, pn2->pn_atom, - pn3)) { - return JS_FALSE; - } - if (!js_EmitTree(cx, cg, pn3)) - return JS_FALSE; - } - } - - /* - * 'for (var x in o) ...' and 'for (var x = i in o) ...' call the - * TOK_VAR case, but only the initialized case (a strange one that - * falls out of ECMA-262's grammar) wants to run past this point. - * Both cases must conditionally emit a JSOP_DEFVAR, above. Note - * that the parser error-checks to ensure that pn->pn_count is 1. - * - * XXX Narcissus keeps track of variable declarations in the node - * for the script being compiled, so there's no need to share any - * conditional prolog code generation there. We could do likewise, - * but it's a big change, requiring extra allocation, so probably - * not worth the trouble for SpiderMonkey. - */ - if ((pn->pn_extra & PNX_FORINVAR) && !pn2->pn_expr) - break; - - if (pn2 == pn->pn_head && - js_NewSrcNote(cx, cg, - (pn->pn_op == JSOP_DEFCONST) - ? SRC_CONST - : SRC_VAR) < 0) { - return JS_FALSE; - } - if (op == JSOP_ARGUMENTS) { - if (js_Emit1(cx, cg, op) < 0) - return JS_FALSE; - } else if (pn2->pn_slot >= 0) { - EMIT_UINT16_IMM_OP(op, atomIndex); - } else { - EMIT_ATOM_INDEX_OP(op, atomIndex); - } - tmp = CG_OFFSET(cg); - if (noteIndex >= 0) { - if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, tmp-off)) - return JS_FALSE; - } - if (!pn2->pn_next) - break; - off = tmp; - noteIndex = js_NewSrcNote2(cx, cg, SRC_PCDELTA, 0); - if (noteIndex < 0 || - js_Emit1(cx, cg, JSOP_POP) < 0) { - return JS_FALSE; - } - } - if (pn->pn_extra & PNX_POPVAR) { - if (js_Emit1(cx, cg, JSOP_POP) < 0) - return JS_FALSE; - } - break; - - case TOK_RETURN: - /* Push a return value */ - pn2 = pn->pn_kid; - if (pn2) { - if (!js_EmitTree(cx, cg, pn2)) - return JS_FALSE; - } else { - if (js_Emit1(cx, cg, JSOP_PUSH) < 0) - return JS_FALSE; - } - - /* - * EmitNonLocalJumpFixup mutates op to JSOP_RETRVAL after emitting a - * JSOP_SETRVAL if there are open try blocks having finally clauses. - * We can't simply transfer control flow to our caller in that case, - * because we must gosub to those clauses from inner to outer, with - * the correct stack pointer (i.e., after popping any with, for/in, - * etc., slots nested inside the finally's try). - */ - op = JSOP_RETURN; - if (!EmitNonLocalJumpFixup(cx, cg, NULL, &op)) - return JS_FALSE; - if (js_Emit1(cx, cg, op) < 0) - return JS_FALSE; - break; - - case TOK_LC: -#if JS_HAS_XML_SUPPORT - if (pn->pn_arity == PN_UNARY) { - if (!js_EmitTree(cx, cg, pn->pn_kid)) - return JS_FALSE; - if (js_Emit1(cx, cg, pn->pn_op) < 0) - return JS_FALSE; - break; - } -#endif - - JS_ASSERT(pn->pn_arity == PN_LIST); - js_PushStatement(&cg->treeContext, &stmtInfo, STMT_BLOCK, top); - for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) { - if (!js_EmitTree(cx, cg, pn2)) - return JS_FALSE; - } - ok = js_PopStatementCG(cx, cg); - break; - - case TOK_SEMI: - pn2 = pn->pn_kid; - if (pn2) { - /* - * Top-level or called-from-a-native JS_Execute/EvaluateScript, - * debugger, and eval frames may need the value of the ultimate - * expression statement as the script's result, despite the fact - * that it appears useless to the compiler. - */ - useful = wantval = !cx->fp->fun || - !cx->fp->fun->interpreted || - (cx->fp->flags & JSFRAME_SPECIAL); - if (!useful) { - if (!CheckSideEffects(cx, &cg->treeContext, pn2, &useful)) - return JS_FALSE; - } - if (!useful) { - CG_CURRENT_LINE(cg) = pn2->pn_pos.begin.lineno; - if (!js_ReportCompileErrorNumber(cx, cg, - JSREPORT_CG | - JSREPORT_WARNING | - JSREPORT_STRICT, - JSMSG_USELESS_EXPR)) { - return JS_FALSE; - } - } else { - if (!js_EmitTree(cx, cg, pn2)) - return JS_FALSE; - if (js_Emit1(cx, cg, wantval ? JSOP_POPV : JSOP_POP) < 0) - return JS_FALSE; - } - } - break; - - case TOK_COLON: - /* Emit an annotated nop so we know to decompile a label. */ - atom = pn->pn_atom; - ale = js_IndexAtom(cx, atom, &cg->atomList); - if (!ale) - return JS_FALSE; - pn2 = pn->pn_expr; - noteIndex = js_NewSrcNote2(cx, cg, - (pn2->pn_type == TOK_LC) - ? SRC_LABELBRACE - : SRC_LABEL, - (ptrdiff_t) ALE_INDEX(ale)); - if (noteIndex < 0 || - js_Emit1(cx, cg, JSOP_NOP) < 0) { - return JS_FALSE; - } - - /* Emit code for the labeled statement. */ - js_PushStatement(&cg->treeContext, &stmtInfo, STMT_LABEL, - CG_OFFSET(cg)); - stmtInfo.label = atom; - if (!js_EmitTree(cx, cg, pn2)) - return JS_FALSE; - if (!js_PopStatementCG(cx, cg)) - return JS_FALSE; - - /* If the statement was compound, emit a note for the end brace. */ - if (pn2->pn_type == TOK_LC) { - if (js_NewSrcNote(cx, cg, SRC_ENDBRACE) < 0 || - js_Emit1(cx, cg, JSOP_NOP) < 0) { - return JS_FALSE; - } - } - break; - - case TOK_COMMA: - /* - * Emit SRC_PCDELTA notes on each JSOP_POP between comma operands. - * These notes help the decompiler bracket the bytecodes generated - * from each sub-expression that follows a comma. - */ - off = noteIndex = -1; - for (pn2 = pn->pn_head; ; pn2 = pn2->pn_next) { - if (!js_EmitTree(cx, cg, pn2)) - return JS_FALSE; - tmp = CG_OFFSET(cg); - if (noteIndex >= 0) { - if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, tmp-off)) - return JS_FALSE; - } - if (!pn2->pn_next) - break; - off = tmp; - noteIndex = js_NewSrcNote2(cx, cg, SRC_PCDELTA, 0); - if (noteIndex < 0 || - js_Emit1(cx, cg, JSOP_POP) < 0) { - return JS_FALSE; - } - } - break; - - case TOK_ASSIGN: - /* - * Check left operand type and generate specialized code for it. - * Specialize to avoid ECMA "reference type" values on the operand - * stack, which impose pervasive runtime "GetValue" costs. - */ - pn2 = pn->pn_left; - JS_ASSERT(pn2->pn_type != TOK_RP); - atomIndex = (jsatomid) -1; /* Suppress warning. */ - switch (pn2->pn_type) { - case TOK_NAME: - if (!LookupArgOrVar(cx, &cg->treeContext, pn2)) - return JS_FALSE; - if (pn2->pn_slot >= 0) { - atomIndex = (jsatomid) pn2->pn_slot; - } else { - ale = js_IndexAtom(cx, pn2->pn_atom, &cg->atomList); - if (!ale) - return JS_FALSE; - atomIndex = ALE_INDEX(ale); - EMIT_ATOM_INDEX_OP(JSOP_BINDNAME, atomIndex); - } - break; - case TOK_DOT: - if (!js_EmitTree(cx, cg, pn2->pn_expr)) - return JS_FALSE; - ale = js_IndexAtom(cx, pn2->pn_atom, &cg->atomList); - if (!ale) - return JS_FALSE; - atomIndex = ALE_INDEX(ale); - break; - case TOK_LB: - JS_ASSERT(pn->pn_arity == PN_BINARY); - if (!js_EmitTree(cx, cg, pn2->pn_left)) - return JS_FALSE; - if (!js_EmitTree(cx, cg, pn2->pn_right)) - return JS_FALSE; - break; -#if JS_HAS_LVALUE_RETURN - case TOK_LP: - if (!js_EmitTree(cx, cg, pn2)) - return JS_FALSE; - break; -#endif -#if JS_HAS_XML_SUPPORT - case TOK_UNARYOP: - JS_ASSERT(pn2->pn_op == JSOP_SETXMLNAME); - if (!js_EmitTree(cx, cg, pn2->pn_kid)) - return JS_FALSE; - if (js_Emit1(cx, cg, JSOP_BINDXMLNAME) < 0) - return JS_FALSE; - break; -#endif - default: - JS_ASSERT(0); - } - - op = pn->pn_op; -#if JS_HAS_GETTER_SETTER - if (op == JSOP_GETTER || op == JSOP_SETTER) { - /* We'll emit these prefix bytecodes after emitting the r.h.s. */ - } else -#endif - /* If += or similar, dup the left operand and get its value. */ - if (op != JSOP_NOP) { - switch (pn2->pn_type) { - case TOK_NAME: - if (pn2->pn_op != JSOP_SETNAME) { - EMIT_UINT16_IMM_OP((pn2->pn_op == JSOP_SETGVAR) - ? JSOP_GETGVAR - : (pn2->pn_op == JSOP_SETARG) - ? JSOP_GETARG - : JSOP_GETVAR, - atomIndex); - break; - } - /* FALL THROUGH */ - case TOK_DOT: - if (js_Emit1(cx, cg, JSOP_DUP) < 0) - return JS_FALSE; - EMIT_ATOM_INDEX_OP(JSOP_GETPROP, atomIndex); - break; - case TOK_LB: -#if JS_HAS_LVALUE_RETURN - case TOK_LP: -#endif -#if JS_HAS_XML_SUPPORT - case TOK_UNARYOP: -#endif - if (js_Emit1(cx, cg, JSOP_DUP2) < 0) - return JS_FALSE; - if (js_Emit1(cx, cg, JSOP_GETELEM) < 0) - return JS_FALSE; - break; - default:; - } - } - - /* Now emit the right operand (it may affect the namespace). */ - if (!js_EmitTree(cx, cg, pn->pn_right)) - return JS_FALSE; - - /* If += etc., emit the binary operator with a decompiler note. */ - if (op != JSOP_NOP) { - if (js_NewSrcNote(cx, cg, SRC_ASSIGNOP) < 0 || - js_Emit1(cx, cg, op) < 0) { - return JS_FALSE; - } - } - - /* Left parts such as a.b.c and a[b].c need a decompiler note. */ - if (pn2->pn_type != TOK_NAME && - js_NewSrcNote2(cx, cg, SrcNoteForPropOp(pn2, pn2->pn_op), - CG_OFFSET(cg) - top) < 0) { - return JS_FALSE; - } - - /* Finally, emit the specialized assignment bytecode. */ - switch (pn2->pn_type) { - case TOK_NAME: - if (pn2->pn_slot < 0 || !(pn2->pn_attrs & JSPROP_READONLY)) { - if (pn2->pn_slot >= 0) { - EMIT_UINT16_IMM_OP(pn2->pn_op, atomIndex); - } else { - case TOK_DOT: - EMIT_ATOM_INDEX_OP(pn2->pn_op, atomIndex); - } - } - break; - case TOK_LB: -#if JS_HAS_LVALUE_RETURN - case TOK_LP: -#endif - if (js_Emit1(cx, cg, JSOP_SETELEM) < 0) - return JS_FALSE; - break; -#if JS_HAS_XML_SUPPORT - case TOK_UNARYOP: - if (js_Emit1(cx, cg, JSOP_SETXMLNAME) < 0) - return JS_FALSE; - break; -#endif - default:; - } - break; - - case TOK_HOOK: - /* Emit the condition, then branch if false to the else part. */ - if (!js_EmitTree(cx, cg, pn->pn_kid1)) - return JS_FALSE; - noteIndex = js_NewSrcNote(cx, cg, SRC_COND); - if (noteIndex < 0) - return JS_FALSE; - beq = EmitJump(cx, cg, JSOP_IFEQ, 0); - if (beq < 0 || !js_EmitTree(cx, cg, pn->pn_kid2)) - return JS_FALSE; - - /* Jump around else, fixup the branch, emit else, fixup jump. */ - jmp = EmitJump(cx, cg, JSOP_GOTO, 0); - if (jmp < 0) - return JS_FALSE; - CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, beq); - if (!js_EmitTree(cx, cg, pn->pn_kid3)) - return JS_FALSE; - CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, jmp); - if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, jmp - beq)) - return JS_FALSE; - - /* - * Because each branch pushes a single value, but our stack budgeting - * analysis ignores branches, we now have two values accounted for in - * cg->stackDepth. Execution will follow only one path, so we must - * decrement cg->stackDepth here. Failing to do this will foil code, - * such as the try/catch/finally exception handling code generator, - * that samples cg->stackDepth for use at runtime (JSOP_SETSP). - */ - JS_ASSERT(cg->stackDepth > 1); - cg->stackDepth--; - break; - - case TOK_OR: - case TOK_AND: - /* - * JSOP_OR converts the operand on the stack to boolean, and if true, - * leaves the original operand value on the stack and jumps; otherwise - * it pops and falls into the next bytecode, which evaluates the right - * operand. The jump goes around the right operand evaluation. - * - * JSOP_AND converts the operand on the stack to boolean, and if false, - * leaves the original operand value on the stack and jumps; otherwise - * it pops and falls into the right operand's bytecode. - * - * Avoid tail recursion for long ||...|| expressions and long &&...&& - * expressions or long mixtures of ||'s and &&'s that can easily blow - * the stack, by forward-linking and then backpatching all the JSOP_OR - * and JSOP_AND bytecodes' immediate jump-offset operands. - */ - pn3 = pn; - if (!js_EmitTree(cx, cg, pn->pn_left)) - return JS_FALSE; - top = EmitJump(cx, cg, JSOP_BACKPATCH_POP, 0); - if (top < 0) - return JS_FALSE; - jmp = top; - pn2 = pn->pn_right; - while (pn2->pn_type == TOK_OR || pn2->pn_type == TOK_AND) { - pn = pn2; - if (!js_EmitTree(cx, cg, pn->pn_left)) - return JS_FALSE; - off = EmitJump(cx, cg, JSOP_BACKPATCH_POP, 0); - if (off < 0) - return JS_FALSE; - if (!SetBackPatchDelta(cx, cg, CG_CODE(cg, jmp), off - jmp)) - return JS_FALSE; - jmp = off; - pn2 = pn->pn_right; - } - if (!js_EmitTree(cx, cg, pn2)) - return JS_FALSE; - off = CG_OFFSET(cg); - do { - pc = CG_CODE(cg, top); - tmp = GetJumpOffset(cg, pc); - CHECK_AND_SET_JUMP_OFFSET(cx, cg, pc, off - top); - *pc = pn3->pn_op; - top += tmp; - } while ((pn3 = pn3->pn_right) != pn2); - break; - - case TOK_BITOR: - case TOK_BITXOR: - case TOK_BITAND: - case TOK_EQOP: - case TOK_RELOP: -#if JS_HAS_IN_OPERATOR - case TOK_IN: -#endif -#if JS_HAS_INSTANCEOF - case TOK_INSTANCEOF: -#endif - case TOK_SHOP: - case TOK_PLUS: - case TOK_MINUS: - case TOK_STAR: - case TOK_DIVOP: - if (pn->pn_arity == PN_LIST) { - /* Left-associative operator chain: avoid too much recursion. */ - pn2 = pn->pn_head; - if (!js_EmitTree(cx, cg, pn2)) - return JS_FALSE; - op = pn->pn_op; - while ((pn2 = pn2->pn_next) != NULL) { - if (!js_EmitTree(cx, cg, pn2)) - return JS_FALSE; - if (js_Emit1(cx, cg, op) < 0) - return JS_FALSE; - } - } else { -#if JS_HAS_XML_SUPPORT - case TOK_DBLCOLON: - if (pn->pn_arity == PN_NAME) { - if (!js_EmitTree(cx, cg, pn->pn_expr)) - return JS_FALSE; - if (!EmitAtomOp(cx, pn, pn->pn_op, cg)) - return JS_FALSE; - break; - } -#endif - /* Binary operators that evaluate both operands unconditionally. */ - if (!js_EmitTree(cx, cg, pn->pn_left)) - return JS_FALSE; - if (!js_EmitTree(cx, cg, pn->pn_right)) - return JS_FALSE; - if (js_Emit1(cx, cg, pn->pn_op) < 0) - return JS_FALSE; - } - break; - -#if JS_HAS_EXCEPTIONS - case TOK_THROW: -#endif -#if JS_HAS_XML_SUPPORT - case TOK_AT: - case TOK_DEFAULT: - JS_ASSERT(pn->pn_arity == PN_UNARY); - /* FALL THROUGH */ -#endif - case TOK_UNARYOP: - /* Unary op, including unary +/-. */ - pn2 = pn->pn_kid; - if (!js_EmitTree(cx, cg, pn2)) - return JS_FALSE; - op = pn->pn_op; -#if JS_HAS_XML_SUPPORT - if (op == JSOP_XMLNAME && - js_NewSrcNote2(cx, cg, SRC_PCBASE, - CG_OFFSET(cg) - pn2->pn_offset) < 0) { - return JS_FALSE; - } -#endif - if (js_Emit1(cx, cg, op) < 0) - return JS_FALSE; - break; - - case TOK_INC: - case TOK_DEC: - /* Emit lvalue-specialized code for ++/-- operators. */ - pn2 = pn->pn_kid; - JS_ASSERT(pn2->pn_type != TOK_RP); - op = pn->pn_op; - - /* - * Allocate another stack slot for GC protection in case the initial - * value being post-incremented or -decremented is not a number, but - * converts to a jsdouble. In the TOK_NAME cases, op has 0 operand - * uses and 1 definition, so we don't need an extra stack slot -- we - * can use the one allocated for the def. - */ - if (pn2->pn_type != TOK_NAME && - (js_CodeSpec[op].format & JOF_POST) && - (uintN)++cg->stackDepth > cg->maxStackDepth) { - cg->maxStackDepth = cg->stackDepth; - } - - switch (pn2->pn_type) { - case TOK_NAME: - pn2->pn_op = op; - if (!LookupArgOrVar(cx, &cg->treeContext, pn2)) - return JS_FALSE; - op = pn2->pn_op; - if (pn2->pn_slot >= 0) { - if (pn2->pn_attrs & JSPROP_READONLY) { - /* Incrementing a declared const: just get its value. */ - op = ((js_CodeSpec[op].format & JOF_TYPEMASK) == JOF_CONST) - ? JSOP_GETGVAR - : JSOP_GETVAR; - } - atomIndex = (jsatomid) pn2->pn_slot; - EMIT_UINT16_IMM_OP(op, atomIndex); - } else { - if (!EmitAtomOp(cx, pn2, op, cg)) - return JS_FALSE; - } - break; - case TOK_DOT: - if (!EmitPropOp(cx, pn2, op, cg)) - return JS_FALSE; - break; - case TOK_LB: - if (!EmitElemOp(cx, pn2, op, cg)) - return JS_FALSE; - break; -#if JS_HAS_LVALUE_RETURN - case TOK_LP: - if (!js_EmitTree(cx, cg, pn2)) - return JS_FALSE; - if (js_NewSrcNote2(cx, cg, SRC_PCBASE, - CG_OFFSET(cg) - pn2->pn_offset) < 0) { - return JS_FALSE; - } - if (js_Emit1(cx, cg, op) < 0) - return JS_FALSE; - break; -#endif -#if JS_HAS_XML_SUPPORT - case TOK_UNARYOP: - JS_ASSERT(pn2->pn_op == JSOP_SETXMLNAME); - if (!js_EmitTree(cx, cg, pn2->pn_kid)) - return JS_FALSE; - if (js_Emit1(cx, cg, JSOP_BINDXMLNAME) < 0) - return JS_FALSE; - if (js_Emit1(cx, cg, op) < 0) - return JS_FALSE; - break; -#endif - default: - JS_ASSERT(0); - } - - if (pn2->pn_type != TOK_NAME && (js_CodeSpec[op].format & JOF_POST)) - --cg->stackDepth; - break; - - case TOK_DELETE: - /* - * Under ECMA 3, deleting a non-reference returns true -- but alas we - * must evaluate the operand if it appears it might have side effects. - */ - pn2 = pn->pn_kid; - switch (pn2->pn_type) { - case TOK_NAME: - pn2->pn_op = JSOP_DELNAME; - if (!LookupArgOrVar(cx, &cg->treeContext, pn2)) - return JS_FALSE; - op = pn2->pn_op; - if (op == JSOP_FALSE) { - if (js_Emit1(cx, cg, op) < 0) - return JS_FALSE; - } else { - if (!EmitAtomOp(cx, pn2, op, cg)) - return JS_FALSE; - } - break; - case TOK_DOT: - if (!EmitPropOp(cx, pn2, JSOP_DELPROP, cg)) - return JS_FALSE; - break; -#if JS_HAS_XML_SUPPORT - case TOK_DBLDOT: - if (!EmitElemOp(cx, pn2, JSOP_DELDESC, cg)) - return JS_FALSE; - break; -#endif - case TOK_LB: - if (!EmitElemOp(cx, pn2, JSOP_DELELEM, cg)) - return JS_FALSE; - break; - default: - useful = JS_FALSE; - if (!CheckSideEffects(cx, &cg->treeContext, pn2, &useful)) - return JS_FALSE; - if (useful) { - if (!js_EmitTree(cx, cg, pn2)) - return JS_FALSE; - if (js_Emit1(cx, cg, JSOP_POP) < 0) - return JS_FALSE; - } - if (js_Emit1(cx, cg, JSOP_TRUE) < 0) - return JS_FALSE; - } - break; - -#if JS_HAS_XML_SUPPORT - case TOK_FILTER: - if (!js_EmitTree(cx, cg, pn->pn_left)) - return JS_FALSE; - jmp = js_Emit3(cx, cg, JSOP_FILTER, 0, 0); - if (jmp < 0) - return JS_FALSE; - if (!js_EmitTree(cx, cg, pn->pn_right)) - return JS_FALSE; - if (js_Emit1(cx, cg, JSOP_ENDFILTER) < 0) - return JS_FALSE; - CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, jmp); - break; -#endif - - case TOK_DOT: - /* - * Pop a stack operand, convert it to object, get a property named by - * this bytecode's immediate-indexed atom operand, and push its value - * (not a reference to it). This bytecode sets the virtual machine's - * "obj" register to the left operand's ToObject conversion result, - * for use by JSOP_PUSHOBJ. - */ - ok = EmitPropOp(cx, pn, pn->pn_op, cg); - break; - - case TOK_LB: -#if JS_HAS_XML_SUPPORT - case TOK_DBLDOT: -#endif - /* - * Pop two operands, convert the left one to object and the right one - * to property name (atom or tagged int), get the named property, and - * push its value. Set the "obj" register to the result of ToObject - * on the left operand. - */ - ok = EmitElemOp(cx, pn, pn->pn_op, cg); - break; - - case TOK_NEW: - case TOK_LP: - /* - * Emit function call or operator new (constructor call) code. - * First, emit code for the left operand to evaluate the callable or - * constructable object expression. - * - * For E4X, if this expression is a dotted member reference, select - * JSOP_GETMETHOD instead of JSOP_GETPROP. ECMA-357 separates XML - * method lookup from the normal property id lookup done for native - * objects. - */ - pn2 = pn->pn_head; -#if JS_HAS_XML_SUPPORT - if (pn2->pn_type == TOK_DOT && pn2->pn_op != JSOP_GETMETHOD) { - JS_ASSERT(pn2->pn_op == JSOP_GETPROP); - pn2->pn_op = JSOP_GETMETHOD; - pn2->pn_attrs |= JSPROP_IMPLICIT_FUNCTION_NAMESPACE; - } -#endif - if (!js_EmitTree(cx, cg, pn2)) - return JS_FALSE; - - /* - * Push the virtual machine's "obj" register, which was set by a - * name, property, or element get (or set) bytecode. - */ - if (js_Emit1(cx, cg, JSOP_PUSHOBJ) < 0) - return JS_FALSE; - - /* Remember start of callable-object bytecode for decompilation hint. */ - off = top; - - /* - * Emit code for each argument in order, then emit the JSOP_*CALL* or - * JSOP_NEW bytecode with a two-byte immediate telling how many args - * were pushed on the operand stack. - */ - for (pn2 = pn2->pn_next; pn2; pn2 = pn2->pn_next) { - if (!js_EmitTree(cx, cg, pn2)) - return JS_FALSE; - } - if (js_NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - off) < 0) - return JS_FALSE; - - argc = pn->pn_count - 1; - if (js_Emit3(cx, cg, pn->pn_op, ARGC_HI(argc), ARGC_LO(argc)) < 0) - return JS_FALSE; - break; - -#if JS_HAS_INITIALIZERS - case TOK_RB: - /* - * Emit code for [a, b, c] of the form: - * t = new Array; t[0] = a; t[1] = b; t[2] = c; t; - * but use a stack slot for t and avoid dup'ing and popping it via - * the JSOP_NEWINIT and JSOP_INITELEM bytecodes. - */ - ale = js_IndexAtom(cx, cx->runtime->atomState.ArrayAtom, - &cg->atomList); - if (!ale) - return JS_FALSE; - EMIT_ATOM_INDEX_OP(JSOP_NAME, ALE_INDEX(ale)); - if (js_Emit1(cx, cg, JSOP_PUSHOBJ) < 0) - return JS_FALSE; - if (js_Emit1(cx, cg, JSOP_NEWINIT) < 0) - return JS_FALSE; - - pn2 = pn->pn_head; -#if JS_HAS_SHARP_VARS - if (pn2 && pn2->pn_type == TOK_DEFSHARP) { - EMIT_UINT16_IMM_OP(JSOP_DEFSHARP, (jsatomid)pn2->pn_num); - pn2 = pn2->pn_next; - } -#endif - - for (atomIndex = 0; pn2; atomIndex++, pn2 = pn2->pn_next) { - if (!EmitNumberOp(cx, atomIndex, cg)) - return JS_FALSE; - - /* FIXME 260106: holes in a sparse initializer are void-filled. */ - if (pn2->pn_type == TOK_COMMA) { - if (js_Emit1(cx, cg, JSOP_PUSH) < 0) - return JS_FALSE; - } else { - if (!js_EmitTree(cx, cg, pn2)) - return JS_FALSE; - } - - if (js_Emit1(cx, cg, JSOP_INITELEM) < 0) - return JS_FALSE; - } - - if (pn->pn_extra & PNX_ENDCOMMA) { - /* Emit a source note so we know to decompile an extra comma. */ - if (js_NewSrcNote(cx, cg, SRC_CONTINUE) < 0) - return JS_FALSE; - } - - /* Emit an op for sharp array cleanup and decompilation. */ - if (js_Emit1(cx, cg, JSOP_ENDINIT) < 0) - return JS_FALSE; - break; - - case TOK_RC: - /* - * Emit code for {p:a, '%q':b, 2:c} of the form: - * t = new Object; t.p = a; t['%q'] = b; t[2] = c; t; - * but use a stack slot for t and avoid dup'ing and popping it via - * the JSOP_NEWINIT and JSOP_INITELEM bytecodes. - */ - ale = js_IndexAtom(cx, cx->runtime->atomState.ObjectAtom, - &cg->atomList); - if (!ale) - return JS_FALSE; - EMIT_ATOM_INDEX_OP(JSOP_NAME, ALE_INDEX(ale)); - - if (js_Emit1(cx, cg, JSOP_PUSHOBJ) < 0) - return JS_FALSE; - if (js_Emit1(cx, cg, JSOP_NEWINIT) < 0) - return JS_FALSE; - - pn2 = pn->pn_head; -#if JS_HAS_SHARP_VARS - if (pn2 && pn2->pn_type == TOK_DEFSHARP) { - EMIT_UINT16_IMM_OP(JSOP_DEFSHARP, (jsatomid)pn2->pn_num); - pn2 = pn2->pn_next; - } -#endif - - for (; pn2; pn2 = pn2->pn_next) { - /* Emit an index for t[2], else map an atom for t.p or t['%q']. */ - pn3 = pn2->pn_left; - switch (pn3->pn_type) { - case TOK_NUMBER: - if (!EmitNumberOp(cx, pn3->pn_dval, cg)) - return JS_FALSE; - break; - case TOK_NAME: - case TOK_STRING: - ale = js_IndexAtom(cx, pn3->pn_atom, &cg->atomList); - if (!ale) - return JS_FALSE; - break; - default: - JS_ASSERT(0); - } - - /* Emit code for the property initializer. */ - if (!js_EmitTree(cx, cg, pn2->pn_right)) - return JS_FALSE; - -#if JS_HAS_GETTER_SETTER - op = pn2->pn_op; - if (op == JSOP_GETTER || op == JSOP_SETTER) { - if (js_Emit1(cx, cg, op) < 0) - return JS_FALSE; - } -#endif - /* Annotate JSOP_INITELEM so we decompile 2:c and not just c. */ - if (pn3->pn_type == TOK_NUMBER) { - if (js_NewSrcNote2(cx, cg, SRC_LABEL, 0) < 0) - return JS_FALSE; - if (js_Emit1(cx, cg, JSOP_INITELEM) < 0) - return JS_FALSE; - } else { - EMIT_ATOM_INDEX_OP(JSOP_INITPROP, ALE_INDEX(ale)); - } - } - - /* Emit an op for sharpArray cleanup and decompilation. */ - if (js_Emit1(cx, cg, JSOP_ENDINIT) < 0) - return JS_FALSE; - break; - -#if JS_HAS_SHARP_VARS - case TOK_DEFSHARP: - if (!js_EmitTree(cx, cg, pn->pn_kid)) - return JS_FALSE; - EMIT_UINT16_IMM_OP(JSOP_DEFSHARP, (jsatomid) pn->pn_num); - break; - - case TOK_USESHARP: - EMIT_UINT16_IMM_OP(JSOP_USESHARP, (jsatomid) pn->pn_num); - break; -#endif /* JS_HAS_SHARP_VARS */ -#endif /* JS_HAS_INITIALIZERS */ - - case TOK_RP: - /* - * The node for (e) has e as its kid, enabling users who want to nest - * assignment expressions in conditions to avoid the error correction - * done by Condition (from x = y to x == y) by double-parenthesizing. - */ - if (!js_EmitTree(cx, cg, pn->pn_kid)) - return JS_FALSE; - if (js_Emit1(cx, cg, JSOP_GROUP) < 0) - return JS_FALSE; - break; - - case TOK_NAME: - if (!LookupArgOrVar(cx, &cg->treeContext, pn)) - return JS_FALSE; - op = pn->pn_op; - if (op == JSOP_ARGUMENTS) { - if (js_Emit1(cx, cg, op) < 0) - return JS_FALSE; - break; - } - if (pn->pn_slot >= 0) { - atomIndex = (jsatomid) pn->pn_slot; - EMIT_UINT16_IMM_OP(op, atomIndex); - break; - } - /* FALL THROUGH */ - -#if JS_HAS_XML_SUPPORT - case TOK_XMLATTR: - case TOK_XMLSPACE: - case TOK_XMLTEXT: - case TOK_XMLCDATA: - case TOK_XMLCOMMENT: -#endif - case TOK_STRING: - case TOK_OBJECT: - /* - * The scanner and parser associate JSOP_NAME with TOK_NAME, although - * other bytecodes may result instead (JSOP_BINDNAME/JSOP_SETNAME, - * JSOP_FORNAME, etc.). Among JSOP_*NAME* variants, only JSOP_NAME - * may generate the first operand of a call or new expression, so only - * it sets the "obj" virtual machine register to the object along the - * scope chain in which the name was found. - * - * Token types for STRING and OBJECT have corresponding bytecode ops - * in pn_op and emit the same format as NAME, so they share this code. - */ - ok = EmitAtomOp(cx, pn, pn->pn_op, cg); - break; - - case TOK_NUMBER: - ok = EmitNumberOp(cx, pn->pn_dval, cg); - break; - -#if JS_HAS_XML_SUPPORT - case TOK_ANYNAME: -#endif - case TOK_PRIMARY: - if (js_Emit1(cx, cg, pn->pn_op) < 0) - return JS_FALSE; - break; - -#if JS_HAS_DEBUGGER_KEYWORD - case TOK_DEBUGGER: - if (js_Emit1(cx, cg, JSOP_DEBUGGER) < 0) - return JS_FALSE; - break; -#endif /* JS_HAS_DEBUGGER_KEYWORD */ - -#if JS_HAS_XML_SUPPORT - case TOK_XMLELEM: - case TOK_XMLLIST: - if (pn->pn_op == JSOP_XMLOBJECT) { - ok = EmitAtomOp(cx, pn, pn->pn_op, cg); - break; - } - - JS_ASSERT(pn->pn_type == TOK_XMLLIST || pn->pn_count != 0); - switch (pn->pn_head ? pn->pn_head->pn_type : TOK_XMLLIST) { - case TOK_XMLETAGO: - JS_ASSERT(0); - /* FALL THROUGH */ - case TOK_XMLPTAGC: - case TOK_XMLSTAGO: - break; - default: - if (js_Emit1(cx, cg, JSOP_STARTXML) < 0) - return JS_FALSE; - } - - for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) { - if (pn2->pn_type == TOK_LC && - js_Emit1(cx, cg, JSOP_STARTXMLEXPR) < 0) { - return JS_FALSE; - } - if (!js_EmitTree(cx, cg, pn2)) - return JS_FALSE; - if (pn2 != pn->pn_head && js_Emit1(cx, cg, JSOP_ADD) < 0) - return JS_FALSE; - } - - if (pn->pn_extra & PNX_XMLROOT) { - if (pn->pn_count == 0) { - JS_ASSERT(pn->pn_type == TOK_XMLLIST); - atom = cx->runtime->atomState.emptyAtom; - ale = js_IndexAtom(cx, atom, &cg->atomList); - if (!ale) - return JS_FALSE; - EMIT_ATOM_INDEX_OP(JSOP_STRING, ALE_INDEX(ale)); - } - if (js_Emit1(cx, cg, pn->pn_op) < 0) - return JS_FALSE; - } -#ifdef DEBUG - else - JS_ASSERT(pn->pn_count != 0); -#endif - break; - - case TOK_XMLPTAGC: - if (pn->pn_op == JSOP_XMLOBJECT) { - ok = EmitAtomOp(cx, pn, pn->pn_op, cg); - break; - } - /* FALL THROUGH */ - - case TOK_XMLSTAGO: - case TOK_XMLETAGO: - { - uint32 i; - - if (js_Emit1(cx, cg, JSOP_STARTXML) < 0) - return JS_FALSE; - - ale = js_IndexAtom(cx, - (pn->pn_type == TOK_XMLETAGO) - ? cx->runtime->atomState.etagoAtom - : cx->runtime->atomState.stagoAtom, - &cg->atomList); - if (!ale) - return JS_FALSE; - EMIT_ATOM_INDEX_OP(JSOP_STRING, ALE_INDEX(ale)); - - JS_ASSERT(pn->pn_count != 0); - pn2 = pn->pn_head; - if (pn2->pn_type == TOK_LC && js_Emit1(cx, cg, JSOP_STARTXMLEXPR) < 0) - return JS_FALSE; - if (!js_EmitTree(cx, cg, pn2)) - return JS_FALSE; - if (js_Emit1(cx, cg, JSOP_ADD) < 0) - return JS_FALSE; - - for (pn2 = pn2->pn_next, i = 0; pn2; pn2 = pn2->pn_next, i++) { - if (pn2->pn_type == TOK_LC && - js_Emit1(cx, cg, JSOP_STARTXMLEXPR) < 0) { - return JS_FALSE; - } - if (!js_EmitTree(cx, cg, pn2)) - return JS_FALSE; - if ((i & 1) && pn2->pn_type == TOK_LC) { - if (js_Emit1(cx, cg, JSOP_TOATTRVAL) < 0) - return JS_FALSE; - } - if (js_Emit1(cx, cg, - (i & 1) ? JSOP_ADDATTRVAL : JSOP_ADDATTRNAME) < 0) { - return JS_FALSE; - } - } - - ale = js_IndexAtom(cx, - (pn->pn_type == TOK_XMLPTAGC) - ? cx->runtime->atomState.ptagcAtom - : cx->runtime->atomState.tagcAtom, - &cg->atomList); - if (!ale) - return JS_FALSE; - EMIT_ATOM_INDEX_OP(JSOP_STRING, ALE_INDEX(ale)); - if (js_Emit1(cx, cg, JSOP_ADD) < 0) - return JS_FALSE; - - if ((pn->pn_extra & PNX_XMLROOT) && js_Emit1(cx, cg, pn->pn_op) < 0) - return JS_FALSE; - break; - } - - case TOK_XMLNAME: - if (pn->pn_arity == PN_LIST) { - JS_ASSERT(pn->pn_count != 0); - for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) { - if (!js_EmitTree(cx, cg, pn2)) - return JS_FALSE; - if (pn2 != pn->pn_head && js_Emit1(cx, cg, JSOP_ADD) < 0) - return JS_FALSE; - } - } else { - JS_ASSERT(pn->pn_arity == PN_NULLARY); - ok = EmitAtomOp(cx, pn, pn->pn_op, cg); - } - break; - - case TOK_XMLPI: - ale = js_IndexAtom(cx, pn->pn_atom2, &cg->atomList); - if (!ale) - return JS_FALSE; - if (!EmitAtomIndexOp(cx, JSOP_STRING, ALE_INDEX(ale), cg)) - return JS_FALSE; - if (!EmitAtomOp(cx, pn, JSOP_XMLPI, cg)) - return JS_FALSE; - break; -#endif /* JS_HAS_XML_SUPPORT */ - - default: - JS_ASSERT(0); - } - - if (ok && --cg->emitLevel == 0 && cg->spanDeps) - ok = OptimizeSpanDeps(cx, cg); - - return ok; -} - -JS_FRIEND_DATA(JSSrcNoteSpec) js_SrcNoteSpec[] = { - {"null", 0, 0, 0}, - {"if", 0, 0, 0}, - {"if-else", 1, 0, 1}, - {"while", 1, 0, 1}, - {"for", 3, 1, 1}, - {"continue", 0, 0, 0}, - {"var", 0, 0, 0}, - {"pcdelta", 1, 0, 1}, - {"assignop", 0, 0, 0}, - {"cond", 1, 0, 1}, - {"reserved0", 0, 0, 0}, - {"hidden", 0, 0, 0}, - {"pcbase", 1, 0, -1}, - {"label", 1, 0, 0}, - {"labelbrace", 1, 0, 0}, - {"endbrace", 0, 0, 0}, - {"break2label", 1, 0, 0}, - {"cont2label", 1, 0, 0}, - {"switch", 2, 0, 1}, - {"funcdef", 1, 0, 0}, - {"catch", 1, 11, 1}, - {"const", 0, 0, 0}, - {"newline", 0, 0, 0}, - {"setline", 1, 0, 0}, - {"xdelta", 0, 0, 0}, -}; - -static intN -AllocSrcNote(JSContext *cx, JSCodeGenerator *cg) -{ - intN index; - JSArenaPool *pool; - size_t size; - - index = CG_NOTE_COUNT(cg); - if (((uintN)index & CG_NOTE_MASK(cg)) == 0) { - pool = cg->notePool; - size = SRCNOTE_SIZE(CG_NOTE_MASK(cg) + 1); - if (!CG_NOTES(cg)) { - /* Allocate the first note array lazily; leave noteMask alone. */ - JS_ARENA_ALLOCATE_CAST(CG_NOTES(cg), jssrcnote *, pool, size); - } else { - /* Grow by doubling note array size; update noteMask on success. */ - JS_ARENA_GROW_CAST(CG_NOTES(cg), jssrcnote *, pool, size, size); - if (CG_NOTES(cg)) - CG_NOTE_MASK(cg) = (CG_NOTE_MASK(cg) << 1) | 1; - } - if (!CG_NOTES(cg)) { - JS_ReportOutOfMemory(cx); - return -1; - } - } - - CG_NOTE_COUNT(cg) = index + 1; - return index; -} - -intN -js_NewSrcNote(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type) -{ - intN index, n; - jssrcnote *sn; - ptrdiff_t offset, delta, xdelta; - - /* - * Claim a note slot in CG_NOTES(cg) by growing it if necessary and then - * incrementing CG_NOTE_COUNT(cg). - */ - index = AllocSrcNote(cx, cg); - if (index < 0) - return -1; - sn = &CG_NOTES(cg)[index]; - - /* - * Compute delta from the last annotated bytecode's offset. If it's too - * big to fit in sn, allocate one or more xdelta notes and reset sn. - */ - offset = CG_OFFSET(cg); - delta = offset - CG_LAST_NOTE_OFFSET(cg); - CG_LAST_NOTE_OFFSET(cg) = offset; - if (delta >= SN_DELTA_LIMIT) { - do { - xdelta = JS_MIN(delta, SN_XDELTA_MASK); - SN_MAKE_XDELTA(sn, xdelta); - delta -= xdelta; - index = AllocSrcNote(cx, cg); - if (index < 0) - return -1; - sn = &CG_NOTES(cg)[index]; - } while (delta >= SN_DELTA_LIMIT); - } - - /* - * Initialize type and delta, then allocate the minimum number of notes - * needed for type's arity. Usually, we won't need more, but if an offset - * does take two bytes, js_SetSrcNoteOffset will grow CG_NOTES(cg). - */ - SN_MAKE_NOTE(sn, type, delta); - for (n = (intN)js_SrcNoteSpec[type].arity; n > 0; n--) { - if (js_NewSrcNote(cx, cg, SRC_NULL) < 0) - return -1; - } - return index; -} - -intN -js_NewSrcNote2(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type, - ptrdiff_t offset) -{ - intN index; - - index = js_NewSrcNote(cx, cg, type); - if (index >= 0) { - if (!js_SetSrcNoteOffset(cx, cg, index, 0, offset)) - return -1; - } - return index; -} - -intN -js_NewSrcNote3(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type, - ptrdiff_t offset1, ptrdiff_t offset2) -{ - intN index; - - index = js_NewSrcNote(cx, cg, type); - if (index >= 0) { - if (!js_SetSrcNoteOffset(cx, cg, index, 0, offset1)) - return -1; - if (!js_SetSrcNoteOffset(cx, cg, index, 1, offset2)) - return -1; - } - return index; -} - -static JSBool -GrowSrcNotes(JSContext *cx, JSCodeGenerator *cg) -{ - JSArenaPool *pool; - size_t size; - - /* Grow by doubling note array size; update noteMask on success. */ - pool = cg->notePool; - size = SRCNOTE_SIZE(CG_NOTE_MASK(cg) + 1); - JS_ARENA_GROW_CAST(CG_NOTES(cg), jssrcnote *, pool, size, size); - if (!CG_NOTES(cg)) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - CG_NOTE_MASK(cg) = (CG_NOTE_MASK(cg) << 1) | 1; - return JS_TRUE; -} - -jssrcnote * -js_AddToSrcNoteDelta(JSContext *cx, JSCodeGenerator *cg, jssrcnote *sn, - ptrdiff_t delta) -{ - ptrdiff_t base, limit, newdelta, diff; - intN index; - - /* - * Called only from OptimizeSpanDeps and js_FinishTakingSrcNotes to add to - * main script note deltas, and only by a small positive amount. - */ - JS_ASSERT(cg->current == &cg->main); - JS_ASSERT((unsigned) delta < (unsigned) SN_XDELTA_LIMIT); - - base = SN_DELTA(sn); - limit = SN_IS_XDELTA(sn) ? SN_XDELTA_LIMIT : SN_DELTA_LIMIT; - newdelta = base + delta; - if (newdelta < limit) { - SN_SET_DELTA(sn, newdelta); - } else { - index = sn - cg->main.notes; - if ((cg->main.noteCount & cg->main.noteMask) == 0) { - if (!GrowSrcNotes(cx, cg)) - return NULL; - sn = cg->main.notes + index; - } - diff = cg->main.noteCount - index; - cg->main.noteCount++; - memmove(sn + 1, sn, SRCNOTE_SIZE(diff)); - SN_MAKE_XDELTA(sn, delta); - sn++; - } - return sn; -} - -JS_FRIEND_API(uintN) -js_SrcNoteLength(jssrcnote *sn) -{ - uintN arity; - jssrcnote *base; - - arity = (intN)js_SrcNoteSpec[SN_TYPE(sn)].arity; - for (base = sn++; arity; sn++, arity--) { - if (*sn & SN_3BYTE_OFFSET_FLAG) - sn += 2; - } - return sn - base; -} - -JS_FRIEND_API(ptrdiff_t) -js_GetSrcNoteOffset(jssrcnote *sn, uintN which) -{ - /* Find the offset numbered which (i.e., skip exactly which offsets). */ - JS_ASSERT(SN_TYPE(sn) != SRC_XDELTA); - JS_ASSERT(which < js_SrcNoteSpec[SN_TYPE(sn)].arity); - for (sn++; which; sn++, which--) { - if (*sn & SN_3BYTE_OFFSET_FLAG) - sn += 2; - } - if (*sn & SN_3BYTE_OFFSET_FLAG) { - return (ptrdiff_t)(((uint32)(sn[0] & SN_3BYTE_OFFSET_MASK) << 16) - | (sn[1] << 8) - | sn[2]); - } - return (ptrdiff_t)*sn; -} - -JSBool -js_SetSrcNoteOffset(JSContext *cx, JSCodeGenerator *cg, uintN index, - uintN which, ptrdiff_t offset) -{ - jssrcnote *sn; - ptrdiff_t diff; - - if ((jsuword)offset >= (jsuword)((ptrdiff_t)SN_3BYTE_OFFSET_FLAG << 16)) { - ReportStatementTooLarge(cx, cg); - return JS_FALSE; - } - - /* Find the offset numbered which (i.e., skip exactly which offsets). */ - sn = &CG_NOTES(cg)[index]; - JS_ASSERT(SN_TYPE(sn) != SRC_XDELTA); - JS_ASSERT(which < js_SrcNoteSpec[SN_TYPE(sn)].arity); - for (sn++; which; sn++, which--) { - if (*sn & SN_3BYTE_OFFSET_FLAG) - sn += 2; - } - - /* See if the new offset requires three bytes. */ - if (offset > (ptrdiff_t)SN_3BYTE_OFFSET_MASK) { - /* Maybe this offset was already set to a three-byte value. */ - if (!(*sn & SN_3BYTE_OFFSET_FLAG)) { - /* Losing, need to insert another two bytes for this offset. */ - index = PTRDIFF(sn, CG_NOTES(cg), jssrcnote); - - /* - * Simultaneously test to see if the source note array must grow to - * accomodate either the first or second byte of additional storage - * required by this 3-byte offset. - */ - if (((CG_NOTE_COUNT(cg) + 1) & CG_NOTE_MASK(cg)) <= 1) { - if (!GrowSrcNotes(cx, cg)) - return JS_FALSE; - sn = CG_NOTES(cg) + index; - } - CG_NOTE_COUNT(cg) += 2; - - diff = CG_NOTE_COUNT(cg) - (index + 3); - JS_ASSERT(diff >= 0); - if (diff > 0) - memmove(sn + 3, sn + 1, SRCNOTE_SIZE(diff)); - } - *sn++ = (jssrcnote)(SN_3BYTE_OFFSET_FLAG | (offset >> 16)); - *sn++ = (jssrcnote)(offset >> 8); - } - *sn = (jssrcnote)offset; - return JS_TRUE; -} - -#ifdef DEBUG_brendan -#define NBINS 10 -static uint32 hist[NBINS]; - -void DumpSrcNoteSizeHist() -{ - static FILE *fp; - int i, n; - - if (!fp) { - fp = fopen("/tmp/srcnotes.hist", "w"); - if (!fp) - return; - setvbuf(fp, NULL, _IONBF, 0); - } - fprintf(fp, "SrcNote size histogram:\n"); - for (i = 0; i < NBINS; i++) { - fprintf(fp, "%4u %4u ", JS_BIT(i), hist[i]); - for (n = (int) JS_HOWMANY(hist[i], 10); n > 0; --n) - fputc('*', fp); - fputc('\n', fp); - } - fputc('\n', fp); -} -#endif - -/* - * Fill in the storage at notes with prolog and main srcnotes; the space at - * notes was allocated using the CG_COUNT_FINAL_SRCNOTES macro from jsemit.h. - * SO DON'T CHANGE THIS FUNCTION WITHOUT AT LEAST CHECKING WHETHER jsemit.h's - * CG_COUNT_FINAL_SRCNOTES MACRO NEEDS CORRESPONDING CHANGES! - */ -JSBool -js_FinishTakingSrcNotes(JSContext *cx, JSCodeGenerator *cg, jssrcnote *notes) -{ - uintN prologCount, mainCount, totalCount; - ptrdiff_t offset, delta; - jssrcnote *sn; - - JS_ASSERT(cg->current == &cg->main); - - prologCount = cg->prolog.noteCount; - if (prologCount && cg->prolog.currentLine != cg->firstLine) { - CG_SWITCH_TO_PROLOG(cg); - if (js_NewSrcNote2(cx, cg, SRC_SETLINE, (ptrdiff_t)cg->firstLine) < 0) - return JS_FALSE; - prologCount = cg->prolog.noteCount; - CG_SWITCH_TO_MAIN(cg); - } else { - /* - * Either no prolog srcnotes, or no line number change over prolog. - * We don't need a SRC_SETLINE, but we may need to adjust the offset - * of the first main note, by adding to its delta and possibly even - * prepending SRC_XDELTA notes to it to account for prolog bytecodes - * that came at and after the last annotated bytecode. - */ - offset = CG_PROLOG_OFFSET(cg) - cg->prolog.lastNoteOffset; - JS_ASSERT(offset >= 0); - if (offset > 0) { - /* NB: Use as much of the first main note's delta as we can. */ - sn = cg->main.notes; - delta = SN_IS_XDELTA(sn) - ? SN_XDELTA_MASK - (*sn & SN_XDELTA_MASK) - : SN_DELTA_MASK - (*sn & SN_DELTA_MASK); - if (offset < delta) - delta = offset; - for (;;) { - if (!js_AddToSrcNoteDelta(cx, cg, sn, delta)) - return JS_FALSE; - offset -= delta; - if (offset == 0) - break; - delta = JS_MIN(offset, SN_XDELTA_MASK); - sn = cg->main.notes; - } - } - } - - mainCount = cg->main.noteCount; - totalCount = prologCount + mainCount; - if (prologCount) - memcpy(notes, cg->prolog.notes, SRCNOTE_SIZE(prologCount)); - memcpy(notes + prologCount, cg->main.notes, SRCNOTE_SIZE(mainCount)); - SN_MAKE_TERMINATOR(¬es[totalCount]); - -#ifdef DEBUG_brendan - { int bin = JS_CeilingLog2(totalCount); - if (bin >= NBINS) - bin = NBINS - 1; - ++hist[bin]; - } -#endif - return JS_TRUE; -} - -JSBool -js_AllocTryNotes(JSContext *cx, JSCodeGenerator *cg) -{ - size_t size, incr; - ptrdiff_t delta; - - size = TRYNOTE_SIZE(cg->treeContext.tryCount); - if (size <= cg->tryNoteSpace) - return JS_TRUE; - - /* - * Allocate trynotes from cx->tempPool. - * XXX Too much growing and we bloat, as other tempPool allocators block - * in-place growth, and we never recycle old free space in an arena. - * YYY But once we consume an entire arena, we'll realloc it, letting the - * malloc heap recycle old space, while still freeing _en masse_ via the - * arena pool. - */ - if (!cg->tryBase) { - size = JS_ROUNDUP(size, TRYNOTE_SIZE(TRYNOTE_CHUNK)); - JS_ARENA_ALLOCATE_CAST(cg->tryBase, JSTryNote *, &cx->tempPool, size); - if (!cg->tryBase) - return JS_FALSE; - cg->tryNoteSpace = size; - cg->tryNext = cg->tryBase; - } else { - delta = PTRDIFF((char *)cg->tryNext, (char *)cg->tryBase, char); - incr = size - cg->tryNoteSpace; - incr = JS_ROUNDUP(incr, TRYNOTE_SIZE(TRYNOTE_CHUNK)); - size = cg->tryNoteSpace; - JS_ARENA_GROW_CAST(cg->tryBase, JSTryNote *, &cx->tempPool, size, incr); - if (!cg->tryBase) - return JS_FALSE; - cg->tryNoteSpace = size + incr; - cg->tryNext = (JSTryNote *)((char *)cg->tryBase + delta); - } - return JS_TRUE; -} - -JSTryNote * -js_NewTryNote(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t start, - ptrdiff_t end, ptrdiff_t catchStart) -{ - JSTryNote *tn; - - JS_ASSERT(cg->tryBase <= cg->tryNext); - JS_ASSERT(catchStart >= 0); - tn = cg->tryNext++; - tn->start = start; - tn->length = end - start; - tn->catchStart = catchStart; - return tn; -} - -void -js_FinishTakingTryNotes(JSContext *cx, JSCodeGenerator *cg, JSTryNote *notes) -{ - uintN count; - - count = PTRDIFF(cg->tryNext, cg->tryBase, JSTryNote); - if (!count) - return; - - memcpy(notes, cg->tryBase, TRYNOTE_SIZE(count)); - notes[count].start = 0; - notes[count].length = CG_OFFSET(cg); - notes[count].catchStart = 0; -} diff --git a/lib/javascript/jsemit.h b/lib/javascript/jsemit.h deleted file mode 100644 index 6ec4600b..00000000 --- a/lib/javascript/jsemit.h +++ /dev/null @@ -1,592 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jsemit_h___ -#define jsemit_h___ -/* - * JS bytecode generation. - */ - -#include "jsstddef.h" -#include "jstypes.h" -#include "jsatom.h" -#include "jsopcode.h" -#include "jsprvtd.h" -#include "jspubtd.h" - -JS_BEGIN_EXTERN_C - -/* - * NB: If you add non-loop STMT_* enumerators, do so before STMT_DO_LOOP or - * you will break the STMT_IS_LOOP macro, just below this enum. - */ -typedef enum JSStmtType { - STMT_BLOCK = 0, /* compound statement: { s1[;... sN] } */ - STMT_LABEL = 1, /* labeled statement: L: s */ - STMT_IF = 2, /* if (then) statement */ - STMT_ELSE = 3, /* else clause of if statement */ - STMT_SWITCH = 4, /* switch statement */ - STMT_WITH = 5, /* with statement */ - STMT_TRY = 6, /* try statement */ - STMT_CATCH = 7, /* catch block */ - STMT_FINALLY = 8, /* finally statement */ - STMT_SUBROUTINE = 9, /* gosub-target subroutine body */ - STMT_DO_LOOP = 10, /* do/while loop statement */ - STMT_FOR_LOOP = 11, /* for loop statement */ - STMT_FOR_IN_LOOP = 12, /* for/in loop statement */ - STMT_WHILE_LOOP = 13 /* while loop statement */ -} JSStmtType; - -#define STMT_IS_LOOP(stmt) ((stmt)->type >= STMT_DO_LOOP) - -typedef struct JSStmtInfo JSStmtInfo; - -struct JSStmtInfo { - JSStmtType type; /* statement type */ - ptrdiff_t update; /* loop update offset (top if none) */ - ptrdiff_t breaks; /* offset of last break in loop */ - ptrdiff_t continues; /* offset of last continue in loop */ - ptrdiff_t gosub; /* offset of last GOSUB for this finally */ - ptrdiff_t catchJump; /* offset of last end-of-catch jump */ - JSAtom *label; /* name of LABEL or CATCH var */ - JSStmtInfo *down; /* info for enclosing statement */ -}; - -#define SET_STATEMENT_TOP(stmt, top) \ - ((stmt)->update = (top), (stmt)->breaks = \ - (stmt)->continues = (stmt)->catchJump = (stmt)->gosub = (-1)) - -struct JSTreeContext { /* tree context for semantic checks */ - uint16 flags; /* statement state flags, see below */ - uint16 numGlobalVars; /* max. no. of global variables/regexps */ - uint32 tryCount; /* total count of try statements parsed */ - uint32 globalUses; /* optimizable global var uses in total */ - uint32 loopyGlobalUses;/* optimizable global var uses in loops */ - JSStmtInfo *topStmt; /* top of statement info stack */ - JSAtomList decls; /* function, const, and var declarations */ - JSParseNode *nodeList; /* list of recyclable parse-node structs */ -}; - -#define TCF_COMPILING 0x01 /* generating bytecode; this tc is a cg */ -#define TCF_IN_FUNCTION 0x02 /* parsing inside function body */ -#define TCF_RETURN_EXPR 0x04 /* function has 'return expr;' */ -#define TCF_RETURN_VOID 0x08 /* function has 'return;' */ -#define TCF_IN_FOR_INIT 0x10 /* parsing init expr of for; exclude 'in' */ -#define TCF_FUN_CLOSURE_VS_VAR 0x20 /* function and var with same name */ -#define TCF_FUN_USES_NONLOCALS 0x40 /* function refers to non-local names */ -#define TCF_FUN_HEAVYWEIGHT 0x80 /* function needs Call object per call */ -#define TCF_FUN_FLAGS 0xE0 /* flags to propagate from FunctionBody */ -#define TCF_HAS_DEFXMLNS 0x100 /* default xml namespace = ...; parsed */ - -#define TREE_CONTEXT_INIT(tc) \ - ((tc)->flags = (tc)->numGlobalVars = 0, \ - (tc)->tryCount = (tc)->globalUses = (tc)->loopyGlobalUses = 0, \ - (tc)->topStmt = NULL, ATOM_LIST_INIT(&(tc)->decls), \ - (tc)->nodeList = NULL) - -#define TREE_CONTEXT_FINISH(tc) \ - ((void)0) - -/* - * Span-dependent instructions are jumps whose span (from the jump bytecode to - * the jump target) may require 2 or 4 bytes of immediate operand. - */ -typedef struct JSSpanDep JSSpanDep; -typedef struct JSJumpTarget JSJumpTarget; - -struct JSSpanDep { - ptrdiff_t top; /* offset of first bytecode in an opcode */ - ptrdiff_t offset; /* offset - 1 within opcode of jump operand */ - ptrdiff_t before; /* original offset - 1 of jump operand */ - JSJumpTarget *target; /* tagged target pointer or backpatch delta */ -}; - -/* - * Jump targets are stored in an AVL tree, for O(log(n)) lookup with targets - * sorted by offset from left to right, so that targets after a span-dependent - * instruction whose jump offset operand must be extended can be found quickly - * and adjusted upward (toward higher offsets). - */ -struct JSJumpTarget { - ptrdiff_t offset; /* offset of span-dependent jump target */ - int balance; /* AVL tree balance number */ - JSJumpTarget *kids[2]; /* left and right AVL tree child pointers */ -}; - -#define JT_LEFT 0 -#define JT_RIGHT 1 -#define JT_OTHER_DIR(dir) (1 - (dir)) -#define JT_IMBALANCE(dir) (((dir) << 1) - 1) -#define JT_DIR(imbalance) (((imbalance) + 1) >> 1) - -/* - * Backpatch deltas are encoded in JSSpanDep.target if JT_TAG_BIT is clear, - * so we can maintain backpatch chains when using span dependency records to - * hold jump offsets that overflow 16 bits. - */ -#define JT_TAG_BIT ((jsword) 1) -#define JT_UNTAG_SHIFT 1 -#define JT_SET_TAG(jt) ((JSJumpTarget *)((jsword)(jt) | JT_TAG_BIT)) -#define JT_CLR_TAG(jt) ((JSJumpTarget *)((jsword)(jt) & ~JT_TAG_BIT)) -#define JT_HAS_TAG(jt) ((jsword)(jt) & JT_TAG_BIT) - -#define BITS_PER_PTRDIFF (sizeof(ptrdiff_t) * JS_BITS_PER_BYTE) -#define BITS_PER_BPDELTA (BITS_PER_PTRDIFF - 1 - JT_UNTAG_SHIFT) -#define BPDELTA_MAX (((ptrdiff_t)1 << BITS_PER_BPDELTA) - 1) -#define BPDELTA_TO_JT(bp) ((JSJumpTarget *)((bp) << JT_UNTAG_SHIFT)) -#define JT_TO_BPDELTA(jt) ((ptrdiff_t)((jsword)(jt) >> JT_UNTAG_SHIFT)) - -#define SD_SET_TARGET(sd,jt) ((sd)->target = JT_SET_TAG(jt)) -#define SD_GET_TARGET(sd) (JS_ASSERT(JT_HAS_TAG((sd)->target)), \ - JT_CLR_TAG((sd)->target)) -#define SD_SET_BPDELTA(sd,bp) ((sd)->target = BPDELTA_TO_JT(bp)) -#define SD_GET_BPDELTA(sd) (JS_ASSERT(!JT_HAS_TAG((sd)->target)), \ - JT_TO_BPDELTA((sd)->target)) - -/* Avoid asserting twice by expanding SD_GET_TARGET in the "then" clause. */ -#define SD_SPAN(sd,pivot) (SD_GET_TARGET(sd) \ - ? JT_CLR_TAG((sd)->target)->offset - (pivot) \ - : 0) - -struct JSCodeGenerator { - JSTreeContext treeContext; /* base state: statement info stack, etc. */ - - JSArenaPool *codePool; /* pointer to thread code arena pool */ - JSArenaPool *notePool; /* pointer to thread srcnote arena pool */ - void *codeMark; /* low watermark in cg->codePool */ - void *noteMark; /* low watermark in cg->notePool */ - void *tempMark; /* low watermark in cx->tempPool */ - - struct { - jsbytecode *base; /* base of JS bytecode vector */ - jsbytecode *limit; /* one byte beyond end of bytecode */ - jsbytecode *next; /* pointer to next free bytecode */ - jssrcnote *notes; /* source notes, see below */ - uintN noteCount; /* number of source notes so far */ - uintN noteMask; /* growth increment for notes */ - ptrdiff_t lastNoteOffset; /* code offset for last source note */ - uintN currentLine; /* line number for tree-based srcnote gen */ - } prolog, main, *current; - - const char *filename; /* null or weak link to source filename */ - uintN firstLine; /* first line, for js_NewScriptFromCG */ - JSPrincipals *principals; /* principals for constant folding eval */ - JSAtomList atomList; /* literals indexed for mapping */ - - intN stackDepth; /* current stack depth in script frame */ - uintN maxStackDepth; /* maximum stack depth so far */ - - JSTryNote *tryBase; /* first exception handling note */ - JSTryNote *tryNext; /* next available note */ - size_t tryNoteSpace; /* # of bytes allocated at tryBase */ - - JSSpanDep *spanDeps; /* span dependent instruction records */ - JSJumpTarget *jumpTargets; /* AVL tree of jump target offsets */ - JSJumpTarget *jtFreeList; /* JT_LEFT-linked list of free structs */ - uintN numSpanDeps; /* number of span dependencies */ - uintN numJumpTargets; /* number of jump targets */ - ptrdiff_t spanDepTodo; /* offset from main.base of potentially - unoptimized spandeps */ - - uintN emitLevel; /* js_EmitTree recursion level */ - JSAtomList constList; /* compile time constants */ - JSCodeGenerator *parent; /* Enclosing function or global context */ -}; - -#define CG_BASE(cg) ((cg)->current->base) -#define CG_LIMIT(cg) ((cg)->current->limit) -#define CG_NEXT(cg) ((cg)->current->next) -#define CG_CODE(cg,offset) (CG_BASE(cg) + (offset)) -#define CG_OFFSET(cg) PTRDIFF(CG_NEXT(cg), CG_BASE(cg), jsbytecode) - -#define CG_NOTES(cg) ((cg)->current->notes) -#define CG_NOTE_COUNT(cg) ((cg)->current->noteCount) -#define CG_NOTE_MASK(cg) ((cg)->current->noteMask) -#define CG_LAST_NOTE_OFFSET(cg) ((cg)->current->lastNoteOffset) -#define CG_CURRENT_LINE(cg) ((cg)->current->currentLine) - -#define CG_PROLOG_BASE(cg) ((cg)->prolog.base) -#define CG_PROLOG_LIMIT(cg) ((cg)->prolog.limit) -#define CG_PROLOG_NEXT(cg) ((cg)->prolog.next) -#define CG_PROLOG_CODE(cg,poff) (CG_PROLOG_BASE(cg) + (poff)) -#define CG_PROLOG_OFFSET(cg) PTRDIFF(CG_PROLOG_NEXT(cg), CG_PROLOG_BASE(cg),\ - jsbytecode) - -#define CG_SWITCH_TO_MAIN(cg) ((cg)->current = &(cg)->main) -#define CG_SWITCH_TO_PROLOG(cg) ((cg)->current = &(cg)->prolog) - -/* - * Initialize cg to allocate bytecode space from codePool, source note space - * from notePool, and all other arena-allocated temporaries from cx->tempPool. - * Return true on success. Report an error and return false if the initial - * code segment can't be allocated. - */ -extern JS_FRIEND_API(JSBool) -js_InitCodeGenerator(JSContext *cx, JSCodeGenerator *cg, - JSArenaPool *codePool, JSArenaPool *notePool, - const char *filename, uintN lineno, - JSPrincipals *principals); - -/* - * Release cg->codePool, cg->notePool, and cx->tempPool to marks set by - * js_InitCodeGenerator. Note that cgs are magic: they own the arena pool - * "tops-of-stack" space above their codeMark, noteMark, and tempMark points. - * This means you cannot alloc from tempPool and save the pointer beyond the - * next JS_FinishCodeGenerator. - */ -extern JS_FRIEND_API(void) -js_FinishCodeGenerator(JSContext *cx, JSCodeGenerator *cg); - -/* - * Emit one bytecode. - */ -extern ptrdiff_t -js_Emit1(JSContext *cx, JSCodeGenerator *cg, JSOp op); - -/* - * Emit two bytecodes, an opcode (op) with a byte of immediate operand (op1). - */ -extern ptrdiff_t -js_Emit2(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1); - -/* - * Emit three bytecodes, an opcode with two bytes of immediate operands. - */ -extern ptrdiff_t -js_Emit3(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1, - jsbytecode op2); - -/* - * Emit (1 + extra) bytecodes, for N bytes of op and its immediate operand. - */ -extern ptrdiff_t -js_EmitN(JSContext *cx, JSCodeGenerator *cg, JSOp op, size_t extra); - -/* - * Unsafe macro to call js_SetJumpOffset and return false if it does. - */ -#define CHECK_AND_SET_JUMP_OFFSET(cx,cg,pc,off) \ - JS_BEGIN_MACRO \ - if (!js_SetJumpOffset(cx, cg, pc, off)) \ - return JS_FALSE; \ - JS_END_MACRO - -#define CHECK_AND_SET_JUMP_OFFSET_AT(cx,cg,off) \ - CHECK_AND_SET_JUMP_OFFSET(cx, cg, CG_CODE(cg,off), CG_OFFSET(cg) - (off)) - -extern JSBool -js_SetJumpOffset(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc, - ptrdiff_t off); - -/* Test whether we're in a with statement. */ -extern JSBool -js_InWithStatement(JSTreeContext *tc); - -/* Test whether we're in a catch block with exception named by atom. */ -extern JSBool -js_InCatchBlock(JSTreeContext *tc, JSAtom *atom); - -/* - * Push the C-stack-allocated struct at stmt onto the stmtInfo stack. - */ -extern void -js_PushStatement(JSTreeContext *tc, JSStmtInfo *stmt, JSStmtType type, - ptrdiff_t top); - -/* - * Pop tc->topStmt. If the top JSStmtInfo struct is not stack-allocated, it - * is up to the caller to free it. - */ -extern void -js_PopStatement(JSTreeContext *tc); - -/* - * Like js_PopStatement(&cg->treeContext), also patch breaks and continues. - * May fail if a jump offset overflows. - */ -extern JSBool -js_PopStatementCG(JSContext *cx, JSCodeGenerator *cg); - -/* - * Define and lookup a primitive jsval associated with the const named by atom. - * js_DefineCompileTimeConstant analyzes the constant-folded initializer at pn - * and saves the const's value in cg->constList, if it can be used at compile - * time. It returns true unless an error occurred. - * - * If the initializer's value could not be saved, js_LookupCompileTimeConstant - * calls will return the undefined value. js_LookupCompileTimeConstant tries - * to find a const value memorized for atom, returning true with *vp set to a - * value other than undefined if the constant was found, true with *vp set to - * JSVAL_VOID if not found, and false on error. - */ -extern JSBool -js_DefineCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom, - JSParseNode *pn); - -extern JSBool -js_LookupCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom, - jsval *vp); - -/* - * Emit code into cg for the tree rooted at pn. - */ -extern JSBool -js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn); - -/* - * Emit code into cg for the tree rooted at body, then create a persistent - * script for fun from cg. - */ -extern JSBool -js_EmitFunctionBody(JSContext *cx, JSCodeGenerator *cg, JSParseNode *body, - JSFunction *fun); - -/* - * Source notes generated along with bytecode for decompiling and debugging. - * A source note is a uint8 with 5 bits of type and 3 of offset from the pc of - * the previous note. If 3 bits of offset aren't enough, extended delta notes - * (SRC_XDELTA) consisting of 2 set high order bits followed by 6 offset bits - * are emitted before the next note. Some notes have operand offsets encoded - * immediately after them, in note bytes or byte-triples. - * - * Source Note Extended Delta - * +7-6-5-4-3+2-1-0+ +7-6-5+4-3-2-1-0+ - * |note-type|delta| |1 1| ext-delta | - * +---------+-----+ +---+-----------+ - * - * At most one "gettable" note (i.e., a note of type other than SRC_NEWLINE, - * SRC_SETLINE, and SRC_XDELTA) applies to a given bytecode. - * - * NB: the js_SrcNoteSpec array in jsemit.c is indexed by this enum, so its - * initializers need to match the order here. - */ -typedef enum JSSrcNoteType { - SRC_NULL = 0, /* terminates a note vector */ - SRC_IF = 1, /* JSOP_IFEQ bytecode is from an if-then */ - SRC_IF_ELSE = 2, /* JSOP_IFEQ bytecode is from an if-then-else */ - SRC_WHILE = 3, /* JSOP_IFEQ is from a while loop */ - SRC_FOR = 4, /* JSOP_NOP or JSOP_POP in for loop head */ - SRC_CONTINUE = 5, /* JSOP_GOTO is a continue, not a break; - also used on JSOP_ENDINIT if extra comma - at end of array literal: [1,2,,] */ - SRC_VAR = 6, /* JSOP_NAME/SETNAME/FORNAME in a var decl */ - SRC_PCDELTA = 7, /* distance from comma-operator to next POP, - or from CONDSWITCH to first CASE opcode -- - or SRC_PCBASE variant for obj.function::foo - gets and sets */ - SRC_ASSIGNOP = 8, /* += or another assign-op follows */ - SRC_COND = 9, /* JSOP_IFEQ is from conditional ?: operator */ - SRC_RESERVED0 = 10, /* reserved for future use */ - SRC_HIDDEN = 11, /* opcode shouldn't be decompiled */ - SRC_PCBASE = 12, /* distance back from annotated get- or setprop - op to first obj.prop.subprop bytecode */ - SRC_LABEL = 13, /* JSOP_NOP for label: with atomid immediate */ - SRC_LABELBRACE = 14, /* JSOP_NOP for label: {...} begin brace */ - SRC_ENDBRACE = 15, /* JSOP_NOP for label: {...} end brace */ - SRC_BREAK2LABEL = 16, /* JSOP_GOTO for 'break label' with atomid */ - SRC_CONT2LABEL = 17, /* JSOP_GOTO for 'continue label' with atomid */ - SRC_SWITCH = 18, /* JSOP_*SWITCH with offset to end of switch, - 2nd off to first JSOP_CASE if condswitch */ - SRC_FUNCDEF = 19, /* JSOP_NOP for function f() with atomid */ - SRC_CATCH = 20, /* catch block has guard */ - SRC_CONST = 21, /* JSOP_SETCONST in a const decl */ - SRC_NEWLINE = 22, /* bytecode follows a source newline */ - SRC_SETLINE = 23, /* a file-absolute source line number note */ - SRC_XDELTA = 24 /* 24-31 are for extended delta notes */ -} JSSrcNoteType; - -#define SN_TYPE_BITS 5 -#define SN_DELTA_BITS 3 -#define SN_XDELTA_BITS 6 -#define SN_TYPE_MASK (JS_BITMASK(SN_TYPE_BITS) << SN_DELTA_BITS) -#define SN_DELTA_MASK ((ptrdiff_t)JS_BITMASK(SN_DELTA_BITS)) -#define SN_XDELTA_MASK ((ptrdiff_t)JS_BITMASK(SN_XDELTA_BITS)) - -#define SN_MAKE_NOTE(sn,t,d) (*(sn) = (jssrcnote) \ - (((t) << SN_DELTA_BITS) \ - | ((d) & SN_DELTA_MASK))) -#define SN_MAKE_XDELTA(sn,d) (*(sn) = (jssrcnote) \ - ((SRC_XDELTA << SN_DELTA_BITS) \ - | ((d) & SN_XDELTA_MASK))) - -#define SN_IS_XDELTA(sn) ((*(sn) >> SN_DELTA_BITS) >= SRC_XDELTA) -#define SN_TYPE(sn) (SN_IS_XDELTA(sn) ? SRC_XDELTA \ - : *(sn) >> SN_DELTA_BITS) -#define SN_SET_TYPE(sn,type) SN_MAKE_NOTE(sn, type, SN_DELTA(sn)) -#define SN_IS_GETTABLE(sn) (SN_TYPE(sn) < SRC_NEWLINE) - -#define SN_DELTA(sn) ((ptrdiff_t)(SN_IS_XDELTA(sn) \ - ? *(sn) & SN_XDELTA_MASK \ - : *(sn) & SN_DELTA_MASK)) -#define SN_SET_DELTA(sn,delta) (SN_IS_XDELTA(sn) \ - ? SN_MAKE_XDELTA(sn, delta) \ - : SN_MAKE_NOTE(sn, SN_TYPE(sn), delta)) - -#define SN_DELTA_LIMIT ((ptrdiff_t)JS_BIT(SN_DELTA_BITS)) -#define SN_XDELTA_LIMIT ((ptrdiff_t)JS_BIT(SN_XDELTA_BITS)) - -/* - * Offset fields follow certain notes and are frequency-encoded: an offset in - * [0,0x7f] consumes one byte, an offset in [0x80,0x7fffff] takes three, and - * the high bit of the first byte is set. - */ -#define SN_3BYTE_OFFSET_FLAG 0x80 -#define SN_3BYTE_OFFSET_MASK 0x7f - -typedef struct JSSrcNoteSpec { - const char *name; /* name for disassembly/debugging output */ - uint8 arity; /* number of offset operands */ - uint8 offsetBias; /* bias of offset(s) from annotated pc */ - int8 isSpanDep; /* 1 or -1 if offsets could span extended ops, - 0 otherwise; sign tells span direction */ -} JSSrcNoteSpec; - -extern JS_FRIEND_DATA(JSSrcNoteSpec) js_SrcNoteSpec[]; -extern JS_FRIEND_API(uintN) js_SrcNoteLength(jssrcnote *sn); - -#define SN_LENGTH(sn) ((js_SrcNoteSpec[SN_TYPE(sn)].arity == 0) ? 1 \ - : js_SrcNoteLength(sn)) -#define SN_NEXT(sn) ((sn) + SN_LENGTH(sn)) - -/* A source note array is terminated by an all-zero element. */ -#define SN_MAKE_TERMINATOR(sn) (*(sn) = SRC_NULL) -#define SN_IS_TERMINATOR(sn) (*(sn) == SRC_NULL) - -/* - * Append a new source note of the given type (and therefore size) to cg's - * notes dynamic array, updating cg->noteCount. Return the new note's index - * within the array pointed at by cg->current->notes. Return -1 if out of - * memory. - */ -extern intN -js_NewSrcNote(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type); - -extern intN -js_NewSrcNote2(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type, - ptrdiff_t offset); - -extern intN -js_NewSrcNote3(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type, - ptrdiff_t offset1, ptrdiff_t offset2); - -/* - * NB: this function can add at most one extra extended delta note. - */ -extern jssrcnote * -js_AddToSrcNoteDelta(JSContext *cx, JSCodeGenerator *cg, jssrcnote *sn, - ptrdiff_t delta); - -/* - * Get and set the offset operand identified by which (0 for the first, etc.). - */ -extern JS_FRIEND_API(ptrdiff_t) -js_GetSrcNoteOffset(jssrcnote *sn, uintN which); - -extern JSBool -js_SetSrcNoteOffset(JSContext *cx, JSCodeGenerator *cg, uintN index, - uintN which, ptrdiff_t offset); - -/* - * Finish taking source notes in cx's notePool, copying final notes to the new - * stable store allocated by the caller and passed in via notes. Return false - * on malloc failure, which means this function reported an error. - * - * To compute the number of jssrcnotes to allocate and pass in via notes, use - * the CG_COUNT_FINAL_SRCNOTES macro. This macro knows a lot about details of - * js_FinishTakingSrcNotes, SO DON'T CHANGE jsemit.c's js_FinishTakingSrcNotes - * FUNCTION WITHOUT CHECKING WHETHER THIS MACRO NEEDS CORRESPONDING CHANGES! - */ -#define CG_COUNT_FINAL_SRCNOTES(cg, cnt) \ - JS_BEGIN_MACRO \ - ptrdiff_t diff_ = CG_PROLOG_OFFSET(cg) - (cg)->prolog.lastNoteOffset; \ - cnt = (cg)->prolog.noteCount + (cg)->main.noteCount + 1; \ - if ((cg)->prolog.noteCount && \ - (cg)->prolog.currentLine != (cg)->firstLine) { \ - if (diff_ > SN_DELTA_MASK) \ - cnt += JS_HOWMANY(diff_ - SN_DELTA_MASK, SN_XDELTA_MASK); \ - cnt += 2 + (((cg)->firstLine > SN_3BYTE_OFFSET_MASK) << 1); \ - } else if (diff_ > 0) { \ - if (cg->main.noteCount) { \ - jssrcnote *sn_ = (cg)->main.notes; \ - diff_ -= SN_IS_XDELTA(sn_) \ - ? SN_XDELTA_MASK - (*sn_ & SN_XDELTA_MASK) \ - : SN_DELTA_MASK - (*sn_ & SN_DELTA_MASK); \ - } \ - if (diff_ > 0) \ - cnt += JS_HOWMANY(diff_, SN_XDELTA_MASK); \ - } \ - JS_END_MACRO - -extern JSBool -js_FinishTakingSrcNotes(JSContext *cx, JSCodeGenerator *cg, jssrcnote *notes); - -/* - * Allocate cg->treeContext.tryCount notes (plus one for the end sentinel) - * from cx->tempPool and set up cg->tryBase/tryNext for exactly tryCount - * js_NewTryNote calls. The storage is freed by js_FinishCodeGenerator. - */ -extern JSBool -js_AllocTryNotes(JSContext *cx, JSCodeGenerator *cg); - -/* - * Grab the next trynote slot in cg, filling it in appropriately. - */ -extern JSTryNote * -js_NewTryNote(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t start, - ptrdiff_t end, ptrdiff_t catchStart); - -/* - * Finish generating exception information into the space at notes. As with - * js_FinishTakingSrcNotes, the caller must use CG_COUNT_FINAL_TRYNOTES(cg) to - * preallocate enough space in a JSTryNote[] to pass as the notes parameter of - * js_FinishTakingTryNotes. - */ -#define CG_COUNT_FINAL_TRYNOTES(cg, cnt) \ - JS_BEGIN_MACRO \ - cnt = ((cg)->tryNext > (cg)->tryBase) \ - ? PTRDIFF(cg->tryNext, cg->tryBase, JSTryNote) + 1 \ - : 0; \ - JS_END_MACRO - -extern void -js_FinishTakingTryNotes(JSContext *cx, JSCodeGenerator *cg, JSTryNote *notes); - -JS_END_EXTERN_C - -#endif /* jsemit_h___ */ diff --git a/lib/javascript/jsexn.c b/lib/javascript/jsexn.c deleted file mode 100644 index c637a563..00000000 --- a/lib/javascript/jsexn.c +++ /dev/null @@ -1,1186 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sw=4 et tw=80: - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JS standard exception implementation. - */ - -#include "jsstddef.h" -#include -#include -#include "jstypes.h" -#include "jsbit.h" -#include "jsutil.h" /* Added by JSIFY */ -#include "jsprf.h" -#include "jsapi.h" -#include "jscntxt.h" -#include "jsconfig.h" -#include "jsdbgapi.h" -#include "jsexn.h" -#include "jsfun.h" -#include "jsinterp.h" -#include "jsnum.h" -#include "jsopcode.h" -#include "jsscript.h" - -#if JS_HAS_ERROR_EXCEPTIONS -#if !JS_HAS_EXCEPTIONS -# error "JS_HAS_EXCEPTIONS must be defined to use JS_HAS_ERROR_EXCEPTIONS" -#endif - -/* XXX consider adding rt->atomState.messageAtom */ -static char js_message_str[] = "message"; -static char js_filename_str[] = "fileName"; -static char js_lineno_str[] = "lineNumber"; -static char js_stack_str[] = "stack"; - -/* Forward declarations for ExceptionClass's initializer. */ -static JSBool -Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); - -static void -exn_finalize(JSContext *cx, JSObject *obj); - -static JSClass ExceptionClass = { - "Error", - JSCLASS_HAS_PRIVATE, - JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, exn_finalize, - NULL, NULL, NULL, Exception, - NULL, NULL, NULL, 0 -}; - -/* - * A copy of the JSErrorReport originally generated. - */ -typedef struct JSExnPrivate { - JSErrorReport *errorReport; -} JSExnPrivate; - -static JSErrorReport * -CopyErrorReport(JSContext *cx, JSErrorReport *report) -{ - /* - * We use a single malloc block to make a deep copy of JSErrorReport with - * the following layout: - * JSErrorReport - * array of copies of report->messageArgs - * jschar array with characters for all messageArgs - * jschar array with characters for ucmessage - * jschar array with characters for uclinebuf and uctokenptr - * char array with characters for linebuf and tokenptr - * char array with characters for filename - * Such layout does not need any extra alignment padding. - */ - size_t filenameSize; - size_t linebufSize; - size_t uclinebufSize; - size_t ucmessageSize; - size_t i, argsArraySize, argsCopySize, argSize; - size_t mallocSize; - JSErrorReport *copy; - uint8 *cursor; - -#define JS_CHARS_SIZE(jschars) ((js_strlen(jschars) + 1) * sizeof(jschar)) - - filenameSize = report->filename ? strlen(report->filename) + 1 : 0; - linebufSize = report->linebuf ? strlen(report->linebuf) + 1 : 0; - uclinebufSize = report->uclinebuf ? JS_CHARS_SIZE(report->uclinebuf) : 0; - ucmessageSize = 0; - argsArraySize = 0; - argsCopySize = 0; - if (report->ucmessage) { - ucmessageSize = JS_CHARS_SIZE(report->ucmessage); - if (report->messageArgs) { - for (i = 0; report->messageArgs[i]; ++i) - argsCopySize += JS_CHARS_SIZE(report->messageArgs[i]); - - /* Non-null messageArgs should have at least one non-null arg. */ - JS_ASSERT(i != 0); - argsArraySize = (i + 1) * sizeof(const jschar *); - } - } - - /* - * The mallocSize can not overflow since it represents the sum of the - * sizes of already allocated objects. - */ - mallocSize = sizeof(JSErrorReport) + argsArraySize + argsCopySize + - ucmessageSize + uclinebufSize + linebufSize + filenameSize; - cursor = (uint8 *)JS_malloc(cx, mallocSize); - if (!cursor) - return NULL; - - copy = (JSErrorReport *)cursor; - memset(cursor, 0, sizeof(JSErrorReport)); - cursor += sizeof(JSErrorReport); - - if (argsArraySize != 0) { - copy->messageArgs = (const jschar **)cursor; - cursor += argsArraySize; - for (i = 0; report->messageArgs[i]; ++i) { - copy->messageArgs[i] = (const jschar *)cursor; - argSize = JS_CHARS_SIZE(report->messageArgs[i]); - memcpy(cursor, report->messageArgs[i], argSize); - cursor += argSize; - } - copy->messageArgs[i] = NULL; - JS_ASSERT(cursor == (uint8 *)copy->messageArgs[0] + argsCopySize); - } - - if (report->ucmessage) { - copy->ucmessage = (const jschar *)cursor; - memcpy(cursor, report->ucmessage, ucmessageSize); - cursor += ucmessageSize; - } - - if (report->uclinebuf) { - copy->uclinebuf = (const jschar *)cursor; - memcpy(cursor, report->uclinebuf, uclinebufSize); - cursor += uclinebufSize; - if (report->uctokenptr) { - copy->uctokenptr = copy->uclinebuf + (report->uctokenptr - - report->uclinebuf); - } - } - - if (report->linebuf) { - copy->linebuf = (const char *)cursor; - memcpy(cursor, report->linebuf, linebufSize); - cursor += linebufSize; - if (report->tokenptr) { - copy->tokenptr = copy->linebuf + (report->tokenptr - - report->linebuf); - } - } - - if (report->filename) { - copy->filename = (const char *)cursor; - memcpy(cursor, report->filename, filenameSize); - } - JS_ASSERT(cursor + filenameSize == (uint8 *)copy + mallocSize); - - /* Copy non-pointer members. */ - copy->lineno = report->lineno; - copy->errorNumber = report->errorNumber; - - /* Note that this is before it gets flagged with JSREPORT_EXCEPTION */ - copy->flags = report->flags; - -#undef JS_CHARS_SIZE - return copy; -} - -/* - * Copy everything interesting about an error into allocated memory. - */ -static JSExnPrivate * -exn_newPrivate(JSContext *cx, JSErrorReport *report) -{ - JSExnPrivate *newPrivate; - - newPrivate = (JSExnPrivate *)JS_malloc(cx, sizeof (JSExnPrivate)); - if (!newPrivate) - return NULL; - newPrivate->errorReport = CopyErrorReport(cx, report); - if (!newPrivate->errorReport) { - JS_free(cx, newPrivate); - return NULL; - } - return newPrivate; -} - -static void -exn_finalize(JSContext *cx, JSObject *obj) -{ - JSExnPrivate *privateData; - jsval privateValue; - - privateValue = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE); - - if (!JSVAL_IS_VOID(privateValue)) { - privateData = (JSExnPrivate*) JSVAL_TO_PRIVATE(privateValue); - if (privateData) { - if (privateData->errorReport) - JS_free(cx, privateData->errorReport); - JS_free(cx, privateData); - } - } -} - -JSErrorReport * -js_ErrorFromException(JSContext *cx, jsval exn) -{ - JSObject *obj; - JSExnPrivate *privateData; - jsval privateValue; - - if (JSVAL_IS_PRIMITIVE(exn)) - return NULL; - obj = JSVAL_TO_OBJECT(exn); - if (OBJ_GET_CLASS(cx, obj) != &ExceptionClass) - return NULL; - privateValue = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE); - if (JSVAL_IS_VOID(privateValue)) - return NULL; - privateData = (JSExnPrivate*) JSVAL_TO_PRIVATE(privateValue); - if (!privateData) - return NULL; - - JS_ASSERT(privateData->errorReport); - return privateData->errorReport; -} - -/* - * This must be kept in synch with the exceptions array below. - * XXX use a jsexn.tbl file a la jsopcode.tbl - */ -typedef enum JSExnType { - JSEXN_NONE = -1, - JSEXN_ERR, - JSEXN_INTERNALERR, - JSEXN_EVALERR, - JSEXN_RANGEERR, - JSEXN_REFERENCEERR, - JSEXN_SYNTAXERR, - JSEXN_TYPEERR, - JSEXN_URIERR, - JSEXN_LIMIT -} JSExnType; - -struct JSExnSpec { - int protoIndex; - const char *name; - JSNative native; -}; - -/* - * All *Error constructors share the same JSClass, ExceptionClass. But each - * constructor function for an *Error class must have a distinct native 'call' - * function pointer, in order for instanceof to work properly across multiple - * standard class sets. See jsfun.c:fun_hasInstance. - */ -#define MAKE_EXCEPTION_CTOR(name) \ -const char js_##name##_str[] = #name; \ -static JSBool \ -name(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) \ -{ \ - return Exception(cx, obj, argc, argv, rval); \ -} - -MAKE_EXCEPTION_CTOR(Error) -MAKE_EXCEPTION_CTOR(InternalError) -MAKE_EXCEPTION_CTOR(EvalError) -MAKE_EXCEPTION_CTOR(RangeError) -MAKE_EXCEPTION_CTOR(ReferenceError) -MAKE_EXCEPTION_CTOR(SyntaxError) -MAKE_EXCEPTION_CTOR(TypeError) -MAKE_EXCEPTION_CTOR(URIError) - -#undef MAKE_EXCEPTION_CTOR - -static struct JSExnSpec exceptions[] = { - { JSEXN_NONE, js_Error_str, Error }, - { JSEXN_ERR, js_InternalError_str, InternalError }, - { JSEXN_ERR, js_EvalError_str, EvalError }, - { JSEXN_ERR, js_RangeError_str, RangeError }, - { JSEXN_ERR, js_ReferenceError_str, ReferenceError }, - { JSEXN_ERR, js_SyntaxError_str, SyntaxError }, - { JSEXN_ERR, js_TypeError_str, TypeError }, - { JSEXN_ERR, js_URIError_str, URIError }, - {0,NULL,NULL} -}; - -static JSBool -InitExceptionObject(JSContext *cx, JSObject *obj, JSString *message, - JSString *filename, uintN lineno) -{ - JSCheckAccessOp checkAccess; - JSErrorReporter older; - JSExceptionState *state; - jschar *stackbuf; - size_t stacklen, stackmax; - JSStackFrame *fp; - jsval callerid, v; - JSBool ok; - JSString *argsrc, *stack; - uintN i, ulineno; - const char *cp; - char ulnbuf[11]; - - if (!JS_DefineProperty(cx, obj, js_message_str, STRING_TO_JSVAL(message), - NULL, NULL, JSPROP_ENUMERATE)) { - return JS_FALSE; - } - - if (!JS_DefineProperty(cx, obj, js_filename_str, - STRING_TO_JSVAL(filename), - NULL, NULL, JSPROP_ENUMERATE)) { - return JS_FALSE; - } - - if (!JS_DefineProperty(cx, obj, js_lineno_str, - INT_TO_JSVAL(lineno), - NULL, NULL, JSPROP_ENUMERATE)) { - return JS_FALSE; - } - - /* - * Set the 'stack' property. - * - * First, set aside any error reporter for cx and save its exception state - * so we can suppress any checkAccess failures. Such failures should stop - * the backtrace procedure, not result in a failure of this constructor. - */ - checkAccess = cx->runtime->checkObjectAccess; - if (checkAccess) { - older = JS_SetErrorReporter(cx, NULL); - state = JS_SaveExceptionState(cx); - } -#ifdef __GNUC__ /* suppress bogus gcc warnings */ - else { - older = NULL; - state = NULL; - } -#endif - callerid = ATOM_KEY(cx->runtime->atomState.callerAtom); - - /* - * Prepare to allocate a jschar buffer at stackbuf, where stacklen indexes - * the next free jschar slot, and with room for at most stackmax non-null - * jschars. If stackbuf is non-null, it always contains an extra slot for - * the null terminator we'll store at the end, as a backstop. - * - * All early returns must goto done after this point, till the after-loop - * cleanup code has run! - */ - stackbuf = NULL; - stacklen = stackmax = 0; - ok = JS_TRUE; - -/* Limit the stackbuf length to a reasonable value to avoid overflow checks. */ -#define STACK_LENGTH_LIMIT JS_BIT(20) - -#define APPEND_CHAR_TO_STACK(c) \ - JS_BEGIN_MACRO \ - if (stacklen == stackmax) { \ - void *ptr_; \ - if (stackmax >= STACK_LENGTH_LIMIT) \ - goto done; \ - stackmax = stackmax ? 2 * stackmax : 64; \ - ptr_ = JS_realloc(cx, stackbuf, (stackmax+1) * sizeof(jschar)); \ - if (!ptr_) { \ - ok = JS_FALSE; \ - goto done; \ - } \ - stackbuf = ptr_; \ - } \ - stackbuf[stacklen++] = (c); \ - JS_END_MACRO - -#define APPEND_STRING_TO_STACK(str) \ - JS_BEGIN_MACRO \ - JSString *str_ = str; \ - size_t length_ = JSSTRING_LENGTH(str_); \ - if (length_ > stackmax - stacklen) { \ - void *ptr_; \ - if (stackmax >= STACK_LENGTH_LIMIT || \ - length_ >= STACK_LENGTH_LIMIT - stacklen) { \ - goto done; \ - } \ - stackmax = JS_BIT(JS_CeilingLog2(stacklen + length_)); \ - ptr_ = JS_realloc(cx, stackbuf, (stackmax+1) * sizeof(jschar)); \ - if (!ptr_) { \ - ok = JS_FALSE; \ - goto done; \ - } \ - stackbuf = ptr_; \ - } \ - js_strncpy(stackbuf + stacklen, JSSTRING_CHARS(str_), length_); \ - stacklen += length_; \ - JS_END_MACRO - - for (fp = cx->fp; fp; fp = fp->down) { - if (checkAccess) { - v = (fp->fun && fp->argv) ? fp->argv[-2] : JSVAL_NULL; - if (!JSVAL_IS_PRIMITIVE(v)) { - ok = checkAccess(cx, JSVAL_TO_OBJECT(fp->argv[-2]), callerid, - JSACC_READ, &v /* ignored */); - if (!ok) { - ok = JS_TRUE; - break; - } - } - } - - if (fp->fun) { - if (fp->fun->atom) - APPEND_STRING_TO_STACK(ATOM_TO_STRING(fp->fun->atom)); - - APPEND_CHAR_TO_STACK('('); - for (i = 0; i < fp->argc; i++) { - /* Avoid toSource bloat and fallibility for object types. */ - v = fp->argv[i]; - if (JSVAL_IS_PRIMITIVE(v)) { - argsrc = js_ValueToSource(cx, v); - } else if (JSVAL_IS_FUNCTION(cx, v)) { - /* XXX Avoid function decompilation bloat for now. */ - argsrc = JS_GetFunctionId(JS_ValueToFunction(cx, v)); - if (!argsrc) - argsrc = js_ValueToSource(cx, v); - } else { - /* XXX Avoid toString on objects, it takes too long and - uses too much memory, for too many classes (see - Mozilla bug 166743). */ - char buf[100]; - JS_snprintf(buf, sizeof buf, "[object %s]", - OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(v))->name); - argsrc = JS_NewStringCopyZ(cx, buf); - } - if (!argsrc) { - ok = JS_FALSE; - goto done; - } - if (i > 0) - APPEND_CHAR_TO_STACK(','); - APPEND_STRING_TO_STACK(argsrc); - } - APPEND_CHAR_TO_STACK(')'); - } - - APPEND_CHAR_TO_STACK('@'); - if (fp->script && fp->script->filename) { - for (cp = fp->script->filename; *cp; cp++) - APPEND_CHAR_TO_STACK(*cp); - } - APPEND_CHAR_TO_STACK(':'); - if (fp->script && fp->pc) { - ulineno = js_PCToLineNumber(cx, fp->script, fp->pc); - JS_snprintf(ulnbuf, sizeof ulnbuf, "%u", ulineno); - for (cp = ulnbuf; *cp; cp++) - APPEND_CHAR_TO_STACK(*cp); - } else { - APPEND_CHAR_TO_STACK('0'); - } - APPEND_CHAR_TO_STACK('\n'); - } - -#undef APPEND_CHAR_TO_STACK -#undef APPEND_STRING_TO_STACK -#undef STACK_LENGTH_LIMIT - -done: - if (checkAccess) { - if (ok) - JS_RestoreExceptionState(cx, state); - else - JS_DropExceptionState(cx, state); - JS_SetErrorReporter(cx, older); - } - if (!ok) { - JS_free(cx, stackbuf); - return JS_FALSE; - } - - if (!stackbuf) { - stack = cx->runtime->emptyString; - } else { - /* NB: if stackbuf was allocated, it has room for the terminator. */ - JS_ASSERT(stacklen <= stackmax); - if (stacklen < stackmax) { - /* - * Realloc can fail when shrinking on some FreeBSD versions, so - * don't use JS_realloc here; simply let the oversized allocation - * be owned by the string in that rare case. - */ - void *shrunk = realloc(stackbuf, (stacklen+1) * sizeof(jschar)); - if (shrunk) - stackbuf = shrunk; - } - stackbuf[stacklen] = 0; - stack = js_NewString(cx, stackbuf, stacklen, 0); - if (!stack) { - JS_free(cx, stackbuf); - return JS_FALSE; - } - } - return JS_DefineProperty(cx, obj, js_stack_str, - STRING_TO_JSVAL(stack), - NULL, NULL, JSPROP_ENUMERATE); -} - -/* XXXbe Consolidate the ugly truth that we don't treat filename as UTF-8 - with these two functions. */ -static JSString * -FilenameToString(JSContext *cx, const char *filename) -{ - return JS_NewStringCopyZ(cx, filename); -} - -static const char * -StringToFilename(JSContext *cx, JSString *str) -{ - return JS_GetStringBytes(str); -} - -static JSBool -Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSBool ok; - uint32 lineno; - JSString *message, *filename; - JSStackFrame *fp; - - if (cx->creatingException) - return JS_FALSE; - cx->creatingException = JS_TRUE; - - if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) { - /* - * ECMA ed. 3, 15.11.1 requires Error, etc., to construct even when - * called as functions, without operator new. But as we do not give - * each constructor a distinct JSClass, whose .name member is used by - * js_NewObject to find the class prototype, we must get the class - * prototype ourselves. - */ - ok = OBJ_GET_PROPERTY(cx, JSVAL_TO_OBJECT(argv[-2]), - ATOM_TO_JSID(cx->runtime->atomState - .classPrototypeAtom), - rval); - if (!ok) - goto out; - obj = js_NewObject(cx, &ExceptionClass, JSVAL_TO_OBJECT(*rval), NULL); - if (!obj) { - ok = JS_FALSE; - goto out; - } - *rval = OBJECT_TO_JSVAL(obj); - } - - /* - * If it's a new object of class Exception, then null out the private - * data so that the finalizer doesn't attempt to free it. - */ - if (OBJ_GET_CLASS(cx, obj) == &ExceptionClass) - OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, JSVAL_VOID); - - /* Set the 'message' property. */ - if (argc != 0) { - message = js_ValueToString(cx, argv[0]); - if (!message) { - ok = JS_FALSE; - goto out; - } - argv[0] = STRING_TO_JSVAL(message); - } else { - message = cx->runtime->emptyString; - } - - /* Set the 'fileName' property. */ - if (argc > 1) { - filename = js_ValueToString(cx, argv[1]); - if (!filename) { - ok = JS_FALSE; - goto out; - } - argv[1] = STRING_TO_JSVAL(filename); - fp = NULL; - } else { - fp = JS_GetScriptedCaller(cx, NULL); - if (fp) { - filename = FilenameToString(cx, fp->script->filename); - if (!filename) { - ok = JS_FALSE; - goto out; - } - } else { - filename = cx->runtime->emptyString; - } - } - - /* Set the 'lineNumber' property. */ - if (argc > 2) { - ok = js_ValueToECMAUint32(cx, argv[2], &lineno); - if (!ok) - goto out; - } else { - if (!fp) - fp = JS_GetScriptedCaller(cx, NULL); - lineno = (fp && fp->pc) ? js_PCToLineNumber(cx, fp->script, fp->pc) : 0; - } - - ok = InitExceptionObject(cx, obj, message, filename, lineno); - -out: - cx->creatingException = JS_FALSE; - return ok; -} - -/* - * Convert to string. - * - * This method only uses JavaScript-modifiable properties name, message. It - * is left to the host to check for private data and report filename and line - * number information along with this message. - */ -static JSBool -exn_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsval v; - JSString *name, *message, *result; - jschar *chars, *cp; - size_t name_length, message_length, length; - - if (!OBJ_GET_PROPERTY(cx, obj, - ATOM_TO_JSID(cx->runtime->atomState.nameAtom), - &v)) { - return JS_FALSE; - } - name = JSVAL_IS_STRING(v) ? JSVAL_TO_STRING(v) : cx->runtime->emptyString; - *rval = STRING_TO_JSVAL(name); - - if (!JS_GetProperty(cx, obj, js_message_str, &v)) - return JS_FALSE; - message = JSVAL_IS_STRING(v) ? JSVAL_TO_STRING(v) - : cx->runtime->emptyString; - - if (JSSTRING_LENGTH(message) != 0) { - name_length = JSSTRING_LENGTH(name); - message_length = JSSTRING_LENGTH(message); - length = (name_length ? name_length + 2 : 0) + message_length; - cp = chars = (jschar*) JS_malloc(cx, (length + 1) * sizeof(jschar)); - if (!chars) - return JS_FALSE; - - if (name_length) { - js_strncpy(cp, JSSTRING_CHARS(name), name_length); - cp += name_length; - *cp++ = ':'; *cp++ = ' '; - } - js_strncpy(cp, JSSTRING_CHARS(message), message_length); - cp += message_length; - *cp = 0; - - result = js_NewString(cx, chars, length, 0); - if (!result) { - JS_free(cx, chars); - return JS_FALSE; - } - } else { - result = name; - } - - *rval = STRING_TO_JSVAL(result); - return JS_TRUE; -} - -#if JS_HAS_TOSOURCE -/* - * Return a string that may eval to something similar to the original object. - */ -static JSBool -exn_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsval *vp; - JSString *name, *message, *filename, *lineno_as_str, *result; - uint32 lineno; - size_t lineno_length, name_length, message_length, filename_length, length; - jschar *chars, *cp; - - vp = argv + argc; /* beginning of explicit local roots */ - - if (!OBJ_GET_PROPERTY(cx, obj, - ATOM_TO_JSID(cx->runtime->atomState.nameAtom), - rval)) { - return JS_FALSE; - } - name = js_ValueToString(cx, *rval); - if (!name) - return JS_FALSE; - *rval = STRING_TO_JSVAL(name); - - if (!JS_GetProperty(cx, obj, js_message_str, &vp[0]) || - !(message = js_ValueToSource(cx, vp[0]))) { - return JS_FALSE; - } - vp[0] = STRING_TO_JSVAL(message); - - if (!JS_GetProperty(cx, obj, js_filename_str, &vp[1]) || - !(filename = js_ValueToSource(cx, vp[1]))) { - return JS_FALSE; - } - vp[1] = STRING_TO_JSVAL(filename); - - if (!JS_GetProperty(cx, obj, js_lineno_str, &vp[2]) || - !js_ValueToECMAUint32 (cx, vp[2], &lineno)) { - return JS_FALSE; - } - - if (lineno != 0) { - lineno_as_str = js_ValueToString(cx, vp[2]); - if (!lineno_as_str) - return JS_FALSE; - lineno_length = JSSTRING_LENGTH(lineno_as_str); - } else { - lineno_as_str = NULL; - lineno_length = 0; - } - - /* Magic 8, for the characters in ``(new ())''. */ - name_length = JSSTRING_LENGTH(name); - message_length = JSSTRING_LENGTH(message); - length = 8 + name_length + message_length; - - filename_length = JSSTRING_LENGTH(filename); - if (filename_length != 0) { - /* append filename as ``, {filename}'' */ - length += 2 + filename_length; - if (lineno_as_str) { - /* append lineno as ``, {lineno_as_str}'' */ - length += 2 + lineno_length; - } - } else { - if (lineno_as_str) { - /* - * no filename, but have line number, - * need to append ``, "", {lineno_as_str}'' - */ - length += 6 + lineno_length; - } - } - - cp = chars = (jschar*) JS_malloc(cx, (length + 1) * sizeof(jschar)); - if (!chars) - return JS_FALSE; - - *cp++ = '('; *cp++ = 'n'; *cp++ = 'e'; *cp++ = 'w'; *cp++ = ' '; - js_strncpy(cp, JSSTRING_CHARS(name), name_length); - cp += name_length; - *cp++ = '('; - if (message_length != 0) { - js_strncpy(cp, JSSTRING_CHARS(message), message_length); - cp += message_length; - } - - if (filename_length != 0) { - /* append filename as ``, {filename}'' */ - *cp++ = ','; *cp++ = ' '; - js_strncpy(cp, JSSTRING_CHARS(filename), filename_length); - cp += filename_length; - } else { - if (lineno_as_str) { - /* - * no filename, but have line number, - * need to append ``, "", {lineno_as_str}'' - */ - *cp++ = ','; *cp++ = ' '; *cp++ = '"'; *cp++ = '"'; - } - } - if (lineno_as_str) { - /* append lineno as ``, {lineno_as_str}'' */ - *cp++ = ','; *cp++ = ' '; - js_strncpy(cp, JSSTRING_CHARS(lineno_as_str), lineno_length); - cp += lineno_length; - } - - *cp++ = ')'; *cp++ = ')'; *cp = 0; - - result = js_NewString(cx, chars, length, 0); - if (!result) { - JS_free(cx, chars); - return JS_FALSE; - } - *rval = STRING_TO_JSVAL(result); - return JS_TRUE; -} -#endif - -static JSFunctionSpec exception_methods[] = { -#if JS_HAS_TOSOURCE - {js_toSource_str, exn_toSource, 0,0,3}, -#endif - {js_toString_str, exn_toString, 0,0,0}, - {0,0,0,0,0} -}; - -JSObject * -js_InitExceptionClasses(JSContext *cx, JSObject *obj) -{ - int i; - JSObject *protos[JSEXN_LIMIT]; - - if (!js_EnterLocalRootScope(cx)) - return NULL; - - /* Initialize the prototypes first. */ - for (i = 0; exceptions[i].name != 0; i++) { - JSAtom *atom; - JSFunction *fun; - JSString *nameString; - int protoIndex = exceptions[i].protoIndex; - - /* Make the prototype for the current constructor name. */ - protos[i] = js_NewObject(cx, &ExceptionClass, - (protoIndex != JSEXN_NONE) - ? protos[protoIndex] - : NULL, - obj); - if (!protos[i]) - break; - - /* So exn_finalize knows whether to destroy private data. */ - OBJ_SET_SLOT(cx, protos[i], JSSLOT_PRIVATE, JSVAL_VOID); - - atom = js_Atomize(cx, exceptions[i].name, strlen(exceptions[i].name), 0); - if (!atom) - break; - - /* Make a constructor function for the current name. */ - fun = js_DefineFunction(cx, obj, atom, exceptions[i].native, 3, 0); - if (!fun) - break; - - /* Make this constructor make objects of class Exception. */ - fun->clasp = &ExceptionClass; - - /* Make the prototype and constructor links. */ - if (!js_SetClassPrototype(cx, fun->object, protos[i], - JSPROP_READONLY | JSPROP_PERMANENT)) { - break; - } - - /* proto bootstrap bit from JS_InitClass omitted. */ - nameString = JS_NewStringCopyZ(cx, exceptions[i].name); - if (!nameString) - break; - - /* Add the name property to the prototype. */ - if (!JS_DefineProperty(cx, protos[i], js_name_str, - STRING_TO_JSVAL(nameString), - NULL, NULL, - JSPROP_ENUMERATE)) { - break; - } - } - - js_LeaveLocalRootScope(cx); - if (exceptions[i].name) - return NULL; - - /* - * Add an empty message property. (To Exception.prototype only, - * because this property will be the same for all the exception - * protos.) - */ - if (!JS_DefineProperty(cx, protos[0], js_message_str, - STRING_TO_JSVAL(cx->runtime->emptyString), - NULL, NULL, JSPROP_ENUMERATE)) { - return NULL; - } - if (!JS_DefineProperty(cx, protos[0], js_filename_str, - STRING_TO_JSVAL(cx->runtime->emptyString), - NULL, NULL, JSPROP_ENUMERATE)) { - return NULL; - } - if (!JS_DefineProperty(cx, protos[0], js_lineno_str, - INT_TO_JSVAL(0), - NULL, NULL, JSPROP_ENUMERATE)) { - return NULL; - } - - /* - * Add methods only to Exception.prototype, because ostensibly all - * exception types delegate to that. - */ - if (!JS_DefineFunctions(cx, protos[0], exception_methods)) - return NULL; - - return protos[0]; -} - -static JSExnType errorToExceptionNum[] = { -#define MSG_DEF(name, number, count, exception, format) \ - exception, -#include "js.msg" -#undef MSG_DEF -}; - -#if defined ( DEBUG_mccabe ) && defined ( PRINTNAMES ) -/* For use below... get character strings for error name and exception name */ -static struct exnname { char *name; char *exception; } errortoexnname[] = { -#define MSG_DEF(name, number, count, exception, format) \ - {#name, #exception}, -#include "js.msg" -#undef MSG_DEF -}; -#endif /* DEBUG */ - -JSBool -js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp) -{ - JSErrNum errorNumber; - JSExnType exn; - jsval tv[4]; - JSTempValueRooter tvr; - JSBool ok; - JSObject *errProto, *errObject; - JSString *messageStr, *filenameStr; - uintN lineno; - JSExnPrivate *privateData; - - /* - * Tell our caller to report immediately if cx has no active frames, or if - * this report is just a warning. - */ - JS_ASSERT(reportp); - if (!cx->fp || JSREPORT_IS_WARNING(reportp->flags)) - return JS_FALSE; - - /* Find the exception index associated with this error. */ - errorNumber = (JSErrNum) reportp->errorNumber; - exn = errorToExceptionNum[errorNumber]; - JS_ASSERT(exn < JSEXN_LIMIT); - -#if defined( DEBUG_mccabe ) && defined ( PRINTNAMES ) - /* Print the error name and the associated exception name to stderr */ - fprintf(stderr, "%s\t%s\n", - errortoexnname[errorNumber].name, - errortoexnname[errorNumber].exception); -#endif - - /* - * Return false (no exception raised) if no exception is associated - * with the given error number. - */ - if (exn == JSEXN_NONE) - return JS_FALSE; - - /* - * Prevent runaway recursion, just as the Exception native constructor - * must do, via cx->creatingException. If an out-of-memory error occurs, - * no exception object will be created, but we don't assume that OOM is - * the only kind of error that subroutines of this function called below - * might raise. - */ - if (cx->creatingException) - return JS_FALSE; - - /* After this point the control must flow through the label out. */ - cx->creatingException = JS_TRUE; - - /* Protect the newly-created strings below from nesting GCs. */ - memset(tv, 0, sizeof tv); - JS_PUSH_TEMP_ROOT(cx, sizeof tv / sizeof tv[0], tv, &tvr); - - /* - * Try to get an appropriate prototype by looking up the corresponding - * exception constructor name in the scope chain of the current context's - * top stack frame, or in the global object if no frame is active. - */ - ok = js_GetClassPrototype(cx, exceptions[exn].name, &errProto); - if (!ok) - goto out; - tv[0] = OBJECT_TO_JSVAL(errProto); - - errObject = js_NewObject(cx, &ExceptionClass, errProto, NULL); - if (!errObject) { - ok = JS_FALSE; - goto out; - } - tv[1] = OBJECT_TO_JSVAL(errObject); - - messageStr = JS_NewStringCopyZ(cx, message); - if (!messageStr) { - ok = JS_FALSE; - goto out; - } - tv[2] = STRING_TO_JSVAL(messageStr); - - if (reportp) { - filenameStr = JS_NewStringCopyZ(cx, reportp->filename); - if (!filenameStr) { - ok = JS_FALSE; - goto out; - } - tv[3] = STRING_TO_JSVAL(filenameStr); - lineno = reportp->lineno; - } else { - filenameStr = cx->runtime->emptyString; - lineno = 0; - } - ok = InitExceptionObject(cx, errObject, messageStr, filenameStr, lineno); - if (!ok) - goto out; - - /* - * Construct a new copy of the error report struct, and store it in the - * exception object's private data. We can't use the error report struct - * that was passed in, because it's stack-allocated, and also because it - * may point to transient data in the JSTokenStream. - */ - privateData = exn_newPrivate(cx, reportp); - if (!privateData) { - ok = JS_FALSE; - goto out; - } - OBJ_SET_SLOT(cx, errObject, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(privateData)); - - JS_SetPendingException(cx, OBJECT_TO_JSVAL(errObject)); - - /* Flag the error report passed in to indicate an exception was raised. */ - reportp->flags |= JSREPORT_EXCEPTION; - -out: - JS_POP_TEMP_ROOT(cx, &tvr); - cx->creatingException = JS_FALSE; - return ok; -} -#endif /* JS_HAS_ERROR_EXCEPTIONS */ - -#if JS_HAS_EXCEPTIONS - -JSBool -js_ReportUncaughtException(JSContext *cx) -{ - jsval exn, *vp; - JSObject *exnObject; - void *mark; - JSErrorReport *reportp, report; - JSString *str; - const char *bytes; - JSBool ok; - - if (!JS_IsExceptionPending(cx)) - return JS_TRUE; - - if (!JS_GetPendingException(cx, &exn)) - return JS_FALSE; - - /* - * Because js_ValueToString below could error and an exception object - * could become unrooted, we must root exnObject. Later, if exnObject is - * non-null, we need to root other intermediates, so allocate an operand - * stack segment to protect all of these values. - */ - if (JSVAL_IS_PRIMITIVE(exn)) { - exnObject = NULL; - vp = NULL; -#ifdef __GNUC__ /* suppress bogus gcc warnings */ - mark = NULL; -#endif - } else { - exnObject = JSVAL_TO_OBJECT(exn); - vp = js_AllocStack(cx, 5, &mark); - if (!vp) { - ok = JS_FALSE; - goto out; - } - vp[0] = exn; - } - -#if JS_HAS_ERROR_EXCEPTIONS - reportp = js_ErrorFromException(cx, exn); -#else - reportp = NULL; -#endif - - /* XXX L10N angels cry once again (see also jsemit.c, /L10N gaffes/) */ - str = js_ValueToString(cx, exn); - if (!str) { - bytes = "unknown (can't convert to string)"; - } else { - if (vp) - vp[1] = STRING_TO_JSVAL(str); - bytes = js_GetStringBytes(str); - } - ok = JS_TRUE; - - if (!reportp && - exnObject && - OBJ_GET_CLASS(cx, exnObject) == &ExceptionClass) { - const char *filename; - uint32 lineno; - - ok = JS_GetProperty(cx, exnObject, js_message_str, &vp[2]); - if (!ok) - goto out; - if (JSVAL_IS_STRING(vp[2])) - bytes = JS_GetStringBytes(JSVAL_TO_STRING(vp[2])); - - ok = JS_GetProperty(cx, exnObject, js_filename_str, &vp[3]); - if (!ok) - goto out; - str = js_ValueToString(cx, vp[3]); - if (!str) { - ok = JS_FALSE; - goto out; - } - filename = StringToFilename(cx, str); - - ok = JS_GetProperty(cx, exnObject, js_lineno_str, &vp[4]); - if (!ok) - goto out; - ok = js_ValueToECMAUint32 (cx, vp[4], &lineno); - if (!ok) - goto out; - - reportp = &report; - memset(&report, 0, sizeof report); - report.filename = filename; - report.lineno = (uintN) lineno; - } - - if (!reportp) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_UNCAUGHT_EXCEPTION, bytes); - } else { - /* Flag the error as an exception. */ - reportp->flags |= JSREPORT_EXCEPTION; - js_ReportErrorAgain(cx, bytes, reportp); - } - - JS_ClearPendingException(cx); -out: - if (exnObject) - js_FreeStack(cx, mark); - return ok; -} - -#endif /* JS_HAS_EXCEPTIONS */ diff --git a/lib/javascript/jsexn.h b/lib/javascript/jsexn.h deleted file mode 100644 index aeaab0a5..00000000 --- a/lib/javascript/jsexn.h +++ /dev/null @@ -1,102 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JS runtime exception classes. - */ - -#ifndef jsexn_h___ -#define jsexn_h___ - -JS_BEGIN_EXTERN_C - -/* - * Initialize the exception constructor/prototype hierarchy. - */ -extern JSObject * -js_InitExceptionClasses(JSContext *cx, JSObject *obj); - -/* - * String constants naming the exception classes. - */ -extern const char js_Error_str[]; -extern const char js_InternalError_str[]; -extern const char js_EvalError_str[]; -extern const char js_RangeError_str[]; -extern const char js_ReferenceError_str[]; -extern const char js_SyntaxError_str[]; -extern const char js_TypeError_str[]; -extern const char js_URIError_str[]; - -/* - * Given a JSErrorReport, check to see if there is an exception associated with - * the error number. If there is, then create an appropriate exception object, - * set it as the pending exception, and set the JSREPORT_EXCEPTION flag on the - * error report. Exception-aware host error reporters should probably ignore - * error reports so flagged. Returns JS_TRUE if an associated exception is - * found and set, JS_FALSE otherwise.. - */ -extern JSBool -js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp); - -/* - * Called if a JS API call to js_Execute or js_InternalCall fails; calls the - * error reporter with the error report associated with any uncaught exception - * that has been raised. Returns true if there was an exception pending, and - * the error reporter was actually called. - * - * The JSErrorReport * that the error reporter is called with is currently - * associated with a JavaScript object, and is not guaranteed to persist after - * the object is collected. Any persistent uses of the JSErrorReport contents - * should make their own copy. - * - * The flags field of the JSErrorReport will have the JSREPORT_EXCEPTION flag - * set; embeddings that want to silently propagate JavaScript exceptions to - * other contexts may want to use an error reporter that ignores errors with - * this flag. - */ -extern JSBool -js_ReportUncaughtException(JSContext *cx); - -extern JSErrorReport * -js_ErrorFromException(JSContext *cx, jsval exn); - -JS_END_EXTERN_C - -#endif /* jsexn_h___ */ diff --git a/lib/javascript/jsfile.c b/lib/javascript/jsfile.c deleted file mode 100644 index 2237dbd4..00000000 --- a/lib/javascript/jsfile.c +++ /dev/null @@ -1,2720 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sw=4 et tw=80: - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JS File object - */ -#if JS_HAS_FILE_OBJECT - -#include "jsstddef.h" - -/* ----------------- Platform-specific includes and defines ----------------- */ -#if defined(XP_WIN) || defined(XP_OS2) -# include -# include -# include -# include -# define FILESEPARATOR '\\' -# define FILESEPARATOR2 '/' -# define CURRENT_DIR "c:\\" -# define POPEN _popen -# define PCLOSE _pclose -#elif defined(XP_UNIX) || defined(XP_BEOS) -# include -# include -# include -# include -# define FILESEPARATOR '/' -# define FILESEPARATOR2 '\0' -# define CURRENT_DIR "/" -# define POPEN popen -# define PCLOSE pclose -#endif - -/* --------------- Platform-independent includes and defines ---------------- */ -#include "jsapi.h" -#include "jsatom.h" -#include "jscntxt.h" -#include "jsdate.h" -#include "jsdbgapi.h" -#include "jsemit.h" -#include "jsfun.h" -#include "jslock.h" -#include "jsobj.h" -#include "jsparse.h" -#include "jsscan.h" -#include "jsscope.h" -#include "jsscript.h" -#include "jsstr.h" -#include "jsutil.h" /* Added by JSIFY */ -#include - -/* NSPR dependencies */ -#include "prio.h" -#include "prerror.h" - -#define SPECIAL_FILE_STRING "Special File" -#define CURRENTDIR_PROPERTY "currentDir" -#define SEPARATOR_PROPERTY "separator" -#define FILE_CONSTRUCTOR "File" -#define PIPE_SYMBOL '|' - -#define ASCII 0 -#define UTF8 1 -#define UCS2 2 - -#define asciistring "text" -#define utfstring "binary" -#define unicodestring "unicode" - -#define MAX_PATH_LENGTH 1024 -#define MODE_SIZE 256 -#define NUMBER_SIZE 32 -#define MAX_LINE_LENGTH 256 -#define URL_PREFIX "file://" - -#define STDINPUT_NAME "Standard input stream" -#define STDOUTPUT_NAME "Standard output stream" -#define STDERROR_NAME "Standard error stream" - -#define RESOLVE_PATH js_canonicalPath /* js_absolutePath */ - -/* Error handling */ -typedef enum JSFileErrNum { -#define MSG_DEF(name, number, count, exception, format) \ - name = number, -#include "jsfile.msg" -#undef MSG_DEF - JSFileErr_Limit -#undef MSGDEF -} JSFileErrNum; - -#define JSFILE_HAS_DFLT_MSG_STRINGS 1 - -JSErrorFormatString JSFile_ErrorFormatString[JSFileErr_Limit] = { -#if JSFILE_HAS_DFLT_MSG_STRINGS -#define MSG_DEF(name, number, count, exception, format) \ - { format, count }, -#else -#define MSG_DEF(name, number, count, exception, format) \ - { NULL, count }, -#endif -#include "jsfile.msg" -#undef MSG_DEF -}; - -const JSErrorFormatString * -JSFile_GetErrorMessage(void *userRef, const char *locale, - const uintN errorNumber) -{ - if ((errorNumber > 0) && (errorNumber < JSFileErr_Limit)) - return &JSFile_ErrorFormatString[errorNumber]; - else - return NULL; -} - -#define JSFILE_CHECK_NATIVE(op) \ - if (file->isNative) { \ - JS_ReportWarning(cx, "Cannot call or access \"%s\" on native file %s",\ - op, file->path); \ - goto out; \ - } - -#define JSFILE_CHECK_WRITE \ - if (!file->isOpen) { \ - JS_ReportWarning(cx, \ - "File %s is closed, will open it for writing, proceeding", \ - file->path); \ - js_FileOpen(cx, obj, file, "write,append,create"); \ - } \ - if (!js_canWrite(cx, file)) { \ - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \ - JSFILEMSG_CANNOT_WRITE, file->path); \ - goto out; \ - } - -#define JSFILE_CHECK_READ \ - if (!file->isOpen) { \ - JS_ReportWarning(cx, \ - "File %s is closed, will open it for reading, proceeding", \ - file->path); \ - js_FileOpen(cx, obj, file, "read"); \ - } \ - if (!js_canRead(cx, file)) { \ - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \ - JSFILEMSG_CANNOT_READ, file->path); \ - goto out; \ - } - -#define JSFILE_CHECK_OPEN(op) \ - if (!file->isOpen) { \ - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \ - JSFILEMSG_FILE_MUST_BE_CLOSED, op); \ - goto out; \ - } - -#define JSFILE_CHECK_CLOSED(op) \ - if (file->isOpen) { \ - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \ - JSFILEMSG_FILE_MUST_BE_OPEN, op); \ - goto out; \ - } - -#define JSFILE_CHECK_ONE_ARG(op) \ - if (argc != 1) { \ - char str[NUMBER_SIZE]; \ - sprintf(str, "%d", argc); \ - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \ - JSFILEMSG_EXPECTS_ONE_ARG_ERROR, op, str); \ - goto out; \ - } - - -/* - Security mechanism, should define a callback for this. - The parameters are as follows: - SECURITY_CHECK(JSContext *cx, JSPrincipals *ps, char *op_name, JSFile *file) - XXX Should this be a real function returning a JSBool result (and getting - some typesafety help from the compiler?). -*/ -#define SECURITY_CHECK(cx, ps, op, file) \ - /* Define a callback here... */ - - -/* Structure representing the file internally */ -typedef struct JSFile { - char *path; /* the path to the file. */ - JSBool isOpen; - int32 mode; /* mode used to open the file: read, write, append, create, etc.. */ - int32 type; /* Asciiz, utf, unicode */ - char byteBuffer[3]; /* bytes read in advance by js_FileRead ( UTF8 encoding ) */ - jsint nbBytesInBuf; /* number of bytes stored in the buffer above */ - jschar charBuffer; /* character read in advance by readln ( mac files only ) */ - JSBool charBufferUsed; /* flag indicating if the buffer above is being used */ - JSBool hasRandomAccess;/* can the file be randomly accessed? false for stdin, and - UTF-encoded files. */ - JSBool hasAutoflush; /* should we force a flush for each line break? */ - JSBool isNative; /* if the file is using OS-specific file FILE type */ - /* We can actually put the following two in a union since they should never be used at the same time */ - PRFileDesc *handle; /* the handle for the file, if open. */ - FILE *nativehandle; /* native handle, for stuff NSPR doesn't do. */ - JSBool isPipe; /* if the file is really an OS pipe */ -} JSFile; - -/* a few forward declarations... */ -static JSClass file_class; -JS_PUBLIC_API(JSObject*) js_NewFileObject(JSContext *cx, char *filename); -static JSBool file_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); -static JSBool file_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); - -/* New filename manipulation procesures */ -/* assumes we don't have leading/trailing spaces */ -static JSBool -js_filenameHasAPipe(const char *filename) -{ - if (!filename) - return JS_FALSE; - - return filename[0] == PIPE_SYMBOL || - filename[strlen(filename) - 1] == PIPE_SYMBOL; -} - -static JSBool -js_isAbsolute(const char *name) -{ -#if defined(XP_WIN) || defined(XP_OS2) - return *name && name[1] == ':'; -#else - return (name[0] -# if defined(XP_UNIX) || defined(XP_BEOS) - == -# else - != -# endif - FILESEPARATOR); -#endif -} - -/* - * Concatinates base and name to produce a valid filename. - * Returned string must be freed. -*/ -static char* -js_combinePath(JSContext *cx, const char *base, const char *name) -{ - int len = strlen(base); - char* result = JS_malloc(cx, len + strlen(name) + 2); - - if (!result) - return NULL; - - strcpy(result, base); - - if (base[len - 1] != FILESEPARATOR && base[len - 1] != FILESEPARATOR2) { - result[len] = FILESEPARATOR; - result[len + 1] = '\0'; - } - strcat(result, name); - return result; -} - -/* Extract the last component from a path name. Returned string must be freed */ -static char * -js_fileBaseName(JSContext *cx, const char *pathname) -{ - jsint index, aux; - char *result; - - index = strlen(pathname)-1; - - /* Chop off trailing seperators. */ - while (index > 0 && (pathname[index]==FILESEPARATOR || - pathname[index]==FILESEPARATOR2)) { - --index; - } - - aux = index; - - /* Now find the next separator. */ - while (index >= 0 && pathname[index] != FILESEPARATOR && - pathname[index] != FILESEPARATOR2) { - --index; - } - - /* Allocate and copy. */ - result = JS_malloc(cx, aux - index + 1); - if (!result) - return NULL; - strncpy(result, pathname + index + 1, aux - index); - result[aux - index] = '\0'; - return result; -} - -/* - * Returns everything but the last component from a path name. - * Returned string must be freed. - */ -static char * -js_fileDirectoryName(JSContext *cx, const char *pathname) -{ - char *result; - const char *cp, *end; - size_t pathsize; - - end = pathname + strlen(pathname); - cp = end - 1; - - /* If this is already a directory, chop off the trailing /s. */ - while (cp >= pathname) { - if (*cp != FILESEPARATOR && *cp != FILESEPARATOR2) - break; - --cp; - } - - if (cp < pathname && end != pathname) { - /* There were just /s, return the root. */ - result = JS_malloc(cx, 1 + 1); /* The separator + trailing NUL. */ - result[0] = FILESEPARATOR; - result[1] = '\0'; - return result; - } - - /* Now chop off the last portion. */ - while (cp >= pathname) { - if (*cp == FILESEPARATOR || *cp == FILESEPARATOR2) - break; - --cp; - } - - /* Check if this is a leaf. */ - if (cp < pathname) { - /* It is, return "pathname/". */ - if (end[-1] == FILESEPARATOR || end[-1] == FILESEPARATOR2) { - /* Already has its terminating /. */ - return JS_strdup(cx, pathname); - } - - pathsize = end - pathname + 1; - result = JS_malloc(cx, pathsize + 1); - if (!result) - return NULL; - - strcpy(result, pathname); - result[pathsize - 1] = FILESEPARATOR; - result[pathsize] = '\0'; - - return result; - } - - /* Return everything up to and including the seperator. */ - pathsize = cp - pathname + 1; - result = JS_malloc(cx, pathsize + 1); - if (!result) - return NULL; - - strncpy(result, pathname, pathsize); - result[pathsize] = '\0'; - - return result; -} - -static char * -js_absolutePath(JSContext *cx, const char * path) -{ - JSObject *obj; - JSString *str; - jsval prop; - - if (js_isAbsolute(path)) { - return JS_strdup(cx, path); - } else { - obj = JS_GetGlobalObject(cx); - if (!JS_GetProperty(cx, obj, FILE_CONSTRUCTOR, &prop)) { - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_FILE_CONSTRUCTOR_UNDEFINED_ERROR); - return JS_strdup(cx, path); - } - - obj = JSVAL_TO_OBJECT(prop); - if (!JS_GetProperty(cx, obj, CURRENTDIR_PROPERTY, &prop)) { - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_FILE_CURRENTDIR_UNDEFINED_ERROR); - return JS_strdup(cx, path); - } - - str = JS_ValueToString(cx, prop); - if (!str) - return JS_strdup(cx, path); - - /* should we have an array of curr dirs indexed by drive for windows? */ - return js_combinePath(cx, JS_GetStringBytes(str), path); - } -} - -/* Side effect: will remove spaces in the beginning/end of the filename */ -static char * -js_canonicalPath(JSContext *cx, char *oldpath) -{ - char *tmp; - char *path = oldpath; - char *base, *dir, *current, *result; - jsint c; - jsint back = 0; - unsigned int i = 0, j = strlen(path)-1; - - /* This is probably optional */ - /* Remove possible spaces in the beginning and end */ - while (i < j && path[i] == ' ') - i++; - while (j >= 0 && path[j] == ' ') - j--; - - tmp = JS_malloc(cx, j-i+2); - if (!tmp) - return NULL; - - strncpy(tmp, path + i, j - i + 1); - tmp[j - i + 1] = '\0'; - - path = tmp; - - /* Pipe support. */ - if (js_filenameHasAPipe(path)) - return path; - - /* file:// support. */ - if (!strncmp(path, URL_PREFIX, strlen(URL_PREFIX))) { - tmp = js_canonicalPath(cx, path + strlen(URL_PREFIX)); - JS_free(cx, path); - return tmp; - } - - if (!js_isAbsolute(path)) { - tmp = js_absolutePath(cx, path); - if (!tmp) - return NULL; - path = tmp; - } - - result = JS_strdup(cx, ""); - - current = path; - - base = js_fileBaseName(cx, current); - dir = js_fileDirectoryName(cx, current); - - while (strcmp(dir, current)) { - if (!strcmp(base, "..")) { - back++; - } else { - if (back > 0) { - back--; - } else { - tmp = result; - result = JS_malloc(cx, strlen(base) + 1 + strlen(tmp) + 1); - if (!result) - goto out; - - strcpy(result, base); - c = strlen(result); - if (*tmp) { - result[c] = FILESEPARATOR; - result[c + 1] = '\0'; - strcat(result, tmp); - } - JS_free(cx, tmp); - } - } - JS_free(cx, current); - JS_free(cx, base); - current = dir; - base = js_fileBaseName(cx, current); - dir = js_fileDirectoryName(cx, current); - } - - tmp = result; - result = JS_malloc(cx, strlen(dir)+1+strlen(tmp)+1); - if (!result) - goto out; - - strcpy(result, dir); - c = strlen(result); - if (tmp[0]!='\0') { - if ((result[c-1]!=FILESEPARATOR)&&(result[c-1]!=FILESEPARATOR2)) { - result[c] = FILESEPARATOR; - result[c+1] = '\0'; - } - strcat(result, tmp); - } - -out: - if (tmp) - JS_free(cx, tmp); - if (dir) - JS_free(cx, dir); - if (base) - JS_free(cx, base); - if (current) - JS_free(cx, current); - - return result; -} - -/* -------------------------- Text conversion ------------------------------- */ -/* The following is ripped from libi18n/unicvt.c and include files.. */ - -/* - * UTF8 defines and macros - */ -#define ONE_OCTET_BASE 0x00 /* 0xxxxxxx */ -#define ONE_OCTET_MASK 0x7F /* x1111111 */ -#define CONTINUING_OCTET_BASE 0x80 /* 10xxxxxx */ -#define CONTINUING_OCTET_MASK 0x3F /* 00111111 */ -#define TWO_OCTET_BASE 0xC0 /* 110xxxxx */ -#define TWO_OCTET_MASK 0x1F /* 00011111 */ -#define THREE_OCTET_BASE 0xE0 /* 1110xxxx */ -#define THREE_OCTET_MASK 0x0F /* 00001111 */ -#define FOUR_OCTET_BASE 0xF0 /* 11110xxx */ -#define FOUR_OCTET_MASK 0x07 /* 00000111 */ -#define FIVE_OCTET_BASE 0xF8 /* 111110xx */ -#define FIVE_OCTET_MASK 0x03 /* 00000011 */ -#define SIX_OCTET_BASE 0xFC /* 1111110x */ -#define SIX_OCTET_MASK 0x01 /* 00000001 */ - -#define IS_UTF8_1ST_OF_1(x) (( (x)&~ONE_OCTET_MASK ) == ONE_OCTET_BASE) -#define IS_UTF8_1ST_OF_2(x) (( (x)&~TWO_OCTET_MASK ) == TWO_OCTET_BASE) -#define IS_UTF8_1ST_OF_3(x) (( (x)&~THREE_OCTET_MASK) == THREE_OCTET_BASE) -#define IS_UTF8_1ST_OF_4(x) (( (x)&~FOUR_OCTET_MASK ) == FOUR_OCTET_BASE) -#define IS_UTF8_1ST_OF_5(x) (( (x)&~FIVE_OCTET_MASK ) == FIVE_OCTET_BASE) -#define IS_UTF8_1ST_OF_6(x) (( (x)&~SIX_OCTET_MASK ) == SIX_OCTET_BASE) -#define IS_UTF8_2ND_THRU_6TH(x) \ - (( (x)&~CONTINUING_OCTET_MASK ) == CONTINUING_OCTET_BASE) -#define IS_UTF8_1ST_OF_UCS2(x) \ - IS_UTF8_1ST_OF_1(x) \ - || IS_UTF8_1ST_OF_2(x) \ - || IS_UTF8_1ST_OF_3(x) - - -#define MAX_UCS2 0xFFFF -#define DEFAULT_CHAR 0x003F /* Default char is "?" */ -#define BYTE_MASK 0xBF -#define BYTE_MARK 0x80 - - -/* Function: one_ucs2_to_utf8_char - * - * Function takes one UCS-2 char and writes it to a UTF-8 buffer. - * We need a UTF-8 buffer because we don't know before this - * function how many bytes of utf-8 data will be written. It also - * takes a pointer to the end of the UTF-8 buffer so that we don't - * overwrite data. This function returns the number of UTF-8 bytes - * of data written, or -1 if the buffer would have been overrun. - */ - -#define LINE_SEPARATOR 0x2028 -#define PARAGRAPH_SEPARATOR 0x2029 -static int16 one_ucs2_to_utf8_char(unsigned char *tobufp, - unsigned char *tobufendp, - uint16 onechar) -{ - int16 numUTF8bytes = 0; - - if (onechar == LINE_SEPARATOR || onechar == PARAGRAPH_SEPARATOR) { - strcpy((char*)tobufp, "\n"); - return strlen((char*)tobufp); - } - - if (onechar < 0x80) { - numUTF8bytes = 1; - } else if (onechar < 0x800) { - numUTF8bytes = 2; - } else { - /* 0x800 >= onechar <= MAX_UCS2 */ - numUTF8bytes = 3; - } - - tobufp += numUTF8bytes; - - /* return error if we don't have space for the whole character */ - if (tobufp > tobufendp) { - return(-1); - } - - switch(numUTF8bytes) { - case 3: *--tobufp = (onechar | BYTE_MARK) & BYTE_MASK; onechar >>=6; - *--tobufp = (onechar | BYTE_MARK) & BYTE_MASK; onechar >>=6; - *--tobufp = onechar | THREE_OCTET_BASE; - break; - - case 2: *--tobufp = (onechar | BYTE_MARK) & BYTE_MASK; onechar >>=6; - *--tobufp = onechar | TWO_OCTET_BASE; - break; - - case 1: *--tobufp = (unsigned char)onechar; - break; - } - - return numUTF8bytes; -} - -/* - * utf8_to_ucs2_char - * - * Convert a utf8 multibyte character to ucs2 - * - * inputs: pointer to utf8 character(s) - * length of utf8 buffer ("read" length limit) - * pointer to return ucs2 character - * - * outputs: number of bytes in the utf8 character - * -1 if not a valid utf8 character sequence - * -2 if the buffer is too short - */ -static int16 -utf8_to_ucs2_char(const unsigned char *utf8p, int16 buflen, uint16 *ucs2p) -{ - uint16 lead, cont1, cont2; - - /* - * Check for minimum buffer length - */ - if ((buflen < 1) || (utf8p == NULL)) { - return -2; - } - lead = (uint16) (*utf8p); - - /* - * Check for a one octet sequence - */ - if (IS_UTF8_1ST_OF_1(lead)) { - *ucs2p = lead & ONE_OCTET_MASK; - return 1; - } - - /* - * Check for a two octet sequence - */ - if (IS_UTF8_1ST_OF_2(*utf8p)) { - if (buflen < 2) - return -2; - cont1 = (uint16) *(utf8p+1); - if (!IS_UTF8_2ND_THRU_6TH(cont1)) - return -1; - *ucs2p = (lead & TWO_OCTET_MASK) << 6; - *ucs2p |= cont1 & CONTINUING_OCTET_MASK; - return 2; - } - - /* - * Check for a three octet sequence - */ - else if (IS_UTF8_1ST_OF_3(lead)) { - if (buflen < 3) - return -2; - cont1 = (uint16) *(utf8p+1); - cont2 = (uint16) *(utf8p+2); - if ( (!IS_UTF8_2ND_THRU_6TH(cont1)) - || (!IS_UTF8_2ND_THRU_6TH(cont2))) - return -1; - *ucs2p = (lead & THREE_OCTET_MASK) << 12; - *ucs2p |= (cont1 & CONTINUING_OCTET_MASK) << 6; - *ucs2p |= cont2 & CONTINUING_OCTET_MASK; - return 3; - } - else { /* not a valid utf8/ucs2 character */ - return -1; - } -} - -/* ----------------------------- Helper functions --------------------------- */ -/* Ripped off from lm_win.c .. */ -/* where is strcasecmp?.. for now, it's case sensitive.. - * - * strcasecmp is in strings.h, but on windows it's called _stricmp... - * will need to #ifdef this -*/ - -static int32 -js_FileHasOption(JSContext *cx, const char *oldoptions, const char *name) -{ - char *comma, *equal, *current; - char *options = JS_strdup(cx, oldoptions); - int32 found = 0; - - current = options; - for (;;) { - comma = strchr(current, ','); - if (comma) *comma = '\0'; - equal = strchr(current, '='); - if (equal) *equal = '\0'; - if (strcmp(current, name) == 0) { - if (!equal || strcmp(equal + 1, "yes") == 0) - found = 1; - else - found = atoi(equal + 1); - } - if (equal) *equal = '='; - if (comma) *comma = ','; - if (found || !comma) - break; - current = comma + 1; - } - JS_free(cx, options); - return found; -} - -/* empty the buffer */ -static void -js_ResetBuffers(JSFile * file) -{ - file->charBufferUsed = JS_FALSE; - file->nbBytesInBuf = 0; -} - -/* Reset file attributes */ -static void -js_ResetAttributes(JSFile * file) -{ - file->mode = file->type = 0; - file->isOpen = JS_FALSE; - file->handle = NULL; - file->nativehandle = NULL; - file->hasRandomAccess = JS_TRUE; /* Innocent until proven guilty. */ - file->hasAutoflush = JS_FALSE; - file->isNative = JS_FALSE; - file->isPipe = JS_FALSE; - - js_ResetBuffers(file); -} - -static JSBool -js_FileOpen(JSContext *cx, JSObject *obj, JSFile *file, char *mode){ - JSString *type, *mask; - jsval v[2]; - jsval rval; - - type = JS_InternString(cx, asciistring); - mask = JS_NewStringCopyZ(cx, mode); - v[0] = STRING_TO_JSVAL(mask); - v[1] = STRING_TO_JSVAL(type); - - if (!file_open(cx, obj, 2, v, &rval)) - return JS_FALSE; - return JS_TRUE; -} - -/* Buffered version of PR_Read. Used by js_FileRead */ -static int32 -js_BufferedRead(JSFile * f, char *buf, int32 len) -{ - int32 count = 0; - - while (f->nbBytesInBuf>0&&len>0) { - buf[0] = f->byteBuffer[0]; - f->byteBuffer[0] = f->byteBuffer[1]; - f->byteBuffer[1] = f->byteBuffer[2]; - f->nbBytesInBuf--; - len--; - buf+=1; - count++; - } - - if (len>0) { - count += (!f->isNative) - ? PR_Read(f->handle, buf, len) - : fread(buf, 1, len, f->nativehandle); - } - return count; -} - -static int32 -js_FileRead(JSContext *cx, JSFile *file, jschar *buf, int32 len, int32 mode) -{ - unsigned char *aux; - int32 count = 0, i; - jsint remainder; - unsigned char utfbuf[3]; - - if (file->charBufferUsed) { - buf[0] = file->charBuffer; - buf++; - len--; - file->charBufferUsed = JS_FALSE; - } - - switch (mode) { - case ASCII: - aux = (unsigned char*)JS_malloc(cx, len); - if (!aux) - return 0; - - count = js_BufferedRead(file, aux, len); - if (count == -1) { - JS_free(cx, aux); - return 0; - } - - for (i = 0; i < len; i++) - buf[i] = (jschar)aux[i]; - - JS_free(cx, aux); - break; - - case UTF8: - remainder = 0; - for (count = 0;count0) { - file->byteBuffer[file->nbBytesInBuf] = utfbuf[0]; - file->nbBytesInBuf++; - utfbuf[0] = utfbuf[1]; - utfbuf[1] = utfbuf[2]; - remainder--; - } - break; - - case UCS2: - count = js_BufferedRead(file, (char*)buf, len*2) >> 1; - if (count == -1) - return 0; - - break; - - default: - /* Not reached. */ - JS_ASSERT(0); - } - - if(count == -1) { - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_OP_FAILED, "read", file->path); - } - - return count; -} - -static int32 -js_FileSeek(JSContext *cx, JSFile *file, int32 len, int32 mode) -{ - int32 count = 0, i; - jsint remainder; - unsigned char utfbuf[3]; - jschar tmp; - - switch (mode) { - case ASCII: - count = PR_Seek(file->handle, len, PR_SEEK_CUR); - break; - - case UTF8: - remainder = 0; - for (count = 0;count0) { - file->byteBuffer[file->nbBytesInBuf] = utfbuf[0]; - file->nbBytesInBuf++; - utfbuf[0] = utfbuf[1]; - utfbuf[1] = utfbuf[2]; - remainder--; - } - break; - - case UCS2: - count = PR_Seek(file->handle, len*2, PR_SEEK_CUR)/2; - break; - - default: - /* Not reached. */ - JS_ASSERT(0); - } - - if(count == -1) { - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_OP_FAILED, "seek", file->path); - } - - return count; -} - -static int32 -js_FileWrite(JSContext *cx, JSFile *file, jschar *buf, int32 len, int32 mode) -{ - unsigned char *aux; - int32 count = 0, i, j; - unsigned char *utfbuf; - - switch (mode) { - case ASCII: - aux = (unsigned char*)JS_malloc(cx, len); - if (!aux) - return 0; - - for (i = 0; iisNative) - ? PR_Write(file->handle, aux, len) - : fwrite(aux, 1, len, file->nativehandle); - - if (count==-1) { - JS_free(cx, aux); - return 0; - } - - JS_free(cx, aux); - break; - - case UTF8: - utfbuf = (unsigned char*)JS_malloc(cx, len*3); - if (!utfbuf) return 0; - i = 0; - for (count = 0;countisNative) - ? PR_Write(file->handle, utfbuf, i) - : fwrite(utfbuf, 1, i, file->nativehandle); - - if (jisNative) - ? PR_Write(file->handle, buf, len*2) >> 1 - : fwrite(buf, 1, len*2, file->nativehandle) >> 1; - - if (count == -1) - return 0; - break; - - default: - /* Not reached. */ - JS_ASSERT(0); - } - - if(count == -1) { - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_OP_FAILED, "write", file->path); - } - - return count; -} - -/* ----------------------------- Property checkers -------------------------- */ -static JSBool -js_exists(JSContext *cx, JSFile *file) -{ - if (file->isNative) { - /* It doesn't make sense for a pipe of stdstream. */ - return JS_FALSE; - } - - return PR_Access(file->path, PR_ACCESS_EXISTS) == PR_SUCCESS; -} - -static JSBool -js_canRead(JSContext *cx, JSFile *file) -{ - if (!file->isNative) { - if (file->isOpen && !(file->mode & PR_RDONLY)) - return JS_FALSE; - return PR_Access(file->path, PR_ACCESS_READ_OK) == PR_SUCCESS; - } - - if (file->isPipe) { - /* Is this pipe open for reading? */ - return file->path[0] == PIPE_SYMBOL; - } - - return !strcmp(file->path, STDINPUT_NAME); -} - -static JSBool -js_canWrite(JSContext *cx, JSFile *file) -{ - if (!file->isNative) { - if (file->isOpen && !(file->mode & PR_WRONLY)) - return JS_FALSE; - return PR_Access(file->path, PR_ACCESS_WRITE_OK) == PR_SUCCESS; - } - - if(file->isPipe) { - /* Is this pipe open for writing? */ - return file->path[strlen(file->path)-1] == PIPE_SYMBOL; - } - - return !strcmp(file->path, STDOUTPUT_NAME) || - !strcmp(file->path, STDERROR_NAME); -} - -static JSBool -js_isFile(JSContext *cx, JSFile *file) -{ - if (!file->isNative) { - PRFileInfo info; - - if (file->isOpen - ? PR_GetOpenFileInfo(file->handle, &info) - : PR_GetFileInfo(file->path, &info) != PR_SUCCESS) { - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path); - return JS_FALSE; - } - - return info.type == PR_FILE_FILE; - } - - /* This doesn't make sense for a pipe of stdstream. */ - return JS_FALSE; -} - -static JSBool -js_isDirectory(JSContext *cx, JSFile *file) -{ - if(!file->isNative){ - PRFileInfo info; - - /* Hack needed to get get_property to work. */ - if (!js_exists(cx, file)) - return JS_FALSE; - - if (file->isOpen - ? PR_GetOpenFileInfo(file->handle, &info) - : PR_GetFileInfo(file->path, &info) != PR_SUCCESS) { - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path); - return JS_FALSE; - } - - return info.type == PR_FILE_DIRECTORY; - } - - /* This doesn't make sense for a pipe of stdstream. */ - return JS_FALSE; -} - -static jsval -js_size(JSContext *cx, JSFile *file) -{ - PRFileInfo info; - - JSFILE_CHECK_NATIVE("size"); - - if (file->isOpen - ? PR_GetOpenFileInfo(file->handle, &info) - : PR_GetFileInfo(file->path, &info) != PR_SUCCESS) { - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path); - return JS_FALSE; - } - - return INT_TO_JSVAL(info.size); - -out: - return JSVAL_VOID; -} - -/* - * Return the parent object - */ -static JSBool -js_parent(JSContext *cx, JSFile *file, jsval *resultp) -{ - char *str; - - /* Since we only care about pipes and native files, return NULL. */ - if (file->isNative) { - *resultp = JSVAL_VOID; - return JS_TRUE; - } - - str = js_fileDirectoryName(cx, file->path); - if (!str) - return JS_FALSE; - - /* If the directory is equal to the original path, we're at the root. */ - if (!strcmp(file->path, str)) { - *resultp = JSVAL_NULL; - } else { - JSObject *obj = js_NewFileObject(cx, str); - if (!obj) { - JS_free(cx, str); - return JS_FALSE; - } - *resultp = OBJECT_TO_JSVAL(obj); - } - - JS_free(cx, str); - return JS_TRUE; -} - -static JSBool -js_name(JSContext *cx, JSFile *file, jsval *vp) -{ - char *name; - JSString *str; - - if (file->isPipe) { - *vp = JSVAL_VOID; - return JS_TRUE; - } - - name = js_fileBaseName(cx, file->path); - if (!name) - return JS_FALSE; - - str = JS_NewString(cx, name, strlen(name)); - if (!str) { - JS_free(cx, name); - return JS_FALSE; - } - - *vp = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -/* ------------------------------ File object methods ---------------------------- */ -static JSBool -file_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL); - JSString *strmode, *strtype; - char *ctype, *mode; - int32 mask, type; - int len; - - mode = NULL; - - SECURITY_CHECK(cx, NULL, "open", file); - - /* A native file that is already open */ - if(file->isOpen && file->isNative) { - JS_ReportWarning(cx, "Native file %s is already open, proceeding", - file->path); - goto good; - } - - /* Close before proceeding */ - if (file->isOpen) { - JS_ReportWarning(cx, "File %s is already open, we will close it and " - "reopen, proceeding", file->path); - if(!file_close(cx, obj, 0, NULL, rval)) - goto out; - } - - if (js_isDirectory(cx, file)) { - JS_ReportWarning(cx, "%s seems to be a directory, there is no point in " - "trying to open it, proceeding", file->path); - goto good; - } - - /* Path must be defined at this point */ - len = strlen(file->path); - - /* Mode */ - if (argc >= 1) { - strmode = JS_ValueToString(cx, argv[0]); - if (!strmode) { - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_FIRST_ARGUMENT_OPEN_NOT_STRING_ERROR, - argv[0]); - goto out; - } - mode = JS_strdup(cx, JS_GetStringBytes(strmode)); - } else { - if(file->path[0]==PIPE_SYMBOL) { - /* pipe default mode */ - mode = JS_strdup(cx, "read"); - } else if(file->path[len-1]==PIPE_SYMBOL) { - /* pipe default mode */ - mode = JS_strdup(cx, "write"); - } else { - /* non-destructive, permissive defaults. */ - mode = JS_strdup(cx, "readWrite,append,create"); - } - } - - /* Process the mode */ - mask = 0; - /* TODO: this is pretty ugly, we walk thru the string too many times */ - mask |= js_FileHasOption(cx, mode, "read") ? PR_RDONLY : 0; - mask |= js_FileHasOption(cx, mode, "write") ? PR_WRONLY : 0; - mask |= js_FileHasOption(cx, mode, "readWrite")? PR_RDWR : 0; - mask |= js_FileHasOption(cx, mode, "append") ? PR_APPEND : 0; - mask |= js_FileHasOption(cx, mode, "create") ? PR_CREATE_FILE : 0; - mask |= js_FileHasOption(cx, mode, "replace") ? PR_TRUNCATE : 0; - - if (mask & PR_RDWR) - mask |= (PR_RDONLY | PR_WRONLY); - if ((mask & PR_RDONLY) && (mask & PR_WRONLY)) - mask |= PR_RDWR; - - file->hasAutoflush |= js_FileHasOption(cx, mode, "autoflush"); - - /* Type */ - if (argc > 1) { - strtype = JS_ValueToString(cx, argv[1]); - if (!strtype) { - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_SECOND_ARGUMENT_OPEN_NOT_STRING_ERROR, - argv[1]); - goto out; - } - ctype = JS_GetStringBytes(strtype); - - if(!strcmp(ctype, utfstring)) { - type = UTF8; - } else if (!strcmp(ctype, unicodestring)) { - type = UCS2; - } else { - if (strcmp(ctype, asciistring)) { - JS_ReportWarning(cx, "File type %s is not supported, using " - "'text' instead, proceeding", ctype); - } - type = ASCII; - } - } else { - type = ASCII; - } - - /* Save the relevant fields */ - file->type = type; - file->mode = mask; - file->nativehandle = NULL; - file->hasRandomAccess = (type != UTF8); - - /* - * Deal with pipes here. We can't use NSPR for pipes, so we have to use - * POPEN. - */ - if (file->path[0]==PIPE_SYMBOL || file->path[len-1]==PIPE_SYMBOL) { - if (file->path[0] == PIPE_SYMBOL && file->path[len-1] == PIPE_SYMBOL) { - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_BIDIRECTIONAL_PIPE_NOT_SUPPORTED); - goto out; - } else { - int i = 0; - char pipemode[3]; - SECURITY_CHECK(cx, NULL, "pipe_open", file); - - if(file->path[0] == PIPE_SYMBOL){ - if(mask & (PR_WRONLY | PR_APPEND | PR_CREATE_FILE | PR_TRUNCATE)){ - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_OPEN_MODE_NOT_SUPPORTED_WITH_PIPES, - mode, file->path); - goto out; - } - /* open(SPOOLER, "| cat -v | lpr -h 2>/dev/null") -- pipe for writing */ - pipemode[i++] = 'r'; -#ifndef XP_UNIX - pipemode[i++] = file->type==UTF8 ? 'b' : 't'; -#endif - pipemode[i++] = '\0'; - file->nativehandle = POPEN(&file->path[1], pipemode); - } else if(file->path[len-1] == PIPE_SYMBOL) { - char *command = JS_malloc(cx, len); - - strncpy(command, file->path, len-1); - command[len-1] = '\0'; - /* open(STATUS, "netstat -an 2>&1 |") */ - pipemode[i++] = 'w'; -#ifndef XP_UNIX - pipemode[i++] = file->type==UTF8 ? 'b' : 't'; -#endif - pipemode[i++] = '\0'; - file->nativehandle = POPEN(command, pipemode); - JS_free(cx, command); - } - /* set the flags */ - file->isNative = JS_TRUE; - file->isPipe = JS_TRUE; - file->hasRandomAccess = JS_FALSE; - } - } else { - /* TODO: what about the permissions?? Java ignores the problem... */ - file->handle = PR_Open(file->path, mask, 0644); - } - - js_ResetBuffers(file); - JS_free(cx, mode); - mode = NULL; - - /* Set the open flag and return result */ - if (file->handle == NULL && file->nativehandle == NULL) { - file->isOpen = JS_FALSE; - - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_OP_FAILED, "open", file->path); - goto out; - } - -good: - file->isOpen = JS_TRUE; - *rval = JSVAL_TRUE; - return JS_TRUE; - -out: - if(mode) - JS_free(cx, mode); - return JS_FALSE; -} - -static JSBool -file_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL); - - SECURITY_CHECK(cx, NULL, "close", file); - - if(!file->isOpen){ - JS_ReportWarning(cx, "File %s is not open, can't close it, proceeding", - file->path); - goto out; - } - - if(!file->isPipe){ - if(file->isNative){ - JS_ReportWarning(cx, "Unable to close a native file, proceeding", file->path); - goto out; - }else{ - if(file->handle && PR_Close(file->handle)){ - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_OP_FAILED, "close", file->path); - - goto out; - } - } - }else{ - if(PCLOSE(file->nativehandle)==-1){ - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_OP_FAILED, "pclose", file->path); - goto out; - } - } - - js_ResetAttributes(file); - *rval = JSVAL_TRUE; - return JS_TRUE; - -out: - return JS_FALSE; -} - - -static JSBool -file_remove(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL); - - SECURITY_CHECK(cx, NULL, "remove", file); - JSFILE_CHECK_NATIVE("remove"); - JSFILE_CHECK_CLOSED("remove"); - - if ((js_isDirectory(cx, file) ? - PR_RmDir(file->path) : PR_Delete(file->path))==PR_SUCCESS) { - js_ResetAttributes(file); - *rval = JSVAL_TRUE; - return JS_TRUE; - } else { - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_OP_FAILED, "remove", file->path); - goto out; - } -out: - *rval = JSVAL_FALSE; - return JS_FALSE; -} - -/* Raw PR-based function. No text processing. Just raw data copying. */ -static JSBool -file_copyTo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL); - char *dest = NULL; - PRFileDesc *handle = NULL; - char *buffer; - jsval count, size; - JSBool fileInitiallyOpen=JS_FALSE; - - SECURITY_CHECK(cx, NULL, "copyTo", file); /* may need a second argument!*/ - JSFILE_CHECK_ONE_ARG("copyTo"); - JSFILE_CHECK_NATIVE("copyTo"); - /* remeber the state */ - fileInitiallyOpen = file->isOpen; - JSFILE_CHECK_READ; - - dest = JS_GetStringBytes(JS_ValueToString(cx, argv[0])); - - /* make sure we are not reading a file open for writing */ - if (file->isOpen && !js_canRead(cx, file)) { - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_CANNOT_COPY_FILE_OPEN_FOR_WRITING_ERROR, file->path); - goto out; - } - - if (file->handle==NULL){ - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_OP_FAILED, "open", file->path); - goto out; - } - - handle = PR_Open(dest, PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE, 0644); - - if(!handle){ - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_OP_FAILED, "open", dest); - goto out; - } - - if ((size=js_size(cx, file))==JSVAL_VOID) { - goto out; - } - - buffer = JS_malloc(cx, size); - - count = INT_TO_JSVAL(PR_Read(file->handle, buffer, size)); - - /* reading panic */ - if (count!=size) { - JS_free(cx, buffer); - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_COPY_READ_ERROR, file->path); - goto out; - } - - count = INT_TO_JSVAL(PR_Write(handle, buffer, JSVAL_TO_INT(size))); - - /* writing panic */ - if (count!=size) { - JS_free(cx, buffer); - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_COPY_WRITE_ERROR, file->path); - goto out; - } - - JS_free(cx, buffer); - - if(!fileInitiallyOpen){ - if(!file_close(cx, obj, 0, NULL, rval)) goto out; - } - - if(PR_Close(handle)!=PR_SUCCESS){ - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_OP_FAILED, "close", dest); - goto out; - } - - *rval = JSVAL_TRUE; - return JS_TRUE; -out: - if(file->isOpen && !fileInitiallyOpen){ - if(PR_Close(file->handle)!=PR_SUCCESS){ - JS_ReportWarning(cx, "Can't close %s, proceeding", file->path); - } - } - - if(handle && PR_Close(handle)!=PR_SUCCESS){ - JS_ReportWarning(cx, "Can't close %s, proceeding", dest); - } - - *rval = JSVAL_FALSE; - return JS_FALSE; -} - -static JSBool -file_renameTo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL); - char *dest; - - SECURITY_CHECK(cx, NULL, "renameTo", file); /* may need a second argument!*/ - JSFILE_CHECK_ONE_ARG("renameTo"); - JSFILE_CHECK_NATIVE("renameTo"); - JSFILE_CHECK_CLOSED("renameTo"); - - dest = RESOLVE_PATH(cx, JS_GetStringBytes(JS_ValueToString(cx, argv[0]))); - - if (PR_Rename(file->path, dest)==PR_SUCCESS){ - /* copy the new filename */ - JS_free(cx, file->path); - file->path = dest; - *rval = JSVAL_TRUE; - return JS_TRUE; - }else{ - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_RENAME_FAILED, file->path, dest); - goto out; - } -out: - *rval = JSVAL_FALSE; - return JS_FALSE; -} - -static JSBool -file_flush(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL); - - SECURITY_CHECK(cx, NULL, "flush", file); - JSFILE_CHECK_NATIVE("flush"); - JSFILE_CHECK_OPEN("flush"); - - if (PR_Sync(file->handle)==PR_SUCCESS){ - *rval = JSVAL_TRUE; - return JS_TRUE; - }else{ - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_OP_FAILED, "flush", file->path); - goto out; - } -out: - *rval = JSVAL_FALSE; - return JS_FALSE; -} - -static JSBool -file_write(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL); - JSString *str; - int32 count; - uintN i; - - SECURITY_CHECK(cx, NULL, "write", file); - JSFILE_CHECK_WRITE; - - for (i = 0; itype); - if (count==-1){ - *rval = JSVAL_FALSE; - return JS_FALSE; - } - } - - *rval = JSVAL_TRUE; - return JS_TRUE; -out: - *rval = JSVAL_FALSE; - return JS_FALSE; -} - -static JSBool -file_writeln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL); - JSString *str; - - SECURITY_CHECK(cx, NULL, "writeln", file); - JSFILE_CHECK_WRITE; - - /* don't report an error here */ - if(!file_write(cx, obj, argc, argv, rval)) return JS_FALSE; - /* don't do security here -- we passed the check in file_write */ - str = JS_NewStringCopyZ(cx, "\n"); - - if (js_FileWrite(cx, file, JS_GetStringChars(str), JS_GetStringLength(str), - file->type)==-1){ - *rval = JSVAL_FALSE; - return JS_FALSE; - } - - /* eol causes flush if hasAutoflush is turned on */ - if (file->hasAutoflush) - file_flush(cx, obj, 0, NULL, rval); - - *rval = JSVAL_TRUE; - return JS_TRUE; -out: - *rval = JSVAL_FALSE; - return JS_FALSE; -} - -static JSBool -file_writeAll(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL); - jsuint i; - jsuint limit; - JSObject *array; - JSObject *elem; - jsval elemval; - - SECURITY_CHECK(cx, NULL, "writeAll", file); - JSFILE_CHECK_ONE_ARG("writeAll"); - JSFILE_CHECK_WRITE; - - if (!JS_IsArrayObject(cx, JSVAL_TO_OBJECT(argv[0]))) { - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_FIRST_ARGUMENT_WRITEALL_NOT_ARRAY_ERROR); - goto out; - } - - array = JSVAL_TO_OBJECT(argv[0]); - - JS_GetArrayLength(cx, array, &limit); - - for (i = 0; i262144)?262144:want; * arbitrary size limitation */ - - buf = JS_malloc(cx, want*sizeof buf[0]); - if (!buf) goto out; - - count = js_FileRead(cx, file, buf, want, file->type); - if (count>0) { - str = JS_NewUCStringCopyN(cx, buf, count); - *rval = STRING_TO_JSVAL(str); - JS_free(cx, buf); - return JS_TRUE; - } else { - JS_free(cx, buf); - goto out; - } -out: - *rval = JSVAL_FALSE; - return JS_FALSE; -} - -static JSBool -file_readln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL); - JSString *str; - jschar *buf = NULL, *tmp; - int32 offset, read; - intN room; - jschar data, data2; - - SECURITY_CHECK(cx, NULL, "readln", file); - JSFILE_CHECK_READ; - - buf = JS_malloc(cx, MAX_LINE_LENGTH * sizeof data); - if (!buf) - return JS_FALSE; - - room = MAX_LINE_LENGTH - 1; - offset = 0; - - for (;;) { - read = js_FileRead(cx, file, &data, 1, file->type); - if (read < 0) - goto out; - if (read == 0) - goto eof; - - switch (data) { - case '\r': - read = js_FileRead(cx, file, &data2, 1, file->type); - if (read < 0) - goto out; - - if (read == 1 && data2 != '\n') { - /* We read one char too far. Buffer it. */ - file->charBuffer = data2; - file->charBufferUsed = JS_TRUE; - } - - /* Fall through. */ - case '\n': - goto done; - - default: - if (--room < 0) { - tmp = JS_realloc(cx, buf, - (offset + MAX_LINE_LENGTH) * sizeof data); - if (!tmp) - goto out; - - room = MAX_LINE_LENGTH - 1; - buf = tmp; - } - - buf[offset++] = data; - break; - } - } - -eof: - if (offset == 0) { - *rval = JSVAL_NULL; - return JS_TRUE; - } - -done: - buf[offset] = 0; - tmp = JS_realloc(cx, buf, (offset + 1) * sizeof data); - if (!tmp) - goto out; - - str = JS_NewUCString(cx, tmp, offset); - if (!str) - goto out; - - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; - -out: - if (buf) - JS_free(cx, buf); - - return JS_FALSE; -} - -static JSBool -file_readAll(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL); - JSObject *array; - jsint len; - jsval line; - JSBool lineok = JS_FALSE; - - SECURITY_CHECK(cx, NULL, "readAll", file); - JSFILE_CHECK_READ; - - array = JS_NewArrayObject(cx, 0, NULL); - if (!array) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(array); - - len = 0; - - lineok = file_readln(cx, obj, 0, NULL, &line); - while (lineok && !JSVAL_IS_NULL(line)) { - JS_SetElement(cx, array, len++, &line); - lineok = file_readln(cx, obj, 0, NULL, &line); - } - -out: - return lineok; -} - -static JSBool -file_seek(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL); - int32 toskip; - int32 pos; - - SECURITY_CHECK(cx, NULL, "seek", file); - JSFILE_CHECK_ONE_ARG("seek"); - JSFILE_CHECK_NATIVE("seek"); - JSFILE_CHECK_READ; - - if (!JS_ValueToInt32(cx, argv[0], &toskip)){ - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_NUMBER, "seek", argv[0]); - goto out; - } - - if(!file->hasRandomAccess){ - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_NO_RANDOM_ACCESS, file->path); - goto out; - } - - if(js_isDirectory(cx, file)){ - JS_ReportWarning(cx,"Seek on directories is not supported, proceeding"); - goto out; - } - - pos = js_FileSeek(cx, file, toskip, file->type); - - if (pos!=-1) { - *rval = INT_TO_JSVAL(pos); - return JS_TRUE; - } -out: - *rval = JSVAL_VOID; - return JS_FALSE; -} - -static JSBool -file_list(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - PRDir *dir; - PRDirEntry *entry; - JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL); - JSObject *array; - JSObject *eachFile; - jsint len; - jsval v; - JSRegExp *re = NULL; - JSFunction *func = NULL; - JSString *str; - jsval args[1]; - char *filePath; - - SECURITY_CHECK(cx, NULL, "list", file); - JSFILE_CHECK_NATIVE("list"); - - if (argc==1) { - if (JSVAL_IS_REGEXP(cx, argv[0])) { - re = JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0])); - }else - if (JSVAL_IS_FUNCTION(cx, argv[0])) { - func = JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0])); - }else{ - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_FUNCTION_OR_REGEX, argv[0]); - goto out; - } - } - - if (!js_isDirectory(cx, file)) { - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_CANNOT_DO_LIST_ON_A_FILE, file->path); - goto out; - } - - dir = PR_OpenDir(file->path); - if(!dir){ - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_OP_FAILED, "open", file->path); - goto out; - } - - /* create JSArray here... */ - array = JS_NewArrayObject(cx, 0, NULL); - len = 0; - - while ((entry = PR_ReadDir(dir, PR_SKIP_BOTH))!=NULL) { - /* first, check if we have a regexp */ - if (re!=NULL) { - size_t index = 0; - - str = JS_NewStringCopyZ(cx, entry->name); - if(!js_ExecuteRegExp(cx, re, str, &index, JS_TRUE, &v)){ - /* don't report anything here */ - goto out; - } - /* not matched! */ - if (JSVAL_IS_NULL(v)) { - continue; - } - }else - if (func!=NULL) { - str = JS_NewStringCopyZ(cx, entry->name); - args[0] = STRING_TO_JSVAL(str); - if(!JS_CallFunction(cx, obj, func, 1, args, &v)){ - goto out; - } - - if (v==JSVAL_FALSE) { - continue; - } - } - - filePath = js_combinePath(cx, file->path, (char*)entry->name); - - eachFile = js_NewFileObject(cx, filePath); - JS_free(cx, filePath); - if (!eachFile){ - JS_ReportWarning(cx, "File %s cannot be retrieved", filePath); - continue; - } - v = OBJECT_TO_JSVAL(eachFile); - JS_SetElement(cx, array, len, &v); - JS_SetProperty(cx, array, entry->name, &v); - len++; - } - - if(PR_CloseDir(dir)!=PR_SUCCESS){ - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_OP_FAILED, "close", file->path); - goto out; - } - *rval = OBJECT_TO_JSVAL(array); - return JS_TRUE; -out: - *rval = JSVAL_NULL; - return JS_FALSE; -} - -static JSBool -file_mkdir(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL); - - SECURITY_CHECK(cx, NULL, "mkdir", file); - JSFILE_CHECK_ONE_ARG("mkdir"); - JSFILE_CHECK_NATIVE("mkdir"); - - /* if the current file is not a directory, find out the directory name */ - if (!js_isDirectory(cx, file)) { - char *dir = js_fileDirectoryName(cx, file->path); - JSObject *dirObj = js_NewFileObject(cx, dir); - - JS_free(cx, dir); - - /* call file_mkdir with the right set of parameters if needed */ - if (file_mkdir(cx, dirObj, argc, argv, rval)) - return JS_TRUE; - else - goto out; - }else{ - char *dirName = JS_GetStringBytes(JS_ValueToString(cx, argv[0])); - char *fullName; - - fullName = js_combinePath(cx, file->path, dirName); - if (PR_MkDir(fullName, 0755)==PR_SUCCESS){ - *rval = JSVAL_TRUE; - JS_free(cx, fullName); - return JS_TRUE; - }else{ - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_OP_FAILED, "mkdir", fullName); - JS_free(cx, fullName); - goto out; - } - } -out: - *rval = JSVAL_FALSE; - return JS_FALSE; -} - -static JSBool -file_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval*rval) -{ - JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL); - - *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, file->path)); - return JS_TRUE; -} - -static JSBool -file_toURL(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL); - char url[MAX_PATH_LENGTH]; - jschar *urlChars; - - JSFILE_CHECK_NATIVE("toURL"); - - sprintf(url, "file://%s", file->path); - /* TODO: js_escape in jsstr.h may go away at some point */ - - urlChars = js_InflateString(cx, url, strlen(url)); - if (urlChars == NULL) return JS_FALSE; - *rval = STRING_TO_JSVAL(js_NewString(cx, urlChars, strlen(url), 0)); - if (!js_str_escape(cx, obj, 0, rval, rval)) return JS_FALSE; - - return JS_TRUE; -out: - *rval = JSVAL_VOID; - return JS_FALSE; -} - - -static void -file_finalize(JSContext *cx, JSObject *obj) -{ - JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL); - - if(file) { - /* Close the file before exiting. */ - if(file->isOpen && !file->isNative) { - jsval vp; - file_close(cx, obj, 0, NULL, &vp); - } - - if (file->path) - JS_free(cx, file->path); - - JS_free(cx, file); - } -} - -/* - Allocates memory for the file object, sets fields to defaults. -*/ -static JSFile* -file_init(JSContext *cx, JSObject *obj, char *bytes) -{ - JSFile *file; - - file = JS_malloc(cx, sizeof *file); - if (!file) - return NULL; - memset(file, 0 , sizeof *file); - - js_ResetAttributes(file); - - file->path = RESOLVE_PATH(cx, bytes); - - if (!JS_SetPrivate(cx, obj, file)) { - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_CANNOT_SET_PRIVATE_FILE, file->path); - JS_free(cx, file); - return NULL; - } - - return file; -} - -/* Returns a JSObject. This function is globally visible */ -JS_PUBLIC_API(JSObject*) -js_NewFileObject(JSContext *cx, char *filename) -{ - JSObject *obj; - JSFile *file; - - obj = JS_NewObject(cx, &file_class, NULL, NULL); - if (!obj){ - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_OBJECT_CREATION_FAILED, "js_NewFileObject"); - return NULL; - } - file = file_init(cx, obj, filename); - if(!file) return NULL; - return obj; -} - -/* Internal function, used for cases which NSPR file support doesn't cover */ -JSObject* -js_NewFileObjectFromFILE(JSContext *cx, FILE *nativehandle, char *filename, - int32 mode, JSBool open, JSBool randomAccess) -{ - JSObject *obj; - JSFile *file; - - obj = JS_NewObject(cx, &file_class, NULL, NULL); - if (!obj){ - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_OBJECT_CREATION_FAILED, "js_NewFileObjectFromFILE"); - return NULL; - } - file = file_init(cx, obj, filename); - if(!file) return NULL; - - file->nativehandle = nativehandle; - - /* free result of RESOLVE_PATH from file_init. */ - JS_ASSERT(file->path != NULL); - JS_free(cx, file->path); - - file->path = strdup(filename); - file->isOpen = open; - file->mode = mode; - file->hasRandomAccess = randomAccess; - file->isNative = JS_TRUE; - return obj; -} - -/* - Real file constructor that is called from JavaScript. - Basically, does error processing and calls file_init. -*/ -static JSBool -file_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSString *str; - JSFile *file; - - if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) { - /* Replace obj with a new File object. */ - obj = JS_NewObject(cx, &file_class, NULL, NULL); - if (!obj) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(obj); - } - - str = (argc == 0) - ? JS_InternString(cx, "") - : JS_ValueToString(cx, argv[0]); - - if (!str) { - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_FIRST_ARGUMENT_CONSTRUCTOR_NOT_STRING_ERROR, - argv[0]); - return JS_FALSE; - } - - file = file_init(cx, obj, JS_GetStringBytes(str)); - if (!file) - return JS_FALSE; - - SECURITY_CHECK(cx, NULL, "constructor", file); - - return JS_TRUE; -} - -/* -------------------- File methods and properties ------------------------- */ -static JSFunctionSpec file_functions[] = { - { "open", file_open, 0}, - { "close", file_close, 0}, - { "remove", file_remove, 0}, - { "copyTo", file_copyTo, 0}, - { "renameTo", file_renameTo, 0}, - { "flush", file_flush, 0}, - { "seek", file_seek, 0}, - { "read", file_read, 0}, - { "readln", file_readln, 0}, - { "readAll", file_readAll, 0}, - { "write", file_write, 0}, - { "writeln", file_writeln, 0}, - { "writeAll", file_writeAll, 0}, - { "list", file_list, 0}, - { "mkdir", file_mkdir, 0}, - { "toString", file_toString, 0}, - { "toURL", file_toURL, 0}, - {0} -}; - -enum file_tinyid { - FILE_LENGTH = -2, - FILE_PARENT = -3, - FILE_PATH = -4, - FILE_NAME = -5, - FILE_ISDIR = -6, - FILE_ISFILE = -7, - FILE_EXISTS = -8, - FILE_CANREAD = -9, - FILE_CANWRITE = -10, - FILE_OPEN = -11, - FILE_TYPE = -12, - FILE_MODE = -13, - FILE_CREATED = -14, - FILE_MODIFIED = -15, - FILE_SIZE = -16, - FILE_RANDOMACCESS = -17, - FILE_POSITION = -18, - FILE_APPEND = -19, - FILE_REPLACE = -20, - FILE_AUTOFLUSH = -21, - FILE_ISNATIVE = -22, -}; - -static JSPropertySpec file_props[] = { - {"length", FILE_LENGTH, JSPROP_ENUMERATE | JSPROP_READONLY }, - {"parent", FILE_PARENT, JSPROP_ENUMERATE | JSPROP_READONLY }, - {"path", FILE_PATH, JSPROP_ENUMERATE | JSPROP_READONLY }, - {"name", FILE_NAME, JSPROP_ENUMERATE | JSPROP_READONLY }, - {"isDirectory", FILE_ISDIR, JSPROP_ENUMERATE | JSPROP_READONLY }, - {"isFile", FILE_ISFILE, JSPROP_ENUMERATE | JSPROP_READONLY }, - {"exists", FILE_EXISTS, JSPROP_ENUMERATE | JSPROP_READONLY }, - {"canRead", FILE_CANREAD, JSPROP_ENUMERATE | JSPROP_READONLY }, - {"canWrite", FILE_CANWRITE, JSPROP_ENUMERATE | JSPROP_READONLY }, - {"canAppend", FILE_APPEND, JSPROP_ENUMERATE | JSPROP_READONLY }, - {"canReplace", FILE_REPLACE, JSPROP_ENUMERATE | JSPROP_READONLY }, - {"isOpen", FILE_OPEN, JSPROP_ENUMERATE | JSPROP_READONLY }, - {"type", FILE_TYPE, JSPROP_ENUMERATE | JSPROP_READONLY }, - {"mode", FILE_MODE, JSPROP_ENUMERATE | JSPROP_READONLY }, - {"creationTime", FILE_CREATED, JSPROP_ENUMERATE | JSPROP_READONLY }, - {"lastModified", FILE_MODIFIED, JSPROP_ENUMERATE | JSPROP_READONLY }, - {"size", FILE_SIZE, JSPROP_ENUMERATE | JSPROP_READONLY }, - {"hasRandomAccess", FILE_RANDOMACCESS, JSPROP_ENUMERATE | JSPROP_READONLY }, - {"hasAutoFlush", FILE_AUTOFLUSH, JSPROP_ENUMERATE | JSPROP_READONLY }, - {"position", FILE_POSITION, JSPROP_ENUMERATE }, - {"isNative", FILE_ISNATIVE, JSPROP_ENUMERATE | JSPROP_READONLY }, - {0} -}; - -/* ------------------------- Property getter/setter ------------------------- */ -static JSBool -file_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL); - char *bytes; - JSString *str; - jsint tiny; - PRFileInfo info; - JSBool flag; - PRExplodedTime expandedTime; - - tiny = JSVAL_TO_INT(id); - if (!file) - return JS_TRUE; - - switch (tiny) { - case FILE_PARENT: - SECURITY_CHECK(cx, NULL, "parent", file); - if (!js_parent(cx, file, vp)) - return JS_FALSE; - break; - case FILE_PATH: - str = JS_NewStringCopyZ(cx, file->path); - if (!str) - return JS_FALSE; - *vp = STRING_TO_JSVAL(str); - break; - case FILE_NAME: - if (!js_name(cx, file, vp)) - return JS_FALSE; - break; - case FILE_ISDIR: - SECURITY_CHECK(cx, NULL, "isDirectory", file); - *vp = BOOLEAN_TO_JSVAL(js_isDirectory(cx, file)); - break; - case FILE_ISFILE: - SECURITY_CHECK(cx, NULL, "isFile", file); - *vp = BOOLEAN_TO_JSVAL(js_isFile(cx, file)); - break; - case FILE_EXISTS: - SECURITY_CHECK(cx, NULL, "exists", file); - *vp = BOOLEAN_TO_JSVAL(js_exists(cx, file)); - break; - case FILE_ISNATIVE: - SECURITY_CHECK(cx, NULL, "isNative", file); - *vp = BOOLEAN_TO_JSVAL(file->isNative); - break; - case FILE_CANREAD: - SECURITY_CHECK(cx, NULL, "canRead", file); - *vp = BOOLEAN_TO_JSVAL(js_canRead(cx, file)); - break; - case FILE_CANWRITE: - SECURITY_CHECK(cx, NULL, "canWrite", file); - *vp = BOOLEAN_TO_JSVAL(js_canWrite(cx, file)); - break; - case FILE_OPEN: - SECURITY_CHECK(cx, NULL, "isOpen", file); - *vp = BOOLEAN_TO_JSVAL(file->isOpen); - break; - case FILE_APPEND : - SECURITY_CHECK(cx, NULL, "canAppend", file); - JSFILE_CHECK_OPEN("canAppend"); - *vp = BOOLEAN_TO_JSVAL(!file->isNative && - (file->mode&PR_APPEND)==PR_APPEND); - break; - case FILE_REPLACE : - SECURITY_CHECK(cx, NULL, "canReplace", file); - JSFILE_CHECK_OPEN("canReplace"); - *vp = BOOLEAN_TO_JSVAL(!file->isNative && - (file->mode&PR_TRUNCATE)==PR_TRUNCATE); - break; - case FILE_AUTOFLUSH : - SECURITY_CHECK(cx, NULL, "hasAutoFlush", file); - JSFILE_CHECK_OPEN("hasAutoFlush"); - *vp = BOOLEAN_TO_JSVAL(!file->isNative && file->hasAutoflush); - break; - case FILE_TYPE: - SECURITY_CHECK(cx, NULL, "type", file); - JSFILE_CHECK_OPEN("type"); - if(js_isDirectory(cx, file)){ - *vp = JSVAL_VOID; - break; - } - - switch (file->type) { - case ASCII: - *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, asciistring)); - break; - case UTF8: - *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, utfstring)); - break; - case UCS2: - *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, unicodestring)); - break; - default: - JS_ReportWarning(cx, "Unsupported file type %d, proceeding", - file->type); - } - break; - case FILE_MODE: - SECURITY_CHECK(cx, NULL, "mode", file); - JSFILE_CHECK_OPEN("mode"); - bytes = JS_malloc(cx, MODE_SIZE); - bytes[0] = '\0'; - flag = JS_FALSE; - - if ((file->mode&PR_RDONLY)==PR_RDONLY) { - if (flag) strcat(bytes, ","); - strcat(bytes, "read"); - flag = JS_TRUE; - } - if ((file->mode&PR_WRONLY)==PR_WRONLY) { - if (flag) strcat(bytes, ","); - strcat(bytes, "write"); - flag = JS_TRUE; - } - if ((file->mode&PR_RDWR)==PR_RDWR) { - if (flag) strcat(bytes, ","); - strcat(bytes, "readWrite"); - flag = JS_TRUE; - } - if ((file->mode&PR_APPEND)==PR_APPEND) { - if (flag) strcat(bytes, ","); - strcat(bytes, "append"); - flag = JS_TRUE; - } - if ((file->mode&PR_CREATE_FILE)==PR_CREATE_FILE) { - if (flag) strcat(bytes, ","); - strcat(bytes, "create"); - flag = JS_TRUE; - } - if ((file->mode&PR_TRUNCATE)==PR_TRUNCATE) { - if (flag) strcat(bytes, ","); - strcat(bytes, "replace"); - flag = JS_TRUE; - } - if (file->hasAutoflush) { - if (flag) strcat(bytes, ","); - strcat(bytes, "hasAutoFlush"); - flag = JS_TRUE; - } - *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, bytes)); - JS_free(cx, bytes); - break; - case FILE_CREATED: - SECURITY_CHECK(cx, NULL, "creationTime", file); - JSFILE_CHECK_NATIVE("creationTime"); - if(((file->isOpen)? - PR_GetOpenFileInfo(file->handle, &info): - PR_GetFileInfo(file->path, &info))!=PR_SUCCESS){ - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path); - goto out; - } - - PR_ExplodeTime(info.creationTime, PR_LocalTimeParameters,&expandedTime); - *vp = OBJECT_TO_JSVAL(js_NewDateObject(cx, expandedTime.tm_year, - expandedTime.tm_month, - expandedTime.tm_mday, - expandedTime.tm_hour, - expandedTime.tm_min, - expandedTime.tm_sec)); - break; - case FILE_MODIFIED: - SECURITY_CHECK(cx, NULL, "lastModified", file); - JSFILE_CHECK_NATIVE("lastModified"); - if(((file->isOpen)? - PR_GetOpenFileInfo(file->handle, &info): - PR_GetFileInfo(file->path, &info))!=PR_SUCCESS){ - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path); - goto out; - } - - PR_ExplodeTime(info.modifyTime, PR_LocalTimeParameters, &expandedTime); - *vp = OBJECT_TO_JSVAL(js_NewDateObject(cx, expandedTime.tm_year, - expandedTime.tm_month, - expandedTime.tm_mday, - expandedTime.tm_hour, - expandedTime.tm_min, - expandedTime.tm_sec)); - break; - case FILE_SIZE: - SECURITY_CHECK(cx, NULL, "size", file); - *vp = js_size(cx, file); - break; - case FILE_LENGTH: - SECURITY_CHECK(cx, NULL, "length", file); - JSFILE_CHECK_NATIVE("length"); - - if (js_isDirectory(cx, file)) { /* XXX debug me */ - PRDir *dir; - PRDirEntry *entry; - jsint count = 0; - - if(!(dir = PR_OpenDir(file->path))){ - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_CANNOT_OPEN_DIR, file->path); - goto out; - } - - while ((entry = PR_ReadDir(dir, PR_SKIP_BOTH))) { - count++; - } - - if(!PR_CloseDir(dir)){ - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_OP_FAILED, "close", file->path); - - goto out; - } - - *vp = INT_TO_JSVAL(count); - break; - }else{ - /* return file size */ - *vp = js_size(cx, file); - } - break; - case FILE_RANDOMACCESS: - SECURITY_CHECK(cx, NULL, "hasRandomAccess", file); - JSFILE_CHECK_OPEN("hasRandomAccess"); - *vp = BOOLEAN_TO_JSVAL(file->hasRandomAccess); - break; - case FILE_POSITION: - SECURITY_CHECK(cx, NULL, "position", file); - JSFILE_CHECK_NATIVE("position"); - JSFILE_CHECK_OPEN("position"); - - if(!file->hasRandomAccess){ - JS_ReportWarning(cx, "File %s doesn't support random access, can't report the position, proceeding"); - *vp = JSVAL_VOID; - break; - } - - if (file->isOpen && js_isFile(cx, file)) { - int pos = PR_Seek(file->handle, 0, PR_SEEK_CUR); - if(pos!=-1){ - *vp = INT_TO_JSVAL(pos); - }else{ - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_CANNOT_REPORT_POSITION, file->path); - goto out; - } - }else { - JS_ReportWarning(cx, "File %s is closed or not a plain file," - " can't report position, proceeding"); - goto out; - } - break; - default: - SECURITY_CHECK(cx, NULL, "file_access", file); - - /* this is some other property -- try to use the dir["file"] syntax */ - if (js_isDirectory(cx, file)) { - PRDir *dir = NULL; - PRDirEntry *entry = NULL; - char *prop_name; - - str = JS_ValueToString(cx, id); - if (!str) - return JS_FALSE; - - prop_name = JS_GetStringBytes(str); - - /* no native files past this point */ - dir = PR_OpenDir(file->path); - if(!dir) { - /* This is probably not a directory */ - JS_ReportWarning(cx, "Can't open directory %s", file->path); - return JS_FALSE; - } - - while ((entry = PR_ReadDir(dir, PR_SKIP_NONE)) != NULL) { - if (!strcmp(entry->name, prop_name)){ - bytes = js_combinePath(cx, file->path, prop_name); - *vp = OBJECT_TO_JSVAL(js_NewFileObject(cx, bytes)); - JS_free(cx, bytes); - return JS_TRUE; - } - } - } - } - return JS_TRUE; - -out: - return JS_FALSE; -} - -static JSBool -file_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL); - jsint slot; - - if (JSVAL_IS_STRING(id)){ - return JS_TRUE; - } - - slot = JSVAL_TO_INT(id); - - switch (slot) { - /* File.position = 10 */ - case FILE_POSITION: - SECURITY_CHECK(cx, NULL, "set_position", file); - JSFILE_CHECK_NATIVE("set_position"); - - if(!file->hasRandomAccess){ - JS_ReportWarning(cx, "File %s doesn't support random access, can't " - "report the position, proceeding"); - goto out; - } - - if (file->isOpen && js_isFile(cx, file)) { - int32 pos; - int32 offset; - - if (!JS_ValueToInt32(cx, *vp, &offset)){ - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_NUMBER, "position", *vp); - goto out; - } - - pos = PR_Seek(file->handle, offset, PR_SEEK_SET); - - if(pos!=-1){ - *vp = INT_TO_JSVAL(pos); - }else{ - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_CANNOT_SET_POSITION, file->path); - goto out; - } - } else { - JS_ReportWarning(cx, "File %s is closed or not a file, can't set " - "position, proceeding", file->path); - goto out; - } - } - - return JS_TRUE; -out: - return JS_FALSE; -} - -/* - File.currentDir = new File("D:\") or File.currentDir = "D:\" -*/ -static JSBool -file_currentDirSetter(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - JSFile *file; - - file = JS_GetInstancePrivate(cx, obj, &file_class, NULL); - - /* Look at the rhs and extract a file object from it */ - if (JSVAL_IS_OBJECT(*vp)) { - if (JS_InstanceOf(cx, obj, &file_class, NULL)) { - /* Braindamaged rhs -- just return the old value */ - if (file && (!js_exists(cx, file) || !js_isDirectory(cx, file))) { - JS_GetProperty(cx, obj, CURRENTDIR_PROPERTY, vp); - return JS_FALSE; - } else { - chdir(file->path); - return JS_TRUE; - } - } else { - return JS_FALSE; - } - } else { - JSObject *rhsObject; - char *path; - - path = JS_GetStringBytes(JS_ValueToString(cx, *vp)); - rhsObject = js_NewFileObject(cx, path); - if (!rhsObject) - return JS_FALSE; - - if (!file || !js_exists(cx, file) || !js_isDirectory(cx, file)){ - JS_GetProperty(cx, obj, CURRENTDIR_PROPERTY, vp); - } else { - *vp = OBJECT_TO_JSVAL(rhsObject); - chdir(path); - } - } - - return JS_TRUE; -} - -/* Declare class */ -static JSClass file_class = { - FILE_CONSTRUCTOR, JSCLASS_HAS_PRIVATE, - JS_PropertyStub, JS_PropertyStub, file_getProperty, file_setProperty, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, file_finalize -}; - -/* -------------------- Functions exposed to the outside -------------------- */ -JS_PUBLIC_API(JSObject*) -js_InitFileClass(JSContext *cx, JSObject* obj) -{ - JSObject *file, *ctor, *afile; - jsval vp; - char *currentdir; - char separator[2]; - - file = JS_InitClass(cx, obj, NULL, &file_class, file_constructor, 1, - file_props, file_functions, NULL, NULL); - if (!file) { - JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, - JSFILEMSG_INIT_FAILED); - return NULL; - } - - ctor = JS_GetConstructor(cx, file); - if (!ctor) return NULL; - - /* Define CURRENTDIR property. We are doing this to get a - slash at the end of the current dir */ - afile = js_NewFileObject(cx, CURRENT_DIR); - currentdir = JS_malloc(cx, MAX_PATH_LENGTH); - currentdir = getcwd(currentdir, MAX_PATH_LENGTH); - afile = js_NewFileObject(cx, currentdir); - JS_free(cx, currentdir); - vp = OBJECT_TO_JSVAL(afile); - JS_DefinePropertyWithTinyId(cx, ctor, CURRENTDIR_PROPERTY, 0, vp, - JS_PropertyStub, file_currentDirSetter, - JSPROP_ENUMERATE | JSPROP_READONLY ); - - /* Define input */ - vp = OBJECT_TO_JSVAL(js_NewFileObjectFromFILE(cx, stdin, - STDINPUT_NAME, PR_RDONLY, JS_TRUE, JS_FALSE)); - JS_SetProperty(cx, ctor, "input", &vp); - - /* Define output */ - vp = OBJECT_TO_JSVAL(js_NewFileObjectFromFILE(cx, stdout, - STDOUTPUT_NAME, PR_WRONLY, JS_TRUE, JS_FALSE)); - JS_SetProperty(cx, ctor, "output", &vp); - - /* Define error */ - vp = OBJECT_TO_JSVAL(js_NewFileObjectFromFILE(cx, stderr, - STDERROR_NAME, PR_WRONLY, JS_TRUE, JS_FALSE)); - JS_SetProperty(cx, ctor, "error", &vp); - - separator[0] = FILESEPARATOR; - separator[1] = '\0'; - vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, separator)); - JS_DefinePropertyWithTinyId(cx, ctor, SEPARATOR_PROPERTY, 0, vp, - JS_PropertyStub, JS_PropertyStub, - JSPROP_ENUMERATE | JSPROP_READONLY ); - return file; -} -#endif /* JS_HAS_FILE_OBJECT */ diff --git a/lib/javascript/jsfile.h b/lib/javascript/jsfile.h deleted file mode 100644 index 741c5bdd..00000000 --- a/lib/javascript/jsfile.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef _jsfile_h__ -#define _jsfile_h__ - -#if JS_HAS_FILE_OBJECT -extern JS_PUBLIC_API(JSObject*) -js_InitFileClass(JSContext *cx, JSObject* obj); - -extern JS_PUBLIC_API(JSObject*) -js_NewFileObject(JSContext *cx, char *bytes); -#endif /* JS_HAS_FILE_OBJECT */ -#endif /* _jsfile_h__ */ diff --git a/lib/javascript/jsfile.msg b/lib/javascript/jsfile.msg deleted file mode 100644 index 137b35d8..00000000 --- a/lib/javascript/jsfile.msg +++ /dev/null @@ -1,90 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - Error messages for jsfile.c. See js.msg for format specification. -*/ - -MSG_DEF(JSFILEMSG_NOT_AN_ERROR, 0, 0, JSEXN_NONE, "") -MSG_DEF(JSFILEMSG_FILE_CONSTRUCTOR_UNDEFINED_ERROR, 1, 0, JSEXN_NONE, "File constructor is undefined") -MSG_DEF(JSFILEMSG_FILE_CURRENTDIR_UNDEFINED_ERROR, 2, 0, JSEXN_NONE, "File.currentDir is undefined") -MSG_DEF(JSFILEMSG_FIRST_ARGUMENT_OPEN_NOT_STRING_ERROR, 3, 1, JSEXN_NONE, "The first argument {0} to file.open must be a string") -MSG_DEF(JSFILEMSG_SECOND_ARGUMENT_OPEN_NOT_STRING_ERROR, 4, 0, JSEXN_NONE, "The second argument to file.open must be a string") -MSG_DEF(JSFILEMSG_CANNOT_COPY_FILE_OPEN_FOR_WRITING_ERROR, 5, 1, JSEXN_NONE, "Cannot copy file {0} open for writing") -MSG_DEF(JSFILEMSG_CANNOT_ACCESS_FILE_INFO_ERROR, 6, 1, JSEXN_NONE, "Cannot access file information for {0}") -MSG_DEF(JSFILEMSG_COPY_READ_ERROR, 7, 1, JSEXN_NONE, "An error occured while attempting to read a file {0} to copy") -MSG_DEF(JSFILEMSG_COPY_WRITE_ERROR, 8, 1, JSEXN_NONE, "An error occured while attempting to copy into file {0}") -MSG_DEF(JSFILEMSG_EXPECTS_ONE_ARG_ERROR, 9, 0, JSEXN_NONE, "Operation {0} expects one argument, not {1}") -MSG_DEF(JSFILEMSG_CANNOT_FLUSH_CLOSE_FILE_ERROR, 10, 1, JSEXN_NONE, "Cannot flush closed file {0}") -MSG_DEF(JSFILEMSG_CANNOT_OPEN_WRITING_ERROR, 11, 1, JSEXN_NONE, "Cannot open file {0} for writing") -MSG_DEF(JSFILEMSG_WRITEALL_EXPECTS_ONE_ARG_ERROR, 12, 0, JSEXN_NONE, "writeAll expects one argument") -MSG_DEF(JSFILEMSG_FIRST_ARGUMENT_WRITEALL_NOT_ARRAY_ERROR, 13, 0, JSEXN_NONE, "writeAll expects an array as an argument") -MSG_DEF(JSFILEMSG_UNUSED0, 14, 0, JSEXN_NONE, "Unused error message slot") -MSG_DEF(JSFILEMSG_CANNOT_OPEN_FILE_ERROR, 15, 1, JSEXN_NONE, "Cannot open file {0}") -MSG_DEF(JSFILEMSG_FIRST_ARGUMENT_CONSTRUCTOR_NOT_STRING_ERROR, 16, 1, JSEXN_NONE, "The argument to the File constructor {0} must be a string") -MSG_DEF(JSFILEMSG_BIDIRECTIONAL_PIPE_NOT_SUPPORTED, 17, 0, JSEXN_NONE, "Bidirectional pipes are not supported") -MSG_DEF(JSFILEMSG_OPEN_MODE_NOT_SUPPORTED_WITH_PIPES, 18, 2, JSEXN_NONE, "The opening mode you have chosen {0} is not supported by the pipe you are trying to open: {1}") -MSG_DEF(JSFILEMSG_OPEN_FAILED, 19, 1, JSEXN_NONE, "open on file {0} failed") -MSG_DEF(JSFILEMSG_CLOSE_FAILED, 20, 1, JSEXN_NONE, "close on file {0} failed") -MSG_DEF(JSFILEMSG_PCLOSE_FAILED, 21, 1, JSEXN_NONE, "pclose on file {0} failed") -MSG_DEF(JSFILEMSG_REMOVE_FAILED, 22, 1, JSEXN_NONE, "remove on file {0} failed") -MSG_DEF(JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, 23, 1, JSEXN_NONE, "Cannot access file status for {0}") -MSG_DEF(JSFILEMSG_RENAME_FAILED, 24, 2, JSEXN_NONE, "Cannot rename {0} to {1}") -MSG_DEF(JSFILEMSG_WRITE_FAILED, 25, 1, JSEXN_NONE, "Write failed on file {0}") -MSG_DEF(JSFILEMSG_READ_FAILED, 26, 1, JSEXN_NONE, "Read failed on file {0}") -MSG_DEF(JSFILEMSG_SKIP_FAILED, 27, 1, JSEXN_NONE, "Skip failed on file {0}") -MSG_DEF(JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_FUNCTION_OR_REGEX, 28, 1, JSEXN_NONE, "The first argument to file.list must be a function or a regex") -MSG_DEF(JSFILEMSG_CANNOT_DO_LIST_ON_A_FILE, 29, 1, JSEXN_NONE, "{0} must be a directory, cannot do list") -MSG_DEF(JSFILEMSG_NATIVE_OPERATION_IS_NOT_SUPPORTED, 30, 2, JSEXN_NONE, "Native operation {0} is not supported on {1}") -MSG_DEF(JSFILEMSG_CANNOT_SET_PRIVATE_FILE, 31, 1, JSEXN_NONE, "Cannot set private data for file {0}") -MSG_DEF(JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_NUMBER, 32, 2, JSEXN_NONE, "First argument to {0} must be a number, not {1}") -MSG_DEF(JSFILEMSG_CANNOT_WRITE, 33, 1, JSEXN_NONE, "Cannot write to {0}, file mode is different") -MSG_DEF(JSFILEMSG_CANNOT_READ, 34, 1, JSEXN_NONE, "Cannot read from {0}, file mode is different") -MSG_DEF(JSFILEMSG_CANNOT_FLUSH, 35, 1, JSEXN_NONE, "Flush failed on {0}") -MSG_DEF(JSFILEMSG_OP_FAILED, 36, 1, JSEXN_NONE, "File operation {0} failed") -MSG_DEF(JSFILEMSG_FILE_MUST_BE_OPEN, 37, 1, JSEXN_NONE, "File must be open for {0}") -MSG_DEF(JSFILEMSG_FILE_MUST_BE_CLOSED, 38, 1, JSEXN_NONE, "File must be closed for {0}") -MSG_DEF(JSFILEMSG_NO_RANDOM_ACCESS, 39, 1, JSEXN_NONE, "File {0} doesn't allow random access") -MSG_DEF(JSFILEMSG_OBJECT_CREATION_FAILED, 40, 1, JSEXN_NONE, "Couldn't create {0}") -MSG_DEF(JSFILEMSG_CANNOT_OPEN_DIR, 41, 1, JSEXN_NONE, "Couldn't open directory {0}") -MSG_DEF(JSFILEMSG_CANNOT_REPORT_POSITION, 42, 1, JSEXN_NONE, "Couldn't report position for {0}") -MSG_DEF(JSFILEMSG_CANNOT_SET_POSITION, 43, 1, JSEXN_NONE, "Couldn't set position for {0}") -MSG_DEF(JSFILEMSG_INIT_FAILED, 44, 0, JSEXN_NONE, "File class initialization failed") - - diff --git a/lib/javascript/jsfun.c b/lib/javascript/jsfun.c deleted file mode 100644 index 68372e12..00000000 --- a/lib/javascript/jsfun.c +++ /dev/null @@ -1,2258 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sw=4 et tw=78: - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JS function support. - */ -#include "jsstddef.h" -#include -#include "jstypes.h" -#include "jsbit.h" -#include "jsutil.h" /* Added by JSIFY */ -#include "jsapi.h" -#include "jsarray.h" -#include "jsatom.h" -#include "jscntxt.h" -#include "jsconfig.h" -#include "jsdbgapi.h" -#include "jsfun.h" -#include "jsgc.h" -#include "jsinterp.h" -#include "jslock.h" -#include "jsnum.h" -#include "jsobj.h" -#include "jsopcode.h" -#include "jsparse.h" -#include "jsscan.h" -#include "jsscope.h" -#include "jsscript.h" -#include "jsstr.h" -#include "jsexn.h" - -/* Generic function/call/arguments tinyids -- also reflected bit numbers. */ -enum { - CALL_ARGUMENTS = -1, /* predefined arguments local variable */ - CALL_CALLEE = -2, /* reference to active function's object */ - ARGS_LENGTH = -3, /* number of actual args, arity if inactive */ - ARGS_CALLEE = -4, /* reference from arguments to active funobj */ - FUN_ARITY = -5, /* number of formal parameters; desired argc */ - FUN_NAME = -6, /* function name, "" if anonymous */ - FUN_CALLER = -7 /* Function.prototype.caller, backward compat */ -}; - -#if JSFRAME_OVERRIDE_BITS < 8 -# error "not enough override bits in JSStackFrame.flags!" -#endif - -#define TEST_OVERRIDE_BIT(fp, tinyid) \ - ((fp)->flags & JS_BIT(JSFRAME_OVERRIDE_SHIFT - ((tinyid) + 1))) - -#define SET_OVERRIDE_BIT(fp, tinyid) \ - ((fp)->flags |= JS_BIT(JSFRAME_OVERRIDE_SHIFT - ((tinyid) + 1))) - -#if JS_HAS_ARGS_OBJECT - -JSBool -js_GetArgsValue(JSContext *cx, JSStackFrame *fp, jsval *vp) -{ - JSObject *argsobj; - - if (TEST_OVERRIDE_BIT(fp, CALL_ARGUMENTS)) { - JS_ASSERT(fp->callobj); - return OBJ_GET_PROPERTY(cx, fp->callobj, - ATOM_TO_JSID(cx->runtime->atomState - .argumentsAtom), - vp); - } - argsobj = js_GetArgsObject(cx, fp); - if (!argsobj) - return JS_FALSE; - *vp = OBJECT_TO_JSVAL(argsobj); - return JS_TRUE; -} - -static JSBool -MarkArgDeleted(JSContext *cx, JSStackFrame *fp, uintN slot) -{ - JSObject *argsobj; - jsval bmapval, bmapint; - size_t nbits, nbytes; - jsbitmap *bitmap; - - argsobj = fp->argsobj; - (void) JS_GetReservedSlot(cx, argsobj, 0, &bmapval); - nbits = fp->argc; - JS_ASSERT(slot < nbits); - if (JSVAL_IS_VOID(bmapval)) { - if (nbits <= JSVAL_INT_BITS) { - bmapint = 0; - bitmap = (jsbitmap *) &bmapint; - } else { - nbytes = JS_HOWMANY(nbits, JS_BITS_PER_WORD) * sizeof(jsbitmap); - bitmap = (jsbitmap *) JS_malloc(cx, nbytes); - if (!bitmap) - return JS_FALSE; - memset(bitmap, 0, nbytes); - bmapval = PRIVATE_TO_JSVAL(bitmap); - JS_SetReservedSlot(cx, argsobj, 0, bmapval); - } - } else { - if (nbits <= JSVAL_INT_BITS) { - bmapint = JSVAL_TO_INT(bmapval); - bitmap = (jsbitmap *) &bmapint; - } else { - bitmap = (jsbitmap *) JSVAL_TO_PRIVATE(bmapval); - } - } - JS_SET_BIT(bitmap, slot); - if (bitmap == (jsbitmap *) &bmapint) { - bmapval = INT_TO_JSVAL(bmapint); - JS_SetReservedSlot(cx, argsobj, 0, bmapval); - } - return JS_TRUE; -} - -/* NB: Infallible predicate, false does not mean error/exception. */ -static JSBool -ArgWasDeleted(JSContext *cx, JSStackFrame *fp, uintN slot) -{ - JSObject *argsobj; - jsval bmapval, bmapint; - jsbitmap *bitmap; - - argsobj = fp->argsobj; - (void) JS_GetReservedSlot(cx, argsobj, 0, &bmapval); - if (JSVAL_IS_VOID(bmapval)) - return JS_FALSE; - if (fp->argc <= JSVAL_INT_BITS) { - bmapint = JSVAL_TO_INT(bmapval); - bitmap = (jsbitmap *) &bmapint; - } else { - bitmap = (jsbitmap *) JSVAL_TO_PRIVATE(bmapval); - } - return JS_TEST_BIT(bitmap, slot) != 0; -} - -JSBool -js_GetArgsProperty(JSContext *cx, JSStackFrame *fp, jsid id, - JSObject **objp, jsval *vp) -{ - jsval val; - JSObject *obj; - uintN slot; - - if (TEST_OVERRIDE_BIT(fp, CALL_ARGUMENTS)) { - JS_ASSERT(fp->callobj); - if (!OBJ_GET_PROPERTY(cx, fp->callobj, - ATOM_TO_JSID(cx->runtime->atomState - .argumentsAtom), - &val)) { - return JS_FALSE; - } - if (JSVAL_IS_PRIMITIVE(val)) { - obj = js_ValueToNonNullObject(cx, val); - if (!obj) - return JS_FALSE; - } else { - obj = JSVAL_TO_OBJECT(val); - } - *objp = obj; - return OBJ_GET_PROPERTY(cx, obj, id, vp); - } - - *objp = NULL; - *vp = JSVAL_VOID; - if (JSID_IS_INT(id)) { - slot = (uintN) JSID_TO_INT(id); - if (slot < fp->argc) { - if (fp->argsobj && ArgWasDeleted(cx, fp, slot)) - return OBJ_GET_PROPERTY(cx, fp->argsobj, id, vp); - *vp = fp->argv[slot]; - } else { - /* - * Per ECMA-262 Ed. 3, 10.1.8, last bulleted item, do not share - * storage between the formal parameter and arguments[k] for all - * k >= fp->argc && k < fp->fun->nargs. For example, in - * - * function f(x) { x = 42; return arguments[0]; } - * f(); - * - * the call to f should return undefined, not 42. If fp->argsobj - * is null at this point, as it would be in the example, return - * undefined in *vp. - */ - if (fp->argsobj) - return OBJ_GET_PROPERTY(cx, fp->argsobj, id, vp); - } - } else { - if (id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom)) { - if (fp->argsobj && TEST_OVERRIDE_BIT(fp, ARGS_LENGTH)) - return OBJ_GET_PROPERTY(cx, fp->argsobj, id, vp); - *vp = INT_TO_JSVAL((jsint) fp->argc); - } - } - return JS_TRUE; -} - -JSObject * -js_GetArgsObject(JSContext *cx, JSStackFrame *fp) -{ - JSObject *argsobj; - - /* Skip eval and debugger frames. */ - while (fp->flags & JSFRAME_SPECIAL) - fp = fp->down; - - /* Create an arguments object for fp only if it lacks one. */ - argsobj = fp->argsobj; - if (argsobj) - return argsobj; - - /* Link the new object to fp so it can get actual argument values. */ - argsobj = js_NewObject(cx, &js_ArgumentsClass, NULL, NULL); - if (!argsobj || !JS_SetPrivate(cx, argsobj, fp)) { - cx->newborn[GCX_OBJECT] = NULL; - return NULL; - } - fp->argsobj = argsobj; - return argsobj; -} - -static JSBool -args_enumerate(JSContext *cx, JSObject *obj); - -JSBool -js_PutArgsObject(JSContext *cx, JSStackFrame *fp) -{ - JSObject *argsobj; - jsval bmapval, rval; - JSBool ok; - JSRuntime *rt; - - /* - * Reuse args_enumerate here to reflect fp's actual arguments as indexed - * elements of argsobj. Do this first, before clearing and freeing the - * deleted argument slot bitmap, because args_enumerate depends on that. - */ - argsobj = fp->argsobj; - ok = args_enumerate(cx, argsobj); - - /* - * Now clear the deleted argument number bitmap slot and free the bitmap, - * if one was actually created due to 'delete arguments[0]' or similar. - */ - (void) JS_GetReservedSlot(cx, argsobj, 0, &bmapval); - if (!JSVAL_IS_VOID(bmapval)) { - JS_SetReservedSlot(cx, argsobj, 0, JSVAL_VOID); - if (fp->argc > JSVAL_INT_BITS) - JS_free(cx, JSVAL_TO_PRIVATE(bmapval)); - } - - /* - * Now get the prototype properties so we snapshot fp->fun and fp->argc - * before fp goes away. - */ - rt = cx->runtime; - ok &= js_GetProperty(cx, argsobj, ATOM_TO_JSID(rt->atomState.calleeAtom), - &rval); - ok &= js_SetProperty(cx, argsobj, ATOM_TO_JSID(rt->atomState.calleeAtom), - &rval); - ok &= js_GetProperty(cx, argsobj, ATOM_TO_JSID(rt->atomState.lengthAtom), - &rval); - ok &= js_SetProperty(cx, argsobj, ATOM_TO_JSID(rt->atomState.lengthAtom), - &rval); - - /* - * Clear the private pointer to fp, which is about to go away (js_Invoke). - * Do this last because the args_enumerate and js_GetProperty calls above - * need to follow the private slot to find fp. - */ - ok &= JS_SetPrivate(cx, argsobj, NULL); - fp->argsobj = NULL; - return ok; -} - -static JSBool -args_delProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - jsint slot; - JSStackFrame *fp; - - if (!JSVAL_IS_INT(id)) - return JS_TRUE; - fp = (JSStackFrame *) - JS_GetInstancePrivate(cx, obj, &js_ArgumentsClass, NULL); - if (!fp) - return JS_TRUE; - JS_ASSERT(fp->argsobj); - - slot = JSVAL_TO_INT(id); - switch (slot) { - case ARGS_CALLEE: - case ARGS_LENGTH: - SET_OVERRIDE_BIT(fp, slot); - break; - - default: - if ((uintN)slot < fp->argc && !MarkArgDeleted(cx, fp, slot)) - return JS_FALSE; - break; - } - return JS_TRUE; -} - -static JSBool -args_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - jsint slot; - JSStackFrame *fp; - - if (!JSVAL_IS_INT(id)) - return JS_TRUE; - fp = (JSStackFrame *) - JS_GetInstancePrivate(cx, obj, &js_ArgumentsClass, NULL); - if (!fp) - return JS_TRUE; - JS_ASSERT(fp->argsobj); - - slot = JSVAL_TO_INT(id); - switch (slot) { - case ARGS_CALLEE: - if (!TEST_OVERRIDE_BIT(fp, slot)) - *vp = fp->argv ? fp->argv[-2] : OBJECT_TO_JSVAL(fp->fun->object); - break; - - case ARGS_LENGTH: - if (!TEST_OVERRIDE_BIT(fp, slot)) - *vp = INT_TO_JSVAL((jsint)fp->argc); - break; - - default: - if ((uintN)slot < fp->argc && !ArgWasDeleted(cx, fp, slot)) - *vp = fp->argv[slot]; - break; - } - return JS_TRUE; -} - -static JSBool -args_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - JSStackFrame *fp; - jsint slot; - - if (!JSVAL_IS_INT(id)) - return JS_TRUE; - fp = (JSStackFrame *) - JS_GetInstancePrivate(cx, obj, &js_ArgumentsClass, NULL); - if (!fp) - return JS_TRUE; - JS_ASSERT(fp->argsobj); - - slot = JSVAL_TO_INT(id); - switch (slot) { - case ARGS_CALLEE: - case ARGS_LENGTH: - SET_OVERRIDE_BIT(fp, slot); - break; - - default: - if (fp->fun->interpreted && - (uintN)slot < fp->argc && - !ArgWasDeleted(cx, fp, slot)) { - fp->argv[slot] = *vp; - } - break; - } - return JS_TRUE; -} - -static JSBool -args_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, - JSObject **objp) -{ - JSStackFrame *fp; - uintN slot; - JSString *str; - JSAtom *atom; - intN tinyid; - jsval value; - - *objp = NULL; - fp = (JSStackFrame *) - JS_GetInstancePrivate(cx, obj, &js_ArgumentsClass, NULL); - if (!fp) - return JS_TRUE; - JS_ASSERT(fp->argsobj); - - if (JSVAL_IS_INT(id)) { - slot = JSVAL_TO_INT(id); - if (slot < fp->argc && !ArgWasDeleted(cx, fp, slot)) { - /* XXX ECMA specs DontEnum, contrary to other array-like objects */ - if (!js_DefineProperty(cx, obj, INT_JSVAL_TO_JSID(id), - fp->argv[slot], - args_getProperty, args_setProperty, - JS_VERSION_IS_ECMA(cx) - ? 0 - : JSPROP_ENUMERATE, - NULL)) { - return JS_FALSE; - } - *objp = obj; - } - } else { - str = JSVAL_TO_STRING(id); - atom = cx->runtime->atomState.lengthAtom; - if (str == ATOM_TO_STRING(atom)) { - tinyid = ARGS_LENGTH; - value = INT_TO_JSVAL(fp->argc); - } else { - atom = cx->runtime->atomState.calleeAtom; - if (str == ATOM_TO_STRING(atom)) { - tinyid = ARGS_CALLEE; - value = fp->argv ? fp->argv[-2] - : OBJECT_TO_JSVAL(fp->fun->object); - } else { - atom = NULL; - - /* Quell GCC overwarnings. */ - tinyid = 0; - value = JSVAL_NULL; - } - } - - if (atom && !TEST_OVERRIDE_BIT(fp, tinyid)) { - if (!js_DefineNativeProperty(cx, obj, ATOM_TO_JSID(atom), value, - args_getProperty, args_setProperty, 0, - SPROP_HAS_SHORTID, tinyid, NULL)) { - return JS_FALSE; - } - *objp = obj; - } - } - - return JS_TRUE; -} - -static JSBool -args_enumerate(JSContext *cx, JSObject *obj) -{ - JSStackFrame *fp; - JSObject *pobj; - JSProperty *prop; - uintN slot, argc; - - fp = (JSStackFrame *) - JS_GetInstancePrivate(cx, obj, &js_ArgumentsClass, NULL); - if (!fp) - return JS_TRUE; - JS_ASSERT(fp->argsobj); - - /* - * Trigger reflection with value snapshot in args_resolve using a series - * of js_LookupProperty calls. We handle length, callee, and the indexed - * argument properties. We know that args_resolve covers all these cases - * and creates direct properties of obj, but that it may fail to resolve - * length or callee if overridden. - */ - if (!js_LookupProperty(cx, obj, - ATOM_TO_JSID(cx->runtime->atomState.lengthAtom), - &pobj, &prop)) { - return JS_FALSE; - } - if (prop) - OBJ_DROP_PROPERTY(cx, pobj, prop); - - if (!js_LookupProperty(cx, obj, - ATOM_TO_JSID(cx->runtime->atomState.calleeAtom), - &pobj, &prop)) { - return JS_FALSE; - } - if (prop) - OBJ_DROP_PROPERTY(cx, pobj, prop); - - argc = fp->argc; - for (slot = 0; slot < argc; slot++) { - if (!js_LookupProperty(cx, obj, INT_TO_JSID((jsint)slot), &pobj, &prop)) - return JS_FALSE; - if (prop) - OBJ_DROP_PROPERTY(cx, pobj, prop); - } - return JS_TRUE; -} - -/* - * The Arguments class is not initialized via JS_InitClass, and must not be, - * because its name is "Object". Per ECMA, that causes instances of it to - * delegate to the object named by Object.prototype. It also ensures that - * arguments.toString() returns "[object Object]". - * - * The JSClass functions below collaborate to lazily reflect and synchronize - * actual argument values, argument count, and callee function object stored - * in a JSStackFrame with their corresponding property values in the frame's - * arguments object. - */ -JSClass js_ArgumentsClass = { - js_Object_str, - JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_HAS_RESERVED_SLOTS(1), - JS_PropertyStub, args_delProperty, - args_getProperty, args_setProperty, - args_enumerate, (JSResolveOp) args_resolve, - JS_ConvertStub, JS_FinalizeStub, - JSCLASS_NO_OPTIONAL_MEMBERS -}; - -#endif /* JS_HAS_ARGS_OBJECT */ - -#if JS_HAS_CALL_OBJECT - -JSObject * -js_GetCallObject(JSContext *cx, JSStackFrame *fp, JSObject *parent) -{ - JSObject *callobj, *funobj; - - /* Create a call object for fp only if it lacks one. */ - JS_ASSERT(fp->fun); - callobj = fp->callobj; - if (callobj) - return callobj; - JS_ASSERT(fp->fun); - - /* The default call parent is its function's parent (static link). */ - if (!parent) { - funobj = fp->argv ? JSVAL_TO_OBJECT(fp->argv[-2]) : fp->fun->object; - if (funobj) - parent = OBJ_GET_PARENT(cx, funobj); - } - - /* Create the call object and link it to its stack frame. */ - callobj = js_NewObject(cx, &js_CallClass, NULL, parent); - if (!callobj || !JS_SetPrivate(cx, callobj, fp)) { - cx->newborn[GCX_OBJECT] = NULL; - return NULL; - } - fp->callobj = callobj; - - /* Make callobj be the scope chain and the variables object. */ - fp->scopeChain = callobj; - fp->varobj = callobj; - return callobj; -} - -static JSBool -call_enumerate(JSContext *cx, JSObject *obj); - -JSBool -js_PutCallObject(JSContext *cx, JSStackFrame *fp) -{ - JSObject *callobj; - JSBool ok; - jsid argsid; - jsval aval; - - /* - * Reuse call_enumerate here to reflect all actual args and vars into the - * call object from fp. - */ - callobj = fp->callobj; - if (!callobj) - return JS_TRUE; - ok = call_enumerate(cx, callobj); - - /* - * Get the arguments object to snapshot fp's actual argument values. - */ - if (fp->argsobj) { - argsid = ATOM_TO_JSID(cx->runtime->atomState.argumentsAtom); - ok &= js_GetProperty(cx, callobj, argsid, &aval); - ok &= js_SetProperty(cx, callobj, argsid, &aval); - ok &= js_PutArgsObject(cx, fp); - } - - /* - * Clear the private pointer to fp, which is about to go away (js_Invoke). - * Do this last because the call_enumerate and js_GetProperty calls above - * need to follow the private slot to find fp. - */ - ok &= JS_SetPrivate(cx, callobj, NULL); - fp->callobj = NULL; - return ok; -} - -static JSPropertySpec call_props[] = { - {js_arguments_str, CALL_ARGUMENTS, JSPROP_PERMANENT,0,0}, - {"__callee__", CALL_CALLEE, 0,0,0}, - {0,0,0,0,0} -}; - -static JSBool -call_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - JSStackFrame *fp; - jsint slot; - - if (!JSVAL_IS_INT(id)) - return JS_TRUE; - fp = (JSStackFrame *) JS_GetPrivate(cx, obj); - if (!fp) - return JS_TRUE; - JS_ASSERT(fp->fun); - - slot = JSVAL_TO_INT(id); - switch (slot) { - case CALL_ARGUMENTS: - if (!TEST_OVERRIDE_BIT(fp, slot)) { - JSObject *argsobj = js_GetArgsObject(cx, fp); - if (!argsobj) - return JS_FALSE; - *vp = OBJECT_TO_JSVAL(argsobj); - } - break; - - case CALL_CALLEE: - if (!TEST_OVERRIDE_BIT(fp, slot)) - *vp = fp->argv ? fp->argv[-2] : OBJECT_TO_JSVAL(fp->fun->object); - break; - - default: - if ((uintN)slot < JS_MAX(fp->argc, fp->fun->nargs)) - *vp = fp->argv[slot]; - break; - } - return JS_TRUE; -} - -static JSBool -call_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - JSStackFrame *fp; - jsint slot; - - if (!JSVAL_IS_INT(id)) - return JS_TRUE; - fp = (JSStackFrame *) JS_GetPrivate(cx, obj); - if (!fp) - return JS_TRUE; - JS_ASSERT(fp->fun); - - slot = JSVAL_TO_INT(id); - switch (slot) { - case CALL_ARGUMENTS: - case CALL_CALLEE: - SET_OVERRIDE_BIT(fp, slot); - break; - - default: - if ((uintN)slot < JS_MAX(fp->argc, fp->fun->nargs)) - fp->argv[slot] = *vp; - break; - } - return JS_TRUE; -} - -JSBool -js_GetCallVariable(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - JSStackFrame *fp; - - JS_ASSERT(JSVAL_IS_INT(id)); - fp = (JSStackFrame *) JS_GetPrivate(cx, obj); - if (fp) { - /* XXX no jsint slot commoning here to avoid MSVC1.52 crashes */ - if ((uintN)JSVAL_TO_INT(id) < fp->nvars) - *vp = fp->vars[JSVAL_TO_INT(id)]; - } - return JS_TRUE; -} - -JSBool -js_SetCallVariable(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - JSStackFrame *fp; - - JS_ASSERT(JSVAL_IS_INT(id)); - fp = (JSStackFrame *) JS_GetPrivate(cx, obj); - if (fp) { - /* XXX jsint slot is block-local here to avoid MSVC1.52 crashes */ - jsint slot = JSVAL_TO_INT(id); - if ((uintN)slot < fp->nvars) - fp->vars[slot] = *vp; - } - return JS_TRUE; -} - -static JSBool -call_enumerate(JSContext *cx, JSObject *obj) -{ - JSStackFrame *fp; - JSObject *funobj, *pobj; - JSScope *scope; - JSScopeProperty *sprop, *cprop; - JSPropertyOp getter; - jsval *vec; - JSAtom *atom; - JSProperty *prop; - - fp = (JSStackFrame *) JS_GetPrivate(cx, obj); - if (!fp) - return JS_TRUE; - - /* - * Do not enumerate a cloned function object at fp->argv[-2], it may have - * gained its own (mutable) scope (e.g., a brutally-shared XUL script sets - * the clone's prototype property). We must enumerate the function object - * that was decorated with parameter and local variable properties by the - * compiler when the compiler created fp->fun, namely fp->fun->object. - * - * Contrast with call_resolve, where we prefer fp->argv[-2], because we'll - * use js_LookupProperty to find any overridden properties in that object, - * if it was a mutated clone; and if not, we will search its prototype, - * fp->fun->object, to find compiler-created params and locals. - */ - funobj = fp->fun->object; - if (!funobj) - return JS_TRUE; - - /* - * Reflect actual args from fp->argv for formal parameters, and local vars - * and functions in fp->vars for declared variables and nested-at-top-level - * local functions. - */ - scope = OBJ_SCOPE(funobj); - for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) { - getter = sprop->getter; - if (getter == js_GetArgument) - vec = fp->argv; - else if (getter == js_GetLocalVariable) - vec = fp->vars; - else - continue; - - /* Trigger reflection by looking up the unhidden atom for sprop->id. */ - JS_ASSERT(JSID_IS_ATOM(sprop->id)); - atom = JSID_TO_ATOM(sprop->id); - JS_ASSERT(atom->flags & ATOM_HIDDEN); - atom = atom->entry.value; - - if (!js_LookupProperty(cx, obj, ATOM_TO_JSID(atom), &pobj, &prop)) - return JS_FALSE; - - /* - * If we found the property in a different object, don't try sticking - * it into wrong slots vector. This can occur because we have a mutable - * __proto__ slot, and cloned function objects rely on their __proto__ - * to delegate to the object that contains the var and arg properties. - */ - if (!prop || pobj != obj) { - if (prop) - OBJ_DROP_PROPERTY(cx, pobj, prop); - continue; - } - cprop = (JSScopeProperty *)prop; - LOCKED_OBJ_SET_SLOT(obj, cprop->slot, vec[(uint16) sprop->shortid]); - OBJ_DROP_PROPERTY(cx, obj, prop); - } - - return JS_TRUE; -} - -static JSBool -call_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, - JSObject **objp) -{ - JSStackFrame *fp; - JSObject *funobj; - JSString *str; - JSAtom *atom; - JSObject *obj2; - JSProperty *prop; - JSScopeProperty *sprop; - JSPropertyOp getter, setter; - uintN attrs, slot, nslots, spflags; - jsval *vp, value; - intN shortid; - - fp = (JSStackFrame *) JS_GetPrivate(cx, obj); - if (!fp) - return JS_TRUE; - JS_ASSERT(fp->fun); - - if (!JSVAL_IS_STRING(id)) - return JS_TRUE; - - funobj = fp->argv ? JSVAL_TO_OBJECT(fp->argv[-2]) : fp->fun->object; - if (!funobj) - return JS_TRUE; - JS_ASSERT((JSFunction *) JS_GetPrivate(cx, funobj) == fp->fun); - - str = JSVAL_TO_STRING(id); - atom = js_AtomizeString(cx, str, 0); - if (!atom) - return JS_FALSE; - if (!js_LookupHiddenProperty(cx, funobj, ATOM_TO_JSID(atom), &obj2, &prop)) - return JS_FALSE; - - if (prop) { - if (!OBJ_IS_NATIVE(obj2)) { - OBJ_DROP_PROPERTY(cx, obj2, prop); - return JS_TRUE; - } - - sprop = (JSScopeProperty *) prop; - getter = sprop->getter; - attrs = sprop->attrs & ~JSPROP_SHARED; - slot = (uintN) sprop->shortid; - OBJ_DROP_PROPERTY(cx, obj2, prop); - - /* Ensure we found an arg or var property for the same function. */ - if ((sprop->flags & SPROP_IS_HIDDEN) && - (obj2 == funobj || - (JSFunction *) JS_GetPrivate(cx, obj2) == fp->fun)) { - if (getter == js_GetArgument) { - vp = fp->argv; - nslots = JS_MAX(fp->argc, fp->fun->nargs); - getter = setter = NULL; - } else { - JS_ASSERT(getter == js_GetLocalVariable); - vp = fp->vars; - nslots = fp->nvars; - getter = js_GetCallVariable; - setter = js_SetCallVariable; - } - if (slot < nslots) { - value = vp[slot]; - spflags = SPROP_HAS_SHORTID; - shortid = (intN) slot; - } else { - value = JSVAL_VOID; - spflags = 0; - shortid = 0; - } - if (!js_DefineNativeProperty(cx, obj, ATOM_TO_JSID(atom), value, - getter, setter, attrs, - spflags, shortid, NULL)) { - return JS_FALSE; - } - *objp = obj; - } - } - - return JS_TRUE; -} - -static JSBool -call_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp) -{ - JSStackFrame *fp; - - if (type == JSTYPE_FUNCTION) { - fp = (JSStackFrame *) JS_GetPrivate(cx, obj); - if (fp) { - JS_ASSERT(fp->fun); - *vp = fp->argv ? fp->argv[-2] : OBJECT_TO_JSVAL(fp->fun->object); - } - } - return JS_TRUE; -} - -JSClass js_CallClass = { - js_Call_str, - JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE, - JS_PropertyStub, JS_PropertyStub, - call_getProperty, call_setProperty, - call_enumerate, (JSResolveOp)call_resolve, - call_convert, JS_FinalizeStub, - JSCLASS_NO_OPTIONAL_MEMBERS -}; - -#endif /* JS_HAS_CALL_OBJECT */ - -/* - * ECMA-262 specifies that length is a property of function object instances, - * but we can avoid that space cost by delegating to a prototype property that - * is JSPROP_PERMANENT and JSPROP_SHARED. Each fun_getProperty call computes - * a fresh length value based on the arity of the individual function object's - * private data. - * - * The extensions below other than length, i.e., the ones not in ECMA-262, - * are neither JSPROP_READONLY nor JSPROP_SHARED, because for compatibility - * with ECMA we must allow a delegating object to override them. - */ -#define LENGTH_PROP_ATTRS (JSPROP_READONLY|JSPROP_PERMANENT|JSPROP_SHARED) - -static JSPropertySpec function_props[] = { - {js_arguments_str, CALL_ARGUMENTS, JSPROP_PERMANENT, 0,0}, - {js_arity_str, FUN_ARITY, JSPROP_PERMANENT, 0,0}, - {js_caller_str, FUN_CALLER, JSPROP_PERMANENT, 0,0}, - {js_length_str, ARGS_LENGTH, LENGTH_PROP_ATTRS, 0,0}, - {js_name_str, FUN_NAME, JSPROP_PERMANENT, 0,0}, - {0,0,0,0,0} -}; - -static JSBool -fun_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - jsint slot; - JSFunction *fun; - JSStackFrame *fp; - - if (!JSVAL_IS_INT(id)) - return JS_TRUE; - slot = JSVAL_TO_INT(id); - - /* - * Loop because getter and setter can be delegated from another class, - * but loop only for ARGS_LENGTH because we must pretend that f.length - * is in each function instance f, per ECMA-262, instead of only in the - * Function.prototype object (we use JSPROP_PERMANENT with JSPROP_SHARED - * to make it appear so). - * - * This code couples tightly to the attributes for the function_props[] - * initializers above, and to js_SetProperty and js_HasOwnPropertyHelper. - * - * It's important to allow delegating objects, even though they inherit - * this getter (fun_getProperty), to override arguments, arity, caller, - * and name. If we didn't return early for slot != ARGS_LENGTH, we would - * clobber *vp with the native property value, instead of letting script - * override that value in delegating objects. - * - * Note how that clobbering is what simulates JSPROP_READONLY for all of - * the non-standard properties when the directly addressed object (obj) - * is a function object (i.e., when this loop does not iterate). - */ - while (!(fun = (JSFunction *) - JS_GetInstancePrivate(cx, obj, &js_FunctionClass, NULL))) { - if (slot != ARGS_LENGTH) - return JS_TRUE; - obj = OBJ_GET_PROTO(cx, obj); - if (!obj) - return JS_TRUE; - } - - /* Find fun's top-most activation record. */ - for (fp = cx->fp; fp && (fp->fun != fun || (fp->flags & JSFRAME_SPECIAL)); - fp = fp->down) { - continue; - } - - switch (slot) { - case CALL_ARGUMENTS: -#if JS_HAS_ARGS_OBJECT - /* Warn if strict about f.arguments or equivalent unqualified uses. */ - if (!JS_ReportErrorFlagsAndNumber(cx, - JSREPORT_WARNING | JSREPORT_STRICT, - js_GetErrorMessage, NULL, - JSMSG_DEPRECATED_USAGE, - js_arguments_str)) { - return JS_FALSE; - } - if (fp) { - if (!js_GetArgsValue(cx, fp, vp)) - return JS_FALSE; - } else { - *vp = JSVAL_NULL; - } - break; -#else /* !JS_HAS_ARGS_OBJECT */ - *vp = OBJECT_TO_JSVAL(fp ? obj : NULL); - break; -#endif /* !JS_HAS_ARGS_OBJECT */ - - case ARGS_LENGTH: - if (!JS_VERSION_IS_ECMA(cx)) - *vp = INT_TO_JSVAL((jsint)(fp && fp->fun ? fp->argc : fun->nargs)); - else - case FUN_ARITY: - *vp = INT_TO_JSVAL((jsint)fun->nargs); - break; - - case FUN_NAME: - *vp = fun->atom - ? ATOM_KEY(fun->atom) - : STRING_TO_JSVAL(cx->runtime->emptyString); - break; - - case FUN_CALLER: - while (fp && (fp->flags & JSFRAME_SKIP_CALLER) && fp->down) - fp = fp->down; - if (fp && fp->down && fp->down->fun && fp->down->argv) - *vp = fp->down->argv[-2]; - else - *vp = JSVAL_NULL; - if (!JSVAL_IS_PRIMITIVE(*vp) && cx->runtime->checkObjectAccess) { - id = ATOM_KEY(cx->runtime->atomState.callerAtom); - if (!cx->runtime->checkObjectAccess(cx, obj, id, JSACC_READ, vp)) - return JS_FALSE; - } - break; - - default: - /* XXX fun[0] and fun.arguments[0] are equivalent. */ - if (fp && fp->fun && (uintN)slot < fp->fun->nargs) - *vp = fp->argv[slot]; - break; - } - - return JS_TRUE; -} - -static JSBool -fun_enumerate(JSContext *cx, JSObject *obj) -{ - jsid prototypeId; - JSObject *pobj; - JSProperty *prop; - - prototypeId = ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom); - if (!OBJ_LOOKUP_PROPERTY(cx, obj, prototypeId, &pobj, &prop)) - return JS_FALSE; - if (prop) - OBJ_DROP_PROPERTY(cx, pobj, prop); - return JS_TRUE; -} - -static JSBool -fun_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, - JSObject **objp) -{ - JSFunction *fun; - JSString *str; - JSAtom *prototypeAtom; - - if (!JSVAL_IS_STRING(id)) - return JS_TRUE; - - /* No valid function object should lack private data, but check anyway. */ - fun = (JSFunction *)JS_GetInstancePrivate(cx, obj, &js_FunctionClass, NULL); - if (!fun || !fun->object) - return JS_TRUE; - - /* No need to reflect fun.prototype in 'fun.prototype = ...'. */ - if (flags & JSRESOLVE_ASSIGNING) - return JS_TRUE; - - /* - * Ok, check whether id is 'prototype' and bootstrap the function object's - * prototype property. - */ - str = JSVAL_TO_STRING(id); - prototypeAtom = cx->runtime->atomState.classPrototypeAtom; - if (str == ATOM_TO_STRING(prototypeAtom)) { - JSObject *proto, *parentProto; - jsval pval; - - proto = parentProto = NULL; - if (fun->object != obj && fun->object) { - /* - * Clone of a function: make its prototype property value have the - * same class as the clone-parent's prototype. - */ - if (!OBJ_GET_PROPERTY(cx, fun->object, ATOM_TO_JSID(prototypeAtom), - &pval)) { - return JS_FALSE; - } - if (!JSVAL_IS_PRIMITIVE(pval)) { - /* - * We are about to allocate a new object, so hack the newborn - * root until then to protect pval in case it is figuratively - * up in the air, with no strong refs protecting it. - */ - cx->newborn[GCX_OBJECT] = JSVAL_TO_GCTHING(pval); - parentProto = JSVAL_TO_OBJECT(pval); - } - } - - /* - * Beware of the wacky case of a user function named Object -- trying - * to find a prototype for that will recur back here _ad perniciem_. - */ - if (!parentProto && fun->atom == cx->runtime->atomState.ObjectAtom) - return JS_TRUE; - - /* - * If resolving "prototype" in a clone, clone the parent's prototype. - * Pass the constructor's (obj's) parent as the prototype parent, to - * avoid defaulting to parentProto.constructor.__parent__. - */ - proto = js_NewObject(cx, &js_ObjectClass, parentProto, - OBJ_GET_PARENT(cx, obj)); - if (!proto) - return JS_FALSE; - - /* - * ECMA (15.3.5.2) says that constructor.prototype is DontDelete for - * user-defined functions, but DontEnum | ReadOnly | DontDelete for - * native "system" constructors such as Object or Function. So lazily - * set the former here in fun_resolve, but eagerly define the latter - * in JS_InitClass, with the right attributes. - */ - if (!js_SetClassPrototype(cx, obj, proto, - JSPROP_ENUMERATE | JSPROP_PERMANENT)) { - cx->newborn[GCX_OBJECT] = NULL; - return JS_FALSE; - } - *objp = obj; - } - - return JS_TRUE; -} - -static JSBool -fun_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp) -{ - switch (type) { - case JSTYPE_FUNCTION: - *vp = OBJECT_TO_JSVAL(obj); - return JS_TRUE; - default: - return js_TryValueOf(cx, obj, type, vp); - } -} - -static void -fun_finalize(JSContext *cx, JSObject *obj) -{ - JSFunction *fun; - - /* No valid function object should lack private data, but check anyway. */ - fun = (JSFunction *) JS_GetPrivate(cx, obj); - if (!fun) - return; - if (fun->object == obj) - fun->object = NULL; - JS_ATOMIC_DECREMENT(&fun->nrefs); - if (fun->nrefs) - return; - - /* Null-check required since the parser sets interpreted very early. */ - if (fun->interpreted && fun->u.script) - js_DestroyScript(cx, fun->u.script); -} - -#if JS_HAS_XDR - -#include "jsxdrapi.h" - -enum { - JSXDR_FUNARG = 1, - JSXDR_FUNVAR = 2, - JSXDR_FUNCONST = 3 -}; - -/* XXX store parent and proto, if defined */ -static JSBool -fun_xdrObject(JSXDRState *xdr, JSObject **objp) -{ - JSContext *cx; - JSFunction *fun; - JSString *atomstr; - JSTempValueRooter tvr; - uint32 flagsword; /* originally only flags was JS_XDRUint8'd */ - char *propname; - JSScopeProperty *sprop; - uint32 userid; /* NB: holds a signed int-tagged jsval */ - JSAtom *atom; - uintN i, n, dupflag; - uint32 type; - JSBool ok; -#ifdef DEBUG - uintN nvars = 0, nargs = 0; -#endif - - cx = xdr->cx; - if (xdr->mode == JSXDR_ENCODE) { - /* - * No valid function object should lack private data, but fail soft - * (return true, no error report) in case one does due to API pilot - * or internal error. - */ - fun = (JSFunction *) JS_GetPrivate(cx, *objp); - if (!fun) - return JS_TRUE; - if (!fun->interpreted) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_NOT_SCRIPTED_FUNCTION, - JS_GetFunctionName(fun)); - return JS_FALSE; - } - atomstr = fun->atom ? ATOM_TO_STRING(fun->atom) : NULL; - flagsword = ((uint32)fun->nregexps << 16) | fun->flags; - } else { - fun = js_NewFunction(cx, NULL, NULL, 0, 0, NULL, NULL); - if (!fun) - return JS_FALSE; - atomstr = NULL; - } - - /* From here on, control flow must flow through label out. */ - JS_PUSH_SINGLE_TEMP_ROOT(cx, OBJECT_TO_JSVAL(fun->object), &tvr); - ok = JS_TRUE; - - if (!JS_XDRStringOrNull(xdr, &atomstr) || - !JS_XDRUint16(xdr, &fun->nargs) || - !JS_XDRUint16(xdr, &fun->extra) || - !JS_XDRUint16(xdr, &fun->nvars) || - !JS_XDRUint32(xdr, &flagsword)) { - goto bad; - } - - /* do arguments and local vars */ - if (fun->object) { - n = fun->nargs + fun->nvars; - if (xdr->mode == JSXDR_ENCODE) { - JSScope *scope; - JSScopeProperty **spvec, *auto_spvec[8]; - void *mark; - - if (n <= sizeof auto_spvec / sizeof auto_spvec[0]) { - spvec = auto_spvec; - mark = NULL; - } else { - mark = JS_ARENA_MARK(&cx->tempPool); - JS_ARENA_ALLOCATE_CAST(spvec, JSScopeProperty **, &cx->tempPool, - n * sizeof(JSScopeProperty *)); - if (!spvec) { - JS_ReportOutOfMemory(cx); - goto bad; - } - } - scope = OBJ_SCOPE(fun->object); - for (sprop = SCOPE_LAST_PROP(scope); sprop; - sprop = sprop->parent) { - if (sprop->getter == js_GetArgument) { - JS_ASSERT(nargs++ <= fun->nargs); - spvec[sprop->shortid] = sprop; - } else if (sprop->getter == js_GetLocalVariable) { - JS_ASSERT(nvars++ <= fun->nvars); - spvec[fun->nargs + sprop->shortid] = sprop; - } - } - for (i = 0; i < n; i++) { - sprop = spvec[i]; - JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID); - type = (i < fun->nargs) - ? JSXDR_FUNARG - : (sprop->attrs & JSPROP_READONLY) - ? JSXDR_FUNCONST - : JSXDR_FUNVAR; - userid = INT_TO_JSVAL(sprop->shortid); - /* XXX lossy conversion, need new XDR version for ECMAv3 */ - propname = JS_GetStringBytes(ATOM_TO_STRING(JSID_TO_ATOM(sprop->id))); - if (!propname || - !JS_XDRUint32(xdr, &type) || - !JS_XDRUint32(xdr, &userid) || - !JS_XDRCString(xdr, &propname)) { - if (mark) - JS_ARENA_RELEASE(&cx->tempPool, mark); - goto bad; - } - } - if (mark) - JS_ARENA_RELEASE(&cx->tempPool, mark); - } else { - JSPropertyOp getter, setter; - - for (i = n; i != 0; i--) { - uintN attrs = JSPROP_PERMANENT; - - if (!JS_XDRUint32(xdr, &type) || - !JS_XDRUint32(xdr, &userid) || - !JS_XDRCString(xdr, &propname)) { - goto bad; - } - JS_ASSERT(type == JSXDR_FUNARG || type == JSXDR_FUNVAR || - type == JSXDR_FUNCONST); - if (type == JSXDR_FUNARG) { - getter = js_GetArgument; - setter = js_SetArgument; - JS_ASSERT(nargs++ <= fun->nargs); - } else if (type == JSXDR_FUNVAR || type == JSXDR_FUNCONST) { - getter = js_GetLocalVariable; - setter = js_SetLocalVariable; - if (type == JSXDR_FUNCONST) - attrs |= JSPROP_READONLY; - JS_ASSERT(nvars++ <= fun->nvars); - } else { - getter = NULL; - setter = NULL; - } - atom = js_Atomize(cx, propname, strlen(propname), 0); - JS_free(cx, propname); - if (!atom) - goto bad; - - /* Flag duplicate argument if atom is bound in fun->object. */ - dupflag = SCOPE_GET_PROPERTY(OBJ_SCOPE(fun->object), - ATOM_TO_JSID(atom)) - ? SPROP_IS_DUPLICATE - : 0; - - if (!js_AddHiddenProperty(cx, fun->object, ATOM_TO_JSID(atom), - getter, setter, SPROP_INVALID_SLOT, - attrs | JSPROP_SHARED, - dupflag | SPROP_HAS_SHORTID, - JSVAL_TO_INT(userid))) { - goto bad; - } - } - } - } - - if (!js_XDRScript(xdr, &fun->u.script, NULL)) - goto bad; - - if (xdr->mode == JSXDR_DECODE) { - fun->interpreted = JS_TRUE; - fun->flags = (uint8) flagsword; - fun->nregexps = (uint16) (flagsword >> 16); - - *objp = fun->object; - if (atomstr) { - /* XXX only if this was a top-level function! */ - fun->atom = js_AtomizeString(cx, atomstr, 0); - if (!fun->atom) - goto bad; - } - - js_CallNewScriptHook(cx, fun->u.script, fun); - } - -out: - JS_POP_TEMP_ROOT(cx, &tvr); - return ok; - -bad: - ok = JS_FALSE; - goto out; -} - -#else /* !JS_HAS_XDR */ - -#define fun_xdrObject NULL - -#endif /* !JS_HAS_XDR */ - -#if JS_HAS_INSTANCEOF - -/* - * [[HasInstance]] internal method for Function objects: fetch the .prototype - * property of its 'this' parameter, and walks the prototype chain of v (only - * if v is an object) returning true if .prototype is found. - */ -static JSBool -fun_hasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp) -{ - jsval pval; - JSString *str; - - if (!OBJ_GET_PROPERTY(cx, obj, - ATOM_TO_JSID(cx->runtime->atomState - .classPrototypeAtom), - &pval)) { - return JS_FALSE; - } - - if (JSVAL_IS_PRIMITIVE(pval)) { - /* - * Throw a runtime error if instanceof is called on a function that - * has a non-object as its .prototype value. - */ - str = js_DecompileValueGenerator(cx, -1, OBJECT_TO_JSVAL(obj), NULL); - if (str) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_PROTOTYPE, JS_GetStringBytes(str)); - } - return JS_FALSE; - } - - return js_IsDelegate(cx, JSVAL_TO_OBJECT(pval), v, bp); -} - -#else /* !JS_HAS_INSTANCEOF */ - -#define fun_hasInstance NULL - -#endif /* !JS_HAS_INSTANCEOF */ - -static uint32 -fun_mark(JSContext *cx, JSObject *obj, void *arg) -{ - JSFunction *fun; - - fun = (JSFunction *) JS_GetPrivate(cx, obj); - if (fun) { - JS_MarkGCThing(cx, fun, js_private_str, arg); - if (fun->atom) - GC_MARK_ATOM(cx, fun->atom, arg); - if (fun->interpreted && fun->u.script) - js_MarkScript(cx, fun->u.script, arg); - } - return 0; -} - -static uint32 -fun_reserveSlots(JSContext *cx, JSObject *obj) -{ - JSFunction *fun; - - fun = (JSFunction *) JS_GetPrivate(cx, obj); - return fun ? fun->nregexps : 0; -} - -/* - * Reserve two slots in all function objects for XPConnect. Note that this - * does not bloat every instance, only those on which reserved slots are set, - * and those on which ad-hoc properties are defined. - */ -JS_FRIEND_DATA(JSClass) js_FunctionClass = { - js_Function_str, - JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_HAS_RESERVED_SLOTS(2), - JS_PropertyStub, JS_PropertyStub, - fun_getProperty, JS_PropertyStub, - fun_enumerate, (JSResolveOp)fun_resolve, - fun_convert, fun_finalize, - NULL, NULL, - NULL, NULL, - fun_xdrObject, fun_hasInstance, - fun_mark, fun_reserveSlots -}; - -JSBool -js_fun_toString(JSContext *cx, JSObject *obj, uint32 indent, - uintN argc, jsval *argv, jsval *rval) -{ - jsval fval; - JSFunction *fun; - JSString *str; - - if (!argv) { - JS_ASSERT(JS_ObjectIsFunction(cx, obj)); - } else { - fval = argv[-1]; - if (!JSVAL_IS_FUNCTION(cx, fval)) { - /* - * If we don't have a function to start off with, try converting - * the object to a function. If that doesn't work, complain. - */ - if (JSVAL_IS_OBJECT(fval)) { - obj = JSVAL_TO_OBJECT(fval); - if (!OBJ_GET_CLASS(cx, obj)->convert(cx, obj, JSTYPE_FUNCTION, - &fval)) { - return JS_FALSE; - } - argv[-1] = fval; - } - if (!JSVAL_IS_FUNCTION(cx, fval)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_INCOMPATIBLE_PROTO, - js_Function_str, js_toString_str, - JS_GetTypeName(cx, - JS_TypeOfValue(cx, fval))); - return JS_FALSE; - } - } - - obj = JSVAL_TO_OBJECT(fval); - } - - fun = (JSFunction *) JS_GetPrivate(cx, obj); - if (!fun) - return JS_TRUE; - if (argc && !js_ValueToECMAUint32(cx, argv[0], &indent)) - return JS_FALSE; - str = JS_DecompileFunction(cx, fun, (uintN)indent); - if (!str) - return JS_FALSE; - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -static JSBool -fun_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - return js_fun_toString(cx, obj, 0, argc, argv, rval); -} - -#if JS_HAS_TOSOURCE -static JSBool -fun_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - return js_fun_toString(cx, obj, JS_DONT_PRETTY_PRINT, argc, argv, rval); -} -#endif - -static const char call_str[] = "call"; - -#if JS_HAS_CALL_FUNCTION -static JSBool -fun_call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsval fval, *sp, *oldsp; - JSString *str; - void *mark; - uintN i; - JSStackFrame *fp; - JSBool ok; - - if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_FUNCTION, &argv[-1])) - return JS_FALSE; - fval = argv[-1]; - - if (!JSVAL_IS_FUNCTION(cx, fval)) { - str = JS_ValueToString(cx, fval); - if (str) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_INCOMPATIBLE_PROTO, - js_Function_str, call_str, - JS_GetStringBytes(str)); - } - return JS_FALSE; - } - - if (argc == 0) { - /* Call fun with its global object as the 'this' param if no args. */ - obj = NULL; - } else { - /* Otherwise convert the first arg to 'this' and skip over it. */ - if (!js_ValueToObject(cx, argv[0], &obj)) - return JS_FALSE; - argc--; - argv++; - } - - /* Allocate stack space for fval, obj, and the args. */ - sp = js_AllocStack(cx, 2 + argc, &mark); - if (!sp) - return JS_FALSE; - - /* Push fval, obj, and the args. */ - *sp++ = fval; - *sp++ = OBJECT_TO_JSVAL(obj); - for (i = 0; i < argc; i++) - *sp++ = argv[i]; - - /* Lift current frame to include the args and do the call. */ - fp = cx->fp; - oldsp = fp->sp; - fp->sp = sp; - ok = js_Invoke(cx, argc, JSINVOKE_INTERNAL | JSINVOKE_SKIP_CALLER); - - /* Store rval and pop stack back to our frame's sp. */ - *rval = fp->sp[-1]; - fp->sp = oldsp; - js_FreeStack(cx, mark); - return ok; -} -#endif /* JS_HAS_CALL_FUNCTION */ - -#if JS_HAS_APPLY_FUNCTION -static JSBool -fun_apply(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsval fval, *sp, *oldsp; - JSString *str; - JSObject *aobj; - jsuint length; - void *mark; - uintN i; - JSBool ok; - JSStackFrame *fp; - - if (argc == 0) { - /* Will get globalObject as 'this' and no other arguments. */ - return fun_call(cx, obj, argc, argv, rval); - } - - if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_FUNCTION, &argv[-1])) - return JS_FALSE; - fval = argv[-1]; - - if (!JSVAL_IS_FUNCTION(cx, fval)) { - str = JS_ValueToString(cx, fval); - if (str) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_INCOMPATIBLE_PROTO, - js_Function_str, "apply", - JS_GetStringBytes(str)); - } - return JS_FALSE; - } - - /* Quell GCC overwarnings. */ - aobj = NULL; - length = 0; - - if (argc >= 2) { - /* If the 2nd arg is null or void, call the function with 0 args. */ - if (JSVAL_IS_NULL(argv[1]) || JSVAL_IS_VOID(argv[1])) { - argc = 0; - } else { - /* The second arg must be an array (or arguments object). */ - if (JSVAL_IS_PRIMITIVE(argv[1]) || - (aobj = JSVAL_TO_OBJECT(argv[1]), - OBJ_GET_CLASS(cx, aobj) != &js_ArgumentsClass && - OBJ_GET_CLASS(cx, aobj) != &js_ArrayClass)) - { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_APPLY_ARGS); - return JS_FALSE; - } - if (!js_GetLengthProperty(cx, aobj, &length)) - return JS_FALSE; - } - } - - /* Convert the first arg to 'this' and skip over it. */ - if (!js_ValueToObject(cx, argv[0], &obj)) - return JS_FALSE; - - /* Allocate stack space for fval, obj, and the args. */ - argc = (uintN)JS_MIN(length, ARGC_LIMIT - 1); - sp = js_AllocStack(cx, 2 + argc, &mark); - if (!sp) - return JS_FALSE; - - /* Push fval, obj, and aobj's elements as args. */ - *sp++ = fval; - *sp++ = OBJECT_TO_JSVAL(obj); - for (i = 0; i < argc; i++) { - ok = JS_GetElement(cx, aobj, (jsint)i, sp); - if (!ok) - goto out; - sp++; - } - - /* Lift current frame to include the args and do the call. */ - fp = cx->fp; - oldsp = fp->sp; - fp->sp = sp; - ok = js_Invoke(cx, argc, JSINVOKE_INTERNAL | JSINVOKE_SKIP_CALLER); - - /* Store rval and pop stack back to our frame's sp. */ - *rval = fp->sp[-1]; - fp->sp = oldsp; -out: - js_FreeStack(cx, mark); - return ok; -} -#endif /* JS_HAS_APPLY_FUNCTION */ - -static JSFunctionSpec function_methods[] = { -#if JS_HAS_TOSOURCE - {js_toSource_str, fun_toSource, 0,0,0}, -#endif - {js_toString_str, fun_toString, 1,0,0}, -#if JS_HAS_APPLY_FUNCTION - {"apply", fun_apply, 2,0,0}, -#endif -#if JS_HAS_CALL_FUNCTION - {call_str, fun_call, 1,0,0}, -#endif - {0,0,0,0,0} -}; - -JSBool -js_IsIdentifier(JSString *str) -{ - size_t n; - jschar *s, c; - - n = JSSTRING_LENGTH(str); - if (n == 0) - return JS_FALSE; - s = JSSTRING_CHARS(str); - c = *s; - if (!JS_ISIDSTART(c)) - return JS_FALSE; - for (n--; n != 0; n--) { - c = *++s; - if (!JS_ISIDENT(c)) - return JS_FALSE; - } - return JS_TRUE; -} - -static JSBool -Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSStackFrame *fp, *caller; - JSFunction *fun; - JSObject *parent; - uintN i, n, lineno, dupflag; - JSAtom *atom; - const char *filename; - JSObject *obj2; - JSProperty *prop; - JSScopeProperty *sprop; - JSString *str, *arg; - void *mark; - JSTokenStream *ts; - JSPrincipals *principals; - jschar *collected_args, *cp; - size_t arg_length, args_length, old_args_length; - JSTokenType tt; - JSBool ok; - - fp = cx->fp; - if (fp && !(fp->flags & JSFRAME_CONSTRUCTING)) { - obj = js_NewObject(cx, &js_FunctionClass, NULL, NULL); - if (!obj) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(obj); - } - fun = (JSFunction *) JS_GetPrivate(cx, obj); - if (fun) - return JS_TRUE; - -#if JS_HAS_CALL_OBJECT - /* - * NB: (new Function) is not lexically closed by its caller, it's just an - * anonymous function in the top-level scope that its constructor inhabits. - * Thus 'var x = 42; f = new Function("return x"); print(f())' prints 42, - * and so would a call to f from another top-level's script or function. - * - * In older versions, before call objects, a new Function was adopted by - * its running context's globalObject, which might be different from the - * top-level reachable from scopeChain (in HTML frames, e.g.). - */ - parent = OBJ_GET_PARENT(cx, JSVAL_TO_OBJECT(argv[-2])); -#else - /* Set up for dynamic parenting (see js_Invoke in jsinterp.c). */ - parent = NULL; -#endif - - fun = js_NewFunction(cx, obj, NULL, 0, JSFUN_LAMBDA, parent, - JS_VERSION_IS_ECMA(cx) - ? cx->runtime->atomState.anonymousAtom - : NULL); - - if (!fun) - return JS_FALSE; - - /* - * Function is static and not called directly by other functions in this - * file, therefore it is callable only as a native function by js_Invoke. - * Find the scripted caller, possibly skipping other native frames such as - * are built for Function.prototype.call or .apply activations that invoke - * Function indirectly from a script. - */ - JS_ASSERT(!fp->script && fp->fun && fp->fun->u.native == Function); - caller = JS_GetScriptedCaller(cx, fp); - if (caller) { - filename = caller->script->filename; - lineno = js_PCToLineNumber(cx, caller->script, caller->pc); - principals = JS_EvalFramePrincipals(cx, fp, caller); - } else { - filename = NULL; - lineno = 0; - principals = NULL; - } - - /* Belt-and-braces: check that the caller has access to parent. */ - if (!js_CheckPrincipalsAccess(cx, parent, principals, js_Function_str)) - return JS_FALSE; - - n = argc ? argc - 1 : 0; - if (n > 0) { - /* - * Collect the function-argument arguments into one string, separated - * by commas, then make a tokenstream from that string, and scan it to - * get the arguments. We need to throw the full scanner at the - * problem, because the argument string can legitimately contain - * comments and linefeeds. XXX It might be better to concatenate - * everything up into a function definition and pass it to the - * compiler, but doing it this way is less of a delta from the old - * code. See ECMA 15.3.2.1. - */ - args_length = 0; - for (i = 0; i < n; i++) { - /* Collect the lengths for all the function-argument arguments. */ - arg = js_ValueToString(cx, argv[i]); - if (!arg) - return JS_FALSE; - argv[i] = STRING_TO_JSVAL(arg); - - /* - * Check for overflow. The < test works because the maximum - * JSString length fits in 2 fewer bits than size_t has. - */ - old_args_length = args_length; - args_length = old_args_length + JSSTRING_LENGTH(arg); - if (args_length < old_args_length) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - } - - /* Add 1 for each joining comma and check for overflow (two ways). */ - old_args_length = args_length; - args_length = old_args_length + n - 1; - if (args_length < old_args_length || - args_length >= ~(size_t)0 / sizeof(jschar)) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - - /* - * Allocate a string to hold the concatenated arguments, including room - * for a terminating 0. Mark cx->tempPool for later release, to free - * collected_args and its tokenstream in one swoop. - */ - mark = JS_ARENA_MARK(&cx->tempPool); - JS_ARENA_ALLOCATE_CAST(cp, jschar *, &cx->tempPool, - (args_length+1) * sizeof(jschar)); - if (!cp) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - collected_args = cp; - - /* - * Concatenate the arguments into the new string, separated by commas. - */ - for (i = 0; i < n; i++) { - arg = JSVAL_TO_STRING(argv[i]); - arg_length = JSSTRING_LENGTH(arg); - (void) js_strncpy(cp, JSSTRING_CHARS(arg), arg_length); - cp += arg_length; - - /* Add separating comma or terminating 0. */ - *cp++ = (i + 1 < n) ? ',' : 0; - } - - /* - * Make a tokenstream (allocated from cx->tempPool) that reads from - * the given string. - */ - ts = js_NewTokenStream(cx, collected_args, args_length, filename, - lineno, principals); - if (!ts) { - JS_ARENA_RELEASE(&cx->tempPool, mark); - return JS_FALSE; - } - - /* The argument string may be empty or contain no tokens. */ - tt = js_GetToken(cx, ts); - if (tt != TOK_EOF) { - for (;;) { - /* - * Check that it's a name. This also implicitly guards against - * TOK_ERROR, which was already reported. - */ - if (tt != TOK_NAME) - goto bad_formal; - - /* - * Get the atom corresponding to the name from the tokenstream; - * we're assured at this point that it's a valid identifier. - */ - atom = CURRENT_TOKEN(ts).t_atom; - if (!js_LookupHiddenProperty(cx, obj, ATOM_TO_JSID(atom), - &obj2, &prop)) { - goto bad_formal; - } - sprop = (JSScopeProperty *) prop; - dupflag = 0; - if (sprop) { - ok = JS_TRUE; - if (obj2 == obj) { - const char *name = js_AtomToPrintableString(cx, atom); - - /* - * A duplicate parameter name. We force a duplicate - * node on the SCOPE_LAST_PROP(scope) list with the - * same id, distinguished by the SPROP_IS_DUPLICATE - * flag, and not mapped by an entry in scope. - */ - JS_ASSERT(sprop->getter == js_GetArgument); - ok = name && - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | - JSREPORT_WARNING | - JSREPORT_STRICT, - JSMSG_DUPLICATE_FORMAL, - name); - - dupflag = SPROP_IS_DUPLICATE; - } - OBJ_DROP_PROPERTY(cx, obj2, prop); - if (!ok) - goto bad_formal; - sprop = NULL; - } - if (!js_AddHiddenProperty(cx, fun->object, ATOM_TO_JSID(atom), - js_GetArgument, js_SetArgument, - SPROP_INVALID_SLOT, - JSPROP_PERMANENT | JSPROP_SHARED, - dupflag | SPROP_HAS_SHORTID, - fun->nargs)) { - goto bad_formal; - } - if (fun->nargs == JS_BITMASK(16)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_TOO_MANY_FUN_ARGS); - goto bad; - } - fun->nargs++; - - /* - * Get the next token. Stop on end of stream. Otherwise - * insist on a comma, get another name, and iterate. - */ - tt = js_GetToken(cx, ts); - if (tt == TOK_EOF) - break; - if (tt != TOK_COMMA) - goto bad_formal; - tt = js_GetToken(cx, ts); - } - } - - /* Clean up. */ - ok = js_CloseTokenStream(cx, ts); - JS_ARENA_RELEASE(&cx->tempPool, mark); - if (!ok) - return JS_FALSE; - } - - if (argc) { - str = js_ValueToString(cx, argv[argc-1]); - } else { - /* Can't use cx->runtime->emptyString because we're called too early. */ - str = js_NewStringCopyZ(cx, js_empty_ucstr, 0); - } - if (!str) - return JS_FALSE; - if (argv) { - /* Use the last arg (or this if argc == 0) as a local GC root. */ - argv[(intN)(argc-1)] = STRING_TO_JSVAL(str); - } - - mark = JS_ARENA_MARK(&cx->tempPool); - ts = js_NewTokenStream(cx, JSSTRING_CHARS(str), JSSTRING_LENGTH(str), - filename, lineno, principals); - if (!ts) { - ok = JS_FALSE; - } else { - ok = js_CompileFunctionBody(cx, ts, fun) && - js_CloseTokenStream(cx, ts); - } - JS_ARENA_RELEASE(&cx->tempPool, mark); - return ok; - -bad_formal: - /* - * Report "malformed formal parameter" iff no illegal char or similar - * scanner error was already reported. - */ - if (!(ts->flags & TSF_ERROR)) - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_FORMAL); - -bad: - /* - * Clean up the arguments string and tokenstream if we failed to parse - * the arguments. - */ - (void)js_CloseTokenStream(cx, ts); - JS_ARENA_RELEASE(&cx->tempPool, mark); - return JS_FALSE; -} - -JSObject * -js_InitFunctionClass(JSContext *cx, JSObject *obj) -{ - JSObject *proto; - JSAtom *atom; - JSFunction *fun; - - proto = JS_InitClass(cx, obj, NULL, &js_FunctionClass, Function, 1, - function_props, function_methods, NULL, NULL); - if (!proto) - return NULL; - atom = js_Atomize(cx, js_FunctionClass.name, strlen(js_FunctionClass.name), - 0); - if (!atom) - goto bad; - fun = js_NewFunction(cx, proto, NULL, 0, 0, obj, NULL); - if (!fun) - goto bad; - fun->u.script = js_NewScript(cx, 0, 0, 0); - if (!fun->u.script) - goto bad; - fun->interpreted = JS_TRUE; - return proto; - -bad: - cx->newborn[GCX_OBJECT] = NULL; - return NULL; -} - -#if JS_HAS_CALL_OBJECT -JSObject * -js_InitCallClass(JSContext *cx, JSObject *obj) -{ - JSObject *proto; - - proto = JS_InitClass(cx, obj, NULL, &js_CallClass, NULL, 0, - call_props, NULL, NULL, NULL); - if (!proto) - return NULL; - - /* - * Null Call.prototype's proto slot so that Object.prototype.* does not - * pollute the scope of heavyweight functions. - */ - OBJ_SET_PROTO(cx, proto, NULL); - return proto; -} -#endif - -JSFunction * -js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs, - uintN flags, JSObject *parent, JSAtom *atom) -{ - JSFunction *fun; - JSTempValueRooter tvr; - - /* If funobj is null, allocate an object for it. */ - if (funobj) { - OBJ_SET_PARENT(cx, funobj, parent); - } else { - funobj = js_NewObject(cx, &js_FunctionClass, NULL, parent); - if (!funobj) - return NULL; - } - - /* Protect fun from any potential last-ditch GCs. */ - JS_PUSH_SINGLE_TEMP_ROOT(cx, OBJECT_TO_JSVAL(funobj), &tvr); - - /* - * Allocate fun after allocating funobj so slot allocation in js_NewObject - * does not wipe out fun from cx->newborn[GCX_PRIVATE]. - */ - fun = (JSFunction *) js_NewGCThing(cx, GCX_PRIVATE, sizeof(JSFunction)); - if (!fun) - goto out; - - /* Initialize all function members. */ - fun->nrefs = 0; - fun->object = NULL; - fun->u.native = native; - fun->nargs = nargs; - fun->extra = 0; - fun->nvars = 0; - fun->flags = flags & JSFUN_FLAGS_MASK; - fun->interpreted = JS_FALSE; - fun->nregexps = 0; - fun->spare = 0; - fun->atom = atom; - fun->clasp = NULL; - - /* Link fun to funobj and vice versa. */ - if (!js_LinkFunctionObject(cx, fun, funobj)) { - cx->newborn[GCX_OBJECT] = NULL; - fun = NULL; - } - -out: - JS_POP_TEMP_ROOT(cx, &tvr); - return fun; -} - -JSObject * -js_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent) -{ - JSObject *newfunobj; - JSFunction *fun; - - JS_ASSERT(OBJ_GET_CLASS(cx, funobj) == &js_FunctionClass); - newfunobj = js_NewObject(cx, &js_FunctionClass, funobj, parent); - if (!newfunobj) - return NULL; - fun = (JSFunction *) JS_GetPrivate(cx, funobj); - if (!js_LinkFunctionObject(cx, fun, newfunobj)) { - cx->newborn[GCX_OBJECT] = NULL; - return NULL; - } - return newfunobj; -} - -JSBool -js_LinkFunctionObject(JSContext *cx, JSFunction *fun, JSObject *funobj) -{ - if (!fun->object) - fun->object = funobj; - if (!JS_SetPrivate(cx, funobj, fun)) - return JS_FALSE; - JS_ATOMIC_INCREMENT(&fun->nrefs); - return JS_TRUE; -} - -JSFunction * -js_DefineFunction(JSContext *cx, JSObject *obj, JSAtom *atom, JSNative native, - uintN nargs, uintN attrs) -{ - JSFunction *fun; - - fun = js_NewFunction(cx, NULL, native, nargs, attrs, obj, atom); - if (!fun) - return NULL; - if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), - OBJECT_TO_JSVAL(fun->object), - NULL, NULL, - attrs & ~JSFUN_FLAGS_MASK, NULL)) { - return NULL; - } - return fun; -} - -#if (JSV2F_CONSTRUCT & JSV2F_SEARCH_STACK) -# error "JSINVOKE_CONSTRUCT and JSV2F_SEARCH_STACK are not disjoint!" -#endif - -JSFunction * -js_ValueToFunction(JSContext *cx, jsval *vp, uintN flags) -{ - jsval v; - JSObject *obj; - - v = *vp; - obj = NULL; - if (JSVAL_IS_OBJECT(v)) { - obj = JSVAL_TO_OBJECT(v); - if (obj && OBJ_GET_CLASS(cx, obj) != &js_FunctionClass) { - if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_FUNCTION, &v)) - return NULL; - obj = JSVAL_IS_FUNCTION(cx, v) ? JSVAL_TO_OBJECT(v) : NULL; - } - } - if (!obj) { - js_ReportIsNotFunction(cx, vp, flags); - return NULL; - } - return (JSFunction *) JS_GetPrivate(cx, obj); -} - -JSObject * -js_ValueToFunctionObject(JSContext *cx, jsval *vp, uintN flags) -{ - JSFunction *fun; - JSObject *funobj; - JSStackFrame *caller; - JSPrincipals *principals; - - if (JSVAL_IS_FUNCTION(cx, *vp)) - return JSVAL_TO_OBJECT(*vp); - - fun = js_ValueToFunction(cx, vp, flags); - if (!fun) - return NULL; - funobj = fun->object; - *vp = OBJECT_TO_JSVAL(funobj); - - caller = JS_GetScriptedCaller(cx, cx->fp); - if (caller) { - principals = caller->script->principals; - } else { - /* No scripted caller, don't allow access. */ - principals = NULL; - } - - /* - * FIXME: Reparameterize so we don't call js_AtomToPrintableString unless - * there is an error (bug 324694). - */ - if (!js_CheckPrincipalsAccess(cx, funobj, principals, - fun->atom - ? js_AtomToPrintableString(cx, fun->atom) - : js_anonymous_str)) { - return NULL; - } - return funobj; -} - -JSObject * -js_ValueToCallableObject(JSContext *cx, jsval *vp, uintN flags) -{ - JSObject *callable; - - callable = JSVAL_IS_PRIMITIVE(*vp) ? NULL : JSVAL_TO_OBJECT(*vp); - if (callable && - ((callable->map->ops == &js_ObjectOps) - ? OBJ_GET_CLASS(cx, callable)->call - : callable->map->ops->call)) { - *vp = OBJECT_TO_JSVAL(callable); - } else { - callable = js_ValueToFunctionObject(cx, vp, flags); - } - return callable; -} - -void -js_ReportIsNotFunction(JSContext *cx, jsval *vp, uintN flags) -{ - JSType type; - JSString *fallback; - JSString *str; - - /* - * We provide the typename as the fallback to handle the case when - * valueOf is not a function, which prevents ValueToString from being - * called as the default case inside js_DecompileValueGenerator (and - * so recursing back to here). - */ - type = JS_TypeOfValue(cx, *vp); - fallback = ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[type]); - str = js_DecompileValueGenerator(cx, - (flags & JSV2F_SEARCH_STACK) - ? JSDVG_SEARCH_STACK - : cx->fp - ? vp - cx->fp->sp - : JSDVG_IGNORE_STACK, - *vp, - fallback); - if (str) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - (uintN)((flags & JSV2F_CONSTRUCT) - ? JSMSG_NOT_CONSTRUCTOR - : JSMSG_NOT_FUNCTION), - JS_GetStringBytes(str)); - } -} diff --git a/lib/javascript/jsfun.h b/lib/javascript/jsfun.h deleted file mode 100644 index 25aa1032..00000000 --- a/lib/javascript/jsfun.h +++ /dev/null @@ -1,164 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jsfun_h___ -#define jsfun_h___ -/* - * JS function definitions. - */ -#include "jsprvtd.h" -#include "jspubtd.h" - -JS_BEGIN_EXTERN_C - -struct JSFunction { - jsrefcount nrefs; /* number of referencing objects */ - JSObject *object; /* back-pointer to GC'ed object header */ - union { - JSNative native; /* native method pointer or null */ - JSScript *script; /* interpreted bytecode descriptor or null */ - } u; - uint16 nargs; /* minimum number of actual arguments */ - uint16 extra; /* number of arg slots for local GC roots */ - uint16 nvars; /* number of local variables */ - uint8 flags; /* bound method and other flags, see jsapi.h */ - JSPackedBool interpreted; /* use u.script if true, u.native if false */ - uint16 nregexps; /* number of regular expressions literals */ - uint16 spare; /* reserved for future use */ - JSAtom *atom; /* name for diagnostics and decompiling */ - JSClass *clasp; /* if non-null, constructor for this class */ -}; - -#define FUN_NATIVE(fun) ((fun)->interpreted ? NULL : (fun)->u.native) -#define FUN_SCRIPT(fun) ((fun)->interpreted ? (fun)->u.script : NULL) - -extern JSClass js_ArgumentsClass; -extern JSClass js_CallClass; - -/* JS_FRIEND_DATA so that JSVAL_IS_FUNCTION is callable from outside */ -extern JS_FRIEND_DATA(JSClass) js_FunctionClass; - -/* - * NB: jsapi.h and jsobj.h must be included before any call to this macro. - */ -#define JSVAL_IS_FUNCTION(cx, v) \ - (!JSVAL_IS_PRIMITIVE(v) && \ - OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_FunctionClass) - -extern JSBool -js_fun_toString(JSContext *cx, JSObject *obj, uint32 indent, - uintN argc, jsval *argv, jsval *rval); - -extern JSBool -js_IsIdentifier(JSString *str); - -extern JSObject * -js_InitFunctionClass(JSContext *cx, JSObject *obj); - -extern JSObject * -js_InitArgumentsClass(JSContext *cx, JSObject *obj); - -extern JSObject * -js_InitCallClass(JSContext *cx, JSObject *obj); - -extern JSFunction * -js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs, - uintN flags, JSObject *parent, JSAtom *atom); - -extern JSObject * -js_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent); - -extern JSBool -js_LinkFunctionObject(JSContext *cx, JSFunction *fun, JSObject *object); - -extern JSFunction * -js_DefineFunction(JSContext *cx, JSObject *obj, JSAtom *atom, JSNative native, - uintN nargs, uintN flags); - -/* - * Flags for js_ValueToFunction and js_ReportIsNotFunction. We depend on the - * fact that JSINVOKE_CONSTRUCT (aka JSFRAME_CONSTRUCTING) is 1, and test that - * with #if/#error in jsfun.c. - */ -#define JSV2F_CONSTRUCT JSINVOKE_CONSTRUCT -#define JSV2F_SEARCH_STACK 2 - -extern JSFunction * -js_ValueToFunction(JSContext *cx, jsval *vp, uintN flags); - -extern JSObject * -js_ValueToFunctionObject(JSContext *cx, jsval *vp, uintN flags); - -extern JSObject * -js_ValueToCallableObject(JSContext *cx, jsval *vp, uintN flags); - -extern void -js_ReportIsNotFunction(JSContext *cx, jsval *vp, uintN flags); - -extern JSObject * -js_GetCallObject(JSContext *cx, JSStackFrame *fp, JSObject *parent); - -extern JSBool -js_PutCallObject(JSContext *cx, JSStackFrame *fp); - -extern JSBool -js_GetCallVariable(JSContext *cx, JSObject *obj, jsval id, jsval *vp); - -extern JSBool -js_SetCallVariable(JSContext *cx, JSObject *obj, jsval id, jsval *vp); - -extern JSBool -js_GetArgsValue(JSContext *cx, JSStackFrame *fp, jsval *vp); - -extern JSBool -js_GetArgsProperty(JSContext *cx, JSStackFrame *fp, jsid id, - JSObject **objp, jsval *vp); - -extern JSObject * -js_GetArgsObject(JSContext *cx, JSStackFrame *fp); - -extern JSBool -js_PutArgsObject(JSContext *cx, JSStackFrame *fp); - -extern JSBool -js_XDRFunction(JSXDRState *xdr, JSObject **objp); - -JS_END_EXTERN_C - -#endif /* jsfun_h___ */ diff --git a/lib/javascript/jsgc.c b/lib/javascript/jsgc.c deleted file mode 100644 index 2383240c..00000000 --- a/lib/javascript/jsgc.c +++ /dev/null @@ -1,1989 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JS Mark-and-Sweep Garbage Collector. - * - * This GC allocates only fixed-sized things big enough to contain two words - * (pointers) on any host architecture. It allocates from an arena pool (see - * jsarena.h). It uses an ideally parallel array of flag bytes to hold the - * mark bit, finalizer type index, etc. - * - * XXX swizzle page to freelist for better locality of reference - */ -#include "jsstddef.h" -#include /* for free, called by JS_ARENA_DESTROY */ -#include /* for memset, called by jsarena.h macros if DEBUG */ -#include "jstypes.h" -#include "jsarena.h" /* Added by JSIFY */ -#include "jsutil.h" /* Added by JSIFY */ -#include "jshash.h" /* Added by JSIFY */ -#include "jsapi.h" -#include "jsatom.h" -#include "jscntxt.h" -#include "jsconfig.h" -#include "jsdbgapi.h" -#include "jsfun.h" -#include "jsgc.h" -#include "jsinterp.h" -#include "jslock.h" -#include "jsnum.h" -#include "jsobj.h" -#include "jsscope.h" -#include "jsscript.h" -#include "jsstr.h" - -#if JS_HAS_XML_SUPPORT -#include "jsxml.h" -#endif - -/* - * GC arena sizing depends on amortizing arena overhead using a large number - * of things per arena, and on the thing/flags ratio of 8:1 on most platforms. - * - * On 64-bit platforms, we would have half as many things per arena because - * pointers are twice as big, so we double the bytes for things per arena. - * This preserves the 1024 byte flags sub-arena size, which relates to the - * GC_PAGE_SIZE (see below for why). - */ -#if JS_BYTES_PER_WORD == 8 -# define GC_THINGS_SHIFT 14 /* 16KB for things on Alpha, etc. */ -#else -# define GC_THINGS_SHIFT 13 /* 8KB for things on most platforms */ -#endif -#define GC_THINGS_SIZE JS_BIT(GC_THINGS_SHIFT) -#define GC_FLAGS_SIZE (GC_THINGS_SIZE / sizeof(JSGCThing)) -#define GC_ARENA_SIZE (GC_THINGS_SIZE + GC_FLAGS_SIZE) - -/* - * A GC arena contains one flag byte for each thing in its heap, and supports - * O(1) lookup of a flag given its thing's address. - * - * To implement this, we take advantage of the thing/flags numerology: given - * the 8K bytes worth of GC-things, there are 1K flag bytes. We mask a thing's - * address with ~1023 to find a JSGCPageInfo record at the front of a mythical - * "GC page" within the larger 8K thing arena. That JSGCPageInfo contains a - * pointer to the 128 flag bytes corresponding to the things in the page, so we - * index into this flags array using the thing's index within its page. - * - * To align thing pages on 1024-byte boundaries, we must allocate the 9KB of - * flags+things arena payload, then find the first 0 mod 1024 boundary after - * the first payload address. That's where things start, with a JSGCPageInfo - * taking up the first thing-slot, as usual for 0 mod 1024 byte boundaries. - * The effect of this alignment trick is to split the flags into at most 2 - * discontiguous spans, one before the things and one after (if we're really - * lucky, and the arena payload starts on a 0 mod 1024 byte boundary, no need - * to split). - * - * The overhead of this scheme for most platforms is (16+8*(8+1))/(16+9K) or - * .95% (assuming 16 byte JSArena header size, and 8 byte JSGCThing size). - * - * Here's some ASCII art showing an arena: - * - * split - * | - * V - * +--+-------+-------+-------+-------+-------+-------+-------+-------+-----+ - * |fB| tp0 | tp1 | tp2 | tp3 | tp4 | tp5 | tp6 | tp7 | fA | - * +--+-------+-------+-------+-------+-------+-------+-------+-------+-----+ - * ^ ^ - * tI ---------+ | - * tJ -------------------------------------------+ - * - * - fB are the "before split" flags, fA are the "after split" flags - * - tp0-tp7 are the 8 thing pages - * - thing tI points into tp1, whose flags are below the split, in fB - * - thing tJ points into tp5, clearly above the split - * - * In general, one of the thing pages will have some of its things' flags on - * the low side of the split, and the rest of its things' flags on the high - * side. All the other pages have flags only below or only above. Therefore - * we'll have to test something to decide whether the split divides flags in - * a given thing's page. So we store the split pointer (the pointer to tp0) - * in each JSGCPageInfo, along with the flags pointer for the 128 flag bytes - * ideally starting, for tp0 things, at the beginning of the arena's payload - * (at the start of fB). - * - * That is, each JSGCPageInfo's flags pointer is 128 bytes from the previous, - * or at the start of the arena if there is no previous page in this arena. - * Thus these ideal 128-byte flag pages run contiguously from the start of the - * arena (right over the split!), and the JSGCPageInfo flags pointers contain - * no discontinuities over the split created by the thing pages. So if, for a - * given JSGCPageInfo *pi, we find that - * - * pi->flags + ((jsuword)thing % 1024) / sizeof(JSGCThing) >= pi->split - * - * then we must add GC_THINGS_SIZE to the nominal flags pointer to jump over - * all the thing pages that split the flags into two discontiguous spans. - * - * (If we need to implement card-marking for an incremental GC write barrier, - * we can use the low byte of the pi->split pointer as the card-mark, for an - * extremely efficient write barrier: when mutating an object obj, just store - * a 1 byte at (uint8 *) ((jsuword)obj & ~1023) for little-endian platforms. - * When finding flags, we'll of course have to mask split with ~255, but it is - * guaranteed to be 1024-byte aligned, so no information is lost by overlaying - * the card-mark byte on split's low byte.) - */ -#define GC_PAGE_SHIFT 10 -#define GC_PAGE_MASK ((jsuword) JS_BITMASK(GC_PAGE_SHIFT)) -#define GC_PAGE_SIZE JS_BIT(GC_PAGE_SHIFT) - -typedef struct JSGCPageInfo { - uint8 *split; - uint8 *flags; -} JSGCPageInfo; - -#define FIRST_THING_PAGE(a) (((a)->base + GC_FLAGS_SIZE) & ~GC_PAGE_MASK) - -/* - * Given a jsuword page pointer p and a thing size n, return the address of - * the first thing in p. We know that any n not a power of two packs from - * the end of the page leaving at least enough room for one JSGCPageInfo, but - * not for another thing, at the front of the page (JS_ASSERTs below insist - * on this). - * - * This works because all allocations are a multiple of sizeof(JSGCThing) == - * sizeof(JSGCPageInfo) in size. - */ -#define FIRST_THING(p,n) (((n) & ((n) - 1)) \ - ? (p) + (uint32)(GC_PAGE_SIZE % (n)) \ - : (p) + (n)) - -static JSGCThing * -gc_new_arena(JSArenaPool *pool, size_t nbytes) -{ - uint8 *flagp, *split, *pagep, *limit; - JSArena *a; - jsuword p; - JSGCThing *thing; - JSGCPageInfo *pi; - - /* Use JS_ArenaAllocate to grab another 9K-net-size hunk of space. */ - flagp = (uint8 *) JS_ArenaAllocate(pool, GC_ARENA_SIZE); - if (!flagp) - return NULL; - a = pool->current; - - /* Reset a->avail to start at the flags split, aka the first thing page. */ - p = FIRST_THING_PAGE(a); - split = pagep = (uint8 *) p; - a->avail = FIRST_THING(p, nbytes); - JS_ASSERT(a->avail >= p + sizeof(JSGCPageInfo)); - thing = (JSGCThing *) a->avail; - JS_ArenaCountAllocation(pool, a->avail - p); - a->avail += nbytes; - - /* Initialize the JSGCPageInfo records at the start of every thing page. */ - limit = pagep + GC_THINGS_SIZE; - do { - pi = (JSGCPageInfo *) pagep; - pi->split = split; - pi->flags = flagp; - flagp += GC_PAGE_SIZE >> (GC_THINGS_SHIFT - GC_PAGE_SHIFT); - pagep += GC_PAGE_SIZE; - } while (pagep < limit); - return thing; -} - -uint8 * -js_GetGCThingFlags(void *thing) -{ - JSGCPageInfo *pi; - uint8 *flagp; - - pi = (JSGCPageInfo *) ((jsuword)thing & ~GC_PAGE_MASK); - flagp = pi->flags + ((jsuword)thing & GC_PAGE_MASK) / sizeof(JSGCThing); - if (flagp >= pi->split) - flagp += GC_THINGS_SIZE; - return flagp; -} - -JSBool -js_IsAboutToBeFinalized(JSContext *cx, void *thing) -{ - uint8 flags = *js_GetGCThingFlags(thing); - - return !(flags & (GCF_MARK | GCF_LOCK | GCF_FINAL)); -} - -typedef void (*GCFinalizeOp)(JSContext *cx, JSGCThing *thing); - -#ifndef DEBUG -# define js_FinalizeDouble NULL -#endif - -#if !JS_HAS_XML_SUPPORT -# define js_FinalizeXMLNamespace NULL -# define js_FinalizeXMLQName NULL -# define js_FinalizeXML NULL -#endif - -static GCFinalizeOp gc_finalizers[GCX_NTYPES] = { - (GCFinalizeOp) js_FinalizeObject, /* GCX_OBJECT */ - (GCFinalizeOp) js_FinalizeString, /* GCX_STRING */ - (GCFinalizeOp) js_FinalizeDouble, /* GCX_DOUBLE */ - (GCFinalizeOp) js_FinalizeString, /* GCX_MUTABLE_STRING */ - NULL, /* GCX_PRIVATE */ - (GCFinalizeOp) js_FinalizeXMLNamespace, /* GCX_NAMESPACE */ - (GCFinalizeOp) js_FinalizeXMLQName, /* GCX_QNAME */ - (GCFinalizeOp) js_FinalizeXML, /* GCX_XML */ - NULL, /* GCX_EXTERNAL_STRING */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL -}; - -#ifdef GC_MARK_DEBUG -static const char newborn_external_string[] = "newborn external string"; - -static const char *gc_typenames[GCX_NTYPES] = { - "newborn object", - "newborn string", - "newborn double", - "newborn mutable string", - "newborn private", - "newborn Namespace", - "newborn QName", - "newborn XML", - newborn_external_string, - newborn_external_string, - newborn_external_string, - newborn_external_string, - newborn_external_string, - newborn_external_string, - newborn_external_string, - newborn_external_string -}; -#endif - -intN -js_ChangeExternalStringFinalizer(JSStringFinalizeOp oldop, - JSStringFinalizeOp newop) -{ - uintN i; - - for (i = GCX_EXTERNAL_STRING; i < GCX_NTYPES; i++) { - if (gc_finalizers[i] == (GCFinalizeOp) oldop) { - gc_finalizers[i] = (GCFinalizeOp) newop; - return (intN) i; - } - } - return -1; -} - -#ifdef JS_GCMETER -#define METER(x) x -#else -#define METER(x) /* nothing */ -#endif - -/* Initial size of the gcRootsHash table (SWAG, small enough to amortize). */ -#define GC_ROOTS_SIZE 256 -#define GC_FINALIZE_LEN 1024 - -JSBool -js_InitGC(JSRuntime *rt, uint32 maxbytes) -{ - uintN i; - - JS_ASSERT(sizeof(JSGCThing) == sizeof(JSGCPageInfo)); - JS_ASSERT(sizeof(JSGCThing) >= sizeof(JSObject)); - JS_ASSERT(sizeof(JSGCThing) >= sizeof(JSString)); - JS_ASSERT(sizeof(JSGCThing) >= sizeof(jsdouble)); - JS_ASSERT(GC_FLAGS_SIZE >= GC_PAGE_SIZE); - JS_ASSERT(sizeof(JSStackHeader) >= 2 * sizeof(jsval)); - - for (i = 0; i < GC_NUM_FREELISTS; i++) - JS_InitArenaPool(&rt->gcArenaPool[i], "gc-arena", GC_ARENA_SIZE, 1); - if (!JS_DHashTableInit(&rt->gcRootsHash, JS_DHashGetStubOps(), NULL, - sizeof(JSGCRootHashEntry), GC_ROOTS_SIZE)) { - rt->gcRootsHash.ops = NULL; - return JS_FALSE; - } - rt->gcLocksHash = NULL; /* create lazily */ - - /* - * Separate gcMaxMallocBytes from gcMaxBytes but initialize to maxbytes - * for default backward API compatibility. - */ - rt->gcMaxBytes = rt->gcMaxMallocBytes = maxbytes; - return JS_TRUE; -} - -#ifdef JS_GCMETER -JS_FRIEND_API(void) -js_DumpGCStats(JSRuntime *rt, FILE *fp) -{ - uintN i; - - fprintf(fp, "\nGC allocation statistics:\n"); - -#define UL(x) ((unsigned long)(x)) -#define ULSTAT(x) UL(rt->gcStats.x) - fprintf(fp, " public bytes allocated: %lu\n", UL(rt->gcBytes)); - fprintf(fp, " private bytes allocated: %lu\n", UL(rt->gcPrivateBytes)); - fprintf(fp, " alloc attempts: %lu\n", ULSTAT(alloc)); - for (i = 0; i < GC_NUM_FREELISTS; i++) { - fprintf(fp, " GC freelist %u length: %lu\n", - i, ULSTAT(freelen[i])); - fprintf(fp, " recycles via GC freelist %u: %lu\n", - i, ULSTAT(recycle[i])); - } - fprintf(fp, "allocation retries after GC: %lu\n", ULSTAT(retry)); - fprintf(fp, " allocation failures: %lu\n", ULSTAT(fail)); - fprintf(fp, " things born locked: %lu\n", ULSTAT(lockborn)); - fprintf(fp, " valid lock calls: %lu\n", ULSTAT(lock)); - fprintf(fp, " valid unlock calls: %lu\n", ULSTAT(unlock)); - fprintf(fp, " mark recursion depth: %lu\n", ULSTAT(depth)); - fprintf(fp, " maximum mark recursion: %lu\n", ULSTAT(maxdepth)); - fprintf(fp, " mark C recursion depth: %lu\n", ULSTAT(cdepth)); - fprintf(fp, " maximum mark C recursion: %lu\n", ULSTAT(maxcdepth)); - fprintf(fp, " mark C stack overflows: %lu\n", ULSTAT(dswmark)); - fprintf(fp, " mark DSW recursion depth: %lu\n", ULSTAT(dswdepth)); - fprintf(fp, " maximum mark DSW recursion: %lu\n", ULSTAT(maxdswdepth)); - fprintf(fp, " mark DSW up-tree movement: %lu\n", ULSTAT(dswup)); - fprintf(fp, "DSW up-tree obj->slot steps: %lu\n", ULSTAT(dswupstep)); - fprintf(fp, " maximum GC nesting level: %lu\n", ULSTAT(maxlevel)); - fprintf(fp, "potentially useful GC calls: %lu\n", ULSTAT(poke)); - fprintf(fp, " useless GC calls: %lu\n", ULSTAT(nopoke)); - fprintf(fp, " thing arenas freed so far: %lu\n", ULSTAT(afree)); - fprintf(fp, " stack segments scanned: %lu\n", ULSTAT(stackseg)); - fprintf(fp, "stack segment slots scanned: %lu\n", ULSTAT(segslots)); -#undef UL -#undef US - -#ifdef JS_ARENAMETER - JS_DumpArenaStats(fp); -#endif -} -#endif - -#ifdef DEBUG -JS_STATIC_DLL_CALLBACK(JSDHashOperator) -js_root_printer(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 i, void *arg) -{ - uint32 *leakedroots = (uint32 *)arg; - JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr; - - (*leakedroots)++; - fprintf(stderr, - "JS engine warning: leaking GC root \'%s\' at %p\n", - rhe->name ? (char *)rhe->name : "", rhe->root); - - return JS_DHASH_NEXT; -} -#endif - -void -js_FinishGC(JSRuntime *rt) -{ - uintN i; - -#ifdef JS_ARENAMETER - JS_DumpArenaStats(stdout); -#endif -#ifdef JS_GCMETER - js_DumpGCStats(rt, stdout); -#endif - for (i = 0; i < GC_NUM_FREELISTS; i++) { - JS_FinishArenaPool(&rt->gcArenaPool[i]); - rt->gcFreeList[i] = NULL; - } - JS_ArenaFinish(); - - if (rt->gcRootsHash.ops) { -#ifdef DEBUG - uint32 leakedroots = 0; - - /* Warn (but don't assert) debug builds of any remaining roots. */ - JS_DHashTableEnumerate(&rt->gcRootsHash, js_root_printer, - &leakedroots); - if (leakedroots > 0) { - if (leakedroots == 1) { - fprintf(stderr, -"JS engine warning: 1 GC root remains after destroying the JSRuntime.\n" -" This root may point to freed memory. Objects reachable\n" -" through it have not been finalized.\n"); - } else { - fprintf(stderr, -"JS engine warning: %lu GC roots remain after destroying the JSRuntime.\n" -" These roots may point to freed memory. Objects reachable\n" -" through them have not been finalized.\n", - (unsigned long) leakedroots); - } - } -#endif - - JS_DHashTableFinish(&rt->gcRootsHash); - rt->gcRootsHash.ops = NULL; - } - if (rt->gcLocksHash) { - JS_DHashTableDestroy(rt->gcLocksHash); - rt->gcLocksHash = NULL; - } -} - -JSBool -js_AddRoot(JSContext *cx, void *rp, const char *name) -{ - JSBool ok = js_AddRootRT(cx->runtime, rp, name); - if (!ok) - JS_ReportOutOfMemory(cx); - return ok; -} - -JSBool -js_AddRootRT(JSRuntime *rt, void *rp, const char *name) -{ - JSBool ok; - JSGCRootHashEntry *rhe; - - /* - * Due to the long-standing, but now removed, use of rt->gcLock across the - * bulk of js_GC, API users have come to depend on JS_AddRoot etc. locking - * properly with a racing GC, without calling JS_AddRoot from a request. - * We have to preserve API compatibility here, now that we avoid holding - * rt->gcLock across the mark phase (including the root hashtable mark). - * - * If the GC is running and we're called on another thread, wait for this - * GC activation to finish. We can safely wait here (in the case where we - * are called within a request on another thread's context) without fear - * of deadlock because the GC doesn't set rt->gcRunning until after it has - * waited for all active requests to end. - */ - JS_LOCK_GC(rt); -#ifdef JS_THREADSAFE - JS_ASSERT(!rt->gcRunning || rt->gcLevel > 0); - if (rt->gcRunning && rt->gcThread != js_CurrentThreadId()) { - do { - JS_AWAIT_GC_DONE(rt); - } while (rt->gcLevel > 0); - } -#endif - rhe = (JSGCRootHashEntry *) JS_DHashTableOperate(&rt->gcRootsHash, rp, - JS_DHASH_ADD); - if (rhe) { - rhe->root = rp; - rhe->name = name; - ok = JS_TRUE; - } else { - ok = JS_FALSE; - } - JS_UNLOCK_GC(rt); - return ok; -} - -JSBool -js_RemoveRoot(JSRuntime *rt, void *rp) -{ - /* - * Due to the JS_RemoveRootRT API, we may be called outside of a request. - * Same synchronization drill as above in js_AddRoot. - */ - JS_LOCK_GC(rt); -#ifdef JS_THREADSAFE - JS_ASSERT(!rt->gcRunning || rt->gcLevel > 0); - if (rt->gcRunning && rt->gcThread != js_CurrentThreadId()) { - do { - JS_AWAIT_GC_DONE(rt); - } while (rt->gcLevel > 0); - } -#endif - (void) JS_DHashTableOperate(&rt->gcRootsHash, rp, JS_DHASH_REMOVE); - rt->gcPoke = JS_TRUE; - JS_UNLOCK_GC(rt); - return JS_TRUE; -} - -#ifdef DEBUG_brendan -#define NGCHIST 64 - -static struct GCHist { - JSBool lastDitch; - JSGCThing *freeList; -} gchist[NGCHIST]; - -unsigned gchpos; -#endif - -void * -js_NewGCThing(JSContext *cx, uintN flags, size_t nbytes) -{ - JSBool tried_gc; - JSRuntime *rt; - size_t nflags; - uintN i; - JSGCThing *thing, **flp; - uint8 *flagp; - JSLocalRootStack *lrs; - uint32 *bytesptr; - - rt = cx->runtime; - JS_LOCK_GC(rt); - JS_ASSERT(!rt->gcRunning); - if (rt->gcRunning) { - METER(rt->gcStats.finalfail++); - JS_UNLOCK_GC(rt); - return NULL; - } - -#ifdef TOO_MUCH_GC -#ifdef WAY_TOO_MUCH_GC - rt->gcPoke = JS_TRUE; -#endif - js_GC(cx, GC_KEEP_ATOMS | GC_ALREADY_LOCKED); - tried_gc = JS_TRUE; -#else - tried_gc = JS_FALSE; -#endif - - METER(rt->gcStats.alloc++); - nbytes = JS_ROUNDUP(nbytes, sizeof(JSGCThing)); - nflags = nbytes / sizeof(JSGCThing); - i = GC_FREELIST_INDEX(nbytes); - flp = &rt->gcFreeList[i]; - -retry: - thing = *flp; - if (thing) { - *flp = thing->next; - flagp = thing->flagp; - METER(rt->gcStats.freelen[i]--); - METER(rt->gcStats.recycle[i]++); - } else { - if (rt->gcBytes < rt->gcMaxBytes && - (tried_gc || rt->gcMallocBytes < rt->gcMaxMallocBytes)) - { - /* - * Inline form of JS_ARENA_ALLOCATE adapted to truncate the current - * arena's limit to a GC_PAGE_SIZE boundary, and to skip over every - * GC_PAGE_SIZE-byte-aligned thing (which is actually not a thing, - * it's a JSGCPageInfo record). - */ - JSArenaPool *pool = &rt->gcArenaPool[i]; - JSArena *a = pool->current; - jsuword p = a->avail; - jsuword q = p + nbytes; - - if (q > (a->limit & ~GC_PAGE_MASK)) { - thing = gc_new_arena(pool, nbytes); - } else { - if ((p & GC_PAGE_MASK) == 0) { - /* Beware, p points to a JSGCPageInfo record! */ - p = FIRST_THING(p, nbytes); - q = p + nbytes; - JS_ArenaCountAllocation(pool, p & GC_PAGE_MASK); - } - a->avail = q; - thing = (JSGCThing *)p; - } - JS_ArenaCountAllocation(pool, nbytes); - } - - /* - * Consider doing a "last ditch" GC if thing couldn't be allocated. - * - * Keep rt->gcLock across the call into js_GC so we don't starve and - * lose to racing threads who deplete the heap just after js_GC has - * replenished it (or has synchronized with a racing GC that collected - * a bunch of garbage). This unfair scheduling can happen on certain - * operating systems. For the gory details, see Mozilla bug 162779 - * (http://bugzilla.mozilla.org/show_bug.cgi?id=162779). - */ - if (!thing) { - if (!tried_gc) { - rt->gcPoke = JS_TRUE; - js_GC(cx, GC_KEEP_ATOMS | GC_ALREADY_LOCKED); - tried_gc = JS_TRUE; - METER(rt->gcStats.retry++); - goto retry; - } - goto fail; - } - - /* Find the flags pointer given thing's address. */ - flagp = js_GetGCThingFlags(thing); - } - - lrs = cx->localRootStack; - if (lrs) { - /* - * If we're in a local root scope, don't set cx->newborn[type] at all, - * to avoid entraining garbage from it for an unbounded amount of time - * on this context. A caller will leave the local root scope and pop - * this reference, allowing thing to be GC'd if it has no other refs. - * See JS_EnterLocalRootScope and related APIs. - */ - if (js_PushLocalRoot(cx, lrs, (jsval) thing) < 0) { - /* - * When we fail for a thing allocated through the tail of - * the last arena, thing's flag byte is not initialized. So - * to prevent GC accessing the uninitialized flags during - * the finalization, we always mark the thing as final. See - * bug 337407. - */ - *flagp = GCF_FINAL; - goto fail; - } - } else { - /* - * No local root scope, so we're stuck with the old, fragile model of - * depending on a pigeon-hole newborn per type per context. - */ - cx->newborn[flags & GCF_TYPEMASK] = thing; - } - - /* We can't fail now, so update flags and rt->gc{,Private}Bytes. */ - *flagp = (uint8)flags; - bytesptr = ((flags & GCF_TYPEMASK) == GCX_PRIVATE) - ? &rt->gcPrivateBytes - : &rt->gcBytes; - *bytesptr += nbytes + nflags; - - /* - * Clear thing before unlocking in case a GC run is about to scan it, - * finding it via cx->newborn[]. - */ - thing->next = NULL; - thing->flagp = NULL; -#ifdef DEBUG_brendan - gchist[gchpos].lastDitch = tried_gc; - gchist[gchpos].freeList = *flp; - if (++gchpos == NGCHIST) - gchpos = 0; -#endif - METER(if (flags & GCF_LOCK) rt->gcStats.lockborn++); - JS_UNLOCK_GC(rt); - return thing; - -fail: - METER(rt->gcStats.fail++); - JS_UNLOCK_GC(rt); - JS_ReportOutOfMemory(cx); - return NULL; -} - -JSBool -js_LockGCThing(JSContext *cx, void *thing) -{ - JSBool ok = js_LockGCThingRT(cx->runtime, thing); - if (!ok) - JS_ReportOutOfMemory(cx); - return ok; -} - -/* - * Deep GC-things can't be locked just by setting the GCF_LOCK bit, because - * their descendants must be marked by the GC. To find them during the mark - * phase, they are added to rt->gcLocksHash, which is created lazily. - * - * NB: we depend on the order of GC-thing type indexes here! - */ -#define GC_TYPE_IS_STRING(t) ((t) == GCX_STRING || \ - (t) >= GCX_EXTERNAL_STRING) -#define GC_TYPE_IS_XML(t) ((unsigned)((t) - GCX_NAMESPACE) <= \ - (unsigned)(GCX_XML - GCX_NAMESPACE)) -#define GC_TYPE_IS_DEEP(t) ((t) == GCX_OBJECT || GC_TYPE_IS_XML(t)) - -#define IS_DEEP_STRING(t,o) (GC_TYPE_IS_STRING(t) && \ - JSSTRING_IS_DEPENDENT((JSString *)(o))) - -#define GC_THING_IS_DEEP(t,o) (GC_TYPE_IS_DEEP(t) || IS_DEEP_STRING(t, o)) - -JSBool -js_LockGCThingRT(JSRuntime *rt, void *thing) -{ - JSBool ok, deep; - uint8 *flagp, flags, lock, type; - JSGCLockHashEntry *lhe; - - ok = JS_TRUE; - if (!thing) - return ok; - - flagp = js_GetGCThingFlags(thing); - - JS_LOCK_GC(rt); - flags = *flagp; - lock = (flags & GCF_LOCK); - type = (flags & GCF_TYPEMASK); - deep = GC_THING_IS_DEEP(type, thing); - - /* - * Avoid adding a rt->gcLocksHash entry for shallow things until someone - * nests a lock -- then start such an entry with a count of 2, not 1. - */ - if (lock || deep) { - if (!rt->gcLocksHash) { - rt->gcLocksHash = - JS_NewDHashTable(JS_DHashGetStubOps(), NULL, - sizeof(JSGCLockHashEntry), - GC_ROOTS_SIZE); - if (!rt->gcLocksHash) { - ok = JS_FALSE; - goto done; - } - } else if (lock == 0) { -#ifdef DEBUG - JSDHashEntryHdr *hdr = - JS_DHashTableOperate(rt->gcLocksHash, thing, - JS_DHASH_LOOKUP); - JS_ASSERT(JS_DHASH_ENTRY_IS_FREE(hdr)); -#endif - } - - lhe = (JSGCLockHashEntry *) - JS_DHashTableOperate(rt->gcLocksHash, thing, JS_DHASH_ADD); - if (!lhe) { - ok = JS_FALSE; - goto done; - } - if (!lhe->thing) { - lhe->thing = thing; - lhe->count = deep ? 1 : 2; - } else { - JS_ASSERT(lhe->count >= 1); - lhe->count++; - } - } - - *flagp = (uint8)(flags | GCF_LOCK); - METER(rt->gcStats.lock++); - ok = JS_TRUE; -done: - JS_UNLOCK_GC(rt); - return ok; -} - -JSBool -js_UnlockGCThingRT(JSRuntime *rt, void *thing) -{ - uint8 *flagp, flags; - JSGCLockHashEntry *lhe; - - if (!thing) - return JS_TRUE; - - flagp = js_GetGCThingFlags(thing); - JS_LOCK_GC(rt); - flags = *flagp; - - if (flags & GCF_LOCK) { - if (!rt->gcLocksHash || - (lhe = (JSGCLockHashEntry *) - JS_DHashTableOperate(rt->gcLocksHash, thing, - JS_DHASH_LOOKUP), - JS_DHASH_ENTRY_IS_FREE(&lhe->hdr))) { - /* Shallow GC-thing with an implicit lock count of 1. */ - JS_ASSERT(!GC_THING_IS_DEEP(flags & GCF_TYPEMASK, thing)); - } else { - /* Basis or nested unlock of a deep thing, or nested of shallow. */ - if (--lhe->count != 0) - goto out; - JS_DHashTableOperate(rt->gcLocksHash, thing, JS_DHASH_REMOVE); - } - *flagp = (uint8)(flags & ~GCF_LOCK); - } - - rt->gcPoke = JS_TRUE; -out: - METER(rt->gcStats.unlock++); - JS_UNLOCK_GC(rt); - return JS_TRUE; -} - -#ifdef GC_MARK_DEBUG - -#include -#include "jsprf.h" - -JS_FRIEND_DATA(FILE *) js_DumpGCHeap; -JS_EXPORT_DATA(void *) js_LiveThingToFind; - -#ifdef HAVE_XPCONNECT -#include "dump_xpc.h" -#endif - -static const char * -gc_object_class_name(void* thing) -{ - uint8 *flagp = js_GetGCThingFlags(thing); - const char *className = ""; - static char depbuf[32]; - - switch (*flagp & GCF_TYPEMASK) { - case GCX_OBJECT: { - JSObject *obj = (JSObject *)thing; - JSClass *clasp = JSVAL_TO_PRIVATE(obj->slots[JSSLOT_CLASS]); - className = clasp->name; -#ifdef HAVE_XPCONNECT - if (clasp->flags & JSCLASS_PRIVATE_IS_NSISUPPORTS) { - jsval privateValue = obj->slots[JSSLOT_PRIVATE]; - - JS_ASSERT(clasp->flags & JSCLASS_HAS_PRIVATE); - if (!JSVAL_IS_VOID(privateValue)) { - void *privateThing = JSVAL_TO_PRIVATE(privateValue); - const char *xpcClassName = GetXPCObjectClassName(privateThing); - - if (xpcClassName) - className = xpcClassName; - } - } -#endif - break; - } - - case GCX_STRING: - case GCX_MUTABLE_STRING: { - JSString *str = (JSString *)thing; - if (JSSTRING_IS_DEPENDENT(str)) { - JS_snprintf(depbuf, sizeof depbuf, "start:%u, length:%u", - JSSTRDEP_START(str), JSSTRDEP_LENGTH(str)); - className = depbuf; - } else { - className = "string"; - } - break; - } - - case GCX_DOUBLE: - className = "double"; - break; - } - - return className; -} - -static void -gc_dump_thing(JSGCThing *thing, uint8 flags, GCMarkNode *prev, FILE *fp) -{ - GCMarkNode *next = NULL; - char *path = NULL; - - while (prev) { - next = prev; - prev = prev->prev; - } - while (next) { - uint8 nextFlags = *js_GetGCThingFlags(next->thing); - if ((nextFlags & GCF_TYPEMASK) == GCX_OBJECT) { - path = JS_sprintf_append(path, "%s(%s @ 0x%08p).", - next->name, - gc_object_class_name(next->thing), - (JSObject*)next->thing); - } else { - path = JS_sprintf_append(path, "%s(%s).", - next->name, - gc_object_class_name(next->thing)); - } - next = next->next; - } - if (!path) - return; - - fprintf(fp, "%08lx ", (long)thing); - switch (flags & GCF_TYPEMASK) { - case GCX_OBJECT: - { - JSObject *obj = (JSObject *)thing; - jsval privateValue = obj->slots[JSSLOT_PRIVATE]; - void *privateThing = JSVAL_IS_VOID(privateValue) - ? NULL - : JSVAL_TO_PRIVATE(privateValue); - const char *className = gc_object_class_name(thing); - fprintf(fp, "object %8p %s", privateThing, className); - break; - } -#if JS_HAS_XML_SUPPORT - case GCX_NAMESPACE: - { - JSXMLNamespace *ns = (JSXMLNamespace *)thing; - fprintf(fp, "namespace %s:%s", - JS_GetStringBytes(ns->prefix), JS_GetStringBytes(ns->uri)); - break; - } - case GCX_QNAME: - { - JSXMLQName *qn = (JSXMLQName *)thing; - fprintf(fp, "qname %s(%s):%s", - JS_GetStringBytes(qn->prefix), JS_GetStringBytes(qn->uri), - JS_GetStringBytes(qn->localName)); - break; - } - case GCX_XML: - { - extern const char *js_xml_class_str[]; - JSXML *xml = (JSXML *)thing; - fprintf(fp, "xml %8p %s", xml, js_xml_class_str[xml->xml_class]); - break; - } -#endif - case GCX_DOUBLE: - fprintf(fp, "double %g", *(jsdouble *)thing); - break; - case GCX_PRIVATE: - fprintf(fp, "private %8p", (void *)thing); - break; - default: - fprintf(fp, "string %s", JS_GetStringBytes((JSString *)thing)); - break; - } - fprintf(fp, " via %s\n", path); - free(path); -} - -#endif /* !GC_MARK_DEBUG */ - -static void -gc_mark_atom_key_thing(void *thing, void *arg) -{ - JSContext *cx = (JSContext *) arg; - - GC_MARK(cx, thing, "atom", NULL); -} - -void -js_MarkAtom(JSContext *cx, JSAtom *atom, void *arg) -{ - jsval key; - - if (atom->flags & ATOM_MARK) - return; - atom->flags |= ATOM_MARK; - key = ATOM_KEY(atom); - if (JSVAL_IS_GCTHING(key)) { -#ifdef GC_MARK_DEBUG - char name[32]; - - if (JSVAL_IS_STRING(key)) { - JS_snprintf(name, sizeof name, "'%s'", - JS_GetStringBytes(JSVAL_TO_STRING(key))); - } else { - JS_snprintf(name, sizeof name, "<%x>", key); - } -#endif - GC_MARK(cx, JSVAL_TO_GCTHING(key), name, arg); - } - if (atom->flags & ATOM_HIDDEN) - js_MarkAtom(cx, atom->entry.value, arg); -} - -/* - * These macros help avoid passing the GC_MARK_DEBUG-only |arg| parameter - * during recursive calls when GC_MARK_DEBUG is not defined. - */ -#ifdef GC_MARK_DEBUG -# define UNMARKED_GC_THING_FLAGS(thing, arg) \ - UnmarkedGCThingFlags(thing, arg) -# define NEXT_UNMARKED_GC_THING(vp, end, thingp, flagpp, arg) \ - NextUnmarkedGCThing(vp, end, thingp, flagpp, arg) -# define MARK_GC_THING(cx, thing, flagp, arg) \ - MarkGCThing(cx, thing, flagp, arg) -# define CALL_GC_THING_MARKER(marker, cx, thing, arg) \ - marker(cx, thing, arg) -#else -# define UNMARKED_GC_THING_FLAGS(thing, arg) \ - UnmarkedGCThingFlags(thing) -# define NEXT_UNMARKED_GC_THING(vp, end, thingp, flagpp, arg) \ - NextUnmarkedGCThing(vp, end, thingp, flagpp) -# define MARK_GC_THING(cx, thing, flagp, arg) \ - MarkGCThing(cx, thing, flagp) -# define CALL_GC_THING_MARKER(marker, cx, thing, arg) \ - marker(cx, thing, NULL) -#endif - -static uint8 * -UNMARKED_GC_THING_FLAGS(void *thing, void *arg) -{ - uint8 flags, *flagp; - - if (!thing) - return NULL; - - flagp = js_GetGCThingFlags(thing); - flags = *flagp; - JS_ASSERT(flags != GCF_FINAL); -#ifdef GC_MARK_DEBUG - if (js_LiveThingToFind == thing) - gc_dump_thing(thing, flags, arg, stderr); -#endif - - if (flags & GCF_MARK) - return NULL; - - return flagp; -} - -static jsval * -NEXT_UNMARKED_GC_THING(jsval *vp, jsval *end, void **thingp, uint8 **flagpp, - void *arg) -{ - jsval v; - void *thing; - uint8 *flagp; - - while (vp < end) { - v = *vp; - if (JSVAL_IS_GCTHING(v)) { - thing = JSVAL_TO_GCTHING(v); - flagp = UNMARKED_GC_THING_FLAGS(thing, arg); - if (flagp) { - *thingp = thing; - *flagpp = flagp; - return vp; - } - } - vp++; - } - return NULL; -} - -static void -DeutschSchorrWaite(JSContext *cx, void *thing, uint8 *flagp); - -static JSBool -MARK_GC_THING(JSContext *cx, void *thing, uint8 *flagp, void *arg) -{ - JSRuntime *rt; - JSObject *obj; - jsval v, *vp, *end; - JSString *str; - void *next_thing; - uint8 *next_flagp; -#ifdef JS_GCMETER - uint32 tailCallNesting; -#endif -#ifdef GC_MARK_DEBUG - JSScope *scope; - JSScopeProperty *sprop; - char name[32]; -#endif - int stackDummy; - - rt = cx->runtime; - METER(tailCallNesting = 0); - METER(if (++rt->gcStats.cdepth > rt->gcStats.maxcdepth) - rt->gcStats.maxcdepth = rt->gcStats.cdepth); - -#ifndef GC_MARK_DEBUG - start: -#endif - JS_ASSERT(flagp); - METER(if (++rt->gcStats.depth > rt->gcStats.maxdepth) - rt->gcStats.maxdepth = rt->gcStats.depth); - if (*flagp & GCF_MARK) { - /* - * This should happen only if recursive MARK_GC_THING marks flags - * already stored in the caller's *next_flagp. - */ - goto out; - } - - *flagp |= GCF_MARK; - -#ifdef GC_MARK_DEBUG - if (js_DumpGCHeap) - gc_dump_thing(thing, *flagp, arg, js_DumpGCHeap); -#endif - - switch (*flagp & GCF_TYPEMASK) { - case GCX_OBJECT: - /* If obj->slots is null, obj must be a newborn. */ - obj = (JSObject *) thing; - vp = obj->slots; - if (!vp) - goto out; - - /* Switch to Deutsch-Schorr-Waite if we exhaust our stack quota. */ - if (!JS_CHECK_STACK_SIZE(cx, stackDummy)) { - METER(rt->gcStats.dswmark++); - DeutschSchorrWaite(cx, thing, flagp); - goto out; - } - - /* Mark slots if they are small enough to be GC-allocated. */ - if ((vp[-1] + 1) * sizeof(jsval) <= GC_NBYTES_MAX) - GC_MARK(cx, vp - 1, "slots", arg); - - /* Set up local variables to loop over unmarked things. */ - end = vp + ((obj->map->ops->mark) - ? CALL_GC_THING_MARKER(obj->map->ops->mark, cx, obj, arg) - : JS_MIN(obj->map->freeslot, obj->map->nslots)); - - vp = NEXT_UNMARKED_GC_THING(vp, end, &thing, &flagp, arg); - if (!vp) - goto out; - v = *vp; - - /* - * Here, thing is the first value in obj->slots referring to an - * unmarked GC-thing. - */ -#ifdef GC_MARK_DEBUG - scope = OBJ_IS_NATIVE(obj) ? OBJ_SCOPE(obj) : NULL; -#endif - for (;;) { - /* Check loop invariants. */ - JS_ASSERT(v == *vp && JSVAL_IS_GCTHING(v)); - JS_ASSERT(thing == JSVAL_TO_GCTHING(v)); - JS_ASSERT(flagp == js_GetGCThingFlags(thing)); - -#ifdef GC_MARK_DEBUG - if (scope) { - uint32 slot; - jsval nval; - - slot = vp - obj->slots; - for (sprop = SCOPE_LAST_PROP(scope); ; sprop = sprop->parent) { - if (!sprop) { - switch (slot) { - case JSSLOT_PROTO: - strcpy(name, js_proto_str); - break; - case JSSLOT_PARENT: - strcpy(name, js_parent_str); - break; - default: - JS_snprintf(name, sizeof name, - "**UNKNOWN SLOT %ld**", - (long)slot); - break; - } - break; - } - if (sprop->slot == slot) { - nval = ID_TO_VALUE(sprop->id); - if (JSVAL_IS_INT(nval)) { - JS_snprintf(name, sizeof name, "%ld", - (long)JSVAL_TO_INT(nval)); - } else if (JSVAL_IS_STRING(nval)) { - JS_snprintf(name, sizeof name, "%s", - JS_GetStringBytes(JSVAL_TO_STRING(nval))); - } else { - strcpy(name, "**FINALIZED ATOM KEY**"); - } - break; - } - } - } else { - strcpy(name, "**UNKNOWN OBJECT MAP ENTRY**"); - } -#endif - - do { - vp = NEXT_UNMARKED_GC_THING(vp+1, end, &next_thing, &next_flagp, - arg); - if (!vp) { - /* - * Here thing came from the last unmarked GC-thing slot. - * We can eliminate tail recursion unless GC_MARK_DEBUG - * is defined. - */ -#ifdef GC_MARK_DEBUG - GC_MARK(cx, thing, name, arg); - goto out; -#else - METER(++tailCallNesting); - goto start; -#endif - } - } while (next_thing == thing); - v = *vp; - -#ifdef GC_MARK_DEBUG - GC_MARK(cx, thing, name, arg); -#else - MARK_GC_THING(cx, thing, flagp, arg); -#endif - thing = next_thing; - flagp = next_flagp; - } - break; - -#ifdef DEBUG - case GCX_STRING: - str = (JSString *)thing; - JS_ASSERT(!JSSTRING_IS_DEPENDENT(str)); - break; -#endif - - case GCX_MUTABLE_STRING: - str = (JSString *)thing; - if (JSSTRING_IS_DEPENDENT(str)) { - thing = JSSTRDEP_BASE(str); - flagp = UNMARKED_GC_THING_FLAGS(thing, arg); - if (flagp) { -#ifdef GC_MARK_DEBUG - GC_MARK(cx, thing, "base", arg); - goto out; -#else - METER(++tailCallNesting); - goto start; -#endif - } - } - break; - -#if JS_HAS_XML_SUPPORT - case GCX_NAMESPACE: - CALL_GC_THING_MARKER(js_MarkXMLNamespace, cx, (JSXMLNamespace *)thing, - arg); - break; - - case GCX_QNAME: - CALL_GC_THING_MARKER(js_MarkXMLQName, cx, (JSXMLQName *)thing, arg); - break; - - case GCX_XML: - CALL_GC_THING_MARKER(js_MarkXML, cx, (JSXML *)thing, arg); - break; -#endif - } - -out: - METER(rt->gcStats.depth -= 1 + tailCallNesting); - METER(rt->gcStats.cdepth--); - return JS_TRUE; -} - -/* - * An invalid object reference that's distinct from JSVAL_TRUE and JSVAL_FALSE - * when tagged as a boolean. Used to indicate empty DSW mark stack. - * - * Reversed pointers that link the DSW mark stack through obj->slots entries - * are also tagged as booleans so we can find each pointer and unreverse it. - * Because no object pointer is <= 16, these values can be distinguished from - * JSVAL_EMPTY, JSVAL_TRUE, and JSVAL_FALSE. - */ -#define JSVAL_EMPTY (2 << JSVAL_TAGBITS) - -/* - * To optimize native objects to avoid O(n^2) explosion in pathological cases, - * we use a dswIndex member of JSScope to tell where in obj->slots to find the - * reversed pointer. Scrounging space in JSScope by packing existing members - * tighter yielded 16 bits of index, which we use directly if obj->slots has - * 64K or fewer slots. Otherwise we make scope->dswIndex a fixed-point 16-bit - * fraction of the number of slots. - */ -static JS_INLINE uint16 -EncodeDSWIndex(jsval *vp, jsval *slots) -{ - uint32 nslots, limit, index; - jsdouble d; - - nslots = slots[-1]; - limit = JS_BIT(16); - index = PTRDIFF(vp, slots, jsval); - JS_ASSERT(index < nslots); - if (nslots > limit) { - d = ((jsdouble)index / nslots) * limit; - JS_ASSERT(0 <= d && d < limit); - return (uint16) d; - } - return (uint16) index; -} - -static JS_INLINE uint32 -DecodeDSWIndex(uint16 dswIndex, jsval *slots) -{ - uint32 nslots, limit; - jsdouble d; - - nslots = slots[-1]; - limit = JS_BIT(16); - JS_ASSERT(dswIndex < nslots); - if (nslots > limit) { - d = ((jsdouble)dswIndex * nslots) / limit; - JS_ASSERT(0 <= d && d < nslots); - return (uint32) d; - } - return dswIndex; -} - -static void -DeutschSchorrWaite(JSContext *cx, void *thing, uint8 *flagp) -{ - jsval top, parent, v, *vp, *end; - JSObject *obj; - JSScope *scope; -#ifdef JS_GCMETER - JSRuntime *rt = cx->runtime; -#endif - - top = JSVAL_EMPTY; - -down: - METER(if (++rt->gcStats.dswdepth > rt->gcStats.maxdswdepth) - rt->gcStats.maxdswdepth = rt->gcStats.dswdepth); - obj = (JSObject *) thing; - parent = OBJECT_TO_JSVAL(obj); - - /* Precompute for quick testing to set and get scope->dswIndex. */ - scope = (OBJ_IS_NATIVE(obj) && OBJ_SCOPE(obj)->object == obj) - ? OBJ_SCOPE(obj) - : NULL; - - /* Mark slots if they are small enough to be GC-allocated. */ - vp = obj->slots; - if ((vp[-1] + 1) * sizeof(jsval) <= GC_NBYTES_MAX) - GC_MARK(cx, vp - 1, "slots", NULL); - - end = vp + ((obj->map->ops->mark) - ? obj->map->ops->mark(cx, obj, NULL) - : JS_MIN(obj->map->freeslot, obj->map->nslots)); - - *flagp |= GCF_MARK; - - for (;;) { - while ((vp = NEXT_UNMARKED_GC_THING(vp, end, &thing, &flagp, NULL)) - != NULL) { - v = *vp; - JS_ASSERT(JSVAL_TO_GCTHING(v) == thing); - - if (JSVAL_IS_OBJECT(v)) { - *vp = JSVAL_SETTAG(top, JSVAL_BOOLEAN); - top = parent; - if (scope) - scope->dswIndex = EncodeDSWIndex(vp, obj->slots); - goto down; - } - - /* Handle string and double GC-things. */ - MARK_GC_THING(cx, thing, flagp, NULL); - } - - /* If we are back at the root (or we never left it), we're done. */ - METER(rt->gcStats.dswdepth--); - if (scope) - scope->dswIndex = 0; - if (top == JSVAL_EMPTY) - return; - - /* Time to go back up the spanning tree. */ - METER(rt->gcStats.dswup++); - obj = JSVAL_TO_OBJECT(top); - vp = obj->slots; - end = vp + vp[-1]; - - /* - * If obj is native and owns its own scope, we can minimize the cost - * of searching for the reversed pointer. - */ - scope = (OBJ_IS_NATIVE(obj) && OBJ_SCOPE(obj)->object == obj) - ? OBJ_SCOPE(obj) - : NULL; - if (scope) - vp += DecodeDSWIndex(scope->dswIndex, vp); - - /* - * Alas, we must search for the reversed pointer. If we used the - * scope->dswIndex hint, we'll step over a few slots for objects with - * a few times 64K slots, etc. For more typical (that is, far fewer - * than 64K slots) native objects that own their own scopes, this loop - * won't iterate at all. The order of complexity for host objects and - * unmutated native objects is O(n^2), but n (4 or 5 in most cases) is - * low enough that we don't care. - * - * We cannot use a reversed pointer into obj->slots, because there - * is no way to find an object from an address within its slots. - */ - v = *vp; - while (v <= JSVAL_TRUE || !JSVAL_IS_BOOLEAN(v)) { - METER(rt->gcStats.dswupstep++); - JS_ASSERT(vp + 1 < end); - v = *++vp; - } - - *vp++ = parent; - parent = top; - top = JSVAL_CLRTAG(v); - } -} - -void -js_MarkGCThing(JSContext *cx, void *thing, void *arg) -{ - uint8 *flagp; - - flagp = UNMARKED_GC_THING_FLAGS(thing, arg); - if (!flagp) - return; - MARK_GC_THING(cx, thing, flagp, arg); -} - -JS_STATIC_DLL_CALLBACK(JSDHashOperator) -gc_root_marker(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 num, void *arg) -{ - JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr; - jsval *rp = (jsval *)rhe->root; - jsval v = *rp; - - /* Ignore null object and scalar values. */ - if (!JSVAL_IS_NULL(v) && JSVAL_IS_GCTHING(v)) { - JSContext *cx = (JSContext *)arg; -#ifdef DEBUG - uintN i; - JSArena *a; - jsuword firstpage; - JSBool root_points_to_gcArenaPool = JS_FALSE; - void *thing = JSVAL_TO_GCTHING(v); - - for (i = 0; i < GC_NUM_FREELISTS; i++) { - for (a = cx->runtime->gcArenaPool[i].first.next; a; a = a->next) { - firstpage = FIRST_THING_PAGE(a); - if (JS_UPTRDIFF(thing, firstpage) < a->avail - firstpage) { - root_points_to_gcArenaPool = JS_TRUE; - break; - } - } - } - if (!root_points_to_gcArenaPool && rhe->name) { - fprintf(stderr, -"JS API usage error: the address passed to JS_AddNamedRoot currently holds an\n" -"invalid jsval. This is usually caused by a missing call to JS_RemoveRoot.\n" -"The root's name is \"%s\".\n", - rhe->name); - } - JS_ASSERT(root_points_to_gcArenaPool); -#endif - - GC_MARK(cx, JSVAL_TO_GCTHING(v), rhe->name ? rhe->name : "root", NULL); - } - return JS_DHASH_NEXT; -} - -JS_STATIC_DLL_CALLBACK(JSDHashOperator) -gc_lock_marker(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 num, void *arg) -{ - JSGCLockHashEntry *lhe = (JSGCLockHashEntry *)hdr; - void *thing = (void *)lhe->thing; - JSContext *cx = (JSContext *)arg; - - GC_MARK(cx, thing, "locked object", NULL); - return JS_DHASH_NEXT; -} - -void -js_ForceGC(JSContext *cx, uintN gcflags) -{ - uintN i; - - for (i = 0; i < GCX_NTYPES; i++) - cx->newborn[i] = NULL; - cx->lastAtom = NULL; - cx->runtime->gcPoke = JS_TRUE; - js_GC(cx, gcflags); - JS_ArenaFinish(); -} - -#define GC_MARK_JSVALS(cx, len, vec, name) \ - JS_BEGIN_MACRO \ - jsval _v, *_vp, *_end; \ - \ - for (_vp = vec, _end = _vp + len; _vp < _end; _vp++) { \ - _v = *_vp; \ - if (JSVAL_IS_GCTHING(_v)) \ - GC_MARK(cx, JSVAL_TO_GCTHING(_v), name, NULL); \ - } \ - JS_END_MACRO - -void -js_GC(JSContext *cx, uintN gcflags) -{ - JSRuntime *rt; - JSContext *iter, *acx; - JSStackFrame *fp, *chain; - uintN i, depth, nslots, type; - JSStackHeader *sh; - JSTempValueRooter *tvr; - size_t nbytes, nflags; - JSArena *a, **ap; - uint8 flags, *flagp, *split; - JSGCThing *thing, *limit, **flp, **oflp; - GCFinalizeOp finalizer; - uint32 *bytesptr; - JSBool all_clear; -#ifdef JS_THREADSAFE - jsword currentThread; - uint32 requestDebit; -#endif - - rt = cx->runtime; -#ifdef JS_THREADSAFE - /* Avoid deadlock. */ - JS_ASSERT(!JS_IS_RUNTIME_LOCKED(rt)); -#endif - - /* - * Don't collect garbage if the runtime isn't up, and cx is not the last - * context in the runtime. The last context must force a GC, and nothing - * should suppress that final collection or there may be shutdown leaks, - * or runtime bloat until the next context is created. - */ - if (rt->state != JSRTS_UP && !(gcflags & GC_LAST_CONTEXT)) - return; - - /* - * Let the API user decide to defer a GC if it wants to (unless this - * is the last context). Invoke the callback regardless. - */ - if (rt->gcCallback) { - if (!rt->gcCallback(cx, JSGC_BEGIN) && !(gcflags & GC_LAST_CONTEXT)) - return; - } - - /* Lock out other GC allocator and collector invocations. */ - if (!(gcflags & GC_ALREADY_LOCKED)) - JS_LOCK_GC(rt); - - /* Do nothing if no mutator has executed since the last GC. */ - if (!rt->gcPoke) { - METER(rt->gcStats.nopoke++); - if (!(gcflags & GC_ALREADY_LOCKED)) - JS_UNLOCK_GC(rt); - return; - } - METER(rt->gcStats.poke++); - rt->gcPoke = JS_FALSE; - -#ifdef JS_THREADSAFE - /* Bump gcLevel and return rather than nest on this thread. */ - currentThread = js_CurrentThreadId(); - if (rt->gcThread == currentThread) { - JS_ASSERT(rt->gcLevel > 0); - rt->gcLevel++; - METER(if (rt->gcLevel > rt->gcStats.maxlevel) - rt->gcStats.maxlevel = rt->gcLevel); - if (!(gcflags & GC_ALREADY_LOCKED)) - JS_UNLOCK_GC(rt); - return; - } - - /* - * If we're in one or more requests (possibly on more than one context) - * running on the current thread, indicate, temporarily, that all these - * requests are inactive. NB: if cx->thread is 0, then cx is not using - * the request model, and does not contribute to rt->requestCount. - */ - requestDebit = 0; - if (cx->thread) { - /* - * Check all contexts for any with the same thread-id. XXX should we - * keep a sub-list of contexts having the same id? - */ - iter = NULL; - while ((acx = js_ContextIterator(rt, JS_FALSE, &iter)) != NULL) { - if (acx->thread == cx->thread && acx->requestDepth) - requestDebit++; - } - } else { - /* - * We assert, but check anyway, in case someone is misusing the API. - * Avoiding the loop over all of rt's contexts is a win in the event - * that the GC runs only on request-less contexts with 0 thread-ids, - * in a special thread such as might be used by the UI/DOM/Layout - * "mozilla" or "main" thread in Mozilla-the-browser. - */ - JS_ASSERT(cx->requestDepth == 0); - if (cx->requestDepth) - requestDebit = 1; - } - if (requestDebit) { - JS_ASSERT(requestDebit <= rt->requestCount); - rt->requestCount -= requestDebit; - if (rt->requestCount == 0) - JS_NOTIFY_REQUEST_DONE(rt); - } - - /* If another thread is already in GC, don't attempt GC; wait instead. */ - if (rt->gcLevel > 0) { - /* Bump gcLevel to restart the current GC, so it finds new garbage. */ - rt->gcLevel++; - METER(if (rt->gcLevel > rt->gcStats.maxlevel) - rt->gcStats.maxlevel = rt->gcLevel); - - /* Wait for the other thread to finish, then resume our request. */ - while (rt->gcLevel > 0) - JS_AWAIT_GC_DONE(rt); - if (requestDebit) - rt->requestCount += requestDebit; - if (!(gcflags & GC_ALREADY_LOCKED)) - JS_UNLOCK_GC(rt); - return; - } - - /* No other thread is in GC, so indicate that we're now in GC. */ - rt->gcLevel = 1; - rt->gcThread = currentThread; - - /* Wait for all other requests to finish. */ - while (rt->requestCount > 0) - JS_AWAIT_REQUEST_DONE(rt); - -#else /* !JS_THREADSAFE */ - - /* Bump gcLevel and return rather than nest; the outer gc will restart. */ - rt->gcLevel++; - METER(if (rt->gcLevel > rt->gcStats.maxlevel) - rt->gcStats.maxlevel = rt->gcLevel); - if (rt->gcLevel > 1) - return; - -#endif /* !JS_THREADSAFE */ - - /* - * Set rt->gcRunning here within the GC lock, and after waiting for any - * active requests to end, so that new requests that try to JS_AddRoot, - * JS_RemoveRoot, or JS_RemoveRootRT block in JS_BeginRequest waiting for - * rt->gcLevel to drop to zero, while request-less calls to the *Root* - * APIs block in js_AddRoot or js_RemoveRoot (see above in this file), - * waiting for GC to finish. - */ - rt->gcRunning = JS_TRUE; - JS_UNLOCK_GC(rt); - - /* If a suspended compile is running on another context, keep atoms. */ - if (rt->gcKeepAtoms) - gcflags |= GC_KEEP_ATOMS; - - /* Reset malloc counter. */ - rt->gcMallocBytes = 0; - - /* Drop atoms held by the property cache, and clear property weak links. */ - js_DisablePropertyCache(cx); - js_FlushPropertyCache(cx); -#ifdef DEBUG_notme - { extern void js_DumpScopeMeters(JSRuntime *rt); - js_DumpScopeMeters(rt); - } -#endif - -restart: - rt->gcNumber++; - - /* - * Mark phase. - */ - JS_DHashTableEnumerate(&rt->gcRootsHash, gc_root_marker, cx); - if (rt->gcLocksHash) - JS_DHashTableEnumerate(rt->gcLocksHash, gc_lock_marker, cx); - js_MarkAtomState(&rt->atomState, gcflags, gc_mark_atom_key_thing, cx); - js_MarkWatchPoints(cx); - js_MarkScriptFilenames(rt, gcflags); - js_MarkNativeIteratorStates(cx); - - iter = NULL; - while ((acx = js_ContextIterator(rt, JS_TRUE, &iter)) != NULL) { - /* - * Iterate frame chain and dormant chains. Temporarily tack current - * frame onto the head of the dormant list to ease iteration. - * - * (NB: see comment on this whole "dormant" thing in js_Execute.) - */ - chain = acx->fp; - if (chain) { - JS_ASSERT(!chain->dormantNext); - chain->dormantNext = acx->dormantFrameChain; - } else { - chain = acx->dormantFrameChain; - } - - for (fp = chain; fp; fp = chain = chain->dormantNext) { - do { - if (fp->callobj) - GC_MARK(cx, fp->callobj, "call object", NULL); - if (fp->argsobj) - GC_MARK(cx, fp->argsobj, "arguments object", NULL); - if (fp->varobj) - GC_MARK(cx, fp->varobj, "variables object", NULL); - if (fp->script) { - js_MarkScript(cx, fp->script, NULL); - if (fp->spbase) { - /* - * Don't mark what has not been pushed yet, or what - * has been popped already. - */ - depth = fp->script->depth; - nslots = (JS_UPTRDIFF(fp->sp, fp->spbase) - < depth * sizeof(jsval)) - ? (uintN)(fp->sp - fp->spbase) - : depth; - GC_MARK_JSVALS(cx, nslots, fp->spbase, "operand"); - } - } - GC_MARK(cx, fp->thisp, "this", NULL); - if (fp->argv) { - nslots = fp->argc; - if (fp->fun) { - if (fp->fun->nargs > nslots) - nslots = fp->fun->nargs; - nslots += fp->fun->extra; - } - GC_MARK_JSVALS(cx, nslots, fp->argv, "arg"); - } - if (JSVAL_IS_GCTHING(fp->rval)) - GC_MARK(cx, JSVAL_TO_GCTHING(fp->rval), "rval", NULL); - if (fp->vars) - GC_MARK_JSVALS(cx, fp->nvars, fp->vars, "var"); - GC_MARK(cx, fp->scopeChain, "scope chain", NULL); - if (fp->sharpArray) - GC_MARK(cx, fp->sharpArray, "sharp array", NULL); - - if (fp->xmlNamespace) - GC_MARK(cx, fp->xmlNamespace, "xmlNamespace", NULL); - } while ((fp = fp->down) != NULL); - } - - /* Cleanup temporary "dormant" linkage. */ - if (acx->fp) - acx->fp->dormantNext = NULL; - - /* Mark other roots-by-definition in acx. */ - GC_MARK(cx, acx->globalObject, "global object", NULL); - for (i = 0; i < GCX_NTYPES; i++) - GC_MARK(cx, acx->newborn[i], gc_typenames[i], NULL); - if (acx->lastAtom) - GC_MARK_ATOM(cx, acx->lastAtom, NULL); - if (JSVAL_IS_GCTHING(acx->lastInternalResult)) { - thing = JSVAL_TO_GCTHING(acx->lastInternalResult); - if (thing) - GC_MARK(cx, thing, "lastInternalResult", NULL); - } -#if JS_HAS_EXCEPTIONS - if (acx->throwing && JSVAL_IS_GCTHING(acx->exception)) - GC_MARK(cx, JSVAL_TO_GCTHING(acx->exception), "exception", NULL); -#endif -#if JS_HAS_LVALUE_RETURN - if (acx->rval2set && JSVAL_IS_GCTHING(acx->rval2)) - GC_MARK(cx, JSVAL_TO_GCTHING(acx->rval2), "rval2", NULL); -#endif - - for (sh = acx->stackHeaders; sh; sh = sh->down) { - METER(rt->gcStats.stackseg++); - METER(rt->gcStats.segslots += sh->nslots); - GC_MARK_JSVALS(cx, sh->nslots, JS_STACK_SEGMENT(sh), "stack"); - } - - if (acx->localRootStack) - js_MarkLocalRoots(cx, acx->localRootStack); - for (tvr = acx->tempValueRooters; tvr; tvr = tvr->down) { - if (tvr->count == -1) { - if (JSVAL_IS_GCTHING(tvr->u.value)) { - GC_MARK(cx, JSVAL_TO_GCTHING(tvr->u.value), - "tvr->u.value", NULL); - } - } else if (tvr->count == -2) { - tvr->u.marker(cx, tvr); - } else { - JS_ASSERT(tvr->count >= 0); - GC_MARK_JSVALS(cx, tvr->count, tvr->u.array, "tvr->u.array"); - } - } - - if (acx->sharpObjectMap.depth > 0) - js_GCMarkSharpMap(cx, &acx->sharpObjectMap); - } -#ifdef DUMP_CALL_TABLE - js_DumpCallTable(cx); -#endif - - if (rt->gcCallback) - (void) rt->gcCallback(cx, JSGC_MARK_END); - - /* - * Sweep phase. - * - * Finalize as we sweep, outside of rt->gcLock, but with rt->gcRunning set - * so that any attempt to allocate a GC-thing from a finalizer will fail, - * rather than nest badly and leave the unmarked newborn to be swept. - * - * Finalize smaller objects before larger, to guarantee finalization of - * GC-allocated obj->slots after obj. See FreeSlots in jsobj.c. - */ - js_SweepAtomState(&rt->atomState); - js_SweepScopeProperties(rt); - for (i = 0; i < GC_NUM_FREELISTS; i++) { - nbytes = GC_FREELIST_NBYTES(i); - nflags = nbytes / sizeof(JSGCThing); - - for (a = rt->gcArenaPool[i].first.next; a; a = a->next) { - flagp = (uint8 *) a->base; - split = (uint8 *) FIRST_THING_PAGE(a); - limit = (JSGCThing *) a->avail; - for (thing = (JSGCThing *) split; thing < limit; thing += nflags) { - if (((jsuword)thing & GC_PAGE_MASK) == 0) { - thing = (JSGCThing *) FIRST_THING((jsuword)thing, nbytes); - flagp = js_GetGCThingFlags(thing); - } - flags = *flagp; - if (flags & GCF_MARK) { - *flagp &= ~GCF_MARK; - } else if (!(flags & (GCF_LOCK | GCF_FINAL))) { - /* Call the finalizer with GCF_FINAL ORed into flags. */ - type = flags & GCF_TYPEMASK; - finalizer = gc_finalizers[type]; - if (finalizer) { - *flagp = (uint8)(flags | GCF_FINAL); - if (type >= GCX_EXTERNAL_STRING) - js_PurgeDeflatedStringCache((JSString *)thing); - finalizer(cx, thing); - } - - /* Set flags to GCF_FINAL, signifying that thing is free. */ - *flagp = GCF_FINAL; - - bytesptr = (type == GCX_PRIVATE) - ? &rt->gcPrivateBytes - : &rt->gcBytes; - JS_ASSERT(*bytesptr >= nbytes + nflags); - *bytesptr -= nbytes + nflags; - } - flagp += nflags; - if (JS_UPTRDIFF(flagp, split) < nflags) - flagp += GC_THINGS_SIZE; - } - } - } - - /* - * Sweep script filenames after sweeping functions in the generic loop - * above. In this way when scripted function's finalizer destroys script - * triggering a call to rt->destroyScriptHook, the hook can still access - * script's filename. See bug 323267. - */ - js_SweepScriptFilenames(rt); - - /* - * Free phase. - * Free any unused arenas and rebuild the JSGCThing freelist. - */ - for (i = 0; i < GC_NUM_FREELISTS; i++) { - ap = &rt->gcArenaPool[i].first.next; - a = *ap; - if (!a) - continue; - - all_clear = JS_TRUE; - flp = oflp = &rt->gcFreeList[i]; - *flp = NULL; - METER(rt->gcStats.freelen[i] = 0); - - nbytes = GC_FREELIST_NBYTES(i); - nflags = nbytes / sizeof(JSGCThing); - do { - flagp = (uint8 *) a->base; - split = (uint8 *) FIRST_THING_PAGE(a); - limit = (JSGCThing *) a->avail; - for (thing = (JSGCThing *) split; thing < limit; thing += nflags) { - if (((jsuword)thing & GC_PAGE_MASK) == 0) { - thing = (JSGCThing *) FIRST_THING((jsuword)thing, nbytes); - flagp = js_GetGCThingFlags(thing); - } - if (*flagp != GCF_FINAL) { - all_clear = JS_FALSE; - } else { - thing->flagp = flagp; - *flp = thing; - flp = &thing->next; - METER(rt->gcStats.freelen[i]++); - } - flagp += nflags; - if (JS_UPTRDIFF(flagp, split) < nflags) - flagp += GC_THINGS_SIZE; - } - - if (all_clear) { - JS_ARENA_DESTROY(&rt->gcArenaPool[i], a, ap); - flp = oflp; - METER(rt->gcStats.afree++); - } else { - ap = &a->next; - all_clear = JS_TRUE; - oflp = flp; - } - } while ((a = *ap) != NULL); - - /* Terminate the new freelist. */ - *flp = NULL; - } - - if (rt->gcCallback) - (void) rt->gcCallback(cx, JSGC_FINALIZE_END); -#ifdef DEBUG_notme - { extern void DumpSrcNoteSizeHist(); - DumpSrcNoteSizeHist(); - printf("GC HEAP SIZE %lu (%lu)\n", - (unsigned long)rt->gcBytes, (unsigned long)rt->gcPrivateBytes); - } -#endif - - JS_LOCK_GC(rt); - if (rt->gcLevel > 1 || rt->gcPoke) { - rt->gcLevel = 1; - rt->gcPoke = JS_FALSE; - JS_UNLOCK_GC(rt); - goto restart; - } - js_EnablePropertyCache(cx); - rt->gcLevel = 0; - rt->gcLastBytes = rt->gcBytes; - rt->gcRunning = JS_FALSE; - -#ifdef JS_THREADSAFE - /* If we were invoked during a request, pay back the temporary debit. */ - if (requestDebit) - rt->requestCount += requestDebit; - rt->gcThread = 0; - JS_NOTIFY_GC_DONE(rt); - if (!(gcflags & GC_ALREADY_LOCKED)) - JS_UNLOCK_GC(rt); -#endif - - if (rt->gcCallback) { - if (gcflags & GC_ALREADY_LOCKED) - JS_UNLOCK_GC(rt); - (void) rt->gcCallback(cx, JSGC_END); - if (gcflags & GC_ALREADY_LOCKED) - JS_LOCK_GC(rt); - } -} diff --git a/lib/javascript/jsgc.h b/lib/javascript/jsgc.h deleted file mode 100644 index efc13194..00000000 --- a/lib/javascript/jsgc.h +++ /dev/null @@ -1,272 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jsgc_h___ -#define jsgc_h___ -/* - * JS Garbage Collector. - */ -#include "jsprvtd.h" -#include "jspubtd.h" -#include "jsdhash.h" - -JS_BEGIN_EXTERN_C - -/* GC thing type indexes. */ -#define GCX_OBJECT 0 /* JSObject */ -#define GCX_STRING 1 /* JSString */ -#define GCX_DOUBLE 2 /* jsdouble */ -#define GCX_MUTABLE_STRING 3 /* JSString that's mutable -- - single-threaded only! */ -#define GCX_PRIVATE 4 /* private (unscanned) data */ -#define GCX_NAMESPACE 5 /* JSXMLNamespace */ -#define GCX_QNAME 6 /* JSXMLQName */ -#define GCX_XML 7 /* JSXML */ -#define GCX_EXTERNAL_STRING 8 /* JSString w/ external chars */ - -#define GCX_NTYPES_LOG2 4 /* type index bits */ -#define GCX_NTYPES JS_BIT(GCX_NTYPES_LOG2) - -/* GC flag definitions, must fit in 8 bits (type index goes in the low bits). */ -#define GCF_TYPEMASK JS_BITMASK(GCX_NTYPES_LOG2) -#define GCF_MARK JS_BIT(GCX_NTYPES_LOG2) -#define GCF_FINAL JS_BIT(GCX_NTYPES_LOG2 + 1) -#define GCF_SYSTEM JS_BIT(GCX_NTYPES_LOG2 + 2) -#define GCF_LOCKSHIFT (GCX_NTYPES_LOG2 + 3) /* lock bit shift */ -#define GCF_LOCK JS_BIT(GCF_LOCKSHIFT) /* lock request bit in API */ - -/* Pseudo-flag that modifies GCX_STRING to make GCX_MUTABLE_STRING. */ -#define GCF_MUTABLE 2 - -#if (GCX_STRING | GCF_MUTABLE) != GCX_MUTABLE_STRING -# error "mutable string type index botch!" -#endif - -extern uint8 * -js_GetGCThingFlags(void *thing); - -/* These are compatible with JSDHashEntryStub. */ -struct JSGCRootHashEntry { - JSDHashEntryHdr hdr; - void *root; - const char *name; -}; - -struct JSGCLockHashEntry { - JSDHashEntryHdr hdr; - const JSGCThing *thing; - uint32 count; -}; - -#if 1 -/* - * Since we're forcing a GC from JS_GC anyway, don't bother wasting cycles - * loading oldval. XXX remove implied force, fix jsinterp.c's "second arg - * ignored", etc. - */ -#define GC_POKE(cx, oldval) ((cx)->runtime->gcPoke = JS_TRUE) -#else -#define GC_POKE(cx, oldval) ((cx)->runtime->gcPoke = JSVAL_IS_GCTHING(oldval)) -#endif - -extern intN -js_ChangeExternalStringFinalizer(JSStringFinalizeOp oldop, - JSStringFinalizeOp newop); - -extern JSBool -js_InitGC(JSRuntime *rt, uint32 maxbytes); - -extern void -js_FinishGC(JSRuntime *rt); - -extern JSBool -js_AddRoot(JSContext *cx, void *rp, const char *name); - -extern JSBool -js_AddRootRT(JSRuntime *rt, void *rp, const char *name); - -extern JSBool -js_RemoveRoot(JSRuntime *rt, void *rp); - -/* - * The private JSGCThing struct, which describes a gcFreeList element. - */ -struct JSGCThing { - JSGCThing *next; - uint8 *flagp; -}; - -#define GC_NBYTES_MAX (10 * sizeof(JSGCThing)) -#define GC_NUM_FREELISTS (GC_NBYTES_MAX / sizeof(JSGCThing)) -#define GC_FREELIST_NBYTES(i) (((i) + 1) * sizeof(JSGCThing)) -#define GC_FREELIST_INDEX(n) (((n) / sizeof(JSGCThing)) - 1) - -extern void * -js_NewGCThing(JSContext *cx, uintN flags, size_t nbytes); - -extern JSBool -js_LockGCThing(JSContext *cx, void *thing); - -extern JSBool -js_LockGCThingRT(JSRuntime *rt, void *thing); - -extern JSBool -js_UnlockGCThingRT(JSRuntime *rt, void *thing); - -extern JSBool -js_IsAboutToBeFinalized(JSContext *cx, void *thing); - -extern void -js_MarkAtom(JSContext *cx, JSAtom *atom, void *arg); - -/* We avoid a large number of unnecessary calls by doing the flag check first */ -#define GC_MARK_ATOM(cx, atom, arg) \ - JS_BEGIN_MACRO \ - if (!((atom)->flags & ATOM_MARK)) \ - js_MarkAtom(cx, atom, arg); \ - JS_END_MACRO - -extern void -js_MarkGCThing(JSContext *cx, void *thing, void *arg); - -#ifdef GC_MARK_DEBUG - -typedef struct GCMarkNode GCMarkNode; - -struct GCMarkNode { - void *thing; - const char *name; - GCMarkNode *next; - GCMarkNode *prev; -}; - -#define GC_MARK(cx_, thing_, name_, prev_) \ - JS_BEGIN_MACRO \ - GCMarkNode node_; \ - node_.thing = thing_; \ - node_.name = name_; \ - node_.next = NULL; \ - node_.prev = prev_; \ - if (prev_) ((GCMarkNode *)(prev_))->next = &node_; \ - js_MarkGCThing(cx_, thing_, &node_); \ - JS_END_MACRO - -extern JS_FRIEND_DATA(FILE *) js_DumpGCHeap; -JS_EXTERN_DATA(void *) js_LiveThingToFind; - -#else /* !GC_MARK_DEBUG */ - -#define GC_MARK(cx, thing, name, prev) js_MarkGCThing(cx, thing, NULL) - -#endif /* !GC_MARK_DEBUG */ - -/* - * Flags to modify how a GC marks and sweeps: - * GC_KEEP_ATOMS Don't sweep unmarked atoms, they may be in use by the - * compiler, or by an API function that calls js_Atomize, - * when the GC is called from js_NewGCThing, due to a - * malloc failure or the runtime GC-thing limit. - * GC_LAST_CONTEXT Called from js_DestroyContext for last JSContext in a - * JSRuntime, when it is imperative that rt->gcPoke gets - * cleared early in js_GC, if it is set. - * GC_ALREADY_LOCKED rt->gcLock is already held on entry to js_GC, and kept - * on return to its caller. - */ -#define GC_KEEP_ATOMS 0x1 -#define GC_LAST_CONTEXT 0x2 -#define GC_ALREADY_LOCKED 0x4 - -extern void -js_ForceGC(JSContext *cx, uintN gcflags); - -extern void -js_GC(JSContext *cx, uintN gcflags); - -#ifdef DEBUG_notme -#define JS_GCMETER 1 -#endif - -#ifdef JS_GCMETER - -typedef struct JSGCStats { - uint32 alloc; /* number of allocation attempts */ - uint32 freelen[GC_NUM_FREELISTS]; - /* gcFreeList lengths */ - uint32 recycle[GC_NUM_FREELISTS]; - /* number of things recycled through gcFreeList */ - uint32 retry; /* allocation attempt retries after running the GC */ - uint32 retryhalt; /* allocation retries halted by the branch callback */ - uint32 fail; /* allocation failures */ - uint32 finalfail; /* finalizer calls allocator failures */ - uint32 lockborn; /* things born locked */ - uint32 lock; /* valid lock calls */ - uint32 unlock; /* valid unlock calls */ - uint32 depth; /* mark tail recursion depth */ - uint32 maxdepth; /* maximum mark tail recursion depth */ - uint32 cdepth; /* mark recursion depth of C functions */ - uint32 maxcdepth; /* maximum mark recursion depth of C functions */ - uint32 dswmark; /* mark C stack overflows => Deutsch-Schorr-Waite */ - uint32 dswdepth; /* DSW mark depth */ - uint32 maxdswdepth;/* maximum DSW mark depth */ - uint32 dswup; /* DSW moves up the mark spanning tree */ - uint32 dswupstep; /* steps in obj->slots to find DSW-reversed pointer */ - uint32 maxlevel; /* maximum GC nesting (indirect recursion) level */ - uint32 poke; /* number of potentially useful GC calls */ - uint32 nopoke; /* useless GC calls where js_PokeGC was not set */ - uint32 afree; /* thing arenas freed so far */ - uint32 stackseg; /* total extraordinary stack segments scanned */ - uint32 segslots; /* total stack segment jsval slots scanned */ -} JSGCStats; - -extern JS_FRIEND_API(void) -js_DumpGCStats(JSRuntime *rt, FILE *fp); - -#endif /* JS_GCMETER */ - -#ifdef DEBUG_notme -#define TOO_MUCH_GC 1 -#endif - -#ifdef WAY_TOO_MUCH_GC -#define TOO_MUCH_GC 1 -#endif - -JS_END_EXTERN_C - -#endif /* jsgc_h___ */ diff --git a/lib/javascript/jshash.c b/lib/javascript/jshash.c deleted file mode 100644 index 0f22b5e3..00000000 --- a/lib/javascript/jshash.c +++ /dev/null @@ -1,471 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * PR hash table package. - */ -#include "jsstddef.h" -#include -#include -#include "jstypes.h" -#include "jsbit.h" -#include "jsutil.h" /* Added by JSIFY */ -#include "jshash.h" /* Added by JSIFY */ - -/* Compute the number of buckets in ht */ -#define NBUCKETS(ht) JS_BIT(JS_HASH_BITS - (ht)->shift) - -/* The smallest table has 16 buckets */ -#define MINBUCKETSLOG2 4 -#define MINBUCKETS JS_BIT(MINBUCKETSLOG2) - -/* Compute the maximum entries given n buckets that we will tolerate, ~90% */ -#define OVERLOADED(n) ((n) - ((n) >> 3)) - -/* Compute the number of entries below which we shrink the table by half */ -#define UNDERLOADED(n) (((n) > MINBUCKETS) ? ((n) >> 2) : 0) - -/* -** Stubs for default hash allocator ops. -*/ -static void * -DefaultAllocTable(void *pool, size_t size) -{ - return malloc(size); -} - -static void -DefaultFreeTable(void *pool, void *item) -{ - free(item); -} - -static JSHashEntry * -DefaultAllocEntry(void *pool, const void *key) -{ - return (JSHashEntry*) malloc(sizeof(JSHashEntry)); -} - -static void -DefaultFreeEntry(void *pool, JSHashEntry *he, uintN flag) -{ - if (flag == HT_FREE_ENTRY) - free(he); -} - -static JSHashAllocOps defaultHashAllocOps = { - DefaultAllocTable, DefaultFreeTable, - DefaultAllocEntry, DefaultFreeEntry -}; - -JS_PUBLIC_API(JSHashTable *) -JS_NewHashTable(uint32 n, JSHashFunction keyHash, - JSHashComparator keyCompare, JSHashComparator valueCompare, - JSHashAllocOps *allocOps, void *allocPriv) -{ - JSHashTable *ht; - size_t nb; - - if (n <= MINBUCKETS) { - n = MINBUCKETSLOG2; - } else { - n = JS_CeilingLog2(n); - if ((int32)n < 0) - return NULL; - } - - if (!allocOps) allocOps = &defaultHashAllocOps; - - ht = (JSHashTable*) allocOps->allocTable(allocPriv, sizeof *ht); - if (!ht) - return NULL; - memset(ht, 0, sizeof *ht); - ht->shift = JS_HASH_BITS - n; - n = JS_BIT(n); - nb = n * sizeof(JSHashEntry *); - ht->buckets = (JSHashEntry**) allocOps->allocTable(allocPriv, nb); - if (!ht->buckets) { - allocOps->freeTable(allocPriv, ht); - return NULL; - } - memset(ht->buckets, 0, nb); - - ht->keyHash = keyHash; - ht->keyCompare = keyCompare; - ht->valueCompare = valueCompare; - ht->allocOps = allocOps; - ht->allocPriv = allocPriv; - return ht; -} - -JS_PUBLIC_API(void) -JS_HashTableDestroy(JSHashTable *ht) -{ - uint32 i, n; - JSHashEntry *he, **hep; - JSHashAllocOps *allocOps = ht->allocOps; - void *allocPriv = ht->allocPriv; - - n = NBUCKETS(ht); - for (i = 0; i < n; i++) { - hep = &ht->buckets[i]; - while ((he = *hep) != NULL) { - *hep = he->next; - allocOps->freeEntry(allocPriv, he, HT_FREE_ENTRY); - } - } -#ifdef DEBUG - memset(ht->buckets, 0xDB, n * sizeof ht->buckets[0]); -#endif - allocOps->freeTable(allocPriv, ht->buckets); -#ifdef DEBUG - memset(ht, 0xDB, sizeof *ht); -#endif - allocOps->freeTable(allocPriv, ht); -} - -/* -** Multiplicative hash, from Knuth 6.4. -*/ -JS_PUBLIC_API(JSHashEntry **) -JS_HashTableRawLookup(JSHashTable *ht, JSHashNumber keyHash, const void *key) -{ - JSHashEntry *he, **hep, **hep0; - JSHashNumber h; - -#ifdef HASHMETER - ht->nlookups++; -#endif - h = keyHash * JS_GOLDEN_RATIO; - h >>= ht->shift; - hep = hep0 = &ht->buckets[h]; - while ((he = *hep) != NULL) { - if (he->keyHash == keyHash && ht->keyCompare(key, he->key)) { - /* Move to front of chain if not already there */ - if (hep != hep0) { - *hep = he->next; - he->next = *hep0; - *hep0 = he; - } - return hep0; - } - hep = &he->next; -#ifdef HASHMETER - ht->nsteps++; -#endif - } - return hep; -} - -JS_PUBLIC_API(JSHashEntry *) -JS_HashTableRawAdd(JSHashTable *ht, JSHashEntry **hep, - JSHashNumber keyHash, const void *key, void *value) -{ - uint32 i, n; - JSHashEntry *he, *next, **oldbuckets; - size_t nb; - - /* Grow the table if it is overloaded */ - n = NBUCKETS(ht); - if (ht->nentries >= OVERLOADED(n)) { - oldbuckets = ht->buckets; - nb = 2 * n * sizeof(JSHashEntry *); - ht->buckets = (JSHashEntry**) - ht->allocOps->allocTable(ht->allocPriv, nb); - if (!ht->buckets) { - ht->buckets = oldbuckets; - return NULL; - } - memset(ht->buckets, 0, nb); -#ifdef HASHMETER - ht->ngrows++; -#endif - ht->shift--; - - for (i = 0; i < n; i++) { - for (he = oldbuckets[i]; he; he = next) { - next = he->next; - hep = JS_HashTableRawLookup(ht, he->keyHash, he->key); - JS_ASSERT(*hep == NULL); - he->next = NULL; - *hep = he; - } - } -#ifdef DEBUG - memset(oldbuckets, 0xDB, n * sizeof oldbuckets[0]); -#endif - ht->allocOps->freeTable(ht->allocPriv, oldbuckets); - hep = JS_HashTableRawLookup(ht, keyHash, key); - } - - /* Make a new key value entry */ - he = ht->allocOps->allocEntry(ht->allocPriv, key); - if (!he) - return NULL; - he->keyHash = keyHash; - he->key = key; - he->value = value; - he->next = *hep; - *hep = he; - ht->nentries++; - return he; -} - -JS_PUBLIC_API(JSHashEntry *) -JS_HashTableAdd(JSHashTable *ht, const void *key, void *value) -{ - JSHashNumber keyHash; - JSHashEntry *he, **hep; - - keyHash = ht->keyHash(key); - hep = JS_HashTableRawLookup(ht, keyHash, key); - if ((he = *hep) != NULL) { - /* Hit; see if values match */ - if (ht->valueCompare(he->value, value)) { - /* key,value pair is already present in table */ - return he; - } - if (he->value) - ht->allocOps->freeEntry(ht->allocPriv, he, HT_FREE_VALUE); - he->value = value; - return he; - } - return JS_HashTableRawAdd(ht, hep, keyHash, key, value); -} - -JS_PUBLIC_API(void) -JS_HashTableRawRemove(JSHashTable *ht, JSHashEntry **hep, JSHashEntry *he) -{ - uint32 i, n; - JSHashEntry *next, **oldbuckets; - size_t nb; - - *hep = he->next; - ht->allocOps->freeEntry(ht->allocPriv, he, HT_FREE_ENTRY); - - /* Shrink table if it's underloaded */ - n = NBUCKETS(ht); - if (--ht->nentries < UNDERLOADED(n)) { - oldbuckets = ht->buckets; - nb = n * sizeof(JSHashEntry*) / 2; - ht->buckets = (JSHashEntry**) - ht->allocOps->allocTable(ht->allocPriv, nb); - if (!ht->buckets) { - ht->buckets = oldbuckets; - return; - } - memset(ht->buckets, 0, nb); -#ifdef HASHMETER - ht->nshrinks++; -#endif - ht->shift++; - - for (i = 0; i < n; i++) { - for (he = oldbuckets[i]; he; he = next) { - next = he->next; - hep = JS_HashTableRawLookup(ht, he->keyHash, he->key); - JS_ASSERT(*hep == NULL); - he->next = NULL; - *hep = he; - } - } -#ifdef DEBUG - memset(oldbuckets, 0xDB, n * sizeof oldbuckets[0]); -#endif - ht->allocOps->freeTable(ht->allocPriv, oldbuckets); - } -} - -JS_PUBLIC_API(JSBool) -JS_HashTableRemove(JSHashTable *ht, const void *key) -{ - JSHashNumber keyHash; - JSHashEntry *he, **hep; - - keyHash = ht->keyHash(key); - hep = JS_HashTableRawLookup(ht, keyHash, key); - if ((he = *hep) == NULL) - return JS_FALSE; - - /* Hit; remove element */ - JS_HashTableRawRemove(ht, hep, he); - return JS_TRUE; -} - -JS_PUBLIC_API(void *) -JS_HashTableLookup(JSHashTable *ht, const void *key) -{ - JSHashNumber keyHash; - JSHashEntry *he, **hep; - - keyHash = ht->keyHash(key); - hep = JS_HashTableRawLookup(ht, keyHash, key); - if ((he = *hep) != NULL) { - return he->value; - } - return NULL; -} - -/* -** Iterate over the entries in the hash table calling func for each -** entry found. Stop if "f" says to (return value & JS_ENUMERATE_STOP). -** Return a count of the number of elements scanned. -*/ -JS_PUBLIC_API(int) -JS_HashTableEnumerateEntries(JSHashTable *ht, JSHashEnumerator f, void *arg) -{ - JSHashEntry *he, **hep; - uint32 i, nbuckets; - int rv, n = 0; - JSHashEntry *todo = NULL; - - nbuckets = NBUCKETS(ht); - for (i = 0; i < nbuckets; i++) { - hep = &ht->buckets[i]; - while ((he = *hep) != NULL) { - rv = f(he, n, arg); - n++; - if (rv & (HT_ENUMERATE_REMOVE | HT_ENUMERATE_UNHASH)) { - *hep = he->next; - if (rv & HT_ENUMERATE_REMOVE) { - he->next = todo; - todo = he; - } - } else { - hep = &he->next; - } - if (rv & HT_ENUMERATE_STOP) { - goto out; - } - } - } - -out: - hep = &todo; - while ((he = *hep) != NULL) { - JS_HashTableRawRemove(ht, hep, he); - } - return n; -} - -#ifdef HASHMETER -#include -#include - -JS_PUBLIC_API(void) -JS_HashTableDumpMeter(JSHashTable *ht, JSHashEnumerator dump, FILE *fp) -{ - double sqsum, mean, variance, sigma; - uint32 nchains, nbuckets, nentries; - uint32 i, n, maxChain, maxChainLen; - JSHashEntry *he; - - sqsum = 0; - nchains = 0; - maxChainLen = 0; - nbuckets = NBUCKETS(ht); - for (i = 0; i < nbuckets; i++) { - he = ht->buckets[i]; - if (!he) - continue; - nchains++; - for (n = 0; he; he = he->next) - n++; - sqsum += n * n; - if (n > maxChainLen) { - maxChainLen = n; - maxChain = i; - } - } - nentries = ht->nentries; - mean = (double)nentries / nchains; - variance = nchains * sqsum - nentries * nentries; - if (variance < 0 || nchains == 1) - variance = 0; - else - variance /= nchains * (nchains - 1); - sigma = sqrt(variance); - - fprintf(fp, "\nHash table statistics:\n"); - fprintf(fp, " number of lookups: %u\n", ht->nlookups); - fprintf(fp, " number of entries: %u\n", ht->nentries); - fprintf(fp, " number of grows: %u\n", ht->ngrows); - fprintf(fp, " number of shrinks: %u\n", ht->nshrinks); - fprintf(fp, " mean steps per hash: %g\n", (double)ht->nsteps - / ht->nlookups); - fprintf(fp, "mean hash chain length: %g\n", mean); - fprintf(fp, " standard deviation: %g\n", sigma); - fprintf(fp, " max hash chain length: %u\n", maxChainLen); - fprintf(fp, " max hash chain: [%u]\n", maxChain); - - for (he = ht->buckets[maxChain], i = 0; he; he = he->next, i++) - if (dump(he, i, fp) != HT_ENUMERATE_NEXT) - break; -} -#endif /* HASHMETER */ - -JS_PUBLIC_API(int) -JS_HashTableDump(JSHashTable *ht, JSHashEnumerator dump, FILE *fp) -{ - int count; - - count = JS_HashTableEnumerateEntries(ht, dump, fp); -#ifdef HASHMETER - JS_HashTableDumpMeter(ht, dump, fp); -#endif - return count; -} - -JS_PUBLIC_API(JSHashNumber) -JS_HashString(const void *key) -{ - JSHashNumber h; - const unsigned char *s; - - h = 0; - for (s = (const unsigned char *)key; *s; s++) - h = (h >> (JS_HASH_BITS - 4)) ^ (h << 4) ^ *s; - return h; -} - -JS_PUBLIC_API(int) -JS_CompareValues(const void *v1, const void *v2) -{ - return v1 == v2; -} diff --git a/lib/javascript/jshash.h b/lib/javascript/jshash.h deleted file mode 100644 index 85e3cf81..00000000 --- a/lib/javascript/jshash.h +++ /dev/null @@ -1,152 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jshash_h___ -#define jshash_h___ -/* - * API to portable hash table code. - */ -#include -#include -#include "jstypes.h" -#include "jscompat.h" - -JS_BEGIN_EXTERN_C - -typedef uint32 JSHashNumber; -typedef struct JSHashEntry JSHashEntry; -typedef struct JSHashTable JSHashTable; - -#define JS_HASH_BITS 32 -#define JS_GOLDEN_RATIO 0x9E3779B9U - -typedef JSHashNumber (* JS_DLL_CALLBACK JSHashFunction)(const void *key); -typedef intN (* JS_DLL_CALLBACK JSHashComparator)(const void *v1, const void *v2); -typedef intN (* JS_DLL_CALLBACK JSHashEnumerator)(JSHashEntry *he, intN i, void *arg); - -/* Flag bits in JSHashEnumerator's return value */ -#define HT_ENUMERATE_NEXT 0 /* continue enumerating entries */ -#define HT_ENUMERATE_STOP 1 /* stop enumerating entries */ -#define HT_ENUMERATE_REMOVE 2 /* remove and free the current entry */ -#define HT_ENUMERATE_UNHASH 4 /* just unhash the current entry */ - -typedef struct JSHashAllocOps { - void * (*allocTable)(void *pool, size_t size); - void (*freeTable)(void *pool, void *item); - JSHashEntry * (*allocEntry)(void *pool, const void *key); - void (*freeEntry)(void *pool, JSHashEntry *he, uintN flag); -} JSHashAllocOps; - -#define HT_FREE_VALUE 0 /* just free the entry's value */ -#define HT_FREE_ENTRY 1 /* free value and entire entry */ - -struct JSHashEntry { - JSHashEntry *next; /* hash chain linkage */ - JSHashNumber keyHash; /* key hash function result */ - const void *key; /* ptr to opaque key */ - void *value; /* ptr to opaque value */ -}; - -struct JSHashTable { - JSHashEntry **buckets; /* vector of hash buckets */ - uint32 nentries; /* number of entries in table */ - uint32 shift; /* multiplicative hash shift */ - JSHashFunction keyHash; /* key hash function */ - JSHashComparator keyCompare; /* key comparison function */ - JSHashComparator valueCompare; /* value comparison function */ - JSHashAllocOps *allocOps; /* allocation operations */ - void *allocPriv; /* allocation private data */ -#ifdef HASHMETER - uint32 nlookups; /* total number of lookups */ - uint32 nsteps; /* number of hash chains traversed */ - uint32 ngrows; /* number of table expansions */ - uint32 nshrinks; /* number of table contractions */ -#endif -}; - -/* - * Create a new hash table. - * If allocOps is null, use default allocator ops built on top of malloc(). - */ -extern JS_PUBLIC_API(JSHashTable *) -JS_NewHashTable(uint32 n, JSHashFunction keyHash, - JSHashComparator keyCompare, JSHashComparator valueCompare, - JSHashAllocOps *allocOps, void *allocPriv); - -extern JS_PUBLIC_API(void) -JS_HashTableDestroy(JSHashTable *ht); - -/* Low level access methods */ -extern JS_PUBLIC_API(JSHashEntry **) -JS_HashTableRawLookup(JSHashTable *ht, JSHashNumber keyHash, const void *key); - -extern JS_PUBLIC_API(JSHashEntry *) -JS_HashTableRawAdd(JSHashTable *ht, JSHashEntry **hep, JSHashNumber keyHash, - const void *key, void *value); - -extern JS_PUBLIC_API(void) -JS_HashTableRawRemove(JSHashTable *ht, JSHashEntry **hep, JSHashEntry *he); - -/* Higher level access methods */ -extern JS_PUBLIC_API(JSHashEntry *) -JS_HashTableAdd(JSHashTable *ht, const void *key, void *value); - -extern JS_PUBLIC_API(JSBool) -JS_HashTableRemove(JSHashTable *ht, const void *key); - -extern JS_PUBLIC_API(intN) -JS_HashTableEnumerateEntries(JSHashTable *ht, JSHashEnumerator f, void *arg); - -extern JS_PUBLIC_API(void *) -JS_HashTableLookup(JSHashTable *ht, const void *key); - -extern JS_PUBLIC_API(intN) -JS_HashTableDump(JSHashTable *ht, JSHashEnumerator dump, FILE *fp); - -/* General-purpose C string hash function. */ -extern JS_PUBLIC_API(JSHashNumber) -JS_HashString(const void *key); - -/* Stub function just returns v1 == v2 */ -extern JS_PUBLIC_API(intN) -JS_CompareValues(const void *v1, const void *v2); - -JS_END_EXTERN_C - -#endif /* jshash_h___ */ diff --git a/lib/javascript/jsify.pl b/lib/javascript/jsify.pl deleted file mode 100644 index fa7f4f83..00000000 --- a/lib/javascript/jsify.pl +++ /dev/null @@ -1,485 +0,0 @@ -#!/usr/local/bin/perl - -# This script modifies C code to use the hijacked NSPR routines that are -# now baked into the JavaScript engine rather than using the NSPR -# routines that they were based on, i.e. types like PRArenaPool are changed -# to JSArenaPool. -# -# This script was used in 9/98 to facilitate the incorporation of some NSPR -# code into the JS engine so as to minimize dependency on NSPR. -# - -# Command-line: jsify.pl [options] [filename]* -# -# Options: -# -r Reverse direction of transformation, i.e. JS ==> NSPR2 -# -outdir Directory in which to place output files - - -# NSPR2 symbols that will be modified to JS symbols, e.g. -# PRArena <==> JSArena - -@NSPR_symbols = ( -"PRArena", -"PRArenaPool", -"PRArenaStats", -"PR_ARENAMETER", -"PR_ARENA_", -"PR_ARENA_ALIGN", -"PR_ARENA_ALLOCATE", -"PR_ARENA_CONST_ALIGN_MASK", -"PR_ARENA_DEFAULT_ALIGN", -"PR_ARENA_DESTROY", -"PR_ARENA_GROW", -"PR_ARENA_MARK", -"PR_ARENA_RELEASE", - -"PR_smprintf", -"PR_smprintf_free", -"PR_snprintf", -"PR_sprintf_append", -"PR_sscanf", -"PR_sxprintf", -"PR_vsmprintf", -"PR_vsnprintf", -"PR_vsprintf_append", -"PR_vsxprintf", - -"PRCList", -"PRCListStr", -"PRCLists", - -"PRDestroyEventProc", -"PREvent", -"PREventFunProc", -"PREventQueue", -"PRHandleEventProc", -"PR_PostEvent", -"PR_PostSynchronousEvent", -"PR_ProcessPendingEvents", -"PR_CreateEventQueue", -"PR_DequeueEvent", -"PR_DestroyEvent", -"PR_DestroyEventQueue", -"PR_EventAvailable", -"PR_EventLoop", -"PR_GetEvent", -"PR_GetEventOwner", -"PR_GetEventQueueMonitor", -"PR_GetEventQueueSelectFD", -"PR_GetMainEventQueue", -"PR_HandleEvent", -"PR_InitEvent", -"PR_ENTER_EVENT_QUEUE_MONITOR", -"PR_EXIT_EVENT_QUEUE_MONITOR", -"PR_MapEvents", -"PR_RevokeEvents", - -"PR_cnvtf", -"PR_dtoa", -"PR_strtod", - -"PRFileDesc", - -"PR_HASH_BITS", -"PR_GOLDEN_RATIO", -"PRHashAllocOps", -"PRHashComparator", -"PRHashEntry", -"PRHashEnumerator", -"PRHashFunction", -"PRHashNumber", -"PRHashTable", -"PR_HashString", -"PR_HashTableAdd", -"PR_HashTableDestroy", -"PR_HashTableDump", -"PR_HashTableEnumerateEntries", -"PR_HashTableLookup", -"PR_HashTableRawAdd", -"PR_HashTableRawLookup", -"PR_HashTableRawRemove", -"PR_HashTableRemove", - -"PRBool", -"PRFloat64", -"PRInt16", -"PRInt32", -"PRInt64", -"PRInt8", -"PRIntn", -"PRUint16", -"PRUint32", -"PRUint64", -"PRUint8", -"PRUintn", -"PRPtrDiff", -"PRPtrdiff", -"PRUptrdiff", -"PRUword", -"PRWord", -"PRPackedBool", -"PRSize", -"PRStatus", -"pruword", -"prword", -"prword_t", - -"PR_ALIGN_OF_DOUBLE", -"PR_ALIGN_OF_FLOAT", -"PR_ALIGN_OF_INT", -"PR_ALIGN_OF_INT64", -"PR_ALIGN_OF_LONG", -"PR_ALIGN_OF_POINTER", -"PR_ALIGN_OF_SHORT", -"PR_ALIGN_OF_WORD", -"PR_BITS_PER_BYTE", -"PR_BITS_PER_BYTE_LOG2", -"PR_BITS_PER_DOUBLE", -"PR_BITS_PER_DOUBLE_LOG2", -"PR_BITS_PER_FLOAT", -"PR_BITS_PER_FLOAT_LOG2", -"PR_BITS_PER_INT", -"PR_BITS_PER_INT64", -"PR_BITS_PER_INT64_LOG2", -"PR_BITS_PER_INT_LOG2", -"PR_BITS_PER_LONG", -"PR_BITS_PER_LONG_LOG2", -"PR_BITS_PER_SHORT", -"PR_BITS_PER_SHORT_LOG2", -"PR_BITS_PER_WORD", -"PR_BITS_PER_WORD_LOG2", -"PR_BYTES_PER_BYTE", -"PR_BYTES_PER_DOUBLE", -"PR_BYTES_PER_DWORD", -"PR_BYTES_PER_DWORD_LOG2", -"PR_BYTES_PER_FLOAT", -"PR_BYTES_PER_INT", -"PR_BYTES_PER_INT64", -"PR_BYTES_PER_LONG", -"PR_BYTES_PER_SHORT", -"PR_BYTES_PER_WORD", -"PR_BYTES_PER_WORD_LOG2", - -"PRSegment", -"PRSegmentAccess", -"PRStuffFunc", -"PRThread", - -"PR_APPEND_LINK", - -"PR_ASSERT", - -"PR_ATOMIC_DWORD_LOAD", -"PR_ATOMIC_DWORD_STORE", - -"PR_Abort", - -"PR_ArenaAllocate", -"PR_ArenaCountAllocation", -"PR_ArenaCountGrowth", -"PR_ArenaCountInplaceGrowth", -"PR_ArenaCountRelease", -"PR_ArenaCountRetract", -"PR_ArenaFinish", -"PR_ArenaGrow", -"PR_ArenaRelease", -"PR_CompactArenaPool", -"PR_DumpArenaStats", -"PR_FinishArenaPool", -"PR_FreeArenaPool", -"PR_InitArenaPool", - -"PR_Assert", - -"PR_AttachThread", - -"PR_BEGIN_EXTERN_C", -"PR_BEGIN_MACRO", - -"PR_BIT", -"PR_BITMASK", - -"PR_BUFFER_OVERFLOW_ERROR", - -"PR_CALLBACK", -"PR_CALLBACK_DECL", -"PR_CALLOC", -"PR_CEILING_LOG2", -"PR_CLEAR_ARENA", -"PR_CLEAR_BIT", -"PR_CLEAR_UNUSED", -"PR_CLIST_IS_EMPTY", -"PR_COUNT_ARENA", -"PR_CURRENT_THREAD", - -"PR_GetSegmentAccess", -"PR_GetSegmentSize", -"PR_GetSegmentVaddr", -"PR_GrowSegment", -"PR_DestroySegment", -"PR_MapSegment", -"PR_NewSegment", -"PR_Segment", -"PR_Seg", -"PR_SEGMENT_NONE", -"PR_SEGMENT_RDONLY", -"PR_SEGMENT_RDWR", - -"PR_Calloc", -"PR_CeilingLog2", -"PR_CompareStrings", -"PR_CompareValues", -"PR_DELETE", -"PR_END_EXTERN_C", -"PR_END_MACRO", -"PR_ENUMERATE_STOP", -"PR_FAILURE", -"PR_FALSE", -"PR_FLOOR_LOG2", -"PR_FREEIF", -"PR_FREE_PATTERN", -"PR_FloorLog2", -"PR_FormatTime", -"PR_Free", - -"PR_GetEnv", -"PR_GetError", -"PR_INIT_ARENA_POOL", -"PR_INIT_CLIST", -"PR_INIT_STATIC_CLIST", -"PR_INLINE", -"PR_INSERT_AFTER", -"PR_INSERT_BEFORE", -"PR_INSERT_LINK", -"PR_INT32", -"PR_INTERVAL_NO_TIMEOUT", -"PR_INTERVAL_NO_WAIT", -"PR_Init", -"PR_LIST_HEAD", -"PR_LIST_TAIL", -"PR_LOG", -"PR_LOGGING", -"PR_LOG_ALWAYS", -"PR_LOG_BEGIN", -"PR_LOG_DEBUG", -"PR_LOG_DEFINE", -"PR_LOG_END", -"PR_LOG_ERROR", -"PR_LOG_MAX", -"PR_LOG_MIN", -"PR_LOG_NONE", -"PR_LOG_NOTICE", -"PR_LOG_TEST", -"PR_LOG_WARN", -"PR_LOG_WARNING", -"PR_LogFlush", -"PR_LogPrint", -"PR_MALLOC", -"PR_MAX", -"PR_MD_calloc", -"PR_MD_free", -"PR_MD_malloc", -"PR_MD_realloc", -"PR_MIN", -"PR_Malloc", -"PR_NEW", -"PR_NEWZAP", -"PR_NEXT_LINK", -"PR_NOT_REACHED", -"PR_NewCondVar", -"PR_NewHashTable", -"PR_NewLogModule", -"PR_PREV_LINK", -"PR_PUBLIC_API", -"PR_PUBLIC_DATA", -"PR_RANGE_ERROR", -"PR_REALLOC", -"PR_REMOVE_AND_INIT_LINK", -"PR_REMOVE_LINK", -"PR_ROUNDUP", -"PR_Realloc", - -"PR_SET_BIT", -"PR_STATIC_CALLBACK", -"PR_SUCCESS", -"PR_SetError", -"PR_SetLogBuffering", -"PR_SetLogFile", - -"PR_TEST_BIT", -"PR_TRUE", -"PR_UINT32", -"PR_UPTRDIFF", - -"prarena_h___", -"prbit_h___", -"prclist_h___", -"prdtoa_h___", -"prlog_h___", -"prlong_h___", -"prmacos_h___", -"prmem_h___", -"prprf_h___", -"prtypes_h___", - -"prarena", -"prbit", -"prbitmap_t", -"prclist", -"prcpucfg", -"prdtoa", -"prhash", -"plhash", -"prlong", -"prmacos", -"prmem", -"prosdep", -"protypes", -"prprf", -"prtypes" -); - -while ($ARGV[0] =~ /^-/) { - if ($ARGV[0] eq "-r") { - shift; - $reverse_conversion = 1; - } elsif ($ARGV[0] eq "-outdir") { - shift; - $outdir = shift; - } -} - -# Given an NSPR symbol compute the JS equivalent or -# vice-versa -sub subst { - local ($replacement); - local ($sym) = @_; - - $replacement = substr($sym,0,2) eq "pr" ? "js" : "JS"; - $replacement .= substr($sym, 2); - return $replacement; -} - -# Build the regular expression that will convert between the NSPR -# types and the JS types -if ($reverse_conversion) { - die "Not implemented yet"; -} else { - foreach $sym (@NSPR_symbols) { - $regexp .= $sym . "|" - } - # Get rid of the last "!" - chop $regexp; - - # Replace PR* with JS* and replace pr* with js* - $regexp = 's/(^|\\W)(' . $regexp . ')/$1 . &subst($2)/eg'; -# print $regexp; -} - -# Pre-compile a little subroutine to perform the regexp substitution -# between NSPR types and JS types -eval('sub convert_from_NSPR {($line) = @_; $line =~ ' . $regexp . ';}'); - -sub convert_mallocs { - ($line) = @_; - $line =~ s/PR_MALLOC/malloc/g; - $line =~ s/PR_REALLOC/realloc/g; - $line =~ s/PR_FREE/free/g; - return $line; -} - -sub convert_includes { - ($line) = @_; - if ($line !~ /include/) { - return $line; - } - - if ($line =~ /prlog\.h/) { - $line = '#include "jsutil.h"'. " /* Added by JSIFY */\n"; - } elsif ($line =~ /plhash\.h/) { - $line = '#include "jshash.h"'. " /* Added by JSIFY */\n"; - } elsif ($line =~ /plarena\.h/) { - $line = '#include "jsarena.h"'. " /* Added by JSIFY */\n"; - } elsif ($line =~ /prmem\.h/) { - $line = ""; - } elsif ($line =~ /jsmsg\.def/) { - $line = '#include "js.msg"' . "\n"; - } elsif ($line =~ /shellmsg\.def/) { - $line = '#include "jsshell.msg"' . "\n"; - } elsif ($line =~ /jsopcode\.def/) { - $line = '#include "jsopcode.tbl"' . "\n"; - } - return $line; -} - -sub convert_declarations { - ($line) = @_; - $line =~ s/PR_EXTERN/JS_EXTERN_API/g; - $line =~ s/PR_IMPLEMENT_DATA/JS_EXPORT_DATA/g; - $line =~ s/PR_IMPLEMENT/JS_EXPORT_API/g; - $line =~ s/PR_CALLBACK/JS_DLL_CALLBACK/g; - $line =~ s/PR_STATIC_CALLBACK/JS_STATIC_DLL_CALLBACK/g; - $line =~ s/PR_IMPORT/JS_IMPORT/g; - $line =~ s/PR_PUBLIC_API/JS_EXPORT_API/g; - $line =~ s/PR_PUBLIC_DATA/JS_EXPORT_DATA/g; - return $line; -} - -sub convert_long_long_macros { - ($line) = @_; - $line =~ s/\b(LL_)/JSLL_/g; - return $line; -} - -sub convert_asserts { - ($line) = @_; - $line =~ s/\bPR_ASSERT/JS_ASSERT/g; - return $line; -} - -while ($#ARGV >= 0) { - $infile = shift; - - # Change filename, e.g. prtime.h to jsprtime.h, except for legacy - # files that start with 'prmj', like prmjtime.h. - $outfile = $infile; - if ($infile !~ /^prmj/) { - $outfile =~ s/^pr/js/; - $outfile =~ s/^pl/js/; - } - - if ($outdir) { - $outfile = $outdir . '/' . $outfile; - } - - if ($infile eq $outfile) { - die "Error: refuse to overwrite $outfile, use -outdir option." - } - die "Can't open $infile" if !open(INFILE, "<$infile"); - die "Can't open $outfile for writing" if !open(OUTFILE, ">$outfile"); - - while () { - $line = $_; - - #Get rid of #include "prlog.h" - &convert_includes($line); - - # Rename PR_EXTERN, PR_IMPORT, etc. - &convert_declarations($line); - - # Convert from PR_MALLOC to malloc, etc. - &convert_mallocs($line); - - # Convert from PR_ASSERT to JS_ASSERT -# &convert_asserts($line); - - # Convert from, e.g. PRArena to JSPRArena - &convert_from_NSPR($line); - - # Change LL_* macros to JSLL_* - &convert_long_long_macros($line); - - print OUTFILE $line; - } -} diff --git a/lib/javascript/jsinterp.c b/lib/javascript/jsinterp.c deleted file mode 100644 index 096610cf..00000000 --- a/lib/javascript/jsinterp.c +++ /dev/null @@ -1,5564 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sw=4 et tw=78: - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JavaScript bytecode interpreter. - */ -#include "jsstddef.h" -#include -#include -#include -#include "jstypes.h" -#include "jsarena.h" /* Added by JSIFY */ -#include "jsutil.h" /* Added by JSIFY */ -#include "jsprf.h" -#include "jsapi.h" -#include "jsarray.h" -#include "jsatom.h" -#include "jsbool.h" -#include "jscntxt.h" -#include "jsconfig.h" -#include "jsdbgapi.h" -#include "jsfun.h" -#include "jsgc.h" -#include "jsinterp.h" -#include "jslock.h" -#include "jsnum.h" -#include "jsobj.h" -#include "jsopcode.h" -#include "jsscope.h" -#include "jsscript.h" -#include "jsstr.h" - -#if JS_HAS_JIT -#include "jsjit.h" -#endif - -#if JS_HAS_XML_SUPPORT -#include "jsxml.h" -#endif - -#ifdef DEBUG -#define ASSERT_CACHE_IS_EMPTY(cache) \ - JS_BEGIN_MACRO \ - JSPropertyCacheEntry *end_, *pce_, entry_; \ - JSPropertyCache *cache_ = (cache); \ - JS_ASSERT(cache_->empty); \ - end_ = &cache_->table[PROPERTY_CACHE_SIZE]; \ - for (pce_ = &cache_->table[0]; pce_ < end_; pce_++) { \ - PCE_LOAD(cache_, pce_, entry_); \ - JS_ASSERT(!PCE_OBJECT(entry_)); \ - JS_ASSERT(!PCE_PROPERTY(entry_)); \ - } \ - JS_END_MACRO -#else -#define ASSERT_CACHE_IS_EMPTY(cache) ((void)0) -#endif - -void -js_FlushPropertyCache(JSContext *cx) -{ - JSPropertyCache *cache; - - cache = &cx->runtime->propertyCache; - if (cache->empty) { - ASSERT_CACHE_IS_EMPTY(cache); - return; - } - memset(cache->table, 0, sizeof cache->table); - cache->empty = JS_TRUE; -#ifdef JS_PROPERTY_CACHE_METERING - cache->flushes++; -#endif -} - -void -js_DisablePropertyCache(JSContext *cx) -{ - JS_ASSERT(!cx->runtime->propertyCache.disabled); - cx->runtime->propertyCache.disabled = JS_TRUE; -} - -void -js_EnablePropertyCache(JSContext *cx) -{ - JS_ASSERT(cx->runtime->propertyCache.disabled); - ASSERT_CACHE_IS_EMPTY(&cx->runtime->propertyCache); - cx->runtime->propertyCache.disabled = JS_FALSE; -} - -/* - * Class for for/in loop property iterator objects. - */ -#define JSSLOT_ITER_STATE JSSLOT_PRIVATE - -static void -prop_iterator_finalize(JSContext *cx, JSObject *obj) -{ - jsval iter_state; - jsval iteratee; - - /* Protect against stillborn iterators. */ - iter_state = obj->slots[JSSLOT_ITER_STATE]; - iteratee = obj->slots[JSSLOT_PARENT]; - if (!JSVAL_IS_NULL(iter_state) && !JSVAL_IS_PRIMITIVE(iteratee)) { - OBJ_ENUMERATE(cx, JSVAL_TO_OBJECT(iteratee), JSENUMERATE_DESTROY, - &iter_state, NULL); - } - js_RemoveRoot(cx->runtime, &obj->slots[JSSLOT_PARENT]); -} - -static JSClass prop_iterator_class = { - "PropertyIterator", - 0, - JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, prop_iterator_finalize, - JSCLASS_NO_OPTIONAL_MEMBERS -}; - -/* - * Stack macros and functions. These all use a local variable, jsval *sp, to - * point to the next free stack slot. SAVE_SP must be called before any call - * to a function that may invoke the interpreter. RESTORE_SP must be called - * only after return from js_Invoke, because only js_Invoke changes fp->sp. - */ -#define PUSH(v) (*sp++ = (v)) -#define POP() (*--sp) -#ifdef DEBUG -#define SAVE_SP(fp) \ - (JS_ASSERT((fp)->script || !(fp)->spbase || (sp) == (fp)->spbase), \ - (fp)->sp = sp) -#else -#define SAVE_SP(fp) ((fp)->sp = sp) -#endif -#define RESTORE_SP(fp) (sp = (fp)->sp) - -/* - * Push the generating bytecode's pc onto the parallel pc stack that runs - * depth slots below the operands. - * - * NB: PUSH_OPND uses sp, depth, and pc from its lexical environment. See - * js_Interpret for these local variables' declarations and uses. - */ -#define PUSH_OPND(v) (sp[-depth] = (jsval)pc, PUSH(v)) -#define STORE_OPND(n,v) (sp[(n)-depth] = (jsval)pc, sp[n] = (v)) -#define POP_OPND() POP() -#define FETCH_OPND(n) (sp[n]) - -/* - * Push the jsdouble d using sp, depth, and pc from the lexical environment. - * Try to convert d to a jsint that fits in a jsval, otherwise GC-alloc space - * for it and push a reference. - */ -#define STORE_NUMBER(cx, n, d) \ - JS_BEGIN_MACRO \ - jsint i_; \ - jsval v_; \ - \ - if (JSDOUBLE_IS_INT(d, i_) && INT_FITS_IN_JSVAL(i_)) { \ - v_ = INT_TO_JSVAL(i_); \ - } else { \ - ok = js_NewDoubleValue(cx, d, &v_); \ - if (!ok) \ - goto out; \ - } \ - STORE_OPND(n, v_); \ - JS_END_MACRO - -#define FETCH_NUMBER(cx, n, d) \ - JS_BEGIN_MACRO \ - jsval v_; \ - \ - v_ = FETCH_OPND(n); \ - VALUE_TO_NUMBER(cx, v_, d); \ - JS_END_MACRO - -#define FETCH_INT(cx, n, i) \ - JS_BEGIN_MACRO \ - jsval v_ = FETCH_OPND(n); \ - if (JSVAL_IS_INT(v_)) { \ - i = JSVAL_TO_INT(v_); \ - } else { \ - SAVE_SP(fp); \ - ok = js_ValueToECMAInt32(cx, v_, &i); \ - if (!ok) \ - goto out; \ - } \ - JS_END_MACRO - -#define FETCH_UINT(cx, n, ui) \ - JS_BEGIN_MACRO \ - jsval v_ = FETCH_OPND(n); \ - jsint i_; \ - if (JSVAL_IS_INT(v_) && (i_ = JSVAL_TO_INT(v_)) >= 0) { \ - ui = (uint32) i_; \ - } else { \ - SAVE_SP(fp); \ - ok = js_ValueToECMAUint32(cx, v_, &ui); \ - if (!ok) \ - goto out; \ - } \ - JS_END_MACRO - -/* - * Optimized conversion macros that test for the desired type in v before - * homing sp and calling a conversion function. - */ -#define VALUE_TO_NUMBER(cx, v, d) \ - JS_BEGIN_MACRO \ - if (JSVAL_IS_INT(v)) { \ - d = (jsdouble)JSVAL_TO_INT(v); \ - } else if (JSVAL_IS_DOUBLE(v)) { \ - d = *JSVAL_TO_DOUBLE(v); \ - } else { \ - SAVE_SP(fp); \ - ok = js_ValueToNumber(cx, v, &d); \ - if (!ok) \ - goto out; \ - } \ - JS_END_MACRO - -#define POP_BOOLEAN(cx, v, b) \ - JS_BEGIN_MACRO \ - v = FETCH_OPND(-1); \ - if (v == JSVAL_NULL) { \ - b = JS_FALSE; \ - } else if (JSVAL_IS_BOOLEAN(v)) { \ - b = JSVAL_TO_BOOLEAN(v); \ - } else { \ - SAVE_SP(fp); \ - ok = js_ValueToBoolean(cx, v, &b); \ - if (!ok) \ - goto out; \ - } \ - sp--; \ - JS_END_MACRO - -#define VALUE_TO_OBJECT(cx, v, obj) \ - JS_BEGIN_MACRO \ - if (!JSVAL_IS_PRIMITIVE(v)) { \ - obj = JSVAL_TO_OBJECT(v); \ - } else { \ - SAVE_SP(fp); \ - obj = js_ValueToNonNullObject(cx, v); \ - if (!obj) { \ - ok = JS_FALSE; \ - goto out; \ - } \ - } \ - JS_END_MACRO - -#define FETCH_OBJECT(cx, n, v, obj) \ - JS_BEGIN_MACRO \ - v = FETCH_OPND(n); \ - VALUE_TO_OBJECT(cx, v, obj); \ - STORE_OPND(n, OBJECT_TO_JSVAL(obj)); \ - JS_END_MACRO - -#if JS_BUG_VOID_TOSTRING -#define CHECK_VOID_TOSTRING(cx, v) \ - if (JSVAL_IS_VOID(v)) { \ - JSString *str_; \ - str_ = ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_VOID]); \ - v = STRING_TO_JSVAL(str_); \ - } -#else -#define CHECK_VOID_TOSTRING(cx, v) ((void)0) -#endif - -#if JS_BUG_EAGER_TOSTRING -#define CHECK_EAGER_TOSTRING(hint) (hint = JSTYPE_STRING) -#else -#define CHECK_EAGER_TOSTRING(hint) ((void)0) -#endif - -#define VALUE_TO_PRIMITIVE(cx, v, hint, vp) \ - JS_BEGIN_MACRO \ - if (JSVAL_IS_PRIMITIVE(v)) { \ - CHECK_VOID_TOSTRING(cx, v); \ - *vp = v; \ - } else { \ - SAVE_SP(fp); \ - CHECK_EAGER_TOSTRING(hint); \ - ok = OBJ_DEFAULT_VALUE(cx, JSVAL_TO_OBJECT(v), hint, vp); \ - if (!ok) \ - goto out; \ - } \ - JS_END_MACRO - -JS_FRIEND_API(jsval *) -js_AllocRawStack(JSContext *cx, uintN nslots, void **markp) -{ - jsval *sp; - - if (markp) - *markp = JS_ARENA_MARK(&cx->stackPool); - JS_ARENA_ALLOCATE_CAST(sp, jsval *, &cx->stackPool, nslots * sizeof(jsval)); - if (!sp) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_STACK_OVERFLOW, - (cx->fp && cx->fp->fun) - ? JS_GetFunctionName(cx->fp->fun) - : "script"); - } - return sp; -} - -JS_FRIEND_API(void) -js_FreeRawStack(JSContext *cx, void *mark) -{ - JS_ARENA_RELEASE(&cx->stackPool, mark); -} - -JS_FRIEND_API(jsval *) -js_AllocStack(JSContext *cx, uintN nslots, void **markp) -{ - jsval *sp, *vp, *end; - JSArena *a; - JSStackHeader *sh; - JSStackFrame *fp; - - /* Callers don't check for zero nslots: we do to avoid empty segments. */ - if (nslots == 0) { - *markp = NULL; - return JS_ARENA_MARK(&cx->stackPool); - } - - /* Allocate 2 extra slots for the stack segment header we'll likely need. */ - sp = js_AllocRawStack(cx, 2 + nslots, markp); - if (!sp) - return NULL; - - /* Try to avoid another header if we can piggyback on the last segment. */ - a = cx->stackPool.current; - sh = cx->stackHeaders; - if (sh && JS_STACK_SEGMENT(sh) + sh->nslots == sp) { - /* Extend the last stack segment, give back the 2 header slots. */ - sh->nslots += nslots; - a->avail -= 2 * sizeof(jsval); - } else { - /* - * Need a new stack segment, so we must initialize unused slots in the - * current frame. See js_GC, just before marking the "operand" jsvals, - * where we scan from fp->spbase to fp->sp or through fp->script->depth - * (whichever covers fewer slots). - */ - fp = cx->fp; - if (fp && fp->script && fp->spbase) { -#ifdef DEBUG - jsuword depthdiff = fp->script->depth * sizeof(jsval); - JS_ASSERT(JS_UPTRDIFF(fp->sp, fp->spbase) <= depthdiff); - JS_ASSERT(JS_UPTRDIFF(*markp, fp->spbase) >= depthdiff); -#endif - end = fp->spbase + fp->script->depth; - for (vp = fp->sp; vp < end; vp++) - *vp = JSVAL_VOID; - } - - /* Allocate and push a stack segment header from the 2 extra slots. */ - sh = (JSStackHeader *)sp; - sh->nslots = nslots; - sh->down = cx->stackHeaders; - cx->stackHeaders = sh; - sp += 2; - } - - /* - * Store JSVAL_NULL using memset, to let compilers optimize as they see - * fit, in case a caller allocates and pushes GC-things one by one, which - * could nest a last-ditch GC that will scan this segment. - */ - memset(sp, 0, nslots * sizeof(jsval)); - return sp; -} - -JS_FRIEND_API(void) -js_FreeStack(JSContext *cx, void *mark) -{ - JSStackHeader *sh; - jsuword slotdiff; - - /* Check for zero nslots allocation special case. */ - if (!mark) - return; - - /* We can assert because js_FreeStack always balances js_AllocStack. */ - sh = cx->stackHeaders; - JS_ASSERT(sh); - - /* If mark is in the current segment, reduce sh->nslots, else pop sh. */ - slotdiff = JS_UPTRDIFF(mark, JS_STACK_SEGMENT(sh)) / sizeof(jsval); - if (slotdiff < (jsuword)sh->nslots) - sh->nslots = slotdiff; - else - cx->stackHeaders = sh->down; - - /* Release the stackPool space allocated since mark was set. */ - JS_ARENA_RELEASE(&cx->stackPool, mark); -} - -JSBool -js_GetArgument(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - return JS_TRUE; -} - -JSBool -js_SetArgument(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - return JS_TRUE; -} - -JSBool -js_GetLocalVariable(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - return JS_TRUE; -} - -JSBool -js_SetLocalVariable(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - return JS_TRUE; -} - -JSBool -js_ComputeThis(JSContext *cx, JSObject *thisp, JSStackFrame *fp) -{ - if (thisp && OBJ_GET_CLASS(cx, thisp) != &js_CallClass) { - /* Some objects (e.g., With) delegate 'this' to another object. */ - thisp = OBJ_THIS_OBJECT(cx, thisp); - if (!thisp) - return JS_FALSE; - - /* Default return value for a constructor is the new object. */ - if (fp->flags & JSFRAME_CONSTRUCTING) - fp->rval = OBJECT_TO_JSVAL(thisp); - } else { - /* - * ECMA requires "the global object", but in the presence of multiple - * top-level objects (windows, frames, or certain layers in the client - * object model), we prefer fun's parent. An example that causes this - * code to run: - * - * // in window w1 - * function f() { return this } - * function g() { return f } - * - * // in window w2 - * var h = w1.g() - * alert(h() == w1) - * - * The alert should display "true". - */ - JS_ASSERT(!(fp->flags & JSFRAME_CONSTRUCTING)); - if (JSVAL_IS_PRIMITIVE(fp->argv[-2]) || - !OBJ_GET_PARENT(cx, JSVAL_TO_OBJECT(fp->argv[-2]))) { - thisp = cx->globalObject; - } else { - jsid id; - jsval v; - uintN attrs; - - /* Walk up the parent chain. */ - thisp = JSVAL_TO_OBJECT(fp->argv[-2]); - id = ATOM_TO_JSID(cx->runtime->atomState.parentAtom); - for (;;) { - if (!OBJ_CHECK_ACCESS(cx, thisp, id, JSACC_PARENT, &v, &attrs)) - return JS_FALSE; - if (JSVAL_IS_VOID(v)) - v = OBJ_GET_SLOT(cx, thisp, JSSLOT_PARENT); - if (JSVAL_IS_NULL(v)) - break; - thisp = JSVAL_TO_OBJECT(v); - } - } - } - fp->thisp = thisp; - fp->argv[-1] = OBJECT_TO_JSVAL(thisp); - return JS_TRUE; -} - -#ifdef DUMP_CALL_TABLE - -#include "jsclist.h" -#include "jshash.h" -#include "jsdtoa.h" - -typedef struct CallKey { - jsval callee; /* callee value */ - const char *filename; /* function filename or null */ - uintN lineno; /* function lineno or 0 */ -} CallKey; - -/* Compensate for typeof null == "object" brain damage. */ -#define JSTYPE_NULL JSTYPE_LIMIT -#define TYPEOF(cx,v) (JSVAL_IS_NULL(v) ? JSTYPE_NULL : JS_TypeOfValue(cx,v)) -#define TYPENAME(t) (((t) == JSTYPE_NULL) ? js_null_str : js_type_str[t]) -#define NTYPEHIST (JSTYPE_LIMIT + 1) - -typedef struct CallValue { - uint32 total; /* total call count */ - uint32 recycled; /* LRU-recycled calls lost */ - uint16 minargc; /* minimum argument count */ - uint16 maxargc; /* maximum argument count */ - struct ArgInfo { - uint32 typeHist[NTYPEHIST]; /* histogram by type */ - JSCList lruList; /* top 10 values LRU list */ - struct ArgValCount { - JSCList lruLink; /* LRU list linkage */ - jsval value; /* recently passed value */ - uint32 count; /* number of times passed */ - char strbuf[112]; /* string conversion buffer */ - } topValCounts[10]; /* top 10 value storage */ - } argInfo[8]; -} CallValue; - -typedef struct CallEntry { - JSHashEntry entry; - CallKey key; - CallValue value; - char name[32]; /* function name copy */ -} CallEntry; - -static void * -AllocCallTable(void *pool, size_t size) -{ - return malloc(size); -} - -static void -FreeCallTable(void *pool, void *item) -{ - free(item); -} - -static JSHashEntry * -AllocCallEntry(void *pool, const void *key) -{ - return (JSHashEntry*) calloc(1, sizeof(CallEntry)); -} - -static void -FreeCallEntry(void *pool, JSHashEntry *he, uintN flag) -{ - JS_ASSERT(flag == HT_FREE_ENTRY); - free(he); -} - -static JSHashAllocOps callTableAllocOps = { - AllocCallTable, FreeCallTable, - AllocCallEntry, FreeCallEntry -}; - -JS_STATIC_DLL_CALLBACK(JSHashNumber) -js_hash_call_key(const void *key) -{ - CallKey *ck = (CallKey *) key; - JSHashNumber hash = (jsuword)ck->callee >> 3; - - if (ck->filename) { - hash = (hash << 4) ^ JS_HashString(ck->filename); - hash = (hash << 4) ^ ck->lineno; - } - return hash; -} - -JS_STATIC_DLL_CALLBACK(intN) -js_compare_call_keys(const void *k1, const void *k2) -{ - CallKey *ck1 = (CallKey *)k1, *ck2 = (CallKey *)k2; - - return ck1->callee == ck2->callee && - ((ck1->filename && ck2->filename) - ? strcmp(ck1->filename, ck2->filename) == 0 - : ck1->filename == ck2->filename) && - ck1->lineno == ck2->lineno; -} - -JSHashTable *js_CallTable; -size_t js_LogCallToSourceLimit; - -JS_STATIC_DLL_CALLBACK(intN) -CallTableDumper(JSHashEntry *he, intN k, void *arg) -{ - CallEntry *ce = (CallEntry *)he; - FILE *fp = (FILE *)arg; - uintN argc, i, n; - struct ArgInfo *ai; - JSType save, type; - JSCList *cl; - struct ArgValCount *avc; - jsval argval; - - if (ce->key.filename) { - /* We're called at the end of the mark phase, so mark our filenames. */ - js_MarkScriptFilename(ce->key.filename); - fprintf(fp, "%s:%u ", ce->key.filename, ce->key.lineno); - } else { - fprintf(fp, "@%p ", (void *) ce->key.callee); - } - - if (ce->name[0]) - fprintf(fp, "name %s ", ce->name); - fprintf(fp, "calls %lu (%lu) argc %u/%u\n", - (unsigned long) ce->value.total, - (unsigned long) ce->value.recycled, - ce->value.minargc, ce->value.maxargc); - - argc = JS_MIN(ce->value.maxargc, 8); - for (i = 0; i < argc; i++) { - ai = &ce->value.argInfo[i]; - - n = 0; - save = -1; - for (type = JSTYPE_VOID; type <= JSTYPE_LIMIT; type++) { - if (ai->typeHist[type]) { - save = type; - ++n; - } - } - if (n == 1) { - fprintf(fp, " arg %u type %s: %lu\n", - i, TYPENAME(save), (unsigned long) ai->typeHist[save]); - } else { - fprintf(fp, " arg %u type histogram:\n", i); - for (type = JSTYPE_VOID; type <= JSTYPE_LIMIT; type++) { - fprintf(fp, " %9s: %8lu ", - TYPENAME(type), (unsigned long) ai->typeHist[type]); - for (n = (uintN) JS_HOWMANY(ai->typeHist[type], 10); n > 0; --n) - fputc('*', fp); - fputc('\n', fp); - } - } - - fprintf(fp, " arg %u top 10 values:\n", i); - n = 1; - for (cl = ai->lruList.prev; cl != &ai->lruList; cl = cl->prev) { - avc = (struct ArgValCount *)cl; - if (!avc->count) - break; - argval = avc->value; - fprintf(fp, " %9u: %8lu %.*s (%#lx)\n", - n, (unsigned long) avc->count, - sizeof avc->strbuf, avc->strbuf, argval); - ++n; - } - } - - return HT_ENUMERATE_NEXT; -} - -void -js_DumpCallTable(JSContext *cx) -{ - char name[24]; - FILE *fp; - static uintN dumpCount; - - if (!js_CallTable) - return; - - JS_snprintf(name, sizeof name, "/tmp/calltable.dump.%u", dumpCount & 7); - dumpCount++; - fp = fopen(name, "w"); - if (!fp) - return; - - JS_HashTableEnumerateEntries(js_CallTable, CallTableDumper, fp); - fclose(fp); -} - -static void -LogCall(JSContext *cx, jsval callee, uintN argc, jsval *argv) -{ - CallKey key; - const char *name, *cstr; - JSFunction *fun; - JSHashNumber keyHash; - JSHashEntry **hep, *he; - CallEntry *ce; - uintN i, j; - jsval argval; - JSType type; - struct ArgInfo *ai; - struct ArgValCount *avc; - JSString *str; - - if (!js_CallTable) { - js_CallTable = JS_NewHashTable(1024, js_hash_call_key, - js_compare_call_keys, NULL, - &callTableAllocOps, NULL); - if (!js_CallTable) - return; - } - - key.callee = callee; - key.filename = NULL; - key.lineno = 0; - name = ""; - if (JSVAL_IS_FUNCTION(cx, callee)) { - fun = (JSFunction *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(callee)); - if (fun->atom) - name = js_AtomToPrintableString(cx, fun->atom); - if (fun->interpreted) { - key.filename = fun->u.script->filename; - key.lineno = fun->u.script->lineno; - } - } - keyHash = js_hash_call_key(&key); - - hep = JS_HashTableRawLookup(js_CallTable, keyHash, &key); - he = *hep; - if (he) { - ce = (CallEntry *) he; - JS_ASSERT(strncmp(ce->name, name, sizeof ce->name) == 0); - } else { - he = JS_HashTableRawAdd(js_CallTable, hep, keyHash, &key, NULL); - if (!he) - return; - ce = (CallEntry *) he; - ce->entry.key = &ce->key; - ce->entry.value = &ce->value; - ce->key = key; - for (i = 0; i < 8; i++) { - ai = &ce->value.argInfo[i]; - JS_INIT_CLIST(&ai->lruList); - for (j = 0; j < 10; j++) - JS_APPEND_LINK(&ai->topValCounts[j].lruLink, &ai->lruList); - } - strncpy(ce->name, name, sizeof ce->name); - } - - ++ce->value.total; - if (ce->value.minargc < argc) - ce->value.minargc = argc; - if (ce->value.maxargc < argc) - ce->value.maxargc = argc; - if (argc > 8) - argc = 8; - for (i = 0; i < argc; i++) { - ai = &ce->value.argInfo[i]; - argval = argv[i]; - type = TYPEOF(cx, argval); - ++ai->typeHist[type]; - - for (j = 0; ; j++) { - if (j == 10) { - avc = (struct ArgValCount *) ai->lruList.next; - ce->value.recycled += avc->count; - avc->value = argval; - avc->count = 1; - break; - } - avc = &ai->topValCounts[j]; - if (avc->value == argval) { - ++avc->count; - break; - } - } - - /* Move avc to the back of the LRU list. */ - JS_REMOVE_LINK(&avc->lruLink); - JS_APPEND_LINK(&avc->lruLink, &ai->lruList); - - str = NULL; - cstr = ""; - switch (TYPEOF(cx, argval)) { - case JSTYPE_VOID: - cstr = js_type_str[JSTYPE_VOID]; - break; - case JSTYPE_NULL: - cstr = js_null_str; - break; - case JSTYPE_BOOLEAN: - cstr = js_boolean_str[JSVAL_TO_BOOLEAN(argval)]; - break; - case JSTYPE_NUMBER: - if (JSVAL_IS_INT(argval)) { - JS_snprintf(avc->strbuf, sizeof avc->strbuf, "%ld", - JSVAL_TO_INT(argval)); - } else { - JS_dtostr(avc->strbuf, sizeof avc->strbuf, DTOSTR_STANDARD, 0, - *JSVAL_TO_DOUBLE(argval)); - } - continue; - case JSTYPE_STRING: - str = js_QuoteString(cx, JSVAL_TO_STRING(argval), (jschar)'"'); - break; - case JSTYPE_FUNCTION: - if (JSVAL_IS_FUNCTION(cx, argval)) { - fun = (JSFunction *)JS_GetPrivate(cx, JSVAL_TO_OBJECT(argval)); - if (fun && fun->atom) { - str = ATOM_TO_STRING(fun->atom); - break; - } - } - /* FALL THROUGH */ - case JSTYPE_OBJECT: - js_LogCallToSourceLimit = sizeof avc->strbuf; - cx->options |= JSOPTION_LOGCALL_TOSOURCE; - str = js_ValueToSource(cx, argval); - cx->options &= ~JSOPTION_LOGCALL_TOSOURCE; - break; - } - if (str) - cstr = JS_GetStringBytes(str); - strncpy(avc->strbuf, cstr, sizeof avc->strbuf); - } -} - -#endif /* DUMP_CALL_TABLE */ - -/* - * Find a function reference and its 'this' object implicit first parameter - * under argc arguments on cx's stack, and call the function. Push missing - * required arguments, allocate declared local variables, and pop everything - * when done. Then push the return value. - */ -JS_FRIEND_API(JSBool) -js_Invoke(JSContext *cx, uintN argc, uintN flags) -{ - void *mark; - JSStackFrame *fp, frame; - jsval *sp, *newsp, *limit; - jsval *vp, v; - JSObject *funobj, *parent, *thisp; - JSBool ok; - JSClass *clasp; - JSObjectOps *ops; - JSNative native; - JSFunction *fun; - JSScript *script; - uintN nslots, nvars, nalloc, surplus; - JSInterpreterHook hook; - void *hookData; - - /* Mark the top of stack and load frequently-used registers. */ - mark = JS_ARENA_MARK(&cx->stackPool); - fp = cx->fp; - sp = fp->sp; - - /* - * Set vp to the callee value's stack slot (it's where rval goes). - * Once vp is set, control should flow through label out2: to return. - * Set frame.rval early so native class and object ops can throw and - * return false, causing a goto out2 with ok set to false. Also set - * frame.flags to flags so that ComputeThis can test bits in it. - */ - vp = sp - (2 + argc); - v = *vp; - frame.rval = JSVAL_VOID; - frame.flags = flags; - thisp = JSVAL_TO_OBJECT(vp[1]); - - /* - * A callee must be an object reference, unless its |this| parameter - * implements the __noSuchMethod__ method, in which case that method will - * be called like so: - * - * thisp.__noSuchMethod__(id, args) - * - * where id is the name of the method that this invocation attempted to - * call by name, and args is an Array containing this invocation's actual - * parameters. - */ - if (JSVAL_IS_PRIMITIVE(v)) { -#if JS_HAS_NO_SUCH_METHOD - jsid id; - jsbytecode *pc; - jsatomid atomIndex; - JSAtom *atom; - JSObject *argsobj; - JSArena *a; - - if (!fp->script || (flags & JSINVOKE_INTERNAL)) - goto bad; - - /* - * We must ComputeThis here to censor Call objects; performance hit, - * but at least it's idempotent. - * - * Normally, we call ComputeThis after all frame members have been - * set, and in particular, after any revision of the callee value at - * *vp due to clasp->convert (see below). This matters because - * ComputeThis may access *vp via fp->argv[-2], to follow the parent - * chain to a global object to use as the |this| parameter. - * - * Obviously, here in the JSVAL_IS_PRIMITIVE(v) case, there can't be - * any such defaulting of |this| to callee (v, *vp) ancestor. - */ - frame.argv = vp + 2; - ok = js_ComputeThis(cx, thisp, &frame); - if (!ok) - goto out2; - thisp = frame.thisp; - - id = ATOM_TO_JSID(cx->runtime->atomState.noSuchMethodAtom); - if (OBJECT_IS_XML(cx, thisp)) { - JSXMLObjectOps *ops; - - ops = (JSXMLObjectOps *) thisp->map->ops; - thisp = ops->getMethod(cx, thisp, id, &v); - if (!thisp) { - ok = JS_FALSE; - goto out2; - } - vp[1] = OBJECT_TO_JSVAL(thisp); - } else { - ok = OBJ_GET_PROPERTY(cx, thisp, id, &v); - } - if (!ok) - goto out2; - if (JSVAL_IS_PRIMITIVE(v)) - goto bad; - - pc = (jsbytecode *) vp[-(intN)fp->script->depth]; - switch ((JSOp) *pc) { - case JSOP_NAME: - case JSOP_GETPROP: -#if JS_HAS_XML_SUPPORT - case JSOP_GETMETHOD: -#endif - atomIndex = GET_ATOM_INDEX(pc); - atom = js_GetAtom(cx, &fp->script->atomMap, atomIndex); - argsobj = js_NewArrayObject(cx, argc, vp + 2); - if (!argsobj) { - ok = JS_FALSE; - goto out2; - } - - sp = vp + 4; - if (argc < 2) { - a = cx->stackPool.current; - if ((jsuword)sp > a->limit) { - /* - * Arguments must be contiguous, and must include argv[-1] - * and argv[-2], so allocate more stack, advance sp, and - * set newsp[1] to thisp (vp[1]). The other argv elements - * will be set below, using negative indexing from sp. - */ - newsp = js_AllocRawStack(cx, 4, NULL); - if (!newsp) { - ok = JS_FALSE; - goto out2; - } - newsp[1] = OBJECT_TO_JSVAL(thisp); - sp = newsp + 4; - } else if ((jsuword)sp > a->avail) { - /* - * Inline, optimized version of JS_ARENA_ALLOCATE to claim - * the small number of words not already allocated as part - * of the caller's operand stack. - */ - JS_ArenaCountAllocation(&cx->stackPool, - (jsuword)sp - a->avail); - a->avail = (jsuword)sp; - } - } - - sp[-4] = v; - JS_ASSERT(sp[-3] == OBJECT_TO_JSVAL(thisp)); - sp[-2] = ATOM_KEY(atom); - sp[-1] = OBJECT_TO_JSVAL(argsobj); - fp->sp = sp; - argc = 2; - break; - - default: - goto bad; - } -#else - goto bad; -#endif - } - - funobj = JSVAL_TO_OBJECT(v); - parent = OBJ_GET_PARENT(cx, funobj); - clasp = OBJ_GET_CLASS(cx, funobj); - if (clasp != &js_FunctionClass) { - /* Function is inlined, all other classes use object ops. */ - ops = funobj->map->ops; - - /* - * XXX this makes no sense -- why convert to function if clasp->call? - * XXX better to call that hook without converting - * XXX the only thing that needs fixing is liveconnect - * - * Try converting to function, for closure and API compatibility. - * We attempt the conversion under all circumstances for 1.2, but - * only if there is a call op defined otherwise. - */ - if (JS_VERSION_IS_1_2(cx) || - ((ops == &js_ObjectOps) ? clasp->call : ops->call)) { - ok = clasp->convert(cx, funobj, JSTYPE_FUNCTION, &v); - if (!ok) - goto out2; - - if (JSVAL_IS_FUNCTION(cx, v)) { - /* Make vp refer to funobj to keep it available as argv[-2]. */ - *vp = v; - funobj = JSVAL_TO_OBJECT(v); - parent = OBJ_GET_PARENT(cx, funobj); - goto have_fun; - } - } - fun = NULL; - script = NULL; - nslots = nvars = 0; - - /* Try a call or construct native object op. */ - native = (flags & JSINVOKE_CONSTRUCT) ? ops->construct : ops->call; - if (!native) - goto bad; - } else { -have_fun: - /* Get private data and set derived locals from it. */ - fun = (JSFunction *) JS_GetPrivate(cx, funobj); - if (fun->interpreted) { - native = NULL; - script = fun->u.script; - } else { - native = fun->u.native; - script = NULL; - } - nslots = (fun->nargs > argc) ? fun->nargs - argc : 0; - nslots += fun->extra; - nvars = fun->nvars; - - /* Handle bound method special case. */ - if (fun->flags & JSFUN_BOUND_METHOD) - thisp = parent; - } - - /* Initialize the rest of frame, except for sp (set by SAVE_SP later). */ - frame.varobj = NULL; - frame.callobj = frame.argsobj = NULL; - frame.script = script; - frame.fun = fun; - frame.argc = argc; - frame.argv = sp - argc; - frame.nvars = nvars; - frame.vars = sp; - frame.down = fp; - frame.annotation = NULL; - frame.scopeChain = NULL; /* set below for real, after cx->fp is set */ - frame.pc = NULL; - frame.spbase = NULL; - frame.sharpDepth = 0; - frame.sharpArray = NULL; - frame.dormantNext = NULL; - frame.xmlNamespace = NULL; - - /* Compute the 'this' parameter and store it in frame as frame.thisp. */ - ok = js_ComputeThis(cx, thisp, &frame); - if (!ok) - goto out2; - - /* From here on, control must flow through label out: to return. */ - cx->fp = &frame; - - /* Init these now in case we goto out before first hook call. */ - hook = cx->runtime->callHook; - hookData = NULL; - - /* Check for argument slots required by the function. */ - if (nslots) { - /* All arguments must be contiguous, so we may have to copy actuals. */ - nalloc = nslots; - limit = (jsval *) cx->stackPool.current->limit; - if (sp + nslots > limit) { - /* Hit end of arena: we have to copy argv[-2..(argc+nslots-1)]. */ - nalloc += 2 + argc; - } else { - /* Take advantage of surplus slots in the caller's frame depth. */ - JS_ASSERT((jsval *)mark >= sp); - surplus = (jsval *)mark - sp; - nalloc -= surplus; - } - - /* Check whether we have enough space in the caller's frame. */ - if ((intN)nalloc > 0) { - /* Need space for actuals plus missing formals minus surplus. */ - newsp = js_AllocRawStack(cx, nalloc, NULL); - if (!newsp) { - ok = JS_FALSE; - goto out; - } - - /* If we couldn't allocate contiguous args, copy actuals now. */ - if (newsp != mark) { - JS_ASSERT(sp + nslots > limit); - JS_ASSERT(2 + argc + nslots == nalloc); - *newsp++ = vp[0]; - *newsp++ = vp[1]; - if (argc) - memcpy(newsp, frame.argv, argc * sizeof(jsval)); - frame.argv = newsp; - sp = frame.vars = newsp + argc; - } - } - - /* Advance frame.vars to make room for the missing args. */ - frame.vars += nslots; - - /* Push void to initialize missing args. */ - do { - PUSH(JSVAL_VOID); - } while (--nslots != 0); - } - JS_ASSERT(nslots == 0); - - /* Now allocate stack space for local variables. */ - if (nvars) { - JS_ASSERT((jsval *)cx->stackPool.current->avail >= frame.vars); - surplus = (jsval *)cx->stackPool.current->avail - frame.vars; - if (surplus < nvars) { - newsp = js_AllocRawStack(cx, nvars, NULL); - if (!newsp) { - ok = JS_FALSE; - goto out; - } - if (newsp != sp) { - /* NB: Discontinuity between argv and vars. */ - sp = frame.vars = newsp; - } - } - - /* Push void to initialize local variables. */ - do { - PUSH(JSVAL_VOID); - } while (--nvars != 0); - } - JS_ASSERT(nvars == 0); - - /* Store the current sp in frame before calling fun. */ - SAVE_SP(&frame); - - /* call the hook if present */ - if (hook && (native || script)) - hookData = hook(cx, &frame, JS_TRUE, 0, cx->runtime->callHookData); - - /* Call the function, either a native method or an interpreted script. */ - if (native) { -#if JS_HAS_LVALUE_RETURN - /* Set by JS_SetCallReturnValue2, used to return reference types. */ - cx->rval2set = JS_FALSE; -#endif - - /* If native, use caller varobj and scopeChain for eval. */ - frame.varobj = fp->varobj; - frame.scopeChain = fp->scopeChain; - ok = native(cx, frame.thisp, argc, frame.argv, &frame.rval); - JS_RUNTIME_METER(cx->runtime, nativeCalls); - } else if (script) { -#ifdef DUMP_CALL_TABLE - LogCall(cx, *vp, argc, frame.argv); -#endif - /* Use parent scope so js_GetCallObject can find the right "Call". */ - frame.scopeChain = parent; - if (fun->flags & JSFUN_HEAVYWEIGHT) { -#if JS_HAS_CALL_OBJECT - /* Scope with a call object parented by the callee's parent. */ - if (!js_GetCallObject(cx, &frame, parent)) { - ok = JS_FALSE; - goto out; - } -#else - /* Bad old code used the function as a proxy for all calls to it. */ - frame.scopeChain = funobj; -#endif - } - ok = js_Interpret(cx, script->code, &v); - } else { - /* fun might be onerror trying to report a syntax error in itself. */ - frame.scopeChain = NULL; - ok = JS_TRUE; - } - -out: - if (hookData) { - hook = cx->runtime->callHook; - if (hook) - hook(cx, &frame, JS_FALSE, &ok, hookData); - } -#if JS_HAS_CALL_OBJECT - /* If frame has a call object, sync values and clear back-pointer. */ - if (frame.callobj) - ok &= js_PutCallObject(cx, &frame); -#endif -#if JS_HAS_ARGS_OBJECT - /* If frame has an arguments object, sync values and clear back-pointer. */ - if (frame.argsobj) - ok &= js_PutArgsObject(cx, &frame); -#endif - - /* Restore cx->fp now that we're done releasing frame objects. */ - cx->fp = fp; - -out2: - /* Pop everything we may have allocated off the stack. */ - JS_ARENA_RELEASE(&cx->stackPool, mark); - - /* Store the return value and restore sp just above it. */ - *vp = frame.rval; - fp->sp = vp + 1; - - /* - * Store the location of the JSOP_CALL or JSOP_EVAL that generated the - * return value, but only if this is an external (compiled from script - * source) call that has stack budget for the generating pc. - */ - if (fp->script && !(flags & JSINVOKE_INTERNAL)) - vp[-(intN)fp->script->depth] = (jsval)fp->pc; - return ok; - -bad: - js_ReportIsNotFunction(cx, vp, flags & JSINVOKE_CONSTRUCT); - ok = JS_FALSE; - goto out2; -} - -JSBool -js_InternalInvoke(JSContext *cx, JSObject *obj, jsval fval, uintN flags, - uintN argc, jsval *argv, jsval *rval) -{ - JSStackFrame *fp, *oldfp, frame; - jsval *oldsp, *sp; - void *mark; - uintN i; - JSBool ok; - - fp = oldfp = cx->fp; - if (!fp) { - memset(&frame, 0, sizeof frame); - cx->fp = fp = &frame; - } - oldsp = fp->sp; - sp = js_AllocStack(cx, 2 + argc, &mark); - if (!sp) { - ok = JS_FALSE; - goto out; - } - - PUSH(fval); - PUSH(OBJECT_TO_JSVAL(obj)); - for (i = 0; i < argc; i++) - PUSH(argv[i]); - SAVE_SP(fp); - ok = js_Invoke(cx, argc, flags | JSINVOKE_INTERNAL); - if (ok) { - RESTORE_SP(fp); - - /* - * Store *rval in the a scoped local root if a scope is open, else in - * the cx->lastInternalResult pigeon-hole GC root, solely so users of - * js_InternalInvoke and its direct and indirect (js_ValueToString for - * example) callers do not need to manage roots for local, temporary - * references to such results. - */ - *rval = POP_OPND(); - if (JSVAL_IS_GCTHING(*rval)) { - if (cx->localRootStack) { - if (js_PushLocalRoot(cx, cx->localRootStack, *rval) < 0) - ok = JS_FALSE; - } else { - cx->lastInternalResult = *rval; - } - } - } - - js_FreeStack(cx, mark); -out: - fp->sp = oldsp; - if (oldfp != fp) - cx->fp = oldfp; - - return ok; -} - -JSBool -js_InternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, jsval fval, - JSAccessMode mode, uintN argc, jsval *argv, jsval *rval) -{ - /* - * Check general (not object-ops/class-specific) access from the running - * script to obj.id only if id has a scripted getter or setter that we're - * about to invoke. If we don't check this case, nothing else will -- no - * other native code has the chance to check. - * - * Contrast this non-native (scripted) case with native getter and setter - * accesses, where the native itself must do an access check, if security - * policies requires it. We make a checkAccess or checkObjectAccess call - * back to the embedding program only in those cases where we're not going - * to call an embedding-defined native function, getter, setter, or class - * hook anyway. Where we do call such a native, there's no need for the - * engine to impose a separate access check callback on all embeddings -- - * many embeddings have no security policy at all. - */ - JS_ASSERT(mode == JSACC_READ || mode == JSACC_WRITE); - if (cx->runtime->checkObjectAccess && - JSVAL_IS_FUNCTION(cx, fval) && - ((JSFunction *)JS_GetPrivate(cx, JSVAL_TO_OBJECT(fval)))->interpreted && - !cx->runtime->checkObjectAccess(cx, obj, ID_TO_VALUE(id), mode, - &fval)) { - return JS_FALSE; - } - - return js_InternalCall(cx, obj, fval, argc, argv, rval); -} - -JSBool -js_Execute(JSContext *cx, JSObject *chain, JSScript *script, - JSStackFrame *down, uintN flags, jsval *result) -{ - JSInterpreterHook hook; - void *hookData, *mark; - JSStackFrame *oldfp, frame; - JSObject *obj, *tmp; - JSBool ok; - - hook = cx->runtime->executeHook; - hookData = mark = NULL; - oldfp = cx->fp; - frame.callobj = frame.argsobj = NULL; - frame.script = script; - if (down) { - /* Propagate arg/var state for eval and the debugger API. */ - frame.varobj = down->varobj; - frame.fun = down->fun; - frame.thisp = down->thisp; - frame.argc = down->argc; - frame.argv = down->argv; - frame.nvars = down->nvars; - frame.vars = down->vars; - frame.annotation = down->annotation; - frame.sharpArray = down->sharpArray; - } else { - obj = chain; - if (cx->options & JSOPTION_VAROBJFIX) { - while ((tmp = OBJ_GET_PARENT(cx, obj)) != NULL) - obj = tmp; - } - frame.varobj = obj; - frame.fun = NULL; - frame.thisp = chain; - frame.argc = 0; - frame.argv = NULL; - frame.nvars = script->numGlobalVars; - if (frame.nvars) { - frame.vars = js_AllocRawStack(cx, frame.nvars, &mark); - if (!frame.vars) - return JS_FALSE; - memset(frame.vars, 0, frame.nvars * sizeof(jsval)); - } else { - frame.vars = NULL; - } - frame.annotation = NULL; - frame.sharpArray = NULL; - } - frame.rval = JSVAL_VOID; - frame.down = down; - frame.scopeChain = chain; - frame.pc = NULL; - frame.sp = oldfp ? oldfp->sp : NULL; - frame.spbase = NULL; - frame.sharpDepth = 0; - frame.flags = flags; - frame.dormantNext = NULL; - frame.xmlNamespace = NULL; - - /* - * Here we wrap the call to js_Interpret with code to (conditionally) - * save and restore the old stack frame chain into a chain of 'dormant' - * frame chains. Since we are replacing cx->fp, we were running into - * the problem that if GC was called under this frame, some of the GC - * things associated with the old frame chain (available here only in - * the C variable 'oldfp') were not rooted and were being collected. - * - * So, now we preserve the links to these 'dormant' frame chains in cx - * before calling js_Interpret and cleanup afterwards. The GC walks - * these dormant chains and marks objects in the same way that it marks - * objects in the primary cx->fp chain. - */ - if (oldfp && oldfp != down) { - JS_ASSERT(!oldfp->dormantNext); - oldfp->dormantNext = cx->dormantFrameChain; - cx->dormantFrameChain = oldfp; - } - - cx->fp = &frame; - if (hook) - hookData = hook(cx, &frame, JS_TRUE, 0, cx->runtime->executeHookData); - - /* - * Use frame.rval, not result, so the last result stays rooted across any - * GC activations nested within this js_Interpret. - */ - ok = js_Interpret(cx, script->code, &frame.rval); - *result = frame.rval; - - if (hookData) { - hook = cx->runtime->executeHook; - if (hook) - hook(cx, &frame, JS_FALSE, &ok, hookData); - } - if (mark) - js_FreeRawStack(cx, mark); - cx->fp = oldfp; - - if (oldfp && oldfp != down) { - JS_ASSERT(cx->dormantFrameChain == oldfp); - cx->dormantFrameChain = oldfp->dormantNext; - oldfp->dormantNext = NULL; - } - - return ok; -} - -#if JS_HAS_EXPORT_IMPORT -/* - * If id is JSVAL_VOID, import all exported properties from obj. - */ -static JSBool -ImportProperty(JSContext *cx, JSObject *obj, jsid id) -{ - JSBool ok; - JSIdArray *ida; - JSProperty *prop; - JSObject *obj2, *target, *funobj, *closure; - JSString *str; - uintN attrs; - jsint i; - jsval value; - - if (JSVAL_IS_VOID(id)) { - ida = JS_Enumerate(cx, obj); - if (!ida) - return JS_FALSE; - ok = JS_TRUE; - if (ida->length == 0) - goto out; - } else { - ida = NULL; - if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop)) - return JS_FALSE; - if (!prop) { - str = js_DecompileValueGenerator(cx, JSDVG_IGNORE_STACK, - ID_TO_VALUE(id), NULL); - if (str) - js_ReportIsNotDefined(cx, JS_GetStringBytes(str)); - return JS_FALSE; - } - ok = OBJ_GET_ATTRIBUTES(cx, obj, id, prop, &attrs); - OBJ_DROP_PROPERTY(cx, obj2, prop); - if (!ok) - return JS_FALSE; - if (!(attrs & JSPROP_EXPORTED)) { - str = js_DecompileValueGenerator(cx, JSDVG_IGNORE_STACK, - ID_TO_VALUE(id), NULL); - if (str) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_NOT_EXPORTED, - JS_GetStringBytes(str)); - } - return JS_FALSE; - } - } - - target = cx->fp->varobj; - i = 0; - do { - if (ida) { - id = ida->vector[i]; - ok = OBJ_GET_ATTRIBUTES(cx, obj, id, NULL, &attrs); - if (!ok) - goto out; - if (!(attrs & JSPROP_EXPORTED)) - continue; - } - ok = OBJ_CHECK_ACCESS(cx, obj, id, JSACC_IMPORT, &value, &attrs); - if (!ok) - goto out; - if (JSVAL_IS_FUNCTION(cx, value)) { - funobj = JSVAL_TO_OBJECT(value); - closure = js_CloneFunctionObject(cx, funobj, obj); - if (!closure) { - ok = JS_FALSE; - goto out; - } - value = OBJECT_TO_JSVAL(closure); - } - - /* - * Handle the case of importing a property that refers to a local - * variable or formal parameter of a function activation. These - * properties are accessed by opcodes using stack slot numbers - * generated by the compiler rather than runtime name-lookup. These - * local references, therefore, bypass the normal scope chain lookup. - * So, instead of defining a new property in the activation object, - * modify the existing value in the stack slot. - */ - if (OBJ_GET_CLASS(cx, target) == &js_CallClass) { - ok = OBJ_LOOKUP_PROPERTY(cx, target, id, &obj2, &prop); - if (!ok) - goto out; - } else { - prop = NULL; - } - if (prop && target == obj2) { - ok = OBJ_SET_PROPERTY(cx, target, id, &value); - } else { - ok = OBJ_DEFINE_PROPERTY(cx, target, id, value, NULL, NULL, - attrs & ~(JSPROP_EXPORTED | - JSPROP_GETTER | - JSPROP_SETTER), - NULL); - } - if (prop) - OBJ_DROP_PROPERTY(cx, obj2, prop); - if (!ok) - goto out; - } while (ida && ++i < ida->length); - -out: - if (ida) - JS_DestroyIdArray(cx, ida); - return ok; -} -#endif /* JS_HAS_EXPORT_IMPORT */ - -JSBool -js_CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs, - JSObject **objp, JSProperty **propp) -{ - JSObject *obj2; - JSProperty *prop; - uintN oldAttrs, report; - JSBool isFunction; - jsval value; - const char *type, *name; - - if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop)) - return JS_FALSE; - if (propp) { - *objp = obj2; - *propp = prop; - } - if (!prop) - return JS_TRUE; - - /* From here, return true, or goto bad on failure to drop prop. */ - if (!OBJ_GET_ATTRIBUTES(cx, obj2, id, prop, &oldAttrs)) - goto bad; - - /* If either property is readonly, we have an error. */ - report = ((oldAttrs | attrs) & JSPROP_READONLY) - ? JSREPORT_ERROR - : JSREPORT_WARNING | JSREPORT_STRICT; - - if (report != JSREPORT_ERROR) { - /* - * Allow redeclaration of variables and functions, but insist that the - * new value is not a getter if the old value was, ditto for setters -- - * unless prop is impermanent (in which case anyone could delete it and - * redefine it, willy-nilly). - */ - if (!(attrs & (JSPROP_GETTER | JSPROP_SETTER))) - return JS_TRUE; - if ((~(oldAttrs ^ attrs) & (JSPROP_GETTER | JSPROP_SETTER)) == 0) - return JS_TRUE; - if (!(oldAttrs & JSPROP_PERMANENT)) - return JS_TRUE; - report = JSREPORT_ERROR; - } - - isFunction = (oldAttrs & (JSPROP_GETTER | JSPROP_SETTER)) != 0; - if (!isFunction) { - if (!OBJ_GET_PROPERTY(cx, obj, id, &value)) - goto bad; - isFunction = JSVAL_IS_FUNCTION(cx, value); - } - type = (oldAttrs & attrs & JSPROP_GETTER) - ? js_getter_str - : (oldAttrs & attrs & JSPROP_SETTER) - ? js_setter_str - : (oldAttrs & JSPROP_READONLY) - ? js_const_str - : isFunction - ? js_function_str - : js_var_str; - name = js_AtomToPrintableString(cx, JSID_TO_ATOM(id)); - if (!name) - goto bad; - return JS_ReportErrorFlagsAndNumber(cx, report, - js_GetErrorMessage, NULL, - JSMSG_REDECLARED_VAR, - type, name); - -bad: - if (propp) { - *objp = NULL; - *propp = NULL; - } - OBJ_DROP_PROPERTY(cx, obj2, prop); - return JS_FALSE; -} - -JSBool -js_StrictlyEqual(jsval lval, jsval rval) -{ - jsval ltag = JSVAL_TAG(lval), rtag = JSVAL_TAG(rval); - jsdouble ld, rd; - - if (ltag == rtag) { - if (ltag == JSVAL_STRING) { - JSString *lstr = JSVAL_TO_STRING(lval), - *rstr = JSVAL_TO_STRING(rval); - return js_CompareStrings(lstr, rstr) == 0; - } - if (ltag == JSVAL_DOUBLE) { - ld = *JSVAL_TO_DOUBLE(lval); - rd = *JSVAL_TO_DOUBLE(rval); - return JSDOUBLE_COMPARE(ld, ==, rd, JS_FALSE); - } - return lval == rval; - } - if (ltag == JSVAL_DOUBLE && JSVAL_IS_INT(rval)) { - ld = *JSVAL_TO_DOUBLE(lval); - rd = JSVAL_TO_INT(rval); - return JSDOUBLE_COMPARE(ld, ==, rd, JS_FALSE); - } - if (JSVAL_IS_INT(lval) && rtag == JSVAL_DOUBLE) { - ld = JSVAL_TO_INT(lval); - rd = *JSVAL_TO_DOUBLE(rval); - return JSDOUBLE_COMPARE(ld, ==, rd, JS_FALSE); - } - return lval == rval; -} - -static JSBool -InternStringElementId(JSContext *cx, jsval idval, jsid *idp) -{ - JSAtom *atom; - - atom = js_ValueToStringAtom(cx, idval); - if (!atom) - return JS_FALSE; - *idp = ATOM_TO_JSID(atom); - return JS_TRUE; -} - -static JSBool -InternNonIntElementId(JSContext *cx, jsval idval, jsid *idp) -{ - JS_ASSERT(!JSVAL_IS_INT(idval)); - -#if JS_HAS_XML_SUPPORT - if (JSVAL_IS_OBJECT(idval)) { - *idp = OBJECT_JSVAL_TO_JSID(idval); - return JS_TRUE; - } -#endif - - return InternStringElementId(cx, idval, idp); -} - -#if JS_HAS_XML_SUPPORT -#define CHECK_ELEMENT_ID(obj, id) \ - JS_BEGIN_MACRO \ - if (JSID_IS_OBJECT(id) && !OBJECT_IS_XML(cx, obj)) { \ - SAVE_SP(fp); \ - ok = InternStringElementId(cx, OBJECT_JSID_TO_JSVAL(id), &id); \ - if (!ok) \ - goto out; \ - } \ - JS_END_MACRO - -#else -#define CHECK_ELEMENT_ID(obj, id) JS_ASSERT(!JSID_IS_OBJECT(id)) -#endif - -#ifndef MAX_INTERP_LEVEL -#if defined(XP_OS2) -#define MAX_INTERP_LEVEL 250 -#else -#define MAX_INTERP_LEVEL 1000 -#endif -#endif - -#define MAX_INLINE_CALL_COUNT 1000 - -JSBool -js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result) -{ - JSRuntime *rt; - JSStackFrame *fp; - JSScript *script; - uintN inlineCallCount; - JSObject *obj, *obj2, *proto, *parent; - JSVersion currentVersion, originalVersion; - JSBranchCallback onbranch; - JSBool ok, cond; - JSTrapHandler interruptHandler; - jsint depth, len; - jsval *sp, *newsp; - void *mark; - jsbytecode *endpc, *pc2; - JSOp op, op2; - const JSCodeSpec *cs; - jsatomid atomIndex; - JSAtom *atom; - uintN argc, slot, attrs; - jsval *vp, lval, rval, ltmp, rtmp; - jsid id; - JSObject *withobj, *origobj, *propobj; - jsval iter_state; - JSProperty *prop; - JSScopeProperty *sprop; - JSString *str, *str2; - jsint i, j; - jsdouble d, d2; - JSClass *clasp, *funclasp; - JSFunction *fun; - JSType type; -#ifdef DEBUG - FILE *tracefp; -#endif -#if JS_HAS_EXPORT_IMPORT - JSIdArray *ida; -#endif -#if JS_HAS_SWITCH_STATEMENT - jsint low, high, off, npairs; - JSBool match; -#endif -#if JS_HAS_GETTER_SETTER - JSPropertyOp getter, setter; -#endif -#if JS_HAS_XML_SUPPORT - JSBool foreach = JS_FALSE; -#endif - int stackDummy; - - *result = JSVAL_VOID; - rt = cx->runtime; - - /* Set registerized frame pointer and derived script pointer. */ - fp = cx->fp; - script = fp->script; - - /* Count of JS function calls that nest in this C js_Interpret frame. */ - inlineCallCount = 0; - - /* - * Optimized Get and SetVersion for proper script language versioning. - * - * If any native method or JSClass/JSObjectOps hook calls js_SetVersion - * and changes cx->version, the effect will "stick" and we will stop - * maintaining currentVersion. This is relied upon by testsuites, for - * the most part -- web browsers select version before compiling and not - * at run-time. - */ - currentVersion = script->version; - originalVersion = cx->version; - if (currentVersion != originalVersion) - js_SetVersion(cx, currentVersion); - - /* - * Prepare to call a user-supplied branch handler, and abort the script - * if it returns false. We reload onbranch after calling out to native - * functions (but not to getters, setters, or other native hooks). - */ -#define LOAD_BRANCH_CALLBACK(cx) (onbranch = (cx)->branchCallback) - - LOAD_BRANCH_CALLBACK(cx); - ok = JS_TRUE; -#define CHECK_BRANCH(len) \ - JS_BEGIN_MACRO \ - if (len <= 0 && onbranch) { \ - SAVE_SP(fp); \ - if (!(ok = (*onbranch)(cx, script))) \ - goto out; \ - } \ - JS_END_MACRO - - /* - * Load the debugger's interrupt hook here and after calling out to native - * functions (but not to getters, setters, or other native hooks), so we do - * not have to reload it each time through the interpreter loop -- we hope - * the compiler can keep it in a register. - * XXX if it spills, we still lose - */ -#define LOAD_INTERRUPT_HANDLER(rt) (interruptHandler = (rt)->interruptHandler) - - LOAD_INTERRUPT_HANDLER(rt); - - /* Check for too much js_Interpret nesting, or too deep a C stack. */ - if (++cx->interpLevel == MAX_INTERP_LEVEL || - !JS_CHECK_STACK_SIZE(cx, stackDummy)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_OVER_RECURSED); - ok = JS_FALSE; - goto out2; - } - - /* - * Allocate operand and pc stack slots for the script's worst-case depth, - * unless we're called to interpret a part of an already active script, a - * filtering predicate expression for example. - */ - depth = (jsint) script->depth; - if (JS_LIKELY(!fp->spbase)) { - newsp = js_AllocRawStack(cx, (uintN)(2 * depth), &mark); - if (!newsp) { - ok = JS_FALSE; - goto out2; - } - sp = newsp + depth; - fp->spbase = sp; - SAVE_SP(fp); - } else { - sp = fp->sp; - JS_ASSERT(JS_UPTRDIFF(sp, fp->spbase) <= depth * sizeof(jsval)); - newsp = fp->spbase - depth; - mark = NULL; - } - - endpc = script->code + script->length; - while (pc < endpc) { - fp->pc = pc; - op = (JSOp) *pc; - do_op: - cs = &js_CodeSpec[op]; - len = cs->length; - -#ifdef DEBUG - tracefp = (FILE *) cx->tracefp; - if (tracefp) { - intN nuses, n; - - fprintf(tracefp, "%4u: ", js_PCToLineNumber(cx, script, pc)); - js_Disassemble1(cx, script, pc, - PTRDIFF(pc, script->code, jsbytecode), JS_FALSE, - tracefp); - nuses = cs->nuses; - if (nuses) { - SAVE_SP(fp); - for (n = -nuses; n < 0; n++) { - str = js_DecompileValueGenerator(cx, n, sp[n], NULL); - if (str) { - fprintf(tracefp, "%s %s", - (n == -nuses) ? " inputs:" : ",", - JS_GetStringBytes(str)); - } - } - fprintf(tracefp, " @ %d\n", sp - fp->spbase); - } - } -#endif - - if (interruptHandler) { - SAVE_SP(fp); - switch (interruptHandler(cx, script, pc, &rval, - rt->interruptHandlerData)) { - case JSTRAP_ERROR: - ok = JS_FALSE; - goto out; - case JSTRAP_CONTINUE: - break; - case JSTRAP_RETURN: - fp->rval = rval; - goto out; -#if JS_HAS_EXCEPTIONS - case JSTRAP_THROW: - cx->throwing = JS_TRUE; - cx->exception = rval; - ok = JS_FALSE; - goto out; -#endif /* JS_HAS_EXCEPTIONS */ - default:; - } - LOAD_INTERRUPT_HANDLER(rt); - } - - switch (op) { - case JSOP_NOP: - break; - - case JSOP_GROUP: - break; - - case JSOP_PUSH: - PUSH_OPND(JSVAL_VOID); - break; - - case JSOP_POP: - sp--; - break; - - case JSOP_POP2: - sp -= 2; - break; - - case JSOP_SWAP: - /* - * N.B. JSOP_SWAP doesn't swap the corresponding generating pcs - * for the operands it swaps. - */ - ltmp = sp[-1]; - sp[-1] = sp[-2]; - sp[-2] = ltmp; - break; - - case JSOP_POPV: - *result = POP_OPND(); - break; - - case JSOP_ENTERWITH: - FETCH_OBJECT(cx, -1, rval, obj); - SAVE_SP(fp); - withobj = js_NewWithObject(cx, obj, fp->scopeChain, - sp - fp->spbase - 1); - if (!withobj) - goto out; - rval = INT_TO_JSVAL(sp - fp->spbase); - fp->scopeChain = withobj; - STORE_OPND(-1, OBJECT_TO_JSVAL(withobj)); - break; - - case JSOP_LEAVEWITH: - rval = POP_OPND(); - JS_ASSERT(JSVAL_IS_OBJECT(rval)); - withobj = JSVAL_TO_OBJECT(rval); - JS_ASSERT(OBJ_GET_CLASS(cx, withobj) == &js_WithClass); - - rval = OBJ_GET_SLOT(cx, withobj, JSSLOT_PARENT); - JS_ASSERT(JSVAL_IS_OBJECT(rval)); - fp->scopeChain = JSVAL_TO_OBJECT(rval); - JS_SetPrivate(cx, withobj, NULL); - break; - - case JSOP_SETRVAL: - fp->rval = POP_OPND(); - break; - - case JSOP_RETURN: - CHECK_BRANCH(-1); - fp->rval = POP_OPND(); - /* FALL THROUGH */ - - case JSOP_RETRVAL: /* fp->rval already set */ - if (inlineCallCount) - inline_return: - { - JSInlineFrame *ifp = (JSInlineFrame *) fp; - void *hookData = ifp->hookData; - - if (hookData) { - JSInterpreterHook hook = cx->runtime->callHook; - if (hook) { - hook(cx, fp, JS_FALSE, &ok, hookData); - LOAD_INTERRUPT_HANDLER(rt); - } - } - -#if JS_HAS_CALL_OBJECT - /* - * If frame has a call object, sync values and clear the back- - * pointer. This can happen for a lightweight function if it - * calls eval unexpectedly (in a way that is hidden from the - * compiler). See bug 325540. - */ - if (fp->callobj) - ok &= js_PutCallObject(cx, fp); -#endif -#if JS_HAS_ARGS_OBJECT - if (fp->argsobj) - ok &= js_PutArgsObject(cx, fp); -#endif - - /* Restore context version only if callee hasn't set version. */ - if (cx->version == currentVersion) { - currentVersion = ifp->callerVersion; - if (currentVersion != cx->version) - js_SetVersion(cx, currentVersion); - } - - /* Store the return value in the caller's operand frame. */ - vp = fp->argv - 2; - *vp = fp->rval; - - /* Restore cx->fp and release the inline frame's space. */ - cx->fp = fp = fp->down; - JS_ARENA_RELEASE(&cx->stackPool, ifp->mark); - - /* Restore sp to point just above the return value. */ - fp->sp = vp + 1; - RESTORE_SP(fp); - - /* Restore the calling script's interpreter registers. */ - script = fp->script; - depth = (jsint) script->depth; - pc = fp->pc; - endpc = script->code + script->length; - - /* Store the generating pc for the return value. */ - vp[-depth] = (jsval)pc; - - /* Set remaining variables for 'goto advance_pc'. */ - op = (JSOp) *pc; - cs = &js_CodeSpec[op]; - len = cs->length; - - /* Resume execution in the calling frame. */ - inlineCallCount--; - if (ok) - goto advance_pc; - } - goto out; - -#if JS_HAS_SWITCH_STATEMENT - case JSOP_DEFAULT: - (void) POP(); - /* FALL THROUGH */ -#endif - case JSOP_GOTO: - len = GET_JUMP_OFFSET(pc); - CHECK_BRANCH(len); - break; - - case JSOP_IFEQ: - POP_BOOLEAN(cx, rval, cond); - if (cond == JS_FALSE) { - len = GET_JUMP_OFFSET(pc); - CHECK_BRANCH(len); - } - break; - - case JSOP_IFNE: - POP_BOOLEAN(cx, rval, cond); - if (cond != JS_FALSE) { - len = GET_JUMP_OFFSET(pc); - CHECK_BRANCH(len); - } - break; - - case JSOP_OR: - POP_BOOLEAN(cx, rval, cond); - if (cond == JS_TRUE) { - len = GET_JUMP_OFFSET(pc); - PUSH_OPND(rval); - } - break; - - case JSOP_AND: - POP_BOOLEAN(cx, rval, cond); - if (cond == JS_FALSE) { - len = GET_JUMP_OFFSET(pc); - PUSH_OPND(rval); - } - break; - - -#if JS_HAS_SWITCH_STATEMENT - case JSOP_DEFAULTX: - (void) POP(); - /* FALL THROUGH */ -#endif - case JSOP_GOTOX: - len = GET_JUMPX_OFFSET(pc); - CHECK_BRANCH(len); - break; - - case JSOP_IFEQX: - POP_BOOLEAN(cx, rval, cond); - if (cond == JS_FALSE) { - len = GET_JUMPX_OFFSET(pc); - CHECK_BRANCH(len); - } - break; - - case JSOP_IFNEX: - POP_BOOLEAN(cx, rval, cond); - if (cond != JS_FALSE) { - len = GET_JUMPX_OFFSET(pc); - CHECK_BRANCH(len); - } - break; - - case JSOP_ORX: - POP_BOOLEAN(cx, rval, cond); - if (cond == JS_TRUE) { - len = GET_JUMPX_OFFSET(pc); - PUSH_OPND(rval); - } - break; - - case JSOP_ANDX: - POP_BOOLEAN(cx, rval, cond); - if (cond == JS_FALSE) { - len = GET_JUMPX_OFFSET(pc); - PUSH_OPND(rval); - } - break; - - case JSOP_TOOBJECT: - rval = FETCH_OPND(-1); - if (!JSVAL_IS_PRIMITIVE(rval)) { - obj = JSVAL_TO_OBJECT(rval); - } else { - SAVE_SP(fp); - ok = js_ValueToObject(cx, rval, &obj); - if (!ok) - goto out; - } - STORE_OPND(-1, OBJECT_TO_JSVAL(obj)); - break; - -/* - * If the index value at sp[n] is not an int that fits in a jsval, it could - * be an object (an XML QName, AttributeName, or AnyName), but only if we are - * compiling with JS_HAS_XML_SUPPORT. Otherwise convert the index value to a - * string atom id. - */ -#define FETCH_ELEMENT_ID(n, id) \ - JS_BEGIN_MACRO \ - jsval idval_ = FETCH_OPND(n); \ - if (JSVAL_IS_INT(idval_)) { \ - id = INT_JSVAL_TO_JSID(idval_); \ - } else { \ - SAVE_SP(fp); \ - ok = InternNonIntElementId(cx, idval_, &id); \ - if (!ok) \ - goto out; \ - } \ - JS_END_MACRO - -#if JS_HAS_IN_OPERATOR - case JSOP_IN: - SAVE_SP(fp); - rval = FETCH_OPND(-1); - if (JSVAL_IS_PRIMITIVE(rval)) { - str = js_DecompileValueGenerator(cx, -1, rval, NULL); - if (str) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_IN_NOT_OBJECT, - JS_GetStringBytes(str)); - } - ok = JS_FALSE; - goto out; - } - obj = JSVAL_TO_OBJECT(rval); - FETCH_ELEMENT_ID(-2, id); - CHECK_ELEMENT_ID(obj, id); - ok = OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop); - if (!ok) - goto out; - sp--; - STORE_OPND(-1, BOOLEAN_TO_JSVAL(prop != NULL)); - if (prop) - OBJ_DROP_PROPERTY(cx, obj2, prop); - break; -#endif /* JS_HAS_IN_OPERATOR */ - - case JSOP_FORPROP: - /* - * Handle JSOP_FORPROP first, so the cost of the goto do_forinloop - * is not paid for the more common cases. - */ - lval = FETCH_OPND(-1); - atom = GET_ATOM(cx, script, pc); - id = ATOM_TO_JSID(atom); - i = -2; - goto do_forinloop; - - case JSOP_FORNAME: - atom = GET_ATOM(cx, script, pc); - id = ATOM_TO_JSID(atom); - - /* - * ECMA 12.6.3 says to eval the LHS after looking for properties - * to enumerate, and bail without LHS eval if there are no props. - * We do Find here to share the most code at label do_forinloop. - * If looking for enumerable properties could have side effects, - * then we'd have to move this into the common code and condition - * it on op == JSOP_FORNAME. - */ - SAVE_SP(fp); - ok = js_FindProperty(cx, id, &obj, &obj2, &prop); - if (!ok) - goto out; - if (prop) - OBJ_DROP_PROPERTY(cx, obj2, prop); - lval = OBJECT_TO_JSVAL(obj); - /* FALL THROUGH */ - - case JSOP_FORARG: - case JSOP_FORVAR: - /* - * JSOP_FORARG and JSOP_FORVAR don't require any lval computation - * here, because they address slots on the stack (in fp->args and - * fp->vars, respectively). - */ - /* FALL THROUGH */ - - case JSOP_FORELEM: - /* - * JSOP_FORELEM simply initializes or updates the iteration state - * and leaves the index expression evaluation and assignment to the - * enumerator until after the next property has been acquired, via - * a JSOP_ENUMELEM bytecode. - */ - i = -1; - - do_forinloop: - /* - * ECMA-compatible for/in evals the object just once, before loop. - * Bad old bytecodes (since removed) did it on every iteration. - */ - obj = JSVAL_TO_OBJECT(sp[i]); - - /* If the thing to the right of 'in' has no properties, break. */ - if (!obj) { - rval = JSVAL_FALSE; - goto end_forinloop; - } - - /* - * Save the thing to the right of 'in' as origobj. Later on, we - * use this variable to suppress enumeration of shadowed prototype - * properties. - */ - origobj = obj; - - /* - * Reach under the top of stack to find our property iterator, a - * JSObject that contains the iteration state. (An object is used - * rather than a native struct so that the iteration state is - * cleaned up via GC if the for-in loop terminates abruptly.) - */ - vp = &sp[i - 1]; - rval = *vp; - - /* - * Save sp in fp now, before any OBJ_* call-outs that might nest - * an interpreter or GC activation on this context. - */ - SAVE_SP(fp); - - /* Is this the first iteration ? */ - if (JSVAL_IS_VOID(rval)) { - /* - * Yes, create a new JSObject to hold the iterator state. - * Use NULL as the nominal parent in js_NewObject to ensure - * that we use the correct scope chain lookup to try to find the - * PropertyIterator constructor. - */ - propobj = js_NewObject(cx, &prop_iterator_class, NULL, NULL); - if (!propobj) { - ok = JS_FALSE; - goto out; - } - - /* - * Now that we've resolved the object, use the PARENT slot to - * store the object that we're iterating over. - */ - propobj->slots[JSSLOT_PARENT] = OBJECT_TO_JSVAL(obj); - propobj->slots[JSSLOT_ITER_STATE] = JSVAL_NULL; - - /* - * Root the parent slot so we can get it even in our finalizer - * (otherwise, it would live as long as we do, but it might be - * finalized first). - */ - ok = js_AddRoot(cx, &propobj->slots[JSSLOT_PARENT], - "propobj->parent"); - if (!ok) - goto out; - - /* - * Rewrite the iterator so we know to do the next case. - * Do this before calling the enumerator, which could - * displace cx->newborn and cause GC. - */ - *vp = OBJECT_TO_JSVAL(propobj); - - ok = -#if JS_HAS_XML_SUPPORT - (foreach && OBJECT_IS_XML(cx, obj)) - ? ((JSXMLObjectOps *) obj->map->ops)->enumerateValues - (cx, obj, JSENUMERATE_INIT, &iter_state, - NULL, NULL) - : -#endif - OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &iter_state, - NULL); - if (!ok) - goto out; - - /* - * Stash private iteration state into property iterator object. - * NB: This code knows that the first slots are pre-allocated. - */ -#if JS_INITIAL_NSLOTS < 5 -#error JS_INITIAL_NSLOTS must be greater than or equal to 5. -#endif - propobj->slots[JSSLOT_ITER_STATE] = iter_state; - } else { - /* This is not the first iteration. Recover iterator state. */ - propobj = JSVAL_TO_OBJECT(rval); - JS_ASSERT(OBJ_GET_CLASS(cx, propobj) == &prop_iterator_class); - obj = JSVAL_TO_OBJECT(propobj->slots[JSSLOT_PARENT]); - iter_state = propobj->slots[JSSLOT_ITER_STATE]; - } - - enum_next_property: - { - jsid fid; - - /* Get the next jsid to be enumerated and store it in fid. */ - ok = -#if JS_HAS_XML_SUPPORT - (foreach && OBJECT_IS_XML(cx, obj)) - ? ((JSXMLObjectOps *) obj->map->ops)->enumerateValues - (cx, obj, JSENUMERATE_NEXT, &iter_state, - &fid, &rval) - : -#endif - OBJ_ENUMERATE(cx, obj, JSENUMERATE_NEXT, &iter_state, &fid); - propobj->slots[JSSLOT_ITER_STATE] = iter_state; - - /* No more jsids to iterate in obj? */ - if (iter_state == JSVAL_NULL) { - /* Enumerate the properties on obj's prototype chain. */ - obj = OBJ_GET_PROTO(cx, obj); - if (!obj) { - /* End of property list -- terminate loop. */ - rval = JSVAL_FALSE; -#if JS_HAS_XML_SUPPORT - foreach = JS_FALSE; -#endif - goto end_forinloop; - } - - ok = -#if JS_HAS_XML_SUPPORT - (foreach && OBJECT_IS_XML(cx, obj)) - ? ((JSXMLObjectOps *) obj->map->ops)->enumerateValues - (cx, obj, JSENUMERATE_INIT, &iter_state, - NULL, NULL) - : -#endif - OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &iter_state, - NULL); - - /* - * Stash private iteration state into property iterator object. - * We do this before checking 'ok' to ensure that propobj is - * in a valid state even if OBJ_ENUMERATE returned JS_FALSE. - * NB: This code knows that the first slots are pre-allocated. - */ - propobj->slots[JSSLOT_ITER_STATE] = iter_state; - if (!ok) - goto out; - - /* - * Update the iterator JSObject's parent link to refer to the - * current object. This is used in the iterator JSObject's - * finalizer. - */ - propobj->slots[JSSLOT_PARENT] = OBJECT_TO_JSVAL(obj); - goto enum_next_property; - } - - /* Skip properties not owned by obj when looking from origobj. */ - ok = OBJ_LOOKUP_PROPERTY(cx, origobj, fid, &obj2, &prop); - if (!ok) - goto out; - if (prop) - OBJ_DROP_PROPERTY(cx, obj2, prop); - - /* - * If the id was deleted, or found in a prototype or an unrelated - * object (specifically, not in an inner object for obj), skip it. - * This means that OBJ_LOOKUP_PROPERTY implementations must return - * an object either further on the prototype chain, or related by - * the JSExtendedClass.outerObject optional hook. - */ - if (!prop) - goto enum_next_property; - if (obj != obj2) { - cond = JS_FALSE; - clasp = OBJ_GET_CLASS(cx, obj2); - if (clasp->flags & JSCLASS_IS_EXTENDED) { - JSExtendedClass *xclasp; - - xclasp = (JSExtendedClass *) clasp; - cond = xclasp->outerObject && - xclasp->outerObject(cx, obj2) == obj; - } - if (!cond) - goto enum_next_property; - } - -#if JS_HAS_XML_SUPPORT - if (foreach) { - /* Clear the local foreach flag set by our prefix bytecode. */ - foreach = JS_FALSE; - - /* If obj is not XML, we must get rval given its fid. */ - if (!OBJECT_IS_XML(cx, obj)) { - ok = OBJ_GET_PROPERTY(cx, origobj, fid, &rval); - if (!ok) - goto out; - } - } else -#endif - { - /* Make rval a string for uniformity and compatibility. */ - if (JSID_IS_ATOM(fid)) { - rval = ATOM_KEY(JSID_TO_ATOM(fid)); - } -#if JS_HAS_XML_SUPPORT - else if (JSID_IS_OBJECT(fid)) { - str = js_ValueToString(cx, OBJECT_JSID_TO_JSVAL(fid)); - if (!str) { - ok = JS_FALSE; - goto out; - } - - rval = STRING_TO_JSVAL(str); - } -#endif - else if (!JS_VERSION_IS_1_2(cx)) { - str = js_NumberToString(cx, (jsdouble) JSID_TO_INT(fid)); - if (!str) { - ok = JS_FALSE; - goto out; - } - - rval = STRING_TO_JSVAL(str); - } else { - rval = INT_JSID_TO_JSVAL(fid); - } - } - - switch (op) { - case JSOP_FORARG: - slot = GET_ARGNO(pc); - JS_ASSERT(slot < fp->fun->nargs); - fp->argv[slot] = rval; - break; - - case JSOP_FORVAR: - slot = GET_VARNO(pc); - JS_ASSERT(slot < fp->fun->nvars); - fp->vars[slot] = rval; - break; - - case JSOP_FORELEM: - /* FORELEM is not a SET operation, it's more like BINDNAME. */ - PUSH_OPND(rval); - break; - - default: - /* Convert lval to a non-null object containing id. */ - VALUE_TO_OBJECT(cx, lval, obj); - if (i + 1 < 0) - STORE_OPND(i + 1, OBJECT_TO_JSVAL(obj)); - - /* Set the variable obj[id] to refer to rval. */ - fp->flags |= JSFRAME_ASSIGNING; - ok = OBJ_SET_PROPERTY(cx, obj, id, &rval); - fp->flags &= ~JSFRAME_ASSIGNING; - if (!ok) - goto out; - break; - } - - /* Push true to keep looping through properties. */ - rval = JSVAL_TRUE; - - end_forinloop: - sp += i + 1; - PUSH_OPND(rval); - break; - } - - case JSOP_DUP: - JS_ASSERT(sp > fp->spbase); - rval = sp[-1]; - PUSH_OPND(rval); - break; - - case JSOP_DUP2: - JS_ASSERT(sp - 1 > fp->spbase); - lval = FETCH_OPND(-2); - rval = FETCH_OPND(-1); - PUSH_OPND(lval); - PUSH_OPND(rval); - break; - -#define PROPERTY_OP(n, call) \ - JS_BEGIN_MACRO \ - /* Fetch the left part and resolve it to a non-null object. */ \ - FETCH_OBJECT(cx, n, lval, obj); \ - \ - /* Get or set the property, set ok false if error, true if success. */\ - SAVE_SP(fp); \ - call; \ - if (!ok) \ - goto out; \ - JS_END_MACRO - -#define ELEMENT_OP(n, call) \ - JS_BEGIN_MACRO \ - /* Fetch the right part and resolve it to an internal id. */ \ - FETCH_ELEMENT_ID(n, id); \ - \ - /* Fetch the left part and resolve it to a non-null object. */ \ - FETCH_OBJECT(cx, n - 1, lval, obj); \ - \ - /* Ensure that id has a type suitable for use with obj. */ \ - CHECK_ELEMENT_ID(obj, id); \ - \ - /* Get or set the element, set ok false if error, true if success. */ \ - SAVE_SP(fp); \ - call; \ - if (!ok) \ - goto out; \ - JS_END_MACRO - -/* - * Direct callers, i.e. those who do not wrap CACHED_GET and CACHED_SET calls - * in PROPERTY_OP or ELEMENT_OP macro calls must SAVE_SP(fp); beforehand, just - * in case a getter or setter function is invoked. CACHED_GET and CACHED_SET - * use cx, obj, id, and rval from their caller's lexical environment. - */ -#define CACHED_GET(call) CACHED_GET_VP(call, &rval) - -#define CACHED_GET_VP(call,vp) \ - JS_BEGIN_MACRO \ - if (!OBJ_IS_NATIVE(obj)) { \ - ok = call; \ - } else { \ - JS_LOCK_OBJ(cx, obj); \ - PROPERTY_CACHE_TEST(&rt->propertyCache, obj, id, sprop); \ - if (sprop) { \ - JSScope *scope_ = OBJ_SCOPE(obj); \ - slot = (uintN)sprop->slot; \ - *(vp) = (slot != SPROP_INVALID_SLOT) \ - ? LOCKED_OBJ_GET_SLOT(obj, slot) \ - : JSVAL_VOID; \ - JS_UNLOCK_SCOPE(cx, scope_); \ - ok = SPROP_GET(cx, sprop, obj, obj, vp); \ - JS_LOCK_SCOPE(cx, scope_); \ - if (ok && SPROP_HAS_VALID_SLOT(sprop, scope_)) \ - LOCKED_OBJ_SET_SLOT(obj, slot, *(vp)); \ - JS_UNLOCK_SCOPE(cx, scope_); \ - } else { \ - JS_UNLOCK_OBJ(cx, obj); \ - ok = call; \ - /* No fill here: js_GetProperty fills the cache. */ \ - } \ - } \ - JS_END_MACRO - -#define CACHED_SET(call) \ - JS_BEGIN_MACRO \ - if (!OBJ_IS_NATIVE(obj)) { \ - ok = call; \ - } else { \ - JSScope *scope_; \ - JS_LOCK_OBJ(cx, obj); \ - PROPERTY_CACHE_TEST(&rt->propertyCache, obj, id, sprop); \ - if (sprop && \ - !(sprop->attrs & JSPROP_READONLY) && \ - (scope_ = OBJ_SCOPE(obj), !SCOPE_IS_SEALED(scope_))) { \ - JS_UNLOCK_SCOPE(cx, scope_); \ - ok = SPROP_SET(cx, sprop, obj, obj, &rval); \ - JS_LOCK_SCOPE(cx, scope_); \ - if (ok && SPROP_HAS_VALID_SLOT(sprop, scope_)) { \ - LOCKED_OBJ_SET_SLOT(obj, sprop->slot, rval); \ - GC_POKE(cx, JSVAL_NULL); /* XXX second arg ignored */ \ - } \ - JS_UNLOCK_SCOPE(cx, scope_); \ - } else { \ - JS_UNLOCK_OBJ(cx, obj); \ - ok = call; \ - /* No fill here: js_SetProperty writes through the cache. */ \ - } \ - } \ - JS_END_MACRO - -#define BEGIN_LITOPX_CASE(OP,PCOFF) \ - case OP: \ - atomIndex = GET_ATOM_INDEX(pc + PCOFF); \ - do_##OP: \ - atom = js_GetAtom(cx, &script->atomMap, atomIndex); - -#define END_LITOPX_CASE \ - break; \ - - BEGIN_LITOPX_CASE(JSOP_SETCONST, 0) - obj = fp->varobj; - rval = FETCH_OPND(-1); - SAVE_SP(fp); - ok = OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), rval, - NULL, NULL, - JSPROP_ENUMERATE | JSPROP_PERMANENT | - JSPROP_READONLY, - NULL); - if (!ok) - goto out; - STORE_OPND(-1, rval); - END_LITOPX_CASE - - BEGIN_LITOPX_CASE(JSOP_BINDNAME, 0) - SAVE_SP(fp); - obj = js_FindIdentifierBase(cx, ATOM_TO_JSID(atom)); - if (!obj) { - ok = JS_FALSE; - goto out; - } - PUSH_OPND(OBJECT_TO_JSVAL(obj)); - END_LITOPX_CASE - - case JSOP_SETNAME: - atom = GET_ATOM(cx, script, pc); - id = ATOM_TO_JSID(atom); - rval = FETCH_OPND(-1); - lval = FETCH_OPND(-2); - JS_ASSERT(!JSVAL_IS_PRIMITIVE(lval)); - obj = JSVAL_TO_OBJECT(lval); - SAVE_SP(fp); - CACHED_SET(OBJ_SET_PROPERTY(cx, obj, id, &rval)); - if (!ok) - goto out; - sp--; - STORE_OPND(-1, rval); - obj = NULL; - break; - -#define INTEGER_OP(OP, EXTRA_CODE) \ - JS_BEGIN_MACRO \ - FETCH_INT(cx, -1, j); \ - FETCH_INT(cx, -2, i); \ - if (!ok) \ - goto out; \ - EXTRA_CODE \ - d = i OP j; \ - sp--; \ - STORE_NUMBER(cx, -1, d); \ - JS_END_MACRO - -#define BITWISE_OP(OP) INTEGER_OP(OP, (void) 0;) -#define SIGNED_SHIFT_OP(OP) INTEGER_OP(OP, j &= 31;) - - case JSOP_BITOR: - BITWISE_OP(|); - break; - - case JSOP_BITXOR: - BITWISE_OP(^); - break; - - case JSOP_BITAND: - BITWISE_OP(&); - break; - -#define RELATIONAL_OP(OP) \ - JS_BEGIN_MACRO \ - rval = FETCH_OPND(-1); \ - lval = FETCH_OPND(-2); \ - /* Optimize for two int-tagged operands (typical loop control). */ \ - if ((lval & rval) & JSVAL_INT) { \ - ltmp = lval ^ JSVAL_VOID; \ - rtmp = rval ^ JSVAL_VOID; \ - if (ltmp && rtmp) { \ - cond = JSVAL_TO_INT(lval) OP JSVAL_TO_INT(rval); \ - } else { \ - d = ltmp ? JSVAL_TO_INT(lval) : *rt->jsNaN; \ - d2 = rtmp ? JSVAL_TO_INT(rval) : *rt->jsNaN; \ - cond = JSDOUBLE_COMPARE(d, OP, d2, JS_FALSE); \ - } \ - } else { \ - VALUE_TO_PRIMITIVE(cx, lval, JSTYPE_NUMBER, &lval); \ - sp[-2] = lval; \ - VALUE_TO_PRIMITIVE(cx, rval, JSTYPE_NUMBER, &rval); \ - if (JSVAL_IS_STRING(lval) && JSVAL_IS_STRING(rval)) { \ - str = JSVAL_TO_STRING(lval); \ - str2 = JSVAL_TO_STRING(rval); \ - cond = js_CompareStrings(str, str2) OP 0; \ - } else { \ - VALUE_TO_NUMBER(cx, lval, d); \ - VALUE_TO_NUMBER(cx, rval, d2); \ - cond = JSDOUBLE_COMPARE(d, OP, d2, JS_FALSE); \ - } \ - } \ - sp--; \ - STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond)); \ - JS_END_MACRO - -/* - * NB: These macros can't use JS_BEGIN_MACRO/JS_END_MACRO around their bodies - * because they begin if/else chains, so callers must not put semicolons after - * the call expressions! - */ -#if JS_HAS_XML_SUPPORT -#define XML_EQUALITY_OP(OP) \ - if ((ltmp == JSVAL_OBJECT && \ - (obj2 = JSVAL_TO_OBJECT(lval)) && \ - OBJECT_IS_XML(cx, obj2)) || \ - (rtmp == JSVAL_OBJECT && \ - (obj2 = JSVAL_TO_OBJECT(rval)) && \ - OBJECT_IS_XML(cx, obj2))) { \ - JSXMLObjectOps *ops; \ - \ - ops = (JSXMLObjectOps *) obj2->map->ops; \ - if (obj2 == JSVAL_TO_OBJECT(rval)) \ - rval = lval; \ - SAVE_SP(fp); \ - ok = ops->equality(cx, obj2, rval, &cond); \ - if (!ok) \ - goto out; \ - cond = cond OP JS_TRUE; \ - } else - -#define XML_NAME_EQUALITY_OP(OP) \ - if (ltmp == JSVAL_OBJECT && \ - (obj2 = JSVAL_TO_OBJECT(lval)) && \ - ((clasp = OBJ_GET_CLASS(cx, obj2))->flags & JSCLASS_IS_EXTENDED)) { \ - JSExtendedClass *xclasp; \ - \ - xclasp = (JSExtendedClass *) clasp; \ - SAVE_SP(fp); \ - ok = xclasp->equality(cx, obj2, rval, &cond); \ - if (!ok) \ - goto out; \ - cond = cond OP JS_TRUE; \ - } else -#else -#define XML_EQUALITY_OP(OP) /* nothing */ -#define XML_NAME_EQUALITY_OP(OP) /* nothing */ -#endif - -#define EQUALITY_OP(OP, IFNAN) \ - JS_BEGIN_MACRO \ - rval = FETCH_OPND(-1); \ - lval = FETCH_OPND(-2); \ - ltmp = JSVAL_TAG(lval); \ - rtmp = JSVAL_TAG(rval); \ - XML_EQUALITY_OP(OP) \ - if (ltmp == rtmp) { \ - if (ltmp == JSVAL_STRING) { \ - str = JSVAL_TO_STRING(lval); \ - str2 = JSVAL_TO_STRING(rval); \ - cond = js_CompareStrings(str, str2) OP 0; \ - } else if (ltmp == JSVAL_DOUBLE) { \ - d = *JSVAL_TO_DOUBLE(lval); \ - d2 = *JSVAL_TO_DOUBLE(rval); \ - cond = JSDOUBLE_COMPARE(d, OP, d2, IFNAN); \ - } else { \ - XML_NAME_EQUALITY_OP(OP) \ - /* Handle all undefined (=>NaN) and int combinations. */ \ - cond = lval OP rval; \ - } \ - } else { \ - if (JSVAL_IS_NULL(lval) || JSVAL_IS_VOID(lval)) { \ - cond = (JSVAL_IS_NULL(rval) || JSVAL_IS_VOID(rval)) OP 1; \ - } else if (JSVAL_IS_NULL(rval) || JSVAL_IS_VOID(rval)) { \ - cond = 1 OP 0; \ - } else { \ - if (ltmp == JSVAL_OBJECT) { \ - VALUE_TO_PRIMITIVE(cx, lval, JSTYPE_VOID, &sp[-2]); \ - lval = sp[-2]; \ - ltmp = JSVAL_TAG(lval); \ - } else if (rtmp == JSVAL_OBJECT) { \ - VALUE_TO_PRIMITIVE(cx, rval, JSTYPE_VOID, &sp[-1]); \ - rval = sp[-1]; \ - rtmp = JSVAL_TAG(rval); \ - } \ - if (ltmp == JSVAL_STRING && rtmp == JSVAL_STRING) { \ - str = JSVAL_TO_STRING(lval); \ - str2 = JSVAL_TO_STRING(rval); \ - cond = js_CompareStrings(str, str2) OP 0; \ - } else { \ - VALUE_TO_NUMBER(cx, lval, d); \ - VALUE_TO_NUMBER(cx, rval, d2); \ - cond = JSDOUBLE_COMPARE(d, OP, d2, IFNAN); \ - } \ - } \ - } \ - sp--; \ - STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond)); \ - JS_END_MACRO - - case JSOP_EQ: - EQUALITY_OP(==, JS_FALSE); - break; - - case JSOP_NE: - EQUALITY_OP(!=, JS_TRUE); - break; - -#if !JS_BUG_FALLIBLE_EQOPS -#define NEW_EQUALITY_OP(OP) \ - JS_BEGIN_MACRO \ - rval = FETCH_OPND(-1); \ - lval = FETCH_OPND(-2); \ - cond = js_StrictlyEqual(lval, rval) OP JS_TRUE; \ - sp--; \ - STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond)); \ - JS_END_MACRO - - case JSOP_NEW_EQ: - NEW_EQUALITY_OP(==); - break; - - case JSOP_NEW_NE: - NEW_EQUALITY_OP(!=); - break; - -#if JS_HAS_SWITCH_STATEMENT - case JSOP_CASE: - NEW_EQUALITY_OP(==); - (void) POP(); - if (cond) { - len = GET_JUMP_OFFSET(pc); - CHECK_BRANCH(len); - } else { - PUSH(lval); - } - break; - - case JSOP_CASEX: - NEW_EQUALITY_OP(==); - (void) POP(); - if (cond) { - len = GET_JUMPX_OFFSET(pc); - CHECK_BRANCH(len); - } else { - PUSH(lval); - } - break; -#endif - -#endif /* !JS_BUG_FALLIBLE_EQOPS */ - - case JSOP_LT: - RELATIONAL_OP(<); - break; - - case JSOP_LE: - RELATIONAL_OP(<=); - break; - - case JSOP_GT: - RELATIONAL_OP(>); - break; - - case JSOP_GE: - RELATIONAL_OP(>=); - break; - -#undef EQUALITY_OP -#undef RELATIONAL_OP - - case JSOP_LSH: - SIGNED_SHIFT_OP(<<); - break; - - case JSOP_RSH: - SIGNED_SHIFT_OP(>>); - break; - - case JSOP_URSH: - { - uint32 u; - - FETCH_INT(cx, -1, j); - FETCH_UINT(cx, -2, u); - j &= 31; - d = u >> j; - sp--; - STORE_NUMBER(cx, -1, d); - break; - } - -#undef INTEGER_OP -#undef BITWISE_OP -#undef SIGNED_SHIFT_OP - - case JSOP_ADD: - rval = FETCH_OPND(-1); - lval = FETCH_OPND(-2); -#if JS_HAS_XML_SUPPORT - if (!JSVAL_IS_PRIMITIVE(lval) && - (obj2 = JSVAL_TO_OBJECT(lval), OBJECT_IS_XML(cx, obj2)) && - VALUE_IS_XML(cx, rval)) { - JSXMLObjectOps *ops; - - ops = (JSXMLObjectOps *) obj2->map->ops; - SAVE_SP(fp); - ok = ops->concatenate(cx, obj2, rval, &rval); - if (!ok) - goto out; - sp--; - STORE_OPND(-1, rval); - break; - } -#endif - { - VALUE_TO_PRIMITIVE(cx, lval, JSTYPE_VOID, &sp[-2]); - lval = sp[-2]; - VALUE_TO_PRIMITIVE(cx, rval, JSTYPE_VOID, &sp[-1]); - rval = sp[-1]; - if ((cond = JSVAL_IS_STRING(lval)) || JSVAL_IS_STRING(rval)) { - SAVE_SP(fp); - if (cond) { - str = JSVAL_TO_STRING(lval); - ok = (str2 = js_ValueToString(cx, rval)) != NULL; - } else { - str2 = JSVAL_TO_STRING(rval); - ok = (str = js_ValueToString(cx, lval)) != NULL; - } - if (!ok) - goto out; - str = js_ConcatStrings(cx, str, str2); - if (!str) { - ok = JS_FALSE; - goto out; - } - sp--; - STORE_OPND(-1, STRING_TO_JSVAL(str)); - } else { - VALUE_TO_NUMBER(cx, lval, d); - VALUE_TO_NUMBER(cx, rval, d2); - d += d2; - sp--; - STORE_NUMBER(cx, -1, d); - } - } - break; - -#define BINARY_OP(OP) \ - JS_BEGIN_MACRO \ - FETCH_NUMBER(cx, -1, d2); \ - FETCH_NUMBER(cx, -2, d); \ - d = d OP d2; \ - sp--; \ - STORE_NUMBER(cx, -1, d); \ - JS_END_MACRO - - case JSOP_SUB: - BINARY_OP(-); - break; - - case JSOP_MUL: - BINARY_OP(*); - break; - - case JSOP_DIV: - FETCH_NUMBER(cx, -1, d2); - FETCH_NUMBER(cx, -2, d); - sp--; - if (d2 == 0) { -#if defined(XP_WIN) - /* XXX MSVC miscompiles such that (NaN == 0) */ - if (JSDOUBLE_IS_NaN(d2)) - rval = DOUBLE_TO_JSVAL(rt->jsNaN); - else -#endif - if (d == 0 || JSDOUBLE_IS_NaN(d)) - rval = DOUBLE_TO_JSVAL(rt->jsNaN); - else if ((JSDOUBLE_HI32(d) ^ JSDOUBLE_HI32(d2)) >> 31) - rval = DOUBLE_TO_JSVAL(rt->jsNegativeInfinity); - else - rval = DOUBLE_TO_JSVAL(rt->jsPositiveInfinity); - STORE_OPND(-1, rval); - } else { - d /= d2; - STORE_NUMBER(cx, -1, d); - } - break; - - case JSOP_MOD: - FETCH_NUMBER(cx, -1, d2); - FETCH_NUMBER(cx, -2, d); - sp--; - if (d2 == 0) { - STORE_OPND(-1, DOUBLE_TO_JSVAL(rt->jsNaN)); - } else { -#if defined(XP_WIN) - /* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */ - if (!(JSDOUBLE_IS_FINITE(d) && JSDOUBLE_IS_INFINITE(d2))) -#endif - d = fmod(d, d2); - STORE_NUMBER(cx, -1, d); - } - break; - - case JSOP_NOT: - POP_BOOLEAN(cx, rval, cond); - PUSH_OPND(BOOLEAN_TO_JSVAL(!cond)); - break; - - case JSOP_BITNOT: - FETCH_INT(cx, -1, i); - d = (jsdouble) ~i; - STORE_NUMBER(cx, -1, d); - break; - - case JSOP_NEG: - FETCH_NUMBER(cx, -1, d); -#ifdef HPUX - /* - * Negation of a zero doesn't produce a negative - * zero on HPUX. Perform the operation by bit - * twiddling. - */ - JSDOUBLE_HI32(d) ^= JSDOUBLE_HI32_SIGNBIT; -#else - d = -d; -#endif - STORE_NUMBER(cx, -1, d); - break; - - case JSOP_POS: - FETCH_NUMBER(cx, -1, d); - STORE_NUMBER(cx, -1, d); - break; - - case JSOP_NEW: - /* Get immediate argc and find the constructor function. */ - argc = GET_ARGC(pc); - -#if JS_HAS_INITIALIZERS - do_new: -#endif - SAVE_SP(fp); - vp = sp - (2 + argc); - JS_ASSERT(vp >= fp->spbase); - - fun = NULL; - obj2 = NULL; - lval = *vp; - if (!JSVAL_IS_OBJECT(lval) || - (obj2 = JSVAL_TO_OBJECT(lval)) == NULL || - /* XXX clean up to avoid special cases above ObjectOps layer */ - OBJ_GET_CLASS(cx, obj2) == &js_FunctionClass || - !obj2->map->ops->construct) - { - fun = js_ValueToFunction(cx, vp, JSV2F_CONSTRUCT); - if (!fun) { - ok = JS_FALSE; - goto out; - } - } - - clasp = &js_ObjectClass; - if (!obj2) { - proto = parent = NULL; - fun = NULL; - } else { - /* - * Get the constructor prototype object for this function. - * Use the nominal |this| parameter slot, vp[1], as a local - * root to protect this prototype, in case it has no other - * strong refs. - */ - ok = OBJ_GET_PROPERTY(cx, obj2, - ATOM_TO_JSID(rt->atomState - .classPrototypeAtom), - &vp[1]); - if (!ok) - goto out; - rval = vp[1]; - proto = JSVAL_IS_OBJECT(rval) ? JSVAL_TO_OBJECT(rval) : NULL; - parent = OBJ_GET_PARENT(cx, obj2); - - if (OBJ_GET_CLASS(cx, obj2) == &js_FunctionClass) { - funclasp = ((JSFunction *)JS_GetPrivate(cx, obj2))->clasp; - if (funclasp) - clasp = funclasp; - } - } - obj = js_NewObject(cx, clasp, proto, parent); - if (!obj) { - ok = JS_FALSE; - goto out; - } - - /* Now we have an object with a constructor method; call it. */ - vp[1] = OBJECT_TO_JSVAL(obj); - ok = js_Invoke(cx, argc, JSINVOKE_CONSTRUCT); - RESTORE_SP(fp); - LOAD_BRANCH_CALLBACK(cx); - LOAD_INTERRUPT_HANDLER(rt); - if (!ok) { - cx->newborn[GCX_OBJECT] = NULL; - goto out; - } - - /* Check the return value and update obj from it. */ - rval = *vp; - if (JSVAL_IS_PRIMITIVE(rval)) { - if (fun || !JS_VERSION_IS_ECMA(cx)) { - *vp = OBJECT_TO_JSVAL(obj); - break; - } - /* native [[Construct]] returning primitive is error */ - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_NEW_RESULT, - js_ValueToPrintableString(cx, rval)); - ok = JS_FALSE; - goto out; - } - obj = JSVAL_TO_OBJECT(rval); - JS_RUNTIME_METER(rt, constructs); - break; - - case JSOP_DELNAME: - atom = GET_ATOM(cx, script, pc); - id = ATOM_TO_JSID(atom); - - SAVE_SP(fp); - ok = js_FindProperty(cx, id, &obj, &obj2, &prop); - if (!ok) - goto out; - - /* ECMA says to return true if name is undefined or inherited. */ - rval = JSVAL_TRUE; - if (prop) { - OBJ_DROP_PROPERTY(cx, obj2, prop); - ok = OBJ_DELETE_PROPERTY(cx, obj, id, &rval); - if (!ok) - goto out; - } - PUSH_OPND(rval); - break; - - case JSOP_DELPROP: - atom = GET_ATOM(cx, script, pc); - id = ATOM_TO_JSID(atom); - PROPERTY_OP(-1, ok = OBJ_DELETE_PROPERTY(cx, obj, id, &rval)); - STORE_OPND(-1, rval); - break; - - case JSOP_DELELEM: - ELEMENT_OP(-1, ok = OBJ_DELETE_PROPERTY(cx, obj, id, &rval)); - sp--; - STORE_OPND(-1, rval); - break; - - case JSOP_TYPEOF: - rval = FETCH_OPND(-1); - SAVE_SP(fp); - type = JS_TypeOfValue(cx, rval); - atom = rt->atomState.typeAtoms[type]; - STORE_OPND(-1, ATOM_KEY(atom)); - break; - - case JSOP_VOID: - (void) POP_OPND(); - PUSH_OPND(JSVAL_VOID); - break; - - case JSOP_INCNAME: - case JSOP_DECNAME: - case JSOP_NAMEINC: - case JSOP_NAMEDEC: - atom = GET_ATOM(cx, script, pc); - id = ATOM_TO_JSID(atom); - - SAVE_SP(fp); - ok = js_FindProperty(cx, id, &obj, &obj2, &prop); - if (!ok) - goto out; - if (!prop) - goto atom_not_defined; - - OBJ_DROP_PROPERTY(cx, obj2, prop); - lval = OBJECT_TO_JSVAL(obj); - i = 0; - goto do_incop; - - case JSOP_INCPROP: - case JSOP_DECPROP: - case JSOP_PROPINC: - case JSOP_PROPDEC: - atom = GET_ATOM(cx, script, pc); - id = ATOM_TO_JSID(atom); - lval = FETCH_OPND(-1); - i = -1; - goto do_incop; - - case JSOP_INCELEM: - case JSOP_DECELEM: - case JSOP_ELEMINC: - case JSOP_ELEMDEC: - FETCH_ELEMENT_ID(-1, id); - lval = FETCH_OPND(-2); - i = -2; - - do_incop: - VALUE_TO_OBJECT(cx, lval, obj); - if (i < 0) - STORE_OPND(i, OBJECT_TO_JSVAL(obj)); - CHECK_ELEMENT_ID(obj, id); - - /* The operand must contain a number. */ - SAVE_SP(fp); - CACHED_GET(OBJ_GET_PROPERTY(cx, obj, id, &rval)); - if (!ok) - goto out; - - /* The expression result goes in rtmp, the updated value in rval. */ - if (JSVAL_IS_INT(rval) && - rval != INT_TO_JSVAL(JSVAL_INT_MIN) && - rval != INT_TO_JSVAL(JSVAL_INT_MAX)) { - if (cs->format & JOF_POST) { - rtmp = rval; - (cs->format & JOF_INC) ? (rval += 2) : (rval -= 2); - } else { - (cs->format & JOF_INC) ? (rval += 2) : (rval -= 2); - rtmp = rval; - } - } else { - -/* - * Initially, rval contains the value to increment or decrement, which is not - * yet converted. As above, the expression result goes in rtmp, the updated - * value goes in rval. Our caller must set vp to point at a GC-rooted jsval - * in which we home rtmp, to protect it from GC in case the unconverted rval - * is not a number. - */ -#define NONINT_INCREMENT_OP_MIDDLE() \ - JS_BEGIN_MACRO \ - VALUE_TO_NUMBER(cx, rval, d); \ - if (cs->format & JOF_POST) { \ - rtmp = rval; \ - if (!JSVAL_IS_NUMBER(rtmp)) { \ - ok = js_NewNumberValue(cx, d, &rtmp); \ - if (!ok) \ - goto out; \ - *vp = rtmp; \ - } \ - (cs->format & JOF_INC) ? d++ : d--; \ - ok = js_NewNumberValue(cx, d, &rval); \ - } else { \ - (cs->format & JOF_INC) ? ++d : --d; \ - ok = js_NewNumberValue(cx, d, &rval); \ - rtmp = rval; \ - } \ - if (!ok) \ - goto out; \ - JS_END_MACRO - - if (cs->format & JOF_POST) { - /* - * We must push early to protect the postfix increment - * or decrement result, if converted to a jsdouble from - * a non-number value, from GC nesting in the setter. - */ - vp = sp; - PUSH(JSVAL_VOID); - SAVE_SP(fp); - --i; - } -#ifdef __GNUC__ - else vp = NULL; /* suppress bogus gcc warnings */ -#endif - - NONINT_INCREMENT_OP_MIDDLE(); - } - - fp->flags |= JSFRAME_ASSIGNING; - CACHED_SET(OBJ_SET_PROPERTY(cx, obj, id, &rval)); - fp->flags &= ~JSFRAME_ASSIGNING; - if (!ok) - goto out; - sp += i; - PUSH_OPND(rtmp); - break; - -/* - * NB: This macro can't use JS_BEGIN_MACRO/JS_END_MACRO around its body because - * it must break from the switch case that calls it, not from the do...while(0) - * loop created by the JS_BEGIN/END_MACRO brackets. - */ -#define FAST_INCREMENT_OP(SLOT,COUNT,BASE,PRE,OP,MINMAX) \ - slot = SLOT; \ - JS_ASSERT(slot < fp->fun->COUNT); \ - vp = fp->BASE + slot; \ - rval = *vp; \ - if (JSVAL_IS_INT(rval) && \ - rval != INT_TO_JSVAL(JSVAL_INT_##MINMAX)) { \ - PRE = rval; \ - rval OP 2; \ - *vp = rval; \ - PUSH_OPND(PRE); \ - break; \ - } \ - goto do_nonint_fast_incop; - - case JSOP_INCARG: - FAST_INCREMENT_OP(GET_ARGNO(pc), nargs, argv, rval, +=, MAX); - case JSOP_DECARG: - FAST_INCREMENT_OP(GET_ARGNO(pc), nargs, argv, rval, -=, MIN); - case JSOP_ARGINC: - FAST_INCREMENT_OP(GET_ARGNO(pc), nargs, argv, rtmp, +=, MAX); - case JSOP_ARGDEC: - FAST_INCREMENT_OP(GET_ARGNO(pc), nargs, argv, rtmp, -=, MIN); - - case JSOP_INCVAR: - FAST_INCREMENT_OP(GET_VARNO(pc), nvars, vars, rval, +=, MAX); - case JSOP_DECVAR: - FAST_INCREMENT_OP(GET_VARNO(pc), nvars, vars, rval, -=, MIN); - case JSOP_VARINC: - FAST_INCREMENT_OP(GET_VARNO(pc), nvars, vars, rtmp, +=, MAX); - case JSOP_VARDEC: - FAST_INCREMENT_OP(GET_VARNO(pc), nvars, vars, rtmp, -=, MIN); - -#undef FAST_INCREMENT_OP - - do_nonint_fast_incop: - NONINT_INCREMENT_OP_MIDDLE(); - *vp = rval; - PUSH_OPND(rtmp); - break; - -#define FAST_GLOBAL_INCREMENT_OP(SLOWOP,PRE,OP,MINMAX) \ - slot = GET_VARNO(pc); \ - JS_ASSERT(slot < fp->nvars); \ - lval = fp->vars[slot]; \ - if (JSVAL_IS_NULL(lval)) { \ - op = SLOWOP; \ - goto do_op; \ - } \ - slot = JSVAL_TO_INT(lval); \ - obj = fp->varobj; \ - rval = OBJ_GET_SLOT(cx, obj, slot); \ - if (JSVAL_IS_INT(rval) && \ - rval != INT_TO_JSVAL(JSVAL_INT_##MINMAX)) { \ - PRE = rval; \ - rval OP 2; \ - OBJ_SET_SLOT(cx, obj, slot, rval); \ - PUSH_OPND(PRE); \ - break; \ - } \ - goto do_nonint_fast_global_incop; - - case JSOP_INCGVAR: - FAST_GLOBAL_INCREMENT_OP(JSOP_INCNAME, rval, +=, MAX); - case JSOP_DECGVAR: - FAST_GLOBAL_INCREMENT_OP(JSOP_DECNAME, rval, -=, MIN); - case JSOP_GVARINC: - FAST_GLOBAL_INCREMENT_OP(JSOP_NAMEINC, rtmp, +=, MAX); - case JSOP_GVARDEC: - FAST_GLOBAL_INCREMENT_OP(JSOP_NAMEDEC, rtmp, -=, MIN); - -#undef FAST_GLOBAL_INCREMENT_OP - - do_nonint_fast_global_incop: - vp = sp++; - SAVE_SP(fp); - NONINT_INCREMENT_OP_MIDDLE(); - OBJ_SET_SLOT(cx, obj, slot, rval); - STORE_OPND(-1, rtmp); - break; - - case JSOP_GETPROP: - /* Get an immediate atom naming the property. */ - atom = GET_ATOM(cx, script, pc); - id = ATOM_TO_JSID(atom); - PROPERTY_OP(-1, CACHED_GET(OBJ_GET_PROPERTY(cx, obj, id, &rval))); - STORE_OPND(-1, rval); - break; - - case JSOP_SETPROP: - /* Pop the right-hand side into rval for OBJ_SET_PROPERTY. */ - rval = FETCH_OPND(-1); - - /* Get an immediate atom naming the property. */ - atom = GET_ATOM(cx, script, pc); - id = ATOM_TO_JSID(atom); - PROPERTY_OP(-2, CACHED_SET(OBJ_SET_PROPERTY(cx, obj, id, &rval))); - sp--; - STORE_OPND(-1, rval); - obj = NULL; - break; - - case JSOP_GETELEM: - ELEMENT_OP(-1, CACHED_GET(OBJ_GET_PROPERTY(cx, obj, id, &rval))); - sp--; - STORE_OPND(-1, rval); - break; - - case JSOP_SETELEM: - rval = FETCH_OPND(-1); - ELEMENT_OP(-2, CACHED_SET(OBJ_SET_PROPERTY(cx, obj, id, &rval))); - sp -= 2; - STORE_OPND(-1, rval); - obj = NULL; - break; - - case JSOP_ENUMELEM: - /* Funky: the value to set is under the [obj, id] pair. */ - FETCH_ELEMENT_ID(-1, id); - FETCH_OBJECT(cx, -2, lval, obj); - CHECK_ELEMENT_ID(obj, id); - rval = FETCH_OPND(-3); - SAVE_SP(fp); - ok = OBJ_SET_PROPERTY(cx, obj, id, &rval); - if (!ok) - goto out; - sp -= 3; - break; - -/* - * LAZY_ARGS_THISP allows the JSOP_ARGSUB bytecode to defer creation of the - * arguments object until it is truly needed. JSOP_ARGSUB optimizes away - * arguments objects when the only uses of the 'arguments' parameter are to - * fetch individual actual parameters. But if such a use were then invoked, - * e.g., arguments[i](), the 'this' parameter would and must bind to the - * caller's arguments object. So JSOP_ARGSUB sets obj to LAZY_ARGS_THISP. - */ -#define LAZY_ARGS_THISP ((JSObject *) 1) - - case JSOP_PUSHOBJ: - if (obj == LAZY_ARGS_THISP && !(obj = js_GetArgsObject(cx, fp))) { - ok = JS_FALSE; - goto out; - } - PUSH_OPND(OBJECT_TO_JSVAL(obj)); - break; - - case JSOP_CALL: - case JSOP_EVAL: - argc = GET_ARGC(pc); - vp = sp - (argc + 2); - lval = *vp; - SAVE_SP(fp); - - if (JSVAL_IS_FUNCTION(cx, lval) && - (obj = JSVAL_TO_OBJECT(lval), - fun = (JSFunction *) JS_GetPrivate(cx, obj), - fun->interpreted && - !(fun->flags & (JSFUN_HEAVYWEIGHT | JSFUN_BOUND_METHOD)) && - argc >= (uintN)(fun->nargs + fun->extra))) - /* inline_call: */ - { - uintN nframeslots, nvars; - void *newmark; - JSInlineFrame *newifp; - JSInterpreterHook hook; - - /* Restrict recursion of lightweight functions. */ - if (inlineCallCount == MAX_INLINE_CALL_COUNT) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_OVER_RECURSED); - ok = JS_FALSE; - goto out; - } - -#if JS_HAS_JIT - /* ZZZbe should do this only if interpreted often enough. */ - ok = jsjit_Compile(cx, fun); - if (!ok) - goto out; -#endif - - /* Compute the number of stack slots needed for fun. */ - nframeslots = (sizeof(JSInlineFrame) + sizeof(jsval) - 1) - / sizeof(jsval); - nvars = fun->nvars; - script = fun->u.script; - depth = (jsint) script->depth; - - /* Allocate the frame and space for vars and operands. */ - newsp = js_AllocRawStack(cx, nframeslots + nvars + 2 * depth, - &newmark); - if (!newsp) { - ok = JS_FALSE; - goto bad_inline_call; - } - newifp = (JSInlineFrame *) newsp; - newsp += nframeslots; - - /* Initialize the stack frame. */ - memset(newifp, 0, sizeof(JSInlineFrame)); - newifp->frame.script = script; - newifp->frame.fun = fun; - newifp->frame.argc = argc; - newifp->frame.argv = vp + 2; - newifp->frame.rval = JSVAL_VOID; - newifp->frame.nvars = nvars; - newifp->frame.vars = newsp; - newifp->frame.down = fp; - newifp->frame.scopeChain = OBJ_GET_PARENT(cx, obj); - newifp->mark = newmark; - - /* Compute the 'this' parameter now that argv is set. */ - ok = js_ComputeThis(cx, JSVAL_TO_OBJECT(vp[1]), &newifp->frame); - if (!ok) { - js_FreeRawStack(cx, newmark); - goto bad_inline_call; - } -#ifdef DUMP_CALL_TABLE - LogCall(cx, *vp, argc, vp + 2); -#endif - - /* Push void to initialize local variables. */ - sp = newsp; - while (nvars--) - PUSH(JSVAL_VOID); - sp += depth; - newifp->frame.spbase = sp; - SAVE_SP(&newifp->frame); - - /* Call the debugger hook if present. */ - hook = cx->runtime->callHook; - if (hook) { - newifp->hookData = hook(cx, &newifp->frame, JS_TRUE, 0, - cx->runtime->callHookData); - LOAD_INTERRUPT_HANDLER(rt); - } - - /* Switch to new version if currentVersion wasn't overridden. */ - newifp->callerVersion = cx->version; - if (cx->version == currentVersion) { - currentVersion = script->version; - if (currentVersion != cx->version) - js_SetVersion(cx, currentVersion); - } - - /* Push the frame and set interpreter registers. */ - cx->fp = fp = &newifp->frame; - pc = script->code; - endpc = pc + script->length; - inlineCallCount++; - JS_RUNTIME_METER(rt, inlineCalls); - continue; - - bad_inline_call: - script = fp->script; - depth = (jsint) script->depth; - goto out; - } - - ok = js_Invoke(cx, argc, 0); - RESTORE_SP(fp); - LOAD_BRANCH_CALLBACK(cx); - LOAD_INTERRUPT_HANDLER(rt); - if (!ok) - goto out; - JS_RUNTIME_METER(rt, nonInlineCalls); -#if JS_HAS_LVALUE_RETURN - if (cx->rval2set) { - /* - * Sneaky: use the stack depth we didn't claim in our budget, - * but that we know is there on account of [fun, this] already - * having been pushed, at a minimum (if no args). Those two - * slots have been popped and [rval] has been pushed, which - * leaves one more slot for rval2 before we might overflow. - * - * NB: rval2 must be the property identifier, and rval the - * object from which to get the property. The pair form an - * ECMA "reference type", which can be used on the right- or - * left-hand side of assignment ops. Only native methods can - * return reference types. See JSOP_SETCALL just below for - * the left-hand-side case. - */ - PUSH_OPND(cx->rval2); - cx->rval2set = JS_FALSE; - ELEMENT_OP(-1, ok = OBJ_GET_PROPERTY(cx, obj, id, &rval)); - sp--; - STORE_OPND(-1, rval); - } -#endif - obj = NULL; - break; - -#if JS_HAS_LVALUE_RETURN - case JSOP_SETCALL: - argc = GET_ARGC(pc); - SAVE_SP(fp); - ok = js_Invoke(cx, argc, 0); - RESTORE_SP(fp); - LOAD_BRANCH_CALLBACK(cx); - LOAD_INTERRUPT_HANDLER(rt); - if (!ok) - goto out; - if (!cx->rval2set) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_LEFTSIDE_OF_ASS); - ok = JS_FALSE; - goto out; - } - PUSH_OPND(cx->rval2); - cx->rval2set = JS_FALSE; - obj = NULL; - break; -#endif - - case JSOP_NAME: - atom = GET_ATOM(cx, script, pc); - id = ATOM_TO_JSID(atom); - - SAVE_SP(fp); - ok = js_FindProperty(cx, id, &obj, &obj2, &prop); - if (!ok) - goto out; - if (!prop) { - /* Kludge to allow (typeof foo == "undefined") tests. */ - for (pc2 = pc + len; pc2 < endpc; pc2++) { - op2 = (JSOp)*pc2; - if (op2 == JSOP_TYPEOF) { - PUSH_OPND(JSVAL_VOID); - goto advance_pc; - } - if (op2 != JSOP_GROUP) - break; - } - goto atom_not_defined; - } - - /* Take the slow path if prop was not found in a native object. */ - if (!OBJ_IS_NATIVE(obj) || !OBJ_IS_NATIVE(obj2)) { - OBJ_DROP_PROPERTY(cx, obj2, prop); - ok = OBJ_GET_PROPERTY(cx, obj, id, &rval); - if (!ok) - goto out; - PUSH_OPND(rval); - break; - } - - /* Get and push the obj[id] property's value. */ - sprop = (JSScopeProperty *)prop; - slot = (uintN)sprop->slot; - rval = (slot != SPROP_INVALID_SLOT) - ? LOCKED_OBJ_GET_SLOT(obj2, slot) - : JSVAL_VOID; - JS_UNLOCK_OBJ(cx, obj2); - ok = SPROP_GET(cx, sprop, obj, obj2, &rval); - JS_LOCK_OBJ(cx, obj2); - if (!ok) { - OBJ_DROP_PROPERTY(cx, obj2, prop); - goto out; - } - if (SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj2))) - LOCKED_OBJ_SET_SLOT(obj2, slot, rval); - OBJ_DROP_PROPERTY(cx, obj2, prop); - PUSH_OPND(rval); - break; - - case JSOP_UINT16: - i = (jsint) GET_ATOM_INDEX(pc); - rval = INT_TO_JSVAL(i); - PUSH_OPND(rval); - obj = NULL; - break; - - case JSOP_UINT24: - i = (jsint) GET_LITERAL_INDEX(pc); - rval = INT_TO_JSVAL(i); - PUSH_OPND(rval); - break; - - case JSOP_LITERAL: - atomIndex = GET_LITERAL_INDEX(pc); - atom = js_GetAtom(cx, &script->atomMap, atomIndex); - PUSH_OPND(ATOM_KEY(atom)); - obj = NULL; - break; - - case JSOP_FINDNAME: - atomIndex = GET_LITERAL_INDEX(pc); - atom = js_GetAtom(cx, &script->atomMap, atomIndex); - SAVE_SP(fp); - obj = js_FindIdentifierBase(cx, ATOM_TO_JSID(atom)); - if (!obj) { - ok = JS_FALSE; - goto out; - } - PUSH_OPND(OBJECT_TO_JSVAL(obj)); - PUSH_OPND(ATOM_KEY(atom)); - break; - - case JSOP_LITOPX: - atomIndex = GET_LITERAL_INDEX(pc); - op = pc[1 + LITERAL_INDEX_LEN]; - switch (op) { - case JSOP_ANONFUNOBJ: goto do_JSOP_ANONFUNOBJ; - case JSOP_BINDNAME: goto do_JSOP_BINDNAME; - case JSOP_CLOSURE: goto do_JSOP_CLOSURE; - case JSOP_DEFCONST: goto do_JSOP_DEFCONST; - case JSOP_DEFFUN: goto do_JSOP_DEFFUN; - case JSOP_DEFLOCALFUN: goto do_JSOP_DEFLOCALFUN; - case JSOP_DEFVAR: goto do_JSOP_DEFVAR; -#if JS_HAS_EXPORT_IMPORT - case JSOP_EXPORTNAME: goto do_JSOP_EXPORTNAME; -#endif -#if JS_HAS_XML_SUPPORT - case JSOP_GETMETHOD: goto do_JSOP_GETMETHOD; - case JSOP_SETMETHOD: goto do_JSOP_SETMETHOD; -#endif - case JSOP_INITCATCHVAR: goto do_JSOP_INITCATCHVAR; - case JSOP_NAMEDFUNOBJ: goto do_JSOP_NAMEDFUNOBJ; - case JSOP_NUMBER: goto do_JSOP_NUMBER; - case JSOP_OBJECT: goto do_JSOP_OBJECT; -#if JS_HAS_XML_SUPPORT - case JSOP_QNAMECONST: goto do_JSOP_QNAMECONST; - case JSOP_QNAMEPART: goto do_JSOP_QNAMEPART; -#endif - case JSOP_REGEXP: goto do_JSOP_REGEXP; - case JSOP_SETCONST: goto do_JSOP_SETCONST; - case JSOP_STRING: goto do_JSOP_STRING; -#if JS_HAS_XML_SUPPORT - case JSOP_XMLCDATA: goto do_JSOP_XMLCDATA; - case JSOP_XMLCOMMENT: goto do_JSOP_XMLCOMMENT; - case JSOP_XMLOBJECT: goto do_JSOP_XMLOBJECT; - case JSOP_XMLPI: goto do_JSOP_XMLPI; -#endif - default: JS_ASSERT(0); - } - /* NOTREACHED */ - break; - - case JSOP_NUMBER: - case JSOP_STRING: - case JSOP_OBJECT: - atomIndex = GET_ATOM_INDEX(pc); - - do_JSOP_NUMBER: - do_JSOP_STRING: - do_JSOP_OBJECT: - atom = js_GetAtom(cx, &script->atomMap, atomIndex); - PUSH_OPND(ATOM_KEY(atom)); - obj = NULL; - break; - - BEGIN_LITOPX_CASE(JSOP_REGEXP, 0) - { - JSRegExp *re; - JSObject *funobj; - - /* - * Push a regexp object for the atom mapped by the bytecode at pc, - * cloning the literal's regexp object if necessary, to simulate in - * the pre-compile/execute-later case what ECMA specifies for the - * compile-and-go case: that scanning each regexp literal creates - * a single corresponding RegExp object. - * - * To support pre-compilation transparently, we must handle the - * case where a regexp object literal is used in a different global - * at execution time from the global with which it was scanned at - * compile time. We do this by re-wrapping the JSRegExp private - * data struct with a cloned object having the right prototype and - * parent, and having its own lastIndex property value storage. - * - * Unlike JSOP_DEFFUN and other prolog bytecodes that may clone - * literal objects, we don't want to pay a script prolog execution - * price for all regexp literals in a script (many may not be used - * by a particular execution of that script, depending on control - * flow), so we initialize lazily here. - * - * XXX This code is specific to regular expression objects. If we - * need a similar op for other kinds of object literals, we should - * push cloning down under JSObjectOps and reuse code here. - */ - JS_ASSERT(ATOM_IS_OBJECT(atom)); - obj = ATOM_TO_OBJECT(atom); - JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_RegExpClass); - - re = (JSRegExp *) JS_GetPrivate(cx, obj); - slot = re->cloneIndex; - if (fp->fun) { - /* - * We're in function code, not global or eval code (in eval - * code, JSOP_REGEXP is never emitted). The code generator - * recorded in fp->fun->nregexps the number of re->cloneIndex - * slots that it reserved in the cloned funobj. - */ - funobj = JSVAL_TO_OBJECT(fp->argv[-2]); - slot += JSCLASS_RESERVED_SLOTS(&js_FunctionClass); - if (!JS_GetReservedSlot(cx, funobj, slot, &rval)) - return JS_FALSE; - if (JSVAL_IS_VOID(rval)) - rval = JSVAL_NULL; - } else { - /* - * We're in global code. The code generator already arranged - * via script->numGlobalVars to reserve a global variable slot - * at cloneIndex. All global variable slots are initialized - * to null, not void, for faster testing in JSOP_*GVAR cases. - */ - rval = fp->vars[slot]; -#ifdef __GNUC__ - funobj = NULL; /* suppress bogus gcc warnings */ -#endif - } - - if (JSVAL_IS_NULL(rval)) { - /* Compute the current global object in obj2. */ - obj2 = fp->scopeChain; - while ((parent = OBJ_GET_PARENT(cx, obj2)) != NULL) - obj2 = parent; - - /* - * We must home sp here, because either js_CloneRegExpObject - * or JS_SetReservedSlot could nest a last-ditch GC. We home - * pc as well, in case js_CloneRegExpObject has to lookup the - * "RegExp" class in the global object, which could entail a - * JSNewResolveOp call. - */ - SAVE_SP(fp); - - /* - * If obj's parent is not obj2, we must clone obj so that it - * has the right parent, and therefore, the right prototype. - * - * Yes, this means we assume that the correct RegExp.prototype - * to which regexp instances (including literals) delegate can - * be distinguished solely by the instance's parent, which was - * set to the parent of the RegExp constructor function object - * when the instance was created. In other words, - * - * (/x/.__parent__ == RegExp.__parent__) implies - * (/x/.__proto__ == RegExp.prototype) - * - * (unless you assign a different object to RegExp.prototype - * at runtime, in which case, ECMA doesn't specify operation, - * and you get what you deserve). - * - * This same coupling between instance parent and constructor - * parent turns up everywhere (see jsobj.c's FindConstructor, - * js_ConstructObject, and js_NewObject). It's fundamental to - * the design of the language when you consider multiple global - * objects and separate compilation and execution, even though - * it is not specified fully in ECMA. - */ - if (OBJ_GET_PARENT(cx, obj) != obj2) { - obj = js_CloneRegExpObject(cx, obj, obj2); - if (!obj) { - ok = JS_FALSE; - goto out; - } - } - rval = OBJECT_TO_JSVAL(obj); - - /* Store the regexp object value in its cloneIndex slot. */ - if (fp->fun) { - if (!JS_SetReservedSlot(cx, funobj, slot, rval)) - return JS_FALSE; - } else { - fp->vars[slot] = rval; - } - } - - PUSH_OPND(rval); - obj = NULL; - } - END_LITOPX_CASE - - case JSOP_ZERO: - PUSH_OPND(JSVAL_ZERO); - obj = NULL; - break; - - case JSOP_ONE: - PUSH_OPND(JSVAL_ONE); - obj = NULL; - break; - - case JSOP_NULL: - PUSH_OPND(JSVAL_NULL); - obj = NULL; - break; - - case JSOP_THIS: - obj = fp->thisp; - clasp = OBJ_GET_CLASS(cx, obj); - if (clasp->flags & JSCLASS_IS_EXTENDED) { - JSExtendedClass *xclasp; - - xclasp = (JSExtendedClass *) clasp; - if (xclasp->outerObject) { - obj = xclasp->outerObject(cx, obj); - if (!obj) { - ok = JS_FALSE; - goto out; - } - } - } - - PUSH_OPND(OBJECT_TO_JSVAL(obj)); - obj = NULL; - break; - - case JSOP_FALSE: - PUSH_OPND(JSVAL_FALSE); - obj = NULL; - break; - - case JSOP_TRUE: - PUSH_OPND(JSVAL_TRUE); - obj = NULL; - break; - -#if JS_HAS_SWITCH_STATEMENT - case JSOP_TABLESWITCH: - pc2 = pc; - len = GET_JUMP_OFFSET(pc2); - - /* - * ECMAv2 forbids conversion of discriminant, so we will skip to - * the default case if the discriminant isn't already an int jsval. - * (This opcode is emitted only for dense jsint-domain switches.) - */ - if ((cx->version & JSVERSION_MASK) == JSVERSION_DEFAULT || - (cx->version & JSVERSION_MASK) >= JSVERSION_1_4) { - rval = POP_OPND(); - if (!JSVAL_IS_INT(rval)) - break; - i = JSVAL_TO_INT(rval); - } else { - FETCH_INT(cx, -1, i); - sp--; - } - - pc2 += JUMP_OFFSET_LEN; - low = GET_JUMP_OFFSET(pc2); - pc2 += JUMP_OFFSET_LEN; - high = GET_JUMP_OFFSET(pc2); - - i -= low; - if ((jsuint)i < (jsuint)(high - low + 1)) { - pc2 += JUMP_OFFSET_LEN + JUMP_OFFSET_LEN * i; - off = (jsint) GET_JUMP_OFFSET(pc2); - if (off) - len = off; - } - break; - - case JSOP_LOOKUPSWITCH: - lval = POP_OPND(); - pc2 = pc; - len = GET_JUMP_OFFSET(pc2); - - if (!JSVAL_IS_NUMBER(lval) && - !JSVAL_IS_STRING(lval) && - !JSVAL_IS_BOOLEAN(lval)) { - goto advance_pc; - } - - pc2 += JUMP_OFFSET_LEN; - npairs = (jsint) GET_ATOM_INDEX(pc2); - pc2 += ATOM_INDEX_LEN; - -#define SEARCH_PAIRS(MATCH_CODE) \ - while (npairs) { \ - atom = GET_ATOM(cx, script, pc2); \ - rval = ATOM_KEY(atom); \ - MATCH_CODE \ - if (match) { \ - pc2 += ATOM_INDEX_LEN; \ - len = GET_JUMP_OFFSET(pc2); \ - goto advance_pc; \ - } \ - pc2 += ATOM_INDEX_LEN + JUMP_OFFSET_LEN; \ - npairs--; \ - } - if (JSVAL_IS_STRING(lval)) { - str = JSVAL_TO_STRING(lval); - SEARCH_PAIRS( - match = (JSVAL_IS_STRING(rval) && - ((str2 = JSVAL_TO_STRING(rval)) == str || - !js_CompareStrings(str2, str))); - ) - } else if (JSVAL_IS_DOUBLE(lval)) { - d = *JSVAL_TO_DOUBLE(lval); - SEARCH_PAIRS( - match = (JSVAL_IS_DOUBLE(rval) && - *JSVAL_TO_DOUBLE(rval) == d); - ) - } else { - SEARCH_PAIRS( - match = (lval == rval); - ) - } -#undef SEARCH_PAIRS - break; - - case JSOP_TABLESWITCHX: - pc2 = pc; - len = GET_JUMPX_OFFSET(pc2); - - /* - * ECMAv2 forbids conversion of discriminant, so we will skip to - * the default case if the discriminant isn't already an int jsval. - * (This opcode is emitted only for dense jsint-domain switches.) - */ - if ((cx->version & JSVERSION_MASK) == JSVERSION_DEFAULT || - (cx->version & JSVERSION_MASK) >= JSVERSION_1_4) { - rval = POP_OPND(); - if (!JSVAL_IS_INT(rval)) - break; - i = JSVAL_TO_INT(rval); - } else { - FETCH_INT(cx, -1, i); - sp--; - } - - pc2 += JUMPX_OFFSET_LEN; - low = GET_JUMP_OFFSET(pc2); - pc2 += JUMP_OFFSET_LEN; - high = GET_JUMP_OFFSET(pc2); - - i -= low; - if ((jsuint)i < (jsuint)(high - low + 1)) { - pc2 += JUMP_OFFSET_LEN + JUMPX_OFFSET_LEN * i; - off = (jsint) GET_JUMPX_OFFSET(pc2); - if (off) - len = off; - } - break; - - case JSOP_LOOKUPSWITCHX: - lval = POP_OPND(); - pc2 = pc; - len = GET_JUMPX_OFFSET(pc2); - - if (!JSVAL_IS_NUMBER(lval) && - !JSVAL_IS_STRING(lval) && - !JSVAL_IS_BOOLEAN(lval)) { - goto advance_pc; - } - - pc2 += JUMPX_OFFSET_LEN; - npairs = (jsint) GET_ATOM_INDEX(pc2); - pc2 += ATOM_INDEX_LEN; - -#define SEARCH_EXTENDED_PAIRS(MATCH_CODE) \ - while (npairs) { \ - atom = GET_ATOM(cx, script, pc2); \ - rval = ATOM_KEY(atom); \ - MATCH_CODE \ - if (match) { \ - pc2 += ATOM_INDEX_LEN; \ - len = GET_JUMPX_OFFSET(pc2); \ - goto advance_pc; \ - } \ - pc2 += ATOM_INDEX_LEN + JUMPX_OFFSET_LEN; \ - npairs--; \ - } - if (JSVAL_IS_STRING(lval)) { - str = JSVAL_TO_STRING(lval); - SEARCH_EXTENDED_PAIRS( - match = (JSVAL_IS_STRING(rval) && - ((str2 = JSVAL_TO_STRING(rval)) == str || - !js_CompareStrings(str2, str))); - ) - } else if (JSVAL_IS_DOUBLE(lval)) { - d = *JSVAL_TO_DOUBLE(lval); - SEARCH_EXTENDED_PAIRS( - match = (JSVAL_IS_DOUBLE(rval) && - *JSVAL_TO_DOUBLE(rval) == d); - ) - } else { - SEARCH_EXTENDED_PAIRS( - match = (lval == rval); - ) - } -#undef SEARCH_EXTENDED_PAIRS - break; - - case JSOP_CONDSWITCH: - break; - -#endif /* JS_HAS_SWITCH_STATEMENT */ - -#if JS_HAS_EXPORT_IMPORT - case JSOP_EXPORTALL: - SAVE_SP(fp); - obj = fp->varobj; - ida = JS_Enumerate(cx, obj); - if (!ida) { - ok = JS_FALSE; - } else { - for (i = 0, j = ida->length; i < j; i++) { - id = ida->vector[i]; - ok = OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop); - if (!ok) - break; - if (!prop) - continue; - ok = OBJ_GET_ATTRIBUTES(cx, obj, id, prop, &attrs); - if (ok) { - attrs |= JSPROP_EXPORTED; - ok = OBJ_SET_ATTRIBUTES(cx, obj, id, prop, &attrs); - } - OBJ_DROP_PROPERTY(cx, obj2, prop); - if (!ok) - break; - } - JS_DestroyIdArray(cx, ida); - } - break; - - BEGIN_LITOPX_CASE(JSOP_EXPORTNAME, 0) - id = ATOM_TO_JSID(atom); - obj = fp->varobj; - SAVE_SP(fp); - ok = OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop); - if (!ok) - goto out; - if (!prop) { - ok = OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID, NULL, NULL, - JSPROP_EXPORTED, NULL); - } else { - ok = OBJ_GET_ATTRIBUTES(cx, obj, id, prop, &attrs); - if (ok) { - attrs |= JSPROP_EXPORTED; - ok = OBJ_SET_ATTRIBUTES(cx, obj, id, prop, &attrs); - } - OBJ_DROP_PROPERTY(cx, obj2, prop); - } - if (!ok) - goto out; - END_LITOPX_CASE - - case JSOP_IMPORTALL: - id = (jsid) JSVAL_VOID; - PROPERTY_OP(-1, ok = ImportProperty(cx, obj, id)); - sp--; - break; - - case JSOP_IMPORTPROP: - /* Get an immediate atom naming the property. */ - atom = GET_ATOM(cx, script, pc); - id = ATOM_TO_JSID(atom); - PROPERTY_OP(-1, ok = ImportProperty(cx, obj, id)); - sp--; - break; - - case JSOP_IMPORTELEM: - ELEMENT_OP(-1, ok = ImportProperty(cx, obj, id)); - sp -= 2; - break; -#endif /* JS_HAS_EXPORT_IMPORT */ - - case JSOP_TRAP: - switch (JS_HandleTrap(cx, script, pc, &rval)) { - case JSTRAP_ERROR: - ok = JS_FALSE; - goto out; - case JSTRAP_CONTINUE: - JS_ASSERT(JSVAL_IS_INT(rval)); - op = (JSOp) JSVAL_TO_INT(rval); - JS_ASSERT((uintN)op < (uintN)JSOP_LIMIT); - LOAD_INTERRUPT_HANDLER(rt); - goto do_op; - case JSTRAP_RETURN: - fp->rval = rval; - goto out; -#if JS_HAS_EXCEPTIONS - case JSTRAP_THROW: - cx->throwing = JS_TRUE; - cx->exception = rval; - ok = JS_FALSE; - goto out; -#endif /* JS_HAS_EXCEPTIONS */ - default:; - } - LOAD_INTERRUPT_HANDLER(rt); - break; - - case JSOP_ARGUMENTS: - SAVE_SP(fp); - ok = js_GetArgsValue(cx, fp, &rval); - if (!ok) - goto out; - PUSH_OPND(rval); - break; - - case JSOP_ARGSUB: - id = INT_TO_JSID(GET_ARGNO(pc)); - SAVE_SP(fp); - ok = js_GetArgsProperty(cx, fp, id, &obj, &rval); - if (!ok) - goto out; - if (!obj) { - /* - * If arguments was not overridden by eval('arguments = ...'), - * set obj to the magic cookie respected by JSOP_PUSHOBJ, just - * in case this bytecode is part of an 'arguments[i](j, k)' or - * similar such invocation sequence, where the function that - * is invoked expects its 'this' parameter to be the caller's - * arguments object. - */ - obj = LAZY_ARGS_THISP; - } - PUSH_OPND(rval); - break; - -#undef LAZY_ARGS_THISP - - case JSOP_ARGCNT: - id = ATOM_TO_JSID(rt->atomState.lengthAtom); - SAVE_SP(fp); - ok = js_GetArgsProperty(cx, fp, id, &obj, &rval); - if (!ok) - goto out; - PUSH_OPND(rval); - break; - - case JSOP_GETARG: - slot = GET_ARGNO(pc); - JS_ASSERT(slot < fp->fun->nargs); - PUSH_OPND(fp->argv[slot]); - obj = NULL; - break; - - case JSOP_SETARG: - slot = GET_ARGNO(pc); - JS_ASSERT(slot < fp->fun->nargs); - vp = &fp->argv[slot]; - GC_POKE(cx, *vp); - *vp = FETCH_OPND(-1); - obj = NULL; - break; - - case JSOP_GETVAR: - slot = GET_VARNO(pc); - JS_ASSERT(slot < fp->fun->nvars); - PUSH_OPND(fp->vars[slot]); - obj = NULL; - break; - - case JSOP_SETVAR: - slot = GET_VARNO(pc); - JS_ASSERT(slot < fp->fun->nvars); - vp = &fp->vars[slot]; - GC_POKE(cx, *vp); - *vp = FETCH_OPND(-1); - obj = NULL; - break; - - case JSOP_GETGVAR: - slot = GET_VARNO(pc); - JS_ASSERT(slot < fp->nvars); - lval = fp->vars[slot]; - if (JSVAL_IS_NULL(lval)) { - op = JSOP_NAME; - goto do_op; - } - slot = JSVAL_TO_INT(lval); - obj = fp->varobj; - rval = OBJ_GET_SLOT(cx, obj, slot); - PUSH_OPND(rval); - break; - - case JSOP_SETGVAR: - slot = GET_VARNO(pc); - JS_ASSERT(slot < fp->nvars); - rval = FETCH_OPND(-1); - lval = fp->vars[slot]; - obj = fp->varobj; - if (JSVAL_IS_NULL(lval)) { - /* - * Inline-clone and specialize JSOP_SETNAME code here because - * JSOP_SETGVAR has arity 1: [rval], not arity 2: [obj, rval] - * as JSOP_SETNAME does, where [obj] is due to JSOP_BINDNAME. - */ - atom = GET_ATOM(cx, script, pc); - id = ATOM_TO_JSID(atom); - SAVE_SP(fp); - CACHED_SET(OBJ_SET_PROPERTY(cx, obj, id, &rval)); - if (!ok) - goto out; - STORE_OPND(-1, rval); - } else { - slot = JSVAL_TO_INT(lval); - GC_POKE(cx, obj->slots[slot]); - OBJ_SET_SLOT(cx, obj, slot, rval); - } - obj = NULL; - break; - - case JSOP_DEFCONST: - case JSOP_DEFVAR: - atomIndex = GET_ATOM_INDEX(pc); - - do_JSOP_DEFCONST: - do_JSOP_DEFVAR: - atom = js_GetAtom(cx, &script->atomMap, atomIndex); - obj = fp->varobj; - attrs = JSPROP_ENUMERATE; - if (!(fp->flags & JSFRAME_EVAL)) - attrs |= JSPROP_PERMANENT; - if (op == JSOP_DEFCONST) - attrs |= JSPROP_READONLY; - - /* Lookup id in order to check for redeclaration problems. */ - id = ATOM_TO_JSID(atom); - SAVE_SP(fp); - ok = js_CheckRedeclaration(cx, obj, id, attrs, &obj2, &prop); - if (!ok) - goto out; - - /* Bind a variable only if it's not yet defined. */ - if (!prop) { - ok = OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID, NULL, NULL, - attrs, &prop); - if (!ok) - goto out; - JS_ASSERT(prop); - obj2 = obj; - } - - /* - * Try to optimize a property we either just created, or found - * directly in the global object, that is permanent, has a slot, - * and has stub getter and setter, into a "fast global" accessed - * by the JSOP_*GVAR opcodes. - */ - if (atomIndex < script->numGlobalVars && - (attrs & JSPROP_PERMANENT) && - obj2 == obj && - OBJ_IS_NATIVE(obj)) { - sprop = (JSScopeProperty *) prop; - if (SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj)) && - SPROP_HAS_STUB_GETTER(sprop) && - SPROP_HAS_STUB_SETTER(sprop)) { - /* - * Fast globals use fp->vars to map the global name's - * atomIndex to the permanent fp->varobj slot number, - * tagged as a jsval. The atomIndex for the global's - * name literal is identical to its fp->vars index. - */ - fp->vars[atomIndex] = INT_TO_JSVAL(sprop->slot); - } - } - - OBJ_DROP_PROPERTY(cx, obj2, prop); - break; - - BEGIN_LITOPX_CASE(JSOP_DEFFUN, 0) - { - uintN flags; - - atomIndex = GET_ATOM_INDEX(pc); - atom = js_GetAtom(cx, &script->atomMap, atomIndex); - obj = ATOM_TO_OBJECT(atom); - fun = (JSFunction *) JS_GetPrivate(cx, obj); - id = ATOM_TO_JSID(fun->atom); - - /* - * We must be at top-level (either outermost block that forms a - * function's body, or a global) scope, not inside an expression - * (JSOP_{ANON,NAMED}FUNOBJ) or compound statement (JSOP_CLOSURE) - * in the same compilation unit (ECMA Program). - * - * However, we could be in a Program being eval'd from inside a - * with statement, so we need to distinguish scope chain head from - * variables object. Hence the obj2 vs. parent distinction below. - * First we make sure the function object we're defining has the - * right scope chain. Then we define its name in fp->varobj. - * - * If static link is not current scope, clone fun's object to link - * to the current scope via parent. This clause exists to enable - * sharing of compiled functions among multiple equivalent scopes, - * splitting the cost of compilation evenly among the scopes and - * amortizing it over a number of executions. Examples include XUL - * scripts and event handlers shared among Mozilla chrome windows, - * and server-side JS user-defined functions shared among requests. - * - * NB: The Script object exposes compile and exec in the language, - * such that this clause introduces an incompatible change from old - * JS versions that supported Script. Such a JS version supported - * executing a script that defined and called functions scoped by - * the compile-time static link, not by the exec-time scope chain. - * - * We sacrifice compatibility, breaking such scripts, in order to - * promote compile-cost sharing and amortizing, and because Script - * is not and will not be standardized. - */ - obj2 = fp->scopeChain; - if (OBJ_GET_PARENT(cx, obj) != obj2) { - obj = js_CloneFunctionObject(cx, obj, obj2); - if (!obj) { - ok = JS_FALSE; - goto out; - } - } - - /* - * Protect obj from any GC hiding below OBJ_DEFINE_PROPERTY. All - * paths from here must flow through the "Restore fp->scopeChain" - * code below the OBJ_DEFINE_PROPERTY call. - */ - fp->scopeChain = obj; - rval = OBJECT_TO_JSVAL(obj); - - /* - * ECMA requires functions defined when entering Global code to be - * permanent, and functions defined when entering Eval code to be - * impermanent. - */ - attrs = JSPROP_ENUMERATE; - if (!(fp->flags & JSFRAME_EVAL)) - attrs |= JSPROP_PERMANENT; - - /* - * Load function flags that are also property attributes. Getters - * and setters do not need a slot, their value is stored elsewhere - * in the property itself, not in obj->slots. - */ - flags = fun->flags & (JSFUN_GETTER | JSFUN_SETTER); - if (flags) { - attrs |= flags | JSPROP_SHARED; - rval = JSVAL_VOID; - } - - /* - * Check for a const property of the same name -- or any kind - * of property if executing with the strict option. We check - * here at runtime as well as at compile-time, to handle eval - * as well as multiple HTML script tags. - */ - parent = fp->varobj; - SAVE_SP(fp); - ok = js_CheckRedeclaration(cx, parent, id, attrs, NULL, NULL); - if (ok) { - ok = OBJ_DEFINE_PROPERTY(cx, parent, id, rval, - (flags & JSFUN_GETTER) - ? (JSPropertyOp) obj - : NULL, - (flags & JSFUN_SETTER) - ? (JSPropertyOp) obj - : NULL, - attrs, - &prop); - } - - /* Restore fp->scopeChain now that obj is defined in fp->varobj. */ - fp->scopeChain = obj2; - if (!ok) - goto out; - -#if 0 - if (attrs == (JSPROP_ENUMERATE | JSPROP_PERMANENT) && - script->numGlobalVars) { - /* - * As with JSOP_DEFVAR and JSOP_DEFCONST (above), fast globals - * use fp->vars to map the global function name's atomIndex to - * its permanent fp->varobj slot number, tagged as a jsval. - */ - sprop = (JSScopeProperty *) prop; - fp->vars[atomIndex] = INT_TO_JSVAL(sprop->slot); - } -#endif - OBJ_DROP_PROPERTY(cx, parent, prop); - } - END_LITOPX_CASE - -#if JS_HAS_LEXICAL_CLOSURE - BEGIN_LITOPX_CASE(JSOP_DEFLOCALFUN, VARNO_LEN) - /* - * Define a local function (i.e., one nested at the top level of - * another function), parented by the current scope chain, and - * stored in a local variable slot that the compiler allocated. - * This is an optimization over JSOP_DEFFUN that avoids requiring - * a call object for the outer function's activation. - */ - slot = GET_VARNO(pc); - atom = js_GetAtom(cx, &script->atomMap, atomIndex); - obj = ATOM_TO_OBJECT(atom); - fun = (JSFunction *) JS_GetPrivate(cx, obj); - - parent = fp->scopeChain; - if (OBJ_GET_PARENT(cx, obj) != parent) { - SAVE_SP(fp); - obj = js_CloneFunctionObject(cx, obj, parent); - if (!obj) { - ok = JS_FALSE; - goto out; - } - } - fp->vars[slot] = OBJECT_TO_JSVAL(obj); - END_LITOPX_CASE - - BEGIN_LITOPX_CASE(JSOP_ANONFUNOBJ, 0) - /* Push the specified function object literal. */ - obj = ATOM_TO_OBJECT(atom); - - /* If re-parenting, push a clone of the function object. */ - parent = fp->scopeChain; - if (OBJ_GET_PARENT(cx, obj) != parent) { - SAVE_SP(fp); - obj = js_CloneFunctionObject(cx, obj, parent); - if (!obj) { - ok = JS_FALSE; - goto out; - } - } - PUSH_OPND(OBJECT_TO_JSVAL(obj)); - obj = NULL; - END_LITOPX_CASE - - BEGIN_LITOPX_CASE(JSOP_NAMEDFUNOBJ, 0) - /* ECMA ed. 3 FunctionExpression: function Identifier [etc.]. */ - rval = ATOM_KEY(atom); - JS_ASSERT(JSVAL_IS_FUNCTION(cx, rval)); - - /* - * 1. Create a new object as if by the expression new Object(). - * 2. Add Result(1) to the front of the scope chain. - * - * Step 2 is achieved by making the new object's parent be the - * current scope chain, and then making the new object the parent - * of the Function object clone. - */ - SAVE_SP(fp); - obj2 = fp->scopeChain; - parent = js_NewObject(cx, &js_ObjectClass, NULL, obj2); - if (!parent) { - ok = JS_FALSE; - goto out; - } - - /* - * 3. Create a new Function object as specified in section 13.2 - * with [parameters and body specified by the function expression - * that was parsed by the compiler into a Function object, and - * saved in the script's atom map]. - * - * Protect parent from GC after js_CloneFunctionObject calls into - * js_NewObject, which displaces the newborn object root in cx by - * allocating the clone, then runs a last-ditch GC while trying - * to allocate the clone's slots vector. Another, multi-threaded - * path: js_CloneFunctionObject => js_NewObject => OBJ_GET_CLASS - * which may suspend the current request in ClaimScope, with the - * newborn displaced as in the first scenario. - */ - fp->scopeChain = parent; - obj = js_CloneFunctionObject(cx, JSVAL_TO_OBJECT(rval), parent); - if (!obj) { - ok = JS_FALSE; - goto out; - } - - /* - * Protect obj from any GC hiding below OBJ_DEFINE_PROPERTY. All - * paths from here must flow through the "Restore fp->scopeChain" - * code below the OBJ_DEFINE_PROPERTY call. - */ - fp->scopeChain = obj; - rval = OBJECT_TO_JSVAL(obj); - - /* - * 4. Create a property in the object Result(1). The property's - * name is [fun->atom, the identifier parsed by the compiler], - * value is Result(3), and attributes are { DontDelete, ReadOnly }. - */ - fun = (JSFunction *) JS_GetPrivate(cx, obj); - attrs = fun->flags & (JSFUN_GETTER | JSFUN_SETTER); - if (attrs) { - attrs |= JSPROP_SHARED; - rval = JSVAL_VOID; - } - ok = OBJ_DEFINE_PROPERTY(cx, parent, ATOM_TO_JSID(fun->atom), rval, - (attrs & JSFUN_GETTER) - ? (JSPropertyOp) obj - : NULL, - (attrs & JSFUN_SETTER) - ? (JSPropertyOp) obj - : NULL, - attrs | - JSPROP_ENUMERATE | JSPROP_PERMANENT | - JSPROP_READONLY, - NULL); - - /* Restore fp->scopeChain now that obj is defined in parent. */ - fp->scopeChain = obj2; - if (!ok) { - cx->newborn[GCX_OBJECT] = NULL; - goto out; - } - - /* - * 5. Remove Result(1) from the front of the scope chain [no-op]. - * 6. Return Result(3). - */ - PUSH_OPND(OBJECT_TO_JSVAL(obj)); - obj = NULL; - END_LITOPX_CASE - - BEGIN_LITOPX_CASE(JSOP_CLOSURE, 0) - /* - * ECMA ed. 3 extension: a named function expression in a compound - * statement (not at the top statement level of global code, or at - * the top level of a function body). - * - * Get immediate operand atom, which is a function object literal. - * From it, get the function to close. - */ - JS_ASSERT(JSVAL_IS_FUNCTION(cx, ATOM_KEY(atom))); - obj = ATOM_TO_OBJECT(atom); - - /* - * Clone the function object with the current scope chain as the - * clone's parent. The original function object is the prototype - * of the clone. Do this only if re-parenting; the compiler may - * have seen the right parent already and created a sufficiently - * well-scoped function object. - */ - SAVE_SP(fp); - obj2 = fp->scopeChain; - if (OBJ_GET_PARENT(cx, obj) != obj2) { - obj = js_CloneFunctionObject(cx, obj, obj2); - if (!obj) { - ok = JS_FALSE; - goto out; - } - } - - /* - * Protect obj from any GC hiding below OBJ_DEFINE_PROPERTY. All - * paths from here must flow through the "Restore fp->scopeChain" - * code below the OBJ_DEFINE_PROPERTY call. - */ - fp->scopeChain = obj; - rval = OBJECT_TO_JSVAL(obj); - - /* - * Make a property in fp->varobj with id fun->atom and value obj, - * unless fun is a getter or setter (in which case, obj is cast to - * a JSPropertyOp and passed accordingly). - */ - fun = (JSFunction *) JS_GetPrivate(cx, obj); - attrs = fun->flags & (JSFUN_GETTER | JSFUN_SETTER); - if (attrs) { - attrs |= JSPROP_SHARED; - rval = JSVAL_VOID; - } - parent = fp->varobj; - ok = OBJ_DEFINE_PROPERTY(cx, parent, ATOM_TO_JSID(fun->atom), rval, - (attrs & JSFUN_GETTER) - ? (JSPropertyOp) obj - : NULL, - (attrs & JSFUN_SETTER) - ? (JSPropertyOp) obj - : NULL, - attrs | JSPROP_ENUMERATE - | JSPROP_PERMANENT, - &prop); - - /* Restore fp->scopeChain now that obj is defined in fp->varobj. */ - fp->scopeChain = obj2; - if (!ok) { - cx->newborn[GCX_OBJECT] = NULL; - goto out; - } - -#if 0 - if (attrs == 0 && script->numGlobalVars) { - /* - * As with JSOP_DEFVAR and JSOP_DEFCONST (above), fast globals - * use fp->vars to map the global function name's atomIndex to - * its permanent fp->varobj slot number, tagged as a jsval. - */ - sprop = (JSScopeProperty *) prop; - fp->vars[atomIndex] = INT_TO_JSVAL(sprop->slot); - } -#endif - OBJ_DROP_PROPERTY(cx, parent, prop); - END_LITOPX_CASE -#endif /* JS_HAS_LEXICAL_CLOSURE */ - -#if JS_HAS_GETTER_SETTER - case JSOP_GETTER: - case JSOP_SETTER: - JS_ASSERT(len == 1); - op2 = (JSOp) *++pc; - cs = &js_CodeSpec[op2]; - len = cs->length; - switch (op2) { - case JSOP_SETNAME: - case JSOP_SETPROP: - atom = GET_ATOM(cx, script, pc); - id = ATOM_TO_JSID(atom); - rval = FETCH_OPND(-1); - i = -1; - goto gs_pop_lval; - - case JSOP_SETELEM: - rval = FETCH_OPND(-1); - FETCH_ELEMENT_ID(-2, id); - i = -2; - gs_pop_lval: - FETCH_OBJECT(cx, i - 1, lval, obj); - break; - -#if JS_HAS_INITIALIZERS - case JSOP_INITPROP: - JS_ASSERT(sp - fp->spbase >= 2); - rval = FETCH_OPND(-1); - i = -1; - atom = GET_ATOM(cx, script, pc); - id = ATOM_TO_JSID(atom); - goto gs_get_lval; - - case JSOP_INITELEM: - JS_ASSERT(sp - fp->spbase >= 3); - rval = FETCH_OPND(-1); - FETCH_ELEMENT_ID(-2, id); - i = -2; - gs_get_lval: - lval = FETCH_OPND(i-1); - JS_ASSERT(JSVAL_IS_OBJECT(lval)); - obj = JSVAL_TO_OBJECT(lval); - break; -#endif /* JS_HAS_INITIALIZERS */ - - default: - JS_ASSERT(0); - } - - /* Ensure that id has a type suitable for use with obj. */ - CHECK_ELEMENT_ID(obj, id); - - SAVE_SP(fp); - if (JS_TypeOfValue(cx, rval) != JSTYPE_FUNCTION) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_GETTER_OR_SETTER, - (op == JSOP_GETTER) - ? js_getter_str - : js_setter_str); - ok = JS_FALSE; - goto out; - } - - /* - * Getters and setters are just like watchpoints from an access - * control point of view. - */ - ok = OBJ_CHECK_ACCESS(cx, obj, id, JSACC_WATCH, &rtmp, &attrs); - if (!ok) - goto out; - - if (op == JSOP_GETTER) { - getter = (JSPropertyOp) JSVAL_TO_OBJECT(rval); - setter = NULL; - attrs = JSPROP_GETTER; - } else { - getter = NULL; - setter = (JSPropertyOp) JSVAL_TO_OBJECT(rval); - attrs = JSPROP_SETTER; - } - attrs |= JSPROP_ENUMERATE | JSPROP_SHARED; - - /* Check for a readonly or permanent property of the same name. */ - ok = js_CheckRedeclaration(cx, obj, id, attrs, NULL, NULL); - if (!ok) - goto out; - - ok = OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID, getter, setter, - attrs, NULL); - if (!ok) - goto out; - - obj = NULL; - sp += i; - if (cs->ndefs) - STORE_OPND(-1, rval); - break; -#endif /* JS_HAS_GETTER_SETTER */ - -#if JS_HAS_INITIALIZERS - case JSOP_NEWINIT: - argc = 0; - fp->sharpDepth++; - goto do_new; - - case JSOP_ENDINIT: - if (--fp->sharpDepth == 0) - fp->sharpArray = NULL; - - /* Re-set the newborn root to the top of this object tree. */ - JS_ASSERT(sp - fp->spbase >= 1); - lval = FETCH_OPND(-1); - JS_ASSERT(JSVAL_IS_OBJECT(lval)); - cx->newborn[GCX_OBJECT] = JSVAL_TO_GCTHING(lval); - break; - - case JSOP_INITPROP: - /* Pop the property's value into rval. */ - JS_ASSERT(sp - fp->spbase >= 2); - rval = FETCH_OPND(-1); - - /* Get the immediate property name into id. */ - atom = GET_ATOM(cx, script, pc); - id = ATOM_TO_JSID(atom); - i = -1; - goto do_init; - - case JSOP_INITELEM: - /* Pop the element's value into rval. */ - JS_ASSERT(sp - fp->spbase >= 3); - rval = FETCH_OPND(-1); - - /* Pop and conditionally atomize the element id. */ - FETCH_ELEMENT_ID(-2, id); - i = -2; - - do_init: - /* Find the object being initialized at top of stack. */ - lval = FETCH_OPND(i-1); - JS_ASSERT(JSVAL_IS_OBJECT(lval)); - obj = JSVAL_TO_OBJECT(lval); - - /* Ensure that id has a type suitable for use with obj. */ - CHECK_ELEMENT_ID(obj, id); - - /* Set the property named by obj[id] to rval. */ - SAVE_SP(fp); - ok = OBJ_SET_PROPERTY(cx, obj, id, &rval); - if (!ok) - goto out; - sp += i; - break; - -#if JS_HAS_SHARP_VARS - case JSOP_DEFSHARP: - SAVE_SP(fp); - obj = fp->sharpArray; - if (!obj) { - obj = js_NewArrayObject(cx, 0, NULL); - if (!obj) { - ok = JS_FALSE; - goto out; - } - fp->sharpArray = obj; - } - i = (jsint) GET_ATOM_INDEX(pc); - id = INT_TO_JSID(i); - rval = FETCH_OPND(-1); - if (JSVAL_IS_PRIMITIVE(rval)) { - char numBuf[12]; - JS_snprintf(numBuf, sizeof numBuf, "%u", (unsigned) i); - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_SHARP_DEF, numBuf); - ok = JS_FALSE; - goto out; - } - ok = OBJ_SET_PROPERTY(cx, obj, id, &rval); - if (!ok) - goto out; - break; - - case JSOP_USESHARP: - i = (jsint) GET_ATOM_INDEX(pc); - id = INT_TO_JSID(i); - obj = fp->sharpArray; - if (!obj) { - rval = JSVAL_VOID; - } else { - SAVE_SP(fp); - ok = OBJ_GET_PROPERTY(cx, obj, id, &rval); - if (!ok) - goto out; - } - if (!JSVAL_IS_OBJECT(rval)) { - char numBuf[12]; - JS_snprintf(numBuf, sizeof numBuf, "%u", (unsigned) i); - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_SHARP_USE, numBuf); - ok = JS_FALSE; - goto out; - } - PUSH_OPND(rval); - break; -#endif /* JS_HAS_SHARP_VARS */ -#endif /* JS_HAS_INITIALIZERS */ - -#if JS_HAS_EXCEPTIONS - /* No-ops for ease of decompilation and jit'ing. */ - case JSOP_TRY: - case JSOP_FINALLY: - break; - - /* Reset the stack to the given depth. */ - case JSOP_SETSP: - i = (jsint) GET_ATOM_INDEX(pc); - JS_ASSERT(i >= 0); - sp = fp->spbase + i; - - obj = fp->scopeChain; - while (OBJ_GET_CLASS(cx, obj) == &js_WithClass && - JS_GetPrivate(cx, obj) == fp && - OBJ_BLOCK_DEPTH(cx, obj) >= i) { - obj = OBJ_GET_PARENT(cx, obj); - } - fp->scopeChain = obj; - break; - - case JSOP_GOSUB: - JS_ASSERT(cx->exception != JSVAL_HOLE); - if (!cx->throwing) { - lval = JSVAL_HOLE; - } else { - lval = cx->exception; - cx->throwing = JS_FALSE; - } - PUSH(lval); - i = PTRDIFF(pc, script->main, jsbytecode) + len; - len = GET_JUMP_OFFSET(pc); - PUSH(INT_TO_JSVAL(i)); - break; - - case JSOP_GOSUBX: - JS_ASSERT(cx->exception != JSVAL_HOLE); - lval = cx->throwing ? cx->exception : JSVAL_HOLE; - PUSH(lval); - i = PTRDIFF(pc, script->main, jsbytecode) + len; - len = GET_JUMPX_OFFSET(pc); - PUSH(INT_TO_JSVAL(i)); - break; - - case JSOP_RETSUB: - rval = POP(); - JS_ASSERT(JSVAL_IS_INT(rval)); - lval = POP(); - if (lval != JSVAL_HOLE) { - /* - * Exception was pending during finally, throw it *before* we - * adjust pc, because pc indexes into script->trynotes. This - * turns out not to be necessary, but it seems clearer. And - * it points out a FIXME: 350509, due to Igor Bukanov. - */ - cx->throwing = JS_TRUE; - cx->exception = lval; - ok = JS_FALSE; - goto out; - } - i = JSVAL_TO_INT(rval); - pc = script->main + i; - len = 0; - break; - - case JSOP_EXCEPTION: - PUSH(cx->exception); - cx->throwing = JS_FALSE; - break; - - case JSOP_THROWING: - JS_ASSERT(!cx->throwing); - cx->throwing = JS_TRUE; - break; - - case JSOP_THROW: - cx->throwing = JS_TRUE; - cx->exception = POP_OPND(); - ok = JS_FALSE; - /* let the code at out try to catch the exception. */ - goto out; - - BEGIN_LITOPX_CASE(JSOP_INITCATCHVAR, 0) - /* Load the value into rval, while keeping it live on stack. */ - JS_ASSERT(sp - fp->spbase >= 2); - rval = FETCH_OPND(-1); - - /* Get the immediate catch variable name into id. */ - id = ATOM_TO_JSID(atom); - - /* Find the object being initialized at top of stack. */ - lval = FETCH_OPND(-2); - JS_ASSERT(JSVAL_IS_OBJECT(lval)); - obj = JSVAL_TO_OBJECT(lval); - - SAVE_SP(fp); - - /* - * It's possible for an evil script to substitute a random object - * for the new object. Check to make sure that we don't override a - * readonly property with the below OBJ_DEFINE_PROPERTY. - */ - ok = OBJ_GET_ATTRIBUTES(cx, obj, id, NULL, &attrs); - if (!ok) - goto out; - if (!(attrs & (JSPROP_READONLY | JSPROP_PERMANENT | - JSPROP_GETTER | JSPROP_SETTER))) { - /* Define obj[id] to contain rval and to be permanent. */ - ok = OBJ_DEFINE_PROPERTY(cx, obj, id, rval, NULL, NULL, - JSPROP_PERMANENT, NULL); - if (!ok) - goto out; - } - - /* Now that we're done with rval, pop it. */ - sp--; - END_LITOPX_CASE -#endif /* JS_HAS_EXCEPTIONS */ - -#if JS_HAS_INSTANCEOF - case JSOP_INSTANCEOF: - rval = FETCH_OPND(-1); - if (JSVAL_IS_PRIMITIVE(rval) || - !(obj = JSVAL_TO_OBJECT(rval))->map->ops->hasInstance) { - SAVE_SP(fp); - str = js_DecompileValueGenerator(cx, -1, rval, NULL); - if (str) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_INSTANCEOF_RHS, - JS_GetStringBytes(str)); - } - ok = JS_FALSE; - goto out; - } - lval = FETCH_OPND(-2); - cond = JS_FALSE; - SAVE_SP(fp); - ok = obj->map->ops->hasInstance(cx, obj, lval, &cond); - if (!ok) - goto out; - sp--; - STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond)); - break; -#endif /* JS_HAS_INSTANCEOF */ - -#if JS_HAS_DEBUGGER_KEYWORD - case JSOP_DEBUGGER: - { - JSTrapHandler handler = rt->debuggerHandler; - if (handler) { - SAVE_SP(fp); - switch (handler(cx, script, pc, &rval, - rt->debuggerHandlerData)) { - case JSTRAP_ERROR: - ok = JS_FALSE; - goto out; - case JSTRAP_CONTINUE: - break; - case JSTRAP_RETURN: - fp->rval = rval; - goto out; -#if JS_HAS_EXCEPTIONS - case JSTRAP_THROW: - cx->throwing = JS_TRUE; - cx->exception = rval; - ok = JS_FALSE; - goto out; -#endif /* JS_HAS_EXCEPTIONS */ - default:; - } - LOAD_INTERRUPT_HANDLER(rt); - } - break; - } -#endif /* JS_HAS_DEBUGGER_KEYWORD */ - -#if JS_HAS_XML_SUPPORT - case JSOP_DEFXMLNS: - rval = POP(); - SAVE_SP(fp); - ok = js_SetDefaultXMLNamespace(cx, rval); - if (!ok) - goto out; - break; - - case JSOP_ANYNAME: - SAVE_SP(fp); - ok = js_GetAnyName(cx, &rval); - if (!ok) - goto out; - PUSH_OPND(rval); - break; - - BEGIN_LITOPX_CASE(JSOP_QNAMEPART, 0) - PUSH_OPND(ATOM_KEY(atom)); - END_LITOPX_CASE - - BEGIN_LITOPX_CASE(JSOP_QNAMECONST, 0) - rval = ATOM_KEY(atom); - lval = FETCH_OPND(-1); - SAVE_SP(fp); - obj = js_ConstructXMLQNameObject(cx, lval, rval); - if (!obj) { - ok = JS_FALSE; - goto out; - } - STORE_OPND(-1, OBJECT_TO_JSVAL(obj)); - END_LITOPX_CASE - - case JSOP_QNAME: - rval = FETCH_OPND(-1); - lval = FETCH_OPND(-2); - SAVE_SP(fp); - obj = js_ConstructXMLQNameObject(cx, lval, rval); - if (!obj) { - ok = JS_FALSE; - goto out; - } - sp--; - STORE_OPND(-1, OBJECT_TO_JSVAL(obj)); - break; - - case JSOP_TOATTRNAME: - rval = FETCH_OPND(-1); - SAVE_SP(fp); - ok = js_ToAttributeName(cx, &rval); - if (!ok) - goto out; - STORE_OPND(-1, rval); - break; - - case JSOP_TOATTRVAL: - rval = FETCH_OPND(-1); - JS_ASSERT(JSVAL_IS_STRING(rval)); - SAVE_SP(fp); - str = js_EscapeAttributeValue(cx, JSVAL_TO_STRING(rval)); - if (!str) { - ok = JS_FALSE; - goto out; - } - STORE_OPND(-1, STRING_TO_JSVAL(str)); - break; - - case JSOP_ADDATTRNAME: - case JSOP_ADDATTRVAL: - rval = FETCH_OPND(-1); - lval = FETCH_OPND(-2); - str = JSVAL_TO_STRING(lval); - str2 = JSVAL_TO_STRING(rval); - SAVE_SP(fp); - str = js_AddAttributePart(cx, op == JSOP_ADDATTRNAME, str, str2); - if (!str) { - ok = JS_FALSE; - goto out; - } - sp--; - STORE_OPND(-1, STRING_TO_JSVAL(str)); - break; - - case JSOP_BINDXMLNAME: - lval = FETCH_OPND(-1); - SAVE_SP(fp); - ok = js_FindXMLProperty(cx, lval, &obj, &rval); - if (!ok) - goto out; - STORE_OPND(-1, OBJECT_TO_JSVAL(obj)); - PUSH_OPND(rval); - break; - - case JSOP_SETXMLNAME: - obj = JSVAL_TO_OBJECT(FETCH_OPND(-3)); - lval = FETCH_OPND(-2); - rval = FETCH_OPND(-1); - SAVE_SP(fp); - ok = js_SetXMLProperty(cx, obj, lval, &rval); - if (!ok) - goto out; - sp -= 2; - STORE_OPND(-1, rval); - obj = NULL; - break; - - case JSOP_XMLNAME: - lval = FETCH_OPND(-1); - SAVE_SP(fp); - ok = js_FindXMLProperty(cx, lval, &obj, &rval); - if (!ok) - goto out; - ok = js_GetXMLProperty(cx, obj, rval, &rval); - if (!ok) - goto out; - STORE_OPND(-1, rval); - break; - - case JSOP_DESCENDANTS: - case JSOP_DELDESC: - FETCH_OBJECT(cx, -2, lval, obj); - rval = FETCH_OPND(-1); - SAVE_SP(fp); - ok = js_GetXMLDescendants(cx, obj, rval, &rval); - if (!ok) - goto out; - - if (op == JSOP_DELDESC) { - sp[-1] = rval; /* set local root */ - ok = js_DeleteXMLListElements(cx, JSVAL_TO_OBJECT(rval)); - if (!ok) - goto out; - rval = JSVAL_TRUE; /* always succeed */ - } - - sp--; - STORE_OPND(-1, rval); - break; - - case JSOP_FILTER: - FETCH_OBJECT(cx, -1, lval, obj); - len = GET_JUMP_OFFSET(pc); - SAVE_SP(fp); - ok = js_FilterXMLList(cx, obj, pc + cs->length, &rval); - if (!ok) - goto out; - JS_ASSERT(fp->sp == sp); - STORE_OPND(-1, rval); - break; - - case JSOP_ENDFILTER: - *result = POP_OPND(); - goto out; - - case JSOP_STARTXML: - case JSOP_STARTXMLEXPR: - break; - - case JSOP_TOXML: - rval = FETCH_OPND(-1); - SAVE_SP(fp); - obj = js_ValueToXMLObject(cx, rval); - if (!obj) { - ok = JS_FALSE; - goto out; - } - STORE_OPND(-1, OBJECT_TO_JSVAL(obj)); - break; - - case JSOP_TOXMLLIST: - rval = FETCH_OPND(-1); - SAVE_SP(fp); - obj = js_ValueToXMLListObject(cx, rval); - if (!obj) { - ok = JS_FALSE; - goto out; - } - STORE_OPND(-1, OBJECT_TO_JSVAL(obj)); - break; - - case JSOP_XMLTAGEXPR: - rval = FETCH_OPND(-1); - SAVE_SP(fp); - str = js_ValueToString(cx, rval); - if (!str) { - ok = JS_FALSE; - goto out; - } - STORE_OPND(-1, STRING_TO_JSVAL(str)); - break; - - case JSOP_XMLELTEXPR: - rval = FETCH_OPND(-1); - SAVE_SP(fp); - if (VALUE_IS_XML(cx, rval)) { - str = js_ValueToXMLString(cx, rval); - } else { - str = js_ValueToString(cx, rval); - if (str) - str = js_EscapeElementValue(cx, str); - } - if (!str) { - ok = JS_FALSE; - goto out; - } - STORE_OPND(-1, STRING_TO_JSVAL(str)); - break; - - BEGIN_LITOPX_CASE(JSOP_XMLOBJECT, 0) - SAVE_SP(fp); - obj = js_CloneXMLObject(cx, ATOM_TO_OBJECT(atom)); - if (!obj) { - ok = JS_FALSE; - goto out; - } - PUSH_OPND(OBJECT_TO_JSVAL(obj)); - obj = NULL; - END_LITOPX_CASE - - BEGIN_LITOPX_CASE(JSOP_XMLCDATA, 0) - str = ATOM_TO_STRING(atom); - obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_TEXT, NULL, str); - if (!obj) { - ok = JS_FALSE; - goto out; - } - PUSH_OPND(OBJECT_TO_JSVAL(obj)); - END_LITOPX_CASE - - BEGIN_LITOPX_CASE(JSOP_XMLCOMMENT, 0) - str = ATOM_TO_STRING(atom); - obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_COMMENT, NULL, str); - if (!obj) { - ok = JS_FALSE; - goto out; - } - PUSH_OPND(OBJECT_TO_JSVAL(obj)); - END_LITOPX_CASE - - BEGIN_LITOPX_CASE(JSOP_XMLPI, 0) - str = ATOM_TO_STRING(atom); - rval = FETCH_OPND(-1); - str2 = JSVAL_TO_STRING(rval); - SAVE_SP(fp); - obj = js_NewXMLSpecialObject(cx, - JSXML_CLASS_PROCESSING_INSTRUCTION, - str, str2); - if (!obj) { - ok = JS_FALSE; - goto out; - } - STORE_OPND(-1, OBJECT_TO_JSVAL(obj)); - END_LITOPX_CASE - - BEGIN_LITOPX_CASE(JSOP_GETMETHOD, 0) - /* Get an immediate atom naming the property. */ - id = ATOM_TO_JSID(atom); - FETCH_OBJECT(cx, -1, lval, obj); - SAVE_SP(fp); - - /* Special-case XML object method lookup, per ECMA-357. */ - if (OBJECT_IS_XML(cx, obj)) { - JSXMLObjectOps *ops; - - ops = (JSXMLObjectOps *) obj->map->ops; - obj = ops->getMethod(cx, obj, id, &rval); - if (!obj) - ok = JS_FALSE; - } else { - CACHED_GET(OBJ_GET_PROPERTY(cx, obj, id, &rval)); - } - if (!ok) - goto out; - STORE_OPND(-1, rval); - END_LITOPX_CASE - - BEGIN_LITOPX_CASE(JSOP_SETMETHOD, 0) - /* Get an immediate atom naming the property. */ - id = ATOM_TO_JSID(atom); - rval = FETCH_OPND(-1); - FETCH_OBJECT(cx, -2, lval, obj); - SAVE_SP(fp); - - /* Special-case XML object method lookup, per ECMA-357. */ - if (OBJECT_IS_XML(cx, obj)) { - JSXMLObjectOps *ops; - - ops = (JSXMLObjectOps *) obj->map->ops; - ok = ops->setMethod(cx, obj, id, &rval); - } else { - CACHED_SET(OBJ_SET_PROPERTY(cx, obj, id, &rval)); - } - if (!ok) - goto out; - --sp; - STORE_OPND(-1, rval); - obj = NULL; - END_LITOPX_CASE - - case JSOP_GETFUNNS: - ok = js_GetFunctionNamespace(cx, &rval); - if (!ok) - goto out; - PUSH_OPND(rval); - break; - - case JSOP_FOREACH: - foreach = JS_TRUE; - break; -#endif /* JS_HAS_XML_SUPPORT */ - - default: { - char numBuf[12]; - JS_snprintf(numBuf, sizeof numBuf, "%d", op); - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_BYTECODE, numBuf); - ok = JS_FALSE; - goto out; - } - } - - advance_pc: - pc += len; - -#ifdef DEBUG - if (tracefp) { - intN ndefs, n; - jsval *siter; - - ndefs = cs->ndefs; - if (ndefs) { - SAVE_SP(fp); - if (op == JSOP_FORELEM && sp[-1] == JSVAL_FALSE) - --ndefs; - for (n = -ndefs; n < 0; n++) { - str = js_DecompileValueGenerator(cx, n, sp[n], NULL); - if (str) { - fprintf(tracefp, "%s %s", - (n == -ndefs) ? " output:" : ",", - JS_GetStringBytes(str)); - } - } - fprintf(tracefp, " @ %d\n", sp - fp->spbase); - } - fprintf(tracefp, " stack: "); - for (siter = fp->spbase; siter < sp; siter++) { - str = js_ValueToSource(cx, *siter); - fprintf(tracefp, "%s ", - str ? JS_GetStringBytes(str) : ""); - } - fputc('\n', tracefp); - } -#endif - } -out: - -#if JS_HAS_EXCEPTIONS - if (!ok) { - /* - * Has an exception been raised? Also insist that we are in the - * interpreter activation that pushed fp's operand stack, to avoid - * catching exceptions within XML filtering predicate expressions, - * such as the one from tests/e4x/Regress/regress-301596.js: - * - * try { - * .(@a == 1); - * throw 5; - * } catch (e) { - * } - * - * The inner interpreter activation executing the predicate bytecode - * will throw "reference to undefined XML name @a" (or 5, in older - * versions that followed the first edition of ECMA-357 and evaluated - * unbound identifiers to undefined), and the exception must not be - * caught until control unwinds to the outer interpreter activation. - * - * Otherwise, the wrong stack depth will be restored by JSOP_SETSP, - * and the catch will move into the filtering predicate expression, - * leading to double catch execution if it rethrows. - * - * XXX This assumes the null mark case implies XML filtering predicate - * expression execution! - * FIXME: https://bugzilla.mozilla.org/show_bug.cgi?id=309894 - */ - if (cx->throwing && JS_LIKELY(mark != NULL)) { - /* - * Call debugger throw hook if set (XXX thread safety?). - */ - JSTrapHandler handler = rt->throwHook; - if (handler) { - SAVE_SP(fp); - switch (handler(cx, script, pc, &rval, rt->throwHookData)) { - case JSTRAP_ERROR: - cx->throwing = JS_FALSE; - goto no_catch; - case JSTRAP_RETURN: - ok = JS_TRUE; - cx->throwing = JS_FALSE; - fp->rval = rval; - goto no_catch; - case JSTRAP_THROW: - cx->exception = rval; - case JSTRAP_CONTINUE: - default:; - } - LOAD_INTERRUPT_HANDLER(rt); - } - - /* - * Look for a try block in script that can catch this exception. - */ - SCRIPT_FIND_CATCH_START(script, pc, pc); - if (pc) { - /* Don't clear cx->throwing to save cx->exception from GC. */ - len = 0; - ok = JS_TRUE; -#if JS_HAS_XML_SUPPORT - foreach = JS_FALSE; -#endif - goto advance_pc; - } - } -no_catch:; - } -#endif - - /* - * Check whether control fell off the end of a lightweight function, or an - * exception thrown under such a function was not caught by it. If so, go - * to the inline code under JSOP_RETURN. - */ - if (inlineCallCount) { -#if JS_HAS_XML_SUPPORT - foreach = JS_FALSE; -#endif - goto inline_return; - } - - /* - * Reset sp before freeing stack slots, because our caller may GC soon. - * Clear spbase to indicate that we've popped the 2 * depth operand slots. - * Restore the previous frame's execution state. - */ - if (JS_LIKELY(mark != NULL)) { - fp->sp = fp->spbase; - fp->spbase = NULL; - js_FreeRawStack(cx, mark); - } else { - SAVE_SP(fp); - } - -out2: - if (cx->version == currentVersion && currentVersion != originalVersion) - js_SetVersion(cx, originalVersion); - cx->interpLevel--; - return ok; - -atom_not_defined: - { - const char *printable = js_AtomToPrintableString(cx, atom); - if (printable) - js_ReportIsNotDefined(cx, printable); - ok = JS_FALSE; - goto out; - } -} diff --git a/lib/javascript/jsinterp.h b/lib/javascript/jsinterp.h deleted file mode 100644 index edf70f86..00000000 --- a/lib/javascript/jsinterp.h +++ /dev/null @@ -1,322 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jsinterp_h___ -#define jsinterp_h___ -/* - * JS interpreter interface. - */ -#include "jsprvtd.h" -#include "jspubtd.h" - -JS_BEGIN_EXTERN_C - -/* - * JS stack frame, allocated on the C stack. - */ -struct JSStackFrame { - JSObject *callobj; /* lazily created Call object */ - JSObject *argsobj; /* lazily created arguments object */ - JSObject *varobj; /* variables object, where vars go */ - JSScript *script; /* script being interpreted */ - JSFunction *fun; /* function being called or null */ - JSObject *thisp; /* "this" pointer if in method */ - uintN argc; /* actual argument count */ - jsval *argv; /* base of argument stack slots */ - jsval rval; /* function return value */ - uintN nvars; /* local variable count */ - jsval *vars; /* base of variable stack slots */ - JSStackFrame *down; /* previous frame */ - void *annotation; /* used by Java security */ - JSObject *scopeChain; /* scope chain */ - jsbytecode *pc; /* program counter */ - jsval *sp; /* stack pointer */ - jsval *spbase; /* operand stack base */ - uintN sharpDepth; /* array/object initializer depth */ - JSObject *sharpArray; /* scope for #n= initializer vars */ - uint32 flags; /* frame flags -- see below */ - JSStackFrame *dormantNext; /* next dormant frame chain */ - JSObject *xmlNamespace; /* null or default xml namespace in E4X */ -}; - -typedef struct JSInlineFrame { - JSStackFrame frame; /* base struct */ - void *mark; /* mark before inline frame */ - void *hookData; /* debugger call hook data */ - JSVersion callerVersion; /* dynamic version of calling script */ -} JSInlineFrame; - -/* JS stack frame flags. */ -#define JSFRAME_CONSTRUCTING 0x01 /* frame is for a constructor invocation */ -#define JSFRAME_INTERNAL 0x02 /* internal call, not invoked by a script */ -#define JSFRAME_SKIP_CALLER 0x04 /* skip one link when evaluating f.caller - for this invocation of f */ -#define JSFRAME_ASSIGNING 0x08 /* a complex (not simplex JOF_ASSIGNING) op - is currently assigning to a property */ -#define JSFRAME_DEBUGGER 0x10 /* frame for JS_EvaluateInStackFrame */ -#define JSFRAME_EVAL 0x20 /* frame for obj_eval */ -#define JSFRAME_SPECIAL 0x30 /* special evaluation frame flags */ -#define JSFRAME_COMPILING 0x40 /* frame is being used by compiler */ -#define JSFRAME_COMPILE_N_GO 0x80 /* compiler-and-go mode, can optimize name - references based on scope chain */ -#define JSFRAME_SCRIPT_OBJECT 0x100 /* compiling source for a Script object */ - -#define JSFRAME_OVERRIDE_SHIFT 24 /* override bit-set params; see jsfun.c */ -#define JSFRAME_OVERRIDE_BITS 8 - -/* - * Property cache for quickened get/set property opcodes. - */ -#define PROPERTY_CACHE_LOG2 10 -#define PROPERTY_CACHE_SIZE JS_BIT(PROPERTY_CACHE_LOG2) -#define PROPERTY_CACHE_MASK JS_BITMASK(PROPERTY_CACHE_LOG2) - -#define PROPERTY_CACHE_HASH(obj, id) \ - ((((jsuword)(obj) >> JSVAL_TAGBITS) ^ (jsuword)(id)) & PROPERTY_CACHE_MASK) - -#ifdef JS_THREADSAFE - -#if HAVE_ATOMIC_DWORD_ACCESS - -#define PCE_LOAD(cache, pce, entry) JS_ATOMIC_DWORD_LOAD(pce, entry) -#define PCE_STORE(cache, pce, entry) JS_ATOMIC_DWORD_STORE(pce, entry) - -#else /* !HAVE_ATOMIC_DWORD_ACCESS */ - -#define JS_PROPERTY_CACHE_METERING 1 - -#define PCE_LOAD(cache, pce, entry) \ - JS_BEGIN_MACRO \ - uint32 prefills_; \ - uint32 fills_ = (cache)->fills; \ - do { \ - /* Load until cache->fills is stable (see FILL macro below). */ \ - prefills_ = fills_; \ - (entry) = *(pce); \ - } while ((fills_ = (cache)->fills) != prefills_); \ - JS_END_MACRO - -#define PCE_STORE(cache, pce, entry) \ - JS_BEGIN_MACRO \ - do { \ - /* Store until no racing collider stores half or all of pce. */ \ - *(pce) = (entry); \ - } while (PCE_OBJECT(*pce) != PCE_OBJECT(entry) || \ - PCE_PROPERTY(*pce) != PCE_PROPERTY(entry)); \ - JS_END_MACRO - -#endif /* !HAVE_ATOMIC_DWORD_ACCESS */ - -#else /* !JS_THREADSAFE */ - -#define PCE_LOAD(cache, pce, entry) ((entry) = *(pce)) -#define PCE_STORE(cache, pce, entry) (*(pce) = (entry)) - -#endif /* !JS_THREADSAFE */ - -typedef union JSPropertyCacheEntry { - struct { - JSObject *object; /* weak link to object */ - JSScopeProperty *property; /* weak link to property */ - } s; -#ifdef HAVE_ATOMIC_DWORD_ACCESS - prdword align; -#endif -} JSPropertyCacheEntry; - -/* These may be called in lvalue or rvalue position. */ -#define PCE_OBJECT(entry) ((entry).s.object) -#define PCE_PROPERTY(entry) ((entry).s.property) - -typedef struct JSPropertyCache { - JSPropertyCacheEntry table[PROPERTY_CACHE_SIZE]; - JSBool empty; - JSBool disabled; -#ifdef JS_PROPERTY_CACHE_METERING - uint32 fills; - uint32 recycles; - uint32 tests; - uint32 misses; - uint32 flushes; -# define PCMETER(x) x -#else -# define PCMETER(x) /* nothing */ -#endif -} JSPropertyCache; - -#define PROPERTY_CACHE_FILL(cache, obj, id, sprop) \ - JS_BEGIN_MACRO \ - JSPropertyCache *cache_ = (cache); \ - if (!cache_->disabled) { \ - uintN hashIndex_ = (uintN) PROPERTY_CACHE_HASH(obj, id); \ - JSPropertyCacheEntry *pce_ = &cache_->table[hashIndex_]; \ - JSPropertyCacheEntry entry_; \ - JSScopeProperty *pce_sprop_; \ - PCE_LOAD(cache_, pce_, entry_); \ - pce_sprop_ = PCE_PROPERTY(entry_); \ - PCMETER(if (pce_sprop_ && pce_sprop_ != sprop) \ - cache_->recycles++); \ - PCE_OBJECT(entry_) = obj; \ - PCE_PROPERTY(entry_) = sprop; \ - cache_->empty = JS_FALSE; \ - PCMETER(cache_->fills++); \ - PCE_STORE(cache_, pce_, entry_); \ - } \ - JS_END_MACRO - -#define PROPERTY_CACHE_TEST(cache, obj, id, sprop) \ - JS_BEGIN_MACRO \ - uintN hashIndex_ = (uintN) PROPERTY_CACHE_HASH(obj, id); \ - JSPropertyCache *cache_ = (cache); \ - JSPropertyCacheEntry *pce_ = &cache_->table[hashIndex_]; \ - JSPropertyCacheEntry entry_; \ - JSScopeProperty *pce_sprop_; \ - PCE_LOAD(cache_, pce_, entry_); \ - pce_sprop_ = PCE_PROPERTY(entry_); \ - PCMETER(cache_->tests++); \ - if (pce_sprop_ && \ - PCE_OBJECT(entry_) == obj && \ - pce_sprop_->id == id) { \ - sprop = pce_sprop_; \ - } else { \ - PCMETER(cache_->misses++); \ - sprop = NULL; \ - } \ - JS_END_MACRO - -extern void -js_FlushPropertyCache(JSContext *cx); - -extern void -js_DisablePropertyCache(JSContext *cx); - -extern void -js_EnablePropertyCache(JSContext *cx); - -extern JS_FRIEND_API(jsval *) -js_AllocStack(JSContext *cx, uintN nslots, void **markp); - -extern JS_FRIEND_API(void) -js_FreeStack(JSContext *cx, void *mark); - -extern JSBool -js_GetArgument(JSContext *cx, JSObject *obj, jsval id, jsval *vp); - -extern JSBool -js_SetArgument(JSContext *cx, JSObject *obj, jsval id, jsval *vp); - -extern JSBool -js_GetLocalVariable(JSContext *cx, JSObject *obj, jsval id, jsval *vp); - -extern JSBool -js_SetLocalVariable(JSContext *cx, JSObject *obj, jsval id, jsval *vp); - -#ifdef DUMP_CALL_TABLE -# define JSOPTION_LOGCALL_TOSOURCE JS_BIT(15) - -extern JSHashTable *js_CallTable; -extern size_t js_LogCallToSourceLimit; - -extern void js_DumpCallTable(JSContext *cx); -#endif - -/* - * Compute the 'this' parameter and store it in frame as frame.thisp. - * Activation objects ("Call" objects not created with "new Call()", i.e., - * "Call" objects that have private data) may not be referred to by 'this', - * as dictated by ECMA. - * - * N.B.: fp->argv must be set, fp->argv[-1] the nominal 'this' paramter as - * a jsval, and fp->argv[-2] must be the callee object reference, usually a - * function object. Also, fp->flags must contain JSFRAME_CONSTRUCTING if we - * are preparing for a constructor call. - */ -extern JSBool -js_ComputeThis(JSContext *cx, JSObject *thisp, JSStackFrame *fp); - -/* - * NB: js_Invoke requires that cx is currently running JS (i.e., that cx->fp - * is non-null), and that the callee, |this| parameter, and actual arguments - * are already pushed on the stack under cx->fp->sp. - */ -extern JS_FRIEND_API(JSBool) -js_Invoke(JSContext *cx, uintN argc, uintN flags); - -/* - * Consolidated js_Invoke flags simply rename the low JSFRAME_* flags. - */ -#define JSINVOKE_CONSTRUCT JSFRAME_CONSTRUCTING -#define JSINVOKE_INTERNAL JSFRAME_INTERNAL -#define JSINVOKE_SKIP_CALLER JSFRAME_SKIP_CALLER - -/* - * "Internal" calls may come from C or C++ code using a JSContext on which no - * JS is running (!cx->fp), so they may need to push a dummy JSStackFrame. - */ -#define js_InternalCall(cx,obj,fval,argc,argv,rval) \ - js_InternalInvoke(cx, obj, fval, 0, argc, argv, rval) - -#define js_InternalConstruct(cx,obj,fval,argc,argv,rval) \ - js_InternalInvoke(cx, obj, fval, JSINVOKE_CONSTRUCT, argc, argv, rval) - -extern JSBool -js_InternalInvoke(JSContext *cx, JSObject *obj, jsval fval, uintN flags, - uintN argc, jsval *argv, jsval *rval); - -extern JSBool -js_InternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, jsval fval, - JSAccessMode mode, uintN argc, jsval *argv, jsval *rval); - -extern JSBool -js_Execute(JSContext *cx, JSObject *chain, JSScript *script, - JSStackFrame *down, uintN flags, jsval *result); - -extern JSBool -js_CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs, - JSObject **objp, JSProperty **propp); - -extern JSBool -js_StrictlyEqual(jsval lval, jsval rval); - -extern JSBool -js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result); - -JS_END_EXTERN_C - -#endif /* jsinterp_h___ */ diff --git a/lib/javascript/jslibmath.h b/lib/javascript/jslibmath.h deleted file mode 100644 index 544d8f80..00000000 --- a/lib/javascript/jslibmath.h +++ /dev/null @@ -1,290 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * IBM Corp. - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * By default all math calls go to fdlibm. The defines for each platform - * remap the math calls to native routines. - */ - -#ifndef _LIBMATH_H -#define _LIBMATH_H - -#include -#include "jsconfig.h" - -/* - * Define which platforms on which to use fdlibm. Not used - * by default since there can be problems with endian-ness and such. - */ - -#if defined(_WIN32) && !defined(__MWERKS__) -#define JS_USE_FDLIBM_MATH 1 - -#elif defined(SUNOS4) -#define JS_USE_FDLIBM_MATH 1 - -#elif defined(IRIX) -#define JS_USE_FDLIBM_MATH 1 - -#elif defined(SOLARIS) -#define JS_USE_FDLIBM_MATH 1 - -#elif defined(HPUX) -#define JS_USE_FDLIBM_MATH 1 - -#elif defined(linux) -#define JS_USE_FDLIBM_MATH 1 - -#elif defined(OSF1) -/* Want to use some fdlibm functions but fdlibm broken on OSF1/alpha. */ -#define JS_USE_FDLIBM_MATH 0 - -#elif defined(AIX) -#define JS_USE_FDLIBM_MATH 1 - -#else -#define JS_USE_FDLIBM_MATH 0 -#endif - -#if !JS_USE_FDLIBM_MATH - -/* - * Use system provided math routines. - */ - -#define fd_acos acos -#define fd_asin asin -#define fd_atan atan -#define fd_atan2 atan2 -#define fd_ceil ceil -#define fd_copysign copysign -#define fd_cos cos -#define fd_exp exp -#define fd_fabs fabs -#define fd_floor floor -#define fd_fmod fmod -#define fd_log log -#define fd_pow pow -#define fd_sin sin -#define fd_sqrt sqrt -#define fd_tan tan - -#else - -/* - * Use math routines in fdlibm. - */ - -#undef __P -#ifdef __STDC__ -#define __P(p) p -#else -#define __P(p) () -#endif - -#if (defined _WIN32 && !defined WINCE) || defined SUNOS4 - -#define fd_acos acos -#define fd_asin asin -#define fd_atan atan -#define fd_cos cos -#define fd_sin sin -#define fd_tan tan -#define fd_exp exp -#define fd_log log -#define fd_sqrt sqrt -#define fd_ceil ceil -#define fd_fabs fabs -#define fd_floor floor -#define fd_fmod fmod - -extern double fd_atan2 __P((double, double)); -extern double fd_copysign __P((double, double)); -extern double fd_pow __P((double, double)); - -#elif defined IRIX - -#define fd_acos acos -#define fd_asin asin -#define fd_atan atan -#define fd_exp exp -#define fd_log log -#define fd_log10 log10 -#define fd_sqrt sqrt -#define fd_fabs fabs -#define fd_floor floor -#define fd_fmod fmod - -extern double fd_cos __P((double)); -extern double fd_sin __P((double)); -extern double fd_tan __P((double)); -extern double fd_atan2 __P((double, double)); -extern double fd_pow __P((double, double)); -extern double fd_ceil __P((double)); -extern double fd_copysign __P((double, double)); - -#elif defined SOLARIS - -#define fd_atan atan -#define fd_cos cos -#define fd_sin sin -#define fd_tan tan -#define fd_exp exp -#define fd_sqrt sqrt -#define fd_ceil ceil -#define fd_fabs fabs -#define fd_floor floor -#define fd_fmod fmod - -extern double fd_acos __P((double)); -extern double fd_asin __P((double)); -extern double fd_log __P((double)); -extern double fd_atan2 __P((double, double)); -extern double fd_pow __P((double, double)); -extern double fd_copysign __P((double, double)); - -#elif defined HPUX - -#define fd_cos cos -#define fd_sin sin -#define fd_exp exp -#define fd_sqrt sqrt -#define fd_fabs fabs -#define fd_floor floor -#define fd_fmod fmod - -extern double fd_ceil __P((double)); -extern double fd_acos __P((double)); -extern double fd_log __P((double)); -extern double fd_atan2 __P((double, double)); -extern double fd_tan __P((double)); -extern double fd_pow __P((double, double)); -extern double fd_asin __P((double)); -extern double fd_atan __P((double)); -extern double fd_copysign __P((double, double)); - -#elif defined(linux) - -#define fd_atan atan -#define fd_atan2 atan2 -#define fd_ceil ceil -#define fd_cos cos -#define fd_fabs fabs -#define fd_floor floor -#define fd_fmod fmod -#define fd_sin sin -#define fd_sqrt sqrt -#define fd_tan tan -#define fd_copysign copysign - -extern double fd_asin __P((double)); -extern double fd_acos __P((double)); -extern double fd_exp __P((double)); -extern double fd_log __P((double)); -extern double fd_pow __P((double, double)); - -#elif defined(OSF1) - -#define fd_acos acos -#define fd_asin asin -#define fd_atan atan -#define fd_copysign copysign -#define fd_cos cos -#define fd_exp exp -#define fd_fabs fabs -#define fd_fmod fmod -#define fd_sin sin -#define fd_sqrt sqrt -#define fd_tan tan - -extern double fd_atan2 __P((double, double)); -extern double fd_ceil __P((double)); -extern double fd_floor __P((double)); -extern double fd_log __P((double)); -extern double fd_pow __P((double, double)); - -#elif defined(AIX) - -#define fd_acos acos -#define fd_asin asin -#define fd_atan2 atan2 -#define fd_copysign copysign -#define fd_cos cos -#define fd_exp exp -#define fd_fabs fabs -#define fd_floor floor -#define fd_fmod fmod -#define fd_log log -#define fd_sin sin -#define fd_sqrt sqrt - -extern double fd_atan __P((double)); -extern double fd_ceil __P((double)); -extern double fd_pow __P((double,double)); -extern double fd_tan __P((double)); - -#else /* other platform.. generic paranoid slow fdlibm */ - -extern double fd_acos __P((double)); -extern double fd_asin __P((double)); -extern double fd_atan __P((double)); -extern double fd_cos __P((double)); -extern double fd_sin __P((double)); -extern double fd_tan __P((double)); - -extern double fd_exp __P((double)); -extern double fd_log __P((double)); -extern double fd_sqrt __P((double)); - -extern double fd_ceil __P((double)); -extern double fd_fabs __P((double)); -extern double fd_floor __P((double)); -extern double fd_fmod __P((double, double)); - -extern double fd_atan2 __P((double, double)); -extern double fd_pow __P((double, double)); -extern double fd_copysign __P((double, double)); - -#endif - -#endif /* JS_USE_FDLIBM_MATH */ - -#endif /* _LIBMATH_H */ - diff --git a/lib/javascript/jslock.c b/lib/javascript/jslock.c deleted file mode 100644 index 968e98b8..00000000 --- a/lib/javascript/jslock.c +++ /dev/null @@ -1,1261 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifdef JS_THREADSAFE - -/* - * JS locking stubs. - */ -#include "jsstddef.h" -#include -#include "jspubtd.h" -#include "prthread.h" -#include "jsutil.h" /* Added by JSIFY */ -#include "jstypes.h" -#include "jsbit.h" -#include "jscntxt.h" -#include "jsdtoa.h" -#include "jsgc.h" -#include "jslock.h" -#include "jsscope.h" -#include "jsstr.h" - -#define ReadWord(W) (W) - -#ifndef NSPR_LOCK - -#include - -static PRLock **global_locks; -static uint32 global_lock_count = 1; -static uint32 global_locks_log2 = 0; -static uint32 global_locks_mask = 0; - -#define GLOBAL_LOCK_INDEX(id) (((uint32)(id) >> 2) & global_locks_mask) - -static void -js_LockGlobal(void *id) -{ - uint32 i = GLOBAL_LOCK_INDEX(id); - PR_Lock(global_locks[i]); -} - -static void -js_UnlockGlobal(void *id) -{ - uint32 i = GLOBAL_LOCK_INDEX(id); - PR_Unlock(global_locks[i]); -} - -/* Exclude Alpha NT. */ -#if defined(_WIN32) && defined(_M_IX86) -#pragma warning( disable : 4035 ) - -static JS_INLINE int -js_CompareAndSwap(jsword *w, jsword ov, jsword nv) -{ - __asm { - mov eax, ov - mov ecx, nv - mov ebx, w - lock cmpxchg [ebx], ecx - sete al - and eax, 1h - } -} - -#elif defined(__GNUC__) && defined(__i386__) - -/* Note: This fails on 386 cpus, cmpxchgl is a >= 486 instruction */ -static JS_INLINE int -js_CompareAndSwap(jsword *w, jsword ov, jsword nv) -{ - unsigned int res; - - __asm__ __volatile__ ( - "lock\n" - "cmpxchgl %2, (%1)\n" - "sete %%al\n" - "andl $1, %%eax\n" - : "=a" (res) - : "r" (w), "r" (nv), "a" (ov) - : "cc", "memory"); - return (int)res; -} - -#elif defined(SOLARIS) && defined(sparc) && defined(ULTRA_SPARC) - -static JS_INLINE int -js_CompareAndSwap(jsword *w, jsword ov, jsword nv) -{ -#if defined(__GNUC__) - unsigned int res; - JS_ASSERT(ov != nv); - asm volatile ("\ -stbar\n\ -cas [%1],%2,%3\n\ -cmp %2,%3\n\ -be,a 1f\n\ -mov 1,%0\n\ -mov 0,%0\n\ -1:" - : "=r" (res) - : "r" (w), "r" (ov), "r" (nv)); - return (int)res; -#else /* !__GNUC__ */ - extern int compare_and_swap(jsword*, jsword, jsword); - JS_ASSERT(ov != nv); - return compare_and_swap(w, ov, nv); -#endif -} - -#elif defined(AIX) - -#include - -static JS_INLINE int -js_CompareAndSwap(jsword *w, jsword ov, jsword nv) -{ - return !_check_lock((atomic_p)w, ov, nv); -} - -#else - -#error "Define NSPR_LOCK if your platform lacks a compare-and-swap instruction." - -#endif /* arch-tests */ - -#endif /* !NSPR_LOCK */ - -jsword -js_CurrentThreadId() -{ - return CurrentThreadId(); -} - -void -js_InitLock(JSThinLock *tl) -{ -#ifdef NSPR_LOCK - tl->owner = 0; - tl->fat = (JSFatLock*)JS_NEW_LOCK(); -#else - memset(tl, 0, sizeof(JSThinLock)); -#endif -} - -void -js_FinishLock(JSThinLock *tl) -{ -#ifdef NSPR_LOCK - tl->owner = 0xdeadbeef; - if (tl->fat) - JS_DESTROY_LOCK(((JSLock*)tl->fat)); -#else - JS_ASSERT(tl->owner == 0); - JS_ASSERT(tl->fat == NULL); -#endif -} - -static void js_Dequeue(JSThinLock *); - -#ifdef DEBUG_SCOPE_COUNT - -#include -#include "jsdhash.h" - -static FILE *logfp; -static JSDHashTable logtbl; - -typedef struct logentry { - JSDHashEntryStub stub; - char op; - const char *file; - int line; -} logentry; - -static void -logit(JSScope *scope, char op, const char *file, int line) -{ - logentry *entry; - - if (!logfp) { - logfp = fopen("/tmp/scope.log", "w"); - if (!logfp) - return; - setvbuf(logfp, NULL, _IONBF, 0); - } - fprintf(logfp, "%p %c %s %d\n", scope, op, file, line); - - if (!logtbl.entryStore && - !JS_DHashTableInit(&logtbl, JS_DHashGetStubOps(), NULL, - sizeof(logentry), 100)) { - return; - } - entry = (logentry *) JS_DHashTableOperate(&logtbl, scope, JS_DHASH_ADD); - if (!entry) - return; - entry->stub.key = scope; - entry->op = op; - entry->file = file; - entry->line = line; -} - -void -js_unlog_scope(JSScope *scope) -{ - if (!logtbl.entryStore) - return; - (void) JS_DHashTableOperate(&logtbl, scope, JS_DHASH_REMOVE); -} - -# define LOGIT(scope,op) logit(scope, op, __FILE__, __LINE__) - -#else - -# define LOGIT(scope,op) /* nothing */ - -#endif /* DEBUG_SCOPE_COUNT */ - -/* - * Return true if scope's ownercx, or the ownercx of a single-threaded scope - * for which ownercx is waiting to become multi-threaded and shared, is cx. - * That condition implies deadlock in ClaimScope if cx's thread were to wait - * to share scope. - * - * (i) rt->gcLock held - */ -static JSBool -WillDeadlock(JSScope *scope, JSContext *cx) -{ - JSContext *ownercx; - - do { - ownercx = scope->ownercx; - if (ownercx == cx) { - JS_RUNTIME_METER(cx->runtime, deadlocksAvoided); - return JS_TRUE; - } - } while (ownercx && (scope = ownercx->scopeToShare) != NULL); - return JS_FALSE; -} - -/* - * Make scope multi-threaded, i.e. share its ownership among contexts in rt - * using a "thin" or (if necessary due to contention) "fat" lock. Called only - * from ClaimScope, immediately below, when we detect deadlock were we to wait - * for scope's lock, because its ownercx is waiting on a scope owned by the - * calling cx. - * - * (i) rt->gcLock held - */ -static void -ShareScope(JSRuntime *rt, JSScope *scope) -{ - JSScope **todop; - - if (scope->u.link) { - for (todop = &rt->scopeSharingTodo; *todop != scope; - todop = &(*todop)->u.link) { - JS_ASSERT(*todop != NO_SCOPE_SHARING_TODO); - } - *todop = scope->u.link; - scope->u.link = NULL; /* null u.link for sanity ASAP */ - JS_NOTIFY_ALL_CONDVAR(rt->scopeSharingDone); - } - js_InitLock(&scope->lock); - if (scope == rt->setSlotScope) { - /* - * Nesting locks on another thread that's using scope->ownercx: give - * the held lock a reentrancy count of 1 and set its lock.owner field - * directly (no compare-and-swap needed while scope->ownercx is still - * non-null). See below in ClaimScope, before the ShareScope call, - * for more on why this is necessary. - * - * If NSPR_LOCK is defined, we cannot deadlock holding rt->gcLock and - * acquiring scope->lock.fat here, against another thread holding that - * fat lock and trying to grab rt->gcLock. This is because no other - * thread can attempt to acquire scope->lock.fat until scope->ownercx - * is null *and* our thread has released rt->gcLock, which interlocks - * scope->ownercx's transition to null against tests of that member - * in ClaimScope. - */ - scope->lock.owner = scope->ownercx->thread; -#ifdef NSPR_LOCK - JS_ACQUIRE_LOCK((JSLock*)scope->lock.fat); -#endif - scope->u.count = 1; - } else { - scope->u.count = 0; - } - js_FinishSharingScope(rt, scope); -} - -/* - * js_FinishSharingScope is the tail part of ShareScope, split out to become a - * subroutine of JS_EndRequest too. The bulk of the work here involves making - * mutable strings in the scope's object's slots be immutable. We have to do - * this because such strings will soon be available to multiple threads, so - * their buffers can't be realloc'd any longer in js_ConcatStrings, and their - * members can't be modified by js_ConcatStrings, js_MinimizeDependentStrings, - * or js_UndependString. - * - * The last bit of work done by js_FinishSharingScope nulls scope->ownercx and - * updates rt->sharedScopes. - */ -#define MAKE_STRING_IMMUTABLE(rt, v, vp) \ - JS_BEGIN_MACRO \ - JSString *str_ = JSVAL_TO_STRING(v); \ - uint8 *flagp_ = js_GetGCThingFlags(str_); \ - if (*flagp_ & GCF_MUTABLE) { \ - if (JSSTRING_IS_DEPENDENT(str_) && \ - !js_UndependString(NULL, str_)) { \ - JS_RUNTIME_METER(rt, badUndependStrings); \ - *vp = JSVAL_VOID; \ - } else { \ - *flagp_ &= ~GCF_MUTABLE; \ - } \ - } \ - JS_END_MACRO - -void -js_FinishSharingScope(JSRuntime *rt, JSScope *scope) -{ - JSObject *obj; - uint32 nslots; - jsval v, *vp, *end; - - obj = scope->object; - nslots = JS_MIN(obj->map->freeslot, obj->map->nslots); - for (vp = obj->slots, end = vp + nslots; vp < end; vp++) { - v = *vp; - if (JSVAL_IS_STRING(v)) - MAKE_STRING_IMMUTABLE(rt, v, vp); - } - - scope->ownercx = NULL; /* NB: set last, after lock init */ - JS_RUNTIME_METER(rt, sharedScopes); -} - -/* - * Given a scope with apparently non-null ownercx different from cx, try to - * set ownercx to cx, claiming exclusive (single-threaded) ownership of scope. - * If we claim ownership, return true. Otherwise, we wait for ownercx to be - * set to null (indicating that scope is multi-threaded); or if waiting would - * deadlock, we set ownercx to null ourselves via ShareScope. In any case, - * once ownercx is null we return false. - */ -static JSBool -ClaimScope(JSScope *scope, JSContext *cx) -{ - JSRuntime *rt; - JSContext *ownercx; - jsrefcount saveDepth; - PRStatus stat; - - rt = cx->runtime; - JS_RUNTIME_METER(rt, claimAttempts); - JS_LOCK_GC(rt); - - /* Reload in case ownercx went away while we blocked on the lock. */ - while ((ownercx = scope->ownercx) != NULL) { - /* - * Avoid selflock if ownercx is dead, or is not running a request, or - * has the same thread as cx. Set scope->ownercx to cx so that the - * matching JS_UNLOCK_SCOPE or JS_UNLOCK_OBJ macro call will take the - * fast path around the corresponding js_UnlockScope or js_UnlockObj - * function call. - * - * If scope->u.link is non-null, scope has already been inserted on - * the rt->scopeSharingTodo list, because another thread's context - * already wanted to lock scope while ownercx was running a request. - * We can't claim any scope whose u.link is non-null at this point, - * even if ownercx->requestDepth is 0 (see below where we suspend our - * request before waiting on rt->scopeSharingDone). - */ - if (!scope->u.link && - (!js_ValidContextPointer(rt, ownercx) || - !ownercx->requestDepth || - ownercx->thread == cx->thread)) { - JS_ASSERT(scope->u.count == 0); - scope->ownercx = cx; - JS_UNLOCK_GC(rt); - JS_RUNTIME_METER(rt, claimedScopes); - return JS_TRUE; - } - - /* - * Avoid deadlock if scope's owner context is waiting on a scope that - * we own, by revoking scope's ownership. This approach to deadlock - * avoidance works because the engine never nests scope locks, except - * for the notable case of js_SetProtoOrParent (see jsobj.c). - * - * If cx could hold locks on ownercx->scopeToShare, or if ownercx - * could hold locks on scope, we would need to keep reentrancy counts - * for all such "flyweight" (ownercx != NULL) locks, so that control - * would unwind properly once these locks became "thin" or "fat". - * Apart from the js_SetProtoOrParent exception, the engine promotes - * a scope from exclusive to shared access only when locking, never - * when holding or unlocking. - * - * If ownercx's thread is calling js_SetProtoOrParent, trying to lock - * the inner scope (the scope of the object being set as the prototype - * of the outer object), ShareScope will find the outer object's scope - * at rt->setSlotScope. If it's the same as scope, we give it a lock - * held by ownercx's thread with reentrancy count of 1, then we return - * here and break. After that we unwind to js_[GS]etSlotThreadSafe or - * js_LockScope (our caller), where we wait on the newly-fattened lock - * until ownercx's thread unwinds from js_SetProtoOrParent. - * - * Avoid deadlock before any of this scope/context cycle detection if - * cx is on the active GC's thread, because in that case, no requests - * will run until the GC completes. Any scope wanted by the GC (from - * a finalizer) that can't be claimed must be slated for sharing. - */ - if (rt->gcThread == cx->thread || - (ownercx->scopeToShare && - WillDeadlock(ownercx->scopeToShare, cx))) { - ShareScope(rt, scope); - break; - } - - /* - * Thanks to the non-zero NO_SCOPE_SHARING_TODO link terminator, we - * can decide whether scope is on rt->scopeSharingTodo with a single - * non-null test, and avoid double-insertion bugs. - */ - if (!scope->u.link) { - scope->u.link = rt->scopeSharingTodo; - rt->scopeSharingTodo = scope; - js_HoldObjectMap(cx, &scope->map); - } - - /* - * Inline JS_SuspendRequest before we wait on rt->scopeSharingDone, - * saving and clearing cx->requestDepth so we don't deadlock if the - * GC needs to run on ownercx. - * - * Unlike JS_SuspendRequest and JS_EndRequest, we must take care not - * to decrement rt->requestCount if cx is active on the GC's thread, - * because the GC has already reduced rt->requestCount to exclude all - * such such contexts. - */ - saveDepth = cx->requestDepth; - if (saveDepth) { - cx->requestDepth = 0; - if (rt->gcThread != cx->thread) { - JS_ASSERT(rt->requestCount > 0); - rt->requestCount--; - if (rt->requestCount == 0) - JS_NOTIFY_REQUEST_DONE(rt); - } - } - - /* - * We know that some other thread's context owns scope, which is now - * linked onto rt->scopeSharingTodo, awaiting the end of that other - * thread's request. So it is safe to wait on rt->scopeSharingDone. - */ - cx->scopeToShare = scope; - stat = PR_WaitCondVar(rt->scopeSharingDone, PR_INTERVAL_NO_TIMEOUT); - JS_ASSERT(stat != PR_FAILURE); - - /* - * Inline JS_ResumeRequest after waiting on rt->scopeSharingDone, - * restoring cx->requestDepth. Same note as above for the inlined, - * specialized JS_SuspendRequest code: beware rt->gcThread. - */ - if (saveDepth) { - if (rt->gcThread != cx->thread) { - while (rt->gcLevel > 0) - JS_AWAIT_GC_DONE(rt); - rt->requestCount++; - } - cx->requestDepth = saveDepth; - } - - /* - * Don't clear cx->scopeToShare until after we're through waiting on - * all condition variables protected by rt->gcLock -- that includes - * rt->scopeSharingDone *and* rt->gcDone (hidden in JS_AWAIT_GC_DONE, - * in the inlined JS_ResumeRequest code immediately above). - * - * Otherwise, the GC could easily deadlock with another thread that - * owns a scope wanted by a finalizer. By keeping cx->scopeToShare - * set till here, we ensure that such deadlocks are detected, which - * results in the finalized object's scope being shared (it must, of - * course, have other, live objects sharing it). - */ - cx->scopeToShare = NULL; - } - - JS_UNLOCK_GC(rt); - return JS_FALSE; -} - -/* Exported to js.c, which calls it via OBJ_GET_* and JSVAL_IS_* macros. */ -JS_FRIEND_API(jsval) -js_GetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot) -{ - jsval v; - JSScope *scope; -#ifndef NSPR_LOCK - JSThinLock *tl; - jsword me; -#endif - - /* - * We handle non-native objects via JSObjectOps.getRequiredSlot, treating - * all slots starting from 0 as required slots. A property definition or - * some prior arrangement must have allocated slot. - * - * Note once again (see jspubtd.h, before JSGetRequiredSlotOp's typedef) - * the crucial distinction between a |required slot number| that's passed - * to the get/setRequiredSlot JSObjectOps, and a |reserved slot index| - * passed to the JS_Get/SetReservedSlot APIs. - */ - if (!OBJ_IS_NATIVE(obj)) - return OBJ_GET_REQUIRED_SLOT(cx, obj, slot); - - /* - * Native object locking is inlined here to optimize the single-threaded - * and contention-free multi-threaded cases. - */ - scope = OBJ_SCOPE(obj); - JS_ASSERT(scope->ownercx != cx); - JS_ASSERT(obj->slots && slot < obj->map->freeslot); - - /* - * Avoid locking if called from the GC (see GC_AWARE_GET_SLOT in jsobj.h). - * Also avoid locking an object owning a sealed scope. If neither of those - * special cases applies, try to claim scope's flyweight lock from whatever - * context may have had it in an earlier request. - */ - if (CX_THREAD_IS_RUNNING_GC(cx) || - (SCOPE_IS_SEALED(scope) && scope->object == obj) || - (scope->ownercx && ClaimScope(scope, cx))) { - return obj->slots[slot]; - } - -#ifndef NSPR_LOCK - tl = &scope->lock; - me = cx->thread; - JS_ASSERT(me == CurrentThreadId()); - if (js_CompareAndSwap(&tl->owner, 0, me)) { - /* - * Got the lock with one compare-and-swap. Even so, someone else may - * have mutated obj so it now has its own scope and lock, which would - * require either a restart from the top of this routine, or a thin - * lock release followed by fat lock acquisition. - */ - if (scope == OBJ_SCOPE(obj)) { - v = obj->slots[slot]; - if (!js_CompareAndSwap(&tl->owner, me, 0)) { - /* Assert that scope locks never revert to flyweight. */ - JS_ASSERT(scope->ownercx != cx); - LOGIT(scope, '1'); - scope->u.count = 1; - js_UnlockObj(cx, obj); - } - return v; - } - if (!js_CompareAndSwap(&tl->owner, me, 0)) - js_Dequeue(tl); - } - else if (Thin_RemoveWait(ReadWord(tl->owner)) == me) { - return obj->slots[slot]; - } -#endif - - js_LockObj(cx, obj); - v = obj->slots[slot]; - - /* - * Test whether cx took ownership of obj's scope during js_LockObj. - * - * This does not mean that a given scope reverted to flyweight from "thin" - * or "fat" -- it does mean that obj's map pointer changed due to another - * thread setting a property, requiring obj to cease sharing a prototype - * object's scope (whose lock was not flyweight, else we wouldn't be here - * in the first place!). - */ - scope = OBJ_SCOPE(obj); - if (scope->ownercx != cx) - js_UnlockScope(cx, scope); - return v; -} - -void -js_SetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot, jsval v) -{ - JSScope *scope; -#ifndef NSPR_LOCK - JSThinLock *tl; - jsword me; -#endif - - /* Any string stored in a thread-safe object must be immutable. */ - if (JSVAL_IS_STRING(v)) - MAKE_STRING_IMMUTABLE(cx->runtime, v, &v); - - /* - * We handle non-native objects via JSObjectOps.setRequiredSlot, as above - * for the Get case. - */ - if (!OBJ_IS_NATIVE(obj)) { - OBJ_SET_REQUIRED_SLOT(cx, obj, slot, v); - return; - } - - /* - * Native object locking is inlined here to optimize the single-threaded - * and contention-free multi-threaded cases. - */ - scope = OBJ_SCOPE(obj); - JS_ASSERT(scope->ownercx != cx); - JS_ASSERT(obj->slots && slot < obj->map->freeslot); - - /* - * Avoid locking if called from the GC (see GC_AWARE_GET_SLOT in jsobj.h). - * Also avoid locking an object owning a sealed scope. If neither of those - * special cases applies, try to claim scope's flyweight lock from whatever - * context may have had it in an earlier request. - */ - if (CX_THREAD_IS_RUNNING_GC(cx) || - (SCOPE_IS_SEALED(scope) && scope->object == obj) || - (scope->ownercx && ClaimScope(scope, cx))) { - obj->slots[slot] = v; - return; - } - -#ifndef NSPR_LOCK - tl = &scope->lock; - me = cx->thread; - JS_ASSERT(me == CurrentThreadId()); - if (js_CompareAndSwap(&tl->owner, 0, me)) { - if (scope == OBJ_SCOPE(obj)) { - obj->slots[slot] = v; - if (!js_CompareAndSwap(&tl->owner, me, 0)) { - /* Assert that scope locks never revert to flyweight. */ - JS_ASSERT(scope->ownercx != cx); - LOGIT(scope, '1'); - scope->u.count = 1; - js_UnlockObj(cx, obj); - } - return; - } - if (!js_CompareAndSwap(&tl->owner, me, 0)) - js_Dequeue(tl); - } - else if (Thin_RemoveWait(ReadWord(tl->owner)) == me) { - obj->slots[slot] = v; - return; - } -#endif - - js_LockObj(cx, obj); - obj->slots[slot] = v; - - /* - * Same drill as above, in js_GetSlotThreadSafe. Note that we cannot - * assume obj has its own mutable scope (where scope->object == obj) yet, - * because OBJ_SET_SLOT is called for the "universal", common slots such - * as JSSLOT_PROTO and JSSLOT_PARENT, without a prior js_GetMutableScope. - * See also the JSPROP_SHARED attribute and its usage. - */ - scope = OBJ_SCOPE(obj); - if (scope->ownercx != cx) - js_UnlockScope(cx, scope); -} - -#ifndef NSPR_LOCK - -static JSFatLock * -NewFatlock() -{ - JSFatLock *fl = (JSFatLock *)malloc(sizeof(JSFatLock)); /* for now */ - if (!fl) return NULL; - fl->susp = 0; - fl->next = NULL; - fl->prevp = NULL; - fl->slock = PR_NewLock(); - fl->svar = PR_NewCondVar(fl->slock); - return fl; -} - -static void -DestroyFatlock(JSFatLock *fl) -{ - PR_DestroyLock(fl->slock); - PR_DestroyCondVar(fl->svar); - free(fl); -} - -static JSFatLock * -ListOfFatlocks(int listc) -{ - JSFatLock *m; - JSFatLock *m0; - int i; - - JS_ASSERT(listc>0); - m0 = m = NewFatlock(); - for (i=1; inext = NewFatlock(); - m = m->next; - } - return m0; -} - -static void -DeleteListOfFatlocks(JSFatLock *m) -{ - JSFatLock *m0; - for (; m; m=m0) { - m0 = m->next; - DestroyFatlock(m); - } -} - -static JSFatLockTable *fl_list_table = NULL; -static uint32 fl_list_table_len = 0; -static uint32 fl_list_chunk_len = 0; - -static JSFatLock * -GetFatlock(void *id) -{ - JSFatLock *m; - - uint32 i = GLOBAL_LOCK_INDEX(id); - if (fl_list_table[i].free == NULL) { -#ifdef DEBUG - if (fl_list_table[i].taken) - printf("Ran out of fat locks!\n"); -#endif - fl_list_table[i].free = ListOfFatlocks(fl_list_chunk_len); - } - m = fl_list_table[i].free; - fl_list_table[i].free = m->next; - m->susp = 0; - m->next = fl_list_table[i].taken; - m->prevp = &fl_list_table[i].taken; - if (fl_list_table[i].taken) - fl_list_table[i].taken->prevp = &m->next; - fl_list_table[i].taken = m; - return m; -} - -static void -PutFatlock(JSFatLock *m, void *id) -{ - uint32 i; - if (m == NULL) - return; - - /* Unlink m from fl_list_table[i].taken. */ - *m->prevp = m->next; - if (m->next) - m->next->prevp = m->prevp; - - /* Insert m in fl_list_table[i].free. */ - i = GLOBAL_LOCK_INDEX(id); - m->next = fl_list_table[i].free; - fl_list_table[i].free = m; -} - -#endif /* !NSPR_LOCK */ - -JSBool -js_SetupLocks(int listc, int globc) -{ -#ifndef NSPR_LOCK - uint32 i; - - if (global_locks) - return JS_TRUE; -#ifdef DEBUG - if (listc > 10000 || listc < 0) /* listc == fat lock list chunk length */ - printf("Bad number %d in js_SetupLocks()!\n", listc); - if (globc > 100 || globc < 0) /* globc == number of global locks */ - printf("Bad number %d in js_SetupLocks()!\n", listc); -#endif - global_locks_log2 = JS_CeilingLog2(globc); - global_locks_mask = JS_BITMASK(global_locks_log2); - global_lock_count = JS_BIT(global_locks_log2); - global_locks = (PRLock **) malloc(global_lock_count * sizeof(PRLock*)); - if (!global_locks) - return JS_FALSE; - for (i = 0; i < global_lock_count; i++) { - global_locks[i] = PR_NewLock(); - if (!global_locks[i]) { - global_lock_count = i; - js_CleanupLocks(); - return JS_FALSE; - } - } - fl_list_table = (JSFatLockTable *) malloc(i * sizeof(JSFatLockTable)); - if (!fl_list_table) { - js_CleanupLocks(); - return JS_FALSE; - } - fl_list_table_len = global_lock_count; - for (i = 0; i < global_lock_count; i++) - fl_list_table[i].free = fl_list_table[i].taken = NULL; - fl_list_chunk_len = listc; -#endif /* !NSPR_LOCK */ - return JS_TRUE; -} - -void -js_CleanupLocks() -{ -#ifndef NSPR_LOCK - uint32 i; - - if (global_locks) { - for (i = 0; i < global_lock_count; i++) - PR_DestroyLock(global_locks[i]); - free(global_locks); - global_locks = NULL; - global_lock_count = 1; - global_locks_log2 = 0; - global_locks_mask = 0; - } - if (fl_list_table) { - for (i = 0; i < fl_list_table_len; i++) { - DeleteListOfFatlocks(fl_list_table[i].free); - fl_list_table[i].free = NULL; - DeleteListOfFatlocks(fl_list_table[i].taken); - fl_list_table[i].taken = NULL; - } - free(fl_list_table); - fl_list_table = NULL; - fl_list_table_len = 0; - } -#endif /* !NSPR_LOCK */ -} - -void -js_InitContextForLocking(JSContext *cx) -{ - cx->thread = CurrentThreadId(); - JS_ASSERT(Thin_GetWait(cx->thread) == 0); -} - -#ifndef NSPR_LOCK - -/* - * Fast locking and unlocking is implemented by delaying the allocation of a - * system lock (fat lock) until contention. As long as a locking thread A - * runs uncontended, the lock is represented solely by storing A's identity in - * the object being locked. - * - * If another thread B tries to lock the object currently locked by A, B is - * enqueued into a fat lock structure (which might have to be allocated and - * pointed to by the object), and suspended using NSPR conditional variables - * (wait). A wait bit (Bacon bit) is set in the lock word of the object, - * signalling to A that when releasing the lock, B must be dequeued and - * notified. - * - * The basic operation of the locking primitives (js_Lock, js_Unlock, - * js_Enqueue, and js_Dequeue) is compare-and-swap. Hence, when locking into - * the word pointed at by p, compare-and-swap(p, 0, A) success implies that p - * is unlocked. Similarly, when unlocking p, if compare-and-swap(p, A, 0) - * succeeds this implies that p is uncontended (no one is waiting because the - * wait bit is not set). - * - * When dequeueing, the lock is released, and one of the threads suspended on - * the lock is notified. If other threads still are waiting, the wait bit is - * kept (in js_Enqueue), and if not, the fat lock is deallocated. - * - * The functions js_Enqueue, js_Dequeue, js_SuspendThread, and js_ResumeThread - * are serialized using a global lock. For scalability, a hashtable of global - * locks is used, which is indexed modulo the thin lock pointer. - */ - -/* - * Invariants: - * (i) global lock is held - * (ii) fl->susp >= 0 - */ -static int -js_SuspendThread(JSThinLock *tl) -{ - JSFatLock *fl; - PRStatus stat; - - if (tl->fat == NULL) - fl = tl->fat = GetFatlock(tl); - else - fl = tl->fat; - JS_ASSERT(fl->susp >= 0); - fl->susp++; - PR_Lock(fl->slock); - js_UnlockGlobal(tl); - stat = PR_WaitCondVar(fl->svar, PR_INTERVAL_NO_TIMEOUT); - JS_ASSERT(stat != PR_FAILURE); - PR_Unlock(fl->slock); - js_LockGlobal(tl); - fl->susp--; - if (fl->susp == 0) { - PutFatlock(fl, tl); - tl->fat = NULL; - } - return tl->fat == NULL; -} - -/* - * (i) global lock is held - * (ii) fl->susp > 0 - */ -static void -js_ResumeThread(JSThinLock *tl) -{ - JSFatLock *fl = tl->fat; - PRStatus stat; - - JS_ASSERT(fl != NULL); - JS_ASSERT(fl->susp > 0); - PR_Lock(fl->slock); - js_UnlockGlobal(tl); - stat = PR_NotifyCondVar(fl->svar); - JS_ASSERT(stat != PR_FAILURE); - PR_Unlock(fl->slock); -} - -static void -js_Enqueue(JSThinLock *tl, jsword me) -{ - jsword o, n; - - js_LockGlobal(tl); - for (;;) { - o = ReadWord(tl->owner); - n = Thin_SetWait(o); - if (o != 0 && js_CompareAndSwap(&tl->owner, o, n)) { - if (js_SuspendThread(tl)) - me = Thin_RemoveWait(me); - else - me = Thin_SetWait(me); - } - else if (js_CompareAndSwap(&tl->owner, 0, me)) { - js_UnlockGlobal(tl); - return; - } - } -} - -static void -js_Dequeue(JSThinLock *tl) -{ - jsword o; - - js_LockGlobal(tl); - o = ReadWord(tl->owner); - JS_ASSERT(Thin_GetWait(o) != 0); - JS_ASSERT(tl->fat != NULL); - if (!js_CompareAndSwap(&tl->owner, o, 0)) /* release it */ - JS_ASSERT(0); - js_ResumeThread(tl); -} - -JS_INLINE void -js_Lock(JSThinLock *tl, jsword me) -{ - JS_ASSERT(me == CurrentThreadId()); - if (js_CompareAndSwap(&tl->owner, 0, me)) - return; - if (Thin_RemoveWait(ReadWord(tl->owner)) != me) - js_Enqueue(tl, me); -#ifdef DEBUG - else - JS_ASSERT(0); -#endif -} - -JS_INLINE void -js_Unlock(JSThinLock *tl, jsword me) -{ - JS_ASSERT(me == CurrentThreadId()); - if (js_CompareAndSwap(&tl->owner, me, 0)) - return; - if (Thin_RemoveWait(ReadWord(tl->owner)) == me) - js_Dequeue(tl); -#ifdef DEBUG - else - JS_ASSERT(0); -#endif -} - -#endif /* !NSPR_LOCK */ - -void -js_LockRuntime(JSRuntime *rt) -{ - PR_Lock(rt->rtLock); -#ifdef DEBUG - rt->rtLockOwner = CurrentThreadId(); -#endif -} - -void -js_UnlockRuntime(JSRuntime *rt) -{ -#ifdef DEBUG - rt->rtLockOwner = 0; -#endif - PR_Unlock(rt->rtLock); -} - -void -js_LockScope(JSContext *cx, JSScope *scope) -{ - jsword me = cx->thread; - - JS_ASSERT(me == CurrentThreadId()); - JS_ASSERT(scope->ownercx != cx); - if (CX_THREAD_IS_RUNNING_GC(cx)) - return; - if (scope->ownercx && ClaimScope(scope, cx)) - return; - - if (Thin_RemoveWait(ReadWord(scope->lock.owner)) == me) { - JS_ASSERT(scope->u.count > 0); - LOGIT(scope, '+'); - scope->u.count++; - } else { - JSThinLock *tl = &scope->lock; - JS_LOCK0(tl, me); - JS_ASSERT(scope->u.count == 0); - LOGIT(scope, '1'); - scope->u.count = 1; - } -} - -void -js_UnlockScope(JSContext *cx, JSScope *scope) -{ - jsword me = cx->thread; - - /* We hope compilers use me instead of reloading cx->thread in the macro. */ - if (CX_THREAD_IS_RUNNING_GC(cx)) - return; - if (cx->lockedSealedScope == scope) { - cx->lockedSealedScope = NULL; - return; - } - - /* - * If scope->ownercx is not null, it's likely that two contexts not using - * requests nested locks for scope. The first context, cx here, claimed - * scope; the second, scope->ownercx here, re-claimed it because the first - * was not in a request, or was on the same thread. We don't want to keep - * track of such nesting, because it penalizes the common non-nested case. - * Instead of asserting here and silently coping, we simply re-claim scope - * for cx and return. - * - * See http://bugzilla.mozilla.org/show_bug.cgi?id=229200 for a real world - * case where an asymmetric thread model (Mozilla's main thread is known - * to be the only thread that runs the GC) combined with multiple contexts - * per thread has led to such request-less nesting. - */ - if (scope->ownercx) { - JS_ASSERT(scope->u.count == 0); - JS_ASSERT(scope->lock.owner == 0); - scope->ownercx = cx; - return; - } - - JS_ASSERT(scope->u.count > 0); - if (Thin_RemoveWait(ReadWord(scope->lock.owner)) != me) { - JS_ASSERT(0); /* unbalanced unlock */ - return; - } - LOGIT(scope, '-'); - if (--scope->u.count == 0) { - JSThinLock *tl = &scope->lock; - JS_UNLOCK0(tl, me); - } -} - -/* - * NB: oldscope may be null if our caller is js_GetMutableScope and it just - * dropped the last reference to oldscope. - */ -void -js_TransferScopeLock(JSContext *cx, JSScope *oldscope, JSScope *newscope) -{ - jsword me; - JSThinLock *tl; - - JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, newscope)); - - /* - * If the last reference to oldscope went away, newscope needs no lock - * state update. - */ - if (!oldscope) - return; - JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, oldscope)); - - /* - * Special case in js_LockScope and js_UnlockScope for the GC calling - * code that locks, unlocks, or mutates. Nothing to do in these cases, - * because scope and newscope were "locked" by the GC thread, so neither - * was actually locked. - */ - if (CX_THREAD_IS_RUNNING_GC(cx)) - return; - - /* - * Special case in js_LockObj and js_UnlockScope for locking the sealed - * scope of an object that owns that scope (the prototype or mutated obj - * for which OBJ_SCOPE(obj)->object == obj), and unlocking it. - */ - JS_ASSERT(cx->lockedSealedScope != newscope); - if (cx->lockedSealedScope == oldscope) { - JS_ASSERT(newscope->ownercx == cx || - (!newscope->ownercx && newscope->u.count == 1)); - cx->lockedSealedScope = NULL; - return; - } - - /* - * If oldscope is single-threaded, there's nothing to do. - */ - if (oldscope->ownercx) { - JS_ASSERT(oldscope->ownercx == cx); - JS_ASSERT(newscope->ownercx == cx || - (!newscope->ownercx && newscope->u.count == 1)); - return; - } - - /* - * We transfer oldscope->u.count only if newscope is not single-threaded. - * Flow unwinds from here through some number of JS_UNLOCK_SCOPE and/or - * JS_UNLOCK_OBJ macro calls, which will decrement newscope->u.count only - * if they find newscope->ownercx != cx. - */ - if (newscope->ownercx != cx) { - JS_ASSERT(!newscope->ownercx); - newscope->u.count = oldscope->u.count; - } - - /* - * Reset oldscope's lock state so that it is completely unlocked. - */ - LOGIT(oldscope, '0'); - oldscope->u.count = 0; - tl = &oldscope->lock; - me = cx->thread; - JS_UNLOCK0(tl, me); -} - -void -js_LockObj(JSContext *cx, JSObject *obj) -{ - JSScope *scope; - - JS_ASSERT(OBJ_IS_NATIVE(obj)); - for (;;) { - scope = OBJ_SCOPE(obj); - if (SCOPE_IS_SEALED(scope) && scope->object == obj && - !cx->lockedSealedScope) { - cx->lockedSealedScope = scope; - return; - } - - js_LockScope(cx, scope); - - /* If obj still has this scope, we're done. */ - if (scope == OBJ_SCOPE(obj)) - return; - - /* Lost a race with a mutator; retry with obj's new scope. */ - js_UnlockScope(cx, scope); - } -} - -void -js_UnlockObj(JSContext *cx, JSObject *obj) -{ - JS_ASSERT(OBJ_IS_NATIVE(obj)); - js_UnlockScope(cx, OBJ_SCOPE(obj)); -} - -#ifdef DEBUG - -JSBool -js_IsRuntimeLocked(JSRuntime *rt) -{ - return CurrentThreadId() == rt->rtLockOwner; -} - -JSBool -js_IsObjLocked(JSContext *cx, JSObject *obj) -{ - JSScope *scope = OBJ_SCOPE(obj); - - return MAP_IS_NATIVE(&scope->map) && js_IsScopeLocked(cx, scope); -} - -JSBool -js_IsScopeLocked(JSContext *cx, JSScope *scope) -{ - /* Special case: the GC locking any object's scope, see js_LockScope. */ - if (CX_THREAD_IS_RUNNING_GC(cx)) - return JS_TRUE; - - /* Special case: locked object owning a sealed scope, see js_LockObj. */ - if (cx->lockedSealedScope == scope) - return JS_TRUE; - - /* - * General case: the scope is either exclusively owned (by cx), or it has - * a thin or fat lock to cope with shared (concurrent) ownership. - */ - if (scope->ownercx) { - JS_ASSERT(scope->ownercx == cx); - return JS_TRUE; - } - return CurrentThreadId() == Thin_RemoveWait(ReadWord(scope->lock.owner)); -} - -#endif /* DEBUG */ -#endif /* JS_THREADSAFE */ diff --git a/lib/javascript/jslock.h b/lib/javascript/jslock.h deleted file mode 100644 index 0ab71927..00000000 --- a/lib/javascript/jslock.h +++ /dev/null @@ -1,261 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -#ifndef jslock_h__ -#define jslock_h__ - -#ifdef JS_THREADSAFE - -#include "jstypes.h" -#include "pratom.h" -#include "prlock.h" -#include "prcvar.h" - -#include "jsprvtd.h" /* for JSScope, etc. */ -#include "jspubtd.h" /* for JSRuntime, etc. */ - -#define Thin_GetWait(W) ((jsword)(W) & 0x1) -#define Thin_SetWait(W) ((jsword)(W) | 0x1) -#define Thin_RemoveWait(W) ((jsword)(W) & ~0x1) - -typedef struct JSFatLock JSFatLock; - -struct JSFatLock { - int susp; - PRLock *slock; - PRCondVar *svar; - JSFatLock *next; - JSFatLock **prevp; -}; - -typedef struct JSThinLock { - jsword owner; - JSFatLock *fat; -} JSThinLock; - -typedef PRLock JSLock; - -typedef struct JSFatLockTable { - JSFatLock *free; - JSFatLock *taken; -} JSFatLockTable; - -/* - * Atomic increment and decrement for a reference counter, given jsrefcount *p. - * NB: jsrefcount is int32, aka PRInt32, so that pratom.h functions work. - */ -#define JS_ATOMIC_INCREMENT(p) PR_AtomicIncrement((PRInt32 *)(p)) -#define JS_ATOMIC_DECREMENT(p) PR_AtomicDecrement((PRInt32 *)(p)) -#define JS_ATOMIC_ADD(p,v) PR_AtomicAdd((PRInt32 *)(p), (PRInt32)(v)) - -#define CurrentThreadId() (jsword)PR_GetCurrentThread() -#define JS_CurrentThreadId() js_CurrentThreadId() -#define JS_NEW_LOCK() PR_NewLock() -#define JS_DESTROY_LOCK(l) PR_DestroyLock(l) -#define JS_ACQUIRE_LOCK(l) PR_Lock(l) -#define JS_RELEASE_LOCK(l) PR_Unlock(l) -#define JS_LOCK0(P,M) js_Lock(P,M) -#define JS_UNLOCK0(P,M) js_Unlock(P,M) - -#define JS_NEW_CONDVAR(l) PR_NewCondVar(l) -#define JS_DESTROY_CONDVAR(cv) PR_DestroyCondVar(cv) -#define JS_WAIT_CONDVAR(cv,to) PR_WaitCondVar(cv,to) -#define JS_NO_TIMEOUT PR_INTERVAL_NO_TIMEOUT -#define JS_NOTIFY_CONDVAR(cv) PR_NotifyCondVar(cv) -#define JS_NOTIFY_ALL_CONDVAR(cv) PR_NotifyAllCondVar(cv) - -/* - * Include jsscope.h so JS_LOCK_OBJ macro callers don't have to include it. - * Since there is a JSThinLock member in JSScope, we can't nest this include - * much earlier (see JSThinLock's typedef, above). Yes, that means there is - * an #include cycle between jslock.h and jsscope.h: moderate-sized XXX here, - * to be fixed by moving JS_LOCK_SCOPE to jsscope.h, JS_LOCK_OBJ to jsobj.h, - * and so on. - */ -#include "jsscope.h" - -#define JS_LOCK_RUNTIME(rt) js_LockRuntime(rt) -#define JS_UNLOCK_RUNTIME(rt) js_UnlockRuntime(rt) - -/* - * NB: The JS_LOCK_OBJ and JS_UNLOCK_OBJ macros work *only* on native objects - * (objects for which OBJ_IS_NATIVE returns true). All uses of these macros in - * the engine are predicated on OBJ_IS_NATIVE or equivalent checks. These uses - * are for optimizations above the JSObjectOps layer, under which object locks - * normally hide. - */ -#define JS_LOCK_OBJ(cx,obj) ((OBJ_SCOPE(obj)->ownercx == (cx)) \ - ? (void)0 \ - : (js_LockObj(cx, obj))) -#define JS_UNLOCK_OBJ(cx,obj) ((OBJ_SCOPE(obj)->ownercx == (cx)) \ - ? (void)0 : js_UnlockObj(cx, obj)) - -#define JS_LOCK_SCOPE(cx,scope) ((scope)->ownercx == (cx) ? (void)0 \ - : js_LockScope(cx, scope)) -#define JS_UNLOCK_SCOPE(cx,scope) ((scope)->ownercx == (cx) ? (void)0 \ - : js_UnlockScope(cx, scope)) -#define JS_TRANSFER_SCOPE_LOCK(cx, scope, newscope) \ - js_TransferScopeLock(cx, scope, newscope) - -extern jsword js_CurrentThreadId(); -extern void js_LockRuntime(JSRuntime *rt); -extern void js_UnlockRuntime(JSRuntime *rt); -extern void js_LockObj(JSContext *cx, JSObject *obj); -extern void js_UnlockObj(JSContext *cx, JSObject *obj); -extern void js_LockScope(JSContext *cx, JSScope *scope); -extern void js_UnlockScope(JSContext *cx, JSScope *scope); -extern int js_SetupLocks(int,int); -extern void js_CleanupLocks(); -extern void js_InitContextForLocking(JSContext *); -extern void js_TransferScopeLock(JSContext *, JSScope *, JSScope *); -extern JS_FRIEND_API(jsval) -js_GetSlotThreadSafe(JSContext *, JSObject *, uint32); -extern void js_SetSlotThreadSafe(JSContext *, JSObject *, uint32, jsval); -extern void js_InitLock(JSThinLock *); -extern void js_FinishLock(JSThinLock *); -extern void js_FinishSharingScope(JSRuntime *rt, JSScope *scope); - -#ifdef DEBUG - -#define JS_IS_RUNTIME_LOCKED(rt) js_IsRuntimeLocked(rt) -#define JS_IS_OBJ_LOCKED(cx,obj) js_IsObjLocked(cx,obj) -#define JS_IS_SCOPE_LOCKED(cx,scope) js_IsScopeLocked(cx,scope) - -extern JSBool js_IsRuntimeLocked(JSRuntime *rt); -extern JSBool js_IsObjLocked(JSContext *cx, JSObject *obj); -extern JSBool js_IsScopeLocked(JSContext *cx, JSScope *scope); - -#else - -#define JS_IS_RUNTIME_LOCKED(rt) 0 -#define JS_IS_OBJ_LOCKED(cx,obj) 1 -#define JS_IS_SCOPE_LOCKED(cx,scope) 1 - -#endif /* DEBUG */ - -#define JS_LOCK_OBJ_VOID(cx, obj, e) \ - JS_BEGIN_MACRO \ - JS_LOCK_OBJ(cx, obj); \ - e; \ - JS_UNLOCK_OBJ(cx, obj); \ - JS_END_MACRO - -#define JS_LOCK_VOID(cx, e) \ - JS_BEGIN_MACRO \ - JSRuntime *_rt = (cx)->runtime; \ - JS_LOCK_RUNTIME_VOID(_rt, e); \ - JS_END_MACRO - -#if defined(JS_USE_ONLY_NSPR_LOCKS) || \ - !( (defined(_WIN32) && defined(_M_IX86)) || \ - (defined(__GNUC__) && defined(__i386__)) || \ - (defined(SOLARIS) && defined(sparc) && defined(ULTRA_SPARC)) || \ - defined(AIX) ) - -#define NSPR_LOCK 1 - -#undef JS_LOCK0 -#undef JS_UNLOCK0 -#define JS_LOCK0(P,M) (JS_ACQUIRE_LOCK(((JSLock*)(P)->fat)), (P)->owner = (M)) -#define JS_UNLOCK0(P,M) ((P)->owner = 0, JS_RELEASE_LOCK(((JSLock*)(P)->fat))) - -#else /* arch-tests */ - -#undef NSPR_LOCK - -extern JS_INLINE void js_Lock(JSThinLock *tl, jsword me); -extern JS_INLINE void js_Unlock(JSThinLock *tl, jsword me); - -#endif /* arch-tests */ - -#else /* !JS_THREADSAFE */ - -#define JS_ATOMIC_INCREMENT(p) (++*(p)) -#define JS_ATOMIC_DECREMENT(p) (--*(p)) -#define JS_ATOMIC_ADD(p,v) (*(p) += (v)) - -#define JS_CurrentThreadId() 0 -#define JS_NEW_LOCK() NULL -#define JS_DESTROY_LOCK(l) ((void)0) -#define JS_ACQUIRE_LOCK(l) ((void)0) -#define JS_RELEASE_LOCK(l) ((void)0) -#define JS_LOCK0(P,M) ((void)0) -#define JS_UNLOCK0(P,M) ((void)0) - -#define JS_NEW_CONDVAR(l) NULL -#define JS_DESTROY_CONDVAR(cv) ((void)0) -#define JS_WAIT_CONDVAR(cv,to) ((void)0) -#define JS_NOTIFY_CONDVAR(cv) ((void)0) -#define JS_NOTIFY_ALL_CONDVAR(cv) ((void)0) - -#define JS_LOCK_RUNTIME(rt) ((void)0) -#define JS_UNLOCK_RUNTIME(rt) ((void)0) -#define JS_LOCK_OBJ(cx,obj) ((void)0) -#define JS_UNLOCK_OBJ(cx,obj) ((void)0) -#define JS_LOCK_OBJ_VOID(cx,obj,e) (e) -#define JS_LOCK_SCOPE(cx,scope) ((void)0) -#define JS_UNLOCK_SCOPE(cx,scope) ((void)0) -#define JS_TRANSFER_SCOPE_LOCK(c,o,n) ((void)0) - -#define JS_IS_RUNTIME_LOCKED(rt) 1 -#define JS_IS_OBJ_LOCKED(cx,obj) 1 -#define JS_IS_SCOPE_LOCKED(cx,scope) 1 -#define JS_LOCK_VOID(cx, e) JS_LOCK_RUNTIME_VOID((cx)->runtime, e) - -#endif /* !JS_THREADSAFE */ - -#define JS_LOCK_RUNTIME_VOID(rt,e) \ - JS_BEGIN_MACRO \ - JS_LOCK_RUNTIME(rt); \ - e; \ - JS_UNLOCK_RUNTIME(rt); \ - JS_END_MACRO - -#define JS_LOCK_GC(rt) JS_ACQUIRE_LOCK((rt)->gcLock) -#define JS_UNLOCK_GC(rt) JS_RELEASE_LOCK((rt)->gcLock) -#define JS_LOCK_GC_VOID(rt,e) (JS_LOCK_GC(rt), (e), JS_UNLOCK_GC(rt)) -#define JS_AWAIT_GC_DONE(rt) JS_WAIT_CONDVAR((rt)->gcDone, JS_NO_TIMEOUT) -#define JS_NOTIFY_GC_DONE(rt) JS_NOTIFY_ALL_CONDVAR((rt)->gcDone) -#define JS_AWAIT_REQUEST_DONE(rt) JS_WAIT_CONDVAR((rt)->requestDone, \ - JS_NO_TIMEOUT) -#define JS_NOTIFY_REQUEST_DONE(rt) JS_NOTIFY_CONDVAR((rt)->requestDone) - -#define JS_LOCK(P,CX) JS_LOCK0(P,(CX)->thread) -#define JS_UNLOCK(P,CX) JS_UNLOCK0(P,(CX)->thread) - -#endif /* jslock_h___ */ diff --git a/lib/javascript/jslocko.asm b/lib/javascript/jslocko.asm deleted file mode 100644 index 95353ba1..00000000 --- a/lib/javascript/jslocko.asm +++ /dev/null @@ -1,60 +0,0 @@ -; -*- Mode: asm; tab-width: 8; c-basic-offset: 4 -*- - -; ***** BEGIN LICENSE BLOCK ***** -; Version: MPL 1.1/GPL 2.0/LGPL 2.1 -; -; The contents of this file are subject to the Mozilla Public License Version -; 1.1 (the "License"); you may not use this file except in compliance with -; the License. You may obtain a copy of the License at -; http://www.mozilla.org/MPL/ -; -; Software distributed under the License is distributed on an "AS IS" basis, -; WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -; for the specific language governing rights and limitations under the -; License. -; -; The Original Code is an OS/2 implementation of js_CompareAndSwap in assembly. -; -; The Initial Developer of the Original Code is -; IBM Corporation. -; Portions created by the Initial Developer are Copyright (C) 2001 -; the Initial Developer. All Rights Reserved. -; -; Contributor(s): -; -; Alternatively, the contents of this file may be used under the terms of -; either the GNU General Public License Version 2 or later (the "GPL"), or -; the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -; in which case the provisions of the GPL or the LGPL are applicable instead -; of those above. If you wish to allow use of your version of this file only -; under the terms of either the GPL or the LGPL, and not to allow others to -; use your version of this file under the terms of the MPL, indicate your -; decision by deleting the provisions above and replace them with the notice -; and other provisions required by the GPL or the LGPL. If you do not delete -; the provisions above, a recipient may use your version of this file under -; the terms of any one of the MPL, the GPL or the LGPL. -; -; ***** END LICENSE BLOCK ***** - - .486P - .MODEL FLAT, OPTLINK - .STACK - - .CODE - -;;;--------------------------------------------------------------------- -;;; int _Optlink js_CompareAndSwap(jsword *w, jsword ov, jsword nv) -;;;--------------------------------------------------------------------- -js_CompareAndSwap PROC OPTLINK EXPORT - push ebx - mov ebx, eax - mov eax, edx - mov edx, ebx - lock cmpxchg [ebx], ecx - sete al - and eax, 1h - pop ebx - ret -js_CompareAndSwap endp - - END diff --git a/lib/javascript/jslog2.c b/lib/javascript/jslog2.c deleted file mode 100644 index 9bfca4dd..00000000 --- a/lib/javascript/jslog2.c +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "jsstddef.h" -#include "jsbit.h" - -/* -** Compute the log of the least power of 2 greater than or equal to n -*/ -JS_PUBLIC_API(JSIntn) JS_CeilingLog2(JSUint32 n) -{ - JSIntn log2 = 0; - - if (n & (n-1)) - log2++; - if (n >> 16) - log2 += 16, n >>= 16; - if (n >> 8) - log2 += 8, n >>= 8; - if (n >> 4) - log2 += 4, n >>= 4; - if (n >> 2) - log2 += 2, n >>= 2; - if (n >> 1) - log2++; - return log2; -} - -/* -** Compute the log of the greatest power of 2 less than or equal to n. -** This really just finds the highest set bit in the word. -*/ -JS_PUBLIC_API(JSIntn) JS_FloorLog2(JSUint32 n) -{ - JSIntn log2 = 0; - - if (n >> 16) - log2 += 16, n >>= 16; - if (n >> 8) - log2 += 8, n >>= 8; - if (n >> 4) - log2 += 4, n >>= 4; - if (n >> 2) - log2 += 2, n >>= 2; - if (n >> 1) - log2++; - return log2; -} diff --git a/lib/javascript/jslong.c b/lib/javascript/jslong.c deleted file mode 100644 index 9a4a5b4d..00000000 --- a/lib/javascript/jslong.c +++ /dev/null @@ -1,281 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "jsstddef.h" -#include "jstypes.h" -#include "jslong.h" - -static JSInt64 ll_zero = JSLL_INIT( 0x00000000,0x00000000 ); -static JSInt64 ll_maxint = JSLL_INIT( 0x7fffffff, 0xffffffff ); -static JSInt64 ll_minint = JSLL_INIT( 0x80000000, 0x00000000 ); - -#ifdef HAVE_WATCOM_BUG_2 -JSInt64 __pascal __loadds __export - JSLL_Zero(void) { return ll_zero; } -JSInt64 __pascal __loadds __export - JSLL_MaxInt(void) { return ll_maxint; } -JSInt64 __pascal __loadds __export - JSLL_MinInt(void) { return ll_minint; } -#else -JS_PUBLIC_API(JSInt64) JSLL_Zero(void) { return ll_zero; } -JS_PUBLIC_API(JSInt64) JSLL_MaxInt(void) { return ll_maxint; } -JS_PUBLIC_API(JSInt64) JSLL_MinInt(void) { return ll_minint; } -#endif - -#ifndef JS_HAVE_LONG_LONG -/* -** Divide 64-bit a by 32-bit b, which must be normalized so its high bit is 1. -*/ -static void norm_udivmod32(JSUint32 *qp, JSUint32 *rp, JSUint64 a, JSUint32 b) -{ - JSUint32 d1, d0, q1, q0; - JSUint32 r1, r0, m; - - d1 = jshi16(b); - d0 = jslo16(b); - r1 = a.hi % d1; - q1 = a.hi / d1; - m = q1 * d0; - r1 = (r1 << 16) | jshi16(a.lo); - if (r1 < m) { - q1--, r1 += b; - if (r1 >= b /* i.e., we didn't get a carry when adding to r1 */ - && r1 < m) { - q1--, r1 += b; - } - } - r1 -= m; - r0 = r1 % d1; - q0 = r1 / d1; - m = q0 * d0; - r0 = (r0 << 16) | jslo16(a.lo); - if (r0 < m) { - q0--, r0 += b; - if (r0 >= b - && r0 < m) { - q0--, r0 += b; - } - } - *qp = (q1 << 16) | q0; - *rp = r0 - m; -} - -static JSUint32 CountLeadingZeros(JSUint32 a) -{ - JSUint32 t; - JSUint32 r = 32; - - if ((t = a >> 16) != 0) - r -= 16, a = t; - if ((t = a >> 8) != 0) - r -= 8, a = t; - if ((t = a >> 4) != 0) - r -= 4, a = t; - if ((t = a >> 2) != 0) - r -= 2, a = t; - if ((t = a >> 1) != 0) - r -= 1, a = t; - if (a & 1) - r--; - return r; -} - -JS_PUBLIC_API(void) jsll_udivmod(JSUint64 *qp, JSUint64 *rp, JSUint64 a, JSUint64 b) -{ - JSUint32 n0, n1, n2; - JSUint32 q0, q1; - JSUint32 rsh, lsh; - - n0 = a.lo; - n1 = a.hi; - - if (b.hi == 0) { - if (b.lo > n1) { - /* (0 q0) = (n1 n0) / (0 D0) */ - - lsh = CountLeadingZeros(b.lo); - - if (lsh) { - /* - * Normalize, i.e. make the most significant bit of the - * denominator be set. - */ - b.lo = b.lo << lsh; - n1 = (n1 << lsh) | (n0 >> (32 - lsh)); - n0 = n0 << lsh; - } - - a.lo = n0, a.hi = n1; - norm_udivmod32(&q0, &n0, a, b.lo); - q1 = 0; - - /* remainder is in n0 >> lsh */ - } else { - /* (q1 q0) = (n1 n0) / (0 d0) */ - - if (b.lo == 0) /* user wants to divide by zero! */ - b.lo = 1 / b.lo; /* so go ahead and crash */ - - lsh = CountLeadingZeros(b.lo); - - if (lsh == 0) { - /* - * From (n1 >= b.lo) - * && (the most significant bit of b.lo is set), - * conclude that - * (the most significant bit of n1 is set) - * && (the leading quotient digit q1 = 1). - * - * This special case is necessary, not an optimization - * (Shifts counts of 32 are undefined). - */ - n1 -= b.lo; - q1 = 1; - } else { - /* - * Normalize. - */ - rsh = 32 - lsh; - - b.lo = b.lo << lsh; - n2 = n1 >> rsh; - n1 = (n1 << lsh) | (n0 >> rsh); - n0 = n0 << lsh; - - a.lo = n1, a.hi = n2; - norm_udivmod32(&q1, &n1, a, b.lo); - } - - /* n1 != b.lo... */ - - a.lo = n0, a.hi = n1; - norm_udivmod32(&q0, &n0, a, b.lo); - - /* remainder in n0 >> lsh */ - } - - if (rp) { - rp->lo = n0 >> lsh; - rp->hi = 0; - } - } else { - if (b.hi > n1) { - /* (0 0) = (n1 n0) / (D1 d0) */ - - q0 = 0; - q1 = 0; - - /* remainder in (n1 n0) */ - if (rp) { - rp->lo = n0; - rp->hi = n1; - } - } else { - /* (0 q0) = (n1 n0) / (d1 d0) */ - - lsh = CountLeadingZeros(b.hi); - if (lsh == 0) { - /* - * From (n1 >= b.hi) - * && (the most significant bit of b.hi is set), - * conclude that - * (the most significant bit of n1 is set) - * && (the quotient digit q0 = 0 or 1). - * - * This special case is necessary, not an optimization. - */ - - /* - * The condition on the next line takes advantage of that - * n1 >= b.hi (true due to control flow). - */ - if (n1 > b.hi || n0 >= b.lo) { - q0 = 1; - a.lo = n0, a.hi = n1; - JSLL_SUB(a, a, b); - } else { - q0 = 0; - } - q1 = 0; - - if (rp) { - rp->lo = n0; - rp->hi = n1; - } - } else { - JSInt64 m; - - /* - * Normalize. - */ - rsh = 32 - lsh; - - b.hi = (b.hi << lsh) | (b.lo >> rsh); - b.lo = b.lo << lsh; - n2 = n1 >> rsh; - n1 = (n1 << lsh) | (n0 >> rsh); - n0 = n0 << lsh; - - a.lo = n1, a.hi = n2; - norm_udivmod32(&q0, &n1, a, b.hi); - JSLL_MUL32(m, q0, b.lo); - - if ((m.hi > n1) || ((m.hi == n1) && (m.lo > n0))) { - q0--; - JSLL_SUB(m, m, b); - } - - q1 = 0; - - /* Remainder is ((n1 n0) - (m1 m0)) >> lsh */ - if (rp) { - a.lo = n0, a.hi = n1; - JSLL_SUB(a, a, m); - rp->lo = (a.hi << rsh) | (a.lo >> lsh); - rp->hi = a.hi >> lsh; - } - } - } - } - - if (qp) { - qp->lo = q0; - qp->hi = q1; - } -} -#endif /* !JS_HAVE_LONG_LONG */ diff --git a/lib/javascript/jslong.h b/lib/javascript/jslong.h deleted file mode 100644 index 059cf00b..00000000 --- a/lib/javascript/jslong.h +++ /dev/null @@ -1,437 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* -** File: jslong.h -** Description: Portable access to 64 bit numerics -** -** Long-long (64-bit signed integer type) support. Some C compilers -** don't support 64 bit integers yet, so we use these macros to -** support both machines that do and don't. -**/ -#ifndef jslong_h___ -#define jslong_h___ - -#include "jstypes.h" - -JS_BEGIN_EXTERN_C - -/*********************************************************************** -** DEFINES: JSLL_MaxInt -** JSLL_MinInt -** JSLL_Zero -** DESCRIPTION: -** Various interesting constants and static variable -** initializer -***********************************************************************/ -#ifdef HAVE_WATCOM_BUG_2 -JSInt64 __pascal __loadds __export - JSLL_MaxInt(void); -JSInt64 __pascal __loadds __export - JSLL_MinInt(void); -JSInt64 __pascal __loadds __export - JSLL_Zero(void); -#else -extern JS_PUBLIC_API(JSInt64) JSLL_MaxInt(void); -extern JS_PUBLIC_API(JSInt64) JSLL_MinInt(void); -extern JS_PUBLIC_API(JSInt64) JSLL_Zero(void); -#endif - -#define JSLL_MAXINT JSLL_MaxInt() -#define JSLL_MININT JSLL_MinInt() -#define JSLL_ZERO JSLL_Zero() - -#ifdef JS_HAVE_LONG_LONG - -#if JS_BYTES_PER_LONG == 8 -#define JSLL_INIT(hi, lo) ((hi ## L << 32) + lo ## L) -#elif (defined(WIN32) || defined(WIN16)) && !defined(__GNUC__) -#define JSLL_INIT(hi, lo) ((hi ## i64 << 32) + lo ## i64) -#else -#define JSLL_INIT(hi, lo) ((hi ## LL << 32) + lo ## LL) -#endif - -/*********************************************************************** -** MACROS: JSLL_* -** DESCRIPTION: -** The following macros define portable access to the 64 bit -** math facilities. -** -***********************************************************************/ - -/*********************************************************************** -** MACROS: JSLL_ -** -** JSLL_IS_ZERO Test for zero -** JSLL_EQ Test for equality -** JSLL_NE Test for inequality -** JSLL_GE_ZERO Test for zero or positive -** JSLL_CMP Compare two values -***********************************************************************/ -#define JSLL_IS_ZERO(a) ((a) == 0) -#define JSLL_EQ(a, b) ((a) == (b)) -#define JSLL_NE(a, b) ((a) != (b)) -#define JSLL_GE_ZERO(a) ((a) >= 0) -#define JSLL_CMP(a, op, b) ((JSInt64)(a) op (JSInt64)(b)) -#define JSLL_UCMP(a, op, b) ((JSUint64)(a) op (JSUint64)(b)) - -/*********************************************************************** -** MACROS: JSLL_ -** -** JSLL_AND Logical and -** JSLL_OR Logical or -** JSLL_XOR Logical exclusion -** JSLL_OR2 A disgusting deviation -** JSLL_NOT Negation (one's compliment) -***********************************************************************/ -#define JSLL_AND(r, a, b) ((r) = (a) & (b)) -#define JSLL_OR(r, a, b) ((r) = (a) | (b)) -#define JSLL_XOR(r, a, b) ((r) = (a) ^ (b)) -#define JSLL_OR2(r, a) ((r) = (r) | (a)) -#define JSLL_NOT(r, a) ((r) = ~(a)) - -/*********************************************************************** -** MACROS: JSLL_ -** -** JSLL_NEG Negation (two's compliment) -** JSLL_ADD Summation (two's compliment) -** JSLL_SUB Difference (two's compliment) -***********************************************************************/ -#define JSLL_NEG(r, a) ((r) = -(a)) -#define JSLL_ADD(r, a, b) ((r) = (a) + (b)) -#define JSLL_SUB(r, a, b) ((r) = (a) - (b)) - -/*********************************************************************** -** MACROS: JSLL_ -** -** JSLL_MUL Product (two's compliment) -** JSLL_DIV Quotient (two's compliment) -** JSLL_MOD Modulus (two's compliment) -***********************************************************************/ -#define JSLL_MUL(r, a, b) ((r) = (a) * (b)) -#define JSLL_DIV(r, a, b) ((r) = (a) / (b)) -#define JSLL_MOD(r, a, b) ((r) = (a) % (b)) - -/*********************************************************************** -** MACROS: JSLL_ -** -** JSLL_SHL Shift left [0..64] bits -** JSLL_SHR Shift right [0..64] bits with sign extension -** JSLL_USHR Unsigned shift right [0..64] bits -** JSLL_ISHL Signed shift left [0..64] bits -***********************************************************************/ -#define JSLL_SHL(r, a, b) ((r) = (JSInt64)(a) << (b)) -#define JSLL_SHR(r, a, b) ((r) = (JSInt64)(a) >> (b)) -#define JSLL_USHR(r, a, b) ((r) = (JSUint64)(a) >> (b)) -#define JSLL_ISHL(r, a, b) ((r) = (JSInt64)(a) << (b)) - -/*********************************************************************** -** MACROS: JSLL_ -** -** JSLL_L2I Convert to signed 32 bit -** JSLL_L2UI Convert to unsigned 32 bit -** JSLL_L2F Convert to floating point -** JSLL_L2D Convert to floating point -** JSLL_I2L Convert signed to 64 bit -** JSLL_UI2L Convert unsigned to 64 bit -** JSLL_F2L Convert float to 64 bit -** JSLL_D2L Convert float to 64 bit -***********************************************************************/ -#define JSLL_L2I(i, l) ((i) = (JSInt32)(l)) -#define JSLL_L2UI(ui, l) ((ui) = (JSUint32)(l)) -#define JSLL_L2F(f, l) ((f) = (JSFloat64)(l)) -#define JSLL_L2D(d, l) ((d) = (JSFloat64)(l)) - -#define JSLL_I2L(l, i) ((l) = (JSInt64)(i)) -#define JSLL_UI2L(l, ui) ((l) = (JSInt64)(ui)) -#define JSLL_F2L(l, f) ((l) = (JSInt64)(f)) -#define JSLL_D2L(l, d) ((l) = (JSInt64)(d)) - -/*********************************************************************** -** MACROS: JSLL_UDIVMOD -** DESCRIPTION: -** Produce both a quotient and a remainder given an unsigned -** INPUTS: JSUint64 a: The dividend of the operation -** JSUint64 b: The quotient of the operation -** OUTPUTS: JSUint64 *qp: pointer to quotient -** JSUint64 *rp: pointer to remainder -***********************************************************************/ -#define JSLL_UDIVMOD(qp, rp, a, b) \ - (*(qp) = ((JSUint64)(a) / (b)), \ - *(rp) = ((JSUint64)(a) % (b))) - -#else /* !JS_HAVE_LONG_LONG */ - -#ifdef IS_LITTLE_ENDIAN -#define JSLL_INIT(hi, lo) {JS_INT32(lo), JS_INT32(hi)} -#else -#define JSLL_INIT(hi, lo) {JS_INT32(hi), JS_INT32(lo)} -#endif - -#define JSLL_IS_ZERO(a) (((a).hi == 0) && ((a).lo == 0)) -#define JSLL_EQ(a, b) (((a).hi == (b).hi) && ((a).lo == (b).lo)) -#define JSLL_NE(a, b) (((a).hi != (b).hi) || ((a).lo != (b).lo)) -#define JSLL_GE_ZERO(a) (((a).hi >> 31) == 0) - -#ifdef DEBUG -#define JSLL_CMP(a, op, b) (JS_ASSERT((#op)[1] != '='), JSLL_REAL_CMP(a, op, b)) -#define JSLL_UCMP(a, op, b) (JS_ASSERT((#op)[1] != '='), JSLL_REAL_UCMP(a, op, b)) -#else -#define JSLL_CMP(a, op, b) JSLL_REAL_CMP(a, op, b) -#define JSLL_UCMP(a, op, b) JSLL_REAL_UCMP(a, op, b) -#endif - -#define JSLL_REAL_CMP(a,op,b) (((JSInt32)(a).hi op (JSInt32)(b).hi) || \ - (((a).hi == (b).hi) && ((a).lo op (b).lo))) -#define JSLL_REAL_UCMP(a,op,b) (((a).hi op (b).hi) || \ - (((a).hi == (b).hi) && ((a).lo op (b).lo))) - -#define JSLL_AND(r, a, b) ((r).lo = (a).lo & (b).lo, \ - (r).hi = (a).hi & (b).hi) -#define JSLL_OR(r, a, b) ((r).lo = (a).lo | (b).lo, \ - (r).hi = (a).hi | (b).hi) -#define JSLL_XOR(r, a, b) ((r).lo = (a).lo ^ (b).lo, \ - (r).hi = (a).hi ^ (b).hi) -#define JSLL_OR2(r, a) ((r).lo = (r).lo | (a).lo, \ - (r).hi = (r).hi | (a).hi) -#define JSLL_NOT(r, a) ((r).lo = ~(a).lo, \ - (r).hi = ~(a).hi) - -#define JSLL_NEG(r, a) ((r).lo = -(JSInt32)(a).lo, \ - (r).hi = -(JSInt32)(a).hi - ((r).lo != 0)) -#define JSLL_ADD(r, a, b) { \ - JSInt64 _a, _b; \ - _a = a; _b = b; \ - (r).lo = _a.lo + _b.lo; \ - (r).hi = _a.hi + _b.hi + ((r).lo < _b.lo); \ -} - -#define JSLL_SUB(r, a, b) { \ - JSInt64 _a, _b; \ - _a = a; _b = b; \ - (r).lo = _a.lo - _b.lo; \ - (r).hi = _a.hi - _b.hi - (_a.lo < _b.lo); \ -} - -#define JSLL_MUL(r, a, b) { \ - JSInt64 _a, _b; \ - _a = a; _b = b; \ - JSLL_MUL32(r, _a.lo, _b.lo); \ - (r).hi += _a.hi * _b.lo + _a.lo * _b.hi; \ -} - -#define jslo16(a) ((a) & JS_BITMASK(16)) -#define jshi16(a) ((a) >> 16) - -#define JSLL_MUL32(r, a, b) { \ - JSUint32 _a1, _a0, _b1, _b0, _y0, _y1, _y2, _y3; \ - _a1 = jshi16(a), _a0 = jslo16(a); \ - _b1 = jshi16(b), _b0 = jslo16(b); \ - _y0 = _a0 * _b0; \ - _y1 = _a0 * _b1; \ - _y2 = _a1 * _b0; \ - _y3 = _a1 * _b1; \ - _y1 += jshi16(_y0); /* can't carry */ \ - _y1 += _y2; /* might carry */ \ - if (_y1 < _y2) \ - _y3 += (JSUint32)(JS_BIT(16)); /* propagate */ \ - (r).lo = (jslo16(_y1) << 16) + jslo16(_y0); \ - (r).hi = _y3 + jshi16(_y1); \ -} - -#define JSLL_UDIVMOD(qp, rp, a, b) jsll_udivmod(qp, rp, a, b) - -extern JS_PUBLIC_API(void) jsll_udivmod(JSUint64 *qp, JSUint64 *rp, JSUint64 a, JSUint64 b); - -#define JSLL_DIV(r, a, b) { \ - JSInt64 _a, _b; \ - JSUint32 _negative = (JSInt32)(a).hi < 0; \ - if (_negative) { \ - JSLL_NEG(_a, a); \ - } else { \ - _a = a; \ - } \ - if ((JSInt32)(b).hi < 0) { \ - _negative ^= 1; \ - JSLL_NEG(_b, b); \ - } else { \ - _b = b; \ - } \ - JSLL_UDIVMOD(&(r), 0, _a, _b); \ - if (_negative) \ - JSLL_NEG(r, r); \ -} - -#define JSLL_MOD(r, a, b) { \ - JSInt64 _a, _b; \ - JSUint32 _negative = (JSInt32)(a).hi < 0; \ - if (_negative) { \ - JSLL_NEG(_a, a); \ - } else { \ - _a = a; \ - } \ - if ((JSInt32)(b).hi < 0) { \ - JSLL_NEG(_b, b); \ - } else { \ - _b = b; \ - } \ - JSLL_UDIVMOD(0, &(r), _a, _b); \ - if (_negative) \ - JSLL_NEG(r, r); \ -} - -#define JSLL_SHL(r, a, b) { \ - if (b) { \ - JSInt64 _a; \ - _a = a; \ - if ((b) < 32) { \ - (r).lo = _a.lo << ((b) & 31); \ - (r).hi = (_a.hi << ((b) & 31)) | (_a.lo >> (32 - (b))); \ - } else { \ - (r).lo = 0; \ - (r).hi = _a.lo << ((b) & 31); \ - } \ - } else { \ - (r) = (a); \ - } \ -} - -/* a is an JSInt32, b is JSInt32, r is JSInt64 */ -#define JSLL_ISHL(r, a, b) { \ - if (b) { \ - JSInt64 _a; \ - _a.lo = (a); \ - _a.hi = 0; \ - if ((b) < 32) { \ - (r).lo = (a) << ((b) & 31); \ - (r).hi = ((a) >> (32 - (b))); \ - } else { \ - (r).lo = 0; \ - (r).hi = (a) << ((b) & 31); \ - } \ - } else { \ - (r).lo = (a); \ - (r).hi = 0; \ - } \ -} - -#define JSLL_SHR(r, a, b) { \ - if (b) { \ - JSInt64 _a; \ - _a = a; \ - if ((b) < 32) { \ - (r).lo = (_a.hi << (32 - (b))) | (_a.lo >> ((b) & 31)); \ - (r).hi = (JSInt32)_a.hi >> ((b) & 31); \ - } else { \ - (r).lo = (JSInt32)_a.hi >> ((b) & 31); \ - (r).hi = (JSInt32)_a.hi >> 31; \ - } \ - } else { \ - (r) = (a); \ - } \ -} - -#define JSLL_USHR(r, a, b) { \ - if (b) { \ - JSInt64 _a; \ - _a = a; \ - if ((b) < 32) { \ - (r).lo = (_a.hi << (32 - (b))) | (_a.lo >> ((b) & 31)); \ - (r).hi = _a.hi >> ((b) & 31); \ - } else { \ - (r).lo = _a.hi >> ((b) & 31); \ - (r).hi = 0; \ - } \ - } else { \ - (r) = (a); \ - } \ -} - -#define JSLL_L2I(i, l) ((i) = (l).lo) -#define JSLL_L2UI(ui, l) ((ui) = (l).lo) -#define JSLL_L2F(f, l) { double _d; JSLL_L2D(_d, l); (f) = (JSFloat64)_d; } - -#define JSLL_L2D(d, l) { \ - int _negative; \ - JSInt64 _absval; \ - \ - _negative = (l).hi >> 31; \ - if (_negative) { \ - JSLL_NEG(_absval, l); \ - } else { \ - _absval = l; \ - } \ - (d) = (double)_absval.hi * 4.294967296e9 + _absval.lo; \ - if (_negative) \ - (d) = -(d); \ -} - -#define JSLL_I2L(l, i) { JSInt32 _i = (i) >> 31; (l).lo = (i); (l).hi = _i; } -#define JSLL_UI2L(l, ui) ((l).lo = (ui), (l).hi = 0) -#define JSLL_F2L(l, f) { double _d = (double)f; JSLL_D2L(l, _d); } - -#define JSLL_D2L(l, d) { \ - int _negative; \ - double _absval, _d_hi; \ - JSInt64 _lo_d; \ - \ - _negative = ((d) < 0); \ - _absval = _negative ? -(d) : (d); \ - \ - (l).hi = _absval / 4.294967296e9; \ - (l).lo = 0; \ - JSLL_L2D(_d_hi, l); \ - _absval -= _d_hi; \ - _lo_d.hi = 0; \ - if (_absval < 0) { \ - _lo_d.lo = -_absval; \ - JSLL_SUB(l, l, _lo_d); \ - } else { \ - _lo_d.lo = _absval; \ - JSLL_ADD(l, l, _lo_d); \ - } \ - \ - if (_negative) \ - JSLL_NEG(l, l); \ -} - -#endif /* !JS_HAVE_LONG_LONG */ - -JS_END_EXTERN_C - -#endif /* jslong_h___ */ diff --git a/lib/javascript/jsmath.c b/lib/javascript/jsmath.c deleted file mode 100644 index 19005eaf..00000000 --- a/lib/javascript/jsmath.c +++ /dev/null @@ -1,479 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JS math package. - */ -#include "jsstddef.h" -#include "jslibmath.h" -#include -#include "jstypes.h" -#include "jslong.h" -#include "prmjtime.h" -#include "jsapi.h" -#include "jsatom.h" -#include "jscntxt.h" -#include "jsconfig.h" -#include "jslock.h" -#include "jsmath.h" -#include "jsnum.h" -#include "jsobj.h" - -#ifndef M_E -#define M_E 2.7182818284590452354 -#endif -#ifndef M_LOG2E -#define M_LOG2E 1.4426950408889634074 -#endif -#ifndef M_LOG10E -#define M_LOG10E 0.43429448190325182765 -#endif -#ifndef M_LN2 -#define M_LN2 0.69314718055994530942 -#endif -#ifndef M_LN10 -#define M_LN10 2.30258509299404568402 -#endif -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif -#ifndef M_SQRT2 -#define M_SQRT2 1.41421356237309504880 -#endif -#ifndef M_SQRT1_2 -#define M_SQRT1_2 0.70710678118654752440 -#endif - -static JSConstDoubleSpec math_constants[] = { - {M_E, "E", 0, {0,0,0}}, - {M_LOG2E, "LOG2E", 0, {0,0,0}}, - {M_LOG10E, "LOG10E", 0, {0,0,0}}, - {M_LN2, "LN2", 0, {0,0,0}}, - {M_LN10, "LN10", 0, {0,0,0}}, - {M_PI, "PI", 0, {0,0,0}}, - {M_SQRT2, "SQRT2", 0, {0,0,0}}, - {M_SQRT1_2, "SQRT1_2", 0, {0,0,0}}, - {0,0,0,{0,0,0}} -}; - -static JSClass math_class = { - "Math", - 0, - JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, - JSCLASS_NO_OPTIONAL_MEMBERS -}; - -static JSBool -math_abs(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsdouble x, z; - - if (!js_ValueToNumber(cx, argv[0], &x)) - return JS_FALSE; - z = fd_fabs(x); - return js_NewNumberValue(cx, z, rval); -} - -static JSBool -math_acos(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsdouble x, z; - - if (!js_ValueToNumber(cx, argv[0], &x)) - return JS_FALSE; - z = fd_acos(x); - return js_NewNumberValue(cx, z, rval); -} - -static JSBool -math_asin(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsdouble x, z; - - if (!js_ValueToNumber(cx, argv[0], &x)) - return JS_FALSE; - z = fd_asin(x); - return js_NewNumberValue(cx, z, rval); -} - -static JSBool -math_atan(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsdouble x, z; - - if (!js_ValueToNumber(cx, argv[0], &x)) - return JS_FALSE; - z = fd_atan(x); - return js_NewNumberValue(cx, z, rval); -} - -static JSBool -math_atan2(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsdouble x, y, z; - - if (!js_ValueToNumber(cx, argv[0], &x)) - return JS_FALSE; - if (!js_ValueToNumber(cx, argv[1], &y)) - return JS_FALSE; - z = fd_atan2(x, y); - return js_NewNumberValue(cx, z, rval); -} - -static JSBool -math_ceil(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsdouble x, z; - - if (!js_ValueToNumber(cx, argv[0], &x)) - return JS_FALSE; - z = fd_ceil(x); - return js_NewNumberValue(cx, z, rval); -} - -static JSBool -math_cos(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsdouble x, z; - - if (!js_ValueToNumber(cx, argv[0], &x)) - return JS_FALSE; - z = fd_cos(x); - return js_NewNumberValue(cx, z, rval); -} - -static JSBool -math_exp(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsdouble x, z; - - if (!js_ValueToNumber(cx, argv[0], &x)) - return JS_FALSE; -#ifdef _WIN32 - if (!JSDOUBLE_IS_NaN(x)) { - if (x == *cx->runtime->jsPositiveInfinity) { - *rval = DOUBLE_TO_JSVAL(cx->runtime->jsPositiveInfinity); - return JS_TRUE; - } - if (x == *cx->runtime->jsNegativeInfinity) { - *rval = JSVAL_ZERO; - return JS_TRUE; - } - } -#endif - z = fd_exp(x); - return js_NewNumberValue(cx, z, rval); -} - -static JSBool -math_floor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsdouble x, z; - - if (!js_ValueToNumber(cx, argv[0], &x)) - return JS_FALSE; - z = fd_floor(x); - return js_NewNumberValue(cx, z, rval); -} - -static JSBool -math_log(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsdouble x, z; - - if (!js_ValueToNumber(cx, argv[0], &x)) - return JS_FALSE; - z = fd_log(x); - return js_NewNumberValue(cx, z, rval); -} - -static JSBool -math_max(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsdouble x, z = *cx->runtime->jsNegativeInfinity; - uintN i; - - if (argc == 0) { - *rval = DOUBLE_TO_JSVAL(cx->runtime->jsNegativeInfinity); - return JS_TRUE; - } - for (i = 0; i < argc; i++) { - if (!js_ValueToNumber(cx, argv[i], &x)) - return JS_FALSE; - if (JSDOUBLE_IS_NaN(x)) { - *rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN); - return JS_TRUE; - } - if ((x==0)&&(x==z)&&(fd_copysign(1.0,z)==-1)) - z = x; - else - z = (x > z) ? x : z; - } - return js_NewNumberValue(cx, z, rval); -} - -static JSBool -math_min(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsdouble x, z = *cx->runtime->jsPositiveInfinity; - uintN i; - - if (argc == 0) { - *rval = DOUBLE_TO_JSVAL(cx->runtime->jsPositiveInfinity); - return JS_TRUE; - } - for (i = 0; i < argc; i++) { - if (!js_ValueToNumber(cx, argv[i], &x)) - return JS_FALSE; - if (JSDOUBLE_IS_NaN(x)) { - *rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN); - return JS_TRUE; - } - if ((x==0)&&(x==z)&&(fd_copysign(1.0,x)==-1)) - z = x; - else - z = (x < z) ? x : z; - } - return js_NewNumberValue(cx, z, rval); -} - -static JSBool -math_pow(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsdouble x, y, z; - - if (!js_ValueToNumber(cx, argv[0], &x)) - return JS_FALSE; - if (!js_ValueToNumber(cx, argv[1], &y)) - return JS_FALSE; -#if !JS_USE_FDLIBM_MATH - /* - * Because C99 and ECMA specify different behavior for pow(), - * we need to wrap the libm call to make it ECMA compliant. - */ - if (!JSDOUBLE_IS_FINITE(y) && (x == 1.0 || x == -1.0)) { - *rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN); - return JS_TRUE; - } -#endif - z = fd_pow(x, y); - return js_NewNumberValue(cx, z, rval); -} - -/* - * Math.random() support, lifted from java.util.Random.java. - */ -static void -random_setSeed(JSRuntime *rt, int64 seed) -{ - int64 tmp; - - JSLL_I2L(tmp, 1000); - JSLL_DIV(seed, seed, tmp); - JSLL_XOR(tmp, seed, rt->rngMultiplier); - JSLL_AND(rt->rngSeed, tmp, rt->rngMask); -} - -static void -random_init(JSRuntime *rt) -{ - int64 tmp, tmp2; - - /* Do at most once. */ - if (rt->rngInitialized) - return; - rt->rngInitialized = JS_TRUE; - - /* rt->rngMultiplier = 0x5DEECE66DL */ - JSLL_ISHL(tmp, 0x5, 32); - JSLL_UI2L(tmp2, 0xDEECE66DL); - JSLL_OR(rt->rngMultiplier, tmp, tmp2); - - /* rt->rngAddend = 0xBL */ - JSLL_I2L(rt->rngAddend, 0xBL); - - /* rt->rngMask = (1L << 48) - 1 */ - JSLL_I2L(tmp, 1); - JSLL_SHL(tmp2, tmp, 48); - JSLL_SUB(rt->rngMask, tmp2, tmp); - - /* rt->rngDscale = (jsdouble)(1L << 53) */ - JSLL_SHL(tmp2, tmp, 53); - JSLL_L2D(rt->rngDscale, tmp2); - - /* Finally, set the seed from current time. */ - random_setSeed(rt, PRMJ_Now()); -} - -static uint32 -random_next(JSRuntime *rt, int bits) -{ - int64 nextseed, tmp; - uint32 retval; - - JSLL_MUL(nextseed, rt->rngSeed, rt->rngMultiplier); - JSLL_ADD(nextseed, nextseed, rt->rngAddend); - JSLL_AND(nextseed, nextseed, rt->rngMask); - rt->rngSeed = nextseed; - JSLL_USHR(tmp, nextseed, 48 - bits); - JSLL_L2I(retval, tmp); - return retval; -} - -static jsdouble -random_nextDouble(JSRuntime *rt) -{ - int64 tmp, tmp2; - jsdouble d; - - JSLL_ISHL(tmp, random_next(rt, 26), 27); - JSLL_UI2L(tmp2, random_next(rt, 27)); - JSLL_ADD(tmp, tmp, tmp2); - JSLL_L2D(d, tmp); - return d / rt->rngDscale; -} - -static JSBool -math_random(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSRuntime *rt; - jsdouble z; - - rt = cx->runtime; - JS_LOCK_RUNTIME(rt); - random_init(rt); - z = random_nextDouble(rt); - JS_UNLOCK_RUNTIME(rt); - return js_NewNumberValue(cx, z, rval); -} - -static JSBool -math_round(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsdouble x, z; - - if (!js_ValueToNumber(cx, argv[0], &x)) - return JS_FALSE; - z = fd_copysign(fd_floor(x + 0.5), x); - return js_NewNumberValue(cx, z, rval); -} - -static JSBool -math_sin(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsdouble x, z; - - if (!js_ValueToNumber(cx, argv[0], &x)) - return JS_FALSE; - z = fd_sin(x); - return js_NewNumberValue(cx, z, rval); -} - -static JSBool -math_sqrt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsdouble x, z; - - if (!js_ValueToNumber(cx, argv[0], &x)) - return JS_FALSE; - z = fd_sqrt(x); - return js_NewNumberValue(cx, z, rval); -} - -static JSBool -math_tan(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsdouble x, z; - - if (!js_ValueToNumber(cx, argv[0], &x)) - return JS_FALSE; - z = fd_tan(x); - return js_NewNumberValue(cx, z, rval); -} - -#if JS_HAS_TOSOURCE -static JSBool -math_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - *rval = ATOM_KEY(cx->runtime->atomState.MathAtom); - return JS_TRUE; -} -#endif - -static JSFunctionSpec math_static_methods[] = { -#if JS_HAS_TOSOURCE - {js_toSource_str, math_toSource, 0, 0, 0}, -#endif - {"abs", math_abs, 1, 0, 0}, - {"acos", math_acos, 1, 0, 0}, - {"asin", math_asin, 1, 0, 0}, - {"atan", math_atan, 1, 0, 0}, - {"atan2", math_atan2, 2, 0, 0}, - {"ceil", math_ceil, 1, 0, 0}, - {"cos", math_cos, 1, 0, 0}, - {"exp", math_exp, 1, 0, 0}, - {"floor", math_floor, 1, 0, 0}, - {"log", math_log, 1, 0, 0}, - {"max", math_max, 2, 0, 0}, - {"min", math_min, 2, 0, 0}, - {"pow", math_pow, 2, 0, 0}, - {"random", math_random, 0, 0, 0}, - {"round", math_round, 1, 0, 0}, - {"sin", math_sin, 1, 0, 0}, - {"sqrt", math_sqrt, 1, 0, 0}, - {"tan", math_tan, 1, 0, 0}, - {0,0,0,0,0} -}; - -JSObject * -js_InitMathClass(JSContext *cx, JSObject *obj) -{ - JSObject *Math; - - Math = JS_DefineObject(cx, obj, "Math", &math_class, NULL, 0); - if (!Math) - return NULL; - if (!JS_DefineFunctions(cx, Math, math_static_methods)) - return NULL; - if (!JS_DefineConstDoubles(cx, Math, math_constants)) - return NULL; - return Math; -} diff --git a/lib/javascript/jsmath.h b/lib/javascript/jsmath.h deleted file mode 100644 index b67dba1d..00000000 --- a/lib/javascript/jsmath.h +++ /dev/null @@ -1,55 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* -*- Mode: C; tab-width: 8 -*- - * Copyright (C) 1998-1999 Netscape Communications Corporation, All Rights Reserved. - */ - -#ifndef jsmath_h___ -#define jsmath_h___ -/* - * JS math functions. - */ - -JS_BEGIN_EXTERN_C - -extern JSObject * -js_InitMathClass(JSContext *cx, JSObject *obj); - -JS_END_EXTERN_C - -#endif /* jsmath_h___ */ diff --git a/lib/javascript/jsnum.c b/lib/javascript/jsnum.c deleted file mode 100644 index 8a559630..00000000 --- a/lib/javascript/jsnum.c +++ /dev/null @@ -1,1145 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * IBM Corp. - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JS number type and wrapper class. - */ -#include "jsstddef.h" -#if defined(XP_WIN) || defined(XP_OS2) -#include -#endif -#include -#include -#include -#include -#include -#include "jstypes.h" -#include "jsutil.h" /* Added by JSIFY */ -#include "jsapi.h" -#include "jsatom.h" -#include "jscntxt.h" -#include "jsconfig.h" -#include "jsdtoa.h" -#include "jsgc.h" -#include "jsinterp.h" -#include "jsnum.h" -#include "jsobj.h" -#include "jsopcode.h" -#include "jsprf.h" -#include "jsstr.h" - -static JSBool -num_isNaN(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsdouble x; - - if (!js_ValueToNumber(cx, argv[0], &x)) - return JS_FALSE; - *rval = BOOLEAN_TO_JSVAL(JSDOUBLE_IS_NaN(x)); - return JS_TRUE; -} - -static JSBool -num_isFinite(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsdouble x; - - if (!js_ValueToNumber(cx, argv[0], &x)) - return JS_FALSE; - *rval = BOOLEAN_TO_JSVAL(JSDOUBLE_IS_FINITE(x)); - return JS_TRUE; -} - -static JSBool -num_parseFloat(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSString *str; - jsdouble d; - const jschar *bp, *ep; - - str = js_ValueToString(cx, argv[0]); - if (!str) - return JS_FALSE; - /* XXXbe js_strtod shouldn't require NUL termination */ - bp = js_UndependString(cx, str); - if (!bp) - return JS_FALSE; - if (!js_strtod(cx, bp, &ep, &d)) - return JS_FALSE; - if (ep == bp) { - *rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN); - return JS_TRUE; - } - return js_NewNumberValue(cx, d, rval); -} - -/* See ECMA 15.1.2.2. */ -static JSBool -num_parseInt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsint radix; - JSString *str; - jsdouble d; - const jschar *bp, *ep; - - if (argc > 1) { - if (!js_ValueToECMAInt32(cx, argv[1], &radix)) - return JS_FALSE; - } else { - radix = 0; - } - if (radix != 0 && (radix < 2 || radix > 36)) { - *rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN); - return JS_TRUE; - } - - str = js_ValueToString(cx, argv[0]); - if (!str) - return JS_FALSE; - /* XXXbe js_strtointeger shouldn't require NUL termination */ - bp = js_UndependString(cx, str); - if (!bp) - return JS_FALSE; - if (!js_strtointeger(cx, bp, &ep, radix, &d)) - return JS_FALSE; - if (ep == bp) { - *rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN); - return JS_TRUE; - } - return js_NewNumberValue(cx, d, rval); -} - -const char js_Infinity_str[] = "Infinity"; -const char js_NaN_str[] = "NaN"; -const char js_isNaN_str[] = "isNaN"; -const char js_isFinite_str[] = "isFinite"; -const char js_parseFloat_str[] = "parseFloat"; -const char js_parseInt_str[] = "parseInt"; - -static JSFunctionSpec number_functions[] = { - {"isNaN", num_isNaN, 1,0,0}, - {"isFinite", num_isFinite, 1,0,0}, - {"parseFloat", num_parseFloat, 1,0,0}, - {"parseInt", num_parseInt, 2,0,0}, - {0,0,0,0,0} -}; - -JSClass js_NumberClass = { - "Number", - JSCLASS_HAS_PRIVATE, - JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, - JSCLASS_NO_OPTIONAL_MEMBERS -}; - -static JSBool -Number(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsdouble d; - jsval v; - - if (argc != 0) { - if (!js_ValueToNumber(cx, argv[0], &d)) - return JS_FALSE; - } else { - d = 0.0; - } - if (!js_NewNumberValue(cx, d, &v)) - return JS_FALSE; - if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) { - *rval = v; - return JS_TRUE; - } - OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, v); - return JS_TRUE; -} - -#if JS_HAS_TOSOURCE -static JSBool -num_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsval v; - jsdouble d; - char numBuf[DTOSTR_STANDARD_BUFFER_SIZE], *numStr; - char buf[64]; - JSString *str; - - if (!JS_InstanceOf(cx, obj, &js_NumberClass, argv)) - return JS_FALSE; - v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE); - JS_ASSERT(JSVAL_IS_NUMBER(v)); - d = JSVAL_IS_INT(v) ? (jsdouble)JSVAL_TO_INT(v) : *JSVAL_TO_DOUBLE(v); - numStr = JS_dtostr(numBuf, sizeof numBuf, DTOSTR_STANDARD, 0, d); - if (!numStr) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - JS_snprintf(buf, sizeof buf, "(new %s(%s))", js_NumberClass.name, numStr); - str = JS_NewStringCopyZ(cx, buf); - if (!str) - return JS_FALSE; - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} -#endif - -/* The buf must be big enough for MIN_INT to fit including '-' and '\0'. */ -static char * -IntToString(jsint i, char *buf, size_t bufSize) -{ - char *cp; - jsuint u; - - u = (i < 0) ? -i : i; - - cp = buf + bufSize; /* one past last buffer cell */ - *--cp = '\0'; /* null terminate the string to be */ - - /* - * Build the string from behind. We use multiply and subtraction - * instead of modulus because that's much faster. - */ - do { - jsuint newu = u / 10; - *--cp = (char)(u - newu * 10) + '0'; - u = newu; - } while (u != 0); - - if (i < 0) - *--cp = '-'; - - return cp; -} - -static JSBool -num_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsval v; - jsdouble d; - jsint base; - JSString *str; - - if (!JS_InstanceOf(cx, obj, &js_NumberClass, argv)) - return JS_FALSE; - v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE); - JS_ASSERT(JSVAL_IS_NUMBER(v)); - d = JSVAL_IS_INT(v) ? (jsdouble)JSVAL_TO_INT(v) : *JSVAL_TO_DOUBLE(v); - base = 10; - if (argc != 0) { - if (!js_ValueToECMAInt32(cx, argv[0], &base)) - return JS_FALSE; - if (base < 2 || base > 36) { - char numBuf[12]; - char *numStr = IntToString(base, numBuf, sizeof numBuf); - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_RADIX, - numStr); - return JS_FALSE; - } - } - if (base == 10) - str = js_NumberToString(cx, d); - else { - char *dStr = JS_dtobasestr(base, d); - if (!dStr) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - str = JS_NewStringCopyZ(cx, dStr); - free(dStr); - } - if (!str) - return JS_FALSE; - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -static JSBool -num_toLocaleString(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval) -{ - char thousandsLength, decimalLength; - const char *numGrouping, *tmpGroup; - JSRuntime *rt; - JSString *numStr, *str; - char *num, *buf, *dec, *end, *tmpSrc, *tmpDest; - int digits, size, remainder, nrepeat; - - /* - * Create the string, move back to bytes to make string twiddling - * a bit easier and so we can insert platform charset seperators. - */ - if (!num_toString(cx, obj, 0, argv, rval)) - return JS_FALSE; - JS_ASSERT(JSVAL_IS_STRING(*rval)); - numStr = JSVAL_TO_STRING(*rval); - num = js_GetStringBytes(numStr); - - /* Find bit before the decimal. */ - dec = strchr(num, '.'); - digits = dec ? dec - num : (int)strlen(num); - end = num + digits; - - rt = cx->runtime; - thousandsLength = strlen(rt->thousandsSeparator); - decimalLength = strlen(rt->decimalSeparator); - - /* Figure out how long resulting string will be. */ - size = digits + (dec ? decimalLength + strlen(dec + 1) : 0); - - numGrouping = tmpGroup = rt->numGrouping; - remainder = digits; - if (*num == '-') - remainder--; - - while (*tmpGroup != CHAR_MAX && *tmpGroup != '\0') { - if (*tmpGroup >= remainder) - break; - size += thousandsLength; - remainder -= *tmpGroup; - tmpGroup++; - } - if (*tmpGroup == '\0' && *numGrouping != '\0') { - nrepeat = (remainder - 1) / tmpGroup[-1]; - size += thousandsLength * nrepeat; - remainder -= nrepeat * tmpGroup[-1]; - } else { - nrepeat = 0; - } - tmpGroup--; - - buf = (char *)JS_malloc(cx, size + 1); - if (!buf) - return JS_FALSE; - - tmpDest = buf; - tmpSrc = num; - - while (*tmpSrc == '-' || remainder--) - *tmpDest++ = *tmpSrc++; - while (tmpSrc < end) { - strcpy(tmpDest, rt->thousandsSeparator); - tmpDest += thousandsLength; - memcpy(tmpDest, tmpSrc, *tmpGroup); - tmpDest += *tmpGroup; - tmpSrc += *tmpGroup; - if (--nrepeat < 0) - tmpGroup--; - } - - if (dec) { - strcpy(tmpDest, rt->decimalSeparator); - tmpDest += decimalLength; - strcpy(tmpDest, dec + 1); - } else { - *tmpDest++ = '\0'; - } - - str = JS_NewString(cx, buf, size); - if (!str) { - JS_free(cx, buf); - return JS_FALSE; - } - - *rval = STRING_TO_JSVAL(str); - - return JS_TRUE; -} - -static JSBool -num_valueOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - if (!JS_InstanceOf(cx, obj, &js_NumberClass, argv)) - return JS_FALSE; - *rval = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE); - return JS_TRUE; -} - - -#if JS_HAS_NUMBER_FORMATS -#define MAX_PRECISION 100 - -static JSBool -num_to(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval, JSDToStrMode zeroArgMode, - JSDToStrMode oneArgMode, jsint precisionMin, jsint precisionMax, jsint precisionOffset) -{ - jsval v; - jsdouble d, precision; - JSString *str; - char buf[DTOSTR_VARIABLE_BUFFER_SIZE(MAX_PRECISION+1)], *numStr; /* Use MAX_PRECISION+1 because precisionOffset can be 1 */ - - if (!JS_InstanceOf(cx, obj, &js_NumberClass, argv)) - return JS_FALSE; - v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE); - JS_ASSERT(JSVAL_IS_NUMBER(v)); - d = JSVAL_IS_INT(v) ? (jsdouble)JSVAL_TO_INT(v) : *JSVAL_TO_DOUBLE(v); - - if (JSVAL_IS_VOID(argv[0])) { - precision = 0.0; - oneArgMode = zeroArgMode; - } else { - if (!js_ValueToNumber(cx, argv[0], &precision)) - return JS_FALSE; - precision = js_DoubleToInteger(precision); - if (precision < precisionMin || precision > precisionMax) { - numStr = JS_dtostr(buf, sizeof buf, DTOSTR_STANDARD, 0, precision); - if (!numStr) - JS_ReportOutOfMemory(cx); - else - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_PRECISION_RANGE, numStr); - return JS_FALSE; - } - } - - numStr = JS_dtostr(buf, sizeof buf, oneArgMode, (jsint)precision + precisionOffset, d); - if (!numStr) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - str = JS_NewStringCopyZ(cx, numStr); - if (!str) - return JS_FALSE; - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -static JSBool -num_toFixed(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - /* We allow a larger range of precision than ECMA requires; this is permitted by ECMA. */ - return num_to(cx, obj, argc, argv, rval, DTOSTR_FIXED, DTOSTR_FIXED, -20, MAX_PRECISION, 0); -} - -static JSBool -num_toExponential(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - /* We allow a larger range of precision than ECMA requires; this is permitted by ECMA. */ - return num_to(cx, obj, argc, argv, rval, DTOSTR_STANDARD_EXPONENTIAL, DTOSTR_EXPONENTIAL, 0, MAX_PRECISION, 1); -} - -static JSBool -num_toPrecision(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - /* We allow a larger range of precision than ECMA requires; this is permitted by ECMA. */ - return num_to(cx, obj, argc, argv, rval, DTOSTR_STANDARD, DTOSTR_PRECISION, 1, MAX_PRECISION, 0); -} -#endif /* JS_HAS_NUMBER_FORMATS */ - - -static JSFunctionSpec number_methods[] = { -#if JS_HAS_TOSOURCE - {js_toSource_str, num_toSource, 0,0,0}, -#endif - {js_toString_str, num_toString, 0,0,0}, - {js_toLocaleString_str, num_toLocaleString, 0,0,0}, - {js_valueOf_str, num_valueOf, 0,0,0}, -#if JS_HAS_NUMBER_FORMATS - {"toFixed", num_toFixed, 1,0,0}, - {"toExponential", num_toExponential, 1,0,0}, - {"toPrecision", num_toPrecision, 1,0,0}, -#endif - {0,0,0,0,0} -}; - -/* NB: Keep this in synch with number_constants[]. */ -enum nc_slot { - NC_NaN, - NC_POSITIVE_INFINITY, - NC_NEGATIVE_INFINITY, - NC_MAX_VALUE, - NC_MIN_VALUE, - NC_LIMIT -}; - -/* - * Some to most C compilers forbid spelling these at compile time, or barf - * if you try, so all but MAX_VALUE are set up by js_InitRuntimeNumberState - * using union jsdpun. - */ -static JSConstDoubleSpec number_constants[] = { - {0, js_NaN_str, 0,{0,0,0}}, - {0, "POSITIVE_INFINITY", 0,{0,0,0}}, - {0, "NEGATIVE_INFINITY", 0,{0,0,0}}, - {1.7976931348623157E+308, "MAX_VALUE", 0,{0,0,0}}, - {0, "MIN_VALUE", 0,{0,0,0}}, - {0,0,0,{0,0,0}} -}; - -static jsdouble NaN; - - -#if (defined XP_WIN || defined XP_OS2) && \ - !defined WINCE && \ - !defined __MWERKS__ && \ - (defined _M_IX86 || \ - (defined __GNUC__ && !defined __MINGW32__)) - -/* - * Set the exception mask to mask all exceptions and set the FPU precision - * to 53 bit mantissa. - * On Alpha platform this is handled via Compiler option. - */ -#define FIX_FPU() _control87(MCW_EM | PC_53, MCW_EM | MCW_PC) - -#else - -#define FIX_FPU() ((void)0) - -#endif - -JSBool -js_InitRuntimeNumberState(JSContext *cx) -{ - JSRuntime *rt; - jsdpun u; - struct lconv *locale; - - rt = cx->runtime; - JS_ASSERT(!rt->jsNaN); - - FIX_FPU(); - - u.s.hi = JSDOUBLE_HI32_EXPMASK | JSDOUBLE_HI32_MANTMASK; - u.s.lo = 0xffffffff; - number_constants[NC_NaN].dval = NaN = u.d; - rt->jsNaN = js_NewDouble(cx, NaN, GCF_LOCK); - if (!rt->jsNaN) - return JS_FALSE; - - u.s.hi = JSDOUBLE_HI32_EXPMASK; - u.s.lo = 0x00000000; - number_constants[NC_POSITIVE_INFINITY].dval = u.d; - rt->jsPositiveInfinity = js_NewDouble(cx, u.d, GCF_LOCK); - if (!rt->jsPositiveInfinity) - return JS_FALSE; - - u.s.hi = JSDOUBLE_HI32_SIGNBIT | JSDOUBLE_HI32_EXPMASK; - u.s.lo = 0x00000000; - number_constants[NC_NEGATIVE_INFINITY].dval = u.d; - rt->jsNegativeInfinity = js_NewDouble(cx, u.d, GCF_LOCK); - if (!rt->jsNegativeInfinity) - return JS_FALSE; - - u.s.hi = 0; - u.s.lo = 1; - number_constants[NC_MIN_VALUE].dval = u.d; - - locale = localeconv(); - rt->thousandsSeparator = - JS_strdup(cx, locale->thousands_sep ? locale->thousands_sep : "'"); - rt->decimalSeparator = - JS_strdup(cx, locale->decimal_point ? locale->decimal_point : "."); - rt->numGrouping = - JS_strdup(cx, locale->grouping ? locale->grouping : "\3\0"); - - return rt->thousandsSeparator && rt->decimalSeparator && rt->numGrouping; -} - -void -js_FinishRuntimeNumberState(JSContext *cx) -{ - JSRuntime *rt = cx->runtime; - - js_UnlockGCThingRT(rt, rt->jsNaN); - js_UnlockGCThingRT(rt, rt->jsNegativeInfinity); - js_UnlockGCThingRT(rt, rt->jsPositiveInfinity); - - rt->jsNaN = NULL; - rt->jsNegativeInfinity = NULL; - rt->jsPositiveInfinity = NULL; - - JS_free(cx, (void *)rt->thousandsSeparator); - JS_free(cx, (void *)rt->decimalSeparator); - JS_free(cx, (void *)rt->numGrouping); - rt->thousandsSeparator = rt->decimalSeparator = rt->numGrouping = NULL; -} - -JSObject * -js_InitNumberClass(JSContext *cx, JSObject *obj) -{ - JSObject *proto, *ctor; - JSRuntime *rt; - - /* XXX must do at least once per new thread, so do it per JSContext... */ - FIX_FPU(); - - if (!JS_DefineFunctions(cx, obj, number_functions)) - return NULL; - - proto = JS_InitClass(cx, obj, NULL, &js_NumberClass, Number, 1, - NULL, number_methods, NULL, NULL); - if (!proto || !(ctor = JS_GetConstructor(cx, proto))) - return NULL; - OBJ_SET_SLOT(cx, proto, JSSLOT_PRIVATE, JSVAL_ZERO); - if (!JS_DefineConstDoubles(cx, ctor, number_constants)) - return NULL; - - /* ECMA 15.1.1.1 */ - rt = cx->runtime; - if (!JS_DefineProperty(cx, obj, js_NaN_str, DOUBLE_TO_JSVAL(rt->jsNaN), - NULL, NULL, JSPROP_PERMANENT)) { - return NULL; - } - - /* ECMA 15.1.1.2 */ - if (!JS_DefineProperty(cx, obj, js_Infinity_str, - DOUBLE_TO_JSVAL(rt->jsPositiveInfinity), - NULL, NULL, JSPROP_PERMANENT)) { - return NULL; - } - return proto; -} - -jsdouble * -js_NewDouble(JSContext *cx, jsdouble d, uintN gcflag) -{ - jsdouble *dp; - - dp = (jsdouble *) js_NewGCThing(cx, gcflag | GCX_DOUBLE, sizeof(jsdouble)); - if (!dp) - return NULL; - *dp = d; - return dp; -} - -void -js_FinalizeDouble(JSContext *cx, jsdouble *dp) -{ - *dp = NaN; -} - -JSBool -js_NewDoubleValue(JSContext *cx, jsdouble d, jsval *rval) -{ - jsdouble *dp; - - dp = js_NewDouble(cx, d, 0); - if (!dp) - return JS_FALSE; - *rval = DOUBLE_TO_JSVAL(dp); - return JS_TRUE; -} - -JSBool -js_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval) -{ - jsint i; - - if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i)) { - *rval = INT_TO_JSVAL(i); - } else { - if (!js_NewDoubleValue(cx, d, rval)) - return JS_FALSE; - } - return JS_TRUE; -} - -JSObject * -js_NumberToObject(JSContext *cx, jsdouble d) -{ - JSObject *obj; - jsval v; - - obj = js_NewObject(cx, &js_NumberClass, NULL, NULL); - if (!obj) - return NULL; - if (!js_NewNumberValue(cx, d, &v)) { - cx->newborn[GCX_OBJECT] = NULL; - return NULL; - } - OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, v); - return obj; -} - -JSString * -js_NumberToString(JSContext *cx, jsdouble d) -{ - jsint i; - char buf[DTOSTR_STANDARD_BUFFER_SIZE]; - char *numStr; - - if (JSDOUBLE_IS_INT(d, i)) - numStr = IntToString(i, buf, sizeof buf); - else { - numStr = JS_dtostr(buf, sizeof buf, DTOSTR_STANDARD, 0, d); - if (!numStr) { - JS_ReportOutOfMemory(cx); - return NULL; - } - } - return JS_NewStringCopyZ(cx, numStr); -} - -JSBool -js_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp) -{ - JSObject *obj; - JSString *str; - const jschar *bp, *ep; - - if (JSVAL_IS_OBJECT(v)) { - obj = JSVAL_TO_OBJECT(v); - if (!obj) { - *dp = 0; - return JS_TRUE; - } - if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_NUMBER, &v)) - return JS_FALSE; - } - if (JSVAL_IS_INT(v)) { - *dp = (jsdouble)JSVAL_TO_INT(v); - } else if (JSVAL_IS_DOUBLE(v)) { - *dp = *JSVAL_TO_DOUBLE(v); - } else if (JSVAL_IS_STRING(v)) { - str = JSVAL_TO_STRING(v); - /* - * Note that ECMA doesn't treat a string beginning with a '0' as an - * octal number here. This works because all such numbers will be - * interpreted as decimal by js_strtod and will never get passed to - * js_strtointeger (which would interpret them as octal). - */ - /* XXXbe js_strtod shouldn't require NUL termination */ - bp = js_UndependString(cx, str); - if (!bp) - return JS_FALSE; - if ((!js_strtod(cx, bp, &ep, dp) || - js_SkipWhiteSpace(ep) != bp + str->length) && - (!js_strtointeger(cx, bp, &ep, 0, dp) || - js_SkipWhiteSpace(ep) != bp + str->length)) { - goto badstr; - } - } else if (JSVAL_IS_BOOLEAN(v)) { - *dp = JSVAL_TO_BOOLEAN(v) ? 1 : 0; - } else { -#if JS_BUG_FALLIBLE_TONUM - str = js_DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, v, NULL); -badstr: - if (str) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NAN, - JS_GetStringBytes(str)); - - } - return JS_FALSE; -#else -badstr: - *dp = *cx->runtime->jsNaN; -#endif - } - return JS_TRUE; -} - -JSBool -js_ValueToECMAInt32(JSContext *cx, jsval v, int32 *ip) -{ - jsdouble d; - - if (!js_ValueToNumber(cx, v, &d)) - return JS_FALSE; - return js_DoubleToECMAInt32(cx, d, ip); -} - -JSBool -js_DoubleToECMAInt32(JSContext *cx, jsdouble d, int32 *ip) -{ - jsdouble two32 = 4294967296.0; - jsdouble two31 = 2147483648.0; - - if (!JSDOUBLE_IS_FINITE(d) || d == 0) { - *ip = 0; - return JS_TRUE; - } - d = fmod(d, two32); - d = (d >= 0) ? floor(d) : ceil(d) + two32; - if (d >= two31) - *ip = (int32)(d - two32); - else - *ip = (int32)d; - return JS_TRUE; -} - -JSBool -js_ValueToECMAUint32(JSContext *cx, jsval v, uint32 *ip) -{ - jsdouble d; - - if (!js_ValueToNumber(cx, v, &d)) - return JS_FALSE; - return js_DoubleToECMAUint32(cx, d, ip); -} - -JSBool -js_DoubleToECMAUint32(JSContext *cx, jsdouble d, uint32 *ip) -{ - JSBool neg; - jsdouble two32 = 4294967296.0; - - if (!JSDOUBLE_IS_FINITE(d) || d == 0) { - *ip = 0; - return JS_TRUE; - } - - neg = (d < 0); - d = floor(neg ? -d : d); - d = neg ? -d : d; - - d = fmod(d, two32); - - d = (d >= 0) ? d : d + two32; - *ip = (uint32)d; - return JS_TRUE; -} - -JSBool -js_ValueToInt32(JSContext *cx, jsval v, int32 *ip) -{ - jsdouble d; - JSString *str; - - if (JSVAL_IS_INT(v)) { - *ip = JSVAL_TO_INT(v); - return JS_TRUE; - } - if (!js_ValueToNumber(cx, v, &d)) - return JS_FALSE; - if (JSDOUBLE_IS_NaN(d) || d <= -2147483649.0 || 2147483648.0 <= d) { - str = js_DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, v, NULL); - if (str) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_CANT_CONVERT, JS_GetStringBytes(str)); - - } - return JS_FALSE; - } - *ip = (int32)floor(d + 0.5); /* Round to nearest */ - return JS_TRUE; -} - -JSBool -js_ValueToUint16(JSContext *cx, jsval v, uint16 *ip) -{ - jsdouble d; - jsuint i, m; - JSBool neg; - - if (!js_ValueToNumber(cx, v, &d)) - return JS_FALSE; - if (d == 0 || !JSDOUBLE_IS_FINITE(d)) { - *ip = 0; - return JS_TRUE; - } - i = (jsuint)d; - if ((jsdouble)i == d) { - *ip = (uint16)i; - return JS_TRUE; - } - neg = (d < 0); - d = floor(neg ? -d : d); - d = neg ? -d : d; - m = JS_BIT(16); - d = fmod(d, (double)m); - if (d < 0) - d += m; - *ip = (uint16) d; - return JS_TRUE; -} - -jsdouble -js_DoubleToInteger(jsdouble d) -{ - JSBool neg; - - if (d == 0) - return d; - if (!JSDOUBLE_IS_FINITE(d)) { - if (JSDOUBLE_IS_NaN(d)) - return 0; - return d; - } - neg = (d < 0); - d = floor(neg ? -d : d); - return neg ? -d : d; -} - - -JSBool -js_strtod(JSContext *cx, const jschar *s, const jschar **ep, jsdouble *dp) -{ - char cbuf[32]; - size_t i; - char *cstr, *istr, *estr; - JSBool negative; - jsdouble d; - const jschar *s1 = js_SkipWhiteSpace(s); - size_t length = js_strlen(s1); - - /* Use cbuf to avoid malloc */ - if (length >= sizeof cbuf) { - cstr = (char *) JS_malloc(cx, length + 1); - if (!cstr) - return JS_FALSE; - } else { - cstr = cbuf; - } - - for (i = 0; i <= length; i++) { - if (s1[i] >> 8) { - cstr[i] = 0; - break; - } - cstr[i] = (char)s1[i]; - } - - istr = cstr; - if ((negative = (*istr == '-')) != 0 || *istr == '+') - istr++; - if (!strncmp(istr, js_Infinity_str, sizeof js_Infinity_str - 1)) { - d = *(negative ? cx->runtime->jsNegativeInfinity : cx->runtime->jsPositiveInfinity); - estr = istr + 8; - } else { - int err; - d = JS_strtod(cstr, &estr, &err); - if (err == JS_DTOA_ENOMEM) { - JS_ReportOutOfMemory(cx); - if (cstr != cbuf) - JS_free(cx, cstr); - return JS_FALSE; - } - if (err == JS_DTOA_ERANGE) { - if (d == HUGE_VAL) - d = *cx->runtime->jsPositiveInfinity; - else if (d == -HUGE_VAL) - d = *cx->runtime->jsNegativeInfinity; - } -#ifdef HPUX - if (d == 0.0 && negative) { - /* - * "-0", "-1e-2000" come out as positive zero - * here on HPUX. Force a negative zero instead. - */ - JSDOUBLE_HI32(d) = JSDOUBLE_HI32_SIGNBIT; - JSDOUBLE_LO32(d) = 0; - } -#endif - } - - i = estr - cstr; - if (cstr != cbuf) - JS_free(cx, cstr); - *ep = i ? s1 + i : s; - *dp = d; - return JS_TRUE; -} - -struct BinaryDigitReader -{ - uintN base; /* Base of number; must be a power of 2 */ - uintN digit; /* Current digit value in radix given by base */ - uintN digitMask; /* Mask to extract the next bit from digit */ - const jschar *digits; /* Pointer to the remaining digits */ - const jschar *end; /* Pointer to first non-digit */ -}; - -/* Return the next binary digit from the number or -1 if done */ -static intN GetNextBinaryDigit(struct BinaryDigitReader *bdr) -{ - intN bit; - - if (bdr->digitMask == 0) { - uintN c; - - if (bdr->digits == bdr->end) - return -1; - - c = *bdr->digits++; - if ('0' <= c && c <= '9') - bdr->digit = c - '0'; - else if ('a' <= c && c <= 'z') - bdr->digit = c - 'a' + 10; - else bdr->digit = c - 'A' + 10; - bdr->digitMask = bdr->base >> 1; - } - bit = (bdr->digit & bdr->digitMask) != 0; - bdr->digitMask >>= 1; - return bit; -} - -JSBool -js_strtointeger(JSContext *cx, const jschar *s, const jschar **ep, jsint base, jsdouble *dp) -{ - JSBool negative; - jsdouble value; - const jschar *start; - const jschar *s1 = js_SkipWhiteSpace(s); - - if ((negative = (*s1 == '-')) != 0 || *s1 == '+') - s1++; - - if (base == 0) { - /* No base supplied, or some base that evaluated to 0. */ - if (*s1 == '0') { - /* It's either hex or octal; only increment char if str isn't '0' */ - if (s1[1] == 'X' || s1[1] == 'x') { /* Hex */ - s1 += 2; - base = 16; - } else { /* Octal */ - base = 8; - } - } else { - base = 10; /* Default to decimal. */ - } - } else if (base == 16 && *s1 == '0' && (s1[1] == 'X' || s1[1] == 'x')) { - /* If base is 16, ignore hex prefix. */ - s1 += 2; - } - - /* - * Done with the preliminaries; find some prefix of the string that's - * a number in the given base. - */ - start = s1; /* Mark - if string is empty, we return NaN. */ - value = 0.0; - for (;;) { - uintN digit; - jschar c = *s1; - if ('0' <= c && c <= '9') - digit = c - '0'; - else if ('a' <= c && c <= 'z') - digit = c - 'a' + 10; - else if ('A' <= c && c <= 'Z') - digit = c - 'A' + 10; - else - break; - if (digit >= (uintN)base) - break; - value = value * base + digit; - s1++; - } - - if (value >= 9007199254740992.0) { - if (base == 10) { - /* - * If we're accumulating a decimal number and the number is >= - * 2^53, then the result from the repeated multiply-add above may - * be inaccurate. Call JS_strtod to get the correct answer. - */ - size_t i; - size_t length = s1 - start; - char *cstr = (char *) JS_malloc(cx, length + 1); - char *estr; - int err=0; - - if (!cstr) - return JS_FALSE; - for (i = 0; i != length; i++) - cstr[i] = (char)start[i]; - cstr[length] = 0; - - value = JS_strtod(cstr, &estr, &err); - if (err == JS_DTOA_ENOMEM) { - JS_ReportOutOfMemory(cx); - JS_free(cx, cstr); - return JS_FALSE; - } - if (err == JS_DTOA_ERANGE && value == HUGE_VAL) - value = *cx->runtime->jsPositiveInfinity; - JS_free(cx, cstr); - } else if ((base & (base - 1)) == 0) { - /* - * The number may also be inaccurate for power-of-two bases. This - * happens if the addition in value * base + digit causes a round- - * down to an even least significant mantissa bit when the first - * dropped bit is a one. If any of the following digits in the - * number (which haven't been added in yet) are nonzero, then the - * correct action would have been to round up instead of down. An - * example occurs when reading the number 0x1000000000000081, which - * rounds to 0x1000000000000000 instead of 0x1000000000000100. - */ - struct BinaryDigitReader bdr; - intN bit, bit2; - intN j; - - bdr.base = base; - bdr.digitMask = 0; - bdr.digits = start; - bdr.end = s1; - value = 0.0; - - /* Skip leading zeros. */ - do { - bit = GetNextBinaryDigit(&bdr); - } while (bit == 0); - - if (bit == 1) { - /* Gather the 53 significant bits (including the leading 1) */ - value = 1.0; - for (j = 52; j; j--) { - bit = GetNextBinaryDigit(&bdr); - if (bit < 0) - goto done; - value = value*2 + bit; - } - /* bit2 is the 54th bit (the first dropped from the mantissa) */ - bit2 = GetNextBinaryDigit(&bdr); - if (bit2 >= 0) { - jsdouble factor = 2.0; - intN sticky = 0; /* sticky is 1 if any bit beyond the 54th is 1 */ - intN bit3; - - while ((bit3 = GetNextBinaryDigit(&bdr)) >= 0) { - sticky |= bit3; - factor *= 2; - } - value += bit2 & (bit | sticky); - value *= factor; - } - done:; - } - } - } - /* We don't worry about inaccurate numbers for any other base. */ - - if (s1 == start) { - *dp = 0.0; - *ep = s; - } else { - *dp = negative ? -value : value; - *ep = s1; - } - return JS_TRUE; -} diff --git a/lib/javascript/jsnum.h b/lib/javascript/jsnum.h deleted file mode 100644 index cd99501e..00000000 --- a/lib/javascript/jsnum.h +++ /dev/null @@ -1,268 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jsnum_h___ -#define jsnum_h___ -/* - * JS number (IEEE double) interface. - * - * JS numbers are optimistically stored in the top 31 bits of 32-bit integers, - * but floating point literals, results that overflow 31 bits, and division and - * modulus operands and results require a 64-bit IEEE double. These are GC'ed - * and pointed to by 32-bit jsvals on the stack and in object properties. - * - * When a JS number is treated as an object (followed by . or []), the runtime - * wraps it with a JSObject whose valueOf method returns the unwrapped number. - */ - -JS_BEGIN_EXTERN_C - -/* - * Stefan Hanske reports: - * ARM is a little endian architecture but 64 bit double words are stored - * differently: the 32 bit words are in little endian byte order, the two words - * are stored in big endian`s way. - */ - -#if defined(__arm) || defined(__arm32__) || defined(__arm26__) || defined(__arm__) -#define CPU_IS_ARM -#endif - -typedef union jsdpun { - struct { -#if defined(IS_LITTLE_ENDIAN) && !defined(CPU_IS_ARM) - uint32 lo, hi; -#else - uint32 hi, lo; -#endif - } s; - jsdouble d; -} jsdpun; - -#if (__GNUC__ == 2 && __GNUC_MINOR__ > 95) || __GNUC__ > 2 -/* - * This version of the macros is safe for the alias optimizations that gcc - * does, but uses gcc-specific extensions. - */ - -#define JSDOUBLE_HI32(x) (__extension__ ({ jsdpun u; u.d = (x); u.s.hi; })) -#define JSDOUBLE_LO32(x) (__extension__ ({ jsdpun u; u.d = (x); u.s.lo; })) -#define JSDOUBLE_SET_HI32(x, y) \ - (__extension__ ({ jsdpun u; u.d = (x); u.s.hi = (y); (x) = u.d; })) -#define JSDOUBLE_SET_LO32(x, y) \ - (__extension__ ({ jsdpun u; u.d = (x); u.s.lo = (y); (x) = u.d; })) - -#else /* not or old GNUC */ - -/* - * We don't know of any non-gcc compilers that perform alias optimization, - * so this code should work. - */ - -#if defined(IS_LITTLE_ENDIAN) && !defined(CPU_IS_ARM) -#define JSDOUBLE_HI32(x) (((uint32 *)&(x))[1]) -#define JSDOUBLE_LO32(x) (((uint32 *)&(x))[0]) -#else -#define JSDOUBLE_HI32(x) (((uint32 *)&(x))[0]) -#define JSDOUBLE_LO32(x) (((uint32 *)&(x))[1]) -#endif - -#define JSDOUBLE_SET_HI32(x, y) (JSDOUBLE_HI32(x)=(y)) -#define JSDOUBLE_SET_LO32(x, y) (JSDOUBLE_LO32(x)=(y)) - -#endif /* not or old GNUC */ - -#define JSDOUBLE_HI32_SIGNBIT 0x80000000 -#define JSDOUBLE_HI32_EXPMASK 0x7ff00000 -#define JSDOUBLE_HI32_MANTMASK 0x000fffff - -#define JSDOUBLE_IS_NaN(x) \ - ((JSDOUBLE_HI32(x) & JSDOUBLE_HI32_EXPMASK) == JSDOUBLE_HI32_EXPMASK && \ - (JSDOUBLE_LO32(x) || (JSDOUBLE_HI32(x) & JSDOUBLE_HI32_MANTMASK))) - -#define JSDOUBLE_IS_INFINITE(x) \ - ((JSDOUBLE_HI32(x) & ~JSDOUBLE_HI32_SIGNBIT) == JSDOUBLE_HI32_EXPMASK && \ - !JSDOUBLE_LO32(x)) - -#define JSDOUBLE_IS_FINITE(x) \ - ((JSDOUBLE_HI32(x) & JSDOUBLE_HI32_EXPMASK) != JSDOUBLE_HI32_EXPMASK) - -#define JSDOUBLE_IS_NEGZERO(d) (JSDOUBLE_HI32(d) == JSDOUBLE_HI32_SIGNBIT && \ - JSDOUBLE_LO32(d) == 0) - -/* - * JSDOUBLE_IS_INT first checks that d is neither NaN nor infinite, to avoid - * raising SIGFPE on platforms such as Alpha Linux, then (only if the cast is - * safe) leaves i as (jsint)d. This also avoid anomalous NaN floating point - * comparisons under MSVC. - */ -#define JSDOUBLE_IS_INT(d, i) (JSDOUBLE_IS_FINITE(d) \ - && !JSDOUBLE_IS_NEGZERO(d) \ - && ((d) == (i = (jsint)(d)))) - -#if defined(XP_WIN) -#define JSDOUBLE_COMPARE(LVAL, OP, RVAL, IFNAN) \ - ((JSDOUBLE_IS_NaN(LVAL) || JSDOUBLE_IS_NaN(RVAL)) \ - ? (IFNAN) \ - : (LVAL) OP (RVAL)) -#else -#define JSDOUBLE_COMPARE(LVAL, OP, RVAL, IFNAN) ((LVAL) OP (RVAL)) -#endif - -/* Initialize number constants and runtime state for the first context. */ -extern JSBool -js_InitRuntimeNumberState(JSContext *cx); - -extern void -js_FinishRuntimeNumberState(JSContext *cx); - -/* Initialize the Number class, returning its prototype object. */ -extern JSClass js_NumberClass; - -extern JSObject * -js_InitNumberClass(JSContext *cx, JSObject *obj); - -/* - * String constants for global function names, used in jsapi.c and jsnum.c. - */ -extern const char js_Infinity_str[]; -extern const char js_NaN_str[]; -extern const char js_isNaN_str[]; -extern const char js_isFinite_str[]; -extern const char js_parseFloat_str[]; -extern const char js_parseInt_str[]; - -/* GC-allocate a new JS number. */ -extern jsdouble * -js_NewDouble(JSContext *cx, jsdouble d, uintN gcflag); - -extern void -js_FinalizeDouble(JSContext *cx, jsdouble *dp); - -extern JSBool -js_NewDoubleValue(JSContext *cx, jsdouble d, jsval *rval); - -extern JSBool -js_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval); - -/* Construct a Number instance that wraps around d. */ -extern JSObject * -js_NumberToObject(JSContext *cx, jsdouble d); - -/* Convert a number to a GC'ed string. */ -extern JSString * -js_NumberToString(JSContext *cx, jsdouble d); - -/* - * Convert a value to a number, returning false after reporting any error, - * otherwise returning true with *dp set. - */ -extern JSBool -js_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp); - -/* - * Convert a value or a double to an int32, according to the ECMA rules - * for ToInt32. - */ -extern JSBool -js_ValueToECMAInt32(JSContext *cx, jsval v, int32 *ip); - -extern JSBool -js_DoubleToECMAInt32(JSContext *cx, jsdouble d, int32 *ip); - -/* - * Convert a value or a double to a uint32, according to the ECMA rules - * for ToUint32. - */ -extern JSBool -js_ValueToECMAUint32(JSContext *cx, jsval v, uint32 *ip); - -extern JSBool -js_DoubleToECMAUint32(JSContext *cx, jsdouble d, uint32 *ip); - -/* - * Convert a value to a number, then to an int32 if it fits by rounding to - * nearest; but failing with an error report if the double is out of range - * or unordered. - */ -extern JSBool -js_ValueToInt32(JSContext *cx, jsval v, int32 *ip); - -/* - * Convert a value to a number, then to a uint16 according to the ECMA rules - * for ToUint16. - */ -extern JSBool -js_ValueToUint16(JSContext *cx, jsval v, uint16 *ip); - -/* - * Convert a jsdouble to an integral number, stored in a jsdouble. - * If d is NaN, return 0. If d is an infinity, return it without conversion. - */ -extern jsdouble -js_DoubleToInteger(jsdouble d); - -/* - * Similar to strtod except that it replaces overflows with infinities of the - * correct sign, and underflows with zeros of the correct sign. Guaranteed to - * return the closest double number to the given input in dp. - * - * Also allows inputs of the form [+|-]Infinity, which produce an infinity of - * the appropriate sign. The case of the "Infinity" string must match exactly. - * If the string does not contain a number, set *ep to s and return 0.0 in dp. - * Return false if out of memory. - */ -extern JSBool -js_strtod(JSContext *cx, const jschar *s, const jschar **ep, jsdouble *dp); - -/* - * Similar to strtol except that it handles integers of arbitrary size. - * Guaranteed to return the closest double number to the given input when radix - * is 10 or a power of 2. Callers may see round-off errors for very large - * numbers of a different radix than 10 or a power of 2. - * - * If the string does not contain a number, set *ep to s and return 0.0 in dp. - * Return false if out of memory. - */ -extern JSBool -js_strtointeger(JSContext *cx, const jschar *s, const jschar **ep, jsint radix, jsdouble *dp); - -JS_END_EXTERN_C - -#endif /* jsnum_h___ */ diff --git a/lib/javascript/jsobj.c b/lib/javascript/jsobj.c deleted file mode 100644 index 03a59809..00000000 --- a/lib/javascript/jsobj.c +++ /dev/null @@ -1,4646 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sw=4 et tw=78: - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JS object implementation. - */ -#include "jsstddef.h" -#include -#include -#include "jstypes.h" -#include "jsarena.h" /* Added by JSIFY */ -#include "jsutil.h" /* Added by JSIFY */ -#include "jshash.h" /* Added by JSIFY */ -#include "jsdhash.h" -#include "jsprf.h" -#include "jsapi.h" -#include "jsarray.h" -#include "jsatom.h" -#include "jsbool.h" -#include "jscntxt.h" -#include "jsconfig.h" -#include "jsfun.h" -#include "jsgc.h" -#include "jsinterp.h" -#include "jslock.h" -#include "jsnum.h" -#include "jsobj.h" -#include "jsscope.h" -#include "jsscript.h" -#include "jsstr.h" -#include "jsopcode.h" - -#include "jsdbgapi.h" /* whether or not JS_HAS_OBJ_WATCHPOINT */ - -#if JS_HAS_XML_SUPPORT -#include "jsxml.h" -#endif - -#ifdef JS_THREADSAFE -#define NATIVE_DROP_PROPERTY js_DropProperty - -extern void -js_DropProperty(JSContext *cx, JSObject *obj, JSProperty *prop); -#else -#define NATIVE_DROP_PROPERTY NULL -#endif - -JS_FRIEND_DATA(JSObjectOps) js_ObjectOps = { - js_NewObjectMap, js_DestroyObjectMap, - js_LookupProperty, js_DefineProperty, - js_GetProperty, js_SetProperty, - js_GetAttributes, js_SetAttributes, - js_DeleteProperty, js_DefaultValue, - js_Enumerate, js_CheckAccess, - NULL, NATIVE_DROP_PROPERTY, - js_Call, js_Construct, - NULL, js_HasInstance, - js_SetProtoOrParent, js_SetProtoOrParent, - js_Mark, js_Clear, - js_GetRequiredSlot, js_SetRequiredSlot -}; - -JSClass js_ObjectClass = { - js_Object_str, - 0, - JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, - JSCLASS_NO_OPTIONAL_MEMBERS -}; - -#if JS_HAS_OBJ_PROTO_PROP - -static JSBool -obj_getSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp); - -static JSBool -obj_setSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp); - -static JSBool -obj_getCount(JSContext *cx, JSObject *obj, jsval id, jsval *vp); - -static JSPropertySpec object_props[] = { - /* These two must come first; see object_props[slot].name usage below. */ - {js_proto_str, JSSLOT_PROTO, JSPROP_PERMANENT|JSPROP_SHARED, - obj_getSlot, obj_setSlot}, - {js_parent_str,JSSLOT_PARENT,JSPROP_READONLY|JSPROP_PERMANENT|JSPROP_SHARED, - obj_getSlot, obj_setSlot}, - {js_count_str, 0, JSPROP_PERMANENT,obj_getCount, obj_getCount}, - {0,0,0,0,0} -}; - -/* NB: JSSLOT_PROTO and JSSLOT_PARENT are already indexes into object_props. */ -#define JSSLOT_COUNT 2 - -static JSBool -ReportStrictSlot(JSContext *cx, uint32 slot) -{ - if (slot == JSSLOT_PROTO) - return JS_TRUE; - return JS_ReportErrorFlagsAndNumber(cx, - JSREPORT_WARNING | JSREPORT_STRICT, - js_GetErrorMessage, NULL, - JSMSG_DEPRECATED_USAGE, - object_props[slot].name); -} - -static JSBool -obj_getSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - uint32 slot; - jsid propid; - JSAccessMode mode; - uintN attrs; - JSObject *pobj; - JSClass *clasp; - JSExtendedClass *xclasp; - - slot = (uint32) JSVAL_TO_INT(id); - if (id == INT_TO_JSVAL(JSSLOT_PROTO)) { - propid = ATOM_TO_JSID(cx->runtime->atomState.protoAtom); - mode = JSACC_PROTO; - } else { - propid = ATOM_TO_JSID(cx->runtime->atomState.parentAtom); - mode = JSACC_PARENT; - } - - /* Let OBJ_CHECK_ACCESS get the slot's value, based on the access mode. */ - if (!OBJ_CHECK_ACCESS(cx, obj, propid, mode, vp, &attrs)) - return JS_FALSE; - - pobj = JSVAL_TO_OBJECT(*vp); - if (pobj) { - clasp = OBJ_GET_CLASS(cx, pobj); - if (clasp->flags & JSCLASS_IS_EXTENDED) { - xclasp = (JSExtendedClass *) clasp; - if (xclasp->outerObject) { - pobj = xclasp->outerObject(cx, pobj); - if (!pobj) - return JS_FALSE; - *vp = OBJECT_TO_JSVAL(pobj); - } - } - } - return JS_TRUE; -} - -static JSBool -obj_setSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - JSObject *pobj; - uint32 slot; - jsid propid; - uintN attrs; - - if (!JSVAL_IS_OBJECT(*vp)) - return JS_TRUE; - pobj = JSVAL_TO_OBJECT(*vp); - slot = (uint32) JSVAL_TO_INT(id); - if (JS_HAS_STRICT_OPTION(cx) && !ReportStrictSlot(cx, slot)) - return JS_FALSE; - - /* __parent__ is readonly and permanent, only __proto__ may be set. */ - propid = ATOM_TO_JSID(cx->runtime->atomState.protoAtom); - if (!OBJ_CHECK_ACCESS(cx, obj, propid, JSACC_PROTO|JSACC_WRITE, vp, &attrs)) - return JS_FALSE; - - return js_SetProtoOrParent(cx, obj, slot, pobj); -} - -static JSBool -obj_getCount(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - jsval iter_state; - jsid num_properties; - JSBool ok; - - if (JS_HAS_STRICT_OPTION(cx) && !ReportStrictSlot(cx, JSSLOT_COUNT)) - return JS_FALSE; - - /* Get the number of properties to enumerate. */ - iter_state = JSVAL_NULL; - ok = OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &iter_state, &num_properties); - if (!ok) - goto out; - - if (!JSVAL_IS_INT(num_properties)) { - JS_ASSERT(0); - *vp = JSVAL_ZERO; - goto out; - } - *vp = num_properties; - -out: - if (iter_state != JSVAL_NULL) - ok = OBJ_ENUMERATE(cx, obj, JSENUMERATE_DESTROY, &iter_state, 0); - return ok; -} - -#else /* !JS_HAS_OBJ_PROTO_PROP */ - -#define object_props NULL - -#endif /* !JS_HAS_OBJ_PROTO_PROP */ - -JSBool -js_SetProtoOrParent(JSContext *cx, JSObject *obj, uint32 slot, JSObject *pobj) -{ - JSRuntime *rt; - JSObject *obj2, *oldproto; - JSScope *scope, *newscope; - - /* - * Serialize all proto and parent setting in order to detect cycles. - * We nest locks in this function, and only here, in the following orders: - * - * (1) rt->setSlotLock < pobj's scope lock; - * rt->setSlotLock < pobj's proto-or-parent's scope lock; - * rt->setSlotLock < pobj's grand-proto-or-parent's scope lock; - * etc... - * (2) rt->setSlotLock < obj's scope lock < pobj's scope lock. - * - * We avoid AB-BA deadlock by restricting obj from being on pobj's parent - * or proto chain (pobj may already be on obj's parent or proto chain; it - * could be moving up or down). We finally order obj with respect to pobj - * at the bottom of this routine (just before releasing rt->setSlotLock), - * by making pobj be obj's prototype or parent. - * - * After we have set the slot and released rt->setSlotLock, another call - * to js_SetProtoOrParent could nest locks according to the first order - * list above, but it cannot deadlock with any other thread. For there - * to be a deadlock, other parts of the engine would have to nest scope - * locks in the opposite order. XXXbe ensure they don't! - */ - rt = cx->runtime; -#ifdef JS_THREADSAFE - - JS_ACQUIRE_LOCK(rt->setSlotLock); - while (rt->setSlotBusy) { - jsrefcount saveDepth; - - /* Take pains to avoid nesting rt->gcLock inside rt->setSlotLock! */ - JS_RELEASE_LOCK(rt->setSlotLock); - saveDepth = JS_SuspendRequest(cx); - JS_ACQUIRE_LOCK(rt->setSlotLock); - if (rt->setSlotBusy) - JS_WAIT_CONDVAR(rt->setSlotDone, JS_NO_TIMEOUT); - JS_RELEASE_LOCK(rt->setSlotLock); - JS_ResumeRequest(cx, saveDepth); - JS_ACQUIRE_LOCK(rt->setSlotLock); - } - rt->setSlotBusy = JS_TRUE; - JS_RELEASE_LOCK(rt->setSlotLock); - -#define SET_SLOT_DONE(rt) \ - JS_BEGIN_MACRO \ - JS_ACQUIRE_LOCK((rt)->setSlotLock); \ - (rt)->setSlotBusy = JS_FALSE; \ - JS_NOTIFY_ALL_CONDVAR((rt)->setSlotDone); \ - JS_RELEASE_LOCK((rt)->setSlotLock); \ - JS_END_MACRO - -#else - -#define SET_SLOT_DONE(rt) /* nothing */ - -#endif - - obj2 = pobj; - while (obj2) { - if (obj2 == obj) { - SET_SLOT_DONE(rt); - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_CYCLIC_VALUE, -#if JS_HAS_OBJ_PROTO_PROP - object_props[slot].name -#else - (slot == JSSLOT_PROTO) ? js_proto_str - : js_parent_str -#endif - ); - return JS_FALSE; - } - obj2 = JSVAL_TO_OBJECT(OBJ_GET_SLOT(cx, obj2, slot)); - } - - if (slot == JSSLOT_PROTO && OBJ_IS_NATIVE(obj)) { - /* Check to see whether obj shares its prototype's scope. */ - JS_LOCK_OBJ(cx, obj); - scope = OBJ_SCOPE(obj); - oldproto = JSVAL_TO_OBJECT(LOCKED_OBJ_GET_SLOT(obj, JSSLOT_PROTO)); - if (oldproto && OBJ_SCOPE(oldproto) == scope) { - /* Either obj needs a new empty scope, or it should share pobj's. */ - if (!pobj || - !OBJ_IS_NATIVE(pobj) || - OBJ_GET_CLASS(cx, pobj) != LOCKED_OBJ_GET_CLASS(oldproto)) { - /* - * With no proto and no scope of its own, obj is truly empty. - * - * If pobj is not native, obj needs its own empty scope -- it - * should not continue to share oldproto's scope once oldproto - * is not on obj's prototype chain. That would put properties - * from oldproto's scope ahead of properties defined by pobj, - * in lookup order. - * - * If pobj's class differs from oldproto's, we may need a new - * scope to handle differences in private and reserved slots, - * so we suboptimally but safely make one. - */ - scope = js_GetMutableScope(cx, obj); - if (!scope) { - JS_UNLOCK_OBJ(cx, obj); - SET_SLOT_DONE(rt); - return JS_FALSE; - } - } else if (OBJ_SCOPE(pobj) != scope) { -#ifdef JS_THREADSAFE - /* - * We are about to nest scope locks. Help jslock.c:ShareScope - * keep scope->u.count balanced for the JS_UNLOCK_SCOPE, while - * avoiding deadlock, by recording scope in rt->setSlotScope. - */ - if (scope->ownercx) { - JS_ASSERT(scope->ownercx == cx); - rt->setSlotScope = scope; - } -#endif - - /* We can't deadlock because we checked for cycles above (2). */ - JS_LOCK_OBJ(cx, pobj); - newscope = (JSScope *) js_HoldObjectMap(cx, pobj->map); - obj->map = &newscope->map; - js_DropObjectMap(cx, &scope->map, obj); - JS_TRANSFER_SCOPE_LOCK(cx, scope, newscope); - scope = newscope; -#ifdef JS_THREADSAFE - rt->setSlotScope = NULL; -#endif - } - } - LOCKED_OBJ_SET_SLOT(obj, JSSLOT_PROTO, OBJECT_TO_JSVAL(pobj)); - JS_UNLOCK_SCOPE(cx, scope); - } else { - OBJ_SET_SLOT(cx, obj, slot, OBJECT_TO_JSVAL(pobj)); - } - - SET_SLOT_DONE(rt); - return JS_TRUE; - -#undef SET_SLOT_DONE -} - -JS_STATIC_DLL_CALLBACK(JSHashNumber) -js_hash_object(const void *key) -{ - return (JSHashNumber)JS_PTR_TO_UINT32(key) >> JSVAL_TAGBITS; -} - -static JSHashEntry * -MarkSharpObjects(JSContext *cx, JSObject *obj, JSIdArray **idap) -{ - JSSharpObjectMap *map; - JSHashTable *table; - JSHashNumber hash; - JSHashEntry **hep, *he; - jsatomid sharpid; - JSIdArray *ida; - JSBool ok; - jsint i, length; - jsid id; -#if JS_HAS_GETTER_SETTER - JSObject *obj2; - JSProperty *prop; - uintN attrs; -#endif - jsval val; - int stackDummy; - - if (!JS_CHECK_STACK_SIZE(cx, stackDummy)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_OVER_RECURSED); - return NULL; - } - - map = &cx->sharpObjectMap; - table = map->table; - hash = js_hash_object(obj); - hep = JS_HashTableRawLookup(table, hash, obj); - he = *hep; - if (!he) { - sharpid = 0; - he = JS_HashTableRawAdd(table, hep, hash, obj, - JS_UINT32_TO_PTR(sharpid)); - if (!he) { - JS_ReportOutOfMemory(cx); - return NULL; - } - - /* - * Increment map->depth to protect js_EnterSharpObject from reentering - * itself badly. Without this fix, if we reenter the basis case where - * map->depth == 0, when unwinding the inner call we will destroy the - * newly-created hash table and crash. - */ - ++map->depth; - ida = JS_Enumerate(cx, obj); - --map->depth; - if (!ida) - return NULL; - - ok = JS_TRUE; - for (i = 0, length = ida->length; i < length; i++) { - id = ida->vector[i]; -#if JS_HAS_GETTER_SETTER - ok = OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop); - if (!ok) - break; - if (!prop) - continue; - ok = OBJ_GET_ATTRIBUTES(cx, obj2, id, prop, &attrs); - if (ok) { - if (OBJ_IS_NATIVE(obj2) && - (attrs & (JSPROP_GETTER | JSPROP_SETTER))) { - val = JSVAL_NULL; - if (attrs & JSPROP_GETTER) - val = (jsval) ((JSScopeProperty*)prop)->getter; - if (attrs & JSPROP_SETTER) { - if (val != JSVAL_NULL) { - /* Mark the getter, then set val to setter. */ - ok = (MarkSharpObjects(cx, JSVAL_TO_OBJECT(val), - NULL) - != NULL); - } - val = (jsval) ((JSScopeProperty*)prop)->setter; - } - } else { - ok = OBJ_GET_PROPERTY(cx, obj, id, &val); - } - } - OBJ_DROP_PROPERTY(cx, obj2, prop); -#else - ok = OBJ_GET_PROPERTY(cx, obj, id, &val); -#endif - if (!ok) - break; - if (!JSVAL_IS_PRIMITIVE(val) && - !MarkSharpObjects(cx, JSVAL_TO_OBJECT(val), NULL)) { - ok = JS_FALSE; - break; - } - } - if (!ok || !idap) - JS_DestroyIdArray(cx, ida); - if (!ok) - return NULL; - } else { - sharpid = JS_PTR_TO_UINT32(he->value); - if (sharpid == 0) { - sharpid = ++map->sharpgen << SHARP_ID_SHIFT; - he->value = JS_UINT32_TO_PTR(sharpid); - } - ida = NULL; - } - if (idap) - *idap = ida; - return he; -} - -JSHashEntry * -js_EnterSharpObject(JSContext *cx, JSObject *obj, JSIdArray **idap, - jschar **sp) -{ - JSSharpObjectMap *map; - JSHashTable *table; - JSIdArray *ida; - JSHashNumber hash; - JSHashEntry *he, **hep; - jsatomid sharpid; - char buf[20]; - size_t len; - - if (JS_HAS_NATIVE_BRANCH_CALLBACK_OPTION(cx) && - cx->branchCallback && - !cx->branchCallback(cx, NULL)) { - return NULL; - } - - /* Set to null in case we return an early error. */ - *sp = NULL; - map = &cx->sharpObjectMap; - table = map->table; - if (!table) { - table = JS_NewHashTable(8, js_hash_object, JS_CompareValues, - JS_CompareValues, NULL, NULL); - if (!table) { - JS_ReportOutOfMemory(cx); - return NULL; - } - map->table = table; - JS_KEEP_ATOMS(cx->runtime); - } - - /* From this point the control must flow either through out: or bad:. */ - ida = NULL; - if (map->depth == 0) { - he = MarkSharpObjects(cx, obj, &ida); - if (!he) - goto bad; - JS_ASSERT((JS_PTR_TO_UINT32(he->value) & SHARP_BIT) == 0); - if (!idap) { - JS_DestroyIdArray(cx, ida); - ida = NULL; - } - } else { - hash = js_hash_object(obj); - hep = JS_HashTableRawLookup(table, hash, obj); - he = *hep; - - /* - * It's possible that the value of a property has changed from the - * first time the object's properties are traversed (when the property - * ids are entered into the hash table) to the second (when they are - * converted to strings), i.e., the OBJ_GET_PROPERTY() call is not - * idempotent. - */ - if (!he) { - he = JS_HashTableRawAdd(table, hep, hash, obj, NULL); - if (!he) { - JS_ReportOutOfMemory(cx); - goto bad; - } - sharpid = 0; - goto out; - } - } - - sharpid = JS_PTR_TO_UINT32(he->value); - if (sharpid != 0) { - len = JS_snprintf(buf, sizeof buf, "#%u%c", - sharpid >> SHARP_ID_SHIFT, - (sharpid & SHARP_BIT) ? '#' : '='); - *sp = js_InflateString(cx, buf, &len); - if (!*sp) { - if (ida) - JS_DestroyIdArray(cx, ida); - goto bad; - } - } - -out: - JS_ASSERT(he); - if ((sharpid & SHARP_BIT) == 0) { - if (idap && !ida) { - ida = JS_Enumerate(cx, obj); - if (!ida) { - if (*sp) { - JS_free(cx, *sp); - *sp = NULL; - } - goto bad; - } - } - map->depth++; - } - - if (idap) - *idap = ida; - return he; - -bad: - /* Clean up the sharpObjectMap table on outermost error. */ - if (map->depth == 0) { - JS_UNKEEP_ATOMS(cx->runtime); - map->sharpgen = 0; - JS_HashTableDestroy(map->table); - map->table = NULL; - } - return NULL; -} - -void -js_LeaveSharpObject(JSContext *cx, JSIdArray **idap) -{ - JSSharpObjectMap *map; - JSIdArray *ida; - - map = &cx->sharpObjectMap; - JS_ASSERT(map->depth > 0); - if (--map->depth == 0) { - JS_UNKEEP_ATOMS(cx->runtime); - map->sharpgen = 0; - JS_HashTableDestroy(map->table); - map->table = NULL; - } - if (idap) { - ida = *idap; - if (ida) { - JS_DestroyIdArray(cx, ida); - *idap = NULL; - } - } -} - -JS_STATIC_DLL_CALLBACK(intN) -gc_sharp_table_entry_marker(JSHashEntry *he, intN i, void *arg) -{ - GC_MARK((JSContext *)arg, (JSObject *)he->key, "sharp table entry", NULL); - return JS_DHASH_NEXT; -} - -void -js_GCMarkSharpMap(JSContext *cx, JSSharpObjectMap *map) -{ - JS_ASSERT(map->depth > 0); - JS_ASSERT(map->table); - - /* - * During recursive calls to MarkSharpObjects a non-native object or - * object with a custom getProperty method can potentially return an - * unrooted value or even cut from the object graph an argument of one of - * MarkSharpObjects recursive invocations. So we must protect map->table - * entries against GC. - * - * We can not simply use JSTempValueRooter to mark the obj argument of - * MarkSharpObjects during recursion as we have to protect *all* entries - * in JSSharpObjectMap including those that contains otherwise unreachable - * objects just allocated through custom getProperty. Otherwise newer - * allocations can re-use the address of an object stored in the hashtable - * confusing js_EnterSharpObject. So to address the problem we simply - * mark all objects from map->table. - * - * An alternative "proper" solution is to use JSTempValueRooter in - * MarkSharpObjects with code to remove during finalization entries - * with otherwise unreachable objects. But this is way too complex - * to justify spending efforts. - */ - JS_HashTableEnumerateEntries(map->table, gc_sharp_table_entry_marker, cx); -} - -#define OBJ_TOSTRING_EXTRA 4 /* for 4 local GC roots */ - -#if JS_HAS_INITIALIZERS || JS_HAS_TOSOURCE -JSBool -js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSBool ok, outermost; - JSHashEntry *he; - JSIdArray *ida; - jschar *chars, *ochars, *vsharp; - const jschar *idstrchars, *vchars; - size_t nchars, idstrlength, gsoplength, vlength, vsharplength, curlen; - char *comma; - jsint i, j, length, valcnt; - jsid id; -#if JS_HAS_GETTER_SETTER - JSObject *obj2; - JSProperty *prop; - uintN attrs; -#endif - jsval *val; - JSString *gsop[2]; - JSAtom *atom; - JSString *idstr, *valstr, *str; - int stackDummy; - - if (!JS_CHECK_STACK_SIZE(cx, stackDummy)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_OVER_RECURSED); - return JS_FALSE; - } - - /* - * obj_toString for 1.2 calls toSource, and doesn't want the extra parens - * on the outside. - */ - outermost = !JS_VERSION_IS_1_2(cx) && cx->sharpObjectMap.depth == 0; - he = js_EnterSharpObject(cx, obj, &ida, &chars); - if (!he) - return JS_FALSE; - if (IS_SHARP(he)) { - /* - * We didn't enter -- obj is already "sharp", meaning we've visited it - * already in our depth first search, and therefore chars contains a - * string of the form "#n#". - */ - JS_ASSERT(!ida); -#if JS_HAS_SHARP_VARS - nchars = js_strlen(chars); -#else - chars[0] = '{'; - chars[1] = '}'; - chars[2] = 0; - nchars = 2; -#endif - goto make_string; - } - JS_ASSERT(ida); - ok = JS_TRUE; - - if (!chars) { - /* If outermost, allocate 4 + 1 for "({})" and the terminator. */ - chars = (jschar *) malloc(((outermost ? 4 : 2) + 1) * sizeof(jschar)); - nchars = 0; - if (!chars) - goto error; - if (outermost) - chars[nchars++] = '('; - } else { - /* js_EnterSharpObject returned a string of the form "#n=" in chars. */ - MAKE_SHARP(he); - nchars = js_strlen(chars); - chars = (jschar *) - realloc((ochars = chars), (nchars + 2 + 1) * sizeof(jschar)); - if (!chars) { - free(ochars); - goto error; - } - if (outermost) { - /* - * No need for parentheses around the whole shebang, because #n= - * unambiguously begins an object initializer, and never a block - * statement. - */ - outermost = JS_FALSE; - } - } - -#ifdef DUMP_CALL_TABLE - if (cx->options & JSOPTION_LOGCALL_TOSOURCE) { - const char *classname = OBJ_GET_CLASS(cx, obj)->name; - size_t classnchars = strlen(classname); - static const char classpropid[] = "C"; - const char *cp; - size_t onchars = nchars; - - /* 2 for ': ', 2 quotes around classname, 2 for ', ' after. */ - classnchars += sizeof classpropid - 1 + 2 + 2; - if (ida->length) - classnchars += 2; - - /* 2 for the braces, 1 for the terminator */ - chars = (jschar *) - realloc((ochars = chars), - (nchars + classnchars + 2 + 1) * sizeof(jschar)); - if (!chars) { - free(ochars); - goto error; - } - - chars[nchars++] = '{'; /* 1 from the 2 braces */ - for (cp = classpropid; *cp; cp++) - chars[nchars++] = (jschar) *cp; - chars[nchars++] = ':'; - chars[nchars++] = ' '; /* 2 for ': ' */ - chars[nchars++] = '"'; - for (cp = classname; *cp; cp++) - chars[nchars++] = (jschar) *cp; - chars[nchars++] = '"'; /* 2 quotes */ - if (ida->length) { - chars[nchars++] = ','; - chars[nchars++] = ' '; /* 2 for ', ' */ - } - - JS_ASSERT(nchars - onchars == 1 + classnchars); - } else -#endif - chars[nchars++] = '{'; - - comma = NULL; - - /* - * We have four local roots for cooked and raw value GC safety. Hoist the - * "argv + 2" out of the loop using the val local, which refers to the raw - * (unconverted, "uncooked") values. - */ - val = argv + 2; - - for (i = 0, length = ida->length; i < length; i++) { - /* Get strings for id and value and GC-root them via argv. */ - id = ida->vector[i]; - -#if JS_HAS_GETTER_SETTER - - ok = OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop); - if (!ok) - goto error; - valcnt = 0; - if (prop) { - ok = OBJ_GET_ATTRIBUTES(cx, obj2, id, prop, &attrs); - if (!ok) { - OBJ_DROP_PROPERTY(cx, obj2, prop); - goto error; - } - if (OBJ_IS_NATIVE(obj2) && - (attrs & (JSPROP_GETTER | JSPROP_SETTER))) { - if (attrs & JSPROP_GETTER) { - val[valcnt] = (jsval) ((JSScopeProperty *)prop)->getter; -#ifdef OLD_GETTER_SETTER - gsop[valcnt] = - ATOM_TO_STRING(cx->runtime->atomState.getterAtom); -#else - gsop[valcnt] = - ATOM_TO_STRING(cx->runtime->atomState.getAtom); -#endif - valcnt++; - } - if (attrs & JSPROP_SETTER) { - val[valcnt] = (jsval) ((JSScopeProperty *)prop)->setter; -#ifdef OLD_GETTER_SETTER - gsop[valcnt] = - ATOM_TO_STRING(cx->runtime->atomState.setterAtom); -#else - gsop[valcnt] = - ATOM_TO_STRING(cx->runtime->atomState.setAtom); -#endif - valcnt++; - } - } else { - valcnt = 1; - gsop[0] = NULL; - ok = OBJ_GET_PROPERTY(cx, obj, id, &val[0]); - } - OBJ_DROP_PROPERTY(cx, obj2, prop); - } - -#else /* !JS_HAS_GETTER_SETTER */ - - valcnt = 1; - gsop[0] = NULL; - ok = OBJ_GET_PROPERTY(cx, obj, id, &val[0]); - -#endif /* !JS_HAS_GETTER_SETTER */ - - if (!ok) - goto error; - - /* Convert id to a jsval and then to a string. */ - atom = JSID_IS_ATOM(id) ? JSID_TO_ATOM(id) : NULL; - id = ID_TO_VALUE(id); - idstr = js_ValueToString(cx, id); - if (!idstr) { - ok = JS_FALSE; - goto error; - } - *rval = STRING_TO_JSVAL(idstr); /* local root */ - - /* - * If id is a string that's a reserved identifier, or else id is not - * an identifier at all, then it needs to be quoted. Also, negative - * integer ids must be quoted. - */ - if (atom - ? (ATOM_KEYWORD(atom) || !js_IsIdentifier(idstr)) - : (JSID_IS_OBJECT(id) || JSID_TO_INT(id) < 0)) { - idstr = js_QuoteString(cx, idstr, (jschar)'\''); - if (!idstr) { - ok = JS_FALSE; - goto error; - } - *rval = STRING_TO_JSVAL(idstr); /* local root */ - } - idstrchars = JSSTRING_CHARS(idstr); - idstrlength = JSSTRING_LENGTH(idstr); - - for (j = 0; j < valcnt; j++) { - /* Convert val[j] to its canonical source form. */ - valstr = js_ValueToSource(cx, val[j]); - if (!valstr) { - ok = JS_FALSE; - goto error; - } - argv[j] = STRING_TO_JSVAL(valstr); /* local root */ - vchars = JSSTRING_CHARS(valstr); - vlength = JSSTRING_LENGTH(valstr); - -#ifndef OLD_GETTER_SETTER - /* - * Remove '(function ' from the beginning of valstr and ')' from the - * end so that we can put "get" in front of the function definition. - */ - if (gsop[j]) { - int n = strlen(js_function_str) + 2; - vchars += n; - vlength -= n + 1; - } -#endif - - /* If val[j] is a non-sharp object, consider sharpening it. */ - vsharp = NULL; - vsharplength = 0; -#if JS_HAS_SHARP_VARS - if (!JSVAL_IS_PRIMITIVE(val[j]) && vchars[0] != '#') { - he = js_EnterSharpObject(cx, JSVAL_TO_OBJECT(val[j]), NULL, - &vsharp); - if (!he) { - ok = JS_FALSE; - goto error; - } - if (IS_SHARP(he)) { - vchars = vsharp; - vlength = js_strlen(vchars); - } else { - if (vsharp) { - vsharplength = js_strlen(vsharp); - MAKE_SHARP(he); - } - js_LeaveSharpObject(cx, NULL); - } - } -#endif - -#define SAFE_ADD(n) \ - JS_BEGIN_MACRO \ - size_t n_ = (n); \ - curlen += n_; \ - if (curlen < n_) \ - goto overflow; \ - JS_END_MACRO - - curlen = nchars; - if (comma) - SAFE_ADD(2); - SAFE_ADD(idstrlength + 1); - if (gsop[j]) - SAFE_ADD(JSSTRING_LENGTH(gsop[j]) + 1); - SAFE_ADD(vsharplength); - SAFE_ADD(vlength); - SAFE_ADD((outermost ? 2 : 1) + 1); -#undef SAFE_ADD - - if (curlen > (size_t)-1 / sizeof(jschar)) - goto overflow; - - /* Allocate 1 + 1 at end for closing brace and terminating 0. */ - chars = (jschar *) - realloc((ochars = chars), curlen * sizeof(jschar)); - if (!chars) { - /* Save code space on error: let JS_free ignore null vsharp. */ - JS_free(cx, vsharp); - free(ochars); - goto error; - } - - if (comma) { - chars[nchars++] = comma[0]; - chars[nchars++] = comma[1]; - } - comma = ", "; - -#ifdef OLD_GETTER_SETTER - js_strncpy(&chars[nchars], idstrchars, idstrlength); - nchars += idstrlength; - if (gsop[j]) { - chars[nchars++] = ' '; - gsoplength = JSSTRING_LENGTH(gsop[j]); - js_strncpy(&chars[nchars], JSSTRING_CHARS(gsop[j]), gsoplength); - nchars += gsoplength; - } - chars[nchars++] = ':'; -#else - if (gsop[j]) { - gsoplength = JSSTRING_LENGTH(gsop[j]); - js_strncpy(&chars[nchars], JSSTRING_CHARS(gsop[j]), gsoplength); - nchars += gsoplength; - chars[nchars++] = ' '; - } - js_strncpy(&chars[nchars], idstrchars, idstrlength); - nchars += idstrlength; - if (!gsop[j]) - chars[nchars++] = ':'; -#endif - if (vsharplength) { - js_strncpy(&chars[nchars], vsharp, vsharplength); - nchars += vsharplength; - } - js_strncpy(&chars[nchars], vchars, vlength); - nchars += vlength; - - if (vsharp) - JS_free(cx, vsharp); -#ifdef DUMP_CALL_TABLE - if (outermost && nchars >= js_LogCallToSourceLimit) - break; -#endif - } - } - - chars[nchars++] = '}'; - if (outermost) - chars[nchars++] = ')'; - chars[nchars] = 0; - - error: - js_LeaveSharpObject(cx, &ida); - - if (!ok) { - if (chars) - free(chars); - return ok; - } - - if (!chars) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - make_string: - str = js_NewString(cx, chars, nchars, 0); - if (!str) { - free(chars); - return JS_FALSE; - } - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; - - overflow: - JS_free(cx, vsharp); - free(chars); - chars = NULL; - goto error; -} -#endif /* JS_HAS_INITIALIZERS || JS_HAS_TOSOURCE */ - -JSBool -js_obj_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jschar *chars; - size_t nchars; - const char *clazz, *prefix; - JSString *str; - -#if JS_HAS_INITIALIZERS - if (JS_VERSION_IS_1_2(cx)) - return js_obj_toSource(cx, obj, argc, argv, rval); -#endif - - clazz = OBJ_GET_CLASS(cx, obj)->name; - nchars = 9 + strlen(clazz); /* 9 for "[object ]" */ - chars = (jschar *) JS_malloc(cx, (nchars + 1) * sizeof(jschar)); - if (!chars) - return JS_FALSE; - - prefix = "[object "; - nchars = 0; - while ((chars[nchars] = (jschar)*prefix) != 0) - nchars++, prefix++; - while ((chars[nchars] = (jschar)*clazz) != 0) - nchars++, clazz++; - chars[nchars++] = ']'; - chars[nchars] = 0; - - str = js_NewString(cx, chars, nchars, 0); - if (!str) { - JS_free(cx, chars); - return JS_FALSE; - } - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -static JSBool -js_obj_toLocaleString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSString *str; - - str = js_ValueToString(cx, argv[-1]); - if (!str) - return JS_FALSE; - - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -static JSBool -obj_valueOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - *rval = OBJECT_TO_JSVAL(obj); - return JS_TRUE; -} - -/* - * Check whether principals subsumes scopeobj's principals, and return true - * if so (or if scopeobj has no principals, for backward compatibility with - * the JS API, which does not require principals), and false otherwise. - */ -JSBool -js_CheckPrincipalsAccess(JSContext *cx, JSObject *scopeobj, - JSPrincipals *principals, const char *caller) -{ - JSRuntime *rt; - JSPrincipals *scopePrincipals; - - rt = cx->runtime; - if (rt->findObjectPrincipals) { - scopePrincipals = rt->findObjectPrincipals(cx, scopeobj); - if (!principals || !scopePrincipals || - !principals->subsume(principals, scopePrincipals)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_INDIRECT_CALL, caller); - return JS_FALSE; - } - } - return JS_TRUE; -} - -JSObject * -js_CheckScopeChainValidity(JSContext *cx, JSObject *scopeobj, const char *caller) -{ - JSClass *clasp; - JSExtendedClass *xclasp; - JSObject *inner; - - if (!scopeobj) - goto bad; - - OBJ_TO_INNER_OBJECT(cx, scopeobj); - if (!scopeobj) - return NULL; - - inner = scopeobj; - - /* XXX This is an awful gross hack. */ - while (scopeobj) { - clasp = OBJ_GET_CLASS(cx, scopeobj); - if (clasp->flags & JSCLASS_IS_EXTENDED) { - xclasp = (JSExtendedClass*)clasp; - if (xclasp->innerObject && - xclasp->innerObject(cx, scopeobj) != scopeobj) { - goto bad; - } - } - - scopeobj = OBJ_GET_PARENT(cx, scopeobj); - } - - return inner; - -bad: - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_INDIRECT_CALL, caller); - return NULL; -} - -static JSBool -obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSStackFrame *fp, *caller; - JSBool indirectCall; - JSObject *scopeobj; - JSString *str; - const char *file; - uintN line; - JSPrincipals *principals; - JSScript *script; - JSBool ok; -#if JS_HAS_EVAL_THIS_SCOPE - JSObject *callerScopeChain = NULL, *callerVarObj = NULL; - JSObject *setCallerScopeChain = NULL; - JSBool setCallerVarObj = JS_FALSE; -#endif - - fp = cx->fp; - caller = JS_GetScriptedCaller(cx, fp); - indirectCall = (caller && caller->pc && *caller->pc != JSOP_EVAL); - - if (JS_VERSION_IS_ECMA(cx) && - indirectCall && - !JS_ReportErrorFlagsAndNumber(cx, - JSREPORT_WARNING | JSREPORT_STRICT, - js_GetErrorMessage, NULL, - JSMSG_BAD_INDIRECT_CALL, - js_eval_str)) { - return JS_FALSE; - } - - if (!JSVAL_IS_STRING(argv[0])) { - *rval = argv[0]; - return JS_TRUE; - } - - /* - * If the caller is a lightweight function and doesn't have a variables - * object, then we need to provide one for the compiler to stick any - * declared (var) variables into. - */ - if (caller && !caller->varobj && !js_GetCallObject(cx, caller, NULL)) - return JS_FALSE; - -#if JS_HAS_SCRIPT_OBJECT - /* - * Script.prototype.compile/exec and Object.prototype.eval all take an - * optional trailing argument that overrides the scope object. - */ - scopeobj = NULL; - if (argc >= 2) { - if (!js_ValueToObject(cx, argv[1], &scopeobj)) - return JS_FALSE; - argv[1] = OBJECT_TO_JSVAL(scopeobj); - } - if (!scopeobj) -#endif - { -#if JS_HAS_EVAL_THIS_SCOPE - /* If obj.eval(str), emulate 'with (obj) eval(str)' in the caller. */ - if (indirectCall) { - callerScopeChain = caller->scopeChain; - if (obj != callerScopeChain) { - if (!js_CheckPrincipalsAccess(cx, obj, - caller->script->principals, - js_eval_str)) { - return JS_FALSE; - } - - scopeobj = js_NewWithObject(cx, obj, callerScopeChain, -1); - if (!scopeobj) - return JS_FALSE; - - /* Set fp->scopeChain too, for the compiler. */ - caller->scopeChain = fp->scopeChain = scopeobj; - - /* Remember scopeobj so we can null its private when done. */ - setCallerScopeChain = scopeobj; - } - - callerVarObj = caller->varobj; - if (obj != callerVarObj) { - /* Set fp->varobj too, for the compiler. */ - caller->varobj = fp->varobj = obj; - setCallerVarObj = JS_TRUE; - } - } - /* From here on, control must exit through label out with ok set. */ -#endif - -#if JS_BUG_EVAL_THIS_SCOPE - /* An old version used the object in which eval was found for scope. */ - scopeobj = obj; -#else - /* Compile using caller's current scope object. */ - if (caller) - scopeobj = caller->scopeChain; -#endif - } - - /* Ensure we compile this eval with the right object in the scope chain. */ - scopeobj = js_CheckScopeChainValidity(cx, scopeobj, js_eval_str); - if (!scopeobj) - return JS_FALSE; - - str = JSVAL_TO_STRING(argv[0]); - if (caller) { - file = caller->script->filename; - line = js_PCToLineNumber(cx, caller->script, caller->pc); - principals = JS_EvalFramePrincipals(cx, fp, caller); - } else { - file = NULL; - line = 0; - principals = NULL; - } - - /* - * Set JSFRAME_EVAL on fp and any frames (e.g., fun_call if eval.call was - * invoked) between fp and its scripted caller, to help the compiler easily - * find the same caller whose scope and var obj we've set. - * - * XXX this nonsense could, and perhaps should, go away with a better way - * to pass params to the compiler than via the top-most frame. - */ - do { - fp->flags |= JSFRAME_EVAL; - } while ((fp = fp->down) != caller); - - script = JS_CompileUCScriptForPrincipals(cx, scopeobj, principals, - JSSTRING_CHARS(str), - JSSTRING_LENGTH(str), - file, line); - if (!script) { - ok = JS_FALSE; - goto out; - } - -#if !JS_BUG_EVAL_THIS_SCOPE -#if JS_HAS_SCRIPT_OBJECT - if (argc < 2) -#endif - { - /* Execute using caller's new scope object (might be a Call object). */ - if (caller) - scopeobj = caller->scopeChain; - } -#endif - - /* - * Belt-and-braces: check that the lesser of eval's principals and the - * caller's principals has access to scopeobj. - */ - ok = js_CheckPrincipalsAccess(cx, scopeobj, principals, js_eval_str); - if (ok) - ok = js_Execute(cx, scopeobj, script, caller, JSFRAME_EVAL, rval); - - JS_DestroyScript(cx, script); - -out: -#if JS_HAS_EVAL_THIS_SCOPE - /* Restore OBJ_GET_PARENT(scopeobj) not callerScopeChain in case of Call. */ - if (setCallerScopeChain) { - caller->scopeChain = callerScopeChain; - JS_ASSERT(OBJ_GET_CLASS(cx, setCallerScopeChain) == &js_WithClass); - JS_SetPrivate(cx, setCallerScopeChain, NULL); - } - if (setCallerVarObj) - caller->varobj = callerVarObj; -#endif - return ok; -} - -#if JS_HAS_OBJ_WATCHPOINT - -static JSBool -obj_watch_handler(JSContext *cx, JSObject *obj, jsval id, jsval old, jsval *nvp, - void *closure) -{ - JSObject *callable; - JSRuntime *rt; - JSStackFrame *caller; - JSPrincipals *subject, *watcher; - JSResolvingKey key; - JSResolvingEntry *entry; - uint32 generation; - jsval argv[3]; - JSBool ok; - - callable = (JSObject *) closure; - - rt = cx->runtime; - if (rt->findObjectPrincipals) { - /* Skip over any obj_watch_* frames between us and the real subject. */ - caller = JS_GetScriptedCaller(cx, cx->fp); - if (caller) { - /* - * Only call the watch handler if the watcher is allowed to watch - * the currently executing script. - */ - watcher = rt->findObjectPrincipals(cx, callable); - subject = JS_StackFramePrincipals(cx, caller); - - if (watcher && subject && !watcher->subsume(watcher, subject)) { - /* Silently don't call the watch handler. */ - return JS_TRUE; - } - } - } - - /* Avoid recursion on (obj, id) already being watched on cx. */ - key.obj = obj; - key.id = id; - if (!js_StartResolving(cx, &key, JSRESFLAG_WATCH, &entry)) - return JS_FALSE; - if (!entry) - return JS_TRUE; - generation = cx->resolvingTable->generation; - - argv[0] = id; - argv[1] = old; - argv[2] = *nvp; - ok = js_InternalCall(cx, obj, OBJECT_TO_JSVAL(callable), 3, argv, nvp); - js_StopResolving(cx, &key, JSRESFLAG_WATCH, entry, generation); - return ok; -} - -static JSBool -obj_watch(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSObject *callable; - jsval userid, value; - jsid propid; - uintN attrs; - - callable = js_ValueToCallableObject(cx, &argv[1], 0); - if (!callable) - return JS_FALSE; - - /* Compute the unique int/atom symbol id needed by js_LookupProperty. */ - userid = argv[0]; - if (!JS_ValueToId(cx, userid, &propid)) - return JS_FALSE; - - if (!OBJ_CHECK_ACCESS(cx, obj, propid, JSACC_WATCH, &value, &attrs)) - return JS_FALSE; - if (attrs & JSPROP_READONLY) - return JS_TRUE; - return JS_SetWatchPoint(cx, obj, userid, obj_watch_handler, callable); -} - -static JSBool -obj_unwatch(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - return JS_ClearWatchPoint(cx, obj, argv[0], NULL, NULL); -} - -#endif /* JS_HAS_OBJ_WATCHPOINT */ - -#if JS_HAS_NEW_OBJ_METHODS -/* - * Prototype and property query methods, to complement the 'in' and - * 'instanceof' operators. - */ - -/* Proposed ECMA 15.2.4.5. */ -static JSBool -obj_hasOwnProperty(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - return js_HasOwnPropertyHelper(cx, obj, obj->map->ops->lookupProperty, - argc, argv, rval); -} - -JSBool -js_HasOwnPropertyHelper(JSContext *cx, JSObject *obj, JSLookupPropOp lookup, - uintN argc, jsval *argv, jsval *rval) -{ - jsid id; - JSObject *obj2; - JSProperty *prop; - JSScopeProperty *sprop; - - if (!JS_ValueToId(cx, argv[0], &id)) - return JS_FALSE; - if (!lookup(cx, obj, id, &obj2, &prop)) - return JS_FALSE; - if (!prop) { - *rval = JSVAL_FALSE; - } else if (obj2 == obj) { - *rval = JSVAL_TRUE; - } else { - JSClass *clasp; - JSExtendedClass *xclasp; - - clasp = OBJ_GET_CLASS(cx, obj); - xclasp = (clasp->flags & JSCLASS_IS_EXTENDED) - ? (JSExtendedClass *)clasp - : NULL; - if (xclasp && xclasp->outerObject && - xclasp->outerObject(cx, obj2) == obj) { - *rval = JSVAL_TRUE; - } else if (OBJ_IS_NATIVE(obj2) && OBJ_GET_CLASS(cx, obj2) == clasp) { - /* - * The combination of JSPROP_SHARED and JSPROP_PERMANENT in a - * delegated property makes that property appear to be direct in - * all delegating instances of the same native class. This hack - * avoids bloating every function instance with its own 'length' - * (AKA 'arity') property. But it must not extend across class - * boundaries, to avoid making hasOwnProperty lie (bug 320854). - * - * It's not really a hack, of course: a permanent property can't - * be deleted, and JSPROP_SHARED means "don't allocate a slot in - * any instance, prototype or delegating". Without a slot, and - * without the ability to remove and recreate (with differences) - * the property, there is no way to tell whether it is directly - * owned, or indirectly delegated. - */ - sprop = (JSScopeProperty *)prop; - *rval = BOOLEAN_TO_JSVAL(SPROP_IS_SHARED_PERMANENT(sprop)); - } else { - *rval = JSVAL_FALSE; - } - } - if (prop) - OBJ_DROP_PROPERTY(cx, obj2, prop); - return JS_TRUE; -} - -/* Proposed ECMA 15.2.4.6. */ -static JSBool -obj_isPrototypeOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSBool b; - - if (!js_IsDelegate(cx, obj, *argv, &b)) - return JS_FALSE; - *rval = BOOLEAN_TO_JSVAL(b); - return JS_TRUE; -} - -/* Proposed ECMA 15.2.4.7. */ -static JSBool -obj_propertyIsEnumerable(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jsid id; - uintN attrs; - JSObject *obj2; - JSProperty *prop; - JSBool ok; - - if (!JS_ValueToId(cx, argv[0], &id)) - return JS_FALSE; - - if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop)) - return JS_FALSE; - - if (!prop) { - *rval = JSVAL_FALSE; - return JS_TRUE; - } - - /* - * XXX ECMA spec error compatible: return false unless hasOwnProperty. - * The ECMA spec really should be fixed so propertyIsEnumerable and the - * for..in loop agree on whether prototype properties are enumerable, - * obviously by fixing this method (not by breaking the for..in loop!). - * - * We check here for shared permanent prototype properties, which should - * be treated as if they are local to obj. They are an implementation - * technique used to satisfy ECMA requirements; users should not be able - * to distinguish a shared permanent proto-property from a local one. - */ - if (obj2 != obj && - !(OBJ_IS_NATIVE(obj2) && - SPROP_IS_SHARED_PERMANENT((JSScopeProperty *)prop))) { - OBJ_DROP_PROPERTY(cx, obj2, prop); - *rval = JSVAL_FALSE; - return JS_TRUE; - } - - ok = OBJ_GET_ATTRIBUTES(cx, obj2, id, prop, &attrs); - OBJ_DROP_PROPERTY(cx, obj2, prop); - if (ok) - *rval = BOOLEAN_TO_JSVAL((attrs & JSPROP_ENUMERATE) != 0); - return ok; -} -#endif /* JS_HAS_NEW_OBJ_METHODS */ - -#if JS_HAS_GETTER_SETTER -static JSBool -obj_defineGetter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jsval fval, junk; - jsid id; - uintN attrs; - - fval = argv[1]; - if (JS_TypeOfValue(cx, fval) != JSTYPE_FUNCTION) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_GETTER_OR_SETTER, - js_getter_str); - return JS_FALSE; - } - - if (!JS_ValueToId(cx, argv[0], &id)) - return JS_FALSE; - if (!js_CheckRedeclaration(cx, obj, id, JSPROP_GETTER, NULL, NULL)) - return JS_FALSE; - /* - * Getters and setters are just like watchpoints from an access - * control point of view. - */ - if (!OBJ_CHECK_ACCESS(cx, obj, id, JSACC_WATCH, &junk, &attrs)) - return JS_FALSE; - return OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID, - (JSPropertyOp) JSVAL_TO_OBJECT(fval), NULL, - JSPROP_ENUMERATE | JSPROP_GETTER | JSPROP_SHARED, - NULL); -} - -static JSBool -obj_defineSetter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jsval fval, junk; - jsid id; - uintN attrs; - - fval = argv[1]; - if (JS_TypeOfValue(cx, fval) != JSTYPE_FUNCTION) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_GETTER_OR_SETTER, - js_setter_str); - return JS_FALSE; - } - - if (!JS_ValueToId(cx, argv[0], &id)) - return JS_FALSE; - if (!js_CheckRedeclaration(cx, obj, id, JSPROP_SETTER, NULL, NULL)) - return JS_FALSE; - /* - * Getters and setters are just like watchpoints from an access - * control point of view. - */ - if (!OBJ_CHECK_ACCESS(cx, obj, id, JSACC_WATCH, &junk, &attrs)) - return JS_FALSE; - return OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID, - NULL, (JSPropertyOp) JSVAL_TO_OBJECT(fval), - JSPROP_ENUMERATE | JSPROP_SETTER | JSPROP_SHARED, - NULL); -} - -static JSBool -obj_lookupGetter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jsid id; - JSObject *pobj; - JSProperty *prop; - JSScopeProperty *sprop; - - if (!JS_ValueToId(cx, argv[0], &id)) - return JS_FALSE; - if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &pobj, &prop)) - return JS_FALSE; - if (prop) { - if (OBJ_IS_NATIVE(pobj)) { - sprop = (JSScopeProperty *) prop; - if (sprop->attrs & JSPROP_GETTER) - *rval = OBJECT_TO_JSVAL(sprop->getter); - } - OBJ_DROP_PROPERTY(cx, pobj, prop); - } - return JS_TRUE; -} - -static JSBool -obj_lookupSetter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jsid id; - JSObject *pobj; - JSProperty *prop; - JSScopeProperty *sprop; - - if (!JS_ValueToId(cx, argv[0], &id)) - return JS_FALSE; - if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &pobj, &prop)) - return JS_FALSE; - if (prop) { - if (OBJ_IS_NATIVE(pobj)) { - sprop = (JSScopeProperty *) prop; - if (sprop->attrs & JSPROP_SETTER) - *rval = OBJECT_TO_JSVAL(sprop->setter); - } - OBJ_DROP_PROPERTY(cx, pobj, prop); - } - return JS_TRUE; -} -#endif /* JS_HAS_GETTER_SETTER */ - -#if JS_HAS_OBJ_WATCHPOINT -const char js_watch_str[] = "watch"; -const char js_unwatch_str[] = "unwatch"; -#endif -#if JS_HAS_NEW_OBJ_METHODS -const char js_hasOwnProperty_str[] = "hasOwnProperty"; -const char js_isPrototypeOf_str[] = "isPrototypeOf"; -const char js_propertyIsEnumerable_str[] = "propertyIsEnumerable"; -#endif -#if JS_HAS_GETTER_SETTER -const char js_defineGetter_str[] = "__defineGetter__"; -const char js_defineSetter_str[] = "__defineSetter__"; -const char js_lookupGetter_str[] = "__lookupGetter__"; -const char js_lookupSetter_str[] = "__lookupSetter__"; -#endif - -static JSFunctionSpec object_methods[] = { -#if JS_HAS_TOSOURCE - {js_toSource_str, js_obj_toSource, 0, 0, OBJ_TOSTRING_EXTRA}, -#endif - {js_toString_str, js_obj_toString, 0, 0, OBJ_TOSTRING_EXTRA}, - {js_toLocaleString_str, js_obj_toLocaleString, 0, 0, OBJ_TOSTRING_EXTRA}, - {js_valueOf_str, obj_valueOf, 0,0,0}, - {js_eval_str, obj_eval, 1,0,0}, -#if JS_HAS_OBJ_WATCHPOINT - {js_watch_str, obj_watch, 2,0,0}, - {js_unwatch_str, obj_unwatch, 1,0,0}, -#endif -#if JS_HAS_NEW_OBJ_METHODS - {js_hasOwnProperty_str, obj_hasOwnProperty, 1,0,0}, - {js_isPrototypeOf_str, obj_isPrototypeOf, 1,0,0}, - {js_propertyIsEnumerable_str, obj_propertyIsEnumerable, 1,0,0}, -#endif -#if JS_HAS_GETTER_SETTER - {js_defineGetter_str, obj_defineGetter, 2,0,0}, - {js_defineSetter_str, obj_defineSetter, 2,0,0}, - {js_lookupGetter_str, obj_lookupGetter, 1,0,0}, - {js_lookupSetter_str, obj_lookupSetter, 1,0,0}, -#endif - {0,0,0,0,0} -}; - -static JSBool -Object(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - if (argc == 0) { - /* Trigger logic below to construct a blank object. */ - obj = NULL; - } else { - /* If argv[0] is null or undefined, obj comes back null. */ - if (!js_ValueToObject(cx, argv[0], &obj)) - return JS_FALSE; - } - if (!obj) { - JS_ASSERT(!argc || JSVAL_IS_NULL(argv[0]) || JSVAL_IS_VOID(argv[0])); - if (cx->fp->flags & JSFRAME_CONSTRUCTING) - return JS_TRUE; - obj = js_NewObject(cx, &js_ObjectClass, NULL, NULL); - if (!obj) - return JS_FALSE; - } - *rval = OBJECT_TO_JSVAL(obj); - return JS_TRUE; -} - -/* - * ObjectOps and Class for with-statement stack objects. - */ -static JSBool -with_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, - JSProperty **propp) -{ - JSObject *proto = OBJ_GET_PROTO(cx, obj); - if (!proto) - return js_LookupProperty(cx, obj, id, objp, propp); - return OBJ_LOOKUP_PROPERTY(cx, proto, id, objp, propp); -} - -static JSBool -with_GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp) -{ - JSObject *proto = OBJ_GET_PROTO(cx, obj); - if (!proto) - return js_GetProperty(cx, obj, id, vp); - return OBJ_GET_PROPERTY(cx, proto, id, vp); -} - -static JSBool -with_SetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp) -{ - JSObject *proto = OBJ_GET_PROTO(cx, obj); - if (!proto) - return js_SetProperty(cx, obj, id, vp); - return OBJ_SET_PROPERTY(cx, proto, id, vp); -} - -static JSBool -with_GetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop, - uintN *attrsp) -{ - JSObject *proto = OBJ_GET_PROTO(cx, obj); - if (!proto) - return js_GetAttributes(cx, obj, id, prop, attrsp); - return OBJ_GET_ATTRIBUTES(cx, proto, id, prop, attrsp); -} - -static JSBool -with_SetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop, - uintN *attrsp) -{ - JSObject *proto = OBJ_GET_PROTO(cx, obj); - if (!proto) - return js_SetAttributes(cx, obj, id, prop, attrsp); - return OBJ_SET_ATTRIBUTES(cx, proto, id, prop, attrsp); -} - -static JSBool -with_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval) -{ - JSObject *proto = OBJ_GET_PROTO(cx, obj); - if (!proto) - return js_DeleteProperty(cx, obj, id, rval); - return OBJ_DELETE_PROPERTY(cx, proto, id, rval); -} - -static JSBool -with_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp) -{ - JSObject *proto = OBJ_GET_PROTO(cx, obj); - if (!proto) - return js_DefaultValue(cx, obj, hint, vp); - return OBJ_DEFAULT_VALUE(cx, proto, hint, vp); -} - -static JSBool -with_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, - jsval *statep, jsid *idp) -{ - JSObject *proto = OBJ_GET_PROTO(cx, obj); - if (!proto) - return js_Enumerate(cx, obj, enum_op, statep, idp); - return OBJ_ENUMERATE(cx, proto, enum_op, statep, idp); -} - -static JSBool -with_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode, - jsval *vp, uintN *attrsp) -{ - JSObject *proto = OBJ_GET_PROTO(cx, obj); - if (!proto) - return js_CheckAccess(cx, obj, id, mode, vp, attrsp); - return OBJ_CHECK_ACCESS(cx, proto, id, mode, vp, attrsp); -} - -static JSObject * -with_ThisObject(JSContext *cx, JSObject *obj) -{ - JSObject *proto = OBJ_GET_PROTO(cx, obj); - if (!proto) - return obj; - return OBJ_THIS_OBJECT(cx, proto); -} - -JS_FRIEND_DATA(JSObjectOps) js_WithObjectOps = { - js_NewObjectMap, js_DestroyObjectMap, - with_LookupProperty, js_DefineProperty, - with_GetProperty, with_SetProperty, - with_GetAttributes, with_SetAttributes, - with_DeleteProperty, with_DefaultValue, - with_Enumerate, with_CheckAccess, - with_ThisObject, NATIVE_DROP_PROPERTY, - NULL, NULL, - NULL, NULL, - js_SetProtoOrParent, js_SetProtoOrParent, - js_Mark, js_Clear, - NULL, NULL -}; - -static JSObjectOps * -with_getObjectOps(JSContext *cx, JSClass *clasp) -{ - return &js_WithObjectOps; -} - -JSClass js_WithClass = { - "With", - JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1), - JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, - with_getObjectOps, - 0,0,0,0,0,0,0 -}; - -JSObject * -js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth) -{ - JSObject *obj; - - obj = js_NewObject(cx, &js_WithClass, proto, parent); - if (!obj) - return NULL; - obj->slots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(cx->fp); - OBJ_SET_BLOCK_DEPTH(cx, obj, depth); - return obj; -} - -#if JS_HAS_OBJ_PROTO_PROP -static JSBool -With(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSObject *parent, *proto; - jsval v; - - if (!JS_ReportErrorFlagsAndNumber(cx, - JSREPORT_WARNING | JSREPORT_STRICT, - js_GetErrorMessage, NULL, - JSMSG_DEPRECATED_USAGE, - js_WithClass.name)) { - return JS_FALSE; - } - - if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) { - obj = js_NewWithObject(cx, NULL, NULL, -1); - if (!obj) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(obj); - } - - parent = cx->fp->scopeChain; - if (argc > 0) { - if (!js_ValueToObject(cx, argv[0], &proto)) - return JS_FALSE; - v = OBJECT_TO_JSVAL(proto); - if (!obj_setSlot(cx, obj, INT_TO_JSVAL(JSSLOT_PROTO), &v)) - return JS_FALSE; - if (argc > 1) { - if (!js_ValueToObject(cx, argv[1], &parent)) - return JS_FALSE; - } - } - v = OBJECT_TO_JSVAL(parent); - return obj_setSlot(cx, obj, INT_TO_JSVAL(JSSLOT_PARENT), &v); -} -#endif - -JSObject * -js_InitObjectClass(JSContext *cx, JSObject *obj) -{ - JSObject *proto; - jsval eval; - -#if JS_HAS_SHARP_VARS - JS_ASSERT(sizeof(jsatomid) * JS_BITS_PER_BYTE >= ATOM_INDEX_LIMIT_LOG2 + 1); -#endif - - proto = JS_InitClass(cx, obj, NULL, &js_ObjectClass, Object, 1, - object_props, object_methods, NULL, NULL); - if (!proto) - return NULL; - -#if JS_HAS_OBJ_PROTO_PROP - if (!JS_InitClass(cx, obj, NULL, &js_WithClass, With, 0, - NULL, NULL, NULL, NULL)) { - return NULL; - } -#endif - - /* ECMA (15.1.2.1) says 'eval' is also a property of the global object. */ - if (!OBJ_GET_PROPERTY(cx, proto, - ATOM_TO_JSID(cx->runtime->atomState.evalAtom), - &eval)) { - return NULL; - } - if (!OBJ_DEFINE_PROPERTY(cx, obj, - ATOM_TO_JSID(cx->runtime->atomState.evalAtom), - eval, NULL, NULL, 0, NULL)) { - return NULL; - } - - return proto; -} - -void -js_InitObjectMap(JSObjectMap *map, jsrefcount nrefs, JSObjectOps *ops, - JSClass *clasp) -{ - map->nrefs = nrefs; - map->ops = ops; - map->nslots = JS_INITIAL_NSLOTS; - map->freeslot = JSSLOT_FREE(clasp); -} - -JSObjectMap * -js_NewObjectMap(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops, - JSClass *clasp, JSObject *obj) -{ - return (JSObjectMap *) js_NewScope(cx, nrefs, ops, clasp, obj); -} - -void -js_DestroyObjectMap(JSContext *cx, JSObjectMap *map) -{ - js_DestroyScope(cx, (JSScope *)map); -} - -JSObjectMap * -js_HoldObjectMap(JSContext *cx, JSObjectMap *map) -{ - JS_ASSERT(map->nrefs >= 0); - JS_ATOMIC_INCREMENT(&map->nrefs); - return map; -} - -JSObjectMap * -js_DropObjectMap(JSContext *cx, JSObjectMap *map, JSObject *obj) -{ - JS_ASSERT(map->nrefs > 0); - JS_ATOMIC_DECREMENT(&map->nrefs); - if (map->nrefs == 0) { - map->ops->destroyObjectMap(cx, map); - return NULL; - } - if (MAP_IS_NATIVE(map) && ((JSScope *)map)->object == obj) - ((JSScope *)map)->object = NULL; - return map; -} - -static JSBool -GetClassPrototype(JSContext *cx, JSObject *scope, const char *name, - JSObject **protop); - -static jsval * -AllocSlots(JSContext *cx, jsval *slots, uint32 nslots) -{ - size_t nbytes, obytes, minbytes; - uint32 i, oslots; - jsval *newslots; - - nbytes = (nslots + 1) * sizeof(jsval); - if (slots) { - oslots = slots[-1]; - obytes = (oslots + 1) * sizeof(jsval); - } else { - oslots = 0; - obytes = 0; - } - - if (nbytes <= GC_NBYTES_MAX) { - newslots = (jsval *) js_NewGCThing(cx, GCX_PRIVATE, nbytes); - } else { - newslots = (jsval *) - JS_realloc(cx, - (obytes <= GC_NBYTES_MAX) ? NULL : slots - 1, - nbytes); - } - if (!newslots) - return NULL; - - if (obytes != 0) { - /* If either nbytes or obytes fit in a GC-thing, we must copy. */ - minbytes = JS_MIN(nbytes, obytes); - if (minbytes <= GC_NBYTES_MAX) - memcpy(newslots + 1, slots, minbytes - sizeof(jsval)); - - /* If nbytes are in a GC-thing but obytes aren't, free obytes. */ - if (nbytes <= GC_NBYTES_MAX && obytes > GC_NBYTES_MAX) - JS_free(cx, slots - 1); - - /* If we're extending an allocation, initialize free slots. */ - if (nslots > oslots) { - for (i = 1 + oslots; i <= nslots; i++) - newslots[i] = JSVAL_VOID; - } - } - - newslots[0] = nslots; - return ++newslots; -} - -static void -FreeSlots(JSContext *cx, jsval *slots) -{ - size_t nbytes; - - /* - * NB: We count on smaller GC-things being finalized before larger things - * that become garbage during the same GC. Without this assumption, we - * couldn't load slots[-1] here without possibly loading a gcFreeList link - * (see struct JSGCThing in jsgc.h). - */ - nbytes = (slots[-1] + 1) * sizeof(jsval); - if (nbytes > GC_NBYTES_MAX) - JS_free(cx, slots - 1); -} - -JSObject * -js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent) -{ - JSObject *obj; - JSObjectOps *ops; - JSObjectMap *map; - JSClass *protoclasp; - uint32 nslots, i; - jsval *newslots; - JSTempValueRooter tvr; - - /* Bootstrap the ur-object, and make it the default prototype object. */ - if (!proto) { - if (!GetClassPrototype(cx, parent, clasp->name, &proto)) - return NULL; - if (!proto && !GetClassPrototype(cx, parent, js_Object_str, &proto)) - return NULL; - } - - /* Always call the class's getObjectOps hook if it has one. */ - ops = clasp->getObjectOps - ? clasp->getObjectOps(cx, clasp) - : &js_ObjectOps; - - /* - * Allocate a zeroed object from the GC heap. Do this *after* any other - * GC-thing allocations under GetClassPrototype or clasp->getObjectOps, - * to avoid displacing the newborn root for obj. - */ - obj = (JSObject *) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject)); - if (!obj) - return NULL; - - /* - * Root obj to prevent it from being killed. - * AllocSlots can trigger a finalizer from a last-ditch GC calling - * JS_ClearNewbornRoots. There's also the possibilty of things - * happening under the objectHook call-out below. - */ - JS_PUSH_SINGLE_TEMP_ROOT(cx, OBJECT_TO_JSVAL(obj), &tvr); - - /* - * Share proto's map only if it has the same JSObjectOps, and only if - * proto's class has the same private and reserved slots as obj's map - * and class have. We assume that if prototype and object are of the - * same class, they always have the same number of computed reserved - * slots (returned via clasp->reserveSlots); otherwise, prototype and - * object classes must have the same (null or not) reserveSlots hook. - */ - if (proto && - (map = proto->map)->ops == ops && - ((protoclasp = OBJ_GET_CLASS(cx, proto)) == clasp || - (!((protoclasp->flags ^ clasp->flags) & - (JSCLASS_HAS_PRIVATE | - (JSCLASS_RESERVED_SLOTS_MASK << JSCLASS_RESERVED_SLOTS_SHIFT))) && - protoclasp->reserveSlots == clasp->reserveSlots))) - { - /* - * Default parent to the parent of the prototype, which was set from - * the parent of the prototype's constructor. - */ - if (!parent) - parent = OBJ_GET_PARENT(cx, proto); - - /* Share the given prototype's map. */ - obj->map = js_HoldObjectMap(cx, map); - - /* Ensure that obj starts with the minimum slots for clasp. */ - nslots = JS_INITIAL_NSLOTS; - } else { - /* Leave parent alone. Allocate a new map for obj. */ - map = ops->newObjectMap(cx, 1, ops, clasp, obj); - if (!map) - goto bad; - obj->map = map; - - /* Let ops->newObjectMap set nslots so as to reserve slots. */ - nslots = map->nslots; - } - - /* Allocate a slots vector, with a -1'st element telling its length. */ - newslots = AllocSlots(cx, NULL, nslots); - if (!newslots) { - js_DropObjectMap(cx, obj->map, obj); - obj->map = NULL; - goto bad; - } - - /* Set the proto, parent, and class properties. */ - newslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto); - newslots[JSSLOT_PARENT] = OBJECT_TO_JSVAL(parent); - newslots[JSSLOT_CLASS] = PRIVATE_TO_JSVAL(clasp); - - /* Clear above JSSLOT_CLASS so the GC doesn't load uninitialized memory. */ - for (i = JSSLOT_CLASS + 1; i < nslots; i++) - newslots[i] = JSVAL_VOID; - - /* Store newslots after initializing all of 'em, just in case. */ - obj->slots = newslots; - - if (cx->runtime->objectHook) { - JS_KEEP_ATOMS(cx->runtime); - cx->runtime->objectHook(cx, obj, JS_TRUE, cx->runtime->objectHookData); - JS_UNKEEP_ATOMS(cx->runtime); - } - -out: - JS_POP_TEMP_ROOT(cx, &tvr); - cx->newborn[GCX_OBJECT] = (JSGCThing *) obj; - return obj; - -bad: - obj = NULL; - goto out; -} - -JSBool -js_FindConstructor(JSContext *cx, JSObject *start, const char *name, jsval *vp) -{ - JSAtom *atom; - JSObject *obj, *pobj; - JSProperty *prop; - JSScopeProperty *sprop; - - atom = js_Atomize(cx, name, strlen(name), 0); - if (!atom) - return JS_FALSE; - - if (start || (cx->fp && (start = cx->fp->scopeChain) != NULL)) { - /* Find the topmost object in the scope chain. */ - do { - obj = start; - start = OBJ_GET_PARENT(cx, obj); - } while (start); - } else { - obj = cx->globalObject; - if (!obj) { - *vp = JSVAL_VOID; - return JS_TRUE; - } - } - - JS_ASSERT(OBJ_IS_NATIVE(obj)); - if (!js_LookupPropertyWithFlags(cx, obj, ATOM_TO_JSID(atom), - JSRESOLVE_CLASSNAME, &pobj, &prop)) { - return JS_FALSE; - } - if (!prop) { - *vp = JSVAL_VOID; - return JS_TRUE; - } - - JS_ASSERT(OBJ_IS_NATIVE(pobj)); - sprop = (JSScopeProperty *) prop; - JS_ASSERT(SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(pobj))); - *vp = OBJ_GET_SLOT(cx, pobj, sprop->slot); - OBJ_DROP_PROPERTY(cx, pobj, prop); - return JS_TRUE; -} - -JSObject * -js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto, - JSObject *parent, uintN argc, jsval *argv) -{ - jsval cval, rval; - JSTempValueRooter argtvr, tvr; - JSObject *obj, *ctor; - - JS_PUSH_TEMP_ROOT(cx, argc, argv, &argtvr); - - if (!js_FindConstructor(cx, parent, clasp->name, &cval)) { - JS_POP_TEMP_ROOT(cx, &argtvr); - return NULL; - } - if (JSVAL_IS_PRIMITIVE(cval)) { - js_ReportIsNotFunction(cx, &cval, JSV2F_CONSTRUCT | JSV2F_SEARCH_STACK); - JS_POP_TEMP_ROOT(cx, &argtvr); - return NULL; - } - - /* - * Protect cval in case a crazy getter for .prototype uproots it. After - * this point, all control flow must exit through label out with obj set. - */ - JS_PUSH_SINGLE_TEMP_ROOT(cx, cval, &tvr); - - /* - * If proto or parent are NULL, set them to Constructor.prototype and/or - * Constructor.__parent__, just like JSOP_NEW does. - */ - ctor = JSVAL_TO_OBJECT(cval); - if (!parent) - parent = OBJ_GET_PARENT(cx, ctor); - if (!proto) { - if (!OBJ_GET_PROPERTY(cx, ctor, - ATOM_TO_JSID(cx->runtime->atomState - .classPrototypeAtom), - &rval)) { - obj = NULL; - goto out; - } - if (JSVAL_IS_OBJECT(rval)) - proto = JSVAL_TO_OBJECT(rval); - } - - obj = js_NewObject(cx, clasp, proto, parent); - if (!obj) - goto out; - - if (!js_InternalConstruct(cx, obj, cval, argc, argv, &rval)) - goto bad; - - if (JSVAL_IS_PRIMITIVE(rval)) - goto out; - obj = JSVAL_TO_OBJECT(rval); - - /* - * If the given class has both the JSCLASS_HAS_PRIVATE and the - * JSCLASS_CONSTRUCT_PROTOTYPE flags, then the class should have its private - * data set. If it doesn't, then it means the constructor was replaced, and - * we should throw a typerr. - */ - if (OBJ_GET_CLASS(cx, obj) != clasp || - (!(~clasp->flags & (JSCLASS_HAS_PRIVATE | - JSCLASS_CONSTRUCT_PROTOTYPE)) && - !JS_GetPrivate(cx, obj))) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_WRONG_CONSTRUCTOR, clasp->name); - goto bad; - } - -out: - JS_POP_TEMP_ROOT(cx, &tvr); - JS_POP_TEMP_ROOT(cx, &argtvr); - return obj; - -bad: - cx->newborn[GCX_OBJECT] = NULL; - obj = NULL; - goto out; -} - -void -js_FinalizeObject(JSContext *cx, JSObject *obj) -{ - JSObjectMap *map; - - /* Cope with stillborn objects that have no map. */ - map = obj->map; - if (!map) - return; - JS_ASSERT(obj->slots); - - if (cx->runtime->objectHook) - cx->runtime->objectHook(cx, obj, JS_FALSE, cx->runtime->objectHookData); - - /* Remove all watchpoints with weak links to obj. */ - JS_ClearWatchPointsForObject(cx, obj); - - /* - * Finalize obj first, in case it needs map and slots. Optimized to use - * LOCKED_OBJ_GET_CLASS instead of OBJ_GET_CLASS, so we avoid "promoting" - * obj's scope from lock-free to lock-full (see jslock.c:ClaimScope) when - * we're called from the GC. Only the GC should call js_FinalizeObject, - * and no other threads run JS (and possibly racing to update obj->slots) - * while the GC is running. - */ - LOCKED_OBJ_GET_CLASS(obj)->finalize(cx, obj); - - /* Drop map and free slots. */ - js_DropObjectMap(cx, map, obj); - obj->map = NULL; - FreeSlots(cx, obj->slots); - obj->slots = NULL; -} - -/* XXXbe if one adds props, deletes earlier props, adds more, the last added - won't recycle the deleted props' slots. */ -JSBool -js_AllocSlot(JSContext *cx, JSObject *obj, uint32 *slotp) -{ - JSObjectMap *map; - JSClass *clasp; - uint32 nslots; - jsval *newslots; - - map = obj->map; - JS_ASSERT(!MAP_IS_NATIVE(map) || ((JSScope *)map)->object == obj); - clasp = LOCKED_OBJ_GET_CLASS(obj); - if (map->freeslot == JSSLOT_FREE(clasp)) { - /* Adjust map->freeslot to include computed reserved slots, if any. */ - if (clasp->reserveSlots) - map->freeslot += clasp->reserveSlots(cx, obj); - } - nslots = map->nslots; - if (map->freeslot >= nslots) { - nslots = map->freeslot; - JS_ASSERT(nslots >= JS_INITIAL_NSLOTS); - nslots += (nslots + 1) / 2; - - newslots = AllocSlots(cx, obj->slots, nslots); - if (!newslots) - return JS_FALSE; - map->nslots = nslots; - obj->slots = newslots; - } - -#ifdef TOO_MUCH_GC - obj->slots[map->freeslot] = JSVAL_VOID; -#endif - *slotp = map->freeslot++; - return JS_TRUE; -} - -void -js_FreeSlot(JSContext *cx, JSObject *obj, uint32 slot) -{ - JSObjectMap *map; - uint32 nslots; - jsval *newslots; - - OBJ_CHECK_SLOT(obj, slot); - obj->slots[slot] = JSVAL_VOID; - map = obj->map; - JS_ASSERT(!MAP_IS_NATIVE(map) || ((JSScope *)map)->object == obj); - if (map->freeslot == slot + 1) - map->freeslot = slot; - nslots = map->nslots; - if (nslots > JS_INITIAL_NSLOTS && map->freeslot < nslots / 2) { - nslots = map->freeslot; - nslots += nslots / 2; - if (nslots < JS_INITIAL_NSLOTS) - nslots = JS_INITIAL_NSLOTS; - - newslots = AllocSlots(cx, obj->slots, nslots); - if (!newslots) - return; - map->nslots = nslots; - obj->slots = newslots; - } -} - -#if JS_BUG_EMPTY_INDEX_ZERO -#define CHECK_FOR_EMPTY_INDEX(id) \ - JS_BEGIN_MACRO \ - if (JSSTRING_LENGTH(str_) == 0) \ - id = JSVAL_ZERO; \ - JS_END_MACRO -#else -#define CHECK_FOR_EMPTY_INDEX(id) /* nothing */ -#endif - -/* JSVAL_INT_MAX as a string */ -#define JSVAL_INT_MAX_STRING "1073741823" - -#define CHECK_FOR_STRING_INDEX(id) \ - JS_BEGIN_MACRO \ - if (JSID_IS_ATOM(id)) { \ - JSAtom *atom_ = JSID_TO_ATOM(id); \ - JSString *str_ = ATOM_TO_STRING(atom_); \ - const jschar *cp_ = str_->chars; \ - JSBool negative_ = (*cp_ == '-'); \ - if (negative_) cp_++; \ - if (JS7_ISDEC(*cp_)) { \ - size_t n_ = str_->length - negative_; \ - if (n_ <= sizeof(JSVAL_INT_MAX_STRING) - 1) \ - id = CheckForStringIndex(id, cp_, cp_ + n_, negative_); \ - } else { \ - CHECK_FOR_EMPTY_INDEX(id); \ - } \ - } \ - JS_END_MACRO - -static jsid -CheckForStringIndex(jsid id, const jschar *cp, const jschar *end, - JSBool negative) -{ - jsuint index = JS7_UNDEC(*cp++); - jsuint oldIndex = 0; - jsuint c = 0; - - if (index != 0) { - while (JS7_ISDEC(*cp)) { - oldIndex = index; - c = JS7_UNDEC(*cp); - index = 10 * index + c; - cp++; - } - } - if (cp == end && - (oldIndex < (JSVAL_INT_MAX / 10) || - (oldIndex == (JSVAL_INT_MAX / 10) && - c <= (JSVAL_INT_MAX % 10)))) { - if (negative) - index = 0 - index; - id = INT_TO_JSID((jsint)index); - } - return id; -} - -static JSBool -HidePropertyName(JSContext *cx, jsid *idp) -{ - jsid id; - JSAtom *atom, *hidden; - - id = *idp; - JS_ASSERT(JSID_IS_ATOM(id)); - - atom = JSID_TO_ATOM(id); - JS_ASSERT(!(atom->flags & ATOM_HIDDEN)); - JS_ASSERT(ATOM_IS_STRING(atom)); - - hidden = js_AtomizeString(cx, ATOM_TO_STRING(atom), ATOM_HIDDEN); - if (!hidden) - return JS_FALSE; - - /* - * Link hidden to unhidden atom to optimize call_enumerate -- this means - * the GC must mark a hidden atom's unhidden counterpart (see js_MarkAtom - * in jsgc.c). It overloads the entry.value member, which for unhidden - * atoms may point to keyword information. - */ - hidden->entry.value = atom; - *idp = ATOM_TO_JSID(hidden); - return JS_TRUE; -} - -JSScopeProperty * -js_AddHiddenProperty(JSContext *cx, JSObject *obj, jsid id, - JSPropertyOp getter, JSPropertyOp setter, uint32 slot, - uintN attrs, uintN flags, intN shortid) -{ - if (!HidePropertyName(cx, &id)) - return NULL; - - flags |= SPROP_IS_HIDDEN; - return js_AddNativeProperty(cx, obj, id, getter, setter, slot, attrs, - flags, shortid); -} - -JSBool -js_LookupHiddenProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, - JSProperty **propp) -{ - return HidePropertyName(cx, &id) && - js_LookupProperty(cx, obj, id, objp, propp); -} - -JSScopeProperty * -js_AddNativeProperty(JSContext *cx, JSObject *obj, jsid id, - JSPropertyOp getter, JSPropertyOp setter, uint32 slot, - uintN attrs, uintN flags, intN shortid) -{ - JSScope *scope; - JSScopeProperty *sprop; - - JS_LOCK_OBJ(cx, obj); - scope = js_GetMutableScope(cx, obj); - if (!scope) { - sprop = NULL; - } else { - /* - * Handle old bug that took empty string as zero index. Also convert - * string indices to integers if appropriate. - */ - CHECK_FOR_STRING_INDEX(id); - sprop = js_AddScopeProperty(cx, scope, id, getter, setter, slot, attrs, - flags, shortid); - } - JS_UNLOCK_OBJ(cx, obj); - return sprop; -} - -JSScopeProperty * -js_ChangeNativePropertyAttrs(JSContext *cx, JSObject *obj, - JSScopeProperty *sprop, uintN attrs, uintN mask, - JSPropertyOp getter, JSPropertyOp setter) -{ - JSScope *scope; - - JS_LOCK_OBJ(cx, obj); - scope = js_GetMutableScope(cx, obj); - if (!scope) { - sprop = NULL; - } else { - sprop = js_ChangeScopePropertyAttrs(cx, scope, sprop, attrs, mask, - getter, setter); - if (sprop) { - PROPERTY_CACHE_FILL(&cx->runtime->propertyCache, obj, sprop->id, - sprop); - } - } - JS_UNLOCK_OBJ(cx, obj); - return sprop; -} - -JSBool -js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value, - JSPropertyOp getter, JSPropertyOp setter, uintN attrs, - JSProperty **propp) -{ - return js_DefineNativeProperty(cx, obj, id, value, getter, setter, attrs, - 0, 0, propp); -} - -/* - * Backward compatibility requires allowing addProperty hooks to mutate the - * nominal initial value of a slot-full property, while GC safety wants that - * value to be stored before the call-out through the hook. Optimize to do - * both while saving cycles for classes that stub their addProperty hook. - */ -#define ADD_PROPERTY_HELPER(cx,clasp,obj,scope,sprop,vp,cleanup) \ - JS_BEGIN_MACRO \ - if ((clasp)->addProperty != JS_PropertyStub) { \ - jsval nominal_ = *(vp); \ - if (!(clasp)->addProperty(cx, obj, SPROP_USERID(sprop), vp)) { \ - cleanup; \ - } \ - if (*(vp) != nominal_) { \ - if (SPROP_HAS_VALID_SLOT(sprop, scope)) \ - LOCKED_OBJ_SET_SLOT(obj, (sprop)->slot, *(vp)); \ - } \ - } \ - JS_END_MACRO - -JSBool -js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, jsval value, - JSPropertyOp getter, JSPropertyOp setter, uintN attrs, - uintN flags, intN shortid, JSProperty **propp) -{ - JSClass *clasp; - JSScope *scope; - JSProperty *prop; - JSScopeProperty *sprop; - - /* - * Handle old bug that took empty string as zero index. Also convert - * string indices to integers if appropriate. - */ - CHECK_FOR_STRING_INDEX(id); - -#if JS_HAS_GETTER_SETTER - /* - * If defining a getter or setter, we must check for its counterpart and - * update the attributes and property ops. A getter or setter is really - * only half of a property. - */ - if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) { - JSObject *pobj; - - /* - * If JS_THREADSAFE and id is found, js_LookupProperty returns with - * sprop non-null and pobj locked. If pobj == obj, the property is - * already in obj and obj has its own (mutable) scope. So if we are - * defining a getter whose setter was already defined, or vice versa, - * finish the job via js_ChangeScopePropertyAttributes, and refresh - * the property cache line for (obj, id) to map sprop. - */ - if (!js_LookupProperty(cx, obj, id, &pobj, &prop)) - return JS_FALSE; - sprop = (JSScopeProperty *) prop; - if (sprop && - pobj == obj && - (sprop->attrs & (JSPROP_GETTER | JSPROP_SETTER))) { - sprop = js_ChangeScopePropertyAttrs(cx, OBJ_SCOPE(obj), sprop, - attrs, sprop->attrs, - (attrs & JSPROP_GETTER) - ? getter - : sprop->getter, - (attrs & JSPROP_SETTER) - ? setter - : sprop->setter); - - /* NB: obj == pobj, so we can share unlock code at the bottom. */ - if (!sprop) - goto bad; - goto out; - } - - if (prop) { - /* NB: call OBJ_DROP_PROPERTY, as pobj might not be native. */ - OBJ_DROP_PROPERTY(cx, pobj, prop); - prop = NULL; - } - } -#endif /* JS_HAS_GETTER_SETTER */ - - /* Lock if object locking is required by this implementation. */ - JS_LOCK_OBJ(cx, obj); - - /* Use the object's class getter and setter by default. */ - clasp = LOCKED_OBJ_GET_CLASS(obj); - if (!getter) - getter = clasp->getProperty; - if (!setter) - setter = clasp->setProperty; - - /* Get obj's own scope if it has one, or create a new one for obj. */ - scope = js_GetMutableScope(cx, obj); - if (!scope) - goto bad; - - /* Add the property to scope, or replace an existing one of the same id. */ - if (clasp->flags & JSCLASS_SHARE_ALL_PROPERTIES) - attrs |= JSPROP_SHARED; - sprop = js_AddScopeProperty(cx, scope, id, getter, setter, - SPROP_INVALID_SLOT, attrs, flags, shortid); - if (!sprop) - goto bad; - - /* Store value before calling addProperty, in case the latter GC's. */ - if (SPROP_HAS_VALID_SLOT(sprop, scope)) - LOCKED_OBJ_SET_SLOT(obj, sprop->slot, value); - - /* XXXbe called with lock held */ - ADD_PROPERTY_HELPER(cx, clasp, obj, scope, sprop, &value, - js_RemoveScopeProperty(cx, scope, id); - goto bad); - -#if JS_HAS_GETTER_SETTER -out: -#endif - PROPERTY_CACHE_FILL(&cx->runtime->propertyCache, obj, id, sprop); - if (propp) - *propp = (JSProperty *) sprop; - else - JS_UNLOCK_OBJ(cx, obj); - return JS_TRUE; - -bad: - JS_UNLOCK_OBJ(cx, obj); - return JS_FALSE; -} - -/* - * Given pc pointing after a property accessing bytecode, return true if the - * access is a "object-detecting" in the sense used by web pages, e.g., when - * checking whether document.all is defined. - */ -static JSBool -Detecting(JSContext *cx, jsbytecode *pc) -{ - JSScript *script; - jsbytecode *endpc; - JSOp op; - JSAtom *atom; - - if (!cx->fp) - return JS_FALSE; - script = cx->fp->script; - for (endpc = script->code + script->length; pc < endpc; pc++) { - /* General case: a branch or equality op follows the access. */ - op = (JSOp) *pc; - if (js_CodeSpec[op].format & JOF_DETECTING) - return JS_TRUE; - - /* - * Special case #1: handle (document.all == null). Don't sweat about - * JS1.2's revision of the equality operators here. - */ - if (op == JSOP_NULL) { - if (++pc < endpc) - return *pc == JSOP_EQ || *pc == JSOP_NE; - break; - } - - /* - * Special case #2: handle (document.all == undefined). Don't worry - * about someone redefining undefined, which was added by Edition 3, - * so was read/write for backward compatibility. - */ - if (op == JSOP_NAME) { - atom = GET_ATOM(cx, script, pc); - if (atom == cx->runtime->atomState.typeAtoms[JSTYPE_VOID] && - (pc += js_CodeSpec[op].length) < endpc) { - op = (JSOp) *pc; - return op == JSOP_EQ || op == JSOP_NE || - op == JSOP_NEW_EQ || op == JSOP_NEW_NE; - } - break; - } - - /* At this point, anything but grouping means we're not detecting. */ - if (op != JSOP_GROUP) - break; - } - return JS_FALSE; -} - -JS_FRIEND_API(JSBool) -js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, - JSProperty **propp) -{ - return js_LookupPropertyWithFlags(cx, obj, id, 0, objp, propp); -} - -JSBool -js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags, - JSObject **objp, JSProperty **propp) -{ - JSObject *start, *obj2, *proto; - JSScope *scope; - JSScopeProperty *sprop; - JSClass *clasp; - JSResolveOp resolve; - JSResolvingKey key; - JSResolvingEntry *entry; - uint32 generation; - JSNewResolveOp newresolve; - jsbytecode *pc; - const JSCodeSpec *cs; - uint32 format; - JSBool ok; - - /* - * Handle old bug that took empty string as zero index. Also convert - * string indices to integers if appropriate. - */ - CHECK_FOR_STRING_INDEX(id); - - /* Search scopes starting with obj and following the prototype link. */ - start = obj; - for (;;) { - JS_LOCK_OBJ(cx, obj); - scope = OBJ_SCOPE(obj); - if (scope->object == obj) { - sprop = SCOPE_GET_PROPERTY(scope, id); - } else { - /* Shared prototype scope: try resolve before lookup. */ - sprop = NULL; - } - - /* Try obj's class resolve hook if id was not found in obj's scope. */ - if (!sprop) { - clasp = LOCKED_OBJ_GET_CLASS(obj); - resolve = clasp->resolve; - if (resolve != JS_ResolveStub) { - /* Avoid recursion on (obj, id) already being resolved on cx. */ - key.obj = obj; - key.id = id; - - /* - * Once we have successfully added an entry for (obj, key) to - * cx->resolvingTable, control must go through cleanup: before - * returning. But note that JS_DHASH_ADD may find an existing - * entry, in which case we bail to suppress runaway recursion. - */ - if (!js_StartResolving(cx, &key, JSRESFLAG_LOOKUP, &entry)) { - JS_UNLOCK_OBJ(cx, obj); - return JS_FALSE; - } - if (!entry) { - /* Already resolving id in obj -- dampen recursion. */ - JS_UNLOCK_OBJ(cx, obj); - goto out; - } - generation = cx->resolvingTable->generation; - - /* Null *propp here so we can test it at cleanup: safely. */ - *propp = NULL; - - if (clasp->flags & JSCLASS_NEW_RESOLVE) { - newresolve = (JSNewResolveOp)resolve; - if (!(flags & JSRESOLVE_CLASSNAME) && - cx->fp && - (pc = cx->fp->pc)) { - cs = &js_CodeSpec[*pc]; - format = cs->format; - if ((format & JOF_MODEMASK) != JOF_NAME) - flags |= JSRESOLVE_QUALIFIED; - if ((format & JOF_ASSIGNING) || - (cx->fp->flags & JSFRAME_ASSIGNING)) { - flags |= JSRESOLVE_ASSIGNING; - } else { - pc += cs->length; - if (Detecting(cx, pc)) - flags |= JSRESOLVE_DETECTING; - } - if (format & JOF_DECLARING) - flags |= JSRESOLVE_DECLARING; - } - obj2 = (clasp->flags & JSCLASS_NEW_RESOLVE_GETS_START) - ? start - : NULL; - JS_UNLOCK_OBJ(cx, obj); - - /* Protect id and all atoms from a GC nested in resolve. */ - JS_KEEP_ATOMS(cx->runtime); - ok = newresolve(cx, obj, ID_TO_VALUE(id), flags, &obj2); - JS_UNKEEP_ATOMS(cx->runtime); - if (!ok) - goto cleanup; - - JS_LOCK_OBJ(cx, obj); - if (obj2) { - /* Resolved: juggle locks and lookup id again. */ - if (obj2 != obj) { - JS_UNLOCK_OBJ(cx, obj); - JS_LOCK_OBJ(cx, obj2); - } - scope = OBJ_SCOPE(obj2); - if (!MAP_IS_NATIVE(&scope->map)) { - /* Whoops, newresolve handed back a foreign obj2. */ - JS_ASSERT(obj2 != obj); - JS_UNLOCK_OBJ(cx, obj2); - ok = OBJ_LOOKUP_PROPERTY(cx, obj2, id, objp, propp); - if (!ok || *propp) - goto cleanup; - JS_LOCK_OBJ(cx, obj2); - } else { - /* - * Require that obj2 have its own scope now, as we - * do for old-style resolve. If it doesn't, then - * id was not truly resolved, and we'll find it in - * the proto chain, or miss it if obj2's proto is - * not on obj's proto chain. That last case is a - * "too bad!" case. - */ - if (scope->object == obj2) - sprop = SCOPE_GET_PROPERTY(scope, id); - } - if (sprop) { - JS_ASSERT(obj2 == scope->object); - obj = obj2; - } else if (obj2 != obj) { - JS_UNLOCK_OBJ(cx, obj2); - JS_LOCK_OBJ(cx, obj); - } - } - } else { - /* - * Old resolve always requires id re-lookup if obj owns - * its scope after resolve returns. - */ - JS_UNLOCK_OBJ(cx, obj); - ok = resolve(cx, obj, ID_TO_VALUE(id)); - if (!ok) - goto cleanup; - JS_LOCK_OBJ(cx, obj); - scope = OBJ_SCOPE(obj); - JS_ASSERT(MAP_IS_NATIVE(&scope->map)); - if (scope->object == obj) - sprop = SCOPE_GET_PROPERTY(scope, id); - } - - cleanup: - js_StopResolving(cx, &key, JSRESFLAG_LOOKUP, entry, generation); - if (!ok || *propp) - return ok; - } - } - - if (sprop) { - JS_ASSERT(OBJ_SCOPE(obj) == scope); - *objp = scope->object; /* XXXbe hide in jsscope.[ch] */ - - *propp = (JSProperty *) sprop; - return JS_TRUE; - } - - proto = LOCKED_OBJ_GET_PROTO(obj); - JS_UNLOCK_OBJ(cx, obj); - if (!proto) - break; - if (!OBJ_IS_NATIVE(proto)) - return OBJ_LOOKUP_PROPERTY(cx, proto, id, objp, propp); - obj = proto; - } - -out: - *objp = NULL; - *propp = NULL; - return JS_TRUE; -} - -JS_FRIEND_API(JSBool) -js_FindProperty(JSContext *cx, jsid id, JSObject **objp, JSObject **pobjp, - JSProperty **propp) -{ - JSRuntime *rt; - JSObject *obj, *pobj, *lastobj; - JSScopeProperty *sprop; - JSProperty *prop; - - rt = cx->runtime; - obj = cx->fp->scopeChain; - do { - /* Try the property cache and return immediately on cache hit. */ - if (OBJ_IS_NATIVE(obj)) { - JS_LOCK_OBJ(cx, obj); - PROPERTY_CACHE_TEST(&rt->propertyCache, obj, id, sprop); - if (sprop) { - JS_ASSERT(OBJ_IS_NATIVE(obj)); - *objp = obj; - *pobjp = obj; - *propp = (JSProperty *) sprop; - return JS_TRUE; - } - JS_UNLOCK_OBJ(cx, obj); - } - - /* If cache miss, take the slow path. */ - if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &pobj, &prop)) - return JS_FALSE; - if (prop) { - if (OBJ_IS_NATIVE(pobj)) { - sprop = (JSScopeProperty *) prop; - PROPERTY_CACHE_FILL(&rt->propertyCache, pobj, id, sprop); - } - *objp = obj; - *pobjp = pobj; - *propp = prop; - return JS_TRUE; - } - lastobj = obj; - } while ((obj = OBJ_GET_PARENT(cx, obj)) != NULL); - - *objp = lastobj; - *pobjp = NULL; - *propp = NULL; - return JS_TRUE; -} - -JSObject * -js_FindIdentifierBase(JSContext *cx, jsid id) -{ - JSObject *obj, *pobj; - JSProperty *prop; - - /* - * Look for id's property along the "with" statement chain and the - * statically-linked scope chain. - */ - if (!js_FindProperty(cx, id, &obj, &pobj, &prop)) - return NULL; - if (prop) { - OBJ_DROP_PROPERTY(cx, pobj, prop); - return obj; - } - - /* - * Use the top-level scope from the scope chain, which won't end in the - * same scope as cx->globalObject for cross-context function calls. - */ - JS_ASSERT(obj); - - /* - * Property not found. Give a strict warning if binding an undeclared - * top-level variable. - */ - if (JS_HAS_STRICT_OPTION(cx)) { - JSString *str = JSVAL_TO_STRING(ID_TO_VALUE(id)); - if (!JS_ReportErrorFlagsAndNumber(cx, - JSREPORT_WARNING | JSREPORT_STRICT, - js_GetErrorMessage, NULL, - JSMSG_UNDECLARED_VAR, - JS_GetStringBytes(str))) { - return NULL; - } - } - return obj; -} - -JSBool -js_GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp) -{ - JSObject *obj2; - JSProperty *prop; - JSScope *scope; - JSScopeProperty *sprop; - uint32 slot; - - /* - * Handle old bug that took empty string as zero index. Also convert - * string indices to integers if appropriate. - */ - CHECK_FOR_STRING_INDEX(id); - - if (!js_LookupProperty(cx, obj, id, &obj2, &prop)) - return JS_FALSE; - if (!prop) { - jsval default_val; - -#if JS_BUG_NULL_INDEX_PROPS - /* Indexed properties defaulted to null in old versions. */ - default_val = (JSID_IS_INT(id) && JSID_TO_INT(id) >= 0) - ? JSVAL_NULL - : JSVAL_VOID; -#else - default_val = JSVAL_VOID; -#endif - *vp = default_val; - - if (!OBJ_GET_CLASS(cx, obj)->getProperty(cx, obj, ID_TO_VALUE(id), vp)) - return JS_FALSE; - - /* - * Give a strict warning if foo.bar is evaluated by a script for an - * object foo with no property named 'bar'. - */ - if (JS_HAS_STRICT_OPTION(cx) && - *vp == default_val && - cx->fp && cx->fp->pc && - (*cx->fp->pc == JSOP_GETPROP || *cx->fp->pc == JSOP_GETELEM)) - { - jsbytecode *pc; - JSString *str; - - /* Kludge to allow (typeof foo == "undefined") tests. */ - JS_ASSERT(cx->fp->script); - pc = cx->fp->pc; - pc += js_CodeSpec[*pc].length; - if (Detecting(cx, pc)) - return JS_TRUE; - - /* Ok, bad undefined property reference: whine about it. */ - str = js_DecompileValueGenerator(cx, JSDVG_IGNORE_STACK, - ID_TO_VALUE(id), NULL); - if (!str || - !JS_ReportErrorFlagsAndNumber(cx, - JSREPORT_WARNING|JSREPORT_STRICT, - js_GetErrorMessage, NULL, - JSMSG_UNDEFINED_PROP, - JS_GetStringBytes(str))) { - return JS_FALSE; - } - } - return JS_TRUE; - } - - if (!OBJ_IS_NATIVE(obj2)) { - OBJ_DROP_PROPERTY(cx, obj2, prop); - return OBJ_GET_PROPERTY(cx, obj2, id, vp); - } - - /* Unlock obj2 before calling getter, relock after to avoid deadlock. */ - scope = OBJ_SCOPE(obj2); - sprop = (JSScopeProperty *) prop; - slot = sprop->slot; - if (slot != SPROP_INVALID_SLOT) { - JS_ASSERT(slot < obj2->map->freeslot); - *vp = LOCKED_OBJ_GET_SLOT(obj2, slot); - - /* If sprop has a stub getter, we're done. */ - if (!sprop->getter) - goto out; - } else { - *vp = JSVAL_VOID; - } - - JS_UNLOCK_SCOPE(cx, scope); - if (!SPROP_GET(cx, sprop, obj, obj2, vp)) - return JS_FALSE; - JS_LOCK_SCOPE(cx, scope); - - if (SPROP_HAS_VALID_SLOT(sprop, scope)) { - LOCKED_OBJ_SET_SLOT(obj2, slot, *vp); - PROPERTY_CACHE_FILL(&cx->runtime->propertyCache, obj2, id, sprop); - } - -out: - JS_UNLOCK_SCOPE(cx, scope); - return JS_TRUE; -} - -JSBool -js_SetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp) -{ - JSObject *pobj; - JSProperty *prop; - JSScopeProperty *sprop; - JSScope *scope; - uintN attrs, flags; - intN shortid; - JSClass *clasp; - JSPropertyOp getter, setter; - jsval pval; - uint32 slot; - - /* - * Handle old bug that took empty string as zero index. Also convert - * string indices to integers if appropriate. - */ - CHECK_FOR_STRING_INDEX(id); - - if (!js_LookupProperty(cx, obj, id, &pobj, &prop)) - return JS_FALSE; - - if (prop && !OBJ_IS_NATIVE(pobj)) { - OBJ_DROP_PROPERTY(cx, pobj, prop); - prop = NULL; - } - sprop = (JSScopeProperty *) prop; - - /* - * Now either sprop is null, meaning id was not found in obj or one of its - * prototypes; or sprop is non-null, meaning id was found in pobj's scope. - * If JS_THREADSAFE and sprop is non-null, then scope is locked, and sprop - * is held: we must OBJ_DROP_PROPERTY or JS_UNLOCK_SCOPE before we return - * (the two are equivalent for native objects, but we use JS_UNLOCK_SCOPE - * because it is cheaper). - */ - attrs = JSPROP_ENUMERATE; - flags = 0; - shortid = 0; - clasp = OBJ_GET_CLASS(cx, obj); - getter = clasp->getProperty; - setter = clasp->setProperty; - - if (sprop) { - /* - * Set scope for use below. It was locked by js_LookupProperty, and - * we know pobj owns it (i.e., scope->object == pobj). Therefore we - * optimize JS_UNLOCK_OBJ(cx, pobj) into JS_UNLOCK_SCOPE(cx, scope). - */ - scope = OBJ_SCOPE(pobj); - - attrs = sprop->attrs; - if ((attrs & JSPROP_READONLY) || - (SCOPE_IS_SEALED(scope) && pobj == obj)) { - JS_UNLOCK_SCOPE(cx, scope); - if ((attrs & JSPROP_READONLY) && JS_VERSION_IS_ECMA(cx)) - return JS_TRUE; - goto read_only_error; - } - - if (pobj != obj) { - /* - * We found id in a prototype object: prepare to share or shadow. - * NB: Thanks to the immutable, garbage-collected property tree - * maintained by jsscope.c in cx->runtime, we needn't worry about - * sprop going away behind our back after we've unlocked scope. - */ - JS_UNLOCK_SCOPE(cx, scope); - - /* Don't clone a shared prototype property. */ - if (attrs & JSPROP_SHARED) - return SPROP_SET(cx, sprop, obj, pobj, vp); - - /* Restore attrs to the ECMA default for new properties. */ - attrs = JSPROP_ENUMERATE; - - /* - * Preserve the shortid, getter, and setter when shadowing any - * property that has a shortid. An old API convention requires - * that the property's getter and setter functions receive the - * shortid, not id, when they are called on the shadow we are - * about to create in obj's scope. - */ - if (sprop->flags & SPROP_HAS_SHORTID) { - flags = SPROP_HAS_SHORTID; - shortid = sprop->shortid; - getter = sprop->getter; - setter = sprop->setter; - } - - /* - * Forget we found the proto-property now that we've copied any - * needed member values. - */ - sprop = NULL; - } -#ifdef __GNUC__ /* suppress bogus gcc warnings */ - } else { - scope = NULL; -#endif - } - - if (!sprop) { - if (SCOPE_IS_SEALED(OBJ_SCOPE(obj)) && OBJ_SCOPE(obj)->object == obj) - goto read_only_error; - - /* Find or make a property descriptor with the right heritage. */ - JS_LOCK_OBJ(cx, obj); - scope = js_GetMutableScope(cx, obj); - if (!scope) { - JS_UNLOCK_OBJ(cx, obj); - return JS_FALSE; - } - if (clasp->flags & JSCLASS_SHARE_ALL_PROPERTIES) - attrs |= JSPROP_SHARED; - sprop = js_AddScopeProperty(cx, scope, id, getter, setter, - SPROP_INVALID_SLOT, attrs, flags, shortid); - if (!sprop) { - JS_UNLOCK_SCOPE(cx, scope); - return JS_FALSE; - } - - /* - * Initialize the new property value (passed to setter) to undefined. - * Note that we store before calling addProperty, to match the order - * in js_DefineNativeProperty. - */ - if (SPROP_HAS_VALID_SLOT(sprop, scope)) - LOCKED_OBJ_SET_SLOT(obj, sprop->slot, JSVAL_VOID); - - /* XXXbe called with obj locked */ - ADD_PROPERTY_HELPER(cx, clasp, obj, scope, sprop, vp, - js_RemoveScopeProperty(cx, scope, id); - JS_UNLOCK_SCOPE(cx, scope); - return JS_FALSE); - - PROPERTY_CACHE_FILL(&cx->runtime->propertyCache, obj, id, sprop); - } - - /* Get the current property value from its slot. */ - slot = sprop->slot; - if (slot != SPROP_INVALID_SLOT) { - JS_ASSERT(slot < obj->map->freeslot); - pval = LOCKED_OBJ_GET_SLOT(obj, slot); - - /* If sprop has a stub setter, keep scope locked and just store *vp. */ - if (!sprop->setter) - goto set_slot; - } - - /* Avoid deadlock by unlocking obj's scope while calling sprop's setter. */ - JS_UNLOCK_SCOPE(cx, scope); - - /* Let the setter modify vp before copying from it to obj->slots[slot]. */ - if (!SPROP_SET(cx, sprop, obj, obj, vp)) - return JS_FALSE; - - /* Relock obj's scope until we are done with sprop. */ - JS_LOCK_SCOPE(cx, scope); - - /* - * Check whether sprop is still around (was not deleted), and whether it - * has a slot (it may never have had one, or we may have lost a race with - * someone who cleared scope). - */ - if (SPROP_HAS_VALID_SLOT(sprop, scope)) { - set_slot: - GC_POKE(cx, pval); - LOCKED_OBJ_SET_SLOT(obj, slot, *vp); - } - JS_UNLOCK_SCOPE(cx, scope); - return JS_TRUE; - - read_only_error: { - JSString *str = js_DecompileValueGenerator(cx, - JSDVG_IGNORE_STACK, - ID_TO_VALUE(id), - NULL); - if (str) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_READ_ONLY, - JS_GetStringBytes(str)); - } - return JS_FALSE; - } -} - -JSBool -js_GetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop, - uintN *attrsp) -{ - JSBool noprop, ok; - JSScopeProperty *sprop; - - noprop = !prop; - if (noprop) { - if (!js_LookupProperty(cx, obj, id, &obj, &prop)) - return JS_FALSE; - if (!prop) { - *attrsp = 0; - return JS_TRUE; - } - if (!OBJ_IS_NATIVE(obj)) { - ok = OBJ_GET_ATTRIBUTES(cx, obj, id, prop, attrsp); - OBJ_DROP_PROPERTY(cx, obj, prop); - return ok; - } - } - sprop = (JSScopeProperty *)prop; - *attrsp = sprop->attrs; - if (noprop) - OBJ_DROP_PROPERTY(cx, obj, prop); - return JS_TRUE; -} - -JSBool -js_SetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop, - uintN *attrsp) -{ - JSBool noprop, ok; - JSScopeProperty *sprop; - - noprop = !prop; - if (noprop) { - if (!js_LookupProperty(cx, obj, id, &obj, &prop)) - return JS_FALSE; - if (!prop) - return JS_TRUE; - if (!OBJ_IS_NATIVE(obj)) { - ok = OBJ_SET_ATTRIBUTES(cx, obj, id, prop, attrsp); - OBJ_DROP_PROPERTY(cx, obj, prop); - return ok; - } - } - sprop = (JSScopeProperty *)prop; - sprop = js_ChangeNativePropertyAttrs(cx, obj, sprop, *attrsp, 0, - sprop->getter, sprop->setter); - if (noprop) - OBJ_DROP_PROPERTY(cx, obj, prop); - return (sprop != NULL); -} - -JSBool -js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval) -{ -#if JS_HAS_PROP_DELETE - - JSObject *proto; - JSProperty *prop; - JSScopeProperty *sprop; - JSString *str; - JSScope *scope; - JSBool ok; - - *rval = JS_VERSION_IS_ECMA(cx) ? JSVAL_TRUE : JSVAL_VOID; - - /* - * Handle old bug that took empty string as zero index. Also convert - * string indices to integers if appropriate. - */ - CHECK_FOR_STRING_INDEX(id); - - if (!js_LookupProperty(cx, obj, id, &proto, &prop)) - return JS_FALSE; - if (!prop || proto != obj) { - /* - * If the property was found in a native prototype, check whether it's - * shared and permanent. Such a property stands for direct properties - * in all delegating objects, matching ECMA semantics without bloating - * each delegating object. - */ - if (prop) { - if (OBJ_IS_NATIVE(proto)) { - sprop = (JSScopeProperty *)prop; - if (SPROP_IS_SHARED_PERMANENT(sprop)) - *rval = JSVAL_FALSE; - } - OBJ_DROP_PROPERTY(cx, proto, prop); - if (*rval == JSVAL_FALSE) - return JS_TRUE; - } - - /* - * If no property, or the property comes unshared or impermanent from - * a prototype, call the class's delProperty hook, passing rval as the - * result parameter. - */ - return OBJ_GET_CLASS(cx, obj)->delProperty(cx, obj, ID_TO_VALUE(id), - rval); - } - - sprop = (JSScopeProperty *)prop; - if (sprop->attrs & JSPROP_PERMANENT) { - OBJ_DROP_PROPERTY(cx, obj, prop); - if (JS_VERSION_IS_ECMA(cx)) { - *rval = JSVAL_FALSE; - return JS_TRUE; - } - str = js_DecompileValueGenerator(cx, JSDVG_IGNORE_STACK, - ID_TO_VALUE(id), NULL); - if (str) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_PERMANENT, JS_GetStringBytes(str)); - } - return JS_FALSE; - } - - /* XXXbe called with obj locked */ - if (!LOCKED_OBJ_GET_CLASS(obj)->delProperty(cx, obj, SPROP_USERID(sprop), - rval)) { - OBJ_DROP_PROPERTY(cx, obj, prop); - return JS_FALSE; - } - - scope = OBJ_SCOPE(obj); - if (SPROP_HAS_VALID_SLOT(sprop, scope)) - GC_POKE(cx, LOCKED_OBJ_GET_SLOT(obj, sprop->slot)); - - PROPERTY_CACHE_FILL(&cx->runtime->propertyCache, obj, id, NULL); - ok = js_RemoveScopeProperty(cx, scope, id); - OBJ_DROP_PROPERTY(cx, obj, prop); - return ok; - -#else /* !JS_HAS_PROP_DELETE */ - - jsval null = JSVAL_NULL; - - *rval = JSVAL_VOID; - return js_SetProperty(cx, obj, id, &null); - -#endif /* !JS_HAS_PROP_DELETE */ -} - -JSBool -js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp) -{ - jsval v; - JSString *str; - - v = OBJECT_TO_JSVAL(obj); - switch (hint) { - case JSTYPE_STRING: - /* - * Propagate the exception if js_TryMethod finds an appropriate - * method, and calling that method returned failure. - */ - if (!js_TryMethod(cx, obj, cx->runtime->atomState.toStringAtom, 0, NULL, - &v)) { - return JS_FALSE; - } - - if (!JSVAL_IS_PRIMITIVE(v)) { - if (!OBJ_GET_CLASS(cx, obj)->convert(cx, obj, hint, &v)) - return JS_FALSE; - - /* - * JS1.2 never failed (except for malloc failure) to convert an - * object to a string. ECMA requires an error if both toString - * and valueOf fail to produce a primitive value. - */ - if (!JSVAL_IS_PRIMITIVE(v) && JS_VERSION_IS_1_2(cx)) { - char *bytes = JS_smprintf("[object %s]", - OBJ_GET_CLASS(cx, obj)->name); - if (!bytes) - return JS_FALSE; - str = JS_NewString(cx, bytes, strlen(bytes)); - if (!str) { - free(bytes); - return JS_FALSE; - } - v = STRING_TO_JSVAL(str); - goto out; - } - } - break; - - default: - if (!OBJ_GET_CLASS(cx, obj)->convert(cx, obj, hint, &v)) - return JS_FALSE; - if (!JSVAL_IS_PRIMITIVE(v)) { - JSType type = JS_TypeOfValue(cx, v); - if (type == hint || - (type == JSTYPE_FUNCTION && hint == JSTYPE_OBJECT)) { - goto out; - } - /* Don't convert to string (source object literal) for JS1.2. */ - if (JS_VERSION_IS_1_2(cx) && hint == JSTYPE_BOOLEAN) - goto out; - if (!js_TryMethod(cx, obj, cx->runtime->atomState.toStringAtom, 0, - NULL, &v)) - return JS_FALSE; - } - break; - } - if (!JSVAL_IS_PRIMITIVE(v)) { - /* Avoid recursive death through js_DecompileValueGenerator. */ - if (hint == JSTYPE_STRING) { - str = JS_InternString(cx, OBJ_GET_CLASS(cx, obj)->name); - if (!str) - return JS_FALSE; - } else { - str = NULL; - } - *vp = OBJECT_TO_JSVAL(obj); - str = js_DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, v, str); - if (str) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_CANT_CONVERT_TO, - JS_GetStringBytes(str), - (hint == JSTYPE_VOID) - ? "primitive type" - : js_type_str[hint]); - } - return JS_FALSE; - } -out: - *vp = v; - return JS_TRUE; -} - -JSIdArray * -js_NewIdArray(JSContext *cx, jsint length) -{ - JSIdArray *ida; - - ida = (JSIdArray *) - JS_malloc(cx, sizeof(JSIdArray) + (length-1) * sizeof(jsval)); - if (ida) - ida->length = length; - return ida; -} - -JSIdArray * -js_SetIdArrayLength(JSContext *cx, JSIdArray *ida, jsint length) -{ - JSIdArray *rida; - - rida = (JSIdArray *) - JS_realloc(cx, ida, sizeof(JSIdArray) + (length-1) * sizeof(jsval)); - if (!rida) - JS_DestroyIdArray(cx, ida); - else - rida->length = length; - return rida; -} - -/* Private type used to iterate over all properties of a native JS object */ -struct JSNativeIteratorState { - jsint next_index; /* index into jsid array */ - JSIdArray *ida; /* all property ids in enumeration */ - JSNativeIteratorState *next; /* double-linked list support */ - JSNativeIteratorState **prevp; -}; - -/* - * This function is used to enumerate the properties of native JSObjects - * and those host objects that do not define a JSNewEnumerateOp-style iterator - * function. - */ -JSBool -js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, - jsval *statep, jsid *idp) -{ - JSRuntime *rt; - JSObject *proto; - JSClass *clasp; - JSEnumerateOp enumerate; - JSScopeProperty *sprop, *lastProp; - jsint i, length; - JSScope *scope; - JSIdArray *ida; - JSNativeIteratorState *state; - - rt = cx->runtime; - clasp = OBJ_GET_CLASS(cx, obj); - enumerate = clasp->enumerate; - if (clasp->flags & JSCLASS_NEW_ENUMERATE) - return ((JSNewEnumerateOp) enumerate)(cx, obj, enum_op, statep, idp); - - switch (enum_op) { - case JSENUMERATE_INIT: - if (!enumerate(cx, obj)) - return JS_FALSE; - length = 0; - - /* - * The set of all property ids is pre-computed when the iterator - * is initialized so as to avoid problems with properties being - * deleted during the iteration. - */ - JS_LOCK_OBJ(cx, obj); - scope = OBJ_SCOPE(obj); - - /* - * If this object shares a scope with its prototype, don't enumerate - * its properties. Otherwise they will be enumerated a second time - * when the prototype object is enumerated. - */ - proto = OBJ_GET_PROTO(cx, obj); - if (proto && scope == OBJ_SCOPE(proto)) { - ida = js_NewIdArray(cx, 0); - if (!ida) { - JS_UNLOCK_OBJ(cx, obj); - return JS_FALSE; - } - } else { - /* Object has a private scope; Enumerate all props in scope. */ - for (sprop = lastProp = SCOPE_LAST_PROP(scope); sprop; - sprop = sprop->parent) { - if (( -#ifdef DUMP_CALL_TABLE - (cx->options & JSOPTION_LOGCALL_TOSOURCE) || -#endif - (sprop->attrs & JSPROP_ENUMERATE)) && - !(sprop->flags & SPROP_IS_ALIAS) && - (!SCOPE_HAD_MIDDLE_DELETE(scope) || - SCOPE_HAS_PROPERTY(scope, sprop))) { - length++; - } - } - ida = js_NewIdArray(cx, length); - if (!ida) { - JS_UNLOCK_OBJ(cx, obj); - return JS_FALSE; - } - i = length; - for (sprop = lastProp; sprop; sprop = sprop->parent) { - if (( -#ifdef DUMP_CALL_TABLE - (cx->options & JSOPTION_LOGCALL_TOSOURCE) || -#endif - (sprop->attrs & JSPROP_ENUMERATE)) && - !(sprop->flags & SPROP_IS_ALIAS) && - (!SCOPE_HAD_MIDDLE_DELETE(scope) || - SCOPE_HAS_PROPERTY(scope, sprop))) { - JS_ASSERT(i > 0); - ida->vector[--i] = sprop->id; - } - } - } - JS_UNLOCK_OBJ(cx, obj); - - state = (JSNativeIteratorState *) - JS_malloc(cx, sizeof(JSNativeIteratorState)); - if (!state) { - JS_DestroyIdArray(cx, ida); - return JS_FALSE; - } - state->ida = ida; - state->next_index = 0; - - JS_LOCK_RUNTIME(rt); - state->next = rt->nativeIteratorStates; - if (state->next) - state->next->prevp = &state->next; - state->prevp = &rt->nativeIteratorStates; - *state->prevp = state; - JS_UNLOCK_RUNTIME(rt); - - *statep = PRIVATE_TO_JSVAL(state); - if (idp) - *idp = INT_TO_JSVAL(length); - break; - - case JSENUMERATE_NEXT: - state = (JSNativeIteratorState *) JSVAL_TO_PRIVATE(*statep); - ida = state->ida; - length = ida->length; - if (state->next_index != length) { - *idp = ida->vector[state->next_index++]; - break; - } - /* FALL THROUGH */ - - case JSENUMERATE_DESTROY: - state = (JSNativeIteratorState *) JSVAL_TO_PRIVATE(*statep); - - JS_LOCK_RUNTIME(rt); - JS_ASSERT(rt->nativeIteratorStates); - JS_ASSERT(*state->prevp == state); - if (state->next) { - JS_ASSERT(state->next->prevp == &state->next); - state->next->prevp = state->prevp; - } - *state->prevp = state->next; - JS_UNLOCK_RUNTIME(rt); - - JS_DestroyIdArray(cx, state->ida); - JS_free(cx, state); - *statep = JSVAL_NULL; - break; - } - return JS_TRUE; -} - -void -js_MarkNativeIteratorStates(JSContext *cx) -{ - JSNativeIteratorState *state; - jsid *cursor, *end, id; - - state = cx->runtime->nativeIteratorStates; - if (!state) - return; - - do { - JS_ASSERT(*state->prevp == state); - cursor = state->ida->vector; - end = cursor + state->ida->length; - for (; cursor != end; ++cursor) { - id = *cursor; - if (JSID_IS_ATOM(id)) { - GC_MARK_ATOM(cx, JSID_TO_ATOM(id), NULL); - } else if (JSID_IS_OBJECT(id)) { - GC_MARK(cx, JSID_TO_OBJECT(id), "ida->vector[i]", NULL); - } - } - } while ((state = state->next) != NULL); -} - - -JSBool -js_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode, - jsval *vp, uintN *attrsp) -{ - JSBool writing; - JSObject *pobj; - JSProperty *prop; - JSClass *clasp; - JSScopeProperty *sprop; - JSCheckAccessOp check; - - writing = (mode & JSACC_WRITE) != 0; - switch (mode & JSACC_TYPEMASK) { - case JSACC_PROTO: - pobj = obj; - if (!writing) - *vp = OBJ_GET_SLOT(cx, obj, JSSLOT_PROTO); - *attrsp = JSPROP_PERMANENT; - break; - - case JSACC_PARENT: - JS_ASSERT(!writing); - pobj = obj; - *vp = OBJ_GET_SLOT(cx, obj, JSSLOT_PARENT); - *attrsp = JSPROP_READONLY | JSPROP_PERMANENT; - break; - - default: - if (!js_LookupProperty(cx, obj, id, &pobj, &prop)) - return JS_FALSE; - if (!prop) { - if (!writing) - *vp = JSVAL_VOID; - *attrsp = 0; - clasp = OBJ_GET_CLASS(cx, obj); - return !clasp->checkAccess || - clasp->checkAccess(cx, obj, ID_TO_VALUE(id), mode, vp); - } - if (!OBJ_IS_NATIVE(pobj)) { - OBJ_DROP_PROPERTY(cx, pobj, prop); - return OBJ_CHECK_ACCESS(cx, pobj, id, mode, vp, attrsp); - } - - sprop = (JSScopeProperty *)prop; - *attrsp = sprop->attrs; - if (!writing) { - *vp = (SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(pobj))) - ? LOCKED_OBJ_GET_SLOT(pobj, sprop->slot) - : JSVAL_VOID; - } - OBJ_DROP_PROPERTY(cx, pobj, prop); - } - - /* - * If obj's class has a stub (null) checkAccess hook, use the per-runtime - * checkObjectAccess callback, if configured. - * - * We don't want to require all classes to supply a checkAccess hook; we - * need that hook only for certain classes used when precompiling scripts - * and functions ("brutal sharing"). But for general safety of built-in - * magic properties such as __proto__ and __parent__, we route all access - * checks, even for classes that stub out checkAccess, through the global - * checkObjectAccess hook. This covers precompilation-based sharing and - * (possibly unintended) runtime sharing across trust boundaries. - */ - clasp = OBJ_GET_CLASS(cx, pobj); - check = clasp->checkAccess; - if (!check) - check = cx->runtime->checkObjectAccess; - return !check || check(cx, pobj, ID_TO_VALUE(id), mode, vp); -} - -#ifdef JS_THREADSAFE -void -js_DropProperty(JSContext *cx, JSObject *obj, JSProperty *prop) -{ - JS_UNLOCK_OBJ(cx, obj); -} -#endif - -static void -ReportIsNotFunction(JSContext *cx, jsval *vp, uintN flags) -{ - /* - * The decompiler may need to access the args of the function in - * progress rather than the one we had hoped to call. - * So we switch the cx->fp to the frame below us. We stick the - * current frame in the dormantFrameChain to protect it from gc. - */ - - JSStackFrame *fp = cx->fp; - if (fp->down) { - JS_ASSERT(!fp->dormantNext); - fp->dormantNext = cx->dormantFrameChain; - cx->dormantFrameChain = fp; - cx->fp = fp->down; - } - - js_ReportIsNotFunction(cx, vp, flags); - - if (fp->down) { - JS_ASSERT(cx->dormantFrameChain == fp); - cx->dormantFrameChain = fp->dormantNext; - fp->dormantNext = NULL; - cx->fp = fp; - } -} - -#ifdef NARCISSUS -static JSBool -GetCurrentExecutionContext(JSContext *cx, JSObject *obj, jsval *rval) -{ - JSObject *tmp; - jsval xcval; - - while ((tmp = OBJ_GET_PARENT(cx, obj)) != NULL) - obj = tmp; - if (!OBJ_GET_PROPERTY(cx, obj, - ATOM_TO_JSID(cx->runtime->atomState - .ExecutionContextAtom), - &xcval)) { - return JS_FALSE; - } - if (JSVAL_IS_PRIMITIVE(xcval)) { - JS_ReportError(cx, "invalid ExecutionContext in global object"); - return JS_FALSE; - } - if (!OBJ_GET_PROPERTY(cx, JSVAL_TO_OBJECT(xcval), - ATOM_TO_JSID(cx->runtime->atomState.currentAtom), - rval)) { - return JS_FALSE; - } - return JS_TRUE; -} -#endif - -JSBool -js_Call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSClass *clasp; - - clasp = OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(argv[-2])); - if (!clasp->call) { -#ifdef NARCISSUS - JSObject *callee, *args; - jsval fval, nargv[3]; - JSBool ok; - - callee = JSVAL_TO_OBJECT(argv[-2]); - if (!OBJ_GET_PROPERTY(cx, callee, - ATOM_TO_JSID(cx->runtime->atomState.callAtom), - &fval)) { - return JS_FALSE; - } - if (JSVAL_IS_FUNCTION(cx, fval)) { - if (!GetCurrentExecutionContext(cx, obj, &nargv[2])) - return JS_FALSE; - args = js_GetArgsObject(cx, cx->fp); - if (!args) - return JS_FALSE; - nargv[0] = OBJECT_TO_JSVAL(obj); - nargv[1] = OBJECT_TO_JSVAL(args); - return js_InternalCall(cx, callee, fval, 3, nargv, rval); - } - if (JSVAL_IS_OBJECT(fval) && JSVAL_TO_OBJECT(fval) != callee) { - argv[-2] = fval; - ok = js_Call(cx, obj, argc, argv, rval); - argv[-2] = OBJECT_TO_JSVAL(callee); - return ok; - } -#endif - ReportIsNotFunction(cx, &argv[-2], 0); - return JS_FALSE; - } - return clasp->call(cx, obj, argc, argv, rval); -} - -JSBool -js_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSClass *clasp; - - clasp = OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(argv[-2])); - if (!clasp->construct) { -#ifdef NARCISSUS - JSObject *callee, *args; - jsval cval, nargv[2]; - JSBool ok; - - callee = JSVAL_TO_OBJECT(argv[-2]); - if (!OBJ_GET_PROPERTY(cx, callee, - ATOM_TO_JSID(cx->runtime->atomState - .constructAtom), - &cval)) { - return JS_FALSE; - } - if (JSVAL_IS_FUNCTION(cx, cval)) { - if (!GetCurrentExecutionContext(cx, obj, &nargv[1])) - return JS_FALSE; - args = js_GetArgsObject(cx, cx->fp); - if (!args) - return JS_FALSE; - nargv[0] = OBJECT_TO_JSVAL(args); - return js_InternalCall(cx, callee, cval, 2, nargv, rval); - } - if (JSVAL_IS_OBJECT(cval) && JSVAL_TO_OBJECT(cval) != callee) { - argv[-2] = cval; - ok = js_Call(cx, obj, argc, argv, rval); - argv[-2] = OBJECT_TO_JSVAL(callee); - return ok; - } -#endif - ReportIsNotFunction(cx, &argv[-2], JSV2F_CONSTRUCT); - return JS_FALSE; - } - return clasp->construct(cx, obj, argc, argv, rval); -} - -JSBool -js_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp) -{ - JSClass *clasp; - JSString *str; - - clasp = OBJ_GET_CLASS(cx, obj); - if (clasp->hasInstance) - return clasp->hasInstance(cx, obj, v, bp); -#ifdef NARCISSUS - { - jsval fval, rval; - - if (!OBJ_GET_PROPERTY(cx, obj, - ATOM_TO_JSID(cx->runtime->atomState - .hasInstanceAtom), - &fval)) { - return JS_FALSE; - } - if (JSVAL_IS_FUNCTION(cx, fval)) { - return js_InternalCall(cx, obj, fval, 1, &v, &rval) && - js_ValueToBoolean(cx, rval, bp); - } - } -#endif - str = js_DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, - OBJECT_TO_JSVAL(obj), NULL); - if (str) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_INSTANCEOF_RHS, - JS_GetStringBytes(str)); - } - return JS_FALSE; -} - -JSBool -js_IsDelegate(JSContext *cx, JSObject *obj, jsval v, JSBool *bp) -{ - JSObject *obj2; - - *bp = JS_FALSE; - if (JSVAL_IS_PRIMITIVE(v)) - return JS_TRUE; - obj2 = JSVAL_TO_OBJECT(v); - while ((obj2 = OBJ_GET_PROTO(cx, obj2)) != NULL) { - if (obj2 == obj) { - *bp = JS_TRUE; - break; - } - } - return JS_TRUE; -} - -JSBool -js_GetClassPrototype(JSContext *cx, const char *name, JSObject **protop) -{ - return GetClassPrototype(cx, NULL, name, protop); -} - -static JSBool -GetClassPrototype(JSContext *cx, JSObject *scope, const char *name, - JSObject **protop) -{ - jsval v; - JSObject *ctor; - - if (!js_FindConstructor(cx, scope, name, &v)) - return JS_FALSE; - if (JSVAL_IS_FUNCTION(cx, v)) { - ctor = JSVAL_TO_OBJECT(v); - if (!OBJ_GET_PROPERTY(cx, ctor, - ATOM_TO_JSID(cx->runtime->atomState - .classPrototypeAtom), - &v)) { - return JS_FALSE; - } - if (!JSVAL_IS_PRIMITIVE(v)) { - /* - * Set the newborn root in case v is otherwise unreferenced. - * It's ok to overwrite newborn roots here, since the getter - * called just above could have. Unlike the common GC rooting - * model, our callers do not have to protect protop thanks to - * this newborn root, since they all immediately create a new - * instance that delegates to this object, or just query the - * prototype for its class. - */ - cx->newborn[GCX_OBJECT] = JSVAL_TO_GCTHING(v); - } - } - *protop = JSVAL_IS_OBJECT(v) ? JSVAL_TO_OBJECT(v) : NULL; - return JS_TRUE; -} - -/* - * For shared precompilation of function objects, we support cloning on entry - * to an execution context in which the function declaration or expression - * should be processed as if it were not precompiled, where the precompiled - * function's scope chain does not match the execution context's. The cloned - * function object carries its execution-context scope in its parent slot; it - * links to the precompiled function (the "clone-parent") via its proto slot. - * - * Note that this prototype-based delegation leaves an unchecked access path - * from the clone to the clone-parent's 'constructor' property. If the clone - * lives in a less privileged or shared scope than the clone-parent, this is - * a security hole, a sharing hazard, or both. Therefore we check all such - * accesses with the following getter/setter pair, which we use when defining - * 'constructor' in f.prototype for all function objects f. - */ -static JSBool -CheckCtorGetAccess(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - JSAtom *atom; - uintN attrs; - - atom = cx->runtime->atomState.constructorAtom; - JS_ASSERT(id == ATOM_KEY(atom)); - return OBJ_CHECK_ACCESS(cx, obj, ATOM_TO_JSID(atom), JSACC_READ, - vp, &attrs); -} - -static JSBool -CheckCtorSetAccess(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - JSAtom *atom; - uintN attrs; - - atom = cx->runtime->atomState.constructorAtom; - JS_ASSERT(id == ATOM_KEY(atom)); - return OBJ_CHECK_ACCESS(cx, obj, ATOM_TO_JSID(atom), JSACC_WRITE, - vp, &attrs); -} - -JSBool -js_SetClassPrototype(JSContext *cx, JSObject *ctor, JSObject *proto, - uintN attrs) -{ - /* - * Use the given attributes for the prototype property of the constructor, - * as user-defined constructors have a DontDelete prototype (which may be - * reset), while native or "system" constructors have DontEnum | ReadOnly | - * DontDelete. - */ - if (!OBJ_DEFINE_PROPERTY(cx, ctor, - ATOM_TO_JSID(cx->runtime->atomState - .classPrototypeAtom), - OBJECT_TO_JSVAL(proto), - JS_PropertyStub, JS_PropertyStub, - attrs, NULL)) { - return JS_FALSE; - } - - /* - * ECMA says that Object.prototype.constructor, or f.prototype.constructor - * for a user-defined function f, is DontEnum. - */ - return OBJ_DEFINE_PROPERTY(cx, proto, - ATOM_TO_JSID(cx->runtime->atomState - .constructorAtom), - OBJECT_TO_JSVAL(ctor), - CheckCtorGetAccess, CheckCtorSetAccess, - 0, NULL); -} - -JSBool -js_ValueToObject(JSContext *cx, jsval v, JSObject **objp) -{ - JSObject *obj; - - if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) { - obj = NULL; - } else if (JSVAL_IS_OBJECT(v)) { - obj = JSVAL_TO_OBJECT(v); - if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_OBJECT, &v)) - return JS_FALSE; - if (JSVAL_IS_OBJECT(v)) - obj = JSVAL_TO_OBJECT(v); - } else { - if (JSVAL_IS_STRING(v)) { - obj = js_StringToObject(cx, JSVAL_TO_STRING(v)); - } else if (JSVAL_IS_INT(v)) { - obj = js_NumberToObject(cx, (jsdouble)JSVAL_TO_INT(v)); - } else if (JSVAL_IS_DOUBLE(v)) { - obj = js_NumberToObject(cx, *JSVAL_TO_DOUBLE(v)); - } else { - JS_ASSERT(JSVAL_IS_BOOLEAN(v)); - obj = js_BooleanToObject(cx, JSVAL_TO_BOOLEAN(v)); - } - if (!obj) - return JS_FALSE; - } - *objp = obj; - return JS_TRUE; -} - -JSObject * -js_ValueToNonNullObject(JSContext *cx, jsval v) -{ - JSObject *obj; - JSString *str; - - if (!js_ValueToObject(cx, v, &obj)) - return NULL; - if (!obj) { - str = js_DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, v, NULL); - if (str) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_NO_PROPERTIES, JS_GetStringBytes(str)); - } - } - return obj; -} - -JSBool -js_TryValueOf(JSContext *cx, JSObject *obj, JSType type, jsval *rval) -{ -#if JS_HAS_VALUEOF_HINT - jsval argv[1]; - - argv[0] = ATOM_KEY(cx->runtime->atomState.typeAtoms[type]); - return js_TryMethod(cx, obj, cx->runtime->atomState.valueOfAtom, 1, argv, - rval); -#else - return js_TryMethod(cx, obj, cx->runtime->atomState.valueOfAtom, 0, NULL, - rval); -#endif -} - -JSBool -js_TryMethod(JSContext *cx, JSObject *obj, JSAtom *atom, - uintN argc, jsval *argv, jsval *rval) -{ - JSErrorReporter older; - jsid id; - jsval fval; - JSBool ok; - int stackDummy; - - if (!JS_CHECK_STACK_SIZE(cx, stackDummy)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_OVER_RECURSED); - return JS_FALSE; - } - - /* - * Report failure only if an appropriate method was found, and calling it - * returned failure. We propagate failure in this case to make exceptions - * behave properly. - */ - older = JS_SetErrorReporter(cx, NULL); - id = ATOM_TO_JSID(atom); - fval = JSVAL_VOID; -#if JS_HAS_XML_SUPPORT - if (OBJECT_IS_XML(cx, obj)) { - JSXMLObjectOps *ops; - - ops = (JSXMLObjectOps *) obj->map->ops; - obj = ops->getMethod(cx, obj, id, &fval); - ok = (obj != NULL); - } else -#endif - { - ok = OBJ_GET_PROPERTY(cx, obj, id, &fval); - } - if (!ok) - JS_ClearPendingException(cx); - ok = JSVAL_IS_PRIMITIVE(fval) || - js_InternalCall(cx, obj, fval, argc, argv, rval); - JS_SetErrorReporter(cx, older); - return ok; -} - -#if JS_HAS_XDR - -#include "jsxdrapi.h" - -JSBool -js_XDRObject(JSXDRState *xdr, JSObject **objp) -{ - JSContext *cx; - JSClass *clasp; - const char *className; - uint32 classId, classDef; - JSBool ok; - JSObject *proto; - - cx = xdr->cx; - if (xdr->mode == JSXDR_ENCODE) { - clasp = OBJ_GET_CLASS(cx, *objp); - className = clasp->name; - classId = JS_XDRFindClassIdByName(xdr, className); - classDef = !classId; - if (classDef && !JS_XDRRegisterClass(xdr, clasp, &classId)) - return JS_FALSE; - } else { - classDef = 0; - className = NULL; - clasp = NULL; /* quell GCC overwarning */ - } - - /* XDR a flag word followed (if true) by the class name. */ - if (!JS_XDRUint32(xdr, &classDef)) - return JS_FALSE; - if (classDef && !JS_XDRCString(xdr, (char **) &className)) - return JS_FALSE; - - /* From here on, return through out: to free className if it was set. */ - ok = JS_XDRUint32(xdr, &classId); - if (!ok) - goto out; - - if (xdr->mode != JSXDR_ENCODE) { - if (classDef) { - ok = GetClassPrototype(cx, NULL, className, &proto); - if (!ok) - goto out; - clasp = OBJ_GET_CLASS(cx, proto); - ok = JS_XDRRegisterClass(xdr, clasp, &classId); - if (!ok) - goto out; - } else { - clasp = JS_XDRFindClassById(xdr, classId); - if (!clasp) { - char numBuf[12]; - JS_snprintf(numBuf, sizeof numBuf, "%ld", (long)classId); - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_CANT_FIND_CLASS, numBuf); - ok = JS_FALSE; - goto out; - } - } - } - - if (!clasp->xdrObject) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_CANT_XDR_CLASS, clasp->name); - ok = JS_FALSE; - } else { - ok = clasp->xdrObject(xdr, objp); - } -out: - if (xdr->mode != JSXDR_ENCODE && className) - JS_free(cx, (void *)className); - return ok; -} - -#endif /* JS_HAS_XDR */ - -#ifdef DEBUG_brendan - -#include -#include - -uint32 js_entry_count_max; -uint32 js_entry_count_sum; -double js_entry_count_sqsum; -uint32 js_entry_count_hist[11]; - -static void -MeterEntryCount(uintN count) -{ - if (count) { - js_entry_count_sum += count; - js_entry_count_sqsum += (double)count * count; - if (count > js_entry_count_max) - js_entry_count_max = count; - } - js_entry_count_hist[JS_MIN(count, 10)]++; -} - -void -js_DumpScopeMeters(JSRuntime *rt) -{ - static FILE *logfp; - if (!logfp) - logfp = fopen("/tmp/scope.stats", "a"); - - { - double mean = 0., var = 0., sigma = 0.; - double nscopes = rt->liveScopes; - double nentrys = js_entry_count_sum; - if (nscopes > 0 && nentrys >= 0) { - mean = nentrys / nscopes; - var = nscopes * js_entry_count_sqsum - nentrys * nentrys; - if (var < 0.0 || nscopes <= 1) - var = 0.0; - else - var /= nscopes * (nscopes - 1); - - /* Windows says sqrt(0.0) is "-1.#J" (?!) so we must test. */ - sigma = (var != 0.) ? sqrt(var) : 0.; - } - - fprintf(logfp, - "scopes %g entries %g mean %g sigma %g max %u", - nscopes, nentrys, mean, sigma, js_entry_count_max); - } - - fprintf(logfp, " histogram %u %u %u %u %u %u %u %u %u %u %u\n", - js_entry_count_hist[0], js_entry_count_hist[1], - js_entry_count_hist[2], js_entry_count_hist[3], - js_entry_count_hist[4], js_entry_count_hist[5], - js_entry_count_hist[6], js_entry_count_hist[7], - js_entry_count_hist[8], js_entry_count_hist[9], - js_entry_count_hist[10]); - js_entry_count_sum = js_entry_count_max = 0; - js_entry_count_sqsum = 0; - memset(js_entry_count_hist, 0, sizeof js_entry_count_hist); - fflush(logfp); -} - -#endif /* DEBUG_brendan */ - -uint32 -js_Mark(JSContext *cx, JSObject *obj, void *arg) -{ - JSScope *scope; - JSScopeProperty *sprop; - JSClass *clasp; - - JS_ASSERT(OBJ_IS_NATIVE(obj)); - scope = OBJ_SCOPE(obj); -#ifdef DEBUG_brendan - if (scope->object == obj) - MeterEntryCount(scope->entryCount); -#endif - - JS_ASSERT(!SCOPE_LAST_PROP(scope) || - SCOPE_HAS_PROPERTY(scope, SCOPE_LAST_PROP(scope))); - - for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) { - if (SCOPE_HAD_MIDDLE_DELETE(scope) && !SCOPE_HAS_PROPERTY(scope, sprop)) - continue; - MARK_SCOPE_PROPERTY(sprop); - if (JSID_IS_ATOM(sprop->id)) - GC_MARK_ATOM(cx, JSID_TO_ATOM(sprop->id), arg); - else if (JSID_IS_OBJECT(sprop->id)) - GC_MARK(cx, JSID_TO_OBJECT(sprop->id), "id", arg); - -#if JS_HAS_GETTER_SETTER - if (sprop->attrs & (JSPROP_GETTER | JSPROP_SETTER)) { -#ifdef GC_MARK_DEBUG - char buf[64]; - JSAtom *atom = JSID_TO_ATOM(sprop->id); - const char *id = (atom && ATOM_IS_STRING(atom)) - ? JS_GetStringBytes(ATOM_TO_STRING(atom)) - : "unknown"; -#endif - - if (sprop->attrs & JSPROP_GETTER) { -#ifdef GC_MARK_DEBUG - JS_snprintf(buf, sizeof buf, "%s %s", - id, js_getter_str); -#endif - GC_MARK(cx, - JSVAL_TO_GCTHING((jsval) sprop->getter), - buf, - arg); - } - if (sprop->attrs & JSPROP_SETTER) { -#ifdef GC_MARK_DEBUG - JS_snprintf(buf, sizeof buf, "%s %s", - id, js_setter_str); -#endif - GC_MARK(cx, - JSVAL_TO_GCTHING((jsval) sprop->setter), - buf, - arg); - } - } -#endif /* JS_HAS_GETTER_SETTER */ - } - - /* No one runs while the GC is running, so we can use LOCKED_... here. */ - clasp = LOCKED_OBJ_GET_CLASS(obj); - if (clasp->mark) - (void) clasp->mark(cx, obj, arg); - - if (scope->object != obj) { - /* - * An unmutated object that shares a prototype's scope. We can't tell - * how many slots are allocated and in use at obj->slots by looking at - * scope, so we get obj->slots' length from its -1'st element. - */ - return (uint32) obj->slots[-1]; - } - return JS_MIN(scope->map.freeslot, scope->map.nslots); -} - -void -js_Clear(JSContext *cx, JSObject *obj) -{ - JSScope *scope; - JSRuntime *rt; - JSScopeProperty *sprop; - uint32 i, n; - - /* - * Clear our scope and the property cache of all obj's properties only if - * obj owns the scope (i.e., not if obj is unmutated and therefore sharing - * its prototype's scope). NB: we do not clear any reserved slots lying - * below JSSLOT_FREE(clasp). - */ - JS_LOCK_OBJ(cx, obj); - scope = OBJ_SCOPE(obj); - if (scope->object == obj) { - /* Clear the property cache before we clear the scope. */ - rt = cx->runtime; - for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) { - if (!SCOPE_HAD_MIDDLE_DELETE(scope) || - SCOPE_HAS_PROPERTY(scope, sprop)) { - PROPERTY_CACHE_FILL(&rt->propertyCache, obj, sprop->id, NULL); - } - } - - /* Now that we're done using scope->lastProp/table, clear scope. */ - js_ClearScope(cx, scope); - - /* Clear slot values and reset freeslot so we're consistent. */ - i = scope->map.nslots; - n = JSSLOT_FREE(LOCKED_OBJ_GET_CLASS(obj)); - while (--i >= n) - obj->slots[i] = JSVAL_VOID; - scope->map.freeslot = n; - } - JS_UNLOCK_OBJ(cx, obj); -} - -jsval -js_GetRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot) -{ - jsval v; - - JS_LOCK_OBJ(cx, obj); - v = (slot < (uint32) obj->slots[-1]) ? obj->slots[slot] : JSVAL_VOID; - JS_UNLOCK_OBJ(cx, obj); - return v; -} - -JSBool -js_SetRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot, jsval v) -{ - JSScope *scope; - uint32 nslots; - JSClass *clasp; - jsval *newslots; - - JS_LOCK_OBJ(cx, obj); - scope = OBJ_SCOPE(obj); - nslots = (uint32) obj->slots[-1]; - if (slot >= nslots) { - /* - * At this point, obj may or may not own scope. If some path calls - * js_GetMutableScope but does not add a slot-owning property, then - * scope->object == obj but nslots will be nominal. If obj shares a - * prototype's scope, then we cannot update scope->map here, but we - * must update obj->slots[-1] when we grow obj->slots. - * - * See js_Mark, before the last return, where we make a special case - * for unmutated (scope->object != obj) objects. - */ - JS_ASSERT(nslots == JS_INITIAL_NSLOTS); - clasp = LOCKED_OBJ_GET_CLASS(obj); - nslots = JSSLOT_FREE(clasp); - if (clasp->reserveSlots) - nslots += clasp->reserveSlots(cx, obj); - JS_ASSERT(slot < nslots); - - newslots = AllocSlots(cx, obj->slots, nslots); - if (!newslots) { - JS_UNLOCK_SCOPE(cx, scope); - return JS_FALSE; - } - if (scope->object == obj) - scope->map.nslots = nslots; - obj->slots = newslots; - } - - /* Whether or not we grew nslots, we may need to advance freeslot. */ - if (scope->object == obj && slot >= scope->map.freeslot) - scope->map.freeslot = slot + 1; - - obj->slots[slot] = v; - JS_UNLOCK_SCOPE(cx, scope); - return JS_TRUE; -} - -#ifdef DEBUG - -/* Routines to print out values during debugging. */ - -void printChar(jschar *cp) { - fprintf(stderr, "jschar* (0x%p) \"", (void *)cp); - while (*cp) - fputc(*cp++, stderr); - fputc('"', stderr); - fputc('\n', stderr); -} - -void printString(JSString *str) { - size_t i, n; - jschar *s; - fprintf(stderr, "string (0x%p) \"", (void *)str); - s = JSSTRING_CHARS(str); - for (i=0, n=JSSTRING_LENGTH(str); i < n; i++) - fputc(s[i], stderr); - fputc('"', stderr); - fputc('\n', stderr); -} - -void printVal(JSContext *cx, jsval val); - -void printObj(JSContext *cx, JSObject *jsobj) { - jsuint i; - jsval val; - JSClass *clasp; - - fprintf(stderr, "object 0x%p\n", (void *)jsobj); - clasp = OBJ_GET_CLASS(cx, jsobj); - fprintf(stderr, "class 0x%p %s\n", (void *)clasp, clasp->name); - for (i=0; i < jsobj->map->nslots; i++) { - fprintf(stderr, "slot %3d ", i); - val = jsobj->slots[i]; - if (JSVAL_IS_OBJECT(val)) - fprintf(stderr, "object 0x%p\n", (void *)JSVAL_TO_OBJECT(val)); - else - printVal(cx, val); - } -} - -void printVal(JSContext *cx, jsval val) { - fprintf(stderr, "val %d (0x%p) = ", (int)val, (void *)val); - if (JSVAL_IS_NULL(val)) { - fprintf(stderr, "null\n"); - } else if (JSVAL_IS_VOID(val)) { - fprintf(stderr, "undefined\n"); - } else if (JSVAL_IS_OBJECT(val)) { - printObj(cx, JSVAL_TO_OBJECT(val)); - } else if (JSVAL_IS_INT(val)) { - fprintf(stderr, "(int) %d\n", JSVAL_TO_INT(val)); - } else if (JSVAL_IS_STRING(val)) { - printString(JSVAL_TO_STRING(val)); - } else if (JSVAL_IS_DOUBLE(val)) { - fprintf(stderr, "(double) %g\n", *JSVAL_TO_DOUBLE(val)); - } else { - JS_ASSERT(JSVAL_IS_BOOLEAN(val)); - fprintf(stderr, "(boolean) %s\n", - JSVAL_TO_BOOLEAN(val) ? "true" : "false"); - } - fflush(stderr); -} - -void printId(JSContext *cx, jsid id) { - fprintf(stderr, "id %d (0x%p) is ", (int)id, (void *)id); - printVal(cx, ID_TO_VALUE(id)); -} - -void printAtom(JSAtom *atom) { - printString(ATOM_TO_STRING(atom)); -} - -#endif diff --git a/lib/javascript/jsobj.h b/lib/javascript/jsobj.h deleted file mode 100644 index a2400e98..00000000 --- a/lib/javascript/jsobj.h +++ /dev/null @@ -1,527 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sw=4 et tw=80: - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jsobj_h___ -#define jsobj_h___ -/* - * JS object definitions. - * - * A JS object consists of a possibly-shared object descriptor containing - * ordered property names, called the map; and a dense vector of property - * values, called slots. The map/slot pointer pair is GC'ed, while the map - * is reference counted and the slot vector is malloc'ed. - */ -#include "jshash.h" /* Added by JSIFY */ -#include "jsprvtd.h" -#include "jspubtd.h" - -JS_BEGIN_EXTERN_C - -struct JSObjectMap { - jsrefcount nrefs; /* count of all referencing objects */ - JSObjectOps *ops; /* high level object operation vtable */ - uint32 nslots; /* length of obj->slots vector */ - uint32 freeslot; /* index of next free obj->slots element */ -}; - -/* Shorthand macros for frequently-made calls. */ -#define OBJ_LOOKUP_PROPERTY(cx,obj,id,objp,propp) \ - (obj)->map->ops->lookupProperty(cx,obj,id,objp,propp) -#define OBJ_DEFINE_PROPERTY(cx,obj,id,value,getter,setter,attrs,propp) \ - (obj)->map->ops->defineProperty(cx,obj,id,value,getter,setter,attrs,propp) -#define OBJ_GET_PROPERTY(cx,obj,id,vp) \ - (obj)->map->ops->getProperty(cx,obj,id,vp) -#define OBJ_SET_PROPERTY(cx,obj,id,vp) \ - (obj)->map->ops->setProperty(cx,obj,id,vp) -#define OBJ_GET_ATTRIBUTES(cx,obj,id,prop,attrsp) \ - (obj)->map->ops->getAttributes(cx,obj,id,prop,attrsp) -#define OBJ_SET_ATTRIBUTES(cx,obj,id,prop,attrsp) \ - (obj)->map->ops->setAttributes(cx,obj,id,prop,attrsp) -#define OBJ_DELETE_PROPERTY(cx,obj,id,rval) \ - (obj)->map->ops->deleteProperty(cx,obj,id,rval) -#define OBJ_DEFAULT_VALUE(cx,obj,hint,vp) \ - (obj)->map->ops->defaultValue(cx,obj,hint,vp) -#define OBJ_ENUMERATE(cx,obj,enum_op,statep,idp) \ - (obj)->map->ops->enumerate(cx,obj,enum_op,statep,idp) -#define OBJ_CHECK_ACCESS(cx,obj,id,mode,vp,attrsp) \ - (obj)->map->ops->checkAccess(cx,obj,id,mode,vp,attrsp) - -/* These four are time-optimized to avoid stub calls. */ -#define OBJ_THIS_OBJECT(cx,obj) \ - ((obj)->map->ops->thisObject \ - ? (obj)->map->ops->thisObject(cx,obj) \ - : (obj)) -#define OBJ_DROP_PROPERTY(cx,obj,prop) \ - ((obj)->map->ops->dropProperty \ - ? (obj)->map->ops->dropProperty(cx,obj,prop) \ - : (void)0) -#define OBJ_GET_REQUIRED_SLOT(cx,obj,slot) \ - ((obj)->map->ops->getRequiredSlot \ - ? (obj)->map->ops->getRequiredSlot(cx, obj, slot) \ - : JSVAL_VOID) -#define OBJ_SET_REQUIRED_SLOT(cx,obj,slot,v) \ - ((obj)->map->ops->setRequiredSlot \ - ? (obj)->map->ops->setRequiredSlot(cx, obj, slot, v) \ - : JS_TRUE) - -#define OBJ_TO_INNER_OBJECT(cx,obj) \ - JS_BEGIN_MACRO \ - JSClass *clasp_ = OBJ_GET_CLASS(cx, obj); \ - if (clasp_->flags & JSCLASS_IS_EXTENDED) { \ - JSExtendedClass *xclasp_ = (JSExtendedClass*)clasp_; \ - if (xclasp_->innerObject) \ - obj = xclasp_->innerObject(cx, obj); \ - } \ - JS_END_MACRO - -/* - * In the original JS engine design, obj->slots pointed to a vector of length - * JS_INITIAL_NSLOTS words if obj->map was shared with a prototype object, - * else of length obj->map->nslots. With the advent of JS_GetReservedSlot, - * JS_SetReservedSlot, and JSCLASS_HAS_RESERVED_SLOTS (see jsapi.h), the size - * of the minimum length slots vector in the case where map is shared cannot - * be constant. This length starts at JS_INITIAL_NSLOTS, but may advance to - * include all the reserved slots. - * - * Therefore slots must be self-describing. Rather than tag its low order bit - * (a bit is all we need) to distinguish initial length from reserved length, - * we do "the BSTR thing": over-allocate slots by one jsval, and store the - * *net* length (counting usable slots, which have non-negative obj->slots[] - * indices) in obj->slots[-1]. All code that sets obj->slots must be aware of - * this hack -- you have been warned, and jsobj.c has been updated! - */ -struct JSObject { - JSObjectMap *map; - jsval *slots; -}; - -#define JSSLOT_PROTO 0 -#define JSSLOT_PARENT 1 -#define JSSLOT_CLASS 2 -#define JSSLOT_PRIVATE 3 -#define JSSLOT_START(clasp) (((clasp)->flags & JSCLASS_HAS_PRIVATE) \ - ? JSSLOT_PRIVATE + 1 \ - : JSSLOT_CLASS + 1) - -#define JSSLOT_FREE(clasp) (JSSLOT_START(clasp) \ - + JSCLASS_RESERVED_SLOTS(clasp)) - -#define JS_INITIAL_NSLOTS 5 - -#ifdef DEBUG -#define MAP_CHECK_SLOT(map,slot) \ - JS_ASSERT((uint32)slot < JS_MIN((map)->freeslot, (map)->nslots)) -#define OBJ_CHECK_SLOT(obj,slot) \ - MAP_CHECK_SLOT((obj)->map, slot) -#else -#define OBJ_CHECK_SLOT(obj,slot) ((void)0) -#endif - -/* Fast macros for accessing obj->slots while obj is locked (if thread-safe). */ -#define LOCKED_OBJ_GET_SLOT(obj,slot) \ - (OBJ_CHECK_SLOT(obj, slot), (obj)->slots[slot]) -#define LOCKED_OBJ_SET_SLOT(obj,slot,value) \ - (OBJ_CHECK_SLOT(obj, slot), (obj)->slots[slot] = (value)) -#define LOCKED_OBJ_GET_PROTO(obj) \ - JSVAL_TO_OBJECT(LOCKED_OBJ_GET_SLOT(obj, JSSLOT_PROTO)) -#define LOCKED_OBJ_GET_CLASS(obj) \ - ((JSClass *)JSVAL_TO_PRIVATE(LOCKED_OBJ_GET_SLOT(obj, JSSLOT_CLASS))) - -#ifdef JS_THREADSAFE - -/* Thread-safe functions and wrapper macros for accessing obj->slots. */ -#define OBJ_GET_SLOT(cx,obj,slot) \ - (OBJ_CHECK_SLOT(obj, slot), \ - (OBJ_IS_NATIVE(obj) && OBJ_SCOPE(obj)->ownercx == cx) \ - ? LOCKED_OBJ_GET_SLOT(obj, slot) \ - : js_GetSlotThreadSafe(cx, obj, slot)) - -#define OBJ_SET_SLOT(cx,obj,slot,value) \ - (OBJ_CHECK_SLOT(obj, slot), \ - (OBJ_IS_NATIVE(obj) && OBJ_SCOPE(obj)->ownercx == cx) \ - ? (void) LOCKED_OBJ_SET_SLOT(obj, slot, value) \ - : js_SetSlotThreadSafe(cx, obj, slot, value)) - -/* - * If thread-safe, define an OBJ_GET_SLOT wrapper that bypasses, for a native - * object, the lock-free "fast path" test of (OBJ_SCOPE(obj)->ownercx == cx), - * to avoid needlessly switching from lock-free to lock-full scope when doing - * GC on a different context from the last one to own the scope. The caller - * in this case is probably a JSClass.mark function, e.g., fun_mark, or maybe - * a finalizer. - * - * The GC runs only when all threads except the one on which the GC is active - * are suspended at GC-safe points, so there is no hazard in directly accessing - * obj->slots[slot] from the GC's thread, once rt->gcRunning has been set. See - * jsgc.c for details. - */ -#define THREAD_IS_RUNNING_GC(rt, thread) \ - ((rt)->gcRunning && (rt)->gcThread == (thread)) - -#define CX_THREAD_IS_RUNNING_GC(cx) \ - THREAD_IS_RUNNING_GC((cx)->runtime, (cx)->thread) - -#define GC_AWARE_GET_SLOT(cx, obj, slot) \ - ((OBJ_IS_NATIVE(obj) && CX_THREAD_IS_RUNNING_GC(cx)) \ - ? (obj)->slots[slot] \ - : OBJ_GET_SLOT(cx, obj, slot)) - -#else /* !JS_THREADSAFE */ - -#define OBJ_GET_SLOT(cx,obj,slot) LOCKED_OBJ_GET_SLOT(obj,slot) -#define OBJ_SET_SLOT(cx,obj,slot,value) LOCKED_OBJ_SET_SLOT(obj,slot,value) -#define GC_AWARE_GET_SLOT(cx,obj,slot) LOCKED_OBJ_GET_SLOT(obj,slot) - -#endif /* !JS_THREADSAFE */ - -/* Thread-safe proto, parent, and class access macros. */ -#define OBJ_GET_PROTO(cx,obj) \ - JSVAL_TO_OBJECT(OBJ_GET_SLOT(cx, obj, JSSLOT_PROTO)) -#define OBJ_SET_PROTO(cx,obj,proto) \ - OBJ_SET_SLOT(cx, obj, JSSLOT_PROTO, OBJECT_TO_JSVAL(proto)) - -#define OBJ_GET_PARENT(cx,obj) \ - JSVAL_TO_OBJECT(OBJ_GET_SLOT(cx, obj, JSSLOT_PARENT)) -#define OBJ_SET_PARENT(cx,obj,parent) \ - OBJ_SET_SLOT(cx, obj, JSSLOT_PARENT, OBJECT_TO_JSVAL(parent)) - -#define OBJ_GET_CLASS(cx,obj) \ - ((JSClass *)JSVAL_TO_PRIVATE(OBJ_GET_SLOT(cx, obj, JSSLOT_CLASS))) - -/* Test whether a map or object is native. */ -#define MAP_IS_NATIVE(map) \ - ((map)->ops == &js_ObjectOps || \ - ((map)->ops && (map)->ops->newObjectMap == js_ObjectOps.newObjectMap)) - -#define OBJ_IS_NATIVE(obj) MAP_IS_NATIVE((obj)->map) - -extern JS_FRIEND_DATA(JSObjectOps) js_ObjectOps; -extern JS_FRIEND_DATA(JSObjectOps) js_WithObjectOps; -extern JSClass js_ObjectClass; -extern JSClass js_WithClass; - -extern JSObject * -js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth); - -/* - * A With object is like a Block object, in that both have one reserved slot - * telling the stack depth of the relevant slots (the slot whose value is the - * object named in the with statement, the slots containing the block's local - * variables); and both have a private slot referring to the JSStackFrame in - * whose activation they were created (or null if the with or block object - * outlives the frame). - */ -#define JSSLOT_BLOCK_DEPTH (JSSLOT_PRIVATE + 1) - -#define OBJ_BLOCK_DEPTH(cx,obj) \ - JSVAL_TO_INT(OBJ_GET_SLOT(cx, obj, JSSLOT_BLOCK_DEPTH)) -#define OBJ_SET_BLOCK_DEPTH(cx,obj,depth) \ - OBJ_SET_SLOT(cx, obj, JSSLOT_BLOCK_DEPTH, INT_TO_JSVAL(depth)) - -struct JSSharpObjectMap { - jsrefcount depth; - jsatomid sharpgen; - JSHashTable *table; -}; - -#define SHARP_BIT ((jsatomid) 1) -#define BUSY_BIT ((jsatomid) 2) -#define SHARP_ID_SHIFT 2 -#define IS_SHARP(he) (JS_PTR_TO_UINT32((he)->value) & SHARP_BIT) -#define MAKE_SHARP(he) ((he)->value = JS_UINT32_TO_PTR(JS_PTR_TO_UINT32((he)->value)|SHARP_BIT)) -#define IS_BUSY(he) (JS_PTR_TO_UINT32((he)->value) & BUSY_BIT) -#define MAKE_BUSY(he) ((he)->value = JS_UINT32_TO_PTR(JS_PTR_TO_UINT32((he)->value)|BUSY_BIT)) -#define CLEAR_BUSY(he) ((he)->value = JS_UINT32_TO_PTR(JS_PTR_TO_UINT32((he)->value)&~BUSY_BIT)) - -extern JSHashEntry * -js_EnterSharpObject(JSContext *cx, JSObject *obj, JSIdArray **idap, - jschar **sp); - -extern void -js_LeaveSharpObject(JSContext *cx, JSIdArray **idap); - -/* - * Mark objects stored in map if GC happens between js_EnterSharpObject - * and js_LeaveSharpObject. GC calls this when map->depth > 0. - */ -extern void -js_GCMarkSharpMap(JSContext *cx, JSSharpObjectMap *map); - -extern JSBool -js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval); - -extern JSBool -js_obj_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval); - -extern JSBool -js_HasOwnPropertyHelper(JSContext *cx, JSObject *obj, JSLookupPropOp lookup, - uintN argc, jsval *argv, jsval *rval); - -extern JSObject * -js_InitObjectClass(JSContext *cx, JSObject *obj); - -/* Select Object.prototype method names shared between jsapi.c and jsobj.c. */ -extern const char js_watch_str[]; -extern const char js_unwatch_str[]; -extern const char js_hasOwnProperty_str[]; -extern const char js_isPrototypeOf_str[]; -extern const char js_propertyIsEnumerable_str[]; -extern const char js_defineGetter_str[]; -extern const char js_defineSetter_str[]; -extern const char js_lookupGetter_str[]; -extern const char js_lookupSetter_str[]; - -extern void -js_InitObjectMap(JSObjectMap *map, jsrefcount nrefs, JSObjectOps *ops, - JSClass *clasp); - -extern JSObjectMap * -js_NewObjectMap(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops, - JSClass *clasp, JSObject *obj); - -extern void -js_DestroyObjectMap(JSContext *cx, JSObjectMap *map); - -extern JSObjectMap * -js_HoldObjectMap(JSContext *cx, JSObjectMap *map); - -extern JSObjectMap * -js_DropObjectMap(JSContext *cx, JSObjectMap *map, JSObject *obj); - -extern JSObject * -js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent); - -extern JSBool -js_FindConstructor(JSContext *cx, JSObject *start, const char *name, jsval *vp); - -extern JSObject * -js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto, - JSObject *parent, uintN argc, jsval *argv); - -extern void -js_FinalizeObject(JSContext *cx, JSObject *obj); - -extern JSBool -js_AllocSlot(JSContext *cx, JSObject *obj, uint32 *slotp); - -extern void -js_FreeSlot(JSContext *cx, JSObject *obj, uint32 slot); - -/* - * Native property add and lookup variants that hide id in the hidden atom - * subspace, so as to avoid collisions between internal properties such as - * formal arguments and local variables in function objects, and externally - * set properties with the same ids. - */ -extern JSScopeProperty * -js_AddHiddenProperty(JSContext *cx, JSObject *obj, jsid id, - JSPropertyOp getter, JSPropertyOp setter, uint32 slot, - uintN attrs, uintN flags, intN shortid); - -extern JSBool -js_LookupHiddenProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, - JSProperty **propp); - -/* - * Find or create a property named by id in obj's scope, with the given getter - * and setter, slot, attributes, and other members. - */ -extern JSScopeProperty * -js_AddNativeProperty(JSContext *cx, JSObject *obj, jsid id, - JSPropertyOp getter, JSPropertyOp setter, uint32 slot, - uintN attrs, uintN flags, intN shortid); - -/* - * Change sprop to have the given attrs, getter, and setter in scope, morphing - * it into a potentially new JSScopeProperty. Return a pointer to the changed - * or identical property. - */ -extern JSScopeProperty * -js_ChangeNativePropertyAttrs(JSContext *cx, JSObject *obj, - JSScopeProperty *sprop, uintN attrs, uintN mask, - JSPropertyOp getter, JSPropertyOp setter); - -/* - * On error, return false. On success, if propp is non-null, return true with - * obj locked and with a held property in *propp; if propp is null, return true - * but release obj's lock first. Therefore all callers who pass non-null propp - * result parameters must later call OBJ_DROP_PROPERTY(cx, obj, *propp) both to - * drop the held property, and to release the lock on obj. - */ -extern JSBool -js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value, - JSPropertyOp getter, JSPropertyOp setter, uintN attrs, - JSProperty **propp); - -extern JSBool -js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, jsval value, - JSPropertyOp getter, JSPropertyOp setter, uintN attrs, - uintN flags, intN shortid, JSProperty **propp); - -/* - * Unlike js_DefineProperty, propp must be non-null. On success, and if id was - * found, return true with *objp non-null and locked, and with a held property - * stored in *propp. If successful but id was not found, return true with both - * *objp and *propp null. Therefore all callers who receive a non-null *propp - * must later call OBJ_DROP_PROPERTY(cx, *objp, *propp). - */ -extern JS_FRIEND_API(JSBool) -js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, - JSProperty **propp); - -/* - * Specialized subroutine that allows caller to preset JSRESOLVE_* flags. - */ -extern JSBool -js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags, - JSObject **objp, JSProperty **propp); - -extern JS_FRIEND_API(JSBool) -js_FindProperty(JSContext *cx, jsid id, JSObject **objp, JSObject **pobjp, - JSProperty **propp); - -extern JSObject * -js_FindIdentifierBase(JSContext *cx, jsid id); - -extern JSObject * -js_FindVariableScope(JSContext *cx, JSFunction **funp); - -extern JSBool -js_GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp); - -extern JSBool -js_SetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp); - -extern JSBool -js_GetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop, - uintN *attrsp); - -extern JSBool -js_SetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop, - uintN *attrsp); - -extern JSBool -js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval); - -extern JSBool -js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp); - -extern JSIdArray * -js_NewIdArray(JSContext *cx, jsint length); - -/* - * Unlike realloc(3), this function frees ida on failure. - */ -extern JSIdArray * -js_SetIdArrayLength(JSContext *cx, JSIdArray *ida, jsint length); - -extern JSBool -js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, - jsval *statep, jsid *idp); - -extern void -js_MarkNativeIteratorStates(JSContext *cx); - -extern JSBool -js_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode, - jsval *vp, uintN *attrsp); - -extern JSBool -js_Call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); - -extern JSBool -js_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval); - -extern JSBool -js_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp); - -extern JSBool -js_SetProtoOrParent(JSContext *cx, JSObject *obj, uint32 slot, JSObject *pobj); - -extern JSBool -js_IsDelegate(JSContext *cx, JSObject *obj, jsval v, JSBool *bp); - -extern JSBool -js_GetClassPrototype(JSContext *cx, const char *name, JSObject **protop); - -extern JSBool -js_SetClassPrototype(JSContext *cx, JSObject *ctor, JSObject *proto, - uintN attrs); - -extern JSBool -js_ValueToObject(JSContext *cx, jsval v, JSObject **objp); - -extern JSObject * -js_ValueToNonNullObject(JSContext *cx, jsval v); - -extern JSBool -js_TryValueOf(JSContext *cx, JSObject *obj, JSType type, jsval *rval); - -extern JSBool -js_TryMethod(JSContext *cx, JSObject *obj, JSAtom *atom, - uintN argc, jsval *argv, jsval *rval); - -extern JSBool -js_XDRObject(JSXDRState *xdr, JSObject **objp); - -extern uint32 -js_Mark(JSContext *cx, JSObject *obj, void *arg); - -extern void -js_Clear(JSContext *cx, JSObject *obj); - -extern jsval -js_GetRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot); - -extern JSBool -js_SetRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot, jsval v); - -extern JSObject * -js_CheckScopeChainValidity(JSContext *cx, JSObject *scopeobj, const char *caller); - -extern JSBool -js_CheckPrincipalsAccess(JSContext *cx, JSObject *scopeobj, - JSPrincipals *principals, const char *caller); -JS_END_EXTERN_C - -#endif /* jsobj_h___ */ diff --git a/lib/javascript/jsopcode.c b/lib/javascript/jsopcode.c deleted file mode 100644 index 80c7eb4d..00000000 --- a/lib/javascript/jsopcode.c +++ /dev/null @@ -1,3167 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set sw=4 ts=8 et tw=80: - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JS bytecode descriptors, disassemblers, and decompilers. - */ -#include "jsstddef.h" -#ifdef HAVE_MEMORY_H -#include -#endif -#include -#include -#include -#include -#include "jstypes.h" -#include "jsarena.h" /* Added by JSIFY */ -#include "jsutil.h" /* Added by JSIFY */ -#include "jsdtoa.h" -#include "jsprf.h" -#include "jsapi.h" -#include "jsarray.h" -#include "jsatom.h" -#include "jscntxt.h" -#include "jsconfig.h" -#include "jsdbgapi.h" -#include "jsemit.h" -#include "jsfun.h" -#include "jslock.h" -#include "jsobj.h" -#include "jsopcode.h" -#include "jsregexp.h" -#include "jsscope.h" -#include "jsscript.h" -#include "jsstr.h" - -const char js_const_str[] = "const"; -const char js_var_str[] = "var"; -const char js_function_str[] = "function"; -const char js_in_str[] = "in"; -const char js_instanceof_str[] = "instanceof"; -const char js_new_str[] = "new"; -const char js_delete_str[] = "delete"; -const char js_typeof_str[] = "typeof"; -const char js_void_str[] = "void"; -const char js_null_str[] = "null"; -const char js_this_str[] = "this"; -const char js_false_str[] = "false"; -const char js_true_str[] = "true"; -const char js_default_str[] = "default"; - -const char *js_incop_str[] = {"++", "--"}; - -/* Pollute the namespace locally for MSVC Win16, but not for WatCom. */ -#ifdef __WINDOWS_386__ - #ifdef FAR - #undef FAR - #endif -#else /* !__WINDOWS_386__ */ -#ifndef FAR -#define FAR -#endif -#endif /* !__WINDOWS_386__ */ - -const JSCodeSpec FAR js_CodeSpec[] = { -#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \ - {name,token,length,nuses,ndefs,prec,format}, -#include "jsopcode.tbl" -#undef OPDEF -}; - -uintN js_NumCodeSpecs = sizeof (js_CodeSpec) / sizeof js_CodeSpec[0]; - -/************************************************************************/ - -static ptrdiff_t -GetJumpOffset(jsbytecode *pc, jsbytecode *pc2) -{ - uint32 type; - - type = (js_CodeSpec[*pc].format & JOF_TYPEMASK); - if (JOF_TYPE_IS_EXTENDED_JUMP(type)) - return GET_JUMPX_OFFSET(pc2); - return GET_JUMP_OFFSET(pc2); -} - -#ifdef DEBUG - -JS_FRIEND_API(JSBool) -js_Disassemble(JSContext *cx, JSScript *script, JSBool lines, FILE *fp) -{ - jsbytecode *pc, *end; - uintN len; - - pc = script->code; - end = pc + script->length; - while (pc < end) { - if (pc == script->main) - fputs("main:\n", fp); - len = js_Disassemble1(cx, script, pc, - PTRDIFF(pc, script->code, jsbytecode), - lines, fp); - if (!len) - return JS_FALSE; - pc += len; - } - return JS_TRUE; -} - -JS_FRIEND_API(uintN) -js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, uintN loc, - JSBool lines, FILE *fp) -{ - JSOp op; - const JSCodeSpec *cs; - ptrdiff_t len, off, jmplen; - uint32 type; - JSAtom *atom; - JSString *str; - - op = (JSOp)*pc; - if (op >= JSOP_LIMIT) { - char numBuf1[12], numBuf2[12]; - JS_snprintf(numBuf1, sizeof numBuf1, "%d", op); - JS_snprintf(numBuf2, sizeof numBuf2, "%d", JSOP_LIMIT); - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BYTECODE_TOO_BIG, numBuf1, numBuf2); - return 0; - } - cs = &js_CodeSpec[op]; - len = (ptrdiff_t) cs->length; - fprintf(fp, "%05u:", loc); - if (lines) - fprintf(fp, "%4u", JS_PCToLineNumber(cx, script, pc)); - fprintf(fp, " %s", cs->name); - type = cs->format & JOF_TYPEMASK; - switch (type) { - case JOF_BYTE: - if (op == JSOP_TRAP) { - op = JS_GetTrapOpcode(cx, script, pc); - if (op == JSOP_LIMIT) - return 0; - len = (ptrdiff_t) js_CodeSpec[op].length; - } - break; - - case JOF_JUMP: - case JOF_JUMPX: - off = GetJumpOffset(pc, pc); - fprintf(fp, " %u (%d)", loc + off, off); - break; - - case JOF_CONST: - atom = GET_ATOM(cx, script, pc); - str = js_ValueToSource(cx, ATOM_KEY(atom)); - if (!str) - return 0; - fprintf(fp, " %s", JS_GetStringBytes(str)); - break; - - case JOF_UINT16: - fprintf(fp, " %u", GET_ARGC(pc)); - break; - -#if JS_HAS_SWITCH_STATEMENT - case JOF_TABLESWITCH: - case JOF_TABLESWITCHX: - { - jsbytecode *pc2; - jsint i, low, high; - - jmplen = (type == JOF_TABLESWITCH) ? JUMP_OFFSET_LEN - : JUMPX_OFFSET_LEN; - pc2 = pc; - off = GetJumpOffset(pc, pc2); - pc2 += jmplen; - low = GET_JUMP_OFFSET(pc2); - pc2 += JUMP_OFFSET_LEN; - high = GET_JUMP_OFFSET(pc2); - pc2 += JUMP_OFFSET_LEN; - fprintf(fp, " defaultOffset %d low %d high %d", off, low, high); - for (i = low; i <= high; i++) { - off = GetJumpOffset(pc, pc2); - fprintf(fp, "\n\t%d: %d", i, off); - pc2 += jmplen; - } - len = 1 + pc2 - pc; - break; - } - - case JOF_LOOKUPSWITCH: - case JOF_LOOKUPSWITCHX: - { - jsbytecode *pc2; - jsatomid npairs; - - jmplen = (type == JOF_LOOKUPSWITCH) ? JUMP_OFFSET_LEN - : JUMPX_OFFSET_LEN; - pc2 = pc; - off = GetJumpOffset(pc, pc2); - pc2 += jmplen; - npairs = GET_ATOM_INDEX(pc2); - pc2 += ATOM_INDEX_LEN; - fprintf(fp, " offset %d npairs %u", off, (uintN) npairs); - while (npairs) { - atom = GET_ATOM(cx, script, pc2); - pc2 += ATOM_INDEX_LEN; - off = GetJumpOffset(pc, pc2); - pc2 += jmplen; - - str = js_ValueToSource(cx, ATOM_KEY(atom)); - if (!str) - return 0; - fprintf(fp, "\n\t%s: %d", JS_GetStringBytes(str), off); - npairs--; - } - len = 1 + pc2 - pc; - break; - } -#endif /* JS_HAS_SWITCH_STATEMENT */ - - case JOF_QARG: - fprintf(fp, " %u", GET_ARGNO(pc)); - break; - - case JOF_QVAR: - fprintf(fp, " %u", GET_VARNO(pc)); - break; - -#if JS_HAS_LEXICAL_CLOSURE - case JOF_INDEXCONST: - fprintf(fp, " %u", GET_VARNO(pc)); - pc += VARNO_LEN; - atom = GET_ATOM(cx, script, pc); - str = js_ValueToSource(cx, ATOM_KEY(atom)); - if (!str) - return 0; - fprintf(fp, " %s", JS_GetStringBytes(str)); - break; -#endif - - case JOF_UINT24: - if (op == JSOP_FINDNAME) { - /* Special case to avoid a JOF_FINDNAME just for this op. */ - atom = js_GetAtom(cx, &script->atomMap, GET_LITERAL_INDEX(pc)); - str = js_ValueToSource(cx, ATOM_KEY(atom)); - if (!str) - return 0; - fprintf(fp, " %s", JS_GetStringBytes(str)); - break; - } - - JS_ASSERT(op == JSOP_UINT24 || op == JSOP_LITERAL); - fprintf(fp, " %u", GET_LITERAL_INDEX(pc)); - break; - - case JOF_LITOPX: - atom = js_GetAtom(cx, &script->atomMap, GET_LITERAL_INDEX(pc)); - str = js_ValueToSource(cx, ATOM_KEY(atom)); - if (!str) - return 0; - - /* - * Bytecode: JSOP_LITOPX op [ if JSOP_DEFLOCALFUN]. - * Advance pc to point at op. - */ - pc += 1 + LITERAL_INDEX_LEN; - op = *pc; - cs = &js_CodeSpec[op]; - fprintf(fp, " %s op %s", JS_GetStringBytes(str), cs->name); -#if JS_HAS_LEXICAL_CLOSURE - if ((cs->format & JOF_TYPEMASK) == JOF_INDEXCONST) - fprintf(fp, " %u", GET_VARNO(pc)); -#endif - - /* - * Set len to advance pc to skip op and any other immediates (namely, - * if JSOP_DEFLOCALFUN). - */ - JS_ASSERT(cs->length > ATOM_INDEX_LEN); - len = cs->length - ATOM_INDEX_LEN; - break; - - default: { - char numBuf[12]; - JS_snprintf(numBuf, sizeof numBuf, "%lx", (unsigned long) cs->format); - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_UNKNOWN_FORMAT, numBuf); - return 0; - } - } - fputs("\n", fp); - return len; -} - -#endif /* DEBUG */ - -/************************************************************************/ - -/* - * Sprintf, but with unlimited and automatically allocated buffering. - */ -typedef struct Sprinter { - JSContext *context; /* context executing the decompiler */ - JSArenaPool *pool; /* string allocation pool */ - char *base; /* base address of buffer in pool */ - size_t size; /* size of buffer allocated at base */ - ptrdiff_t offset; /* offset of next free char in buffer */ -} Sprinter; - -#define INIT_SPRINTER(cx, sp, ap, off) \ - ((sp)->context = cx, (sp)->pool = ap, (sp)->base = NULL, (sp)->size = 0, \ - (sp)->offset = off) - -#define OFF2STR(sp,off) ((sp)->base + (off)) -#define STR2OFF(sp,str) ((str) - (sp)->base) -#define RETRACT(sp,str) ((sp)->offset = STR2OFF(sp, str)) - -static JSBool -SprintAlloc(Sprinter *sp, size_t nb) -{ - if (!sp->base) { - JS_ARENA_ALLOCATE_CAST(sp->base, char *, sp->pool, nb); - } else { - JS_ARENA_GROW_CAST(sp->base, char *, sp->pool, sp->size, nb); - } - if (!sp->base) { - JS_ReportOutOfMemory(sp->context); - return JS_FALSE; - } - sp->size += nb; - return JS_TRUE; -} - -static ptrdiff_t -SprintPut(Sprinter *sp, const char *s, size_t len) -{ - ptrdiff_t nb, offset; - char *bp; - - /* Allocate space for s, including the '\0' at the end. */ - nb = (sp->offset + len + 1) - sp->size; - if (nb > 0 && !SprintAlloc(sp, nb)) - return -1; - - /* Advance offset and copy s into sp's buffer. */ - offset = sp->offset; - sp->offset += len; - bp = sp->base + offset; - memmove(bp, s, len); - bp[len] = 0; - return offset; -} - -static ptrdiff_t -Sprint(Sprinter *sp, const char *format, ...) -{ - va_list ap; - char *bp; - ptrdiff_t offset; - - va_start(ap, format); - bp = JS_vsmprintf(format, ap); /* XXX vsaprintf */ - va_end(ap); - if (!bp) { - JS_ReportOutOfMemory(sp->context); - return -1; - } - offset = SprintPut(sp, bp, strlen(bp)); - free(bp); - return offset; -} - -const jschar js_EscapeMap[] = { - '\b', 'b', - '\f', 'f', - '\n', 'n', - '\r', 'r', - '\t', 't', - '\v', 'v', - '"', '"', - '\'', '\'', - '\\', '\\', - 0 -}; - -static char * -QuoteString(Sprinter *sp, JSString *str, jschar quote) -{ - ptrdiff_t off, len, nb; - const jschar *s, *t, *u, *z; - char *bp; - jschar c; - JSBool ok; - - /* Sample off first for later return value pointer computation. */ - off = sp->offset; - if (quote && Sprint(sp, "%c", (char)quote) < 0) - return NULL; - - /* Loop control variables: z points at end of string sentinel. */ - s = JSSTRING_CHARS(str); - z = s + JSSTRING_LENGTH(str); - for (t = s; t < z; s = ++t) { - /* Move t forward from s past un-quote-worthy characters. */ - c = *t; - while (JS_ISPRINT(c) && c != quote && c != '\\' && !(c >> 8)) { - c = *++t; - if (t == z) - break; - } - len = PTRDIFF(t, s, jschar); - - /* Allocate space for s, including the '\0' at the end. */ - nb = (sp->offset + len + 1) - sp->size; - if (nb > 0 && !SprintAlloc(sp, nb)) - return NULL; - - /* Advance sp->offset and copy s into sp's buffer. */ - bp = sp->base + sp->offset; - sp->offset += len; - while (--len >= 0) - *bp++ = (char) *s++; - *bp = '\0'; - - if (t == z) - break; - - /* Use js_EscapeMap, \u, or \x only if necessary. */ - if ((u = js_strchr(js_EscapeMap, c)) != NULL) { - ok = Sprint(sp, "\\%c", (char)u[1]) >= 0; - } else { -#ifdef JS_C_STRINGS_ARE_UTF8 - /* If this is a surrogate pair, make sure to print the pair. */ - if (c >= 0xD800 && c <= 0xDBFF) { - jschar buffer[3]; - buffer[0] = c; - buffer[1] = *++t; - buffer[2] = 0; - if (t == z) { - char numbuf[10]; - JS_snprintf(numbuf, sizeof numbuf, "0x%x", c); - JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, - js_GetErrorMessage, NULL, - JSMSG_BAD_SURROGATE_CHAR, - numbuf); - ok = JS_FALSE; - break; - } - ok = Sprint(sp, "%hs", buffer) >= 0; - } else { - /* Print as UTF-8 string. */ - ok = Sprint(sp, "%hc", c) >= 0; - } -#else - /* Use \uXXXX or \xXX if the string can't be displayed as UTF-8. */ - ok = Sprint(sp, (c >> 8) ? "\\u%04X" : "\\x%02X", c) >= 0; -#endif - } - if (!ok) - return NULL; - } - - /* Sprint the closing quote and return the quoted string. */ - if (quote && Sprint(sp, "%c", (char)quote) < 0) - return NULL; - - /* - * If we haven't Sprint'd anything yet, Sprint an empty string so that - * the OFF2STR below gives a valid result. - */ - if (off == sp->offset && Sprint(sp, "") < 0) - return NULL; - return OFF2STR(sp, off); -} - -JSString * -js_QuoteString(JSContext *cx, JSString *str, jschar quote) -{ - void *mark; - Sprinter sprinter; - char *bytes; - JSString *escstr; - - mark = JS_ARENA_MARK(&cx->tempPool); - INIT_SPRINTER(cx, &sprinter, &cx->tempPool, 0); - bytes = QuoteString(&sprinter, str, quote); - escstr = bytes ? JS_NewStringCopyZ(cx, bytes) : NULL; - JS_ARENA_RELEASE(&cx->tempPool, mark); - return escstr; -} - -/************************************************************************/ - -struct JSPrinter { - Sprinter sprinter; /* base class state */ - JSArenaPool pool; /* string allocation pool */ - uintN indent; /* indentation in spaces */ - JSPackedBool pretty; /* pretty-print: indent, use newlines */ - JSPackedBool grouped; /* in parenthesized expression context */ - JSScript *script; /* script being printed */ - JSScope *scope; /* script function scope */ -}; - -/* - * Hack another flag, a la JS_DONT_PRETTY_PRINT, into uintN indent parameters - * to functions such as js_DecompileFunction and js_NewPrinter. This time, as - * opposed to JS_DONT_PRETTY_PRINT back in the dark ages, we can assume that a - * uintN is at least 32 bits. - */ -#define JS_IN_GROUP_CONTEXT 0x10000 - -JSPrinter * -js_NewPrinter(JSContext *cx, const char *name, uintN indent, JSBool pretty) -{ - JSPrinter *jp; - - jp = (JSPrinter *) JS_malloc(cx, sizeof(JSPrinter)); - if (!jp) - return NULL; - INIT_SPRINTER(cx, &jp->sprinter, &jp->pool, 0); - JS_InitArenaPool(&jp->pool, name, 256, 1); - jp->indent = indent & ~JS_IN_GROUP_CONTEXT; - jp->pretty = pretty; - jp->grouped = (indent & JS_IN_GROUP_CONTEXT) != 0; - jp->script = NULL; - jp->scope = NULL; - return jp; -} - -void -js_DestroyPrinter(JSPrinter *jp) -{ - JS_FinishArenaPool(&jp->pool); - JS_free(jp->sprinter.context, jp); -} - -JSString * -js_GetPrinterOutput(JSPrinter *jp) -{ - JSContext *cx; - JSString *str; - - cx = jp->sprinter.context; - if (!jp->sprinter.base) - return cx->runtime->emptyString; - str = JS_NewStringCopyZ(cx, jp->sprinter.base); - if (!str) - return NULL; - JS_FreeArenaPool(&jp->pool); - INIT_SPRINTER(cx, &jp->sprinter, &jp->pool, 0); - return str; -} - -int -js_printf(JSPrinter *jp, const char *format, ...) -{ - va_list ap; - char *bp, *fp; - int cc; - - if (*format == '\0') - return 0; - - va_start(ap, format); - - /* If pretty-printing, expand magic tab into a run of jp->indent spaces. */ - if (*format == '\t') { - if (jp->pretty && Sprint(&jp->sprinter, "%*s", jp->indent, "") < 0) - return -1; - format++; - } - - /* Suppress newlines (must be once per format, at the end) if not pretty. */ - fp = NULL; - if (!jp->pretty && format[cc = strlen(format) - 1] == '\n') { - fp = JS_strdup(jp->sprinter.context, format); - if (!fp) - return -1; - fp[cc] = '\0'; - format = fp; - } - - /* Allocate temp space, convert format, and put. */ - bp = JS_vsmprintf(format, ap); /* XXX vsaprintf */ - if (fp) { - JS_free(jp->sprinter.context, fp); - format = NULL; - } - if (!bp) { - JS_ReportOutOfMemory(jp->sprinter.context); - return -1; - } - - cc = strlen(bp); - if (SprintPut(&jp->sprinter, bp, (size_t)cc) < 0) - cc = -1; - free(bp); - - va_end(ap); - return cc; -} - -JSBool -js_puts(JSPrinter *jp, const char *s) -{ - return SprintPut(&jp->sprinter, s, strlen(s)) >= 0; -} - -/************************************************************************/ - -typedef struct SprintStack { - Sprinter sprinter; /* sprinter for postfix to infix buffering */ - ptrdiff_t *offsets; /* stack of postfix string offsets */ - jsbytecode *opcodes; /* parallel stack of JS opcodes */ - uintN top; /* top of stack index */ - JSPrinter *printer; /* permanent output goes here */ -} SprintStack; - -/* Gap between stacked strings to allow for insertion of parens and commas. */ -#define PAREN_SLOP (2 + 1) - -/* - * These pseudo-ops help js_DecompileValueGenerator decompile JSOP_SETNAME, - * JSOP_SETPROP, and JSOP_SETELEM, respectively. See the first assertion in - * PushOff. - */ -#define JSOP_GETPROP2 254 -#define JSOP_GETELEM2 255 - -static JSBool -PushOff(SprintStack *ss, ptrdiff_t off, JSOp op) -{ - uintN top; - -#if JSOP_LIMIT > JSOP_GETPROP2 -#error JSOP_LIMIT must be <= JSOP_GETPROP2 -#endif - if (!SprintAlloc(&ss->sprinter, PAREN_SLOP)) - return JS_FALSE; - - /* ss->top points to the next free slot; be paranoid about overflow. */ - top = ss->top; - JS_ASSERT(top < ss->printer->script->depth); - if (top >= ss->printer->script->depth) { - JS_ReportOutOfMemory(ss->sprinter.context); - return JS_FALSE; - } - - /* The opcodes stack must contain real bytecodes that index js_CodeSpec. */ - ss->offsets[top] = off; - ss->opcodes[top] = (op == JSOP_GETPROP2) ? JSOP_GETPROP - : (op == JSOP_GETELEM2) ? JSOP_GETELEM - : (jsbytecode) op; - ss->top = ++top; - ss->sprinter.offset += PAREN_SLOP; - return JS_TRUE; -} - -static ptrdiff_t -PopOff(SprintStack *ss, JSOp op) -{ - uintN top; - const JSCodeSpec *cs, *topcs; - ptrdiff_t off; - - /* ss->top points to the next free slot; be paranoid about underflow. */ - top = ss->top; - JS_ASSERT(top != 0); - if (top == 0) - return 0; - - ss->top = --top; - topcs = &js_CodeSpec[ss->opcodes[top]]; - cs = &js_CodeSpec[op]; - if (topcs->prec != 0 && topcs->prec < cs->prec) { - ss->offsets[top] -= 2; - ss->sprinter.offset = ss->offsets[top]; - off = Sprint(&ss->sprinter, "(%s)", - OFF2STR(&ss->sprinter, ss->sprinter.offset + 2)); - } else { - off = ss->sprinter.offset = ss->offsets[top]; - } - return off; -} - -#if JS_HAS_SWITCH_STATEMENT -typedef struct TableEntry { - jsval key; - ptrdiff_t offset; - JSAtom *label; - jsint order; /* source order for stable tableswitch sort */ -} TableEntry; - -static int -CompareOffsets(const void *v1, const void *v2, void *arg) -{ - const TableEntry *te1 = (const TableEntry *) v1, - *te2 = (const TableEntry *) v2; - - if (te1->offset == te2->offset) - return (int) (te1->order - te2->order); - return (int) (te1->offset - te2->offset); -} - -static JSBool -Decompile(SprintStack *ss, jsbytecode *pc, intN nb); - -static JSBool -DecompileSwitch(SprintStack *ss, TableEntry *table, uintN tableLength, - jsbytecode *pc, ptrdiff_t switchLength, - ptrdiff_t defaultOffset, JSBool isCondSwitch) -{ - JSContext *cx; - JSPrinter *jp; - char *lval, *rval; - uintN i; - ptrdiff_t diff, off, off2, caseExprOff; - jsval key; - JSString *str; - - cx = ss->sprinter.context; - jp = ss->printer; - - lval = OFF2STR(&ss->sprinter, PopOff(ss, JSOP_NOP)); - js_printf(jp, "\tswitch (%s) {\n", lval); - - if (tableLength) { - diff = table[0].offset - defaultOffset; - if (diff > 0) { - jp->indent += 2; - js_printf(jp, "\t%s:\n", js_default_str); - jp->indent += 2; - if (!Decompile(ss, pc + defaultOffset, diff)) - return JS_FALSE; - jp->indent -= 4; - } - - caseExprOff = isCondSwitch - ? (ptrdiff_t) js_CodeSpec[JSOP_CONDSWITCH].length - : 0; - - for (i = 0; i < tableLength; i++) { - off = table[i].offset; - off2 = (i + 1 < tableLength) ? table[i + 1].offset : switchLength; - - key = table[i].key; - if (isCondSwitch) { - ptrdiff_t nextCaseExprOff; - - /* - * key encodes the JSOP_CASE bytecode's offset from switchtop. - * The next case expression follows immediately, unless we are - * at the last case. - */ - nextCaseExprOff = (ptrdiff_t)JSVAL_TO_INT(key); - nextCaseExprOff += js_CodeSpec[pc[nextCaseExprOff]].length; - jp->indent += 2; - if (!Decompile(ss, pc + caseExprOff, - nextCaseExprOff - caseExprOff)) { - return JS_FALSE; - } - caseExprOff = nextCaseExprOff; - } else { - /* - * key comes from an atom, not the decompiler, so we need to - * quote it if it's a string literal. But if table[i].label - * is non-null, key was constant-propagated and label is the - * name of the const we should show as the case label. We set - * key to undefined so this identifier is escaped, if required - * by non-ASCII characters, but not quoted, by QuoteString. - */ - if (table[i].label) { - str = ATOM_TO_STRING(table[i].label); - key = JSVAL_VOID; - } else { - str = js_ValueToString(cx, key); - if (!str) - return JS_FALSE; - } - rval = QuoteString(&ss->sprinter, str, - (jschar)(JSVAL_IS_STRING(key) ? '"' : 0)); - if (!rval) - return JS_FALSE; - RETRACT(&ss->sprinter, rval); - jp->indent += 2; - js_printf(jp, "\tcase %s:\n", rval); - } - - jp->indent += 2; - if (off <= defaultOffset && defaultOffset < off2) { - diff = defaultOffset - off; - if (diff != 0) { - if (!Decompile(ss, pc + off, diff)) - return JS_FALSE; - off = defaultOffset; - } - jp->indent -= 2; - js_printf(jp, "\t%s:\n", js_default_str); - jp->indent += 2; - } - if (!Decompile(ss, pc + off, off2 - off)) - return JS_FALSE; - jp->indent -= 4; - } - } - - if (defaultOffset == switchLength) { - jp->indent += 2; - js_printf(jp, "\t%s:;\n", js_default_str); - jp->indent -= 2; - } - js_printf(jp, "\t}\n"); - return JS_TRUE; -} -#endif - -static JSAtom * -GetSlotAtom(JSPrinter *jp, JSPropertyOp getter, uintN slot) -{ - JSScope *scope; - JSScopeProperty *sprop; - JSObject *obj, *proto; - - scope = jp->scope; - while (scope) { - for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) { - if (sprop->getter != getter) - continue; - JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID); - JS_ASSERT(JSID_IS_ATOM(sprop->id)); - if ((uintN) sprop->shortid == slot) - return JSID_TO_ATOM(sprop->id); - } - obj = scope->object; - if (!obj) - break; - proto = OBJ_GET_PROTO(jp->sprinter.context, obj); - if (!proto) - break; - scope = OBJ_SCOPE(proto); - } - return NULL; -} - -static const char * -VarPrefix(jssrcnote *sn) -{ - if (sn) { - if (SN_TYPE(sn) == SRC_VAR) - return "var "; - if (SN_TYPE(sn) == SRC_CONST) - return "const "; - } - return ""; -} - -static JSBool -Decompile(SprintStack *ss, jsbytecode *pc, intN nb) -{ - JSContext *cx; - JSPrinter *jp, *jp2; - jsbytecode *endpc, *done, *forelem_tail, *forelem_done; - ptrdiff_t tail, todo, len, oplen, cond, next; - JSOp op, lastop, saveop; - const JSCodeSpec *cs, *topcs; - jssrcnote *sn, *sn2; - const char *lval, *rval, *xval, *fmt; - jsint i, argc; - char **argv; - jsatomid atomIndex; - JSAtom *atom; - JSObject *obj; - JSFunction *fun; - JSString *str; - JSBool ok; -#if JS_HAS_XML_SUPPORT - JSBool foreach, inXML, quoteAttr; -#else -#define inXML JS_FALSE -#endif - jsval val; - int stackDummy; - static const char catch_cookie[] = "/*CATCH*/"; - static const char with_cookie[] = "/*WITH*/"; - -/* - * Local macros - */ -#define DECOMPILE_CODE(pc,nb) if (!Decompile(ss, pc, nb)) return JS_FALSE -#define POP_STR() OFF2STR(&ss->sprinter, PopOff(ss, op)) -#define LOCAL_ASSERT(expr) JS_ASSERT(expr); if (!(expr)) return JS_FALSE - -/* - * Callers know that ATOM_IS_STRING(atom), and we leave it to the optimizer to - * common ATOM_TO_STRING(atom) here and near the call sites. - */ -#define ATOM_IS_IDENTIFIER(atom) \ - (!ATOM_KEYWORD(atom) && js_IsIdentifier(ATOM_TO_STRING(atom))) - -/* - * Given an atom already fetched from jp->script's atom map, quote/escape its - * string appropriately into rval, and select fmt from the quoted and unquoted - * alternatives. - */ -#define GET_QUOTE_AND_FMT(qfmt, ufmt, rval) \ - JS_BEGIN_MACRO \ - jschar quote_; \ - if (!ATOM_IS_IDENTIFIER(atom)) { \ - quote_ = '\''; \ - fmt = qfmt; \ - } else { \ - quote_ = 0; \ - fmt = ufmt; \ - } \ - rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), quote_); \ - if (!rval) \ - return JS_FALSE; \ - JS_END_MACRO - -/* - * Get atom from jp->script's atom map, quote/escape its string appropriately - * into rval, and select fmt from the quoted and unquoted alternatives. - */ -#define GET_ATOM_QUOTE_AND_FMT(qfmt, ufmt, rval) \ - JS_BEGIN_MACRO \ - atom = GET_ATOM(cx, jp->script, pc); \ - GET_QUOTE_AND_FMT(qfmt, ufmt, rval); \ - JS_END_MACRO - - cx = ss->sprinter.context; - if (!JS_CHECK_STACK_SIZE(cx, stackDummy)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_OVER_RECURSED); - return JS_FALSE; - } - - jp = ss->printer; - endpc = pc + nb; - forelem_tail = forelem_done = NULL; - tail = -1; - todo = -2; /* NB: different from Sprint() error return. */ - op = JSOP_NOP; - sn = NULL; - rval = NULL; -#if JS_HAS_XML_SUPPORT - foreach = inXML = quoteAttr = JS_FALSE; -#endif - - while (pc < endpc) { - lastop = op; - op = saveop = (JSOp) *pc; - if (op >= JSOP_LIMIT) { - switch (op) { - case JSOP_GETPROP2: - saveop = JSOP_GETPROP; - break; - case JSOP_GETELEM2: - saveop = JSOP_GETELEM; - break; - default:; - } - } - cs = &js_CodeSpec[saveop]; - len = oplen = cs->length; - - if (cs->token) { - switch (cs->nuses) { - case 2: - rval = POP_STR(); - lval = POP_STR(); - sn = js_GetSrcNote(jp->script, pc); - if (sn && SN_TYPE(sn) == SRC_ASSIGNOP) { - /* Print only the right operand of the assignment-op. */ - todo = SprintPut(&ss->sprinter, rval, strlen(rval)); - } else if (!inXML) { - todo = Sprint(&ss->sprinter, "%s %s %s", - lval, cs->token, rval); - } else { - /* In XML, just concatenate the two operands. */ - JS_ASSERT(op == JSOP_ADD); - todo = Sprint(&ss->sprinter, "%s%s", lval, rval); - } - break; - - case 1: - rval = POP_STR(); - todo = Sprint(&ss->sprinter, "%s%s", cs->token, rval); - break; - - case 0: - todo = SprintPut(&ss->sprinter, cs->token, strlen(cs->token)); - break; - - default: - todo = -2; - break; - } - } else { - switch (op) { -#define BEGIN_LITOPX_CASE(OP) \ - case OP: \ - atomIndex = GET_ATOM_INDEX(pc); \ - do_##OP: \ - atom = js_GetAtom(cx, &jp->script->atomMap, atomIndex); - -#define END_LITOPX_CASE \ - break; - - case JSOP_NOP: - /* - * Check for a do-while loop, a for-loop with an empty - * initializer part, a labeled statement, a function - * definition, or try/finally. - */ - sn = js_GetSrcNote(jp->script, pc); - todo = -2; - switch (sn ? SN_TYPE(sn) : SRC_NULL) { -#if JS_HAS_DO_WHILE_LOOP - case SRC_WHILE: - js_printf(jp, "\tdo {\n"); - jp->indent += 4; - break; -#endif /* JS_HAS_DO_WHILE_LOOP */ - - case SRC_FOR: - rval = ""; - - do_forloop: - /* Skip the JSOP_NOP or JSOP_POP bytecode. */ - pc++; - - /* Get the cond, next, and loop-closing tail offsets. */ - cond = js_GetSrcNoteOffset(sn, 0); - next = js_GetSrcNoteOffset(sn, 1); - tail = js_GetSrcNoteOffset(sn, 2); - LOCAL_ASSERT(tail + GetJumpOffset(pc+tail, pc+tail) == 0); - - /* Print the keyword and the possibly empty init-part. */ - js_printf(jp, "\tfor (%s;", rval); - - if (pc[cond] == JSOP_IFEQ || pc[cond] == JSOP_IFEQX) { - /* Decompile the loop condition. */ - DECOMPILE_CODE(pc, cond); - js_printf(jp, " %s", POP_STR()); - } - - /* Need a semicolon whether or not there was a cond. */ - js_puts(jp, ";"); - - if (pc[next] != JSOP_GOTO && pc[next] != JSOP_GOTOX) { - /* Decompile the loop updater. */ - DECOMPILE_CODE(pc + next, tail - next - 1); - js_printf(jp, " %s", POP_STR()); - } - - /* Do the loop body. */ - js_printf(jp, ") {\n"); - jp->indent += 4; - oplen = (cond) ? js_CodeSpec[pc[cond]].length : 0; - DECOMPILE_CODE(pc + cond + oplen, next - cond - oplen); - jp->indent -= 4; - js_printf(jp, "\t}\n"); - - /* Set len so pc skips over the entire loop. */ - len = tail + js_CodeSpec[pc[tail]].length; - break; - - case SRC_LABEL: - atom = js_GetAtom(cx, &jp->script->atomMap, - (jsatomid) js_GetSrcNoteOffset(sn, 0)); - jp->indent -= 4; - rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0); - if (!rval) - return JS_FALSE; - RETRACT(&ss->sprinter, rval); - js_printf(jp, "\t%s:\n", rval); - jp->indent += 4; - break; - - case SRC_LABELBRACE: - atom = js_GetAtom(cx, &jp->script->atomMap, - (jsatomid) js_GetSrcNoteOffset(sn, 0)); - rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0); - if (!rval) - return JS_FALSE; - RETRACT(&ss->sprinter, rval); - js_printf(jp, "\t%s: {\n", rval); - jp->indent += 4; - break; - - case SRC_ENDBRACE: - jp->indent -= 4; - js_printf(jp, "\t}\n"); - break; - - case SRC_CATCH: - jp->indent -= 4; - sn = js_GetSrcNote(jp->script, pc); - pc += oplen; - js_printf(jp, "\t} catch ("); - - LOCAL_ASSERT(*pc == JSOP_NAME); - pc += js_CodeSpec[JSOP_NAME].length; - LOCAL_ASSERT(*pc == JSOP_PUSHOBJ); - pc += js_CodeSpec[JSOP_PUSHOBJ].length; - LOCAL_ASSERT(*pc == JSOP_NEWINIT); - pc += js_CodeSpec[JSOP_NEWINIT].length; - LOCAL_ASSERT(*pc == JSOP_EXCEPTION); - pc += js_CodeSpec[JSOP_EXCEPTION].length; - if (*pc == JSOP_LITOPX) { - atomIndex = GET_LITERAL_INDEX(pc); - pc += 1 + LITERAL_INDEX_LEN; - LOCAL_ASSERT(*pc == JSOP_INITCATCHVAR); - ++pc; - } else { - LOCAL_ASSERT(*pc == JSOP_INITCATCHVAR); - atomIndex = GET_ATOM_INDEX(pc); - pc += js_CodeSpec[JSOP_INITCATCHVAR].length; - } - atom = js_GetAtom(cx, &jp->script->atomMap, atomIndex); - rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0); - if (!rval) - return JS_FALSE; - RETRACT(&ss->sprinter, rval); - js_printf(jp, "%s", rval); - LOCAL_ASSERT(*pc == JSOP_ENTERWITH); - pc += js_CodeSpec[JSOP_ENTERWITH].length; - - len = js_GetSrcNoteOffset(sn, 0); - if (len) { - js_printf(jp, " if "); - DECOMPILE_CODE(pc, len); - js_printf(jp, "%s", POP_STR()); - pc += len; - LOCAL_ASSERT(*pc == JSOP_IFEQ || *pc == JSOP_IFEQX); - pc += js_CodeSpec[*pc].length; - } - - js_printf(jp, ") {\n"); - jp->indent += 4; - todo = Sprint(&ss->sprinter, catch_cookie); - len = 0; - break; - - case SRC_FUNCDEF: - atom = js_GetAtom(cx, &jp->script->atomMap, - (jsatomid) js_GetSrcNoteOffset(sn, 0)); - JS_ASSERT(ATOM_IS_OBJECT(atom)); - do_function: - obj = ATOM_TO_OBJECT(atom); - fun = (JSFunction *) JS_GetPrivate(cx, obj); - jp2 = js_NewPrinter(cx, JS_GetFunctionName(fun), - jp->indent, jp->pretty); - if (!jp2) - return JS_FALSE; - jp2->scope = jp->scope; - js_puts(jp2, "\n"); - ok = js_DecompileFunction(jp2, fun); - if (ok) { - js_puts(jp2, "\n"); - str = js_GetPrinterOutput(jp2); - if (str) - js_printf(jp, "%s\n", JS_GetStringBytes(str)); - else - ok = JS_FALSE; - } - js_DestroyPrinter(jp2); - if (!ok) - return JS_FALSE; - - break; - - default:; - } - case JSOP_RETRVAL: - break; - - case JSOP_GROUP: - /* Use last real op so PopOff adds parens if needed. */ - todo = PopOff(ss, lastop); - - /* Now add user-supplied parens only if PopOff did not. */ - cs = &js_CodeSpec[lastop]; - topcs = &js_CodeSpec[ss->opcodes[ss->top]]; - if (topcs->prec >= cs->prec) { - todo = Sprint(&ss->sprinter, "(%s)", - OFF2STR(&ss->sprinter, todo)); - } - break; - - case JSOP_PUSH: - case JSOP_PUSHOBJ: - case JSOP_BINDNAME: - do_JSOP_BINDNAME: - todo = Sprint(&ss->sprinter, ""); - break; - -#if JS_HAS_EXCEPTIONS - case JSOP_TRY: - js_printf(jp, "\ttry {\n"); - jp->indent += 4; - todo = -2; - break; - - { - static const char exception_cookie[] = "/*EXCEPTION*/"; - static const char retsub_pc_cookie[] = "/*RETSUB_PC*/"; - - case JSOP_FINALLY: - jp->indent -= 4; - js_printf(jp, "\t} finally {\n"); - jp->indent += 4; - - /* - * We must push an empty string placeholder for gosub's return - * address, popped by JSOP_RETSUB and counted by script->depth - * but not by ss->top (see JSOP_SETSP, below). - */ - todo = Sprint(&ss->sprinter, exception_cookie); - if (todo < 0 || !PushOff(ss, todo, op)) - return JS_FALSE; - todo = Sprint(&ss->sprinter, retsub_pc_cookie); - break; - - case JSOP_RETSUB: - rval = POP_STR(); - LOCAL_ASSERT(strcmp(rval, retsub_pc_cookie) == 0); - lval = POP_STR(); - LOCAL_ASSERT(strcmp(lval, exception_cookie) == 0); - todo = -2; - break; - } - - case JSOP_SWAP: - /* - * We don't generate this opcode currently, and previously we - * did not need to decompile it. If old, serialized bytecode - * uses it still, we should fall through and set todo = -2. - */ - /* FALL THROUGH */ - - case JSOP_GOSUB: - case JSOP_GOSUBX: - /* - * JSOP_GOSUB and GOSUBX have no effect on the decompiler's - * string stack because the next op in bytecode order finds - * the stack balanced by a JSOP_RETSUB executed elsewhere. - */ - todo = -2; - break; - - case JSOP_SETSP: - /* - * The compiler models operand stack depth and fixes the stack - * pointer on entry to a catch clause based on its depth model. - * The decompiler must match the code generator's model, which - * is why JSOP_FINALLY pushes a cookie that JSOP_RETSUB pops. - */ - LOCAL_ASSERT(ss->top >= (uintN) GET_ATOM_INDEX(pc)); - ss->top = (uintN) GET_ATOM_INDEX(pc); - break; - - case JSOP_EXCEPTION: - /* - * The only other JSOP_EXCEPTION case occurs as part of a code - * sequence that follows a SRC_CATCH-annotated JSOP_NOP. - */ - sn = js_GetSrcNote(jp->script, pc); - LOCAL_ASSERT(sn && SN_TYPE(sn) == SRC_HIDDEN); - todo = -2; - break; -#endif /* JS_HAS_EXCEPTIONS */ - - case JSOP_POP: - case JSOP_POPV: - sn = js_GetSrcNote(jp->script, pc); - switch (sn ? SN_TYPE(sn) : SRC_NULL) { - case SRC_FOR: - rval = POP_STR(); - todo = -2; - goto do_forloop; - - case SRC_PCDELTA: - /* Pop and save to avoid blowing stack depth budget. */ - lval = JS_strdup(cx, POP_STR()); - if (!lval) - return JS_FALSE; - - /* - * The offset tells distance to the end of the right-hand - * operand of the comma operator. - */ - done = pc + len; - pc += js_GetSrcNoteOffset(sn, 0); - len = 0; - - if (!Decompile(ss, done, pc - done)) { - JS_free(cx, (char *)lval); - return JS_FALSE; - } - - /* Pop Decompile result and print comma expression. */ - rval = POP_STR(); - todo = Sprint(&ss->sprinter, "%s, %s", lval, rval); - JS_free(cx, (char *)lval); - break; - - case SRC_HIDDEN: - /* Hide this pop, it's from a goto in a with or for/in. */ - todo = -2; - break; - - default: - rval = POP_STR(); - if (*rval != '\0') - js_printf(jp, "\t%s;\n", rval); - todo = -2; - break; - } - break; - - case JSOP_POP2: - (void) PopOff(ss, op); - (void) PopOff(ss, op); - todo = -2; - break; - - case JSOP_ENTERWITH: - JS_ASSERT(!js_GetSrcNote(jp->script, pc)); - rval = POP_STR(); - js_printf(jp, "\twith (%s) {\n", rval); - jp->indent += 4; - todo = Sprint(&ss->sprinter, with_cookie); - break; - - case JSOP_LEAVEWITH: - sn = js_GetSrcNote(jp->script, pc); - todo = -2; - if (sn && SN_TYPE(sn) == SRC_HIDDEN) - break; - rval = POP_STR(); - if (sn && SN_TYPE(sn) == SRC_CATCH) { - LOCAL_ASSERT(strcmp(rval, catch_cookie) == 0); - LOCAL_ASSERT((uintN) js_GetSrcNoteOffset(sn, 0) == ss->top); - break; - } - LOCAL_ASSERT(strcmp(rval, with_cookie) == 0); - jp->indent -= 4; - js_printf(jp, "\t}\n"); - break; - - case JSOP_SETRVAL: - case JSOP_RETURN: - lval = js_CodeSpec[JSOP_RETURN].name; - rval = POP_STR(); - if (*rval != '\0') - js_printf(jp, "\t%s %s;\n", lval, rval); - else - js_printf(jp, "\t%s;\n", lval); - todo = -2; - break; - -#if JS_HAS_EXCEPTIONS - case JSOP_THROWING: - todo = -2; - break; - - case JSOP_THROW: - sn = js_GetSrcNote(jp->script, pc); - todo = -2; - if (sn && SN_TYPE(sn) == SRC_HIDDEN) - break; - rval = POP_STR(); - js_printf(jp, "\t%s %s;\n", cs->name, rval); - break; -#endif /* JS_HAS_EXCEPTIONS */ - - case JSOP_GOTO: - case JSOP_GOTOX: - sn = js_GetSrcNote(jp->script, pc); - switch (sn ? SN_TYPE(sn) : SRC_NULL) { - case SRC_CONT2LABEL: - atom = js_GetAtom(cx, &jp->script->atomMap, - (jsatomid) js_GetSrcNoteOffset(sn, 0)); - rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0); - if (!rval) - return JS_FALSE; - RETRACT(&ss->sprinter, rval); - js_printf(jp, "\tcontinue %s;\n", rval); - break; - case SRC_CONTINUE: - js_printf(jp, "\tcontinue;\n"); - break; - case SRC_BREAK2LABEL: - atom = js_GetAtom(cx, &jp->script->atomMap, - (jsatomid) js_GetSrcNoteOffset(sn, 0)); - rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0); - if (!rval) - return JS_FALSE; - RETRACT(&ss->sprinter, rval); - js_printf(jp, "\tbreak %s;\n", rval); - break; - case SRC_HIDDEN: - break; - default: - js_printf(jp, "\tbreak;\n"); - break; - } - todo = -2; - break; - - case JSOP_IFEQ: - case JSOP_IFEQX: - len = GetJumpOffset(pc, pc); - sn = js_GetSrcNote(jp->script, pc); - - switch (sn ? SN_TYPE(sn) : SRC_NULL) { - case SRC_IF: - case SRC_IF_ELSE: - rval = POP_STR(); - js_printf(jp, "\tif (%s) {\n", rval); - jp->indent += 4; - if (SN_TYPE(sn) == SRC_IF) { - DECOMPILE_CODE(pc + oplen, len - oplen); - } else { - len = js_GetSrcNoteOffset(sn, 0); - DECOMPILE_CODE(pc + oplen, len - oplen); - jp->indent -= 4; - pc += len; - LOCAL_ASSERT(*pc == JSOP_GOTO || *pc == JSOP_GOTOX); - oplen = js_CodeSpec[*pc].length; - len = GetJumpOffset(pc, pc); - js_printf(jp, "\t} else {\n"); - jp->indent += 4; - DECOMPILE_CODE(pc + oplen, len - oplen); - } - jp->indent -= 4; - js_printf(jp, "\t}\n"); - todo = -2; - break; - - case SRC_WHILE: - rval = POP_STR(); - js_printf(jp, "\twhile (%s) {\n", rval); - jp->indent += 4; - tail = js_GetSrcNoteOffset(sn, 0); - DECOMPILE_CODE(pc + oplen, tail - oplen); - jp->indent -= 4; - js_printf(jp, "\t}\n"); - todo = -2; - break; - - case SRC_COND: - xval = JS_strdup(cx, POP_STR()); - if (!xval) - return JS_FALSE; - len = js_GetSrcNoteOffset(sn, 0); - DECOMPILE_CODE(pc + oplen, len - oplen); - lval = JS_strdup(cx, POP_STR()); - if (!lval) { - JS_free(cx, (void *)xval); - return JS_FALSE; - } - pc += len; - LOCAL_ASSERT(*pc == JSOP_GOTO || *pc == JSOP_GOTOX); - oplen = js_CodeSpec[*pc].length; - len = GetJumpOffset(pc, pc); - DECOMPILE_CODE(pc + oplen, len - oplen); - rval = POP_STR(); - todo = Sprint(&ss->sprinter, "%s ? %s : %s", - xval, lval, rval); - JS_free(cx, (void *)xval); - JS_free(cx, (void *)lval); - break; - - default: - break; - } - break; - - case JSOP_IFNE: - case JSOP_IFNEX: -#if JS_HAS_DO_WHILE_LOOP - /* Currently, this must be a do-while loop's upward branch. */ - jp->indent -= 4; - js_printf(jp, "\t} while (%s);\n", POP_STR()); - todo = -2; -#else - JS_ASSERT(0); -#endif /* JS_HAS_DO_WHILE_LOOP */ - break; - - case JSOP_OR: - case JSOP_ORX: - xval = "||"; - - do_logical_connective: - /* Top of stack is the first clause in a disjunction (||). */ - lval = JS_strdup(cx, POP_STR()); - if (!lval) - return JS_FALSE; - done = pc + GetJumpOffset(pc, pc); - pc += len; - len = PTRDIFF(done, pc, jsbytecode); - DECOMPILE_CODE(pc, len); - rval = POP_STR(); - if (jp->pretty && - jp->indent + 4 + strlen(lval) + 4 + strlen(rval) > 75) { - rval = JS_strdup(cx, rval); - if (!rval) { - tail = -1; - } else { - todo = Sprint(&ss->sprinter, "%s %s\n", lval, xval); - tail = Sprint(&ss->sprinter, "%*s%s", - jp->indent + 4, "", rval); - JS_free(cx, (char *)rval); - } - if (tail < 0) - todo = -1; - } else { - todo = Sprint(&ss->sprinter, "%s %s %s", lval, xval, rval); - } - JS_free(cx, (char *)lval); - break; - - case JSOP_AND: - case JSOP_ANDX: - xval = "&&"; - goto do_logical_connective; - - case JSOP_FORARG: - atom = GetSlotAtom(jp, js_GetArgument, GET_ARGNO(pc)); - LOCAL_ASSERT(atom); - goto do_fornameinloop; - - case JSOP_FORVAR: - atom = GetSlotAtom(jp, js_GetLocalVariable, GET_VARNO(pc)); - LOCAL_ASSERT(atom); - goto do_fornameinloop; - - case JSOP_FORNAME: - atom = GET_ATOM(cx, jp->script, pc); - - do_fornameinloop: - sn = js_GetSrcNote(jp->script, pc); - xval = NULL; - lval = ""; - goto do_forinloop; - - case JSOP_FORPROP: - xval = NULL; - atom = GET_ATOM(cx, jp->script, pc); - if (!ATOM_IS_IDENTIFIER(atom)) { - xval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), - (jschar)'\''); - if (!xval) - return JS_FALSE; - atom = NULL; - } - lval = POP_STR(); - sn = NULL; - - do_forinloop: - pc += oplen; - LOCAL_ASSERT(*pc == JSOP_IFEQ || *pc == JSOP_IFEQX); - oplen = js_CodeSpec[*pc].length; - len = GetJumpOffset(pc, pc); - sn2 = js_GetSrcNote(jp->script, pc); - tail = js_GetSrcNoteOffset(sn2, 0); - - do_forinbody: -#if JS_HAS_XML_SUPPORT - if (foreach) { - foreach = JS_FALSE; - js_printf(jp, "\tfor %s (%s%s", - js_each_str, VarPrefix(sn), lval); - } else -#endif - js_printf(jp, "\tfor (%s%s", VarPrefix(sn), lval); - if (atom) { - xval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0); - if (!xval) - return JS_FALSE; - RETRACT(&ss->sprinter, xval); - js_printf(jp, *lval ? ".%s" : "%s", xval); - } else if (xval && *xval) { - js_printf(jp, - (js_CodeSpec[lastop].format & JOF_XMLNAME) - ? ".%s" - : "[%s]", - xval); - } - rval = OFF2STR(&ss->sprinter, ss->offsets[ss->top-1]); - js_printf(jp, " in %s) {\n", rval); - jp->indent += 4; - DECOMPILE_CODE(pc + oplen, tail - oplen); - jp->indent -= 4; - js_printf(jp, "\t}\n"); - todo = -2; - break; - - case JSOP_FORELEM: - pc++; - LOCAL_ASSERT(*pc == JSOP_IFEQ || *pc == JSOP_IFEQX); - len = js_CodeSpec[*pc].length; - - /* - * Arrange for the JSOP_ENUMELEM case to set tail for use by - * do_forinbody: code that uses on it to find the loop-closing - * jump (whatever its format, normal or extended), in order to - * bound the recursively decompiled loop body. - */ - sn = js_GetSrcNote(jp->script, pc); - JS_ASSERT(!forelem_tail); - forelem_tail = pc + js_GetSrcNoteOffset(sn, 0); - - /* - * This gets a little wacky. Only the length of the for loop - * body PLUS the element-indexing expression is known here, so - * we pass the after-loop pc to the JSOP_ENUMELEM case, which - * is immediately below, to decompile that helper bytecode via - * the 'forelem_done' local. - * - * Since a for..in loop can't nest in the head of another for - * loop, we can use forelem_{tail,done} singletons to remember - * state from JSOP_FORELEM to JSOP_ENUMELEM, thence (via goto) - * to label do_forinbody. - */ - JS_ASSERT(!forelem_done); - forelem_done = pc + GetJumpOffset(pc, pc); - break; - - case JSOP_ENUMELEM: - /* - * The stack has the object under the (top) index expression. - * The "rval" property id is underneath those two on the stack. - * The for loop body net and gross lengths can now be adjusted - * to account for the length of the indexing expression that - * came after JSOP_FORELEM and before JSOP_ENUMELEM. - */ - atom = NULL; - xval = POP_STR(); - lval = POP_STR(); - rval = OFF2STR(&ss->sprinter, ss->offsets[ss->top-1]); - JS_ASSERT(forelem_tail > pc); - tail = forelem_tail - pc; - forelem_tail = NULL; - JS_ASSERT(forelem_done > pc); - len = forelem_done - pc; - forelem_done = NULL; - goto do_forinbody; - -#if JS_HAS_GETTER_SETTER - case JSOP_GETTER: - case JSOP_SETTER: - todo = -2; - break; -#endif - - case JSOP_DUP2: - rval = OFF2STR(&ss->sprinter, ss->offsets[ss->top-2]); - todo = SprintPut(&ss->sprinter, rval, strlen(rval)); - if (todo < 0 || !PushOff(ss, todo, ss->opcodes[ss->top-2])) - return JS_FALSE; - /* FALL THROUGH */ - - case JSOP_DUP: - rval = OFF2STR(&ss->sprinter, ss->offsets[ss->top-1]); - op = ss->opcodes[ss->top-1]; - todo = SprintPut(&ss->sprinter, rval, strlen(rval)); - break; - - case JSOP_SETARG: - atom = GetSlotAtom(jp, js_GetArgument, GET_ARGNO(pc)); - LOCAL_ASSERT(atom); - goto do_setname; - - case JSOP_SETVAR: - atom = GetSlotAtom(jp, js_GetLocalVariable, GET_VARNO(pc)); - LOCAL_ASSERT(atom); - goto do_setname; - - case JSOP_SETCONST: - case JSOP_SETNAME: - case JSOP_SETGVAR: - atomIndex = GET_ATOM_INDEX(pc); - - do_JSOP_SETCONST: - atom = js_GetAtom(cx, &jp->script->atomMap, atomIndex); - - do_setname: - lval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0); - if (!lval) - return JS_FALSE; - rval = POP_STR(); - if (op == JSOP_SETNAME) - (void) PopOff(ss, op); - - do_setlval: - sn = js_GetSrcNote(jp->script, pc - 1); - if (sn && SN_TYPE(sn) == SRC_ASSIGNOP) { - todo = Sprint(&ss->sprinter, "%s %s= %s", - lval, js_CodeSpec[lastop].token, rval); - } else { - sn = js_GetSrcNote(jp->script, pc); - todo = Sprint(&ss->sprinter, "%s%s = %s", - VarPrefix(sn), lval, rval); - } - break; - - case JSOP_NEW: - case JSOP_CALL: - case JSOP_EVAL: -#if JS_HAS_LVALUE_RETURN - case JSOP_SETCALL: -#endif - saveop = op; - op = JSOP_NOP; /* turn off parens */ - argc = GET_ARGC(pc); - argv = (char **) - JS_malloc(cx, (size_t)(argc + 1) * sizeof *argv); - if (!argv) - return JS_FALSE; - - ok = JS_TRUE; - for (i = argc; i > 0; i--) { - argv[i] = JS_strdup(cx, POP_STR()); - if (!argv[i]) { - ok = JS_FALSE; - break; - } - } - - /* Skip the JSOP_PUSHOBJ-created empty string. */ - LOCAL_ASSERT(ss->top >= 2); - (void) PopOff(ss, op); - - /* Get the callee's decompiled image in argv[0]. */ - argv[0] = JS_strdup(cx, POP_STR()); - if (!argv[i]) - ok = JS_FALSE; - - lval = "(", rval = ")"; - if (saveop == JSOP_NEW) { - todo = Sprint(&ss->sprinter, "%s %s%s", - js_new_str, argv[0], lval); - } else { - todo = Sprint(&ss->sprinter, "%s%s", - argv[0], lval); - } - if (todo < 0) - ok = JS_FALSE; - - for (i = 1; i <= argc; i++) { - if (!argv[i] || - Sprint(&ss->sprinter, "%s%s", - argv[i], (i < argc) ? ", " : "") < 0) { - ok = JS_FALSE; - break; - } - } - if (Sprint(&ss->sprinter, rval) < 0) - ok = JS_FALSE; - - for (i = 0; i <= argc; i++) { - if (argv[i]) - JS_free(cx, argv[i]); - } - JS_free(cx, argv); - if (!ok) - return JS_FALSE; - op = saveop; -#if JS_HAS_LVALUE_RETURN - if (op == JSOP_SETCALL) { - if (!PushOff(ss, todo, op)) - return JS_FALSE; - todo = Sprint(&ss->sprinter, ""); - } -#endif - break; - - case JSOP_DELNAME: - atom = GET_ATOM(cx, jp->script, pc); - lval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0); - if (!lval) - return JS_FALSE; - RETRACT(&ss->sprinter, lval); - todo = Sprint(&ss->sprinter, "%s %s", js_delete_str, lval); - break; - - case JSOP_DELPROP: - GET_ATOM_QUOTE_AND_FMT("%s %s[%s]", "%s %s.%s", rval); - lval = POP_STR(); - todo = Sprint(&ss->sprinter, fmt, js_delete_str, lval, rval); - break; - - case JSOP_DELELEM: - xval = POP_STR(); - lval = POP_STR(); - todo = Sprint(&ss->sprinter, - (js_CodeSpec[lastop].format & JOF_XMLNAME) - ? "%s %s.%s" - : "%s %s[%s]", - js_delete_str, lval, xval); - break; - -#if JS_HAS_XML_SUPPORT - case JSOP_DELDESC: - xval = POP_STR(); - lval = POP_STR(); - todo = Sprint(&ss->sprinter, "%s %s..%s", - js_delete_str, lval, xval); - break; -#endif - - case JSOP_TYPEOF: - case JSOP_VOID: - rval = POP_STR(); - todo = Sprint(&ss->sprinter, "%s %s", cs->name, rval); - break; - - case JSOP_INCARG: - case JSOP_DECARG: - atom = GetSlotAtom(jp, js_GetArgument, GET_ARGNO(pc)); - LOCAL_ASSERT(atom); - goto do_incatom; - - case JSOP_INCVAR: - case JSOP_DECVAR: - atom = GetSlotAtom(jp, js_GetLocalVariable, GET_VARNO(pc)); - LOCAL_ASSERT(atom); - goto do_incatom; - - case JSOP_INCNAME: - case JSOP_DECNAME: - case JSOP_INCGVAR: - case JSOP_DECGVAR: - atom = GET_ATOM(cx, jp->script, pc); - do_incatom: - lval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0); - if (!lval) - return JS_FALSE; - RETRACT(&ss->sprinter, lval); - todo = Sprint(&ss->sprinter, "%s%s", - js_incop_str[!(cs->format & JOF_INC)], lval); - break; - - case JSOP_INCPROP: - case JSOP_DECPROP: - GET_ATOM_QUOTE_AND_FMT("%s%s[%s]", "%s%s.%s", rval); - lval = POP_STR(); - todo = Sprint(&ss->sprinter, fmt, - js_incop_str[!(cs->format & JOF_INC)], - lval, rval); - break; - - case JSOP_INCELEM: - case JSOP_DECELEM: - xval = POP_STR(); - lval = POP_STR(); - if (*xval != '\0') { - todo = Sprint(&ss->sprinter, - (js_CodeSpec[lastop].format & JOF_XMLNAME) - ? "%s%s.%s" - : "%s%s[%s]", - js_incop_str[!(cs->format & JOF_INC)], - lval, xval); - } else { - todo = Sprint(&ss->sprinter, "%s%s", - js_incop_str[!(cs->format & JOF_INC)], lval); - } - break; - - case JSOP_ARGINC: - case JSOP_ARGDEC: - atom = GetSlotAtom(jp, js_GetArgument, GET_ARGNO(pc)); - LOCAL_ASSERT(atom); - goto do_atominc; - - case JSOP_VARINC: - case JSOP_VARDEC: - atom = GetSlotAtom(jp, js_GetLocalVariable, GET_VARNO(pc)); - LOCAL_ASSERT(atom); - goto do_atominc; - - case JSOP_NAMEINC: - case JSOP_NAMEDEC: - case JSOP_GVARINC: - case JSOP_GVARDEC: - atom = GET_ATOM(cx, jp->script, pc); - do_atominc: - lval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0); - if (!lval) - return JS_FALSE; - todo = STR2OFF(&ss->sprinter, lval); - SprintPut(&ss->sprinter, - js_incop_str[!(cs->format & JOF_INC)], - 2); - break; - - case JSOP_PROPINC: - case JSOP_PROPDEC: - GET_ATOM_QUOTE_AND_FMT("%s[%s]%s", "%s.%s%s", rval); - lval = POP_STR(); - todo = Sprint(&ss->sprinter, fmt, lval, rval, - js_incop_str[!(cs->format & JOF_INC)]); - break; - - case JSOP_ELEMINC: - case JSOP_ELEMDEC: - xval = POP_STR(); - lval = POP_STR(); - if (*xval != '\0') { - todo = Sprint(&ss->sprinter, - (js_CodeSpec[lastop].format & JOF_XMLNAME) - ? "%s.%s%s" - : "%s[%s]%s", - lval, xval, - js_incop_str[!(cs->format & JOF_INC)]); - } else { - todo = Sprint(&ss->sprinter, "%s%s", - lval, js_incop_str[!(cs->format & JOF_INC)]); - } - break; - - case JSOP_GETPROP2: - op = JSOP_GETPROP; - (void) PopOff(ss, lastop); - /* FALL THROUGH */ - - case JSOP_GETPROP: - atom = GET_ATOM(cx, jp->script, pc); - - do_getprop: - GET_QUOTE_AND_FMT("%s[%s]", "%s.%s", rval); - - do_getprop_lval: - lval = POP_STR(); - todo = Sprint(&ss->sprinter, fmt, lval, rval); - break; - -#if JS_HAS_XML_SUPPORT - BEGIN_LITOPX_CASE(JSOP_GETMETHOD) - sn = js_GetSrcNote(jp->script, pc); - if (sn && SN_TYPE(sn) == SRC_PCBASE) - goto do_getprop; - GET_QUOTE_AND_FMT("%s.function::[%s]", "%s.function::%s", rval); - goto do_getprop_lval; - - BEGIN_LITOPX_CASE(JSOP_SETMETHOD) - sn = js_GetSrcNote(jp->script, pc); - if (sn && SN_TYPE(sn) == SRC_PCBASE) - goto do_setprop; - GET_QUOTE_AND_FMT("%s.function::[%s] %s= %s", - "%s.function::%s %s= %s", - xval); - goto do_setprop_rval; -#endif - - case JSOP_SETPROP: - atom = GET_ATOM(cx, jp->script, pc); - - do_setprop: - GET_QUOTE_AND_FMT("%s[%s] %s= %s", "%s.%s %s= %s", xval); - - do_setprop_rval: - rval = POP_STR(); - lval = POP_STR(); - sn = js_GetSrcNote(jp->script, pc - 1); - todo = Sprint(&ss->sprinter, fmt, lval, xval, - (sn && SN_TYPE(sn) == SRC_ASSIGNOP) - ? js_CodeSpec[lastop].token - : "", - rval); - break; - - case JSOP_GETELEM2: - op = JSOP_GETELEM; - (void) PopOff(ss, lastop); - /* FALL THROUGH */ - - case JSOP_GETELEM: - op = JSOP_NOP; /* turn off parens */ - xval = POP_STR(); - op = JSOP_GETELEM; - lval = POP_STR(); - if (*xval == '\0') { - todo = Sprint(&ss->sprinter, "%s", lval); - } else { - todo = Sprint(&ss->sprinter, - (js_CodeSpec[lastop].format & JOF_XMLNAME) - ? "%s.%s" - : "%s[%s]", - lval, xval); - } - break; - - case JSOP_SETELEM: - op = JSOP_NOP; /* turn off parens */ - rval = POP_STR(); - xval = POP_STR(); - op = JSOP_SETELEM; - lval = POP_STR(); - if (*xval == '\0') - goto do_setlval; - sn = js_GetSrcNote(jp->script, pc - 1); - todo = Sprint(&ss->sprinter, - (js_CodeSpec[lastop].format & JOF_XMLNAME) - ? "%s.%s %s= %s" - : "%s[%s] %s= %s", - lval, xval, - (sn && SN_TYPE(sn) == SRC_ASSIGNOP) - ? js_CodeSpec[lastop].token - : "", - rval); - break; - - case JSOP_ARGSUB: - i = (jsint) GET_ATOM_INDEX(pc); - todo = Sprint(&ss->sprinter, "%s[%d]", - js_arguments_str, (int) i); - break; - - case JSOP_ARGCNT: - todo = Sprint(&ss->sprinter, "%s.%s", - js_arguments_str, js_length_str); - break; - - case JSOP_GETARG: - atom = GetSlotAtom(jp, js_GetArgument, GET_ARGNO(pc)); - LOCAL_ASSERT(atom); - goto do_name; - - case JSOP_GETVAR: - atom = GetSlotAtom(jp, js_GetLocalVariable, GET_VARNO(pc)); - LOCAL_ASSERT(atom); - goto do_name; - - case JSOP_NAME: - case JSOP_GETGVAR: - atom = GET_ATOM(cx, jp->script, pc); - do_name: - sn = js_GetSrcNote(jp->script, pc); - rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0); - if (!rval) - return JS_FALSE; - RETRACT(&ss->sprinter, rval); - todo = Sprint(&ss->sprinter, "%s%s", VarPrefix(sn), rval); - break; - - case JSOP_UINT16: - i = (jsint) GET_ATOM_INDEX(pc); - goto do_sprint_int; - - case JSOP_UINT24: - i = (jsint) GET_LITERAL_INDEX(pc); - do_sprint_int: - todo = Sprint(&ss->sprinter, "%u", (unsigned) i); - break; - - case JSOP_LITERAL: - atomIndex = GET_LITERAL_INDEX(pc); - goto do_JSOP_STRING; - - case JSOP_FINDNAME: - atomIndex = GET_LITERAL_INDEX(pc); - todo = Sprint(&ss->sprinter, ""); - if (todo < 0 || !PushOff(ss, todo, op)) - return JS_FALSE; - atom = js_GetAtom(cx, &jp->script->atomMap, atomIndex); - goto do_name; - - case JSOP_LITOPX: - atomIndex = GET_LITERAL_INDEX(pc); - op = pc[1 + LITERAL_INDEX_LEN]; - switch (op) { - case JSOP_ANONFUNOBJ: goto do_JSOP_ANONFUNOBJ; - case JSOP_BINDNAME: goto do_JSOP_BINDNAME; - case JSOP_CLOSURE: goto do_JSOP_CLOSURE; -#if JS_HAS_EXPORT_IMPORT - case JSOP_EXPORTNAME: goto do_JSOP_EXPORTNAME; -#endif -#if JS_HAS_XML_SUPPORT - case JSOP_GETMETHOD: goto do_JSOP_GETMETHOD; - case JSOP_SETMETHOD: goto do_JSOP_SETMETHOD; -#endif - case JSOP_NAMEDFUNOBJ: goto do_JSOP_NAMEDFUNOBJ; - case JSOP_NUMBER: goto do_JSOP_NUMBER; - case JSOP_OBJECT: goto do_JSOP_OBJECT; -#if JS_HAS_XML_SUPPORT - case JSOP_QNAMECONST: goto do_JSOP_QNAMECONST; - case JSOP_QNAMEPART: goto do_JSOP_QNAMEPART; -#endif - case JSOP_REGEXP: goto do_JSOP_REGEXP; - case JSOP_SETCONST: goto do_JSOP_SETCONST; - case JSOP_STRING: goto do_JSOP_STRING; -#if JS_HAS_XML_SUPPORT - case JSOP_XMLCDATA: goto do_JSOP_XMLCDATA; - case JSOP_XMLCOMMENT: goto do_JSOP_XMLCOMMENT; - case JSOP_XMLOBJECT: goto do_JSOP_XMLOBJECT; - case JSOP_XMLPI: goto do_JSOP_XMLPI; -#endif - default: JS_ASSERT(0); - } - /* NOTREACHED */ - break; - - BEGIN_LITOPX_CASE(JSOP_NUMBER) - val = ATOM_KEY(atom); - if (JSVAL_IS_INT(val)) { - long ival = (long)JSVAL_TO_INT(val); - todo = Sprint(&ss->sprinter, "%ld", ival); - } else { - char buf[DTOSTR_STANDARD_BUFFER_SIZE]; - char *numStr = JS_dtostr(buf, sizeof buf, DTOSTR_STANDARD, - 0, *JSVAL_TO_DOUBLE(val)); - if (!numStr) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - todo = Sprint(&ss->sprinter, numStr); - } - END_LITOPX_CASE - - BEGIN_LITOPX_CASE(JSOP_STRING) - rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), - inXML ? 0 : (jschar)'"'); - if (!rval) - return JS_FALSE; - todo = STR2OFF(&ss->sprinter, rval); - END_LITOPX_CASE - - case JSOP_OBJECT: - case JSOP_REGEXP: - case JSOP_ANONFUNOBJ: - case JSOP_NAMEDFUNOBJ: - atomIndex = GET_ATOM_INDEX(pc); - - do_JSOP_OBJECT: - do_JSOP_REGEXP: - do_JSOP_ANONFUNOBJ: - do_JSOP_NAMEDFUNOBJ: - atom = js_GetAtom(cx, &jp->script->atomMap, atomIndex); - if (op == JSOP_OBJECT || op == JSOP_REGEXP) { - if (!js_regexp_toString(cx, ATOM_TO_OBJECT(atom), 0, NULL, - &val)) { - return JS_FALSE; - } - } else { - if (!js_fun_toString(cx, ATOM_TO_OBJECT(atom), - (pc + len < endpc && - pc[len] == JSOP_GROUP) - ? JS_IN_GROUP_CONTEXT | - JS_DONT_PRETTY_PRINT - : JS_DONT_PRETTY_PRINT, - 0, NULL, &val)) { - return JS_FALSE; - } - } - str = JSVAL_TO_STRING(val); - todo = SprintPut(&ss->sprinter, JS_GetStringBytes(str), - JSSTRING_LENGTH(str)); - break; - -#if JS_HAS_SWITCH_STATEMENT - case JSOP_TABLESWITCH: - case JSOP_TABLESWITCHX: - { - jsbytecode *pc2; - ptrdiff_t jmplen, off, off2; - jsint j, n, low, high; - TableEntry *table, pivot; - - sn = js_GetSrcNote(jp->script, pc); - JS_ASSERT(sn && SN_TYPE(sn) == SRC_SWITCH); - len = js_GetSrcNoteOffset(sn, 0); - jmplen = (op == JSOP_TABLESWITCH) ? JUMP_OFFSET_LEN - : JUMPX_OFFSET_LEN; - pc2 = pc; - off = GetJumpOffset(pc, pc2); - pc2 += jmplen; - low = GET_JUMP_OFFSET(pc2); - pc2 += JUMP_OFFSET_LEN; - high = GET_JUMP_OFFSET(pc2); - pc2 += JUMP_OFFSET_LEN; - - n = high - low + 1; - if (n == 0) { - table = NULL; - j = 0; - } else { - table = (TableEntry *) - JS_malloc(cx, (size_t)n * sizeof *table); - if (!table) - return JS_FALSE; - for (i = j = 0; i < n; i++) { - table[j].label = NULL; - off2 = GetJumpOffset(pc, pc2); - if (off2) { - sn = js_GetSrcNote(jp->script, pc2); - if (sn) { - JS_ASSERT(SN_TYPE(sn) == SRC_LABEL); - table[j].label = - js_GetAtom(cx, &jp->script->atomMap, - (jsatomid) - js_GetSrcNoteOffset(sn, 0)); - } - table[j].key = INT_TO_JSVAL(low + i); - table[j].offset = off2; - table[j].order = j; - j++; - } - pc2 += jmplen; - } - js_HeapSort(table, (size_t) j, &pivot, sizeof(TableEntry), - CompareOffsets, NULL); - } - - ok = DecompileSwitch(ss, table, (uintN)j, pc, len, off, - JS_FALSE); - JS_free(cx, table); - if (!ok) - return ok; - todo = -2; - break; - } - - case JSOP_LOOKUPSWITCH: - case JSOP_LOOKUPSWITCHX: - { - jsbytecode *pc2; - ptrdiff_t jmplen, off, off2; - jsatomid npairs, k; - TableEntry *table; - - sn = js_GetSrcNote(jp->script, pc); - JS_ASSERT(sn && SN_TYPE(sn) == SRC_SWITCH); - len = js_GetSrcNoteOffset(sn, 0); - jmplen = (op == JSOP_LOOKUPSWITCH) ? JUMP_OFFSET_LEN - : JUMPX_OFFSET_LEN; - pc2 = pc; - off = GetJumpOffset(pc, pc2); - pc2 += jmplen; - npairs = GET_ATOM_INDEX(pc2); - pc2 += ATOM_INDEX_LEN; - - table = (TableEntry *) - JS_malloc(cx, (size_t)npairs * sizeof *table); - if (!table) - return JS_FALSE; - for (k = 0; k < npairs; k++) { - sn = js_GetSrcNote(jp->script, pc2); - if (sn) { - JS_ASSERT(SN_TYPE(sn) == SRC_LABEL); - table[k].label = - js_GetAtom(cx, &jp->script->atomMap, (jsatomid) - js_GetSrcNoteOffset(sn, 0)); - } else { - table[k].label = NULL; - } - atom = GET_ATOM(cx, jp->script, pc2); - pc2 += ATOM_INDEX_LEN; - off2 = GetJumpOffset(pc, pc2); - pc2 += jmplen; - table[k].key = ATOM_KEY(atom); - table[k].offset = off2; - } - - ok = DecompileSwitch(ss, table, (uintN)npairs, pc, len, off, - JS_FALSE); - JS_free(cx, table); - if (!ok) - return ok; - todo = -2; - break; - } - - case JSOP_CONDSWITCH: - { - jsbytecode *pc2; - ptrdiff_t off, off2, caseOff; - jsint ncases; - TableEntry *table; - - sn = js_GetSrcNote(jp->script, pc); - JS_ASSERT(sn && SN_TYPE(sn) == SRC_SWITCH); - len = js_GetSrcNoteOffset(sn, 0); - off = js_GetSrcNoteOffset(sn, 1); - - /* - * Count the cases using offsets from switch to first case, - * and case to case, stored in srcnote immediates. - */ - pc2 = pc; - off2 = off; - for (ncases = 0; off2 != 0; ncases++) { - pc2 += off2; - JS_ASSERT(*pc2 == JSOP_CASE || *pc2 == JSOP_DEFAULT || - *pc2 == JSOP_CASEX || *pc2 == JSOP_DEFAULTX); - if (*pc2 == JSOP_DEFAULT || *pc2 == JSOP_DEFAULTX) { - /* End of cases, but count default as a case. */ - off2 = 0; - } else { - sn = js_GetSrcNote(jp->script, pc2); - JS_ASSERT(sn && SN_TYPE(sn) == SRC_PCDELTA); - off2 = js_GetSrcNoteOffset(sn, 0); - } - } - - /* - * Allocate table and rescan the cases using their srcnotes, - * stashing each case's delta from switch top in table[i].key, - * and the distance to its statements in table[i].offset. - */ - table = (TableEntry *) - JS_malloc(cx, (size_t)ncases * sizeof *table); - if (!table) - return JS_FALSE; - pc2 = pc; - off2 = off; - for (i = 0; i < ncases; i++) { - pc2 += off2; - JS_ASSERT(*pc2 == JSOP_CASE || *pc2 == JSOP_DEFAULT || - *pc2 == JSOP_CASEX || *pc2 == JSOP_DEFAULTX); - caseOff = pc2 - pc; - table[i].key = INT_TO_JSVAL((jsint) caseOff); - table[i].offset = caseOff + GetJumpOffset(pc2, pc2); - if (*pc2 == JSOP_CASE || *pc2 == JSOP_CASEX) { - sn = js_GetSrcNote(jp->script, pc2); - JS_ASSERT(sn && SN_TYPE(sn) == SRC_PCDELTA); - off2 = js_GetSrcNoteOffset(sn, 0); - } - } - - /* - * Find offset of default code by fetching the default offset - * from the end of table. JSOP_CONDSWITCH always has a default - * case at the end. - */ - off = JSVAL_TO_INT(table[ncases-1].key); - pc2 = pc + off; - off += GetJumpOffset(pc2, pc2); - - ok = DecompileSwitch(ss, table, (uintN)ncases, pc, len, off, - JS_TRUE); - JS_free(cx, table); - if (!ok) - return ok; - todo = -2; - break; - } - - case JSOP_CASE: - case JSOP_CASEX: - { - lval = POP_STR(); - if (!lval) - return JS_FALSE; - js_printf(jp, "\tcase %s:\n", lval); - todo = -2; - break; - } - -#endif /* JS_HAS_SWITCH_STATEMENT */ - -#if !JS_BUG_FALLIBLE_EQOPS - case JSOP_NEW_EQ: - case JSOP_NEW_NE: - rval = POP_STR(); - lval = POP_STR(); - todo = Sprint(&ss->sprinter, "%s %c%s %s", - lval, - (op == JSOP_NEW_EQ) ? '=' : '!', -#if JS_HAS_TRIPLE_EQOPS - JS_VERSION_IS_ECMA(cx) ? "==" : -#endif - "=", - rval); - break; -#endif - -#if JS_HAS_LEXICAL_CLOSURE - BEGIN_LITOPX_CASE(JSOP_CLOSURE) - JS_ASSERT(ATOM_IS_OBJECT(atom)); - todo = -2; - goto do_function; - END_LITOPX_CASE -#endif - -#if JS_HAS_EXPORT_IMPORT - case JSOP_EXPORTALL: - js_printf(jp, "\texport *\n"); - todo = -2; - break; - - BEGIN_LITOPX_CASE(JSOP_EXPORTNAME) - rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0); - if (!rval) - return JS_FALSE; - RETRACT(&ss->sprinter, rval); - js_printf(jp, "\texport %s\n", rval); - todo = -2; - END_LITOPX_CASE - - case JSOP_IMPORTALL: - lval = POP_STR(); - js_printf(jp, "\timport %s.*\n", lval); - todo = -2; - break; - - case JSOP_IMPORTPROP: - do_importprop: - GET_ATOM_QUOTE_AND_FMT("\timport %s[%s]\n", "\timport %s.%s\n", - rval); - lval = POP_STR(); - js_printf(jp, fmt, lval, rval); - todo = -2; - break; - - case JSOP_IMPORTELEM: - xval = POP_STR(); - op = JSOP_GETELEM; - if (js_CodeSpec[lastop].format & JOF_XMLNAME) - goto do_importprop; - lval = POP_STR(); - js_printf(jp, "\timport %s[%s]\n", lval, xval); - todo = -2; - break; -#endif /* JS_HAS_EXPORT_IMPORT */ - - case JSOP_TRAP: - op = JS_GetTrapOpcode(cx, jp->script, pc); - if (op == JSOP_LIMIT) - return JS_FALSE; - *pc = op; - cs = &js_CodeSpec[op]; - len = cs->length; - DECOMPILE_CODE(pc, len); - *pc = JSOP_TRAP; - todo = -2; - break; - -#if JS_HAS_INITIALIZERS - case JSOP_NEWINIT: - LOCAL_ASSERT(ss->top >= 2); - (void) PopOff(ss, op); - lval = POP_STR(); -#if JS_HAS_SHARP_VARS - op = (JSOp)pc[len]; - if (op == JSOP_DEFSHARP) { - pc += len; - cs = &js_CodeSpec[op]; - len = cs->length; - i = (jsint) GET_ATOM_INDEX(pc); - todo = Sprint(&ss->sprinter, "#%u=%c", - (unsigned) i, - (*lval == 'O') ? '{' : '['); - } else -#endif /* JS_HAS_SHARP_VARS */ - { - todo = Sprint(&ss->sprinter, (*lval == 'O') ? "{" : "["); - } - break; - - case JSOP_ENDINIT: - rval = POP_STR(); - sn = js_GetSrcNote(jp->script, pc); - todo = Sprint(&ss->sprinter, "%s%s%c", - rval, - (sn && SN_TYPE(sn) == SRC_CONTINUE) ? ", " : "", - (*rval == '{') ? '}' : ']'); - break; - - case JSOP_INITPROP: - atom = GET_ATOM(cx, jp->script, pc); - xval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), - (jschar) - (ATOM_IS_IDENTIFIER(atom) ? 0 : '\'')); - if (!xval) - return JS_FALSE; - rval = POP_STR(); - lval = POP_STR(); - do_initprop: -#ifdef OLD_GETTER_SETTER - todo = Sprint(&ss->sprinter, "%s%s%s%s%s:%s", - lval, - (lval[1] != '\0') ? ", " : "", - xval, - (lastop == JSOP_GETTER || lastop == JSOP_SETTER) - ? " " : "", - (lastop == JSOP_GETTER) ? js_getter_str : - (lastop == JSOP_SETTER) ? js_setter_str : - "", - rval); -#else - if (lastop == JSOP_GETTER || lastop == JSOP_SETTER) { - rval += strlen(js_function_str) + 1; - todo = Sprint(&ss->sprinter, "%s%s%s %s%.*s", - lval, - (lval[1] != '\0') ? ", " : "", - (lastop == JSOP_GETTER) - ? js_get_str : js_set_str, - xval, - strlen(rval) - 1, - rval); - } else { - todo = Sprint(&ss->sprinter, "%s%s%s:%s", - lval, - (lval[1] != '\0') ? ", " : "", - xval, - rval); - } -#endif - break; - - case JSOP_INITELEM: - rval = POP_STR(); - xval = POP_STR(); - lval = POP_STR(); - sn = js_GetSrcNote(jp->script, pc); - if (sn && SN_TYPE(sn) == SRC_LABEL) - goto do_initprop; - todo = Sprint(&ss->sprinter, "%s%s%s", - lval, - (lval[1] != '\0' || *xval != '0') ? ", " : "", - rval); - break; - -#if JS_HAS_SHARP_VARS - case JSOP_DEFSHARP: - i = (jsint) GET_ATOM_INDEX(pc); - rval = POP_STR(); - todo = Sprint(&ss->sprinter, "#%u=%s", (unsigned) i, rval); - break; - - case JSOP_USESHARP: - i = (jsint) GET_ATOM_INDEX(pc); - todo = Sprint(&ss->sprinter, "#%u#", (unsigned) i); - break; -#endif /* JS_HAS_SHARP_VARS */ -#endif /* JS_HAS_INITIALIZERS */ - -#if JS_HAS_DEBUGGER_KEYWORD - case JSOP_DEBUGGER: - js_printf(jp, "\tdebugger;\n"); - todo = -2; - break; -#endif /* JS_HAS_DEBUGGER_KEYWORD */ - -#if JS_HAS_XML_SUPPORT - case JSOP_STARTXML: - case JSOP_STARTXMLEXPR: - inXML = op == JSOP_STARTXML; - todo = -2; - break; - - case JSOP_DEFXMLNS: - rval = POP_STR(); - js_printf(jp, "\t%s %s %s = %s;\n", - js_default_str, js_xml_str, js_namespace_str, rval); - todo = -2; - break; - - case JSOP_ANYNAME: - todo = SprintPut(&ss->sprinter, "*", 1); - break; - - BEGIN_LITOPX_CASE(JSOP_QNAMEPART) - goto do_name; - END_LITOPX_CASE - - BEGIN_LITOPX_CASE(JSOP_QNAMECONST) - rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0); - if (!rval) - return JS_FALSE; - RETRACT(&ss->sprinter, rval); - lval = POP_STR(); - todo = Sprint(&ss->sprinter, "%s::%s", lval, rval); - END_LITOPX_CASE - - case JSOP_QNAME: - rval = POP_STR(); - lval = POP_STR(); - todo = Sprint(&ss->sprinter, "%s::[%s]", lval, rval); - break; - - case JSOP_TOATTRNAME: - rval = POP_STR(); - todo = Sprint(&ss->sprinter, "@%s", rval); - break; - - case JSOP_TOATTRVAL: - todo = -2; - break; - - case JSOP_ADDATTRNAME: - rval = POP_STR(); - lval = POP_STR(); - todo = Sprint(&ss->sprinter, "%s %s", lval, rval); - /* This gets reset by all XML tag expressions. */ - quoteAttr = JS_TRUE; - break; - - case JSOP_ADDATTRVAL: - rval = POP_STR(); - lval = POP_STR(); - if (quoteAttr) - todo = Sprint(&ss->sprinter, "%s=\"%s\"", lval, rval); - else - todo = Sprint(&ss->sprinter, "%s=%s", lval, rval); - break; - - case JSOP_BINDXMLNAME: - /* Leave the name stacked and push a dummy string. */ - todo = Sprint(&ss->sprinter, ""); - break; - - case JSOP_SETXMLNAME: - /* Pop the r.h.s., the dummy string, and the name. */ - rval = POP_STR(); - (void) PopOff(ss, op); - lval = POP_STR(); - goto do_setlval; - - case JSOP_XMLELTEXPR: - case JSOP_XMLTAGEXPR: - todo = Sprint(&ss->sprinter, "{%s}", POP_STR()); - inXML = JS_TRUE; - /* If we're an attribute value, we shouldn't quote this. */ - quoteAttr = JS_FALSE; - break; - - case JSOP_TOXMLLIST: - todo = Sprint(&ss->sprinter, "<>%s", POP_STR()); - inXML = JS_FALSE; - break; - - case JSOP_FOREACH: - foreach = JS_TRUE; - todo = -2; - break; - - case JSOP_TOXML: - inXML = JS_FALSE; - /* FALL THROUGH */ - - case JSOP_XMLNAME: - case JSOP_FILTER: - /* Conversion and prefix ops do nothing in the decompiler. */ - todo = -2; - break; - - case JSOP_ENDFILTER: - rval = POP_STR(); - lval = POP_STR(); - todo = Sprint(&ss->sprinter, "%s.(%s)", lval, rval); - break; - - case JSOP_DESCENDANTS: - rval = POP_STR(); - lval = POP_STR(); - todo = Sprint(&ss->sprinter, "%s..%s", lval, rval); - break; - - BEGIN_LITOPX_CASE(JSOP_XMLOBJECT) - atom = GET_ATOM(cx, jp->script, pc); - todo = Sprint(&ss->sprinter, "", - ATOM_TO_OBJECT(atom)); - END_LITOPX_CASE - - BEGIN_LITOPX_CASE(JSOP_XMLCDATA) - todo = SprintPut(&ss->sprinter, "sprinter, ATOM_TO_STRING(atom), 0)) - return JS_FALSE; - SprintPut(&ss->sprinter, "]]>", 3); - END_LITOPX_CASE - - BEGIN_LITOPX_CASE(JSOP_XMLCOMMENT) - todo = SprintPut(&ss->sprinter, "", 3); - END_LITOPX_CASE - - BEGIN_LITOPX_CASE(JSOP_XMLPI) - rval = JS_strdup(cx, POP_STR()); - if (!rval) - return JS_FALSE; - todo = SprintPut(&ss->sprinter, "sprinter, ATOM_TO_STRING(atom), 0) && - SprintPut(&ss->sprinter, " ", 1) >= 0 && - SprintPut(&ss->sprinter, rval, strlen(rval)); - JS_free(cx, (char *)rval); - if (!ok) - return JS_FALSE; - SprintPut(&ss->sprinter, "?>", 2); - END_LITOPX_CASE - - case JSOP_GETFUNNS: - todo = SprintPut(&ss->sprinter, js_function_str, 8); - break; -#endif /* JS_HAS_XML_SUPPORT */ - - default: - todo = -2; - break; - -#undef BEGIN_LITOPX_CASE -#undef END_LITOPX_CASE - } - } - - if (todo < 0) { - /* -2 means "don't push", -1 means reported error. */ - if (todo == -1) - return JS_FALSE; - } else { - if (!PushOff(ss, todo, op)) - return JS_FALSE; - } - pc += len; - } - -/* - * Undefine local macros. - */ -#undef inXML -#undef DECOMPILE_CODE -#undef POP_STR -#undef LOCAL_ASSERT -#undef ATOM_IS_IDENTIFIER -#undef GET_QUOTE_AND_FMT -#undef GET_ATOM_QUOTE_AND_FMT - - return JS_TRUE; -} - - -JSBool -js_DecompileCode(JSPrinter *jp, JSScript *script, jsbytecode *pc, uintN len) -{ - SprintStack ss; - JSContext *cx; - void *mark, *space; - size_t offsetsz, opcodesz; - JSBool ok; - JSScript *oldscript; - char *last; - - /* Initialize a sprinter for use with the offset stack. */ - ss.printer = jp; - cx = jp->sprinter.context; - mark = JS_ARENA_MARK(&cx->tempPool); - INIT_SPRINTER(cx, &ss.sprinter, &cx->tempPool, PAREN_SLOP); - - /* Allocate the parallel (to avoid padding) offset and opcode stacks. */ - offsetsz = script->depth * sizeof(ptrdiff_t); - opcodesz = script->depth * sizeof(jsbytecode); - JS_ARENA_ALLOCATE(space, &cx->tempPool, offsetsz + opcodesz); - if (!space) { - ok = JS_FALSE; - goto out; - } - ss.offsets = (ptrdiff_t *) space; - ss.opcodes = (jsbytecode *) ((char *)space + offsetsz); - ss.top = 0; - - /* Call recursive subroutine to do the hard work. */ - oldscript = jp->script; - jp->script = script; - ok = Decompile(&ss, pc, len); - jp->script = oldscript; - - /* If the given code didn't empty the stack, do it now. */ - if (ss.top) { - do { - last = OFF2STR(&ss.sprinter, PopOff(&ss, JSOP_NOP)); - } while (ss.top); - js_printf(jp, "%s", last); - } - -out: - /* Free all temporary stuff allocated under this call. */ - JS_ARENA_RELEASE(&cx->tempPool, mark); - return ok; -} - -JSBool -js_DecompileScript(JSPrinter *jp, JSScript *script) -{ - return js_DecompileCode(jp, script, script->code, (uintN)script->length); -} - -static const char native_code_str[] = "\t[native code]\n"; - -JSBool -js_DecompileFunctionBody(JSPrinter *jp, JSFunction *fun) -{ - JSScript *script; - JSScope *scope, *save; - JSBool ok; - - if (!fun->interpreted) { - js_printf(jp, native_code_str); - return JS_TRUE; - } - script = fun->u.script; - scope = fun->object ? OBJ_SCOPE(fun->object) : NULL; - save = jp->scope; - jp->scope = scope; - ok = js_DecompileCode(jp, script, script->code, (uintN)script->length); - jp->scope = save; - return ok; -} - -JSBool -js_DecompileFunction(JSPrinter *jp, JSFunction *fun) -{ - JSContext *cx; - uintN i, nargs, indent; - void *mark; - JSAtom **params; - JSScope *scope, *oldscope; - JSScopeProperty *sprop; - JSBool ok; - - /* - * If pretty, conform to ECMA-262 Edition 3, 15.3.4.2, by decompiling a - * FunctionDeclaration. Otherwise, check the JSFUN_LAMBDA flag and force - * an expression by parenthesizing. - */ - if (jp->pretty) { - js_printf(jp, "\t"); - } else { - if (!jp->grouped && (fun->flags & JSFUN_LAMBDA)) - js_puts(jp, "("); - } - if (fun->flags & JSFUN_GETTER) - js_printf(jp, "%s ", js_getter_str); - else if (fun->flags & JSFUN_SETTER) - js_printf(jp, "%s ", js_setter_str); - - js_printf(jp, "%s ", js_function_str); - if (fun->atom && !QuoteString(&jp->sprinter, ATOM_TO_STRING(fun->atom), 0)) - return JS_FALSE; - js_puts(jp, "("); - - if (fun->interpreted && fun->object) { - size_t paramsize; - - /* - * Print the parameters. - * - * This code is complicated by the need to handle duplicate parameter - * names, as required by ECMA (bah!). A duplicate parameter is stored - * as another node with the same id (the parameter name) but different - * shortid (the argument index) along the property tree ancestor line - * starting at SCOPE_LAST_PROP(scope). Only the last duplicate param - * is mapped by the scope's hash table. - */ - cx = jp->sprinter.context; - nargs = fun->nargs; - mark = JS_ARENA_MARK(&cx->tempPool); - paramsize = nargs * sizeof(JSAtom *); - JS_ARENA_ALLOCATE_CAST(params, JSAtom **, &cx->tempPool, paramsize); - if (!params) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - memset(params, 0, paramsize); - scope = OBJ_SCOPE(fun->object); - for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) { - if (sprop->getter != js_GetArgument) - continue; - JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID); - JS_ASSERT((uint16) sprop->shortid < nargs); - JS_ASSERT(JSID_IS_ATOM(sprop->id)); - params[(uint16) sprop->shortid] = JSID_TO_ATOM(sprop->id); - } - for (i = 0; i < nargs; i++) { - if (i > 0) - js_puts(jp, ", "); - if (!QuoteString(&jp->sprinter, ATOM_TO_STRING(params[i]), 0)) - return JS_FALSE; - } - JS_ARENA_RELEASE(&cx->tempPool, mark); -#ifdef __GNUC__ - } else { - scope = NULL; -#endif - } - - js_printf(jp, ") {\n"); - indent = jp->indent; - jp->indent += 4; - if (fun->interpreted && fun->object) { - oldscope = jp->scope; - jp->scope = scope; - ok = js_DecompileScript(jp, fun->u.script); - jp->scope = oldscope; - if (!ok) { - jp->indent = indent; - return JS_FALSE; - } - } else { - js_printf(jp, native_code_str); - } - jp->indent -= 4; - js_printf(jp, "\t}"); - - if (!jp->pretty) { - if (!jp->grouped && (fun->flags & JSFUN_LAMBDA)) - js_puts(jp, ")"); - } - return JS_TRUE; -} - -JSString * -js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v, - JSString *fallback) -{ - JSStackFrame *fp, *down; - jsbytecode *pc, *begin, *end, *tmp; - jsval *sp, *base, *limit; - JSScript *script; - JSOp op; - const JSCodeSpec *cs; - uint32 format, mode, type; - intN depth; - jssrcnote *sn; - uintN len, off; - JSPrinter *jp; - JSString *name; - - for (fp = cx->fp; fp && !fp->script; fp = fp->down) - continue; - if (!fp) - goto do_fallback; - - /* Try to find sp's generating pc depth slots under it on the stack. */ - pc = fp->pc; - if (spindex == JSDVG_SEARCH_STACK) { - if (!pc) { - /* - * Current frame is native: look under it for a scripted call - * in which a decompilable bytecode string that generated the - * value as an actual argument might exist. - */ - JS_ASSERT(!fp->script && !(fp->fun && fp->fun->interpreted)); - down = fp->down; - if (!down) - goto do_fallback; - script = down->script; - base = fp->argv; - limit = base + fp->argc; - } else { - /* - * This should be a script activation, either a top-level - * script or a scripted function. But be paranoid about calls - * to js_DecompileValueGenerator from code that hasn't fully - * initialized a (default-all-zeroes) frame. - */ - script = fp->script; - base = fp->spbase; - limit = fp->sp; - } - - /* - * Pure paranoia about default-zeroed frames being active while - * js_DecompileValueGenerator is called. It can't hurt much now; - * error reporting performance is not an issue. - */ - if (!script || !base || !limit) - goto do_fallback; - - /* - * Try to find operand-generating pc depth slots below sp. - * - * In the native case, we know the arguments have generating pc's - * under them, on account of fp->down->script being non-null: all - * compiled scripts get depth slots for generating pc's allocated - * upon activation, at the top of js_Interpret. - * - * In the script or scripted function case, the same reasoning - * applies to fp rather than to fp->down. - */ - for (sp = base; sp < limit; sp++) { - if (*sp == v) { - depth = (intN)script->depth; - pc = (jsbytecode *) sp[-depth]; - break; - } - } - } else { - /* - * At this point, pc may or may not be null, i.e., we could be in - * a script activation, or we could be in a native frame that was - * called by another native function. Check pc and script. - */ - if (!pc) - goto do_fallback; - script = fp->script; - if (!script) - goto do_fallback; - - if (spindex != JSDVG_IGNORE_STACK) { - JS_ASSERT(spindex < 0); - depth = (intN)script->depth; -#if !JS_HAS_NO_SUCH_METHOD - JS_ASSERT(-depth <= spindex); -#endif - spindex -= depth; - - base = (jsval *) cx->stackPool.current->base; - limit = (jsval *) cx->stackPool.current->avail; - sp = fp->sp + spindex; - if (JS_UPTRDIFF(sp, base) < JS_UPTRDIFF(limit, base)) - pc = (jsbytecode *) *sp; - } - } - - /* - * Again, be paranoid, this time about possibly loading an invalid pc - * from sp[-(1+depth)]. - */ - if (JS_UPTRDIFF(pc, script->code) >= (jsuword)script->length) { - pc = fp->pc; - if (!pc) - goto do_fallback; - } - op = (JSOp) *pc; - if (op == JSOP_TRAP) - op = JS_GetTrapOpcode(cx, script, pc); - - /* XXX handle null as a special case, to avoid calling null "object" */ - if (op == JSOP_NULL) - return ATOM_TO_STRING(cx->runtime->atomState.nullAtom); - - cs = &js_CodeSpec[op]; - format = cs->format; - mode = (format & JOF_MODEMASK); - - /* NAME ops are self-contained, but others require left context. */ - if (mode == JOF_NAME) { - begin = pc; - } else { - sn = js_GetSrcNote(script, pc); - if (!sn || (SN_TYPE(sn) != SRC_PCBASE && SN_TYPE(sn) != SRC_PCDELTA)) { - if (cs->token) - return JS_NewStringCopyZ(cx, cs->token); - goto do_fallback; - } - begin = pc - js_GetSrcNoteOffset(sn, 0); - } - end = pc + cs->length; - len = PTRDIFF(end, begin, jsbytecode); - - if (format & (JOF_SET | JOF_DEL | JOF_INCDEC | JOF_IMPORT | JOF_FOR)) { - tmp = (jsbytecode *) JS_malloc(cx, len * sizeof(jsbytecode)); - if (!tmp) - return NULL; - memcpy(tmp, begin, len * sizeof(jsbytecode)); - if (mode == JOF_NAME) { - /* - * JOF_NAME does not imply JOF_CONST, so we must check for the - * QARG and QVAR format types and translate those to JSOP_GETARG - * or JSOP_GETVAR appropriately, instead of JSOP_NAME. - */ - type = format & JOF_TYPEMASK; - tmp[0] = (type == JOF_QARG) - ? JSOP_GETARG - : (type == JOF_QVAR) - ? JSOP_GETVAR - : JSOP_NAME; - } else { - /* - * We must replace the faulting pc's bytecode with a corresponding - * JSOP_GET* code. For JSOP_SET{PROP,ELEM}, we must use the "2nd" - * form of JSOP_GET{PROP,ELEM}, to throw away the assignment op's - * right-hand operand and decompile it as if it were a GET of its - * left-hand operand. - */ - off = len - cs->length; - JS_ASSERT(off == (uintN) PTRDIFF(pc, begin, jsbytecode)); - if (mode == JOF_PROP) { - tmp[off] = (format & JOF_SET) ? JSOP_GETPROP2 : JSOP_GETPROP; - } else if (mode == JOF_ELEM) { - tmp[off] = (format & JOF_SET) ? JSOP_GETELEM2 : JSOP_GETELEM; - } else { - /* - * A zero mode means precisely that op is uncategorized for our - * purposes, so we must write per-op special case code here. - */ - switch (op) { - case JSOP_ENUMELEM: - tmp[off] = JSOP_GETELEM; - break; -#if JS_HAS_LVALUE_RETURN - case JSOP_SETCALL: - tmp[off] = JSOP_CALL; - break; -#endif - default: - JS_ASSERT(0); - } - } - } - begin = tmp; - } else { - /* No need to revise script bytecode. */ - tmp = NULL; - } - - name = NULL; - jp = js_NewPrinter(cx, "js_DecompileValueGenerator", 0, JS_FALSE); - if (jp) { - if (fp->fun && fp->fun->object) { - JS_ASSERT(OBJ_IS_NATIVE(fp->fun->object)); - jp->scope = OBJ_SCOPE(fp->fun->object); - } - if (js_DecompileCode(jp, script, begin, len)) - name = js_GetPrinterOutput(jp); - js_DestroyPrinter(jp); - } - if (tmp) - JS_free(cx, tmp); - return name; - - do_fallback: - return fallback ? fallback : js_ValueToString(cx, v); -} diff --git a/lib/javascript/jsopcode.h b/lib/javascript/jsopcode.h deleted file mode 100644 index 2a488f6e..00000000 --- a/lib/javascript/jsopcode.h +++ /dev/null @@ -1,301 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jsopcode_h___ -#define jsopcode_h___ -/* - * JS bytecode definitions. - */ -#include -#include "jsprvtd.h" -#include "jspubtd.h" - -JS_BEGIN_EXTERN_C - -/* - * JS operation bytecodes. - */ -typedef enum JSOp { -#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \ - op = val, -#include "jsopcode.tbl" -#undef OPDEF - JSOP_LIMIT -} JSOp; - -/* - * JS bytecode formats. - */ -#define JOF_BYTE 0 /* single bytecode, no immediates */ -#define JOF_JUMP 1 /* signed 16-bit jump offset immediate */ -#define JOF_CONST 2 /* unsigned 16-bit constant pool index */ -#define JOF_UINT16 3 /* unsigned 16-bit immediate operand */ -#define JOF_TABLESWITCH 4 /* table switch */ -#define JOF_LOOKUPSWITCH 5 /* lookup switch */ -#define JOF_QARG 6 /* quickened get/set function argument ops */ -#define JOF_QVAR 7 /* quickened get/set local variable ops */ -#define JOF_INDEXCONST 8 /* arg or var index + constant pool index */ -#define JOF_JUMPX 9 /* signed 32-bit jump offset immediate */ -#define JOF_TABLESWITCHX 10 /* extended (32-bit offset) table switch */ -#define JOF_LOOKUPSWITCHX 11 /* extended (32-bit offset) lookup switch */ -#define JOF_UINT24 12 /* extended unsigned 24-bit literal (index) */ -#define JOF_LITOPX 13 /* JOF_UINT24 followed by op being extended, - where op if JOF_CONST has no unsigned 16- - bit immediate operand */ -#define JOF_TYPEMASK 0x000f /* mask for above immediate types */ -#define JOF_NAME 0x0010 /* name operation */ -#define JOF_PROP 0x0020 /* obj.prop operation */ -#define JOF_ELEM 0x0030 /* obj[index] operation */ -#define JOF_MODEMASK 0x0030 /* mask for above addressing modes */ -#define JOF_SET 0x0040 /* set (i.e., assignment) operation */ -#define JOF_DEL 0x0080 /* delete operation */ -#define JOF_DEC 0x0100 /* decrement (--, not ++) opcode */ -#define JOF_INC 0x0200 /* increment (++, not --) opcode */ -#define JOF_INCDEC 0x0300 /* increment or decrement opcode */ -#define JOF_POST 0x0400 /* postorder increment or decrement */ -#define JOF_IMPORT 0x0800 /* import property op */ -#define JOF_FOR 0x1000 /* for-in property op */ -#define JOF_ASSIGNING JOF_SET /* hint for JSClass.resolve, used for ops - that do simplex assignment */ -#define JOF_DETECTING 0x2000 /* object detection flag for JSNewResolveOp */ -#define JOF_BACKPATCH 0x4000 /* backpatch placeholder during codegen */ -#define JOF_LEFTASSOC 0x8000 /* left-associative operator */ -#define JOF_DECLARING 0x10000 /* var, const, or function declaration op */ -#define JOF_XMLNAME 0x20000 /* XML name: *, a::b, @a, @a::b, etc. */ - -#define JOF_TYPE_IS_EXTENDED_JUMP(t) \ - ((unsigned)((t) - JOF_JUMPX) <= (unsigned)(JOF_LOOKUPSWITCHX - JOF_JUMPX)) - -/* - * Immediate operand getters, setters, and bounds. - */ - -/* Short (2-byte signed offset) relative jump macros. */ -#define JUMP_OFFSET_LEN 2 -#define JUMP_OFFSET_HI(off) ((jsbytecode)((off) >> 8)) -#define JUMP_OFFSET_LO(off) ((jsbytecode)(off)) -#define GET_JUMP_OFFSET(pc) ((int16)(((pc)[1] << 8) | (pc)[2])) -#define SET_JUMP_OFFSET(pc,off) ((pc)[1] = JUMP_OFFSET_HI(off), \ - (pc)[2] = JUMP_OFFSET_LO(off)) -#define JUMP_OFFSET_MIN ((int16)0x8000) -#define JUMP_OFFSET_MAX ((int16)0x7fff) - -/* - * When a short jump won't hold a relative offset, its 2-byte immediate offset - * operand is an unsigned index of a span-dependency record, maintained until - * code generation finishes -- after which some (but we hope not nearly all) - * span-dependent jumps must be extended (see OptimizeSpanDeps in jsemit.c). - * - * If the span-dependency record index overflows SPANDEP_INDEX_MAX, the jump - * offset will contain SPANDEP_INDEX_HUGE, indicating that the record must be - * found (via binary search) by its "before span-dependency optimization" pc - * offset (from script main entry point). - */ -#define GET_SPANDEP_INDEX(pc) ((uint16)(((pc)[1] << 8) | (pc)[2])) -#define SET_SPANDEP_INDEX(pc,i) ((pc)[1] = JUMP_OFFSET_HI(i), \ - (pc)[2] = JUMP_OFFSET_LO(i)) -#define SPANDEP_INDEX_MAX ((uint16)0xfffe) -#define SPANDEP_INDEX_HUGE ((uint16)0xffff) - -/* Ultimately, if short jumps won't do, emit long (4-byte signed) offsets. */ -#define JUMPX_OFFSET_LEN 4 -#define JUMPX_OFFSET_B3(off) ((jsbytecode)((off) >> 24)) -#define JUMPX_OFFSET_B2(off) ((jsbytecode)((off) >> 16)) -#define JUMPX_OFFSET_B1(off) ((jsbytecode)((off) >> 8)) -#define JUMPX_OFFSET_B0(off) ((jsbytecode)(off)) -#define GET_JUMPX_OFFSET(pc) ((int32)(((pc)[1] << 24) | ((pc)[2] << 16) \ - | ((pc)[3] << 8) | (pc)[4])) -#define SET_JUMPX_OFFSET(pc,off)((pc)[1] = JUMPX_OFFSET_B3(off), \ - (pc)[2] = JUMPX_OFFSET_B2(off), \ - (pc)[3] = JUMPX_OFFSET_B1(off), \ - (pc)[4] = JUMPX_OFFSET_B0(off)) -#define JUMPX_OFFSET_MIN ((int32)0x80000000) -#define JUMPX_OFFSET_MAX ((int32)0x7fffffff) - -/* - * A literal is indexed by a per-script atom map. Most scripts have relatively - * few literals, so the standard JOF_CONST format specifies a fixed 16 bits of - * immediate operand index. A script with more than 64K literals must push all - * high-indexed literals on the stack using JSOP_LITERAL, then use JOF_ELEM ops - * instead of JOF_PROP, etc. - */ -#define ATOM_INDEX_LEN 2 -#define ATOM_INDEX_HI(i) ((jsbytecode)((i) >> 8)) -#define ATOM_INDEX_LO(i) ((jsbytecode)(i)) -#define GET_ATOM_INDEX(pc) ((jsatomid)(((pc)[1] << 8) | (pc)[2])) -#define SET_ATOM_INDEX(pc,i) ((pc)[1] = ATOM_INDEX_HI(i), \ - (pc)[2] = ATOM_INDEX_LO(i)) -#define GET_ATOM(cx,script,pc) js_GetAtom((cx), &(script)->atomMap, \ - GET_ATOM_INDEX(pc)) - -/* A full atom index for JSOP_LITERAL uses 24 bits of immediate operand. */ -#define LITERAL_INDEX_LEN 3 -#define LITERAL_INDEX_HI(i) ((jsbytecode)((i) >> 16)) -#define LITERAL_INDEX_MID(i) ((jsbytecode)((i) >> 8)) -#define LITERAL_INDEX_LO(i) ((jsbytecode)(i)) -#define GET_LITERAL_INDEX(pc) ((jsatomid)(((pc)[1] << 16) | \ - ((pc)[2] << 8) | \ - (pc)[3])) -#define SET_LITERAL_INDEX(pc,i) ((pc)[1] = LITERAL_INDEX_HI(i), \ - (pc)[2] = LITERAL_INDEX_MID(i), \ - (pc)[3] = LITERAL_INDEX_LO(i)) - -/* Atom index limit is determined by SN_3BYTE_OFFSET_FLAG, see jsemit.h. */ -#define ATOM_INDEX_LIMIT_LOG2 23 -#define ATOM_INDEX_LIMIT ((uint32)1 << ATOM_INDEX_LIMIT_LOG2) - -/* Actual argument count operand format helpers. */ -#define ARGC_HI(argc) ((jsbytecode)((argc) >> 8)) -#define ARGC_LO(argc) ((jsbytecode)(argc)) -#define GET_ARGC(pc) ((uintN)(((pc)[1] << 8) | (pc)[2])) -#define ARGC_LIMIT ((uint32)1 << 16) - -/* Synonyms for quick JOF_QARG and JOF_QVAR bytecodes. */ -#define GET_ARGNO(pc) GET_ARGC(pc) -#define SET_ARGNO(pc,argno) SET_JUMP_OFFSET(pc,argno) -#define ARGNO_LEN JUMP_OFFSET_LEN -#define GET_VARNO(pc) GET_ARGC(pc) -#define SET_VARNO(pc,varno) SET_JUMP_OFFSET(pc,varno) -#define VARNO_LEN JUMP_OFFSET_LEN - -struct JSCodeSpec { - const char *name; /* JS bytecode name */ - const char *token; /* JS source literal or null */ - int8 length; /* length including opcode byte */ - int8 nuses; /* arity, -1 if variadic */ - int8 ndefs; /* number of stack results */ - uint8 prec; /* operator precedence */ - uint32 format; /* immediate operand format */ -}; - -extern const char js_const_str[]; -extern const char js_var_str[]; -extern const char js_function_str[]; -extern const char js_in_str[]; -extern const char js_instanceof_str[]; -extern const char js_new_str[]; -extern const char js_delete_str[]; -extern const char js_typeof_str[]; -extern const char js_void_str[]; -extern const char js_null_str[]; -extern const char js_this_str[]; -extern const char js_false_str[]; -extern const char js_true_str[]; -extern const char js_default_str[]; -extern const JSCodeSpec js_CodeSpec[]; -extern uintN js_NumCodeSpecs; -extern const jschar js_EscapeMap[]; - -/* - * Return a GC'ed string containing the chars in str, with any non-printing - * chars or quotes (' or " as specified by the quote argument) escaped, and - * with the quote character at the beginning and end of the result string. - */ -extern JSString * -js_QuoteString(JSContext *cx, JSString *str, jschar quote); - -/* - * JSPrinter operations, for printf style message formatting. The return - * value from js_GetPrinterOutput() is the printer's cumulative output, in - * a GC'ed string. - */ -extern JSPrinter * -js_NewPrinter(JSContext *cx, const char *name, uintN indent, JSBool pretty); - -extern void -js_DestroyPrinter(JSPrinter *jp); - -extern JSString * -js_GetPrinterOutput(JSPrinter *jp); - -extern int -js_printf(JSPrinter *jp, const char *format, ...); - -extern JSBool -js_puts(JSPrinter *jp, const char *s); - -#ifdef DEBUG -/* - * Disassemblers, for debugging only. - */ -#include - -extern JS_FRIEND_API(JSBool) -js_Disassemble(JSContext *cx, JSScript *script, JSBool lines, FILE *fp); - -extern JS_FRIEND_API(uintN) -js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, uintN loc, - JSBool lines, FILE *fp); -#endif /* DEBUG */ - -/* - * Decompilers, for script, function, and expression pretty-printing. - */ -extern JSBool -js_DecompileCode(JSPrinter *jp, JSScript *script, jsbytecode *pc, uintN len); - -extern JSBool -js_DecompileScript(JSPrinter *jp, JSScript *script); - -extern JSBool -js_DecompileFunctionBody(JSPrinter *jp, JSFunction *fun); - -extern JSBool -js_DecompileFunction(JSPrinter *jp, JSFunction *fun); - -/* - * Find the source expression that resulted in v, and return a new string - * containing it. Fall back on v's string conversion (fallback) if we can't - * find the bytecode that generated and pushed v on the operand stack. - * - * Search the current stack frame if spindex is JSDVG_SEARCH_STACK. Don't - * look for v on the stack if spindex is JSDVG_IGNORE_STACK. Otherwise, - * spindex is the negative index of v, measured from cx->fp->sp, or from a - * lower frame's sp if cx->fp is native. - */ -extern JSString * -js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v, - JSString *fallback); - -#define JSDVG_IGNORE_STACK 0 -#define JSDVG_SEARCH_STACK 1 - -JS_END_EXTERN_C - -#endif /* jsopcode_h___ */ diff --git a/lib/javascript/jsopcode.tbl b/lib/javascript/jsopcode.tbl deleted file mode 100644 index 6e649413..00000000 --- a/lib/javascript/jsopcode.tbl +++ /dev/null @@ -1,396 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JavaScript operation bytecodes. If you need to allocate a bytecode, look - * for a name of the form JSOP_UNUSED* and claim it. Otherwise, always add at - * the end of the table. - * - * Includers must define an OPDEF macro of the following form: - * - * #define OPDEF(op,val,name,image,length,nuses,ndefs,prec,format) ... - * - * Selected arguments can be expanded in initializers. The op argument is - * expanded followed by comma in the JSOp enum (jsopcode.h), e.g. The value - * field must be dense for now, because jsopcode.c uses an OPDEF() expansion - * inside the js_CodeSpec[] initializer. - * - * Field Description - * op Bytecode name, which is the JSOp enumerator name - * value Bytecode value, which is the JSOp enumerator value - * name C string containing name for disassembler - * image C string containing "image" for pretty-printer, null if ugly - * length Number of bytes including any immediate operands - * nuses Number of stack slots consumed by bytecode, -1 if variadic - * ndefs Number of stack slots produced by bytecode - * prec Operator precedence, zero if not an operator - * format Bytecode plus immediate operand encoding format - * - * This file is best viewed with 128 columns: -12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678 - */ - -/* legend: op val name image len use def prec format */ - -/* Longstanding JavaScript bytecodes. */ -OPDEF(JSOP_NOP, 0, "nop", NULL, 1, 0, 0, 0, JOF_BYTE) -OPDEF(JSOP_PUSH, 1, "push", NULL, 1, 0, 1, 0, JOF_BYTE) -OPDEF(JSOP_POPV, 2, "popv", NULL, 1, 1, 0, 0, JOF_BYTE) -OPDEF(JSOP_ENTERWITH, 3, "enterwith", NULL, 1, 1, 1, 0, JOF_BYTE) -OPDEF(JSOP_LEAVEWITH, 4, "leavewith", NULL, 1, 1, 0, 0, JOF_BYTE) -OPDEF(JSOP_RETURN, 5, "return", NULL, 1, 1, 0, 0, JOF_BYTE) -OPDEF(JSOP_GOTO, 6, "goto", NULL, 3, 0, 0, 0, JOF_JUMP) -OPDEF(JSOP_IFEQ, 7, "ifeq", NULL, 3, 1, 0, 0, JOF_JUMP|JOF_DETECTING) -OPDEF(JSOP_IFNE, 8, "ifne", NULL, 3, 1, 0, 0, JOF_JUMP) - -/* Get the arguments object for the current, lightweight function activation. */ -OPDEF(JSOP_ARGUMENTS, 9, js_arguments_str, js_arguments_str, 1, 0, 1, 12, JOF_BYTE) - -/* ECMA-compliant for-in loop with argument or local variable loop control. */ -OPDEF(JSOP_FORARG, 10, "forarg", NULL, 3, 0, 1, 0, JOF_QARG|JOF_NAME|JOF_FOR) -OPDEF(JSOP_FORVAR, 11, "forvar", NULL, 3, 0, 1, 0, JOF_QVAR|JOF_NAME|JOF_FOR) - -/* More longstanding bytecodes. */ -OPDEF(JSOP_DUP, 12, "dup", NULL, 1, 1, 2, 0, JOF_BYTE) -OPDEF(JSOP_DUP2, 13, "dup2", NULL, 1, 2, 4, 0, JOF_BYTE) -OPDEF(JSOP_SETCONST, 14, "setconst", NULL, 3, 1, 1, 1, JOF_CONST|JOF_NAME|JOF_SET|JOF_ASSIGNING) -OPDEF(JSOP_BITOR, 15, "bitor", "|", 1, 2, 1, 2, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_BITXOR, 16, "bitxor", "^", 1, 2, 1, 3, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_BITAND, 17, "bitand", "&", 1, 2, 1, 4, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_EQ, 18, "eq", "==", 1, 2, 1, 5, JOF_BYTE|JOF_LEFTASSOC|JOF_DETECTING) -OPDEF(JSOP_NE, 19, "ne", "!=", 1, 2, 1, 5, JOF_BYTE|JOF_LEFTASSOC|JOF_DETECTING) -OPDEF(JSOP_LT, 20, "lt", "<", 1, 2, 1, 6, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_LE, 21, "le", "<=", 1, 2, 1, 6, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_GT, 22, "gt", ">", 1, 2, 1, 6, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_GE, 23, "ge", ">=", 1, 2, 1, 6, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_LSH, 24, "lsh", "<<", 1, 2, 1, 7, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_RSH, 25, "rsh", ">>", 1, 2, 1, 7, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_URSH, 26, "ursh", ">>>", 1, 2, 1, 7, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_ADD, 27, "add", "+", 1, 2, 1, 8, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_SUB, 28, "sub", "-", 1, 2, 1, 8, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_MUL, 29, "mul", "*", 1, 2, 1, 9, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_DIV, 30, "div", "/", 1, 2, 1, 9, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_MOD, 31, "mod", "%", 1, 2, 1, 9, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_NOT, 32, "not", "!", 1, 1, 1, 10, JOF_BYTE|JOF_DETECTING) -OPDEF(JSOP_BITNOT, 33, "bitnot", "~", 1, 1, 1, 10, JOF_BYTE) -OPDEF(JSOP_NEG, 34, "neg", "-", 1, 1, 1, 10, JOF_BYTE) -OPDEF(JSOP_NEW, 35, js_new_str, NULL, 3, -1, 1, 10, JOF_UINT16) -OPDEF(JSOP_DELNAME, 36, "delname", NULL, 3, 0, 1, 10, JOF_CONST|JOF_NAME|JOF_DEL) -OPDEF(JSOP_DELPROP, 37, "delprop", NULL, 3, 1, 1, 10, JOF_CONST|JOF_PROP|JOF_DEL) -OPDEF(JSOP_DELELEM, 38, "delelem", NULL, 1, 2, 1, 10, JOF_BYTE |JOF_ELEM|JOF_DEL) -OPDEF(JSOP_TYPEOF, 39, js_typeof_str,NULL, 1, 1, 1, 10, JOF_BYTE|JOF_DETECTING) -OPDEF(JSOP_VOID, 40, js_void_str, NULL, 1, 1, 1, 10, JOF_BYTE) -OPDEF(JSOP_INCNAME, 41, "incname", NULL, 3, 0, 1, 10, JOF_CONST|JOF_NAME|JOF_INC) -OPDEF(JSOP_INCPROP, 42, "incprop", NULL, 3, 1, 1, 10, JOF_CONST|JOF_PROP|JOF_INC) -OPDEF(JSOP_INCELEM, 43, "incelem", NULL, 1, 2, 1, 10, JOF_BYTE |JOF_ELEM|JOF_INC) -OPDEF(JSOP_DECNAME, 44, "decname", NULL, 3, 0, 1, 10, JOF_CONST|JOF_NAME|JOF_DEC) -OPDEF(JSOP_DECPROP, 45, "decprop", NULL, 3, 1, 1, 10, JOF_CONST|JOF_PROP|JOF_DEC) -OPDEF(JSOP_DECELEM, 46, "decelem", NULL, 1, 2, 1, 10, JOF_BYTE |JOF_ELEM|JOF_DEC) -OPDEF(JSOP_NAMEINC, 47, "nameinc", NULL, 3, 0, 1, 10, JOF_CONST|JOF_NAME|JOF_INC|JOF_POST) -OPDEF(JSOP_PROPINC, 48, "propinc", NULL, 3, 1, 1, 10, JOF_CONST|JOF_PROP|JOF_INC|JOF_POST) -OPDEF(JSOP_ELEMINC, 49, "eleminc", NULL, 1, 2, 1, 10, JOF_BYTE |JOF_ELEM|JOF_INC|JOF_POST) -OPDEF(JSOP_NAMEDEC, 50, "namedec", NULL, 3, 0, 1, 10, JOF_CONST|JOF_NAME|JOF_DEC|JOF_POST) -OPDEF(JSOP_PROPDEC, 51, "propdec", NULL, 3, 1, 1, 10, JOF_CONST|JOF_PROP|JOF_DEC|JOF_POST) -OPDEF(JSOP_ELEMDEC, 52, "elemdec", NULL, 1, 2, 1, 10, JOF_BYTE |JOF_ELEM|JOF_DEC|JOF_POST) -OPDEF(JSOP_GETPROP, 53, "getprop", NULL, 3, 1, 1, 11, JOF_CONST|JOF_PROP) -OPDEF(JSOP_SETPROP, 54, "setprop", NULL, 3, 2, 1, 1, JOF_CONST|JOF_PROP|JOF_SET|JOF_ASSIGNING|JOF_DETECTING) -OPDEF(JSOP_GETELEM, 55, "getelem", NULL, 1, 2, 1, 11, JOF_BYTE |JOF_ELEM|JOF_LEFTASSOC) -OPDEF(JSOP_SETELEM, 56, "setelem", NULL, 1, 3, 1, 1, JOF_BYTE |JOF_ELEM|JOF_SET|JOF_ASSIGNING|JOF_DETECTING) -OPDEF(JSOP_PUSHOBJ, 57, "pushobj", NULL, 1, 0, 1, 0, JOF_BYTE) -OPDEF(JSOP_CALL, 58, "call", NULL, 3, -1, 1, 11, JOF_UINT16) -OPDEF(JSOP_NAME, 59, "name", NULL, 3, 0, 1, 12, JOF_CONST|JOF_NAME) -OPDEF(JSOP_NUMBER, 60, "number", NULL, 3, 0, 1, 12, JOF_CONST) -OPDEF(JSOP_STRING, 61, "string", NULL, 3, 0, 1, 12, JOF_CONST) -OPDEF(JSOP_ZERO, 62, "zero", "0", 1, 0, 1, 12, JOF_BYTE) -OPDEF(JSOP_ONE, 63, "one", "1", 1, 0, 1, 12, JOF_BYTE) -OPDEF(JSOP_NULL, 64, js_null_str, js_null_str, 1, 0, 1, 12, JOF_BYTE) -OPDEF(JSOP_THIS, 65, js_this_str, js_this_str, 1, 0, 1, 12, JOF_BYTE) -OPDEF(JSOP_FALSE, 66, js_false_str, js_false_str, 1, 0, 1, 12, JOF_BYTE) -OPDEF(JSOP_TRUE, 67, js_true_str, js_true_str, 1, 0, 1, 12, JOF_BYTE) -OPDEF(JSOP_OR, 68, "or", NULL, 3, 1, 0, 0, JOF_JUMP|JOF_DETECTING) -OPDEF(JSOP_AND, 69, "and", NULL, 3, 1, 0, 0, JOF_JUMP|JOF_DETECTING) - -/* The switch bytecodes have variable length. */ -OPDEF(JSOP_TABLESWITCH, 70, "tableswitch", NULL, -1, 1, 0, 0, JOF_TABLESWITCH|JOF_DETECTING) -OPDEF(JSOP_LOOKUPSWITCH, 71, "lookupswitch", NULL, -1, 1, 0, 0, JOF_LOOKUPSWITCH|JOF_DETECTING) - -/* New, infallible/transitive identity ops. */ -OPDEF(JSOP_NEW_EQ, 72, "eq", NULL, 1, 2, 1, 5, JOF_BYTE|JOF_DETECTING) -OPDEF(JSOP_NEW_NE, 73, "ne", NULL, 1, 2, 1, 5, JOF_BYTE|JOF_DETECTING) - -/* Lexical closure constructor. */ -OPDEF(JSOP_CLOSURE, 74, "closure", NULL, 3, 0, 0, 0, JOF_CONST) - -/* Export and import ops. */ -OPDEF(JSOP_EXPORTALL, 75, "exportall", NULL, 1, 0, 0, 0, JOF_BYTE) -OPDEF(JSOP_EXPORTNAME,76, "exportname", NULL, 3, 0, 0, 0, JOF_CONST|JOF_NAME) -OPDEF(JSOP_IMPORTALL, 77, "importall", NULL, 1, 1, 0, 0, JOF_BYTE) -OPDEF(JSOP_IMPORTPROP,78, "importprop", NULL, 3, 1, 0, 0, JOF_CONST|JOF_PROP|JOF_IMPORT) -OPDEF(JSOP_IMPORTELEM,79, "importelem", NULL, 1, 2, 0, 0, JOF_BYTE |JOF_ELEM|JOF_IMPORT) - -/* Push object literal. */ -OPDEF(JSOP_OBJECT, 80, "object", NULL, 3, 0, 1, 12, JOF_CONST) - -/* Pop value and discard it. */ -OPDEF(JSOP_POP, 81, "pop", NULL, 1, 1, 0, 0, JOF_BYTE) - -/* Convert value to number, for unary +. */ -OPDEF(JSOP_POS, 82, "pos", "+", 1, 1, 1, 10, JOF_BYTE) - -/* Trap into debugger for breakpoint, etc. */ -OPDEF(JSOP_TRAP, 83, "trap", NULL, 1, 0, 0, 0, JOF_BYTE) - -/* Fast get/set ops for function arguments and local variables. */ -OPDEF(JSOP_GETARG, 84, "getarg", NULL, 3, 0, 1, 12, JOF_QARG |JOF_NAME) -OPDEF(JSOP_SETARG, 85, "setarg", NULL, 3, 1, 1, 1, JOF_QARG |JOF_NAME|JOF_SET|JOF_ASSIGNING) -OPDEF(JSOP_GETVAR, 86, "getvar", NULL, 3, 0, 1, 12, JOF_QVAR |JOF_NAME) -OPDEF(JSOP_SETVAR, 87, "setvar", NULL, 3, 1, 1, 1, JOF_QVAR |JOF_NAME|JOF_SET|JOF_ASSIGNING|JOF_DETECTING) - -/* Push unsigned 16-bit int constant. */ -OPDEF(JSOP_UINT16, 88, "uint16", NULL, 3, 0, 1, 12, JOF_UINT16) - -/* Object and array literal support. */ -OPDEF(JSOP_NEWINIT, 89, "newinit", NULL, 1, 2, 1, 10, JOF_BYTE) -OPDEF(JSOP_ENDINIT, 90, "endinit", NULL, 1, 0, 0, 0, JOF_BYTE) -OPDEF(JSOP_INITPROP, 91, "initprop", NULL, 3, 1, 0, 0, JOF_CONST|JOF_PROP|JOF_DETECTING) -OPDEF(JSOP_INITELEM, 92, "initelem", NULL, 1, 2, 0, 0, JOF_BYTE |JOF_ELEM|JOF_DETECTING) -OPDEF(JSOP_DEFSHARP, 93, "defsharp", NULL, 3, 0, 0, 0, JOF_UINT16) -OPDEF(JSOP_USESHARP, 94, "usesharp", NULL, 3, 0, 1, 0, JOF_UINT16) - -/* Fast inc/dec ops for args and local vars. */ -OPDEF(JSOP_INCARG, 95, "incarg", NULL, 3, 0, 1, 10, JOF_QARG |JOF_NAME|JOF_INC) -OPDEF(JSOP_INCVAR, 96, "incvar", NULL, 3, 0, 1, 10, JOF_QVAR |JOF_NAME|JOF_INC) -OPDEF(JSOP_DECARG, 97, "decarg", NULL, 3, 0, 1, 10, JOF_QARG |JOF_NAME|JOF_DEC) -OPDEF(JSOP_DECVAR, 98, "decvar", NULL, 3, 0, 1, 10, JOF_QVAR |JOF_NAME|JOF_DEC) -OPDEF(JSOP_ARGINC, 99, "arginc", NULL, 3, 0, 1, 10, JOF_QARG |JOF_NAME|JOF_INC|JOF_POST) -OPDEF(JSOP_VARINC, 100,"varinc", NULL, 3, 0, 1, 10, JOF_QVAR |JOF_NAME|JOF_INC|JOF_POST) -OPDEF(JSOP_ARGDEC, 101,"argdec", NULL, 3, 0, 1, 10, JOF_QARG |JOF_NAME|JOF_DEC|JOF_POST) -OPDEF(JSOP_VARDEC, 102,"vardec", NULL, 3, 0, 1, 10, JOF_QVAR |JOF_NAME|JOF_DEC|JOF_POST) - -/* ECMA-compliant for/in ops. */ -OPDEF(JSOP_TOOBJECT, 103,"toobject", NULL, 1, 1, 1, 0, JOF_BYTE) -OPDEF(JSOP_FORNAME, 104,"forname", NULL, 3, 0, 1, 0, JOF_CONST|JOF_NAME|JOF_FOR) -OPDEF(JSOP_FORPROP, 105,"forprop", NULL, 3, 1, 1, 0, JOF_CONST|JOF_PROP|JOF_FOR) -OPDEF(JSOP_FORELEM, 106,"forelem", NULL, 1, 2, 4, 0, JOF_BYTE |JOF_ELEM|JOF_FOR) -OPDEF(JSOP_POP2, 107,"pop2", NULL, 1, 2, 0, 0, JOF_BYTE) - -/* ECMA-compliant assignment ops. */ -OPDEF(JSOP_BINDNAME, 108,"bindname", NULL, 3, 0, 1, 0, JOF_CONST|JOF_NAME|JOF_SET|JOF_ASSIGNING) -OPDEF(JSOP_SETNAME, 109,"setname", NULL, 3, 2, 1, 1, JOF_CONST|JOF_NAME|JOF_SET|JOF_ASSIGNING|JOF_DETECTING) - -/* Exception handling ops. */ -OPDEF(JSOP_THROW, 110,"throw", NULL, 1, 1, 0, 0, JOF_BYTE) - -/* 'in' and 'instanceof' ops. */ -OPDEF(JSOP_IN, 111,js_in_str, js_in_str, 1, 2, 1, 6, JOF_BYTE|JOF_LEFTASSOC) -OPDEF(JSOP_INSTANCEOF,112,js_instanceof_str,js_instanceof_str,1,2,1,6,JOF_BYTE|JOF_LEFTASSOC) - -/* debugger op */ -OPDEF(JSOP_DEBUGGER, 113,"debugger", NULL, 1, 0, 0, 0, JOF_BYTE) - -/* gosub/retsub for finally handling */ -OPDEF(JSOP_GOSUB, 114,"gosub", NULL, 3, 0, 0, 0, JOF_JUMP) -OPDEF(JSOP_RETSUB, 115,"retsub", NULL, 1, 0, 0, 0, JOF_BYTE) - -/* More exception handling ops. */ -OPDEF(JSOP_EXCEPTION, 116,"exception", NULL, 1, 0, 1, 0, JOF_BYTE) -OPDEF(JSOP_SETSP, 117,"setsp", NULL, 3, 0, 0, 0, JOF_UINT16) - -/* - * ECMA-compliant switch statement ops. - * CONDSWITCH is a decompilable NOP; CASE is ===, POP, jump if true, re-push - * lval if false; and DEFAULT is POP lval and GOTO. - */ -OPDEF(JSOP_CONDSWITCH,118,"condswitch", NULL, 1, 0, 0, 0, JOF_BYTE) -OPDEF(JSOP_CASE, 119,"case", NULL, 3, 1, 0, 0, JOF_JUMP) -OPDEF(JSOP_DEFAULT, 120,"default", NULL, 3, 1, 0, 0, JOF_JUMP) - -/* - * ECMA-compliant call to eval op - */ -OPDEF(JSOP_EVAL, 121,"eval", NULL, 3, -1, 1, 11, JOF_UINT16) - -/* - * ECMA-compliant helper for 'for (x[i] in o)' loops. - */ -OPDEF(JSOP_ENUMELEM, 122,"enumelem", NULL, 1, 3, 0, 1, JOF_BYTE |JOF_SET|JOF_ASSIGNING) - -/* - * Getter and setter prefix bytecodes. These modify the next bytecode, either - * an assignment or a property initializer code, which then defines a property - * getter or setter. - */ -OPDEF(JSOP_GETTER, 123,js_getter_str,NULL, 1, 0, 0, 0, JOF_BYTE) -OPDEF(JSOP_SETTER, 124,js_setter_str,NULL, 1, 0, 0, 0, JOF_BYTE) - -/* - * Prolog bytecodes for defining function, var, and const names. - */ -OPDEF(JSOP_DEFFUN, 125,"deffun", NULL, 3, 0, 0, 0, JOF_CONST|JOF_DECLARING) -OPDEF(JSOP_DEFCONST, 126,"defconst", NULL, 3, 0, 0, 0, JOF_CONST|JOF_DECLARING) -OPDEF(JSOP_DEFVAR, 127,"defvar", NULL, 3, 0, 0, 0, JOF_CONST|JOF_DECLARING) - -/* Auto-clone (if needed due to re-parenting) and push an anonymous function. */ -OPDEF(JSOP_ANONFUNOBJ, 128, "anonfunobj", NULL, 3, 0, 1, 12, JOF_CONST) - -/* ECMA ed. 3 named function expression. */ -OPDEF(JSOP_NAMEDFUNOBJ, 129, "namedfunobj", NULL, 3, 0, 1, 12, JOF_CONST) - -/* - * Like JSOP_INITPROP, but specialized to make a DontDelete property for ECMA - * Edition 3 catch variables. - */ -OPDEF(JSOP_INITCATCHVAR,130, "initcatchvar",NULL, 3, 1, 0, 0, JOF_CONST) - -/* ECMA-mandated parenthesization opcode, which nulls the reference base register, obj; see jsinterp.c. */ -OPDEF(JSOP_GROUP, 131, "group", NULL, 1, 0, 0, 0, JOF_BYTE) - -/* Host object extension: given 'o.item(i) = j', the left-hand side compiles JSOP_SETCALL, rather than JSOP_CALL. */ -OPDEF(JSOP_SETCALL, 132, "setcall", NULL, 3, -1, 2, 11, JOF_UINT16|JOF_SET|JOF_ASSIGNING) - -/* - * Exception handling no-ops, for more economical byte-coding than SRC_TRYFIN - * srcnote-annotated JSOP_NOPs. - */ -OPDEF(JSOP_TRY, 133,"try", NULL, 1, 0, 0, 0, JOF_BYTE) -OPDEF(JSOP_FINALLY, 134,"finally", NULL, 1, 0, 0, 0, JOF_BYTE) - -/* - * Swap the top two stack elements. - * N.B. JSOP_SWAP doesn't swap the corresponding pc stack generating pcs, as - * they're not needed for the current use of preserving the top-of-stack return - * value when popping scopes while returning from catch blocks. - */ -OPDEF(JSOP_SWAP, 135,"swap", NULL, 1, 2, 2, 0, JOF_BYTE) - -/* - * Bytecodes that avoid making an arguments object in most cases: - * JSOP_ARGSUB gets arguments[i] from fp->argv, iff i is in [0, fp->argc-1]. - * JSOP_ARGCNT returns fp->argc. - */ -OPDEF(JSOP_ARGSUB, 136,"argsub", NULL, 3, 0, 1, 12, JOF_QARG |JOF_NAME) -OPDEF(JSOP_ARGCNT, 137,"argcnt", NULL, 1, 0, 1, 12, JOF_BYTE) - -/* - * Define a local function object as a local variable. - * The local variable's slot number is the first immediate two-byte operand. - * The function object's atom index is the second immediate operand. - */ -OPDEF(JSOP_DEFLOCALFUN, 138,"deflocalfun",NULL, 5, 0, 0, 0, JOF_INDEXCONST|JOF_DECLARING) - -/* Extended jumps. */ -OPDEF(JSOP_GOTOX, 139,"gotox", NULL, 5, 0, 0, 0, JOF_JUMPX) -OPDEF(JSOP_IFEQX, 140,"ifeqx", NULL, 5, 1, 0, 0, JOF_JUMPX|JOF_DETECTING) -OPDEF(JSOP_IFNEX, 141,"ifnex", NULL, 5, 1, 0, 0, JOF_JUMPX) -OPDEF(JSOP_ORX, 142,"orx", NULL, 5, 1, 0, 0, JOF_JUMPX|JOF_DETECTING) -OPDEF(JSOP_ANDX, 143,"andx", NULL, 5, 1, 0, 0, JOF_JUMPX|JOF_DETECTING) -OPDEF(JSOP_GOSUBX, 144,"gosubx", NULL, 5, 0, 0, 0, JOF_JUMPX) -OPDEF(JSOP_CASEX, 145,"casex", NULL, 5, 1, 0, 0, JOF_JUMPX) -OPDEF(JSOP_DEFAULTX, 146,"defaultx", NULL, 5, 1, 0, 0, JOF_JUMPX) -OPDEF(JSOP_TABLESWITCHX, 147,"tableswitchx",NULL, -1, 1, 0, 0, JOF_TABLESWITCHX|JOF_DETECTING) -OPDEF(JSOP_LOOKUPSWITCHX, 148,"lookupswitchx",NULL, -1, 1, 0, 0, JOF_LOOKUPSWITCHX|JOF_DETECTING) - -/* Placeholders for a real jump opcode set during backpatch chain fixup. */ -OPDEF(JSOP_BACKPATCH, 149,"backpatch",NULL, 3, 0, 0, 0, JOF_JUMP|JOF_BACKPATCH) -OPDEF(JSOP_BACKPATCH_POP, 150,"backpatch_pop",NULL, 3, 1, 0, 0, JOF_JUMP|JOF_BACKPATCH) - -/* Set cx->throwing where cx->exception was already set, to trigger rethrow. */ -OPDEF(JSOP_THROWING, 151,"throwing", NULL, 1, 0, 0, 0, JOF_BYTE) - -/* Set and get return value pseudo-register in stack frame. */ -OPDEF(JSOP_SETRVAL, 152,"setrval", NULL, 1, 1, 0, 0, JOF_BYTE) -OPDEF(JSOP_RETRVAL, 153,"retrval", NULL, 1, 0, 0, 0, JOF_BYTE) - -/* Optimized global variable ops (we don't bother doing a JSOP_FORGVAR op). */ -OPDEF(JSOP_GETGVAR, 154,"getgvar", NULL, 3, 0, 1, 12, JOF_CONST|JOF_NAME) -OPDEF(JSOP_SETGVAR, 155,"setgvar", NULL, 3, 1, 1, 1, JOF_CONST|JOF_NAME|JOF_SET|JOF_ASSIGNING|JOF_DETECTING) -OPDEF(JSOP_INCGVAR, 156,"incgvar", NULL, 3, 0, 1, 10, JOF_CONST|JOF_NAME|JOF_INC) -OPDEF(JSOP_DECGVAR, 157,"decgvar", NULL, 3, 0, 1, 10, JOF_CONST|JOF_NAME|JOF_DEC) -OPDEF(JSOP_GVARINC, 158,"gvarinc", NULL, 3, 0, 1, 10, JOF_CONST|JOF_NAME|JOF_INC|JOF_POST) -OPDEF(JSOP_GVARDEC, 159,"gvardec", NULL, 3, 0, 1, 10, JOF_CONST|JOF_NAME|JOF_DEC|JOF_POST) - -/* Regular expression literal requiring special "fork on exec" handling. */ -OPDEF(JSOP_REGEXP, 160,"regexp", NULL, 3, 0, 1, 12, JOF_CONST) - -/* XML (ECMA-357, a.k.a. "E4X") support. */ -OPDEF(JSOP_DEFXMLNS, 161,"defxmlns", NULL, 1, 1, 0, 0, JOF_BYTE) -OPDEF(JSOP_ANYNAME, 162,"anyname", NULL, 1, 0, 1, 12, JOF_BYTE|JOF_XMLNAME) -OPDEF(JSOP_QNAMEPART, 163,"qnamepart", NULL, 3, 0, 1, 12, JOF_CONST|JOF_XMLNAME) -OPDEF(JSOP_QNAMECONST, 164,"qnameconst", NULL, 3, 1, 1, 12, JOF_CONST|JOF_XMLNAME) -OPDEF(JSOP_QNAME, 165,"qname", NULL, 1, 2, 1, 0, JOF_BYTE|JOF_XMLNAME) -OPDEF(JSOP_TOATTRNAME, 166,"toattrname", NULL, 1, 1, 1, 12, JOF_BYTE|JOF_XMLNAME) -OPDEF(JSOP_TOATTRVAL, 167,"toattrval", NULL, 1, 1, 1, 12, JOF_BYTE) -OPDEF(JSOP_ADDATTRNAME, 168,"addattrname",NULL, 1, 2, 1, 8, JOF_BYTE) -OPDEF(JSOP_ADDATTRVAL, 169,"addattrval", NULL, 1, 2, 1, 8, JOF_BYTE) -OPDEF(JSOP_BINDXMLNAME, 170,"bindxmlname",NULL, 1, 1, 2, 0, JOF_BYTE|JOF_XMLNAME|JOF_SET|JOF_ASSIGNING) -OPDEF(JSOP_SETXMLNAME, 171,"setxmlname", NULL, 1, 3, 1, 1, JOF_BYTE|JOF_XMLNAME|JOF_SET|JOF_ASSIGNING|JOF_DETECTING) -OPDEF(JSOP_XMLNAME, 172,"xmlname", NULL, 1, 1, 1, 12, JOF_BYTE|JOF_XMLNAME) -OPDEF(JSOP_DESCENDANTS, 173,"descendants",NULL, 1, 2, 1, 11, JOF_BYTE) -OPDEF(JSOP_FILTER, 174,"filter", NULL, 3, 1, 1, 11, JOF_JUMP) -OPDEF(JSOP_ENDFILTER, 175,"endfilter", NULL, 1, 1, 0, 0, JOF_BYTE) -OPDEF(JSOP_TOXML, 176,"toxml", NULL, 1, 1, 1, 12, JOF_BYTE) -OPDEF(JSOP_TOXMLLIST, 177,"toxmllist", NULL, 1, 1, 1, 12, JOF_BYTE) -OPDEF(JSOP_XMLTAGEXPR, 178,"xmltagexpr", NULL, 1, 1, 1, 0, JOF_BYTE) -OPDEF(JSOP_XMLELTEXPR, 179,"xmleltexpr", NULL, 1, 1, 1, 0, JOF_BYTE) -OPDEF(JSOP_XMLOBJECT, 180,"xmlobject", NULL, 3, 0, 1, 12, JOF_CONST) -OPDEF(JSOP_XMLCDATA, 181,"xmlcdata", NULL, 3, 0, 1, 12, JOF_CONST) -OPDEF(JSOP_XMLCOMMENT, 182,"xmlcomment", NULL, 3, 0, 1, 12, JOF_CONST) -OPDEF(JSOP_XMLPI, 183,"xmlpi", NULL, 3, 1, 1, 12, JOF_CONST) -OPDEF(JSOP_GETMETHOD, 184,"getmethod", NULL, 3, 1, 1, 11, JOF_CONST|JOF_PROP) -OPDEF(JSOP_GETFUNNS, 185,"getfunns", NULL, 1, 0, 1, 12, JOF_BYTE) -OPDEF(JSOP_FOREACH, 186,"foreach", NULL, 1, 0, 0, 0, JOF_BYTE) -OPDEF(JSOP_DELDESC, 187,"deldesc", NULL, 1, 2, 1, 10, JOF_BYTE |JOF_ELEM|JOF_DEL) - -/* - * Opcodes for extended literal addressing, using unsigned 24-bit immediate - * operands to hold integer operands (JSOP_UINT24), extended atom indexes in - * script->atomMap (JSOP_LITERAL, JSOP_FINDNAME), and ops prefixed by such - * atom index immediates (JSOP_LITOPX). See jsemit.c, EmitAtomIndexOp. - */ -OPDEF(JSOP_UINT24, 188,"uint24", NULL, 4, 0, 1, 12, JOF_UINT24) -OPDEF(JSOP_LITERAL, 189,"literal", NULL, 4, 0, 1, 12, JOF_UINT24) -OPDEF(JSOP_FINDNAME, 190,"findname", NULL, 4, 0, 2, 0, JOF_UINT24) -OPDEF(JSOP_LITOPX, 191,"litopx", NULL, 5, 0, 0, 12, JOF_LITOPX) - -/* - * Opcodes to help the decompiler deal with XML. - */ -OPDEF(JSOP_STARTXML, 192,"startxml", NULL, 1, 0, 0, 0, JOF_BYTE) -OPDEF(JSOP_STARTXMLEXPR, 193,"startxmlexpr",NULL, 1, 0, 0, 0, JOF_BYTE) -OPDEF(JSOP_SETMETHOD, 194,"setmethod", NULL, 3, 2, 1, 1, JOF_CONST|JOF_PROP) diff --git a/lib/javascript/jsosdep.h b/lib/javascript/jsosdep.h deleted file mode 100644 index e9c4a553..00000000 --- a/lib/javascript/jsosdep.h +++ /dev/null @@ -1,112 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jsosdep_h___ -#define jsosdep_h___ -/* - * OS (and machine, and compiler XXX) dependent information. - */ - -#if defined(XP_WIN) || defined(XP_OS2) - -#if defined(_WIN32) || defined (XP_OS2) -#define JS_HAVE_LONG_LONG -#else -#undef JS_HAVE_LONG_LONG -#endif -#endif /* XP_WIN || XP_OS2 */ - -#ifdef XP_BEOS -#define JS_HAVE_LONG_LONG -#endif - - -#ifdef XP_UNIX - -/* - * Get OS specific header information. - */ -#if defined(AIXV3) || defined(AIX) -#define JS_HAVE_LONG_LONG - -#elif defined(BSDI) -#define JS_HAVE_LONG_LONG - -#elif defined(HPUX) -#define JS_HAVE_LONG_LONG - -#elif defined(IRIX) -#define JS_HAVE_LONG_LONG - -#elif defined(linux) -#define JS_HAVE_LONG_LONG - -#elif defined(OSF1) -#define JS_HAVE_LONG_LONG - -#elif defined(_SCO_DS) -#undef JS_HAVE_LONG_LONG - -#elif defined(SOLARIS) -#define JS_HAVE_LONG_LONG - -#elif defined(FREEBSD) -#define JS_HAVE_LONG_LONG - -#elif defined(SUNOS4) -#undef JS_HAVE_LONG_LONG - -/* -** Missing function prototypes -*/ - -extern void *sbrk(int); - -#elif defined(UNIXWARE) -#undef JS_HAVE_LONG_LONG - -#elif defined(VMS) && defined(__ALPHA) -#define JS_HAVE_LONG_LONG - -#endif - -#endif /* XP_UNIX */ - -#endif /* jsosdep_h___ */ - diff --git a/lib/javascript/jsotypes.h b/lib/javascript/jsotypes.h deleted file mode 100644 index 57f5193a..00000000 --- a/lib/javascript/jsotypes.h +++ /dev/null @@ -1,204 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * This section typedefs the old 'native' types to the new PRs. - * These definitions are scheduled to be eliminated at the earliest - * possible time. The NSPR API is implemented and documented using - * the new definitions. - */ - -/* - * Note that we test for PROTYPES_H, not JSOTYPES_H. This is to avoid - * double-definitions of scalar types such as uint32, if NSPR's - * protypes.h is also included. - */ -#ifndef PROTYPES_H -#define PROTYPES_H - -#ifdef XP_BEOS -/* BeOS defines most int types in SupportDefs.h (int8, uint8, int16, - * uint16, int32, uint32, int64, uint64), so in the interest of - * not conflicting with other definitions elsewhere we have to skip the - * #ifdef jungle below, duplicate some definitions, and do our stuff. - */ -#include - -typedef JSUintn uintn; -#ifndef _XP_Core_ -typedef JSIntn intn; -#endif - -#else - -/* SVR4 typedef of uint is commonly found on UNIX machines. */ -#ifdef XP_UNIX -#include -#else -typedef JSUintn uint; -#endif - -typedef JSUintn uintn; -#ifndef HAVE_DARWIN -typedef JSUint64 uint64; -#endif -#if !defined(_WIN32) && !defined(XP_OS2) -typedef JSUint32 uint32; -#else -typedef unsigned long uint32; -#endif -typedef JSUint16 uint16; -typedef JSUint8 uint8; - -#ifndef _XP_Core_ -typedef JSIntn intn; -#endif - -/* - * On AIX 4.3, sys/inttypes.h (which is included by sys/types.h, a very - * common header file) defines the types int8, int16, int32, and int64. - * So we don't define these four types here to avoid conflicts in case - * the code also includes sys/types.h. - */ -#if defined(AIX) && defined(HAVE_SYS_INTTYPES_H) -#include -#else -typedef JSInt64 int64; - -/* /usr/include/model.h on HP-UX defines int8, int16, and int32 */ -#ifdef HPUX -#include -#else -#if !defined(_WIN32) && !defined(XP_OS2) -typedef JSInt32 int32; -#else -typedef long int32; -#endif -typedef JSInt16 int16; -typedef JSInt8 int8; -#endif /* HPUX */ -#endif /* AIX && HAVE_SYS_INTTYPES_H */ - -#endif /* XP_BEOS */ - -typedef JSFloat64 float64; - -/* Re: jsbit.h */ -#define TEST_BIT JS_TEST_BIT -#define SET_BIT JS_SET_BIT -#define CLEAR_BIT JS_CLEAR_BIT - -/* Re: prarena.h->plarena.h */ -#define PRArena PLArena -#define PRArenaPool PLArenaPool -#define PRArenaStats PLArenaStats -#define PR_ARENA_ALIGN PL_ARENA_ALIGN -#define PR_INIT_ARENA_POOL PL_INIT_ARENA_POOL -#define PR_ARENA_ALLOCATE PL_ARENA_ALLOCATE -#define PR_ARENA_GROW PL_ARENA_GROW -#define PR_ARENA_MARK PL_ARENA_MARK -#define PR_CLEAR_UNUSED PL_CLEAR_UNUSED -#define PR_CLEAR_ARENA PL_CLEAR_ARENA -#define PR_ARENA_RELEASE PL_ARENA_RELEASE -#define PR_COUNT_ARENA PL_COUNT_ARENA -#define PR_ARENA_DESTROY PL_ARENA_DESTROY -#define PR_InitArenaPool PL_InitArenaPool -#define PR_FreeArenaPool PL_FreeArenaPool -#define PR_FinishArenaPool PL_FinishArenaPool -#define PR_CompactArenaPool PL_CompactArenaPool -#define PR_ArenaFinish PL_ArenaFinish -#define PR_ArenaAllocate PL_ArenaAllocate -#define PR_ArenaGrow PL_ArenaGrow -#define PR_ArenaRelease PL_ArenaRelease -#define PR_ArenaCountAllocation PL_ArenaCountAllocation -#define PR_ArenaCountInplaceGrowth PL_ArenaCountInplaceGrowth -#define PR_ArenaCountGrowth PL_ArenaCountGrowth -#define PR_ArenaCountRelease PL_ArenaCountRelease -#define PR_ArenaCountRetract PL_ArenaCountRetract - -/* Re: prevent.h->plevent.h */ -#define PREvent PLEvent -#define PREventQueue PLEventQueue -#define PR_CreateEventQueue PL_CreateEventQueue -#define PR_DestroyEventQueue PL_DestroyEventQueue -#define PR_GetEventQueueMonitor PL_GetEventQueueMonitor -#define PR_ENTER_EVENT_QUEUE_MONITOR PL_ENTER_EVENT_QUEUE_MONITOR -#define PR_EXIT_EVENT_QUEUE_MONITOR PL_EXIT_EVENT_QUEUE_MONITOR -#define PR_PostEvent PL_PostEvent -#define PR_PostSynchronousEvent PL_PostSynchronousEvent -#define PR_GetEvent PL_GetEvent -#define PR_EventAvailable PL_EventAvailable -#define PREventFunProc PLEventFunProc -#define PR_MapEvents PL_MapEvents -#define PR_RevokeEvents PL_RevokeEvents -#define PR_ProcessPendingEvents PL_ProcessPendingEvents -#define PR_WaitForEvent PL_WaitForEvent -#define PR_EventLoop PL_EventLoop -#define PR_GetEventQueueSelectFD PL_GetEventQueueSelectFD -#define PRHandleEventProc PLHandleEventProc -#define PRDestroyEventProc PLDestroyEventProc -#define PR_InitEvent PL_InitEvent -#define PR_GetEventOwner PL_GetEventOwner -#define PR_HandleEvent PL_HandleEvent -#define PR_DestroyEvent PL_DestroyEvent -#define PR_DequeueEvent PL_DequeueEvent -#define PR_GetMainEventQueue PL_GetMainEventQueue - -/* Re: prhash.h->plhash.h */ -#define PRHashEntry PLHashEntry -#define PRHashTable PLHashTable -#define PRHashNumber PLHashNumber -#define PRHashFunction PLHashFunction -#define PRHashComparator PLHashComparator -#define PRHashEnumerator PLHashEnumerator -#define PRHashAllocOps PLHashAllocOps -#define PR_NewHashTable PL_NewHashTable -#define PR_HashTableDestroy PL_HashTableDestroy -#define PR_HashTableRawLookup PL_HashTableRawLookup -#define PR_HashTableRawAdd PL_HashTableRawAdd -#define PR_HashTableRawRemove PL_HashTableRawRemove -#define PR_HashTableAdd PL_HashTableAdd -#define PR_HashTableRemove PL_HashTableRemove -#define PR_HashTableEnumerateEntries PL_HashTableEnumerateEntries -#define PR_HashTableLookup PL_HashTableLookup -#define PR_HashTableDump PL_HashTableDump -#define PR_HashString PL_HashString -#define PR_CompareStrings PL_CompareStrings -#define PR_CompareValues PL_CompareValues - -#endif /* !defined(PROTYPES_H) */ diff --git a/lib/javascript/jsparse.c b/lib/javascript/jsparse.c deleted file mode 100644 index 1438f35a..00000000 --- a/lib/javascript/jsparse.c +++ /dev/null @@ -1,4880 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JS parser. - * - * This is a recursive-descent parser for the JavaScript language specified by - * "The JavaScript 1.5 Language Specification". It uses lexical and semantic - * feedback to disambiguate non-LL(1) structures. It generates trees of nodes - * induced by the recursive parsing (not precise syntax trees, see jsparse.h). - * After tree construction, it rewrites trees to fold constants and evaluate - * compile-time expressions. Finally, it calls js_EmitTree (see jsemit.h) to - * generate bytecode. - * - * This parser attempts no error recovery. - */ -#include "jsstddef.h" -#include -#include -#include -#include "jstypes.h" -#include "jsarena.h" /* Added by JSIFY */ -#include "jsutil.h" /* Added by JSIFY */ -#include "jsapi.h" -#include "jsatom.h" -#include "jscntxt.h" -#include "jsconfig.h" -#include "jsemit.h" -#include "jsfun.h" -#include "jsinterp.h" -#include "jslock.h" -#include "jsnum.h" -#include "jsobj.h" -#include "jsopcode.h" -#include "jsparse.h" -#include "jsscan.h" -#include "jsscope.h" -#include "jsscript.h" -#include "jsstr.h" - -#if JS_HAS_XML_SUPPORT -#include "jsxml.h" -#endif - -/* - * JS parsers, from lowest to highest precedence. - * - * Each parser takes a context, a token stream, and a tree context struct. - * Each returns a parse node tree or null on error. - */ - -typedef JSParseNode * -JSParser(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc); - -typedef JSParseNode * -JSMemberParser(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, - JSBool allowCallSyntax); - -static JSParser FunctionStmt; -#if JS_HAS_LEXICAL_CLOSURE -static JSParser FunctionExpr; -#endif -static JSParser Statements; -static JSParser Statement; -static JSParser Variables; -static JSParser Expr; -static JSParser AssignExpr; -static JSParser CondExpr; -static JSParser OrExpr; -static JSParser AndExpr; -static JSParser BitOrExpr; -static JSParser BitXorExpr; -static JSParser BitAndExpr; -static JSParser EqExpr; -static JSParser RelExpr; -static JSParser ShiftExpr; -static JSParser AddExpr; -static JSParser MulExpr; -static JSParser UnaryExpr; -static JSMemberParser MemberExpr; -static JSParser PrimaryExpr; - -/* - * Insist that the next token be of type tt, or report errno and return null. - * NB: this macro uses cx and ts from its lexical environment. - */ -#define MUST_MATCH_TOKEN(tt, errno) \ - JS_BEGIN_MACRO \ - if (js_GetToken(cx, ts) != tt) { \ - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, \ - errno); \ - return NULL; \ - } \ - JS_END_MACRO - -#define CHECK_RECURSION() \ - JS_BEGIN_MACRO \ - int stackDummy; \ - if (!JS_CHECK_STACK_SIZE(cx, stackDummy)) { \ - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, \ - JSMSG_OVER_RECURSED); \ - return NULL; \ - } \ - JS_END_MACRO - -#ifdef METER_PARSENODES -static uint32 parsenodes = 0; -static uint32 maxparsenodes = 0; -static uint32 recyclednodes = 0; -#endif - -static JSParseNode * -RecycleTree(JSParseNode *pn, JSTreeContext *tc) -{ - JSParseNode *next; - - if (!pn) - return NULL; - JS_ASSERT(pn != tc->nodeList); /* catch back-to-back dup recycles */ - next = pn->pn_next; - pn->pn_next = tc->nodeList; - tc->nodeList = pn; -#ifdef METER_PARSENODES - recyclednodes++; -#endif - return next; -} - -static JSParseNode * -NewOrRecycledNode(JSContext *cx, JSTreeContext *tc) -{ - JSParseNode *pn; - - pn = tc->nodeList; - if (!pn) { - JS_ARENA_ALLOCATE_TYPE(pn, JSParseNode, &cx->tempPool); - if (!pn) - JS_ReportOutOfMemory(cx); - } else { - tc->nodeList = pn->pn_next; - - /* Recycle immediate descendents only, to save work and working set. */ - switch (pn->pn_arity) { - case PN_FUNC: - RecycleTree(pn->pn_body, tc); - break; - case PN_LIST: - if (pn->pn_head) { - /* XXX check for dup recycles in the list */ - *pn->pn_tail = tc->nodeList; - tc->nodeList = pn->pn_head; -#ifdef METER_PARSENODES - recyclednodes += pn->pn_count; -#endif - } - break; - case PN_TERNARY: - RecycleTree(pn->pn_kid1, tc); - RecycleTree(pn->pn_kid2, tc); - RecycleTree(pn->pn_kid3, tc); - break; - case PN_BINARY: - RecycleTree(pn->pn_left, tc); - RecycleTree(pn->pn_right, tc); - break; - case PN_UNARY: - RecycleTree(pn->pn_kid, tc); - break; - case PN_NAME: - RecycleTree(pn->pn_expr, tc); - break; - case PN_NULLARY: - break; - } - } -#ifdef METER_PARSENODES - if (pn) { - parsenodes++; - if (parsenodes - recyclednodes > maxparsenodes) - maxparsenodes = parsenodes - recyclednodes; - } -#endif - return pn; -} - -/* - * Allocate a JSParseNode from cx's temporary arena. - */ -static JSParseNode * -NewParseNode(JSContext *cx, JSTokenStream *ts, JSParseNodeArity arity, - JSTreeContext *tc) -{ - JSParseNode *pn; - JSToken *tp; - - pn = NewOrRecycledNode(cx, tc); - if (!pn) - return NULL; - tp = &CURRENT_TOKEN(ts); - pn->pn_type = tp->type; - pn->pn_pos = tp->pos; - pn->pn_op = JSOP_NOP; - pn->pn_arity = arity; - pn->pn_next = NULL; -#if JS_HAS_XML_SUPPORT - pn->pn_ts = ts; -#endif - return pn; -} - -static JSParseNode * -NewBinary(JSContext *cx, JSTokenType tt, - JSOp op, JSParseNode *left, JSParseNode *right, - JSTreeContext *tc) -{ - JSParseNode *pn, *pn1, *pn2; - - if (!left || !right) - return NULL; - - /* - * Flatten a left-associative (left-heavy) tree of a given operator into - * a list, to reduce js_FoldConstants and js_EmitTree recursion. - */ - if (left->pn_type == tt && - left->pn_op == op && - (js_CodeSpec[op].format & JOF_LEFTASSOC)) { - if (left->pn_arity != PN_LIST) { - pn1 = left->pn_left, pn2 = left->pn_right; - left->pn_arity = PN_LIST; - PN_INIT_LIST_1(left, pn1); - PN_APPEND(left, pn2); - if (tt == TOK_PLUS) { - if (pn1->pn_type == TOK_STRING) - left->pn_extra |= PNX_STRCAT; - else if (pn1->pn_type != TOK_NUMBER) - left->pn_extra |= PNX_CANTFOLD; - if (pn2->pn_type == TOK_STRING) - left->pn_extra |= PNX_STRCAT; - else if (pn2->pn_type != TOK_NUMBER) - left->pn_extra |= PNX_CANTFOLD; - } - } - PN_APPEND(left, right); - left->pn_pos.end = right->pn_pos.end; - if (tt == TOK_PLUS) { - if (right->pn_type == TOK_STRING) - left->pn_extra |= PNX_STRCAT; - else if (right->pn_type != TOK_NUMBER) - left->pn_extra |= PNX_CANTFOLD; - } - return left; - } - - /* - * Fold constant addition immediately, to conserve node space and, what's - * more, so js_FoldConstants never sees mixed addition and concatenation - * operations with more than one leading non-string operand in a PN_LIST - * generated for expressions such as 1 + 2 + "pt" (which should evaluate - * to "3pt", not "12pt"). - */ - if (tt == TOK_PLUS && - left->pn_type == TOK_NUMBER && - right->pn_type == TOK_NUMBER) { - left->pn_dval += right->pn_dval; - left->pn_pos.end = right->pn_pos.end; - RecycleTree(right, tc); - return left; - } - - pn = NewOrRecycledNode(cx, tc); - if (!pn) - return NULL; - pn->pn_type = tt; - pn->pn_pos.begin = left->pn_pos.begin; - pn->pn_pos.end = right->pn_pos.end; - pn->pn_op = op; - pn->pn_arity = PN_BINARY; - pn->pn_left = left; - pn->pn_right = right; - pn->pn_next = NULL; -#if JS_HAS_XML_SUPPORT - pn->pn_ts = NULL; -#endif - return pn; -} - -#if JS_HAS_GETTER_SETTER -static JSTokenType -CheckGetterOrSetter(JSContext *cx, JSTokenStream *ts, JSTokenType tt) -{ - JSAtom *atom; - JSRuntime *rt; - JSOp op; - const char *name; - - JS_ASSERT(CURRENT_TOKEN(ts).type == TOK_NAME); - atom = CURRENT_TOKEN(ts).t_atom; - rt = cx->runtime; - if (atom == rt->atomState.getterAtom) - op = JSOP_GETTER; - else if (atom == rt->atomState.setterAtom) - op = JSOP_SETTER; - else - return TOK_NAME; - if (js_PeekTokenSameLine(cx, ts) != tt) - return TOK_NAME; - (void) js_GetToken(cx, ts); - if (CURRENT_TOKEN(ts).t_op != JSOP_NOP) { - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, - JSMSG_BAD_GETTER_OR_SETTER, - (op == JSOP_GETTER) - ? js_getter_str - : js_setter_str); - return TOK_ERROR; - } - CURRENT_TOKEN(ts).t_op = op; - name = js_AtomToPrintableString(cx, atom); - if (!name || - !js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | - JSREPORT_WARNING | - JSREPORT_STRICT, - JSMSG_DEPRECATED_USAGE, - name)) { - return TOK_ERROR; - } - return tt; -} -#endif - -/* - * Parse a top-level JS script. - */ -JS_FRIEND_API(JSParseNode *) -js_ParseTokenStream(JSContext *cx, JSObject *chain, JSTokenStream *ts) -{ - JSStackFrame *fp, frame; - JSTreeContext tc; - JSParseNode *pn; - - /* - * Push a compiler frame if we have no frames, or if the top frame is a - * lightweight function activation, or if its scope chain doesn't match - * the one passed to us. - */ - fp = cx->fp; - if (!fp || !fp->varobj || fp->scopeChain != chain) { - memset(&frame, 0, sizeof frame); - frame.varobj = frame.scopeChain = chain; - if (cx->options & JSOPTION_VAROBJFIX) { - while ((chain = JS_GetParent(cx, chain)) != NULL) - frame.varobj = chain; - } - frame.down = fp; - if (fp) { - frame.flags = fp->flags & (JSFRAME_SPECIAL | JSFRAME_COMPILE_N_GO | - JSFRAME_SCRIPT_OBJECT); - } - cx->fp = &frame; - } - - /* - * Protect atoms from being collected by a GC activation, which might - * - nest on this thread due to out of memory (the so-called "last ditch" - * GC attempted within js_NewGCThing), or - * - run for any reason on another thread if this thread is suspended on - * an object lock before it finishes generating bytecode into a script - * protected from the GC by a root or a stack frame reference. - */ - JS_KEEP_ATOMS(cx->runtime); - TREE_CONTEXT_INIT(&tc); - pn = Statements(cx, ts, &tc); - if (pn) { - if (!js_MatchToken(cx, ts, TOK_EOF)) { - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, - JSMSG_SYNTAX_ERROR); - pn = NULL; - } else { - pn->pn_type = TOK_LC; - if (!js_FoldConstants(cx, pn, &tc)) - pn = NULL; - } - } - - TREE_CONTEXT_FINISH(&tc); - JS_UNKEEP_ATOMS(cx->runtime); - cx->fp = fp; - return pn; -} - -/* - * Compile a top-level script. - */ -JS_FRIEND_API(JSBool) -js_CompileTokenStream(JSContext *cx, JSObject *chain, JSTokenStream *ts, - JSCodeGenerator *cg) -{ - JSStackFrame *fp, frame; - uint32 flags; - JSParseNode *pn; - JSBool ok; -#ifdef METER_PARSENODES - void *sbrk(ptrdiff_t), *before = sbrk(0); -#endif - - /* - * Push a compiler frame if we have no frames, or if the top frame is a - * lightweight function activation, or if its scope chain doesn't match - * the one passed to us. - */ - fp = cx->fp; - if (!fp || !fp->varobj || fp->scopeChain != chain) { - memset(&frame, 0, sizeof frame); - frame.varobj = frame.scopeChain = chain; - if (cx->options & JSOPTION_VAROBJFIX) { - while ((chain = JS_GetParent(cx, chain)) != NULL) - frame.varobj = chain; - } - frame.down = fp; - if (fp) { - frame.flags = fp->flags & (JSFRAME_SPECIAL | JSFRAME_COMPILE_N_GO | - JSFRAME_SCRIPT_OBJECT); - } - cx->fp = &frame; - } - flags = cx->fp->flags; - cx->fp->flags = flags | - (JS_HAS_COMPILE_N_GO_OPTION(cx) - ? JSFRAME_COMPILING | JSFRAME_COMPILE_N_GO - : JSFRAME_COMPILING); - - /* Prevent GC activation while compiling. */ - JS_KEEP_ATOMS(cx->runtime); - - pn = Statements(cx, ts, &cg->treeContext); - if (!pn) { - ok = JS_FALSE; - } else if (!js_MatchToken(cx, ts, TOK_EOF)) { - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, - JSMSG_SYNTAX_ERROR); - ok = JS_FALSE; - } else { -#ifdef METER_PARSENODES - printf("Parser growth: %d (%u nodes, %u max, %u unrecycled)\n", - (char *)sbrk(0) - (char *)before, - parsenodes, - maxparsenodes, - parsenodes - recyclednodes); - before = sbrk(0); -#endif - - /* - * No need to emit code here -- Statements already has, for each - * statement in turn. Search for TCF_COMPILING in Statements, below. - * That flag is set for every tc == &cg->treeContext, and it implies - * that the tc can be downcast to a cg and used to emit code during - * parsing, rather than at the end of the parse phase. - */ - JS_ASSERT(cg->treeContext.flags & TCF_COMPILING); - ok = JS_TRUE; - } - -#ifdef METER_PARSENODES - printf("Code-gen growth: %d (%u bytecodes, %u srcnotes)\n", - (char *)sbrk(0) - (char *)before, CG_OFFSET(cg), cg->noteCount); -#endif -#ifdef JS_ARENAMETER - JS_DumpArenaStats(stdout); -#endif - JS_UNKEEP_ATOMS(cx->runtime); - cx->fp->flags = flags; - cx->fp = fp; - return ok; -} - -/* - * Insist on a final return before control flows out of pn, but don't be too - * smart about loops (do {...; return e2;} while(0) at the end of a function - * that contains an early return e1 will get a strict-option-only warning). - */ -#define ENDS_IN_OTHER 0 -#define ENDS_IN_RETURN 1 -#define ENDS_IN_BREAK 2 - -static int -HasFinalReturn(JSParseNode *pn) -{ - uintN rv, rv2, hasDefault; - JSParseNode *pn2, *pn3; - - switch (pn->pn_type) { - case TOK_LC: - if (!pn->pn_head) - return ENDS_IN_OTHER; - return HasFinalReturn(PN_LAST(pn)); - - case TOK_IF: - rv = HasFinalReturn(pn->pn_kid2); - if (pn->pn_kid3) - rv &= HasFinalReturn(pn->pn_kid3); - return rv; - -#if JS_HAS_SWITCH_STATEMENT - case TOK_SWITCH: - rv = ENDS_IN_RETURN; - hasDefault = ENDS_IN_OTHER; - for (pn2 = pn->pn_kid2->pn_head; rv && pn2; pn2 = pn2->pn_next) { - if (pn2->pn_type == TOK_DEFAULT) - hasDefault = ENDS_IN_RETURN; - pn3 = pn2->pn_right; - JS_ASSERT(pn3->pn_type == TOK_LC); - if (pn3->pn_head) { - rv2 = HasFinalReturn(PN_LAST(pn3)); - if (rv2 == ENDS_IN_OTHER && pn2->pn_next) - /* Falling through to next case or default. */; - else - rv &= rv2; - } - } - /* If a final switch has no default case, we judge it harshly. */ - rv &= hasDefault; - return rv; -#endif /* JS_HAS_SWITCH_STATEMENT */ - - case TOK_BREAK: - return ENDS_IN_BREAK; - - case TOK_WITH: - return HasFinalReturn(pn->pn_right); - - case TOK_RETURN: - return ENDS_IN_RETURN; - - case TOK_COLON: - return HasFinalReturn(pn->pn_expr); - -#if JS_HAS_EXCEPTIONS - case TOK_THROW: - return ENDS_IN_RETURN; - - case TOK_TRY: - /* If we have a finally block that returns, we are done. */ - if (pn->pn_kid3) { - rv = HasFinalReturn(pn->pn_kid3); - if (rv == ENDS_IN_RETURN) - return rv; - } - - /* Else check the try block and any and all catch statements. */ - rv = HasFinalReturn(pn->pn_kid1); - if (pn->pn_kid2) - rv &= HasFinalReturn(pn->pn_kid2); - return rv; - - case TOK_CATCH: - /* Check this block's code and iterate over further catch blocks. */ - rv = HasFinalReturn(pn->pn_kid3); - for (pn2 = pn->pn_kid2; pn2; pn2 = pn2->pn_kid2) - rv &= HasFinalReturn(pn2->pn_kid3); - return rv; -#endif - - default: - return ENDS_IN_OTHER; - } -} - -static JSBool -ReportNoReturnValue(JSContext *cx, JSTokenStream *ts) -{ - JSFunction *fun; - JSBool ok; - - fun = cx->fp->fun; - if (fun->atom) { - char *name = js_GetStringBytes(ATOM_TO_STRING(fun->atom)); - ok = js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | - JSREPORT_WARNING | - JSREPORT_STRICT, - JSMSG_NO_RETURN_VALUE, name); - } else { - ok = js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | - JSREPORT_WARNING | - JSREPORT_STRICT, - JSMSG_ANON_NO_RETURN_VALUE); - } - return ok; -} - -static JSBool -CheckFinalReturn(JSContext *cx, JSTokenStream *ts, JSParseNode *pn) -{ - return HasFinalReturn(pn) == ENDS_IN_RETURN || ReportNoReturnValue(cx, ts); -} - -static JSParseNode * -FunctionBody(JSContext *cx, JSTokenStream *ts, JSFunction *fun, - JSTreeContext *tc) -{ - JSStackFrame *fp, frame; - JSObject *funobj; - uintN oldflags; - JSParseNode *pn; - - fp = cx->fp; - funobj = fun->object; - if (!fp || fp->fun != fun || fp->varobj != funobj || - fp->scopeChain != funobj) { - memset(&frame, 0, sizeof frame); - frame.fun = fun; - frame.varobj = frame.scopeChain = funobj; - frame.down = fp; - if (fp) - frame.flags = fp->flags & JSFRAME_COMPILE_N_GO; - cx->fp = &frame; - } - - oldflags = tc->flags; - tc->flags &= ~(TCF_RETURN_EXPR | TCF_RETURN_VOID); - tc->flags |= TCF_IN_FUNCTION; - pn = Statements(cx, ts, tc); - - /* Check for falling off the end of a function that returns a value. */ - if (pn && JS_HAS_STRICT_OPTION(cx) && (tc->flags & TCF_RETURN_EXPR)) { - if (!CheckFinalReturn(cx, ts, pn)) - pn = NULL; - } - - cx->fp = fp; - tc->flags = oldflags | (tc->flags & (TCF_FUN_FLAGS | TCF_HAS_DEFXMLNS)); - return pn; -} - -/* - * Compile a JS function body, which might appear as the value of an event - * handler attribute in an HTML tag. - */ -JSBool -js_CompileFunctionBody(JSContext *cx, JSTokenStream *ts, JSFunction *fun) -{ - JSArenaPool codePool, notePool; - JSCodeGenerator funcg; - JSStackFrame *fp, frame; - JSObject *funobj; - JSParseNode *pn; - JSBool ok; - - JS_InitArenaPool(&codePool, "code", 1024, sizeof(jsbytecode)); - JS_InitArenaPool(¬ePool, "note", 1024, sizeof(jssrcnote)); - if (!js_InitCodeGenerator(cx, &funcg, &codePool, ¬ePool, - ts->filename, ts->lineno, - ts->principals)) { - return JS_FALSE; - } - - /* Prevent GC activation while compiling. */ - JS_KEEP_ATOMS(cx->runtime); - - /* Push a JSStackFrame for use by FunctionBody. */ - fp = cx->fp; - funobj = fun->object; - JS_ASSERT(!fp || (fp->fun != fun && fp->varobj != funobj && - fp->scopeChain != funobj)); - memset(&frame, 0, sizeof frame); - frame.fun = fun; - frame.varobj = frame.scopeChain = funobj; - frame.down = fp; - frame.flags = JS_HAS_COMPILE_N_GO_OPTION(cx) - ? JSFRAME_COMPILING | JSFRAME_COMPILE_N_GO - : JSFRAME_COMPILING; - cx->fp = &frame; - - /* Ensure that the body looks like a block statement to js_EmitTree. */ - CURRENT_TOKEN(ts).type = TOK_LC; - pn = FunctionBody(cx, ts, fun, &funcg.treeContext); - if (!pn) { - ok = JS_FALSE; - } else { - /* - * No need to emit code here -- Statements (via FunctionBody) already - * has. See similar comment in js_CompileTokenStream, and bug 108257. - */ - fun->u.script = js_NewScriptFromCG(cx, &funcg, fun); - if (!fun->u.script) { - ok = JS_FALSE; - } else { - fun->interpreted = JS_TRUE; - if (funcg.treeContext.flags & TCF_FUN_HEAVYWEIGHT) - fun->flags |= JSFUN_HEAVYWEIGHT; - ok = JS_TRUE; - } - } - - /* Restore saved state and release code generation arenas. */ - cx->fp = fp; - JS_UNKEEP_ATOMS(cx->runtime); - js_FinishCodeGenerator(cx, &funcg); - JS_FinishArenaPool(&codePool); - JS_FinishArenaPool(¬ePool); - return ok; -} - -static JSParseNode * -FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, - JSBool lambda) -{ - JSOp op, prevop; - JSParseNode *pn, *body, *result; - JSAtom *funAtom, *objAtom, *argAtom; - JSStackFrame *fp; - JSObject *varobj, *pobj; - JSAtomListElement *ale; - JSProperty *prop; - JSFunction *fun; - uintN dupflag; - JSBool ok; - JSTreeContext funtc; - - /* Make a TOK_FUNCTION node. */ -#if JS_HAS_GETTER_SETTER - op = CURRENT_TOKEN(ts).t_op; -#endif - pn = NewParseNode(cx, ts, PN_FUNC, tc); - if (!pn) - return NULL; - - /* Scan the optional function name into funAtom. */ - funAtom = js_MatchToken(cx, ts, TOK_NAME) ? CURRENT_TOKEN(ts).t_atom : NULL; -#if !JS_HAS_LEXICAL_CLOSURE - if (!funAtom && !lambda) { - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, - JSMSG_SYNTAX_ERROR); - return NULL; - } -#endif - - /* Find the nearest variable-declaring scope and use it as our parent. */ - fp = cx->fp; - varobj = fp->varobj; - - /* - * Record names for function statements in tc->decls so we know when to - * avoid optimizing variable references that might name a function. - */ - if (!lambda && funAtom) { - ATOM_LIST_SEARCH(ale, &tc->decls, funAtom); - if (ale) { - prevop = ALE_JSOP(ale); - if (JS_HAS_STRICT_OPTION(cx) || prevop == JSOP_DEFCONST) { - const char *name = js_AtomToPrintableString(cx, funAtom); - if (!name || - !js_ReportCompileErrorNumber(cx, ts, - (prevop != JSOP_DEFCONST) - ? JSREPORT_TS | - JSREPORT_WARNING | - JSREPORT_STRICT - : JSREPORT_TS | JSREPORT_ERROR, - JSMSG_REDECLARED_VAR, - (prevop == JSOP_DEFFUN || - prevop == JSOP_CLOSURE) - ? js_function_str - : (prevop == JSOP_DEFCONST) - ? js_const_str - : js_var_str, - name)) { - return NULL; - } - } - if (tc->topStmt && prevop == JSOP_DEFVAR) - tc->flags |= TCF_FUN_CLOSURE_VS_VAR; - } else { - ale = js_IndexAtom(cx, funAtom, &tc->decls); - if (!ale) - return NULL; - } - ALE_SET_JSOP(ale, tc->topStmt ? JSOP_CLOSURE : JSOP_DEFFUN); - -#if JS_HAS_LEXICAL_CLOSURE - /* - * A function nested at top level inside another's body needs only a - * local variable to bind its name to its value, and not an activation - * object property (it might also need the activation property, if the - * outer function contains with statements, e.g., but the stack slot - * wins when jsemit.c's BindNameToSlot can optimize a JSOP_NAME into a - * JSOP_GETVAR bytecode). - */ - if (!tc->topStmt && (tc->flags & TCF_IN_FUNCTION)) { - JSScopeProperty *sprop; - - /* - * Define a property on the outer function so that BindNameToSlot - * can properly optimize accesses. - */ - JS_ASSERT(OBJ_GET_CLASS(cx, varobj) == &js_FunctionClass); - JS_ASSERT(fp->fun == (JSFunction *) JS_GetPrivate(cx, varobj)); - if (!js_LookupHiddenProperty(cx, varobj, ATOM_TO_JSID(funAtom), - &pobj, &prop)) { - return NULL; - } - if (prop) - OBJ_DROP_PROPERTY(cx, pobj, prop); - sprop = NULL; - if (!prop || - pobj != varobj || - (sprop = (JSScopeProperty *)prop, - sprop->getter != js_GetLocalVariable)) { - uintN sflags; - - /* - * Use SPROP_IS_DUPLICATE if there is a formal argument of the - * same name, so the decompiler can find the parameter name. - */ - sflags = (sprop && sprop->getter == js_GetArgument) - ? SPROP_IS_DUPLICATE | SPROP_HAS_SHORTID - : SPROP_HAS_SHORTID; - if (!js_AddHiddenProperty(cx, varobj, ATOM_TO_JSID(funAtom), - js_GetLocalVariable, - js_SetLocalVariable, - SPROP_INVALID_SLOT, - JSPROP_PERMANENT | JSPROP_SHARED, - sflags, fp->fun->nvars)) { - return NULL; - } - if (fp->fun->nvars == JS_BITMASK(16)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_TOO_MANY_FUN_VARS); - return NULL; - } - fp->fun->nvars++; - } - } -#endif - } - - fun = js_NewFunction(cx, NULL, NULL, 0, lambda ? JSFUN_LAMBDA : 0, varobj, - funAtom); - if (!fun) - return NULL; -#if JS_HAS_GETTER_SETTER - if (op != JSOP_NOP) - fun->flags |= (op == JSOP_GETTER) ? JSPROP_GETTER : JSPROP_SETTER; -#endif - - - /* - * Set interpreted early so js_EmitTree can test it to decide whether to - * eliminate useless expressions. - */ - fun->interpreted = JS_TRUE; - - /* - * Atomize fun->object early to protect against a last-ditch GC under - * js_LookupHiddenProperty. - * - * Absent use of the new scoped local GC roots API around compiler calls, - * we need to atomize here to protect against a GC activation. Atoms are - * protected from GC during compilation by the JS_FRIEND_API entry points - * in this file. There doesn't seem to be any gain in switching from the - * atom-keeping method to the bulkier, slower scoped local roots method. - */ - objAtom = js_AtomizeObject(cx, fun->object, 0); - if (!objAtom) - return NULL; - - /* Now parse formal argument list and compute fun->nargs. */ - MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_FORMAL); - if (!js_MatchToken(cx, ts, TOK_RP)) { - do { - MUST_MATCH_TOKEN(TOK_NAME, JSMSG_MISSING_FORMAL); - argAtom = CURRENT_TOKEN(ts).t_atom; - pobj = NULL; - if (!js_LookupHiddenProperty(cx, fun->object, ATOM_TO_JSID(argAtom), - &pobj, &prop)) { - return NULL; - } - dupflag = 0; - if (prop) { - ok = JS_TRUE; - if (pobj == fun->object && - ((JSScopeProperty *) prop)->getter == js_GetArgument) { - const char *name = js_AtomToPrintableString(cx, argAtom); - - /* - * A duplicate parameter name. We force a duplicate node - * on the SCOPE_LAST_PROP(scope) list with the same id, - * distinguished by the SPROP_IS_DUPLICATE flag, and not - * mapped by an entry in scope. - */ - ok = name && - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | - JSREPORT_WARNING | - JSREPORT_STRICT, - JSMSG_DUPLICATE_FORMAL, - name); - - dupflag = SPROP_IS_DUPLICATE; - } - OBJ_DROP_PROPERTY(cx, pobj, prop); - if (!ok) - return NULL; - prop = NULL; - } - if (!js_AddHiddenProperty(cx, fun->object, ATOM_TO_JSID(argAtom), - js_GetArgument, js_SetArgument, - SPROP_INVALID_SLOT, - JSPROP_PERMANENT | JSPROP_SHARED, - dupflag | SPROP_HAS_SHORTID, - fun->nargs)) { - return NULL; - } - if (fun->nargs == JS_BITMASK(16)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_TOO_MANY_FUN_ARGS); - return NULL; - } - fun->nargs++; - } while (js_MatchToken(cx, ts, TOK_COMMA)); - - MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_FORMAL); - } - - MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_BODY); - pn->pn_pos.begin = CURRENT_TOKEN(ts).pos.begin; - - TREE_CONTEXT_INIT(&funtc); - body = FunctionBody(cx, ts, fun, &funtc); - if (!body) - return NULL; - - MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_BODY); - pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end; - -#if JS_HAS_LEXICAL_CLOSURE - /* - * If we collected flags that indicate nested heavyweight functions, or - * this function contains heavyweight-making statements (references to - * __parent__ or __proto__; use of with, eval, import, or export; and - * assignment to arguments), flag the function as heavyweight (requiring - * a call object per invocation). - */ - if (funtc.flags & TCF_FUN_HEAVYWEIGHT) { - fun->flags |= JSFUN_HEAVYWEIGHT; - tc->flags |= TCF_FUN_HEAVYWEIGHT; - } else { - /* - * If this function is a named statement function not at top-level - * (i.e. a JSOP_CLOSURE), or if it refers to unqualified names that - * are not local args or vars (TCF_FUN_USES_NONLOCALS), then our - * enclosing function, if any, must be heavyweight. - */ - if ((!lambda && funAtom && tc->topStmt) || - (funtc.flags & TCF_FUN_USES_NONLOCALS)) { - tc->flags |= TCF_FUN_HEAVYWEIGHT; - } - } -#endif - - result = pn; -#if JS_HAS_LEXICAL_CLOSURE - if (lambda) { - /* - * ECMA ed. 3 standard: function expression, possibly anonymous. - */ - op = funAtom ? JSOP_NAMEDFUNOBJ : JSOP_ANONFUNOBJ; - } else if (!funAtom) { - /* - * If this anonymous function definition is *not* embedded within a - * larger expression, we treat it as an expression statement, not as - * a function declaration -- and not as a syntax error (as ECMA-262 - * Edition 3 would have it). Backward compatibility trumps all. - */ - result = NewParseNode(cx, ts, PN_UNARY, tc); - if (!result) - return NULL; - result->pn_type = TOK_SEMI; - result->pn_pos = pn->pn_pos; - result->pn_kid = pn; - op = JSOP_ANONFUNOBJ; - } else if (tc->topStmt) { - /* - * ECMA ed. 3 extension: a function expression statement not at the - * top level, e.g., in a compound statement such as the "then" part - * of an "if" statement, binds a closure only if control reaches that - * sub-statement. - */ - op = JSOP_CLOSURE; - } else -#endif - op = JSOP_NOP; - - pn->pn_funAtom = objAtom; - pn->pn_op = op; - pn->pn_body = body; - pn->pn_flags = funtc.flags & (TCF_FUN_FLAGS | TCF_HAS_DEFXMLNS); - pn->pn_tryCount = funtc.tryCount; - TREE_CONTEXT_FINISH(&funtc); - return result; -} - -static JSParseNode * -FunctionStmt(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - return FunctionDef(cx, ts, tc, JS_FALSE); -} - -#if JS_HAS_LEXICAL_CLOSURE -static JSParseNode * -FunctionExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - return FunctionDef(cx, ts, tc, JS_TRUE); -} -#endif - -/* - * Parse the statements in a block, creating a TOK_LC node that lists the - * statements' trees. If called from block-parsing code, the caller must - * match { before and } after. - */ -static JSParseNode * -Statements(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - JSParseNode *pn, *pn2; - JSTokenType tt; - - CHECK_RECURSION(); - - pn = NewParseNode(cx, ts, PN_LIST, tc); - if (!pn) - return NULL; - PN_INIT_LIST(pn); - - ts->flags |= TSF_OPERAND; - while ((tt = js_PeekToken(cx, ts)) > TOK_EOF && tt != TOK_RC) { - ts->flags &= ~TSF_OPERAND; - pn2 = Statement(cx, ts, tc); - if (!pn2) { - if (ts->flags & TSF_EOF) - ts->flags |= TSF_UNEXPECTED_EOF; - return NULL; - } - ts->flags |= TSF_OPERAND; - - /* If compiling top-level statements, emit as we go to save space. */ - if (!tc->topStmt && (tc->flags & TCF_COMPILING)) { - if (cx->fp->fun && - JS_HAS_STRICT_OPTION(cx) && - (tc->flags & TCF_RETURN_EXPR)) { - /* - * Check pn2 for lack of a final return statement if it is the - * last statement in the block. - */ - tt = js_PeekToken(cx, ts); - if ((tt == TOK_EOF || tt == TOK_RC) && - !CheckFinalReturn(cx, ts, pn2)) { - tt = TOK_ERROR; - break; - } - - /* - * Clear TCF_RETURN_EXPR so FunctionBody doesn't try to - * CheckFinalReturn again. - */ - tc->flags &= ~TCF_RETURN_EXPR; - } - if (!js_FoldConstants(cx, pn2, tc) || - !js_AllocTryNotes(cx, (JSCodeGenerator *)tc) || - !js_EmitTree(cx, (JSCodeGenerator *)tc, pn2)) { - tt = TOK_ERROR; - break; - } - RecycleTree(pn2, tc); - } else { - PN_APPEND(pn, pn2); - } - } - ts->flags &= ~TSF_OPERAND; - if (tt == TOK_ERROR) - return NULL; - - pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end; - return pn; -} - -static JSParseNode * -Condition(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - JSParseNode *pn, *pn2; - - MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_COND); - pn = Expr(cx, ts, tc); - if (!pn) - return NULL; - MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_COND); - - /* - * Check for (a = b) and "correct" it to (a == b) iff b's operator has - * greater precedence than ==. - * XXX not ECMA, but documented in several books -- now a strict warning. - */ - if (pn->pn_type == TOK_ASSIGN && - pn->pn_op == JSOP_NOP && - pn->pn_right->pn_type > TOK_EQOP) - { - JSBool rewrite = !JS_VERSION_IS_ECMA(cx); - if (!js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | - JSREPORT_WARNING | - JSREPORT_STRICT, - JSMSG_EQUAL_AS_ASSIGN, - rewrite - ? "\nAssuming equality test" - : "")) { - return NULL; - } - if (rewrite) { - pn->pn_type = TOK_EQOP; - pn->pn_op = (JSOp)cx->jsop_eq; - pn2 = pn->pn_left; - switch (pn2->pn_op) { - case JSOP_SETNAME: - pn2->pn_op = JSOP_NAME; - break; - case JSOP_SETPROP: - pn2->pn_op = JSOP_GETPROP; - break; - case JSOP_SETELEM: - pn2->pn_op = JSOP_GETELEM; - break; - default: - JS_ASSERT(0); - } - } - } - return pn; -} - -static JSBool -MatchLabel(JSContext *cx, JSTokenStream *ts, JSParseNode *pn) -{ - JSAtom *label; -#if JS_HAS_LABEL_STATEMENT - JSTokenType tt; - - tt = js_PeekTokenSameLine(cx, ts); - if (tt == TOK_ERROR) - return JS_FALSE; - if (tt == TOK_NAME) { - (void) js_GetToken(cx, ts); - label = CURRENT_TOKEN(ts).t_atom; - } else { - label = NULL; - } -#else - label = NULL; -#endif - pn->pn_atom = label; - return JS_TRUE; -} - -#if JS_HAS_EXPORT_IMPORT -static JSParseNode * -ImportExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - JSParseNode *pn, *pn2; - JSTokenType tt; - - MUST_MATCH_TOKEN(TOK_NAME, JSMSG_NO_IMPORT_NAME); - pn = NewParseNode(cx, ts, PN_NAME, tc); - if (!pn) - return NULL; - pn->pn_op = JSOP_NAME; - pn->pn_atom = CURRENT_TOKEN(ts).t_atom; - pn->pn_expr = NULL; - pn->pn_slot = -1; - pn->pn_attrs = 0; - - ts->flags |= TSF_OPERAND; - while ((tt = js_GetToken(cx, ts)) == TOK_DOT || tt == TOK_LB) { - ts->flags &= ~TSF_OPERAND; - if (pn->pn_op == JSOP_IMPORTALL) - goto bad_import; - - if (tt == TOK_DOT) { - pn2 = NewParseNode(cx, ts, PN_NAME, tc); - if (!pn2) - return NULL; - if (js_MatchToken(cx, ts, TOK_STAR)) { - pn2->pn_op = JSOP_IMPORTALL; - pn2->pn_atom = NULL; - } else { - MUST_MATCH_TOKEN(TOK_NAME, JSMSG_NAME_AFTER_DOT); - pn2->pn_op = JSOP_GETPROP; - pn2->pn_atom = CURRENT_TOKEN(ts).t_atom; - pn2->pn_slot = -1; - pn2->pn_attrs = 0; - } - pn2->pn_expr = pn; - pn2->pn_pos.begin = pn->pn_pos.begin; - pn2->pn_pos.end = CURRENT_TOKEN(ts).pos.end; - } else { - /* Make a TOK_LB binary node. */ - pn2 = NewBinary(cx, tt, JSOP_GETELEM, pn, Expr(cx, ts, tc), tc); - if (!pn2) - return NULL; - - MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_IN_INDEX); - } - - pn = pn2; - ts->flags |= TSF_OPERAND; - } - ts->flags &= ~TSF_OPERAND; - if (tt == TOK_ERROR) - return NULL; - js_UngetToken(ts); - - switch (pn->pn_op) { - case JSOP_GETPROP: - pn->pn_op = JSOP_IMPORTPROP; - break; - case JSOP_GETELEM: - pn->pn_op = JSOP_IMPORTELEM; - break; - case JSOP_IMPORTALL: - break; - default: - goto bad_import; - } - return pn; - - bad_import: - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, - JSMSG_BAD_IMPORT); - return NULL; -} -#endif /* JS_HAS_EXPORT_IMPORT */ - -extern const char js_with_statement_str[]; - -static JSParseNode * -Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - JSTokenType tt; - JSParseNode *pn, *pn1, *pn2, *pn3, *pn4; - JSStmtInfo stmtInfo, *stmt, *stmt2; - JSAtom *label; - - CHECK_RECURSION(); - - ts->flags |= TSF_OPERAND; - tt = js_GetToken(cx, ts); - ts->flags &= ~TSF_OPERAND; - -#if JS_HAS_GETTER_SETTER - if (tt == TOK_NAME) { - tt = CheckGetterOrSetter(cx, ts, TOK_FUNCTION); - if (tt == TOK_ERROR) - return NULL; - } -#endif - - switch (tt) { -#if JS_HAS_EXPORT_IMPORT - case TOK_EXPORT: - pn = NewParseNode(cx, ts, PN_LIST, tc); - if (!pn) - return NULL; - PN_INIT_LIST(pn); - if (js_MatchToken(cx, ts, TOK_STAR)) { - pn2 = NewParseNode(cx, ts, PN_NULLARY, tc); - if (!pn2) - return NULL; - PN_APPEND(pn, pn2); - } else { - do { - MUST_MATCH_TOKEN(TOK_NAME, JSMSG_NO_EXPORT_NAME); - pn2 = NewParseNode(cx, ts, PN_NAME, tc); - if (!pn2) - return NULL; - pn2->pn_op = JSOP_NAME; - pn2->pn_atom = CURRENT_TOKEN(ts).t_atom; - pn2->pn_expr = NULL; - pn2->pn_slot = -1; - pn2->pn_attrs = 0; - PN_APPEND(pn, pn2); - } while (js_MatchToken(cx, ts, TOK_COMMA)); - } - pn->pn_pos.end = PN_LAST(pn)->pn_pos.end; - tc->flags |= TCF_FUN_HEAVYWEIGHT; - break; - - case TOK_IMPORT: - pn = NewParseNode(cx, ts, PN_LIST, tc); - if (!pn) - return NULL; - PN_INIT_LIST(pn); - do { - pn2 = ImportExpr(cx, ts, tc); - if (!pn2) - return NULL; - PN_APPEND(pn, pn2); - } while (js_MatchToken(cx, ts, TOK_COMMA)); - pn->pn_pos.end = PN_LAST(pn)->pn_pos.end; - tc->flags |= TCF_FUN_HEAVYWEIGHT; - break; -#endif /* JS_HAS_EXPORT_IMPORT */ - - case TOK_FUNCTION: -#if JS_HAS_XML_SUPPORT - if (js_PeekToken(cx, ts) == TOK_DBLCOLON) - goto expression; -#endif - return FunctionStmt(cx, ts, tc); - - case TOK_IF: - /* An IF node has three kids: condition, then, and optional else. */ - pn = NewParseNode(cx, ts, PN_TERNARY, tc); - if (!pn) - return NULL; - pn1 = Condition(cx, ts, tc); - if (!pn1) - return NULL; - js_PushStatement(tc, &stmtInfo, STMT_IF, -1); - pn2 = Statement(cx, ts, tc); - if (!pn2) - return NULL; - if (js_MatchToken(cx, ts, TOK_ELSE)) { - stmtInfo.type = STMT_ELSE; - pn3 = Statement(cx, ts, tc); - if (!pn3) - return NULL; - pn->pn_pos.end = pn3->pn_pos.end; - } else { - pn3 = NULL; - pn->pn_pos.end = pn2->pn_pos.end; - } - js_PopStatement(tc); - pn->pn_kid1 = pn1; - pn->pn_kid2 = pn2; - pn->pn_kid3 = pn3; - return pn; - -#if JS_HAS_SWITCH_STATEMENT - case TOK_SWITCH: - { - JSParseNode *pn5; - JSBool seenDefault = JS_FALSE; - - pn = NewParseNode(cx, ts, PN_BINARY, tc); - if (!pn) - return NULL; - MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_SWITCH); - - /* pn1 points to the switch's discriminant. */ - pn1 = Expr(cx, ts, tc); - if (!pn1) - return NULL; - - MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_SWITCH); - MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_SWITCH); - - /* pn2 is a list of case nodes. The default case has pn_left == NULL */ - pn2 = NewParseNode(cx, ts, PN_LIST, tc); - if (!pn2) - return NULL; - PN_INIT_LIST(pn2); - - js_PushStatement(tc, &stmtInfo, STMT_SWITCH, -1); - - while ((tt = js_GetToken(cx, ts)) != TOK_RC) { - switch (tt) { - case TOK_DEFAULT: - if (seenDefault) { - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_TOO_MANY_DEFAULTS); - return NULL; - } - seenDefault = JS_TRUE; - /* fall through */ - - case TOK_CASE: - pn3 = NewParseNode(cx, ts, PN_BINARY, tc); - if (!pn3) - return NULL; - if (tt == TOK_DEFAULT) { - pn3->pn_left = NULL; - } else { - pn3->pn_left = Expr(cx, ts, tc); - if (!pn3->pn_left) - return NULL; - } - PN_APPEND(pn2, pn3); - if (pn2->pn_count == JS_BIT(16)) { - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_TOO_MANY_CASES); - return NULL; - } - break; - - case TOK_ERROR: - return NULL; - - default: - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_BAD_SWITCH); - return NULL; - } - MUST_MATCH_TOKEN(TOK_COLON, JSMSG_COLON_AFTER_CASE); - - pn4 = NewParseNode(cx, ts, PN_LIST, tc); - if (!pn4) - return NULL; - pn4->pn_type = TOK_LC; - PN_INIT_LIST(pn4); - ts->flags |= TSF_OPERAND; - while ((tt = js_PeekToken(cx, ts)) != TOK_RC && - tt != TOK_CASE && tt != TOK_DEFAULT) { - ts->flags &= ~TSF_OPERAND; - if (tt == TOK_ERROR) - return NULL; - pn5 = Statement(cx, ts, tc); - if (!pn5) - return NULL; - pn4->pn_pos.end = pn5->pn_pos.end; - PN_APPEND(pn4, pn5); - ts->flags |= TSF_OPERAND; - } - ts->flags &= ~TSF_OPERAND; - - /* Fix the PN_LIST so it doesn't begin at the TOK_COLON. */ - if (pn4->pn_head) - pn4->pn_pos.begin = pn4->pn_head->pn_pos.begin; - pn3->pn_pos.end = pn4->pn_pos.end; - pn3->pn_right = pn4; - } - - js_PopStatement(tc); - - pn->pn_pos.end = pn2->pn_pos.end = CURRENT_TOKEN(ts).pos.end; - pn->pn_kid1 = pn1; - pn->pn_kid2 = pn2; - return pn; - } -#endif /* JS_HAS_SWITCH_STATEMENT */ - - case TOK_WHILE: - pn = NewParseNode(cx, ts, PN_BINARY, tc); - if (!pn) - return NULL; - js_PushStatement(tc, &stmtInfo, STMT_WHILE_LOOP, -1); - pn2 = Condition(cx, ts, tc); - if (!pn2) - return NULL; - pn->pn_left = pn2; - pn2 = Statement(cx, ts, tc); - if (!pn2) - return NULL; - js_PopStatement(tc); - pn->pn_pos.end = pn2->pn_pos.end; - pn->pn_right = pn2; - return pn; - -#if JS_HAS_DO_WHILE_LOOP - case TOK_DO: - pn = NewParseNode(cx, ts, PN_BINARY, tc); - if (!pn) - return NULL; - js_PushStatement(tc, &stmtInfo, STMT_DO_LOOP, -1); - pn2 = Statement(cx, ts, tc); - if (!pn2) - return NULL; - pn->pn_left = pn2; - MUST_MATCH_TOKEN(TOK_WHILE, JSMSG_WHILE_AFTER_DO); - pn2 = Condition(cx, ts, tc); - if (!pn2) - return NULL; - js_PopStatement(tc); - pn->pn_pos.end = pn2->pn_pos.end; - pn->pn_right = pn2; - if ((cx->version & JSVERSION_MASK) != JSVERSION_ECMA_3) { - /* - * All legacy and extended versions must do automatic semicolon - * insertion after do-while. See the testcase and discussion in - * http://bugzilla.mozilla.org/show_bug.cgi?id=238945. - */ - (void) js_MatchToken(cx, ts, TOK_SEMI); - return pn; - } - break; -#endif /* JS_HAS_DO_WHILE_LOOP */ - - case TOK_FOR: - /* A FOR node is binary, left is loop control and right is the body. */ - pn = NewParseNode(cx, ts, PN_BINARY, tc); - if (!pn) - return NULL; - js_PushStatement(tc, &stmtInfo, STMT_FOR_LOOP, -1); - -#if JS_HAS_XML_SUPPORT - pn->pn_op = JSOP_NOP; - if (js_MatchToken(cx, ts, TOK_NAME)) { - if (CURRENT_TOKEN(ts).t_atom == cx->runtime->atomState.eachAtom) - pn->pn_op = JSOP_FOREACH; - else - js_UngetToken(ts); - } -#endif - - MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_AFTER_FOR); - ts->flags |= TSF_OPERAND; - tt = js_PeekToken(cx, ts); - ts->flags &= ~TSF_OPERAND; - if (tt == TOK_SEMI) { -#if JS_HAS_XML_SUPPORT - if (pn->pn_op == JSOP_FOREACH) - goto bad_for_each; -#endif - - /* No initializer -- set first kid of left sub-node to null. */ - pn1 = NULL; - } else { - /* Set pn1 to a var list or an initializing expression. */ -#if JS_HAS_IN_OPERATOR - /* - * Set the TCF_IN_FOR_INIT flag during parsing of the first clause - * of the for statement. This flag will be used by the RelExpr - * production; if it is set, then the 'in' keyword will not be - * recognized as an operator, leaving it available to be parsed as - * part of a for/in loop. A side effect of this restriction is - * that (unparenthesized) expressions involving an 'in' operator - * are illegal in the init clause of an ordinary for loop. - */ - tc->flags |= TCF_IN_FOR_INIT; -#endif /* JS_HAS_IN_OPERATOR */ - if (tt == TOK_VAR) { - (void) js_GetToken(cx, ts); - pn1 = Variables(cx, ts, tc); - } else { - pn1 = Expr(cx, ts, tc); - } -#if JS_HAS_IN_OPERATOR - tc->flags &= ~TCF_IN_FOR_INIT; -#endif /* JS_HAS_IN_OPERATOR */ - if (!pn1) - return NULL; - } - - /* - * We can be sure that it's a for/in loop if there's still an 'in' - * keyword here, even if JavaScript recognizes 'in' as an operator, - * as we've excluded 'in' from being parsed in RelExpr by setting - * the TCF_IN_FOR_INIT flag in our JSTreeContext. - */ - if (pn1 && js_MatchToken(cx, ts, TOK_IN)) { - stmtInfo.type = STMT_FOR_IN_LOOP; - - /* Check that the left side of the 'in' is valid. */ - while (pn1->pn_type == TOK_RP) - pn1 = pn1->pn_kid; - if ((pn1->pn_type == TOK_VAR) - ? (pn1->pn_count > 1 || pn1->pn_op == JSOP_DEFCONST) - : (pn1->pn_type != TOK_NAME && - pn1->pn_type != TOK_DOT && -#if JS_HAS_LVALUE_RETURN - pn1->pn_type != TOK_LP && -#endif -#if JS_HAS_XML_SUPPORT - (pn1->pn_type != TOK_UNARYOP || - pn1->pn_op != JSOP_XMLNAME) && -#endif - pn1->pn_type != TOK_LB)) { - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_BAD_FOR_LEFTSIDE); - return NULL; - } - - if (pn1->pn_type == TOK_VAR) { - /* Tell js_EmitTree(TOK_VAR) that pn1 is part of a for/in. */ - pn1->pn_extra |= PNX_FORINVAR; - - /* Generate a final POP only if the var has an initializer. */ - pn2 = pn1->pn_head; - if (pn2->pn_expr) - pn1->pn_extra |= PNX_POPVAR; - } else { - pn2 = pn1; -#if JS_HAS_LVALUE_RETURN - if (pn2->pn_type == TOK_LP) - pn2->pn_op = JSOP_SETCALL; -#endif -#if JS_HAS_XML_SUPPORT - if (pn2->pn_type == TOK_UNARYOP) - pn2->pn_op = JSOP_BINDXMLNAME; -#endif - } - - /* Beware 'for (arguments in ...)' with or without a 'var'. */ - if (pn2->pn_type == TOK_NAME && - pn2->pn_atom == cx->runtime->atomState.argumentsAtom) { - tc->flags |= TCF_FUN_HEAVYWEIGHT; - } - - /* Parse the object expression as the right operand of 'in'. */ - pn2 = NewBinary(cx, TOK_IN, JSOP_NOP, pn1, Expr(cx, ts, tc), tc); - if (!pn2) - return NULL; - pn->pn_left = pn2; - } else { -#if JS_HAS_XML_SUPPORT - if (pn->pn_op == JSOP_FOREACH) - goto bad_for_each; -#endif - - /* Parse the loop condition or null into pn2. */ - MUST_MATCH_TOKEN(TOK_SEMI, JSMSG_SEMI_AFTER_FOR_INIT); - ts->flags |= TSF_OPERAND; - tt = js_PeekToken(cx, ts); - ts->flags &= ~TSF_OPERAND; - if (tt == TOK_SEMI) { - pn2 = NULL; - } else { - pn2 = Expr(cx, ts, tc); - if (!pn2) - return NULL; - } - - /* Parse the update expression or null into pn3. */ - MUST_MATCH_TOKEN(TOK_SEMI, JSMSG_SEMI_AFTER_FOR_COND); - ts->flags |= TSF_OPERAND; - tt = js_PeekToken(cx, ts); - ts->flags &= ~TSF_OPERAND; - if (tt == TOK_RP) { - pn3 = NULL; - } else { - pn3 = Expr(cx, ts, tc); - if (!pn3) - return NULL; - } - - /* Build the RESERVED node to use as the left kid of pn. */ - pn4 = NewParseNode(cx, ts, PN_TERNARY, tc); - if (!pn4) - return NULL; - pn4->pn_type = TOK_RESERVED; - pn4->pn_op = JSOP_NOP; - pn4->pn_kid1 = pn1; - pn4->pn_kid2 = pn2; - pn4->pn_kid3 = pn3; - pn->pn_left = pn4; - } - - MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_FOR_CTRL); - - /* Parse the loop body into pn->pn_right. */ - pn2 = Statement(cx, ts, tc); - if (!pn2) - return NULL; - pn->pn_right = pn2; - js_PopStatement(tc); - - /* Record the absolute line number for source note emission. */ - pn->pn_pos.end = pn2->pn_pos.end; - return pn; - -#if JS_HAS_XML_SUPPORT - bad_for_each: - js_ReportCompileErrorNumber(cx, pn, - JSREPORT_PN | JSREPORT_ERROR, - JSMSG_BAD_FOR_EACH_LOOP); - return NULL; -#endif - -#if JS_HAS_EXCEPTIONS - case TOK_TRY: { - JSParseNode *catchtail = NULL; - /* - * try nodes are ternary. - * kid1 is the try Statement - * kid2 is the catch node - * kid3 is the finally Statement - * - * catch nodes are ternary. - * kid1 is the discriminant - * kid2 is the next catch node, or NULL - * kid3 is the catch block (on kid3 so that we can always append a - * new catch pn on catchtail->kid2) - * - * catch discriminant nodes are binary - * atom is the receptacle - * expr is the discriminant code - * - * finally nodes are unary (just the finally expression) - */ - pn = NewParseNode(cx, ts, PN_TERNARY, tc); - pn->pn_op = JSOP_NOP; - - MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_TRY); - js_PushStatement(tc, &stmtInfo, STMT_TRY, -1); - pn->pn_kid1 = Statements(cx, ts, tc); - if (!pn->pn_kid1) - return NULL; - MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_TRY); - js_PopStatement(tc); - - catchtail = pn; - while (js_PeekToken(cx, ts) == TOK_CATCH) { - /* check for another catch after unconditional catch */ - if (catchtail != pn && !catchtail->pn_kid1->pn_expr) { - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_CATCH_AFTER_GENERAL); - return NULL; - } - - /* - * legal catch forms are: - * catch (v) - * catch (v if ) - * (the latter is legal only #ifdef JS_HAS_CATCH_GUARD) - */ - (void) js_GetToken(cx, ts); /* eat `catch' */ - pn2 = NewParseNode(cx, ts, PN_TERNARY, tc); - if (!pn2) - return NULL; - - /* - * We use a PN_NAME for the discriminant (catchguard) node - * with the actual discriminant code in the initializer spot - */ - MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_CATCH); - MUST_MATCH_TOKEN(TOK_NAME, JSMSG_CATCH_IDENTIFIER); - pn3 = NewParseNode(cx, ts, PN_NAME, tc); - if (!pn3) - return NULL; - - pn3->pn_atom = CURRENT_TOKEN(ts).t_atom; - pn3->pn_expr = NULL; -#if JS_HAS_CATCH_GUARD - /* - * We use `catch (x if x === 5)' (not `catch (x : x === 5)') to - * avoid conflicting with the JS2/ECMA2 proposed catchguard syntax. - */ - if (js_PeekToken(cx, ts) == TOK_IF) { - (void)js_GetToken(cx, ts); /* eat `if' */ - pn3->pn_expr = Expr(cx, ts, tc); - if (!pn3->pn_expr) - return NULL; - } -#endif - pn2->pn_kid1 = pn3; - - MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_CATCH); - - MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_CATCH); - js_PushStatement(tc, &stmtInfo, STMT_CATCH, -1); - stmtInfo.label = pn3->pn_atom; - pn2->pn_kid3 = Statements(cx, ts, tc); - if (!pn2->pn_kid3) - return NULL; - MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_CATCH); - js_PopStatement(tc); - - catchtail = catchtail->pn_kid2 = pn2; - } - catchtail->pn_kid2 = NULL; - - if (js_MatchToken(cx, ts, TOK_FINALLY)) { - tc->tryCount++; - MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_FINALLY); - js_PushStatement(tc, &stmtInfo, STMT_FINALLY, -1); - pn->pn_kid3 = Statements(cx, ts, tc); - if (!pn->pn_kid3) - return NULL; - MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_FINALLY); - js_PopStatement(tc); - } else { - pn->pn_kid3 = NULL; - } - if (!pn->pn_kid2 && !pn->pn_kid3) { - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, - JSMSG_CATCH_OR_FINALLY); - return NULL; - } - tc->tryCount++; - return pn; - } - - case TOK_THROW: - pn = NewParseNode(cx, ts, PN_UNARY, tc); - if (!pn) - return NULL; - - /* ECMA-262 Edition 3 says 'throw [no LineTerminator here] Expr'. */ - ts->flags |= TSF_OPERAND; - tt = js_PeekTokenSameLine(cx, ts); - ts->flags &= ~TSF_OPERAND; - if (tt == TOK_ERROR) - return NULL; - if (tt == TOK_EOF || tt == TOK_EOL || tt == TOK_SEMI || tt == TOK_RC) { - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, - JSMSG_SYNTAX_ERROR); - return NULL; - } - - pn2 = Expr(cx, ts, tc); - if (!pn2) - return NULL; - pn->pn_pos.end = pn2->pn_pos.end; - pn->pn_op = JSOP_THROW; - pn->pn_kid = pn2; - break; - - /* TOK_CATCH and TOK_FINALLY are both handled in the TOK_TRY case */ - case TOK_CATCH: - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, - JSMSG_CATCH_WITHOUT_TRY); - return NULL; - - case TOK_FINALLY: - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, - JSMSG_FINALLY_WITHOUT_TRY); - return NULL; - -#endif /* JS_HAS_EXCEPTIONS */ - - case TOK_BREAK: - pn = NewParseNode(cx, ts, PN_NULLARY, tc); - if (!pn) - return NULL; - if (!MatchLabel(cx, ts, pn)) - return NULL; - stmt = tc->topStmt; - label = pn->pn_atom; - if (label) { - for (; ; stmt = stmt->down) { - if (!stmt) { - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_LABEL_NOT_FOUND); - return NULL; - } - if (stmt->type == STMT_LABEL && stmt->label == label) - break; - } - } else { - for (; ; stmt = stmt->down) { - if (!stmt) { - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_TOUGH_BREAK); - return NULL; - } - if (STMT_IS_LOOP(stmt) || stmt->type == STMT_SWITCH) - break; - } - } - if (label) - pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end; - break; - - case TOK_CONTINUE: - pn = NewParseNode(cx, ts, PN_NULLARY, tc); - if (!pn) - return NULL; - if (!MatchLabel(cx, ts, pn)) - return NULL; - stmt = tc->topStmt; - label = pn->pn_atom; - if (label) { - for (stmt2 = NULL; ; stmt = stmt->down) { - if (!stmt) { - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_LABEL_NOT_FOUND); - return NULL; - } - if (stmt->type == STMT_LABEL) { - if (stmt->label == label) { - if (!stmt2 || !STMT_IS_LOOP(stmt2)) { - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | - JSREPORT_ERROR, - JSMSG_BAD_CONTINUE); - return NULL; - } - break; - } - } else { - stmt2 = stmt; - } - } - } else { - for (; ; stmt = stmt->down) { - if (!stmt) { - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_BAD_CONTINUE); - return NULL; - } - if (STMT_IS_LOOP(stmt)) - break; - } - } - if (label) - pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end; - break; - - case TOK_WITH: - pn = NewParseNode(cx, ts, PN_BINARY, tc); - if (!pn) - return NULL; - MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_WITH); - pn2 = Expr(cx, ts, tc); - if (!pn2) - return NULL; - MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_WITH); - pn->pn_left = pn2; - - js_PushStatement(tc, &stmtInfo, STMT_WITH, -1); - pn2 = Statement(cx, ts, tc); - if (!pn2) - return NULL; - js_PopStatement(tc); - - pn->pn_pos.end = pn2->pn_pos.end; - pn->pn_right = pn2; - tc->flags |= TCF_FUN_HEAVYWEIGHT; - return pn; - - case TOK_VAR: - pn = Variables(cx, ts, tc); - if (!pn) - return NULL; - - /* Tell js_EmitTree to generate a final POP. */ - pn->pn_extra |= PNX_POPVAR; - break; - - case TOK_RETURN: - if (!(tc->flags & TCF_IN_FUNCTION)) { - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, - JSMSG_BAD_RETURN); - return NULL; - } - pn = NewParseNode(cx, ts, PN_UNARY, tc); - if (!pn) - return NULL; - - /* This is ugly, but we don't want to require a semicolon. */ - ts->flags |= TSF_OPERAND; - tt = js_PeekTokenSameLine(cx, ts); - ts->flags &= ~TSF_OPERAND; - if (tt == TOK_ERROR) - return NULL; - - if (tt != TOK_EOF && tt != TOK_EOL && tt != TOK_SEMI && tt != TOK_RC) { - pn2 = Expr(cx, ts, tc); - if (!pn2) - return NULL; - tc->flags |= TCF_RETURN_EXPR; - pn->pn_pos.end = pn2->pn_pos.end; - pn->pn_kid = pn2; - } else { - tc->flags |= TCF_RETURN_VOID; - pn->pn_kid = NULL; - } - - if (JS_HAS_STRICT_OPTION(cx) && - (~tc->flags & (TCF_RETURN_EXPR | TCF_RETURN_VOID)) == 0) { - /* - * We must be in a frame with a non-native function, because - * we're compiling one. - */ - if (!ReportNoReturnValue(cx, ts)) - return NULL; - } - break; - - case TOK_LC: - js_PushStatement(tc, &stmtInfo, STMT_BLOCK, -1); - pn = Statements(cx, ts, tc); - if (!pn) - return NULL; - - MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_IN_COMPOUND); - js_PopStatement(tc); - return pn; - - case TOK_EOL: - case TOK_SEMI: - pn = NewParseNode(cx, ts, PN_UNARY, tc); - if (!pn) - return NULL; - pn->pn_type = TOK_SEMI; - pn->pn_kid = NULL; - return pn; - -#if JS_HAS_DEBUGGER_KEYWORD - case TOK_DEBUGGER: - pn = NewParseNode(cx, ts, PN_NULLARY, tc); - if (!pn) - return NULL; - pn->pn_type = TOK_DEBUGGER; - tc->flags |= TCF_FUN_HEAVYWEIGHT; - break; -#endif /* JS_HAS_DEBUGGER_KEYWORD */ - -#if JS_HAS_XML_SUPPORT - case TOK_DEFAULT: - pn = NewParseNode(cx, ts, PN_UNARY, tc); - if (!pn) - return NULL; - if (!js_MatchToken(cx, ts, TOK_NAME) || - CURRENT_TOKEN(ts).t_atom != cx->runtime->atomState.xmlAtom || - !js_MatchToken(cx, ts, TOK_NAME) || - CURRENT_TOKEN(ts).t_atom != cx->runtime->atomState.namespaceAtom || - !js_MatchToken(cx, ts, TOK_ASSIGN) || - CURRENT_TOKEN(ts).t_op != JSOP_NOP) { - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, - JSMSG_BAD_DEFAULT_XML_NAMESPACE); - return NULL; - } - pn2 = Expr(cx, ts, tc); - if (!pn2) - return NULL; - pn->pn_op = JSOP_DEFXMLNS; - pn->pn_pos.end = pn2->pn_pos.end; - pn->pn_kid = pn2; - tc->flags |= TCF_HAS_DEFXMLNS; - break; -#endif - - case TOK_ERROR: - return NULL; - - default: -#if JS_HAS_XML_SUPPORT - expression: -#endif - js_UngetToken(ts); - pn2 = Expr(cx, ts, tc); - if (!pn2) - return NULL; - - if (js_PeekToken(cx, ts) == TOK_COLON) { - if (pn2->pn_type != TOK_NAME) { - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_BAD_LABEL); - return NULL; - } - label = pn2->pn_atom; - for (stmt = tc->topStmt; stmt; stmt = stmt->down) { - if (stmt->type == STMT_LABEL && stmt->label == label) { - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_DUPLICATE_LABEL); - return NULL; - } - } - (void) js_GetToken(cx, ts); - - /* Push a label struct and parse the statement. */ - js_PushStatement(tc, &stmtInfo, STMT_LABEL, -1); - stmtInfo.label = label; - pn = Statement(cx, ts, tc); - if (!pn) - return NULL; - - /* Pop the label, set pn_expr, and return early. */ - js_PopStatement(tc); - pn2->pn_type = TOK_COLON; - pn2->pn_pos.end = pn->pn_pos.end; - pn2->pn_expr = pn; - return pn2; - } - - pn = NewParseNode(cx, ts, PN_UNARY, tc); - if (!pn) - return NULL; - pn->pn_type = TOK_SEMI; - pn->pn_pos = pn2->pn_pos; - pn->pn_kid = pn2; - break; - } - - /* Check termination of this primitive statement. */ - if (ON_CURRENT_LINE(ts, pn->pn_pos)) { - tt = js_PeekTokenSameLine(cx, ts); - if (tt == TOK_ERROR) - return NULL; - if (tt != TOK_EOF && tt != TOK_EOL && tt != TOK_SEMI && tt != TOK_RC) { - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, - JSMSG_SEMI_BEFORE_STMNT); - return NULL; - } - } - - (void) js_MatchToken(cx, ts, TOK_SEMI); - return pn; -} - -static JSParseNode * -Variables(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - JSParseNode *pn, *pn2; - JSObject *obj, *pobj; - JSStackFrame *fp; - JSFunction *fun; - JSClass *clasp; - JSPropertyOp getter, setter, currentGetter, currentSetter; - JSAtom *atom; - JSAtomListElement *ale; - JSOp prevop; - JSProperty *prop; - JSScopeProperty *sprop; - JSBool ok; - - /* - * The tricky part of this code is to create special parsenode opcodes for - * getting and setting variables (which will be stored as special slots in - * the frame). The complex special case is an eval() inside a function. - * If the evaluated string references variables in the enclosing function, - * then we need to generate the special variable opcodes. We determine - * this by looking up the variable id in the current variable scope. - */ - JS_ASSERT(CURRENT_TOKEN(ts).type == TOK_VAR); - pn = NewParseNode(cx, ts, PN_LIST, tc); - if (!pn) - return NULL; - pn->pn_op = CURRENT_TOKEN(ts).t_op; - PN_INIT_LIST(pn); - - /* - * Skip eval and debugger frames when looking for the function whose code - * is being compiled. If we are called from FunctionBody, TCF_IN_FUNCTION - * will be set in tc->flags, and we can be sure fp->fun is the function to - * use. But if a function calls eval, the string argument is treated as a - * Program (per ECMA), so TCF_IN_FUNCTION won't be set. - * - * What's more, when the following code is reached from eval, cx->fp->fun - * is eval's JSFunction (a native function), so we need to skip its frame. - * We should find the scripted caller's function frame just below it, but - * we code a loop out of paranoia. - */ - for (fp = cx->fp; (fp->flags & JSFRAME_SPECIAL) && fp->down; fp = fp->down) - continue; - obj = fp->varobj; - fun = fp->fun; - clasp = OBJ_GET_CLASS(cx, obj); - if (fun && clasp == &js_FunctionClass) { - /* We are compiling code inside a function */ - getter = js_GetLocalVariable; - setter = js_SetLocalVariable; - } else if (fun && clasp == &js_CallClass) { - /* We are compiling code from an eval inside a function */ - getter = js_GetCallVariable; - setter = js_SetCallVariable; - } else { - getter = clasp->getProperty; - setter = clasp->setProperty; - } - - ok = JS_TRUE; - do { - currentGetter = getter; - currentSetter = setter; - MUST_MATCH_TOKEN(TOK_NAME, JSMSG_NO_VARIABLE_NAME); - atom = CURRENT_TOKEN(ts).t_atom; - - ATOM_LIST_SEARCH(ale, &tc->decls, atom); - if (ale) { - prevop = ALE_JSOP(ale); - if (JS_HAS_STRICT_OPTION(cx) - ? pn->pn_op != JSOP_DEFVAR || prevop != JSOP_DEFVAR - : pn->pn_op == JSOP_DEFCONST || prevop == JSOP_DEFCONST) { - const char *name = js_AtomToPrintableString(cx, atom); - if (!name || - !js_ReportCompileErrorNumber(cx, ts, - (pn->pn_op != JSOP_DEFCONST && - prevop != JSOP_DEFCONST) - ? JSREPORT_TS | - JSREPORT_WARNING | - JSREPORT_STRICT - : JSREPORT_TS | JSREPORT_ERROR, - JSMSG_REDECLARED_VAR, - (prevop == JSOP_DEFFUN || - prevop == JSOP_CLOSURE) - ? js_function_str - : (prevop == JSOP_DEFCONST) - ? js_const_str - : js_var_str, - name)) { - return NULL; - } - } - if (pn->pn_op == JSOP_DEFVAR && prevop == JSOP_CLOSURE) - tc->flags |= TCF_FUN_CLOSURE_VS_VAR; - } else { - ale = js_IndexAtom(cx, atom, &tc->decls); - if (!ale) - return NULL; - } - ALE_SET_JSOP(ale, pn->pn_op); - - pn2 = NewParseNode(cx, ts, PN_NAME, tc); - if (!pn2) - return NULL; - pn2->pn_op = JSOP_NAME; - pn2->pn_atom = atom; - pn2->pn_expr = NULL; - pn2->pn_slot = -1; - pn2->pn_attrs = (pn->pn_op == JSOP_DEFCONST) - ? JSPROP_PERMANENT | JSPROP_READONLY - : JSPROP_PERMANENT; - PN_APPEND(pn, pn2); - - if (!fun) { - /* Don't lookup global variables at compile time. */ - prop = NULL; - } else if (OBJ_IS_NATIVE(obj)) { - if (!js_LookupHiddenProperty(cx, obj, ATOM_TO_JSID(atom), - &pobj, &prop)) { - return NULL; - } - } else { - if (!OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &pobj, &prop)) - return NULL; - } - if (prop && pobj == obj && OBJ_IS_NATIVE(pobj)) { - sprop = (JSScopeProperty *)prop; - if (sprop->getter == js_GetArgument) { - const char *name = js_AtomToPrintableString(cx, atom); - if (!name) { - ok = JS_FALSE; - } else if (pn->pn_op == JSOP_DEFCONST) { - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_REDECLARED_PARAM, - name); - ok = JS_FALSE; - } else { - currentGetter = js_GetArgument; - currentSetter = js_SetArgument; - ok = js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | - JSREPORT_WARNING | - JSREPORT_STRICT, - JSMSG_VAR_HIDES_ARG, - name); - } - } else { - if (fun) { - /* Not an argument, must be a redeclared local var. */ - if (clasp == &js_FunctionClass) { - JS_ASSERT(sprop->getter == js_GetLocalVariable); - JS_ASSERT((sprop->flags & SPROP_HAS_SHORTID) && - (uint16) sprop->shortid < fun->nvars); - } else if (clasp == &js_CallClass) { - if (sprop->getter == js_GetCallVariable) { - /* - * Referencing a variable introduced by a var - * statement in the enclosing function. Check - * that the slot number we have is in range. - */ - JS_ASSERT((sprop->flags & SPROP_HAS_SHORTID) && - (uint16) sprop->shortid < fun->nvars); - } else { - /* - * A variable introduced through another eval: - * don't use the special getters and setters - * since we can't allocate a slot in the frame. - */ - currentGetter = sprop->getter; - currentSetter = sprop->setter; - } - } - - /* Override the old getter and setter, to handle eval. */ - sprop = js_ChangeNativePropertyAttrs(cx, obj, sprop, - 0, sprop->attrs, - currentGetter, - currentSetter); - if (!sprop) - ok = JS_FALSE; - } - } - } else { - /* - * Property not found in current variable scope: we have not seen - * this variable before. Define a new local variable by adding a - * property to the function's scope, allocating one slot in the - * function's frame. Global variables and any locals declared in - * with statement bodies are handled at runtime, by script prolog - * JSOP_DEFVAR bytecodes generated for slot-less vars. - */ - sprop = NULL; - if (prop) { - OBJ_DROP_PROPERTY(cx, pobj, prop); - prop = NULL; - } - if (currentGetter == js_GetCallVariable) { - /* Can't increase fun->nvars in an active frame! */ - currentGetter = clasp->getProperty; - currentSetter = clasp->setProperty; - } - if (currentGetter == js_GetLocalVariable && - atom != cx->runtime->atomState.argumentsAtom && - fp->scopeChain == obj && - !js_InWithStatement(tc)) { - if (!js_AddHiddenProperty(cx, obj, ATOM_TO_JSID(atom), - currentGetter, currentSetter, - SPROP_INVALID_SLOT, - pn2->pn_attrs | JSPROP_SHARED, - SPROP_HAS_SHORTID, fun->nvars)) { - return NULL; - } - if (fun->nvars == JS_BITMASK(16)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_TOO_MANY_FUN_VARS); - return NULL; - } - fun->nvars++; - } - } - - if (js_MatchToken(cx, ts, TOK_ASSIGN)) { - if (CURRENT_TOKEN(ts).t_op != JSOP_NOP) { - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_BAD_VAR_INIT); - ok = JS_FALSE; - } else { - pn2->pn_expr = AssignExpr(cx, ts, tc); - if (!pn2->pn_expr) { - ok = JS_FALSE; - } else { - pn2->pn_op = (pn->pn_op == JSOP_DEFCONST) - ? JSOP_SETCONST - : JSOP_SETNAME; - if (atom == cx->runtime->atomState.argumentsAtom) - tc->flags |= TCF_FUN_HEAVYWEIGHT; - } - } - } - - if (prop) - OBJ_DROP_PROPERTY(cx, pobj, prop); - if (!ok) - return NULL; - } while (js_MatchToken(cx, ts, TOK_COMMA)); - - pn->pn_pos.end = PN_LAST(pn)->pn_pos.end; - return pn; -} - -static JSParseNode * -Expr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - JSParseNode *pn, *pn2; - - pn = AssignExpr(cx, ts, tc); - if (pn && js_MatchToken(cx, ts, TOK_COMMA)) { - pn2 = NewParseNode(cx, ts, PN_LIST, tc); - if (!pn2) - return NULL; - pn2->pn_pos.begin = pn->pn_pos.begin; - PN_INIT_LIST_1(pn2, pn); - pn = pn2; - do { - pn2 = AssignExpr(cx, ts, tc); - if (!pn2) - return NULL; - PN_APPEND(pn, pn2); - } while (js_MatchToken(cx, ts, TOK_COMMA)); - pn->pn_pos.end = PN_LAST(pn)->pn_pos.end; - } - return pn; -} - -static JSParseNode * -AssignExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - JSParseNode *pn, *pn2; - JSTokenType tt; - JSOp op; - - CHECK_RECURSION(); - - pn = CondExpr(cx, ts, tc); - if (!pn) - return NULL; - - tt = js_GetToken(cx, ts); -#if JS_HAS_GETTER_SETTER - if (tt == TOK_NAME) { - tt = CheckGetterOrSetter(cx, ts, TOK_ASSIGN); - if (tt == TOK_ERROR) - return NULL; - } -#endif - if (tt != TOK_ASSIGN) { - js_UngetToken(ts); - return pn; - } - - op = CURRENT_TOKEN(ts).t_op; - for (pn2 = pn; pn2->pn_type == TOK_RP; pn2 = pn2->pn_kid) - continue; - switch (pn2->pn_type) { - case TOK_NAME: - pn2->pn_op = JSOP_SETNAME; - if (pn2->pn_atom == cx->runtime->atomState.argumentsAtom) - tc->flags |= TCF_FUN_HEAVYWEIGHT; - break; - case TOK_DOT: - pn2->pn_op = (pn2->pn_op == JSOP_GETMETHOD) - ? JSOP_SETMETHOD - : JSOP_SETPROP; - break; - case TOK_LB: - pn2->pn_op = JSOP_SETELEM; - break; -#if JS_HAS_LVALUE_RETURN - case TOK_LP: - pn2->pn_op = JSOP_SETCALL; - break; -#endif -#if JS_HAS_XML_SUPPORT - case TOK_UNARYOP: - if (pn2->pn_op == JSOP_XMLNAME) { - pn2->pn_op = JSOP_SETXMLNAME; - break; - } - /* FALL THROUGH */ -#endif - default: - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, - JSMSG_BAD_LEFTSIDE_OF_ASS); - return NULL; - } - pn = NewBinary(cx, TOK_ASSIGN, op, pn2, AssignExpr(cx, ts, tc), tc); - return pn; -} - -static JSParseNode * -CondExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - JSParseNode *pn, *pn1, *pn2, *pn3; -#if JS_HAS_IN_OPERATOR - uintN oldflags; -#endif /* JS_HAS_IN_OPERATOR */ - - pn = OrExpr(cx, ts, tc); - if (pn && js_MatchToken(cx, ts, TOK_HOOK)) { - pn1 = pn; - pn = NewParseNode(cx, ts, PN_TERNARY, tc); - if (!pn) - return NULL; -#if JS_HAS_IN_OPERATOR - /* - * Always accept the 'in' operator in the middle clause of a ternary, - * where it's unambiguous, even if we might be parsing the init of a - * for statement. - */ - oldflags = tc->flags; - tc->flags &= ~TCF_IN_FOR_INIT; -#endif /* JS_HAS_IN_OPERATOR */ - pn2 = AssignExpr(cx, ts, tc); -#if JS_HAS_IN_OPERATOR - tc->flags = oldflags | (tc->flags & TCF_FUN_FLAGS); -#endif /* JS_HAS_IN_OPERATOR */ - - if (!pn2) - return NULL; - MUST_MATCH_TOKEN(TOK_COLON, JSMSG_COLON_IN_COND); - pn3 = AssignExpr(cx, ts, tc); - if (!pn3) - return NULL; - pn->pn_pos.begin = pn1->pn_pos.begin; - pn->pn_pos.end = pn3->pn_pos.end; - pn->pn_kid1 = pn1; - pn->pn_kid2 = pn2; - pn->pn_kid3 = pn3; - } - return pn; -} - -static JSParseNode * -OrExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - JSParseNode *pn; - - pn = AndExpr(cx, ts, tc); - if (pn && js_MatchToken(cx, ts, TOK_OR)) - pn = NewBinary(cx, TOK_OR, JSOP_OR, pn, OrExpr(cx, ts, tc), tc); - return pn; -} - -static JSParseNode * -AndExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - JSParseNode *pn; - - pn = BitOrExpr(cx, ts, tc); - if (pn && js_MatchToken(cx, ts, TOK_AND)) - pn = NewBinary(cx, TOK_AND, JSOP_AND, pn, AndExpr(cx, ts, tc), tc); - return pn; -} - -static JSParseNode * -BitOrExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - JSParseNode *pn; - - pn = BitXorExpr(cx, ts, tc); - while (pn && js_MatchToken(cx, ts, TOK_BITOR)) { - pn = NewBinary(cx, TOK_BITOR, JSOP_BITOR, pn, BitXorExpr(cx, ts, tc), - tc); - } - return pn; -} - -static JSParseNode * -BitXorExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - JSParseNode *pn; - - pn = BitAndExpr(cx, ts, tc); - while (pn && js_MatchToken(cx, ts, TOK_BITXOR)) { - pn = NewBinary(cx, TOK_BITXOR, JSOP_BITXOR, pn, BitAndExpr(cx, ts, tc), - tc); - } - return pn; -} - -static JSParseNode * -BitAndExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - JSParseNode *pn; - - pn = EqExpr(cx, ts, tc); - while (pn && js_MatchToken(cx, ts, TOK_BITAND)) - pn = NewBinary(cx, TOK_BITAND, JSOP_BITAND, pn, EqExpr(cx, ts, tc), tc); - return pn; -} - -static JSParseNode * -EqExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - JSParseNode *pn; - JSOp op; - - pn = RelExpr(cx, ts, tc); - while (pn && js_MatchToken(cx, ts, TOK_EQOP)) { - op = CURRENT_TOKEN(ts).t_op; - pn = NewBinary(cx, TOK_EQOP, op, pn, RelExpr(cx, ts, tc), tc); - } - return pn; -} - -static JSParseNode * -RelExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - JSParseNode *pn; - JSTokenType tt; - JSOp op; -#if JS_HAS_IN_OPERATOR - uintN inForInitFlag = tc->flags & TCF_IN_FOR_INIT; - - /* - * Uses of the in operator in ShiftExprs are always unambiguous, - * so unset the flag that prohibits recognizing it. - */ - tc->flags &= ~TCF_IN_FOR_INIT; -#endif /* JS_HAS_IN_OPERATOR */ - - pn = ShiftExpr(cx, ts, tc); - while (pn && - (js_MatchToken(cx, ts, TOK_RELOP) -#if JS_HAS_IN_OPERATOR - /* - * Recognize the 'in' token as an operator only if we're not - * currently in the init expr of a for loop. - */ - || (inForInitFlag == 0 && js_MatchToken(cx, ts, TOK_IN)) -#endif /* JS_HAS_IN_OPERATOR */ -#if JS_HAS_INSTANCEOF - || js_MatchToken(cx, ts, TOK_INSTANCEOF) -#endif /* JS_HAS_INSTANCEOF */ - )) { - tt = CURRENT_TOKEN(ts).type; - op = CURRENT_TOKEN(ts).t_op; - pn = NewBinary(cx, tt, op, pn, ShiftExpr(cx, ts, tc), tc); - } -#if JS_HAS_IN_OPERATOR - /* Restore previous state of inForInit flag. */ - tc->flags |= inForInitFlag; -#endif /* JS_HAS_IN_OPERATOR */ - - return pn; -} - -static JSParseNode * -ShiftExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - JSParseNode *pn; - JSOp op; - - pn = AddExpr(cx, ts, tc); - while (pn && js_MatchToken(cx, ts, TOK_SHOP)) { - op = CURRENT_TOKEN(ts).t_op; - pn = NewBinary(cx, TOK_SHOP, op, pn, AddExpr(cx, ts, tc), tc); - } - return pn; -} - -static JSParseNode * -AddExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - JSParseNode *pn; - JSTokenType tt; - JSOp op; - - pn = MulExpr(cx, ts, tc); - while (pn && - (js_MatchToken(cx, ts, TOK_PLUS) || - js_MatchToken(cx, ts, TOK_MINUS))) { - tt = CURRENT_TOKEN(ts).type; - op = (tt == TOK_PLUS) ? JSOP_ADD : JSOP_SUB; - pn = NewBinary(cx, tt, op, pn, MulExpr(cx, ts, tc), tc); - } - return pn; -} - -static JSParseNode * -MulExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - JSParseNode *pn; - JSTokenType tt; - JSOp op; - - pn = UnaryExpr(cx, ts, tc); - while (pn && - (js_MatchToken(cx, ts, TOK_STAR) || - js_MatchToken(cx, ts, TOK_DIVOP))) { - tt = CURRENT_TOKEN(ts).type; - op = CURRENT_TOKEN(ts).t_op; - pn = NewBinary(cx, tt, op, pn, UnaryExpr(cx, ts, tc), tc); - } - return pn; -} - -static JSParseNode * -SetLvalKid(JSContext *cx, JSTokenStream *ts, JSParseNode *pn, JSParseNode *kid, - const char *name) -{ - while (kid->pn_type == TOK_RP) - kid = kid->pn_kid; - if (kid->pn_type != TOK_NAME && - kid->pn_type != TOK_DOT && -#if JS_HAS_LVALUE_RETURN - (kid->pn_type != TOK_LP || kid->pn_op != JSOP_CALL) && -#endif -#if JS_HAS_XML_SUPPORT - (kid->pn_type != TOK_UNARYOP || kid->pn_op != JSOP_XMLNAME) && -#endif - kid->pn_type != TOK_LB) { - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, - JSMSG_BAD_OPERAND, name); - return NULL; - } - pn->pn_kid = kid; - return kid; -} - -static const char *incop_name_str[] = {"increment", "decrement"}; - -static JSBool -SetIncOpKid(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, - JSParseNode *pn, JSParseNode *kid, - JSTokenType tt, JSBool preorder) -{ - JSOp op; - - kid = SetLvalKid(cx, ts, pn, kid, incop_name_str[tt == TOK_DEC]); - if (!kid) - return JS_FALSE; - switch (kid->pn_type) { - case TOK_NAME: - op = (tt == TOK_INC) - ? (preorder ? JSOP_INCNAME : JSOP_NAMEINC) - : (preorder ? JSOP_DECNAME : JSOP_NAMEDEC); - if (kid->pn_atom == cx->runtime->atomState.argumentsAtom) - tc->flags |= TCF_FUN_HEAVYWEIGHT; - break; - - case TOK_DOT: - op = (tt == TOK_INC) - ? (preorder ? JSOP_INCPROP : JSOP_PROPINC) - : (preorder ? JSOP_DECPROP : JSOP_PROPDEC); - break; - -#if JS_HAS_LVALUE_RETURN - case TOK_LP: - JS_ASSERT(kid->pn_op == JSOP_CALL); - kid->pn_op = JSOP_SETCALL; - /* FALL THROUGH */ -#endif -#if JS_HAS_XML_SUPPORT - case TOK_UNARYOP: - if (kid->pn_op == JSOP_XMLNAME) - kid->pn_op = JSOP_SETXMLNAME; - /* FALL THROUGH */ -#endif - case TOK_LB: - op = (tt == TOK_INC) - ? (preorder ? JSOP_INCELEM : JSOP_ELEMINC) - : (preorder ? JSOP_DECELEM : JSOP_ELEMDEC); - break; - - default: - JS_ASSERT(0); - op = JSOP_NOP; - } - pn->pn_op = op; - return JS_TRUE; -} - -static JSParseNode * -UnaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - JSTokenType tt; - JSParseNode *pn, *pn2; - - CHECK_RECURSION(); - - ts->flags |= TSF_OPERAND; - tt = js_GetToken(cx, ts); - ts->flags &= ~TSF_OPERAND; - - switch (tt) { - case TOK_UNARYOP: - case TOK_PLUS: - case TOK_MINUS: - pn = NewParseNode(cx, ts, PN_UNARY, tc); - if (!pn) - return NULL; - pn->pn_type = TOK_UNARYOP; /* PLUS and MINUS are binary */ - pn->pn_op = CURRENT_TOKEN(ts).t_op; - pn2 = UnaryExpr(cx, ts, tc); - if (!pn2) - return NULL; - pn->pn_pos.end = pn2->pn_pos.end; - pn->pn_kid = pn2; - break; - - case TOK_INC: - case TOK_DEC: - pn = NewParseNode(cx, ts, PN_UNARY, tc); - if (!pn) - return NULL; - pn2 = MemberExpr(cx, ts, tc, JS_TRUE); - if (!pn2) - return NULL; - if (!SetIncOpKid(cx, ts, tc, pn, pn2, tt, JS_TRUE)) - return NULL; - pn->pn_pos.end = pn2->pn_pos.end; - break; - - case TOK_DELETE: - pn = NewParseNode(cx, ts, PN_UNARY, tc); - if (!pn) - return NULL; - pn2 = UnaryExpr(cx, ts, tc); - if (!pn2) - return NULL; - pn->pn_pos.end = pn2->pn_pos.end; - - /* - * Under ECMA3, deleting any unary expression is valid -- it simply - * returns true. Here we strip off any parentheses. - */ - while (pn2->pn_type == TOK_RP) - pn2 = pn2->pn_kid; - pn->pn_kid = pn2; - break; - - case TOK_ERROR: - return NULL; - - default: - js_UngetToken(ts); - pn = MemberExpr(cx, ts, tc, JS_TRUE); - if (!pn) - return NULL; - - /* Don't look across a newline boundary for a postfix incop. */ - if (ON_CURRENT_LINE(ts, pn->pn_pos)) { - tt = js_PeekTokenSameLine(cx, ts); - if (tt == TOK_INC || tt == TOK_DEC) { - (void) js_GetToken(cx, ts); - pn2 = NewParseNode(cx, ts, PN_UNARY, tc); - if (!pn2) - return NULL; - if (!SetIncOpKid(cx, ts, tc, pn2, pn, tt, JS_FALSE)) - return NULL; - pn2->pn_pos.begin = pn->pn_pos.begin; - pn = pn2; - } - } - break; - } - return pn; -} - -static JSBool -ArgumentList(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, - JSParseNode *listNode) -{ - JSBool matched; - - ts->flags |= TSF_OPERAND; - matched = js_MatchToken(cx, ts, TOK_RP); - ts->flags &= ~TSF_OPERAND; - if (!matched) { - do { - JSParseNode *argNode = AssignExpr(cx, ts, tc); - if (!argNode) - return JS_FALSE; - PN_APPEND(listNode, argNode); - } while (js_MatchToken(cx, ts, TOK_COMMA)); - - if (js_GetToken(cx, ts) != TOK_RP) { - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, - JSMSG_PAREN_AFTER_ARGS); - return JS_FALSE; - } - } - return JS_TRUE; -} - -static JSParseNode * -MemberExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, - JSBool allowCallSyntax) -{ - JSParseNode *pn, *pn2, *pn3; - JSTokenType tt; - - CHECK_RECURSION(); - - /* Check for new expression first. */ - ts->flags |= TSF_OPERAND; - tt = js_PeekToken(cx, ts); - ts->flags &= ~TSF_OPERAND; - if (tt == TOK_NEW) { - (void) js_GetToken(cx, ts); - - pn = NewParseNode(cx, ts, PN_LIST, tc); - if (!pn) - return NULL; - pn2 = MemberExpr(cx, ts, tc, JS_FALSE); - if (!pn2) - return NULL; - pn->pn_op = JSOP_NEW; - PN_INIT_LIST_1(pn, pn2); - pn->pn_pos.begin = pn2->pn_pos.begin; - - if (js_MatchToken(cx, ts, TOK_LP) && !ArgumentList(cx, ts, tc, pn)) - return NULL; - if (pn->pn_count > ARGC_LIMIT) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_TOO_MANY_CON_ARGS); - return NULL; - } - pn->pn_pos.end = PN_LAST(pn)->pn_pos.end; - } else { - pn = PrimaryExpr(cx, ts, tc); - if (!pn) - return NULL; - - if (pn->pn_type == TOK_ANYNAME || - pn->pn_type == TOK_AT || - pn->pn_type == TOK_DBLCOLON) { - pn2 = NewOrRecycledNode(cx, tc); - if (!pn2) - return NULL; - pn2->pn_type = TOK_UNARYOP; - pn2->pn_pos = pn->pn_pos; - pn2->pn_op = JSOP_XMLNAME; - pn2->pn_arity = PN_UNARY; - pn2->pn_kid = pn; - pn2->pn_next = NULL; -#if JS_HAS_XML_SUPPORT - pn2->pn_ts = ts; -#endif - pn = pn2; - } - } - - while ((tt = js_GetToken(cx, ts)) > TOK_EOF) { - if (tt == TOK_DOT) { - pn2 = NewParseNode(cx, ts, PN_NAME, tc); - if (!pn2) - return NULL; -#if JS_HAS_XML_SUPPORT - pn3 = PrimaryExpr(cx, ts, tc); - if (!pn3) - return NULL; - tt = pn3->pn_type; - if (tt == TOK_NAME || - (tt == TOK_DBLCOLON && - pn3->pn_arity == PN_NAME && - pn3->pn_expr->pn_type == TOK_FUNCTION)) { - pn2->pn_op = (tt == TOK_NAME) ? JSOP_GETPROP : JSOP_GETMETHOD; - pn2->pn_expr = pn; - pn2->pn_atom = pn3->pn_atom; - RecycleTree(pn3, tc); - } else { - if (TOKEN_TYPE_IS_XML(tt)) { - pn2->pn_type = TOK_LB; - pn2->pn_op = JSOP_GETELEM; - } else if (tt == TOK_RP) { - JSParseNode *group = pn3; - - /* Recycle the useless TOK_RP/JSOP_GROUP node. */ - pn3 = group->pn_kid; - group->pn_kid = NULL; - RecycleTree(group, tc); - pn2->pn_type = TOK_FILTER; - pn2->pn_op = JSOP_FILTER; - } else { - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_NAME_AFTER_DOT); - return NULL; - } - pn2->pn_arity = PN_BINARY; - pn2->pn_left = pn; - pn2->pn_right = pn3; - } -#else - MUST_MATCH_TOKEN(TOK_NAME, JSMSG_NAME_AFTER_DOT); - pn2->pn_op = JSOP_GETPROP; - pn2->pn_expr = pn; - pn2->pn_atom = CURRENT_TOKEN(ts).t_atom; -#endif - pn2->pn_pos.begin = pn->pn_pos.begin; - pn2->pn_pos.end = CURRENT_TOKEN(ts).pos.end; -#if JS_HAS_XML_SUPPORT - } else if (tt == TOK_DBLDOT) { - pn2 = NewParseNode(cx, ts, PN_BINARY, tc); - if (!pn2) - return NULL; - pn3 = PrimaryExpr(cx, ts, tc); - if (!pn3) - return NULL; - tt = pn3->pn_type; - if (tt == TOK_NAME) { - pn3->pn_type = TOK_STRING; - pn3->pn_arity = PN_NULLARY; - pn3->pn_op = JSOP_STRING; - } else if (!TOKEN_TYPE_IS_XML(tt)) { - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_NAME_AFTER_DOT); - return NULL; - } - pn2->pn_op = JSOP_DESCENDANTS; - pn2->pn_left = pn; - pn2->pn_right = pn3; - pn2->pn_pos.begin = pn->pn_pos.begin; - pn2->pn_pos.end = CURRENT_TOKEN(ts).pos.end; -#endif - } else if (tt == TOK_LB) { - pn2 = NewParseNode(cx, ts, PN_BINARY, tc); - if (!pn2) - return NULL; - pn3 = Expr(cx, ts, tc); - if (!pn3) - return NULL; - - MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_IN_INDEX); - pn2->pn_pos.begin = pn->pn_pos.begin; - pn2->pn_pos.end = CURRENT_TOKEN(ts).pos.end; - - /* Optimize o['p'] to o.p by rewriting pn2. */ - if (pn3->pn_type == TOK_STRING) { - pn2->pn_type = TOK_DOT; - pn2->pn_op = JSOP_GETPROP; - pn2->pn_arity = PN_NAME; - pn2->pn_expr = pn; - pn2->pn_atom = pn3->pn_atom; - } else { - pn2->pn_op = JSOP_GETELEM; - pn2->pn_left = pn; - pn2->pn_right = pn3; - } - } else if (allowCallSyntax && tt == TOK_LP) { - pn2 = NewParseNode(cx, ts, PN_LIST, tc); - if (!pn2) - return NULL; - - /* Pick JSOP_EVAL and flag tc as heavyweight if eval(...). */ - pn2->pn_op = JSOP_CALL; - if (pn->pn_op == JSOP_NAME && - pn->pn_atom == cx->runtime->atomState.evalAtom) { - pn2->pn_op = JSOP_EVAL; - tc->flags |= TCF_FUN_HEAVYWEIGHT; - } - - PN_INIT_LIST_1(pn2, pn); - pn2->pn_pos.begin = pn->pn_pos.begin; - - if (!ArgumentList(cx, ts, tc, pn2)) - return NULL; - if (pn2->pn_count > ARGC_LIMIT) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_TOO_MANY_FUN_ARGS); - return NULL; - } - pn2->pn_pos.end = CURRENT_TOKEN(ts).pos.end; - } else { - js_UngetToken(ts); - return pn; - } - - pn = pn2; - } - if (tt == TOK_ERROR) - return NULL; - return pn; -} - -static JSParseNode * -BracketedExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - uintN oldflags; - JSParseNode *pn; - -#if JS_HAS_IN_OPERATOR - /* - * Always accept the 'in' operator in a parenthesized expression, - * where it's unambiguous, even if we might be parsing the init of a - * for statement. - */ - oldflags = tc->flags; - tc->flags &= ~TCF_IN_FOR_INIT; -#endif - pn = Expr(cx, ts, tc); -#if JS_HAS_IN_OPERATOR - tc->flags = oldflags | (tc->flags & TCF_FUN_FLAGS); -#endif - return pn; -} - -#if JS_HAS_XML_SUPPORT - -static JSParseNode * -EndBracketedExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - JSParseNode *pn; - - pn = BracketedExpr(cx, ts, tc); - if (!pn) - return NULL; - - MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_AFTER_ATTR_EXPR); - return pn; -} - -/* - * From the ECMA-357 grammar in 11.1.1 and 11.1.2: - * - * AttributeIdentifier: - * @ PropertySelector - * @ QualifiedIdentifier - * @ [ Expression ] - * - * PropertySelector: - * Identifier - * * - * - * QualifiedIdentifier: - * PropertySelector :: PropertySelector - * PropertySelector :: [ Expression ] - * - * We adapt AttributeIdentifier and QualifiedIdentier to be LL(1), like so: - * - * AttributeIdentifier: - * @ QualifiedIdentifier - * @ [ Expression ] - * - * PropertySelector: - * Identifier - * * - * - * QualifiedIdentifier: - * PropertySelector :: PropertySelector - * PropertySelector :: [ Expression ] - * PropertySelector - * - * Since PrimaryExpression: Identifier in ECMA-262 and we want the semantics - * for that rule to result in a name node, but extend the grammar to include - * PrimaryExpression: QualifiedIdentifier, we factor further: - * - * QualifiedIdentifier: - * PropertySelector QualifiedSuffix - * - * QualifiedSuffix: - * :: PropertySelector - * :: [ Expression ] - * /nothing/ - * - * And use this production instead of PrimaryExpression: QualifiedIdentifier: - * - * PrimaryExpression: - * Identifier QualifiedSuffix - * - * We hoists the :: match into callers of QualifiedSuffix, in order to tweak - * PropertySelector vs. Identifier pn_arity, pn_op, and other members. - */ -static JSParseNode * -PropertySelector(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - JSParseNode *pn; - - pn = NewParseNode(cx, ts, PN_NULLARY, tc); - if (!pn) - return NULL; - if (pn->pn_type == TOK_STAR) { - pn->pn_type = TOK_ANYNAME; - pn->pn_op = JSOP_ANYNAME; - pn->pn_atom = cx->runtime->atomState.starAtom; - } else { - JS_ASSERT(pn->pn_type == TOK_NAME); - pn->pn_op = JSOP_QNAMEPART; - pn->pn_arity = PN_NAME; - pn->pn_atom = CURRENT_TOKEN(ts).t_atom; - pn->pn_expr = NULL; - pn->pn_slot = -1; - pn->pn_attrs = 0; - } - return pn; -} - -static JSParseNode * -QualifiedSuffix(JSContext *cx, JSTokenStream *ts, JSParseNode *pn, - JSTreeContext *tc) -{ - JSParseNode *pn2, *pn3; - JSTokenType tt; - - JS_ASSERT(CURRENT_TOKEN(ts).type == TOK_DBLCOLON); - pn2 = NewParseNode(cx, ts, PN_NAME, tc); - if (!pn2) - return NULL; - - /* Left operand of :: must be evaluated if it is an identifier. */ - if (pn->pn_op == JSOP_QNAMEPART) - pn->pn_op = JSOP_NAME; - - tt = js_GetToken(cx, ts); - if (tt == TOK_STAR || tt == TOK_NAME) { - /* Inline and specialize PropertySelector for JSOP_QNAMECONST. */ - pn2->pn_op = JSOP_QNAMECONST; - pn2->pn_atom = (tt == TOK_STAR) - ? cx->runtime->atomState.starAtom - : CURRENT_TOKEN(ts).t_atom; - pn2->pn_expr = pn; - pn2->pn_slot = -1; - pn2->pn_attrs = 0; - return pn2; - } - - if (tt != TOK_LB) { - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, - JSMSG_SYNTAX_ERROR); - return NULL; - } - pn3 = EndBracketedExpr(cx, ts, tc); - if (!pn3) - return NULL; - - pn2->pn_op = JSOP_QNAME; - pn2->pn_arity = PN_BINARY; - pn2->pn_left = pn; - pn2->pn_right = pn3; - return pn2; -} - -static JSParseNode * -QualifiedIdentifier(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - JSParseNode *pn; - - pn = PropertySelector(cx, ts, tc); - if (!pn) - return NULL; - if (js_MatchToken(cx, ts, TOK_DBLCOLON)) - pn = QualifiedSuffix(cx, ts, pn, tc); - return pn; -} - -static JSParseNode * -AttributeIdentifier(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - JSParseNode *pn, *pn2; - JSTokenType tt; - - JS_ASSERT(CURRENT_TOKEN(ts).type == TOK_AT); - pn = NewParseNode(cx, ts, PN_UNARY, tc); - if (!pn) - return NULL; - pn->pn_op = JSOP_TOATTRNAME; - tt = js_GetToken(cx, ts); - if (tt == TOK_STAR || tt == TOK_NAME) { - pn2 = QualifiedIdentifier(cx, ts, tc); - } else if (tt == TOK_LB) { - pn2 = EndBracketedExpr(cx, ts, tc); - } else { - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, - JSMSG_SYNTAX_ERROR); - return NULL; - } - if (!pn2) - return NULL; - pn->pn_kid = pn2; - return pn; -} - -/* - * Make a TOK_LC unary node whose pn_kid is an expression. - */ -static JSParseNode * -XMLExpr(JSContext *cx, JSTokenStream *ts, JSBool inTag, JSTreeContext *tc) -{ - JSParseNode *pn, *pn2; - uintN oldflags; - - JS_ASSERT(CURRENT_TOKEN(ts).type == TOK_LC); - pn = NewParseNode(cx, ts, PN_UNARY, tc); - if (!pn) - return NULL; - - /* - * Turn off XML tag mode, but don't restore it after parsing this braced - * expression. Instead, simply restore ts's old flags. This is required - * because XMLExpr is called both from within a tag, and from within text - * contained in an element, but outside of any start, end, or point tag. - */ - oldflags = ts->flags; - ts->flags = oldflags & ~TSF_XMLTAGMODE; - pn2 = Expr(cx, ts, tc); - if (!pn2) - return NULL; - - MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_IN_XML_EXPR); - ts->flags = oldflags; - pn->pn_kid = pn2; - pn->pn_op = inTag ? JSOP_XMLTAGEXPR : JSOP_XMLELTEXPR; - return pn; -} - -/* - * Make a terminal node for oneof TOK_XMLNAME, TOK_XMLATTR, TOK_XMLSPACE, - * TOK_XMLTEXT, TOK_XMLCDATA, TOK_XMLCOMMENT, or TOK_XMLPI. When converting - * parse tree to XML, we preserve a TOK_XMLSPACE node only if it's the sole - * child of a container tag. - */ -static JSParseNode * -XMLAtomNode(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - JSParseNode *pn; - JSToken *tp; - - pn = NewParseNode(cx, ts, PN_NULLARY, tc); - if (!pn) - return NULL; - tp = &CURRENT_TOKEN(ts); - pn->pn_op = tp->t_op; - pn->pn_atom = tp->t_atom; - if (tp->type == TOK_XMLPI) - pn->pn_atom2 = tp->t_atom2; - return pn; -} - -/* - * Parse the productions: - * - * XMLNameExpr: - * XMLName XMLNameExpr? - * { Expr } XMLNameExpr? - * - * Return a PN_LIST, PN_UNARY, or PN_NULLARY according as XMLNameExpr produces - * a list of names and/or expressions, a single expression, or a single name. - * If PN_LIST or PN_NULLARY, pn_type will be TOK_XMLNAME; if PN_UNARY, pn_type - * will be TOK_LC. - */ -static JSParseNode * -XMLNameExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - JSParseNode *pn, *pn2, *list; - JSTokenType tt; - - pn = list = NULL; - do { - tt = CURRENT_TOKEN(ts).type; - if (tt == TOK_LC) { - pn2 = XMLExpr(cx, ts, JS_TRUE, tc); - if (!pn2) - return NULL; - } else { - JS_ASSERT(tt == TOK_XMLNAME); - pn2 = XMLAtomNode(cx, ts, tc); - if (!pn2) - return NULL; - } - - if (!pn) { - pn = pn2; - } else { - if (!list) { - list = NewParseNode(cx, ts, PN_LIST, tc); - if (!list) - return NULL; - list->pn_type = TOK_XMLNAME; - list->pn_pos.begin = pn->pn_pos.begin; - PN_INIT_LIST_1(list, pn); - list->pn_extra = PNX_CANTFOLD; - pn = list; - } - pn->pn_pos.end = pn2->pn_pos.end; - PN_APPEND(pn, pn2); - } - } while ((tt = js_GetToken(cx, ts)) == TOK_XMLNAME || tt == TOK_LC); - - js_UngetToken(ts); - return pn; -} - -/* - * Macro to test whether an XMLNameExpr or XMLTagContent node can be folded - * at compile time into a JSXML tree. - */ -#define XML_FOLDABLE(pn) ((pn)->pn_arity == PN_LIST \ - ? ((pn)->pn_extra & PNX_CANTFOLD) == 0 \ - : (pn)->pn_type != TOK_LC) - -/* - * Parse the productions: - * - * XMLTagContent: - * XMLNameExpr - * XMLTagContent S XMLNameExpr S? = S? XMLAttr - * XMLTagContent S XMLNameExpr S? = S? { Expr } - * - * Return a PN_LIST, PN_UNARY, or PN_NULLARY according to how XMLTagContent - * produces a list of name and attribute values and/or braced expressions, a - * single expression, or a single name. - * - * If PN_LIST or PN_NULLARY, pn_type will be TOK_XMLNAME for the case where - * XMLTagContent: XMLNameExpr. If pn_type is not TOK_XMLNAME but pn_arity is - * PN_LIST, pn_type will be tagtype. If PN_UNARY, pn_type will be TOK_LC and - * we parsed exactly one expression. - */ -static JSParseNode * -XMLTagContent(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, - JSTokenType tagtype, JSAtom **namep) -{ - JSParseNode *pn, *pn2, *list; - JSTokenType tt; - - pn = XMLNameExpr(cx, ts, tc); - if (!pn) - return NULL; - *namep = (pn->pn_arity == PN_NULLARY) ? pn->pn_atom : NULL; - list = NULL; - - while (js_MatchToken(cx, ts, TOK_XMLSPACE)) { - tt = js_GetToken(cx, ts); - if (tt != TOK_XMLNAME && tt != TOK_LC) { - js_UngetToken(ts); - break; - } - - pn2 = XMLNameExpr(cx, ts, tc); - if (!pn2) - return NULL; - if (!list) { - list = NewParseNode(cx, ts, PN_LIST, tc); - if (!list) - return NULL; - list->pn_type = tagtype; - list->pn_pos.begin = pn->pn_pos.begin; - PN_INIT_LIST_1(list, pn); - pn = list; - } - PN_APPEND(pn, pn2); - if (!XML_FOLDABLE(pn2)) - pn->pn_extra |= PNX_CANTFOLD; - - js_MatchToken(cx, ts, TOK_XMLSPACE); - MUST_MATCH_TOKEN(TOK_ASSIGN, JSMSG_NO_ASSIGN_IN_XML_ATTR); - js_MatchToken(cx, ts, TOK_XMLSPACE); - - tt = js_GetToken(cx, ts); - if (tt == TOK_XMLATTR) { - pn2 = XMLAtomNode(cx, ts, tc); - } else if (tt == TOK_LC) { - pn2 = XMLExpr(cx, ts, JS_TRUE, tc); - pn->pn_extra |= PNX_CANTFOLD; - } else { - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, - JSMSG_BAD_XML_ATTR_VALUE); - return NULL; - } - if (!pn2) - return NULL; - pn->pn_pos.end = pn2->pn_pos.end; - PN_APPEND(pn, pn2); - } - - return pn; -} - -#define XML_CHECK_FOR_ERROR_AND_EOF(tt,result) \ - JS_BEGIN_MACRO \ - if ((tt) <= TOK_EOF) { \ - if ((tt) == TOK_EOF) { \ - js_ReportCompileErrorNumber(cx, ts, \ - JSREPORT_TS | JSREPORT_ERROR, \ - JSMSG_END_OF_XML_SOURCE); \ - } \ - return result; \ - } \ - JS_END_MACRO - -static JSParseNode * -XMLElementOrList(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, - JSBool allowList); - -/* - * Consume XML element tag content, including the TOK_XMLETAGO (flags &= ~TSF_XMLTAGMODE; - for (;;) { - ts->flags |= TSF_XMLTEXTMODE; - tt = js_GetToken(cx, ts); - ts->flags &= ~TSF_XMLTEXTMODE; - XML_CHECK_FOR_ERROR_AND_EOF(tt, JS_FALSE); - - JS_ASSERT(tt == TOK_XMLSPACE || tt == TOK_XMLTEXT); - textAtom = CURRENT_TOKEN(ts).t_atom; - if (textAtom) { - /* Non-zero-length XML text scanned. */ - pn2 = XMLAtomNode(cx, ts, tc); - if (!pn2) - return JS_FALSE; - pn->pn_pos.end = pn2->pn_pos.end; - PN_APPEND(pn, pn2); - } - - ts->flags |= TSF_OPERAND; - tt = js_GetToken(cx, ts); - ts->flags &= ~TSF_OPERAND; - XML_CHECK_FOR_ERROR_AND_EOF(tt, JS_FALSE); - if (tt == TOK_XMLETAGO) - break; - - if (tt == TOK_LC) { - pn2 = XMLExpr(cx, ts, JS_FALSE, tc); - pn->pn_extra |= PNX_CANTFOLD; - } else if (tt == TOK_XMLSTAGO) { - pn2 = XMLElementOrList(cx, ts, tc, JS_FALSE); - if (pn2) { - pn2->pn_extra &= ~PNX_XMLROOT; - pn->pn_extra |= pn2->pn_extra; - } - } else { - JS_ASSERT(tt == TOK_XMLCDATA || tt == TOK_XMLCOMMENT || - tt == TOK_XMLPI); - pn2 = XMLAtomNode(cx, ts, tc); - } - if (!pn2) - return JS_FALSE; - pn->pn_pos.end = pn2->pn_pos.end; - PN_APPEND(pn, pn2); - } - - JS_ASSERT(CURRENT_TOKEN(ts).type == TOK_XMLETAGO); - ts->flags |= TSF_XMLTAGMODE; - return JS_TRUE; -} - -/* - * Return a PN_LIST node containing an XML or XMLList Initialiser. - */ -static JSParseNode * -XMLElementOrList(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, - JSBool allowList) -{ - JSParseNode *pn, *pn2, *list; - JSBool hadSpace; - JSTokenType tt; - JSAtom *startAtom, *endAtom; - - JS_ASSERT(CURRENT_TOKEN(ts).type == TOK_XMLSTAGO); - pn = NewParseNode(cx, ts, PN_LIST, tc); - if (!pn) - return NULL; - - ts->flags |= TSF_XMLTAGMODE; - hadSpace = js_MatchToken(cx, ts, TOK_XMLSPACE); - tt = js_GetToken(cx, ts); - if (tt == TOK_ERROR) - return NULL; - - if (tt == TOK_XMLNAME || tt == TOK_LC) { - /* - * XMLElement. Append the tag and its contents, if any, to pn. - */ - pn2 = XMLTagContent(cx, ts, tc, TOK_XMLSTAGO, &startAtom); - if (!pn2) - return NULL; - js_MatchToken(cx, ts, TOK_XMLSPACE); - - tt = js_GetToken(cx, ts); - if (tt == TOK_XMLPTAGC) { - /* Point tag (/>): recycle pn if pn2 is a list of tag contents. */ - if (pn2->pn_type == TOK_XMLSTAGO) { - PN_INIT_LIST(pn); - RecycleTree(pn, tc); - pn = pn2; - } else { - JS_ASSERT(pn2->pn_type == TOK_XMLNAME || - pn2->pn_type == TOK_LC); - PN_INIT_LIST_1(pn, pn2); - if (!XML_FOLDABLE(pn2)) - pn->pn_extra |= PNX_CANTFOLD; - } - pn->pn_type = TOK_XMLPTAGC; - pn->pn_extra |= PNX_XMLROOT; - } else { - /* We had better have a tag-close (>) at this point. */ - if (tt != TOK_XMLTAGC) { - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_BAD_XML_TAG_SYNTAX); - return NULL; - } - pn2->pn_pos.end = CURRENT_TOKEN(ts).pos.end; - - /* Make sure pn2 is a TOK_XMLSTAGO list containing tag contents. */ - if (pn2->pn_type != TOK_XMLSTAGO) { - PN_INIT_LIST_1(pn, pn2); - if (!XML_FOLDABLE(pn2)) - pn->pn_extra |= PNX_CANTFOLD; - pn2 = pn; - pn = NewParseNode(cx, ts, PN_LIST, tc); - if (!pn) - return NULL; - } - - /* Now make pn a nominal-root TOK_XMLELEM list containing pn2. */ - pn->pn_type = TOK_XMLELEM; - PN_INIT_LIST_1(pn, pn2); - if (!XML_FOLDABLE(pn2)) - pn->pn_extra |= PNX_CANTFOLD; - pn->pn_extra |= PNX_XMLROOT; - - /* Get element contents and delimiting end-tag-open sequence. */ - if (!XMLElementContent(cx, ts, pn, tc)) - return NULL; - - js_MatchToken(cx, ts, TOK_XMLSPACE); - tt = js_GetToken(cx, ts); - XML_CHECK_FOR_ERROR_AND_EOF(tt, NULL); - if (tt != TOK_XMLNAME && tt != TOK_LC) { - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_BAD_XML_TAG_SYNTAX); - return NULL; - } - - /* Parse end tag; check mismatch at compile-time if we can. */ - pn2 = XMLTagContent(cx, ts, tc, TOK_XMLETAGO, &endAtom); - if (!pn2) - return NULL; - if (pn2->pn_type == TOK_XMLETAGO) { - /* Oops, end tag has attributes! */ - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_BAD_XML_TAG_SYNTAX); - return NULL; - } - if (endAtom && startAtom && endAtom != startAtom) { - /* End vs. start tag name mismatch: point to the tag name. */ - ++pn2->pn_pos.begin.index; - js_ReportCompileErrorNumber(cx, pn2, - JSREPORT_PN | JSREPORT_ERROR, - JSMSG_XML_TAG_NAME_MISMATCH); - return NULL; - } - - /* Make a TOK_XMLETAGO list with pn2 as its single child. */ - JS_ASSERT(pn2->pn_type == TOK_XMLNAME || pn2->pn_type == TOK_LC); - list = NewParseNode(cx, ts, PN_LIST, tc); - if (!list) - return NULL; - list->pn_type = TOK_XMLETAGO; - PN_INIT_LIST_1(list, pn2); - PN_APPEND(pn, list); - if (!XML_FOLDABLE(pn2)) { - list->pn_extra |= PNX_CANTFOLD; - pn->pn_extra |= PNX_CANTFOLD; - } - - js_MatchToken(cx, ts, TOK_XMLSPACE); - MUST_MATCH_TOKEN(TOK_XMLTAGC, JSMSG_BAD_XML_TAG_SYNTAX); - } - - /* Set pn_op now that pn has been updated to its final value. */ - pn->pn_op = JSOP_TOXML; - } else if (!hadSpace && allowList && tt == TOK_XMLTAGC) { - /* XMLList Initialiser. */ - pn->pn_type = TOK_XMLLIST; - pn->pn_op = JSOP_TOXMLLIST; - PN_INIT_LIST(pn); - pn->pn_extra |= PNX_XMLROOT; - if (!XMLElementContent(cx, ts, pn, tc)) - return NULL; - - MUST_MATCH_TOKEN(TOK_XMLTAGC, JSMSG_BAD_XML_LIST_SYNTAX); - } else { - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, - JSMSG_BAD_XML_NAME_SYNTAX); - return NULL; - } - - pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end; - ts->flags &= ~TSF_XMLTAGMODE; - return pn; -} - -static JSParseNode * -XMLElementOrListRoot(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, - JSBool allowList) -{ - uint32 oldopts; - JSParseNode *pn; - - /* - * Force XML support to be enabled so that comments and CDATA literals - * are recognized, instead of ). - */ - oldopts = JS_SetOptions(cx, cx->options | JSOPTION_XML); - pn = XMLElementOrList(cx, ts, tc, allowList); - JS_SetOptions(cx, oldopts); - return pn; -} - -JS_FRIEND_API(JSParseNode *) -js_ParseXMLTokenStream(JSContext *cx, JSObject *chain, JSTokenStream *ts, - JSBool allowList) -{ - JSStackFrame *fp, frame; - JSParseNode *pn; - JSTreeContext tc; - JSTokenType tt; - - /* - * Push a compiler frame if we have no frames, or if the top frame is a - * lightweight function activation, or if its scope chain doesn't match - * the one passed to us. - */ - fp = cx->fp; - if (!fp || !fp->varobj || fp->scopeChain != chain) { - memset(&frame, 0, sizeof frame); - frame.varobj = frame.scopeChain = chain; - if (cx->options & JSOPTION_VAROBJFIX) { - while ((chain = JS_GetParent(cx, chain)) != NULL) - frame.varobj = chain; - } - frame.down = fp; - if (fp) { - frame.flags = fp->flags & (JSFRAME_SPECIAL | JSFRAME_COMPILE_N_GO | - JSFRAME_SCRIPT_OBJECT); - } - cx->fp = &frame; - } - - JS_KEEP_ATOMS(cx->runtime); - TREE_CONTEXT_INIT(&tc); - - /* Set XML-only mode to turn off special treatment of {expr} in XML. */ - ts->flags |= TSF_OPERAND | TSF_XMLONLYMODE; - tt = js_GetToken(cx, ts); - ts->flags &= ~TSF_OPERAND; - - if (tt != TOK_XMLSTAGO) { - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, - JSMSG_BAD_XML_MARKUP); - pn = NULL; - } else { - pn = XMLElementOrListRoot(cx, ts, &tc, allowList); - } - - ts->flags &= ~TSF_XMLONLYMODE; - TREE_CONTEXT_FINISH(&tc); - JS_UNKEEP_ATOMS(cx->runtime); - cx->fp = fp; - return pn; -} - -#endif /* JS_HAS_XMLSUPPORT */ - -static JSParseNode * -PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc) -{ - JSTokenType tt; - JSParseNode *pn, *pn2, *pn3; -#if JS_HAS_GETTER_SETTER - JSAtom *atom; - JSRuntime *rt; -#endif - -#if JS_HAS_SHARP_VARS - JSParseNode *defsharp; - JSBool notsharp; - - defsharp = NULL; - notsharp = JS_FALSE; - again: - /* - * Control flows here after #n= is scanned. If the following primary is - * not valid after such a "sharp variable" definition, the tt switch case - * should set notsharp. - */ -#endif - - CHECK_RECURSION(); - - ts->flags |= TSF_OPERAND; - tt = js_GetToken(cx, ts); - ts->flags &= ~TSF_OPERAND; - -#if JS_HAS_GETTER_SETTER - if (tt == TOK_NAME) { - tt = CheckGetterOrSetter(cx, ts, TOK_FUNCTION); - if (tt == TOK_ERROR) - return NULL; - } -#endif - - switch (tt) { -#if JS_HAS_LEXICAL_CLOSURE || JS_HAS_XML_SUPPORT - case TOK_FUNCTION: -#if JS_HAS_XML_SUPPORT - if (js_MatchToken(cx, ts, TOK_DBLCOLON)) { - pn2 = NewParseNode(cx, ts, PN_NULLARY, tc); - if (!pn2) - return NULL; - pn2->pn_type = TOK_FUNCTION; - pn = QualifiedSuffix(cx, ts, pn2, tc); - if (!pn) - return NULL; - break; - } -#endif - pn = FunctionExpr(cx, ts, tc); - if (!pn) - return NULL; - break; -#endif - -#if JS_HAS_INITIALIZERS - case TOK_LB: - { - JSBool matched; - jsuint atomIndex; - - pn = NewParseNode(cx, ts, PN_LIST, tc); - if (!pn) - return NULL; - pn->pn_type = TOK_RB; - -#if JS_HAS_SHARP_VARS - if (defsharp) { - PN_INIT_LIST_1(pn, defsharp); - defsharp = NULL; - } else -#endif - PN_INIT_LIST(pn); - - ts->flags |= TSF_OPERAND; - matched = js_MatchToken(cx, ts, TOK_RB); - ts->flags &= ~TSF_OPERAND; - if (!matched) { - for (atomIndex = 0; ; atomIndex++) { - if (atomIndex == ATOM_INDEX_LIMIT) { - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_ARRAY_INIT_TOO_BIG); - return NULL; - } - - ts->flags |= TSF_OPERAND; - tt = js_PeekToken(cx, ts); - ts->flags &= ~TSF_OPERAND; - if (tt == TOK_RB) { - pn->pn_extra |= PNX_ENDCOMMA; - break; - } - - if (tt == TOK_COMMA) { - /* So CURRENT_TOKEN gets TOK_COMMA and not TOK_LB. */ - js_MatchToken(cx, ts, TOK_COMMA); - pn2 = NewParseNode(cx, ts, PN_NULLARY, tc); - } else { - pn2 = AssignExpr(cx, ts, tc); - } - if (!pn2) - return NULL; - PN_APPEND(pn, pn2); - - if (tt != TOK_COMMA) { - /* If we didn't already match TOK_COMMA in above case. */ - if (!js_MatchToken(cx, ts, TOK_COMMA)) - break; - } - } - - MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_AFTER_LIST); - } - pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end; - return pn; - } - - case TOK_LC: - pn = NewParseNode(cx, ts, PN_LIST, tc); - if (!pn) - return NULL; - pn->pn_type = TOK_RC; - -#if JS_HAS_SHARP_VARS - if (defsharp) { - PN_INIT_LIST_1(pn, defsharp); - defsharp = NULL; - } else -#endif - PN_INIT_LIST(pn); - - if (!js_MatchToken(cx, ts, TOK_RC)) { - do { - JSOp op; - - tt = js_GetToken(cx, ts); - switch (tt) { - case TOK_NUMBER: - pn3 = NewParseNode(cx, ts, PN_NULLARY, tc); - if (pn3) - pn3->pn_dval = CURRENT_TOKEN(ts).t_dval; - break; - case TOK_NAME: -#if JS_HAS_GETTER_SETTER - atom = CURRENT_TOKEN(ts).t_atom; - rt = cx->runtime; - if (atom == rt->atomState.getAtom || - atom == rt->atomState.setAtom) { - op = (atom == rt->atomState.getAtom) - ? JSOP_GETTER - : JSOP_SETTER; - if (js_MatchToken(cx, ts, TOK_NAME)) { - pn3 = NewParseNode(cx, ts, PN_NAME, tc); - if (!pn3) - return NULL; - pn3->pn_atom = CURRENT_TOKEN(ts).t_atom; - pn3->pn_expr = NULL; - - /* We have to fake a 'function' token here. */ - CURRENT_TOKEN(ts).t_op = JSOP_NOP; - CURRENT_TOKEN(ts).type = TOK_FUNCTION; - pn2 = FunctionExpr(cx, ts, tc); - pn2 = NewBinary(cx, TOK_COLON, op, pn3, pn2, tc); - goto skip; - } - } - /* else fall thru ... */ -#endif - case TOK_STRING: - pn3 = NewParseNode(cx, ts, PN_NULLARY, tc); - if (pn3) - pn3->pn_atom = CURRENT_TOKEN(ts).t_atom; - break; - case TOK_RC: - if (!js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | - JSREPORT_WARNING | - JSREPORT_STRICT, - JSMSG_TRAILING_COMMA)) { - return NULL; - } - goto end_obj_init; - default: - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_BAD_PROP_ID); - return NULL; - } - - tt = js_GetToken(cx, ts); -#if JS_HAS_GETTER_SETTER - if (tt == TOK_NAME) { - tt = CheckGetterOrSetter(cx, ts, TOK_COLON); - if (tt == TOK_ERROR) - return NULL; - } -#endif - if (tt != TOK_COLON) { - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_COLON_AFTER_ID); - return NULL; - } - op = CURRENT_TOKEN(ts).t_op; - pn2 = NewBinary(cx, TOK_COLON, op, pn3, AssignExpr(cx, ts, tc), - tc); -#if JS_HAS_GETTER_SETTER - skip: -#endif - if (!pn2) - return NULL; - PN_APPEND(pn, pn2); - } while (js_MatchToken(cx, ts, TOK_COMMA)); - - MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_LIST); - } - end_obj_init: - pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end; - return pn; - -#if JS_HAS_SHARP_VARS - case TOK_DEFSHARP: - if (defsharp) - goto badsharp; - defsharp = NewParseNode(cx, ts, PN_UNARY, tc); - if (!defsharp) - return NULL; - defsharp->pn_kid = NULL; - defsharp->pn_num = (jsint) CURRENT_TOKEN(ts).t_dval; - goto again; - - case TOK_USESHARP: - /* Check for forward/dangling references at runtime, to allow eval. */ - pn = NewParseNode(cx, ts, PN_NULLARY, tc); - if (!pn) - return NULL; - pn->pn_num = (jsint) CURRENT_TOKEN(ts).t_dval; - notsharp = JS_TRUE; - break; -#endif /* JS_HAS_SHARP_VARS */ -#endif /* JS_HAS_INITIALIZERS */ - - case TOK_LP: - pn = NewParseNode(cx, ts, PN_UNARY, tc); - if (!pn) - return NULL; - pn2 = BracketedExpr(cx, ts, tc); - if (!pn2) - return NULL; - - MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_IN_PAREN); - pn->pn_type = TOK_RP; - pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end; - pn->pn_kid = pn2; - break; - -#if JS_HAS_XML_SUPPORT - case TOK_STAR: - pn = QualifiedIdentifier(cx, ts, tc); - if (!pn) - return NULL; - notsharp = JS_TRUE; - break; - - case TOK_AT: - pn = AttributeIdentifier(cx, ts, tc); - if (!pn) - return NULL; - notsharp = JS_TRUE; - break; - - case TOK_XMLSTAGO: - pn = XMLElementOrListRoot(cx, ts, tc, JS_TRUE); - if (!pn) - return NULL; - notsharp = JS_TRUE; /* XXXbe could be sharp? */ - break; -#endif /* JS_HAS_XML_SUPPORT */ - - case TOK_STRING: -#if JS_HAS_SHARP_VARS - notsharp = JS_TRUE; - /* FALL THROUGH */ -#endif - -#if JS_HAS_XML_SUPPORT - case TOK_XMLCDATA: - case TOK_XMLCOMMENT: - case TOK_XMLPI: -#endif - case TOK_NAME: - case TOK_OBJECT: - pn = NewParseNode(cx, ts, PN_NULLARY, tc); - if (!pn) - return NULL; - pn->pn_atom = CURRENT_TOKEN(ts).t_atom; -#if JS_HAS_XML_SUPPORT - if (tt == TOK_XMLPI) - pn->pn_atom2 = CURRENT_TOKEN(ts).t_atom2; - else -#endif - pn->pn_op = CURRENT_TOKEN(ts).t_op; - if (tt == TOK_NAME) { - pn->pn_arity = PN_NAME; - pn->pn_expr = NULL; - pn->pn_slot = -1; - pn->pn_attrs = 0; - -#if JS_HAS_XML_SUPPORT - if (js_MatchToken(cx, ts, TOK_DBLCOLON)) { - pn = QualifiedSuffix(cx, ts, pn, tc); - if (!pn) - return NULL; - break; - } -#endif - - /* Unqualified __parent__ and __proto__ uses require activations. */ - if (pn->pn_atom == cx->runtime->atomState.parentAtom || - pn->pn_atom == cx->runtime->atomState.protoAtom) { - tc->flags |= TCF_FUN_HEAVYWEIGHT; - } else { - JSAtomListElement *ale; - JSStackFrame *fp; - JSStmtInfo *stmt; - - /* Measure optimizable global variable uses. */ - ATOM_LIST_SEARCH(ale, &tc->decls, pn->pn_atom); - if (ale && - !(fp = cx->fp)->fun && - fp->scopeChain == fp->varobj && - !js_InWithStatement(tc) && - !js_InCatchBlock(tc, pn->pn_atom)) { - tc->globalUses++; - for (stmt = tc->topStmt; stmt; stmt = stmt->down) { - if (STMT_IS_LOOP(stmt)) { - tc->loopyGlobalUses++; - break; - } - } - } - } - } - break; - - case TOK_NUMBER: - pn = NewParseNode(cx, ts, PN_NULLARY, tc); - if (!pn) - return NULL; - pn->pn_dval = CURRENT_TOKEN(ts).t_dval; -#if JS_HAS_SHARP_VARS - notsharp = JS_TRUE; -#endif - break; - - case TOK_PRIMARY: - pn = NewParseNode(cx, ts, PN_NULLARY, tc); - if (!pn) - return NULL; - pn->pn_op = CURRENT_TOKEN(ts).t_op; -#if JS_HAS_SHARP_VARS - notsharp = JS_TRUE; -#endif - break; - -#if !JS_HAS_EXPORT_IMPORT - case TOK_EXPORT: - case TOK_IMPORT: -#endif - case TOK_ERROR: - /* The scanner or one of its subroutines reported the error. */ - return NULL; - - default: - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, - JSMSG_SYNTAX_ERROR); - return NULL; - } - -#if JS_HAS_SHARP_VARS - if (defsharp) { - if (notsharp) { - badsharp: - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, - JSMSG_BAD_SHARP_VAR_DEF); - return NULL; - } - defsharp->pn_kid = pn; - return defsharp; - } -#endif - return pn; -} - -static JSBool -ContainsVarStmt(JSParseNode *pn) -{ - JSParseNode *pn2; - - if (!pn) - return JS_FALSE; - switch (pn->pn_arity) { - case PN_LIST: - if (pn->pn_type == TOK_VAR) - return JS_TRUE; - for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) { - if (ContainsVarStmt(pn2)) - return JS_TRUE; - } - break; - case PN_TERNARY: - return ContainsVarStmt(pn->pn_kid1) || - ContainsVarStmt(pn->pn_kid2) || - ContainsVarStmt(pn->pn_kid3); - case PN_BINARY: - /* - * Limit recursion if pn is a binary expression, which can't contain a - * var statement. - */ - if (pn->pn_op != JSOP_NOP) - return JS_FALSE; - return ContainsVarStmt(pn->pn_left) || ContainsVarStmt(pn->pn_right); - case PN_UNARY: - if (pn->pn_op != JSOP_NOP) - return JS_FALSE; - return ContainsVarStmt(pn->pn_kid); - default:; - } - return JS_FALSE; -} - -/* - * Fold from one constant type to another. - * XXX handles only strings and numbers for now - */ -static JSBool -FoldType(JSContext *cx, JSParseNode *pn, JSTokenType type) -{ - if (pn->pn_type != type) { - switch (type) { - case TOK_NUMBER: - if (pn->pn_type == TOK_STRING) { - jsdouble d; - if (!js_ValueToNumber(cx, ATOM_KEY(pn->pn_atom), &d)) - return JS_FALSE; - pn->pn_dval = d; - pn->pn_type = TOK_NUMBER; - pn->pn_op = JSOP_NUMBER; - } - break; - - case TOK_STRING: - if (pn->pn_type == TOK_NUMBER) { - JSString *str = js_NumberToString(cx, pn->pn_dval); - if (!str) - return JS_FALSE; - pn->pn_atom = js_AtomizeString(cx, str, 0); - if (!pn->pn_atom) - return JS_FALSE; - pn->pn_type = TOK_STRING; - pn->pn_op = JSOP_STRING; - } - break; - - default:; - } - } - return JS_TRUE; -} - -/* - * Fold two numeric constants. Beware that pn1 and pn2 are recycled, unless - * one of them aliases pn, so you can't safely fetch pn2->pn_next, e.g., after - * a successful call to this function. - */ -static JSBool -FoldBinaryNumeric(JSContext *cx, JSOp op, JSParseNode *pn1, JSParseNode *pn2, - JSParseNode *pn, JSTreeContext *tc) -{ - jsdouble d, d2; - int32 i, j; - uint32 u; - - JS_ASSERT(pn1->pn_type == TOK_NUMBER && pn2->pn_type == TOK_NUMBER); - d = pn1->pn_dval; - d2 = pn2->pn_dval; - switch (op) { - case JSOP_LSH: - case JSOP_RSH: - if (!js_DoubleToECMAInt32(cx, d, &i)) - return JS_FALSE; - if (!js_DoubleToECMAInt32(cx, d2, &j)) - return JS_FALSE; - j &= 31; - d = (op == JSOP_LSH) ? i << j : i >> j; - break; - - case JSOP_URSH: - if (!js_DoubleToECMAUint32(cx, d, &u)) - return JS_FALSE; - if (!js_DoubleToECMAInt32(cx, d2, &j)) - return JS_FALSE; - j &= 31; - d = u >> j; - break; - - case JSOP_ADD: - d += d2; - break; - - case JSOP_SUB: - d -= d2; - break; - - case JSOP_MUL: - d *= d2; - break; - - case JSOP_DIV: - if (d2 == 0) { -#if defined(XP_WIN) - /* XXX MSVC miscompiles such that (NaN == 0) */ - if (JSDOUBLE_IS_NaN(d2)) - d = *cx->runtime->jsNaN; - else -#endif - if (d == 0 || JSDOUBLE_IS_NaN(d)) - d = *cx->runtime->jsNaN; - else if ((JSDOUBLE_HI32(d) ^ JSDOUBLE_HI32(d2)) >> 31) - d = *cx->runtime->jsNegativeInfinity; - else - d = *cx->runtime->jsPositiveInfinity; - } else { - d /= d2; - } - break; - - case JSOP_MOD: - if (d2 == 0) { - d = *cx->runtime->jsNaN; - } else { -#if defined(XP_WIN) - /* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */ - if (!(JSDOUBLE_IS_FINITE(d) && JSDOUBLE_IS_INFINITE(d2))) -#endif - d = fmod(d, d2); - } - break; - - default:; - } - - /* Take care to allow pn1 or pn2 to alias pn. */ - if (pn1 != pn) - RecycleTree(pn1, tc); - if (pn2 != pn) - RecycleTree(pn2, tc); - pn->pn_type = TOK_NUMBER; - pn->pn_op = JSOP_NUMBER; - pn->pn_arity = PN_NULLARY; - pn->pn_dval = d; - return JS_TRUE; -} - -#if JS_HAS_XML_SUPPORT - -static JSBool -FoldXMLConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc) -{ - JSTokenType tt; - JSParseNode **pnp, *pn1, *pn2; - JSString *accum, *str; - uint32 i, j; - - JS_ASSERT(pn->pn_arity == PN_LIST); - tt = pn->pn_type; - pnp = &pn->pn_head; - pn1 = *pnp; - accum = NULL; - if ((pn->pn_extra & PNX_CANTFOLD) == 0) { - if (tt == TOK_XMLETAGO) - accum = ATOM_TO_STRING(cx->runtime->atomState.etagoAtom); - else if (tt == TOK_XMLSTAGO || tt == TOK_XMLPTAGC) - accum = ATOM_TO_STRING(cx->runtime->atomState.stagoAtom); - } - - for (pn2 = pn1, i = j = 0; pn2; pn2 = pn2->pn_next, i++) { - /* The parser already rejected end-tags with attributes. */ - JS_ASSERT(tt != TOK_XMLETAGO || i == 0); - switch (pn2->pn_type) { - case TOK_XMLATTR: - if (!accum) - goto cantfold; - /* FALL THROUGH */ - case TOK_XMLNAME: - case TOK_XMLSPACE: - case TOK_XMLTEXT: - case TOK_STRING: - if (pn2->pn_arity == PN_LIST) - goto cantfold; - str = ATOM_TO_STRING(pn2->pn_atom); - break; - - case TOK_XMLCDATA: - str = js_MakeXMLCDATAString(cx, ATOM_TO_STRING(pn2->pn_atom)); - if (!str) - return JS_FALSE; - break; - - case TOK_XMLCOMMENT: - str = js_MakeXMLCommentString(cx, ATOM_TO_STRING(pn2->pn_atom)); - if (!str) - return JS_FALSE; - break; - - case TOK_XMLPI: - str = js_MakeXMLPIString(cx, ATOM_TO_STRING(pn2->pn_atom), - ATOM_TO_STRING(pn2->pn_atom2)); - if (!str) - return JS_FALSE; - break; - - cantfold: - default: - JS_ASSERT(*pnp == pn1); - if ((tt == TOK_XMLSTAGO || tt == TOK_XMLPTAGC) && - (i & 1) ^ (j & 1)) { -#ifdef DEBUG_brendanXXX - printf("1: %d, %d => %s\n", - i, j, accum ? JS_GetStringBytes(accum) : "NULL"); -#endif - } else if (accum && pn1 != pn2) { - while (pn1->pn_next != pn2) { - pn1 = RecycleTree(pn1, tc); - --pn->pn_count; - } - pn1->pn_type = TOK_XMLTEXT; - pn1->pn_op = JSOP_STRING; - pn1->pn_arity = PN_NULLARY; - pn1->pn_atom = js_AtomizeString(cx, accum, 0); - if (!pn1->pn_atom) - return JS_FALSE; - JS_ASSERT(pnp != &pn1->pn_next); - *pnp = pn1; - } - pnp = &pn2->pn_next; - pn1 = *pnp; - accum = NULL; - continue; - } - - if (accum) { - str = ((tt == TOK_XMLSTAGO || tt == TOK_XMLPTAGC) && i != 0) - ? js_AddAttributePart(cx, i & 1, accum, str) - : js_ConcatStrings(cx, accum, str); - if (!str) - return JS_FALSE; -#ifdef DEBUG_brendanXXX - printf("2: %d, %d => %s (%u)\n", - i, j, JS_GetStringBytes(str), JSSTRING_LENGTH(str)); -#endif - ++j; - } - accum = str; - } - - if (accum) { - str = NULL; - if ((pn->pn_extra & PNX_CANTFOLD) == 0) { - if (tt == TOK_XMLPTAGC) - str = ATOM_TO_STRING(cx->runtime->atomState.ptagcAtom); - else if (tt == TOK_XMLSTAGO || tt == TOK_XMLETAGO) - str = ATOM_TO_STRING(cx->runtime->atomState.tagcAtom); - } - if (str) { - accum = js_ConcatStrings(cx, accum, str); - if (!accum) - return JS_FALSE; - } - - JS_ASSERT(*pnp == pn1); - while (pn1->pn_next) { - pn1 = RecycleTree(pn1, tc); - --pn->pn_count; - } - pn1->pn_type = TOK_XMLTEXT; - pn1->pn_op = JSOP_STRING; - pn1->pn_arity = PN_NULLARY; - pn1->pn_atom = js_AtomizeString(cx, accum, 0); - if (!pn1->pn_atom) - return JS_FALSE; - JS_ASSERT(pnp != &pn1->pn_next); - *pnp = pn1; - } - - if (pn1 && pn->pn_count == 1) { - /* - * Only one node under pn, and it has been folded: move pn1 onto pn - * unless pn is an XML root (in which case we need it to tell the code - * generator to emit a JSOP_TOXML or JSOP_TOXMLLIST op). If pn is an - * XML root *and* it's a point-tag, rewrite it to TOK_XMLELEM to avoid - * extra "<" and "/>" bracketing at runtime. - */ - if (!(pn->pn_extra & PNX_XMLROOT)) { - PN_MOVE_NODE(pn, pn1); - } else if (tt == TOK_XMLPTAGC) { - pn->pn_type = TOK_XMLELEM; - pn->pn_op = JSOP_TOXML; - } - } - return JS_TRUE; -} - -#endif /* JS_HAS_XML_SUPPORT */ - -JSBool -js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc) -{ - JSParseNode *pn1 = NULL, *pn2 = NULL, *pn3 = NULL; - int stackDummy; - - if (!JS_CHECK_STACK_SIZE(cx, stackDummy)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_OVER_RECURSED); - return JS_FALSE; - } - - switch (pn->pn_arity) { - case PN_FUNC: - { - uint16 oldflags = tc->flags; - - tc->flags = (uint16) pn->pn_flags; - if (!js_FoldConstants(cx, pn->pn_body, tc)) - return JS_FALSE; - tc->flags = oldflags; - break; - } - - case PN_LIST: -#if 0 /* JS_HAS_XML_SUPPORT */ - switch (pn->pn_type) { - case TOK_XMLELEM: - case TOK_XMLLIST: - case TOK_XMLPTAGC: - /* - * Try to fold this XML parse tree once, from the top down, into - * a JSXML tree with just one object wrapping the tree root. - * - * Certain subtrees could be folded similarly, but we'd have to - * ensure that none used namespace prefixes declared elsewhere in - * its super-tree, and we would have to convert each XML object - * created at runtime for such sub-trees back into a string, and - * concatenate and re-parse anyway. - */ - if ((pn->pn_extra & (PNX_XMLROOT | PNX_CANTFOLD)) == PNX_XMLROOT && - !(tc->flags & TCF_HAS_DEFXMLNS)) { - JSObject *obj; - JSAtom *atom; - - obj = js_ParseNodeToXMLObject(cx, pn); - if (!obj) - return JS_FALSE; - atom = js_AtomizeObject(cx, obj, 0); - if (!atom) - return JS_FALSE; - pn->pn_op = JSOP_XMLOBJECT; - pn->pn_arity = PN_NULLARY; - pn->pn_atom = atom; - return JS_TRUE; - } - - /* - * Can't fold from parse node to XML tree -- try folding strings - * as much as possible, and folding XML sub-trees bottom up to - * minimize string concatenation and ToXML/ToXMLList operations - * at runtime. - */ - break; - - default:; - } -#endif - - /* Save the list head in pn1 for later use. */ - for (pn1 = pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) { - if (!js_FoldConstants(cx, pn2, tc)) - return JS_FALSE; - } - break; - - case PN_TERNARY: - /* Any kid may be null (e.g. for (;;)). */ - pn1 = pn->pn_kid1; - pn2 = pn->pn_kid2; - pn3 = pn->pn_kid3; - if (pn1 && !js_FoldConstants(cx, pn1, tc)) - return JS_FALSE; - if (pn2 && !js_FoldConstants(cx, pn2, tc)) - return JS_FALSE; - if (pn3 && !js_FoldConstants(cx, pn3, tc)) - return JS_FALSE; - break; - - case PN_BINARY: - /* First kid may be null (for default case in switch). */ - pn1 = pn->pn_left; - pn2 = pn->pn_right; - if (pn1 && !js_FoldConstants(cx, pn1, tc)) - return JS_FALSE; - if (!js_FoldConstants(cx, pn2, tc)) - return JS_FALSE; - break; - - case PN_UNARY: - /* Our kid may be null (e.g. return; vs. return e;). */ - pn1 = pn->pn_kid; - if (pn1 && !js_FoldConstants(cx, pn1, tc)) - return JS_FALSE; - break; - - case PN_NAME: - /* - * Skip pn1 down along a chain of dotted member expressions to avoid - * excessive recursion. Our only goal here is to fold constants (if - * any) in the primary expression operand to the left of the first - * dot in the chain. - */ - pn1 = pn->pn_expr; - while (pn1 && pn1->pn_arity == PN_NAME) - pn1 = pn1->pn_expr; - if (pn1 && !js_FoldConstants(cx, pn1, tc)) - return JS_FALSE; - break; - - case PN_NULLARY: - break; - } - - switch (pn->pn_type) { - case TOK_IF: - if (ContainsVarStmt(pn2) || ContainsVarStmt(pn3)) - break; - /* FALL THROUGH */ - - case TOK_HOOK: - /* Reduce 'if (C) T; else E' into T for true C, E for false. */ - switch (pn1->pn_type) { - case TOK_NUMBER: - if (pn1->pn_dval == 0) - pn2 = pn3; - break; - case TOK_STRING: - if (JSSTRING_LENGTH(ATOM_TO_STRING(pn1->pn_atom)) == 0) - pn2 = pn3; - break; - case TOK_PRIMARY: - if (pn1->pn_op == JSOP_TRUE) - break; - if (pn1->pn_op == JSOP_FALSE || pn1->pn_op == JSOP_NULL) { - pn2 = pn3; - break; - } - /* FALL THROUGH */ - default: - /* Early return to dodge common code that copies pn2 to pn. */ - return JS_TRUE; - } - - if (pn2) { - /* pn2 is the then- or else-statement subtree to compile. */ - PN_MOVE_NODE(pn, pn2); - } else { - /* False condition and no else: make pn an empty statement. */ - pn->pn_type = TOK_SEMI; - pn->pn_arity = PN_UNARY; - pn->pn_kid = NULL; - } - RecycleTree(pn2, tc); - if (pn3 && pn3 != pn2) - RecycleTree(pn3, tc); - break; - - case TOK_PLUS: - if (pn->pn_arity == PN_LIST) { - size_t length, length2; - jschar *chars; - JSString *str, *str2; - - /* - * Any string literal term with all others number or string means - * this is a concatenation. If any term is not a string or number - * literal, we can't fold. - */ - JS_ASSERT(pn->pn_count > 2); - if (pn->pn_extra & PNX_CANTFOLD) - return JS_TRUE; - if (pn->pn_extra != PNX_STRCAT) - goto do_binary_op; - - /* Ok, we're concatenating: convert non-string constant operands. */ - length = 0; - for (pn2 = pn1; pn2; pn2 = pn2->pn_next) { - if (!FoldType(cx, pn2, TOK_STRING)) - return JS_FALSE; - /* XXX fold only if all operands convert to string */ - if (pn2->pn_type != TOK_STRING) - return JS_TRUE; - length += ATOM_TO_STRING(pn2->pn_atom)->length; - } - - /* Allocate a new buffer and string descriptor for the result. */ - chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar)); - if (!chars) - return JS_FALSE; - str = js_NewString(cx, chars, length, 0); - if (!str) { - JS_free(cx, chars); - return JS_FALSE; - } - - /* Fill the buffer, advancing chars and recycling kids as we go. */ - for (pn2 = pn1; pn2; pn2 = RecycleTree(pn2, tc)) { - str2 = ATOM_TO_STRING(pn2->pn_atom); - length2 = str2->length; - js_strncpy(chars, str2->chars, length2); - chars += length2; - } - *chars = 0; - - /* Atomize the result string and mutate pn to refer to it. */ - pn->pn_atom = js_AtomizeString(cx, str, 0); - if (!pn->pn_atom) - return JS_FALSE; - pn->pn_type = TOK_STRING; - pn->pn_op = JSOP_STRING; - pn->pn_arity = PN_NULLARY; - break; - } - - /* Handle a binary string concatenation. */ - JS_ASSERT(pn->pn_arity == PN_BINARY); - if (pn1->pn_type == TOK_STRING || pn2->pn_type == TOK_STRING) { - JSString *left, *right, *str; - - if (!FoldType(cx, (pn1->pn_type != TOK_STRING) ? pn1 : pn2, - TOK_STRING)) { - return JS_FALSE; - } - if (pn1->pn_type != TOK_STRING || pn2->pn_type != TOK_STRING) - return JS_TRUE; - left = ATOM_TO_STRING(pn1->pn_atom); - right = ATOM_TO_STRING(pn2->pn_atom); - str = js_ConcatStrings(cx, left, right); - if (!str) - return JS_FALSE; - pn->pn_atom = js_AtomizeString(cx, str, 0); - if (!pn->pn_atom) - return JS_FALSE; - pn->pn_type = TOK_STRING; - pn->pn_op = JSOP_STRING; - pn->pn_arity = PN_NULLARY; - RecycleTree(pn1, tc); - RecycleTree(pn2, tc); - break; - } - - /* Can't concatenate string literals, let's try numbers. */ - goto do_binary_op; - - case TOK_STAR: - /* The * in 'import *;' parses as a nullary star node. */ - if (pn->pn_arity == PN_NULLARY) - break; - /* FALL THROUGH */ - - case TOK_SHOP: - case TOK_MINUS: - case TOK_DIVOP: - do_binary_op: - if (pn->pn_arity == PN_LIST) { - JS_ASSERT(pn->pn_count > 2); - for (pn2 = pn1; pn2; pn2 = pn2->pn_next) { - if (!FoldType(cx, pn2, TOK_NUMBER)) - return JS_FALSE; - /* XXX fold only if all operands convert to number */ - if (pn2->pn_type != TOK_NUMBER) - break; - } - if (!pn2) { - JSOp op = pn->pn_op; - - pn2 = pn1->pn_next; - pn3 = pn2->pn_next; - if (!FoldBinaryNumeric(cx, op, pn1, pn2, pn, tc)) - return JS_FALSE; - while ((pn2 = pn3) != NULL) { - pn3 = pn2->pn_next; - if (!FoldBinaryNumeric(cx, op, pn, pn2, pn, tc)) - return JS_FALSE; - } - } - } else { - JS_ASSERT(pn->pn_arity == PN_BINARY); - if (!FoldType(cx, pn1, TOK_NUMBER) || - !FoldType(cx, pn2, TOK_NUMBER)) { - return JS_FALSE; - } - if (pn1->pn_type == TOK_NUMBER && pn2->pn_type == TOK_NUMBER) { - if (!FoldBinaryNumeric(cx, pn->pn_op, pn1, pn2, pn, tc)) - return JS_FALSE; - } - } - break; - - case TOK_UNARYOP: - if (pn1->pn_type == TOK_NUMBER) { - jsdouble d; - int32 i; - - /* Operate on one numeric constant. */ - d = pn1->pn_dval; - switch (pn->pn_op) { - case JSOP_BITNOT: - if (!js_DoubleToECMAInt32(cx, d, &i)) - return JS_FALSE; - d = ~i; - break; - - case JSOP_NEG: -#ifdef HPUX - /* - * Negation of a zero doesn't produce a negative - * zero on HPUX. Perform the operation by bit - * twiddling. - */ - JSDOUBLE_HI32(d) ^= JSDOUBLE_HI32_SIGNBIT; -#else - d = -d; -#endif - break; - - case JSOP_POS: - break; - - case JSOP_NOT: - pn->pn_type = TOK_PRIMARY; - pn->pn_op = (d == 0) ? JSOP_TRUE : JSOP_FALSE; - pn->pn_arity = PN_NULLARY; - /* FALL THROUGH */ - - default: - /* Return early to dodge the common TOK_NUMBER code. */ - return JS_TRUE; - } - pn->pn_type = TOK_NUMBER; - pn->pn_op = JSOP_NUMBER; - pn->pn_arity = PN_NULLARY; - pn->pn_dval = d; - RecycleTree(pn1, tc); - } - break; - -#if JS_HAS_XML_SUPPORT - case TOK_XMLELEM: - case TOK_XMLLIST: - case TOK_XMLPTAGC: - case TOK_XMLSTAGO: - case TOK_XMLETAGO: - case TOK_XMLNAME: - if (pn->pn_arity == PN_LIST) { - JS_ASSERT(pn->pn_type == TOK_XMLLIST || pn->pn_count != 0); - if (!FoldXMLConstants(cx, pn, tc)) - return JS_FALSE; - } - break; - - case TOK_AT: - if (pn1->pn_type == TOK_XMLNAME) { - jsval v; - JSAtom *atom; - - v = ATOM_KEY(pn1->pn_atom); - if (!js_ToAttributeName(cx, &v)) - return JS_FALSE; - JS_ASSERT(!JSVAL_IS_PRIMITIVE(v)); - atom = js_AtomizeObject(cx, JSVAL_TO_OBJECT(v), 0); - if (!atom) - return JS_FALSE; - - pn->pn_type = TOK_XMLNAME; - pn->pn_op = JSOP_OBJECT; - pn->pn_arity = PN_NULLARY; - pn->pn_atom = atom; - RecycleTree(pn1, tc); - } - break; -#endif /* JS_HAS_XML_SUPPORT */ - - default:; - } - - return JS_TRUE; -} diff --git a/lib/javascript/jsparse.h b/lib/javascript/jsparse.h deleted file mode 100644 index 24b27bdc..00000000 --- a/lib/javascript/jsparse.h +++ /dev/null @@ -1,414 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jsparse_h___ -#define jsparse_h___ -/* - * JS parser definitions. - */ -#include "jsconfig.h" -#include "jsprvtd.h" -#include "jspubtd.h" -#include "jsscan.h" - -JS_BEGIN_EXTERN_C - -/* - * Parsing builds a tree of nodes that directs code generation. This tree is - * not a concrete syntax tree in all respects (for example, || and && are left - * associative, but (A && B && C) translates into the right-associated tree - * > so that code generation can emit a left-associative branch - * around when A is false). Nodes are labeled by token type, with a - * JSOp secondary label when needed: - * - * Label Variant Members - * ----- ------- ------- - * - * TOK_FUNCTION func pn_funAtom: atom holding function object containing - * arg and var properties. We create the function - * object at parse (not emit) time to specialize arg - * and var bytecodes early. - * pn_body: TOK_LC node for function body statements - * pn_flags: TCF_FUN_* flags (see jsemit.h) collected - * while parsing the function's body - * pn_tryCount: of try statements in function - * - * - * TOK_LC list pn_head: list of pn_count statements - * TOK_EXPORT list pn_head: list of pn_count TOK_NAMEs or one TOK_STAR - * (which is not a multiply node) - * TOK_IMPORT list pn_head: list of pn_count sub-trees of the form - * a.b.*, a[b].*, a.*, a.b, or a[b] -- but never a. - * Each member is expressed with TOK_DOT or TOK_LB. - * Each sub-tree's root node has a pn_op in the set - * JSOP_IMPORT{ALL,PROP,ELEM} - * TOK_IF ternary pn_kid1: cond, pn_kid2: then, pn_kid3: else or null - * TOK_SWITCH binary pn_left: discriminant - * pn_right: list of TOK_CASE nodes, with at most one - * TOK_DEFAULT node - * TOK_CASE, binary pn_left: case expr or null if TOK_DEFAULT - * TOK_DEFAULT pn_right: TOK_LC node for this case's statements - * pn_val: constant value if lookup or table switch - * TOK_WHILE binary pn_left: cond, pn_right: body - * TOK_DO binary pn_left: body, pn_right: cond - * TOK_FOR binary pn_left: either - * for/in loop: a binary TOK_IN node with - * pn_left: TOK_VAR or TOK_NAME to left of 'in' - * if TOK_VAR, its pn_extra may have PNX_POPVAR - * and PNX_FORINVAR bits set - * pn_right: object expr to right of 'in' - * for(;;) loop: a ternary TOK_RESERVED node with - * pn_kid1: init expr before first ';' - * pn_kid2: cond expr before second ';' - * pn_kid3: update expr after second ';' - * any kid may be null - * pn_right: body - * TOK_THROW unary pn_op: JSOP_THROW, pn_kid: exception - * TOK_TRY ternary pn_kid1: try block - * pn_kid2: catch blocks or null - * pn_kid3: finally block or null - * TOK_CATCH ternary pn_kid1: PN_NAME node for catch var (with pn_expr - * null or the catch guard expression) - * pn_kid2: more catch blocks or null - * pn_kid3: catch block statements - * TOK_BREAK name pn_atom: label or null - * TOK_CONTINUE name pn_atom: label or null - * TOK_WITH binary pn_left: head expr, pn_right: body - * TOK_VAR list pn_head: list of pn_count TOK_NAME nodes - * each name node has - * pn_atom: variable name - * pn_expr: initializer or null - * TOK_RETURN unary pn_kid: return expr or null - * TOK_SEMI unary pn_kid: expr or null statement - * TOK_COLON name pn_atom: label, pn_expr: labeled statement - * - * - * All left-associated binary trees of the same type are optimized into lists - * to avoid recursion when processing expression chains. - * TOK_COMMA list pn_head: list of pn_count comma-separated exprs - * TOK_ASSIGN binary pn_left: lvalue, pn_right: rvalue - * pn_op: JSOP_ADD for +=, etc. - * TOK_HOOK ternary pn_kid1: cond, pn_kid2: then, pn_kid3: else - * TOK_OR binary pn_left: first in || chain, pn_right: rest of chain - * TOK_AND binary pn_left: first in && chain, pn_right: rest of chain - * TOK_BITOR binary pn_left: left-assoc | expr, pn_right: ^ expr - * TOK_BITXOR binary pn_left: left-assoc ^ expr, pn_right: & expr - * TOK_BITAND binary pn_left: left-assoc & expr, pn_right: EQ expr - * TOK_EQOP binary pn_left: left-assoc EQ expr, pn_right: REL expr - * pn_op: JSOP_EQ, JSOP_NE, JSOP_NEW_EQ, JSOP_NEW_NE - * TOK_RELOP binary pn_left: left-assoc REL expr, pn_right: SH expr - * pn_op: JSOP_LT, JSOP_LE, JSOP_GT, JSOP_GE - * TOK_SHOP binary pn_left: left-assoc SH expr, pn_right: ADD expr - * pn_op: JSOP_LSH, JSOP_RSH, JSOP_URSH - * TOK_PLUS, binary pn_left: left-assoc ADD expr, pn_right: MUL expr - * pn_extra: if a left-associated binary TOK_PLUS - * tree has been flattened into a list (see above - * under ), pn_extra will contain - * PNX_STRCAT if at least one list element is a - * string literal (TOK_STRING); if such a list has - * any non-string, non-number term, pn_extra will - * contain PNX_CANTFOLD. - * pn_ - * TOK_MINUS pn_op: JSOP_ADD, JSOP_SUB - * TOK_STAR, binary pn_left: left-assoc MUL expr, pn_right: UNARY expr - * TOK_DIVOP pn_op: JSOP_MUL, JSOP_DIV, JSOP_MOD - * TOK_UNARYOP unary pn_kid: UNARY expr, pn_op: JSOP_NEG, JSOP_POS, - * JSOP_NOT, JSOP_BITNOT, JSOP_TYPEOF, JSOP_VOID - * TOK_INC, unary pn_kid: MEMBER expr - * TOK_DEC - * TOK_NEW list pn_head: list of ctor, arg1, arg2, ... argN - * pn_count: 1 + N (where N is number of args) - * ctor is a MEMBER expr - * TOK_DELETE unary pn_kid: MEMBER expr - * TOK_DOT, name pn_expr: MEMBER expr to left of . - * TOK_DBLDOT pn_atom: name to right of . - * TOK_LB binary pn_left: MEMBER expr to left of [ - * pn_right: expr between [ and ] - * TOK_LP list pn_head: list of call, arg1, arg2, ... argN - * pn_count: 1 + N (where N is number of args) - * call is a MEMBER expr naming a callable object - * TOK_RB list pn_head: list of pn_count array element exprs - * [,,] holes are represented by TOK_COMMA nodes - * #n=[...] produces TOK_DEFSHARP at head of list - * pn_extra: PN_ENDCOMMA if extra comma at end - * TOK_RC list pn_head: list of pn_count TOK_COLON nodes where - * each has pn_left: property id, pn_right: value - * #n={...} produces TOK_DEFSHARP at head of list - * TOK_DEFSHARP unary pn_num: jsint value of n in #n= - * pn_kid: null for #n=[...] and #n={...}, primary - * if #n=primary for function, paren, name, object - * literal expressions - * TOK_USESHARP nullary pn_num: jsint value of n in #n# - * TOK_RP unary pn_kid: parenthesized expression - * TOK_NAME, name pn_atom: name, string, or object atom - * TOK_STRING, pn_op: JSOP_NAME, JSOP_STRING, or JSOP_OBJECT, or - * JSOP_REGEXP - * TOK_OBJECT If JSOP_NAME, pn_op may be JSOP_*ARG or JSOP_*VAR - * with pn_slot >= 0 and pn_attrs telling const-ness - * TOK_NUMBER dval pn_dval: double value of numeric literal - * TOK_PRIMARY nullary pn_op: JSOp bytecode - * TOK_ANYNAME nullary pn_op: JSOP_ANYNAME - * pn_atom: cx->runtime->atomState.starAtom - * TOK_AT unary pn_op: JSOP_TOATTRNAME; pn_kid attribute id/expr - * TOK_DBLCOLON binary pn_op: JSOP_QNAME - * pn_left: TOK_ANYNAME or TOK_NAME node - * pn_right: TOK_STRING "*" node, or expr within [] - * name pn_op: JSOP_QNAMECONST - * pn_expr: TOK_ANYNAME or TOK_NAME left operand - * pn_atom: name on right of :: - * TOK_XMLELEM list XML element node - * pn_head: start tag, content1, ... contentN, end tag - * pn_count: 2 + N where N is number of content nodes - * N may be > x.length() if {expr} embedded - * TOK_XMLLIST list XML list node - * pn_head: content1, ... contentN - * TOK_XMLSTAGO, list XML start, end, and point tag contents - * TOK_XMLETAGC, pn_head: tag name or {expr}, ... XML attrs ... - * TOK_XMLPTAGO - * TOK_XMLNAME nullary pn_atom: XML name, with no {expr} embedded - * TOK_XMLNAME list pn_head: tag name or {expr}, ... name or {expr} - * TOK_XMLATTR, nullary pn_atom: attribute value string; pn_op: JSOP_STRING - * TOK_XMLCDATA, - * TOK_XMLCOMMENT - * TOK_XMLPI nullary pn_atom: XML processing instruction target - * pn_atom2: XML PI content, or null if no content - * TOK_XMLTEXT nullary pn_atom: marked-up text, or null if empty string - * TOK_LC unary {expr} in XML tag or content; pn_kid is expr - * - * So an XML tag with no {expr} and three attributes is a list with the form: - * - * (tagname attrname1 attrvalue1 attrname2 attrvalue2 attrname2 attrvalue3) - * - * An XML tag with embedded expressions like so: - * - * - * - * would have the form: - * - * ((name1 {expr1}) (name2 {expr2} name3) {expr3}) - * - * where () bracket a list with elements separated by spaces, and {expr} is a - * TOK_LC unary node with expr as its kid. - * - * Thus, the attribute name/value pairs occupy successive odd and even list - * locations, where pn_head is the TOK_XMLNAME node at list location 0. The - * parser builds the same sort of structures for elements: - * - * Hi there!How are you?{x + y} - * - * translates to: - * - * ((a x {x}) 'Hi there!' ((b y {y}) 'How are you?') ((answer) {x + y})) - */ -typedef enum JSParseNodeArity { - PN_FUNC = -3, - PN_LIST = -2, - PN_TERNARY = 3, - PN_BINARY = 2, - PN_UNARY = 1, - PN_NAME = -1, - PN_NULLARY = 0 -} JSParseNodeArity; - -struct JSParseNode { - uint16 pn_type; - uint8 pn_op; - int8 pn_arity; - JSTokenPos pn_pos; - ptrdiff_t pn_offset; /* first generated bytecode offset */ - union { - struct { /* TOK_FUNCTION node */ - JSAtom *funAtom; /* atomized function object */ - JSParseNode *body; /* TOK_LC list of statements */ - uint32 flags; /* accumulated tree context flags */ - uint32 tryCount; /* count of try statements in body */ - } func; - struct { /* list of next-linked nodes */ - JSParseNode *head; /* first node in list */ - JSParseNode **tail; /* ptr to ptr to last node in list */ - uint32 count; /* number of nodes in list */ - uint32 extra; /* extra comma flag for [1,2,,] */ - } list; - struct { /* ternary: if, for(;;), ?: */ - JSParseNode *kid1; /* condition, discriminant, etc. */ - JSParseNode *kid2; /* then-part, case list, etc. */ - JSParseNode *kid3; /* else-part, default case, etc. */ - } ternary; - struct { /* two kids if binary */ - JSParseNode *left; - JSParseNode *right; - jsval val; /* switch case value */ - } binary; - struct { /* one kid if unary */ - JSParseNode *kid; - jsint num; /* -1 or sharp variable number */ - } unary; - struct { /* name, labeled statement, etc. */ - JSAtom *atom; /* name or label atom, null if slot */ - JSParseNode *expr; /* object or initializer */ - jsint slot; /* -1 or arg or local var slot */ - uintN attrs; /* attributes if local var or const */ - } name; - struct { - JSAtom *atom; /* first atom in pair */ - JSAtom *atom2; /* second atom in pair or null */ - } apair; - jsdouble dval; /* aligned numeric literal value */ - } pn_u; - JSParseNode *pn_next; /* to align dval and pn_u on RISCs */ -#if JS_HAS_XML_SUPPORT - JSTokenStream *pn_ts; /* token stream for XML error reports */ -#endif -}; - -#define pn_funAtom pn_u.func.funAtom -#define pn_body pn_u.func.body -#define pn_flags pn_u.func.flags -#define pn_tryCount pn_u.func.tryCount -#define pn_head pn_u.list.head -#define pn_tail pn_u.list.tail -#define pn_count pn_u.list.count -#define pn_extra pn_u.list.extra -#define pn_kid1 pn_u.ternary.kid1 -#define pn_kid2 pn_u.ternary.kid2 -#define pn_kid3 pn_u.ternary.kid3 -#define pn_left pn_u.binary.left -#define pn_right pn_u.binary.right -#define pn_val pn_u.binary.val -#define pn_kid pn_u.unary.kid -#define pn_num pn_u.unary.num -#define pn_atom pn_u.name.atom -#define pn_expr pn_u.name.expr -#define pn_slot pn_u.name.slot -#define pn_attrs pn_u.name.attrs -#define pn_dval pn_u.dval -#define pn_atom2 pn_u.apair.atom2 - -/* PN_LIST pn_extra flags. */ -#define PNX_STRCAT 0x01 /* TOK_PLUS list has string term */ -#define PNX_CANTFOLD 0x02 /* TOK_PLUS list has unfoldable term */ -#define PNX_POPVAR 0x04 /* TOK_VAR last result needs popping */ -#define PNX_FORINVAR 0x08 /* TOK_VAR is left kid of TOK_IN node, - which is left kid of TOK_FOR */ -#define PNX_ENDCOMMA 0x10 /* array literal has comma at end */ -#define PNX_XMLROOT 0x20 /* top-most node in XML literal tree */ - -/* - * Move pn2 into pn, preserving pn->pn_pos and pn->pn_offset and handing off - * any kids in pn2->pn_u, by clearing pn2. - */ -#define PN_MOVE_NODE(pn, pn2) \ - JS_BEGIN_MACRO \ - (pn)->pn_type = (pn2)->pn_type; \ - (pn)->pn_op = (pn2)->pn_op; \ - (pn)->pn_arity = (pn2)->pn_arity; \ - (pn)->pn_u = (pn2)->pn_u; \ - PN_CLEAR_NODE(pn2); \ - JS_END_MACRO - -#define PN_CLEAR_NODE(pn) \ - JS_BEGIN_MACRO \ - (pn)->pn_type = TOK_EOF; \ - (pn)->pn_op = JSOP_NOP; \ - (pn)->pn_arity = PN_NULLARY; \ - JS_END_MACRO - -/* True if pn is a parsenode representing a literal constant. */ -#define PN_IS_CONSTANT(pn) \ - ((pn)->pn_type == TOK_NUMBER || \ - (pn)->pn_type == TOK_STRING || \ - ((pn)->pn_type == TOK_PRIMARY && (pn)->pn_op != JSOP_THIS)) - -/* - * Compute a pointer to the last JSParseNode element in a singly-linked list. - * NB: list must be non-empty for correct PN_LAST usage! - */ -#define PN_LAST(list) \ - ((JSParseNode *)((char *)(list)->pn_tail - offsetof(JSParseNode, pn_next))) - -#define PN_INIT_LIST(list) \ - JS_BEGIN_MACRO \ - (list)->pn_head = NULL; \ - (list)->pn_tail = &(list)->pn_head; \ - (list)->pn_count = (list)->pn_extra = 0; \ - JS_END_MACRO - -#define PN_INIT_LIST_1(list, pn) \ - JS_BEGIN_MACRO \ - (list)->pn_head = (pn); \ - (list)->pn_tail = &(pn)->pn_next; \ - (list)->pn_count = 1; \ - (list)->pn_extra = 0; \ - JS_END_MACRO - -#define PN_APPEND(list, pn) \ - JS_BEGIN_MACRO \ - *(list)->pn_tail = (pn); \ - (list)->pn_tail = &(pn)->pn_next; \ - (list)->pn_count++; \ - JS_END_MACRO - -/* - * Parse a top-level JS script. - * - * The caller must prevent the GC from running while this function is active, - * because atoms and function newborns are not rooted yet. - */ -extern JS_FRIEND_API(JSParseNode *) -js_ParseTokenStream(JSContext *cx, JSObject *chain, JSTokenStream *ts); - -extern JS_FRIEND_API(JSBool) -js_CompileTokenStream(JSContext *cx, JSObject *chain, JSTokenStream *ts, - JSCodeGenerator *cg); - -extern JSBool -js_CompileFunctionBody(JSContext *cx, JSTokenStream *ts, JSFunction *fun); - -extern JSBool -js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc); - -#if JS_HAS_XML_SUPPORT -JS_FRIEND_API(JSParseNode *) -js_ParseXMLTokenStream(JSContext *cx, JSObject *chain, JSTokenStream *ts, - JSBool allowList); -#endif - -JS_END_EXTERN_C - -#endif /* jsparse_h___ */ diff --git a/lib/javascript/jsprf.c b/lib/javascript/jsprf.c deleted file mode 100644 index ba7c0f03..00000000 --- a/lib/javascript/jsprf.c +++ /dev/null @@ -1,1264 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* -** Portable safe sprintf code. -** -** Author: Kipp E.B. Hickman -*/ -#include "jsstddef.h" -#include -#include -#include -#include -#include "jsprf.h" -#include "jslong.h" -#include "jsutil.h" /* Added by JSIFY */ -#include "jspubtd.h" -#include "jsstr.h" - -/* -** Note: on some platforms va_list is defined as an array, -** and requires array notation. -*/ -#ifdef HAVE_VA_COPY -#define VARARGS_ASSIGN(foo, bar) VA_COPY(foo,bar) -#elif defined(HAVE_VA_LIST_AS_ARRAY) -#define VARARGS_ASSIGN(foo, bar) foo[0] = bar[0] -#else -#define VARARGS_ASSIGN(foo, bar) (foo) = (bar) -#endif - -/* -** WARNING: This code may *NOT* call JS_LOG (because JS_LOG calls it) -*/ - -/* -** XXX This needs to be internationalized! -*/ - -typedef struct SprintfStateStr SprintfState; - -struct SprintfStateStr { - int (*stuff)(SprintfState *ss, const char *sp, JSUint32 len); - - char *base; - char *cur; - JSUint32 maxlen; - - int (*func)(void *arg, const char *sp, JSUint32 len); - void *arg; -}; - -/* -** Numbered Arguement State -*/ -struct NumArgState{ - int type; /* type of the current ap */ - va_list ap; /* point to the corresponding position on ap */ -}; - -#define NAS_DEFAULT_NUM 20 /* default number of NumberedArgumentState array */ - - -#define TYPE_INT16 0 -#define TYPE_UINT16 1 -#define TYPE_INTN 2 -#define TYPE_UINTN 3 -#define TYPE_INT32 4 -#define TYPE_UINT32 5 -#define TYPE_INT64 6 -#define TYPE_UINT64 7 -#define TYPE_STRING 8 -#define TYPE_DOUBLE 9 -#define TYPE_INTSTR 10 -#define TYPE_WSTRING 11 -#define TYPE_UNKNOWN 20 - -#define FLAG_LEFT 0x1 -#define FLAG_SIGNED 0x2 -#define FLAG_SPACED 0x4 -#define FLAG_ZEROS 0x8 -#define FLAG_NEG 0x10 - -/* -** Fill into the buffer using the data in src -*/ -static int fill2(SprintfState *ss, const char *src, int srclen, int width, - int flags) -{ - char space = ' '; - int rv; - - width -= srclen; - if ((width > 0) && ((flags & FLAG_LEFT) == 0)) { /* Right adjusting */ - if (flags & FLAG_ZEROS) { - space = '0'; - } - while (--width >= 0) { - rv = (*ss->stuff)(ss, &space, 1); - if (rv < 0) { - return rv; - } - } - } - - /* Copy out the source data */ - rv = (*ss->stuff)(ss, src, (JSUint32)srclen); - if (rv < 0) { - return rv; - } - - if ((width > 0) && ((flags & FLAG_LEFT) != 0)) { /* Left adjusting */ - while (--width >= 0) { - rv = (*ss->stuff)(ss, &space, 1); - if (rv < 0) { - return rv; - } - } - } - return 0; -} - -/* -** Fill a number. The order is: optional-sign zero-filling conversion-digits -*/ -static int fill_n(SprintfState *ss, const char *src, int srclen, int width, - int prec, int type, int flags) -{ - int zerowidth = 0; - int precwidth = 0; - int signwidth = 0; - int leftspaces = 0; - int rightspaces = 0; - int cvtwidth; - int rv; - char sign; - - if ((type & 1) == 0) { - if (flags & FLAG_NEG) { - sign = '-'; - signwidth = 1; - } else if (flags & FLAG_SIGNED) { - sign = '+'; - signwidth = 1; - } else if (flags & FLAG_SPACED) { - sign = ' '; - signwidth = 1; - } - } - cvtwidth = signwidth + srclen; - - if (prec > 0) { - if (prec > srclen) { - precwidth = prec - srclen; /* Need zero filling */ - cvtwidth += precwidth; - } - } - - if ((flags & FLAG_ZEROS) && (prec < 0)) { - if (width > cvtwidth) { - zerowidth = width - cvtwidth; /* Zero filling */ - cvtwidth += zerowidth; - } - } - - if (flags & FLAG_LEFT) { - if (width > cvtwidth) { - /* Space filling on the right (i.e. left adjusting) */ - rightspaces = width - cvtwidth; - } - } else { - if (width > cvtwidth) { - /* Space filling on the left (i.e. right adjusting) */ - leftspaces = width - cvtwidth; - } - } - while (--leftspaces >= 0) { - rv = (*ss->stuff)(ss, " ", 1); - if (rv < 0) { - return rv; - } - } - if (signwidth) { - rv = (*ss->stuff)(ss, &sign, 1); - if (rv < 0) { - return rv; - } - } - while (--precwidth >= 0) { - rv = (*ss->stuff)(ss, "0", 1); - if (rv < 0) { - return rv; - } - } - while (--zerowidth >= 0) { - rv = (*ss->stuff)(ss, "0", 1); - if (rv < 0) { - return rv; - } - } - rv = (*ss->stuff)(ss, src, (JSUint32)srclen); - if (rv < 0) { - return rv; - } - while (--rightspaces >= 0) { - rv = (*ss->stuff)(ss, " ", 1); - if (rv < 0) { - return rv; - } - } - return 0; -} - -/* -** Convert a long into its printable form -*/ -static int cvt_l(SprintfState *ss, long num, int width, int prec, int radix, - int type, int flags, const char *hexp) -{ - char cvtbuf[100]; - char *cvt; - int digits; - - /* according to the man page this needs to happen */ - if ((prec == 0) && (num == 0)) { - return 0; - } - - /* - ** Converting decimal is a little tricky. In the unsigned case we - ** need to stop when we hit 10 digits. In the signed case, we can - ** stop when the number is zero. - */ - cvt = cvtbuf + sizeof(cvtbuf); - digits = 0; - while (num) { - int digit = (((unsigned long)num) % radix) & 0xF; - *--cvt = hexp[digit]; - digits++; - num = (long)(((unsigned long)num) / radix); - } - if (digits == 0) { - *--cvt = '0'; - digits++; - } - - /* - ** Now that we have the number converted without its sign, deal with - ** the sign and zero padding. - */ - return fill_n(ss, cvt, digits, width, prec, type, flags); -} - -/* -** Convert a 64-bit integer into its printable form -*/ -static int cvt_ll(SprintfState *ss, JSInt64 num, int width, int prec, int radix, - int type, int flags, const char *hexp) -{ - char cvtbuf[100]; - char *cvt; - int digits; - JSInt64 rad; - - /* according to the man page this needs to happen */ - if ((prec == 0) && (JSLL_IS_ZERO(num))) { - return 0; - } - - /* - ** Converting decimal is a little tricky. In the unsigned case we - ** need to stop when we hit 10 digits. In the signed case, we can - ** stop when the number is zero. - */ - JSLL_I2L(rad, radix); - cvt = cvtbuf + sizeof(cvtbuf); - digits = 0; - while (!JSLL_IS_ZERO(num)) { - JSInt32 digit; - JSInt64 quot, rem; - JSLL_UDIVMOD(", &rem, num, rad); - JSLL_L2I(digit, rem); - *--cvt = hexp[digit & 0xf]; - digits++; - num = quot; - } - if (digits == 0) { - *--cvt = '0'; - digits++; - } - - /* - ** Now that we have the number converted without its sign, deal with - ** the sign and zero padding. - */ - return fill_n(ss, cvt, digits, width, prec, type, flags); -} - -/* -** Convert a double precision floating point number into its printable -** form. -** -** XXX stop using sprintf to convert floating point -*/ -static int cvt_f(SprintfState *ss, double d, const char *fmt0, const char *fmt1) -{ - char fin[20]; - char fout[300]; - int amount = fmt1 - fmt0; - - JS_ASSERT((amount > 0) && (amount < (int)sizeof(fin))); - if (amount >= (int)sizeof(fin)) { - /* Totally bogus % command to sprintf. Just ignore it */ - return 0; - } - memcpy(fin, fmt0, (size_t)amount); - fin[amount] = 0; - - /* Convert floating point using the native sprintf code */ -#ifdef DEBUG - { - const char *p = fin; - while (*p) { - JS_ASSERT(*p != 'L'); - p++; - } - } -#endif - sprintf(fout, fin, d); - - /* - ** This assert will catch overflow's of fout, when building with - ** debugging on. At least this way we can track down the evil piece - ** of calling code and fix it! - */ - JS_ASSERT(strlen(fout) < sizeof(fout)); - - return (*ss->stuff)(ss, fout, strlen(fout)); -} - -/* -** Convert a string into its printable form. "width" is the output -** width. "prec" is the maximum number of characters of "s" to output, -** where -1 means until NUL. -*/ -static int cvt_s(SprintfState *ss, const char *s, int width, int prec, - int flags) -{ - int slen; - - if (prec == 0) - return 0; - - /* Limit string length by precision value */ - slen = s ? strlen(s) : 6; - if (prec > 0) { - if (prec < slen) { - slen = prec; - } - } - - /* and away we go */ - return fill2(ss, s ? s : "(null)", slen, width, flags); -} - -static int cvt_ws(SprintfState *ss, const jschar *ws, int width, int prec, - int flags) -{ - int result; - /* - * Supply NULL as the JSContext; errors are not reported, - * and malloc() is used to allocate the buffer buffer. - */ - if (ws) { - int slen = js_strlen(ws); - char *s = js_DeflateString(NULL, ws, slen); - if (!s) - return -1; /* JSStuffFunc error indicator. */ - result = cvt_s(ss, s, width, prec, flags); - free(s); - } else { - result = cvt_s(ss, NULL, width, prec, flags); - } - return result; -} - -/* -** BuildArgArray stands for Numbered Argument list Sprintf -** for example, -** fmp = "%4$i, %2$d, %3s, %1d"; -** the number must start from 1, and no gap among them -*/ - -static struct NumArgState* BuildArgArray( const char *fmt, va_list ap, int* rv, struct NumArgState* nasArray ) -{ - int number = 0, cn = 0, i; - const char *p; - char c; - struct NumArgState *nas; - - - /* - ** first pass: - ** detemine how many legal % I have got, then allocate space - */ - - p = fmt; - *rv = 0; - i = 0; - while( ( c = *p++ ) != 0 ){ - if( c != '%' ) - continue; - if( ( c = *p++ ) == '%' ) /* skip %% case */ - continue; - - while( c != 0 ){ - if( c > '9' || c < '0' ){ - if( c == '$' ){ /* numbered argument csae */ - if( i > 0 ){ - *rv = -1; - return NULL; - } - number++; - } else { /* non-numbered argument case */ - if( number > 0 ){ - *rv = -1; - return NULL; - } - i = 1; - } - break; - } - - c = *p++; - } - } - - if( number == 0 ){ - return NULL; - } - - - if( number > NAS_DEFAULT_NUM ){ - nas = (struct NumArgState*)malloc( number * sizeof( struct NumArgState ) ); - if( !nas ){ - *rv = -1; - return NULL; - } - } else { - nas = nasArray; - } - - for( i = 0; i < number; i++ ){ - nas[i].type = TYPE_UNKNOWN; - } - - - /* - ** second pass: - ** set nas[].type - */ - - p = fmt; - while( ( c = *p++ ) != 0 ){ - if( c != '%' ) continue; - c = *p++; - if( c == '%' ) continue; - - cn = 0; - while( c && c != '$' ){ /* should improve error check later */ - cn = cn*10 + c - '0'; - c = *p++; - } - - if( !c || cn < 1 || cn > number ){ - *rv = -1; - break; - } - - /* nas[cn] starts from 0, and make sure nas[cn].type is not assigned */ - cn--; - if( nas[cn].type != TYPE_UNKNOWN ) - continue; - - c = *p++; - - /* width */ - if (c == '*') { - /* not supported feature, for the argument is not numbered */ - *rv = -1; - break; - } - - while ((c >= '0') && (c <= '9')) { - c = *p++; - } - - /* precision */ - if (c == '.') { - c = *p++; - if (c == '*') { - /* not supported feature, for the argument is not numbered */ - *rv = -1; - break; - } - - while ((c >= '0') && (c <= '9')) { - c = *p++; - } - } - - /* size */ - nas[cn].type = TYPE_INTN; - if (c == 'h') { - nas[cn].type = TYPE_INT16; - c = *p++; - } else if (c == 'L') { - /* XXX not quite sure here */ - nas[cn].type = TYPE_INT64; - c = *p++; - } else if (c == 'l') { - nas[cn].type = TYPE_INT32; - c = *p++; - if (c == 'l') { - nas[cn].type = TYPE_INT64; - c = *p++; - } - } - - /* format */ - switch (c) { - case 'd': - case 'c': - case 'i': - case 'o': - case 'u': - case 'x': - case 'X': - break; - - case 'e': - case 'f': - case 'g': - nas[ cn ].type = TYPE_DOUBLE; - break; - - case 'p': - /* XXX should use cpp */ - if (sizeof(void *) == sizeof(JSInt32)) { - nas[ cn ].type = TYPE_UINT32; - } else if (sizeof(void *) == sizeof(JSInt64)) { - nas[ cn ].type = TYPE_UINT64; - } else if (sizeof(void *) == sizeof(JSIntn)) { - nas[ cn ].type = TYPE_UINTN; - } else { - nas[ cn ].type = TYPE_UNKNOWN; - } - break; - - case 'C': - case 'S': - case 'E': - case 'G': - /* XXX not supported I suppose */ - JS_ASSERT(0); - nas[ cn ].type = TYPE_UNKNOWN; - break; - - case 's': - nas[ cn ].type = (nas[ cn ].type == TYPE_UINT16) ? TYPE_WSTRING : TYPE_STRING; - break; - - case 'n': - nas[ cn ].type = TYPE_INTSTR; - break; - - default: - JS_ASSERT(0); - nas[ cn ].type = TYPE_UNKNOWN; - break; - } - - /* get a legal para. */ - if( nas[ cn ].type == TYPE_UNKNOWN ){ - *rv = -1; - break; - } - } - - - /* - ** third pass - ** fill the nas[cn].ap - */ - - if( *rv < 0 ){ - if( nas != nasArray ) - free( nas ); - return NULL; - } - - cn = 0; - while( cn < number ){ - if( nas[cn].type == TYPE_UNKNOWN ){ - cn++; - continue; - } - - VARARGS_ASSIGN(nas[cn].ap, ap); - - switch( nas[cn].type ){ - case TYPE_INT16: - case TYPE_UINT16: - case TYPE_INTN: - case TYPE_UINTN: (void)va_arg( ap, JSIntn ); break; - - case TYPE_INT32: (void)va_arg( ap, JSInt32 ); break; - - case TYPE_UINT32: (void)va_arg( ap, JSUint32 ); break; - - case TYPE_INT64: (void)va_arg( ap, JSInt64 ); break; - - case TYPE_UINT64: (void)va_arg( ap, JSUint64 ); break; - - case TYPE_STRING: (void)va_arg( ap, char* ); break; - - case TYPE_WSTRING: (void)va_arg( ap, jschar* ); break; - - case TYPE_INTSTR: (void)va_arg( ap, JSIntn* ); break; - - case TYPE_DOUBLE: (void)va_arg( ap, double ); break; - - default: - if( nas != nasArray ) - free( nas ); - *rv = -1; - return NULL; - } - - cn++; - } - - - return nas; -} - -/* -** The workhorse sprintf code. -*/ -static int dosprintf(SprintfState *ss, const char *fmt, va_list ap) -{ - char c; - int flags, width, prec, radix, type; - union { - char ch; - jschar wch; - int i; - long l; - JSInt64 ll; - double d; - const char *s; - const jschar* ws; - int *ip; - } u; - const char *fmt0; - static char *hex = "0123456789abcdef"; - static char *HEX = "0123456789ABCDEF"; - char *hexp; - int rv, i; - struct NumArgState *nas = NULL; - struct NumArgState nasArray[ NAS_DEFAULT_NUM ]; - char pattern[20]; - const char *dolPt = NULL; /* in "%4$.2f", dolPt will poiont to . */ -#ifdef JS_C_STRINGS_ARE_UTF8 - char utf8buf[6]; - int utf8len; -#endif - - /* - ** build an argument array, IF the fmt is numbered argument - ** list style, to contain the Numbered Argument list pointers - */ - - nas = BuildArgArray( fmt, ap, &rv, nasArray ); - if( rv < 0 ){ - /* the fmt contains error Numbered Argument format, jliu@netscape.com */ - JS_ASSERT(0); - return rv; - } - - while ((c = *fmt++) != 0) { - if (c != '%') { - rv = (*ss->stuff)(ss, fmt - 1, 1); - if (rv < 0) { - return rv; - } - continue; - } - fmt0 = fmt - 1; - - /* - ** Gobble up the % format string. Hopefully we have handled all - ** of the strange cases! - */ - flags = 0; - c = *fmt++; - if (c == '%') { - /* quoting a % with %% */ - rv = (*ss->stuff)(ss, fmt - 1, 1); - if (rv < 0) { - return rv; - } - continue; - } - - if( nas != NULL ){ - /* the fmt contains the Numbered Arguments feature */ - i = 0; - while( c && c != '$' ){ /* should imporve error check later */ - i = ( i * 10 ) + ( c - '0' ); - c = *fmt++; - } - - if( nas[i-1].type == TYPE_UNKNOWN ){ - if( nas && ( nas != nasArray ) ) - free( nas ); - return -1; - } - - ap = nas[i-1].ap; - dolPt = fmt; - c = *fmt++; - } - - /* - * Examine optional flags. Note that we do not implement the - * '#' flag of sprintf(). The ANSI C spec. of the '#' flag is - * somewhat ambiguous and not ideal, which is perhaps why - * the various sprintf() implementations are inconsistent - * on this feature. - */ - while ((c == '-') || (c == '+') || (c == ' ') || (c == '0')) { - if (c == '-') flags |= FLAG_LEFT; - if (c == '+') flags |= FLAG_SIGNED; - if (c == ' ') flags |= FLAG_SPACED; - if (c == '0') flags |= FLAG_ZEROS; - c = *fmt++; - } - if (flags & FLAG_SIGNED) flags &= ~FLAG_SPACED; - if (flags & FLAG_LEFT) flags &= ~FLAG_ZEROS; - - /* width */ - if (c == '*') { - c = *fmt++; - width = va_arg(ap, int); - } else { - width = 0; - while ((c >= '0') && (c <= '9')) { - width = (width * 10) + (c - '0'); - c = *fmt++; - } - } - - /* precision */ - prec = -1; - if (c == '.') { - c = *fmt++; - if (c == '*') { - c = *fmt++; - prec = va_arg(ap, int); - } else { - prec = 0; - while ((c >= '0') && (c <= '9')) { - prec = (prec * 10) + (c - '0'); - c = *fmt++; - } - } - } - - /* size */ - type = TYPE_INTN; - if (c == 'h') { - type = TYPE_INT16; - c = *fmt++; - } else if (c == 'L') { - /* XXX not quite sure here */ - type = TYPE_INT64; - c = *fmt++; - } else if (c == 'l') { - type = TYPE_INT32; - c = *fmt++; - if (c == 'l') { - type = TYPE_INT64; - c = *fmt++; - } - } - - /* format */ - hexp = hex; - switch (c) { - case 'd': case 'i': /* decimal/integer */ - radix = 10; - goto fetch_and_convert; - - case 'o': /* octal */ - radix = 8; - type |= 1; - goto fetch_and_convert; - - case 'u': /* unsigned decimal */ - radix = 10; - type |= 1; - goto fetch_and_convert; - - case 'x': /* unsigned hex */ - radix = 16; - type |= 1; - goto fetch_and_convert; - - case 'X': /* unsigned HEX */ - radix = 16; - hexp = HEX; - type |= 1; - goto fetch_and_convert; - - fetch_and_convert: - switch (type) { - case TYPE_INT16: - u.l = va_arg(ap, int); - if (u.l < 0) { - u.l = -u.l; - flags |= FLAG_NEG; - } - goto do_long; - case TYPE_UINT16: - u.l = va_arg(ap, int) & 0xffff; - goto do_long; - case TYPE_INTN: - u.l = va_arg(ap, int); - if (u.l < 0) { - u.l = -u.l; - flags |= FLAG_NEG; - } - goto do_long; - case TYPE_UINTN: - u.l = (long)va_arg(ap, unsigned int); - goto do_long; - - case TYPE_INT32: - u.l = va_arg(ap, JSInt32); - if (u.l < 0) { - u.l = -u.l; - flags |= FLAG_NEG; - } - goto do_long; - case TYPE_UINT32: - u.l = (long)va_arg(ap, JSUint32); - do_long: - rv = cvt_l(ss, u.l, width, prec, radix, type, flags, hexp); - if (rv < 0) { - return rv; - } - break; - - case TYPE_INT64: - u.ll = va_arg(ap, JSInt64); - if (!JSLL_GE_ZERO(u.ll)) { - JSLL_NEG(u.ll, u.ll); - flags |= FLAG_NEG; - } - goto do_longlong; - case TYPE_UINT64: - u.ll = va_arg(ap, JSUint64); - do_longlong: - rv = cvt_ll(ss, u.ll, width, prec, radix, type, flags, hexp); - if (rv < 0) { - return rv; - } - break; - } - break; - - case 'e': - case 'E': - case 'f': - case 'g': - u.d = va_arg(ap, double); - if( nas != NULL ){ - i = fmt - dolPt; - if( i < (int)sizeof( pattern ) ){ - pattern[0] = '%'; - memcpy( &pattern[1], dolPt, (size_t)i ); - rv = cvt_f(ss, u.d, pattern, &pattern[i+1] ); - } - } else - rv = cvt_f(ss, u.d, fmt0, fmt); - - if (rv < 0) { - return rv; - } - break; - - case 'c': - if ((flags & FLAG_LEFT) == 0) { - while (width-- > 1) { - rv = (*ss->stuff)(ss, " ", 1); - if (rv < 0) { - return rv; - } - } - } - switch (type) { - case TYPE_INT16: - /* Treat %hc as %c if JS_C_STRINGS_ARE_UTF8 is undefined. */ -#ifdef JS_C_STRINGS_ARE_UTF8 - u.wch = va_arg(ap, int); - utf8len = js_OneUcs4ToUtf8Char (utf8buf, u.wch); - rv = (*ss->stuff)(ss, utf8buf, utf8len); - break; -#endif - case TYPE_INTN: - u.ch = va_arg(ap, int); - rv = (*ss->stuff)(ss, &u.ch, 1); - break; - } - if (rv < 0) { - return rv; - } - if (flags & FLAG_LEFT) { - while (width-- > 1) { - rv = (*ss->stuff)(ss, " ", 1); - if (rv < 0) { - return rv; - } - } - } - break; - - case 'p': - if (sizeof(void *) == sizeof(JSInt32)) { - type = TYPE_UINT32; - } else if (sizeof(void *) == sizeof(JSInt64)) { - type = TYPE_UINT64; - } else if (sizeof(void *) == sizeof(int)) { - type = TYPE_UINTN; - } else { - JS_ASSERT(0); - break; - } - radix = 16; - goto fetch_and_convert; - -#if 0 - case 'C': - case 'S': - case 'E': - case 'G': - /* XXX not supported I suppose */ - JS_ASSERT(0); - break; -#endif - - case 's': - if(type == TYPE_INT16) { - /* - * This would do a simple string/byte conversion - * if JS_C_STRINGS_ARE_UTF8 is not defined. - */ - u.ws = va_arg(ap, const jschar*); - rv = cvt_ws(ss, u.ws, width, prec, flags); - } else { - u.s = va_arg(ap, const char*); - rv = cvt_s(ss, u.s, width, prec, flags); - } - if (rv < 0) { - return rv; - } - break; - - case 'n': - u.ip = va_arg(ap, int*); - if (u.ip) { - *u.ip = ss->cur - ss->base; - } - break; - - default: - /* Not a % token after all... skip it */ -#if 0 - JS_ASSERT(0); -#endif - rv = (*ss->stuff)(ss, "%", 1); - if (rv < 0) { - return rv; - } - rv = (*ss->stuff)(ss, fmt - 1, 1); - if (rv < 0) { - return rv; - } - } - } - - /* Stuff trailing NUL */ - rv = (*ss->stuff)(ss, "\0", 1); - - if( nas && ( nas != nasArray ) ){ - free( nas ); - } - - return rv; -} - -/************************************************************************/ - -static int FuncStuff(SprintfState *ss, const char *sp, JSUint32 len) -{ - int rv; - - rv = (*ss->func)(ss->arg, sp, len); - if (rv < 0) { - return rv; - } - ss->maxlen += len; - return 0; -} - -JS_PUBLIC_API(JSUint32) JS_sxprintf(JSStuffFunc func, void *arg, - const char *fmt, ...) -{ - va_list ap; - int rv; - - va_start(ap, fmt); - rv = JS_vsxprintf(func, arg, fmt, ap); - va_end(ap); - return rv; -} - -JS_PUBLIC_API(JSUint32) JS_vsxprintf(JSStuffFunc func, void *arg, - const char *fmt, va_list ap) -{ - SprintfState ss; - int rv; - - ss.stuff = FuncStuff; - ss.func = func; - ss.arg = arg; - ss.maxlen = 0; - rv = dosprintf(&ss, fmt, ap); - return (rv < 0) ? (JSUint32)-1 : ss.maxlen; -} - -/* -** Stuff routine that automatically grows the malloc'd output buffer -** before it overflows. -*/ -static int GrowStuff(SprintfState *ss, const char *sp, JSUint32 len) -{ - ptrdiff_t off; - char *newbase; - JSUint32 newlen; - - off = ss->cur - ss->base; - if (off + len >= ss->maxlen) { - /* Grow the buffer */ - newlen = ss->maxlen + ((len > 32) ? len : 32); - if (ss->base) { - newbase = (char*) realloc(ss->base, newlen); - } else { - newbase = (char*) malloc(newlen); - } - if (!newbase) { - /* Ran out of memory */ - return -1; - } - ss->base = newbase; - ss->maxlen = newlen; - ss->cur = ss->base + off; - } - - /* Copy data */ - while (len) { - --len; - *ss->cur++ = *sp++; - } - JS_ASSERT((JSUint32)(ss->cur - ss->base) <= ss->maxlen); - return 0; -} - -/* -** sprintf into a malloc'd buffer -*/ -JS_PUBLIC_API(char *) JS_smprintf(const char *fmt, ...) -{ - va_list ap; - char *rv; - - va_start(ap, fmt); - rv = JS_vsmprintf(fmt, ap); - va_end(ap); - return rv; -} - -/* -** Free memory allocated, for the caller, by JS_smprintf -*/ -JS_PUBLIC_API(void) JS_smprintf_free(char *mem) -{ - free(mem); -} - -JS_PUBLIC_API(char *) JS_vsmprintf(const char *fmt, va_list ap) -{ - SprintfState ss; - int rv; - - ss.stuff = GrowStuff; - ss.base = 0; - ss.cur = 0; - ss.maxlen = 0; - rv = dosprintf(&ss, fmt, ap); - if (rv < 0) { - if (ss.base) { - free(ss.base); - } - return 0; - } - return ss.base; -} - -/* -** Stuff routine that discards overflow data -*/ -static int LimitStuff(SprintfState *ss, const char *sp, JSUint32 len) -{ - JSUint32 limit = ss->maxlen - (ss->cur - ss->base); - - if (len > limit) { - len = limit; - } - while (len) { - --len; - *ss->cur++ = *sp++; - } - return 0; -} - -/* -** sprintf into a fixed size buffer. Make sure there is a NUL at the end -** when finished. -*/ -JS_PUBLIC_API(JSUint32) JS_snprintf(char *out, JSUint32 outlen, const char *fmt, ...) -{ - va_list ap; - int rv; - - JS_ASSERT((JSInt32)outlen > 0); - if ((JSInt32)outlen <= 0) { - return 0; - } - - va_start(ap, fmt); - rv = JS_vsnprintf(out, outlen, fmt, ap); - va_end(ap); - return rv; -} - -JS_PUBLIC_API(JSUint32) JS_vsnprintf(char *out, JSUint32 outlen,const char *fmt, - va_list ap) -{ - SprintfState ss; - JSUint32 n; - - JS_ASSERT((JSInt32)outlen > 0); - if ((JSInt32)outlen <= 0) { - return 0; - } - - ss.stuff = LimitStuff; - ss.base = out; - ss.cur = out; - ss.maxlen = outlen; - (void) dosprintf(&ss, fmt, ap); - - /* If we added chars, and we didn't append a null, do it now. */ - if( (ss.cur != ss.base) && (ss.cur[-1] != '\0') ) - ss.cur[-1] = '\0'; - - n = ss.cur - ss.base; - return n ? n - 1 : n; -} - -JS_PUBLIC_API(char *) JS_sprintf_append(char *last, const char *fmt, ...) -{ - va_list ap; - char *rv; - - va_start(ap, fmt); - rv = JS_vsprintf_append(last, fmt, ap); - va_end(ap); - return rv; -} - -JS_PUBLIC_API(char *) JS_vsprintf_append(char *last, const char *fmt, va_list ap) -{ - SprintfState ss; - int rv; - - ss.stuff = GrowStuff; - if (last) { - int lastlen = strlen(last); - ss.base = last; - ss.cur = last + lastlen; - ss.maxlen = lastlen; - } else { - ss.base = 0; - ss.cur = 0; - ss.maxlen = 0; - } - rv = dosprintf(&ss, fmt, ap); - if (rv < 0) { - if (ss.base) { - free(ss.base); - } - return 0; - } - return ss.base; -} - diff --git a/lib/javascript/jsprf.h b/lib/javascript/jsprf.h deleted file mode 100644 index 0eb910f2..00000000 --- a/lib/javascript/jsprf.h +++ /dev/null @@ -1,150 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jsprf_h___ -#define jsprf_h___ - -/* -** API for PR printf like routines. Supports the following formats -** %d - decimal -** %u - unsigned decimal -** %x - unsigned hex -** %X - unsigned uppercase hex -** %o - unsigned octal -** %hd, %hu, %hx, %hX, %ho - 16-bit versions of above -** %ld, %lu, %lx, %lX, %lo - 32-bit versions of above -** %lld, %llu, %llx, %llX, %llo - 64 bit versions of above -** %s - string -** %hs - 16-bit version of above (only available if compiled with JS_C_STRINGS_ARE_UTF8) -** %c - character -** %hc - 16-bit version of above (only available if compiled with JS_C_STRINGS_ARE_UTF8) -** %p - pointer (deals with machine dependent pointer size) -** %f - float -** %g - float -*/ -#include "jstypes.h" -#include -#include - -JS_BEGIN_EXTERN_C - -/* -** sprintf into a fixed size buffer. Guarantees that a NUL is at the end -** of the buffer. Returns the length of the written output, NOT including -** the NUL, or (JSUint32)-1 if an error occurs. -*/ -extern JS_PUBLIC_API(JSUint32) JS_snprintf(char *out, JSUint32 outlen, const char *fmt, ...); - -/* -** sprintf into a malloc'd buffer. Return a pointer to the malloc'd -** buffer on success, NULL on failure. Call "JS_smprintf_free" to release -** the memory returned. -*/ -extern JS_PUBLIC_API(char*) JS_smprintf(const char *fmt, ...); - -/* -** Free the memory allocated, for the caller, by JS_smprintf -*/ -extern JS_PUBLIC_API(void) JS_smprintf_free(char *mem); - -/* -** "append" sprintf into a malloc'd buffer. "last" is the last value of -** the malloc'd buffer. sprintf will append data to the end of last, -** growing it as necessary using realloc. If last is NULL, JS_sprintf_append -** will allocate the initial string. The return value is the new value of -** last for subsequent calls, or NULL if there is a malloc failure. -*/ -extern JS_PUBLIC_API(char*) JS_sprintf_append(char *last, const char *fmt, ...); - -/* -** sprintf into a function. The function "f" is called with a string to -** place into the output. "arg" is an opaque pointer used by the stuff -** function to hold any state needed to do the storage of the output -** data. The return value is a count of the number of characters fed to -** the stuff function, or (JSUint32)-1 if an error occurs. -*/ -typedef JSIntn (*JSStuffFunc)(void *arg, const char *s, JSUint32 slen); - -extern JS_PUBLIC_API(JSUint32) JS_sxprintf(JSStuffFunc f, void *arg, const char *fmt, ...); - -/* -** va_list forms of the above. -*/ -extern JS_PUBLIC_API(JSUint32) JS_vsnprintf(char *out, JSUint32 outlen, const char *fmt, va_list ap); -extern JS_PUBLIC_API(char*) JS_vsmprintf(const char *fmt, va_list ap); -extern JS_PUBLIC_API(char*) JS_vsprintf_append(char *last, const char *fmt, va_list ap); -extern JS_PUBLIC_API(JSUint32) JS_vsxprintf(JSStuffFunc f, void *arg, const char *fmt, va_list ap); - -/* -*************************************************************************** -** FUNCTION: JS_sscanf -** DESCRIPTION: -** JS_sscanf() scans the input character string, performs data -** conversions, and stores the converted values in the data objects -** pointed to by its arguments according to the format control -** string. -** -** JS_sscanf() behaves the same way as the sscanf() function in the -** Standard C Library (stdio.h), with the following exceptions: -** - JS_sscanf() handles the NSPR integer and floating point types, -** such as JSInt16, JSInt32, JSInt64, and JSFloat64, whereas -** sscanf() handles the standard C types like short, int, long, -** and double. -** - JS_sscanf() has no multibyte character support, while sscanf() -** does. -** INPUTS: -** const char *buf -** a character string holding the input to scan -** const char *fmt -** the format control string for the conversions -** ... -** variable number of arguments, each of them is a pointer to -** a data object in which the converted value will be stored -** OUTPUTS: none -** RETURNS: JSInt32 -** The number of values converted and stored. -** RESTRICTIONS: -** Multibyte characters in 'buf' or 'fmt' are not allowed. -*************************************************************************** -*/ - -extern JS_PUBLIC_API(JSInt32) JS_sscanf(const char *buf, const char *fmt, ...); - -JS_END_EXTERN_C - -#endif /* jsprf_h___ */ diff --git a/lib/javascript/jsprvtd.h b/lib/javascript/jsprvtd.h deleted file mode 100644 index ed12f1bd..00000000 --- a/lib/javascript/jsprvtd.h +++ /dev/null @@ -1,203 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jsprvtd_h___ -#define jsprvtd_h___ -/* - * JS private typename definitions. - * - * This header is included only in other .h files, for convenience and for - * simplicity of type naming. The alternative for structures is to use tags, - * which are named the same as their typedef names (legal in C/C++, and less - * noisy than suffixing the typedef name with "Struct" or "Str"). Instead, - * all .h files that include this file may use the same typedef name, whether - * declaring a pointer to struct type, or defining a member of struct type. - * - * A few fundamental scalar types are defined here too. Neither the scalar - * nor the struct typedefs should change much, therefore the nearly-global - * make dependency induced by this file should not prove painful. - */ - -#include "jspubtd.h" - -/* Internal identifier (jsid) macros. */ -#define JSID_ATOM 0x0 -#define JSID_INT 0x1 -#define JSID_OBJECT 0x2 -#define JSID_TAGMASK 0x3 -#define JSID_TAG(id) ((id) & JSID_TAGMASK) -#define JSID_SETTAG(id,t) ((id) | (t)) -#define JSID_CLRTAG(id) ((id) & ~(jsid)JSID_TAGMASK) - -#define JSID_IS_ATOM(id) (JSID_TAG(id) == JSID_ATOM) -#define JSID_TO_ATOM(id) ((JSAtom *)(id)) -#define ATOM_TO_JSID(atom) ((jsid)(atom)) -#define ATOM_JSID_TO_JSVAL(id) ATOM_KEY(JSID_TO_ATOM(id)) - -#define JSID_IS_INT(id) ((id) & JSID_INT) -#define JSID_TO_INT(id) ((jsint)(id) >> 1) -#define INT_TO_JSID(i) (((jsint)(i) << 1) | JSID_INT) -#define INT_JSID_TO_JSVAL(id) (id) -#define INT_JSVAL_TO_JSID(v) (v) - -#define JSID_IS_OBJECT(id) (JSID_TAG(id) == JSID_OBJECT) -#define JSID_TO_OBJECT(id) ((JSObject *) JSID_CLRTAG(id)) -#define OBJECT_TO_JSID(obj) ((jsid)(obj) | JSID_OBJECT) -#define OBJECT_JSID_TO_JSVAL(id) OBJECT_TO_JSVAL(JSID_CLRTAG(id)) -#define OBJECT_JSVAL_TO_JSID(v) OBJECT_TO_JSID(JSVAL_TO_OBJECT(v)) - -/* Scalar typedefs. */ -typedef uint8 jsbytecode; -typedef uint8 jssrcnote; -typedef uint32 jsatomid; - -/* Struct typedefs. */ -typedef struct JSArgumentFormatMap JSArgumentFormatMap; -typedef struct JSCodeGenerator JSCodeGenerator; -typedef struct JSDependentString JSDependentString; -typedef struct JSGCLockHashEntry JSGCLockHashEntry; -typedef struct JSGCRootHashEntry JSGCRootHashEntry; -typedef struct JSGCThing JSGCThing; -typedef struct JSParseNode JSParseNode; -typedef struct JSSharpObjectMap JSSharpObjectMap; -typedef struct JSToken JSToken; -typedef struct JSTokenPos JSTokenPos; -typedef struct JSTokenPtr JSTokenPtr; -typedef struct JSTokenStream JSTokenStream; -typedef struct JSTreeContext JSTreeContext; -typedef struct JSTryNote JSTryNote; - -/* Friend "Advanced API" typedefs. */ -typedef struct JSAtom JSAtom; -typedef struct JSAtomList JSAtomList; -typedef struct JSAtomListElement JSAtomListElement; -typedef struct JSAtomMap JSAtomMap; -typedef struct JSAtomState JSAtomState; -typedef struct JSCodeSpec JSCodeSpec; -typedef struct JSPrinter JSPrinter; -typedef struct JSRegExp JSRegExp; -typedef struct JSRegExpStatics JSRegExpStatics; -typedef struct JSScope JSScope; -typedef struct JSScopeOps JSScopeOps; -typedef struct JSScopeProperty JSScopeProperty; -typedef struct JSStackFrame JSStackFrame; -typedef struct JSStackHeader JSStackHeader; -typedef struct JSStringBuffer JSStringBuffer; -typedef struct JSSubString JSSubString; -typedef struct JSXML JSXML; -typedef struct JSXMLNamespace JSXMLNamespace; -typedef struct JSXMLQName JSXMLQName; -typedef struct JSXMLArray JSXMLArray; -typedef struct JSXMLArrayCursor JSXMLArrayCursor; - -/* "Friend" types used by jscntxt.h and jsdbgapi.h. */ -typedef enum JSTrapStatus { - JSTRAP_ERROR, - JSTRAP_CONTINUE, - JSTRAP_RETURN, - JSTRAP_THROW, - JSTRAP_LIMIT -} JSTrapStatus; - -typedef JSTrapStatus -(* JS_DLL_CALLBACK JSTrapHandler)(JSContext *cx, JSScript *script, - jsbytecode *pc, jsval *rval, void *closure); - -typedef JSBool -(* JS_DLL_CALLBACK JSWatchPointHandler)(JSContext *cx, JSObject *obj, jsval id, - jsval old, jsval *newp, void *closure); - -/* called just after script creation */ -typedef void -(* JS_DLL_CALLBACK JSNewScriptHook)(JSContext *cx, - const char *filename, /* URL of script */ - uintN lineno, /* first line */ - JSScript *script, - JSFunction *fun, - void *callerdata); - -/* called just before script destruction */ -typedef void -(* JS_DLL_CALLBACK JSDestroyScriptHook)(JSContext *cx, - JSScript *script, - void *callerdata); - -typedef void -(* JS_DLL_CALLBACK JSSourceHandler)(const char *filename, uintN lineno, - jschar *str, size_t length, - void **listenerTSData, void *closure); - -/* - * This hook captures high level script execution and function calls (JS or - * native). It is used by JS_SetExecuteHook to hook top level scripts and by - * JS_SetCallHook to hook function calls. It will get called twice per script - * or function call: just before execution begins and just after it finishes. - * In both cases the 'current' frame is that of the executing code. - * - * The 'before' param is JS_TRUE for the hook invocation before the execution - * and JS_FALSE for the invocation after the code has run. - * - * The 'ok' param is significant only on the post execution invocation to - * signify whether or not the code completed 'normally'. - * - * The 'closure' param is as passed to JS_SetExecuteHook or JS_SetCallHook - * for the 'before'invocation, but is whatever value is returned from that - * invocation for the 'after' invocation. Thus, the hook implementor *could* - * allocate a stucture in the 'before' invocation and return a pointer to that - * structure. The pointer would then be handed to the hook for the 'after' - * invocation. Alternately, the 'before' could just return the same value as - * in 'closure' to cause the 'after' invocation to be called with the same - * 'closure' value as the 'before'. - * - * Returning NULL in the 'before' hook will cause the 'after' hook *not* to - * be called. - */ -typedef void * -(* JS_DLL_CALLBACK JSInterpreterHook)(JSContext *cx, JSStackFrame *fp, JSBool before, - JSBool *ok, void *closure); - -typedef void -(* JS_DLL_CALLBACK JSObjectHook)(JSContext *cx, JSObject *obj, JSBool isNew, - void *closure); - -typedef JSBool -(* JS_DLL_CALLBACK JSDebugErrorHook)(JSContext *cx, const char *message, - JSErrorReport *report, void *closure); - -#endif /* jsprvtd_h___ */ diff --git a/lib/javascript/jspubtd.h b/lib/javascript/jspubtd.h deleted file mode 100644 index e9da9278..00000000 --- a/lib/javascript/jspubtd.h +++ /dev/null @@ -1,618 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jspubtd_h___ -#define jspubtd_h___ -/* - * JS public API typedefs. - */ -#include "jstypes.h" -#include "jscompat.h" - -JS_BEGIN_EXTERN_C - -/* Scalar typedefs. */ -typedef uint16 jschar; -typedef int32 jsint; -typedef uint32 jsuint; -typedef float64 jsdouble; -typedef jsword jsval; -typedef jsword jsid; -typedef int32 jsrefcount; /* PRInt32 if JS_THREADSAFE, see jslock.h */ - -/* - * Run-time version enumeration. See jsconfig.h for compile-time counterparts - * to these values that may be selected by the JS_VERSION macro, and tested by - * #if expressions. - */ -typedef enum JSVersion { - JSVERSION_1_0 = 100, - JSVERSION_1_1 = 110, - JSVERSION_1_2 = 120, - JSVERSION_1_3 = 130, - JSVERSION_1_4 = 140, - JSVERSION_ECMA_3 = 148, - JSVERSION_1_5 = 150, - JSVERSION_1_6 = 160, - JSVERSION_DEFAULT = 0, - JSVERSION_UNKNOWN = -1 -} JSVersion; - -#define JSVERSION_IS_ECMA(version) \ - ((version) == JSVERSION_DEFAULT || (version) >= JSVERSION_1_3) - -/* Result of typeof operator enumeration. */ -typedef enum JSType { - JSTYPE_VOID, /* undefined */ - JSTYPE_OBJECT, /* object */ - JSTYPE_FUNCTION, /* function */ - JSTYPE_STRING, /* string */ - JSTYPE_NUMBER, /* number */ - JSTYPE_BOOLEAN, /* boolean */ - JSTYPE_NULL, /* null */ - JSTYPE_XML, /* xml object */ - JSTYPE_LIMIT -} JSType; - -/* JSObjectOps.checkAccess mode enumeration. */ -typedef enum JSAccessMode { - JSACC_PROTO = 0, /* XXXbe redundant w.r.t. id */ - JSACC_PARENT = 1, /* XXXbe redundant w.r.t. id */ - JSACC_IMPORT = 2, /* import foo.bar */ - JSACC_WATCH = 3, /* a watchpoint on object foo for id 'bar' */ - JSACC_READ = 4, /* a "get" of foo.bar */ - JSACC_WRITE = 8, /* a "set" of foo.bar = baz */ - JSACC_LIMIT -} JSAccessMode; - -#define JSACC_TYPEMASK (JSACC_WRITE - 1) - -/* - * This enum type is used to control the behavior of a JSObject property - * iterator function that has type JSNewEnumerate. - */ -typedef enum JSIterateOp { - JSENUMERATE_INIT, /* Create new iterator state */ - JSENUMERATE_NEXT, /* Iterate once */ - JSENUMERATE_DESTROY /* Destroy iterator state */ -} JSIterateOp; - -/* Struct typedefs. */ -typedef struct JSClass JSClass; -typedef struct JSExtendedClass JSExtendedClass; -typedef struct JSConstDoubleSpec JSConstDoubleSpec; -typedef struct JSContext JSContext; -typedef struct JSErrorReport JSErrorReport; -typedef struct JSFunction JSFunction; -typedef struct JSFunctionSpec JSFunctionSpec; -typedef struct JSIdArray JSIdArray; -typedef struct JSProperty JSProperty; -typedef struct JSPropertySpec JSPropertySpec; -typedef struct JSObject JSObject; -typedef struct JSObjectMap JSObjectMap; -typedef struct JSObjectOps JSObjectOps; -typedef struct JSXMLObjectOps JSXMLObjectOps; -typedef struct JSRuntime JSRuntime; -typedef struct JSRuntime JSTaskState; /* XXX deprecated name */ -typedef struct JSScript JSScript; -typedef struct JSString JSString; -typedef struct JSXDRState JSXDRState; -typedef struct JSExceptionState JSExceptionState; -typedef struct JSLocaleCallbacks JSLocaleCallbacks; - -/* JSClass (and JSObjectOps where appropriate) function pointer typedefs. */ - -/* - * Add, delete, get or set a property named by id in obj. Note the jsval id - * type -- id may be a string (Unicode property identifier) or an int (element - * index). The *vp out parameter, on success, is the new property value after - * an add, get, or set. After a successful delete, *vp is JSVAL_FALSE iff - * obj[id] can't be deleted (because it's permanent). - */ -typedef JSBool -(* JS_DLL_CALLBACK JSPropertyOp)(JSContext *cx, JSObject *obj, jsval id, - jsval *vp); - -/* - * This function type is used for callbacks that enumerate the properties of - * a JSObject. The behavior depends on the value of enum_op: - * - * JSENUMERATE_INIT - * A new, opaque iterator state should be allocated and stored in *statep. - * (You can use PRIVATE_TO_JSVAL() to tag the pointer to be stored). - * - * The number of properties that will be enumerated should be returned as - * an integer jsval in *idp, if idp is non-null, and provided the number of - * enumerable properties is known. If idp is non-null and the number of - * enumerable properties can't be computed in advance, *idp should be set - * to JSVAL_ZERO. - * - * JSENUMERATE_NEXT - * A previously allocated opaque iterator state is passed in via statep. - * Return the next jsid in the iteration using *idp. The opaque iterator - * state pointed at by statep is destroyed and *statep is set to JSVAL_NULL - * if there are no properties left to enumerate. - * - * JSENUMERATE_DESTROY - * Destroy the opaque iterator state previously allocated in *statep by a - * call to this function when enum_op was JSENUMERATE_INIT. - * - * The return value is used to indicate success, with a value of JS_FALSE - * indicating failure. - */ -typedef JSBool -(* JS_DLL_CALLBACK JSNewEnumerateOp)(JSContext *cx, JSObject *obj, - JSIterateOp enum_op, - jsval *statep, jsid *idp); - -/* - * The old-style JSClass.enumerate op should define all lazy properties not - * yet reflected in obj. - */ -typedef JSBool -(* JS_DLL_CALLBACK JSEnumerateOp)(JSContext *cx, JSObject *obj); - -/* - * Resolve a lazy property named by id in obj by defining it directly in obj. - * Lazy properties are those reflected from some peer native property space - * (e.g., the DOM attributes for a given node reflected as obj) on demand. - * - * JS looks for a property in an object, and if not found, tries to resolve - * the given id. If resolve succeeds, the engine looks again in case resolve - * defined obj[id]. If no such property exists directly in obj, the process - * is repeated with obj's prototype, etc. - * - * NB: JSNewResolveOp provides a cheaper way to resolve lazy properties. - */ -typedef JSBool -(* JS_DLL_CALLBACK JSResolveOp)(JSContext *cx, JSObject *obj, jsval id); - -/* - * Like JSResolveOp, but flags provide contextual information as follows: - * - * JSRESOLVE_QUALIFIED a qualified property id: obj.id or obj[id], not id - * JSRESOLVE_ASSIGNING obj[id] is on the left-hand side of an assignment - * JSRESOLVE_DETECTING 'if (o.p)...' or similar detection opcode sequence - * JSRESOLVE_DECLARING var, const, or function prolog declaration opcode - * JSRESOLVE_CLASSNAME class name used when constructing - * - * The *objp out parameter, on success, should be null to indicate that id - * was not resolved; and non-null, referring to obj or one of its prototypes, - * if id was resolved. - * - * This hook instead of JSResolveOp is called via the JSClass.resolve member - * if JSCLASS_NEW_RESOLVE is set in JSClass.flags. - * - * Setting JSCLASS_NEW_RESOLVE and JSCLASS_NEW_RESOLVE_GETS_START further - * extends this hook by passing in the starting object on the prototype chain - * via *objp. Thus a resolve hook implementation may define the property id - * being resolved in the object in which the id was first sought, rather than - * in a prototype object whose class led to the resolve hook being called. - * - * When using JSCLASS_NEW_RESOLVE_GETS_START, the resolve hook must therefore - * null *objp to signify "not resolved". With only JSCLASS_NEW_RESOLVE and no - * JSCLASS_NEW_RESOLVE_GETS_START, the hook can assume *objp is null on entry. - * This is not good practice, but enough existing hook implementations count - * on it that we can't break compatibility by passing the starting object in - * *objp without a new JSClass flag. - */ -typedef JSBool -(* JS_DLL_CALLBACK JSNewResolveOp)(JSContext *cx, JSObject *obj, jsval id, - uintN flags, JSObject **objp); - -/* - * Convert obj to the given type, returning true with the resulting value in - * *vp on success, and returning false on error or exception. - */ -typedef JSBool -(* JS_DLL_CALLBACK JSConvertOp)(JSContext *cx, JSObject *obj, JSType type, - jsval *vp); - -/* - * Finalize obj, which the garbage collector has determined to be unreachable - * from other live objects or from GC roots. Obviously, finalizers must never - * store a reference to obj. - */ -typedef void -(* JS_DLL_CALLBACK JSFinalizeOp)(JSContext *cx, JSObject *obj); - -/* - * Used by JS_AddExternalStringFinalizer and JS_RemoveExternalStringFinalizer - * to extend and reduce the set of string types finalized by the GC. - */ -typedef void -(* JS_DLL_CALLBACK JSStringFinalizeOp)(JSContext *cx, JSString *str); - -/* - * The signature for JSClass.getObjectOps, used by JS_NewObject's internals - * to discover the set of high-level object operations to use for new objects - * of the given class. All native objects have a JSClass, which is stored as - * a private (int-tagged) pointer in obj->slots[JSSLOT_CLASS]. In contrast, - * all native and host objects have a JSObjectMap at obj->map, which may be - * shared among a number of objects, and which contains the JSObjectOps *ops - * pointer used to dispatch object operations from API calls. - * - * Thus JSClass (which pre-dates JSObjectOps in the API) provides a low-level - * interface to class-specific code and data, while JSObjectOps allows for a - * higher level of operation, which does not use the object's class except to - * find the class's JSObjectOps struct, by calling clasp->getObjectOps, and to - * finalize the object. - * - * If this seems backwards, that's because it is! API compatibility requires - * a JSClass *clasp parameter to JS_NewObject, etc. Most host objects do not - * need to implement the larger JSObjectOps, and can share the common JSScope - * code and data used by the native (js_ObjectOps, see jsobj.c) ops. - * - * Further extension to preserve API compatibility: if this function returns - * a pointer to JSXMLObjectOps.base, not to JSObjectOps, then the engine calls - * extended hooks needed for E4X. - */ -typedef JSObjectOps * -(* JS_DLL_CALLBACK JSGetObjectOps)(JSContext *cx, JSClass *clasp); - -/* - * JSClass.checkAccess type: check whether obj[id] may be accessed per mode, - * returning false on error/exception, true on success with obj[id]'s last-got - * value in *vp, and its attributes in *attrsp. As for JSPropertyOp above, id - * is either a string or an int jsval. - * - * See JSCheckAccessIdOp, below, for the JSObjectOps counterpart, which takes - * a jsid (a tagged int or aligned, unique identifier pointer) rather than a - * jsval. The native js_ObjectOps.checkAccess simply forwards to the object's - * clasp->checkAccess, so that both JSClass and JSObjectOps implementors may - * specialize access checks. - */ -typedef JSBool -(* JS_DLL_CALLBACK JSCheckAccessOp)(JSContext *cx, JSObject *obj, jsval id, - JSAccessMode mode, jsval *vp); - -/* - * Encode or decode an object, given an XDR state record representing external - * data. See jsxdrapi.h. - */ -typedef JSBool -(* JS_DLL_CALLBACK JSXDRObjectOp)(JSXDRState *xdr, JSObject **objp); - -/* - * Check whether v is an instance of obj. Return false on error or exception, - * true on success with JS_TRUE in *bp if v is an instance of obj, JS_FALSE in - * *bp otherwise. - */ -typedef JSBool -(* JS_DLL_CALLBACK JSHasInstanceOp)(JSContext *cx, JSObject *obj, jsval v, - JSBool *bp); - -/* - * Function type for JSClass.mark and JSObjectOps.mark, called from the GC to - * scan live GC-things reachable from obj's private data structure. For each - * such thing, a mark implementation must call - * - * JS_MarkGCThing(cx, thing, name, arg); - * - * The trailing name and arg parameters are used for GC_MARK_DEBUG-mode heap - * dumping and ref-path tracing. The mark function should pass a (typically - * literal) string naming the private data member for name, and it must pass - * the opaque arg parameter through from its caller. - * - * For the JSObjectOps.mark hook, the return value is the number of slots at - * obj->slots to scan. For JSClass.mark, the return value is ignored. - * - * NB: JSMarkOp implementations cannot allocate new GC-things (JS_NewObject - * called from a mark function will fail silently, e.g.). - */ -typedef uint32 -(* JS_DLL_CALLBACK JSMarkOp)(JSContext *cx, JSObject *obj, void *arg); - -/* - * The optional JSClass.reserveSlots hook allows a class to make computed - * per-instance object slots reservations, in addition to or instead of using - * JSCLASS_HAS_RESERVED_SLOTS(n) in the JSClass.flags initializer to reserve - * a constant-per-class number of slots. Implementations of this hook should - * return the number of slots to reserve, not including any reserved by using - * JSCLASS_HAS_RESERVED_SLOTS(n) in JSClass.flags. - * - * NB: called with obj locked by the JSObjectOps-specific mutual exclusion - * mechanism appropriate for obj, so don't nest other operations that might - * also lock obj. - */ -typedef uint32 -(* JS_DLL_CALLBACK JSReserveSlotsOp)(JSContext *cx, JSObject *obj); - -/* JSObjectOps function pointer typedefs. */ - -/* - * Create a new subclass of JSObjectMap (see jsobj.h), with the nrefs and ops - * members initialized from the same-named parameters, and with the nslots and - * freeslot members initialized according to ops and clasp. Return null on - * error, non-null on success. - * - * JSObjectMaps are reference-counted by generic code in the engine. Usually, - * the nrefs parameter to JSObjectOps.newObjectMap will be 1, to count the ref - * returned to the caller on success. After a successful construction, some - * number of js_HoldObjectMap and js_DropObjectMap calls ensue. When nrefs - * reaches 0 due to a js_DropObjectMap call, JSObjectOps.destroyObjectMap will - * be called to dispose of the map. - */ -typedef JSObjectMap * -(* JS_DLL_CALLBACK JSNewObjectMapOp)(JSContext *cx, jsrefcount nrefs, - JSObjectOps *ops, JSClass *clasp, - JSObject *obj); - -/* - * Generic type for an infallible JSObjectMap operation, used currently by - * JSObjectOps.destroyObjectMap. - */ -typedef void -(* JS_DLL_CALLBACK JSObjectMapOp)(JSContext *cx, JSObjectMap *map); - -/* - * Look for id in obj and its prototype chain, returning false on error or - * exception, true on success. On success, return null in *propp if id was - * not found. If id was found, return the first object searching from obj - * along its prototype chain in which id names a direct property in *objp, and - * return a non-null, opaque property pointer in *propp. - * - * If JSLookupPropOp succeeds and returns with *propp non-null, that pointer - * may be passed as the prop parameter to a JSAttributesOp, as a short-cut - * that bypasses id re-lookup. In any case, a non-null *propp result after a - * successful lookup must be dropped via JSObjectOps.dropProperty. - * - * NB: successful return with non-null *propp means the implementation may - * have locked *objp and added a reference count associated with *propp, so - * callers should not risk deadlock by nesting or interleaving other lookups - * or any obj-bearing ops before dropping *propp. - */ -typedef JSBool -(* JS_DLL_CALLBACK JSLookupPropOp)(JSContext *cx, JSObject *obj, jsid id, - JSObject **objp, JSProperty **propp); - -/* - * Define obj[id], a direct property of obj named id, having the given initial - * value, with the specified getter, setter, and attributes. If the propp out - * param is non-null, *propp on successful return contains an opaque property - * pointer usable as a speedup hint with JSAttributesOp. But note that propp - * may be null, indicating that the caller is not interested in recovering an - * opaque pointer to the newly-defined property. - * - * If propp is non-null and JSDefinePropOp succeeds, its caller must be sure - * to drop *propp using JSObjectOps.dropProperty in short order, just as with - * JSLookupPropOp. - */ -typedef JSBool -(* JS_DLL_CALLBACK JSDefinePropOp)(JSContext *cx, JSObject *obj, - jsid id, jsval value, - JSPropertyOp getter, JSPropertyOp setter, - uintN attrs, JSProperty **propp); - -/* - * Get, set, or delete obj[id], returning false on error or exception, true - * on success. If getting or setting, the new value is returned in *vp on - * success. If deleting without error, *vp will be JSVAL_FALSE if obj[id] is - * permanent, and JSVAL_TRUE if id named a direct property of obj that was in - * fact deleted, or if id names no direct property of obj (id could name a - * prototype property, or no property in obj or its prototype chain). - */ -typedef JSBool -(* JS_DLL_CALLBACK JSPropertyIdOp)(JSContext *cx, JSObject *obj, jsid id, - jsval *vp); - -/* - * Get or set attributes of the property obj[id]. Return false on error or - * exception, true with current attributes in *attrsp. If prop is non-null, - * it must come from the *propp out parameter of a prior JSDefinePropOp or - * JSLookupPropOp call. - */ -typedef JSBool -(* JS_DLL_CALLBACK JSAttributesOp)(JSContext *cx, JSObject *obj, jsid id, - JSProperty *prop, uintN *attrsp); - -/* - * JSObjectOps.checkAccess type: check whether obj[id] may be accessed per - * mode, returning false on error/exception, true on success with obj[id]'s - * last-got value in *vp, and its attributes in *attrsp. - */ -typedef JSBool -(* JS_DLL_CALLBACK JSCheckAccessIdOp)(JSContext *cx, JSObject *obj, jsid id, - JSAccessMode mode, jsval *vp, - uintN *attrsp); - -/* - * A generic type for functions mapping an object to another object, or null - * if an error or exception was thrown on cx. Used by JSObjectOps.thisObject - * at present. - */ -typedef JSObject * -(* JS_DLL_CALLBACK JSObjectOp)(JSContext *cx, JSObject *obj); - -/* - * A generic type for functions taking a context, object, and property, with - * no return value. Used by JSObjectOps.dropProperty currently (see above, - * JSDefinePropOp and JSLookupPropOp, for the object-locking protocol in which - * dropProperty participates). - */ -typedef void -(* JS_DLL_CALLBACK JSPropertyRefOp)(JSContext *cx, JSObject *obj, - JSProperty *prop); - -/* - * Function type for JSObjectOps.setProto and JSObjectOps.setParent. These - * hooks must check for cycles without deadlocking, and otherwise take special - * steps. See jsobj.c, js_SetProtoOrParent, for an example. - */ -typedef JSBool -(* JS_DLL_CALLBACK JSSetObjectSlotOp)(JSContext *cx, JSObject *obj, - uint32 slot, JSObject *pobj); - -/* - * Get and set a required slot, one that should already have been allocated. - * These operations are infallible, so required slots must be pre-allocated, - * or implementations must suppress out-of-memory errors. The native ops - * (js_ObjectOps, see jsobj.c) access slots reserved by including a call to - * the JSCLASS_HAS_RESERVED_SLOTS(n) macro in the JSClass.flags initializer. - * - * NB: the slot parameter is a zero-based index into obj->slots[], unlike the - * index parameter to the JS_GetReservedSlot and JS_SetReservedSlot API entry - * points, which is a zero-based index into the JSCLASS_RESERVED_SLOTS(clasp) - * reserved slots that come after the initial well-known slots: proto, parent, - * class, and optionally, the private data slot. - */ -typedef jsval -(* JS_DLL_CALLBACK JSGetRequiredSlotOp)(JSContext *cx, JSObject *obj, - uint32 slot); - -typedef JSBool -(* JS_DLL_CALLBACK JSSetRequiredSlotOp)(JSContext *cx, JSObject *obj, - uint32 slot, jsval v); - -typedef JSObject * -(* JS_DLL_CALLBACK JSGetMethodOp)(JSContext *cx, JSObject *obj, jsid id, - jsval *vp); - -typedef JSBool -(* JS_DLL_CALLBACK JSSetMethodOp)(JSContext *cx, JSObject *obj, jsid id, - jsval *vp); - -typedef JSBool -(* JS_DLL_CALLBACK JSEnumerateValuesOp)(JSContext *cx, JSObject *obj, - JSIterateOp enum_op, - jsval *statep, jsid *idp, jsval *vp); - -typedef JSBool -(* JS_DLL_CALLBACK JSEqualityOp)(JSContext *cx, JSObject *obj, jsval v, - JSBool *bp); - -typedef JSBool -(* JS_DLL_CALLBACK JSConcatenateOp)(JSContext *cx, JSObject *obj, jsval v, - jsval *vp); - -/* Typedef for native functions called by the JS VM. */ - -typedef JSBool -(* JS_DLL_CALLBACK JSNative)(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval); - -/* Callbacks and their arguments. */ - -typedef enum JSGCStatus { - JSGC_BEGIN, - JSGC_END, - JSGC_MARK_END, - JSGC_FINALIZE_END -} JSGCStatus; - -typedef JSBool -(* JS_DLL_CALLBACK JSGCCallback)(JSContext *cx, JSGCStatus status); - -typedef JSBool -(* JS_DLL_CALLBACK JSBranchCallback)(JSContext *cx, JSScript *script); - -typedef void -(* JS_DLL_CALLBACK JSErrorReporter)(JSContext *cx, const char *message, - JSErrorReport *report); - -typedef struct JSErrorFormatString { - /* The error format string (UTF-8 if JS_C_STRINGS_ARE_UTF8 is defined). */ - const char *format; - - /* The number of arguments to expand in the formatted error message. */ - uint16 argCount; - - /* One of the JSExnType constants above. */ - int16 exnType; -} JSErrorFormatString; - -typedef const JSErrorFormatString * -(* JS_DLL_CALLBACK JSErrorCallback)(void *userRef, const char *locale, - const uintN errorNumber); - -#ifdef va_start -#define JS_ARGUMENT_FORMATTER_DEFINED 1 - -typedef JSBool -(* JS_DLL_CALLBACK JSArgumentFormatter)(JSContext *cx, const char *format, - JSBool fromJS, jsval **vpp, - va_list *app); -#endif - -typedef JSBool -(* JS_DLL_CALLBACK JSLocaleToUpperCase)(JSContext *cx, JSString *src, - jsval *rval); - -typedef JSBool -(* JS_DLL_CALLBACK JSLocaleToLowerCase)(JSContext *cx, JSString *src, - jsval *rval); - -typedef JSBool -(* JS_DLL_CALLBACK JSLocaleCompare)(JSContext *cx, - JSString *src1, JSString *src2, - jsval *rval); - -typedef JSBool -(* JS_DLL_CALLBACK JSLocaleToUnicode)(JSContext *cx, char *src, jsval *rval); - -/* - * Security protocol types. - */ -typedef struct JSPrincipals JSPrincipals; - -/* - * XDR-encode or -decode a principals instance, based on whether xdr->mode is - * JSXDR_ENCODE, in which case *principalsp should be encoded; or JSXDR_DECODE, - * in which case implementations must return a held (via JSPRINCIPALS_HOLD), - * non-null *principalsp out parameter. Return true on success, false on any - * error, which the implementation must have reported. - */ -typedef JSBool -(* JS_DLL_CALLBACK JSPrincipalsTranscoder)(JSXDRState *xdr, - JSPrincipals **principalsp); - -/* - * Return a weak reference to the principals associated with obj, possibly via - * the immutable parent chain leading from obj to a top-level container (e.g., - * a window object in the DOM level 0). If there are no principals associated - * with obj, return null. Therefore null does not mean an error was reported; - * in no event should an error be reported or an exception be thrown by this - * callback's implementation. - */ -typedef JSPrincipals * -(* JS_DLL_CALLBACK JSObjectPrincipalsFinder)(JSContext *cx, JSObject *obj); - -JS_END_EXTERN_C - -#endif /* jspubtd_h___ */ diff --git a/lib/javascript/jsregexp.c b/lib/javascript/jsregexp.c deleted file mode 100644 index e9400eb0..00000000 --- a/lib/javascript/jsregexp.c +++ /dev/null @@ -1,4180 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set sw=4 ts=8 et tw=80: - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JS regular expressions, after Perl. - */ -#include "jsstddef.h" -#include -#include -#include "jstypes.h" -#include "jsarena.h" /* Added by JSIFY */ -#include "jsutil.h" /* Added by JSIFY */ -#include "jsapi.h" -#include "jsarray.h" -#include "jsatom.h" -#include "jscntxt.h" -#include "jsconfig.h" -#include "jsfun.h" -#include "jsgc.h" -#include "jsinterp.h" -#include "jslock.h" -#include "jsnum.h" -#include "jsobj.h" -#include "jsopcode.h" -#include "jsregexp.h" -#include "jsscan.h" -#include "jsstr.h" - -#if JS_HAS_REGEXPS - -/* Note : contiguity of 'simple opcodes' is important for SimpleMatch() */ -typedef enum REOp { - REOP_EMPTY = 0, /* match rest of input against rest of r.e. */ - REOP_ALT = 1, /* alternative subexpressions in kid and next */ - REOP_SIMPLE_START = 2, /* start of 'simple opcodes' */ - REOP_BOL = 2, /* beginning of input (or line if multiline) */ - REOP_EOL = 3, /* end of input (or line if multiline) */ - REOP_WBDRY = 4, /* match "" at word boundary */ - REOP_WNONBDRY = 5, /* match "" at word non-boundary */ - REOP_DOT = 6, /* stands for any character */ - REOP_DIGIT = 7, /* match a digit char: [0-9] */ - REOP_NONDIGIT = 8, /* match a non-digit char: [^0-9] */ - REOP_ALNUM = 9, /* match an alphanumeric char: [0-9a-z_A-Z] */ - REOP_NONALNUM = 10, /* match a non-alphanumeric char: [^0-9a-z_A-Z] */ - REOP_SPACE = 11, /* match a whitespace char */ - REOP_NONSPACE = 12, /* match a non-whitespace char */ - REOP_BACKREF = 13, /* back-reference (e.g., \1) to a parenthetical */ - REOP_FLAT = 14, /* match a flat string */ - REOP_FLAT1 = 15, /* match a single char */ - REOP_FLATi = 16, /* case-independent REOP_FLAT */ - REOP_FLAT1i = 17, /* case-independent REOP_FLAT1 */ - REOP_UCFLAT1 = 18, /* single Unicode char */ - REOP_UCFLAT1i = 19, /* case-independent REOP_UCFLAT1 */ - REOP_UCFLAT = 20, /* flat Unicode string; len immediate counts chars */ - REOP_UCFLATi = 21, /* case-independent REOP_UCFLAT */ - REOP_CLASS = 22, /* character class with index */ - REOP_NCLASS = 23, /* negated character class with index */ - REOP_SIMPLE_END = 23, /* end of 'simple opcodes' */ - REOP_QUANT = 25, /* quantified atom: atom{1,2} */ - REOP_STAR = 26, /* zero or more occurrences of kid */ - REOP_PLUS = 27, /* one or more occurrences of kid */ - REOP_OPT = 28, /* optional subexpression in kid */ - REOP_LPAREN = 29, /* left paren bytecode: kid is u.num'th sub-regexp */ - REOP_RPAREN = 30, /* right paren bytecode */ - REOP_JUMP = 31, /* for deoptimized closure loops */ - REOP_DOTSTAR = 32, /* optimize .* to use a single opcode */ - REOP_ANCHOR = 33, /* like .* but skips left context to unanchored r.e. */ - REOP_EOLONLY = 34, /* $ not preceded by any pattern */ - REOP_BACKREFi = 37, /* case-independent REOP_BACKREF */ - REOP_LPARENNON = 41, /* non-capturing version of REOP_LPAREN */ - REOP_ASSERT = 43, /* zero width positive lookahead assertion */ - REOP_ASSERT_NOT = 44, /* zero width negative lookahead assertion */ - REOP_ASSERTTEST = 45, /* sentinel at end of assertion child */ - REOP_ASSERTNOTTEST = 46, /* sentinel at end of !assertion child */ - REOP_MINIMALSTAR = 47, /* non-greedy version of * */ - REOP_MINIMALPLUS = 48, /* non-greedy version of + */ - REOP_MINIMALOPT = 49, /* non-greedy version of ? */ - REOP_MINIMALQUANT = 50, /* non-greedy version of {} */ - REOP_ENDCHILD = 51, /* sentinel at end of quantifier child */ - REOP_REPEAT = 52, /* directs execution of greedy quantifier */ - REOP_MINIMALREPEAT = 53, /* directs execution of non-greedy quantifier */ - REOP_ALTPREREQ = 54, /* prerequisite for ALT, either of two chars */ - REOP_ALTPREREQ2 = 55, /* prerequisite for ALT, a char or a class */ - REOP_ENDALT = 56, /* end of final alternate */ - REOP_CONCAT = 57, /* concatenation of terms (parse time only) */ - - REOP_END -} REOp; - -#define REOP_IS_SIMPLE(op) ((unsigned)((op) - REOP_SIMPLE_START) < \ - (unsigned)REOP_SIMPLE_END) - -struct RENode { - REOp op; /* r.e. op bytecode */ - RENode *next; /* next in concatenation order */ - void *kid; /* first operand */ - union { - void *kid2; /* second operand */ - jsint num; /* could be a number */ - size_t parenIndex; /* or a parenthesis index */ - struct { /* or a quantifier range */ - uintN min; - uintN max; - JSPackedBool greedy; - } range; - struct { /* or a character class */ - size_t startIndex; - size_t kidlen; /* length of string at kid, in jschars */ - size_t index; /* index into class list */ - uint16 bmsize; /* bitmap size, based on max char code */ - JSPackedBool sense; - } ucclass; - struct { /* or a literal sequence */ - jschar chr; /* of one character */ - size_t length; /* or many (via the kid) */ - } flat; - struct { - RENode *kid2; /* second operand from ALT */ - jschar ch1; /* match char for ALTPREREQ */ - jschar ch2; /* ditto, or class index for ALTPREREQ2 */ - } altprereq; - } u; -}; - -#define RE_IS_LETTER(c) (((c >= 'A') && (c <= 'Z')) || \ - ((c >= 'a') && (c <= 'z')) ) -#define RE_IS_LINE_TERM(c) ((c == '\n') || (c == '\r') || \ - (c == LINE_SEPARATOR) || (c == PARA_SEPARATOR)) - -#define CLASS_CACHE_SIZE 4 - -typedef struct CompilerState { - JSContext *context; - JSTokenStream *tokenStream; /* For reporting errors */ - const jschar *cpbegin; - const jschar *cpend; - const jschar *cp; - size_t parenCount; - size_t classCount; /* number of [] encountered */ - size_t treeDepth; /* maximum depth of parse tree */ - size_t progLength; /* estimated bytecode length */ - RENode *result; - size_t classBitmapsMem; /* memory to hold all class bitmaps */ - struct { - const jschar *start; /* small cache of class strings */ - size_t length; /* since they're often the same */ - size_t index; - } classCache[CLASS_CACHE_SIZE]; - uint16 flags; -} CompilerState; - -typedef struct EmitStateStackEntry { - jsbytecode *altHead; /* start of REOP_ALT* opcode */ - jsbytecode *nextAltFixup; /* fixup pointer to next-alt offset */ - jsbytecode *nextTermFixup; /* fixup ptr. to REOP_JUMP offset */ - jsbytecode *endTermFixup; /* fixup ptr. to REOPT_ALTPREREQ* offset */ - RENode *continueNode; /* original REOP_ALT* node being stacked */ - jsbytecode continueOp; /* REOP_JUMP or REOP_ENDALT continuation */ - JSPackedBool jumpToJumpFlag; /* true if we've patched jump-to-jump to - avoid 16-bit unsigned offset overflow */ -} EmitStateStackEntry; - -/* - * Immediate operand sizes and getter/setters. Unlike the ones in jsopcode.h, - * the getters and setters take the pc of the offset, not of the opcode before - * the offset. - */ -#define ARG_LEN 2 -#define GET_ARG(pc) ((uint16)(((pc)[0] << 8) | (pc)[1])) -#define SET_ARG(pc, arg) ((pc)[0] = (jsbytecode) ((arg) >> 8), \ - (pc)[1] = (jsbytecode) (arg)) - -#define OFFSET_LEN ARG_LEN -#define OFFSET_MAX (JS_BIT(ARG_LEN * 8) - 1) -#define GET_OFFSET(pc) GET_ARG(pc) - -/* - * Maximum supported tree depth is maximum size of EmitStateStackEntry stack. - * For sanity, we limit it to 2^24 bytes. - */ -#define TREE_DEPTH_MAX (JS_BIT(24) / sizeof(EmitStateStackEntry)) - -/* - * The maximum memory that can be allocated for class bitmaps. - * For sanity, we limit it to 2^24 bytes. - */ -#define CLASS_BITMAPS_MEM_LIMIT JS_BIT(24) - -/* - * Functions to get size and write/read bytecode that represent small indexes - * compactly. - * Each byte in the code represent 7-bit chunk of the index. 8th bit when set - * indicates that the following byte brings more bits to the index. Otherwise - * this is the last byte in the index bytecode representing highest index bits. - */ -static size_t -GetCompactIndexWidth(size_t index) -{ - size_t width; - - for (width = 1; (index >>= 7) != 0; ++width) { } - return width; -} - -static jsbytecode * -WriteCompactIndex(jsbytecode *pc, size_t index) -{ - size_t next; - - while ((next = index >> 7) != 0) { - *pc++ = (jsbytecode)(index | 0x80); - index = next; - } - *pc++ = (jsbytecode)index; - return pc; -} - -static jsbytecode * -ReadCompactIndex(jsbytecode *pc, size_t *result) -{ - size_t nextByte; - - nextByte = *pc++; - if ((nextByte & 0x80) == 0) { - /* - * Short-circuit the most common case when compact index <= 127. - */ - *result = nextByte; - } else { - size_t shift = 7; - *result = 0x7F & nextByte; - do { - nextByte = *pc++; - *result |= (nextByte & 0x7F) << shift; - shift += 7; - } while ((nextByte & 0x80) != 0); - } - return pc; -} - -typedef struct RECapture { - ptrdiff_t index; /* start of contents, -1 for empty */ - size_t length; /* length of capture */ -} RECapture; - -typedef struct REMatchState { - const jschar *cp; - RECapture parens[1]; /* first of 're->parenCount' captures, - allocated at end of this struct */ -} REMatchState; - -struct REBackTrackData; - -typedef struct REProgState { - jsbytecode *continue_pc; /* current continuation data */ - jsbytecode continue_op; - ptrdiff_t index; /* progress in text */ - size_t parenSoFar; /* highest indexed paren started */ - union { - struct { - uintN min; /* current quantifier limits */ - uintN max; - } quantifier; - struct { - size_t top; /* backtrack stack state */ - size_t sz; - } assertion; - } u; -} REProgState; - -typedef struct REBackTrackData { - size_t sz; /* size of previous stack entry */ - jsbytecode *backtrack_pc; /* where to backtrack to */ - jsbytecode backtrack_op; - const jschar *cp; /* index in text of match at backtrack */ - size_t parenIndex; /* start index of saved paren contents */ - size_t parenCount; /* # of saved paren contents */ - size_t saveStateStackTop; /* number of parent states */ - /* saved parent states follow */ - /* saved paren contents follow */ -} REBackTrackData; - -#define INITIAL_STATESTACK 100 -#define INITIAL_BACKTRACK 8000 - -typedef struct REGlobalData { - JSContext *cx; - JSRegExp *regexp; /* the RE in execution */ - JSBool ok; /* runtime error (out_of_memory only?) */ - size_t start; /* offset to start at */ - ptrdiff_t skipped; /* chars skipped anchoring this r.e. */ - const jschar *cpbegin; /* text base address */ - const jschar *cpend; /* text limit address */ - - REProgState *stateStack; /* stack of state of current parents */ - size_t stateStackTop; - size_t stateStackLimit; - - REBackTrackData *backTrackStack;/* stack of matched-so-far positions */ - REBackTrackData *backTrackSP; - size_t backTrackStackSize; - size_t cursz; /* size of current stack entry */ - - JSArenaPool pool; /* It's faster to use one malloc'd pool - than to malloc/free the three items - that are allocated from this pool */ -} REGlobalData; - -/* - * 1. If IgnoreCase is false, return ch. - * 2. Let u be ch converted to upper case as if by calling - * String.prototype.toUpperCase on the one-character string ch. - * 3. If u does not consist of a single character, return ch. - * 4. Let cu be u's character. - * 5. If ch's code point value is greater than or equal to decimal 128 and cu's - * code point value is less than decimal 128, then return ch. - * 6. Return cu. - */ -static jschar -upcase(jschar ch) -{ - jschar cu = JS_TOUPPER(ch); - if (ch >= 128 && cu < 128) - return ch; - return cu; -} - -static jschar -downcase(jschar ch) -{ - jschar cl = JS_TOLOWER(ch); - if (cl >= 128 && ch < 128) - return ch; - return cl; -} - -/* Construct and initialize an RENode, returning NULL for out-of-memory */ -static RENode * -NewRENode(CompilerState *state, REOp op) -{ - JSContext *cx; - RENode *ren; - - cx = state->context; - JS_ARENA_ALLOCATE_CAST(ren, RENode *, &cx->tempPool, sizeof *ren); - if (!ren) { - JS_ReportOutOfMemory(cx); - return NULL; - } - ren->op = op; - ren->next = NULL; - ren->kid = NULL; - return ren; -} - -/* - * Validates and converts hex ascii value. - */ -static JSBool -isASCIIHexDigit(jschar c, uintN *digit) -{ - uintN cv = c; - - if (cv < '0') - return JS_FALSE; - if (cv <= '9') { - *digit = cv - '0'; - return JS_TRUE; - } - cv |= 0x20; - if (cv >= 'a' && cv <= 'f') { - *digit = cv - 'a' + 10; - return JS_TRUE; - } - return JS_FALSE; -} - - -typedef struct { - REOp op; - const jschar *errPos; - size_t parenIndex; -} REOpData; - - -/* - * Process the op against the two top operands, reducing them to a single - * operand in the penultimate slot. Update progLength and treeDepth. - */ -static JSBool -ProcessOp(CompilerState *state, REOpData *opData, RENode **operandStack, - intN operandSP) -{ - RENode *result; - - switch (opData->op) { - case REOP_ALT: - result = NewRENode(state, REOP_ALT); - if (!result) - return JS_FALSE; - result->kid = operandStack[operandSP - 2]; - result->u.kid2 = operandStack[operandSP - 1]; - operandStack[operandSP - 2] = result; - - if (state->treeDepth == TREE_DEPTH_MAX) { - js_ReportCompileErrorNumber(state->context, state->tokenStream, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_REGEXP_TOO_COMPLEX); - return JS_FALSE; - } - ++state->treeDepth; - - /* - * Look at both alternates to see if there's a FLAT or a CLASS at - * the start of each. If so, use a prerequisite match. - */ - if (((RENode *) result->kid)->op == REOP_FLAT && - ((RENode *) result->u.kid2)->op == REOP_FLAT && - (state->flags & JSREG_FOLD) == 0) { - result->op = REOP_ALTPREREQ; - result->u.altprereq.ch1 = ((RENode *) result->kid)->u.flat.chr; - result->u.altprereq.ch2 = ((RENode *) result->u.kid2)->u.flat.chr; - /* ALTPREREQ, , uch1, uch2, , ..., - JUMP, ... ENDALT */ - state->progLength += 13; - } - else - if (((RENode *) result->kid)->op == REOP_CLASS && - ((RENode *) result->kid)->u.ucclass.index < 256 && - ((RENode *) result->u.kid2)->op == REOP_FLAT && - (state->flags & JSREG_FOLD) == 0) { - result->op = REOP_ALTPREREQ2; - result->u.altprereq.ch1 = ((RENode *) result->u.kid2)->u.flat.chr; - result->u.altprereq.ch2 = ((RENode *) result->kid)->u.ucclass.index; - /* ALTPREREQ2, , uch1, uch2, , ..., - JUMP, ... ENDALT */ - state->progLength += 13; - } - else - if (((RENode *) result->kid)->op == REOP_FLAT && - ((RENode *) result->u.kid2)->op == REOP_CLASS && - ((RENode *) result->u.kid2)->u.ucclass.index < 256 && - (state->flags & JSREG_FOLD) == 0) { - result->op = REOP_ALTPREREQ2; - result->u.altprereq.ch1 = ((RENode *) result->kid)->u.flat.chr; - result->u.altprereq.ch2 = - ((RENode *) result->u.kid2)->u.ucclass.index; - /* ALTPREREQ2, , uch1, uch2, , ..., - JUMP, ... ENDALT */ - state->progLength += 13; - } - else { - /* ALT, , ..., JUMP, ... ENDALT */ - state->progLength += 7; - } - break; - - case REOP_CONCAT: - result = operandStack[operandSP - 2]; - while (result->next) - result = result->next; - result->next = operandStack[operandSP - 1]; - break; - - case REOP_ASSERT: - case REOP_ASSERT_NOT: - case REOP_LPARENNON: - case REOP_LPAREN: - /* These should have been processed by a close paren. */ - js_ReportCompileErrorNumberUC(state->context, state->tokenStream, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_MISSING_PAREN, opData->errPos); - return JS_FALSE; - - default:; - } - return JS_TRUE; -} - -/* - * Parser forward declarations. - */ -static JSBool ParseTerm(CompilerState *state); -static JSBool ParseQuantifier(CompilerState *state); -static intN ParseMinMaxQuantifier(CompilerState *state, JSBool ignoreValues); - -/* - * Top-down regular expression grammar, based closely on Perl4. - * - * regexp: altern A regular expression is one or more - * altern '|' regexp alternatives separated by vertical bar. - */ -#define INITIAL_STACK_SIZE 128 - -static JSBool -ParseRegExp(CompilerState *state) -{ - size_t parenIndex; - RENode *operand; - REOpData *operatorStack; - RENode **operandStack; - REOp op; - intN i; - JSBool result = JS_FALSE; - - intN operatorSP = 0, operatorStackSize = INITIAL_STACK_SIZE; - intN operandSP = 0, operandStackSize = INITIAL_STACK_SIZE; - - /* Watch out for empty regexp */ - if (state->cp == state->cpend) { - state->result = NewRENode(state, REOP_EMPTY); - return (state->result != NULL); - } - - operatorStack = (REOpData *) - JS_malloc(state->context, sizeof(REOpData) * operatorStackSize); - if (!operatorStack) - return JS_FALSE; - - operandStack = (RENode **) - JS_malloc(state->context, sizeof(RENode *) * operandStackSize); - if (!operandStack) - goto out; - - for (;;) { - parenIndex = state->parenCount; - if (state->cp == state->cpend) { - /* - * If we are at the end of the regexp and we're short one or more - * operands, the regexp must have the form /x|/ or some such, with - * left parentheses making us short more than one operand. - */ - if (operatorSP >= operandSP) { - operand = NewRENode(state, REOP_EMPTY); - if (!operand) - goto out; - goto pushOperand; - } - } else { - switch (*state->cp) { - case '(': - ++state->cp; - if (state->cp + 1 < state->cpend && - *state->cp == '?' && - (state->cp[1] == '=' || - state->cp[1] == '!' || - state->cp[1] == ':')) { - switch (state->cp[1]) { - case '=': - op = REOP_ASSERT; - /* ASSERT, , ... ASSERTTEST */ - state->progLength += 4; - break; - case '!': - op = REOP_ASSERT_NOT; - /* ASSERTNOT, , ... ASSERTNOTTEST */ - state->progLength += 4; - break; - default: - op = REOP_LPARENNON; - break; - } - state->cp += 2; - } else { - op = REOP_LPAREN; - /* LPAREN, , ... RPAREN, */ - state->progLength - += 2 * (1 + GetCompactIndexWidth(parenIndex)); - state->parenCount++; - if (state->parenCount == 65535) { - js_ReportCompileErrorNumber(state->context, - state->tokenStream, - JSREPORT_TS | - JSREPORT_ERROR, - JSMSG_TOO_MANY_PARENS); - goto out; - } - } - goto pushOperator; - - case ')': - /* - * If there's no stacked open parenthesis, throw syntax error. - */ - for (i = operatorSP - 1; ; i--) { - if (i < 0) { - js_ReportCompileErrorNumber(state->context, - state->tokenStream, - JSREPORT_TS | - JSREPORT_ERROR, - JSMSG_UNMATCHED_RIGHT_PAREN); - goto out; - } - if (operatorStack[i].op == REOP_ASSERT || - operatorStack[i].op == REOP_ASSERT_NOT || - operatorStack[i].op == REOP_LPARENNON || - operatorStack[i].op == REOP_LPAREN) { - break; - } - } - /* FALL THROUGH */ - - case '|': - /* Expected an operand before these, so make an empty one */ - operand = NewRENode(state, REOP_EMPTY); - if (!operand) - goto out; - goto pushOperand; - - default: - if (!ParseTerm(state)) - goto out; - operand = state->result; -pushOperand: - if (operandSP == operandStackSize) { - operandStackSize += operandStackSize; - operandStack = (RENode **) - JS_realloc(state->context, operandStack, - sizeof(RENode *) * operandStackSize); - if (!operandStack) - goto out; - } - operandStack[operandSP++] = operand; - break; - } - } - - /* At the end; process remaining operators. */ -restartOperator: - if (state->cp == state->cpend) { - while (operatorSP) { - --operatorSP; - if (!ProcessOp(state, &operatorStack[operatorSP], - operandStack, operandSP)) - goto out; - --operandSP; - } - JS_ASSERT(operandSP == 1); - state->result = operandStack[0]; - result = JS_TRUE; - goto out; - } - - switch (*state->cp) { - case '|': - /* Process any stacked 'concat' operators */ - ++state->cp; - while (operatorSP && - operatorStack[operatorSP - 1].op == REOP_CONCAT) { - --operatorSP; - if (!ProcessOp(state, &operatorStack[operatorSP], - operandStack, operandSP)) { - goto out; - } - --operandSP; - } - op = REOP_ALT; - goto pushOperator; - - case ')': - /* - * If there's no stacked open parenthesis, throw syntax error. - */ - for (i = operatorSP - 1; ; i--) { - if (i < 0) { - js_ReportCompileErrorNumber(state->context, - state->tokenStream, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_UNMATCHED_RIGHT_PAREN); - goto out; - } - if (operatorStack[i].op == REOP_ASSERT || - operatorStack[i].op == REOP_ASSERT_NOT || - operatorStack[i].op == REOP_LPARENNON || - operatorStack[i].op == REOP_LPAREN) { - break; - } - } - ++state->cp; - - /* Process everything on the stack until the open parenthesis. */ - for (;;) { - JS_ASSERT(operatorSP); - --operatorSP; - switch (operatorStack[operatorSP].op) { - case REOP_ASSERT: - case REOP_ASSERT_NOT: - case REOP_LPAREN: - operand = NewRENode(state, operatorStack[operatorSP].op); - if (!operand) - goto out; - operand->u.parenIndex = - operatorStack[operatorSP].parenIndex; - JS_ASSERT(operandSP); - operand->kid = operandStack[operandSP - 1]; - operandStack[operandSP - 1] = operand; - if (state->treeDepth == TREE_DEPTH_MAX) { - js_ReportCompileErrorNumber(state->context, - state->tokenStream, - JSREPORT_TS | - JSREPORT_ERROR, - JSMSG_REGEXP_TOO_COMPLEX); - goto out; - } - ++state->treeDepth; - /* FALL THROUGH */ - - case REOP_LPARENNON: - state->result = operandStack[operandSP - 1]; - if (!ParseQuantifier(state)) - goto out; - operandStack[operandSP - 1] = state->result; - goto restartOperator; - default: - if (!ProcessOp(state, &operatorStack[operatorSP], - operandStack, operandSP)) - goto out; - --operandSP; - break; - } - } - break; - - case '{': - { - const jschar *errp = state->cp; - - if (ParseMinMaxQuantifier(state, JS_TRUE) < 0) { - /* - * This didn't even scan correctly as a quantifier, so we should - * treat it as flat. - */ - op = REOP_CONCAT; - goto pushOperator; - } - - state->cp = errp; - /* FALL THROUGH */ - } - - case '+': - case '*': - case '?': - js_ReportCompileErrorNumberUC(state->context, state->tokenStream, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_BAD_QUANTIFIER, state->cp); - result = JS_FALSE; - goto out; - - default: - /* Anything else is the start of the next term. */ - op = REOP_CONCAT; -pushOperator: - if (operatorSP == operatorStackSize) { - operatorStackSize += operatorStackSize; - operatorStack = (REOpData *) - JS_realloc(state->context, operatorStack, - sizeof(REOpData) * operatorStackSize); - if (!operatorStack) - goto out; - } - operatorStack[operatorSP].op = op; - operatorStack[operatorSP].errPos = state->cp; - operatorStack[operatorSP++].parenIndex = parenIndex; - break; - } - } -out: - if (operatorStack) - JS_free(state->context, operatorStack); - if (operandStack) - JS_free(state->context, operandStack); - return result; -} - -/* - * Hack two bits in CompilerState.flags, for use within FindParenCount to flag - * its being on the stack, and to propagate errors to its callers. - */ -#define JSREG_FIND_PAREN_COUNT 0x8000 -#define JSREG_FIND_PAREN_ERROR 0x4000 - -/* - * Magic return value from FindParenCount and GetDecimalValue, to indicate - * overflow beyond GetDecimalValue's max parameter, or a computed maximum if - * its findMax parameter is non-null. - */ -#define OVERFLOW_VALUE ((uintN)-1) - -static uintN -FindParenCount(CompilerState *state) -{ - CompilerState temp; - int i; - - if (state->flags & JSREG_FIND_PAREN_COUNT) - return OVERFLOW_VALUE; - - /* - * Copy state into temp, flag it so we never report an invalid backref, - * and reset its members to parse the entire regexp. This is obviously - * suboptimal, but GetDecimalValue calls us only if a backref appears to - * refer to a forward parenthetical, which is rare. - */ - temp = *state; - temp.flags |= JSREG_FIND_PAREN_COUNT; - temp.cp = temp.cpbegin; - temp.parenCount = 0; - temp.classCount = 0; - temp.progLength = 0; - temp.treeDepth = 0; - temp.classBitmapsMem = 0; - for (i = 0; i < CLASS_CACHE_SIZE; i++) - temp.classCache[i].start = NULL; - - if (!ParseRegExp(&temp)) { - state->flags |= JSREG_FIND_PAREN_ERROR; - return OVERFLOW_VALUE; - } - return temp.parenCount; -} - -/* - * Extract and return a decimal value at state->cp. The initial character c - * has already been read. Return OVERFLOW_VALUE if the result exceeds max. - * Callers who pass a non-null findMax should test JSREG_FIND_PAREN_ERROR in - * state->flags to discover whether an error occurred under findMax. - */ -static uintN -GetDecimalValue(jschar c, uintN max, uintN (*findMax)(CompilerState *state), - CompilerState *state) -{ - uintN value = JS7_UNDEC(c); - JSBool overflow = (value > max && (!findMax || value > findMax(state))); - - /* The following restriction allows simpler overflow checks. */ - JS_ASSERT(max <= ((uintN)-1 - 9) / 10); - while (state->cp < state->cpend) { - c = *state->cp; - if (!JS7_ISDEC(c)) - break; - value = 10 * value + JS7_UNDEC(c); - if (!overflow && value > max && (!findMax || value > findMax(state))) - overflow = JS_TRUE; - ++state->cp; - } - return overflow ? OVERFLOW_VALUE : value; -} - -/* - * Calculate the total size of the bitmap required for a class expression. - */ -static JSBool -CalculateBitmapSize(CompilerState *state, RENode *target, const jschar *src, - const jschar *end) -{ - uintN max = 0; - JSBool inRange = JS_FALSE; - jschar c, rangeStart = 0; - uintN n, digit, nDigits, i; - - target->u.ucclass.bmsize = 0; - target->u.ucclass.sense = JS_TRUE; - - if (src == end) - return JS_TRUE; - - if (*src == '^') { - ++src; - target->u.ucclass.sense = JS_FALSE; - } - - while (src != end) { - uintN localMax = 0; - switch (*src) { - case '\\': - ++src; - c = *src++; - switch (c) { - case 'b': - localMax = 0x8; - break; - case 'f': - localMax = 0xC; - break; - case 'n': - localMax = 0xA; - break; - case 'r': - localMax = 0xD; - break; - case 't': - localMax = 0x9; - break; - case 'v': - localMax = 0xB; - break; - case 'c': - if (src + 1 < end && RE_IS_LETTER(src[1])) - localMax = (jschar) (*src++ & 0x1F); - else - localMax = '\\'; - break; - case 'x': - nDigits = 2; - goto lexHex; - case 'u': - nDigits = 4; -lexHex: - n = 0; - for (i = 0; (i < nDigits) && (src < end); i++) { - c = *src++; - if (!isASCIIHexDigit(c, &digit)) { - /* - * Back off to accepting the original - *'\' as a literal. - */ - src -= i + 1; - n = '\\'; - break; - } - n = (n << 4) | digit; - } - localMax = n; - break; - case 'd': - if (inRange) { - JS_ReportErrorNumber(state->context, - js_GetErrorMessage, NULL, - JSMSG_BAD_CLASS_RANGE); - return JS_FALSE; - } - localMax = '9'; - break; - case 'D': - case 's': - case 'S': - case 'w': - case 'W': - if (inRange) { - JS_ReportErrorNumber(state->context, - js_GetErrorMessage, NULL, - JSMSG_BAD_CLASS_RANGE); - return JS_FALSE; - } - target->u.ucclass.bmsize = 65535; - return JS_TRUE; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - /* - * This is a non-ECMA extension - decimal escapes (in this - * case, octal!) are supposed to be an error inside class - * ranges, but supported here for backwards compatibility. - * - */ - n = JS7_UNDEC(c); - c = *src; - if ('0' <= c && c <= '7') { - src++; - n = 8 * n + JS7_UNDEC(c); - c = *src; - if ('0' <= c && c <= '7') { - src++; - i = 8 * n + JS7_UNDEC(c); - if (i <= 0377) - n = i; - else - src--; - } - } - localMax = n; - break; - - default: - localMax = c; - break; - } - break; - default: - localMax = *src++; - break; - } - if (inRange) { - if (rangeStart > localMax) { - JS_ReportErrorNumber(state->context, - js_GetErrorMessage, NULL, - JSMSG_BAD_CLASS_RANGE); - return JS_FALSE; - } - inRange = JS_FALSE; - } else { - if (src < end - 1) { - if (*src == '-') { - ++src; - inRange = JS_TRUE; - rangeStart = (jschar)localMax; - continue; - } - } - } - if (state->flags & JSREG_FOLD) { - c = JS_MAX(upcase((jschar)localMax), downcase((jschar)localMax)); - if (c > localMax) - localMax = c; - } - if (localMax > max) - max = localMax; - } - target->u.ucclass.bmsize = max; - return JS_TRUE; -} - -/* - * item: assertion An item is either an assertion or - * quantatom a quantified atom. - * - * assertion: '^' Assertions match beginning of string - * (or line if the class static property - * RegExp.multiline is true). - * '$' End of string (or line if the class - * static property RegExp.multiline is - * true). - * '\b' Word boundary (between \w and \W). - * '\B' Word non-boundary. - * - * quantatom: atom An unquantified atom. - * quantatom '{' n ',' m '}' - * Atom must occur between n and m times. - * quantatom '{' n ',' '}' Atom must occur at least n times. - * quantatom '{' n '}' Atom must occur exactly n times. - * quantatom '*' Zero or more times (same as {0,}). - * quantatom '+' One or more times (same as {1,}). - * quantatom '?' Zero or one time (same as {0,1}). - * - * any of which can be optionally followed by '?' for ungreedy - * - * atom: '(' regexp ')' A parenthesized regexp (what matched - * can be addressed using a backreference, - * see '\' n below). - * '.' Matches any char except '\n'. - * '[' classlist ']' A character class. - * '[' '^' classlist ']' A negated character class. - * '\f' Form Feed. - * '\n' Newline (Line Feed). - * '\r' Carriage Return. - * '\t' Horizontal Tab. - * '\v' Vertical Tab. - * '\d' A digit (same as [0-9]). - * '\D' A non-digit. - * '\w' A word character, [0-9a-z_A-Z]. - * '\W' A non-word character. - * '\s' A whitespace character, [ \b\f\n\r\t\v]. - * '\S' A non-whitespace character. - * '\' n A backreference to the nth (n decimal - * and positive) parenthesized expression. - * '\' octal An octal escape sequence (octal must be - * two or three digits long, unless it is - * 0 for the null character). - * '\x' hex A hex escape (hex must be two digits). - * '\u' unicode A unicode escape (must be four digits). - * '\c' ctrl A control character, ctrl is a letter. - * '\' literalatomchar Any character except one of the above - * that follow '\' in an atom. - * otheratomchar Any character not first among the other - * atom right-hand sides. - */ -static JSBool -ParseTerm(CompilerState *state) -{ - jschar c = *state->cp++; - uintN nDigits; - uintN num, tmp, n, i; - const jschar *termStart; - - switch (c) { - /* assertions and atoms */ - case '^': - state->result = NewRENode(state, REOP_BOL); - if (!state->result) - return JS_FALSE; - state->progLength++; - return JS_TRUE; - case '$': - state->result = NewRENode(state, REOP_EOL); - if (!state->result) - return JS_FALSE; - state->progLength++; - return JS_TRUE; - case '\\': - if (state->cp >= state->cpend) { - /* a trailing '\' is an error */ - js_ReportCompileErrorNumber(state->context, state->tokenStream, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_TRAILING_SLASH); - return JS_FALSE; - } - c = *state->cp++; - switch (c) { - /* assertion escapes */ - case 'b' : - state->result = NewRENode(state, REOP_WBDRY); - if (!state->result) - return JS_FALSE; - state->progLength++; - return JS_TRUE; - case 'B': - state->result = NewRENode(state, REOP_WNONBDRY); - if (!state->result) - return JS_FALSE; - state->progLength++; - return JS_TRUE; - /* Decimal escape */ - case '0': - /* Give a strict warning. See also the note below. */ - if (!js_ReportCompileErrorNumber(state->context, - state->tokenStream, - JSREPORT_TS | - JSREPORT_WARNING | - JSREPORT_STRICT, - JSMSG_INVALID_BACKREF)) { - return JS_FALSE; - } - doOctal: - num = 0; - while (state->cp < state->cpend) { - c = *state->cp; - if (c < '0' || '7' < c) - break; - state->cp++; - tmp = 8 * num + (uintN)JS7_UNDEC(c); - if (tmp > 0377) - break; - num = tmp; - } - c = (jschar)num; - doFlat: - state->result = NewRENode(state, REOP_FLAT); - if (!state->result) - return JS_FALSE; - state->result->u.flat.chr = c; - state->result->u.flat.length = 1; - state->progLength += 3; - break; - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - termStart = state->cp - 1; - num = GetDecimalValue(c, state->parenCount, FindParenCount, state); - if (state->flags & JSREG_FIND_PAREN_ERROR) - return JS_FALSE; - if (num == OVERFLOW_VALUE) { - /* Give a strict mode warning. */ - if (!js_ReportCompileErrorNumber(state->context, - state->tokenStream, - JSREPORT_TS | - JSREPORT_WARNING | - JSREPORT_STRICT, - (c >= '8') - ? JSMSG_INVALID_BACKREF - : JSMSG_BAD_BACKREF)) { - return JS_FALSE; - } - - /* - * Note: ECMA 262, 15.10.2.9 says that we should throw a syntax - * error here. However, for compatibility with IE, we treat the - * whole backref as flat if the first character in it is not a - * valid octal character, and as an octal escape otherwise. - */ - state->cp = termStart; - if (c >= '8') { - /* Treat this as flat. termStart - 1 is the \. */ - c = '\\'; - goto asFlat; - } - - /* Treat this as an octal escape. */ - goto doOctal; - } - JS_ASSERT(1 <= num && num <= 0x10000); - state->result = NewRENode(state, REOP_BACKREF); - if (!state->result) - return JS_FALSE; - state->result->u.parenIndex = num - 1; - state->progLength - += 1 + GetCompactIndexWidth(state->result->u.parenIndex); - break; - /* Control escape */ - case 'f': - c = 0xC; - goto doFlat; - case 'n': - c = 0xA; - goto doFlat; - case 'r': - c = 0xD; - goto doFlat; - case 't': - c = 0x9; - goto doFlat; - case 'v': - c = 0xB; - goto doFlat; - /* Control letter */ - case 'c': - if (state->cp + 1 < state->cpend && RE_IS_LETTER(state->cp[1])) { - c = (jschar) (*state->cp++ & 0x1F); - } else { - /* back off to accepting the original '\' as a literal */ - --state->cp; - c = '\\'; - } - goto doFlat; - /* HexEscapeSequence */ - case 'x': - nDigits = 2; - goto lexHex; - /* UnicodeEscapeSequence */ - case 'u': - nDigits = 4; -lexHex: - n = 0; - for (i = 0; i < nDigits && state->cp < state->cpend; i++) { - uintN digit; - c = *state->cp++; - if (!isASCIIHexDigit(c, &digit)) { - /* - * Back off to accepting the original 'u' or 'x' as a - * literal. - */ - state->cp -= i + 2; - n = *state->cp++; - break; - } - n = (n << 4) | digit; - } - c = (jschar) n; - goto doFlat; - /* Character class escapes */ - case 'd': - state->result = NewRENode(state, REOP_DIGIT); -doSimple: - if (!state->result) - return JS_FALSE; - state->progLength++; - break; - case 'D': - state->result = NewRENode(state, REOP_NONDIGIT); - goto doSimple; - case 's': - state->result = NewRENode(state, REOP_SPACE); - goto doSimple; - case 'S': - state->result = NewRENode(state, REOP_NONSPACE); - goto doSimple; - case 'w': - state->result = NewRENode(state, REOP_ALNUM); - goto doSimple; - case 'W': - state->result = NewRENode(state, REOP_NONALNUM); - goto doSimple; - /* IdentityEscape */ - default: - state->result = NewRENode(state, REOP_FLAT); - if (!state->result) - return JS_FALSE; - state->result->u.flat.chr = c; - state->result->u.flat.length = 1; - state->result->kid = (void *) (state->cp - 1); - state->progLength += 3; - break; - } - break; - case '[': - state->result = NewRENode(state, REOP_CLASS); - if (!state->result) - return JS_FALSE; - termStart = state->cp; - state->result->u.ucclass.startIndex = termStart - state->cpbegin; - for (;;) { - if (state->cp == state->cpend) { - js_ReportCompileErrorNumberUC(state->context, state->tokenStream, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_UNTERM_CLASS, termStart); - - return JS_FALSE; - } - if (*state->cp == '\\') { - state->cp++; - if (state->cp != state->cpend) - state->cp++; - continue; - } - if (*state->cp == ']') { - state->result->u.ucclass.kidlen = state->cp - termStart; - break; - } - state->cp++; - } - for (i = 0; i < CLASS_CACHE_SIZE; i++) { - if (!state->classCache[i].start) { - state->classCache[i].start = termStart; - state->classCache[i].length = state->result->u.ucclass.kidlen; - state->classCache[i].index = state->classCount; - break; - } - if (state->classCache[i].length == - state->result->u.ucclass.kidlen) { - for (n = 0; ; n++) { - if (n == state->classCache[i].length) { - state->result->u.ucclass.index - = state->classCache[i].index; - goto claim; - } - if (state->classCache[i].start[n] != termStart[n]) - break; - } - } - } - state->result->u.ucclass.index = state->classCount++; - - claim: - /* - * Call CalculateBitmapSize now as we want any errors it finds - * to be reported during the parse phase, not at execution. - */ - if (!CalculateBitmapSize(state, state->result, termStart, state->cp++)) - return JS_FALSE; - /* - * Update classBitmapsMem with number of bytes to hold bmsize bits, - * which is (bitsCount + 7) / 8 or (highest_bit + 1 + 7) / 8 - * or highest_bit / 8 + 1 where highest_bit is u.ucclass.bmsize. - */ - n = (state->result->u.ucclass.bmsize >> 3) + 1; - if (n > CLASS_BITMAPS_MEM_LIMIT - state->classBitmapsMem) { - js_ReportCompileErrorNumber(state->context, state->tokenStream, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_REGEXP_TOO_COMPLEX); - return JS_FALSE; - } - state->classBitmapsMem += n; - /* CLASS, */ - state->progLength - += 1 + GetCompactIndexWidth(state->result->u.ucclass.index); - break; - - case '.': - state->result = NewRENode(state, REOP_DOT); - goto doSimple; - - case '{': - { - const jschar *errp = state->cp--; - intN err; - - err = ParseMinMaxQuantifier(state, JS_TRUE); - state->cp = errp; - - if (err < 0) - goto asFlat; - - /* FALL THROUGH */ - } - case '*': - case '+': - case '?': - js_ReportCompileErrorNumberUC(state->context, state->tokenStream, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_BAD_QUANTIFIER, state->cp - 1); - return JS_FALSE; - default: -asFlat: - state->result = NewRENode(state, REOP_FLAT); - if (!state->result) - return JS_FALSE; - state->result->u.flat.chr = c; - state->result->u.flat.length = 1; - state->result->kid = (void *) (state->cp - 1); - state->progLength += 3; - break; - } - return ParseQuantifier(state); -} - -static JSBool -ParseQuantifier(CompilerState *state) -{ - RENode *term; - term = state->result; - if (state->cp < state->cpend) { - switch (*state->cp) { - case '+': - state->result = NewRENode(state, REOP_QUANT); - if (!state->result) - return JS_FALSE; - state->result->u.range.min = 1; - state->result->u.range.max = (uintN)-1; - /* , ... */ - state->progLength += 4; - goto quantifier; - case '*': - state->result = NewRENode(state, REOP_QUANT); - if (!state->result) - return JS_FALSE; - state->result->u.range.min = 0; - state->result->u.range.max = (uintN)-1; - /* , ... */ - state->progLength += 4; - goto quantifier; - case '?': - state->result = NewRENode(state, REOP_QUANT); - if (!state->result) - return JS_FALSE; - state->result->u.range.min = 0; - state->result->u.range.max = 1; - /* , ... */ - state->progLength += 4; - goto quantifier; - case '{': /* balance '}' */ - { - intN err; - const jschar *errp = state->cp; - - err = ParseMinMaxQuantifier(state, JS_FALSE); - if (err == 0) - goto quantifier; - if (err == -1) - return JS_TRUE; - - js_ReportCompileErrorNumberUC(state->context, - state->tokenStream, - JSREPORT_TS | JSREPORT_ERROR, - err, errp); - return JS_FALSE; - } - default:; - } - } - return JS_TRUE; - -quantifier: - if (state->treeDepth == TREE_DEPTH_MAX) { - js_ReportCompileErrorNumber(state->context, state->tokenStream, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_REGEXP_TOO_COMPLEX); - return JS_FALSE; - } - - ++state->treeDepth; - ++state->cp; - state->result->kid = term; - if (state->cp < state->cpend && *state->cp == '?') { - ++state->cp; - state->result->u.range.greedy = JS_FALSE; - } else { - state->result->u.range.greedy = JS_TRUE; - } - return JS_TRUE; -} - -static intN -ParseMinMaxQuantifier(CompilerState *state, JSBool ignoreValues) -{ - uintN min, max; - jschar c; - const jschar *errp = state->cp++; - - c = *state->cp; - if (JS7_ISDEC(c)) { - ++state->cp; - min = GetDecimalValue(c, 0xFFFF, NULL, state); - c = *state->cp; - - if (!ignoreValues && min == OVERFLOW_VALUE) - return JSMSG_MIN_TOO_BIG; - - if (c == ',') { - c = *++state->cp; - if (JS7_ISDEC(c)) { - ++state->cp; - max = GetDecimalValue(c, 0xFFFF, NULL, state); - c = *state->cp; - if (!ignoreValues && max == OVERFLOW_VALUE) - return JSMSG_MAX_TOO_BIG; - if (!ignoreValues && min > max) - return JSMSG_OUT_OF_ORDER; - } else { - max = (uintN)-1; - } - } else { - max = min; - } - if (c == '}') { - state->result = NewRENode(state, REOP_QUANT); - if (!state->result) - return JS_FALSE; - state->result->u.range.min = min; - state->result->u.range.max = max; - /* - * QUANT, , , ... - * where is written as compact(max+1) to make - * (uintN)-1 sentinel to occupy 1 byte, not width_of(max)+1. - */ - state->progLength += (1 + GetCompactIndexWidth(min) - + GetCompactIndexWidth(max + 1) - +3); - return 0; - } - } - - state->cp = errp; - return -1; -} - -static JSBool -SetForwardJumpOffset(jsbytecode *jump, jsbytecode *target) -{ - ptrdiff_t offset = target - jump; - - /* Check that target really points forward. */ - JS_ASSERT(offset >= 2); - if ((size_t)offset > OFFSET_MAX) - return JS_FALSE; - - jump[0] = JUMP_OFFSET_HI(offset); - jump[1] = JUMP_OFFSET_LO(offset); - return JS_TRUE; -} - -/* - * Generate bytecode for the tree rooted at t using an explicit stack instead - * of recursion. - */ -static jsbytecode * -EmitREBytecode(CompilerState *state, JSRegExp *re, size_t treeDepth, - jsbytecode *pc, RENode *t) -{ - EmitStateStackEntry *emitStateSP, *emitStateStack; - RECharSet *charSet; - REOp op; - - if (treeDepth == 0) { - emitStateStack = NULL; - } else { - emitStateStack = - (EmitStateStackEntry *)JS_malloc(state->context, - sizeof(EmitStateStackEntry) * - treeDepth); - if (!emitStateStack) - return NULL; - } - emitStateSP = emitStateStack; - op = t->op; - - for (;;) { - *pc++ = op; - switch (op) { - case REOP_EMPTY: - --pc; - break; - - case REOP_ALTPREREQ2: - case REOP_ALTPREREQ: - JS_ASSERT(emitStateSP); - emitStateSP->altHead = pc - 1; - emitStateSP->endTermFixup = pc; - pc += OFFSET_LEN; - SET_ARG(pc, t->u.altprereq.ch1); - pc += ARG_LEN; - SET_ARG(pc, t->u.altprereq.ch2); - pc += ARG_LEN; - - emitStateSP->nextAltFixup = pc; /* offset to next alternate */ - pc += OFFSET_LEN; - - emitStateSP->continueNode = t; - emitStateSP->continueOp = REOP_JUMP; - emitStateSP->jumpToJumpFlag = JS_FALSE; - ++emitStateSP; - JS_ASSERT((size_t)(emitStateSP - emitStateStack) <= treeDepth); - t = (RENode *) t->kid; - op = t->op; - continue; - - case REOP_JUMP: - emitStateSP->nextTermFixup = pc; /* offset to following term */ - pc += OFFSET_LEN; - if (!SetForwardJumpOffset(emitStateSP->nextAltFixup, pc)) - goto jump_too_big; - emitStateSP->continueOp = REOP_ENDALT; - ++emitStateSP; - JS_ASSERT((size_t)(emitStateSP - emitStateStack) <= treeDepth); - t = t->u.kid2; - op = t->op; - continue; - - case REOP_ENDALT: - /* - * If we already patched emitStateSP->nextTermFixup to jump to - * a nearer jump, to avoid 16-bit immediate offset overflow, we - * are done here. - */ - if (emitStateSP->jumpToJumpFlag) - break; - - /* - * Fix up the REOP_JUMP offset to go to the op after REOP_ENDALT. - * REOP_ENDALT is executed only on successful match of the last - * alternate in a group. - */ - if (!SetForwardJumpOffset(emitStateSP->nextTermFixup, pc)) - goto jump_too_big; - if (t->op != REOP_ALT) { - if (!SetForwardJumpOffset(emitStateSP->endTermFixup, pc)) - goto jump_too_big; - } - - /* - * If the program is bigger than the REOP_JUMP offset range, then - * we must check for alternates before this one that are part of - * the same group, and fix up their jump offsets to target jumps - * close enough to fit in a 16-bit unsigned offset immediate. - */ - if ((size_t)(pc - re->program) > OFFSET_MAX && - emitStateSP > emitStateStack) { - EmitStateStackEntry *esp, *esp2; - jsbytecode *alt, *jump; - ptrdiff_t span, header; - - esp2 = emitStateSP; - alt = esp2->altHead; - for (esp = esp2 - 1; esp >= emitStateStack; --esp) { - if (esp->continueOp == REOP_ENDALT && - !esp->jumpToJumpFlag && - esp->nextTermFixup + OFFSET_LEN == alt && - (size_t)(pc - ((esp->continueNode->op != REOP_ALT) - ? esp->endTermFixup - : esp->nextTermFixup)) > OFFSET_MAX) { - alt = esp->altHead; - jump = esp->nextTermFixup; - - /* - * The span must be 1 less than the distance from - * jump offset to jump offset, so we actually jump - * to a REOP_JUMP bytecode, not to its offset! - */ - for (;;) { - JS_ASSERT(jump < esp2->nextTermFixup); - span = esp2->nextTermFixup - jump - 1; - if ((size_t)span <= OFFSET_MAX) - break; - do { - if (--esp2 == esp) - goto jump_too_big; - } while (esp2->continueOp != REOP_ENDALT); - } - - jump[0] = JUMP_OFFSET_HI(span); - jump[1] = JUMP_OFFSET_LO(span); - - if (esp->continueNode->op != REOP_ALT) { - /* - * We must patch the offset at esp->endTermFixup - * as well, for the REOP_ALTPREREQ{,2} opcodes. - * If we're unlucky and endTermFixup is more than - * OFFSET_MAX bytes from its target, we cheat by - * jumping 6 bytes to the jump whose offset is at - * esp->nextTermFixup, which has the same target. - */ - jump = esp->endTermFixup; - header = esp->nextTermFixup - jump; - span += header; - if ((size_t)span > OFFSET_MAX) - span = header; - - jump[0] = JUMP_OFFSET_HI(span); - jump[1] = JUMP_OFFSET_LO(span); - } - - esp->jumpToJumpFlag = JS_TRUE; - } - } - } - break; - - case REOP_ALT: - JS_ASSERT(emitStateSP); - emitStateSP->altHead = pc - 1; - emitStateSP->nextAltFixup = pc; /* offset to next alternate */ - pc += OFFSET_LEN; - emitStateSP->continueNode = t; - emitStateSP->continueOp = REOP_JUMP; - emitStateSP->jumpToJumpFlag = JS_FALSE; - ++emitStateSP; - JS_ASSERT((size_t)(emitStateSP - emitStateStack) <= treeDepth); - t = t->kid; - op = t->op; - continue; - - case REOP_FLAT: - /* - * Coalesce FLATs if possible and if it would not increase bytecode - * beyond preallocated limit. The latter happens only when bytecode - * size for coalesced string with offset p and length 2 exceeds 6 - * bytes preallocated for 2 single char nodes, i.e. when - * 1 + GetCompactIndexWidth(p) + GetCompactIndexWidth(2) > 6 or - * GetCompactIndexWidth(p) > 4. - * Since when GetCompactIndexWidth(p) <= 4 coalescing of 3 or more - * nodes strictly decreases bytecode size, the check has to be - * done only for the first coalescing. - */ - if (t->kid && - GetCompactIndexWidth((jschar *)t->kid - state->cpbegin) <= 4) - { - while (t->next && - t->next->op == REOP_FLAT && - (jschar*)t->kid + t->u.flat.length == - (jschar*)t->next->kid) { - t->u.flat.length += t->next->u.flat.length; - t->next = t->next->next; - } - } - if (t->kid && t->u.flat.length > 1) { - pc[-1] = (state->flags & JSREG_FOLD) ? REOP_FLATi : REOP_FLAT; - pc = WriteCompactIndex(pc, (jschar *)t->kid - state->cpbegin); - pc = WriteCompactIndex(pc, t->u.flat.length); - } else if (t->u.flat.chr < 256) { - pc[-1] = (state->flags & JSREG_FOLD) ? REOP_FLAT1i : REOP_FLAT1; - *pc++ = (jsbytecode) t->u.flat.chr; - } else { - pc[-1] = (state->flags & JSREG_FOLD) - ? REOP_UCFLAT1i - : REOP_UCFLAT1; - SET_ARG(pc, t->u.flat.chr); - pc += ARG_LEN; - } - break; - - case REOP_LPAREN: - JS_ASSERT(emitStateSP); - pc = WriteCompactIndex(pc, t->u.parenIndex); - emitStateSP->continueNode = t; - emitStateSP->continueOp = REOP_RPAREN; - ++emitStateSP; - JS_ASSERT((size_t)(emitStateSP - emitStateStack) <= treeDepth); - t = (RENode *) t->kid; - op = t->op; - continue; - - case REOP_RPAREN: - pc = WriteCompactIndex(pc, t->u.parenIndex); - break; - - case REOP_BACKREF: - pc = WriteCompactIndex(pc, t->u.parenIndex); - break; - - case REOP_ASSERT: - JS_ASSERT(emitStateSP); - emitStateSP->nextTermFixup = pc; - pc += OFFSET_LEN; - emitStateSP->continueNode = t; - emitStateSP->continueOp = REOP_ASSERTTEST; - ++emitStateSP; - JS_ASSERT((size_t)(emitStateSP - emitStateStack) <= treeDepth); - t = (RENode *) t->kid; - op = t->op; - continue; - - case REOP_ASSERTTEST: - case REOP_ASSERTNOTTEST: - if (!SetForwardJumpOffset(emitStateSP->nextTermFixup, pc)) - goto jump_too_big; - break; - - case REOP_ASSERT_NOT: - JS_ASSERT(emitStateSP); - emitStateSP->nextTermFixup = pc; - pc += OFFSET_LEN; - emitStateSP->continueNode = t; - emitStateSP->continueOp = REOP_ASSERTNOTTEST; - ++emitStateSP; - JS_ASSERT((size_t)(emitStateSP - emitStateStack) <= treeDepth); - t = (RENode *) t->kid; - op = t->op; - continue; - - case REOP_QUANT: - JS_ASSERT(emitStateSP); - if (t->u.range.min == 0 && t->u.range.max == (uintN)-1) { - pc[-1] = (t->u.range.greedy) ? REOP_STAR : REOP_MINIMALSTAR; - } else if (t->u.range.min == 0 && t->u.range.max == 1) { - pc[-1] = (t->u.range.greedy) ? REOP_OPT : REOP_MINIMALOPT; - } else if (t->u.range.min == 1 && t->u.range.max == (uintN) -1) { - pc[-1] = (t->u.range.greedy) ? REOP_PLUS : REOP_MINIMALPLUS; - } else { - if (!t->u.range.greedy) - pc[-1] = REOP_MINIMALQUANT; - pc = WriteCompactIndex(pc, t->u.range.min); - /* - * Write max + 1 to avoid using size_t(max) + 1 bytes - * for (uintN)-1 sentinel. - */ - pc = WriteCompactIndex(pc, t->u.range.max + 1); - } - emitStateSP->nextTermFixup = pc; - pc += OFFSET_LEN; - emitStateSP->continueNode = t; - emitStateSP->continueOp = REOP_ENDCHILD; - ++emitStateSP; - JS_ASSERT((size_t)(emitStateSP - emitStateStack) <= treeDepth); - t = (RENode *) t->kid; - op = t->op; - continue; - - case REOP_ENDCHILD: - if (!SetForwardJumpOffset(emitStateSP->nextTermFixup, pc)) - goto jump_too_big; - break; - - case REOP_CLASS: - if (!t->u.ucclass.sense) - pc[-1] = REOP_NCLASS; - pc = WriteCompactIndex(pc, t->u.ucclass.index); - charSet = &re->classList[t->u.ucclass.index]; - charSet->converted = JS_FALSE; - charSet->length = t->u.ucclass.bmsize; - charSet->u.src.startIndex = t->u.ucclass.startIndex; - charSet->u.src.length = t->u.ucclass.kidlen; - charSet->sense = t->u.ucclass.sense; - break; - - default: - break; - } - - t = t->next; - if (t) { - op = t->op; - } else { - if (emitStateSP == emitStateStack) - break; - --emitStateSP; - t = emitStateSP->continueNode; - op = emitStateSP->continueOp; - } - } - - cleanup: - if (emitStateStack) - JS_free(state->context, emitStateStack); - return pc; - - jump_too_big: - js_ReportCompileErrorNumber(state->context, state->tokenStream, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_REGEXP_TOO_COMPLEX); - pc = NULL; - goto cleanup; -} - - -JSRegExp * -js_NewRegExp(JSContext *cx, JSTokenStream *ts, - JSString *str, uintN flags, JSBool flat) -{ - JSRegExp *re; - void *mark; - CompilerState state; - size_t resize; - jsbytecode *endPC; - uintN i; - size_t len; - - re = NULL; - mark = JS_ARENA_MARK(&cx->tempPool); - len = JSSTRING_LENGTH(str); - - state.context = cx; - state.tokenStream = ts; - state.cpbegin = state.cp = JSSTRING_CHARS(str); - state.cpend = state.cp + len; - state.flags = flags; - state.parenCount = 0; - state.classCount = 0; - state.progLength = 0; - state.treeDepth = 0; - state.classBitmapsMem = 0; - for (i = 0; i < CLASS_CACHE_SIZE; i++) - state.classCache[i].start = NULL; - - if (len != 0 && flat) { - state.result = NewRENode(&state, REOP_FLAT); - state.result->u.flat.chr = *state.cpbegin; - state.result->u.flat.length = len; - state.result->kid = (void *) state.cpbegin; - /* Flat bytecode: REOP_FLAT compact(string_offset) compact(len). */ - state.progLength += 1 + GetCompactIndexWidth(0) - + GetCompactIndexWidth(len); - } else { - if (!ParseRegExp(&state)) - goto out; - } - resize = offsetof(JSRegExp, program) + state.progLength + 1; - re = (JSRegExp *) JS_malloc(cx, resize); - if (!re) - goto out; - - re->nrefs = 1; - JS_ASSERT(state.classBitmapsMem <= CLASS_BITMAPS_MEM_LIMIT); - re->classCount = state.classCount; - if (re->classCount) { - re->classList = (RECharSet *) - JS_malloc(cx, re->classCount * sizeof(RECharSet)); - if (!re->classList) { - js_DestroyRegExp(cx, re); - re = NULL; - goto out; - } - } else { - re->classList = NULL; - } - endPC = EmitREBytecode(&state, re, state.treeDepth, re->program, state.result); - if (!endPC) { - js_DestroyRegExp(cx, re); - re = NULL; - goto out; - } - *endPC++ = REOP_END; - /* - * Check whether size was overestimated and shrink using realloc. - * This is safe since no pointers to newly parsed regexp or its parts - * besides re exist here. - */ - if ((size_t)(endPC - re->program) != state.progLength + 1) { - JSRegExp *tmp; - JS_ASSERT((size_t)(endPC - re->program) < state.progLength + 1); - resize = offsetof(JSRegExp, program) + (endPC - re->program); - tmp = (JSRegExp *) JS_realloc(cx, re, resize); - if (tmp) - re = tmp; - } - - re->flags = flags; - re->cloneIndex = 0; - re->parenCount = state.parenCount; - re->source = str; - -out: - JS_ARENA_RELEASE(&cx->tempPool, mark); - return re; -} - -JSRegExp * -js_NewRegExpOpt(JSContext *cx, JSTokenStream *ts, - JSString *str, JSString *opt, JSBool flat) -{ - uintN flags; - jschar *s; - size_t i, n; - char charBuf[2]; - - flags = 0; - if (opt) { - s = JSSTRING_CHARS(opt); - for (i = 0, n = JSSTRING_LENGTH(opt); i < n; i++) { - switch (s[i]) { - case 'g': - flags |= JSREG_GLOB; - break; - case 'i': - flags |= JSREG_FOLD; - break; - case 'm': - flags |= JSREG_MULTILINE; - break; - default: - charBuf[0] = (char)s[i]; - charBuf[1] = '\0'; - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_BAD_FLAG, charBuf); - return NULL; - } - } - } - return js_NewRegExp(cx, ts, str, flags, flat); -} - -/* - * Save the current state of the match - the position in the input - * text as well as the position in the bytecode. The state of any - * parent expressions is also saved (preceding state). - * Contents of parenCount parentheses from parenIndex are also saved. - */ -static REBackTrackData * -PushBackTrackState(REGlobalData *gData, REOp op, - jsbytecode *target, REMatchState *x, const jschar *cp, - size_t parenIndex, size_t parenCount) -{ - size_t i; - REBackTrackData *result = - (REBackTrackData *) ((char *)gData->backTrackSP + gData->cursz); - - size_t sz = sizeof(REBackTrackData) + - gData->stateStackTop * sizeof(REProgState) + - parenCount * sizeof(RECapture); - - ptrdiff_t btsize = gData->backTrackStackSize; - ptrdiff_t btincr = ((char *)result + sz) - - ((char *)gData->backTrackStack + btsize); - - if (btincr > 0) { - ptrdiff_t offset = (char *)result - (char *)gData->backTrackStack; - - btincr = JS_ROUNDUP(btincr, btsize); - JS_ARENA_GROW_CAST(gData->backTrackStack, REBackTrackData *, - &gData->pool, btsize, btincr); - if (!gData->backTrackStack) - return NULL; - gData->backTrackStackSize = btsize + btincr; - result = (REBackTrackData *) ((char *)gData->backTrackStack + offset); - } - gData->backTrackSP = result; - result->sz = gData->cursz; - gData->cursz = sz; - - result->backtrack_op = op; - result->backtrack_pc = target; - result->cp = cp; - result->parenCount = parenCount; - - result->saveStateStackTop = gData->stateStackTop; - JS_ASSERT(gData->stateStackTop); - memcpy(result + 1, gData->stateStack, - sizeof(REProgState) * result->saveStateStackTop); - - if (parenCount != 0) { - result->parenIndex = parenIndex; - memcpy((char *)(result + 1) + - sizeof(REProgState) * result->saveStateStackTop, - &x->parens[parenIndex], - sizeof(RECapture) * parenCount); - for (i = 0; i != parenCount; i++) - x->parens[parenIndex + i].index = -1; - } - - return result; -} - - -/* - * Consecutive literal characters. - */ -#if 0 -static REMatchState * -FlatNMatcher(REGlobalData *gData, REMatchState *x, jschar *matchChars, - size_t length) -{ - size_t i; - if (length > gData->cpend - x->cp) - return NULL; - for (i = 0; i != length; i++) { - if (matchChars[i] != x->cp[i]) - return NULL; - } - x->cp += length; - return x; -} -#endif - -static REMatchState * -FlatNIMatcher(REGlobalData *gData, REMatchState *x, jschar *matchChars, - size_t length) -{ - size_t i; - JS_ASSERT(gData->cpend >= x->cp); - if (length > (size_t)(gData->cpend - x->cp)) - return NULL; - for (i = 0; i != length; i++) { - if (upcase(matchChars[i]) != upcase(x->cp[i])) - return NULL; - } - x->cp += length; - return x; -} - -/* - * 1. Evaluate DecimalEscape to obtain an EscapeValue E. - * 2. If E is not a character then go to step 6. - * 3. Let ch be E's character. - * 4. Let A be a one-element RECharSet containing the character ch. - * 5. Call CharacterSetMatcher(A, false) and return its Matcher result. - * 6. E must be an integer. Let n be that integer. - * 7. If n=0 or n>NCapturingParens then throw a SyntaxError exception. - * 8. Return an internal Matcher closure that takes two arguments, a State x - * and a Continuation c, and performs the following: - * 1. Let cap be x's captures internal array. - * 2. Let s be cap[n]. - * 3. If s is undefined, then call c(x) and return its result. - * 4. Let e be x's endIndex. - * 5. Let len be s's length. - * 6. Let f be e+len. - * 7. If f>InputLength, return failure. - * 8. If there exists an integer i between 0 (inclusive) and len (exclusive) - * such that Canonicalize(s[i]) is not the same character as - * Canonicalize(Input [e+i]), then return failure. - * 9. Let y be the State (f, cap). - * 10. Call c(y) and return its result. - */ -static REMatchState * -BackrefMatcher(REGlobalData *gData, REMatchState *x, size_t parenIndex) -{ - size_t len, i; - const jschar *parenContent; - RECapture *cap = &x->parens[parenIndex]; - - if (cap->index == -1) - return x; - - len = cap->length; - if (x->cp + len > gData->cpend) - return NULL; - - parenContent = &gData->cpbegin[cap->index]; - if (gData->regexp->flags & JSREG_FOLD) { - for (i = 0; i < len; i++) { - if (upcase(parenContent[i]) != upcase(x->cp[i])) - return NULL; - } - } else { - for (i = 0; i < len; i++) { - if (parenContent[i] != x->cp[i]) - return NULL; - } - } - x->cp += len; - return x; -} - - -/* Add a single character to the RECharSet */ -static void -AddCharacterToCharSet(RECharSet *cs, jschar c) -{ - uintN byteIndex = (uintN)(c >> 3); - JS_ASSERT(c <= cs->length); - cs->u.bits[byteIndex] |= 1 << (c & 0x7); -} - - -/* Add a character range, c1 to c2 (inclusive) to the RECharSet */ -static void -AddCharacterRangeToCharSet(RECharSet *cs, jschar c1, jschar c2) -{ - uintN i; - - uintN byteIndex1 = (uintN)(c1 >> 3); - uintN byteIndex2 = (uintN)(c2 >> 3); - - JS_ASSERT((c2 <= cs->length) && (c1 <= c2)); - - c1 &= 0x7; - c2 &= 0x7; - - if (byteIndex1 == byteIndex2) { - cs->u.bits[byteIndex1] |= ((uint8)0xFF >> (7 - (c2 - c1))) << c1; - } else { - cs->u.bits[byteIndex1] |= 0xFF << c1; - for (i = byteIndex1 + 1; i < byteIndex2; i++) - cs->u.bits[i] = 0xFF; - cs->u.bits[byteIndex2] |= (uint8)0xFF >> (7 - c2); - } -} - -/* Compile the source of the class into a RECharSet */ -static JSBool -ProcessCharSet(REGlobalData *gData, RECharSet *charSet) -{ - const jschar *src, *end; - JSBool inRange = JS_FALSE; - jschar rangeStart = 0; - uintN byteLength, n; - jschar c, thisCh; - intN nDigits, i; - - JS_ASSERT(!charSet->converted); - /* - * Assert that startIndex and length points to chars inside [] inside - * source string. - */ - JS_ASSERT(1 <= charSet->u.src.startIndex); - JS_ASSERT(charSet->u.src.startIndex - < JSSTRING_LENGTH(gData->regexp->source)); - JS_ASSERT(charSet->u.src.length <= JSSTRING_LENGTH(gData->regexp->source) - - 1 - charSet->u.src.startIndex); - - charSet->converted = JS_TRUE; - src = JSSTRING_CHARS(gData->regexp->source) + charSet->u.src.startIndex; - end = src + charSet->u.src.length; - JS_ASSERT(src[-1] == '['); - JS_ASSERT(end[0] == ']'); - - byteLength = (charSet->length >> 3) + 1; - charSet->u.bits = (uint8 *)JS_malloc(gData->cx, byteLength); - if (!charSet->u.bits) - return JS_FALSE; - memset(charSet->u.bits, 0, byteLength); - - if (src == end) - return JS_TRUE; - - if (*src == '^') { - JS_ASSERT(charSet->sense == JS_FALSE); - ++src; - } else { - JS_ASSERT(charSet->sense == JS_TRUE); - } - - while (src != end) { - switch (*src) { - case '\\': - ++src; - c = *src++; - switch (c) { - case 'b': - thisCh = 0x8; - break; - case 'f': - thisCh = 0xC; - break; - case 'n': - thisCh = 0xA; - break; - case 'r': - thisCh = 0xD; - break; - case 't': - thisCh = 0x9; - break; - case 'v': - thisCh = 0xB; - break; - case 'c': - if (src + 1 < end && JS_ISWORD(src[1])) { - thisCh = (jschar)(*src++ & 0x1F); - } else { - --src; - thisCh = '\\'; - } - break; - case 'x': - nDigits = 2; - goto lexHex; - case 'u': - nDigits = 4; - lexHex: - n = 0; - for (i = 0; (i < nDigits) && (src < end); i++) { - uintN digit; - c = *src++; - if (!isASCIIHexDigit(c, &digit)) { - /* - * Back off to accepting the original '\' - * as a literal - */ - src -= i + 1; - n = '\\'; - break; - } - n = (n << 4) | digit; - } - thisCh = (jschar)n; - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - /* - * This is a non-ECMA extension - decimal escapes (in this - * case, octal!) are supposed to be an error inside class - * ranges, but supported here for backwards compatibility. - */ - n = JS7_UNDEC(c); - c = *src; - if ('0' <= c && c <= '7') { - src++; - n = 8 * n + JS7_UNDEC(c); - c = *src; - if ('0' <= c && c <= '7') { - src++; - i = 8 * n + JS7_UNDEC(c); - if (i <= 0377) - n = i; - else - src--; - } - } - thisCh = (jschar)n; - break; - - case 'd': - AddCharacterRangeToCharSet(charSet, '0', '9'); - continue; /* don't need range processing */ - case 'D': - AddCharacterRangeToCharSet(charSet, 0, '0' - 1); - AddCharacterRangeToCharSet(charSet, - (jschar)('9' + 1), - (jschar)charSet->length); - continue; - case 's': - for (i = (intN)charSet->length; i >= 0; i--) - if (JS_ISSPACE(i)) - AddCharacterToCharSet(charSet, (jschar)i); - continue; - case 'S': - for (i = (intN)charSet->length; i >= 0; i--) - if (!JS_ISSPACE(i)) - AddCharacterToCharSet(charSet, (jschar)i); - continue; - case 'w': - for (i = (intN)charSet->length; i >= 0; i--) - if (JS_ISWORD(i)) - AddCharacterToCharSet(charSet, (jschar)i); - continue; - case 'W': - for (i = (intN)charSet->length; i >= 0; i--) - if (!JS_ISWORD(i)) - AddCharacterToCharSet(charSet, (jschar)i); - continue; - default: - thisCh = c; - break; - - } - break; - - default: - thisCh = *src++; - break; - - } - if (inRange) { - if (gData->regexp->flags & JSREG_FOLD) { - AddCharacterRangeToCharSet(charSet, upcase(rangeStart), - upcase(thisCh)); - AddCharacterRangeToCharSet(charSet, downcase(rangeStart), - downcase(thisCh)); - } else { - AddCharacterRangeToCharSet(charSet, rangeStart, thisCh); - } - inRange = JS_FALSE; - } else { - if (gData->regexp->flags & JSREG_FOLD) { - AddCharacterToCharSet(charSet, upcase(thisCh)); - AddCharacterToCharSet(charSet, downcase(thisCh)); - } else { - AddCharacterToCharSet(charSet, thisCh); - } - if (src < end - 1) { - if (*src == '-') { - ++src; - inRange = JS_TRUE; - rangeStart = thisCh; - } - } - } - } - return JS_TRUE; -} - -void -js_DestroyRegExp(JSContext *cx, JSRegExp *re) -{ - if (JS_ATOMIC_DECREMENT(&re->nrefs) == 0) { - if (re->classList) { - uintN i; - for (i = 0; i < re->classCount; i++) { - if (re->classList[i].converted) - JS_free(cx, re->classList[i].u.bits); - re->classList[i].u.bits = NULL; - } - JS_free(cx, re->classList); - } - JS_free(cx, re); - } -} - -static JSBool -ReallocStateStack(REGlobalData *gData) -{ - size_t limit = gData->stateStackLimit; - size_t sz = sizeof(REProgState) * limit; - - JS_ARENA_GROW_CAST(gData->stateStack, REProgState *, &gData->pool, sz, sz); - if (!gData->stateStack) { - gData->ok = JS_FALSE; - return JS_FALSE; - } - gData->stateStackLimit = limit + limit; - return JS_TRUE; -} - -#define PUSH_STATE_STACK(data) \ - JS_BEGIN_MACRO \ - ++(data)->stateStackTop; \ - if ((data)->stateStackTop == (data)->stateStackLimit && \ - !ReallocStateStack((data))) { \ - return NULL; \ - } \ - JS_END_MACRO - -/* - * Apply the current op against the given input to see if it's going to match - * or fail. Return false if we don't get a match, true if we do and update the - * state of the input and pc if the update flag is true. - */ -static REMatchState * -SimpleMatch(REGlobalData *gData, REMatchState *x, REOp op, - jsbytecode **startpc, JSBool update) -{ - REMatchState *result = NULL; - jschar matchCh; - size_t parenIndex; - size_t offset, length, index; - jsbytecode *pc = *startpc; /* pc has already been incremented past op */ - jschar *source; - const jschar *startcp = x->cp; - jschar ch; - RECharSet *charSet; - - switch (op) { - case REOP_BOL: - if (x->cp != gData->cpbegin) { - if (!gData->cx->regExpStatics.multiline && - !(gData->regexp->flags & JSREG_MULTILINE)) { - break; - } - if (!RE_IS_LINE_TERM(x->cp[-1])) - break; - } - result = x; - break; - case REOP_EOL: - if (x->cp != gData->cpend) { - if (!gData->cx->regExpStatics.multiline && - !(gData->regexp->flags & JSREG_MULTILINE)) { - break; - } - if (!RE_IS_LINE_TERM(*x->cp)) - break; - } - result = x; - break; - case REOP_WBDRY: - if ((x->cp == gData->cpbegin || !JS_ISWORD(x->cp[-1])) ^ - !(x->cp != gData->cpend && JS_ISWORD(*x->cp))) { - result = x; - } - break; - case REOP_WNONBDRY: - if ((x->cp == gData->cpbegin || !JS_ISWORD(x->cp[-1])) ^ - (x->cp != gData->cpend && JS_ISWORD(*x->cp))) { - result = x; - } - break; - case REOP_DOT: - if (x->cp != gData->cpend && !RE_IS_LINE_TERM(*x->cp)) { - result = x; - result->cp++; - } - break; - case REOP_DIGIT: - if (x->cp != gData->cpend && JS_ISDIGIT(*x->cp)) { - result = x; - result->cp++; - } - break; - case REOP_NONDIGIT: - if (x->cp != gData->cpend && !JS_ISDIGIT(*x->cp)) { - result = x; - result->cp++; - } - break; - case REOP_ALNUM: - if (x->cp != gData->cpend && JS_ISWORD(*x->cp)) { - result = x; - result->cp++; - } - break; - case REOP_NONALNUM: - if (x->cp != gData->cpend && !JS_ISWORD(*x->cp)) { - result = x; - result->cp++; - } - break; - case REOP_SPACE: - if (x->cp != gData->cpend && JS_ISSPACE(*x->cp)) { - result = x; - result->cp++; - } - break; - case REOP_NONSPACE: - if (x->cp != gData->cpend && !JS_ISSPACE(*x->cp)) { - result = x; - result->cp++; - } - break; - case REOP_BACKREF: - pc = ReadCompactIndex(pc, &parenIndex); - JS_ASSERT(parenIndex < gData->regexp->parenCount); - result = BackrefMatcher(gData, x, parenIndex); - break; - case REOP_FLAT: - pc = ReadCompactIndex(pc, &offset); - JS_ASSERT(offset < JSSTRING_LENGTH(gData->regexp->source)); - pc = ReadCompactIndex(pc, &length); - JS_ASSERT(1 <= length); - JS_ASSERT(length <= JSSTRING_LENGTH(gData->regexp->source) - offset); - if (length <= (size_t)(gData->cpend - x->cp)) { - source = JSSTRING_CHARS(gData->regexp->source) + offset; - for (index = 0; index != length; index++) { - if (source[index] != x->cp[index]) - return NULL; - } - x->cp += length; - result = x; - } - break; - case REOP_FLAT1: - matchCh = *pc++; - if (x->cp != gData->cpend && *x->cp == matchCh) { - result = x; - result->cp++; - } - break; - case REOP_FLATi: - pc = ReadCompactIndex(pc, &offset); - JS_ASSERT(offset < JSSTRING_LENGTH(gData->regexp->source)); - pc = ReadCompactIndex(pc, &length); - JS_ASSERT(1 <= length); - JS_ASSERT(length <= JSSTRING_LENGTH(gData->regexp->source) - offset); - source = JSSTRING_CHARS(gData->regexp->source); - result = FlatNIMatcher(gData, x, source + offset, length); - break; - case REOP_FLAT1i: - matchCh = *pc++; - if (x->cp != gData->cpend && upcase(*x->cp) == upcase(matchCh)) { - result = x; - result->cp++; - } - break; - case REOP_UCFLAT1: - matchCh = GET_ARG(pc); - pc += ARG_LEN; - if (x->cp != gData->cpend && *x->cp == matchCh) { - result = x; - result->cp++; - } - break; - case REOP_UCFLAT1i: - matchCh = GET_ARG(pc); - pc += ARG_LEN; - if (x->cp != gData->cpend && upcase(*x->cp) == upcase(matchCh)) { - result = x; - result->cp++; - } - break; - case REOP_CLASS: - pc = ReadCompactIndex(pc, &index); - JS_ASSERT(index < gData->regexp->classCount); - if (x->cp != gData->cpend) { - charSet = &gData->regexp->classList[index]; - JS_ASSERT(charSet->converted); - ch = *x->cp; - index = ch >> 3; - if (charSet->length != 0 && - ch <= charSet->length && - (charSet->u.bits[index] & (1 << (ch & 0x7)))) { - result = x; - result->cp++; - } - } - break; - case REOP_NCLASS: - pc = ReadCompactIndex(pc, &index); - JS_ASSERT(index < gData->regexp->classCount); - if (x->cp != gData->cpend) { - charSet = &gData->regexp->classList[index]; - JS_ASSERT(charSet->converted); - ch = *x->cp; - index = ch >> 3; - if (charSet->length == 0 || - ch > charSet->length || - !(charSet->u.bits[index] & (1 << (ch & 0x7)))) { - result = x; - result->cp++; - } - } - break; - default: - JS_ASSERT(JS_FALSE); - } - if (result) { - if (update) - *startpc = pc; - else - x->cp = startcp; - return result; - } - x->cp = startcp; - return NULL; -} - -static REMatchState * -ExecuteREBytecode(REGlobalData *gData, REMatchState *x) -{ - REMatchState *result = NULL; - REBackTrackData *backTrackData; - jsbytecode *nextpc; - REOp nextop; - RECapture *cap; - REProgState *curState; - const jschar *startcp; - size_t parenIndex, k; - size_t parenSoFar = 0; - - jschar matchCh1, matchCh2; - RECharSet *charSet; - - JSBool anchor; - jsbytecode *pc = gData->regexp->program; - REOp op = (REOp) *pc++; - - /* - * If the first node is a simple match, step the index into the string - * until that match is made, or fail if it can't be found at all. - */ - if (REOP_IS_SIMPLE(op)) { - anchor = JS_FALSE; - while (x->cp <= gData->cpend) { - nextpc = pc; /* reset back to start each time */ - result = SimpleMatch(gData, x, op, &nextpc, JS_TRUE); - if (result) { - anchor = JS_TRUE; - x = result; - pc = nextpc; /* accept skip to next opcode */ - op = (REOp) *pc++; - break; - } - gData->skipped++; - x->cp++; - } - if (!anchor) - return NULL; - } - - for (;;) { - if (REOP_IS_SIMPLE(op)) { - result = SimpleMatch(gData, x, op, &pc, JS_TRUE); - } else { - curState = &gData->stateStack[gData->stateStackTop]; - switch (op) { - case REOP_EMPTY: - result = x; - break; - - case REOP_ALTPREREQ2: - nextpc = pc + GET_OFFSET(pc); /* start of next op */ - pc += ARG_LEN; - matchCh2 = GET_ARG(pc); - pc += ARG_LEN; - k = GET_ARG(pc); - pc += ARG_LEN; - - if (x->cp != gData->cpend) { - if (*x->cp == matchCh2) - goto doAlt; - - charSet = &gData->regexp->classList[k]; - if (!charSet->converted) - if (!ProcessCharSet(gData, charSet)) - return NULL; - matchCh1 = *x->cp; - k = matchCh1 >> 3; - if ((charSet->length == 0 || - matchCh1 > charSet->length || - !(charSet->u.bits[k] & (1 << (matchCh1 & 0x7)))) ^ - charSet->sense) { - goto doAlt; - } - } - result = NULL; - break; - - case REOP_ALTPREREQ: - nextpc = pc + GET_OFFSET(pc); /* start of next op */ - pc += ARG_LEN; - matchCh1 = GET_ARG(pc); - pc += ARG_LEN; - matchCh2 = GET_ARG(pc); - pc += ARG_LEN; - if (x->cp == gData->cpend || - (*x->cp != matchCh1 && *x->cp != matchCh2)) { - result = NULL; - break; - } - /* else false thru... */ - - case REOP_ALT: - doAlt: - nextpc = pc + GET_OFFSET(pc); /* start of next alternate */ - pc += ARG_LEN; /* start of this alternate */ - curState->parenSoFar = parenSoFar; - PUSH_STATE_STACK(gData); - op = (REOp) *pc++; - startcp = x->cp; - if (REOP_IS_SIMPLE(op)) { - if (!SimpleMatch(gData, x, op, &pc, JS_TRUE)) { - op = (REOp) *nextpc++; - pc = nextpc; - continue; - } - result = x; - op = (REOp) *pc++; - } - nextop = (REOp) *nextpc++; - if (!PushBackTrackState(gData, nextop, nextpc, x, startcp, 0, 0)) - return NULL; - continue; - - /* - * Occurs at (succesful) end of REOP_ALT, - */ - case REOP_JUMP: - --gData->stateStackTop; - pc += GET_OFFSET(pc); - op = (REOp) *pc++; - continue; - - /* - * Occurs at last (succesful) end of REOP_ALT, - */ - case REOP_ENDALT: - --gData->stateStackTop; - op = (REOp) *pc++; - continue; - - case REOP_LPAREN: - pc = ReadCompactIndex(pc, &parenIndex); - JS_ASSERT(parenIndex < gData->regexp->parenCount); - if (parenIndex + 1 > parenSoFar) - parenSoFar = parenIndex + 1; - x->parens[parenIndex].index = x->cp - gData->cpbegin; - x->parens[parenIndex].length = 0; - op = (REOp) *pc++; - continue; - - case REOP_RPAREN: - pc = ReadCompactIndex(pc, &parenIndex); - JS_ASSERT(parenIndex < gData->regexp->parenCount); - cap = &x->parens[parenIndex]; - - /* - * FIXME: https://bugzilla.mozilla.org/show_bug.cgi?id=346090 - * This wallpaper prevents a case where we somehow took a step - * backward in input while minimally-matching an empty string. - */ - if (x->cp < gData->cpbegin + cap->index) - cap->index = -1; - cap->length = x->cp - (gData->cpbegin + cap->index); - op = (REOp) *pc++; - continue; - - case REOP_ASSERT: - nextpc = pc + GET_OFFSET(pc); /* start of term after ASSERT */ - pc += ARG_LEN; /* start of ASSERT child */ - op = (REOp) *pc++; - if (REOP_IS_SIMPLE(op) && - !SimpleMatch(gData, x, op, &pc, JS_FALSE)) { - result = NULL; - break; - } - curState->u.assertion.top = - (char *)gData->backTrackSP - (char *)gData->backTrackStack; - curState->u.assertion.sz = gData->cursz; - curState->index = x->cp - gData->cpbegin; - curState->parenSoFar = parenSoFar; - PUSH_STATE_STACK(gData); - if (!PushBackTrackState(gData, REOP_ASSERTTEST, - nextpc, x, x->cp, 0, 0)) { - return NULL; - } - continue; - - case REOP_ASSERT_NOT: - nextpc = pc + GET_OFFSET(pc); - pc += ARG_LEN; - op = (REOp) *pc++; - if (REOP_IS_SIMPLE(op) /* Note - fail to fail! */ && - SimpleMatch(gData, x, op, &pc, JS_FALSE) && - pc == nextpc) { - result = NULL; - break; - } - curState->u.assertion.top - = (char *)gData->backTrackSP - - (char *)gData->backTrackStack; - curState->u.assertion.sz = gData->cursz; - curState->index = x->cp - gData->cpbegin; - curState->parenSoFar = parenSoFar; - PUSH_STATE_STACK(gData); - if (!PushBackTrackState(gData, REOP_ASSERTNOTTEST, - nextpc, x, x->cp, 0, 0)) - return NULL; - continue; - - case REOP_ASSERTTEST: - --gData->stateStackTop; - --curState; - x->cp = gData->cpbegin + curState->index; - gData->backTrackSP = - (REBackTrackData *) ((char *)gData->backTrackStack + - curState->u.assertion.top); - gData->cursz = curState->u.assertion.sz; - if (result) - result = x; - break; - - case REOP_ASSERTNOTTEST: - --gData->stateStackTop; - --curState; - x->cp = gData->cpbegin + curState->index; - gData->backTrackSP = - (REBackTrackData *) ((char *)gData->backTrackStack + - curState->u.assertion.top); - gData->cursz = curState->u.assertion.sz; - result = (!result) ? x : NULL; - break; - - case REOP_END: - if (x) - return x; - break; - - case REOP_STAR: - curState->u.quantifier.min = 0; - curState->u.quantifier.max = (uintN)-1; - goto quantcommon; - case REOP_PLUS: - curState->u.quantifier.min = 1; - curState->u.quantifier.max = (uintN)-1; - goto quantcommon; - case REOP_OPT: - curState->u.quantifier.min = 0; - curState->u.quantifier.max = 1; - goto quantcommon; - case REOP_QUANT: - pc = ReadCompactIndex(pc, &k); - curState->u.quantifier.min = k; - pc = ReadCompactIndex(pc, &k); - /* max is k - 1 to use one byte for (uintN)-1 sentinel. */ - curState->u.quantifier.max = k - 1; - JS_ASSERT(curState->u.quantifier.min - <= curState->u.quantifier.max); - quantcommon: - if (curState->u.quantifier.max == 0) { - pc = pc + GET_OFFSET(pc); - op = (REOp) *pc++; - result = x; - continue; - } - /* Step over */ - nextpc = pc + ARG_LEN; - op = (REOp) *nextpc++; - startcp = x->cp; - if (REOP_IS_SIMPLE(op)) { - if (!SimpleMatch(gData, x, op, &nextpc, JS_TRUE)) { - if (curState->u.quantifier.min == 0) - result = x; - else - result = NULL; - pc = pc + GET_OFFSET(pc); - break; - } - op = (REOp) *nextpc++; - result = x; - } - curState->index = startcp - gData->cpbegin; - curState->continue_op = REOP_REPEAT; - curState->continue_pc = pc; - curState->parenSoFar = parenSoFar; - PUSH_STATE_STACK(gData); - if (curState->u.quantifier.min == 0 && - !PushBackTrackState(gData, REOP_REPEAT, pc, x, startcp, - 0, 0)) { - return NULL; - } - pc = nextpc; - continue; - - case REOP_ENDCHILD: /* marks the end of a quantifier child */ - pc = curState[-1].continue_pc; - op = curState[-1].continue_op; - continue; - - case REOP_REPEAT: - --curState; - do { - --gData->stateStackTop; - if (!result) { - /* Failed, see if we have enough children. */ - if (curState->u.quantifier.min == 0) - goto repeatDone; - goto break_switch; - } - if (curState->u.quantifier.min == 0 && - x->cp == gData->cpbegin + curState->index) { - /* matched an empty string, that'll get us nowhere */ - result = NULL; - goto break_switch; - } - if (curState->u.quantifier.min != 0) - curState->u.quantifier.min--; - if (curState->u.quantifier.max != (uintN) -1) - curState->u.quantifier.max--; - if (curState->u.quantifier.max == 0) - goto repeatDone; - nextpc = pc + ARG_LEN; - nextop = (REOp) *nextpc; - startcp = x->cp; - if (REOP_IS_SIMPLE(nextop)) { - nextpc++; - if (!SimpleMatch(gData, x, nextop, &nextpc, JS_TRUE)) { - if (curState->u.quantifier.min == 0) - goto repeatDone; - result = NULL; - goto break_switch; - } - result = x; - } - curState->index = startcp - gData->cpbegin; - PUSH_STATE_STACK(gData); - if (curState->u.quantifier.min == 0 && - !PushBackTrackState(gData, REOP_REPEAT, - pc, x, startcp, - curState->parenSoFar, - parenSoFar - - curState->parenSoFar)) { - return NULL; - } - } while (*nextpc == REOP_ENDCHILD); - pc = nextpc; - op = (REOp) *pc++; - parenSoFar = curState->parenSoFar; - continue; - - repeatDone: - result = x; - pc += GET_OFFSET(pc); - goto break_switch; - - case REOP_MINIMALSTAR: - curState->u.quantifier.min = 0; - curState->u.quantifier.max = (uintN)-1; - goto minimalquantcommon; - case REOP_MINIMALPLUS: - curState->u.quantifier.min = 1; - curState->u.quantifier.max = (uintN)-1; - goto minimalquantcommon; - case REOP_MINIMALOPT: - curState->u.quantifier.min = 0; - curState->u.quantifier.max = 1; - goto minimalquantcommon; - case REOP_MINIMALQUANT: - pc = ReadCompactIndex(pc, &k); - curState->u.quantifier.min = k; - pc = ReadCompactIndex(pc, &k); - /* See REOP_QUANT comments about k - 1. */ - curState->u.quantifier.max = k - 1; - JS_ASSERT(curState->u.quantifier.min - <= curState->u.quantifier.max); - minimalquantcommon: - curState->index = x->cp - gData->cpbegin; - curState->parenSoFar = parenSoFar; - PUSH_STATE_STACK(gData); - if (curState->u.quantifier.min != 0) { - curState->continue_op = REOP_MINIMALREPEAT; - curState->continue_pc = pc; - /* step over */ - pc += OFFSET_LEN; - op = (REOp) *pc++; - } else { - if (!PushBackTrackState(gData, REOP_MINIMALREPEAT, - pc, x, x->cp, 0, 0)) { - return NULL; - } - --gData->stateStackTop; - pc = pc + GET_OFFSET(pc); - op = (REOp) *pc++; - } - continue; - - case REOP_MINIMALREPEAT: - --gData->stateStackTop; - --curState; - - if (!result) { - /* - * Non-greedy failure - try to consume another child. - */ - if (curState->u.quantifier.max == (uintN) -1 || - curState->u.quantifier.max > 0) { - curState->index = x->cp - gData->cpbegin; - curState->continue_op = REOP_MINIMALREPEAT; - curState->continue_pc = pc; - pc += ARG_LEN; - for (k = curState->parenSoFar; k < parenSoFar; k++) - x->parens[k].index = -1; - PUSH_STATE_STACK(gData); - op = (REOp) *pc++; - continue; - } - /* Don't need to adjust pc since we're going to pop. */ - break; - } - if (curState->u.quantifier.min == 0 && - x->cp == gData->cpbegin + curState->index) { - /* Matched an empty string, that'll get us nowhere. */ - result = NULL; - break; - } - if (curState->u.quantifier.min != 0) - curState->u.quantifier.min--; - if (curState->u.quantifier.max != (uintN) -1) - curState->u.quantifier.max--; - if (curState->u.quantifier.min != 0) { - curState->continue_op = REOP_MINIMALREPEAT; - curState->continue_pc = pc; - pc += ARG_LEN; - for (k = curState->parenSoFar; k < parenSoFar; k++) - x->parens[k].index = -1; - curState->index = x->cp - gData->cpbegin; - PUSH_STATE_STACK(gData); - op = (REOp) *pc++; - continue; - } - curState->index = x->cp - gData->cpbegin; - curState->parenSoFar = parenSoFar; - PUSH_STATE_STACK(gData); - if (!PushBackTrackState(gData, REOP_MINIMALREPEAT, - pc, x, x->cp, - curState->parenSoFar, - parenSoFar - curState->parenSoFar)) { - return NULL; - } - --gData->stateStackTop; - pc = pc + GET_OFFSET(pc); - op = (REOp) *pc++; - continue; - - default: - JS_ASSERT(JS_FALSE); - result = NULL; - } - break_switch:; - } - - /* - * If the match failed and there's a backtrack option, take it. - * Otherwise this is a complete and utter failure. - */ - if (!result) { - if (gData->cursz == 0) - return NULL; - backTrackData = gData->backTrackSP; - gData->cursz = backTrackData->sz; - gData->backTrackSP = - (REBackTrackData *) ((char *)backTrackData - backTrackData->sz); - x->cp = backTrackData->cp; - pc = backTrackData->backtrack_pc; - op = backTrackData->backtrack_op; - gData->stateStackTop = backTrackData->saveStateStackTop; - JS_ASSERT(gData->stateStackTop); - - memcpy(gData->stateStack, backTrackData + 1, - sizeof(REProgState) * backTrackData->saveStateStackTop); - curState = &gData->stateStack[gData->stateStackTop - 1]; - - if (backTrackData->parenCount) { - memcpy(&x->parens[backTrackData->parenIndex], - (char *)(backTrackData + 1) + - sizeof(REProgState) * backTrackData->saveStateStackTop, - sizeof(RECapture) * backTrackData->parenCount); - parenSoFar = backTrackData->parenIndex + backTrackData->parenCount; - } else { - for (k = curState->parenSoFar; k < parenSoFar; k++) - x->parens[k].index = -1; - parenSoFar = curState->parenSoFar; - } - continue; - } - x = result; - - /* - * Continue with the expression. - */ - op = (REOp)*pc++; - } - return NULL; -} - -static REMatchState * -MatchRegExp(REGlobalData *gData, REMatchState *x) -{ - REMatchState *result; - const jschar *cp = x->cp; - const jschar *cp2; - uintN j; - - /* - * Have to include the position beyond the last character - * in order to detect end-of-input/line condition. - */ - for (cp2 = cp; cp2 <= gData->cpend; cp2++) { - gData->skipped = cp2 - cp; - x->cp = cp2; - for (j = 0; j < gData->regexp->parenCount; j++) - x->parens[j].index = -1; - result = ExecuteREBytecode(gData, x); - if (!gData->ok || result) - return result; - gData->backTrackSP = gData->backTrackStack; - gData->cursz = 0; - gData->stateStackTop = 0; - cp2 = cp + gData->skipped; - } - return NULL; -} - - -static REMatchState * -InitMatch(JSContext *cx, REGlobalData *gData, JSRegExp *re) -{ - REMatchState *result; - uintN i; - - gData->backTrackStackSize = INITIAL_BACKTRACK; - JS_ARENA_ALLOCATE_CAST(gData->backTrackStack, REBackTrackData *, - &gData->pool, - INITIAL_BACKTRACK); - if (!gData->backTrackStack) - return NULL; - gData->backTrackSP = gData->backTrackStack; - gData->cursz = 0; - - - gData->stateStackLimit = INITIAL_STATESTACK; - JS_ARENA_ALLOCATE_CAST(gData->stateStack, REProgState *, - &gData->pool, - sizeof(REProgState) * INITIAL_STATESTACK); - if (!gData->stateStack) - return NULL; - gData->stateStackTop = 0; - - gData->cx = cx; - gData->regexp = re; - gData->ok = JS_TRUE; - - JS_ARENA_ALLOCATE_CAST(result, REMatchState *, - &gData->pool, - offsetof(REMatchState, parens) - + re->parenCount * sizeof(RECapture)); - if (!result) - return NULL; - - for (i = 0; i < re->classCount; i++) - if (!re->classList[i].converted) - if (!ProcessCharSet(gData, &re->classList[i])) - return NULL; - - return result; -} - -JSBool -js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp, - JSBool test, jsval *rval) -{ - REGlobalData gData; - REMatchState *x, *result; - - const jschar *cp, *ep; - size_t i, length, start; - JSSubString *morepar; - JSBool ok; - JSRegExpStatics *res; - ptrdiff_t matchlen; - uintN num, morenum; - JSString *parstr, *matchstr; - JSObject *obj; - - RECapture *parsub = NULL; - - /* - * It's safe to load from cp because JSStrings have a zero at the end, - * and we never let cp get beyond cpend. - */ - start = *indexp; - length = JSSTRING_LENGTH(str); - if (start > length) - start = length; - cp = JSSTRING_CHARS(str); - gData.cpbegin = cp; - gData.cpend = cp + length; - cp += start; - gData.start = start; - gData.skipped = 0; - - JS_InitArenaPool(&gData.pool, "RegExpPool", 8096, 4); - x = InitMatch(cx, &gData, re); - if (!x) - return JS_FALSE; - x->cp = cp; - - /* - * Call the recursive matcher to do the real work. Return null on mismatch - * whether testing or not. On match, return an extended Array object. - */ - result = MatchRegExp(&gData, x); - ok = gData.ok; - if (!ok) - goto out; - if (!result) { - *rval = JSVAL_NULL; - goto out; - } - cp = result->cp; - i = cp - gData.cpbegin; - *indexp = i; - matchlen = i - (start + gData.skipped); - ep = cp; - cp -= matchlen; - - if (test) { - /* - * Testing for a match and updating cx->regExpStatics: don't allocate - * an array object, do return true. - */ - *rval = JSVAL_TRUE; - - /* Avoid warning. (gcc doesn't detect that obj is needed iff !test); */ - obj = NULL; - } else { - /* - * The array returned on match has element 0 bound to the matched - * string, elements 1 through state.parenCount bound to the paren - * matches, an index property telling the length of the left context, - * and an input property referring to the input string. - */ - obj = js_NewArrayObject(cx, 0, NULL); - if (!obj) { - ok = JS_FALSE; - goto out; - } - *rval = OBJECT_TO_JSVAL(obj); - -#define DEFVAL(val, id) { \ - ok = js_DefineProperty(cx, obj, id, val, \ - JS_PropertyStub, JS_PropertyStub, \ - JSPROP_ENUMERATE, NULL); \ - if (!ok) { \ - cx->newborn[GCX_OBJECT] = NULL; \ - cx->newborn[GCX_STRING] = NULL; \ - goto out; \ - } \ -} - - matchstr = js_NewStringCopyN(cx, cp, matchlen, 0); - if (!matchstr) { - cx->newborn[GCX_OBJECT] = NULL; - ok = JS_FALSE; - goto out; - } - DEFVAL(STRING_TO_JSVAL(matchstr), INT_TO_JSID(0)); - } - - res = &cx->regExpStatics; - res->input = str; - res->parenCount = re->parenCount; - if (re->parenCount == 0) { - res->lastParen = js_EmptySubString; - } else { - for (num = 0; num < re->parenCount; num++) { - parsub = &result->parens[num]; - if (num < 9) { - if (parsub->index == -1) { - res->parens[num].chars = NULL; - res->parens[num].length = 0; - } else { - res->parens[num].chars = gData.cpbegin + parsub->index; - res->parens[num].length = parsub->length; - } - } else { - morenum = num - 9; - morepar = res->moreParens; - if (!morepar) { - res->moreLength = 10; - morepar = (JSSubString*) - JS_malloc(cx, 10 * sizeof(JSSubString)); - } else if (morenum >= res->moreLength) { - res->moreLength += 10; - morepar = (JSSubString*) - JS_realloc(cx, morepar, - res->moreLength * sizeof(JSSubString)); - } - if (!morepar) { - cx->newborn[GCX_OBJECT] = NULL; - cx->newborn[GCX_STRING] = NULL; - ok = JS_FALSE; - goto out; - } - res->moreParens = morepar; - if (parsub->index == -1) { - morepar[morenum].chars = NULL; - morepar[morenum].length = 0; - } else { - morepar[morenum].chars = gData.cpbegin + parsub->index; - morepar[morenum].length = parsub->length; - } - } - if (test) - continue; - if (parsub->index == -1) { - ok = js_DefineProperty(cx, obj, INT_TO_JSID(num + 1), - JSVAL_VOID, NULL, NULL, - JSPROP_ENUMERATE, NULL); - } else { - parstr = js_NewStringCopyN(cx, gData.cpbegin + parsub->index, - parsub->length, 0); - if (!parstr) { - cx->newborn[GCX_OBJECT] = NULL; - cx->newborn[GCX_STRING] = NULL; - ok = JS_FALSE; - goto out; - } - ok = js_DefineProperty(cx, obj, INT_TO_JSID(num + 1), - STRING_TO_JSVAL(parstr), NULL, NULL, - JSPROP_ENUMERATE, NULL); - } - if (!ok) { - cx->newborn[GCX_OBJECT] = NULL; - cx->newborn[GCX_STRING] = NULL; - goto out; - } - } - if (parsub->index == -1) { - res->lastParen = js_EmptySubString; - } else { - res->lastParen.chars = gData.cpbegin + parsub->index; - res->lastParen.length = parsub->length; - } - } - - if (!test) { - /* - * Define the index and input properties last for better for/in loop - * order (so they come after the elements). - */ - DEFVAL(INT_TO_JSVAL(start + gData.skipped), - ATOM_TO_JSID(cx->runtime->atomState.indexAtom)); - DEFVAL(STRING_TO_JSVAL(str), - ATOM_TO_JSID(cx->runtime->atomState.inputAtom)); - } - -#undef DEFVAL - - res->lastMatch.chars = cp; - res->lastMatch.length = matchlen; - if (JS_VERSION_IS_1_2(cx)) { - /* - * JS1.2 emulated Perl4.0.1.8 (patch level 36) for global regexps used - * in scalar contexts, and unintentionally for the string.match "list" - * pseudo-context. On "hi there bye", the following would result: - * - * Language while(/ /g){print("$`");} s/ /$`/g - * perl4.036 "hi", "there" "hihitherehi therebye" - * perl5 "hi", "hi there" "hihitherehi therebye" - * js1.2 "hi", "there" "hihitheretherebye" - */ - res->leftContext.chars = JSSTRING_CHARS(str) + start; - res->leftContext.length = gData.skipped; - } else { - /* - * For JS1.3 and ECMAv2, emulate Perl5 exactly: - * - * js1.3 "hi", "hi there" "hihitherehi therebye" - */ - res->leftContext.chars = JSSTRING_CHARS(str); - res->leftContext.length = start + gData.skipped; - } - res->rightContext.chars = ep; - res->rightContext.length = gData.cpend - ep; - -out: - JS_FinishArenaPool(&gData.pool); - return ok; -} - -/************************************************************************/ - -enum regexp_tinyid { - REGEXP_SOURCE = -1, - REGEXP_GLOBAL = -2, - REGEXP_IGNORE_CASE = -3, - REGEXP_LAST_INDEX = -4, - REGEXP_MULTILINE = -5 -}; - -#define REGEXP_PROP_ATTRS (JSPROP_PERMANENT|JSPROP_SHARED) - -static JSPropertySpec regexp_props[] = { - {"source", REGEXP_SOURCE, REGEXP_PROP_ATTRS | JSPROP_READONLY,0,0}, - {"global", REGEXP_GLOBAL, REGEXP_PROP_ATTRS | JSPROP_READONLY,0,0}, - {"ignoreCase", REGEXP_IGNORE_CASE, REGEXP_PROP_ATTRS | JSPROP_READONLY,0,0}, - {"lastIndex", REGEXP_LAST_INDEX, REGEXP_PROP_ATTRS,0,0}, - {"multiline", REGEXP_MULTILINE, REGEXP_PROP_ATTRS | JSPROP_READONLY,0,0}, - {0,0,0,0,0} -}; - -static JSBool -regexp_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - jsint slot; - JSRegExp *re; - - if (!JSVAL_IS_INT(id)) - return JS_TRUE; - slot = JSVAL_TO_INT(id); - if (slot == REGEXP_LAST_INDEX) - return JS_GetReservedSlot(cx, obj, 0, vp); - - JS_LOCK_OBJ(cx, obj); - re = (JSRegExp *) JS_GetInstancePrivate(cx, obj, &js_RegExpClass, NULL); - if (re) { - switch (slot) { - case REGEXP_SOURCE: - *vp = STRING_TO_JSVAL(re->source); - break; - case REGEXP_GLOBAL: - *vp = BOOLEAN_TO_JSVAL((re->flags & JSREG_GLOB) != 0); - break; - case REGEXP_IGNORE_CASE: - *vp = BOOLEAN_TO_JSVAL((re->flags & JSREG_FOLD) != 0); - break; - case REGEXP_MULTILINE: - *vp = BOOLEAN_TO_JSVAL((re->flags & JSREG_MULTILINE) != 0); - break; - } - } - JS_UNLOCK_OBJ(cx, obj); - return JS_TRUE; -} - -static JSBool -regexp_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - JSBool ok; - jsint slot; - jsdouble lastIndex; - - ok = JS_TRUE; - if (!JSVAL_IS_INT(id)) - return ok; - slot = JSVAL_TO_INT(id); - if (slot == REGEXP_LAST_INDEX) { - if (!js_ValueToNumber(cx, *vp, &lastIndex)) - return JS_FALSE; - lastIndex = js_DoubleToInteger(lastIndex); - ok = js_NewNumberValue(cx, lastIndex, vp) && - JS_SetReservedSlot(cx, obj, 0, *vp); - } - return ok; -} - -/* - * RegExp class static properties and their Perl counterparts: - * - * RegExp.input $_ - * RegExp.multiline $* - * RegExp.lastMatch $& - * RegExp.lastParen $+ - * RegExp.leftContext $` - * RegExp.rightContext $' - */ -enum regexp_static_tinyid { - REGEXP_STATIC_INPUT = -1, - REGEXP_STATIC_MULTILINE = -2, - REGEXP_STATIC_LAST_MATCH = -3, - REGEXP_STATIC_LAST_PAREN = -4, - REGEXP_STATIC_LEFT_CONTEXT = -5, - REGEXP_STATIC_RIGHT_CONTEXT = -6 -}; - -JSBool -js_InitRegExpStatics(JSContext *cx, JSRegExpStatics *res) -{ - JS_ClearRegExpStatics(cx); - return js_AddRoot(cx, &res->input, "res->input"); -} - -void -js_FreeRegExpStatics(JSContext *cx, JSRegExpStatics *res) -{ - if (res->moreParens) { - JS_free(cx, res->moreParens); - res->moreParens = NULL; - } - js_RemoveRoot(cx->runtime, &res->input); -} - -static JSBool -regexp_static_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - jsint slot; - JSRegExpStatics *res; - JSString *str; - JSSubString *sub; - - res = &cx->regExpStatics; - if (!JSVAL_IS_INT(id)) - return JS_TRUE; - slot = JSVAL_TO_INT(id); - switch (slot) { - case REGEXP_STATIC_INPUT: - *vp = res->input ? STRING_TO_JSVAL(res->input) - : JS_GetEmptyStringValue(cx); - return JS_TRUE; - case REGEXP_STATIC_MULTILINE: - *vp = BOOLEAN_TO_JSVAL(res->multiline); - return JS_TRUE; - case REGEXP_STATIC_LAST_MATCH: - sub = &res->lastMatch; - break; - case REGEXP_STATIC_LAST_PAREN: - sub = &res->lastParen; - break; - case REGEXP_STATIC_LEFT_CONTEXT: - sub = &res->leftContext; - break; - case REGEXP_STATIC_RIGHT_CONTEXT: - sub = &res->rightContext; - break; - default: - sub = REGEXP_PAREN_SUBSTRING(res, slot); - break; - } - str = js_NewStringCopyN(cx, sub->chars, sub->length, 0); - if (!str) - return JS_FALSE; - *vp = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -static JSBool -regexp_static_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - JSRegExpStatics *res; - - if (!JSVAL_IS_INT(id)) - return JS_TRUE; - res = &cx->regExpStatics; - /* XXX use if-else rather than switch to keep MSVC1.52 from crashing */ - if (JSVAL_TO_INT(id) == REGEXP_STATIC_INPUT) { - if (!JSVAL_IS_STRING(*vp) && - !JS_ConvertValue(cx, *vp, JSTYPE_STRING, vp)) { - return JS_FALSE; - } - res->input = JSVAL_TO_STRING(*vp); - } else if (JSVAL_TO_INT(id) == REGEXP_STATIC_MULTILINE) { - if (!JSVAL_IS_BOOLEAN(*vp) && - !JS_ConvertValue(cx, *vp, JSTYPE_BOOLEAN, vp)) { - return JS_FALSE; - } - res->multiline = JSVAL_TO_BOOLEAN(*vp); - } - return JS_TRUE; -} - -static JSPropertySpec regexp_static_props[] = { - {"input", - REGEXP_STATIC_INPUT, - JSPROP_ENUMERATE|JSPROP_SHARED, - regexp_static_getProperty, regexp_static_setProperty}, - {"multiline", - REGEXP_STATIC_MULTILINE, - JSPROP_ENUMERATE|JSPROP_SHARED, - regexp_static_getProperty, regexp_static_setProperty}, - {"lastMatch", - REGEXP_STATIC_LAST_MATCH, - JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_SHARED, - regexp_static_getProperty, regexp_static_getProperty}, - {"lastParen", - REGEXP_STATIC_LAST_PAREN, - JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_SHARED, - regexp_static_getProperty, regexp_static_getProperty}, - {"leftContext", - REGEXP_STATIC_LEFT_CONTEXT, - JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_SHARED, - regexp_static_getProperty, regexp_static_getProperty}, - {"rightContext", - REGEXP_STATIC_RIGHT_CONTEXT, - JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_SHARED, - regexp_static_getProperty, regexp_static_getProperty}, - - /* XXX should have block scope and local $1, etc. */ - {"$1", 0, JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_SHARED, - regexp_static_getProperty, regexp_static_getProperty}, - {"$2", 1, JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_SHARED, - regexp_static_getProperty, regexp_static_getProperty}, - {"$3", 2, JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_SHARED, - regexp_static_getProperty, regexp_static_getProperty}, - {"$4", 3, JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_SHARED, - regexp_static_getProperty, regexp_static_getProperty}, - {"$5", 4, JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_SHARED, - regexp_static_getProperty, regexp_static_getProperty}, - {"$6", 5, JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_SHARED, - regexp_static_getProperty, regexp_static_getProperty}, - {"$7", 6, JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_SHARED, - regexp_static_getProperty, regexp_static_getProperty}, - {"$8", 7, JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_SHARED, - regexp_static_getProperty, regexp_static_getProperty}, - {"$9", 8, JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_SHARED, - regexp_static_getProperty, regexp_static_getProperty}, - - {0,0,0,0,0} -}; - -static void -regexp_finalize(JSContext *cx, JSObject *obj) -{ - JSRegExp *re; - - re = (JSRegExp *) JS_GetPrivate(cx, obj); - if (!re) - return; - js_DestroyRegExp(cx, re); -} - -/* Forward static prototype. */ -static JSBool -regexp_exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval); - -static JSBool -regexp_call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - return regexp_exec(cx, JSVAL_TO_OBJECT(argv[-2]), argc, argv, rval); -} - -#if JS_HAS_XDR - -#include "jsxdrapi.h" - -static JSBool -regexp_xdrObject(JSXDRState *xdr, JSObject **objp) -{ - JSRegExp *re; - JSString *source; - uint32 flagsword; - JSObject *obj; - - if (xdr->mode == JSXDR_ENCODE) { - re = (JSRegExp *) JS_GetPrivate(xdr->cx, *objp); - if (!re) - return JS_FALSE; - source = re->source; - flagsword = ((uint32)re->cloneIndex << 16) | re->flags; - } - if (!JS_XDRString(xdr, &source) || - !JS_XDRUint32(xdr, &flagsword)) { - return JS_FALSE; - } - if (xdr->mode == JSXDR_DECODE) { - obj = js_NewObject(xdr->cx, &js_RegExpClass, NULL, NULL); - if (!obj) - return JS_FALSE; - re = js_NewRegExp(xdr->cx, NULL, source, (uint16)flagsword, JS_FALSE); - if (!re) - return JS_FALSE; - if (!JS_SetPrivate(xdr->cx, obj, re) || - !js_SetLastIndex(xdr->cx, obj, 0)) { - js_DestroyRegExp(xdr->cx, re); - return JS_FALSE; - } - re->cloneIndex = (uint16)(flagsword >> 16); - *objp = obj; - } - return JS_TRUE; -} - -#else /* !JS_HAS_XDR */ - -#define regexp_xdrObject NULL - -#endif /* !JS_HAS_XDR */ - -static uint32 -regexp_mark(JSContext *cx, JSObject *obj, void *arg) -{ - JSRegExp *re = (JSRegExp *) JS_GetPrivate(cx, obj); - if (re) - JS_MarkGCThing(cx, re->source, "source", arg); - return 0; -} - -JSClass js_RegExpClass = { - js_RegExp_str, - JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1), - JS_PropertyStub, JS_PropertyStub, - regexp_getProperty, regexp_setProperty, - JS_EnumerateStub, JS_ResolveStub, - JS_ConvertStub, regexp_finalize, - NULL, NULL, - regexp_call, NULL, - regexp_xdrObject, NULL, - regexp_mark, 0 -}; - -static const jschar empty_regexp_ucstr[] = {'(', '?', ':', ')', 0}; - -JSBool -js_regexp_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSRegExp *re; - const jschar *source; - jschar *chars; - size_t length, nflags; - uintN flags; - JSString *str; - - if (!JS_InstanceOf(cx, obj, &js_RegExpClass, argv)) - return JS_FALSE; - JS_LOCK_OBJ(cx, obj); - re = (JSRegExp *) JS_GetPrivate(cx, obj); - if (!re) { - JS_UNLOCK_OBJ(cx, obj); - *rval = STRING_TO_JSVAL(cx->runtime->emptyString); - return JS_TRUE; - } - - source = JSSTRING_CHARS(re->source); - length = JSSTRING_LENGTH(re->source); - if (length == 0) { - source = empty_regexp_ucstr; - length = sizeof(empty_regexp_ucstr) / sizeof(jschar) - 1; - } - length += 2; - nflags = 0; - for (flags = re->flags; flags != 0; flags &= flags - 1) - nflags++; - chars = (jschar*) JS_malloc(cx, (length + nflags + 1) * sizeof(jschar)); - if (!chars) { - JS_UNLOCK_OBJ(cx, obj); - return JS_FALSE; - } - - chars[0] = '/'; - js_strncpy(&chars[1], source, length - 2); - chars[length-1] = '/'; - if (nflags) { - if (re->flags & JSREG_GLOB) - chars[length++] = 'g'; - if (re->flags & JSREG_FOLD) - chars[length++] = 'i'; - if (re->flags & JSREG_MULTILINE) - chars[length++] = 'm'; - } - JS_UNLOCK_OBJ(cx, obj); - chars[length] = 0; - - str = js_NewString(cx, chars, length, 0); - if (!str) { - JS_free(cx, chars); - return JS_FALSE; - } - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -static JSBool -regexp_compile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSString *opt, *str; - JSRegExp *oldre, *re; - JSBool ok, ok2; - JSObject *obj2; - size_t length, nbytes; - const jschar *cp, *start, *end; - jschar *nstart, *ncp, *tmp; - - if (!JS_InstanceOf(cx, obj, &js_RegExpClass, argv)) - return JS_FALSE; - opt = NULL; - if (argc == 0) { - str = cx->runtime->emptyString; - } else { - if (JSVAL_IS_OBJECT(argv[0])) { - /* - * If we get passed in a RegExp object we construct a new - * RegExp that is a duplicate of it by re-compiling the - * original source code. ECMA requires that it be an error - * here if the flags are specified. (We must use the flags - * from the original RegExp also). - */ - obj2 = JSVAL_TO_OBJECT(argv[0]); - if (obj2 && OBJ_GET_CLASS(cx, obj2) == &js_RegExpClass) { - if (argc >= 2 && !JSVAL_IS_VOID(argv[1])) { /* 'flags' passed */ - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_NEWREGEXP_FLAGGED); - return JS_FALSE; - } - JS_LOCK_OBJ(cx, obj2); - re = (JSRegExp *) JS_GetPrivate(cx, obj2); - if (!re) { - JS_UNLOCK_OBJ(cx, obj2); - return JS_FALSE; - } - re = js_NewRegExp(cx, NULL, re->source, re->flags, JS_FALSE); - JS_UNLOCK_OBJ(cx, obj2); - goto created; - } - } - str = js_ValueToString(cx, argv[0]); - if (!str) - return JS_FALSE; - argv[0] = STRING_TO_JSVAL(str); - if (argc > 1) { - if (JSVAL_IS_VOID(argv[1])) { - opt = NULL; - } else { - opt = js_ValueToString(cx, argv[1]); - if (!opt) - return JS_FALSE; - argv[1] = STRING_TO_JSVAL(opt); - } - } - - /* Escape any naked slashes in the regexp source. */ - length = JSSTRING_LENGTH(str); - start = JSSTRING_CHARS(str); - end = start + length; - nstart = ncp = NULL; - for (cp = start; cp < end; cp++) { - if (*cp == '/' && (cp == start || cp[-1] != '\\')) { - nbytes = (++length + 1) * sizeof(jschar); - if (!nstart) { - nstart = (jschar *) JS_malloc(cx, nbytes); - if (!nstart) - return JS_FALSE; - ncp = nstart + (cp - start); - js_strncpy(nstart, start, cp - start); - } else { - tmp = (jschar *) JS_realloc(cx, nstart, nbytes); - if (!tmp) { - JS_free(cx, nstart); - return JS_FALSE; - } - ncp = tmp + (ncp - nstart); - nstart = tmp; - } - *ncp++ = '\\'; - } - if (nstart) - *ncp++ = *cp; - } - - if (nstart) { - /* Don't forget to store the backstop after the new string. */ - JS_ASSERT((size_t)(ncp - nstart) == length); - *ncp = 0; - str = js_NewString(cx, nstart, length, 0); - if (!str) { - JS_free(cx, nstart); - return JS_FALSE; - } - argv[0] = STRING_TO_JSVAL(str); - } - } - - re = js_NewRegExpOpt(cx, NULL, str, opt, JS_FALSE); -created: - if (!re) - return JS_FALSE; - JS_LOCK_OBJ(cx, obj); - oldre = (JSRegExp *) JS_GetPrivate(cx, obj); - ok = JS_SetPrivate(cx, obj, re); - ok2 = js_SetLastIndex(cx, obj, 0); - JS_UNLOCK_OBJ(cx, obj); - if (!ok) { - js_DestroyRegExp(cx, re); - return JS_FALSE; - } - if (oldre) - js_DestroyRegExp(cx, oldre); - *rval = OBJECT_TO_JSVAL(obj); - return ok2; -} - -static JSBool -regexp_exec_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - JSBool test, jsval *rval) -{ - JSBool ok; - JSRegExp *re; - jsdouble lastIndex; - JSString *str; - size_t i; - - ok = JS_InstanceOf(cx, obj, &js_RegExpClass, argv); - if (!ok) - return JS_FALSE; - JS_LOCK_OBJ(cx, obj); - re = (JSRegExp *) JS_GetPrivate(cx, obj); - if (!re) { - JS_UNLOCK_OBJ(cx, obj); - return JS_TRUE; - } - - /* NB: we must reach out: after this paragraph, in order to drop re. */ - HOLD_REGEXP(cx, re); - if (re->flags & JSREG_GLOB) { - ok = js_GetLastIndex(cx, obj, &lastIndex); - } else { - lastIndex = 0; - } - JS_UNLOCK_OBJ(cx, obj); - if (!ok) - goto out; - - /* Now that obj is unlocked, it's safe to (potentially) grab the GC lock. */ - if (argc == 0) { - str = cx->regExpStatics.input; - if (!str) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_NO_INPUT, - JS_GetStringBytes(re->source), - (re->flags & JSREG_GLOB) ? "g" : "", - (re->flags & JSREG_FOLD) ? "i" : "", - (re->flags & JSREG_MULTILINE) ? "m" : ""); - ok = JS_FALSE; - goto out; - } - } else { - str = js_ValueToString(cx, argv[0]); - if (!str) - goto out; - argv[0] = STRING_TO_JSVAL(str); - } - - if (lastIndex < 0 || JSSTRING_LENGTH(str) < lastIndex) { - ok = js_SetLastIndex(cx, obj, 0); - *rval = JSVAL_NULL; - } else { - i = (size_t) lastIndex; - ok = js_ExecuteRegExp(cx, re, str, &i, test, rval); - if (ok && (re->flags & JSREG_GLOB)) - ok = js_SetLastIndex(cx, obj, (*rval == JSVAL_NULL) ? 0 : i); - } - -out: - DROP_REGEXP(cx, re); - return ok; -} - -static JSBool -regexp_exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - return regexp_exec_sub(cx, obj, argc, argv, JS_FALSE, rval); -} - -static JSBool -regexp_test(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - if (!regexp_exec_sub(cx, obj, argc, argv, JS_TRUE, rval)) - return JS_FALSE; - if (*rval != JSVAL_TRUE) - *rval = JSVAL_FALSE; - return JS_TRUE; -} - -static JSFunctionSpec regexp_methods[] = { -#if JS_HAS_TOSOURCE - {js_toSource_str, js_regexp_toString, 0,0,0}, -#endif - {js_toString_str, js_regexp_toString, 0,0,0}, - {"compile", regexp_compile, 1,0,0}, - {"exec", regexp_exec, 0,0,0}, - {"test", regexp_test, 0,0,0}, - {0,0,0,0,0} -}; - -static JSBool -RegExp(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) { - /* - * If first arg is regexp and no flags are given, just return the arg. - * (regexp_compile detects the regexp + flags case and throws a - * TypeError.) See 10.15.3.1. - */ - if ((argc < 2 || JSVAL_IS_VOID(argv[1])) && - !JSVAL_IS_PRIMITIVE(argv[0]) && - OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(argv[0])) == &js_RegExpClass) { - *rval = argv[0]; - return JS_TRUE; - } - - /* Otherwise, replace obj with a new RegExp object. */ - obj = js_NewObject(cx, &js_RegExpClass, NULL, NULL); - if (!obj) - return JS_FALSE; - - /* - * regexp_compile does not use rval to root its temporaries - * so we can use it to root obj. - */ - *rval = OBJECT_TO_JSVAL(obj); - } - return regexp_compile(cx, obj, argc, argv, rval); -} - -JSObject * -js_InitRegExpClass(JSContext *cx, JSObject *obj) -{ - JSObject *proto, *ctor; - jsval rval; - - proto = JS_InitClass(cx, obj, NULL, &js_RegExpClass, RegExp, 1, - regexp_props, regexp_methods, - regexp_static_props, NULL); - - if (!proto || !(ctor = JS_GetConstructor(cx, proto))) - return NULL; - if (!JS_AliasProperty(cx, ctor, "input", "$_") || - !JS_AliasProperty(cx, ctor, "multiline", "$*") || - !JS_AliasProperty(cx, ctor, "lastMatch", "$&") || - !JS_AliasProperty(cx, ctor, "lastParen", "$+") || - !JS_AliasProperty(cx, ctor, "leftContext", "$`") || - !JS_AliasProperty(cx, ctor, "rightContext", "$'")) { - goto bad; - } - - /* Give RegExp.prototype private data so it matches the empty string. */ - if (!regexp_compile(cx, proto, 0, NULL, &rval)) - goto bad; - return proto; - -bad: - JS_DeleteProperty(cx, obj, js_RegExpClass.name); - return NULL; -} - -JSObject * -js_NewRegExpObject(JSContext *cx, JSTokenStream *ts, - jschar *chars, size_t length, uintN flags) -{ - JSString *str; - JSObject *obj; - JSRegExp *re; - JSTempValueRooter tvr; - - str = js_NewStringCopyN(cx, chars, length, 0); - if (!str) - return NULL; - re = js_NewRegExp(cx, ts, str, flags, JS_FALSE); - if (!re) - return NULL; - JS_PUSH_SINGLE_TEMP_ROOT(cx, STRING_TO_JSVAL(str), &tvr); - obj = js_NewObject(cx, &js_RegExpClass, NULL, NULL); - if (!obj || !JS_SetPrivate(cx, obj, re) || !js_SetLastIndex(cx, obj, 0)) { - js_DestroyRegExp(cx, re); - obj = NULL; - } - JS_POP_TEMP_ROOT(cx, &tvr); - return obj; -} - -JSObject * -js_CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *parent) -{ - JSObject *clone; - JSRegExp *re; - - JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_RegExpClass); - clone = js_NewObject(cx, &js_RegExpClass, NULL, parent); - if (!clone) - return NULL; - re = JS_GetPrivate(cx, obj); - if (!JS_SetPrivate(cx, clone, re) || !js_SetLastIndex(cx, clone, 0)) { - cx->newborn[GCX_OBJECT] = NULL; - return NULL; - } - HOLD_REGEXP(cx, re); - return clone; -} - -JSBool -js_GetLastIndex(JSContext *cx, JSObject *obj, jsdouble *lastIndex) -{ - jsval v; - - return JS_GetReservedSlot(cx, obj, 0, &v) && - js_ValueToNumber(cx, v, lastIndex); -} - -JSBool -js_SetLastIndex(JSContext *cx, JSObject *obj, jsdouble lastIndex) -{ - jsval v; - - return js_NewNumberValue(cx, lastIndex, &v) && - JS_SetReservedSlot(cx, obj, 0, v); -} - -#endif /* JS_HAS_REGEXPS */ diff --git a/lib/javascript/jsregexp.h b/lib/javascript/jsregexp.h deleted file mode 100644 index 50789832..00000000 --- a/lib/javascript/jsregexp.h +++ /dev/null @@ -1,183 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jsregexp_h___ -#define jsregexp_h___ -/* - * JS regular expression interface. - */ -#include -#include "jspubtd.h" -#include "jsstr.h" - -#ifdef JS_THREADSAFE -#include "jsdhash.h" -#endif - -struct JSRegExpStatics { - JSString *input; /* input string to match (perl $_, GC root) */ - JSBool multiline; /* whether input contains newlines (perl $*) */ - uint16 parenCount; /* number of valid elements in parens[] */ - uint16 moreLength; /* number of allocated elements in moreParens */ - JSSubString parens[9]; /* last set of parens matched (perl $1, $2) */ - JSSubString *moreParens; /* null or realloc'd vector for $10, etc. */ - JSSubString lastMatch; /* last string matched (perl $&) */ - JSSubString lastParen; /* last paren matched (perl $+) */ - JSSubString leftContext; /* input to left of last match (perl $`) */ - JSSubString rightContext; /* input to right of last match (perl $') */ -}; - -/* - * This struct holds a bitmap representation of a class from a regexp. - * There's a list of these referenced by the classList field in the JSRegExp - * struct below. The initial state has startIndex set to the offset in the - * original regexp source of the beginning of the class contents. The first - * use of the class converts the source representation into a bitmap. - * - */ -typedef struct RECharSet { - JSPackedBool converted; - JSPackedBool sense; - uint16 length; - union { - uint8 *bits; - struct { - size_t startIndex; - size_t length; - } src; - } u; -} RECharSet; - -/* - * This macro is safe because moreParens is guaranteed to be allocated and big - * enough to hold parenCount, or else be null when parenCount is 0. - */ -#define REGEXP_PAREN_SUBSTRING(res, num) \ - (((jsuint)(num) < (jsuint)(res)->parenCount) \ - ? ((jsuint)(num) < 9) \ - ? &(res)->parens[num] \ - : &(res)->moreParens[(num) - 9] \ - : &js_EmptySubString) - -typedef struct RENode RENode; - -struct JSRegExp { - jsrefcount nrefs; /* reference count */ - uint16 flags; /* flags, see jsapi.h's JSREG_* defines */ - uint16 cloneIndex; /* index in fp->vars or funobj->slots of - cloned regexp object */ - size_t parenCount; /* number of parenthesized submatches */ - size_t classCount; /* count [...] bitmaps */ - RECharSet *classList; /* list of [...] bitmaps */ - JSString *source; /* locked source string, sans // */ - jsbytecode program[1]; /* regular expression bytecode */ -}; - -extern JSRegExp * -js_NewRegExp(JSContext *cx, JSTokenStream *ts, - JSString *str, uintN flags, JSBool flat); - -extern JSRegExp * -js_NewRegExpOpt(JSContext *cx, JSTokenStream *ts, - JSString *str, JSString *opt, JSBool flat); - -#define HOLD_REGEXP(cx, re) JS_ATOMIC_INCREMENT(&(re)->nrefs) -#define DROP_REGEXP(cx, re) js_DestroyRegExp(cx, re) - -extern void -js_DestroyRegExp(JSContext *cx, JSRegExp *re); - -/* - * Execute re on input str at *indexp, returning null in *rval on mismatch. - * On match, return true if test is true, otherwise return an array object. - * Update *indexp and cx->regExpStatics always on match. - */ -extern JSBool -js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp, - JSBool test, jsval *rval); - -/* - * These two add and remove GC roots, respectively, so their calls must be - * well-ordered. - */ -extern JSBool -js_InitRegExpStatics(JSContext *cx, JSRegExpStatics *res); - -extern void -js_FreeRegExpStatics(JSContext *cx, JSRegExpStatics *res); - -#define JSVAL_IS_REGEXP(cx, v) \ - (JSVAL_IS_OBJECT(v) && JSVAL_TO_OBJECT(v) && \ - OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_RegExpClass) - -extern JSClass js_RegExpClass; - -extern JSObject * -js_InitRegExpClass(JSContext *cx, JSObject *obj); - -/* - * Export js_regexp_toString to the decompiler. - */ -extern JSBool -js_regexp_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval); - -/* - * Create, serialize/deserialize, or clone a RegExp object. - */ -extern JSObject * -js_NewRegExpObject(JSContext *cx, JSTokenStream *ts, - jschar *chars, size_t length, uintN flags); - -extern JSBool -js_XDRRegExp(JSXDRState *xdr, JSObject **objp); - -extern JSObject * -js_CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *parent); - -/* - * Get and set the per-object (clone or clone-parent) lastIndex slot. - */ -extern JSBool -js_GetLastIndex(JSContext *cx, JSObject *obj, jsdouble *lastIndex); - -extern JSBool -js_SetLastIndex(JSContext *cx, JSObject *obj, jsdouble lastIndex); - -#endif /* jsregexp_h___ */ diff --git a/lib/javascript/jsscan.c b/lib/javascript/jsscan.c deleted file mode 100644 index c043799d..00000000 --- a/lib/javascript/jsscan.c +++ /dev/null @@ -1,2170 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set sw=4 ts=8 et tw=78: - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JS lexical scanner. - */ -#include "jsstddef.h" -#include /* first to avoid trouble on some systems */ -#include -#include -#include -#ifdef HAVE_MEMORY_H -#include -#endif -#include -#include -#include -#include "jstypes.h" -#include "jsarena.h" /* Added by JSIFY */ -#include "jsutil.h" /* Added by JSIFY */ -#include "jsdtoa.h" -#include "jsprf.h" -#include "jsapi.h" -#include "jsatom.h" -#include "jscntxt.h" -#include "jsconfig.h" -#include "jsemit.h" -#include "jsexn.h" -#include "jsnum.h" -#include "jsopcode.h" -#include "jsregexp.h" -#include "jsscan.h" -#include "jsscript.h" - -#if JS_HAS_XML_SUPPORT -#include "jsparse.h" -#include "jsxml.h" -#endif - -#define RESERVE_JAVA_KEYWORDS -#define RESERVE_ECMA_KEYWORDS - -#define MAX_KEYWORD_LENGTH 12 - -static struct keyword { - const char *name; - JSTokenType tokentype; /* JSTokenType */ - JSOp op; /* JSOp */ - JSVersion version; /* JSVersion */ -} keywords[] = { - {"break", TOK_BREAK, JSOP_NOP, JSVERSION_DEFAULT}, - {"case", TOK_CASE, JSOP_NOP, JSVERSION_DEFAULT}, - {"continue", TOK_CONTINUE, JSOP_NOP, JSVERSION_DEFAULT}, - {js_default_str, TOK_DEFAULT, JSOP_NOP, JSVERSION_DEFAULT}, - {js_delete_str, TOK_DELETE, JSOP_NOP, JSVERSION_DEFAULT}, - {"do", TOK_DO, JSOP_NOP, JSVERSION_DEFAULT}, - {"else", TOK_ELSE, JSOP_NOP, JSVERSION_DEFAULT}, - {"export", TOK_EXPORT, JSOP_NOP, JSVERSION_1_2}, - {js_false_str, TOK_PRIMARY, JSOP_FALSE, JSVERSION_DEFAULT}, - {"for", TOK_FOR, JSOP_NOP, JSVERSION_DEFAULT}, - {js_function_str, TOK_FUNCTION, JSOP_NOP, JSVERSION_DEFAULT}, - {"if", TOK_IF, JSOP_NOP, JSVERSION_DEFAULT}, - {js_in_str, TOK_IN, JSOP_IN, JSVERSION_DEFAULT}, - {js_new_str, TOK_NEW, JSOP_NEW, JSVERSION_DEFAULT}, - {js_null_str, TOK_PRIMARY, JSOP_NULL, JSVERSION_DEFAULT}, - {"return", TOK_RETURN, JSOP_NOP, JSVERSION_DEFAULT}, - {"switch", TOK_SWITCH, JSOP_NOP, JSVERSION_DEFAULT}, - {js_this_str, TOK_PRIMARY, JSOP_THIS, JSVERSION_DEFAULT}, - {js_true_str, TOK_PRIMARY, JSOP_TRUE, JSVERSION_DEFAULT}, - {js_typeof_str, TOK_UNARYOP, JSOP_TYPEOF,JSVERSION_DEFAULT}, - {js_var_str, TOK_VAR, JSOP_DEFVAR,JSVERSION_DEFAULT}, - {js_void_str, TOK_UNARYOP, JSOP_VOID, JSVERSION_DEFAULT}, - {"while", TOK_WHILE, JSOP_NOP, JSVERSION_DEFAULT}, - {"with", TOK_WITH, JSOP_NOP, JSVERSION_DEFAULT}, - -#if JS_HAS_CONST - {js_const_str, TOK_VAR, JSOP_DEFCONST,JSVERSION_DEFAULT}, -#else - {js_const_str, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, -#endif - -#if JS_HAS_EXCEPTIONS - {"try", TOK_TRY, JSOP_NOP, JSVERSION_DEFAULT}, - {"catch", TOK_CATCH, JSOP_NOP, JSVERSION_DEFAULT}, - {"finally", TOK_FINALLY, JSOP_NOP, JSVERSION_DEFAULT}, - {"throw", TOK_THROW, JSOP_NOP, JSVERSION_DEFAULT}, -#else - {"try", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"catch", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"finally", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"throw", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, -#endif - -#if JS_HAS_INSTANCEOF - {js_instanceof_str, TOK_INSTANCEOF, JSOP_INSTANCEOF,JSVERSION_1_4}, -#else - {js_instanceof_str, TOK_RESERVED, JSOP_NOP, JSVERSION_1_4}, -#endif - -#ifdef RESERVE_JAVA_KEYWORDS - {"abstract", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"boolean", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"byte", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"char", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"class", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"double", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"extends", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"final", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"float", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"goto", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"implements", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"import", TOK_IMPORT, JSOP_NOP, JSVERSION_DEFAULT}, - {"int", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"interface", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"long", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"native", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"package", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"private", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"protected", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"public", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"short", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"static", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"super", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"synchronized", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"throws", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"transient", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, - {"volatile", TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT}, -#endif - -#ifdef RESERVE_ECMA_KEYWORDS - {"enum", TOK_RESERVED, JSOP_NOP, JSVERSION_1_3}, -#endif - -#if JS_HAS_DEBUGGER_KEYWORD - {"debugger", TOK_DEBUGGER, JSOP_NOP, JSVERSION_1_3}, -#elif defined(RESERVE_ECMA_KEYWORDS) - {"debugger", TOK_RESERVED, JSOP_NOP, JSVERSION_1_3}, -#endif - {0, TOK_EOF, JSOP_NOP, JSVERSION_DEFAULT} -}; - -JSBool -js_InitScanner(JSContext *cx) -{ - struct keyword *kw; - size_t length; - JSAtom *atom; - - for (kw = keywords; kw->name; kw++) { - length = strlen(kw->name); - JS_ASSERT(length <= MAX_KEYWORD_LENGTH); - atom = js_Atomize(cx, kw->name, length, ATOM_PINNED); - if (!atom) - return JS_FALSE; - ATOM_SET_KEYWORD(atom, kw); - } - return JS_TRUE; -} - -JS_FRIEND_API(void) -js_MapKeywords(void (*mapfun)(const char *)) -{ - struct keyword *kw; - - for (kw = keywords; kw->name; kw++) - mapfun(kw->name); -} - -JSTokenStream * -js_NewTokenStream(JSContext *cx, const jschar *base, size_t length, - const char *filename, uintN lineno, - JSPrincipals *principals) -{ - JSTokenStream *ts; - - ts = js_NewBufferTokenStream(cx, base, length); - if (!ts) - return NULL; - ts->filename = filename; - ts->lineno = lineno; - if (principals) - JSPRINCIPALS_HOLD(cx, principals); - ts->principals = principals; - return ts; -} - -#define TBMIN 64 - -static JSBool -GrowTokenBuf(JSStringBuffer *sb, size_t newlength) -{ - JSContext *cx; - jschar *base; - ptrdiff_t offset, length; - size_t tbsize; - JSArenaPool *pool; - - cx = sb->data; - base = sb->base; - offset = PTRDIFF(sb->ptr, base, jschar); - pool = &cx->tempPool; - if (!base) { - tbsize = TBMIN * sizeof(jschar); - length = TBMIN - 1; - JS_ARENA_ALLOCATE_CAST(base, jschar *, pool, tbsize); - } else { - length = PTRDIFF(sb->limit, base, jschar); - tbsize = (length + 1) * sizeof(jschar); - length += length + 1; - JS_ARENA_GROW_CAST(base, jschar *, pool, tbsize, tbsize); - } - if (!base) { - JS_ReportOutOfMemory(cx); - sb->base = STRING_BUFFER_ERROR_BASE; - return JS_FALSE; - } - sb->base = base; - sb->limit = base + length; - sb->ptr = base + offset; - return JS_TRUE; -} - -JS_FRIEND_API(JSTokenStream *) -js_NewBufferTokenStream(JSContext *cx, const jschar *base, size_t length) -{ - size_t nb; - JSTokenStream *ts; - - nb = sizeof(JSTokenStream) + JS_LINE_LIMIT * sizeof(jschar); - JS_ARENA_ALLOCATE_CAST(ts, JSTokenStream *, &cx->tempPool, nb); - if (!ts) { - JS_ReportOutOfMemory(cx); - return NULL; - } - memset(ts, 0, nb); - ts->lineno = 1; - ts->linebuf.base = ts->linebuf.limit = ts->linebuf.ptr = (jschar *)(ts + 1); - ts->userbuf.base = (jschar *)base; - ts->userbuf.limit = (jschar *)base + length; - ts->userbuf.ptr = (jschar *)base; - ts->tokenbuf.grow = GrowTokenBuf; - ts->tokenbuf.data = cx; - ts->listener = cx->runtime->sourceHandler; - ts->listenerData = cx->runtime->sourceHandlerData; - return ts; -} - -JS_FRIEND_API(JSTokenStream *) -js_NewFileTokenStream(JSContext *cx, const char *filename, FILE *defaultfp) -{ - jschar *base; - JSTokenStream *ts; - FILE *file; - - JS_ARENA_ALLOCATE_CAST(base, jschar *, &cx->tempPool, - JS_LINE_LIMIT * sizeof(jschar)); - if (!base) - return NULL; - ts = js_NewBufferTokenStream(cx, base, JS_LINE_LIMIT); - if (!ts) - return NULL; - if (!filename || strcmp(filename, "-") == 0) { - file = defaultfp; - } else { - file = fopen(filename, "r"); - if (!file) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_OPEN, - filename, "No such file or directory"); - return NULL; - } - } - ts->userbuf.ptr = ts->userbuf.limit; - ts->file = file; - ts->filename = filename; - return ts; -} - -JS_FRIEND_API(JSBool) -js_CloseTokenStream(JSContext *cx, JSTokenStream *ts) -{ - if (ts->flags & TSF_OWNFILENAME) - JS_free(cx, (void *) ts->filename); - if (ts->principals) - JSPRINCIPALS_DROP(cx, ts->principals); - return !ts->file || fclose(ts->file) == 0; -} - -JS_FRIEND_API(int) -js_fgets(char *buf, int size, FILE *file) -{ - int n, i, c; - JSBool crflag; - - n = size - 1; - if (n < 0) - return -1; - - crflag = JS_FALSE; - for (i = 0; i < n && (c = getc(file)) != EOF; i++) { - buf[i] = c; - if (c == '\n') { /* any \n ends a line */ - i++; /* keep the \n; we know there is room for \0 */ - break; - } - if (crflag) { /* \r not followed by \n ends line at the \r */ - ungetc(c, file); - break; /* and overwrite c in buf with \0 */ - } - crflag = (c == '\r'); - } - - buf[i] = '\0'; - return i; -} - -static int32 -GetChar(JSTokenStream *ts) -{ - int32 c; - ptrdiff_t i, j, len, olen; - JSBool crflag; - char cbuf[JS_LINE_LIMIT]; - jschar *ubuf, *nl; - - if (ts->ungetpos != 0) { - c = ts->ungetbuf[--ts->ungetpos]; - } else { - do { - if (ts->linebuf.ptr == ts->linebuf.limit) { - len = PTRDIFF(ts->userbuf.limit, ts->userbuf.ptr, jschar); - if (len <= 0) { - if (!ts->file) { - ts->flags |= TSF_EOF; - return EOF; - } - - /* Fill ts->userbuf so that \r and \r\n convert to \n. */ - crflag = (ts->flags & TSF_CRFLAG) != 0; - len = js_fgets(cbuf, JS_LINE_LIMIT - crflag, ts->file); - if (len <= 0) { - ts->flags |= TSF_EOF; - return EOF; - } - olen = len; - ubuf = ts->userbuf.base; - i = 0; - if (crflag) { - ts->flags &= ~TSF_CRFLAG; - if (cbuf[0] != '\n') { - ubuf[i++] = '\n'; - len++; - ts->linepos--; - } - } - for (j = 0; i < len; i++, j++) - ubuf[i] = (jschar) (unsigned char) cbuf[j]; - ts->userbuf.limit = ubuf + len; - ts->userbuf.ptr = ubuf; - } - if (ts->listener) { - ts->listener(ts->filename, ts->lineno, ts->userbuf.ptr, len, - &ts->listenerTSData, ts->listenerData); - } - - nl = ts->saveEOL; - if (!nl) { - /* - * Any one of \n, \r, or \r\n ends a line (the longest - * match wins). Also allow the Unicode line and paragraph - * separators. - */ - for (nl = ts->userbuf.ptr; nl < ts->userbuf.limit; nl++) { - /* - * Try to prevent value-testing on most characters by - * filtering out characters that aren't 000x or 202x. - */ - if ((*nl & 0xDFD0) == 0) { - if (*nl == '\n') - break; - if (*nl == '\r') { - if (nl + 1 < ts->userbuf.limit && nl[1] == '\n') - nl++; - break; - } - if (*nl == LINE_SEPARATOR || *nl == PARA_SEPARATOR) - break; - } - } - } - - /* - * If there was a line terminator, copy thru it into linebuf. - * Else copy JS_LINE_LIMIT-1 bytes into linebuf. - */ - if (nl < ts->userbuf.limit) - len = PTRDIFF(nl, ts->userbuf.ptr, jschar) + 1; - if (len >= JS_LINE_LIMIT) { - len = JS_LINE_LIMIT - 1; - ts->saveEOL = nl; - } else { - ts->saveEOL = NULL; - } - js_strncpy(ts->linebuf.base, ts->userbuf.ptr, len); - ts->userbuf.ptr += len; - olen = len; - - /* - * Make sure linebuf contains \n for EOL (don't do this in - * userbuf because the user's string might be readonly). - */ - if (nl < ts->userbuf.limit) { - if (*nl == '\r') { - if (ts->linebuf.base[len-1] == '\r') { - /* - * Does the line segment end in \r? We must check - * for a \n at the front of the next segment before - * storing a \n into linebuf. This case matters - * only when we're reading from a file. - */ - if (nl + 1 == ts->userbuf.limit && ts->file) { - len--; - ts->flags |= TSF_CRFLAG; /* clear NLFLAG? */ - if (len == 0) { - /* - * This can happen when a segment ends in - * \r\r. Start over. ptr == limit in this - * case, so we'll fall into buffer-filling - * code. - */ - return GetChar(ts); - } - } else { - ts->linebuf.base[len-1] = '\n'; - } - } - } else if (*nl == '\n') { - if (nl > ts->userbuf.base && - nl[-1] == '\r' && - ts->linebuf.base[len-2] == '\r') { - len--; - JS_ASSERT(ts->linebuf.base[len] == '\n'); - ts->linebuf.base[len-1] = '\n'; - } - } else if (*nl == LINE_SEPARATOR || *nl == PARA_SEPARATOR) { - ts->linebuf.base[len-1] = '\n'; - } - } - - /* Reset linebuf based on adjusted segment length. */ - ts->linebuf.limit = ts->linebuf.base + len; - ts->linebuf.ptr = ts->linebuf.base; - - /* Update position of linebuf within physical userbuf line. */ - if (!(ts->flags & TSF_NLFLAG)) - ts->linepos += ts->linelen; - else - ts->linepos = 0; - if (ts->linebuf.limit[-1] == '\n') - ts->flags |= TSF_NLFLAG; - else - ts->flags &= ~TSF_NLFLAG; - - /* Update linelen from original segment length. */ - ts->linelen = olen; - } - c = *ts->linebuf.ptr++; - } while (JS_ISFORMAT(c)); - } - if (c == '\n') - ts->lineno++; - return c; -} - -static void -UngetChar(JSTokenStream *ts, int32 c) -{ - if (c == EOF) - return; - JS_ASSERT(ts->ungetpos < sizeof ts->ungetbuf / sizeof ts->ungetbuf[0]); - if (c == '\n') - ts->lineno--; - ts->ungetbuf[ts->ungetpos++] = (jschar)c; -} - -static int32 -PeekChar(JSTokenStream *ts) -{ - int32 c; - - c = GetChar(ts); - UngetChar(ts, c); - return c; -} - -/* - * Peek n chars ahead into ts. Return true if n chars were read, false if - * there weren't enough characters in the input stream. This function cannot - * be used to peek into or past a newline. - */ -static JSBool -PeekChars(JSTokenStream *ts, intN n, jschar *cp) -{ - intN i, j; - int32 c; - - for (i = 0; i < n; i++) { - c = GetChar(ts); - if (c == EOF) - break; - if (c == '\n') { - UngetChar(ts, c); - break; - } - cp[i] = (jschar)c; - } - for (j = i - 1; j >= 0; j--) - UngetChar(ts, cp[j]); - return i == n; -} - -static void -SkipChars(JSTokenStream *ts, intN n) -{ - while (--n >= 0) - GetChar(ts); -} - -static JSBool -MatchChar(JSTokenStream *ts, int32 expect) -{ - int32 c; - - c = GetChar(ts); - if (c == expect) - return JS_TRUE; - UngetChar(ts, c); - return JS_FALSE; -} - -static JSBool -ReportCompileErrorNumber(JSContext *cx, void *handle, uintN flags, - uintN errorNumber, JSErrorReport *report, - JSBool charArgs, va_list ap) -{ - JSString *linestr = NULL; - JSTokenStream *ts = NULL; - JSCodeGenerator *cg = NULL; -#if JS_HAS_XML_SUPPORT - JSParseNode *pn = NULL; -#endif - JSErrorReporter onError; - JSTokenPos *tp; - JSStackFrame *fp; - uintN index; - char *message; - JSBool warning; - - memset(report, 0, sizeof (struct JSErrorReport)); - report->flags = flags; - report->errorNumber = errorNumber; - message = NULL; - - if (!js_ExpandErrorArguments(cx, js_GetErrorMessage, NULL, - errorNumber, &message, report, &warning, - charArgs, ap)) { - return JS_FALSE; - } - - js_AddRoot(cx, &linestr, "error line buffer"); - - switch (flags & JSREPORT_HANDLE) { - case JSREPORT_TS: - ts = handle; - break; - case JSREPORT_CG: - cg = handle; - break; -#if JS_HAS_XML_SUPPORT - case JSREPORT_PN: - pn = handle; - ts = pn->pn_ts; - break; -#endif - } - - JS_ASSERT(!ts || ts->linebuf.limit < ts->linebuf.base + JS_LINE_LIMIT); - onError = cx->errorReporter; - if (onError) { - /* - * We are typically called with non-null ts and null cg from jsparse.c. - * We can be called with null ts from the regexp compilation functions. - * The code generator (jsemit.c) may pass null ts and non-null cg. - */ - do { - if (ts) { - report->filename = ts->filename; -#if JS_HAS_XML_SUPPORT - if (pn) { - report->lineno = pn->pn_pos.begin.lineno; - if (report->lineno != ts->lineno) - break; - } -#endif - report->lineno = ts->lineno; - linestr = js_NewStringCopyN(cx, ts->linebuf.base, - PTRDIFF(ts->linebuf.limit, - ts->linebuf.base, - jschar), - 0); - report->linebuf = linestr - ? JS_GetStringBytes(linestr) - : NULL; - tp = &ts->tokens[(ts->cursor+ts->lookahead) & NTOKENS_MASK].pos; -#if JS_HAS_XML_SUPPORT - if (pn) - tp = &pn->pn_pos; -#endif - /* - * FIXME: What should instead happen here is that we should - * find error-tokens in userbuf, if !ts->file. That will - * allow us to deliver a more helpful error message, which - * includes all or part of the bad string or bad token. The - * code here yields something that looks truncated. - * See https://bugzilla.mozilla.org/show_bug.cgi?id=352970 - */ - index = 0; - if (tp->begin.lineno == tp->end.lineno) { - if (tp->begin.index < ts->linepos) - break; - - index = tp->begin.index - ts->linepos; - } - - report->tokenptr = linestr ? report->linebuf + index : NULL; - report->uclinebuf = linestr ? JS_GetStringChars(linestr) : NULL; - report->uctokenptr = linestr ? report->uclinebuf + index : NULL; - break; - } - - if (cg) { - report->filename = cg->filename; - report->lineno = CG_CURRENT_LINE(cg); - break; - } - - /* - * If we can't find out where the error was based on the current frame, - * see if the next frame has a script/pc combo we can use. - */ - for (fp = cx->fp; fp; fp = fp->down) { - if (fp->script && fp->pc) { - report->filename = fp->script->filename; - report->lineno = js_PCToLineNumber(cx, fp->script, fp->pc); - break; - } - } - } while (0); - -#if JS_HAS_ERROR_EXCEPTIONS - /* - * If there's a runtime exception type associated with this error - * number, set that as the pending exception. For errors occuring at - * compile time, this is very likely to be a JSEXN_SYNTAXERR. - * - * If an exception is thrown but not caught, the JSREPORT_EXCEPTION - * flag will be set in report.flags. Proper behavior for an error - * reporter is to ignore a report with this flag for all but top-level - * compilation errors. The exception will remain pending, and so long - * as the non-top-level "load", "eval", or "compile" native function - * returns false, the top-level reporter will eventually receive the - * uncaught exception report. - * - * XXX it'd probably be best if there was only one call to this - * function, but there seem to be two error reporter call points. - */ - - /* - * Try to raise an exception only if there isn't one already set -- - * otherwise the exception will describe the last compile-time error, - * which is likely spurious. - */ - if (!ts || !(ts->flags & TSF_ERROR)) { - if (js_ErrorToException(cx, message, report)) - onError = NULL; - } - - /* - * Suppress any compile-time errors that don't occur at the top level. - * This may still fail, as interplevel may be zero in contexts where we - * don't really want to call the error reporter, as when js is called - * by other code which could catch the error. - */ - if (cx->interpLevel != 0 && !JSREPORT_IS_WARNING(flags)) - onError = NULL; -#endif - if (onError) { - JSDebugErrorHook hook = cx->runtime->debugErrorHook; - - /* - * If debugErrorHook is present then we give it a chance to veto - * sending the error on to the regular error reporter. - */ - if (hook && !hook(cx, message, report, - cx->runtime->debugErrorHookData)) { - onError = NULL; - } - } - if (onError) - (*onError)(cx, message, report); - } - - if (message) - JS_free(cx, message); - if (report->ucmessage) - JS_free(cx, (void *)report->ucmessage); - - js_RemoveRoot(cx->runtime, &linestr); - - if (ts && !JSREPORT_IS_WARNING(flags)) { - /* Set the error flag to suppress spurious reports. */ - ts->flags |= TSF_ERROR; - } - - return warning; -} - -JSBool -js_ReportCompileErrorNumber(JSContext *cx, void *handle, uintN flags, - uintN errorNumber, ...) -{ - va_list ap; - JSErrorReport report; - JSBool warning; - - if ((flags & JSREPORT_STRICT) && !JS_HAS_STRICT_OPTION(cx)) - return JS_TRUE; - - va_start(ap, errorNumber); - warning = ReportCompileErrorNumber(cx, handle, flags, errorNumber, - &report, JS_TRUE, ap); - va_end(ap); - - /* - * We have to do this here because js_ReportCompileErrorNumberUC doesn't - * need to do this. - */ - if (report.messageArgs) { - int i = 0; - while (report.messageArgs[i]) - JS_free(cx, (void *)report.messageArgs[i++]); - JS_free(cx, (void *)report.messageArgs); - } - - return warning; -} - -JSBool -js_ReportCompileErrorNumberUC(JSContext *cx, void *handle, uintN flags, - uintN errorNumber, ...) -{ - va_list ap; - JSErrorReport report; - JSBool warning; - - if ((flags & JSREPORT_STRICT) && !JS_HAS_STRICT_OPTION(cx)) - return JS_TRUE; - - va_start(ap, errorNumber); - warning = ReportCompileErrorNumber(cx, handle, flags, errorNumber, - &report, JS_FALSE, ap); - va_end(ap); - - if (report.messageArgs) - JS_free(cx, (void *)report.messageArgs); - - return warning; -} - -static JSBool -GrowStringBuffer(JSStringBuffer *sb, size_t newlength) -{ - ptrdiff_t offset; - jschar *bp; - - offset = PTRDIFF(sb->ptr, sb->base, jschar); - JS_ASSERT(offset >= 0); - newlength += offset + 1; - if ((size_t)offset < newlength && newlength < ~(size_t)0 / sizeof(jschar)) - bp = realloc(sb->base, newlength * sizeof(jschar)); - else - bp = NULL; - if (!bp) { - free(sb->base); - sb->base = STRING_BUFFER_ERROR_BASE; - return JS_FALSE; - } - sb->base = bp; - sb->ptr = bp + offset; - sb->limit = bp + newlength - 1; - return JS_TRUE; -} - -static void -FreeStringBuffer(JSStringBuffer *sb) -{ - JS_ASSERT(STRING_BUFFER_OK(sb)); - if (sb->base) - free(sb->base); -} - -void -js_InitStringBuffer(JSStringBuffer *sb) -{ - sb->base = sb->limit = sb->ptr = NULL; - sb->data = NULL; - sb->grow = GrowStringBuffer; - sb->free = FreeStringBuffer; -} - -void -js_FinishStringBuffer(JSStringBuffer *sb) -{ - sb->free(sb); -} - -#define ENSURE_STRING_BUFFER(sb,n) \ - ((sb)->ptr + (n) <= (sb)->limit || sb->grow(sb, n)) - -static void -FastAppendChar(JSStringBuffer *sb, jschar c) -{ - if (!STRING_BUFFER_OK(sb)) - return; - if (!ENSURE_STRING_BUFFER(sb, 1)) - return; - *sb->ptr++ = c; -} - -void -js_AppendChar(JSStringBuffer *sb, jschar c) -{ - jschar *bp; - - if (!STRING_BUFFER_OK(sb)) - return; - if (!ENSURE_STRING_BUFFER(sb, 1)) - return; - bp = sb->ptr; - *bp++ = c; - *bp = 0; - sb->ptr = bp; -} - -#if JS_HAS_XML_SUPPORT - -void -js_RepeatChar(JSStringBuffer *sb, jschar c, uintN count) -{ - jschar *bp; - - if (!STRING_BUFFER_OK(sb) || count == 0) - return; - if (!ENSURE_STRING_BUFFER(sb, count)) - return; - for (bp = sb->ptr; count; --count) - *bp++ = c; - *bp = 0; - sb->ptr = bp; -} - -void -js_AppendCString(JSStringBuffer *sb, const char *asciiz) -{ - size_t length; - jschar *bp; - - if (!STRING_BUFFER_OK(sb) || *asciiz == '\0') - return; - length = strlen(asciiz); - if (!ENSURE_STRING_BUFFER(sb, length)) - return; - for (bp = sb->ptr; length; --length) - *bp++ = (jschar) *asciiz++; - *bp = 0; - sb->ptr = bp; -} - -void -js_AppendJSString(JSStringBuffer *sb, JSString *str) -{ - size_t length; - jschar *bp; - - if (!STRING_BUFFER_OK(sb)) - return; - length = JSSTRING_LENGTH(str); - if (length == 0 || !ENSURE_STRING_BUFFER(sb, length)) - return; - bp = sb->ptr; - js_strncpy(bp, JSSTRING_CHARS(str), length); - bp += length; - *bp = 0; - sb->ptr = bp; -} - -static JSBool -GetXMLEntity(JSContext *cx, JSTokenStream *ts) -{ - ptrdiff_t offset, length, i; - int32 c, d; - JSBool ispair; - jschar *bp, digit; - char *bytes; - JSErrNum msg; - - /* Put the entity, including the '&' already scanned, in ts->tokenbuf. */ - offset = PTRDIFF(ts->tokenbuf.ptr, ts->tokenbuf.base, jschar); - FastAppendChar(&ts->tokenbuf, '&'); - while ((c = GetChar(ts)) != ';') { - if (c == EOF || c == '\n') { - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_END_OF_XML_ENTITY); - return JS_FALSE; - } - FastAppendChar(&ts->tokenbuf, (jschar) c); - } - - /* Let length be the number of jschars after the '&', including the ';'. */ - length = PTRDIFF(ts->tokenbuf.ptr, ts->tokenbuf.base, jschar) - offset; - bp = ts->tokenbuf.base + offset; - c = d = 0; - ispair = JS_FALSE; - if (length > 2 && bp[1] == '#') { - /* Match a well-formed XML Character Reference. */ - i = 2; - if (length > 3 && JS_TOLOWER(bp[i]) == 'x') { - if (length > 9) /* at most 6 hex digits allowed */ - goto badncr; - while (++i < length) { - digit = bp[i]; - if (!JS7_ISHEX(digit)) - goto badncr; - c = (c << 4) + JS7_UNHEX(digit); - } - } else { - while (i < length) { - digit = bp[i++]; - if (!JS7_ISDEC(digit)) - goto badncr; - c = (c * 10) + JS7_UNDEC(digit); - if (c < 0) - goto badncr; - } - } - - if (0x10000 <= c && c <= 0x10FFFF) { - /* Form a surrogate pair (c, d) -- c is the high surrogate. */ - d = 0xDC00 + (c & 0x3FF); - c = 0xD7C0 + (c >> 10); - ispair = JS_TRUE; - } else { - /* Enforce the http://www.w3.org/TR/REC-xml/#wf-Legalchar WFC. */ - if (c != 0x9 && c != 0xA && c != 0xD && - !(0x20 <= c && c <= 0xD7FF) && - !(0xE000 <= c && c <= 0xFFFD)) { - goto badncr; - } - } - } else { - /* Try to match one of the five XML 1.0 predefined entities. */ - switch (length) { - case 3: - if (bp[2] == 't') { - if (bp[1] == 'l') - c = '<'; - else if (bp[1] == 'g') - c = '>'; - } - break; - case 4: - if (bp[1] == 'a' && bp[2] == 'm' && bp[3] == 'p') - c = '&'; - break; - case 5: - if (bp[3] == 'o') { - if (bp[1] == 'a' && bp[2] == 'p' && bp[4] == 's') - c = '\''; - else if (bp[1] == 'q' && bp[2] == 'u' && bp[4] == 't') - c = '"'; - } - break; - } - if (c == 0) { - msg = JSMSG_UNKNOWN_XML_ENTITY; - goto bad; - } - } - - /* If we matched, retract ts->tokenbuf and store the entity's value. */ - *bp++ = (jschar) c; - if (ispair) - *bp++ = (jschar) d; - *bp = 0; - ts->tokenbuf.ptr = bp; - return JS_TRUE; - -badncr: - msg = JSMSG_BAD_XML_NCR; -bad: - /* No match: throw a TypeError per ECMA-357 10.3.2.1 step 8(a). */ - bytes = js_DeflateString(cx, bp + 1, - PTRDIFF(ts->tokenbuf.ptr, bp, jschar) - 1); - if (bytes) { - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, - msg, bytes); - JS_free(cx, bytes); - } - return JS_FALSE; -} - -#endif /* JS_HAS_XML_SUPPORT */ - -JSTokenType -js_PeekToken(JSContext *cx, JSTokenStream *ts) -{ - JSTokenType tt; - - if (ts->lookahead != 0) { - tt = ts->tokens[(ts->cursor + ts->lookahead) & NTOKENS_MASK].type; - } else { - tt = js_GetToken(cx, ts); - js_UngetToken(ts); - } - return tt; -} - -JSTokenType -js_PeekTokenSameLine(JSContext *cx, JSTokenStream *ts) -{ - JSTokenType tt; - - JS_ASSERT(ts->lookahead == 0 || - ON_CURRENT_LINE(ts, CURRENT_TOKEN(ts).pos) || - ts->tokens[(ts->cursor + ts->lookahead) & NTOKENS_MASK].type - == TOK_EOL); - ts->flags |= TSF_NEWLINES; - tt = js_PeekToken(cx, ts); - ts->flags &= ~TSF_NEWLINES; - return tt; -} - -/* - * We have encountered a '\': check for a Unicode escape sequence after it, - * returning the character code value if we found a Unicode escape sequence. - * Otherwise, non-destructively return the original '\'. - */ -static int32 -GetUnicodeEscape(JSTokenStream *ts) -{ - jschar cp[5]; - int32 c; - - if (PeekChars(ts, 5, cp) && cp[0] == 'u' && - JS7_ISHEX(cp[1]) && JS7_ISHEX(cp[2]) && - JS7_ISHEX(cp[3]) && JS7_ISHEX(cp[4])) - { - c = (((((JS7_UNHEX(cp[1]) << 4) - + JS7_UNHEX(cp[2])) << 4) - + JS7_UNHEX(cp[3])) << 4) - + JS7_UNHEX(cp[4]); - SkipChars(ts, 5); - return c; - } - return '\\'; -} - -static JSToken * -NewToken(JSTokenStream *ts, ptrdiff_t adjust) -{ - JSToken *tp; - - ts->cursor = (ts->cursor + 1) & NTOKENS_MASK; - tp = &CURRENT_TOKEN(ts); - tp->ptr = ts->linebuf.ptr + adjust; - tp->pos.begin.index = ts->linepos + - PTRDIFF(tp->ptr, ts->linebuf.base, jschar) - - ts->ungetpos; - tp->pos.begin.lineno = tp->pos.end.lineno = (uint16)ts->lineno; - return tp; -} - -JSTokenType -js_GetToken(JSContext *cx, JSTokenStream *ts) -{ - JSTokenType tt; - int32 c, qc; - JSToken *tp; - JSAtom *atom; - JSBool hadUnicodeEscape; - -#define INIT_TOKENBUF() (ts->tokenbuf.ptr = ts->tokenbuf.base) -#define TOKENBUF_LENGTH() PTRDIFF(ts->tokenbuf.ptr, ts->tokenbuf.base, jschar) -#define TOKENBUF_OK() STRING_BUFFER_OK(&ts->tokenbuf) -#define TOKENBUF_TO_ATOM() (TOKENBUF_OK() \ - ? js_AtomizeChars(cx, \ - TOKENBUF_BASE(), \ - TOKENBUF_LENGTH(), \ - 0) \ - : NULL) -#define ADD_TO_TOKENBUF(c) FastAppendChar(&ts->tokenbuf, (jschar) (c)) - -/* The following 4 macros should only be used when TOKENBUF_OK() is true. */ -#define TOKENBUF_BASE() (ts->tokenbuf.base) -#define TOKENBUF_CHAR(i) (ts->tokenbuf.base[i]) -#define TRIM_TOKENBUF(i) (ts->tokenbuf.ptr = ts->tokenbuf.base + i) -#define NUL_TERM_TOKENBUF() (*ts->tokenbuf.ptr = 0) - - /* If there was a fatal error, keep returning TOK_ERROR. */ - if (ts->flags & TSF_ERROR) - return TOK_ERROR; - - /* Check for a pushed-back token resulting from mismatching lookahead. */ - while (ts->lookahead != 0) { - JS_ASSERT(!(ts->flags & TSF_XMLTEXTMODE)); - ts->lookahead--; - ts->cursor = (ts->cursor + 1) & NTOKENS_MASK; - tt = CURRENT_TOKEN(ts).type; - if (tt != TOK_EOL || (ts->flags & TSF_NEWLINES)) - return tt; - } - -#if JS_HAS_XML_SUPPORT - if (ts->flags & TSF_XMLTEXTMODE) { - tt = TOK_XMLSPACE; /* veto if non-space, return TOK_XMLTEXT */ - tp = NewToken(ts, 0); - INIT_TOKENBUF(); - qc = (ts->flags & TSF_XMLONLYMODE) ? '<' : '{'; - - while ((c = GetChar(ts)) != qc && c != '<' && c != EOF) { - if (c == '&' && qc == '<') { - if (!GetXMLEntity(cx, ts)) - goto error; - tt = TOK_XMLTEXT; - continue; - } - - if (!JS_ISXMLSPACE(c)) - tt = TOK_XMLTEXT; - ADD_TO_TOKENBUF(c); - } - UngetChar(ts, c); - - if (TOKENBUF_LENGTH() == 0) { - atom = NULL; - } else { - atom = TOKENBUF_TO_ATOM(); - if (!atom) - goto error; - } - tp->pos.end.lineno = (uint16)ts->lineno; - tp->t_op = JSOP_STRING; - tp->t_atom = atom; - goto out; - } - - if (ts->flags & TSF_XMLTAGMODE) { - tp = NewToken(ts, 0); - c = GetChar(ts); - if (JS_ISXMLSPACE(c)) { - do { - c = GetChar(ts); - } while (JS_ISXMLSPACE(c)); - UngetChar(ts, c); - tt = TOK_XMLSPACE; - goto out; - } - - if (c == EOF) { - tt = TOK_EOF; - goto out; - } - - INIT_TOKENBUF(); - if (JS_ISXMLNSSTART(c)) { - JSBool sawColon = JS_FALSE; - - ADD_TO_TOKENBUF(c); - while ((c = GetChar(ts)) != EOF && JS_ISXMLNAME(c)) { - if (c == ':') { - int nextc; - - if (sawColon || - (nextc = PeekChar(ts), - ((ts->flags & TSF_XMLONLYMODE) || nextc != '{') && - !JS_ISXMLNAME(nextc))) { - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | - JSREPORT_ERROR, - JSMSG_BAD_XML_QNAME); - goto error; - } - sawColon = JS_TRUE; - } - - ADD_TO_TOKENBUF(c); - } - - UngetChar(ts, c); - atom = TOKENBUF_TO_ATOM(); - if (!atom) - goto error; - tp->t_op = JSOP_STRING; - tp->t_atom = atom; - tt = TOK_XMLNAME; - goto out; - } - - switch (c) { - case '{': - if (ts->flags & TSF_XMLONLYMODE) - goto bad_xml_char; - tt = TOK_LC; - goto out; - - case '=': - tt = TOK_ASSIGN; - goto out; - - case '"': - case '\'': - qc = c; - while ((c = GetChar(ts)) != qc) { - if (c == EOF) { - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_UNTERMINATED_STRING); - goto error; - } - - /* - * XML attribute values are double-quoted when pretty-printed, - * so escape " if it is expressed directly in a single-quoted - * attribute value. - */ - if (c == '"' && !(ts->flags & TSF_XMLONLYMODE)) { - JS_ASSERT(qc == '\''); - js_AppendCString(&ts->tokenbuf, js_quot_entity_str); - continue; - } - - if (c == '&' && (ts->flags & TSF_XMLONLYMODE)) { - if (!GetXMLEntity(cx, ts)) - goto error; - continue; - } - - ADD_TO_TOKENBUF(c); - } - atom = TOKENBUF_TO_ATOM(); - if (!atom) - goto error; - tp->pos.end.lineno = (uint16)ts->lineno; - tp->t_op = JSOP_STRING; - tp->t_atom = atom; - tt = TOK_XMLATTR; - goto out; - - case '>': - tt = TOK_XMLTAGC; - goto out; - - case '/': - if (MatchChar(ts, '>')) { - tt = TOK_XMLPTAGC; - goto out; - } - /* FALL THROUGH */ - - bad_xml_char: - default: - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, - JSMSG_BAD_XML_CHARACTER); - goto error; - } - /* NOTREACHED */ - } -#endif /* JS_HAS_XML_SUPPORT */ - -retry: - do { - c = GetChar(ts); - if (c == '\n') { - ts->flags &= ~TSF_DIRTYLINE; - if (ts->flags & TSF_NEWLINES) - break; - } - } while (JS_ISSPACE(c)); - - tp = NewToken(ts, -1); - if (c == EOF) { - tt = TOK_EOF; - goto out; - } - - hadUnicodeEscape = JS_FALSE; - if (JS_ISIDSTART(c) || - (c == '\\' && - (c = GetUnicodeEscape(ts), - hadUnicodeEscape = JS_ISIDSTART(c)))) { - INIT_TOKENBUF(); - for (;;) { - ADD_TO_TOKENBUF(c); - c = GetChar(ts); - if (c == '\\') { - c = GetUnicodeEscape(ts); - if (!JS_ISIDENT(c)) - break; - hadUnicodeEscape = JS_TRUE; - } else { - if (!JS_ISIDENT(c)) - break; - } - } - UngetChar(ts, c); - - atom = TOKENBUF_TO_ATOM(); - if (!atom) - goto error; - if (!hadUnicodeEscape && ATOM_KEYWORD(atom)) { - struct keyword *kw; - - JS_ASSERT(!(atom->flags & ATOM_HIDDEN)); - kw = ATOM_KEYWORD(atom); - if (kw->tokentype == TOK_RESERVED) { - char buf[MAX_KEYWORD_LENGTH + 1]; - size_t buflen = sizeof(buf) - 1; - if (!js_DeflateStringToBuffer(cx, TOKENBUF_BASE(), TOKENBUF_LENGTH(), - buf, &buflen)) - goto error; - buf [buflen] = 0; - if (!js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | - JSREPORT_WARNING | - JSREPORT_STRICT, - JSMSG_RESERVED_ID, buf)) { - goto error; - } - } else if (JS_VERSION_IS_ECMA(cx) || - kw->version <= (cx->version & JSVERSION_MASK)) { - tt = kw->tokentype; - tp->t_op = (JSOp) kw->op; - goto out; - } - } - tp->t_op = JSOP_NAME; - tp->t_atom = atom; - tt = TOK_NAME; - goto out; - } - - if (JS7_ISDEC(c) || (c == '.' && JS7_ISDEC(PeekChar(ts)))) { - jsint radix; - const jschar *endptr; - jsdouble dval; - - radix = 10; - INIT_TOKENBUF(); - - if (c == '0') { - ADD_TO_TOKENBUF(c); - c = GetChar(ts); - if (JS_TOLOWER(c) == 'x') { - ADD_TO_TOKENBUF(c); - c = GetChar(ts); - radix = 16; - } else if (JS7_ISDEC(c)) { - radix = 8; - } - } - - while (JS7_ISHEX(c)) { - if (radix < 16) { - if (JS7_ISLET(c)) - break; - - /* - * We permit 08 and 09 as decimal numbers, which makes our - * behaviour a superset of the ECMA numeric grammar. We might - * not always be so permissive, so we warn about it. - */ - if (radix == 8 && c >= '8') { - if (!js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | - JSREPORT_WARNING, - JSMSG_BAD_OCTAL, - c == '8' ? "08" : "09")) { - goto error; - } - radix = 10; - } - } - ADD_TO_TOKENBUF(c); - c = GetChar(ts); - } - - if (radix == 10 && (c == '.' || JS_TOLOWER(c) == 'e')) { - if (c == '.') { - do { - ADD_TO_TOKENBUF(c); - c = GetChar(ts); - } while (JS7_ISDEC(c)); - } - if (JS_TOLOWER(c) == 'e') { - ADD_TO_TOKENBUF(c); - c = GetChar(ts); - if (c == '+' || c == '-') { - ADD_TO_TOKENBUF(c); - c = GetChar(ts); - } - if (!JS7_ISDEC(c)) { - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_MISSING_EXPONENT); - goto error; - } - do { - ADD_TO_TOKENBUF(c); - c = GetChar(ts); - } while (JS7_ISDEC(c)); - } - } - - /* Put back the next char and NUL-terminate tokenbuf for js_strto*. */ - UngetChar(ts, c); - ADD_TO_TOKENBUF(0); - - if (!TOKENBUF_OK()) - goto error; - if (radix == 10) { - if (!js_strtod(cx, TOKENBUF_BASE(), &endptr, &dval)) { - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_OUT_OF_MEMORY); - goto error; - } - } else { - if (!js_strtointeger(cx, TOKENBUF_BASE(), &endptr, radix, &dval)) { - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_OUT_OF_MEMORY); - goto error; - } - } - tp->t_dval = dval; - tt = TOK_NUMBER; - goto out; - } - - if (c == '"' || c == '\'') { - qc = c; - INIT_TOKENBUF(); - while ((c = GetChar(ts)) != qc) { - if (c == '\n' || c == EOF) { - UngetChar(ts, c); - js_ReportCompileErrorNumber(cx, ts, - JSREPORT_TS | JSREPORT_ERROR, - JSMSG_UNTERMINATED_STRING); - goto error; - } - if (c == '\\') { - switch (c = GetChar(ts)) { - case 'b': c = '\b'; break; - case 'f': c = '\f'; break; - case 'n': c = '\n'; break; - case 'r': c = '\r'; break; - case 't': c = '\t'; break; - case 'v': c = '\v'; break; - - default: - if ('0' <= c && c < '8') { - int32 val = JS7_UNDEC(c); - - c = PeekChar(ts); - if ('0' <= c && c < '8') { - val = 8 * val + JS7_UNDEC(c); - GetChar(ts); - c = PeekChar(ts); - if ('0' <= c && c < '8') { - int32 save = val; - val = 8 * val + JS7_UNDEC(c); - if (val <= 0377) - GetChar(ts); - else - val = save; - } - } - - c = (jschar)val; - } else if (c == 'u') { - jschar cp[4]; - if (PeekChars(ts, 4, cp) && - JS7_ISHEX(cp[0]) && JS7_ISHEX(cp[1]) && - JS7_ISHEX(cp[2]) && JS7_ISHEX(cp[3])) { - c = (((((JS7_UNHEX(cp[0]) << 4) - + JS7_UNHEX(cp[1])) << 4) - + JS7_UNHEX(cp[2])) << 4) - + JS7_UNHEX(cp[3]); - SkipChars(ts, 4); - } - } else if (c == 'x') { - jschar cp[2]; - if (PeekChars(ts, 2, cp) && - JS7_ISHEX(cp[0]) && JS7_ISHEX(cp[1])) { - c = (JS7_UNHEX(cp[0]) << 4) + JS7_UNHEX(cp[1]); - SkipChars(ts, 2); - } - } else if (c == '\n' && JS_VERSION_IS_ECMA(cx)) { - /* ECMA follows C by removing escaped newlines. */ - continue; - } - break; - } - } - ADD_TO_TOKENBUF(c); - } - atom = TOKENBUF_TO_ATOM(); - if (!atom) - goto error; - tp->pos.end.lineno = (uint16)ts->lineno; - tp->t_op = JSOP_STRING; - tp->t_atom = atom; - tt = TOK_STRING; - goto out; - } - - switch (c) { - case '\n': tt = TOK_EOL; goto eol_out; - case ';': tt = TOK_SEMI; break; - case '[': tt = TOK_LB; break; - case ']': tt = TOK_RB; break; - case '{': tt = TOK_LC; break; - case '}': tt = TOK_RC; break; - case '(': tt = TOK_LP; break; - case ')': tt = TOK_RP; break; - case ',': tt = TOK_COMMA; break; - case '?': tt = TOK_HOOK; break; - - case '.': -#if JS_HAS_XML_SUPPORT - if (MatchChar(ts, c)) - tt = TOK_DBLDOT; - else -#endif - tt = TOK_DOT; - break; - - case ':': -#if JS_HAS_XML_SUPPORT - if (MatchChar(ts, c)) { - tt = TOK_DBLCOLON; - break; - } -#endif - /* - * Default so compiler can modify to JSOP_GETTER if 'p getter: v' in an - * object initializer, likewise for setter. - */ - tp->t_op = JSOP_NOP; - tt = TOK_COLON; - break; - - case '|': - if (MatchChar(ts, c)) { - tt = TOK_OR; - } else if (MatchChar(ts, '=')) { - tp->t_op = JSOP_BITOR; - tt = TOK_ASSIGN; - } else { - tt = TOK_BITOR; - } - break; - - case '^': - if (MatchChar(ts, '=')) { - tp->t_op = JSOP_BITXOR; - tt = TOK_ASSIGN; - } else { - tt = TOK_BITXOR; - } - break; - - case '&': - if (MatchChar(ts, c)) { - tt = TOK_AND; - } else if (MatchChar(ts, '=')) { - tp->t_op = JSOP_BITAND; - tt = TOK_ASSIGN; - } else { - tt = TOK_BITAND; - } - break; - - case '=': - if (MatchChar(ts, c)) { -#if JS_HAS_TRIPLE_EQOPS - tp->t_op = MatchChar(ts, c) ? JSOP_NEW_EQ : (JSOp)cx->jsop_eq; -#else - tp->t_op = cx->jsop_eq; -#endif - tt = TOK_EQOP; - } else { - tp->t_op = JSOP_NOP; - tt = TOK_ASSIGN; - } - break; - - case '!': - if (MatchChar(ts, '=')) { -#if JS_HAS_TRIPLE_EQOPS - tp->t_op = MatchChar(ts, '=') ? JSOP_NEW_NE : (JSOp)cx->jsop_ne; -#else - tp->t_op = cx->jsop_ne; -#endif - tt = TOK_EQOP; - } else { - tp->t_op = JSOP_NOT; - tt = TOK_UNARYOP; - } - break; - -#if JS_HAS_XML_SUPPORT - case '@': - tt = TOK_AT; - break; -#endif - - case '<': -#if JS_HAS_XML_SUPPORT - /* - * After much testing, it's clear that Postel's advice to protocol - * designers ("be liberal in what you accept, and conservative in what - * you send") invites a natural-law repercussion for JS as "protocol": - * - * "If you are liberal in what you accept, others will utterly fail to - * be conservative in what they send." - * - * Which means you will get within every //-style comment unless we have to. So we set - * TSF_IN_HTML_COMMENT when a either on a clean line, or - * only if (ts->flags & TSF_IN_HTML_COMMENT), in a //-style comment. - * - * This still works as before given a malformed comment hiding hack such as: - * - * - * - * It does not cope with malformed comment hiding hacks where --> is hidden - * by C-style comments, or on a dirty line. Such cases are already broken. - */ -#define TSF_IN_HTML_COMMENT 0x2000 - -/* Unicode separators that are treated as line terminators, in addition to \n, \r */ -#define LINE_SEPARATOR 0x2028 -#define PARA_SEPARATOR 0x2029 - -/* - * Create a new token stream, either from an input buffer or from a file. - * Return null on file-open or memory-allocation failure. - * - * NB: All of js_New{,Buffer,File}TokenStream() return a pointer to transient - * memory in the current context's temp pool. This memory is deallocated via - * JS_ARENA_RELEASE() after parsing is finished. - */ -extern JSTokenStream * -js_NewTokenStream(JSContext *cx, const jschar *base, size_t length, - const char *filename, uintN lineno, JSPrincipals *principals); - -extern JS_FRIEND_API(JSTokenStream *) -js_NewBufferTokenStream(JSContext *cx, const jschar *base, size_t length); - -extern JS_FRIEND_API(JSTokenStream *) -js_NewFileTokenStream(JSContext *cx, const char *filename, FILE *defaultfp); - -extern JS_FRIEND_API(JSBool) -js_CloseTokenStream(JSContext *cx, JSTokenStream *ts); - -extern JS_FRIEND_API(int) -js_fgets(char *buf, int size, FILE *file); - -/* - * Initialize the scanner, installing JS keywords into cx's global scope. - */ -extern JSBool -js_InitScanner(JSContext *cx); - -/* - * Friend-exported API entry point to call a mapping function on each reserved - * identifier in the scanner's keyword table. - */ -extern JS_FRIEND_API(void) -js_MapKeywords(void (*mapfun)(const char *)); - -/* - * Report a compile-time error by its number, using ts or cg to show context. - * Return true for a warning, false for an error. - */ -extern JSBool -js_ReportCompileErrorNumber(JSContext *cx, void *handle, uintN flags, - uintN errorNumber, ...); - -extern JSBool -js_ReportCompileErrorNumberUC(JSContext *cx, void *handle, uintN flags, - uintN errorNumber, ...); - -/* Steal some JSREPORT_* bits (see jsapi.h) to tell handle's type. */ -#define JSREPORT_HANDLE 0x300 -#define JSREPORT_TS 0x000 -#define JSREPORT_CG 0x100 -#define JSREPORT_PN 0x200 - -/* - * Look ahead one token and return its type. - */ -extern JSTokenType -js_PeekToken(JSContext *cx, JSTokenStream *ts); - -extern JSTokenType -js_PeekTokenSameLine(JSContext *cx, JSTokenStream *ts); - -/* - * Get the next token from ts. - */ -extern JSTokenType -js_GetToken(JSContext *cx, JSTokenStream *ts); - -/* - * Push back the last scanned token onto ts. - */ -extern void -js_UngetToken(JSTokenStream *ts); - -/* - * Get the next token from ts if its type is tt. - */ -extern JSBool -js_MatchToken(JSContext *cx, JSTokenStream *ts, JSTokenType tt); - -JS_END_EXTERN_C - -#endif /* jsscan_h___ */ diff --git a/lib/javascript/jsscope.c b/lib/javascript/jsscope.c deleted file mode 100644 index 4f951238..00000000 --- a/lib/javascript/jsscope.c +++ /dev/null @@ -1,1702 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JS symbol tables. - */ -#include "jsstddef.h" -#include -#include -#include "jstypes.h" -#include "jsarena.h" -#include "jsbit.h" -#include "jsclist.h" -#include "jsdhash.h" -#include "jsutil.h" /* Added by JSIFY */ -#include "jsapi.h" -#include "jsatom.h" -#include "jscntxt.h" -#include "jsdbgapi.h" -#include "jslock.h" -#include "jsnum.h" -#include "jsscope.h" -#include "jsstr.h" - -JSScope * -js_GetMutableScope(JSContext *cx, JSObject *obj) -{ - JSScope *scope, *newscope; - - scope = OBJ_SCOPE(obj); - JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, scope)); - if (scope->object == obj) - return scope; - newscope = js_NewScope(cx, 0, scope->map.ops, LOCKED_OBJ_GET_CLASS(obj), - obj); - if (!newscope) - return NULL; - JS_LOCK_SCOPE(cx, newscope); - obj->map = js_HoldObjectMap(cx, &newscope->map); - scope = (JSScope *) js_DropObjectMap(cx, &scope->map, obj); - JS_TRANSFER_SCOPE_LOCK(cx, scope, newscope); - return newscope; -} - -/* - * JSScope uses multiplicative hashing, _a la_ jsdhash.[ch], but specialized - * to minimize footprint. But if a scope has fewer than SCOPE_HASH_THRESHOLD - * entries, we use linear search and avoid allocating scope->table. - */ -#define SCOPE_HASH_THRESHOLD 6 -#define MIN_SCOPE_SIZE_LOG2 4 -#define MIN_SCOPE_SIZE JS_BIT(MIN_SCOPE_SIZE_LOG2) -#define SCOPE_TABLE_NBYTES(n) ((n) * sizeof(JSScopeProperty *)) - -static void -InitMinimalScope(JSScope *scope) -{ - scope->hashShift = JS_DHASH_BITS - MIN_SCOPE_SIZE_LOG2; - scope->entryCount = scope->removedCount = 0; - scope->table = NULL; - scope->lastProp = NULL; -} - -static JSBool -CreateScopeTable(JSContext *cx, JSScope *scope, JSBool report) -{ - int sizeLog2; - JSScopeProperty *sprop, **spp; - - JS_ASSERT(!scope->table); - JS_ASSERT(scope->lastProp); - - if (scope->entryCount > SCOPE_HASH_THRESHOLD) { - /* - * Ouch: calloc failed at least once already -- let's try again, - * overallocating to hold at least twice the current population. - */ - sizeLog2 = JS_CeilingLog2(2 * scope->entryCount); - scope->hashShift = JS_DHASH_BITS - sizeLog2; - } else { - JS_ASSERT(scope->hashShift == JS_DHASH_BITS - MIN_SCOPE_SIZE_LOG2); - sizeLog2 = MIN_SCOPE_SIZE_LOG2; - } - - scope->table = (JSScopeProperty **) - calloc(JS_BIT(sizeLog2), sizeof(JSScopeProperty *)); - if (!scope->table) { - if (report) - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - - /* Racy update after calloc, to help keep the GC self-scheduled well. */ - cx->runtime->gcMallocBytes += JS_BIT(sizeLog2) * sizeof(JSScopeProperty *); - - scope->hashShift = JS_DHASH_BITS - sizeLog2; - for (sprop = scope->lastProp; sprop; sprop = sprop->parent) { - spp = js_SearchScope(scope, sprop->id, JS_TRUE); - SPROP_STORE_PRESERVING_COLLISION(spp, sprop); - } - return JS_TRUE; -} - -JSScope * -js_NewScope(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops, JSClass *clasp, - JSObject *obj) -{ - JSScope *scope; - - scope = (JSScope *) JS_malloc(cx, sizeof(JSScope)); - if (!scope) - return NULL; - - js_InitObjectMap(&scope->map, nrefs, ops, clasp); - scope->object = obj; - scope->flags = 0; - scope->dswIndex = 0; - InitMinimalScope(scope); - -#ifdef JS_THREADSAFE - scope->ownercx = cx; - memset(&scope->lock, 0, sizeof scope->lock); - - /* - * Set u.link = NULL, not u.count = 0, in case the target architecture's - * null pointer has a non-zero integer representation. - */ - scope->u.link = NULL; - -#ifdef DEBUG - scope->file[0] = scope->file[1] = scope->file[2] = scope->file[3] = NULL; - scope->line[0] = scope->line[1] = scope->line[2] = scope->line[3] = 0; -#endif -#endif - - JS_RUNTIME_METER(cx->runtime, liveScopes); - JS_RUNTIME_METER(cx->runtime, totalScopes); - return scope; -} - -#ifdef DEBUG_SCOPE_COUNT -extern void -js_unlog_scope(JSScope *scope); -#endif - -void -js_DestroyScope(JSContext *cx, JSScope *scope) -{ -#ifdef DEBUG_SCOPE_COUNT - js_unlog_scope(scope); -#endif - -#ifdef JS_THREADSAFE - /* Scope must be single-threaded at this point, so set scope->ownercx. */ - JS_ASSERT(scope->u.count == 0); - scope->ownercx = cx; - js_FinishLock(&scope->lock); -#endif - if (scope->table) - JS_free(cx, scope->table); - -#ifdef DEBUG - JS_LOCK_RUNTIME_VOID(cx->runtime, - cx->runtime->liveScopeProps -= scope->entryCount); -#endif - JS_RUNTIME_UNMETER(cx->runtime, liveScopes); - JS_free(cx, scope); -} - -#ifdef DUMP_SCOPE_STATS -typedef struct JSScopeStats { - jsrefcount searches; - jsrefcount steps; - jsrefcount hits; - jsrefcount misses; - jsrefcount stepHits; - jsrefcount stepMisses; - jsrefcount adds; - jsrefcount redundantAdds; - jsrefcount addFailures; - jsrefcount changeFailures; - jsrefcount compresses; - jsrefcount grows; - jsrefcount removes; - jsrefcount removeFrees; - jsrefcount uselessRemoves; - jsrefcount shrinks; -} JSScopeStats; - -JS_FRIEND_DATA(JSScopeStats) js_scope_stats; - -# define METER(x) JS_ATOMIC_INCREMENT(&js_scope_stats.x) -#else -# define METER(x) /* nothing */ -#endif - -/* - * Double hashing needs the second hash code to be relatively prime to table - * size, so we simply make hash2 odd. The inputs to multiplicative hash are - * the golden ratio, expressed as a fixed-point 32 bit fraction, and the int - * property index or named property's atom number (observe that most objects - * have either no indexed properties, or almost all indexed and a few names, - * so collisions between index and atom number are unlikely). - */ -#define SCOPE_HASH0(id) (HASH_ID(id) * JS_GOLDEN_RATIO) -#define SCOPE_HASH1(hash0,shift) ((hash0) >> (shift)) -#define SCOPE_HASH2(hash0,log2,shift) ((((hash0) << (log2)) >> (shift)) | 1) - -JS_FRIEND_API(JSScopeProperty **) -js_SearchScope(JSScope *scope, jsid id, JSBool adding) -{ - JSHashNumber hash0, hash1, hash2; - int hashShift, sizeLog2; - JSScopeProperty *stored, *sprop, **spp, **firstRemoved; - uint32 sizeMask; - - METER(searches); - if (!scope->table) { - /* Not enough properties to justify hashing: search from lastProp. */ - JS_ASSERT(!SCOPE_HAD_MIDDLE_DELETE(scope)); - for (spp = &scope->lastProp; (sprop = *spp); spp = &sprop->parent) { - if (sprop->id == id) { - METER(hits); - return spp; - } - } - METER(misses); - return spp; - } - - /* Compute the primary hash address. */ - hash0 = SCOPE_HASH0(id); - hashShift = scope->hashShift; - hash1 = SCOPE_HASH1(hash0, hashShift); - spp = scope->table + hash1; - - /* Miss: return space for a new entry. */ - stored = *spp; - if (SPROP_IS_FREE(stored)) { - METER(misses); - return spp; - } - - /* Hit: return entry. */ - sprop = SPROP_CLEAR_COLLISION(stored); - if (sprop && sprop->id == id) { - METER(hits); - return spp; - } - - /* Collision: double hash. */ - sizeLog2 = JS_DHASH_BITS - hashShift; - hash2 = SCOPE_HASH2(hash0, sizeLog2, hashShift); - sizeMask = JS_BITMASK(sizeLog2); - - /* Save the first removed entry pointer so we can recycle it if adding. */ - if (SPROP_IS_REMOVED(stored)) { - firstRemoved = spp; - } else { - firstRemoved = NULL; - if (adding && !SPROP_HAD_COLLISION(stored)) - SPROP_FLAG_COLLISION(spp, sprop); - } - - for (;;) { - METER(steps); - hash1 -= hash2; - hash1 &= sizeMask; - spp = scope->table + hash1; - - stored = *spp; - if (SPROP_IS_FREE(stored)) { - METER(stepMisses); - return (adding && firstRemoved) ? firstRemoved : spp; - } - - sprop = SPROP_CLEAR_COLLISION(stored); - if (sprop && sprop->id == id) { - METER(stepHits); - return spp; - } - - if (SPROP_IS_REMOVED(stored)) { - if (!firstRemoved) - firstRemoved = spp; - } else { - if (adding && !SPROP_HAD_COLLISION(stored)) - SPROP_FLAG_COLLISION(spp, sprop); - } - } - - /* NOTREACHED */ - return NULL; -} - -static JSBool -ChangeScope(JSContext *cx, JSScope *scope, int change) -{ - int oldlog2, newlog2; - uint32 oldsize, newsize, nbytes; - JSScopeProperty **table, **oldtable, **spp, **oldspp, *sprop; - - /* Grow, shrink, or compress by changing scope->table. */ - oldlog2 = JS_DHASH_BITS - scope->hashShift; - newlog2 = oldlog2 + change; - oldsize = JS_BIT(oldlog2); - newsize = JS_BIT(newlog2); - nbytes = SCOPE_TABLE_NBYTES(newsize); - table = (JSScopeProperty **) calloc(nbytes, 1); - if (!table) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - - /* Now that we have a new table allocated, update scope members. */ - scope->hashShift = JS_DHASH_BITS - newlog2; - scope->removedCount = 0; - oldtable = scope->table; - scope->table = table; - - /* Treat the above calloc as a JS_malloc, to match CreateScopeTable. */ - cx->runtime->gcMallocBytes += nbytes; - - /* Copy only live entries, leaving removed and free ones behind. */ - for (oldspp = oldtable; oldsize != 0; oldspp++) { - sprop = SPROP_FETCH(oldspp); - if (sprop) { - spp = js_SearchScope(scope, sprop->id, JS_TRUE); - JS_ASSERT(SPROP_IS_FREE(*spp)); - *spp = sprop; - } - oldsize--; - } - - /* Finally, free the old table storage. */ - JS_free(cx, oldtable); - return JS_TRUE; -} - -/* - * Take care to exclude the mark and duplicate bits, in case we're called from - * the GC, or we are searching for a property that has not yet been flagged as - * a duplicate when making a duplicate formal parameter. - */ -#define SPROP_FLAGS_NOT_MATCHED (SPROP_MARK | SPROP_IS_DUPLICATE) - -JS_STATIC_DLL_CALLBACK(JSDHashNumber) -js_HashScopeProperty(JSDHashTable *table, const void *key) -{ - const JSScopeProperty *sprop = (const JSScopeProperty *)key; - JSDHashNumber hash; - JSPropertyOp gsop; - - /* Accumulate from least to most random so the low bits are most random. */ - hash = 0; - gsop = sprop->getter; - if (gsop) - hash = (hash >> (JS_DHASH_BITS - 4)) ^ (hash << 4) ^ (jsword)gsop; - gsop = sprop->setter; - if (gsop) - hash = (hash >> (JS_DHASH_BITS - 4)) ^ (hash << 4) ^ (jsword)gsop; - - hash = (hash >> (JS_DHASH_BITS - 4)) ^ (hash << 4) - ^ (sprop->flags & ~SPROP_FLAGS_NOT_MATCHED); - - hash = (hash >> (JS_DHASH_BITS - 4)) ^ (hash << 4) ^ sprop->attrs; - hash = (hash >> (JS_DHASH_BITS - 4)) ^ (hash << 4) ^ sprop->shortid; - hash = (hash >> (JS_DHASH_BITS - 4)) ^ (hash << 4) ^ sprop->slot; - hash = (hash >> (JS_DHASH_BITS - 4)) ^ (hash << 4) ^ sprop->id; - return hash; -} - -#define SPROP_MATCH(sprop, child) \ - SPROP_MATCH_PARAMS(sprop, (child)->id, (child)->getter, (child)->setter, \ - (child)->slot, (child)->attrs, (child)->flags, \ - (child)->shortid) - -#define SPROP_MATCH_PARAMS(sprop, aid, agetter, asetter, aslot, aattrs, \ - aflags, ashortid) \ - ((sprop)->id == (aid) && \ - SPROP_MATCH_PARAMS_AFTER_ID(sprop, agetter, asetter, aslot, aattrs, \ - aflags, ashortid)) - -#define SPROP_MATCH_PARAMS_AFTER_ID(sprop, agetter, asetter, aslot, aattrs, \ - aflags, ashortid) \ - ((sprop)->getter == (agetter) && \ - (sprop)->setter == (asetter) && \ - (sprop)->slot == (aslot) && \ - (sprop)->attrs == (aattrs) && \ - (((sprop)->flags ^ (aflags)) & ~SPROP_FLAGS_NOT_MATCHED) == 0 && \ - (sprop)->shortid == (ashortid)) - -JS_STATIC_DLL_CALLBACK(JSBool) -js_MatchScopeProperty(JSDHashTable *table, - const JSDHashEntryHdr *hdr, - const void *key) -{ - const JSPropertyTreeEntry *entry = (const JSPropertyTreeEntry *)hdr; - const JSScopeProperty *sprop = entry->child; - const JSScopeProperty *kprop = (const JSScopeProperty *)key; - - return SPROP_MATCH(sprop, kprop); -} - -static const JSDHashTableOps PropertyTreeHashOps = { - JS_DHashAllocTable, - JS_DHashFreeTable, - JS_DHashGetKeyStub, - js_HashScopeProperty, - js_MatchScopeProperty, - JS_DHashMoveEntryStub, - JS_DHashClearEntryStub, - JS_DHashFinalizeStub, - NULL -}; - -/* - * A property tree node on rt->propertyFreeList overlays the following prefix - * struct on JSScopeProperty. - */ -typedef struct FreeNode { - jsid id; - JSScopeProperty *next; - JSScopeProperty **prevp; -} FreeNode; - -#define FREENODE(sprop) ((FreeNode *) (sprop)) - -#define FREENODE_INSERT(list, sprop) \ - JS_BEGIN_MACRO \ - FREENODE(sprop)->next = (list); \ - FREENODE(sprop)->prevp = &(list); \ - if (list) \ - FREENODE(list)->prevp = &FREENODE(sprop)->next; \ - (list) = (sprop); \ - JS_END_MACRO - -#define FREENODE_REMOVE(sprop) \ - JS_BEGIN_MACRO \ - *FREENODE(sprop)->prevp = FREENODE(sprop)->next; \ - if (FREENODE(sprop)->next) \ - FREENODE(FREENODE(sprop)->next)->prevp = FREENODE(sprop)->prevp; \ - JS_END_MACRO - -/* NB: Called with the runtime lock held. */ -static JSScopeProperty * -NewScopeProperty(JSRuntime *rt) -{ - JSScopeProperty *sprop; - - sprop = rt->propertyFreeList; - if (sprop) { - FREENODE_REMOVE(sprop); - } else { - JS_ARENA_ALLOCATE_CAST(sprop, JSScopeProperty *, - &rt->propertyArenaPool, - sizeof(JSScopeProperty)); - if (!sprop) - return NULL; - } - - JS_RUNTIME_METER(rt, livePropTreeNodes); - JS_RUNTIME_METER(rt, totalPropTreeNodes); - return sprop; -} - -#define CHUNKY_KIDS_TAG ((jsuword)1) -#define KIDS_IS_CHUNKY(kids) ((jsuword)(kids) & CHUNKY_KIDS_TAG) -#define KIDS_TO_CHUNK(kids) ((PropTreeKidsChunk *) \ - ((jsuword)(kids) & ~CHUNKY_KIDS_TAG)) -#define CHUNK_TO_KIDS(chunk) ((JSScopeProperty *) \ - ((jsuword)(chunk) | CHUNKY_KIDS_TAG)) -#define MAX_KIDS_PER_CHUNK 10 - -typedef struct PropTreeKidsChunk PropTreeKidsChunk; - -struct PropTreeKidsChunk { - JSScopeProperty *kids[MAX_KIDS_PER_CHUNK]; - PropTreeKidsChunk *next; -}; - -static PropTreeKidsChunk * -NewPropTreeKidsChunk(JSRuntime *rt) -{ - PropTreeKidsChunk *chunk; - - chunk = calloc(1, sizeof *chunk); - if (!chunk) - return NULL; - JS_ASSERT(((jsuword)chunk & CHUNKY_KIDS_TAG) == 0); - JS_RUNTIME_METER(rt, propTreeKidsChunks); - return chunk; -} - -static void -DestroyPropTreeKidsChunk(JSRuntime *rt, PropTreeKidsChunk *chunk) -{ - JS_RUNTIME_UNMETER(rt, propTreeKidsChunks); - free(chunk); -} - -/* NB: Called with the runtime lock held. */ -static JSBool -InsertPropertyTreeChild(JSRuntime *rt, JSScopeProperty *parent, - JSScopeProperty *child, PropTreeKidsChunk *sweptChunk) -{ - JSPropertyTreeEntry *entry; - JSScopeProperty **childp, *kids, *sprop; - PropTreeKidsChunk *chunk, **chunkp; - uintN i; - - JS_ASSERT(!parent || child->parent != parent); - - if (!parent) { - entry = (JSPropertyTreeEntry *) - JS_DHashTableOperate(&rt->propertyTreeHash, child, JS_DHASH_ADD); - if (!entry) - return JS_FALSE; - childp = &entry->child; - sprop = *childp; - if (!sprop) { - *childp = child; - } else { - /* - * A "Duplicate child" case. - * - * We can't do away with child, as at least one live scope entry - * still points at it. What's more, that scope's lastProp chains - * through an ancestor line to reach child, and js_Enumerate and - * others count on this linkage. We must leave child out of the - * hash table, and not require it to be there when we eventually - * GC it (see RemovePropertyTreeChild, below). - * - * It is necessary to leave the duplicate child out of the hash - * table to preserve entry uniqueness. It is safe to leave the - * child out of the hash table (unlike the duplicate child cases - * below), because the child's parent link will be null, which - * can't dangle. - */ - JS_ASSERT(sprop != child && SPROP_MATCH(sprop, child)); - JS_RUNTIME_METER(rt, duplicatePropTreeNodes); - } - } else { - childp = &parent->kids; - kids = *childp; - if (kids) { - if (KIDS_IS_CHUNKY(kids)) { - chunk = KIDS_TO_CHUNK(kids); - do { - for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) { - childp = &chunk->kids[i]; - sprop = *childp; - if (!sprop) - goto insert; - - JS_ASSERT(sprop != child); - if (SPROP_MATCH(sprop, child)) { - /* - * Duplicate child, see comment above. In this - * case, we must let the duplicate be inserted at - * this level in the tree, so we keep iterating, - * looking for an empty slot in which to insert. - */ - JS_ASSERT(sprop != child); - JS_RUNTIME_METER(rt, duplicatePropTreeNodes); - } - } - chunkp = &chunk->next; - } while ((chunk = *chunkp) != NULL); - - if (sweptChunk) { - chunk = sweptChunk; - } else { - chunk = NewPropTreeKidsChunk(rt); - if (!chunk) - return JS_FALSE; - } - *chunkp = chunk; - childp = &chunk->kids[0]; - } else { - sprop = kids; - JS_ASSERT(sprop != child); - if (SPROP_MATCH(sprop, child)) { - /* - * Duplicate child, see comment above. Once again, we - * must let duplicates created by deletion pile up in a - * kids-chunk-list, in order to find them when sweeping - * and thereby avoid dangling parent pointers. - */ - JS_RUNTIME_METER(rt, duplicatePropTreeNodes); - } - - chunk = NewPropTreeKidsChunk(rt); - if (!chunk) - return JS_FALSE; - parent->kids = CHUNK_TO_KIDS(chunk); - chunk->kids[0] = sprop; - childp = &chunk->kids[1]; - } - } - insert: - *childp = child; - } - - child->parent = parent; - return JS_TRUE; -} - -/* NB: Called with the runtime lock held. */ -static void -RemovePropertyTreeChild(JSRuntime *rt, JSScopeProperty *child) -{ - JSPropertyTreeEntry *entry; - JSScopeProperty *parent, *kids, *kid; - PropTreeKidsChunk *list, *chunk, **chunkp, *lastChunk; - uintN i, j; - - parent = child->parent; - if (!parent) { - /* - * Don't remove child if it is not in rt->propertyTreeHash, but only - * matches a root child in the table that has compatible members. See - * the "Duplicate child" comments in InsertPropertyTreeChild, above. - */ - entry = (JSPropertyTreeEntry *) - JS_DHashTableOperate(&rt->propertyTreeHash, child, JS_DHASH_LOOKUP); - - if (entry->child == child) - JS_DHashTableRawRemove(&rt->propertyTreeHash, &entry->hdr); - } else { - kids = parent->kids; - if (KIDS_IS_CHUNKY(kids)) { - list = chunk = KIDS_TO_CHUNK(kids); - chunkp = &list; - - do { - for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) { - if (chunk->kids[i] == child) { - lastChunk = chunk; - if (!lastChunk->next) { - j = i + 1; - } else { - j = 0; - do { - chunkp = &lastChunk->next; - lastChunk = *chunkp; - } while (lastChunk->next); - } - for (; j < MAX_KIDS_PER_CHUNK; j++) { - if (!lastChunk->kids[j]) - break; - } - --j; - if (chunk != lastChunk || j > i) - chunk->kids[i] = lastChunk->kids[j]; - lastChunk->kids[j] = NULL; - if (j == 0) { - *chunkp = NULL; - if (!list) - parent->kids = NULL; - DestroyPropTreeKidsChunk(rt, lastChunk); - } - return; - } - } - - chunkp = &chunk->next; - } while ((chunk = *chunkp) != NULL); - } else { - kid = kids; - if (kid == child) - parent->kids = NULL; - } - } -} - -/* - * Called *without* the runtime lock held, this function acquires that lock - * only when inserting a new child. Thus there may be races to find or add - * a node that result in duplicates. We expect such races to be rare! - */ -static JSScopeProperty * -GetPropertyTreeChild(JSContext *cx, JSScopeProperty *parent, - JSScopeProperty *child) -{ - JSRuntime *rt; - JSPropertyTreeEntry *entry; - JSScopeProperty *sprop; - PropTreeKidsChunk *chunk; - uintN i; - - rt = cx->runtime; - if (!parent) { - JS_LOCK_RUNTIME(rt); - - entry = (JSPropertyTreeEntry *) - JS_DHashTableOperate(&rt->propertyTreeHash, child, JS_DHASH_ADD); - if (!entry) - goto out_of_memory; - - sprop = entry->child; - if (sprop) - goto out; - } else { - /* - * Because chunks are appended at the end and never deleted except by - * the GC, we can search without taking the runtime lock. We may miss - * a matching sprop added by another thread, and make a duplicate one, - * but that is an unlikely, therefore small, cost. The property tree - * has extremely low fan-out below its root in popular embeddings with - * real-world workloads. - * - * If workload changes so as to increase fan-out significantly below - * the property tree root, we'll want to add another tag bit stored in - * parent->kids that indicates a JSDHashTable pointer. - */ - entry = NULL; - sprop = parent->kids; - if (sprop) { - if (KIDS_IS_CHUNKY(sprop)) { - chunk = KIDS_TO_CHUNK(sprop); - do { - for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) { - sprop = chunk->kids[i]; - if (!sprop) - goto not_found; - - if (SPROP_MATCH(sprop, child)) - return sprop; - } - } while ((chunk = chunk->next) != NULL); - } else { - if (SPROP_MATCH(sprop, child)) - return sprop; - } - } - - not_found: - JS_LOCK_RUNTIME(rt); - } - - sprop = NewScopeProperty(rt); - if (!sprop) - goto out_of_memory; - - sprop->id = child->id; - sprop->getter = child->getter; - sprop->setter = child->setter; - sprop->slot = child->slot; - sprop->attrs = child->attrs; - sprop->flags = child->flags; - sprop->shortid = child->shortid; - sprop->parent = sprop->kids = NULL; - if (!parent) { - entry->child = sprop; - } else { - if (!InsertPropertyTreeChild(rt, parent, sprop, NULL)) - goto out_of_memory; - } - -out: - JS_UNLOCK_RUNTIME(rt); - return sprop; - -out_of_memory: - JS_UNLOCK_RUNTIME(rt); - JS_ReportOutOfMemory(cx); - return NULL; -} - -#ifdef DEBUG_notbrendan -#define CHECK_ANCESTOR_LINE(scope, sparse) \ - JS_BEGIN_MACRO \ - if ((scope)->table) CheckAncestorLine(scope, sparse); \ - JS_END_MACRO - -static void -CheckAncestorLine(JSScope *scope, JSBool sparse) -{ - uint32 size; - JSScopeProperty **spp, **start, **end, *ancestorLine, *sprop, *aprop; - uint32 entryCount, ancestorCount; - - ancestorLine = SCOPE_LAST_PROP(scope); - if (ancestorLine) - JS_ASSERT(SCOPE_HAS_PROPERTY(scope, ancestorLine)); - - entryCount = 0; - size = SCOPE_CAPACITY(scope); - start = scope->table; - for (spp = start, end = start + size; spp < end; spp++) { - sprop = SPROP_FETCH(spp); - if (sprop) { - entryCount++; - for (aprop = ancestorLine; aprop; aprop = aprop->parent) { - if (aprop == sprop) - break; - } - JS_ASSERT(aprop); - } - } - JS_ASSERT(entryCount == scope->entryCount); - - ancestorCount = 0; - for (sprop = ancestorLine; sprop; sprop = sprop->parent) { - if (SCOPE_HAD_MIDDLE_DELETE(scope) && - !SCOPE_HAS_PROPERTY(scope, sprop)) { - JS_ASSERT(sparse || (sprop->flags & SPROP_IS_DUPLICATE)); - continue; - } - ancestorCount++; - } - JS_ASSERT(ancestorCount == scope->entryCount); -} -#else -#define CHECK_ANCESTOR_LINE(scope, sparse) /* nothing */ -#endif - -static void -ReportReadOnlyScope(JSContext *cx, JSScope *scope) -{ - JSString *str; - - str = js_ValueToString(cx, OBJECT_TO_JSVAL(scope->object)); - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_READ_ONLY, - str - ? JS_GetStringBytes(str) - : LOCKED_OBJ_GET_CLASS(scope->object)->name); -} - -JSScopeProperty * -js_AddScopeProperty(JSContext *cx, JSScope *scope, jsid id, - JSPropertyOp getter, JSPropertyOp setter, uint32 slot, - uintN attrs, uintN flags, intN shortid) -{ - JSScopeProperty **spp, *sprop, *overwriting, **spvec, **spp2, child; - uint32 size, splen, i; - int change; - - JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, scope)); - CHECK_ANCESTOR_LINE(scope, JS_TRUE); - - /* - * You can't add properties to a sealed scope. But note well that you can - * change property attributes in a sealed scope, even though that replaces - * a JSScopeProperty * in the scope's hash table -- but no id is added, so - * the scope remains sealed. - */ - if (SCOPE_IS_SEALED(scope)) { - ReportReadOnlyScope(cx, scope); - return NULL; - } - - /* - * Normalize stub getter and setter values for faster is-stub testing in - * the SPROP_CALL_[GS]ETTER macros. - */ - if (getter == JS_PropertyStub) - getter = NULL; - if (setter == JS_PropertyStub) - setter = NULL; - - /* - * Search for id in order to claim its entry, allocating a property tree - * node if one doesn't already exist for our parameters. - */ - spp = js_SearchScope(scope, id, JS_TRUE); - sprop = overwriting = SPROP_FETCH(spp); - if (!sprop) { - /* Check whether we need to grow, if the load factor is >= .75. */ - size = SCOPE_CAPACITY(scope); - if (scope->entryCount + scope->removedCount >= size - (size >> 2)) { - if (scope->removedCount >= size >> 2) { - METER(compresses); - change = 0; - } else { - METER(grows); - change = 1; - } - if (!ChangeScope(cx, scope, change) && - scope->entryCount + scope->removedCount == size - 1) { - METER(addFailures); - return NULL; - } - spp = js_SearchScope(scope, id, JS_TRUE); - JS_ASSERT(!SPROP_FETCH(spp)); - } - } else { - /* Property exists: js_SearchScope must have returned a valid entry. */ - JS_ASSERT(!SPROP_IS_REMOVED(*spp)); - - /* - * If all property members match, this is a redundant add and we can - * return early. If the caller wants to allocate a slot, but doesn't - * care which slot, copy sprop->slot into slot so we can match sprop, - * if all other members match. - */ - if (!(attrs & JSPROP_SHARED) && - slot == SPROP_INVALID_SLOT && - SPROP_HAS_VALID_SLOT(sprop, scope)) { - slot = sprop->slot; - } - if (SPROP_MATCH_PARAMS_AFTER_ID(sprop, getter, setter, slot, attrs, - flags, shortid)) { - METER(redundantAdds); - return sprop; - } - - /* - * Duplicate formal parameters require us to leave the old property - * on the ancestor line, so the decompiler can find it, even though - * its entry in scope->table is overwritten to point at a new property - * descending from the old one. The SPROP_IS_DUPLICATE flag helps us - * cope with the consequent disparity between ancestor line height and - * scope->entryCount. - */ - if (flags & SPROP_IS_DUPLICATE) { - sprop->flags |= SPROP_IS_DUPLICATE; - } else { - /* - * If we are clearing sprop to force an existing property to be - * overwritten (apart from a duplicate formal parameter), we must - * unlink it from the ancestor line at scope->lastProp, lazily if - * sprop is not lastProp. And we must remove the entry at *spp, - * precisely so the lazy "middle delete" fixup code further below - * won't find sprop in scope->table, in spite of sprop being on - * the ancestor line. - * - * When we finally succeed in finding or creating a new sprop - * and storing its pointer at *spp, we'll use the |overwriting| - * local saved when we first looked up id to decide whether we're - * indeed creating a new entry, or merely overwriting an existing - * property. - */ - if (sprop == SCOPE_LAST_PROP(scope)) { - do { - SCOPE_REMOVE_LAST_PROP(scope); - if (!SCOPE_HAD_MIDDLE_DELETE(scope)) - break; - sprop = SCOPE_LAST_PROP(scope); - } while (sprop && !SCOPE_HAS_PROPERTY(scope, sprop)); - } else if (!SCOPE_HAD_MIDDLE_DELETE(scope)) { - /* - * If we have no hash table yet, we need one now. The middle - * delete code is simple-minded that way! - */ - if (!scope->table) { - if (!CreateScopeTable(cx, scope, JS_TRUE)) - return NULL; - spp = js_SearchScope(scope, id, JS_TRUE); - sprop = overwriting = SPROP_FETCH(spp); - } - SCOPE_SET_MIDDLE_DELETE(scope); - } - } - - /* - * If we fail later on trying to find or create a new sprop, we will - * goto fail_overwrite and restore *spp from |overwriting|. Note that - * we don't bother to keep scope->removedCount in sync, because we'll - * fix up *spp and scope->entryCount shortly, no matter how control - * flow returns from this function. - */ - if (scope->table) - SPROP_STORE_PRESERVING_COLLISION(spp, NULL); - scope->entryCount--; - CHECK_ANCESTOR_LINE(scope, JS_TRUE); - sprop = NULL; - } - - if (!sprop) { - /* - * If properties were deleted from the middle of the list starting at - * scope->lastProp, we may need to fork the property tree and squeeze - * all deleted properties out of scope's ancestor line. Otherwise we - * risk adding a node with the same id as a "middle" node, violating - * the rule that properties along an ancestor line have distinct ids - * (unless flagged SPROP_IS_DUPLICATE). - */ - if (SCOPE_HAD_MIDDLE_DELETE(scope)) { - JS_ASSERT(scope->table); - CHECK_ANCESTOR_LINE(scope, JS_TRUE); - - splen = scope->entryCount; - if (splen == 0) { - JS_ASSERT(scope->lastProp == NULL); - } else { - /* - * Enumerate live entries in scope->table using a temporary - * vector, by walking the (possibly sparse, due to deletions) - * ancestor line from scope->lastProp. - */ - spvec = (JSScopeProperty **) - JS_malloc(cx, SCOPE_TABLE_NBYTES(splen)); - if (!spvec) - goto fail_overwrite; - i = splen; - sprop = SCOPE_LAST_PROP(scope); - JS_ASSERT(sprop); - do { - /* - * NB: test SCOPE_GET_PROPERTY, not SCOPE_HAS_PROPERTY -- - * the latter insists that sprop->id maps to sprop, while - * the former simply tests whether sprop->id is bound in - * scope. We must allow for duplicate formal parameters - * along the ancestor line, and fork them as needed. - */ - if (!SCOPE_GET_PROPERTY(scope, sprop->id)) - continue; - - JS_ASSERT(sprop != overwriting); - if (i == 0) { - /* - * If our original splen estimate, scope->entryCount, - * is less than the ancestor line height, there must - * be duplicate formal parameters in this (function - * object) scope. Count remaining ancestors in order - * to realloc spvec. - */ - JSScopeProperty *tmp = sprop; - do { - if (SCOPE_GET_PROPERTY(scope, tmp->id)) - i++; - } while ((tmp = tmp->parent) != NULL); - spp2 = (JSScopeProperty **) - JS_realloc(cx, spvec, SCOPE_TABLE_NBYTES(splen+i)); - if (!spp2) { - JS_free(cx, spvec); - goto fail_overwrite; - } - - spvec = spp2; - memmove(spvec + i, spvec, SCOPE_TABLE_NBYTES(splen)); - splen += i; - } - - spvec[--i] = sprop; - } while ((sprop = sprop->parent) != NULL); - JS_ASSERT(i == 0); - - /* - * Now loop forward through spvec, forking the property tree - * whenever we see a "parent gap" due to deletions from scope. - * NB: sprop is null on first entry to the loop body. - */ - do { - if (spvec[i]->parent == sprop) { - sprop = spvec[i]; - } else { - sprop = GetPropertyTreeChild(cx, sprop, spvec[i]); - if (!sprop) { - JS_free(cx, spvec); - goto fail_overwrite; - } - - spp2 = js_SearchScope(scope, sprop->id, JS_FALSE); - JS_ASSERT(SPROP_FETCH(spp2) == spvec[i]); - SPROP_STORE_PRESERVING_COLLISION(spp2, sprop); - } - } while (++i < splen); - JS_free(cx, spvec); - - /* - * Now sprop points to the last property in scope, where the - * ancestor line from sprop to the root is dense w.r.t. scope: - * it contains no nodes not mapped by scope->table, apart from - * any stinking ECMA-mandated duplicate formal parameters. - */ - scope->lastProp = sprop; - CHECK_ANCESTOR_LINE(scope, JS_FALSE); - JS_RUNTIME_METER(cx->runtime, middleDeleteFixups); - } - - SCOPE_CLR_MIDDLE_DELETE(scope); - } - - /* - * Aliases share another property's slot, passed in the |slot| param. - * Shared properties have no slot. Unshared properties that do not - * alias another property's slot get one here, but may lose it due to - * a JS_ClearScope call. - */ - if (!(flags & SPROP_IS_ALIAS)) { - if (attrs & JSPROP_SHARED) { - slot = SPROP_INVALID_SLOT; - } else { - /* - * We may have set slot from a nearly-matching sprop, above. - * If so, we're overwriting that nearly-matching sprop, so we - * can reuse its slot -- we don't need to allocate a new one. - * Callers should therefore pass SPROP_INVALID_SLOT for all - * non-alias, unshared property adds. - */ - if (slot != SPROP_INVALID_SLOT) - JS_ASSERT(overwriting); - else if (!js_AllocSlot(cx, scope->object, &slot)) - goto fail_overwrite; - } - } - - /* - * Check for a watchpoint on a deleted property; if one exists, change - * setter to js_watch_set. - * XXXbe this could get expensive with lots of watchpoints... - */ - if (!JS_CLIST_IS_EMPTY(&cx->runtime->watchPointList) && - js_FindWatchPoint(cx->runtime, scope, id)) { - setter = js_WrapWatchedSetter(cx, id, attrs, setter); - if (!setter) - goto fail_overwrite; - } - - /* Find or create a property tree node labeled by our arguments. */ - child.id = id; - child.getter = getter; - child.setter = setter; - child.slot = slot; - child.attrs = attrs; - child.flags = flags; - child.shortid = shortid; - sprop = GetPropertyTreeChild(cx, scope->lastProp, &child); - if (!sprop) - goto fail_overwrite; - - /* Store the tree node pointer in the table entry for id. */ - if (scope->table) - SPROP_STORE_PRESERVING_COLLISION(spp, sprop); - scope->entryCount++; - scope->lastProp = sprop; - CHECK_ANCESTOR_LINE(scope, JS_FALSE); - if (!overwriting) { - JS_RUNTIME_METER(cx->runtime, liveScopeProps); - JS_RUNTIME_METER(cx->runtime, totalScopeProps); - } - - /* - * If we reach the hashing threshold, try to allocate scope->table. - * If we can't (a rare event, preceded by swapping to death on most - * modern OSes), stick with linear search rather than whining about - * this little set-back. Therefore we must test !scope->table and - * scope->entryCount >= SCOPE_HASH_THRESHOLD, not merely whether the - * entry count just reached the threshold. - */ - if (!scope->table && scope->entryCount >= SCOPE_HASH_THRESHOLD) - (void) CreateScopeTable(cx, scope, JS_FALSE); - } - - METER(adds); - return sprop; - -fail_overwrite: - if (overwriting) { - /* - * We may or may not have forked overwriting out of scope's ancestor - * line, so we must check (the alternative is to set a flag above, but - * that hurts the common, non-error case). If we did fork overwriting - * out, we'll add it back at scope->lastProp. This means enumeration - * order can change due to a failure to overwrite an id. - * XXXbe very minor incompatibility - */ - for (sprop = SCOPE_LAST_PROP(scope); ; sprop = sprop->parent) { - if (!sprop) { - sprop = SCOPE_LAST_PROP(scope); - if (overwriting->parent == sprop) { - scope->lastProp = overwriting; - } else { - sprop = GetPropertyTreeChild(cx, sprop, overwriting); - if (sprop) { - JS_ASSERT(sprop != overwriting); - scope->lastProp = sprop; - } - overwriting = sprop; - } - break; - } - if (sprop == overwriting) - break; - } - if (overwriting) { - if (scope->table) - SPROP_STORE_PRESERVING_COLLISION(spp, overwriting); - scope->entryCount++; - } - CHECK_ANCESTOR_LINE(scope, JS_TRUE); - } - METER(addFailures); - return NULL; -} - -JSScopeProperty * -js_ChangeScopePropertyAttrs(JSContext *cx, JSScope *scope, - JSScopeProperty *sprop, uintN attrs, uintN mask, - JSPropertyOp getter, JSPropertyOp setter) -{ - JSScopeProperty child, *newsprop, **spp; - - CHECK_ANCESTOR_LINE(scope, JS_TRUE); - - /* Allow only shared (slot-less) => unshared (slot-full) transition. */ - attrs |= sprop->attrs & mask; - JS_ASSERT(!((attrs ^ sprop->attrs) & JSPROP_SHARED) || - !(attrs & JSPROP_SHARED)); - if (getter == JS_PropertyStub) - getter = NULL; - if (setter == JS_PropertyStub) - setter = NULL; - if (sprop->attrs == attrs && - sprop->getter == getter && - sprop->setter == setter) { - return sprop; - } - - child.id = sprop->id; - child.getter = getter; - child.setter = setter; - child.slot = sprop->slot; - child.attrs = attrs; - child.flags = sprop->flags; - child.shortid = sprop->shortid; - - if (SCOPE_LAST_PROP(scope) == sprop) { - /* - * Optimize the case where the last property added to scope is changed - * to have a different attrs, getter, or setter. In the last property - * case, we need not fork the property tree. But since we do not call - * js_AddScopeProperty, we may need to allocate a new slot directly. - */ - if ((sprop->attrs & JSPROP_SHARED) && !(attrs & JSPROP_SHARED)) { - JS_ASSERT(child.slot == SPROP_INVALID_SLOT); - if (!js_AllocSlot(cx, scope->object, &child.slot)) - return NULL; - } - - newsprop = GetPropertyTreeChild(cx, sprop->parent, &child); - if (newsprop) { - spp = js_SearchScope(scope, sprop->id, JS_FALSE); - JS_ASSERT(SPROP_FETCH(spp) == sprop); - - if (scope->table) - SPROP_STORE_PRESERVING_COLLISION(spp, newsprop); - scope->lastProp = newsprop; - CHECK_ANCESTOR_LINE(scope, JS_TRUE); - } - } else { - /* - * Let js_AddScopeProperty handle this |overwriting| case, including - * the conservation of sprop->slot (if it's valid). We must not call - * js_RemoveScopeProperty here, it will free a valid sprop->slot and - * js_AddScopeProperty won't re-allocate it. - */ - newsprop = js_AddScopeProperty(cx, scope, child.id, - child.getter, child.setter, child.slot, - child.attrs, child.flags, child.shortid); - } - -#ifdef DUMP_SCOPE_STATS - if (!newsprop) - METER(changeFailures); -#endif - return newsprop; -} - -JSBool -js_RemoveScopeProperty(JSContext *cx, JSScope *scope, jsid id) -{ - JSScopeProperty **spp, *stored, *sprop; - uint32 size; - - JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, scope)); - CHECK_ANCESTOR_LINE(scope, JS_TRUE); - if (SCOPE_IS_SEALED(scope)) { - ReportReadOnlyScope(cx, scope); - return JS_FALSE; - } - METER(removes); - - spp = js_SearchScope(scope, id, JS_FALSE); - stored = *spp; - sprop = SPROP_CLEAR_COLLISION(stored); - if (!sprop) { - METER(uselessRemoves); - return JS_TRUE; - } - - /* Convert from a list to a hash so we can handle "middle deletes". */ - if (!scope->table && sprop != scope->lastProp) { - if (!CreateScopeTable(cx, scope, JS_TRUE)) - return JS_FALSE; - spp = js_SearchScope(scope, id, JS_FALSE); - stored = *spp; - sprop = SPROP_CLEAR_COLLISION(stored); - } - - /* First, if sprop is unshared and not cleared, free its slot number. */ - if (SPROP_HAS_VALID_SLOT(sprop, scope)) - js_FreeSlot(cx, scope->object, sprop->slot); - - /* Next, remove id by setting its entry to a removed or free sentinel. */ - if (SPROP_HAD_COLLISION(stored)) { - JS_ASSERT(scope->table); - *spp = SPROP_REMOVED; - scope->removedCount++; - } else { - METER(removeFrees); - if (scope->table) - *spp = NULL; - } - scope->entryCount--; - JS_RUNTIME_UNMETER(cx->runtime, liveScopeProps); - - /* Update scope->lastProp directly, or set its deferred update flag. */ - if (sprop == SCOPE_LAST_PROP(scope)) { - do { - SCOPE_REMOVE_LAST_PROP(scope); - if (!SCOPE_HAD_MIDDLE_DELETE(scope)) - break; - sprop = SCOPE_LAST_PROP(scope); - } while (sprop && !SCOPE_HAS_PROPERTY(scope, sprop)); - } else if (!SCOPE_HAD_MIDDLE_DELETE(scope)) { - SCOPE_SET_MIDDLE_DELETE(scope); - } - CHECK_ANCESTOR_LINE(scope, JS_TRUE); - - /* Last, consider shrinking scope's table if its load factor is <= .25. */ - size = SCOPE_CAPACITY(scope); - if (size > MIN_SCOPE_SIZE && scope->entryCount <= size >> 2) { - METER(shrinks); - (void) ChangeScope(cx, scope, -1); - } - - return JS_TRUE; -} - -void -js_ClearScope(JSContext *cx, JSScope *scope) -{ - CHECK_ANCESTOR_LINE(scope, JS_TRUE); -#ifdef DEBUG - JS_LOCK_RUNTIME_VOID(cx->runtime, - cx->runtime->liveScopeProps -= scope->entryCount); -#endif - - if (scope->table) - free(scope->table); - SCOPE_CLR_MIDDLE_DELETE(scope); - InitMinimalScope(scope); -} - -#ifdef DUMP_SCOPE_STATS - -#include -#include - -uint32 js_nkids_max; -uint32 js_nkids_sum; -double js_nkids_sqsum; -uint32 js_nkids_hist[11]; - -static void -MeterKidCount(uintN nkids) -{ - if (nkids) { - js_nkids_sum += nkids; - js_nkids_sqsum += (double)nkids * nkids; - if (nkids > js_nkids_max) - js_nkids_max = nkids; - } - js_nkids_hist[JS_MIN(nkids, 10)]++; -} - -static void -MeterPropertyTree(JSScopeProperty *node) -{ - uintN i, nkids; - JSScopeProperty *kids, *kid; - PropTreeKidsChunk *chunk; - - nkids = 0; - kids = node->kids; - if (kids) { - if (KIDS_IS_CHUNKY(kids)) { - for (chunk = KIDS_TO_CHUNK(kids); chunk; chunk = chunk->next) { - for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) { - kid = chunk->kids[i]; - if (!kid) - break; - MeterPropertyTree(kid); - nkids++; - } - } - } else { - MeterPropertyTree(kids); - nkids = 1; - } - } - - MeterKidCount(nkids); -} - -JS_STATIC_DLL_CALLBACK(JSDHashOperator) -js_MeterPropertyTree(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number, - void *arg) -{ - JSPropertyTreeEntry *entry = (JSPropertyTreeEntry *)hdr; - - MeterPropertyTree(entry->child); - return JS_DHASH_NEXT; -} - -#include "jsprf.h" - -static void -DumpSubtree(JSScopeProperty *sprop, int level, FILE *fp) -{ - char buf[10]; - JSScopeProperty *kids, *kid; - PropTreeKidsChunk *chunk; - uintN i; - - fprintf(fp, "%*sid %s g/s %p/%p slot %lu attrs %x flags %x shortid %d\n", - level, "", - JSID_IS_ATOM(sprop->id) - ? JS_GetStringBytes(ATOM_TO_STRING(JSID_TO_ATOM(sprop->id))) - : JSID_IS_OBJECT(sprop->id) - ? js_ValueToPrintableString(cx, OBJECT_JSID_TO_JSVAL(sprop->id)) - : (JS_snprintf(buf, sizeof buf, "%ld", JSVAL_TO_INT(sprop->id)), - buf) - (void *) sprop->getter, (void *) sprop->setter, - (unsigned long) sprop->slot, sprop->attrs, sprop->flags, - sprop->shortid); - kids = sprop->kids; - if (kids) { - ++level; - if (KIDS_IS_CHUNKY(kids)) { - chunk = KIDS_TO_CHUNK(kids); - do { - for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) { - kid = chunk->kids[i]; - if (!kid) - break; - JS_ASSERT(kid->parent == sprop); - DumpSubtree(kid, level, fp); - } - } while ((chunk = chunk->next) != NULL); - } else { - kid = kids; - DumpSubtree(kid, level, fp); - } - } -} - -#endif /* DUMP_SCOPE_STATS */ - -void -js_SweepScopeProperties(JSRuntime *rt) -{ - JSArena **ap, *a; - JSScopeProperty *limit, *sprop, *parent, *kids, *kid; - uintN liveCount; - PropTreeKidsChunk *chunk, *nextChunk; - uintN i; - -#ifdef DUMP_SCOPE_STATS - uint32 livePropCapacity = 0, totalLiveCount = 0; - static FILE *logfp; - if (!logfp) - logfp = fopen("/tmp/proptree.stats", "a"); - - MeterKidCount(rt->propertyTreeHash.entryCount); - JS_DHashTableEnumerate(&rt->propertyTreeHash, js_MeterPropertyTree, NULL); - - { - double mean = 0.0, var = 0.0, sigma = 0.0; - double nodesum = rt->livePropTreeNodes; - double kidsum = js_nkids_sum; - if (nodesum > 0 && kidsum >= 0) { - mean = kidsum / nodesum; - var = nodesum * js_nkids_sqsum - kidsum * kidsum; - if (var < 0.0 || nodesum <= 1) - var = 0.0; - else - var /= nodesum * (nodesum - 1); - - /* Windows says sqrt(0.0) is "-1.#J" (?!) so we must test. */ - sigma = (var != 0.0) ? sqrt(var) : 0.0; - } - - fprintf(logfp, - "props %u nodes %g beta %g meankids %g sigma %g max %u", - rt->liveScopeProps, nodesum, nodesum / rt->liveScopeProps, - mean, sigma, js_nkids_max); - } - - fprintf(logfp, " histogram %u %u %u %u %u %u %u %u %u %u %u", - js_nkids_hist[0], js_nkids_hist[1], - js_nkids_hist[2], js_nkids_hist[3], - js_nkids_hist[4], js_nkids_hist[5], - js_nkids_hist[6], js_nkids_hist[7], - js_nkids_hist[8], js_nkids_hist[9], - js_nkids_hist[10]); - js_nkids_sum = js_nkids_max = 0; - js_nkids_sqsum = 0; - memset(js_nkids_hist, 0, sizeof js_nkids_hist); -#endif - - ap = &rt->propertyArenaPool.first.next; - while ((a = *ap) != NULL) { - limit = (JSScopeProperty *) a->avail; - liveCount = 0; - for (sprop = (JSScopeProperty *) a->base; sprop < limit; sprop++) { - /* If the id is null, sprop is already on the freelist. */ - if (sprop->id == JSVAL_NULL) - continue; - - /* If the mark bit is set, sprop is alive, so we skip it. */ - if (sprop->flags & SPROP_MARK) { - sprop->flags &= ~SPROP_MARK; - liveCount++; - continue; - } - - /* Ok, sprop is garbage to collect: unlink it from its parent. */ - RemovePropertyTreeChild(rt, sprop); - - /* - * Take care to reparent all sprop's kids to their grandparent. - * InsertPropertyTreeChild can potentially fail for two reasons: - * - * 1. If parent is null, insertion into the root property hash - * table may fail. We are forced to leave the kid out of the - * table (as can already happen with duplicates) but ensure - * that the kid's parent pointer is set to null. - * - * 2. If parent is non-null, allocation of a new KidsChunk can - * fail. To prevent this from happening, we allow sprops's own - * chunks to be reused by the grandparent, which removes the - * need for InsertPropertyTreeChild to malloc a new KidsChunk. - * - * We also require the grandparent to have either no kids or else - * chunky kids. A single non-chunky kid would force a new chunk to - * be malloced in some cases (if sprop had a single non-chunky - * kid, or a multiple of MAX_KIDS_PER_CHUNK kids). Note that - * RemovePropertyTreeChild never converts a single entry chunky - * kid back to a non-chunky kid, so we are assured of correct - * behaviour. - */ - kids = sprop->kids; - if (kids) { - sprop->kids = NULL; - parent = sprop->parent; - /* Validate that grandparent has no kids or chunky kids. */ - JS_ASSERT(!parent || !parent->kids || - KIDS_IS_CHUNKY(parent->kids)); - if (KIDS_IS_CHUNKY(kids)) { - chunk = KIDS_TO_CHUNK(kids); - do { - nextChunk = chunk->next; - chunk->next = NULL; - for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) { - kid = chunk->kids[i]; - if (!kid) - break; - JS_ASSERT(kid->parent == sprop); - - /* - * Clear a space in the kids array for possible - * re-use by InsertPropertyTreeChild. - */ - chunk->kids[i] = NULL; - if (!InsertPropertyTreeChild(rt, parent, kid, - chunk)) { - /* - * This can happen only if we failed to add an - * entry to the root property hash table. - */ - JS_ASSERT(!parent); - kid->parent = NULL; - } - } - if (!chunk->kids[0]) { - /* The chunk wasn't reused so we can free it */ - DestroyPropTreeKidsChunk(rt, chunk); - } - } while ((chunk = nextChunk) != NULL); - } else { - kid = kids; - if (!InsertPropertyTreeChild(rt, parent, kid, NULL)) { - /* - * The removal of sprop should have left a free space - * for kid to be inserted into parent, unless the root - * hash table was shrunk. In this case we allow for - * failure only when parent is null. - */ - JS_ASSERT(!parent); - kid->parent = NULL; - } - } - } - - /* Clear id so we know (above) that sprop is on the freelist. */ - sprop->id = JSVAL_NULL; - FREENODE_INSERT(rt->propertyFreeList, sprop); - JS_RUNTIME_UNMETER(rt, livePropTreeNodes); - } - - /* If a contains no live properties, return it to the malloc heap. */ - if (liveCount == 0) { - for (sprop = (JSScopeProperty *) a->base; sprop < limit; sprop++) - FREENODE_REMOVE(sprop); - JS_ARENA_DESTROY(&rt->propertyArenaPool, a, ap); - } else { -#ifdef DUMP_SCOPE_STATS - livePropCapacity += limit - (JSScopeProperty *) a->base; - totalLiveCount += liveCount; -#endif - ap = &a->next; - } - } - -#ifdef DUMP_SCOPE_STATS - fprintf(logfp, " arenautil %g%%\n", - (totalLiveCount * 100.0) / livePropCapacity); - fflush(logfp); -#endif - -#ifdef DUMP_PROPERTY_TREE - { - FILE *dumpfp = fopen("/tmp/proptree.dump", "w"); - if (dumpfp) { - JSPropertyTreeEntry *pte, *end; - - pte = (JSPropertyTreeEntry *) rt->propertyTreeHash.entryStore; - end = pte + JS_DHASH_TABLE_SIZE(&rt->propertyTreeHash); - while (pte < end) { - if (pte->child) - DumpSubtree(pte->child, 0, dumpfp); - pte++; - } - fclose(dumpfp); - } - } -#endif -} - -JSBool -js_InitPropertyTree(JSRuntime *rt) -{ - if (!JS_DHashTableInit(&rt->propertyTreeHash, &PropertyTreeHashOps, NULL, - sizeof(JSPropertyTreeEntry), JS_DHASH_MIN_SIZE)) { - rt->propertyTreeHash.ops = NULL; - return JS_FALSE; - } - JS_InitArenaPool(&rt->propertyArenaPool, "properties", - 256 * sizeof(JSScopeProperty), sizeof(void *)); - return JS_TRUE; -} - -void -js_FinishPropertyTree(JSRuntime *rt) -{ - if (rt->propertyTreeHash.ops) { - JS_DHashTableFinish(&rt->propertyTreeHash); - rt->propertyTreeHash.ops = NULL; - } - JS_FinishArenaPool(&rt->propertyArenaPool); -} diff --git a/lib/javascript/jsscope.h b/lib/javascript/jsscope.h deleted file mode 100644 index 0f8a837c..00000000 --- a/lib/javascript/jsscope.h +++ /dev/null @@ -1,394 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jsscope_h___ -#define jsscope_h___ -/* - * JS symbol tables. - */ -#include "jstypes.h" -#include "jsobj.h" -#include "jsprvtd.h" -#include "jspubtd.h" - -#ifdef JS_THREADSAFE -# include "jslock.h" -#endif - -/* - * Given P independent, non-unique properties each of size S words mapped by - * all scopes in a runtime, construct a property tree of N nodes each of size - * S+L words (L for tree linkage). A nominal L value is 2 for leftmost-child - * and right-sibling links. We hope that the N < P by enough that the space - * overhead of L, and the overhead of scope entries pointing at property tree - * nodes, is worth it. - * - * The tree construction goes as follows. If any empty scope in the runtime - * has a property X added to it, find or create a node under the tree root - * labeled X, and set scope->lastProp to point at that node. If any non-empty - * scope whose most recently added property is labeled Y has another property - * labeled Z added, find or create a node for Z under the node that was added - * for Y, and set scope->lastProp to point at that node. - * - * A property is labeled by its members' values: id, getter, setter, slot, - * attributes, tiny or short id, and a field telling for..in order. Note that - * labels are not unique in the tree, but they are unique among a node's kids - * (barring rare and benign multi-threaded race condition outcomes, see below) - * and along any ancestor line from the tree root to a given leaf node (except - * for the hard case of duplicate formal parameters to a function). - * - * Thus the root of the tree represents all empty scopes, and the first ply - * of the tree represents all scopes containing one property, etc. Each node - * in the tree can stand for any number of scopes having the same ordered set - * of properties, where that node was the last added to the scope. (We need - * not store the root of the tree as a node, and do not -- all we need are - * links to its kids.) - * - * Sidebar on for..in loop order: ECMA requires no particular order, but this - * implementation has promised and delivered property definition order, and - * compatibility is king. We could use an order number per property, which - * would require a sort in js_Enumerate, and an entry order generation number - * per scope. An order number beats a list, which should be doubly-linked for - * O(1) delete. An even better scheme is to use a parent link in the property - * tree, so that the ancestor line can be iterated from scope->lastProp when - * filling in a JSIdArray from back to front. This parent link also helps the - * GC to sweep properties iteratively. - * - * What if a property Y is deleted from a scope? If Y is the last property in - * the scope, we simply adjust the scope's lastProp member after we remove the - * scope's hash-table entry pointing at that property node. The parent link - * mentioned in the for..in sidebar above makes this adjustment O(1). But if - * Y comes between X and Z in the scope, then we might have to "fork" the tree - * at X, leaving X->Y->Z in case other scopes have those properties added in - * that order; and to finish the fork, we'd add a node labeled Z with the path - * X->Z, if it doesn't exist. This could lead to lots of extra nodes, and to - * O(n^2) growth when deleting lots of properties. - * - * Rather, for O(1) growth all around, we should share the path X->Y->Z among - * scopes having those three properties added in that order, and among scopes - * having only X->Z where Y was deleted. All such scopes have a lastProp that - * points to the Z child of Y. But a scope in which Y was deleted does not - * have a table entry for Y, and when iterating that scope by traversing the - * ancestor line from Z, we will have to test for a table entry for each node, - * skipping nodes that lack entries. - * - * What if we add Y again? X->Y->Z->Y is wrong and we'll enumerate Y twice. - * Therefore we must fork in such a case, if not earlier. Because delete is - * "bursty", we should not fork eagerly. Delaying a fork till we are at risk - * of adding Y after it was deleted already requires a flag in the JSScope, to - * wit, SCOPE_MIDDLE_DELETE. - * - * What about thread safety? If the property tree operations done by requests - * are find-node and insert-node, then the only hazard is duplicate insertion. - * This is harmless except for minor bloat. When all requests have ended or - * been suspended, the GC is free to sweep the tree after marking all nodes - * reachable from scopes, performing remove-node operations as needed. Note - * also that the stable storage of the property nodes during active requests - * permits the property cache (see jsinterp.h) to dereference JSScopeProperty - * weak references safely. - * - * Is the property tree worth it compared to property storage in each table's - * entries? To decide, we must find the relation <> between the words used - * with a property tree and the words required without a tree. - * - * Model all scopes as one super-scope of capacity T entries (T a power of 2). - * Let alpha be the load factor of this double hash-table. With the property - * tree, each entry in the table is a word-sized pointer to a node that can be - * shared by many scopes. But all such pointers are overhead compared to the - * situation without the property tree, where the table stores property nodes - * directly, as entries each of size S words. With the property tree, we need - * L=2 extra words per node for siblings and kids pointers. Without the tree, - * (1-alpha)*S*T words are wasted on free or removed sentinel-entries required - * by double hashing. - * - * Therefore, - * - * (property tree) <> (no property tree) - * N*(S+L) + T <> S*T - * N*(S+L) + T <> P*S + (1-alpha)*S*T - * N*(S+L) + alpha*T + (1-alpha)*T <> P*S + (1-alpha)*S*T - * - * Note that P is alpha*T by definition, so - * - * N*(S+L) + P + (1-alpha)*T <> P*S + (1-alpha)*S*T - * N*(S+L) <> P*S - P + (1-alpha)*S*T - (1-alpha)*T - * N*(S+L) <> (P + (1-alpha)*T) * (S-1) - * N*(S+L) <> (P + (1-alpha)*P/alpha) * (S-1) - * N*(S+L) <> P * (1/alpha) * (S-1) - * - * Let N = P*beta for a compression ratio beta, beta <= 1: - * - * P*beta*(S+L) <> P * (1/alpha) * (S-1) - * beta*(S+L) <> (S-1)/alpha - * beta <> (S-1)/((S+L)*alpha) - * - * For S = 6 (32-bit architectures) and L = 2, the property tree wins iff - * - * beta < 5/(8*alpha) - * - * We ensure that alpha <= .75, so the property tree wins if beta < .83_. An - * average beta from recent Mozilla browser startups was around .6. - * - * Can we reduce L? Observe that the property tree degenerates into a list of - * lists if at most one property Y follows X in all scopes. In or near such a - * case, we waste a word on the right-sibling link outside of the root ply of - * the tree. Note also that the root ply tends to be large, so O(n^2) growth - * searching it is likely, indicating the need for hashing (but with increased - * thread safety costs). - * - * If only K out of N nodes in the property tree have more than one child, we - * could eliminate the sibling link and overlay a children list or hash-table - * pointer on the leftmost-child link (which would then be either null or an - * only-child link; the overlay could be tagged in the low bit of the pointer, - * or flagged elsewhere in the property tree node, although such a flag must - * not be considered when comparing node labels during tree search). - * - * For such a system, L = 1 + (K * averageChildrenTableSize) / N instead of 2. - * If K << N, L approaches 1 and the property tree wins if beta < .95. - * - * We observe that fan-out below the root ply of the property tree appears to - * have extremely low degree (see the MeterPropertyTree code that histograms - * child-counts in jsscope.c), so instead of a hash-table we use a linked list - * of child node pointer arrays ("kid chunks"). The details are isolated in - * jsscope.c; others must treat JSScopeProperty.kids as opaque. We leave it - * strongly typed for debug-ability of the common (null or one-kid) cases. - * - * One final twist (can you stand it?): the mean number of entries per scope - * in Mozilla is < 5, with a large standard deviation (~8). Instead of always - * allocating scope->table, we leave it null while initializing all the other - * scope members as if it were non-null and minimal-length. Until a property - * is added that crosses the threshold of 6 or more entries for hashing, or - * until a "middle delete" occurs, we use linear search from scope->lastProp - * to find a given id, and save on the space overhead of a hash table. - */ - -struct JSScope { - JSObjectMap map; /* base class state */ - JSObject *object; /* object that owns this scope */ - uint8 flags; /* flags, see below */ - int8 hashShift; /* multiplicative hash shift */ - uint16 dswIndex; /* Deutsch-Schorr-Waite scaled index */ - uint32 entryCount; /* number of entries in table */ - uint32 removedCount; /* removed entry sentinels in table */ - JSScopeProperty **table; /* table of ptrs to shared tree nodes */ - JSScopeProperty *lastProp; /* pointer to last property added */ -#ifdef JS_THREADSAFE - JSContext *ownercx; /* creating context, NULL if shared */ - JSThinLock lock; /* binary semaphore protecting scope */ - union { /* union lockful and lock-free state: */ - jsrefcount count; /* lock entry count for reentrancy */ - JSScope *link; /* next link in rt->scopeSharingTodo */ - } u; -#ifdef DEBUG - const char *file[4]; /* file where lock was (re-)taken */ - unsigned int line[4]; /* line where lock was (re-)taken */ -#endif -#endif -}; - -#define OBJ_SCOPE(obj) ((JSScope *)(obj)->map) - -/* By definition, hashShift = JS_DHASH_BITS - log2(capacity). */ -#define SCOPE_CAPACITY(scope) JS_BIT(JS_DHASH_BITS-(scope)->hashShift) - -/* Scope flags and some macros to hide them from other files than jsscope.c. */ -#define SCOPE_MIDDLE_DELETE 0x0001 -#define SCOPE_SEALED 0x0002 - -#define SCOPE_HAD_MIDDLE_DELETE(scope) ((scope)->flags & SCOPE_MIDDLE_DELETE) -#define SCOPE_SET_MIDDLE_DELETE(scope) ((scope)->flags |= SCOPE_MIDDLE_DELETE) -#define SCOPE_CLR_MIDDLE_DELETE(scope) ((scope)->flags &= ~SCOPE_MIDDLE_DELETE) - -#define SCOPE_IS_SEALED(scope) ((scope)->flags & SCOPE_SEALED) -#define SCOPE_SET_SEALED(scope) ((scope)->flags |= SCOPE_SEALED) -#if 0 -/* - * Don't define this, it can't be done safely because JS_LOCK_OBJ will avoid - * taking the lock if the object owns its scope and the scope is sealed. - */ -#define SCOPE_CLR_SEALED(scope) ((scope)->flags &= ~SCOPE_SEALED) -#endif - -/* - * A little information hiding for scope->lastProp, in case it ever becomes - * a tagged pointer again. - */ -#define SCOPE_LAST_PROP(scope) ((scope)->lastProp) -#define SCOPE_REMOVE_LAST_PROP(scope) ((scope)->lastProp = \ - (scope)->lastProp->parent) - -struct JSScopeProperty { - jsid id; /* int-tagged jsval/untagged JSAtom* */ - JSPropertyOp getter; /* getter and setter hooks or objects */ - JSPropertyOp setter; - uint32 slot; /* index in obj->slots vector */ - uint8 attrs; /* attributes, see jsapi.h JSPROP_* */ - uint8 flags; /* flags, see below for defines */ - int16 shortid; /* tinyid, or local arg/var index */ - JSScopeProperty *parent; /* parent node, reverse for..in order */ - JSScopeProperty *kids; /* null, single child, or a tagged ptr - to many-kids data structure */ -}; - -/* JSScopeProperty pointer tag bit indicating a collision. */ -#define SPROP_COLLISION ((jsuword)1) -#define SPROP_REMOVED ((JSScopeProperty *) SPROP_COLLISION) - -/* Macros to get and set sprop pointer values and collision flags. */ -#define SPROP_IS_FREE(sprop) ((sprop) == NULL) -#define SPROP_IS_REMOVED(sprop) ((sprop) == SPROP_REMOVED) -#define SPROP_IS_LIVE(sprop) ((sprop) > SPROP_REMOVED) -#define SPROP_FLAG_COLLISION(spp,sprop) (*(spp) = (JSScopeProperty *) \ - ((jsuword)(sprop) | SPROP_COLLISION)) -#define SPROP_HAD_COLLISION(sprop) ((jsuword)(sprop) & SPROP_COLLISION) -#define SPROP_FETCH(spp) SPROP_CLEAR_COLLISION(*(spp)) - -#define SPROP_CLEAR_COLLISION(sprop) \ - ((JSScopeProperty *) ((jsuword)(sprop) & ~SPROP_COLLISION)) - -#define SPROP_STORE_PRESERVING_COLLISION(spp, sprop) \ - (*(spp) = (JSScopeProperty *) ((jsuword)(sprop) \ - | SPROP_HAD_COLLISION(*(spp)))) - -/* Bits stored in sprop->flags. */ -#define SPROP_MARK 0x01 -#define SPROP_IS_DUPLICATE 0x02 -#define SPROP_IS_ALIAS 0x04 -#define SPROP_HAS_SHORTID 0x08 -#define SPROP_IS_HIDDEN 0x10 /* a normally-hidden property, - e.g., function arg or var */ - -/* - * If SPROP_HAS_SHORTID is set in sprop->flags, we use sprop->shortid rather - * than id when calling sprop's getter or setter. - */ -#define SPROP_USERID(sprop) \ - (((sprop)->flags & SPROP_HAS_SHORTID) ? INT_TO_JSVAL((sprop)->shortid) \ - : ID_TO_VALUE((sprop)->id)) - -#define SPROP_INVALID_SLOT 0xffffffff - -#define SPROP_HAS_VALID_SLOT(sprop, scope) \ - ((sprop)->slot < (scope)->map.freeslot) - -#define SPROP_HAS_STUB_GETTER(sprop) (!(sprop)->getter) -#define SPROP_HAS_STUB_SETTER(sprop) (!(sprop)->setter) - -#define SPROP_CALL_GETTER(cx,sprop,getter,obj,obj2,vp) \ - (!(getter) || \ - (getter)(cx, OBJ_THIS_OBJECT(cx,obj), SPROP_USERID(sprop), vp)) -#define SPROP_CALL_SETTER(cx,sprop,setter,obj,obj2,vp) \ - (!(setter) || \ - (setter)(cx, OBJ_THIS_OBJECT(cx,obj), SPROP_USERID(sprop), vp)) - -#define SPROP_GET(cx,sprop,obj,obj2,vp) \ - (((sprop)->attrs & JSPROP_GETTER) \ - ? js_InternalGetOrSet(cx, obj, (sprop)->id, \ - OBJECT_TO_JSVAL((sprop)->getter), JSACC_READ, \ - 0, 0, vp) \ - : SPROP_CALL_GETTER(cx, sprop, (sprop)->getter, obj, obj2, vp)) - -#define SPROP_SET(cx,sprop,obj,obj2,vp) \ - (((sprop)->attrs & JSPROP_SETTER) \ - ? js_InternalGetOrSet(cx, obj, (sprop)->id, \ - OBJECT_TO_JSVAL((sprop)->setter), JSACC_WRITE, \ - 1, vp, vp) \ - : ((sprop)->attrs & JSPROP_GETTER) \ - ? (JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, \ - JSMSG_GETTER_ONLY, NULL), JS_FALSE) \ - : SPROP_CALL_SETTER(cx, sprop, (sprop)->setter, obj, obj2, vp)) - -/* Macro for common expression to test for shared permanent attributes. */ -#define SPROP_IS_SHARED_PERMANENT(sprop) \ - ((~(sprop)->attrs & (JSPROP_SHARED | JSPROP_PERMANENT)) == 0) - -extern JSScope * -js_GetMutableScope(JSContext *cx, JSObject *obj); - -extern JSScope * -js_NewScope(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops, JSClass *clasp, - JSObject *obj); - -extern void -js_DestroyScope(JSContext *cx, JSScope *scope); - -#define ID_TO_VALUE(id) (JSID_IS_ATOM(id) ? ATOM_JSID_TO_JSVAL(id) : \ - JSID_IS_OBJECT(id) ? OBJECT_JSID_TO_JSVAL(id) : \ - (jsval)(id)) -#define HASH_ID(id) (JSID_IS_ATOM(id) ? JSID_TO_ATOM(id)->number : \ - JSID_IS_OBJECT(id) ? (jsatomid) JSID_CLRTAG(id) : \ - (jsatomid) JSID_TO_INT(id)) - -extern JS_FRIEND_API(JSScopeProperty **) -js_SearchScope(JSScope *scope, jsid id, JSBool adding); - -#define SCOPE_GET_PROPERTY(scope, id) \ - SPROP_FETCH(js_SearchScope(scope, id, JS_FALSE)) - -#define SCOPE_HAS_PROPERTY(scope, sprop) \ - (SCOPE_GET_PROPERTY(scope, (sprop)->id) == (sprop)) - -extern JSScopeProperty * -js_AddScopeProperty(JSContext *cx, JSScope *scope, jsid id, - JSPropertyOp getter, JSPropertyOp setter, uint32 slot, - uintN attrs, uintN flags, intN shortid); - -extern JSScopeProperty * -js_ChangeScopePropertyAttrs(JSContext *cx, JSScope *scope, - JSScopeProperty *sprop, uintN attrs, uintN mask, - JSPropertyOp getter, JSPropertyOp setter); - -extern JSBool -js_RemoveScopeProperty(JSContext *cx, JSScope *scope, jsid id); - -extern void -js_ClearScope(JSContext *cx, JSScope *scope); - -#define MARK_SCOPE_PROPERTY(sprop) ((sprop)->flags |= SPROP_MARK) - -extern void -js_SweepScopeProperties(JSRuntime *rt); - -extern JSBool -js_InitPropertyTree(JSRuntime *rt); - -extern void -js_FinishPropertyTree(JSRuntime *rt); - -#endif /* jsscope_h___ */ diff --git a/lib/javascript/jsscript.c b/lib/javascript/jsscript.c deleted file mode 100644 index 6fc92de9..00000000 --- a/lib/javascript/jsscript.c +++ /dev/null @@ -1,1490 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sw=4 et tw=80: - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JS script operations. - */ -#include "jsstddef.h" -#include -#include "jstypes.h" -#include "jsutil.h" /* Added by JSIFY */ -#include "jsprf.h" -#include "jsapi.h" -#include "jsatom.h" -#include "jscntxt.h" -#include "jsconfig.h" -#include "jsdbgapi.h" -#include "jsemit.h" -#include "jsfun.h" -#include "jsinterp.h" -#include "jslock.h" -#include "jsnum.h" -#include "jsopcode.h" -#include "jsscript.h" -#if JS_HAS_XDR -#include "jsxdrapi.h" -#endif - -#if JS_HAS_SCRIPT_OBJECT - -static const char js_script_exec[] = "Script.prototype.exec"; -static const char js_script_compile[] = "Script.prototype.compile"; - -#if JS_HAS_TOSOURCE -static JSBool -script_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSScript *script; - size_t i, j, k, n; - char buf[16]; - jschar *s, *t; - uint32 indent; - JSString *str; - - if (!JS_InstanceOf(cx, obj, &js_ScriptClass, argv)) - return JS_FALSE; - script = (JSScript *) JS_GetPrivate(cx, obj); - - /* Let n count the source string length, j the "front porch" length. */ - j = JS_snprintf(buf, sizeof buf, "(new %s(", js_ScriptClass.name); - n = j + 2; - if (!script) { - /* Let k count the constructor argument string length. */ - k = 0; - s = NULL; /* quell GCC overwarning */ - } else { - indent = 0; - if (argc && !js_ValueToECMAUint32(cx, argv[0], &indent)) - return JS_FALSE; - str = JS_DecompileScript(cx, script, "Script.prototype.toSource", - (uintN)indent); - if (!str) - return JS_FALSE; - str = js_QuoteString(cx, str, '\''); - if (!str) - return JS_FALSE; - s = JSSTRING_CHARS(str); - k = JSSTRING_LENGTH(str); - n += k; - } - - /* Allocate the source string and copy into it. */ - t = (jschar *) JS_malloc(cx, (n + 1) * sizeof(jschar)); - if (!t) - return JS_FALSE; - for (i = 0; i < j; i++) - t[i] = buf[i]; - for (j = 0; j < k; i++, j++) - t[i] = s[j]; - t[i++] = ')'; - t[i++] = ')'; - t[i] = 0; - - /* Create and return a JS string for t. */ - str = JS_NewUCString(cx, t, n); - if (!str) { - JS_free(cx, t); - return JS_FALSE; - } - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} -#endif /* JS_HAS_TOSOURCE */ - -static JSBool -script_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSScript *script; - uint32 indent; - JSString *str; - - if (!JS_InstanceOf(cx, obj, &js_ScriptClass, argv)) - return JS_FALSE; - script = (JSScript *) JS_GetPrivate(cx, obj); - if (!script) { - *rval = STRING_TO_JSVAL(cx->runtime->emptyString); - return JS_TRUE; - } - - indent = 0; - if (argc && !js_ValueToECMAUint32(cx, argv[0], &indent)) - return JS_FALSE; - str = JS_DecompileScript(cx, script, "Script.prototype.toString", - (uintN)indent); - if (!str) - return JS_FALSE; - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -static JSBool -script_compile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSScript *oldscript, *script; - JSStackFrame *fp, *caller; - JSString *str; - JSObject *scopeobj; - const char *file; - uintN line; - JSPrincipals *principals; - - /* Make sure obj is a Script object. */ - if (!JS_InstanceOf(cx, obj, &js_ScriptClass, argv)) - return JS_FALSE; - - /* If no args, leave private undefined and return early. */ - if (argc == 0) - goto out; - - /* XXX thread safety was completely neglected in this function... */ - oldscript = (JSScript *) JS_GetPrivate(cx, obj); - if (oldscript) { - for (fp = cx->fp; fp; fp = fp->down) { - if (fp->script == oldscript) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_SELF_MODIFYING_SCRIPT); - return JS_FALSE; - } - } - } - - /* Otherwise, the first arg is the script source to compile. */ - str = js_ValueToString(cx, argv[0]); - if (!str) - return JS_FALSE; - argv[0] = STRING_TO_JSVAL(str); - - /* Compile using the caller's scope chain, which js_Invoke passes to fp. */ - fp = cx->fp; - caller = JS_GetScriptedCaller(cx, fp); - JS_ASSERT(!caller || fp->scopeChain == caller->scopeChain); - - scopeobj = NULL; - if (argc >= 2) { - if (!js_ValueToObject(cx, argv[1], &scopeobj)) - return JS_FALSE; - argv[1] = OBJECT_TO_JSVAL(scopeobj); - } - if (caller) { - if (!scopeobj) - scopeobj = caller->scopeChain; - - file = caller->script->filename; - line = js_PCToLineNumber(cx, caller->script, caller->pc); - principals = JS_EvalFramePrincipals(cx, fp, caller); - } else { - file = NULL; - line = 0; - principals = NULL; - } - - /* Ensure we compile this script with the right (inner) principals. */ - scopeobj = js_CheckScopeChainValidity(cx, scopeobj, js_script_compile); - if (!scopeobj) - return JS_FALSE; - - /* - * Compile the new script using the caller's scope chain, a la eval(). - * Unlike jsobj.c:obj_eval, however, we do not set JSFRAME_EVAL in fp's - * flags, because compilation is here separated from execution, and the - * run-time scope chain may not match the compile-time. JSFRAME_EVAL is - * tested in jsemit.c and jsscan.c to optimize based on identity of run- - * and compile-time scope. - */ - fp->flags |= JSFRAME_SCRIPT_OBJECT; - script = JS_CompileUCScriptForPrincipals(cx, scopeobj, principals, - JSSTRING_CHARS(str), - JSSTRING_LENGTH(str), - file, line); - if (!script) - return JS_FALSE; - - /* Swap script for obj's old script, if any. */ - if (!JS_SetPrivate(cx, obj, script)) { - js_DestroyScript(cx, script); - return JS_FALSE; - } - if (oldscript) - js_DestroyScript(cx, oldscript); - - script->object = obj; -out: - /* Return the object. */ - *rval = OBJECT_TO_JSVAL(obj); - return JS_TRUE; -} - -static JSBool -script_exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSScript *script; - JSObject *scopeobj, *parent; - JSStackFrame *fp, *caller; - JSPrincipals *principals; - - if (!JS_InstanceOf(cx, obj, &js_ScriptClass, argv)) - return JS_FALSE; - script = (JSScript *) JS_GetPrivate(cx, obj); - if (!script) - return JS_TRUE; - - scopeobj = NULL; - if (argc) { - if (!js_ValueToObject(cx, argv[0], &scopeobj)) - return JS_FALSE; - argv[0] = OBJECT_TO_JSVAL(scopeobj); - } - - /* - * Emulate eval() by using caller's this, var object, sharp array, etc., - * all propagated by js_Execute via a non-null fourth (down) argument to - * js_Execute. If there is no scripted caller, js_Execute uses its second - * (chain) argument to set the exec frame's varobj, thisp, and scopeChain. - * - * Unlike eval, which the compiler detects, Script.prototype.exec may be - * called from a lightweight function, or even from native code (in which - * case fp->varobj and fp->scopeChain are null). If exec is called from - * a lightweight function, we will need to get a Call object representing - * its frame, to act as the var object and scope chain head. - */ - fp = cx->fp; - caller = JS_GetScriptedCaller(cx, fp); - if (caller && !caller->varobj) { - /* Called from a lightweight function. */ - JS_ASSERT(caller->fun && !(caller->fun->flags & JSFUN_HEAVYWEIGHT)); - - /* Scope chain links from Call object to callee's parent. */ - parent = OBJ_GET_PARENT(cx, JSVAL_TO_OBJECT(caller->argv[-2])); - if (!js_GetCallObject(cx, caller, parent)) - return JS_FALSE; - } - - if (!scopeobj) { - /* No scope object passed in: try to use the caller's scope chain. */ - if (caller) { - /* - * Load caller->scopeChain after the conditional js_GetCallObject - * call above, which resets scopeChain as well as varobj. - */ - scopeobj = caller->scopeChain; - } else { - /* - * Called from native code, so we don't know what scope object to - * use. We could use parent (see above), but Script.prototype.exec - * might be a shared/sealed "superglobal" method. A more general - * approach would use cx->globalObject, which will be the same as - * exec.__parent__ in the non-superglobal case. In the superglobal - * case it's the right object: the global, not the superglobal. - */ - scopeobj = cx->globalObject; - } - } - - scopeobj = js_CheckScopeChainValidity(cx, scopeobj, js_script_exec); - if (!scopeobj) - return JS_FALSE; - - /* Belt-and-braces: check that this script object has access to scopeobj. */ - principals = script->principals; - if (!js_CheckPrincipalsAccess(cx, scopeobj, principals, js_script_exec)) - return JS_FALSE; - - return js_Execute(cx, scopeobj, script, caller, JSFRAME_EVAL, rval); -} - -#if JS_HAS_XDR - -static JSBool -XDRAtomListElement(JSXDRState *xdr, JSAtomListElement *ale) -{ - jsval value; - jsatomid index; - - if (xdr->mode == JSXDR_ENCODE) - value = ATOM_KEY(ALE_ATOM(ale)); - - index = ALE_INDEX(ale); - if (!JS_XDRUint32(xdr, &index)) - return JS_FALSE; - ALE_SET_INDEX(ale, index); - - if (!JS_XDRValue(xdr, &value)) - return JS_FALSE; - - if (xdr->mode == JSXDR_DECODE) { - if (!ALE_SET_ATOM(ale, js_AtomizeValue(xdr->cx, value, 0))) - return JS_FALSE; - } - return JS_TRUE; -} - -static JSBool -XDRAtomMap(JSXDRState *xdr, JSAtomMap *map) -{ - uint32 length; - uintN i; - JSBool ok; - - if (xdr->mode == JSXDR_ENCODE) - length = map->length; - - if (!JS_XDRUint32(xdr, &length)) - return JS_FALSE; - - if (xdr->mode == JSXDR_DECODE) { - JSContext *cx; - void *mark; - JSAtomList al; - JSAtomListElement *ale; - - cx = xdr->cx; - mark = JS_ARENA_MARK(&cx->tempPool); - ATOM_LIST_INIT(&al); - for (i = 0; i < length; i++) { - JS_ARENA_ALLOCATE_TYPE(ale, JSAtomListElement, &cx->tempPool); - if (!ale || - !XDRAtomListElement(xdr, ale)) { - if (!ale) - JS_ReportOutOfMemory(cx); - JS_ARENA_RELEASE(&cx->tempPool, mark); - return JS_FALSE; - } - ALE_SET_NEXT(ale, al.list); - al.count++; - al.list = ale; - } - ok = js_InitAtomMap(cx, map, &al); - JS_ARENA_RELEASE(&cx->tempPool, mark); - return ok; - } - - if (xdr->mode == JSXDR_ENCODE) { - JSAtomListElement ale; - - for (i = 0; i < map->length; i++) { - ALE_SET_ATOM(&ale, map->vector[i]); - ALE_SET_INDEX(&ale, i); - if (!XDRAtomListElement(xdr, &ale)) - return JS_FALSE; - } - } - return JS_TRUE; -} - -JSBool -js_XDRScript(JSXDRState *xdr, JSScript **scriptp, JSBool *hasMagic) -{ - JSContext *cx; - JSScript *script, *newscript; - uint32 length, lineno, depth, magic, nsrcnotes, ntrynotes; - uint32 prologLength, version; - JSBool filenameWasSaved; - jssrcnote *notes, *sn; - - cx = xdr->cx; - script = *scriptp; - nsrcnotes = ntrynotes = 0; - filenameWasSaved = JS_FALSE; - notes = NULL; - - /* - * Encode prologLength and version after script->length (_2 or greater), - * but decode both new (>= _2) and old, prolog&version-free (_1) scripts. - * Version _3 supports principals serialization. Version _4 reorders the - * nsrcnotes and ntrynotes fields to come before everything except magic, - * length, prologLength, and version, so that srcnote and trynote storage - * can be allocated as part of the JSScript (along with bytecode storage). - */ - if (xdr->mode == JSXDR_ENCODE) - magic = JSXDR_MAGIC_SCRIPT_CURRENT; - if (!JS_XDRUint32(xdr, &magic)) - return JS_FALSE; - if (magic != JSXDR_MAGIC_SCRIPT_4 && - magic != JSXDR_MAGIC_SCRIPT_3 && - magic != JSXDR_MAGIC_SCRIPT_2 && - magic != JSXDR_MAGIC_SCRIPT_1) { - if (!hasMagic) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_SCRIPT_MAGIC); - return JS_FALSE; - } - *hasMagic = JS_FALSE; - return JS_TRUE; - } - if (hasMagic) - *hasMagic = JS_TRUE; - - if (xdr->mode == JSXDR_ENCODE) { - length = script->length; - prologLength = PTRDIFF(script->main, script->code, jsbytecode); - JS_ASSERT((int16)script->version != JSVERSION_UNKNOWN); - version = (uint32)script->version | (script->numGlobalVars << 16); - lineno = (uint32)script->lineno; - depth = (uint32)script->depth; - - /* Count the srcnotes, keeping notes pointing at the first one. */ - notes = SCRIPT_NOTES(script); - for (sn = notes; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) - continue; - nsrcnotes = PTRDIFF(sn, notes, jssrcnote); - nsrcnotes++; /* room for the terminator */ - - /* Count the trynotes. */ - if (script->trynotes) { - while (script->trynotes[ntrynotes].catchStart) - ntrynotes++; - ntrynotes++; /* room for the end marker */ - } - } - - if (!JS_XDRUint32(xdr, &length)) - return JS_FALSE; - if (magic >= JSXDR_MAGIC_SCRIPT_2) { - if (!JS_XDRUint32(xdr, &prologLength)) - return JS_FALSE; - if (!JS_XDRUint32(xdr, &version)) - return JS_FALSE; - - /* To fuse allocations, we need srcnote and trynote counts early. */ - if (magic >= JSXDR_MAGIC_SCRIPT_4) { - if (!JS_XDRUint32(xdr, &nsrcnotes)) - return JS_FALSE; - if (!JS_XDRUint32(xdr, &ntrynotes)) - return JS_FALSE; - } - } - - if (xdr->mode == JSXDR_DECODE) { - script = js_NewScript(cx, length, nsrcnotes, ntrynotes); - if (!script) - return JS_FALSE; - if (magic >= JSXDR_MAGIC_SCRIPT_2) { - script->main += prologLength; - script->version = (JSVersion) (version & 0xffff); - script->numGlobalVars = (uint16) (version >> 16); - - /* If we know nsrcnotes, we allocated space for notes in script. */ - if (magic >= JSXDR_MAGIC_SCRIPT_4) - notes = SCRIPT_NOTES(script); - } - *scriptp = script; - } - - /* - * Control hereafter must goto error on failure, in order for the DECODE - * case to destroy script and conditionally free notes, which if non-null - * in the (DECODE and magic < _4) case must point at a temporary vector - * allocated just below. - */ - if (!JS_XDRBytes(xdr, (char *)script->code, length * sizeof(jsbytecode)) || - !XDRAtomMap(xdr, &script->atomMap)) { - goto error; - } - - if (magic < JSXDR_MAGIC_SCRIPT_4) { - if (!JS_XDRUint32(xdr, &nsrcnotes)) - goto error; - if (xdr->mode == JSXDR_DECODE) { - notes = (jssrcnote *) JS_malloc(cx, nsrcnotes * sizeof(jssrcnote)); - if (!notes) - goto error; - } - } - - if (!JS_XDRBytes(xdr, (char *)notes, nsrcnotes * sizeof(jssrcnote)) || - !JS_XDRCStringOrNull(xdr, (char **)&script->filename) || - !JS_XDRUint32(xdr, &lineno) || - !JS_XDRUint32(xdr, &depth) || - (magic < JSXDR_MAGIC_SCRIPT_4 && !JS_XDRUint32(xdr, &ntrynotes))) { - goto error; - } - - /* Script principals transcoding support comes with versions >= _3. */ - if (magic >= JSXDR_MAGIC_SCRIPT_3) { - JSPrincipals *principals; - uint32 encodeable; - - if (xdr->mode == JSXDR_ENCODE) { - principals = script->principals; - encodeable = (cx->runtime->principalsTranscoder != NULL); - if (!JS_XDRUint32(xdr, &encodeable)) - goto error; - if (encodeable && - !cx->runtime->principalsTranscoder(xdr, &principals)) { - goto error; - } - } else { - if (!JS_XDRUint32(xdr, &encodeable)) - goto error; - if (encodeable) { - if (!cx->runtime->principalsTranscoder) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_CANT_DECODE_PRINCIPALS); - goto error; - } - if (!cx->runtime->principalsTranscoder(xdr, &principals)) - goto error; - script->principals = principals; - } - } - } - - if (xdr->mode == JSXDR_DECODE) { - const char *filename = script->filename; - if (filename) { - filename = js_SaveScriptFilename(cx, filename); - if (!filename) - goto error; - JS_free(cx, (void *) script->filename); - script->filename = filename; - filenameWasSaved = JS_TRUE; - } - script->lineno = (uintN)lineno; - script->depth = (uintN)depth; - - if (magic < JSXDR_MAGIC_SCRIPT_4) { - /* - * Argh, we have to reallocate script, copy notes into the extra - * space after the bytecodes, and free the temporary notes vector. - * First, add enough slop to nsrcnotes so we can align the address - * after the srcnotes of the first trynote. - */ - uint32 osrcnotes = nsrcnotes; - - if (ntrynotes) - nsrcnotes += JSTRYNOTE_ALIGNMASK; - newscript = (JSScript *) JS_realloc(cx, script, - sizeof(JSScript) + - length * sizeof(jsbytecode) + - nsrcnotes * sizeof(jssrcnote) + - ntrynotes * sizeof(JSTryNote)); - if (!newscript) - goto error; - - *scriptp = script = newscript; - script->code = (jsbytecode *)(script + 1); - script->main = script->code + prologLength; - memcpy(script->code + length, notes, osrcnotes * sizeof(jssrcnote)); - JS_free(cx, (void *) notes); - notes = NULL; - if (ntrynotes) { - script->trynotes = (JSTryNote *) - ((jsword)(SCRIPT_NOTES(script) + nsrcnotes) & - ~(jsword)JSTRYNOTE_ALIGNMASK); - memset(script->trynotes, 0, ntrynotes * sizeof(JSTryNote)); - } - } - } - - while (ntrynotes) { - JSTryNote *tn = &script->trynotes[--ntrynotes]; - uint32 start = (uint32) tn->start, - catchLength = (uint32) tn->length, - catchStart = (uint32) tn->catchStart; - - if (!JS_XDRUint32(xdr, &start) || - !JS_XDRUint32(xdr, &catchLength) || - !JS_XDRUint32(xdr, &catchStart)) { - goto error; - } - tn->start = (ptrdiff_t) start; - tn->length = (ptrdiff_t) catchLength; - tn->catchStart = (ptrdiff_t) catchStart; - } - return JS_TRUE; - - error: - if (xdr->mode == JSXDR_DECODE) { - if (script->filename && !filenameWasSaved) { - JS_free(cx, (void *) script->filename); - script->filename = NULL; - } - if (notes && magic < JSXDR_MAGIC_SCRIPT_4) - JS_free(cx, (void *) notes); - js_DestroyScript(cx, script); - *scriptp = NULL; - } - return JS_FALSE; -} - -#if JS_HAS_XDR_FREEZE_THAW -/* - * These cannot be exposed to web content, and chrome does not need them, so - * we take them out of the Mozilla client altogether. Fortunately, there is - * no way to serialize a native function (see fun_xdrObject in jsfun.c). - */ - -static JSBool -script_freeze(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSXDRState *xdr; - JSScript *script; - JSBool ok, hasMagic; - uint32 len; - void *buf; - JSString *str; - - if (!JS_InstanceOf(cx, obj, &js_ScriptClass, argv)) - return JS_FALSE; - script = (JSScript *) JS_GetPrivate(cx, obj); - if (!script) - return JS_TRUE; - - /* create new XDR */ - xdr = JS_XDRNewMem(cx, JSXDR_ENCODE); - if (!xdr) - return JS_FALSE; - - /* write */ - ok = js_XDRScript(xdr, &script, &hasMagic); - if (!ok) - goto out; - if (!hasMagic) { - *rval = JSVAL_VOID; - goto out; - } - - buf = JS_XDRMemGetData(xdr, &len); - if (!buf) { - ok = JS_FALSE; - goto out; - } - - JS_ASSERT((jsword)buf % sizeof(jschar) == 0); - len /= sizeof(jschar); - str = JS_NewUCStringCopyN(cx, (jschar *)buf, len); - if (!str) { - ok = JS_FALSE; - goto out; - } - -#if IS_BIG_ENDIAN - { - jschar *chars; - uint32 i; - - /* Swap bytes in Unichars to keep frozen strings machine-independent. */ - chars = JS_GetStringChars(str); - for (i = 0; i < len; i++) - chars[i] = JSXDR_SWAB16(chars[i]); - } -#endif - *rval = STRING_TO_JSVAL(str); - -out: - JS_XDRDestroy(xdr); - return ok; -} - -static JSBool -script_thaw(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSXDRState *xdr; - JSString *str; - void *buf; - uint32 len; - JSScript *script, *oldscript; - JSBool ok, hasMagic; - - if (!JS_InstanceOf(cx, obj, &js_ScriptClass, argv)) - return JS_FALSE; - - if (argc == 0) - return JS_TRUE; - str = js_ValueToString(cx, argv[0]); - if (!str) - return JS_FALSE; - argv[0] = STRING_TO_JSVAL(str); - - /* create new XDR */ - xdr = JS_XDRNewMem(cx, JSXDR_DECODE); - if (!xdr) - return JS_FALSE; - - buf = JS_GetStringChars(str); - len = JS_GetStringLength(str); -#if IS_BIG_ENDIAN - { - jschar *from, *to; - uint32 i; - - /* Swap bytes in Unichars to keep frozen strings machine-independent. */ - from = (jschar *)buf; - to = (jschar *) JS_malloc(cx, len * sizeof(jschar)); - if (!to) { - JS_XDRDestroy(xdr); - return JS_FALSE; - } - for (i = 0; i < len; i++) - to[i] = JSXDR_SWAB16(from[i]); - buf = (char *)to; - } -#endif - len *= sizeof(jschar); - JS_XDRMemSetData(xdr, buf, len); - - /* XXXbe should magic mismatch be error, or false return value? */ - ok = js_XDRScript(xdr, &script, &hasMagic); - if (!ok) - goto out; - if (!hasMagic) { - *rval = JSVAL_FALSE; - goto out; - } - - /* Swap script for obj's old script, if any. */ - oldscript = (JSScript *) JS_GetPrivate(cx, obj); - ok = JS_SetPrivate(cx, obj, script); - if (!ok) { - JS_free(cx, script); - goto out; - } - if (oldscript) - js_DestroyScript(cx, oldscript); - - script->object = obj; - js_CallNewScriptHook(cx, script, NULL); - -out: - /* - * We reset the buffer to be NULL so that it doesn't free the chars - * memory owned by str (argv[0]). - */ - JS_XDRMemSetData(xdr, NULL, 0); - JS_XDRDestroy(xdr); -#if IS_BIG_ENDIAN - JS_free(cx, buf); -#endif - *rval = JSVAL_TRUE; - return ok; -} - -static const char js_thaw_str[] = "thaw"; - -#endif /* JS_HAS_XDR_FREEZE_THAW */ -#endif /* JS_HAS_XDR */ - -static JSFunctionSpec script_methods[] = { -#if JS_HAS_TOSOURCE - {js_toSource_str, script_toSource, 0,0,0}, -#endif - {js_toString_str, script_toString, 0,0,0}, - {"compile", script_compile, 2,0,0}, - {"exec", script_exec, 1,0,0}, -#if JS_HAS_XDR_FREEZE_THAW - {"freeze", script_freeze, 0,0,0}, - {js_thaw_str, script_thaw, 1,0,0}, -#endif /* JS_HAS_XDR_FREEZE_THAW */ - {0,0,0,0,0} -}; - -#endif /* JS_HAS_SCRIPT_OBJECT */ - -static void -script_finalize(JSContext *cx, JSObject *obj) -{ - JSScript *script; - - script = (JSScript *) JS_GetPrivate(cx, obj); - if (script) - js_DestroyScript(cx, script); -} - -static JSBool -script_call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ -#if JS_HAS_SCRIPT_OBJECT - return script_exec(cx, JSVAL_TO_OBJECT(argv[-2]), argc, argv, rval); -#else - return JS_FALSE; -#endif -} - -static uint32 -script_mark(JSContext *cx, JSObject *obj, void *arg) -{ - JSScript *script; - - script = (JSScript *) JS_GetPrivate(cx, obj); - if (script) - js_MarkScript(cx, script, arg); - return 0; -} - -JS_FRIEND_DATA(JSClass) js_ScriptClass = { - js_Script_str, - JSCLASS_HAS_PRIVATE, - JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, script_finalize, - NULL, NULL, script_call, NULL,/*XXXbe xdr*/ - NULL, NULL, script_mark, 0 -}; - -#if JS_HAS_SCRIPT_OBJECT - -static JSBool -Script(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - /* If not constructing, replace obj with a new Script object. */ - if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) { - obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL); - if (!obj) - return JS_FALSE; - - /* - * script_compile does not use rval to root its temporaries - * so we can use it to root obj. - */ - *rval = OBJECT_TO_JSVAL(obj); - } - return script_compile(cx, obj, argc, argv, rval); -} - -#if JS_HAS_XDR_FREEZE_THAW - -static JSBool -script_static_thaw(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL); - if (!obj) - return JS_FALSE; - if (!script_thaw(cx, obj, argc, argv, rval)) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(obj); - return JS_TRUE; -} - -static JSFunctionSpec script_static_methods[] = { - {js_thaw_str, script_static_thaw, 1,0,0}, - {0,0,0,0,0} -}; - -#else /* !JS_HAS_XDR_FREEZE_THAW */ - -#define script_static_methods NULL - -#endif /* !JS_HAS_XDR_FREEZE_THAW */ - -JSObject * -js_InitScriptClass(JSContext *cx, JSObject *obj) -{ - return JS_InitClass(cx, obj, NULL, &js_ScriptClass, Script, 1, - NULL, script_methods, NULL, script_static_methods); -} - -#endif /* JS_HAS_SCRIPT_OBJECT */ - -/* - * Shared script filename management. - */ -JS_STATIC_DLL_CALLBACK(int) -js_compare_strings(const void *k1, const void *k2) -{ - return strcmp(k1, k2) == 0; -} - -/* Shared with jsatom.c to save code space. */ -extern void * JS_DLL_CALLBACK -js_alloc_table_space(void *priv, size_t size); - -extern void JS_DLL_CALLBACK -js_free_table_space(void *priv, void *item); - -/* NB: This struct overlays JSHashEntry -- see jshash.h, do not reorganize. */ -typedef struct ScriptFilenameEntry { - JSHashEntry *next; /* hash chain linkage */ - JSHashNumber keyHash; /* key hash function result */ - const void *key; /* ptr to filename, below */ - uint32 flags; /* user-defined filename prefix flags */ - JSPackedBool mark; /* GC mark flag */ - char filename[3]; /* two or more bytes, NUL-terminated */ -} ScriptFilenameEntry; - -JS_STATIC_DLL_CALLBACK(JSHashEntry *) -js_alloc_sftbl_entry(void *priv, const void *key) -{ - size_t nbytes = offsetof(ScriptFilenameEntry, filename) + strlen(key) + 1; - - return (JSHashEntry *) malloc(JS_MAX(nbytes, sizeof(JSHashEntry))); -} - -JS_STATIC_DLL_CALLBACK(void) -js_free_sftbl_entry(void *priv, JSHashEntry *he, uintN flag) -{ - if (flag != HT_FREE_ENTRY) - return; - free(he); -} - -static JSHashAllocOps sftbl_alloc_ops = { - js_alloc_table_space, js_free_table_space, - js_alloc_sftbl_entry, js_free_sftbl_entry -}; - -JSBool -js_InitRuntimeScriptState(JSRuntime *rt) -{ -#ifdef JS_THREADSAFE - JS_ASSERT(!rt->scriptFilenameTableLock); - rt->scriptFilenameTableLock = JS_NEW_LOCK(); - if (!rt->scriptFilenameTableLock) - return JS_FALSE; -#endif - JS_ASSERT(!rt->scriptFilenameTable); - rt->scriptFilenameTable = - JS_NewHashTable(16, JS_HashString, js_compare_strings, NULL, - &sftbl_alloc_ops, NULL); - if (!rt->scriptFilenameTable) { - js_FinishRuntimeScriptState(rt); /* free lock if threadsafe */ - return JS_FALSE; - } - JS_INIT_CLIST(&rt->scriptFilenamePrefixes); - return JS_TRUE; -} - -typedef struct ScriptFilenamePrefix { - JSCList links; /* circular list linkage for easy deletion */ - const char *name; /* pointer to pinned ScriptFilenameEntry string */ - size_t length; /* prefix string length, precomputed */ - uint32 flags; /* user-defined flags to inherit from this prefix */ -} ScriptFilenamePrefix; - -void -js_FinishRuntimeScriptState(JSRuntime *rt) -{ - if (rt->scriptFilenameTable) { - JS_HashTableDestroy(rt->scriptFilenameTable); - rt->scriptFilenameTable = NULL; - } -#ifdef JS_THREADSAFE - if (rt->scriptFilenameTableLock) { - JS_DESTROY_LOCK(rt->scriptFilenameTableLock); - rt->scriptFilenameTableLock = NULL; - } -#endif -} - -void -js_FreeRuntimeScriptState(JSRuntime *rt) -{ - ScriptFilenamePrefix *sfp; - - while (!JS_CLIST_IS_EMPTY(&rt->scriptFilenamePrefixes)) { - sfp = (ScriptFilenamePrefix *) rt->scriptFilenamePrefixes.next; - JS_REMOVE_LINK(&sfp->links); - free(sfp); - } - js_FinishRuntimeScriptState(rt); -} - -#ifdef DEBUG_brendan -size_t sftbl_savings = 0; -#endif - -static ScriptFilenameEntry * -SaveScriptFilename(JSRuntime *rt, const char *filename, uint32 flags) -{ - JSHashTable *table; - JSHashNumber hash; - JSHashEntry **hep; - ScriptFilenameEntry *sfe; - size_t length; - JSCList *head, *link; - ScriptFilenamePrefix *sfp; - - table = rt->scriptFilenameTable; - hash = JS_HashString(filename); - hep = JS_HashTableRawLookup(table, hash, filename); - sfe = (ScriptFilenameEntry *) *hep; -#ifdef DEBUG_brendan - if (sfe) - sftbl_savings += strlen(sfe->filename); -#endif - - if (!sfe) { - sfe = (ScriptFilenameEntry *) - JS_HashTableRawAdd(table, hep, hash, filename, NULL); - if (!sfe) - return NULL; - sfe->key = strcpy(sfe->filename, filename); - sfe->flags = 0; - sfe->mark = JS_FALSE; - } - - /* If saving a prefix, add it to the set in rt->scriptFilenamePrefixes. */ - if (flags != 0) { - /* Search in case filename was saved already; we must be idempotent. */ - sfp = NULL; - length = strlen(filename); - for (head = link = &rt->scriptFilenamePrefixes; - link->next != head; - link = link->next) { - /* Lag link behind sfp to insert in non-increasing length order. */ - sfp = (ScriptFilenamePrefix *) link->next; - if (!strcmp(sfp->name, filename)) - break; - if (sfp->length <= length) { - sfp = NULL; - break; - } - sfp = NULL; - } - - if (!sfp) { - /* No such prefix: add one now. */ - sfp = (ScriptFilenamePrefix *) malloc(sizeof(ScriptFilenamePrefix)); - if (!sfp) - return NULL; - JS_INSERT_AFTER(&sfp->links, link); - sfp->name = sfe->filename; - sfp->length = length; - sfp->flags = 0; - } - - /* - * Accumulate flags in both sfe and sfp: sfe for later access from the - * JS_GetScriptedCallerFilenameFlags debug-API, and sfp so that longer - * filename entries can inherit by prefix. - */ - sfe->flags |= flags; - sfp->flags |= flags; - } - - return sfe; -} - -const char * -js_SaveScriptFilename(JSContext *cx, const char *filename) -{ - JSRuntime *rt; - ScriptFilenameEntry *sfe; - JSCList *head, *link; - ScriptFilenamePrefix *sfp; - - rt = cx->runtime; - JS_ACQUIRE_LOCK(rt->scriptFilenameTableLock); - sfe = SaveScriptFilename(rt, filename, 0); - if (!sfe) { - JS_RELEASE_LOCK(rt->scriptFilenameTableLock); - JS_ReportOutOfMemory(cx); - return NULL; - } - - /* - * Try to inherit flags by prefix. We assume there won't be more than a - * few (dozen! ;-) prefixes, so linear search is tolerable. - * XXXbe every time I've assumed that in the JS engine, I've been wrong! - */ - for (head = &rt->scriptFilenamePrefixes, link = head->next; - link != head; - link = link->next) { - sfp = (ScriptFilenamePrefix *) link; - if (!strncmp(sfp->name, filename, sfp->length)) { - sfe->flags |= sfp->flags; - break; - } - } - JS_RELEASE_LOCK(rt->scriptFilenameTableLock); - return sfe->filename; -} - -const char * -js_SaveScriptFilenameRT(JSRuntime *rt, const char *filename, uint32 flags) -{ - ScriptFilenameEntry *sfe; - - /* This may be called very early, via the jsdbgapi.h entry point. */ - if (!rt->scriptFilenameTable && !js_InitRuntimeScriptState(rt)) - return NULL; - - JS_ACQUIRE_LOCK(rt->scriptFilenameTableLock); - sfe = SaveScriptFilename(rt, filename, flags); - JS_RELEASE_LOCK(rt->scriptFilenameTableLock); - if (!sfe) - return NULL; - - return sfe->filename; -} - -/* - * Back up from a saved filename by its offset within its hash table entry. - */ -#define FILENAME_TO_SFE(fn) \ - ((ScriptFilenameEntry *) ((fn) - offsetof(ScriptFilenameEntry, filename))) - -/* - * The sfe->key member, redundant given sfe->filename but required by the old - * jshash.c code, here gives us a useful sanity check. This assertion will - * very likely botch if someone tries to mark a string that wasn't allocated - * as an sfe->filename. - */ -#define ASSERT_VALID_SFE(sfe) JS_ASSERT((sfe)->key == (sfe)->filename) - -uint32 -js_GetScriptFilenameFlags(const char *filename) -{ - ScriptFilenameEntry *sfe; - - sfe = FILENAME_TO_SFE(filename); - ASSERT_VALID_SFE(sfe); - return sfe->flags; -} - -void -js_MarkScriptFilename(const char *filename) -{ - ScriptFilenameEntry *sfe; - - sfe = FILENAME_TO_SFE(filename); - ASSERT_VALID_SFE(sfe); - sfe->mark = JS_TRUE; -} - -JS_STATIC_DLL_CALLBACK(intN) -js_script_filename_marker(JSHashEntry *he, intN i, void *arg) -{ - ScriptFilenameEntry *sfe = (ScriptFilenameEntry *) he; - - sfe->mark = JS_TRUE; - return HT_ENUMERATE_NEXT; -} - -void -js_MarkScriptFilenames(JSRuntime *rt, uintN gcflags) -{ - JSCList *head, *link; - ScriptFilenamePrefix *sfp; - - if (gcflags & GC_KEEP_ATOMS) { - JS_HashTableEnumerateEntries(rt->scriptFilenameTable, - js_script_filename_marker, - rt); - } - for (head = &rt->scriptFilenamePrefixes, link = head->next; - link != head; - link = link->next) { - sfp = (ScriptFilenamePrefix *) link; - js_MarkScriptFilename(sfp->name); - } -} - -JS_STATIC_DLL_CALLBACK(intN) -js_script_filename_sweeper(JSHashEntry *he, intN i, void *arg) -{ - ScriptFilenameEntry *sfe = (ScriptFilenameEntry *) he; - - if (!sfe->mark) - return HT_ENUMERATE_REMOVE; - sfe->mark = JS_FALSE; - return HT_ENUMERATE_NEXT; -} - -void -js_SweepScriptFilenames(JSRuntime *rt) -{ - JS_HashTableEnumerateEntries(rt->scriptFilenameTable, - js_script_filename_sweeper, - rt); -#ifdef DEBUG_notme - printf("script filename table savings so far: %u\n", sftbl_savings); -#endif -} - -JSScript * -js_NewScript(JSContext *cx, uint32 length, uint32 nsrcnotes, uint32 ntrynotes) -{ - JSScript *script; - - /* Round up source note count to align script->trynotes for its type. */ - if (ntrynotes) - nsrcnotes += JSTRYNOTE_ALIGNMASK; - script = (JSScript *) JS_malloc(cx, - sizeof(JSScript) + - length * sizeof(jsbytecode) + - nsrcnotes * sizeof(jssrcnote) + - ntrynotes * sizeof(JSTryNote)); - if (!script) - return NULL; - memset(script, 0, sizeof(JSScript)); - script->code = script->main = (jsbytecode *)(script + 1); - script->length = length; - script->version = cx->version; - if (ntrynotes) { - script->trynotes = (JSTryNote *) - ((jsword)(SCRIPT_NOTES(script) + nsrcnotes) & - ~(jsword)JSTRYNOTE_ALIGNMASK); - memset(script->trynotes, 0, ntrynotes * sizeof(JSTryNote)); - } - return script; -} - -JS_FRIEND_API(JSScript *) -js_NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg, JSFunction *fun) -{ - uint32 mainLength, prologLength, nsrcnotes, ntrynotes; - JSScript *script; - const char *filename; - - mainLength = CG_OFFSET(cg); - prologLength = CG_PROLOG_OFFSET(cg); - CG_COUNT_FINAL_SRCNOTES(cg, nsrcnotes); - CG_COUNT_FINAL_TRYNOTES(cg, ntrynotes); - script = js_NewScript(cx, prologLength + mainLength, nsrcnotes, ntrynotes); - if (!script) - return NULL; - - /* Now that we have script, error control flow must go to label bad. */ - script->main += prologLength; - memcpy(script->code, CG_PROLOG_BASE(cg), prologLength * sizeof(jsbytecode)); - memcpy(script->main, CG_BASE(cg), mainLength * sizeof(jsbytecode)); - script->numGlobalVars = cg->treeContext.numGlobalVars; - if (!js_InitAtomMap(cx, &script->atomMap, &cg->atomList)) - goto bad; - - filename = cg->filename; - if (filename) { - script->filename = js_SaveScriptFilename(cx, filename); - if (!script->filename) - goto bad; - } - script->lineno = cg->firstLine; - script->depth = cg->maxStackDepth; - if (cg->principals) { - script->principals = cg->principals; - JSPRINCIPALS_HOLD(cx, script->principals); - } - - if (!js_FinishTakingSrcNotes(cx, cg, SCRIPT_NOTES(script))) - goto bad; - if (script->trynotes) - js_FinishTakingTryNotes(cx, cg, script->trynotes); - - /* Tell the debugger about this compiled script. */ - js_CallNewScriptHook(cx, script, fun); - return script; - -bad: - js_DestroyScript(cx, script); - return NULL; -} - -JS_FRIEND_API(void) -js_CallNewScriptHook(JSContext *cx, JSScript *script, JSFunction *fun) -{ - JSRuntime *rt; - JSNewScriptHook hook; - - rt = cx->runtime; - hook = rt->newScriptHook; - if (hook) { - JS_KEEP_ATOMS(rt); - hook(cx, script->filename, script->lineno, script, fun, - rt->newScriptHookData); - JS_UNKEEP_ATOMS(rt); - } -} - -JS_FRIEND_API(void) -js_CallDestroyScriptHook(JSContext *cx, JSScript *script) -{ - JSRuntime *rt; - JSDestroyScriptHook hook; - - rt = cx->runtime; - hook = rt->destroyScriptHook; - if (hook) - hook(cx, script, rt->destroyScriptHookData); -} - -void -js_DestroyScript(JSContext *cx, JSScript *script) -{ - js_CallDestroyScriptHook(cx, script); - - JS_ClearScriptTraps(cx, script); - js_FreeAtomMap(cx, &script->atomMap); - if (script->principals) - JSPRINCIPALS_DROP(cx, script->principals); - JS_free(cx, script); -} - -void -js_MarkScript(JSContext *cx, JSScript *script, void *arg) -{ - JSAtomMap *map; - uintN i, length; - JSAtom **vector; - - map = &script->atomMap; - length = map->length; - vector = map->vector; - for (i = 0; i < length; i++) - GC_MARK_ATOM(cx, vector[i], arg); - - if (script->filename) - js_MarkScriptFilename(script->filename); -} - -jssrcnote * -js_GetSrcNote(JSScript *script, jsbytecode *pc) -{ - jssrcnote *sn; - ptrdiff_t offset, target; - - target = PTRDIFF(pc, script->code, jsbytecode); - if ((uint32)target >= script->length) - return NULL; - offset = 0; - for (sn = SCRIPT_NOTES(script); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) { - offset += SN_DELTA(sn); - if (offset == target && SN_IS_GETTABLE(sn)) - return sn; - } - return NULL; -} - -uintN -js_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc) -{ - JSAtom *atom; - JSFunction *fun; - uintN lineno; - ptrdiff_t offset, target; - jssrcnote *sn; - JSSrcNoteType type; - - /* - * Special case: function definition needs no line number note because - * the function's script contains its starting line number. - */ - if (*pc == JSOP_DEFFUN) { - atom = GET_ATOM(cx, script, pc); - fun = (JSFunction *) JS_GetPrivate(cx, ATOM_TO_OBJECT(atom)); - JS_ASSERT(fun->interpreted); - return fun->u.script->lineno; - } - - /* - * General case: walk through source notes accumulating their deltas, - * keeping track of line-number notes, until we pass the note for pc's - * offset within script->code. - */ - lineno = script->lineno; - offset = 0; - target = PTRDIFF(pc, script->code, jsbytecode); - for (sn = SCRIPT_NOTES(script); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) { - offset += SN_DELTA(sn); - type = (JSSrcNoteType) SN_TYPE(sn); - if (type == SRC_SETLINE) { - if (offset <= target) - lineno = (uintN) js_GetSrcNoteOffset(sn, 0); - } else if (type == SRC_NEWLINE) { - if (offset <= target) - lineno++; - } - if (offset > target) - break; - } - return lineno; -} - -/* The line number limit is the same as the jssrcnote offset limit. */ -#define SN_LINE_LIMIT (SN_3BYTE_OFFSET_FLAG << 16) - -jsbytecode * -js_LineNumberToPC(JSScript *script, uintN target) -{ - ptrdiff_t offset, best; - uintN lineno, bestdiff, diff; - jssrcnote *sn; - JSSrcNoteType type; - - offset = 0; - best = -1; - lineno = script->lineno; - bestdiff = SN_LINE_LIMIT; - for (sn = SCRIPT_NOTES(script); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) { - if (lineno == target) - goto out; - if (lineno > target) { - diff = lineno - target; - if (diff < bestdiff) { - bestdiff = diff; - best = offset; - } - } - offset += SN_DELTA(sn); - type = (JSSrcNoteType) SN_TYPE(sn); - if (type == SRC_SETLINE) { - lineno = (uintN) js_GetSrcNoteOffset(sn, 0); - } else if (type == SRC_NEWLINE) { - lineno++; - } - } - if (best >= 0) - offset = best; -out: - return script->code + offset; -} - -JS_FRIEND_API(uintN) -js_GetScriptLineExtent(JSScript *script) -{ - uintN lineno; - jssrcnote *sn; - JSSrcNoteType type; - - lineno = script->lineno; - for (sn = SCRIPT_NOTES(script); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) { - type = (JSSrcNoteType) SN_TYPE(sn); - if (type == SRC_SETLINE) { - lineno = (uintN) js_GetSrcNoteOffset(sn, 0); - } else if (type == SRC_NEWLINE) { - lineno++; - } - } - return 1 + lineno - script->lineno; -} diff --git a/lib/javascript/jsscript.h b/lib/javascript/jsscript.h deleted file mode 100644 index 77f59ed7..00000000 --- a/lib/javascript/jsscript.h +++ /dev/null @@ -1,209 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jsscript_h___ -#define jsscript_h___ -/* - * JS script descriptor. - */ -#include "jsatom.h" -#include "jsprvtd.h" - -JS_BEGIN_EXTERN_C - -/* - * Exception handling runtime information. - * - * All fields except length are code offsets relative to the main entry point - * of the script. If script->trynotes is not null, it points to a vector of - * these structs terminated by one with catchStart == 0. - */ -struct JSTryNote { - ptrdiff_t start; /* start of try statement */ - ptrdiff_t length; /* count of try statement bytecodes */ - ptrdiff_t catchStart; /* start of catch block (0 if end) */ -}; - -#define JSTRYNOTE_GRAIN sizeof(ptrdiff_t) -#define JSTRYNOTE_ALIGNMASK (JSTRYNOTE_GRAIN - 1) - -struct JSScript { - jsbytecode *code; /* bytecodes and their immediate operands */ - uint32 length; /* length of code vector */ - jsbytecode *main; /* main entry point, after predef'ing prolog */ - uint16 version; /* JS version under which script was compiled */ - uint16 numGlobalVars; /* declared global var/const/function count */ - JSAtomMap atomMap; /* maps immediate index to literal struct */ - const char *filename; /* source filename or null */ - uintN lineno; /* base line number of script */ - uintN depth; /* maximum stack depth in slots */ - JSTryNote *trynotes; /* exception table for this script */ - JSPrincipals *principals; /* principals for this script */ - JSObject *object; /* optional Script-class object wrapper */ -}; - -/* No need to store script->notes now that it is allocated right after code. */ -#define SCRIPT_NOTES(script) ((jssrcnote*)((script)->code+(script)->length)) - -#define SCRIPT_FIND_CATCH_START(script, pc, catchpc) \ - JS_BEGIN_MACRO \ - JSTryNote *tn_ = (script)->trynotes; \ - jsbytecode *catchpc_ = NULL; \ - if (tn_) { \ - ptrdiff_t off_ = PTRDIFF(pc, (script)->main, jsbytecode); \ - if (off_ >= 0) { \ - while ((jsuword)(off_ - tn_->start) >= (jsuword)tn_->length) \ - ++tn_; \ - if (tn_->catchStart) \ - catchpc_ = (script)->main + tn_->catchStart; \ - } \ - } \ - catchpc = catchpc_; \ - JS_END_MACRO - -extern JS_FRIEND_DATA(JSClass) js_ScriptClass; - -extern JSObject * -js_InitScriptClass(JSContext *cx, JSObject *obj); - -/* - * On first new context in rt, initialize script runtime state, specifically - * the script filename table and its lock. - */ -extern JSBool -js_InitRuntimeScriptState(JSRuntime *rt); - -/* - * On last context destroy for rt, if script filenames are all GC'd, free the - * script filename table and its lock. - */ -extern void -js_FinishRuntimeScriptState(JSRuntime *rt); - -/* - * On JS_DestroyRuntime(rt), forcibly free script filename prefixes and any - * script filename table entries that have not been GC'd, the latter using - * js_FinishRuntimeScriptState. - * - * This allows script filename prefixes to outlive any context in rt. - */ -extern void -js_FreeRuntimeScriptState(JSRuntime *rt); - -extern const char * -js_SaveScriptFilename(JSContext *cx, const char *filename); - -extern const char * -js_SaveScriptFilenameRT(JSRuntime *rt, const char *filename, uint32 flags); - -extern uint32 -js_GetScriptFilenameFlags(const char *filename); - -extern void -js_MarkScriptFilename(const char *filename); - -extern void -js_MarkScriptFilenames(JSRuntime *rt, uintN gcflags); - -extern void -js_SweepScriptFilenames(JSRuntime *rt); - -/* - * Two successively less primitive ways to make a new JSScript. The first - * does *not* call a non-null cx->runtime->newScriptHook -- only the second, - * js_NewScriptFromCG, calls this optional debugger hook. - * - * The js_NewScript function can't know whether the script it creates belongs - * to a function, or is top-level or eval code, but the debugger wants access - * to the newly made script's function, if any -- so callers of js_NewScript - * are responsible for notifying the debugger after successfully creating any - * kind (function or other) of new JSScript. - */ -extern JSScript * -js_NewScript(JSContext *cx, uint32 length, uint32 snlength, uint32 tnlength); - -extern JS_FRIEND_API(JSScript *) -js_NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg, JSFunction *fun); - -/* - * New-script-hook calling is factored from js_NewScriptFromCG so that it - * and callers of js_XDRScript can share this code. In the case of callers - * of js_XDRScript, the hook should be invoked only after successful decode - * of any owning function (the fun parameter) or script object (null fun). - */ -extern JS_FRIEND_API(void) -js_CallNewScriptHook(JSContext *cx, JSScript *script, JSFunction *fun); - -extern JS_FRIEND_API(void) -js_CallDestroyScriptHook(JSContext *cx, JSScript *script); - -extern void -js_DestroyScript(JSContext *cx, JSScript *script); - -extern void -js_MarkScript(JSContext *cx, JSScript *script, void *arg); - -extern jssrcnote * -js_GetSrcNote(JSScript *script, jsbytecode *pc); - -/* XXX need cx to lock function objects declared by prolog bytecodes. */ -extern uintN -js_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc); - -extern jsbytecode * -js_LineNumberToPC(JSScript *script, uintN lineno); - -extern JS_FRIEND_API(uintN) -js_GetScriptLineExtent(JSScript *script); - -/* - * If magic is non-null, js_XDRScript succeeds on magic number mismatch but - * returns false in *magic; it reflects a match via a true *magic out param. - * If magic is null, js_XDRScript returns false on bad magic number errors, - * which it reports. - * - * NB: callers must call js_CallNewScriptHook after successful JSXDR_DECODE - * and subsequent set-up of owning function or script object, if any. - */ -extern JSBool -js_XDRScript(JSXDRState *xdr, JSScript **scriptp, JSBool *magic); - -JS_END_EXTERN_C - -#endif /* jsscript_h___ */ diff --git a/lib/javascript/jsshell.msg b/lib/javascript/jsshell.msg deleted file mode 100644 index 4b811ac0..00000000 --- a/lib/javascript/jsshell.msg +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - Error messages for JSShell. See js.msg for format. -*/ - -MSG_DEF(JSSMSG_NOT_AN_ERROR, 0, 0, JSEXN_NONE, "") -MSG_DEF(JSSMSG_CANT_OPEN, 1, 2, JSEXN_NONE, "can't open {0}: {1}") -MSG_DEF(JSSMSG_TRAP_USAGE, 2, 0, JSEXN_NONE, "usage: trap [fun] [pc] expr") -MSG_DEF(JSSMSG_LINE2PC_USAGE, 3, 0, JSEXN_NONE, "usage: line2pc [fun] line") -MSG_DEF(JSSMSG_FILE_SCRIPTS_ONLY, 4, 0, JSEXN_NONE, "only works on JS scripts read from files") -MSG_DEF(JSSMSG_UNEXPECTED_EOF, 5, 1, JSEXN_NONE, "unexpected EOF in {0}") -MSG_DEF(JSSMSG_DOEXP_USAGE, 6, 0, JSEXN_NONE, "usage: doexp obj id") diff --git a/lib/javascript/jsstddef.h b/lib/javascript/jsstddef.h deleted file mode 100644 index addaa88f..00000000 --- a/lib/javascript/jsstddef.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * stddef inclusion here to first declare ptrdif as a signed long instead of a - * signed int. - */ - -#ifdef _WINDOWS -# ifndef XP_WIN -# define XP_WIN -# endif -#if defined(_WIN32) || defined(WIN32) -# ifndef XP_WIN32 -# define XP_WIN32 -# endif -#else -# ifndef XP_WIN16 -# define XP_WIN16 -# endif -#endif -#endif - -#ifdef XP_WIN16 -#ifndef _PTRDIFF_T_DEFINED -typedef long ptrdiff_t; - -/* - * The Win16 compiler treats pointer differences as 16-bit signed values. - * This macro allows us to treat them as 17-bit signed values, stored in - * a 32-bit type. - */ -#define PTRDIFF(p1, p2, type) \ - ((((unsigned long)(p1)) - ((unsigned long)(p2))) / sizeof(type)) - -#define _PTRDIFF_T_DEFINED -#endif /*_PTRDIFF_T_DEFINED*/ -#else /*WIN16*/ - -#define PTRDIFF(p1, p2, type) \ - ((p1) - (p2)) - -#endif - -#include - - diff --git a/lib/javascript/jsstr.c b/lib/javascript/jsstr.c deleted file mode 100644 index 5e0bafd3..00000000 --- a/lib/javascript/jsstr.c +++ /dev/null @@ -1,4868 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sw=4 et tw=80: - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JS string type implementation. - * - * In order to avoid unnecessary js_LockGCThing/js_UnlockGCThing calls, these - * native methods store strings (possibly newborn) converted from their 'this' - * parameter and arguments on the stack: 'this' conversions at argv[-1], arg - * conversions at their index (argv[0], argv[1]). This is a legitimate method - * of rooting things that might lose their newborn root due to subsequent GC - * allocations in the same native method. - */ -#include "jsstddef.h" -#include -#include -#include "jstypes.h" -#include "jsutil.h" /* Added by JSIFY */ -#include "jshash.h" /* Added by JSIFY */ -#include "jsprf.h" -#include "jsapi.h" -#include "jsarray.h" -#include "jsatom.h" -#include "jsbool.h" -#include "jscntxt.h" -#include "jsconfig.h" -#include "jsgc.h" -#include "jsinterp.h" -#include "jslock.h" -#include "jsnum.h" -#include "jsobj.h" -#include "jsopcode.h" -#include "jsregexp.h" -#include "jsstr.h" - -#if JS_HAS_REPLACE_LAMBDA -#include "jsinterp.h" -#endif - -#define JSSTRDEP_RECURSION_LIMIT 100 - -size_t -js_MinimizeDependentStrings(JSString *str, int level, JSString **basep) -{ - JSString *base; - size_t start, length; - - JS_ASSERT(JSSTRING_IS_DEPENDENT(str)); - base = JSSTRDEP_BASE(str); - start = JSSTRDEP_START(str); - if (JSSTRING_IS_DEPENDENT(base)) { - if (level < JSSTRDEP_RECURSION_LIMIT) { - start += js_MinimizeDependentStrings(base, level + 1, &base); - } else { - do { - start += JSSTRDEP_START(base); - base = JSSTRDEP_BASE(base); - } while (JSSTRING_IS_DEPENDENT(base)); - } - if (start == 0) { - JS_ASSERT(JSSTRING_IS_PREFIX(str)); - JSPREFIX_SET_BASE(str, base); - } else if (start <= JSSTRDEP_START_MASK) { - length = JSSTRDEP_LENGTH(str); - JSSTRDEP_SET_START_AND_LENGTH(str, start, length); - JSSTRDEP_SET_BASE(str, base); - } - } - *basep = base; - return start; -} - -jschar * -js_GetDependentStringChars(JSString *str) -{ - size_t start; - JSString *base; - - start = js_MinimizeDependentStrings(str, 0, &base); - JS_ASSERT(!JSSTRING_IS_DEPENDENT(base)); - JS_ASSERT(start < base->length); - return base->chars + start; -} - -jschar * -js_GetStringChars(JSString *str) -{ - if (JSSTRING_IS_DEPENDENT(str) && !js_UndependString(NULL, str)) - return NULL; - - *js_GetGCThingFlags(str) &= ~GCF_MUTABLE; - return str->chars; -} - -JSString * -js_ConcatStrings(JSContext *cx, JSString *left, JSString *right) -{ - size_t rn, ln, lrdist, n; - jschar *rs, *ls, *s; - JSDependentString *ldep; /* non-null if left should become dependent */ - JSString *str; - - if (JSSTRING_IS_DEPENDENT(right)) { - rn = JSSTRDEP_LENGTH(right); - rs = JSSTRDEP_CHARS(right); - } else { - rn = right->length; - rs = right->chars; - } - if (rn == 0) - return left; - - if (JSSTRING_IS_DEPENDENT(left) || - !(*js_GetGCThingFlags(left) & GCF_MUTABLE)) { - /* We must copy if left does not own a buffer to realloc. */ - ln = JSSTRING_LENGTH(left); - if (ln == 0) - return right; - ls = JSSTRING_CHARS(left); - s = (jschar *) JS_malloc(cx, (ln + rn + 1) * sizeof(jschar)); - if (!s) - return NULL; - js_strncpy(s, ls, ln); - ldep = NULL; - } else { - /* We can realloc left's space and make it depend on our result. */ - ln = left->length; - if (ln == 0) - return right; - ls = left->chars; - s = (jschar *) JS_realloc(cx, ls, (ln + rn + 1) * sizeof(jschar)); - if (!s) - return NULL; - - /* Take care: right could depend on left! */ - lrdist = (size_t)(rs - ls); - if (lrdist < ln) - rs = s + lrdist; - left->chars = ls = s; - ldep = JSSTRDEP(left); - } - - js_strncpy(s + ln, rs, rn); - n = ln + rn; - s[n] = 0; - str = js_NewString(cx, s, n, GCF_MUTABLE); - if (!str) { - /* Out of memory: clean up any space we (re-)allocated. */ - if (!ldep) { - JS_free(cx, s); - } else { - s = JS_realloc(cx, ls, (ln + 1) * sizeof(jschar)); - if (s) - left->chars = s; - } - } else { - /* Morph left into a dependent prefix if we realloc'd its buffer. */ - if (ldep) { - JSPREFIX_SET_LENGTH(ldep, ln); - JSPREFIX_SET_BASE(ldep, str); -#ifdef DEBUG - { - JSRuntime *rt = cx->runtime; - JS_RUNTIME_METER(rt, liveDependentStrings); - JS_RUNTIME_METER(rt, totalDependentStrings); - JS_LOCK_RUNTIME_VOID(rt, - (rt->strdepLengthSum += (double)ln, - rt->strdepLengthSquaredSum += (double)ln * (double)ln)); - } -#endif - } - } - - return str; -} - -/* - * May be called with null cx by js_GetStringChars, above; and by the jslock.c - * MAKE_STRING_IMMUTABLE file-local macro. - */ -const jschar * -js_UndependString(JSContext *cx, JSString *str) -{ - size_t n, size; - jschar *s; - - if (JSSTRING_IS_DEPENDENT(str)) { - n = JSSTRDEP_LENGTH(str); - size = (n + 1) * sizeof(jschar); - s = (jschar *) (cx ? JS_malloc(cx, size) : malloc(size)); - if (!s) - return NULL; - - js_strncpy(s, JSSTRDEP_CHARS(str), n); - s[n] = 0; - str->length = n; - str->chars = s; - -#ifdef DEBUG - if (cx) { - JSRuntime *rt = cx->runtime; - JS_RUNTIME_UNMETER(rt, liveDependentStrings); - JS_RUNTIME_UNMETER(rt, totalDependentStrings); - JS_LOCK_RUNTIME_VOID(rt, - (rt->strdepLengthSum -= (double)n, - rt->strdepLengthSquaredSum -= (double)n * (double)n)); - } -#endif - } - - return str->chars; -} - -/* - * Forward declarations for URI encode/decode and helper routines - */ -static JSBool -str_decodeURI(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval); - -static JSBool -str_decodeURI_Component(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval); - -static JSBool -str_encodeURI(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval); - -static JSBool -str_encodeURI_Component(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval); - -static uint32 -Utf8ToOneUcs4Char(const uint8 *utf8Buffer, int utf8Length); - -/* - * Contributions from the String class to the set of methods defined for the - * global object. escape and unescape used to be defined in the Mocha library, - * but as ECMA decided to spec them, they've been moved to the core engine - * and made ECMA-compliant. (Incomplete escapes are interpreted as literal - * characters by unescape.) - */ - -/* - * Stuff to emulate the old libmocha escape, which took a second argument - * giving the type of escape to perform. Retained for compatibility, and - * copied here to avoid reliance on net.h, mkparse.c/NET_EscapeBytes. - */ - -#define URL_XALPHAS ((uint8) 1) -#define URL_XPALPHAS ((uint8) 2) -#define URL_PATH ((uint8) 4) - -static const uint8 urlCharType[256] = -/* Bit 0 xalpha -- the alphas - * Bit 1 xpalpha -- as xalpha but - * converts spaces to plus and plus to %20 - * Bit 2 ... path -- as xalphas but doesn't escape '/' - */ - /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ - { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1x */ - 0,0,0,0,0,0,0,0,0,0,7,4,0,7,7,4, /* 2x !"#$%&'()*+,-./ */ - 7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,0, /* 3x 0123456789:;<=>? */ - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, /* 4x @ABCDEFGHIJKLMNO */ - 7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,7, /* 5X PQRSTUVWXYZ[\]^_ */ - 0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, /* 6x `abcdefghijklmno */ - 7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0, /* 7X pqrstuvwxyz{\}~ DEL */ - 0, }; - -/* This matches the ECMA escape set when mask is 7 (default.) */ - -#define IS_OK(C, mask) (urlCharType[((uint8) (C))] & (mask)) - -/* See ECMA-262 15.1.2.4. */ -JSBool -js_str_escape(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSString *str; - size_t i, ni, length, newlength; - const jschar *chars; - jschar *newchars; - jschar ch; - jsint mask; - jsdouble d; - const char digits[] = {'0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - - mask = URL_XALPHAS | URL_XPALPHAS | URL_PATH; - if (argc > 1) { - if (!js_ValueToNumber(cx, argv[1], &d)) - return JS_FALSE; - if (!JSDOUBLE_IS_FINITE(d) || - (mask = (jsint)d) != d || - mask & ~(URL_XALPHAS | URL_XPALPHAS | URL_PATH)) - { - char numBuf[12]; - JS_snprintf(numBuf, sizeof numBuf, "%lx", (unsigned long) mask); - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_STRING_MASK, numBuf); - return JS_FALSE; - } - } - - str = js_ValueToString(cx, argv[0]); - if (!str) - return JS_FALSE; - argv[0] = STRING_TO_JSVAL(str); - - chars = JSSTRING_CHARS(str); - length = newlength = JSSTRING_LENGTH(str); - - /* Take a first pass and see how big the result string will need to be. */ - for (i = 0; i < length; i++) { - if ((ch = chars[i]) < 128 && IS_OK(ch, mask)) - continue; - if (ch < 256) { - if (mask == URL_XPALPHAS && ch == ' ') - continue; /* The character will be encoded as '+' */ - newlength += 2; /* The character will be encoded as %XX */ - } else { - newlength += 5; /* The character will be encoded as %uXXXX */ - } - - /* - * This overflow test works because newlength is incremented by at - * most 5 on each iteration. - */ - if (newlength < length) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - } - - if (newlength >= ~(size_t)0 / sizeof(jschar)) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - - newchars = (jschar *) JS_malloc(cx, (newlength + 1) * sizeof(jschar)); - if (!newchars) - return JS_FALSE; - for (i = 0, ni = 0; i < length; i++) { - if ((ch = chars[i]) < 128 && IS_OK(ch, mask)) { - newchars[ni++] = ch; - } else if (ch < 256) { - if (mask == URL_XPALPHAS && ch == ' ') { - newchars[ni++] = '+'; /* convert spaces to pluses */ - } else { - newchars[ni++] = '%'; - newchars[ni++] = digits[ch >> 4]; - newchars[ni++] = digits[ch & 0xF]; - } - } else { - newchars[ni++] = '%'; - newchars[ni++] = 'u'; - newchars[ni++] = digits[ch >> 12]; - newchars[ni++] = digits[(ch & 0xF00) >> 8]; - newchars[ni++] = digits[(ch & 0xF0) >> 4]; - newchars[ni++] = digits[ch & 0xF]; - } - } - JS_ASSERT(ni == newlength); - newchars[newlength] = 0; - - str = js_NewString(cx, newchars, newlength, 0); - if (!str) { - JS_free(cx, newchars); - return JS_FALSE; - } - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} -#undef IS_OK - -/* See ECMA-262 15.1.2.5 */ -static JSBool -str_unescape(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSString *str; - size_t i, ni, length; - const jschar *chars; - jschar *newchars; - jschar ch; - - str = js_ValueToString(cx, argv[0]); - if (!str) - return JS_FALSE; - argv[0] = STRING_TO_JSVAL(str); - - chars = JSSTRING_CHARS(str); - length = JSSTRING_LENGTH(str); - - /* Don't bother allocating less space for the new string. */ - newchars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar)); - if (!newchars) - return JS_FALSE; - ni = i = 0; - while (i < length) { - ch = chars[i++]; - if (ch == '%') { - if (i + 1 < length && - JS7_ISHEX(chars[i]) && JS7_ISHEX(chars[i + 1])) - { - ch = JS7_UNHEX(chars[i]) * 16 + JS7_UNHEX(chars[i + 1]); - i += 2; - } else if (i + 4 < length && chars[i] == 'u' && - JS7_ISHEX(chars[i + 1]) && JS7_ISHEX(chars[i + 2]) && - JS7_ISHEX(chars[i + 3]) && JS7_ISHEX(chars[i + 4])) - { - ch = (((((JS7_UNHEX(chars[i + 1]) << 4) - + JS7_UNHEX(chars[i + 2])) << 4) - + JS7_UNHEX(chars[i + 3])) << 4) - + JS7_UNHEX(chars[i + 4]); - i += 5; - } - } - newchars[ni++] = ch; - } - newchars[ni] = 0; - - str = js_NewString(cx, newchars, ni, 0); - if (!str) { - JS_free(cx, newchars); - return JS_FALSE; - } - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -#if JS_HAS_UNEVAL -static JSBool -str_uneval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSString *str; - - str = js_ValueToSource(cx, argv[0]); - if (!str) - return JS_FALSE; - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} -#endif - -const char js_escape_str[] = "escape"; -const char js_unescape_str[] = "unescape"; -#if JS_HAS_UNEVAL -const char js_uneval_str[] = "uneval"; -#endif -const char js_decodeURI_str[] = "decodeURI"; -const char js_encodeURI_str[] = "encodeURI"; -const char js_decodeURIComponent_str[] = "decodeURIComponent"; -const char js_encodeURIComponent_str[] = "encodeURIComponent"; - -static JSFunctionSpec string_functions[] = { - {js_escape_str, js_str_escape, 1,0,0}, - {js_unescape_str, str_unescape, 1,0,0}, -#if JS_HAS_UNEVAL - {js_uneval_str, str_uneval, 1,0,0}, -#endif - {js_decodeURI_str, str_decodeURI, 1,0,0}, - {js_encodeURI_str, str_encodeURI, 1,0,0}, - {js_decodeURIComponent_str, str_decodeURI_Component, 1,0,0}, - {js_encodeURIComponent_str, str_encodeURI_Component, 1,0,0}, - - {0,0,0,0,0} -}; - -jschar js_empty_ucstr[] = {0}; -JSSubString js_EmptySubString = {0, js_empty_ucstr}; - -enum string_tinyid { - STRING_LENGTH = -1 -}; - -static JSPropertySpec string_props[] = { - {js_length_str, STRING_LENGTH, - JSPROP_READONLY|JSPROP_PERMANENT|JSPROP_SHARED, 0,0}, - {0,0,0,0,0} -}; - -static JSBool -str_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - JSString *str; - jsint slot; - - if (!JSVAL_IS_INT(id)) - return JS_TRUE; - - /* - * Call js_ValueToString because getters and setters can be invoked on - * objects of different class, unlike enumerate, resolve, and the other - * class hooks. - */ - str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); - if (!str) - return JS_FALSE; - - slot = JSVAL_TO_INT(id); - if (slot == STRING_LENGTH) - *vp = INT_TO_JSVAL((jsint) JSSTRING_LENGTH(str)); - return JS_TRUE; -} - -#define STRING_ELEMENT_ATTRS (JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT) - -static JSBool -str_enumerate(JSContext *cx, JSObject *obj) -{ - JSString *str, *str1; - size_t i, length; - - /* Avoid infinite recursion via js_obj_toSource (see bug 271477). */ - if (JS_VERSION_IS_1_2(cx)) - return JS_TRUE; - - str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); - if (!str) - return JS_TRUE; - cx->newborn[GCX_STRING] = (JSGCThing *) str; - - length = JSSTRING_LENGTH(str); - for (i = 0; i < length; i++) { - str1 = js_NewDependentString(cx, str, i, 1, 0); - if (!str1) - return JS_FALSE; - if (!OBJ_DEFINE_PROPERTY(cx, obj, INT_TO_JSID(i), - STRING_TO_JSVAL(str1), NULL, NULL, - STRING_ELEMENT_ATTRS, NULL)) { - return JS_FALSE; - } - } - return JS_TRUE; -} - -static JSBool -str_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, - JSObject **objp) -{ - JSString *str, *str1; - jsint slot; - - if (!JSVAL_IS_INT(id) || (flags & JSRESOLVE_ASSIGNING)) - return JS_TRUE; - - str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); - if (!str) - return JS_TRUE; - cx->newborn[GCX_STRING] = (JSGCThing *) str; - - slot = JSVAL_TO_INT(id); - if ((size_t)slot < JSSTRING_LENGTH(str)) { - str1 = js_NewDependentString(cx, str, (size_t)slot, 1, 0); - if (!str1) - return JS_FALSE; - if (!OBJ_DEFINE_PROPERTY(cx, obj, INT_TO_JSID(slot), - STRING_TO_JSVAL(str1), NULL, NULL, - STRING_ELEMENT_ATTRS, NULL)) { - return JS_FALSE; - } - *objp = obj; - } - return JS_TRUE; -} - -JSClass js_StringClass = { - js_String_str, - JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE, - JS_PropertyStub, JS_PropertyStub, str_getProperty, JS_PropertyStub, - str_enumerate, (JSResolveOp)str_resolve, JS_ConvertStub, JS_FinalizeStub, - JSCLASS_NO_OPTIONAL_MEMBERS -}; - -#if JS_HAS_TOSOURCE - -/* - * String.prototype.quote is generic (as are most string methods), unlike - * toSource, toString, and valueOf. - */ -static JSBool -str_quote(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSString *str; - - str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); - if (!str) - return JS_FALSE; - argv[-1] = STRING_TO_JSVAL(str); - - str = js_QuoteString(cx, str, '"'); - if (!str) - return JS_FALSE; - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -static JSBool -str_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsval v; - JSString *str; - size_t i, j, k, n; - char buf[16]; - jschar *s, *t; - - if (!JS_InstanceOf(cx, obj, &js_StringClass, argv)) - return JS_FALSE; - v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE); - if (!JSVAL_IS_STRING(v)) - return js_obj_toSource(cx, obj, argc, argv, rval); - str = js_QuoteString(cx, JSVAL_TO_STRING(v), '"'); - if (!str) - return JS_FALSE; - j = JS_snprintf(buf, sizeof buf, "(new %s(", js_StringClass.name); - s = JSSTRING_CHARS(str); - k = JSSTRING_LENGTH(str); - n = j + k + 2; - t = (jschar *) JS_malloc(cx, (n + 1) * sizeof(jschar)); - if (!t) - return JS_FALSE; - for (i = 0; i < j; i++) - t[i] = buf[i]; - for (j = 0; j < k; i++, j++) - t[i] = s[j]; - t[i++] = ')'; - t[i++] = ')'; - t[i] = 0; - str = js_NewString(cx, t, n, 0); - if (!str) { - JS_free(cx, t); - return JS_FALSE; - } - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -#endif /* JS_HAS_TOSOURCE */ - -static JSBool -str_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsval v; - - if (!JS_InstanceOf(cx, obj, &js_StringClass, argv)) - return JS_FALSE; - v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE); - if (!JSVAL_IS_STRING(v)) - return js_obj_toString(cx, obj, argc, argv, rval); - *rval = v; - return JS_TRUE; -} - -static JSBool -str_valueOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - if (!JS_InstanceOf(cx, obj, &js_StringClass, argv)) - return JS_FALSE; - *rval = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE); - return JS_TRUE; -} - -/* - * Java-like string native methods. - */ -static JSBool -str_substring(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSString *str; - jsdouble d; - jsdouble length, begin, end; - - str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); - if (!str) - return JS_FALSE; - argv[-1] = STRING_TO_JSVAL(str); - - if (argc != 0) { - if (!js_ValueToNumber(cx, argv[0], &d)) - return JS_FALSE; - length = JSSTRING_LENGTH(str); - begin = js_DoubleToInteger(d); - if (begin < 0) - begin = 0; - else if (begin > length) - begin = length; - - if (argc == 1) { - end = length; - } else { - if (!js_ValueToNumber(cx, argv[1], &d)) - return JS_FALSE; - end = js_DoubleToInteger(d); - if (end < 0) - end = 0; - else if (end > length) - end = length; - if (end < begin) { - if (!JS_VERSION_IS_1_2(cx)) { - /* XXX emulate old JDK1.0 java.lang.String.substring. */ - jsdouble tmp = begin; - begin = end; - end = tmp; - } else { - end = begin; - } - } - } - - str = js_NewDependentString(cx, str, (size_t)begin, - (size_t)(end - begin), 0); - if (!str) - return JS_FALSE; - } - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -static JSBool -str_toLowerCase(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSString *str; - size_t i, n; - jschar *s, *news; - - str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); - if (!str) - return JS_FALSE; - argv[-1] = STRING_TO_JSVAL(str); - - n = JSSTRING_LENGTH(str); - news = (jschar *) JS_malloc(cx, (n + 1) * sizeof(jschar)); - if (!news) - return JS_FALSE; - s = JSSTRING_CHARS(str); - for (i = 0; i < n; i++) - news[i] = JS_TOLOWER(s[i]); - news[n] = 0; - str = js_NewString(cx, news, n, 0); - if (!str) { - JS_free(cx, news); - return JS_FALSE; - } - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -static JSBool -str_toLocaleLowerCase(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSString *str; - - /* - * Forcefully ignore the first (or any) argument and return toLowerCase(), - * ECMA has reserved that argument, presumably for defining the locale. - */ - if (cx->localeCallbacks && cx->localeCallbacks->localeToLowerCase) { - str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); - if (!str) - return JS_FALSE; - argv[-1] = STRING_TO_JSVAL(str); - return cx->localeCallbacks->localeToLowerCase(cx, str, rval); - } - return str_toLowerCase(cx, obj, 0, argv, rval); -} - -static JSBool -str_toUpperCase(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSString *str; - size_t i, n; - jschar *s, *news; - - str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); - if (!str) - return JS_FALSE; - argv[-1] = STRING_TO_JSVAL(str); - - n = JSSTRING_LENGTH(str); - news = (jschar *) JS_malloc(cx, (n + 1) * sizeof(jschar)); - if (!news) - return JS_FALSE; - s = JSSTRING_CHARS(str); - for (i = 0; i < n; i++) - news[i] = JS_TOUPPER(s[i]); - news[n] = 0; - str = js_NewString(cx, news, n, 0); - if (!str) { - JS_free(cx, news); - return JS_FALSE; - } - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -static JSBool -str_toLocaleUpperCase(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSString *str; - - /* - * Forcefully ignore the first (or any) argument and return toUpperCase(), - * ECMA has reserved that argument, presumbaly for defining the locale. - */ - if (cx->localeCallbacks && cx->localeCallbacks->localeToUpperCase) { - str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); - if (!str) - return JS_FALSE; - argv[-1] = STRING_TO_JSVAL(str); - return cx->localeCallbacks->localeToUpperCase(cx, str, rval); - } - return str_toUpperCase(cx, obj, 0, argv, rval); -} - -static JSBool -str_localeCompare(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSString *str, *thatStr; - - str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); - if (!str) - return JS_FALSE; - argv[-1] = STRING_TO_JSVAL(str); - - if (argc == 0) { - *rval = JSVAL_ZERO; - } else { - thatStr = js_ValueToString(cx, argv[0]); - if (!thatStr) - return JS_FALSE; - if (cx->localeCallbacks && cx->localeCallbacks->localeCompare) { - argv[0] = STRING_TO_JSVAL(thatStr); - return cx->localeCallbacks->localeCompare(cx, str, thatStr, rval); - } - *rval = INT_TO_JSVAL(js_CompareStrings(str, thatStr)); - } - return JS_TRUE; -} - -static JSBool -str_charAt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSString *str; - jsdouble d; - size_t index; - - str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); - if (!str) - return JS_FALSE; - argv[-1] = STRING_TO_JSVAL(str); - - if (argc == 0) { - d = 0.0; - } else { - if (!js_ValueToNumber(cx, argv[0], &d)) - return JS_FALSE; - d = js_DoubleToInteger(d); - } - - if (d < 0 || JSSTRING_LENGTH(str) <= d) { - *rval = JS_GetEmptyStringValue(cx); - } else { - index = (size_t)d; - str = js_NewDependentString(cx, str, index, 1, 0); - if (!str) - return JS_FALSE; - *rval = STRING_TO_JSVAL(str); - } - return JS_TRUE; -} - -static JSBool -str_charCodeAt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSString *str; - jsdouble d; - size_t index; - - str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); - if (!str) - return JS_FALSE; - argv[-1] = STRING_TO_JSVAL(str); - - if (argc == 0) { - d = 0.0; - } else { - if (!js_ValueToNumber(cx, argv[0], &d)) - return JS_FALSE; - d = js_DoubleToInteger(d); - } - - if (d < 0 || JSSTRING_LENGTH(str) <= d) { - *rval = JS_GetNaNValue(cx); - } else { - index = (size_t)d; - *rval = INT_TO_JSVAL((jsint) JSSTRING_CHARS(str)[index]); - } - return JS_TRUE; -} - -jsint -js_BoyerMooreHorspool(const jschar *text, jsint textlen, - const jschar *pat, jsint patlen, - jsint start) -{ - jsint i, j, k, m; - uint8 skip[BMH_CHARSET_SIZE]; - jschar c; - - JS_ASSERT(0 < patlen && patlen <= BMH_PATLEN_MAX); - for (i = 0; i < BMH_CHARSET_SIZE; i++) - skip[i] = (uint8)patlen; - m = patlen - 1; - for (i = 0; i < m; i++) { - c = pat[i]; - if (c >= BMH_CHARSET_SIZE) - return BMH_BAD_PATTERN; - skip[c] = (uint8)(m - i); - } - for (k = start + m; - k < textlen; - k += ((c = text[k]) >= BMH_CHARSET_SIZE) ? patlen : skip[c]) { - for (i = k, j = m; ; i--, j--) { - if (j < 0) - return i + 1; - if (text[i] != pat[j]) - break; - } - } - return -1; -} - -static JSBool -str_indexOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSString *str, *str2; - jsint i, j, index, textlen, patlen; - const jschar *text, *pat; - jsdouble d; - - str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); - if (!str) - return JS_FALSE; - argv[-1] = STRING_TO_JSVAL(str); - text = JSSTRING_CHARS(str); - textlen = (jsint) JSSTRING_LENGTH(str); - - str2 = js_ValueToString(cx, argv[0]); - if (!str2) - return JS_FALSE; - argv[0] = STRING_TO_JSVAL(str2); - pat = JSSTRING_CHARS(str2); - patlen = (jsint) JSSTRING_LENGTH(str2); - - if (argc > 1) { - if (!js_ValueToNumber(cx, argv[1], &d)) - return JS_FALSE; - d = js_DoubleToInteger(d); - if (d < 0) - i = 0; - else if (d > textlen) - i = textlen; - else - i = (jsint)d; - } else { - i = 0; - } - if (patlen == 0) { - *rval = INT_TO_JSVAL(i); - return JS_TRUE; - } - - /* XXX tune the BMH threshold (512) */ - if ((jsuint)(patlen - 2) <= BMH_PATLEN_MAX - 2 && textlen >= 512) { - index = js_BoyerMooreHorspool(text, textlen, pat, patlen, i); - if (index != BMH_BAD_PATTERN) - goto out; - } - - index = -1; - j = 0; - while (i + j < textlen) { - if (text[i + j] == pat[j]) { - if (++j == patlen) { - index = i; - break; - } - } else { - i++; - j = 0; - } - } - -out: - *rval = INT_TO_JSVAL(index); - return JS_TRUE; -} - -static JSBool -str_lastIndexOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSString *str, *str2; - const jschar *text, *pat; - jsint i, j, textlen, patlen; - jsdouble d; - - str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); - if (!str) - return JS_FALSE; - argv[-1] = STRING_TO_JSVAL(str); - text = JSSTRING_CHARS(str); - textlen = (jsint) JSSTRING_LENGTH(str); - - str2 = js_ValueToString(cx, argv[0]); - if (!str2) - return JS_FALSE; - argv[0] = STRING_TO_JSVAL(str2); - pat = JSSTRING_CHARS(str2); - patlen = (jsint) JSSTRING_LENGTH(str2); - - if (argc > 1) { - if (!js_ValueToNumber(cx, argv[1], &d)) - return JS_FALSE; - if (JSDOUBLE_IS_NaN(d)) { - i = textlen; - } else { - d = js_DoubleToInteger(d); - if (d < 0) - i = 0; - else if (d > textlen) - i = textlen; - else - i = (jsint)d; - } - } else { - i = textlen; - } - - if (patlen == 0) { - *rval = INT_TO_JSVAL(i); - return JS_TRUE; - } - - j = 0; - while (i >= 0) { - /* Don't assume that text is NUL-terminated: it could be dependent. */ - if (i + j < textlen && text[i + j] == pat[j]) { - if (++j == patlen) - break; - } else { - i--; - j = 0; - } - } - *rval = INT_TO_JSVAL(i); - return JS_TRUE; -} - -/* - * Perl-inspired string functions. - */ -#if JS_HAS_REGEXPS -typedef struct GlobData { - uintN flags; /* inout: mode and flag bits, see below */ - uintN optarg; /* in: index of optional flags argument */ - JSString *str; /* out: 'this' parameter object as string */ - JSRegExp *regexp; /* out: regexp parameter object private data */ -} GlobData; - -/* - * Mode and flag bit definitions for match_or_replace's GlobData.flags field. - */ -#define MODE_MATCH 0x00 /* in: return match array on success */ -#define MODE_REPLACE 0x01 /* in: match and replace */ -#define MODE_SEARCH 0x02 /* in: search only, return match index or -1 */ -#define GET_MODE(f) ((f) & 0x03) -#define FORCE_FLAT 0x04 /* in: force flat (non-regexp) string match */ -#define KEEP_REGEXP 0x08 /* inout: keep GlobData.regexp alive for caller - of match_or_replace; if set on input - but clear on output, regexp ownership - does not pass to caller */ -#define GLOBAL_REGEXP 0x10 /* out: regexp had the 'g' flag */ - -static JSBool -match_or_replace(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - JSBool (*glob)(JSContext *cx, jsint count, GlobData *data), - GlobData *data, jsval *rval) -{ - JSString *str, *src, *opt; - JSObject *reobj; - JSRegExp *re; - size_t index, length; - JSBool ok, test; - jsint count; - - str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); - if (!str) - return JS_FALSE; - argv[-1] = STRING_TO_JSVAL(str); - data->str = str; - - if (JSVAL_IS_REGEXP(cx, argv[0])) { - reobj = JSVAL_TO_OBJECT(argv[0]); - re = (JSRegExp *) JS_GetPrivate(cx, reobj); - } else { - src = js_ValueToString(cx, argv[0]); - if (!src) - return JS_FALSE; - if (data->optarg < argc) { - argv[0] = STRING_TO_JSVAL(src); - opt = js_ValueToString(cx, argv[data->optarg]); - if (!opt) - return JS_FALSE; - } else { - opt = NULL; - } - re = js_NewRegExpOpt(cx, NULL, src, opt, - (data->flags & FORCE_FLAT) != 0); - if (!re) - return JS_FALSE; - reobj = NULL; - } - /* From here on, all control flow must reach the matching DROP. */ - data->regexp = re; - HOLD_REGEXP(cx, re); - - if (re->flags & JSREG_GLOB) - data->flags |= GLOBAL_REGEXP; - index = 0; - if (GET_MODE(data->flags) == MODE_SEARCH) { - ok = js_ExecuteRegExp(cx, re, str, &index, JS_TRUE, rval); - if (ok) { - *rval = (*rval == JSVAL_TRUE) - ? INT_TO_JSVAL(cx->regExpStatics.leftContext.length) - : INT_TO_JSVAL(-1); - } - } else if (data->flags & GLOBAL_REGEXP) { - if (reobj) { - /* Set the lastIndex property's reserved slot to 0. */ - ok = js_SetLastIndex(cx, reobj, 0); - } else { - ok = JS_TRUE; - } - if (ok) { - length = JSSTRING_LENGTH(str); - for (count = 0; index <= length; count++) { - ok = js_ExecuteRegExp(cx, re, str, &index, JS_TRUE, rval); - if (!ok || *rval != JSVAL_TRUE) - break; - ok = glob(cx, count, data); - if (!ok) - break; - if (cx->regExpStatics.lastMatch.length == 0) { - if (index == length) - break; - index++; - } - } - } - } else { - if (GET_MODE(data->flags) == MODE_REPLACE) { - test = JS_TRUE; - } else { - /* - * MODE_MATCH implies str_match is being called from a script or a - * scripted function. If the caller cares only about testing null - * vs. non-null return value, optimize away the array object that - * would normally be returned in *rval. - */ - JSStackFrame *fp = cx->fp->down; - - /* Skip Function.prototype.call and .apply frames. */ - while (fp && !fp->pc) { - JS_ASSERT(!fp->script); - fp = fp->down; - } - - /* Assume a full array result is required, then prove otherwise. */ - test = JS_FALSE; - if (fp) { - JS_ASSERT(*fp->pc == JSOP_CALL || *fp->pc == JSOP_NEW); - JS_ASSERT(js_CodeSpec[*fp->pc].length == 3); - switch (fp->pc[3]) { - case JSOP_POP: - case JSOP_IFEQ: - case JSOP_IFNE: - case JSOP_IFEQX: - case JSOP_IFNEX: - test = JS_TRUE; - break; - default:; - } - } - } - ok = js_ExecuteRegExp(cx, re, str, &index, test, rval); - } - - DROP_REGEXP(cx, re); - if (reobj) { - /* Tell our caller that it doesn't need to destroy data->regexp. */ - data->flags &= ~KEEP_REGEXP; - } else if (!(data->flags & KEEP_REGEXP)) { - /* Caller didn't want to keep data->regexp, so null and destroy it. */ - data->regexp = NULL; - js_DestroyRegExp(cx, re); - } - - return ok; -} - -typedef struct MatchData { - GlobData base; - jsval *arrayval; /* NB: local root pointer */ -} MatchData; - -static JSBool -match_glob(JSContext *cx, jsint count, GlobData *data) -{ - MatchData *mdata; - JSObject *arrayobj; - JSSubString *matchsub; - JSString *matchstr; - jsval v; - - mdata = (MatchData *)data; - arrayobj = JSVAL_TO_OBJECT(*mdata->arrayval); - if (!arrayobj) { - arrayobj = js_ConstructObject(cx, &js_ArrayClass, NULL, NULL, 0, NULL); - if (!arrayobj) - return JS_FALSE; - *mdata->arrayval = OBJECT_TO_JSVAL(arrayobj); - } - matchsub = &cx->regExpStatics.lastMatch; - matchstr = js_NewStringCopyN(cx, matchsub->chars, matchsub->length, 0); - if (!matchstr) - return JS_FALSE; - v = STRING_TO_JSVAL(matchstr); - return js_SetProperty(cx, arrayobj, INT_TO_JSID(count), &v); -} - -static JSBool -str_match(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - MatchData mdata; - JSBool ok; - - mdata.base.flags = MODE_MATCH; - mdata.base.optarg = 1; - mdata.arrayval = &argv[2]; - *mdata.arrayval = JSVAL_NULL; - ok = match_or_replace(cx, obj, argc, argv, match_glob, &mdata.base, rval); - if (ok && !JSVAL_IS_NULL(*mdata.arrayval)) - *rval = *mdata.arrayval; - return ok; -} - -static JSBool -str_search(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - GlobData data; - - data.flags = MODE_SEARCH; - data.optarg = 1; - return match_or_replace(cx, obj, argc, argv, NULL, &data, rval); -} - -typedef struct ReplaceData { - GlobData base; /* base struct state */ - JSObject *lambda; /* replacement function object or null */ - JSString *repstr; /* replacement string */ - jschar *dollar; /* null or pointer to first $ in repstr */ - jschar *dollarEnd; /* limit pointer for js_strchr_limit */ - jschar *chars; /* result chars, null initially */ - size_t length; /* result length, 0 initially */ - jsint index; /* index in result of next replacement */ - jsint leftIndex; /* left context index in base.str->chars */ - JSSubString dollarStr; /* for "$$" interpret_dollar result */ -} ReplaceData; - -static JSSubString * -interpret_dollar(JSContext *cx, jschar *dp, jschar *ep, ReplaceData *rdata, - size_t *skip) -{ - JSVersion version; - JSRegExpStatics *res; - jschar dc, *cp; - uintN num, tmp; - JSString *str; - - JS_ASSERT(*dp == '$'); - - /* - * Allow a real backslash (literal "\\" before "$1") to escape "$1", e.g. - * Do this only for versions strictly less than ECMAv3. - */ - version = cx->version & JSVERSION_MASK; - if (version != JSVERSION_DEFAULT && version <= JSVERSION_1_4) { - if (dp > JSSTRING_CHARS(rdata->repstr) && dp[-1] == '\\') - return NULL; - } - - /* If there is only a dollar, bail now */ - if (dp + 1 >= ep) - return NULL; - - /* Interpret all Perl match-induced dollar variables. */ - res = &cx->regExpStatics; - dc = dp[1]; - if (JS7_ISDEC(dc)) { - if (version != JSVERSION_DEFAULT && version <= JSVERSION_1_4) { - if (dc == '0') - return NULL; - - /* Check for overflow to avoid gobbling arbitrary decimal digits. */ - num = 0; - cp = dp; - while (++cp < ep && (dc = *cp, JS7_ISDEC(dc))) { - tmp = 10 * num + JS7_UNDEC(dc); - if (tmp < num) - break; - num = tmp; - } - } else { /* ECMA 3, 1-9 or 01-99 */ - num = JS7_UNDEC(dc); - if (num > res->parenCount) - return NULL; - - cp = dp + 2; - if (cp < ep && (dc = *cp, JS7_ISDEC(dc))) { - tmp = 10 * num + JS7_UNDEC(dc); - if (tmp <= res->parenCount) { - cp++; - num = tmp; - } - } - if (num == 0) - return NULL; - } - /* Adjust num from 1 $n-origin to 0 array-index-origin. */ - num--; - *skip = cp - dp; - return REGEXP_PAREN_SUBSTRING(res, num); - } - - *skip = 2; - switch (dc) { - case '$': - rdata->dollarStr.chars = dp; - rdata->dollarStr.length = 1; - return &rdata->dollarStr; - case '&': - return &res->lastMatch; - case '+': - return &res->lastParen; - case '`': - if (version == JSVERSION_1_2) { - /* - * JS1.2 imitated the Perl4 bug where left context at each step - * in an iterative use of a global regexp started from last match, - * not from the start of the target string. But Perl4 does start - * $` at the beginning of the target string when it is used in a - * substitution, so we emulate that special case here. - */ - str = rdata->base.str; - res->leftContext.chars = JSSTRING_CHARS(str); - res->leftContext.length = res->lastMatch.chars - - JSSTRING_CHARS(str); - } - return &res->leftContext; - case '\'': - return &res->rightContext; - } - return NULL; -} - -static JSBool -find_replen(JSContext *cx, ReplaceData *rdata, size_t *sizep) -{ - JSString *repstr; - size_t replen, skip; - jschar *dp, *ep; - JSSubString *sub; -#if JS_HAS_REPLACE_LAMBDA - JSObject *lambda; - - lambda = rdata->lambda; - if (lambda) { - uintN argc, i, j, m, n, p; - jsval *sp, *oldsp, rval; - void *mark; - JSStackFrame *fp; - JSBool ok; - - /* - * Save the regExpStatics from the current regexp, since they may be - * clobbered by a RegExp usage in the lambda function. Note that all - * members of JSRegExpStatics are JSSubStrings, so not GC roots, save - * input, which is rooted otherwise via argv[-1] in str_replace. - */ - JSRegExpStatics save = cx->regExpStatics; - JSBool freeMoreParens = JS_FALSE; - - /* - * In the lambda case, not only do we find the replacement string's - * length, we compute repstr and return it via rdata for use within - * do_replace. The lambda is called with arguments ($&, $1, $2, ..., - * index, input), i.e., all the properties of a regexp match array. - * For $&, etc., we must create string jsvals from cx->regExpStatics. - * We grab up stack space to keep the newborn strings GC-rooted. - */ - p = rdata->base.regexp->parenCount; - argc = 1 + p + 2; - sp = js_AllocStack(cx, 2 + argc, &mark); - if (!sp) - return JS_FALSE; - - /* Push lambda and its 'this' parameter. */ - *sp++ = OBJECT_TO_JSVAL(lambda); - *sp++ = OBJECT_TO_JSVAL(OBJ_GET_PARENT(cx, lambda)); - -#define PUSH_REGEXP_STATIC(sub) \ - JS_BEGIN_MACRO \ - JSString *str = js_NewStringCopyN(cx, \ - cx->regExpStatics.sub.chars, \ - cx->regExpStatics.sub.length, \ - 0); \ - if (!str) { \ - ok = JS_FALSE; \ - goto lambda_out; \ - } \ - *sp++ = STRING_TO_JSVAL(str); \ - JS_END_MACRO - - /* Push $&, $1, $2, ... */ - PUSH_REGEXP_STATIC(lastMatch); - i = 0; - m = cx->regExpStatics.parenCount; - n = JS_MIN(m, 9); - for (j = 0; i < n; i++, j++) - PUSH_REGEXP_STATIC(parens[j]); - for (j = 0; i < m; i++, j++) - PUSH_REGEXP_STATIC(moreParens[j]); - - /* - * We need to clear moreParens in the top-of-stack cx->regExpStatics - * to it won't be possibly realloc'ed, leaving the bottom-of-stack - * moreParens pointing to freed memory. - */ - cx->regExpStatics.moreParens = NULL; - freeMoreParens = JS_TRUE; - -#undef PUSH_REGEXP_STATIC - - /* Make sure to push undefined for any unmatched parens. */ - for (; i < p; i++) - *sp++ = JSVAL_VOID; - - /* Push match index and input string. */ - *sp++ = INT_TO_JSVAL((jsint)cx->regExpStatics.leftContext.length); - *sp++ = STRING_TO_JSVAL(rdata->base.str); - - /* Lift current frame to include the args and do the call. */ - fp = cx->fp; - oldsp = fp->sp; - fp->sp = sp; - ok = js_Invoke(cx, argc, JSINVOKE_INTERNAL); - rval = fp->sp[-1]; - fp->sp = oldsp; - - if (ok) { - /* - * NB: we count on the newborn string root to hold any string - * created by this js_ValueToString that would otherwise be GC- - * able, until we use rdata->repstr in do_replace. - */ - repstr = js_ValueToString(cx, rval); - if (!repstr) { - ok = JS_FALSE; - } else { - rdata->repstr = repstr; - *sizep = JSSTRING_LENGTH(repstr); - } - } - - lambda_out: - js_FreeStack(cx, mark); - if (freeMoreParens) - JS_free(cx, cx->regExpStatics.moreParens); - cx->regExpStatics = save; - return ok; - } -#endif /* JS_HAS_REPLACE_LAMBDA */ - - repstr = rdata->repstr; - replen = JSSTRING_LENGTH(repstr); - for (dp = rdata->dollar, ep = rdata->dollarEnd; dp; - dp = js_strchr_limit(dp, '$', ep)) { - sub = interpret_dollar(cx, dp, ep, rdata, &skip); - if (sub) { - replen += sub->length - skip; - dp += skip; - } - else - dp++; - } - *sizep = replen; - return JS_TRUE; -} - -static void -do_replace(JSContext *cx, ReplaceData *rdata, jschar *chars) -{ - JSString *repstr; - jschar *bp, *cp, *dp, *ep; - size_t len, skip; - JSSubString *sub; - - repstr = rdata->repstr; - bp = cp = JSSTRING_CHARS(repstr); - for (dp = rdata->dollar, ep = rdata->dollarEnd; dp; - dp = js_strchr_limit(dp, '$', ep)) { - len = dp - cp; - js_strncpy(chars, cp, len); - chars += len; - cp = dp; - sub = interpret_dollar(cx, dp, ep, rdata, &skip); - if (sub) { - len = sub->length; - js_strncpy(chars, sub->chars, len); - chars += len; - cp += skip; - dp += skip; - } else { - dp++; - } - } - js_strncpy(chars, cp, JSSTRING_LENGTH(repstr) - (cp - bp)); -} - -static JSBool -replace_glob(JSContext *cx, jsint count, GlobData *data) -{ - ReplaceData *rdata; - JSString *str; - size_t leftoff, leftlen, replen, growth; - const jschar *left; - jschar *chars; - - rdata = (ReplaceData *)data; - str = data->str; - leftoff = rdata->leftIndex; - left = JSSTRING_CHARS(str) + leftoff; - leftlen = cx->regExpStatics.lastMatch.chars - left; - rdata->leftIndex = cx->regExpStatics.lastMatch.chars - JSSTRING_CHARS(str); - rdata->leftIndex += cx->regExpStatics.lastMatch.length; - if (!find_replen(cx, rdata, &replen)) - return JS_FALSE; - growth = leftlen + replen; - chars = (jschar *) - (rdata->chars - ? JS_realloc(cx, rdata->chars, (rdata->length + growth + 1) - * sizeof(jschar)) - : JS_malloc(cx, (growth + 1) * sizeof(jschar))); - if (!chars) { - JS_free(cx, rdata->chars); - rdata->chars = NULL; - return JS_FALSE; - } - rdata->chars = chars; - rdata->length += growth; - chars += rdata->index; - rdata->index += growth; - js_strncpy(chars, left, leftlen); - chars += leftlen; - do_replace(cx, rdata, chars); - return JS_TRUE; -} - -static JSBool -str_replace(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSObject *lambda; - JSString *repstr, *str; - ReplaceData rdata; - JSVersion version; - JSBool ok; - jschar *chars; - size_t leftlen, rightlen, length; - -#if JS_HAS_REPLACE_LAMBDA - if (JS_TypeOfValue(cx, argv[1]) == JSTYPE_FUNCTION) { - lambda = JSVAL_TO_OBJECT(argv[1]); - repstr = NULL; - } else -#endif - { - if (!JS_ConvertValue(cx, argv[1], JSTYPE_STRING, &argv[1])) - return JS_FALSE; - repstr = JSVAL_TO_STRING(argv[1]); - lambda = NULL; - } - - /* - * For ECMA Edition 3, the first argument is to be converted to a string - * to match in a "flat" sense (without regular expression metachars having - * special meanings) UNLESS the first arg is a RegExp object. - */ - rdata.base.flags = MODE_REPLACE | KEEP_REGEXP; - version = cx->version & JSVERSION_MASK; - if (version == JSVERSION_DEFAULT || version > JSVERSION_1_4) - rdata.base.flags |= FORCE_FLAT; - rdata.base.optarg = 2; - - rdata.lambda = lambda; - rdata.repstr = repstr; - if (repstr) { - rdata.dollarEnd = JSSTRING_CHARS(repstr) + JSSTRING_LENGTH(repstr); - rdata.dollar = js_strchr_limit(JSSTRING_CHARS(repstr), '$', - rdata.dollarEnd); - } else { - rdata.dollar = rdata.dollarEnd = NULL; - } - rdata.chars = NULL; - rdata.length = 0; - rdata.index = 0; - rdata.leftIndex = 0; - - ok = match_or_replace(cx, obj, argc, argv, replace_glob, &rdata.base, rval); - if (!ok) - return JS_FALSE; - - if (!rdata.chars) { - if ((rdata.base.flags & GLOBAL_REGEXP) || *rval != JSVAL_TRUE) { - /* Didn't match even once. */ - *rval = STRING_TO_JSVAL(rdata.base.str); - goto out; - } - leftlen = cx->regExpStatics.leftContext.length; - ok = find_replen(cx, &rdata, &length); - if (!ok) - goto out; - length += leftlen; - chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar)); - if (!chars) { - ok = JS_FALSE; - goto out; - } - js_strncpy(chars, cx->regExpStatics.leftContext.chars, leftlen); - do_replace(cx, &rdata, chars + leftlen); - rdata.chars = chars; - rdata.length = length; - } - - rightlen = cx->regExpStatics.rightContext.length; - length = rdata.length + rightlen; - chars = (jschar *) - JS_realloc(cx, rdata.chars, (length + 1) * sizeof(jschar)); - if (!chars) { - JS_free(cx, rdata.chars); - ok = JS_FALSE; - goto out; - } - js_strncpy(chars + rdata.length, cx->regExpStatics.rightContext.chars, - rightlen); - chars[length] = 0; - - str = js_NewString(cx, chars, length, 0); - if (!str) { - JS_free(cx, chars); - ok = JS_FALSE; - goto out; - } - *rval = STRING_TO_JSVAL(str); - -out: - /* If KEEP_REGEXP is still set, it's our job to destroy regexp now. */ - if (rdata.base.flags & KEEP_REGEXP) - js_DestroyRegExp(cx, rdata.base.regexp); - return ok; -} -#endif /* JS_HAS_REGEXPS */ - -/* - * Subroutine used by str_split to find the next split point in str, starting - * at offset *ip and looking either for the separator substring given by sep, - * or for the next re match. In the re case, return the matched separator in - * *sep, and the possibly updated offset in *ip. - * - * Return -2 on error, -1 on end of string, >= 0 for a valid index of the next - * separator occurrence if found, or str->length if no separator is found. - */ -static jsint -find_split(JSContext *cx, JSString *str, JSRegExp *re, jsint *ip, - JSSubString *sep) -{ - jsint i, j, k; - jschar *chars; - size_t length; - - /* - * Stop if past end of string. If at end of string, we will compare the - * null char stored there (by js_NewString*) to sep->chars[j] in the while - * loop at the end of this function, so that - * - * "ab,".split(',') => ["ab", ""] - * - * and the resulting array converts back to the string "ab," for symmetry. - * However, we ape Perl and do this only if there is a sufficiently large - * limit argument (see str_split). - */ - i = *ip; - if ((size_t)i > JSSTRING_LENGTH(str)) - return -1; - - /* - * Perl4 special case for str.split(' '), only if the user has selected - * JavaScript1.2 explicitly. Split on whitespace, and skip leading w/s. - * Strange but true, apparently modeled after awk. - * - * NB: we set sep->length to the length of the w/s run, so we must test - * sep->chars[1] == 0 to make sure sep is just one space. - */ - chars = JSSTRING_CHARS(str); - length = JSSTRING_LENGTH(str); - if (JS_VERSION_IS_1_2(cx) && - !re && *sep->chars == ' ' && sep->chars[1] == 0) { - - /* Skip leading whitespace if at front of str. */ - if (i == 0) { - while (JS_ISSPACE(chars[i])) - i++; - *ip = i; - } - - /* Don't delimit whitespace at end of string. */ - if ((size_t)i == length) - return -1; - - /* Skip over the non-whitespace chars. */ - while ((size_t)i < length && !JS_ISSPACE(chars[i])) - i++; - - /* Now skip the next run of whitespace. */ - j = i; - while ((size_t)j < length && JS_ISSPACE(chars[j])) - j++; - - /* Update sep->length to count delimiter chars. */ - sep->length = (size_t)(j - i); - return i; - } - -#if JS_HAS_REGEXPS - /* - * Match a regular expression against the separator at or above index i. - * Call js_ExecuteRegExp with true for the test argument. On successful - * match, get the separator from cx->regExpStatics.lastMatch. - */ - if (re) { - size_t index; - jsval rval; - - again: - /* JS1.2 deviated from Perl by never matching at end of string. */ - index = (size_t)i; - if (!js_ExecuteRegExp(cx, re, str, &index, JS_TRUE, &rval)) - return -2; - if (rval != JSVAL_TRUE) { - /* Mismatch: ensure our caller advances i past end of string. */ - sep->length = 1; - return length; - } - i = (jsint)index; - *sep = cx->regExpStatics.lastMatch; - if (sep->length == 0) { - /* - * Empty string match: never split on an empty match at the start - * of a find_split cycle. Same rule as for an empty global match - * in match_or_replace. - */ - if (i == *ip) { - /* - * "Bump-along" to avoid sticking at an empty match, but don't - * bump past end of string -- our caller must do that by adding - * sep->length to our return value. - */ - if ((size_t)i == length) { - if (JS_VERSION_IS_1_2(cx)) { - sep->length = 1; - return i; - } - return -1; - } - i++; - goto again; - } - if ((size_t)i == length) { - /* - * If there was a trivial zero-length match at the end of the - * split, then we shouldn't output the matched string at the end - * of the split array. See ECMA-262 Ed. 3, 15.5.4.14, Step 15. - */ - sep->chars = NULL; - } - } - JS_ASSERT((size_t)i >= sep->length); - return i - sep->length; - } -#endif /* JS_HAS_REGEXPS */ - - /* - * Deviate from ECMA by never splitting an empty string by any separator - * string into a non-empty array (an array of length 1 that contains the - * empty string). - */ - if (!JS_VERSION_IS_ECMA(cx) && length == 0) - return -1; - - /* - * Special case: if sep is the empty string, split str into one character - * substrings. Let our caller worry about whether to split once at end of - * string into an empty substring. - * - * For 1.2 compatibility, at the end of the string, we return the length as - * the result, and set the separator length to 1 -- this allows the caller - * to include an additional null string at the end of the substring list. - */ - if (sep->length == 0) { - if (JS_VERSION_IS_1_2(cx)) { - if ((size_t)i == length) { - sep->length = 1; - return i; - } - return i + 1; - } - return ((size_t)i == length) ? -1 : i + 1; - } - - /* - * Now that we know sep is non-empty, search starting at i in str for an - * occurrence of all of sep's chars. If we find them, return the index of - * the first separator char. Otherwise, return length. - */ - j = 0; - while ((size_t)(k = i + j) < length) { - if (chars[k] == sep->chars[j]) { - if ((size_t)++j == sep->length) - return i; - } else { - i++; - j = 0; - } - } - return k; -} - -static JSBool -str_split(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSString *str, *sub; - JSObject *arrayobj; - jsval v; - JSBool ok, limited; - JSRegExp *re; - JSSubString *sep, tmp; - jsdouble d; - jsint i, j; - uint32 len, limit; - - str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); - if (!str) - return JS_FALSE; - argv[-1] = STRING_TO_JSVAL(str); - - arrayobj = js_ConstructObject(cx, &js_ArrayClass, NULL, NULL, 0, NULL); - if (!arrayobj) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(arrayobj); - - if (argc == 0) { - v = STRING_TO_JSVAL(str); - ok = JS_SetElement(cx, arrayobj, 0, &v); - } else { -#if JS_HAS_REGEXPS - if (JSVAL_IS_REGEXP(cx, argv[0])) { - re = (JSRegExp *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0])); - sep = &tmp; - - /* Set a magic value so we can detect a successful re match. */ - sep->chars = NULL; - } else -#endif - { - JSString *str2 = js_ValueToString(cx, argv[0]); - if (!str2) - return JS_FALSE; - argv[0] = STRING_TO_JSVAL(str2); - - /* - * Point sep at a local copy of str2's header because find_split - * will modify sep->length. - */ - tmp.length = JSSTRING_LENGTH(str2); - tmp.chars = JSSTRING_CHARS(str2); - sep = &tmp; - re = NULL; - } - - /* Use the second argument as the split limit, if given. */ - limited = (argc > 1) && !JSVAL_IS_VOID(argv[1]); - limit = 0; /* Avoid warning. */ - if (limited) { - if (!js_ValueToNumber(cx, argv[1], &d)) - return JS_FALSE; - - /* Clamp limit between 0 and 1 + string length. */ - if (!js_DoubleToECMAUint32(cx, d, &limit)) - return JS_FALSE; - if (limit > JSSTRING_LENGTH(str)) - limit = 1 + JSSTRING_LENGTH(str); - } - - len = i = 0; - while ((j = find_split(cx, str, re, &i, sep)) >= 0) { - if (limited && len >= limit) - break; - sub = js_NewDependentString(cx, str, i, (size_t)(j - i), 0); - if (!sub) - return JS_FALSE; - v = STRING_TO_JSVAL(sub); - if (!JS_SetElement(cx, arrayobj, len, &v)) - return JS_FALSE; - len++; -#if JS_HAS_REGEXPS - /* - * Imitate perl's feature of including parenthesized substrings - * that matched part of the delimiter in the new array, after the - * split substring that was delimited. - */ - if (re && sep->chars) { - uintN num; - JSSubString *parsub; - - for (num = 0; num < cx->regExpStatics.parenCount; num++) { - if (limited && len >= limit) - break; - parsub = REGEXP_PAREN_SUBSTRING(&cx->regExpStatics, num); - sub = js_NewStringCopyN(cx, parsub->chars, parsub->length, - 0); - if (!sub) - return JS_FALSE; - v = STRING_TO_JSVAL(sub); - if (!JS_SetElement(cx, arrayobj, len, &v)) - return JS_FALSE; - len++; - } - sep->chars = NULL; - } -#endif - i = j + sep->length; - if (!JS_VERSION_IS_ECMA(cx)) { - /* - * Deviate from ECMA to imitate Perl, which omits a final - * split unless a limit argument is given and big enough. - */ - if (!limited && (size_t)i == JSSTRING_LENGTH(str)) - break; - } - } - ok = (j != -2); - } - return ok; -} - -#if JS_HAS_PERL_SUBSTR -static JSBool -str_substr(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSString *str; - jsdouble d; - jsdouble length, begin, end; - - str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); - if (!str) - return JS_FALSE; - argv[-1] = STRING_TO_JSVAL(str); - - if (argc != 0) { - if (!js_ValueToNumber(cx, argv[0], &d)) - return JS_FALSE; - length = JSSTRING_LENGTH(str); - begin = js_DoubleToInteger(d); - if (begin < 0) { - begin += length; - if (begin < 0) - begin = 0; - } else if (begin > length) { - begin = length; - } - - if (argc == 1) { - end = length; - } else { - if (!js_ValueToNumber(cx, argv[1], &d)) - return JS_FALSE; - end = js_DoubleToInteger(d); - if (end < 0) - end = 0; - end += begin; - if (end > length) - end = length; - } - - str = js_NewDependentString(cx, str, (size_t)begin, - (size_t)(end - begin), 0); - if (!str) - return JS_FALSE; - } - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} -#endif /* JS_HAS_PERL_SUBSTR */ - -#if JS_HAS_SEQUENCE_OPS -/* - * Python-esque sequence operations. - */ -static JSBool -str_concat(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSString *str, *str2; - uintN i; - - str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); - if (!str) - return JS_FALSE; - argv[-1] = STRING_TO_JSVAL(str); - - for (i = 0; i < argc; i++) { - str2 = js_ValueToString(cx, argv[i]); - if (!str2) - return JS_FALSE; - argv[i] = STRING_TO_JSVAL(str2); - - str = js_ConcatStrings(cx, str, str2); - if (!str) - return JS_FALSE; - } - - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -static JSBool -str_slice(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSString *str; - jsdouble d; - jsdouble length, begin, end; - - str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); - if (!str) - return JS_FALSE; - argv[-1] = STRING_TO_JSVAL(str); - - if (argc != 0) { - if (!js_ValueToNumber(cx, argv[0], &d)) - return JS_FALSE; - length = JSSTRING_LENGTH(str); - begin = js_DoubleToInteger(d); - if (begin < 0) { - begin += length; - if (begin < 0) - begin = 0; - } else if (begin > length) { - begin = length; - } - - if (argc == 1) { - end = length; - } else { - if (!js_ValueToNumber(cx, argv[1], &d)) - return JS_FALSE; - end = js_DoubleToInteger(d); - if (end < 0) { - end += length; - if (end < 0) - end = 0; - } else if (end > length) { - end = length; - } - if (end < begin) - end = begin; - } - - str = js_NewDependentString(cx, str, (size_t)begin, - (size_t)(end - begin), 0); - if (!str) - return JS_FALSE; - } - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} -#endif /* JS_HAS_SEQUENCE_OPS */ - -#if JS_HAS_STR_HTML_HELPERS -/* - * HTML composition aids. - */ -static JSBool -tagify(JSContext *cx, JSObject *obj, jsval *argv, - const char *begin, JSString *param, const char *end, - jsval *rval) -{ - JSString *str; - jschar *tagbuf; - size_t beglen, endlen, parlen, taglen; - size_t i, j; - - str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); - if (!str) - return JS_FALSE; - argv[-1] = STRING_TO_JSVAL(str); - - if (!end) - end = begin; - - beglen = strlen(begin); - taglen = 1 + beglen + 1; /* '' */ - parlen = 0; /* Avoid warning. */ - if (param) { - parlen = JSSTRING_LENGTH(param); - taglen += 2 + parlen + 1; /* '="param"' */ - } - endlen = strlen(end); - taglen += JSSTRING_LENGTH(str) + 2 + endlen + 1; /* 'str' */ - - if (taglen >= ~(size_t)0 / sizeof(jschar)) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - - tagbuf = (jschar *) JS_malloc(cx, (taglen + 1) * sizeof(jschar)); - if (!tagbuf) - return JS_FALSE; - - j = 0; - tagbuf[j++] = '<'; - for (i = 0; i < beglen; i++) - tagbuf[j++] = (jschar)begin[i]; - if (param) { - tagbuf[j++] = '='; - tagbuf[j++] = '"'; - js_strncpy(&tagbuf[j], JSSTRING_CHARS(param), parlen); - j += parlen; - tagbuf[j++] = '"'; - } - tagbuf[j++] = '>'; - js_strncpy(&tagbuf[j], JSSTRING_CHARS(str), JSSTRING_LENGTH(str)); - j += JSSTRING_LENGTH(str); - tagbuf[j++] = '<'; - tagbuf[j++] = '/'; - for (i = 0; i < endlen; i++) - tagbuf[j++] = (jschar)end[i]; - tagbuf[j++] = '>'; - JS_ASSERT(j == taglen); - tagbuf[j] = 0; - - str = js_NewString(cx, tagbuf, taglen, 0); - if (!str) { - free((char *)tagbuf); - return JS_FALSE; - } - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -static JSBool -tagify_value(JSContext *cx, JSObject *obj, jsval *argv, - const char *begin, const char *end, - jsval *rval) -{ - JSString *param; - - param = js_ValueToString(cx, argv[0]); - if (!param) - return JS_FALSE; - argv[0] = STRING_TO_JSVAL(param); - return tagify(cx, obj, argv, begin, param, end, rval); -} - -static JSBool -str_bold(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - return tagify(cx, obj, argv, "b", NULL, NULL, rval); -} - -static JSBool -str_italics(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - return tagify(cx, obj, argv, "i", NULL, NULL, rval); -} - -static JSBool -str_fixed(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - return tagify(cx, obj, argv, "tt", NULL, NULL, rval); -} - -static JSBool -str_fontsize(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - return tagify_value(cx, obj, argv, "font size", "font", rval); -} - -static JSBool -str_fontcolor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - return tagify_value(cx, obj, argv, "font color", "font", rval); -} - -static JSBool -str_link(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - return tagify_value(cx, obj, argv, "a href", "a", rval); -} - -static JSBool -str_anchor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - return tagify_value(cx, obj, argv, "a name", "a", rval); -} - -static JSBool -str_strike(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - return tagify(cx, obj, argv, "strike", NULL, NULL, rval); -} - -static JSBool -str_small(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - return tagify(cx, obj, argv, "small", NULL, NULL, rval); -} - -static JSBool -str_big(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - return tagify(cx, obj, argv, "big", NULL, NULL, rval); -} - -static JSBool -str_blink(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - return tagify(cx, obj, argv, "blink", NULL, NULL, rval); -} - -static JSBool -str_sup(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - return tagify(cx, obj, argv, "sup", NULL, NULL, rval); -} - -static JSBool -str_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - return tagify(cx, obj, argv, "sub", NULL, NULL, rval); -} -#endif /* JS_HAS_STR_HTML_HELPERS */ - -static JSFunctionSpec string_methods[] = { -#if JS_HAS_TOSOURCE - {"quote", str_quote, 0,JSFUN_GENERIC_NATIVE,0}, - {js_toSource_str, str_toSource, 0,0,0}, -#endif - - /* Java-like methods. */ - {js_toString_str, str_toString, 0,0,0}, - {js_valueOf_str, str_valueOf, 0,0,0}, - {"substring", str_substring, 2,JSFUN_GENERIC_NATIVE,0}, - {"toLowerCase", str_toLowerCase, 0,JSFUN_GENERIC_NATIVE,0}, - {"toUpperCase", str_toUpperCase, 0,JSFUN_GENERIC_NATIVE,0}, - {"charAt", str_charAt, 1,JSFUN_GENERIC_NATIVE,0}, - {"charCodeAt", str_charCodeAt, 1,JSFUN_GENERIC_NATIVE,0}, - {"indexOf", str_indexOf, 1,JSFUN_GENERIC_NATIVE,0}, - {"lastIndexOf", str_lastIndexOf, 1,JSFUN_GENERIC_NATIVE,0}, - {"toLocaleLowerCase", str_toLocaleLowerCase, 0,JSFUN_GENERIC_NATIVE,0}, - {"toLocaleUpperCase", str_toLocaleUpperCase, 0,JSFUN_GENERIC_NATIVE,0}, - {"localeCompare", str_localeCompare, 1,JSFUN_GENERIC_NATIVE,0}, - - /* Perl-ish methods (search is actually Python-esque). */ -#if JS_HAS_REGEXPS - {"match", str_match, 1,JSFUN_GENERIC_NATIVE,2}, - {"search", str_search, 1,JSFUN_GENERIC_NATIVE,0}, - {"replace", str_replace, 2,JSFUN_GENERIC_NATIVE,0}, - {"split", str_split, 2,JSFUN_GENERIC_NATIVE,0}, -#endif -#if JS_HAS_PERL_SUBSTR - {"substr", str_substr, 2,JSFUN_GENERIC_NATIVE,0}, -#endif - - /* Python-esque sequence methods. */ -#if JS_HAS_SEQUENCE_OPS - {"concat", str_concat, 0,JSFUN_GENERIC_NATIVE,0}, - {"slice", str_slice, 0,JSFUN_GENERIC_NATIVE,0}, -#endif - - /* HTML string methods. */ -#if JS_HAS_STR_HTML_HELPERS - {"bold", str_bold, 0,0,0}, - {"italics", str_italics, 0,0,0}, - {"fixed", str_fixed, 0,0,0}, - {"fontsize", str_fontsize, 1,0,0}, - {"fontcolor", str_fontcolor, 1,0,0}, - {"link", str_link, 1,0,0}, - {"anchor", str_anchor, 1,0,0}, - {"strike", str_strike, 0,0,0}, - {"small", str_small, 0,0,0}, - {"big", str_big, 0,0,0}, - {"blink", str_blink, 0,0,0}, - {"sup", str_sup, 0,0,0}, - {"sub", str_sub, 0,0,0}, -#endif - - {0,0,0,0,0} -}; - -static JSBool -String(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSString *str; - - if (argc > 0) { - str = js_ValueToString(cx, argv[0]); - if (!str) - return JS_FALSE; - argv[0] = STRING_TO_JSVAL(str); - } else { - str = cx->runtime->emptyString; - } - if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) { - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; - } - OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, STRING_TO_JSVAL(str)); - return JS_TRUE; -} - -static JSBool -str_fromCharCode(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jschar *chars; - uintN i; - uint16 code; - JSString *str; - - chars = (jschar *) JS_malloc(cx, (argc + 1) * sizeof(jschar)); - if (!chars) - return JS_FALSE; - for (i = 0; i < argc; i++) { - if (!js_ValueToUint16(cx, argv[i], &code)) { - JS_free(cx, chars); - return JS_FALSE; - } - chars[i] = (jschar)code; - } - chars[i] = 0; - str = js_NewString(cx, chars, argc, 0); - if (!str) { - JS_free(cx, chars); - return JS_FALSE; - } - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -static JSFunctionSpec string_static_methods[] = { - {"fromCharCode", str_fromCharCode, 1,0,0}, - {0,0,0,0,0} -}; - -static JSHashTable *deflated_string_cache; -#ifdef DEBUG -static uint32 deflated_string_cache_bytes; -#endif -#ifdef JS_THREADSAFE -static JSLock *deflated_string_cache_lock; -#endif - -JSBool -js_InitStringGlobals(void) -{ -#ifdef JS_THREADSAFE - /* Must come through here once in primordial thread to init safely! */ - if (!deflated_string_cache_lock) { - deflated_string_cache_lock = JS_NEW_LOCK(); - if (!deflated_string_cache_lock) - return JS_FALSE; - } -#endif - return JS_TRUE; -} - -void -js_FreeStringGlobals() -{ - if (deflated_string_cache) { - JS_HashTableDestroy(deflated_string_cache); - deflated_string_cache = NULL; - } -#ifdef JS_THREADSAFE - if (deflated_string_cache_lock) { - JS_DESTROY_LOCK(deflated_string_cache_lock); - deflated_string_cache_lock = NULL; - } -#endif -} - -JSBool -js_InitRuntimeStringState(JSContext *cx) -{ - JSRuntime *rt; - JSString *empty; - JSAtom *atom; - - rt = cx->runtime; - JS_ASSERT(!rt->emptyString); - - /* Make a permanently locked empty string. */ - empty = js_NewStringCopyN(cx, js_empty_ucstr, 0, GCF_LOCK); - if (!empty) - return JS_FALSE; - - /* Atomize it for scripts that use '' + x to convert x to string. */ - atom = js_AtomizeString(cx, empty, ATOM_PINNED); - if (!atom) - return JS_FALSE; - - rt->emptyString = empty; - rt->atomState.emptyAtom = atom; - return JS_TRUE; -} - -void -js_FinishRuntimeStringState(JSContext *cx) -{ - JSRuntime *rt = cx->runtime; - - js_UnlockGCThingRT(rt, rt->emptyString); - rt->emptyString = NULL; -} - -JSObject * -js_InitStringClass(JSContext *cx, JSObject *obj) -{ - JSObject *proto; - - /* Define the escape, unescape functions in the global object. */ - if (!JS_DefineFunctions(cx, obj, string_functions)) - return NULL; - - proto = JS_InitClass(cx, obj, NULL, &js_StringClass, String, 1, - string_props, string_methods, - NULL, string_static_methods); - if (!proto) - return NULL; - OBJ_SET_SLOT(cx, proto, JSSLOT_PRIVATE, - STRING_TO_JSVAL(cx->runtime->emptyString)); - return proto; -} - -JSString * -js_NewString(JSContext *cx, jschar *chars, size_t length, uintN gcflag) -{ - JSString *str; - - if (length > JSSTRING_LENGTH_MASK) { - JS_ReportOutOfMemory(cx); - return NULL; - } - - str = (JSString *) js_NewGCThing(cx, gcflag | GCX_STRING, sizeof(JSString)); - if (!str) - return NULL; - str->length = length; - str->chars = chars; -#ifdef DEBUG - { - JSRuntime *rt = cx->runtime; - JS_RUNTIME_METER(rt, liveStrings); - JS_RUNTIME_METER(rt, totalStrings); - JS_LOCK_RUNTIME_VOID(rt, - (rt->lengthSum += (double)length, - rt->lengthSquaredSum += (double)length * (double)length)); - } -#endif - return str; -} - -JSString * -js_NewDependentString(JSContext *cx, JSString *base, size_t start, - size_t length, uintN gcflag) -{ - JSDependentString *ds; - - if (length == 0) - return cx->runtime->emptyString; - - if (start == 0 && length == JSSTRING_LENGTH(base)) - return base; - - if (start > JSSTRDEP_START_MASK || - (start != 0 && length > JSSTRDEP_LENGTH_MASK)) { - return js_NewStringCopyN(cx, JSSTRING_CHARS(base) + start, length, - gcflag); - } - - ds = (JSDependentString *) - js_NewGCThing(cx, gcflag | GCX_MUTABLE_STRING, sizeof(JSString)); - if (!ds) - return NULL; - if (start == 0) { - JSPREFIX_SET_LENGTH(ds, length); - JSPREFIX_SET_BASE(ds, base); - } else { - JSSTRDEP_SET_START_AND_LENGTH(ds, start, length); - JSSTRDEP_SET_BASE(ds, base); - } -#ifdef DEBUG - { - JSRuntime *rt = cx->runtime; - JS_RUNTIME_METER(rt, liveDependentStrings); - JS_RUNTIME_METER(rt, totalDependentStrings); - JS_RUNTIME_METER(rt, liveStrings); - JS_RUNTIME_METER(rt, totalStrings); - JS_LOCK_RUNTIME_VOID(rt, - (rt->strdepLengthSum += (double)length, - rt->strdepLengthSquaredSum += (double)length * (double)length)); - JS_LOCK_RUNTIME_VOID(rt, - (rt->lengthSum += (double)length, - rt->lengthSquaredSum += (double)length * (double)length)); - } -#endif - return (JSString *)ds; -} - -#ifdef DEBUG -#include - -void printJSStringStats(JSRuntime *rt) { - double mean = 0., var = 0., sigma = 0.; - jsrefcount count = rt->totalStrings; - if (count > 0 && rt->lengthSum >= 0) { - mean = rt->lengthSum / count; - var = count * rt->lengthSquaredSum - rt->lengthSum * rt->lengthSum; - if (var < 0.0 || count <= 1) - var = 0.0; - else - var /= count * (count - 1); - - /* Windows says sqrt(0.0) is "-1.#J" (?!) so we must test. */ - sigma = (var != 0.) ? sqrt(var) : 0.; - } - fprintf(stderr, "%lu total strings, mean length %g (sigma %g)\n", - (unsigned long)count, mean, sigma); - - mean = var = sigma = 0.; - count = rt->totalDependentStrings; - if (count > 0 && rt->strdepLengthSum >= 0) { - mean = rt->strdepLengthSum / count; - var = count * rt->strdepLengthSquaredSum - - rt->strdepLengthSum * rt->strdepLengthSum; - if (var < 0.0 || count <= 1) - var = 0.0; - else - var /= count * (count - 1); - - /* Windows says sqrt(0.0) is "-1.#J" (?!) so we must test. */ - sigma = (var != 0.) ? sqrt(var) : 0.; - } - fprintf(stderr, "%lu total dependent strings, mean length %g (sigma %g)\n", - (unsigned long)count, mean, sigma); -} -#endif - -JSString * -js_NewStringCopyN(JSContext *cx, const jschar *s, size_t n, uintN gcflag) -{ - jschar *news; - JSString *str; - - news = (jschar *)JS_malloc(cx, (n + 1) * sizeof(jschar)); - if (!news) - return NULL; - js_strncpy(news, s, n); - news[n] = 0; - str = js_NewString(cx, news, n, gcflag); - if (!str) - JS_free(cx, news); - return str; -} - -JSString * -js_NewStringCopyZ(JSContext *cx, const jschar *s, uintN gcflag) -{ - size_t n, m; - jschar *news; - JSString *str; - - n = js_strlen(s); - m = (n + 1) * sizeof(jschar); - news = (jschar *) JS_malloc(cx, m); - if (!news) - return NULL; - memcpy(news, s, m); - str = js_NewString(cx, news, n, gcflag); - if (!str) - JS_free(cx, news); - return str; -} - -JS_STATIC_DLL_CALLBACK(JSHashNumber) -js_hash_string_pointer(const void *key) -{ - return (JSHashNumber)JS_PTR_TO_UINT32(key) >> JSVAL_TAGBITS; -} - -void -js_PurgeDeflatedStringCache(JSString *str) -{ - JSHashNumber hash; - JSHashEntry *he, **hep; - - if (!deflated_string_cache) - return; - - hash = js_hash_string_pointer(str); - JS_ACQUIRE_LOCK(deflated_string_cache_lock); - hep = JS_HashTableRawLookup(deflated_string_cache, hash, str); - he = *hep; - if (he) { -#ifdef DEBUG - deflated_string_cache_bytes -= JSSTRING_LENGTH(str); -#endif - free(he->value); - JS_HashTableRawRemove(deflated_string_cache, hep, he); - } - JS_RELEASE_LOCK(deflated_string_cache_lock); -} - -void -js_FinalizeString(JSContext *cx, JSString *str) -{ - js_FinalizeStringRT(cx->runtime, str); -} - -void -js_FinalizeStringRT(JSRuntime *rt, JSString *str) -{ - JSBool valid; - - JS_RUNTIME_UNMETER(rt, liveStrings); - if (JSSTRING_IS_DEPENDENT(str)) { - /* If JSSTRFLAG_DEPENDENT is set, this string must be valid. */ - JS_ASSERT(JSSTRDEP_BASE(str)); - JS_RUNTIME_UNMETER(rt, liveDependentStrings); - valid = JS_TRUE; - } else { - /* A stillborn string has null chars, so is not valid. */ - valid = (str->chars != NULL); - if (valid) - free(str->chars); - } - if (valid) { - js_PurgeDeflatedStringCache(str); - str->chars = NULL; - } - str->length = 0; -} - -JSObject * -js_StringToObject(JSContext *cx, JSString *str) -{ - JSObject *obj; - - obj = js_NewObject(cx, &js_StringClass, NULL, NULL); - if (!obj) - return NULL; - OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, STRING_TO_JSVAL(str)); - return obj; -} - -JS_FRIEND_API(const char *) -js_ValueToPrintableString(JSContext *cx, jsval v) -{ - JSString *str; - const char *bytes; - - str = js_ValueToString(cx, v); - if (!str) - return NULL; - str = js_QuoteString(cx, str, 0); - if (!str) - return NULL; - bytes = js_GetStringBytes(str); - if (!bytes) - JS_ReportOutOfMemory(cx); - return bytes; -} - -JSString * -js_ValueToString(JSContext *cx, jsval v) -{ - JSObject *obj; - JSString *str; - - if (JSVAL_IS_OBJECT(v)) { - obj = JSVAL_TO_OBJECT(v); - if (!obj) - return ATOM_TO_STRING(cx->runtime->atomState.nullAtom); - if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_STRING, &v)) - return NULL; - } - if (JSVAL_IS_STRING(v)) { - str = JSVAL_TO_STRING(v); - } else if (JSVAL_IS_INT(v)) { - str = js_NumberToString(cx, JSVAL_TO_INT(v)); - } else if (JSVAL_IS_DOUBLE(v)) { - str = js_NumberToString(cx, *JSVAL_TO_DOUBLE(v)); - } else if (JSVAL_IS_BOOLEAN(v)) { - str = js_BooleanToString(cx, JSVAL_TO_BOOLEAN(v)); - } else { - str = ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_VOID]); - } - return str; -} - -JSString * -js_ValueToSource(JSContext *cx, jsval v) -{ - JSTempValueRooter tvr; - JSString *str; - - if (JSVAL_IS_STRING(v)) - return js_QuoteString(cx, JSVAL_TO_STRING(v), '"'); - if (JSVAL_IS_PRIMITIVE(v)) { - /* Special case to preserve negative zero, _contra_ toString. */ - if (JSVAL_IS_DOUBLE(v) && JSDOUBLE_IS_NEGZERO(*JSVAL_TO_DOUBLE(v))) { - /* NB: _ucNstr rather than _ucstr to indicate non-terminated. */ - static const jschar js_negzero_ucNstr[] = {'-', '0'}; - - return js_NewStringCopyN(cx, js_negzero_ucNstr, 2, 0); - } - return js_ValueToString(cx, v); - } - - JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr); - if (!js_TryMethod(cx, JSVAL_TO_OBJECT(v), - cx->runtime->atomState.toSourceAtom, - 0, NULL, &tvr.u.value)) { - str = NULL; - } else { - str = js_ValueToString(cx, tvr.u.value); - } - JS_POP_TEMP_ROOT(cx, &tvr); - return str; -} - -JSHashNumber -js_HashString(JSString *str) -{ - JSHashNumber h; - const jschar *s; - size_t n; - - h = 0; - for (s = JSSTRING_CHARS(str), n = JSSTRING_LENGTH(str); n; s++, n--) - h = (h >> (JS_HASH_BITS - 4)) ^ (h << 4) ^ *s; - return h; -} - -intN -js_CompareStrings(JSString *str1, JSString *str2) -{ - size_t l1, l2, n, i; - const jschar *s1, *s2; - intN cmp; - - l1 = JSSTRING_LENGTH(str1), l2 = JSSTRING_LENGTH(str2); - s1 = JSSTRING_CHARS(str1), s2 = JSSTRING_CHARS(str2); - n = JS_MIN(l1, l2); - for (i = 0; i < n; i++) { - cmp = s1[i] - s2[i]; - if (cmp != 0) - return cmp; - } - return (intN)(l1 - l2); -} - -size_t -js_strlen(const jschar *s) -{ - const jschar *t; - - for (t = s; *t != 0; t++) - continue; - return (size_t)(t - s); -} - -jschar * -js_strchr(const jschar *s, jschar c) -{ - while (*s != 0) { - if (*s == c) - return (jschar *)s; - s++; - } - return NULL; -} - -jschar * -js_strchr_limit(const jschar *s, jschar c, const jschar *limit) -{ - while (s < limit) { - if (*s == c) - return (jschar *)s; - s++; - } - return NULL; -} - -const jschar * -js_SkipWhiteSpace(const jschar *s) -{ - /* JS_ISSPACE is false on a null. */ - while (JS_ISSPACE(*s)) - s++; - return s; -} - -#ifdef JS_C_STRINGS_ARE_UTF8 - -jschar * -js_InflateString(JSContext *cx, const char *bytes, size_t *length) -{ - jschar *chars = NULL; - size_t dstlen = 0; - - if (!js_InflateStringToBuffer(cx, bytes, *length, NULL, &dstlen)) - return NULL; - chars = (jschar *) JS_malloc(cx, (dstlen + 1) * sizeof (jschar)); - if (!chars) - return NULL; - js_InflateStringToBuffer(cx, bytes, *length, chars, &dstlen); - chars[dstlen] = 0; - *length = dstlen; - return chars; -} - -/* - * May be called with null cx by js_GetStringBytes, see below. - */ -char * -js_DeflateString(JSContext *cx, const jschar *chars, size_t length) -{ - size_t size = 0; - char *bytes = NULL; - if (!js_DeflateStringToBuffer(cx, chars, length, NULL, &size)) - return NULL; - bytes = (char *) (cx ? JS_malloc(cx, size+1) : malloc(size+1)); - if (!bytes) - return NULL; - js_DeflateStringToBuffer(cx, chars, length, bytes, &size); - bytes[size] = 0; - return bytes; -} - -JSBool -js_DeflateStringToBuffer(JSContext *cx, const jschar *src, size_t srclen, - char *dst, size_t *dstlenp) -{ - size_t i, utf8Len, dstlen = *dstlenp, origDstlen = dstlen; - jschar c, c2; - uint32 v; - uint8 utf8buf[6]; - - if (!dst) - dstlen = origDstlen = (size_t) -1; - - while (srclen) { - c = *src++; - srclen--; - if ((c >= 0xDC00) && (c <= 0xDFFF)) - goto badSurrogate; - if (c < 0xD800 || c > 0xDBFF) { - v = c; - } else { - if (srclen < 1) - goto bufferTooSmall; - c2 = *src++; - srclen--; - if ((c2 < 0xDC00) || (c2 > 0xDFFF)) { - c = c2; - goto badSurrogate; - } - v = ((c - 0xD800) << 10) + (c2 - 0xDC00) + 0x10000; - } - if (v < 0x0080) { - /* no encoding necessary - performance hack */ - if (!dstlen) - goto bufferTooSmall; - if (dst) - *dst++ = (char) v; - utf8Len = 1; - } else { - utf8Len = js_OneUcs4ToUtf8Char(utf8buf, v); - if (utf8Len > dstlen) - goto bufferTooSmall; - if (dst) { - for (i = 0; i < utf8Len; i++) - *dst++ = (char) utf8buf[i]; - } - } - dstlen -= utf8Len; - } - *dstlenp = (origDstlen - dstlen); - return JS_TRUE; - -badSurrogate: - *dstlenp = (origDstlen - dstlen); - if (cx) { - char buffer[10]; - JS_snprintf(buffer, 10, "0x%x", c); - JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, - js_GetErrorMessage, NULL, - JSMSG_BAD_SURROGATE_CHAR, - buffer); - } - return JS_FALSE; - -bufferTooSmall: - *dstlenp = (origDstlen - dstlen); - if (cx) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BUFFER_TOO_SMALL); - } - return JS_FALSE; -} - -JSBool -js_InflateStringToBuffer(JSContext *cx, const char *src, size_t srclen, - jschar *dst, size_t *dstlenp) -{ - uint32 v; - size_t offset = 0, j, n, dstlen = *dstlenp, origDstlen = dstlen; - - if (!dst) - dstlen = origDstlen = (size_t) -1; - - while (srclen) { - v = (uint8) *src; - n = 1; - if (v & 0x80) { - while (v & (0x80 >> n)) - n++; - if (n > srclen) - goto bufferTooSmall; - if (n == 1 || n > 6) - goto badCharacter; - for (j = 1; j < n; j++) { - if ((src[j] & 0xC0) != 0x80) - goto badCharacter; - } - v = Utf8ToOneUcs4Char(src, n); - if (v >= 0x10000) { - v -= 0x10000; - if (v > 0xFFFFF || dstlen < 2) { - *dstlenp = (origDstlen - dstlen); - if (cx) { - char buffer[10]; - JS_snprintf(buffer, 10, "0x%x", v + 0x10000); - JS_ReportErrorFlagsAndNumber(cx, - JSREPORT_ERROR, - js_GetErrorMessage, NULL, - JSMSG_UTF8_CHAR_TOO_LARGE, - buffer); - } - return JS_FALSE; - } - if (dstlen < 2) - goto bufferTooSmall; - if (dst) { - *dst++ = (jschar)((v >> 10) + 0xD800); - v = (jschar)((v & 0x3FF) + 0xDC00); - } - dstlen--; - } - } - if (!dstlen) - goto bufferTooSmall; - if (dst) - *dst++ = (jschar) v; - dstlen--; - offset += n; - src += n; - srclen -= n; - } - *dstlenp = (origDstlen - dstlen); - return JS_TRUE; - -badCharacter: - *dstlenp = (origDstlen - dstlen); - if (cx) { - char buffer[10]; - JS_snprintf(buffer, 10, "%d", offset); - JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, - js_GetErrorMessage, NULL, - JSMSG_MALFORMED_UTF8_CHAR, - buffer); - } - return JS_FALSE; - -bufferTooSmall: - *dstlenp = (origDstlen - dstlen); - if (cx) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BUFFER_TOO_SMALL); - } - return JS_FALSE; -} - -#else /* !JS_C_STRINGS_ARE_UTF8 */ - -JSBool -js_InflateStringToBuffer(JSContext* cx, const char *bytes, size_t length, - jschar *chars, size_t* charsLength) -{ - size_t i; - - if (length > *charsLength) { - for (i = 0; i < *charsLength; i++) - chars[i] = (unsigned char) bytes[i]; - if (cx) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BUFFER_TOO_SMALL); - } - return JS_FALSE; - } - for (i = 0; i < length; i++) - chars[i] = (unsigned char) bytes[i]; - *charsLength = length; - return JS_TRUE; -} - -jschar * -js_InflateString(JSContext *cx, const char *bytes, size_t *bytesLength) -{ - jschar *chars; - size_t i, length = *bytesLength; - - chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar)); - if (!chars) { - *bytesLength = 0; - return NULL; - } - for (i = 0; i < length; i++) - chars[i] = (unsigned char) bytes[i]; - chars[length] = 0; - *bytesLength = length; - return chars; -} - -JSBool -js_DeflateStringToBuffer(JSContext* cx, const jschar *chars, size_t length, - char *bytes, size_t* bytesLength) -{ - size_t i; - - if (length > *bytesLength) { - for (i = 0; i < *bytesLength; i++) - bytes[i] = (char) chars[i]; - if (cx) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BUFFER_TOO_SMALL); - } - return JS_FALSE; - } - for (i = 0; i < length; i++) - bytes[i] = (char) chars[i]; - *bytesLength = length; - return JS_TRUE; -} - -/* - * May be called with null cx by js_GetStringBytes, see below. - */ -char * -js_DeflateString(JSContext *cx, const jschar *chars, size_t length) -{ - size_t i, size; - char *bytes; - - size = (length + 1) * sizeof(char); - bytes = (char *) (cx ? JS_malloc(cx, size) : malloc(size)); - if (!bytes) - return NULL; - - for (i = 0; i < length; i++) - bytes[i] = (char) chars[i]; - - bytes[length] = 0; - return bytes; -} - -#endif /* !JS_C_STRINGS_ARE_UTF8 */ - -static JSHashTable * -GetDeflatedStringCache(void) -{ - JSHashTable *cache; - - cache = deflated_string_cache; - if (!cache) { - cache = JS_NewHashTable(8, js_hash_string_pointer, - JS_CompareValues, JS_CompareValues, - NULL, NULL); - deflated_string_cache = cache; - } - return cache; -} - -JSBool -js_SetStringBytes(JSString *str, char *bytes, size_t length) -{ - JSHashTable *cache; - JSBool ok; - JSHashNumber hash; - JSHashEntry **hep; - - JS_ACQUIRE_LOCK(deflated_string_cache_lock); - - cache = GetDeflatedStringCache(); - if (!cache) { - ok = JS_FALSE; - } else { - hash = js_hash_string_pointer(str); - hep = JS_HashTableRawLookup(cache, hash, str); - JS_ASSERT(*hep == NULL); - ok = JS_HashTableRawAdd(cache, hep, hash, str, bytes) != NULL; -#ifdef DEBUG - if (ok) - deflated_string_cache_bytes += length; -#endif - } - - JS_RELEASE_LOCK(deflated_string_cache_lock); - return ok; -} - -char * -js_GetStringBytes(JSString *str) -{ - JSHashTable *cache; - char *bytes; - JSHashNumber hash; - JSHashEntry *he, **hep; - - JS_ACQUIRE_LOCK(deflated_string_cache_lock); - - cache = GetDeflatedStringCache(); - if (!cache) { - bytes = NULL; - } else { - hash = js_hash_string_pointer(str); - hep = JS_HashTableRawLookup(cache, hash, str); - he = *hep; - if (he) { - bytes = (char *) he->value; - - /* Try to catch failure to JS_ShutDown between runtime epochs. */ - JS_ASSERT((*bytes == '\0' && JSSTRING_LENGTH(str) == 0) || - *bytes == (char) JSSTRING_CHARS(str)[0]); - } else { - bytes = js_DeflateString(NULL, JSSTRING_CHARS(str), - JSSTRING_LENGTH(str)); - if (bytes) { - if (JS_HashTableRawAdd(cache, hep, hash, str, bytes)) { -#ifdef DEBUG - deflated_string_cache_bytes += JSSTRING_LENGTH(str); -#endif - } else { - free(bytes); - bytes = NULL; - } - } - } - } - - JS_RELEASE_LOCK(deflated_string_cache_lock); - return bytes; -} - -/* - * From java.lang.Character.java: - * - * The character properties are currently encoded into 32 bits in the - * following manner: - * - * 10 bits signed offset used for converting case - * 1 bit if 1, adding the signed offset converts the character to - * lowercase - * 1 bit if 1, subtracting the signed offset converts the character to - * uppercase - * 1 bit if 1, character has a titlecase equivalent (possibly itself) - * 3 bits 0 may not be part of an identifier - * 1 ignorable control; may continue a Unicode identifier or JS - * identifier - * 2 may continue a JS identifier but not a Unicode identifier - * (unused) - * 3 may continue a Unicode identifier or JS identifier - * 4 is a JS whitespace character - * 5 may start or continue a JS identifier; - * may continue but not start a Unicode identifier (_) - * 6 may start or continue a JS identifier but not a Unicode - * identifier ($) - * 7 may start or continue a Unicode identifier or JS identifier - * Thus: - * 5, 6, 7 may start a JS identifier - * 1, 2, 3, 5, 6, 7 may continue a JS identifier - * 7 may start a Unicode identifier - * 1, 3, 5, 7 may continue a Unicode identifier - * 1 is ignorable within an identifier - * 4 is JS whitespace - * 2 bits 0 this character has no numeric property - * 1 adding the digit offset to the character code and then - * masking with 0x1F will produce the desired numeric value - * 2 this character has a "strange" numeric value - * 3 a JS supradecimal digit: adding the digit offset to the - * character code, then masking with 0x1F, then adding 10 - * will produce the desired numeric value - * 5 bits digit offset - * 1 bit XML 1.0 name start character - * 1 bit XML 1.0 name character - * 2 bits reserved for future use - * 5 bits character type - */ - -/* The X table has 1024 entries for a total of 1024 bytes. */ - -const uint8 js_X[] = { - 0, 1, 2, 3, 4, 5, 6, 7, /* 0x0000 */ - 8, 9, 10, 11, 12, 13, 14, 15, /* 0x0200 */ - 16, 17, 18, 19, 20, 21, 22, 23, /* 0x0400 */ - 24, 25, 26, 27, 28, 28, 28, 28, /* 0x0600 */ - 28, 28, 28, 28, 29, 30, 31, 32, /* 0x0800 */ - 33, 34, 35, 36, 37, 38, 39, 40, /* 0x0A00 */ - 41, 42, 43, 44, 45, 46, 28, 28, /* 0x0C00 */ - 47, 48, 49, 50, 51, 52, 53, 28, /* 0x0E00 */ - 28, 28, 54, 55, 56, 57, 58, 59, /* 0x1000 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0x1200 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0x1400 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0x1600 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0x1800 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0x1A00 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0x1C00 */ - 60, 60, 61, 62, 63, 64, 65, 66, /* 0x1E00 */ - 67, 68, 69, 70, 71, 72, 73, 74, /* 0x2000 */ - 75, 75, 75, 76, 77, 78, 28, 28, /* 0x2200 */ - 79, 80, 81, 82, 83, 83, 84, 85, /* 0x2400 */ - 86, 85, 28, 28, 87, 88, 89, 28, /* 0x2600 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0x2800 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0x2A00 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0x2C00 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0x2E00 */ - 90, 91, 92, 93, 94, 56, 95, 28, /* 0x3000 */ - 96, 97, 98, 99, 83, 100, 83, 101, /* 0x3200 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0x3400 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0x3600 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0x3800 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0x3A00 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0x3C00 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0x3E00 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0x4000 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0x4200 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0x4400 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0x4600 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0x4800 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0x4A00 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0x4C00 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x4E00 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5000 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5200 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5400 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5600 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5800 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5A00 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5C00 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5E00 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6000 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6200 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6400 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6600 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6800 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6A00 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6C00 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6E00 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7000 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7200 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7400 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7600 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7800 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7A00 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7C00 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7E00 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8000 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8200 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8400 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8600 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8800 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8A00 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8C00 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8E00 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x9000 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x9200 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x9400 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x9600 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x9800 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x9A00 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0x9C00 */ - 56, 56, 56, 56, 56, 56, 102, 28, /* 0x9E00 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0xA000 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0xA200 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0xA400 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0xA600 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0xA800 */ - 28, 28, 28, 28, 28, 28, 28, 28, /* 0xAA00 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0xAC00 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0xAE00 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0xB000 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0xB200 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0xB400 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0xB600 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0xB800 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0xBA00 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0xBC00 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0xBE00 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0xC000 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0xC200 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0xC400 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0xC600 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0xC800 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0xCA00 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0xCC00 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0xCE00 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0xD000 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0xD200 */ - 56, 56, 56, 56, 56, 56, 56, 56, /* 0xD400 */ - 56, 56, 56, 56, 56, 56, 103, 28, /* 0xD600 */ -104, 104, 104, 104, 104, 104, 104, 104, /* 0xD800 */ -104, 104, 104, 104, 104, 104, 104, 104, /* 0xDA00 */ -104, 104, 104, 104, 104, 104, 104, 104, /* 0xDC00 */ -104, 104, 104, 104, 104, 104, 104, 104, /* 0xDE00 */ -105, 105, 105, 105, 105, 105, 105, 105, /* 0xE000 */ -105, 105, 105, 105, 105, 105, 105, 105, /* 0xE200 */ -105, 105, 105, 105, 105, 105, 105, 105, /* 0xE400 */ -105, 105, 105, 105, 105, 105, 105, 105, /* 0xE600 */ -105, 105, 105, 105, 105, 105, 105, 105, /* 0xE800 */ -105, 105, 105, 105, 105, 105, 105, 105, /* 0xEA00 */ -105, 105, 105, 105, 105, 105, 105, 105, /* 0xEC00 */ -105, 105, 105, 105, 105, 105, 105, 105, /* 0xEE00 */ -105, 105, 105, 105, 105, 105, 105, 105, /* 0xF000 */ -105, 105, 105, 105, 105, 105, 105, 105, /* 0xF200 */ -105, 105, 105, 105, 105, 105, 105, 105, /* 0xF400 */ -105, 105, 105, 105, 105, 105, 105, 105, /* 0xF600 */ -105, 105, 105, 105, 56, 56, 56, 56, /* 0xF800 */ -106, 28, 28, 28, 107, 108, 109, 110, /* 0xFA00 */ - 56, 56, 56, 56, 111, 112, 113, 114, /* 0xFC00 */ -115, 116, 56, 117, 118, 119, 120, 121 /* 0xFE00 */ -}; - -/* The Y table has 7808 entries for a total of 7808 bytes. */ - -const uint8 js_Y[] = { - 0, 0, 0, 0, 0, 0, 0, 0, /* 0 */ - 0, 1, 1, 1, 1, 1, 0, 0, /* 0 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 0 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 0 */ - 2, 3, 3, 3, 4, 3, 3, 3, /* 0 */ - 5, 6, 3, 7, 3, 8, 3, 3, /* 0 */ - 9, 9, 9, 9, 9, 9, 9, 9, /* 0 */ - 9, 9, 3, 3, 7, 7, 7, 3, /* 0 */ - 3, 10, 10, 10, 10, 10, 10, 10, /* 1 */ - 10, 10, 10, 10, 10, 10, 10, 10, /* 1 */ - 10, 10, 10, 10, 10, 10, 10, 10, /* 1 */ - 10, 10, 10, 5, 3, 6, 11, 12, /* 1 */ - 11, 13, 13, 13, 13, 13, 13, 13, /* 1 */ - 13, 13, 13, 13, 13, 13, 13, 13, /* 1 */ - 13, 13, 13, 13, 13, 13, 13, 13, /* 1 */ - 13, 13, 13, 5, 7, 6, 7, 0, /* 1 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */ - 2, 3, 4, 4, 4, 4, 15, 15, /* 2 */ - 11, 15, 16, 5, 7, 8, 15, 11, /* 2 */ - 15, 7, 17, 17, 11, 16, 15, 3, /* 2 */ - 11, 18, 16, 6, 19, 19, 19, 3, /* 2 */ - 20, 20, 20, 20, 20, 20, 20, 20, /* 3 */ - 20, 20, 20, 20, 20, 20, 20, 20, /* 3 */ - 20, 20, 20, 20, 20, 20, 20, 7, /* 3 */ - 20, 20, 20, 20, 20, 20, 20, 16, /* 3 */ - 21, 21, 21, 21, 21, 21, 21, 21, /* 3 */ - 21, 21, 21, 21, 21, 21, 21, 21, /* 3 */ - 21, 21, 21, 21, 21, 21, 21, 7, /* 3 */ - 21, 21, 21, 21, 21, 21, 21, 22, /* 3 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 4 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 4 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 4 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 4 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 4 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 4 */ - 25, 26, 23, 24, 23, 24, 23, 24, /* 4 */ - 16, 23, 24, 23, 24, 23, 24, 23, /* 4 */ - 24, 23, 24, 23, 24, 23, 24, 23, /* 5 */ - 24, 16, 23, 24, 23, 24, 23, 24, /* 5 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 5 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 5 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 5 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 5 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 5 */ - 27, 23, 24, 23, 24, 23, 24, 28, /* 5 */ - 16, 29, 23, 24, 23, 24, 30, 23, /* 6 */ - 24, 31, 31, 23, 24, 16, 32, 32, /* 6 */ - 33, 23, 24, 31, 34, 16, 35, 36, /* 6 */ - 23, 24, 16, 16, 35, 37, 16, 38, /* 6 */ - 23, 24, 23, 24, 23, 24, 38, 23, /* 6 */ - 24, 39, 40, 16, 23, 24, 39, 23, /* 6 */ - 24, 41, 41, 23, 24, 23, 24, 42, /* 6 */ - 23, 24, 16, 40, 23, 24, 40, 40, /* 6 */ - 40, 40, 40, 40, 43, 44, 45, 43, /* 7 */ - 44, 45, 43, 44, 45, 23, 24, 23, /* 7 */ - 24, 23, 24, 23, 24, 23, 24, 23, /* 7 */ - 24, 23, 24, 23, 24, 16, 23, 24, /* 7 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 7 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 7 */ - 16, 43, 44, 45, 23, 24, 46, 46, /* 7 */ - 46, 46, 23, 24, 23, 24, 23, 24, /* 7 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 8 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 8 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 8 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 8 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 8 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 8 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 8 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 8 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 9 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 9 */ - 16, 16, 16, 47, 48, 16, 49, 49, /* 9 */ - 50, 50, 16, 51, 16, 16, 16, 16, /* 9 */ - 49, 16, 16, 52, 16, 16, 16, 16, /* 9 */ - 53, 54, 16, 16, 16, 16, 16, 54, /* 9 */ - 16, 16, 55, 16, 16, 16, 16, 16, /* 9 */ - 16, 16, 16, 16, 16, 16, 16, 16, /* 9 */ - 16, 16, 16, 56, 16, 16, 16, 16, /* 10 */ - 56, 16, 57, 57, 16, 16, 16, 16, /* 10 */ - 16, 16, 58, 16, 16, 16, 16, 16, /* 10 */ - 16, 16, 16, 16, 16, 16, 16, 16, /* 10 */ - 16, 16, 16, 16, 16, 16, 16, 16, /* 10 */ - 16, 46, 46, 46, 46, 46, 46, 46, /* 10 */ - 59, 59, 59, 59, 59, 59, 59, 59, /* 10 */ - 59, 11, 11, 59, 59, 59, 59, 59, /* 10 */ - 59, 59, 11, 11, 11, 11, 11, 11, /* 11 */ - 11, 11, 11, 11, 11, 11, 11, 11, /* 11 */ - 59, 59, 11, 11, 11, 11, 11, 11, /* 11 */ - 11, 11, 11, 11, 11, 11, 11, 46, /* 11 */ - 59, 59, 59, 59, 59, 11, 11, 11, /* 11 */ - 11, 11, 46, 46, 46, 46, 46, 46, /* 11 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 11 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 11 */ - 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */ - 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */ - 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */ - 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */ - 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */ - 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */ - 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */ - 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */ - 60, 60, 60, 60, 60, 60, 46, 46, /* 13 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 13 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 13 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 13 */ - 60, 60, 46, 46, 46, 46, 46, 46, /* 13 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 13 */ - 46, 46, 46, 46, 3, 3, 46, 46, /* 13 */ - 46, 46, 59, 46, 46, 46, 3, 46, /* 13 */ - 46, 46, 46, 46, 11, 11, 61, 3, /* 14 */ - 62, 62, 62, 46, 63, 46, 64, 64, /* 14 */ - 16, 20, 20, 20, 20, 20, 20, 20, /* 14 */ - 20, 20, 20, 20, 20, 20, 20, 20, /* 14 */ - 20, 20, 46, 20, 20, 20, 20, 20, /* 14 */ - 20, 20, 20, 20, 65, 66, 66, 66, /* 14 */ - 16, 21, 21, 21, 21, 21, 21, 21, /* 14 */ - 21, 21, 21, 21, 21, 21, 21, 21, /* 14 */ - 21, 21, 16, 21, 21, 21, 21, 21, /* 15 */ - 21, 21, 21, 21, 67, 68, 68, 46, /* 15 */ - 69, 70, 38, 38, 38, 71, 72, 46, /* 15 */ - 46, 46, 38, 46, 38, 46, 38, 46, /* 15 */ - 38, 46, 23, 24, 23, 24, 23, 24, /* 15 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 15 */ - 73, 74, 16, 40, 46, 46, 46, 46, /* 15 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 15 */ - 46, 75, 75, 75, 75, 75, 75, 75, /* 16 */ - 75, 75, 75, 75, 75, 46, 75, 75, /* 16 */ - 20, 20, 20, 20, 20, 20, 20, 20, /* 16 */ - 20, 20, 20, 20, 20, 20, 20, 20, /* 16 */ - 20, 20, 20, 20, 20, 20, 20, 20, /* 16 */ - 20, 20, 20, 20, 20, 20, 20, 20, /* 16 */ - 21, 21, 21, 21, 21, 21, 21, 21, /* 16 */ - 21, 21, 21, 21, 21, 21, 21, 21, /* 16 */ - 21, 21, 21, 21, 21, 21, 21, 21, /* 17 */ - 21, 21, 21, 21, 21, 21, 21, 21, /* 17 */ - 46, 74, 74, 74, 74, 74, 74, 74, /* 17 */ - 74, 74, 74, 74, 74, 46, 74, 74, /* 17 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 17 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 17 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 17 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 17 */ - 23, 24, 15, 60, 60, 60, 60, 46, /* 18 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 18 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 18 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 18 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 18 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 18 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 18 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 18 */ - 40, 23, 24, 23, 24, 46, 46, 23, /* 19 */ - 24, 46, 46, 23, 24, 46, 46, 46, /* 19 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 19 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 19 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 19 */ - 23, 24, 23, 24, 46, 46, 23, 24, /* 19 */ - 23, 24, 23, 24, 23, 24, 46, 46, /* 19 */ - 23, 24, 46, 46, 46, 46, 46, 46, /* 19 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 20 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 20 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 20 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 20 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 20 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 20 */ - 46, 76, 76, 76, 76, 76, 76, 76, /* 20 */ - 76, 76, 76, 76, 76, 76, 76, 76, /* 20 */ - 76, 76, 76, 76, 76, 76, 76, 76, /* 21 */ - 76, 76, 76, 76, 76, 76, 76, 76, /* 21 */ - 76, 76, 76, 76, 76, 76, 76, 46, /* 21 */ - 46, 59, 3, 3, 3, 3, 3, 3, /* 21 */ - 46, 77, 77, 77, 77, 77, 77, 77, /* 21 */ - 77, 77, 77, 77, 77, 77, 77, 77, /* 21 */ - 77, 77, 77, 77, 77, 77, 77, 77, /* 21 */ - 77, 77, 77, 77, 77, 77, 77, 77, /* 21 */ - 77, 77, 77, 77, 77, 77, 77, 16, /* 22 */ - 46, 3, 46, 46, 46, 46, 46, 46, /* 22 */ - 46, 60, 60, 60, 60, 60, 60, 60, /* 22 */ - 60, 60, 60, 60, 60, 60, 60, 60, /* 22 */ - 60, 60, 46, 60, 60, 60, 60, 60, /* 22 */ - 60, 60, 60, 60, 60, 60, 60, 60, /* 22 */ - 60, 60, 60, 60, 60, 60, 60, 60, /* 22 */ - 60, 60, 46, 60, 60, 60, 3, 60, /* 22 */ - 3, 60, 60, 3, 60, 46, 46, 46, /* 23 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 23 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 23 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 23 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 23 */ - 40, 40, 40, 46, 46, 46, 46, 46, /* 23 */ - 40, 40, 40, 3, 3, 46, 46, 46, /* 23 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 23 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 24 */ - 46, 46, 46, 46, 3, 46, 46, 46, /* 24 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 24 */ - 46, 46, 46, 3, 46, 46, 46, 3, /* 24 */ - 46, 40, 40, 40, 40, 40, 40, 40, /* 24 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 24 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 24 */ - 40, 40, 40, 46, 46, 46, 46, 46, /* 24 */ - 59, 40, 40, 40, 40, 40, 40, 40, /* 25 */ - 40, 40, 40, 60, 60, 60, 60, 60, /* 25 */ - 60, 60, 60, 46, 46, 46, 46, 46, /* 25 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 25 */ - 78, 78, 78, 78, 78, 78, 78, 78, /* 25 */ - 78, 78, 3, 3, 3, 3, 46, 46, /* 25 */ - 60, 40, 40, 40, 40, 40, 40, 40, /* 25 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 25 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 26 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 26 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 26 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 26 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 26 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 26 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 26 */ - 46, 46, 40, 40, 40, 40, 40, 46, /* 26 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 27 */ - 40, 40, 40, 40, 40, 40, 40, 46, /* 27 */ - 40, 40, 40, 40, 3, 40, 60, 60, /* 27 */ - 60, 60, 60, 60, 60, 79, 79, 60, /* 27 */ - 60, 60, 60, 60, 60, 59, 59, 60, /* 27 */ - 60, 15, 60, 60, 60, 60, 46, 46, /* 27 */ - 9, 9, 9, 9, 9, 9, 9, 9, /* 27 */ - 9, 9, 46, 46, 46, 46, 46, 46, /* 27 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */ - 46, 60, 60, 80, 46, 40, 40, 40, /* 29 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 29 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 29 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 29 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 29 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 29 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 29 */ - 40, 40, 46, 46, 60, 40, 80, 80, /* 29 */ - 80, 60, 60, 60, 60, 60, 60, 60, /* 30 */ - 60, 80, 80, 80, 80, 60, 46, 46, /* 30 */ - 15, 60, 60, 60, 60, 46, 46, 46, /* 30 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 30 */ - 40, 40, 60, 60, 3, 3, 81, 81, /* 30 */ - 81, 81, 81, 81, 81, 81, 81, 81, /* 30 */ - 3, 46, 46, 46, 46, 46, 46, 46, /* 30 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 30 */ - 46, 60, 80, 80, 46, 40, 40, 40, /* 31 */ - 40, 40, 40, 40, 40, 46, 46, 40, /* 31 */ - 40, 46, 46, 40, 40, 40, 40, 40, /* 31 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 31 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 31 */ - 40, 46, 40, 40, 40, 40, 40, 40, /* 31 */ - 40, 46, 40, 46, 46, 46, 40, 40, /* 31 */ - 40, 40, 46, 46, 60, 46, 80, 80, /* 31 */ - 80, 60, 60, 60, 60, 46, 46, 80, /* 32 */ - 80, 46, 46, 80, 80, 60, 46, 46, /* 32 */ - 46, 46, 46, 46, 46, 46, 46, 80, /* 32 */ - 46, 46, 46, 46, 40, 40, 46, 40, /* 32 */ - 40, 40, 60, 60, 46, 46, 81, 81, /* 32 */ - 81, 81, 81, 81, 81, 81, 81, 81, /* 32 */ - 40, 40, 4, 4, 82, 82, 82, 82, /* 32 */ - 19, 83, 15, 46, 46, 46, 46, 46, /* 32 */ - 46, 46, 60, 46, 46, 40, 40, 40, /* 33 */ - 40, 40, 40, 46, 46, 46, 46, 40, /* 33 */ - 40, 46, 46, 40, 40, 40, 40, 40, /* 33 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 33 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 33 */ - 40, 46, 40, 40, 40, 40, 40, 40, /* 33 */ - 40, 46, 40, 40, 46, 40, 40, 46, /* 33 */ - 40, 40, 46, 46, 60, 46, 80, 80, /* 33 */ - 80, 60, 60, 46, 46, 46, 46, 60, /* 34 */ - 60, 46, 46, 60, 60, 60, 46, 46, /* 34 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 34 */ - 46, 40, 40, 40, 40, 46, 40, 46, /* 34 */ - 46, 46, 46, 46, 46, 46, 81, 81, /* 34 */ - 81, 81, 81, 81, 81, 81, 81, 81, /* 34 */ - 60, 60, 40, 40, 40, 46, 46, 46, /* 34 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 34 */ - 46, 60, 60, 80, 46, 40, 40, 40, /* 35 */ - 40, 40, 40, 40, 46, 40, 46, 40, /* 35 */ - 40, 40, 46, 40, 40, 40, 40, 40, /* 35 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 35 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 35 */ - 40, 46, 40, 40, 40, 40, 40, 40, /* 35 */ - 40, 46, 40, 40, 46, 40, 40, 40, /* 35 */ - 40, 40, 46, 46, 60, 40, 80, 80, /* 35 */ - 80, 60, 60, 60, 60, 60, 46, 60, /* 36 */ - 60, 80, 46, 80, 80, 60, 46, 46, /* 36 */ - 15, 46, 46, 46, 46, 46, 46, 46, /* 36 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 36 */ - 40, 46, 46, 46, 46, 46, 81, 81, /* 36 */ - 81, 81, 81, 81, 81, 81, 81, 81, /* 36 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 36 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 36 */ - 46, 60, 80, 80, 46, 40, 40, 40, /* 37 */ - 40, 40, 40, 40, 40, 46, 46, 40, /* 37 */ - 40, 46, 46, 40, 40, 40, 40, 40, /* 37 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 37 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 37 */ - 40, 46, 40, 40, 40, 40, 40, 40, /* 37 */ - 40, 46, 40, 40, 46, 46, 40, 40, /* 37 */ - 40, 40, 46, 46, 60, 40, 80, 60, /* 37 */ - 80, 60, 60, 60, 46, 46, 46, 80, /* 38 */ - 80, 46, 46, 80, 80, 60, 46, 46, /* 38 */ - 46, 46, 46, 46, 46, 46, 60, 80, /* 38 */ - 46, 46, 46, 46, 40, 40, 46, 40, /* 38 */ - 40, 40, 46, 46, 46, 46, 81, 81, /* 38 */ - 81, 81, 81, 81, 81, 81, 81, 81, /* 38 */ - 15, 46, 46, 46, 46, 46, 46, 46, /* 38 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 38 */ - 46, 46, 60, 80, 46, 40, 40, 40, /* 39 */ - 40, 40, 40, 46, 46, 46, 40, 40, /* 39 */ - 40, 46, 40, 40, 40, 40, 46, 46, /* 39 */ - 46, 40, 40, 46, 40, 46, 40, 40, /* 39 */ - 46, 46, 46, 40, 40, 46, 46, 46, /* 39 */ - 40, 40, 40, 46, 46, 46, 40, 40, /* 39 */ - 40, 40, 40, 40, 40, 40, 46, 40, /* 39 */ - 40, 40, 46, 46, 46, 46, 80, 80, /* 39 */ - 60, 80, 80, 46, 46, 46, 80, 80, /* 40 */ - 80, 46, 80, 80, 80, 60, 46, 46, /* 40 */ - 46, 46, 46, 46, 46, 46, 46, 80, /* 40 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 40 */ - 46, 46, 46, 46, 46, 46, 46, 81, /* 40 */ - 81, 81, 81, 81, 81, 81, 81, 81, /* 40 */ - 84, 19, 19, 46, 46, 46, 46, 46, /* 40 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 40 */ - 46, 80, 80, 80, 46, 40, 40, 40, /* 41 */ - 40, 40, 40, 40, 40, 46, 40, 40, /* 41 */ - 40, 46, 40, 40, 40, 40, 40, 40, /* 41 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 41 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 41 */ - 40, 46, 40, 40, 40, 40, 40, 40, /* 41 */ - 40, 40, 40, 40, 46, 40, 40, 40, /* 41 */ - 40, 40, 46, 46, 46, 46, 60, 60, /* 41 */ - 60, 80, 80, 80, 80, 46, 60, 60, /* 42 */ - 60, 46, 60, 60, 60, 60, 46, 46, /* 42 */ - 46, 46, 46, 46, 46, 60, 60, 46, /* 42 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 42 */ - 40, 40, 46, 46, 46, 46, 81, 81, /* 42 */ - 81, 81, 81, 81, 81, 81, 81, 81, /* 42 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 42 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 42 */ - 46, 46, 80, 80, 46, 40, 40, 40, /* 43 */ - 40, 40, 40, 40, 40, 46, 40, 40, /* 43 */ - 40, 46, 40, 40, 40, 40, 40, 40, /* 43 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 43 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 43 */ - 40, 46, 40, 40, 40, 40, 40, 40, /* 43 */ - 40, 40, 40, 40, 46, 40, 40, 40, /* 43 */ - 40, 40, 46, 46, 46, 46, 80, 60, /* 43 */ - 80, 80, 80, 80, 80, 46, 60, 80, /* 44 */ - 80, 46, 80, 80, 60, 60, 46, 46, /* 44 */ - 46, 46, 46, 46, 46, 80, 80, 46, /* 44 */ - 46, 46, 46, 46, 46, 46, 40, 46, /* 44 */ - 40, 40, 46, 46, 46, 46, 81, 81, /* 44 */ - 81, 81, 81, 81, 81, 81, 81, 81, /* 44 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 44 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 44 */ - 46, 46, 80, 80, 46, 40, 40, 40, /* 45 */ - 40, 40, 40, 40, 40, 46, 40, 40, /* 45 */ - 40, 46, 40, 40, 40, 40, 40, 40, /* 45 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 45 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 45 */ - 40, 46, 40, 40, 40, 40, 40, 40, /* 45 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 45 */ - 40, 40, 46, 46, 46, 46, 80, 80, /* 45 */ - 80, 60, 60, 60, 46, 46, 80, 80, /* 46 */ - 80, 46, 80, 80, 80, 60, 46, 46, /* 46 */ - 46, 46, 46, 46, 46, 46, 46, 80, /* 46 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 46 */ - 40, 40, 46, 46, 46, 46, 81, 81, /* 46 */ - 81, 81, 81, 81, 81, 81, 81, 81, /* 46 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 46 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 46 */ - 46, 40, 40, 40, 40, 40, 40, 40, /* 47 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 47 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 47 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 47 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 47 */ - 40, 40, 40, 40, 40, 40, 40, 3, /* 47 */ - 40, 60, 40, 40, 60, 60, 60, 60, /* 47 */ - 60, 60, 60, 46, 46, 46, 46, 4, /* 47 */ - 40, 40, 40, 40, 40, 40, 59, 60, /* 48 */ - 60, 60, 60, 60, 60, 60, 60, 15, /* 48 */ - 9, 9, 9, 9, 9, 9, 9, 9, /* 48 */ - 9, 9, 3, 3, 46, 46, 46, 46, /* 48 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 48 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 48 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 48 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 48 */ - 46, 40, 40, 46, 40, 46, 46, 40, /* 49 */ - 40, 46, 40, 46, 46, 40, 46, 46, /* 49 */ - 46, 46, 46, 46, 40, 40, 40, 40, /* 49 */ - 46, 40, 40, 40, 40, 40, 40, 40, /* 49 */ - 46, 40, 40, 40, 46, 40, 46, 40, /* 49 */ - 46, 46, 40, 40, 46, 40, 40, 3, /* 49 */ - 40, 60, 40, 40, 60, 60, 60, 60, /* 49 */ - 60, 60, 46, 60, 60, 40, 46, 46, /* 49 */ - 40, 40, 40, 40, 40, 46, 59, 46, /* 50 */ - 60, 60, 60, 60, 60, 60, 46, 46, /* 50 */ - 9, 9, 9, 9, 9, 9, 9, 9, /* 50 */ - 9, 9, 46, 46, 40, 40, 46, 46, /* 50 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 50 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 50 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 50 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 50 */ - 15, 15, 15, 15, 3, 3, 3, 3, /* 51 */ - 3, 3, 3, 3, 3, 3, 3, 3, /* 51 */ - 3, 3, 3, 15, 15, 15, 15, 15, /* 51 */ - 60, 60, 15, 15, 15, 15, 15, 15, /* 51 */ - 78, 78, 78, 78, 78, 78, 78, 78, /* 51 */ - 78, 78, 85, 85, 85, 85, 85, 85, /* 51 */ - 85, 85, 85, 85, 15, 60, 15, 60, /* 51 */ - 15, 60, 5, 6, 5, 6, 80, 80, /* 51 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 52 */ - 46, 40, 40, 40, 40, 40, 40, 40, /* 52 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 52 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 52 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 52 */ - 40, 40, 46, 46, 46, 46, 46, 46, /* 52 */ - 46, 60, 60, 60, 60, 60, 60, 60, /* 52 */ - 60, 60, 60, 60, 60, 60, 60, 80, /* 52 */ - 60, 60, 60, 60, 60, 3, 60, 60, /* 53 */ - 60, 60, 60, 60, 46, 46, 46, 46, /* 53 */ - 60, 60, 60, 60, 60, 60, 46, 60, /* 53 */ - 46, 60, 60, 60, 60, 60, 60, 60, /* 53 */ - 60, 60, 60, 60, 60, 60, 60, 60, /* 53 */ - 60, 60, 60, 60, 60, 60, 46, 46, /* 53 */ - 46, 60, 60, 60, 60, 60, 60, 60, /* 53 */ - 46, 60, 46, 46, 46, 46, 46, 46, /* 53 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 54 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 54 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 54 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 54 */ - 76, 76, 76, 76, 76, 76, 76, 76, /* 54 */ - 76, 76, 76, 76, 76, 76, 76, 76, /* 54 */ - 76, 76, 76, 76, 76, 76, 76, 76, /* 54 */ - 76, 76, 76, 76, 76, 76, 76, 76, /* 54 */ - 76, 76, 76, 76, 76, 76, 46, 46, /* 55 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 55 */ - 16, 16, 16, 16, 16, 16, 16, 16, /* 55 */ - 16, 16, 16, 16, 16, 16, 16, 16, /* 55 */ - 16, 16, 16, 16, 16, 16, 16, 16, /* 55 */ - 16, 16, 16, 16, 16, 16, 16, 16, /* 55 */ - 16, 16, 16, 16, 16, 16, 16, 46, /* 55 */ - 46, 46, 46, 3, 46, 46, 46, 46, /* 55 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 57 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 57 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 57 */ - 40, 40, 46, 46, 46, 46, 46, 40, /* 57 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 57 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 57 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 57 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 57 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 58 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 58 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 58 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 58 */ - 40, 40, 40, 46, 46, 46, 46, 46, /* 58 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 58 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 58 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 58 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 59 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 59 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 59 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 59 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 59 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 59 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 59 */ - 40, 40, 46, 46, 46, 46, 46, 46, /* 59 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 61 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 61 */ - 23, 24, 23, 24, 23, 24, 16, 16, /* 61 */ - 16, 16, 16, 16, 46, 46, 46, 46, /* 61 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 61 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 61 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 61 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 61 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 62 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 62 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 62 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 62 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 62 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 62 */ - 23, 24, 23, 24, 23, 24, 23, 24, /* 62 */ - 23, 24, 46, 46, 46, 46, 46, 46, /* 62 */ - 86, 86, 86, 86, 86, 86, 86, 86, /* 63 */ - 87, 87, 87, 87, 87, 87, 87, 87, /* 63 */ - 86, 86, 86, 86, 86, 86, 46, 46, /* 63 */ - 87, 87, 87, 87, 87, 87, 46, 46, /* 63 */ - 86, 86, 86, 86, 86, 86, 86, 86, /* 63 */ - 87, 87, 87, 87, 87, 87, 87, 87, /* 63 */ - 86, 86, 86, 86, 86, 86, 86, 86, /* 63 */ - 87, 87, 87, 87, 87, 87, 87, 87, /* 63 */ - 86, 86, 86, 86, 86, 86, 46, 46, /* 64 */ - 87, 87, 87, 87, 87, 87, 46, 46, /* 64 */ - 16, 86, 16, 86, 16, 86, 16, 86, /* 64 */ - 46, 87, 46, 87, 46, 87, 46, 87, /* 64 */ - 86, 86, 86, 86, 86, 86, 86, 86, /* 64 */ - 87, 87, 87, 87, 87, 87, 87, 87, /* 64 */ - 88, 88, 89, 89, 89, 89, 90, 90, /* 64 */ - 91, 91, 92, 92, 93, 93, 46, 46, /* 64 */ - 86, 86, 86, 86, 86, 86, 86, 86, /* 65 */ - 87, 87, 87, 87, 87, 87, 87, 87, /* 65 */ - 86, 86, 86, 86, 86, 86, 86, 86, /* 65 */ - 87, 87, 87, 87, 87, 87, 87, 87, /* 65 */ - 86, 86, 86, 86, 86, 86, 86, 86, /* 65 */ - 87, 87, 87, 87, 87, 87, 87, 87, /* 65 */ - 86, 86, 16, 94, 16, 46, 16, 16, /* 65 */ - 87, 87, 95, 95, 96, 11, 38, 11, /* 65 */ - 11, 11, 16, 94, 16, 46, 16, 16, /* 66 */ - 97, 97, 97, 97, 96, 11, 11, 11, /* 66 */ - 86, 86, 16, 16, 46, 46, 16, 16, /* 66 */ - 87, 87, 98, 98, 46, 11, 11, 11, /* 66 */ - 86, 86, 16, 16, 16, 99, 16, 16, /* 66 */ - 87, 87, 100, 100, 101, 11, 11, 11, /* 66 */ - 46, 46, 16, 94, 16, 46, 16, 16, /* 66 */ -102, 102, 103, 103, 96, 11, 11, 46, /* 66 */ - 2, 2, 2, 2, 2, 2, 2, 2, /* 67 */ - 2, 2, 2, 2, 104, 104, 104, 104, /* 67 */ - 8, 8, 8, 8, 8, 8, 3, 3, /* 67 */ - 5, 6, 5, 5, 5, 6, 5, 5, /* 67 */ - 3, 3, 3, 3, 3, 3, 3, 3, /* 67 */ -105, 106, 104, 104, 104, 104, 104, 46, /* 67 */ - 3, 3, 3, 3, 3, 3, 3, 3, /* 67 */ - 3, 5, 6, 3, 3, 3, 3, 12, /* 67 */ - 12, 3, 3, 3, 7, 5, 6, 46, /* 68 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 68 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 68 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 68 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 68 */ - 46, 46, 104, 104, 104, 104, 104, 104, /* 68 */ - 17, 46, 46, 46, 17, 17, 17, 17, /* 68 */ - 17, 17, 7, 7, 7, 5, 6, 16, /* 68 */ -107, 107, 107, 107, 107, 107, 107, 107, /* 69 */ -107, 107, 7, 7, 7, 5, 6, 46, /* 69 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 69 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 69 */ - 4, 4, 4, 4, 4, 4, 4, 4, /* 69 */ - 4, 4, 4, 4, 46, 46, 46, 46, /* 69 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 69 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 69 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 70 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 70 */ - 60, 60, 60, 60, 60, 60, 60, 60, /* 70 */ - 60, 60, 60, 60, 60, 79, 79, 79, /* 70 */ - 79, 60, 46, 46, 46, 46, 46, 46, /* 70 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 70 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 70 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 70 */ - 15, 15, 38, 15, 15, 15, 15, 38, /* 71 */ - 15, 15, 16, 38, 38, 38, 16, 16, /* 71 */ - 38, 38, 38, 16, 15, 38, 15, 15, /* 71 */ - 38, 38, 38, 38, 38, 38, 15, 15, /* 71 */ - 15, 15, 15, 15, 38, 15, 38, 15, /* 71 */ - 38, 15, 38, 38, 38, 38, 16, 16, /* 71 */ - 38, 38, 15, 38, 16, 40, 40, 40, /* 71 */ - 40, 46, 46, 46, 46, 46, 46, 46, /* 71 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 72 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 72 */ - 46, 46, 46, 19, 19, 19, 19, 19, /* 72 */ - 19, 19, 19, 19, 19, 19, 19, 108, /* 72 */ -109, 109, 109, 109, 109, 109, 109, 109, /* 72 */ -109, 109, 109, 109, 110, 110, 110, 110, /* 72 */ -111, 111, 111, 111, 111, 111, 111, 111, /* 72 */ -111, 111, 111, 111, 112, 112, 112, 112, /* 72 */ -113, 113, 113, 46, 46, 46, 46, 46, /* 73 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 73 */ - 7, 7, 7, 7, 7, 15, 15, 15, /* 73 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 73 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 73 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 73 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 73 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 73 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 74 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 74 */ - 15, 15, 7, 15, 7, 15, 15, 15, /* 74 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 74 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 74 */ - 15, 15, 15, 46, 46, 46, 46, 46, /* 74 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 74 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 74 */ - 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */ - 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */ - 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */ - 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */ - 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */ - 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */ - 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */ - 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */ - 7, 7, 7, 7, 7, 7, 7, 7, /* 76 */ - 7, 7, 7, 7, 7, 7, 7, 7, /* 76 */ - 7, 7, 7, 7, 7, 7, 7, 7, /* 76 */ - 7, 7, 7, 7, 7, 7, 7, 7, /* 76 */ - 7, 7, 7, 7, 7, 7, 7, 7, /* 76 */ - 7, 7, 7, 7, 7, 7, 7, 7, /* 76 */ - 7, 7, 46, 46, 46, 46, 46, 46, /* 76 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 76 */ - 15, 46, 15, 15, 15, 15, 15, 15, /* 77 */ - 7, 7, 7, 7, 15, 15, 15, 15, /* 77 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 77 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 77 */ - 7, 7, 15, 15, 15, 15, 15, 15, /* 77 */ - 15, 5, 6, 15, 15, 15, 15, 15, /* 77 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 77 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 77 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 78 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 78 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 78 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 78 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 78 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 78 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 78 */ - 15, 15, 15, 46, 46, 46, 46, 46, /* 78 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 79 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 79 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 79 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 79 */ - 15, 15, 15, 15, 15, 46, 46, 46, /* 79 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 79 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 79 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 79 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 80 */ - 15, 15, 15, 46, 46, 46, 46, 46, /* 80 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 80 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 80 */ -114, 114, 114, 114, 114, 114, 114, 114, /* 80 */ -114, 114, 114, 114, 114, 114, 114, 114, /* 80 */ -114, 114, 114, 114, 82, 82, 82, 82, /* 80 */ - 82, 82, 82, 82, 82, 82, 82, 82, /* 80 */ - 82, 82, 82, 82, 82, 82, 82, 82, /* 81 */ -115, 115, 115, 115, 115, 115, 115, 115, /* 81 */ -115, 115, 115, 115, 115, 115, 115, 115, /* 81 */ -115, 115, 115, 115, 15, 15, 15, 15, /* 81 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 81 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 81 */ - 15, 15, 15, 15, 15, 15, 116, 116, /* 81 */ -116, 116, 116, 116, 116, 116, 116, 116, /* 81 */ -116, 116, 116, 116, 116, 116, 116, 116, /* 82 */ -116, 116, 116, 116, 116, 116, 116, 116, /* 82 */ -117, 117, 117, 117, 117, 117, 117, 117, /* 82 */ -117, 117, 117, 117, 117, 117, 117, 117, /* 82 */ -117, 117, 117, 117, 117, 117, 117, 117, /* 82 */ -117, 117, 118, 46, 46, 46, 46, 46, /* 82 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 82 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 82 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 84 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 84 */ - 15, 15, 15, 15, 15, 15, 46, 46, /* 84 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 84 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 84 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 84 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 84 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 84 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 85 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 85 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 85 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 85 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 85 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 85 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 85 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 85 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 86 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 86 */ - 15, 15, 15, 15, 46, 46, 46, 46, /* 86 */ - 46, 46, 15, 15, 15, 15, 15, 15, /* 86 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 86 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 86 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 86 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 86 */ - 46, 15, 15, 15, 15, 46, 15, 15, /* 87 */ - 15, 15, 46, 46, 15, 15, 15, 15, /* 87 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 87 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 87 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 87 */ - 46, 15, 15, 15, 15, 15, 15, 15, /* 87 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 87 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 87 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 88 */ - 15, 15, 15, 15, 46, 15, 46, 15, /* 88 */ - 15, 15, 15, 46, 46, 46, 15, 46, /* 88 */ - 15, 15, 15, 15, 15, 15, 15, 46, /* 88 */ - 46, 15, 15, 15, 15, 15, 15, 15, /* 88 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 88 */ - 46, 46, 46, 46, 46, 46, 119, 119, /* 88 */ -119, 119, 119, 119, 119, 119, 119, 119, /* 88 */ -114, 114, 114, 114, 114, 114, 114, 114, /* 89 */ -114, 114, 83, 83, 83, 83, 83, 83, /* 89 */ - 83, 83, 83, 83, 15, 46, 46, 46, /* 89 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 89 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 89 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 89 */ - 46, 15, 15, 15, 15, 15, 15, 15, /* 89 */ - 15, 15, 15, 15, 15, 15, 15, 46, /* 89 */ - 2, 3, 3, 3, 15, 59, 3, 120, /* 90 */ - 5, 6, 5, 6, 5, 6, 5, 6, /* 90 */ - 5, 6, 15, 15, 5, 6, 5, 6, /* 90 */ - 5, 6, 5, 6, 8, 5, 6, 5, /* 90 */ - 15, 121, 121, 121, 121, 121, 121, 121, /* 90 */ -121, 121, 60, 60, 60, 60, 60, 60, /* 90 */ - 8, 59, 59, 59, 59, 59, 15, 15, /* 90 */ - 46, 46, 46, 46, 46, 46, 46, 15, /* 90 */ - 46, 40, 40, 40, 40, 40, 40, 40, /* 91 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 91 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 91 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 91 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 91 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 91 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 91 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 91 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 92 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 92 */ - 40, 40, 40, 40, 40, 46, 46, 46, /* 92 */ - 46, 60, 60, 59, 59, 59, 59, 46, /* 92 */ - 46, 40, 40, 40, 40, 40, 40, 40, /* 92 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 92 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 92 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 92 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 93 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 93 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 93 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 93 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 93 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 93 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 93 */ - 40, 40, 40, 3, 59, 59, 59, 46, /* 93 */ - 46, 46, 46, 46, 46, 40, 40, 40, /* 94 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 94 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 94 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 94 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 94 */ - 40, 40, 40, 40, 40, 46, 46, 46, /* 94 */ - 46, 40, 40, 40, 40, 40, 40, 40, /* 94 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 94 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 95 */ - 40, 40, 40, 40, 40, 40, 40, 46, /* 95 */ - 15, 15, 85, 85, 85, 85, 15, 15, /* 95 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 95 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 95 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 95 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 95 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 95 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 96 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 96 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 96 */ - 15, 15, 15, 15, 15, 46, 46, 46, /* 96 */ - 85, 85, 85, 85, 85, 85, 85, 85, /* 96 */ - 85, 85, 15, 15, 15, 15, 15, 15, /* 96 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 96 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 96 */ - 15, 15, 15, 15, 46, 46, 46, 46, /* 97 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 97 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 97 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 97 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 97 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 97 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 97 */ - 15, 15, 15, 15, 46, 46, 46, 15, /* 97 */ -114, 114, 114, 114, 114, 114, 114, 114, /* 98 */ -114, 114, 15, 15, 15, 15, 15, 15, /* 98 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 98 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 98 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 98 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 98 */ - 15, 46, 46, 46, 46, 46, 46, 46, /* 98 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 98 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 99 */ - 15, 15, 15, 15, 46, 46, 46, 46, /* 99 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 99 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 99 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 99 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 99 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 99 */ - 15, 15, 15, 15, 15, 15, 15, 46, /* 99 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 100 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 100 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 100 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 100 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 100 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 100 */ - 15, 15, 15, 15, 15, 15, 15, 46, /* 100 */ - 46, 46, 46, 15, 15, 15, 15, 15, /* 100 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 101 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 101 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 101 */ - 15, 15, 15, 15, 15, 15, 46, 46, /* 101 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 101 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 101 */ - 15, 15, 15, 15, 15, 15, 15, 15, /* 101 */ - 15, 15, 15, 15, 15, 15, 15, 46, /* 101 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 102 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 102 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 102 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 102 */ - 40, 40, 40, 40, 40, 40, 46, 46, /* 102 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 102 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 102 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 102 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 103 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 103 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 103 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 103 */ - 40, 40, 40, 40, 46, 46, 46, 46, /* 103 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 103 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 103 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 103 */ -122, 122, 122, 122, 122, 122, 122, 122, /* 104 */ -122, 122, 122, 122, 122, 122, 122, 122, /* 104 */ -122, 122, 122, 122, 122, 122, 122, 122, /* 104 */ -122, 122, 122, 122, 122, 122, 122, 122, /* 104 */ -122, 122, 122, 122, 122, 122, 122, 122, /* 104 */ -122, 122, 122, 122, 122, 122, 122, 122, /* 104 */ -122, 122, 122, 122, 122, 122, 122, 122, /* 104 */ -122, 122, 122, 122, 122, 122, 122, 122, /* 104 */ -123, 123, 123, 123, 123, 123, 123, 123, /* 105 */ -123, 123, 123, 123, 123, 123, 123, 123, /* 105 */ -123, 123, 123, 123, 123, 123, 123, 123, /* 105 */ -123, 123, 123, 123, 123, 123, 123, 123, /* 105 */ -123, 123, 123, 123, 123, 123, 123, 123, /* 105 */ -123, 123, 123, 123, 123, 123, 123, 123, /* 105 */ -123, 123, 123, 123, 123, 123, 123, 123, /* 105 */ -123, 123, 123, 123, 123, 123, 123, 123, /* 105 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 106 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 106 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 106 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 106 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 106 */ - 40, 40, 40, 40, 40, 40, 46, 46, /* 106 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 106 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 106 */ - 16, 16, 16, 16, 16, 16, 16, 46, /* 107 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 107 */ - 46, 46, 46, 16, 16, 16, 16, 16, /* 107 */ - 46, 46, 46, 46, 46, 46, 60, 40, /* 107 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 107 */ - 40, 7, 40, 40, 40, 40, 40, 40, /* 107 */ - 40, 40, 40, 40, 40, 40, 40, 46, /* 107 */ - 40, 40, 40, 40, 40, 46, 40, 46, /* 107 */ - 40, 40, 46, 40, 40, 46, 40, 40, /* 108 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 108 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 108 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 108 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 108 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 108 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 108 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 108 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 109 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 109 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 109 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 109 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 109 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 109 */ - 40, 40, 46, 46, 46, 46, 46, 46, /* 109 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 109 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 110 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 110 */ - 46, 46, 46, 40, 40, 40, 40, 40, /* 110 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 110 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 110 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 110 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 110 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 110 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 111 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 111 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 111 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 111 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 111 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 111 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 111 */ - 40, 40, 40, 40, 40, 40, 5, 6, /* 111 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 112 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 112 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 112 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 112 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 112 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 112 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 112 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 112 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 113 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 113 */ - 46, 46, 40, 40, 40, 40, 40, 40, /* 113 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 113 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 113 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 113 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 113 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 113 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 114 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 114 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 114 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 114 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 114 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 114 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 114 */ - 40, 40, 40, 40, 46, 46, 46, 46, /* 114 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 115 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 115 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 115 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 115 */ - 60, 60, 60, 60, 46, 46, 46, 46, /* 115 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 115 */ - 3, 8, 8, 12, 12, 5, 6, 5, /* 115 */ - 6, 5, 6, 5, 6, 5, 6, 5, /* 115 */ - 6, 5, 6, 5, 6, 46, 46, 46, /* 116 */ - 46, 3, 3, 3, 3, 12, 12, 12, /* 116 */ - 3, 3, 3, 46, 3, 3, 3, 3, /* 116 */ - 8, 5, 6, 5, 6, 5, 6, 3, /* 116 */ - 3, 3, 7, 8, 7, 7, 7, 46, /* 116 */ - 3, 4, 3, 3, 46, 46, 46, 46, /* 116 */ - 40, 40, 40, 46, 40, 46, 40, 40, /* 116 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 116 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 117 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 117 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 117 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 117 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 117 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 117 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 117 */ - 40, 40, 40, 40, 40, 46, 46, 104, /* 117 */ - 46, 3, 3, 3, 4, 3, 3, 3, /* 118 */ - 5, 6, 3, 7, 3, 8, 3, 3, /* 118 */ - 9, 9, 9, 9, 9, 9, 9, 9, /* 118 */ - 9, 9, 3, 3, 7, 7, 7, 3, /* 118 */ - 3, 10, 10, 10, 10, 10, 10, 10, /* 118 */ - 10, 10, 10, 10, 10, 10, 10, 10, /* 118 */ - 10, 10, 10, 10, 10, 10, 10, 10, /* 118 */ - 10, 10, 10, 5, 3, 6, 11, 12, /* 118 */ - 11, 13, 13, 13, 13, 13, 13, 13, /* 119 */ - 13, 13, 13, 13, 13, 13, 13, 13, /* 119 */ - 13, 13, 13, 13, 13, 13, 13, 13, /* 119 */ - 13, 13, 13, 5, 7, 6, 7, 46, /* 119 */ - 46, 3, 5, 6, 3, 3, 40, 40, /* 119 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 119 */ - 59, 40, 40, 40, 40, 40, 40, 40, /* 119 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 119 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 120 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 120 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 120 */ - 40, 40, 40, 40, 40, 40, 59, 59, /* 120 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 120 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 120 */ - 40, 40, 40, 40, 40, 40, 40, 40, /* 120 */ - 40, 40, 40, 40, 40, 40, 40, 46, /* 120 */ - 46, 46, 40, 40, 40, 40, 40, 40, /* 121 */ - 46, 46, 40, 40, 40, 40, 40, 40, /* 121 */ - 46, 46, 40, 40, 40, 40, 40, 40, /* 121 */ - 46, 46, 40, 40, 40, 46, 46, 46, /* 121 */ - 4, 4, 7, 11, 15, 4, 4, 46, /* 121 */ - 7, 7, 7, 7, 7, 15, 15, 46, /* 121 */ - 46, 46, 46, 46, 46, 46, 46, 46, /* 121 */ - 46, 46, 46, 46, 46, 15, 46, 46 /* 121 */ -}; - -/* The A table has 124 entries for a total of 496 bytes. */ - -const uint32 js_A[] = { -0x0001000F, /* 0 Cc, ignorable */ -0x0004000F, /* 1 Cc, whitespace */ -0x0004000C, /* 2 Zs, whitespace */ -0x00000018, /* 3 Po */ -0x0006001A, /* 4 Sc, currency */ -0x00000015, /* 5 Ps */ -0x00000016, /* 6 Pe */ -0x00000019, /* 7 Sm */ -0x00000014, /* 8 Pd */ -0x00036089, /* 9 Nd, identifier part, decimal 16 */ -0x0827FF81, /* 10 Lu, hasLower (add 32), identifier start, supradecimal 31 */ -0x0000001B, /* 11 Sk */ -0x00050017, /* 12 Pc, underscore */ -0x0817FF82, /* 13 Ll, hasUpper (subtract 32), identifier start, supradecimal 31 */ -0x0000000C, /* 14 Zs */ -0x0000001C, /* 15 So */ -0x00070182, /* 16 Ll, identifier start */ -0x0000600B, /* 17 No, decimal 16 */ -0x0000500B, /* 18 No, decimal 8 */ -0x0000800B, /* 19 No, strange */ -0x08270181, /* 20 Lu, hasLower (add 32), identifier start */ -0x08170182, /* 21 Ll, hasUpper (subtract 32), identifier start */ -0xE1D70182, /* 22 Ll, hasUpper (subtract -121), identifier start */ -0x00670181, /* 23 Lu, hasLower (add 1), identifier start */ -0x00570182, /* 24 Ll, hasUpper (subtract 1), identifier start */ -0xCE670181, /* 25 Lu, hasLower (add -199), identifier start */ -0x3A170182, /* 26 Ll, hasUpper (subtract 232), identifier start */ -0xE1E70181, /* 27 Lu, hasLower (add -121), identifier start */ -0x4B170182, /* 28 Ll, hasUpper (subtract 300), identifier start */ -0x34A70181, /* 29 Lu, hasLower (add 210), identifier start */ -0x33A70181, /* 30 Lu, hasLower (add 206), identifier start */ -0x33670181, /* 31 Lu, hasLower (add 205), identifier start */ -0x32A70181, /* 32 Lu, hasLower (add 202), identifier start */ -0x32E70181, /* 33 Lu, hasLower (add 203), identifier start */ -0x33E70181, /* 34 Lu, hasLower (add 207), identifier start */ -0x34E70181, /* 35 Lu, hasLower (add 211), identifier start */ -0x34670181, /* 36 Lu, hasLower (add 209), identifier start */ -0x35670181, /* 37 Lu, hasLower (add 213), identifier start */ -0x00070181, /* 38 Lu, identifier start */ -0x36A70181, /* 39 Lu, hasLower (add 218), identifier start */ -0x00070185, /* 40 Lo, identifier start */ -0x36670181, /* 41 Lu, hasLower (add 217), identifier start */ -0x36E70181, /* 42 Lu, hasLower (add 219), identifier start */ -0x00AF0181, /* 43 Lu, hasLower (add 2), hasTitle, identifier start */ -0x007F0183, /* 44 Lt, hasUpper (subtract 1), hasLower (add 1), hasTitle, identifier start */ -0x009F0182, /* 45 Ll, hasUpper (subtract 2), hasTitle, identifier start */ -0x00000000, /* 46 unassigned */ -0x34970182, /* 47 Ll, hasUpper (subtract 210), identifier start */ -0x33970182, /* 48 Ll, hasUpper (subtract 206), identifier start */ -0x33570182, /* 49 Ll, hasUpper (subtract 205), identifier start */ -0x32970182, /* 50 Ll, hasUpper (subtract 202), identifier start */ -0x32D70182, /* 51 Ll, hasUpper (subtract 203), identifier start */ -0x33D70182, /* 52 Ll, hasUpper (subtract 207), identifier start */ -0x34570182, /* 53 Ll, hasUpper (subtract 209), identifier start */ -0x34D70182, /* 54 Ll, hasUpper (subtract 211), identifier start */ -0x35570182, /* 55 Ll, hasUpper (subtract 213), identifier start */ -0x36970182, /* 56 Ll, hasUpper (subtract 218), identifier start */ -0x36570182, /* 57 Ll, hasUpper (subtract 217), identifier start */ -0x36D70182, /* 58 Ll, hasUpper (subtract 219), identifier start */ -0x00070084, /* 59 Lm, identifier start */ -0x00030086, /* 60 Mn, identifier part */ -0x09A70181, /* 61 Lu, hasLower (add 38), identifier start */ -0x09670181, /* 62 Lu, hasLower (add 37), identifier start */ -0x10270181, /* 63 Lu, hasLower (add 64), identifier start */ -0x0FE70181, /* 64 Lu, hasLower (add 63), identifier start */ -0x09970182, /* 65 Ll, hasUpper (subtract 38), identifier start */ -0x09570182, /* 66 Ll, hasUpper (subtract 37), identifier start */ -0x10170182, /* 67 Ll, hasUpper (subtract 64), identifier start */ -0x0FD70182, /* 68 Ll, hasUpper (subtract 63), identifier start */ -0x0F970182, /* 69 Ll, hasUpper (subtract 62), identifier start */ -0x0E570182, /* 70 Ll, hasUpper (subtract 57), identifier start */ -0x0BD70182, /* 71 Ll, hasUpper (subtract 47), identifier start */ -0x0D970182, /* 72 Ll, hasUpper (subtract 54), identifier start */ -0x15970182, /* 73 Ll, hasUpper (subtract 86), identifier start */ -0x14170182, /* 74 Ll, hasUpper (subtract 80), identifier start */ -0x14270181, /* 75 Lu, hasLower (add 80), identifier start */ -0x0C270181, /* 76 Lu, hasLower (add 48), identifier start */ -0x0C170182, /* 77 Ll, hasUpper (subtract 48), identifier start */ -0x00034089, /* 78 Nd, identifier part, decimal 0 */ -0x00000087, /* 79 Me */ -0x00030088, /* 80 Mc, identifier part */ -0x00037489, /* 81 Nd, identifier part, decimal 26 */ -0x00005A0B, /* 82 No, decimal 13 */ -0x00006E0B, /* 83 No, decimal 23 */ -0x0000740B, /* 84 No, decimal 26 */ -0x0000000B, /* 85 No */ -0xFE170182, /* 86 Ll, hasUpper (subtract -8), identifier start */ -0xFE270181, /* 87 Lu, hasLower (add -8), identifier start */ -0xED970182, /* 88 Ll, hasUpper (subtract -74), identifier start */ -0xEA970182, /* 89 Ll, hasUpper (subtract -86), identifier start */ -0xE7170182, /* 90 Ll, hasUpper (subtract -100), identifier start */ -0xE0170182, /* 91 Ll, hasUpper (subtract -128), identifier start */ -0xE4170182, /* 92 Ll, hasUpper (subtract -112), identifier start */ -0xE0970182, /* 93 Ll, hasUpper (subtract -126), identifier start */ -0xFDD70182, /* 94 Ll, hasUpper (subtract -9), identifier start */ -0xEDA70181, /* 95 Lu, hasLower (add -74), identifier start */ -0xFDE70181, /* 96 Lu, hasLower (add -9), identifier start */ -0xEAA70181, /* 97 Lu, hasLower (add -86), identifier start */ -0xE7270181, /* 98 Lu, hasLower (add -100), identifier start */ -0xFE570182, /* 99 Ll, hasUpper (subtract -7), identifier start */ -0xE4270181, /* 100 Lu, hasLower (add -112), identifier start */ -0xFE670181, /* 101 Lu, hasLower (add -7), identifier start */ -0xE0270181, /* 102 Lu, hasLower (add -128), identifier start */ -0xE0A70181, /* 103 Lu, hasLower (add -126), identifier start */ -0x00010010, /* 104 Cf, ignorable */ -0x0004000D, /* 105 Zl, whitespace */ -0x0004000E, /* 106 Zp, whitespace */ -0x0000400B, /* 107 No, decimal 0 */ -0x0000440B, /* 108 No, decimal 2 */ -0x0427438A, /* 109 Nl, hasLower (add 16), identifier start, decimal 1 */ -0x0427818A, /* 110 Nl, hasLower (add 16), identifier start, strange */ -0x0417638A, /* 111 Nl, hasUpper (subtract 16), identifier start, decimal 17 */ -0x0417818A, /* 112 Nl, hasUpper (subtract 16), identifier start, strange */ -0x0007818A, /* 113 Nl, identifier start, strange */ -0x0000420B, /* 114 No, decimal 1 */ -0x0000720B, /* 115 No, decimal 25 */ -0x06A0001C, /* 116 So, hasLower (add 26) */ -0x0690001C, /* 117 So, hasUpper (subtract 26) */ -0x00006C0B, /* 118 No, decimal 22 */ -0x0000560B, /* 119 No, decimal 11 */ -0x0007738A, /* 120 Nl, identifier start, decimal 25 */ -0x0007418A, /* 121 Nl, identifier start, decimal 0 */ -0x00000013, /* 122 Cs */ -0x00000012 /* 123 Co */ -}; - -const jschar js_uriReservedPlusPound_ucstr[] = - {';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '#', 0}; -const jschar js_uriUnescaped_ucstr[] = - {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', - 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', - 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', - '-', '_', '.', '!', '~', '*', '\'', '(', ')', 0}; - -#define URI_CHUNK 64U - -/* Concatenate jschars onto an unshared/newborn JSString. */ -static JSBool -AddCharsToURI(JSContext *cx, JSString *str, const jschar *chars, size_t length) -{ - size_t total; - - JS_ASSERT(!JSSTRING_IS_DEPENDENT(str)); - total = str->length + length + 1; - if (!str->chars || - JS_HOWMANY(total, URI_CHUNK) > JS_HOWMANY(str->length + 1, URI_CHUNK)) { - total = JS_ROUNDUP(total, URI_CHUNK); - str->chars = JS_realloc(cx, str->chars, total * sizeof(jschar)); - if (!str->chars) - return JS_FALSE; - } - js_strncpy(str->chars + str->length, chars, length); - str->length += length; - str->chars[str->length] = 0; - return JS_TRUE; -} - -/* - * ECMA 3, 15.1.3 URI Handling Function Properties - * - * The following are implementations of the algorithms - * given in the ECMA specification for the hidden functions - * 'Encode' and 'Decode'. - */ -static JSBool -Encode(JSContext *cx, JSString *str, const jschar *unescapedSet, - const jschar *unescapedSet2, jsval *rval) -{ - size_t length, j, k, L; - jschar *chars, c, c2; - uint32 v; - uint8 utf8buf[6]; - jschar hexBuf[4]; - static const char HexDigits[] = "0123456789ABCDEF"; /* NB: uppercase */ - JSString *R; - - length = JSSTRING_LENGTH(str); - if (length == 0) { - *rval = STRING_TO_JSVAL(cx->runtime->emptyString); - return JS_TRUE; - } - - R = js_NewString(cx, NULL, 0, 0); - if (!R) - return JS_FALSE; - - hexBuf[0] = '%'; - hexBuf[3] = 0; - chars = JSSTRING_CHARS(str); - for (k = 0; k < length; k++) { - c = chars[k]; - if (js_strchr(unescapedSet, c) || - (unescapedSet2 && js_strchr(unescapedSet2, c))) { - if (!AddCharsToURI(cx, R, &c, 1)) - return JS_FALSE; - } else { - if ((c >= 0xDC00) && (c <= 0xDFFF)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_URI, NULL); - return JS_FALSE; - } - if (c < 0xD800 || c > 0xDBFF) { - v = c; - } else { - k++; - if (k == length) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_URI, NULL); - return JS_FALSE; - } - c2 = chars[k]; - if ((c2 < 0xDC00) || (c2 > 0xDFFF)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_URI, NULL); - return JS_FALSE; - } - v = ((c - 0xD800) << 10) + (c2 - 0xDC00) + 0x10000; - } - L = js_OneUcs4ToUtf8Char(utf8buf, v); - for (j = 0; j < L; j++) { - hexBuf[1] = HexDigits[utf8buf[j] >> 4]; - hexBuf[2] = HexDigits[utf8buf[j] & 0xf]; - if (!AddCharsToURI(cx, R, hexBuf, 3)) - return JS_FALSE; - } - } - } - - /* - * Shrinking realloc can fail (e.g., with a BSD-style allocator), but we - * don't worry about that case here. Worst case, R hangs onto URI_CHUNK-1 - * more jschars than it needs. - */ - chars = (jschar *) JS_realloc(cx, R->chars, (R->length+1) * sizeof(jschar)); - if (chars) - R->chars = chars; - *rval = STRING_TO_JSVAL(R); - return JS_TRUE; -} - -static JSBool -Decode(JSContext *cx, JSString *str, const jschar *reservedSet, jsval *rval) -{ - size_t length, start, k; - jschar *chars, c, H; - uint32 v; - jsuint B; - uint8 octets[6]; - JSString *R; - intN j, n; - - length = JSSTRING_LENGTH(str); - if (length == 0) { - *rval = STRING_TO_JSVAL(cx->runtime->emptyString); - return JS_TRUE; - } - - R = js_NewString(cx, NULL, 0, 0); - if (!R) - return JS_FALSE; - - chars = JSSTRING_CHARS(str); - for (k = 0; k < length; k++) { - c = chars[k]; - if (c == '%') { - start = k; - if ((k + 2) >= length) - goto bad; - if (!JS7_ISHEX(chars[k+1]) || !JS7_ISHEX(chars[k+2])) - goto bad; - B = JS7_UNHEX(chars[k+1]) * 16 + JS7_UNHEX(chars[k+2]); - k += 2; - if (!(B & 0x80)) { - c = (jschar)B; - } else { - n = 1; - while (B & (0x80 >> n)) - n++; - if (n == 1 || n > 6) - goto bad; - octets[0] = (uint8)B; - if (k + 3 * (n - 1) >= length) - goto bad; - for (j = 1; j < n; j++) { - k++; - if (chars[k] != '%') - goto bad; - if (!JS7_ISHEX(chars[k+1]) || !JS7_ISHEX(chars[k+2])) - goto bad; - B = JS7_UNHEX(chars[k+1]) * 16 + JS7_UNHEX(chars[k+2]); - if ((B & 0xC0) != 0x80) - goto bad; - k += 2; - octets[j] = (char)B; - } - v = Utf8ToOneUcs4Char(octets, n); - if (v >= 0x10000) { - v -= 0x10000; - if (v > 0xFFFFF) - goto bad; - c = (jschar)((v & 0x3FF) + 0xDC00); - H = (jschar)((v >> 10) + 0xD800); - if (!AddCharsToURI(cx, R, &H, 1)) - return JS_FALSE; - } else { - c = (jschar)v; - } - } - if (js_strchr(reservedSet, c)) { - if (!AddCharsToURI(cx, R, &chars[start], (k - start + 1))) - return JS_FALSE; - } else { - if (!AddCharsToURI(cx, R, &c, 1)) - return JS_FALSE; - } - } else { - if (!AddCharsToURI(cx, R, &c, 1)) - return JS_FALSE; - } - } - - /* - * Shrinking realloc can fail (e.g., with a BSD-style allocator), but we - * don't worry about that case here. Worst case, R hangs onto URI_CHUNK-1 - * more jschars than it needs. - */ - chars = (jschar *) JS_realloc(cx, R->chars, (R->length+1) * sizeof(jschar)); - if (chars) - R->chars = chars; - *rval = STRING_TO_JSVAL(R); - return JS_TRUE; - -bad: - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_URI); - return JS_FALSE; -} - -static JSBool -str_decodeURI(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSString *str; - - str = js_ValueToString(cx, argv[0]); - if (!str) - return JS_FALSE; - argv[0] = STRING_TO_JSVAL(str); - return Decode(cx, str, js_uriReservedPlusPound_ucstr, rval); -} - -static JSBool -str_decodeURI_Component(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSString *str; - - str = js_ValueToString(cx, argv[0]); - if (!str) - return JS_FALSE; - argv[0] = STRING_TO_JSVAL(str); - return Decode(cx, str, js_empty_ucstr, rval); -} - -static JSBool -str_encodeURI(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSString *str; - - str = js_ValueToString(cx, argv[0]); - if (!str) - return JS_FALSE; - argv[0] = STRING_TO_JSVAL(str); - return Encode(cx, str, js_uriReservedPlusPound_ucstr, js_uriUnescaped_ucstr, - rval); -} - -static JSBool -str_encodeURI_Component(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSString *str; - - str = js_ValueToString(cx, argv[0]); - if (!str) - return JS_FALSE; - argv[0] = STRING_TO_JSVAL(str); - return Encode(cx, str, js_uriUnescaped_ucstr, NULL, rval); -} - -/* - * Convert one UCS-4 char and write it into a UTF-8 buffer, which must be at - * least 6 bytes long. Return the number of UTF-8 bytes of data written. - */ -int -js_OneUcs4ToUtf8Char(uint8 *utf8Buffer, uint32 ucs4Char) -{ - int utf8Length = 1; - - JS_ASSERT(ucs4Char <= 0x7FFFFFFF); - if (ucs4Char < 0x80) { - *utf8Buffer = (uint8)ucs4Char; - } else { - int i; - uint32 a = ucs4Char >> 11; - utf8Length = 2; - while (a) { - a >>= 5; - utf8Length++; - } - i = utf8Length; - while (--i) { - utf8Buffer[i] = (uint8)((ucs4Char & 0x3F) | 0x80); - ucs4Char >>= 6; - } - *utf8Buffer = (uint8)(0x100 - (1 << (8-utf8Length)) + ucs4Char); - } - return utf8Length; -} - -/* - * Convert a utf8 character sequence into a UCS-4 character and return that - * character. It is assumed that the caller already checked that the sequence - * is valid. - */ -static uint32 -Utf8ToOneUcs4Char(const uint8 *utf8Buffer, int utf8Length) -{ - uint32 ucs4Char; - uint32 minucs4Char; - /* from Unicode 3.1, non-shortest form is illegal */ - static const uint32 minucs4Table[] = { - 0x00000080, 0x00000800, 0x0001000, 0x0020000, 0x0400000 - }; - - JS_ASSERT(utf8Length >= 1 && utf8Length <= 6); - if (utf8Length == 1) { - ucs4Char = *utf8Buffer; - JS_ASSERT(!(ucs4Char & 0x80)); - } else { - JS_ASSERT((*utf8Buffer & (0x100 - (1 << (7-utf8Length)))) == - (0x100 - (1 << (8-utf8Length)))); - ucs4Char = *utf8Buffer++ & ((1<<(7-utf8Length))-1); - minucs4Char = minucs4Table[utf8Length-2]; - while (--utf8Length) { - JS_ASSERT((*utf8Buffer & 0xC0) == 0x80); - ucs4Char = ucs4Char<<6 | (*utf8Buffer++ & 0x3F); - } - if (ucs4Char < minucs4Char || - ucs4Char == 0xFFFE || ucs4Char == 0xFFFF) { - ucs4Char = 0xFFFD; - } - } - return ucs4Char; -} diff --git a/lib/javascript/jsstr.h b/lib/javascript/jsstr.h deleted file mode 100644 index 658a87f9..00000000 --- a/lib/javascript/jsstr.h +++ /dev/null @@ -1,482 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jsstr_h___ -#define jsstr_h___ -/* - * JS string type implementation. - * - * A JS string is a counted array of unicode characters. To support handoff - * of API client memory, the chars are allocated separately from the length, - * necessitating a pointer after the count, to form a separately allocated - * string descriptor. String descriptors are GC'ed, while their chars are - * allocated from the malloc heap. - * - * When a string is treated as an object (by following it with . or []), the - * runtime wraps it with a JSObject whose valueOf method returns the unwrapped - * string descriptor. - */ -#include -#include "jspubtd.h" -#include "jsprvtd.h" -#include "jshash.h" - -JS_BEGIN_EXTERN_C - -/* - * The original GC-thing "string" type, a flat character string owned by its - * GC-thing descriptor. The chars member points to a vector having byte size - * (length + 1) * sizeof(jschar), terminated at index length by a zero jschar. - * The terminator is purely a backstop, in case the chars pointer flows out to - * native code that requires \u0000 termination. - * - * NB: Always use the JSSTRING_LENGTH and JSSTRING_CHARS accessor macros, - * unless you guard str->member uses with !JSSTRING_IS_DEPENDENT(str). - */ -struct JSString { - size_t length; - jschar *chars; -}; - -/* - * Overlay structure for a string that depends on another string's characters. - * Distinguished by the JSSTRFLAG_DEPENDENT bit being set in length. The base - * member may point to another dependent string if JSSTRING_CHARS has not been - * called yet. The length chars in a dependent string are stored starting at - * base->chars + start, and are not necessarily zero-terminated. If start is - * 0, it is not stored, length is a full size_t (minus the JSSTRFLAG_* bits in - * the high two positions), and the JSSTRFLAG_PREFIX flag is set. - */ -struct JSDependentString { - size_t length; - JSString *base; -}; - -/* Definitions for flags stored in the high order bits of JSString.length. */ -#define JSSTRFLAG_BITS 2 -#define JSSTRFLAG_SHIFT(flg) ((size_t)(flg) << JSSTRING_LENGTH_BITS) -#define JSSTRFLAG_MASK JSSTRFLAG_SHIFT(JS_BITMASK(JSSTRFLAG_BITS)) -#define JSSTRFLAG_DEPENDENT JSSTRFLAG_SHIFT(1) -#define JSSTRFLAG_PREFIX JSSTRFLAG_SHIFT(2) - -/* Universal JSString type inquiry and accessor macros. */ -#define JSSTRING_BIT(n) ((size_t)1 << (n)) -#define JSSTRING_BITMASK(n) (JSSTRING_BIT(n) - 1) -#define JSSTRING_HAS_FLAG(str,flg) ((str)->length & (flg)) -#define JSSTRING_IS_DEPENDENT(str) JSSTRING_HAS_FLAG(str, JSSTRFLAG_DEPENDENT) -#define JSSTRING_IS_PREFIX(str) JSSTRING_HAS_FLAG(str, JSSTRFLAG_PREFIX) -#define JSSTRING_CHARS(str) (JSSTRING_IS_DEPENDENT(str) \ - ? JSSTRDEP_CHARS(str) \ - : (str)->chars) -#define JSSTRING_LENGTH(str) (JSSTRING_IS_DEPENDENT(str) \ - ? JSSTRDEP_LENGTH(str) \ - : (str)->length) -#define JSSTRING_LENGTH_BITS (sizeof(size_t) * JS_BITS_PER_BYTE \ - - JSSTRFLAG_BITS) -#define JSSTRING_LENGTH_MASK JSSTRING_BITMASK(JSSTRING_LENGTH_BITS) - -/* Specific JSDependentString shift/mask accessor and mutator macros. */ -#define JSSTRDEP_START_BITS (JSSTRING_LENGTH_BITS-JSSTRDEP_LENGTH_BITS) -#define JSSTRDEP_START_SHIFT JSSTRDEP_LENGTH_BITS -#define JSSTRDEP_START_MASK JSSTRING_BITMASK(JSSTRDEP_START_BITS) -#define JSSTRDEP_LENGTH_BITS (JSSTRING_LENGTH_BITS / 2) -#define JSSTRDEP_LENGTH_MASK JSSTRING_BITMASK(JSSTRDEP_LENGTH_BITS) - -#define JSSTRDEP(str) ((JSDependentString *)(str)) -#define JSSTRDEP_START(str) (JSSTRING_IS_PREFIX(str) ? 0 \ - : ((JSSTRDEP(str)->length \ - >> JSSTRDEP_START_SHIFT) \ - & JSSTRDEP_START_MASK)) -#define JSSTRDEP_LENGTH(str) (JSSTRDEP(str)->length \ - & (JSSTRING_IS_PREFIX(str) \ - ? JSSTRING_LENGTH_MASK \ - : JSSTRDEP_LENGTH_MASK)) - -#define JSSTRDEP_SET_START_AND_LENGTH(str,off,len) \ - (JSSTRDEP(str)->length = JSSTRFLAG_DEPENDENT \ - | ((off) << JSSTRDEP_START_SHIFT) \ - | (len)) -#define JSPREFIX_SET_LENGTH(str,len) \ - (JSSTRDEP(str)->length = JSSTRFLAG_DEPENDENT | JSSTRFLAG_PREFIX | (len)) - -#define JSSTRDEP_BASE(str) (JSSTRDEP(str)->base) -#define JSSTRDEP_SET_BASE(str,bstr) (JSSTRDEP(str)->base = (bstr)) -#define JSPREFIX_BASE(str) JSSTRDEP_BASE(str) -#define JSPREFIX_SET_BASE(str,bstr) JSSTRDEP_SET_BASE(str,bstr) - -#define JSSTRDEP_CHARS(str) \ - (JSSTRING_IS_DEPENDENT(JSSTRDEP_BASE(str)) \ - ? js_GetDependentStringChars(str) \ - : JSSTRDEP_BASE(str)->chars + JSSTRDEP_START(str)) - -extern size_t -js_MinimizeDependentStrings(JSString *str, int level, JSString **basep); - -extern jschar * -js_GetDependentStringChars(JSString *str); - -extern jschar * -js_GetStringChars(JSString *str); - -extern JSString * -js_ConcatStrings(JSContext *cx, JSString *left, JSString *right); - -extern const jschar * -js_UndependString(JSContext *cx, JSString *str); - -struct JSSubString { - size_t length; - const jschar *chars; -}; - -extern jschar js_empty_ucstr[]; -extern JSSubString js_EmptySubString; - -/* Unicode character attribute lookup tables. */ -extern const uint8 js_X[]; -extern const uint8 js_Y[]; -extern const uint32 js_A[]; - -/* Enumerated Unicode general category types. */ -typedef enum JSCharType { - JSCT_UNASSIGNED = 0, - JSCT_UPPERCASE_LETTER = 1, - JSCT_LOWERCASE_LETTER = 2, - JSCT_TITLECASE_LETTER = 3, - JSCT_MODIFIER_LETTER = 4, - JSCT_OTHER_LETTER = 5, - JSCT_NON_SPACING_MARK = 6, - JSCT_ENCLOSING_MARK = 7, - JSCT_COMBINING_SPACING_MARK = 8, - JSCT_DECIMAL_DIGIT_NUMBER = 9, - JSCT_LETTER_NUMBER = 10, - JSCT_OTHER_NUMBER = 11, - JSCT_SPACE_SEPARATOR = 12, - JSCT_LINE_SEPARATOR = 13, - JSCT_PARAGRAPH_SEPARATOR = 14, - JSCT_CONTROL = 15, - JSCT_FORMAT = 16, - JSCT_PRIVATE_USE = 18, - JSCT_SURROGATE = 19, - JSCT_DASH_PUNCTUATION = 20, - JSCT_START_PUNCTUATION = 21, - JSCT_END_PUNCTUATION = 22, - JSCT_CONNECTOR_PUNCTUATION = 23, - JSCT_OTHER_PUNCTUATION = 24, - JSCT_MATH_SYMBOL = 25, - JSCT_CURRENCY_SYMBOL = 26, - JSCT_MODIFIER_SYMBOL = 27, - JSCT_OTHER_SYMBOL = 28 -} JSCharType; - -/* Character classifying and mapping macros, based on java.lang.Character. */ -#define JS_CCODE(c) (js_A[js_Y[(js_X[(uint16)(c)>>6]<<6)|((c)&0x3F)]]) -#define JS_CTYPE(c) (JS_CCODE(c) & 0x1F) - -#define JS_ISALPHA(c) ((((1 << JSCT_UPPERCASE_LETTER) | \ - (1 << JSCT_LOWERCASE_LETTER) | \ - (1 << JSCT_TITLECASE_LETTER) | \ - (1 << JSCT_MODIFIER_LETTER) | \ - (1 << JSCT_OTHER_LETTER)) \ - >> JS_CTYPE(c)) & 1) - -#define JS_ISALNUM(c) ((((1 << JSCT_UPPERCASE_LETTER) | \ - (1 << JSCT_LOWERCASE_LETTER) | \ - (1 << JSCT_TITLECASE_LETTER) | \ - (1 << JSCT_MODIFIER_LETTER) | \ - (1 << JSCT_OTHER_LETTER) | \ - (1 << JSCT_DECIMAL_DIGIT_NUMBER)) \ - >> JS_CTYPE(c)) & 1) - -/* A unicode letter, suitable for use in an identifier. */ -#define JS_ISLETTER(c) ((((1 << JSCT_UPPERCASE_LETTER) | \ - (1 << JSCT_LOWERCASE_LETTER) | \ - (1 << JSCT_TITLECASE_LETTER) | \ - (1 << JSCT_MODIFIER_LETTER) | \ - (1 << JSCT_OTHER_LETTER) | \ - (1 << JSCT_LETTER_NUMBER)) \ - >> JS_CTYPE(c)) & 1) - -/* - * 'IdentifierPart' from ECMA grammar, is Unicode letter or combining mark or - * digit or connector punctuation. - */ -#define JS_ISIDPART(c) ((((1 << JSCT_UPPERCASE_LETTER) | \ - (1 << JSCT_LOWERCASE_LETTER) | \ - (1 << JSCT_TITLECASE_LETTER) | \ - (1 << JSCT_MODIFIER_LETTER) | \ - (1 << JSCT_OTHER_LETTER) | \ - (1 << JSCT_LETTER_NUMBER) | \ - (1 << JSCT_NON_SPACING_MARK) | \ - (1 << JSCT_COMBINING_SPACING_MARK) | \ - (1 << JSCT_DECIMAL_DIGIT_NUMBER) | \ - (1 << JSCT_CONNECTOR_PUNCTUATION)) \ - >> JS_CTYPE(c)) & 1) - -/* Unicode control-format characters, ignored in input */ -#define JS_ISFORMAT(c) (((1 << JSCT_FORMAT) >> JS_CTYPE(c)) & 1) - -/* - * Per ECMA-262 15.10.2.6, these characters are the only ones that make up a - * "word", as far as a RegExp is concerned. If we want a Unicode-friendlier - * definition of "word", we should rename this macro to something regexp-y. - */ -#define JS_ISWORD(c) ((c) < 128 && (isalnum(c) || (c) == '_')) - -#define JS_ISIDSTART(c) (JS_ISLETTER(c) || (c) == '_' || (c) == '$') -#define JS_ISIDENT(c) (JS_ISIDPART(c) || (c) == '_' || (c) == '$') - -#define JS_ISXMLSPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || \ - (c) == '\n') -#define JS_ISXMLNSSTART(c) ((JS_CCODE(c) & 0x00000100) || (c) == '_') -#define JS_ISXMLNS(c) ((JS_CCODE(c) & 0x00000080) || (c) == '.' || \ - (c) == '-' || (c) == '_') -#define JS_ISXMLNAMESTART(c) (JS_ISXMLNSSTART(c) || (c) == ':') -#define JS_ISXMLNAME(c) (JS_ISXMLNS(c) || (c) == ':') - -#define JS_ISDIGIT(c) (JS_CTYPE(c) == JSCT_DECIMAL_DIGIT_NUMBER) - -/* XXXbe unify on A/X/Y tbls, avoid ctype.h? */ -/* XXXbe fs, etc. ? */ -#define JS_ISSPACE(c) ((JS_CCODE(c) & 0x00070000) == 0x00040000) -#define JS_ISPRINT(c) ((c) < 128 && isprint(c)) - -#define JS_ISUPPER(c) (JS_CTYPE(c) == JSCT_UPPERCASE_LETTER) -#define JS_ISLOWER(c) (JS_CTYPE(c) == JSCT_LOWERCASE_LETTER) - -#define JS_TOUPPER(c) ((jschar) ((JS_CCODE(c) & 0x00100000) \ - ? (c) - ((int32)JS_CCODE(c) >> 22) \ - : (c))) -#define JS_TOLOWER(c) ((jschar) ((JS_CCODE(c) & 0x00200000) \ - ? (c) + ((int32)JS_CCODE(c) >> 22) \ - : (c))) - -/* Shorthands for ASCII (7-bit) decimal and hex conversion. */ -#define JS7_ISDEC(c) ((c) < 128 && isdigit(c)) -#define JS7_UNDEC(c) ((c) - '0') -#define JS7_ISHEX(c) ((c) < 128 && isxdigit(c)) -#define JS7_UNHEX(c) (uintN)(isdigit(c) ? (c) - '0' : 10 + tolower(c) - 'a') -#define JS7_ISLET(c) ((c) < 128 && isalpha(c)) - -/* Initialize truly global state associated with JS strings. */ -extern JSBool -js_InitStringGlobals(void); - -extern void -js_FreeStringGlobals(void); - -extern void -js_PurgeDeflatedStringCache(JSString *str); - -/* Initialize per-runtime string state for the first context in the runtime. */ -extern JSBool -js_InitRuntimeStringState(JSContext *cx); - -extern void -js_FinishRuntimeStringState(JSContext *cx); - -/* Initialize the String class, returning its prototype object. */ -extern JSClass js_StringClass; - -extern JSObject * -js_InitStringClass(JSContext *cx, JSObject *obj); - -extern const char js_escape_str[]; -extern const char js_unescape_str[]; -extern const char js_uneval_str[]; -extern const char js_decodeURI_str[]; -extern const char js_encodeURI_str[]; -extern const char js_decodeURIComponent_str[]; -extern const char js_encodeURIComponent_str[]; - -/* GC-allocate a string descriptor for the given malloc-allocated chars. */ -extern JSString * -js_NewString(JSContext *cx, jschar *chars, size_t length, uintN gcflag); - -extern JSString * -js_NewDependentString(JSContext *cx, JSString *base, size_t start, - size_t length, uintN gcflag); - -/* Copy a counted string and GC-allocate a descriptor for it. */ -extern JSString * -js_NewStringCopyN(JSContext *cx, const jschar *s, size_t n, uintN gcflag); - -/* Copy a C string and GC-allocate a descriptor for it. */ -extern JSString * -js_NewStringCopyZ(JSContext *cx, const jschar *s, uintN gcflag); - -/* Free the chars held by str when it is finalized by the GC. */ -extern void -js_FinalizeString(JSContext *cx, JSString *str); - -extern void -js_FinalizeStringRT(JSRuntime *rt, JSString *str); - -/* Wrap a string value in a String object. */ -extern JSObject * -js_StringToObject(JSContext *cx, JSString *str); - -/* - * Convert a value to a printable C string. - */ -extern JS_FRIEND_API(const char *) -js_ValueToPrintableString(JSContext *cx, jsval v); - -/* - * Convert a value to a string, returning null after reporting an error, - * otherwise returning a new string reference. - */ -extern JSString * -js_ValueToString(JSContext *cx, jsval v); - -/* - * Convert a value to its source expression, returning null after reporting - * an error, otherwise returning a new string reference. - */ -extern JSString * -js_ValueToSource(JSContext *cx, jsval v); - -#ifdef HT_ENUMERATE_NEXT /* XXX don't require jshash.h */ -/* - * Compute a hash function from str. - */ -extern JSHashNumber -js_HashString(JSString *str); -#endif - -/* - * Return less than, equal to, or greater than zero depending on whether - * str1 is less than, equal to, or greater than str2. - */ -extern intN -js_CompareStrings(JSString *str1, JSString *str2); - -/* - * Boyer-Moore-Horspool superlinear search for pat:patlen in text:textlen. - * The patlen argument must be positive and no greater than BMH_PATLEN_MAX. - * The start argument tells where in text to begin the search. - * - * Return the index of pat in text, or -1 if not found. - */ -#define BMH_CHARSET_SIZE 256 /* ISO-Latin-1 */ -#define BMH_PATLEN_MAX 255 /* skip table element is uint8 */ - -#define BMH_BAD_PATTERN (-2) /* return value if pat is not ISO-Latin-1 */ - -extern jsint -js_BoyerMooreHorspool(const jschar *text, jsint textlen, - const jschar *pat, jsint patlen, - jsint start); - -extern size_t -js_strlen(const jschar *s); - -extern jschar * -js_strchr(const jschar *s, jschar c); - -extern jschar * -js_strchr_limit(const jschar *s, jschar c, const jschar *limit); - -#define js_strncpy(t, s, n) memcpy((t), (s), (n) * sizeof(jschar)) - -/* - * Return s advanced past any Unicode white space characters. - */ -extern const jschar * -js_SkipWhiteSpace(const jschar *s); - -/* - * Inflate bytes to JS chars and vice versa. Report out of memory via cx - * and return null on error, otherwise return the jschar or byte vector that - * was JS_malloc'ed. length is updated with the length of the new string in jschars. - */ -extern jschar * -js_InflateString(JSContext *cx, const char *bytes, size_t *length); - -extern char * -js_DeflateString(JSContext *cx, const jschar *chars, size_t length); - -/* - * Inflate bytes to JS chars into a buffer. - * 'chars' must be large enough for 'length' jschars. - * The buffer is NOT null-terminated. - * cx may be NULL, which means no errors are thrown. - * The destination length needs to be initialized with the buffer size, takes the number of chars moved. - */ -extern JSBool -js_InflateStringToBuffer(JSContext* cx, const char *bytes, size_t length, jschar *chars, size_t* charsLength); - -/* - * Deflate JS chars to bytes into a buffer. - * 'bytes' must be large enough for 'length chars. - * The buffer is NOT null-terminated. - * cx may be NULL, which means no errors are thrown. - * The destination length needs to be initialized with the buffer size, takes the number of bytes moved. - */ -extern JSBool -js_DeflateStringToBuffer(JSContext* cx, const jschar *chars, size_t charsLength, char *bytes, size_t* length); - -/* - * Associate bytes with str in the deflated string cache, returning true on - * successful association, false on out of memory. - */ -extern JSBool -js_SetStringBytes(JSString *str, char *bytes, size_t length); - -/* - * Find or create a deflated string cache entry for str that contains its - * characters chopped from Unicode code points into bytes. - */ -extern char * -js_GetStringBytes(JSString *str); - -JSBool -js_str_escape(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval); - -/* - * Convert one UCS-4 char and write it into a UTF-8 buffer, which must be at - * least 6 bytes long. Return the number of UTF-8 bytes of data written. - */ -extern int -js_OneUcs4ToUtf8Char(uint8 *utf8Buffer, uint32 ucs4Char); - -JS_END_EXTERN_C - -#endif /* jsstr_h___ */ diff --git a/lib/javascript/jstypes.h b/lib/javascript/jstypes.h deleted file mode 100644 index 92e13f91..00000000 --- a/lib/javascript/jstypes.h +++ /dev/null @@ -1,421 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * IBM Corp. - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* -** File: jstypes.h -** Description: Definitions of NSPR's basic types -** -** Prototypes and macros used to make up for deficiencies in ANSI environments -** that we have found. -** -** Since we do not wrap and all the other standard headers, authors -** of portable code will not know in general that they need these definitions. -** Instead of requiring these authors to find the dependent uses in their code -** and take the following steps only in those C files, we take steps once here -** for all C files. -**/ - -#ifndef jstypes_h___ -#define jstypes_h___ - -#include - -/*********************************************************************** -** MACROS: JS_EXTERN_API -** JS_EXPORT_API -** DESCRIPTION: -** These are only for externally visible routines and globals. For -** internal routines, just use "extern" for type checking and that -** will not export internal cross-file or forward-declared symbols. -** Define a macro for declaring procedures return types. We use this to -** deal with windoze specific type hackery for DLL definitions. Use -** JS_EXTERN_API when the prototype for the method is declared. Use -** JS_EXPORT_API for the implementation of the method. -** -** Example: -** in dowhim.h -** JS_EXTERN_API( void ) DoWhatIMean( void ); -** in dowhim.c -** JS_EXPORT_API( void ) DoWhatIMean( void ) { return; } -** -** -***********************************************************************/ -#ifdef WIN32 -/* These also work for __MWERKS__ */ -#define JS_EXTERN_API(__type) extern __declspec(dllexport) __type -#define JS_EXPORT_API(__type) __declspec(dllexport) __type -#define JS_EXTERN_DATA(__type) extern __declspec(dllexport) __type -#define JS_EXPORT_DATA(__type) __declspec(dllexport) __type - -#define JS_DLL_CALLBACK -#define JS_STATIC_DLL_CALLBACK(__x) static __x - -#elif defined(WIN16) - -#ifdef _WINDLL -#define JS_EXTERN_API(__type) extern __type _cdecl _export _loadds -#define JS_EXPORT_API(__type) __type _cdecl _export _loadds -#define JS_EXTERN_DATA(__type) extern __type _export -#define JS_EXPORT_DATA(__type) __type _export - -#define JS_DLL_CALLBACK __cdecl __loadds -#define JS_STATIC_DLL_CALLBACK(__x) static __x CALLBACK - -#else /* this must be .EXE */ -#define JS_EXTERN_API(__type) extern __type _cdecl _export -#define JS_EXPORT_API(__type) __type _cdecl _export -#define JS_EXTERN_DATA(__type) extern __type _export -#define JS_EXPORT_DATA(__type) __type _export - -#define JS_DLL_CALLBACK __cdecl __loadds -#define JS_STATIC_DLL_CALLBACK(__x) __x JS_DLL_CALLBACK -#endif /* _WINDLL */ - -#else /* Unix */ - -#ifdef HAVE_VISIBILITY_PRAGMA -#define JS_EXTERNAL_VIS __attribute__((visibility ("default"))) -#else -#define JS_EXTERNAL_VIS -#endif - -#define JS_EXTERN_API(__type) extern JS_EXTERNAL_VIS __type -#define JS_EXPORT_API(__type) JS_EXTERNAL_VIS __type -#define JS_EXTERN_DATA(__type) extern JS_EXTERNAL_VIS __type -#define JS_EXPORT_DATA(__type) JS_EXTERNAL_VIS __type - -#define JS_DLL_CALLBACK -#define JS_STATIC_DLL_CALLBACK(__x) static __x - -#endif - -#ifdef _WIN32 -# if defined(__MWERKS__) || defined(__GNUC__) -# define JS_IMPORT_API(__x) __x -# else -# define JS_IMPORT_API(__x) __declspec(dllimport) __x -# endif -#else -# define JS_IMPORT_API(__x) JS_EXPORT_API (__x) -#endif - -#if defined(_WIN32) && !defined(__MWERKS__) -# define JS_IMPORT_DATA(__x) __declspec(dllimport) __x -#else -# define JS_IMPORT_DATA(__x) JS_EXPORT_DATA (__x) -#endif - -/* - * The linkage of JS API functions differs depending on whether the file is - * used within the JS library or not. Any source file within the JS - * interpreter should define EXPORT_JS_API whereas any client of the library - * should not. - */ -#ifdef EXPORT_JS_API -#define JS_PUBLIC_API(t) JS_EXPORT_API(t) -#define JS_PUBLIC_DATA(t) JS_EXPORT_DATA(t) -#else -#define JS_PUBLIC_API(t) JS_IMPORT_API(t) -#define JS_PUBLIC_DATA(t) JS_IMPORT_DATA(t) -#endif - -#define JS_FRIEND_API(t) JS_PUBLIC_API(t) -#define JS_FRIEND_DATA(t) JS_PUBLIC_DATA(t) - -#ifdef _WIN32 -# define JS_INLINE __inline -#elif defined(__GNUC__) -# define JS_INLINE -#else -# define JS_INLINE -#endif - -/*********************************************************************** -** MACROS: JS_BEGIN_MACRO -** JS_END_MACRO -** DESCRIPTION: -** Macro body brackets so that macros with compound statement definitions -** behave syntactically more like functions when called. -***********************************************************************/ -#define JS_BEGIN_MACRO do { -#define JS_END_MACRO } while (0) - -/*********************************************************************** -** MACROS: JS_BEGIN_EXTERN_C -** JS_END_EXTERN_C -** DESCRIPTION: -** Macro shorthands for conditional C++ extern block delimiters. -***********************************************************************/ -#ifdef __cplusplus -#define JS_BEGIN_EXTERN_C extern "C" { -#define JS_END_EXTERN_C } -#else -#define JS_BEGIN_EXTERN_C -#define JS_END_EXTERN_C -#endif - -/*********************************************************************** -** MACROS: JS_BIT -** JS_BITMASK -** DESCRIPTION: -** Bit masking macros. XXX n must be <= 31 to be portable -***********************************************************************/ -#define JS_BIT(n) ((JSUint32)1 << (n)) -#define JS_BITMASK(n) (JS_BIT(n) - 1) - -/*********************************************************************** -** MACROS: JS_PTR_TO_INT32 -** JS_PTR_TO_UINT32 -** JS_INT32_TO_PTR -** JS_UINT32_TO_PTR -** DESCRIPTION: -** Integer to pointer and pointer to integer conversion macros. -***********************************************************************/ -#define JS_PTR_TO_INT32(x) ((jsint)((char *)(x) - (char *)0)) -#define JS_PTR_TO_UINT32(x) ((jsuint)((char *)(x) - (char *)0)) -#define JS_INT32_TO_PTR(x) ((void *)((char *)0 + (jsint)(x))) -#define JS_UINT32_TO_PTR(x) ((void *)((char *)0 + (jsuint)(x))) - -/*********************************************************************** -** MACROS: JS_HOWMANY -** JS_ROUNDUP -** JS_MIN -** JS_MAX -** DESCRIPTION: -** Commonly used macros for operations on compatible types. -***********************************************************************/ -#define JS_HOWMANY(x,y) (((x)+(y)-1)/(y)) -#define JS_ROUNDUP(x,y) (JS_HOWMANY(x,y)*(y)) -#define JS_MIN(x,y) ((x)<(y)?(x):(y)) -#define JS_MAX(x,y) ((x)>(y)?(x):(y)) - -#if (defined(XP_WIN) && !defined(CROSS_COMPILE)) || defined (WINCE) -# include "jscpucfg.h" /* Use standard Mac or Windows configuration */ -#elif defined(XP_UNIX) || defined(XP_BEOS) || defined(XP_OS2) || defined(CROSS_COMPILE) -# include "obj/jsautocfg.h" /* Use auto-detected configuration */ -# include "jsosdep.h" /* ...and platform-specific flags */ -#else -# error "Must define one of XP_BEOS, XP_OS2, XP_WIN or XP_UNIX" -#endif - -JS_BEGIN_EXTERN_C - -/************************************************************************ -** TYPES: JSUint8 -** JSInt8 -** DESCRIPTION: -** The int8 types are known to be 8 bits each. There is no type that -** is equivalent to a plain "char". -************************************************************************/ -#if JS_BYTES_PER_BYTE == 1 -typedef unsigned char JSUint8; -typedef signed char JSInt8; -#else -#error No suitable type for JSInt8/JSUint8 -#endif - -/************************************************************************ -** TYPES: JSUint16 -** JSInt16 -** DESCRIPTION: -** The int16 types are known to be 16 bits each. -************************************************************************/ -#if JS_BYTES_PER_SHORT == 2 -typedef unsigned short JSUint16; -typedef short JSInt16; -#else -#error No suitable type for JSInt16/JSUint16 -#endif - -/************************************************************************ -** TYPES: JSUint32 -** JSInt32 -** DESCRIPTION: -** The int32 types are known to be 32 bits each. -************************************************************************/ -#if JS_BYTES_PER_INT == 4 -typedef unsigned int JSUint32; -typedef int JSInt32; -#define JS_INT32(x) x -#define JS_UINT32(x) x ## U -#elif JS_BYTES_PER_LONG == 4 -typedef unsigned long JSUint32; -typedef long JSInt32; -#define JS_INT32(x) x ## L -#define JS_UINT32(x) x ## UL -#else -#error No suitable type for JSInt32/JSUint32 -#endif - -/************************************************************************ -** TYPES: JSUint64 -** JSInt64 -** DESCRIPTION: -** The int64 types are known to be 64 bits each. Care must be used when -** declaring variables of type JSUint64 or JSInt64. Different hardware -** architectures and even different compilers have varying support for -** 64 bit values. The only guaranteed portability requires the use of -** the JSLL_ macros (see jslong.h). -************************************************************************/ -#ifdef JS_HAVE_LONG_LONG -#if JS_BYTES_PER_LONG == 8 -typedef long JSInt64; -typedef unsigned long JSUint64; -#elif defined(WIN16) -typedef __int64 JSInt64; -typedef unsigned __int64 JSUint64; -#elif defined(WIN32) && !defined(__GNUC__) -typedef __int64 JSInt64; -typedef unsigned __int64 JSUint64; -#else -typedef long long JSInt64; -typedef unsigned long long JSUint64; -#endif /* JS_BYTES_PER_LONG == 8 */ -#else /* !JS_HAVE_LONG_LONG */ -typedef struct { -#ifdef IS_LITTLE_ENDIAN - JSUint32 lo, hi; -#else - JSUint32 hi, lo; -#endif -} JSInt64; -typedef JSInt64 JSUint64; -#endif /* !JS_HAVE_LONG_LONG */ - -/************************************************************************ -** TYPES: JSUintn -** JSIntn -** DESCRIPTION: -** The JSIntn types are most appropriate for automatic variables. They are -** guaranteed to be at least 16 bits, though various architectures may -** define them to be wider (e.g., 32 or even 64 bits). These types are -** never valid for fields of a structure. -************************************************************************/ -#if JS_BYTES_PER_INT >= 2 -typedef int JSIntn; -typedef unsigned int JSUintn; -#else -#error 'sizeof(int)' not sufficient for platform use -#endif - -/************************************************************************ -** TYPES: JSFloat64 -** DESCRIPTION: -** NSPR's floating point type is always 64 bits. -************************************************************************/ -typedef double JSFloat64; - -/************************************************************************ -** TYPES: JSSize -** DESCRIPTION: -** A type for representing the size of objects. -************************************************************************/ -typedef size_t JSSize; - -/************************************************************************ -** TYPES: JSPtrDiff -** DESCRIPTION: -** A type for pointer difference. Variables of this type are suitable -** for storing a pointer or pointer sutraction. -************************************************************************/ -typedef ptrdiff_t JSPtrdiff; - -/************************************************************************ -** TYPES: JSUptrdiff -** DESCRIPTION: -** A type for pointer difference. Variables of this type are suitable -** for storing a pointer or pointer sutraction. -************************************************************************/ -typedef unsigned long JSUptrdiff; - -/************************************************************************ -** TYPES: JSBool -** DESCRIPTION: -** Use JSBool for variables and parameter types. Use JS_FALSE and JS_TRUE -** for clarity of target type in assignments and actual arguments. Use -** 'if (bool)', 'while (!bool)', '(bool) ? x : y' etc., to test booleans -** just as you would C int-valued conditions. -************************************************************************/ -typedef JSIntn JSBool; -#define JS_TRUE (JSIntn)1 -#define JS_FALSE (JSIntn)0 - -/************************************************************************ -** TYPES: JSPackedBool -** DESCRIPTION: -** Use JSPackedBool within structs where bitfields are not desireable -** but minimum and consistant overhead matters. -************************************************************************/ -typedef JSUint8 JSPackedBool; - -/* -** A JSWord is an integer that is the same size as a void* -*/ -typedef long JSWord; -typedef unsigned long JSUword; - -#include "jsotypes.h" - -/*********************************************************************** -** MACROS: JS_LIKELY -** JS_UNLIKELY -** DESCRIPTION: -** These macros allow you to give a hint to the compiler about branch -** probability so that it can better optimize. Use them like this: -** -** if (JS_LIKELY(v == 1)) { -** ... expected code path ... -** } -** -** if (JS_UNLIKELY(v == 0)) { -** ... non-expected code path ... -** } -** -***********************************************************************/ -#if defined(__GNUC__) && (__GNUC__ > 2) -#define JS_LIKELY(x) (__builtin_expect((x), 1)) -#define JS_UNLIKELY(x) (__builtin_expect((x), 0)) -#else -#define JS_LIKELY(x) (x) -#define JS_UNLIKELY(x) (x) -#endif - -JS_END_EXTERN_C - -#endif /* jstypes_h___ */ diff --git a/lib/javascript/jsutil.c b/lib/javascript/jsutil.c deleted file mode 100644 index d7fab0f8..00000000 --- a/lib/javascript/jsutil.c +++ /dev/null @@ -1,192 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * IBM Corp. - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * PR assertion checker. - */ -#include "jsstddef.h" -#include -#include -#include "jstypes.h" -#include "jsutil.h" - -#ifdef WIN32 -# include -#endif - -JS_PUBLIC_API(void) JS_Assert(const char *s, const char *file, JSIntn ln) -{ - fprintf(stderr, "Assertion failure: %s, at %s:%d\n", s, file, ln); -#if defined(WIN32) - DebugBreak(); - exit(3); -#endif -#if defined(XP_OS2) - asm("int $3"); -#endif - abort(); -} - -#if defined DEBUG_notme && defined XP_UNIX - -#define __USE_GNU 1 -#include -#include -#include -#include "jshash.h" -#include "jsprf.h" - -JSCallsite js_calltree_root = {0, NULL, NULL, 0, NULL, NULL, NULL, NULL}; - -static JSCallsite * -CallTree(uint32 *bp) -{ - uint32 *bpup, *bpdown, pc; - JSCallsite *parent, *site, **csp; - Dl_info info; - int ok, offset; - const char *symbol; - char *method; - - /* Reverse the stack frame list to avoid recursion. */ - bpup = NULL; - for (;;) { - bpdown = (uint32*) bp[0]; - bp[0] = (uint32) bpup; - if ((uint32*) bpdown[0] < bpdown) - break; - bpup = bp; - bp = bpdown; - } - - /* Reverse the stack again, finding and building a path in the tree. */ - parent = &js_calltree_root; - do { - bpup = (uint32*) bp[0]; - bp[0] = (uint32) bpdown; - pc = bp[1]; - - csp = &parent->kids; - while ((site = *csp) != NULL) { - if (site->pc == pc) { - /* Put the most recently used site at the front of siblings. */ - *csp = site->siblings; - site->siblings = parent->kids; - parent->kids = site; - - /* Site already built -- go up the stack. */ - goto upward; - } - csp = &site->siblings; - } - - /* Check for recursion: see if pc is on our ancestor line. */ - for (site = parent; site; site = site->parent) { - if (site->pc == pc) - goto upward; - } - - /* - * Not in tree at all: let's find our symbolic callsite info. - * XXX static syms are masked by nearest lower global - */ - info.dli_fname = info.dli_sname = NULL; - ok = dladdr((void*) pc, &info); - if (ok < 0) { - fprintf(stderr, "dladdr failed!\n"); - return NULL; - } - -/* XXXbe sub 0x08040000? or something, see dbaron bug with tenthumbs comment */ - symbol = info.dli_sname; - offset = (char*)pc - (char*)info.dli_fbase; - method = symbol - ? strdup(symbol) - : JS_smprintf("%s+%X", - info.dli_fname ? info.dli_fname : "main", - offset); - if (!method) - return NULL; - - /* Create a new callsite record. */ - site = (JSCallsite *) malloc(sizeof(JSCallsite)); - if (!site) - return NULL; - - /* Insert the new site into the tree. */ - site->pc = pc; - site->name = method; - site->library = info.dli_fname; - site->offset = offset; - site->parent = parent; - site->siblings = parent->kids; - parent->kids = site; - site->kids = NULL; - - upward: - parent = site; - bpdown = bp; - bp = bpup; - } while (bp); - - return site; -} - -JSCallsite * -JS_Backtrace(int skip) -{ - jmp_buf jb; - uint32 *bp, *bpdown; - - setjmp(jb); - - /* Stack walking code adapted from Kipp's "leaky". */ - bp = (uint32*) jb[0].__jmpbuf[JB_BP]; - while (--skip >= 0) { - bpdown = (uint32*) *bp++; - if (bpdown < bp) - break; - bp = bpdown; - } - - return CallTree(bp); -} - -#endif /* DEBUG_notme && XP_UNIX */ diff --git a/lib/javascript/jsutil.h b/lib/javascript/jsutil.h deleted file mode 100644 index 5e26c16a..00000000 --- a/lib/javascript/jsutil.h +++ /dev/null @@ -1,94 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * PR assertion checker. - */ - -#ifndef jsutil_h___ -#define jsutil_h___ - -JS_BEGIN_EXTERN_C - -#ifdef DEBUG - -extern JS_PUBLIC_API(void) -JS_Assert(const char *s, const char *file, JSIntn ln); -#define JS_ASSERT(_expr) \ - ((_expr)?((void)0):JS_Assert(# _expr,__FILE__,__LINE__)) - -#define JS_NOT_REACHED(_reasonStr) \ - JS_Assert(_reasonStr,__FILE__,__LINE__) - -#else - -#define JS_ASSERT(expr) ((void) 0) -#define JS_NOT_REACHED(reasonStr) - -#endif /* defined(DEBUG) */ - -/* -** Abort the process in a non-graceful manner. This will cause a core file, -** call to the debugger or other moral equivalent as well as causing the -** entire process to stop. -*/ -extern JS_PUBLIC_API(void) JS_Abort(void); - -#ifdef XP_UNIX - -typedef struct JSCallsite JSCallsite; - -struct JSCallsite { - uint32 pc; - char *name; - const char *library; - int offset; - JSCallsite *parent; - JSCallsite *siblings; - JSCallsite *kids; - void *handy; -}; - -extern JSCallsite *JS_Backtrace(int skip); - -#endif - -JS_END_EXTERN_C - -#endif /* jsutil_h___ */ diff --git a/lib/javascript/jsxdrapi.c b/lib/javascript/jsxdrapi.c deleted file mode 100644 index 0c9aecee..00000000 --- a/lib/javascript/jsxdrapi.c +++ /dev/null @@ -1,686 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -#include "jsstddef.h" -#include "jsconfig.h" - -#if JS_HAS_XDR - -#include -#include "jstypes.h" -#include "jsutil.h" /* Added by JSIFY */ -#include "jsdhash.h" -#include "jsprf.h" -#include "jsapi.h" -#include "jscntxt.h" -#include "jsnum.h" -#include "jsobj.h" /* js_XDRObject */ -#include "jsscript.h" /* js_XDRScript */ -#include "jsstr.h" -#include "jsxdrapi.h" - -#ifdef DEBUG -#define DBG(x) x -#else -#define DBG(x) ((void)0) -#endif - -typedef struct JSXDRMemState { - JSXDRState state; - char *base; - uint32 count; - uint32 limit; -} JSXDRMemState; - -#define MEM_BLOCK 8192 -#define MEM_PRIV(xdr) ((JSXDRMemState *)(xdr)) - -#define MEM_BASE(xdr) (MEM_PRIV(xdr)->base) -#define MEM_COUNT(xdr) (MEM_PRIV(xdr)->count) -#define MEM_LIMIT(xdr) (MEM_PRIV(xdr)->limit) - -#define MEM_LEFT(xdr, bytes) \ - JS_BEGIN_MACRO \ - if ((xdr)->mode == JSXDR_DECODE && \ - MEM_COUNT(xdr) + bytes > MEM_LIMIT(xdr)) { \ - JS_ReportErrorNumber((xdr)->cx, js_GetErrorMessage, NULL, \ - JSMSG_END_OF_DATA); \ - return 0; \ - } \ - JS_END_MACRO - -#define MEM_NEED(xdr, bytes) \ - JS_BEGIN_MACRO \ - if ((xdr)->mode == JSXDR_ENCODE) { \ - if (MEM_LIMIT(xdr) && \ - MEM_COUNT(xdr) + bytes > MEM_LIMIT(xdr)) { \ - uint32 limit_ = JS_ROUNDUP(MEM_COUNT(xdr) + bytes, MEM_BLOCK);\ - void *data_ = JS_realloc((xdr)->cx, MEM_BASE(xdr), limit_); \ - if (!data_) \ - return 0; \ - MEM_BASE(xdr) = data_; \ - MEM_LIMIT(xdr) = limit_; \ - } \ - } else { \ - MEM_LEFT(xdr, bytes); \ - } \ - JS_END_MACRO - -#define MEM_DATA(xdr) ((void *)(MEM_BASE(xdr) + MEM_COUNT(xdr))) -#define MEM_INCR(xdr,bytes) (MEM_COUNT(xdr) += (bytes)) - -static JSBool -mem_get32(JSXDRState *xdr, uint32 *lp) -{ - MEM_LEFT(xdr, 4); - *lp = *(uint32 *)MEM_DATA(xdr); - MEM_INCR(xdr, 4); - return JS_TRUE; -} - -static JSBool -mem_set32(JSXDRState *xdr, uint32 *lp) -{ - MEM_NEED(xdr, 4); - *(uint32 *)MEM_DATA(xdr) = *lp; - MEM_INCR(xdr, 4); - return JS_TRUE; -} - -static JSBool -mem_getbytes(JSXDRState *xdr, char *bytes, uint32 len) -{ - MEM_LEFT(xdr, len); - memcpy(bytes, MEM_DATA(xdr), len); - MEM_INCR(xdr, len); - return JS_TRUE; -} - -static JSBool -mem_setbytes(JSXDRState *xdr, char *bytes, uint32 len) -{ - MEM_NEED(xdr, len); - memcpy(MEM_DATA(xdr), bytes, len); - MEM_INCR(xdr, len); - return JS_TRUE; -} - -static void * -mem_raw(JSXDRState *xdr, uint32 len) -{ - void *data; - if (xdr->mode == JSXDR_ENCODE) { - MEM_NEED(xdr, len); - } else if (xdr->mode == JSXDR_DECODE) { - MEM_LEFT(xdr, len); - } - data = MEM_DATA(xdr); - MEM_INCR(xdr, len); - return data; -} - -static JSBool -mem_seek(JSXDRState *xdr, int32 offset, JSXDRWhence whence) -{ - switch (whence) { - case JSXDR_SEEK_CUR: - if ((int32)MEM_COUNT(xdr) + offset < 0) { - JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL, - JSMSG_SEEK_BEYOND_START); - return JS_FALSE; - } - if (offset > 0) - MEM_NEED(xdr, offset); - MEM_COUNT(xdr) += offset; - return JS_TRUE; - case JSXDR_SEEK_SET: - if (offset < 0) { - JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL, - JSMSG_SEEK_BEYOND_START); - return JS_FALSE; - } - if (xdr->mode == JSXDR_ENCODE) { - if ((uint32)offset > MEM_COUNT(xdr)) - MEM_NEED(xdr, offset - MEM_COUNT(xdr)); - MEM_COUNT(xdr) = offset; - } else { - if ((uint32)offset > MEM_LIMIT(xdr)) { - JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL, - JSMSG_SEEK_BEYOND_END); - return JS_FALSE; - } - MEM_COUNT(xdr) = offset; - } - return JS_TRUE; - case JSXDR_SEEK_END: - if (offset >= 0 || - xdr->mode == JSXDR_ENCODE || - (int32)MEM_LIMIT(xdr) + offset < 0) { - JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL, - JSMSG_END_SEEK); - return JS_FALSE; - } - MEM_COUNT(xdr) = MEM_LIMIT(xdr) + offset; - return JS_TRUE; - default: { - char numBuf[12]; - JS_snprintf(numBuf, sizeof numBuf, "%d", whence); - JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL, - JSMSG_WHITHER_WHENCE, numBuf); - return JS_FALSE; - } - } -} - -static uint32 -mem_tell(JSXDRState *xdr) -{ - return MEM_COUNT(xdr); -} - -static void -mem_finalize(JSXDRState *xdr) -{ - JS_free(xdr->cx, MEM_BASE(xdr)); -} - -static JSXDROps xdrmem_ops = { - mem_get32, mem_set32, mem_getbytes, mem_setbytes, - mem_raw, mem_seek, mem_tell, mem_finalize -}; - -JS_PUBLIC_API(void) -JS_XDRInitBase(JSXDRState *xdr, JSXDRMode mode, JSContext *cx) -{ - xdr->mode = mode; - xdr->cx = cx; - xdr->registry = NULL; - xdr->numclasses = xdr->maxclasses = 0; - xdr->reghash = NULL; - xdr->userdata = NULL; -} - -JS_PUBLIC_API(JSXDRState *) -JS_XDRNewMem(JSContext *cx, JSXDRMode mode) -{ - JSXDRState *xdr = (JSXDRState *) JS_malloc(cx, sizeof(JSXDRMemState)); - if (!xdr) - return NULL; - JS_XDRInitBase(xdr, mode, cx); - if (mode == JSXDR_ENCODE) { - if (!(MEM_BASE(xdr) = JS_malloc(cx, MEM_BLOCK))) { - JS_free(cx, xdr); - return NULL; - } - } else { - /* XXXbe ok, so better not deref MEM_BASE(xdr) if not ENCODE */ - MEM_BASE(xdr) = NULL; - } - xdr->ops = &xdrmem_ops; - MEM_COUNT(xdr) = 0; - MEM_LIMIT(xdr) = MEM_BLOCK; - return xdr; -} - -JS_PUBLIC_API(void *) -JS_XDRMemGetData(JSXDRState *xdr, uint32 *lp) -{ - if (xdr->ops != &xdrmem_ops) - return NULL; - *lp = MEM_COUNT(xdr); - return MEM_BASE(xdr); -} - -JS_PUBLIC_API(void) -JS_XDRMemSetData(JSXDRState *xdr, void *data, uint32 len) -{ - if (xdr->ops != &xdrmem_ops) - return; - MEM_LIMIT(xdr) = len; - MEM_BASE(xdr) = data; - MEM_COUNT(xdr) = 0; -} - -JS_PUBLIC_API(uint32) -JS_XDRMemDataLeft(JSXDRState *xdr) -{ - if (xdr->ops != &xdrmem_ops) - return 0; - return MEM_LIMIT(xdr) - MEM_COUNT(xdr); -} - -JS_PUBLIC_API(void) -JS_XDRMemResetData(JSXDRState *xdr) -{ - if (xdr->ops != &xdrmem_ops) - return; - MEM_COUNT(xdr) = 0; -} - -JS_PUBLIC_API(void) -JS_XDRDestroy(JSXDRState *xdr) -{ - JSContext *cx = xdr->cx; - xdr->ops->finalize(xdr); - if (xdr->registry) { - JS_free(cx, xdr->registry); - if (xdr->reghash) - JS_DHashTableDestroy(xdr->reghash); - } - JS_free(cx, xdr); -} - -JS_PUBLIC_API(JSBool) -JS_XDRUint8(JSXDRState *xdr, uint8 *b) -{ - uint32 l = *b; - if (!JS_XDRUint32(xdr, &l)) - return JS_FALSE; - *b = (uint8) l; - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_XDRUint16(JSXDRState *xdr, uint16 *s) -{ - uint32 l = *s; - if (!JS_XDRUint32(xdr, &l)) - return JS_FALSE; - *s = (uint16) l; - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_XDRUint32(JSXDRState *xdr, uint32 *lp) -{ - JSBool ok = JS_TRUE; - if (xdr->mode == JSXDR_ENCODE) { - uint32 xl = JSXDR_SWAB32(*lp); - ok = xdr->ops->set32(xdr, &xl); - } else if (xdr->mode == JSXDR_DECODE) { - ok = xdr->ops->get32(xdr, lp); - *lp = JSXDR_SWAB32(*lp); - } - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_XDRBytes(JSXDRState *xdr, char *bytes, uint32 len) -{ - uint32 padlen; - static char padbuf[JSXDR_ALIGN-1]; - - if (xdr->mode == JSXDR_ENCODE) { - if (!xdr->ops->setbytes(xdr, bytes, len)) - return JS_FALSE; - } else { - if (!xdr->ops->getbytes(xdr, bytes, len)) - return JS_FALSE; - } - len = xdr->ops->tell(xdr); - if (len % JSXDR_ALIGN) { - padlen = JSXDR_ALIGN - (len % JSXDR_ALIGN); - if (xdr->mode == JSXDR_ENCODE) { - if (!xdr->ops->setbytes(xdr, padbuf, padlen)) - return JS_FALSE; - } else { - if (!xdr->ops->seek(xdr, padlen, JSXDR_SEEK_CUR)) - return JS_FALSE; - } - } - return JS_TRUE; -} - -/** - * Convert between a C string and the XDR representation: - * leading 32-bit count, then counted vector of chars, - * then possibly \0 padding to multiple of 4. - */ -JS_PUBLIC_API(JSBool) -JS_XDRCString(JSXDRState *xdr, char **sp) -{ - uint32 len; - - if (xdr->mode == JSXDR_ENCODE) - len = strlen(*sp); - JS_XDRUint32(xdr, &len); - if (xdr->mode == JSXDR_DECODE) { - if (!(*sp = (char *) JS_malloc(xdr->cx, len + 1))) - return JS_FALSE; - } - if (!JS_XDRBytes(xdr, *sp, len)) { - if (xdr->mode == JSXDR_DECODE) - JS_free(xdr->cx, *sp); - return JS_FALSE; - } - if (xdr->mode == JSXDR_DECODE) { - (*sp)[len] = '\0'; - } else if (xdr->mode == JSXDR_FREE) { - JS_free(xdr->cx, *sp); - *sp = NULL; - } - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_XDRCStringOrNull(JSXDRState *xdr, char **sp) -{ - uint32 null = (*sp == NULL); - if (!JS_XDRUint32(xdr, &null)) - return JS_FALSE; - if (null) { - *sp = NULL; - return JS_TRUE; - } - return JS_XDRCString(xdr, sp); -} - -/* - * Convert between a JS (Unicode) string and the XDR representation. - */ -JS_PUBLIC_API(JSBool) -JS_XDRString(JSXDRState *xdr, JSString **strp) -{ - uint32 i, len, padlen, nbytes; - jschar *chars = NULL, *raw; - - if (xdr->mode == JSXDR_ENCODE) - len = JSSTRING_LENGTH(*strp); - if (!JS_XDRUint32(xdr, &len)) - return JS_FALSE; - nbytes = len * sizeof(jschar); - - if (xdr->mode == JSXDR_DECODE) { - if (!(chars = (jschar *) JS_malloc(xdr->cx, nbytes + sizeof(jschar)))) - return JS_FALSE; - } else { - chars = JSSTRING_CHARS(*strp); - } - - padlen = nbytes % JSXDR_ALIGN; - if (padlen) { - padlen = JSXDR_ALIGN - padlen; - nbytes += padlen; - } - if (!(raw = (jschar *) xdr->ops->raw(xdr, nbytes))) - goto bad; - if (xdr->mode == JSXDR_ENCODE) { - for (i = 0; i < len; i++) - raw[i] = JSXDR_SWAB16(chars[i]); - if (padlen) - memset((char *)raw + nbytes - padlen, 0, padlen); - } else if (xdr->mode == JSXDR_DECODE) { - for (i = 0; i < len; i++) - chars[i] = JSXDR_SWAB16(raw[i]); - chars[len] = 0; - - if (!(*strp = JS_NewUCString(xdr->cx, chars, len))) - goto bad; - } - return JS_TRUE; - -bad: - if (xdr->mode == JSXDR_DECODE) - JS_free(xdr->cx, chars); - return JS_FALSE; -} - -JS_PUBLIC_API(JSBool) -JS_XDRStringOrNull(JSXDRState *xdr, JSString **strp) -{ - uint32 null = (*strp == NULL); - if (!JS_XDRUint32(xdr, &null)) - return JS_FALSE; - if (null) { - *strp = NULL; - return JS_TRUE; - } - return JS_XDRString(xdr, strp); -} - -JS_PUBLIC_API(JSBool) -JS_XDRDouble(JSXDRState *xdr, jsdouble **dp) -{ - jsdpun u; - - if (xdr->mode == JSXDR_ENCODE) - u.d = **dp; - if (!JS_XDRUint32(xdr, &u.s.lo) || !JS_XDRUint32(xdr, &u.s.hi)) - return JS_FALSE; - if (xdr->mode == JSXDR_DECODE) { - *dp = JS_NewDouble(xdr->cx, u.d); - if (!*dp) - return JS_FALSE; - } - return JS_TRUE; -} - -/* These are magic pseudo-tags: see jsapi.h, near the top, for real tags. */ -#define JSVAL_XDRNULL 0x8 -#define JSVAL_XDRVOID 0xA - -JS_PUBLIC_API(JSBool) -JS_XDRValue(JSXDRState *xdr, jsval *vp) -{ - uint32 type; - - if (xdr->mode == JSXDR_ENCODE) { - if (JSVAL_IS_NULL(*vp)) - type = JSVAL_XDRNULL; - else if (JSVAL_IS_VOID(*vp)) - type = JSVAL_XDRVOID; - else - type = JSVAL_TAG(*vp); - } - if (!JS_XDRUint32(xdr, &type)) - return JS_FALSE; - - switch (type) { - case JSVAL_XDRNULL: - *vp = JSVAL_NULL; - break; - case JSVAL_XDRVOID: - *vp = JSVAL_VOID; - break; - case JSVAL_STRING: { - JSString *str; - if (xdr->mode == JSXDR_ENCODE) - str = JSVAL_TO_STRING(*vp); - if (!JS_XDRString(xdr, &str)) - return JS_FALSE; - if (xdr->mode == JSXDR_DECODE) - *vp = STRING_TO_JSVAL(str); - break; - } - case JSVAL_DOUBLE: { - jsdouble *dp; - if (xdr->mode == JSXDR_ENCODE) - dp = JSVAL_TO_DOUBLE(*vp); - if (!JS_XDRDouble(xdr, &dp)) - return JS_FALSE; - if (xdr->mode == JSXDR_DECODE) - *vp = DOUBLE_TO_JSVAL(dp); - break; - } - case JSVAL_OBJECT: { - JSObject *obj; - if (xdr->mode == JSXDR_ENCODE) - obj = JSVAL_TO_OBJECT(*vp); - if (!js_XDRObject(xdr, &obj)) - return JS_FALSE; - if (xdr->mode == JSXDR_DECODE) - *vp = OBJECT_TO_JSVAL(obj); - break; - } - case JSVAL_BOOLEAN: { - uint32 b; - if (xdr->mode == JSXDR_ENCODE) - b = (uint32) JSVAL_TO_BOOLEAN(*vp); - if (!JS_XDRUint32(xdr, &b)) - return JS_FALSE; - if (xdr->mode == JSXDR_DECODE) - *vp = BOOLEAN_TO_JSVAL((JSBool) b); - break; - } - default: { - uint32 i; - - JS_ASSERT(type & JSVAL_INT); - if (xdr->mode == JSXDR_ENCODE) - i = (uint32) JSVAL_TO_INT(*vp); - if (!JS_XDRUint32(xdr, &i)) - return JS_FALSE; - if (xdr->mode == JSXDR_DECODE) - *vp = INT_TO_JSVAL((int32) i); - break; - } - } - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_XDRScript(JSXDRState *xdr, JSScript **scriptp) -{ - if (!js_XDRScript(xdr, scriptp, NULL)) - return JS_FALSE; - if (xdr->mode == JSXDR_DECODE) - js_CallNewScriptHook(xdr->cx, *scriptp, NULL); - return JS_TRUE; -} - -#define CLASS_REGISTRY_MIN 8 -#define CLASS_INDEX_TO_ID(i) ((i)+1) -#define CLASS_ID_TO_INDEX(id) ((id)-1) - -typedef struct JSRegHashEntry { - JSDHashEntryHdr hdr; - const char *name; - uint32 index; -} JSRegHashEntry; - -JS_PUBLIC_API(JSBool) -JS_XDRRegisterClass(JSXDRState *xdr, JSClass *clasp, uint32 *idp) -{ - uintN numclasses, maxclasses; - JSClass **registry; - - numclasses = xdr->numclasses; - maxclasses = xdr->maxclasses; - if (numclasses == maxclasses) { - maxclasses = (maxclasses == 0) ? CLASS_REGISTRY_MIN : maxclasses << 1; - registry = (JSClass **) - JS_realloc(xdr->cx, xdr->registry, maxclasses * sizeof(JSClass *)); - if (!registry) - return JS_FALSE; - xdr->registry = registry; - xdr->maxclasses = maxclasses; - } else { - JS_ASSERT(numclasses && numclasses < maxclasses); - registry = xdr->registry; - } - - registry[numclasses] = clasp; - if (xdr->reghash) { - JSRegHashEntry *entry = (JSRegHashEntry *) - JS_DHashTableOperate(xdr->reghash, clasp->name, JS_DHASH_ADD); - if (!entry) { - JS_ReportOutOfMemory(xdr->cx); - return JS_FALSE; - } - entry->name = clasp->name; - entry->index = numclasses; - } - *idp = CLASS_INDEX_TO_ID(numclasses); - xdr->numclasses = ++numclasses; - return JS_TRUE; -} - -JS_PUBLIC_API(uint32) -JS_XDRFindClassIdByName(JSXDRState *xdr, const char *name) -{ - uintN i, numclasses; - - numclasses = xdr->numclasses; - if (numclasses >= 10) { - JSRegHashEntry *entry; - - /* Bootstrap reghash from registry on first overpopulated Find. */ - if (!xdr->reghash) { - xdr->reghash = JS_NewDHashTable(JS_DHashGetStubOps(), NULL, - sizeof(JSRegHashEntry), - numclasses); - if (xdr->reghash) { - for (i = 0; i < numclasses; i++) { - JSClass *clasp = xdr->registry[i]; - entry = (JSRegHashEntry *) - JS_DHashTableOperate(xdr->reghash, clasp->name, - JS_DHASH_ADD); - entry->name = clasp->name; - entry->index = i; - } - } - } - - /* If we managed to create reghash, use it for O(1) Find. */ - if (xdr->reghash) { - entry = (JSRegHashEntry *) - JS_DHashTableOperate(xdr->reghash, name, JS_DHASH_LOOKUP); - if (JS_DHASH_ENTRY_IS_BUSY(&entry->hdr)) - return CLASS_INDEX_TO_ID(entry->index); - } - } - - /* Only a few classes, or we couldn't malloc reghash: use linear search. */ - for (i = 0; i < numclasses; i++) { - if (!strcmp(name, xdr->registry[i]->name)) - return CLASS_INDEX_TO_ID(i); - } - return 0; -} - -JS_PUBLIC_API(JSClass *) -JS_XDRFindClassById(JSXDRState *xdr, uint32 id) -{ - uintN i = CLASS_ID_TO_INDEX(id); - - if (i >= xdr->numclasses) - return NULL; - return xdr->registry[i]; -} - -#endif /* JS_HAS_XDR */ diff --git a/lib/javascript/jsxdrapi.h b/lib/javascript/jsxdrapi.h deleted file mode 100644 index 874a62ee..00000000 --- a/lib/javascript/jsxdrapi.h +++ /dev/null @@ -1,193 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jsxdrapi_h___ -#define jsxdrapi_h___ - -/* - * JS external data representation interface API. - * - * The XDR system is comprised of three major parts: - * - * - the state serialization/deserialization APIs, which allow consumers - * of the API to serialize JS runtime state (script bytecodes, atom maps, - * object graphs, etc.) for later restoration. These portions - * are implemented in various appropriate files, such as jsscript.c - * for the script portions and jsobj.c for object state. - * - the callback APIs through which the runtime requests an opaque - * representation of a native object, and through which the runtime - * constructs a live native object from an opaque representation. These - * portions are the responsibility of the native object implementor. - * - utility functions for en/decoding of primitive types, such as - * JSStrings. This portion is implemented in jsxdrapi.c. - * - * Spiritually guided by Sun's XDR, where appropriate. - */ - -#include "jspubtd.h" -#include "jsprvtd.h" - -JS_BEGIN_EXTERN_C - -/* We use little-endian byteorder for all encoded data */ - -#if defined IS_LITTLE_ENDIAN -#define JSXDR_SWAB32(x) x -#define JSXDR_SWAB16(x) x -#elif defined IS_BIG_ENDIAN -#define JSXDR_SWAB32(x) (((uint32)(x) >> 24) | \ - (((uint32)(x) >> 8) & 0xff00) | \ - (((uint32)(x) << 8) & 0xff0000) | \ - ((uint32)(x) << 24)) -#define JSXDR_SWAB16(x) (((uint16)(x) >> 8) | ((uint16)(x) << 8)) -#else -#error "unknown byte order" -#endif - -#define JSXDR_ALIGN 4 - -typedef enum JSXDRMode { - JSXDR_ENCODE, - JSXDR_DECODE, - JSXDR_FREE -} JSXDRMode; - -typedef enum JSXDRWhence { - JSXDR_SEEK_SET, - JSXDR_SEEK_CUR, - JSXDR_SEEK_END -} JSXDRWhence; - -typedef struct JSXDROps { - JSBool (*get32)(JSXDRState *, uint32 *); - JSBool (*set32)(JSXDRState *, uint32 *); - JSBool (*getbytes)(JSXDRState *, char *, uint32); - JSBool (*setbytes)(JSXDRState *, char *, uint32); - void * (*raw)(JSXDRState *, uint32); - JSBool (*seek)(JSXDRState *, int32, JSXDRWhence); - uint32 (*tell)(JSXDRState *); - void (*finalize)(JSXDRState *); -} JSXDROps; - -struct JSXDRState { - JSXDRMode mode; - JSXDROps *ops; - JSContext *cx; - JSClass **registry; - uintN numclasses; - uintN maxclasses; - void *reghash; - void *userdata; -}; - -extern JS_PUBLIC_API(void) -JS_XDRInitBase(JSXDRState *xdr, JSXDRMode mode, JSContext *cx); - -extern JS_PUBLIC_API(JSXDRState *) -JS_XDRNewMem(JSContext *cx, JSXDRMode mode); - -extern JS_PUBLIC_API(void *) -JS_XDRMemGetData(JSXDRState *xdr, uint32 *lp); - -extern JS_PUBLIC_API(void) -JS_XDRMemSetData(JSXDRState *xdr, void *data, uint32 len); - -extern JS_PUBLIC_API(uint32) -JS_XDRMemDataLeft(JSXDRState *xdr); - -extern JS_PUBLIC_API(void) -JS_XDRMemResetData(JSXDRState *xdr); - -extern JS_PUBLIC_API(void) -JS_XDRDestroy(JSXDRState *xdr); - -extern JS_PUBLIC_API(JSBool) -JS_XDRUint8(JSXDRState *xdr, uint8 *b); - -extern JS_PUBLIC_API(JSBool) -JS_XDRUint16(JSXDRState *xdr, uint16 *s); - -extern JS_PUBLIC_API(JSBool) -JS_XDRUint32(JSXDRState *xdr, uint32 *lp); - -extern JS_PUBLIC_API(JSBool) -JS_XDRBytes(JSXDRState *xdr, char *bytes, uint32 len); - -extern JS_PUBLIC_API(JSBool) -JS_XDRCString(JSXDRState *xdr, char **sp); - -extern JS_PUBLIC_API(JSBool) -JS_XDRCStringOrNull(JSXDRState *xdr, char **sp); - -extern JS_PUBLIC_API(JSBool) -JS_XDRString(JSXDRState *xdr, JSString **strp); - -extern JS_PUBLIC_API(JSBool) -JS_XDRStringOrNull(JSXDRState *xdr, JSString **strp); - -extern JS_PUBLIC_API(JSBool) -JS_XDRDouble(JSXDRState *xdr, jsdouble **dp); - -extern JS_PUBLIC_API(JSBool) -JS_XDRValue(JSXDRState *xdr, jsval *vp); - -extern JS_PUBLIC_API(JSBool) -JS_XDRScript(JSXDRState *xdr, JSScript **scriptp); - -extern JS_PUBLIC_API(JSBool) -JS_XDRRegisterClass(JSXDRState *xdr, JSClass *clasp, uint32 *lp); - -extern JS_PUBLIC_API(uint32) -JS_XDRFindClassIdByName(JSXDRState *xdr, const char *name); - -extern JS_PUBLIC_API(JSClass *) -JS_XDRFindClassById(JSXDRState *xdr, uint32 id); - -/* - * Magic numbers. - */ -#define JSXDR_MAGIC_SCRIPT_1 0xdead0001 -#define JSXDR_MAGIC_SCRIPT_2 0xdead0002 -#define JSXDR_MAGIC_SCRIPT_3 0xdead0003 -#define JSXDR_MAGIC_SCRIPT_4 0xdead0004 -#define JSXDR_MAGIC_SCRIPT_CURRENT JSXDR_MAGIC_SCRIPT_4 - -JS_END_EXTERN_C - -#endif /* ! jsxdrapi_h___ */ diff --git a/lib/javascript/jsxml.c b/lib/javascript/jsxml.c deleted file mode 100644 index e7cde2ed..00000000 --- a/lib/javascript/jsxml.c +++ /dev/null @@ -1,8295 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=4 sw=4 et tw=78: - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is SpiderMonkey E4X code, released August, 2004. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "jsstddef.h" -#include "jsconfig.h" - -#if JS_HAS_XML_SUPPORT - -#include -#include -#include -#include "jstypes.h" -#include "jsbit.h" -#include "jsprf.h" -#include "jsutil.h" -#include "jsapi.h" -#include "jsarray.h" -#include "jsatom.h" -#include "jsbool.h" -#include "jscntxt.h" -#include "jsfun.h" -#include "jsgc.h" -#include "jsinterp.h" -#include "jslock.h" -#include "jsnum.h" -#include "jsobj.h" -#include "jsopcode.h" -#include "jsparse.h" -#include "jsscan.h" -#include "jsscope.h" -#include "jsscript.h" -#include "jsstr.h" -#include "jsxml.h" - -#ifdef DEBUG -#include /* for #ifdef DEBUG memset calls */ -#endif - -/* - * NOTES - * - in the js shell, you must use the -x command line option, or call - * options('xml') before compiling anything that uses XML literals - * - * TODO - * - XXXbe patrol - * - Fuse objects and their JSXML* private data into single GC-things - * - fix function::foo vs. x.(foo == 42) collision using proper namespacing - * - fix the !TCF_HAS_DEFXMLNS optimization in js_FoldConstants - * - JSCLASS_DOCUMENT_OBSERVER support -- live two-way binding to Gecko's DOM! - * - JS_TypeOfValue sure could use a cleaner interface to "types" - */ - -#ifdef DEBUG_brendan -#define METERING 1 -#endif - -#ifdef METERING -static struct { - jsrefcount qname; - jsrefcount qnameobj; - jsrefcount liveqname; - jsrefcount liveqnameobj; - jsrefcount namespace; - jsrefcount namespaceobj; - jsrefcount livenamespace; - jsrefcount livenamespaceobj; - jsrefcount xml; - jsrefcount xmlobj; - jsrefcount livexml; - jsrefcount livexmlobj; -} xml_stats; - -#define METER(x) JS_ATOMIC_INCREMENT(&(x)) -#define UNMETER(x) JS_ATOMIC_DECREMENT(&(x)) -#else -#define METER(x) /* nothing */ -#define UNMETER(x) /* nothing */ -#endif - -/* - * Random utilities and global functions. - */ -const char js_AnyName_str[] = "AnyName"; -const char js_AttributeName_str[] = "AttributeName"; -const char js_isXMLName_str[] = "isXMLName"; -const char js_XMLList_str[] = "XMLList"; -const char js_localName_str[] = "localName"; -const char js_xml_parent_str[] = "parent"; -const char js_prefix_str[] = "prefix"; -const char js_toXMLString_str[] = "toXMLString"; -const char js_uri_str[] = "uri"; - -const char js_amp_entity_str[] = "&"; -const char js_gt_entity_str[] = ">"; -const char js_lt_entity_str[] = "<"; -const char js_quot_entity_str[] = """; - -#define IS_EMPTY(str) (JSSTRING_LENGTH(str) == 0) -#define IS_STAR(str) (JSSTRING_LENGTH(str) == 1 && *JSSTRING_CHARS(str) == '*') - -static JSBool -xml_isXMLName(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - *rval = BOOLEAN_TO_JSVAL(js_IsXMLName(cx, argv[0])); - return JS_TRUE; -} - -/* - * Namespace class and library functions. - */ -enum namespace_tinyid { - NAMESPACE_PREFIX = -1, - NAMESPACE_URI = -2 -}; - -static JSBool -namespace_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - JSXMLNamespace *ns; - - if (!JSVAL_IS_INT(id)) - return JS_TRUE; - - ns = (JSXMLNamespace *) - JS_GetInstancePrivate(cx, obj, &js_NamespaceClass.base, NULL); - if (!ns) - return JS_TRUE; - - switch (JSVAL_TO_INT(id)) { - case NAMESPACE_PREFIX: - *vp = ns->prefix ? STRING_TO_JSVAL(ns->prefix) : JSVAL_VOID; - break; - case NAMESPACE_URI: - *vp = STRING_TO_JSVAL(ns->uri); - break; - } - return JS_TRUE; -} - -static void -namespace_finalize(JSContext *cx, JSObject *obj) -{ - JSXMLNamespace *ns; - JSRuntime *rt; - - ns = (JSXMLNamespace *) JS_GetPrivate(cx, obj); - if (!ns) - return; - JS_ASSERT(ns->object == obj); - ns->object = NULL; - UNMETER(xml_stats.livenamespaceobj); - - rt = cx->runtime; - if (rt->functionNamespaceObject == obj) - rt->functionNamespaceObject = NULL; -} - -static void -namespace_mark_vector(JSContext *cx, JSXMLNamespace **vec, uint32 len, - void *arg) -{ - uint32 i; - JSXMLNamespace *ns; - - for (i = 0; i < len; i++) { - ns = vec[i]; - { -#ifdef GC_MARK_DEBUG - char buf[100]; - - JS_snprintf(buf, sizeof buf, "%s=%s", - ns->prefix ? JS_GetStringBytes(ns->prefix) : "", - JS_GetStringBytes(ns->uri)); -#else - const char *buf = NULL; -#endif - JS_MarkGCThing(cx, ns, buf, arg); - } - } -} - -static uint32 -namespace_mark(JSContext *cx, JSObject *obj, void *arg) -{ - JSXMLNamespace *ns; - - ns = (JSXMLNamespace *) JS_GetPrivate(cx, obj); - JS_MarkGCThing(cx, ns, js_private_str, arg); - return 0; -} - -static JSBool -namespace_equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp) -{ - JSXMLNamespace *ns, *ns2; - JSObject *obj2; - - ns = (JSXMLNamespace *) JS_GetPrivate(cx, obj); - JS_ASSERT(JSVAL_IS_OBJECT(v)); - obj2 = JSVAL_TO_OBJECT(v); - if (!obj2 || OBJ_GET_CLASS(cx, obj2) != &js_NamespaceClass.base) { - *bp = JS_FALSE; - } else { - ns2 = (JSXMLNamespace *) JS_GetPrivate(cx, obj2); - *bp = !js_CompareStrings(ns->uri, ns2->uri); - } - return JS_TRUE; -} - -JS_FRIEND_DATA(JSExtendedClass) js_NamespaceClass = { - { "Namespace", - JSCLASS_HAS_PRIVATE | JSCLASS_CONSTRUCT_PROTOTYPE | JSCLASS_IS_EXTENDED, - JS_PropertyStub, JS_PropertyStub, namespace_getProperty, NULL, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, namespace_finalize, - NULL, NULL, NULL, NULL, - NULL, NULL, namespace_mark, NULL }, - namespace_equality, - NULL, NULL, - JSCLASS_NO_RESERVED_MEMBERS -}; - -#define NAMESPACE_ATTRS \ - (JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED) - -static JSPropertySpec namespace_props[] = { - {js_prefix_str, NAMESPACE_PREFIX, NAMESPACE_ATTRS, 0, 0}, - {js_uri_str, NAMESPACE_URI, NAMESPACE_ATTRS, 0, 0}, - {0,0,0,0,0} -}; - -static JSBool -namespace_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSXMLNamespace *ns; - - ns = (JSXMLNamespace *) - JS_GetInstancePrivate(cx, obj, &js_NamespaceClass.base, argv); - if (!ns) - return JS_FALSE; - - *rval = STRING_TO_JSVAL(ns->uri); - return JS_TRUE; -} - -static JSFunctionSpec namespace_methods[] = { - {js_toString_str, namespace_toString, 0,0,0}, - {0,0,0,0,0} -}; - -JSXMLNamespace * -js_NewXMLNamespace(JSContext *cx, JSString *prefix, JSString *uri, - JSBool declared) -{ - JSXMLNamespace *ns; - - ns = (JSXMLNamespace *) - js_NewGCThing(cx, GCX_NAMESPACE, sizeof(JSXMLNamespace)); - if (!ns) - return NULL; - ns->object = NULL; - ns->prefix = prefix; - ns->uri = uri; - ns->declared = declared; - METER(xml_stats.namespace); - METER(xml_stats.livenamespace); - return ns; -} - -void -js_MarkXMLNamespace(JSContext *cx, JSXMLNamespace *ns, void *arg) -{ - JS_MarkGCThing(cx, ns->object, js_object_str, arg); - JS_MarkGCThing(cx, ns->prefix, js_prefix_str, arg); - JS_MarkGCThing(cx, ns->uri, js_uri_str, arg); -} - -void -js_FinalizeXMLNamespace(JSContext *cx, JSXMLNamespace *ns) -{ - UNMETER(xml_stats.livenamespace); -} - -JSObject * -js_NewXMLNamespaceObject(JSContext *cx, JSString *prefix, JSString *uri, - JSBool declared) -{ - JSXMLNamespace *ns; - - ns = js_NewXMLNamespace(cx, prefix, uri, declared); - if (!ns) - return NULL; - return js_GetXMLNamespaceObject(cx, ns); -} - -JSObject * -js_GetXMLNamespaceObject(JSContext *cx, JSXMLNamespace *ns) -{ - JSObject *obj; - - obj = ns->object; - if (obj) { - JS_ASSERT(JS_GetPrivate(cx, obj) == ns); - return obj; - } - obj = js_NewObject(cx, &js_NamespaceClass.base, NULL, NULL); - if (!obj || !JS_SetPrivate(cx, obj, ns)) { - cx->newborn[GCX_OBJECT] = NULL; - return NULL; - } - ns->object = obj; - METER(xml_stats.namespaceobj); - METER(xml_stats.livenamespaceobj); - return obj; -} - -/* - * QName class and library functions. - */ -enum qname_tinyid { - QNAME_URI = -1, - QNAME_LOCALNAME = -2 -}; - -static JSBool -qname_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - JSXMLQName *qn; - - if (!JSVAL_IS_INT(id)) - return JS_TRUE; - - qn = (JSXMLQName *) - JS_GetInstancePrivate(cx, obj, &js_QNameClass.base, NULL); - if (!qn) - return JS_TRUE; - - switch (JSVAL_TO_INT(id)) { - case QNAME_URI: - *vp = qn->uri ? STRING_TO_JSVAL(qn->uri) : JSVAL_NULL; - break; - case QNAME_LOCALNAME: - *vp = STRING_TO_JSVAL(qn->localName); - break; - } - return JS_TRUE; -} - -static void -qname_finalize(JSContext *cx, JSObject *obj) -{ - JSXMLQName *qn; - - qn = (JSXMLQName *) JS_GetPrivate(cx, obj); - if (!qn) - return; - JS_ASSERT(qn->object == obj); - qn->object = NULL; - UNMETER(xml_stats.liveqnameobj); -} - -static void -anyname_finalize(JSContext* cx, JSObject* obj) -{ - JSRuntime *rt; - - /* Make sure the next call to js_GetAnyName doesn't try to use obj. */ - rt = cx->runtime; - if (rt->anynameObject == obj) - rt->anynameObject = NULL; - - qname_finalize(cx, obj); -} - -static uint32 -qname_mark(JSContext *cx, JSObject *obj, void *arg) -{ - JSXMLQName *qn; - - qn = (JSXMLQName *) JS_GetPrivate(cx, obj); - JS_MarkGCThing(cx, qn, js_private_str, arg); - return 0; -} - -static JSBool -qname_identity(JSXMLQName *qna, JSXMLQName *qnb) -{ - if (!qna->uri ^ !qnb->uri) - return JS_FALSE; - if (qna->uri && js_CompareStrings(qna->uri, qnb->uri)) - return JS_FALSE; - return !js_CompareStrings(qna->localName, qnb->localName); -} - -static JSBool -qname_equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp) -{ - JSXMLQName *qn, *qn2; - JSObject *obj2; - - qn = (JSXMLQName *) JS_GetPrivate(cx, obj); - JS_ASSERT(JSVAL_IS_OBJECT(v)); - obj2 = JSVAL_TO_OBJECT(v); - if (!obj2 || OBJ_GET_CLASS(cx, obj2) != &js_QNameClass.base) { - *bp = JS_FALSE; - } else { - qn2 = (JSXMLQName *) JS_GetPrivate(cx, obj2); - *bp = qname_identity(qn, qn2); - } - return JS_TRUE; -} - -JS_FRIEND_DATA(JSExtendedClass) js_QNameClass = { - { "QName", - JSCLASS_HAS_PRIVATE | JSCLASS_CONSTRUCT_PROTOTYPE | JSCLASS_IS_EXTENDED, - JS_PropertyStub, JS_PropertyStub, qname_getProperty, NULL, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, qname_finalize, - NULL, NULL, NULL, NULL, - NULL, NULL, qname_mark, NULL }, - qname_equality, - NULL, NULL, - JSCLASS_NO_RESERVED_MEMBERS -}; - -/* - * Classes for the ECMA-357-internal types AttributeName and AnyName, which - * are like QName, except that they have no property getters. They share the - * qname_toString method, and therefore are exposed as constructable objects - * in this implementation. - */ -JS_FRIEND_DATA(JSClass) js_AttributeNameClass = { - js_AttributeName_str, JSCLASS_HAS_PRIVATE | JSCLASS_CONSTRUCT_PROTOTYPE, - JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, qname_finalize, - NULL, NULL, NULL, NULL, - NULL, NULL, qname_mark, NULL -}; - -JS_FRIEND_DATA(JSClass) js_AnyNameClass = { - js_AnyName_str, JSCLASS_HAS_PRIVATE | JSCLASS_CONSTRUCT_PROTOTYPE, - JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, anyname_finalize, - NULL, NULL, NULL, NULL, - NULL, NULL, qname_mark, NULL -}; - -#define QNAME_ATTRS \ - (JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED) - -static JSPropertySpec qname_props[] = { - {js_uri_str, QNAME_URI, QNAME_ATTRS, 0, 0}, - {js_localName_str, QNAME_LOCALNAME, QNAME_ATTRS, 0, 0}, - {0,0,0,0,0} -}; - -static JSBool -qname_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSClass *clasp; - JSXMLQName *qn; - JSString *str, *qualstr; - size_t length; - jschar *chars; - - clasp = OBJ_GET_CLASS(cx, obj); - if (clasp == &js_AttributeNameClass || clasp == &js_AnyNameClass) { - qn = (JSXMLQName *) JS_GetPrivate(cx, obj); - } else { - qn = (JSXMLQName *) - JS_GetInstancePrivate(cx, obj, &js_QNameClass.base, argv); - if (!qn) - return JS_FALSE; - } - - if (!qn->uri) { - /* No uri means wildcard qualifier. */ - str = ATOM_TO_STRING(cx->runtime->atomState.starQualifierAtom); - } else if (IS_EMPTY(qn->uri)) { - /* Empty string for uri means localName is in no namespace. */ - str = cx->runtime->emptyString; - } else { - qualstr = ATOM_TO_STRING(cx->runtime->atomState.qualifierAtom); - str = js_ConcatStrings(cx, qn->uri, qualstr); - if (!str) - return JS_FALSE; - } - str = js_ConcatStrings(cx, str, qn->localName); - if (!str) - return JS_FALSE; - - if (str && clasp == &js_AttributeNameClass) { - length = JSSTRING_LENGTH(str); - chars = (jschar *) JS_malloc(cx, (length + 2) * sizeof(jschar)); - if (!chars) - return JS_FALSE; - *chars = '@'; - js_strncpy(chars + 1, JSSTRING_CHARS(str), length); - chars[++length] = 0; - str = js_NewString(cx, chars, length, 0); - if (!str) { - JS_free(cx, chars); - return JS_FALSE; - } - } - - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -static JSFunctionSpec qname_methods[] = { - {js_toString_str, qname_toString, 0,0,0}, - {0,0,0,0,0} -}; - -JSXMLQName * -js_NewXMLQName(JSContext *cx, JSString *uri, JSString *prefix, - JSString *localName) -{ - JSXMLQName *qn; - - qn = (JSXMLQName *) js_NewGCThing(cx, GCX_QNAME, sizeof(JSXMLQName)); - if (!qn) - return NULL; - qn->object = NULL; - qn->uri = uri; - qn->prefix = prefix; - qn->localName = localName; - METER(xml_stats.qname); - METER(xml_stats.liveqname); - return qn; -} - -void -js_MarkXMLQName(JSContext *cx, JSXMLQName *qn, void *arg) -{ - JS_MarkGCThing(cx, qn->object, js_object_str, arg); - JS_MarkGCThing(cx, qn->uri, js_uri_str, arg); - JS_MarkGCThing(cx, qn->prefix, js_prefix_str, arg); - JS_MarkGCThing(cx, qn->localName, js_localName_str, arg); -} - -void -js_FinalizeXMLQName(JSContext *cx, JSXMLQName *qn) -{ - UNMETER(xml_stats.liveqname); -} - -JSObject * -js_NewXMLQNameObject(JSContext *cx, JSString *uri, JSString *prefix, - JSString *localName) -{ - JSXMLQName *qn; - - qn = js_NewXMLQName(cx, uri, prefix, localName); - if (!qn) - return NULL; - return js_GetXMLQNameObject(cx, qn); -} - -JSObject * -js_GetXMLQNameObject(JSContext *cx, JSXMLQName *qn) -{ - JSObject *obj; - - obj = qn->object; - if (obj) { - JS_ASSERT(JS_GetPrivate(cx, obj) == qn); - return obj; - } - obj = js_NewObject(cx, &js_QNameClass.base, NULL, NULL); - if (!obj || !JS_SetPrivate(cx, obj, qn)) { - cx->newborn[GCX_OBJECT] = NULL; - return NULL; - } - qn->object = obj; - METER(xml_stats.qnameobj); - METER(xml_stats.liveqnameobj); - return obj; -} - -JSObject * -js_GetAttributeNameObject(JSContext *cx, JSXMLQName *qn) -{ - JSObject *obj; - - obj = qn->object; - if (obj) { - if (OBJ_GET_CLASS(cx, obj) == &js_AttributeNameClass) - return obj; - qn = js_NewXMLQName(cx, qn->uri, qn->prefix, qn->localName); - if (!qn) - return NULL; - } - - obj = js_NewObject(cx, &js_AttributeNameClass, NULL, NULL); - if (!obj || !JS_SetPrivate(cx, obj, qn)) { - cx->newborn[GCX_OBJECT] = NULL; - return NULL; - } - - qn->object = obj; - METER(xml_stats.qnameobj); - METER(xml_stats.liveqnameobj); - return obj; -} - -JSObject * -js_ConstructXMLQNameObject(JSContext *cx, jsval nsval, jsval lnval) -{ - jsval argv[2]; - - /* - * ECMA-357 11.1.2, - * The _QualifiedIdentifier : PropertySelector :: PropertySelector_ - * production, step 2. - */ - if (!JSVAL_IS_PRIMITIVE(nsval) && - OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(nsval)) == &js_AnyNameClass) { - nsval = JSVAL_NULL; - } - - argv[0] = nsval; - argv[1] = lnval; - return js_ConstructObject(cx, &js_QNameClass.base, NULL, NULL, 2, argv); -} - -static JSBool -IsXMLName(const jschar *cp, size_t n) -{ - JSBool rv; - jschar c; - - rv = JS_FALSE; - if (n != 0 && JS_ISXMLNSSTART(*cp)) { - while (--n != 0) { - c = *++cp; - if (!JS_ISXMLNS(c)) - return rv; - } - rv = JS_TRUE; - } - return rv; -} - -JSBool -js_IsXMLName(JSContext *cx, jsval v) -{ - JSClass *clasp; - JSXMLQName *qn; - JSString *name; - JSErrorReporter older; - - /* - * Inline specialization of the QName constructor called with v passed as - * the only argument, to compute the localName for the constructed qname, - * without actually allocating the object or computing its uri and prefix. - * See ECMA-357 13.1.2.1 step 1 and 13.3.2. - */ - if (!JSVAL_IS_PRIMITIVE(v) && - (clasp = OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(v)), - clasp == &js_QNameClass.base || - clasp == &js_AttributeNameClass || - clasp == &js_AnyNameClass)) { - qn = (JSXMLQName *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v)); - name = qn->localName; - } else { - older = JS_SetErrorReporter(cx, NULL); - name = js_ValueToString(cx, v); - JS_SetErrorReporter(cx, older); - if (!name) { - JS_ClearPendingException(cx); - return JS_FALSE; - } - } - - return IsXMLName(JSSTRING_CHARS(name), JSSTRING_LENGTH(name)); -} - -static JSBool -Namespace(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsval urival, prefixval; - JSObject *uriobj; - JSBool isNamespace, isQName; - JSClass *clasp; - JSString *empty, *prefix; - JSXMLNamespace *ns, *ns2; - JSXMLQName *qn; - - urival = argv[argc > 1]; - isNamespace = isQName = JS_FALSE; - if (!JSVAL_IS_PRIMITIVE(urival)) { - uriobj = JSVAL_TO_OBJECT(urival); - clasp = OBJ_GET_CLASS(cx, uriobj); - isNamespace = (clasp == &js_NamespaceClass.base); - isQName = (clasp == &js_QNameClass.base); - } -#ifdef __GNUC__ /* suppress bogus gcc warnings */ - else uriobj = NULL; -#endif - - if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) { - /* Namespace called as function. */ - if (argc == 1 && isNamespace) { - /* Namespace called with one Namespace argument is identity. */ - *rval = urival; - return JS_TRUE; - } - - /* Create and return a new QName object exactly as if constructed. */ - obj = js_NewObject(cx, &js_NamespaceClass.base, NULL, NULL); - if (!obj) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(obj); - } - METER(xml_stats.namespaceobj); - METER(xml_stats.livenamespaceobj); - - /* - * Create and connect private data to rooted obj early, so we don't have - * to worry about rooting string newborns hanging off of the private data - * further below. - */ - empty = cx->runtime->emptyString; - ns = js_NewXMLNamespace(cx, empty, empty, JS_FALSE); - if (!ns) - return JS_FALSE; - if (!JS_SetPrivate(cx, obj, ns)) - return JS_FALSE; - ns->object = obj; - - if (argc == 1) { - if (isNamespace) { - ns2 = (JSXMLNamespace *) JS_GetPrivate(cx, uriobj); - ns->uri = ns2->uri; - ns->prefix = ns2->prefix; - } else if (isQName && - (qn = (JSXMLQName *) JS_GetPrivate(cx, uriobj))->uri) { - ns->uri = qn->uri; - ns->prefix = qn->prefix; - } else { - ns->uri = js_ValueToString(cx, urival); - if (!ns->uri) - return JS_FALSE; - - /* NULL here represents *undefined* in ECMA-357 13.2.2 3(c)iii. */ - if (!IS_EMPTY(ns->uri)) - ns->prefix = NULL; - } - } else if (argc == 2) { - if (isQName && - (qn = (JSXMLQName *) JS_GetPrivate(cx, uriobj))->uri) { - ns->uri = qn->uri; - } else { - ns->uri = js_ValueToString(cx, urival); - if (!ns->uri) - return JS_FALSE; - } - - prefixval = argv[0]; - if (IS_EMPTY(ns->uri)) { - if (!JSVAL_IS_VOID(prefixval)) { - prefix = js_ValueToString(cx, prefixval); - if (!prefix) - return JS_FALSE; - if (!IS_EMPTY(prefix)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_XML_NAMESPACE, - js_ValueToPrintableString(cx, - STRING_TO_JSVAL(prefix))); - return JS_FALSE; - } - } - } else if (JSVAL_IS_VOID(prefixval) || !js_IsXMLName(cx, prefixval)) { - /* NULL here represents *undefined* in ECMA-357 13.2.2 4(d) etc. */ - ns->prefix = NULL; - } else { - prefix = js_ValueToString(cx, prefixval); - if (!prefix) - return JS_FALSE; - ns->prefix = prefix; - } - } - - return JS_TRUE; -} - -static JSBool -QName(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsval nameval, nsval; - JSBool isQName, isNamespace; - JSXMLQName *qn; - JSString *uri, *prefix, *name; - JSObject *nsobj; - JSClass *clasp; - JSXMLNamespace *ns; - - nameval = argv[argc > 1]; - isQName = - !JSVAL_IS_PRIMITIVE(nameval) && - OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(nameval)) == &js_QNameClass.base; - - if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) { - /* QName called as function. */ - if (argc == 1 && isQName) { - /* QName called with one QName argument is identity. */ - *rval = nameval; - return JS_TRUE; - } - - /* - * Create and return a new QName object exactly as if constructed. - * Use the constructor's clasp so we can be shared by AttributeName - * (see below after this function). - */ - obj = js_NewObject(cx, - argv - ? JS_ValueToFunction(cx, argv[-2])->clasp - : &js_QNameClass.base, - NULL, NULL); - if (!obj) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(obj); - } - METER(xml_stats.qnameobj); - METER(xml_stats.liveqnameobj); - - if (isQName) { - /* If namespace is not specified and name is a QName, clone it. */ - qn = (JSXMLQName *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(nameval)); - if (argc == 1) { - uri = qn->uri; - prefix = qn->prefix; - name = qn->localName; - goto out; - } - - /* Namespace and qname were passed -- use the qname's localName. */ - nameval = STRING_TO_JSVAL(qn->localName); - } - - if (argc == 0) { - name = cx->runtime->emptyString; - } else { - name = js_ValueToString(cx, nameval); - if (!name) - return JS_FALSE; - - /* Use argv[1] as a local root for name, even if it was not passed. */ - argv[1] = STRING_TO_JSVAL(name); - } - - nsval = argv[0]; - if (argc == 1 || JSVAL_IS_VOID(nsval)) { - if (IS_STAR(name)) { - nsval = JSVAL_NULL; - } else { - if (!js_GetDefaultXMLNamespace(cx, &nsval)) - return JS_FALSE; - } - } - - if (JSVAL_IS_NULL(nsval)) { - /* NULL prefix represents *undefined* in ECMA-357 13.3.2 5(a). */ - uri = prefix = NULL; - } else { - /* - * Inline specialization of the Namespace constructor called with - * nsval passed as the only argument, to compute the uri and prefix - * for the constructed namespace, without actually allocating the - * object or computing other members. See ECMA-357 13.3.2 6(a) and - * 13.2.2. - */ - isNamespace = isQName = JS_FALSE; - if (!JSVAL_IS_PRIMITIVE(nsval)) { - nsobj = JSVAL_TO_OBJECT(nsval); - clasp = OBJ_GET_CLASS(cx, nsobj); - isNamespace = (clasp == &js_NamespaceClass.base); - isQName = (clasp == &js_QNameClass.base); - } -#ifdef __GNUC__ /* suppress bogus gcc warnings */ - else nsobj = NULL; -#endif - - if (isNamespace) { - ns = (JSXMLNamespace *) JS_GetPrivate(cx, nsobj); - uri = ns->uri; - prefix = ns->prefix; - } else if (isQName && - (qn = (JSXMLQName *) JS_GetPrivate(cx, nsobj))->uri) { - uri = qn->uri; - prefix = qn->prefix; - } else { - uri = js_ValueToString(cx, nsval); - if (!uri) - return JS_FALSE; - argv[0] = STRING_TO_JSVAL(uri); /* local root */ - - /* NULL here represents *undefined* in ECMA-357 13.2.2 3(c)iii. */ - prefix = IS_EMPTY(uri) ? cx->runtime->emptyString : NULL; - } - } - -out: - qn = js_NewXMLQName(cx, uri, prefix, name); - if (!qn) - return JS_FALSE; - if (!JS_SetPrivate(cx, obj, qn)) - return JS_FALSE; - qn->object = obj; - return JS_TRUE; -} - -static JSBool -AttributeName(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - /* - * Since js_AttributeNameClass was initialized, obj will have that as its - * class, not js_QNameClass. - */ - return QName(cx, obj, argc, argv, rval); -} - -/* - * XMLArray library functions. - */ -static JSBool -namespace_identity(const void *a, const void *b) -{ - const JSXMLNamespace *nsa = (const JSXMLNamespace *) a; - const JSXMLNamespace *nsb = (const JSXMLNamespace *) b; - - if (nsa->prefix && nsb->prefix) { - if (js_CompareStrings(nsa->prefix, nsb->prefix)) - return JS_FALSE; - } else { - if (nsa->prefix || nsb->prefix) - return JS_FALSE; - } - return !js_CompareStrings(nsa->uri, nsb->uri); -} - -static JSBool -attr_identity(const void *a, const void *b) -{ - const JSXML *xmla = (const JSXML *) a; - const JSXML *xmlb = (const JSXML *) b; - - return qname_identity(xmla->name, xmlb->name); -} - -static void -XMLArrayCursorInit(JSXMLArrayCursor *cursor, JSXMLArray *array) -{ - JSXMLArrayCursor *next; - - cursor->array = array; - cursor->index = 0; - next = cursor->next = array->cursors; - if (next) - next->prevp = &cursor->next; - cursor->prevp = &array->cursors; - array->cursors = cursor; - cursor->root = NULL; -} - -static void -XMLArrayCursorFinish(JSXMLArrayCursor *cursor) -{ - JSXMLArrayCursor *next; - - if (!cursor->array) - return; - next = cursor->next; - if (next) - next->prevp = cursor->prevp; - *cursor->prevp = next; - cursor->array = NULL; -} - -static void * -XMLArrayCursorNext(JSXMLArrayCursor *cursor) -{ - JSXMLArray *array; - - array = cursor->array; - if (!array || cursor->index >= array->length) - return NULL; - return cursor->root = array->vector[cursor->index++]; -} - -static void * -XMLArrayCursorItem(JSXMLArrayCursor *cursor) -{ - JSXMLArray *array; - - array = cursor->array; - if (!array || cursor->index >= array->length) - return NULL; - return cursor->root = array->vector[cursor->index]; -} - -static void -XMLArrayCursorMark(JSContext *cx, JSXMLArrayCursor *cursor) -{ - while (cursor) { - GC_MARK(cx, cursor->root, "cursor->root", NULL); - cursor = cursor->next; - } -} - -/* NB: called with null cx from the GC, via xml_mark => XMLArrayTrim. */ -static JSBool -XMLArraySetCapacity(JSContext *cx, JSXMLArray *array, uint32 capacity) -{ - void **vector; - - if (capacity == 0) { - /* We could let realloc(p, 0) free this, but purify gets confused. */ - if (array->vector) - free(array->vector); - vector = NULL; - } else { - if ((size_t)capacity > ~(size_t)0 / sizeof(void *) || - !(vector = (void **) - realloc(array->vector, capacity * sizeof(void *)))) { - if (cx) - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - } - array->capacity = JSXML_PRESET_CAPACITY | capacity; - array->vector = vector; - return JS_TRUE; -} - -static void -XMLArrayTrim(JSXMLArray *array) -{ - if (array->capacity & JSXML_PRESET_CAPACITY) - return; - if (array->length < array->capacity) - XMLArraySetCapacity(NULL, array, array->length); -} - -static JSBool -XMLArrayInit(JSContext *cx, JSXMLArray *array, uint32 capacity) -{ - array->length = array->capacity = 0; - array->vector = NULL; - array->cursors = NULL; - return capacity == 0 || XMLArraySetCapacity(cx, array, capacity); -} - -static void -XMLArrayFinish(JSContext *cx, JSXMLArray *array) -{ - JSXMLArrayCursor *cursor; - - JS_free(cx, array->vector); - - while ((cursor = array->cursors) != NULL) - XMLArrayCursorFinish(cursor); - -#ifdef DEBUG - memset(array, 0xd5, sizeof *array); -#endif -} - -#define XML_NOT_FOUND ((uint32) -1) - -static uint32 -XMLArrayFindMember(const JSXMLArray *array, void *elt, JSIdentityOp identity) -{ - void **vector; - uint32 i, n; - - /* The identity op must not reallocate array->vector. */ - vector = array->vector; - if (identity) { - for (i = 0, n = array->length; i < n; i++) { - if (identity(vector[i], elt)) - return i; - } - } else { - for (i = 0, n = array->length; i < n; i++) { - if (vector[i] == elt) - return i; - } - } - return XML_NOT_FOUND; -} - -/* - * Grow array vector capacity by powers of two to LINEAR_THRESHOLD, and after - * that, grow by LINEAR_INCREMENT. Both must be powers of two, and threshold - * should be greater than increment. - */ -#define LINEAR_THRESHOLD 256 -#define LINEAR_INCREMENT 32 - -static JSBool -XMLArrayAddMember(JSContext *cx, JSXMLArray *array, uint32 index, void *elt) -{ - uint32 capacity, i; - int log2; - void **vector; - - if (index >= array->length) { - if (index >= JSXML_CAPACITY(array)) { - /* Arrange to clear JSXML_PRESET_CAPACITY from array->capacity. */ - capacity = index + 1; - if (index >= LINEAR_THRESHOLD) { - capacity = JS_ROUNDUP(capacity, LINEAR_INCREMENT); - } else { - JS_CEILING_LOG2(log2, capacity); - capacity = JS_BIT(log2); - } - if ((size_t)capacity > ~(size_t)0 / sizeof(void *) || - !(vector = (void **) - realloc(array->vector, capacity * sizeof(void *)))) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - array->capacity = capacity; - array->vector = vector; - for (i = array->length; i < index; i++) - vector[i] = NULL; - } - array->length = index + 1; - } - - array->vector[index] = elt; - return JS_TRUE; -} - -static JSBool -XMLArrayInsert(JSContext *cx, JSXMLArray *array, uint32 i, uint32 n) -{ - uint32 j; - JSXMLArrayCursor *cursor; - - j = array->length; - JS_ASSERT(i <= j); - if (!XMLArraySetCapacity(cx, array, j + n)) - return JS_FALSE; - - array->length = j + n; - JS_ASSERT(n != (uint32)-1); - while (j != i) { - --j; - array->vector[j + n] = array->vector[j]; - } - - for (cursor = array->cursors; cursor; cursor = cursor->next) { - if (cursor->index > i) - cursor->index += n; - } - return JS_TRUE; -} - -static void * -XMLArrayDelete(JSContext *cx, JSXMLArray *array, uint32 index, JSBool compress) -{ - uint32 length; - void **vector, *elt; - JSXMLArrayCursor *cursor; - - length = array->length; - if (index >= length) - return NULL; - - vector = array->vector; - elt = vector[index]; - if (compress) { - while (++index < length) - vector[index-1] = vector[index]; - array->length = length - 1; - array->capacity = JSXML_CAPACITY(array); - } else { - vector[index] = NULL; - } - - for (cursor = array->cursors; cursor; cursor = cursor->next) { - if (cursor->index > index) - --cursor->index; - } - return elt; -} - -static void -XMLArrayTruncate(JSContext *cx, JSXMLArray *array, uint32 length) -{ - void **vector; - - JS_ASSERT(!array->cursors); - if (length >= array->length) - return; - - if (length == 0) { - if (array->vector) - free(array->vector); - vector = NULL; - } else { - vector = realloc(array->vector, length * sizeof(void *)); - if (!vector) - return; - } - - if (array->length > length) - array->length = length; - array->capacity = length; - array->vector = vector; -} - -#define XMLARRAY_FIND_MEMBER(a,e,f) XMLArrayFindMember(a, (void *)(e), f) -#define XMLARRAY_HAS_MEMBER(a,e,f) (XMLArrayFindMember(a, (void *)(e), f) != \ - XML_NOT_FOUND) -#define XMLARRAY_MEMBER(a,i,t) (((i) < (a)->length) \ - ? (t *) (a)->vector[i] \ - : NULL) -#define XMLARRAY_SET_MEMBER(a,i,e) JS_BEGIN_MACRO \ - if ((a)->length <= (i)) \ - (a)->length = (i) + 1; \ - ((a)->vector[i] = (void *)(e)); \ - JS_END_MACRO -#define XMLARRAY_ADD_MEMBER(x,a,i,e)XMLArrayAddMember(x, a, i, (void *)(e)) -#define XMLARRAY_INSERT(x,a,i,n) XMLArrayInsert(x, a, i, n) -#define XMLARRAY_APPEND(x,a,e) XMLARRAY_ADD_MEMBER(x, a, (a)->length, (e)) -#define XMLARRAY_DELETE(x,a,i,c,t) ((t *) XMLArrayDelete(x, a, i, c)) -#define XMLARRAY_TRUNCATE(x,a,n) XMLArrayTruncate(x, a, n) - -/* - * Define XML setting property strings and constants early, so everyone can - * use the same names and their magic numbers (tinyids, flags). - */ -static const char js_ignoreComments_str[] = "ignoreComments"; -static const char js_ignoreProcessingInstructions_str[] - = "ignoreProcessingInstructions"; -static const char js_ignoreWhitespace_str[] = "ignoreWhitespace"; -static const char js_prettyPrinting_str[] = "prettyPrinting"; -static const char js_prettyIndent_str[] = "prettyIndent"; - -/* - * NB: These XML static property tinyids must - * (a) not collide with the generic negative tinyids at the top of jsfun.c; - * (b) index their corresponding xml_static_props array elements. - * Don't change 'em! - */ -enum xml_static_tinyid { - XML_IGNORE_COMMENTS, - XML_IGNORE_PROCESSING_INSTRUCTIONS, - XML_IGNORE_WHITESPACE, - XML_PRETTY_PRINTING, - XML_PRETTY_INDENT -}; - -static JSBool -xml_setting_getter(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - return JS_TRUE; -} - -static JSBool -xml_setting_setter(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - JSBool b; - uint8 flag; - - JS_ASSERT(JSVAL_IS_INT(id)); - if (!js_ValueToBoolean(cx, *vp, &b)) - return JS_FALSE; - - flag = JS_BIT(JSVAL_TO_INT(id)); - if (b) - cx->xmlSettingFlags |= flag; - else - cx->xmlSettingFlags &= ~flag; - return JS_TRUE; -} - -static JSPropertySpec xml_static_props[] = { - {js_ignoreComments_str, XML_IGNORE_COMMENTS, JSPROP_PERMANENT, - xml_setting_getter, xml_setting_setter}, - {js_ignoreProcessingInstructions_str, - XML_IGNORE_PROCESSING_INSTRUCTIONS, JSPROP_PERMANENT, - xml_setting_getter, xml_setting_setter}, - {js_ignoreWhitespace_str, XML_IGNORE_WHITESPACE, JSPROP_PERMANENT, - xml_setting_getter, xml_setting_setter}, - {js_prettyPrinting_str, XML_PRETTY_PRINTING, JSPROP_PERMANENT, - xml_setting_getter, xml_setting_setter}, - {js_prettyIndent_str, XML_PRETTY_INDENT, JSPROP_PERMANENT, - xml_setting_getter, NULL}, - {0,0,0,0,0} -}; - -/* Derive cx->xmlSettingFlags bits from xml_static_props tinyids. */ -#define XSF_IGNORE_COMMENTS JS_BIT(XML_IGNORE_COMMENTS) -#define XSF_IGNORE_PROCESSING_INSTRUCTIONS \ - JS_BIT(XML_IGNORE_PROCESSING_INSTRUCTIONS) -#define XSF_IGNORE_WHITESPACE JS_BIT(XML_IGNORE_WHITESPACE) -#define XSF_PRETTY_PRINTING JS_BIT(XML_PRETTY_PRINTING) -#define XSF_CACHE_VALID JS_BIT(XML_PRETTY_INDENT) - -/* - * Extra, unrelated but necessarily disjoint flag used by ParseNodeToXML. - * This flag means a couple of things: - * - * - The top JSXML created for a parse tree must have an object owning it. - * - * - That the default namespace normally inherited from the temporary - * tag that wraps a runtime-concatenated XML source - * string must, in the case of a precompiled XML object tree, inherit via - * ad-hoc code in ParseNodeToXML. - * - * Because of the second purpose, we name this flag XSF_PRECOMPILED_ROOT. - */ -#define XSF_PRECOMPILED_ROOT (XSF_CACHE_VALID << 1) - -/* Macros for special-casing xml:, xmlns= and xmlns:foo= in ParseNodeToQName. */ -#define IS_XML(str) \ - (JSSTRING_LENGTH(str) == 3 && IS_XML_CHARS(JSSTRING_CHARS(str))) - -#define IS_XMLNS(str) \ - (JSSTRING_LENGTH(str) == 5 && IS_XMLNS_CHARS(JSSTRING_CHARS(str))) - -#define IS_XML_CHARS(chars) \ - (JS_TOLOWER((chars)[0]) == 'x' && \ - JS_TOLOWER((chars)[1]) == 'm' && \ - JS_TOLOWER((chars)[2]) == 'l') - -#define HAS_NS_AFTER_XML(chars) \ - (JS_TOLOWER((chars)[3]) == 'n' && \ - JS_TOLOWER((chars)[4]) == 's') - -#define IS_XMLNS_CHARS(chars) \ - (IS_XML_CHARS(chars) && HAS_NS_AFTER_XML(chars)) - -#define STARTS_WITH_XML(chars,length) \ - (length >= 3 && IS_XML_CHARS(chars)) - -static const char xml_namespace_str[] = "http://www.w3.org/XML/1998/namespace"; -static const char xmlns_namespace_str[] = "http://www.w3.org/2000/xmlns/"; - -static JSXMLQName * -ParseNodeToQName(JSContext *cx, JSParseNode *pn, JSXMLArray *inScopeNSes, - JSBool isAttributeName) -{ - JSString *str, *uri, *prefix, *localName; - size_t length, offset; - const jschar *start, *limit, *colon; - uint32 n; - JSXMLNamespace *ns; - - JS_ASSERT(pn->pn_arity == PN_NULLARY); - str = ATOM_TO_STRING(pn->pn_atom); - length = JSSTRING_LENGTH(str); - start = JSSTRING_CHARS(str); - JS_ASSERT(length != 0 && *start != '@'); - JS_ASSERT(length != 1 || *start != '*'); - - uri = cx->runtime->emptyString; - limit = start + length; - colon = js_strchr_limit(start, ':', limit); - if (colon) { - offset = PTRDIFF(colon, start, jschar); - prefix = js_NewDependentString(cx, str, 0, offset, 0); - if (!prefix) - return NULL; - - if (STARTS_WITH_XML(start, offset)) { - if (offset == 3) { - uri = JS_InternString(cx, xml_namespace_str); - if (!uri) - return NULL; - } else if (offset == 5 && HAS_NS_AFTER_XML(start)) { - uri = JS_InternString(cx, xmlns_namespace_str); - if (!uri) - return NULL; - } else { - uri = NULL; - } - } else { - uri = NULL; - n = inScopeNSes->length; - while (n != 0) { - --n; - ns = XMLARRAY_MEMBER(inScopeNSes, n, JSXMLNamespace); - if (ns->prefix && !js_CompareStrings(ns->prefix, prefix)) { - uri = ns->uri; - break; - } - } - } - - if (!uri) { - js_ReportCompileErrorNumber(cx, pn, - JSREPORT_PN | JSREPORT_ERROR, - JSMSG_BAD_XML_NAMESPACE, - js_ValueToPrintableString(cx, - STRING_TO_JSVAL(prefix))); - return NULL; - } - - localName = js_NewStringCopyN(cx, colon + 1, length - (offset + 1), 0); - if (!localName) - return NULL; - } else { - if (isAttributeName) { - /* - * An unprefixed attribute is not in any namespace, so set prefix - * as well as uri to the empty string. - */ - prefix = uri; - } else { - /* - * Loop from back to front looking for the closest declared default - * namespace. - */ - n = inScopeNSes->length; - while (n != 0) { - --n; - ns = XMLARRAY_MEMBER(inScopeNSes, n, JSXMLNamespace); - if (!ns->prefix || IS_EMPTY(ns->prefix)) { - uri = ns->uri; - break; - } - } - prefix = NULL; - } - localName = str; - } - - return js_NewXMLQName(cx, uri, prefix, localName); -} - -static JSString * -ChompXMLWhitespace(JSContext *cx, JSString *str) -{ - size_t length, newlength, offset; - const jschar *cp, *start, *end; - jschar c; - - length = JSSTRING_LENGTH(str); - for (cp = start = JSSTRING_CHARS(str), end = cp + length; cp < end; cp++) { - c = *cp; - if (!JS_ISXMLSPACE(c)) - break; - } - while (end > cp) { - c = end[-1]; - if (!JS_ISXMLSPACE(c)) - break; - --end; - } - newlength = PTRDIFF(end, cp, jschar); - if (newlength == length) - return str; - offset = PTRDIFF(cp, start, jschar); - return js_NewDependentString(cx, str, offset, newlength, 0); -} - -static JSXML * -ParseNodeToXML(JSContext *cx, JSParseNode *pn, JSXMLArray *inScopeNSes, - uintN flags) -{ - JSXML *xml, *kid, *attr, *attrj; - JSString *str; - uint32 length, n, i, j; - JSParseNode *pn2, *pn3, *head, **pnp; - JSXMLNamespace *ns; - JSXMLQName *qn, *attrjqn; - JSXMLClass xml_class; - -#define PN2X_SKIP_CHILD ((JSXML *) 1) - - /* - * Cases return early to avoid common code that gets an outermost xml's - * object, which protects GC-things owned by xml and its descendants from - * garbage collection. - */ - xml = NULL; - if (!JS_EnterLocalRootScope(cx)) - return NULL; - switch (pn->pn_type) { - case TOK_XMLELEM: - length = inScopeNSes->length; - pn2 = pn->pn_head; - xml = ParseNodeToXML(cx, pn2, inScopeNSes, flags); - if (!xml) - goto fail; - if (js_PushLocalRoot(cx, cx->localRootStack, (jsval)xml) < 0) - goto fail; - - flags &= ~XSF_PRECOMPILED_ROOT; - n = pn->pn_count; - JS_ASSERT(n >= 2); - n -= 2; - if (!XMLArraySetCapacity(cx, &xml->xml_kids, n)) - goto fail; - - i = 0; - while ((pn2 = pn2->pn_next) != NULL) { - if (!pn2->pn_next) { - /* Don't append the end tag! */ - JS_ASSERT(pn2->pn_type == TOK_XMLETAGO); - break; - } - - if ((flags & XSF_IGNORE_WHITESPACE) && - n > 1 && pn2->pn_type == TOK_XMLSPACE) { - --n; - continue; - } - - kid = ParseNodeToXML(cx, pn2, inScopeNSes, flags); - if (kid == PN2X_SKIP_CHILD) { - --n; - continue; - } - - if (!kid) - goto fail; - - /* Store kid in xml right away, to protect it from GC. */ - XMLARRAY_SET_MEMBER(&xml->xml_kids, i, kid); - kid->parent = xml; - ++i; - - /* XXX where is this documented in an XML spec, or in E4X? */ - if ((flags & XSF_IGNORE_WHITESPACE) && - n > 1 && kid->xml_class == JSXML_CLASS_TEXT) { - str = ChompXMLWhitespace(cx, kid->xml_value); - if (!str) - goto fail; - kid->xml_value = str; - } - } - - JS_ASSERT(i == n); - if (n < pn->pn_count - 2) - XMLArrayTrim(&xml->xml_kids); - XMLARRAY_TRUNCATE(cx, inScopeNSes, length); - break; - - case TOK_XMLLIST: - xml = js_NewXML(cx, JSXML_CLASS_LIST); - if (!xml) - goto fail; - - n = pn->pn_count; - if (!XMLArraySetCapacity(cx, &xml->xml_kids, n)) - goto fail; - - i = 0; - for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) { - /* - * Always ignore insignificant whitespace in lists -- we shouldn't - * condition this on an XML.ignoreWhitespace setting when the list - * constructor is XMLList (note XML/XMLList unification hazard). - */ - if (pn2->pn_type == TOK_XMLSPACE) { - --n; - continue; - } - - kid = ParseNodeToXML(cx, pn2, inScopeNSes, flags); - if (kid == PN2X_SKIP_CHILD) { - --n; - continue; - } - - if (!kid) - goto fail; - - XMLARRAY_SET_MEMBER(&xml->xml_kids, i, kid); - ++i; - } - - if (n < pn->pn_count) - XMLArrayTrim(&xml->xml_kids); - break; - - case TOK_XMLSTAGO: - case TOK_XMLPTAGC: - length = inScopeNSes->length; - pn2 = pn->pn_head; - JS_ASSERT(pn2->pn_type == TOK_XMLNAME); - if (pn2->pn_arity == PN_LIST) - goto syntax; - - xml = js_NewXML(cx, JSXML_CLASS_ELEMENT); - if (!xml) - goto fail; - - /* First pass: check syntax and process namespace declarations. */ - JS_ASSERT(pn->pn_count >= 1); - n = pn->pn_count - 1; - pnp = &pn2->pn_next; - head = *pnp; - while ((pn2 = *pnp) != NULL) { - size_t length; - const jschar *chars; - - if (pn2->pn_type != TOK_XMLNAME || pn2->pn_arity != PN_NULLARY) - goto syntax; - - /* Enforce "Well-formedness constraint: Unique Att Spec". */ - for (pn3 = head; pn3 != pn2; pn3 = pn3->pn_next->pn_next) { - if (pn3->pn_atom == pn2->pn_atom) { - js_ReportCompileErrorNumber(cx, pn2, - JSREPORT_PN | JSREPORT_ERROR, - JSMSG_DUPLICATE_XML_ATTR, - js_ValueToPrintableString(cx, - ATOM_KEY(pn2->pn_atom))); - goto fail; - } - } - - str = ATOM_TO_STRING(pn2->pn_atom); - pn2 = pn2->pn_next; - JS_ASSERT(pn2); - if (pn2->pn_type != TOK_XMLATTR) - goto syntax; - - length = JSSTRING_LENGTH(str); - chars = JSSTRING_CHARS(str); - if (length >= 5 && - IS_XMLNS_CHARS(chars) && - (length == 5 || chars[5] == ':')) { - JSString *uri, *prefix; - - uri = ATOM_TO_STRING(pn2->pn_atom); - if (length == 5) { - /* 10.3.2.1. Step 6(h)(i)(1)(a). */ - prefix = cx->runtime->emptyString; - } else { - prefix = js_NewStringCopyN(cx, chars + 6, length - 6, 0); - if (!prefix) - goto fail; - } - - /* - * Once the new ns is appended to xml->xml_namespaces, it is - * protected from GC by the object that owns xml -- which is - * either xml->object if outermost, or the object owning xml's - * oldest ancestor if !outermost. - */ - ns = js_NewXMLNamespace(cx, prefix, uri, JS_TRUE); - if (!ns) - goto fail; - - /* - * Don't add a namespace that's already in scope. If someone - * extracts a child property from its parent via [[Get]], then - * we enforce the invariant, noted many times in ECMA-357, that - * the child's namespaces form a possibly-improper superset of - * its ancestors' namespaces. - */ - if (!XMLARRAY_HAS_MEMBER(inScopeNSes, ns, namespace_identity)) { - if (!XMLARRAY_APPEND(cx, inScopeNSes, ns) || - !XMLARRAY_APPEND(cx, &xml->xml_namespaces, ns)) { - goto fail; - } - } - - JS_ASSERT(n >= 2); - n -= 2; - *pnp = pn2->pn_next; - /* XXXbe recycle pn2 */ - continue; - } - - pnp = &pn2->pn_next; - } - - /* - * If called from js_ParseNodeToXMLObject, emulate the effect of the - * ... wrapping done by "ToXML Applied to - * the String Type" (ECMA-357 10.3.1). - */ - if (flags & XSF_PRECOMPILED_ROOT) { - JS_ASSERT(length >= 1); - ns = XMLARRAY_MEMBER(inScopeNSes, 0, JSXMLNamespace); - JS_ASSERT(!XMLARRAY_HAS_MEMBER(&xml->xml_namespaces, ns, - namespace_identity)); - ns = js_NewXMLNamespace(cx, ns->prefix, ns->uri, JS_FALSE); - if (!ns) - goto fail; - if (!XMLARRAY_APPEND(cx, &xml->xml_namespaces, ns)) - goto fail; - } - XMLArrayTrim(&xml->xml_namespaces); - - /* Second pass: process tag name and attributes, using namespaces. */ - pn2 = pn->pn_head; - qn = ParseNodeToQName(cx, pn2, inScopeNSes, JS_FALSE); - if (!qn) - goto fail; - xml->name = qn; - - JS_ASSERT((n & 1) == 0); - n >>= 1; - if (!XMLArraySetCapacity(cx, &xml->xml_attrs, n)) - goto fail; - - for (i = 0; (pn2 = pn2->pn_next) != NULL; i++) { - qn = ParseNodeToQName(cx, pn2, inScopeNSes, JS_TRUE); - if (!qn) { - xml->xml_attrs.length = i; - goto fail; - } - - /* - * Enforce "Well-formedness constraint: Unique Att Spec", part 2: - * this time checking local name and namespace URI. - */ - for (j = 0; j < i; j++) { - attrj = XMLARRAY_MEMBER(&xml->xml_attrs, j, JSXML); - attrjqn = attrj->name; - if (!js_CompareStrings(attrjqn->uri, qn->uri) && - !js_CompareStrings(attrjqn->localName, qn->localName)) { - js_ReportCompileErrorNumber(cx, pn2, - JSREPORT_PN | JSREPORT_ERROR, - JSMSG_DUPLICATE_XML_ATTR, - js_ValueToPrintableString(cx, - ATOM_KEY(pn2->pn_atom))); - goto fail; - } - } - - pn2 = pn2->pn_next; - JS_ASSERT(pn2); - JS_ASSERT(pn2->pn_type == TOK_XMLATTR); - - attr = js_NewXML(cx, JSXML_CLASS_ATTRIBUTE); - if (!attr) - goto fail; - - XMLARRAY_SET_MEMBER(&xml->xml_attrs, i, attr); - attr->parent = xml; - attr->name = qn; - attr->xml_value = ATOM_TO_STRING(pn2->pn_atom); - } - - /* Point tag closes its own namespace scope. */ - if (pn->pn_type == TOK_XMLPTAGC) - XMLARRAY_TRUNCATE(cx, inScopeNSes, length); - break; - - case TOK_XMLSPACE: - case TOK_XMLTEXT: - case TOK_XMLCDATA: - case TOK_XMLCOMMENT: - case TOK_XMLPI: - str = ATOM_TO_STRING(pn->pn_atom); - qn = NULL; - if (pn->pn_type == TOK_XMLCOMMENT) { - if (flags & XSF_IGNORE_COMMENTS) - goto skip_child; - xml_class = JSXML_CLASS_COMMENT; - } else if (pn->pn_type == TOK_XMLPI) { - if (IS_XML(str)) { - js_ReportCompileErrorNumber(cx, pn, - JSREPORT_PN | JSREPORT_ERROR, - JSMSG_RESERVED_ID, - js_ValueToPrintableString(cx, - STRING_TO_JSVAL(str))); - goto fail; - } - - if (flags & XSF_IGNORE_PROCESSING_INSTRUCTIONS) - goto skip_child; - - qn = ParseNodeToQName(cx, pn, inScopeNSes, JS_FALSE); - if (!qn) - goto fail; - - str = pn->pn_atom2 - ? ATOM_TO_STRING(pn->pn_atom2) - : cx->runtime->emptyString; - xml_class = JSXML_CLASS_PROCESSING_INSTRUCTION; - } else { - /* CDATA section content, or element text. */ - xml_class = JSXML_CLASS_TEXT; - } - - xml = js_NewXML(cx, xml_class); - if (!xml) - goto fail; - xml->name = qn; - if (pn->pn_type == TOK_XMLSPACE) - xml->xml_flags |= XMLF_WHITESPACE_TEXT; - xml->xml_value = str; - break; - - default: - goto syntax; - } - - JS_LeaveLocalRootScope(cx); - if ((flags & XSF_PRECOMPILED_ROOT) && !js_GetXMLObject(cx, xml)) - return NULL; - return xml; - -skip_child: - js_LeaveLocalRootScope(cx); - return PN2X_SKIP_CHILD; - -#undef PN2X_SKIP_CHILD - -syntax: - js_ReportCompileErrorNumber(cx, pn, JSREPORT_PN | JSREPORT_ERROR, - JSMSG_BAD_XML_MARKUP); -fail: - JS_LeaveLocalRootScope(cx); - return NULL; -} - -/* - * XML helper, object-ops, and library functions. We start with the helpers, - * in ECMA-357 order, but merging XML (9.1) and XMLList (9.2) helpers. - */ -static JSBool -GetXMLSetting(JSContext *cx, const char *name, jsval *vp) -{ - jsval v; - - if (!js_FindConstructor(cx, NULL, js_XML_str, &v)) - return JS_FALSE; - if (!JSVAL_IS_FUNCTION(cx, v)) { - *vp = JSVAL_VOID; - return JS_TRUE; - } - return JS_GetProperty(cx, JSVAL_TO_OBJECT(v), name, vp); -} - -static JSBool -FillSettingsCache(JSContext *cx) -{ - int i; - const char *name; - jsval v; - JSBool isSet; - - /* Note: XML_PRETTY_INDENT is not a boolean setting. */ - for (i = XML_IGNORE_COMMENTS; i < XML_PRETTY_INDENT; i++) { - name = xml_static_props[i].name; - if (!GetXMLSetting(cx, name, &v) || !js_ValueToBoolean(cx, v, &isSet)) - return JS_FALSE; - if (isSet) - cx->xmlSettingFlags |= JS_BIT(i); - else - cx->xmlSettingFlags &= ~JS_BIT(i); - } - - cx->xmlSettingFlags |= XSF_CACHE_VALID; - return JS_TRUE; -} - -static JSBool -GetBooleanXMLSetting(JSContext *cx, const char *name, JSBool *bp) -{ - int i; - - if (!(cx->xmlSettingFlags & XSF_CACHE_VALID) && !FillSettingsCache(cx)) - return JS_FALSE; - - for (i = 0; xml_static_props[i].name; i++) { - if (!strcmp(xml_static_props[i].name, name)) { - *bp = (cx->xmlSettingFlags & JS_BIT(i)) != 0; - return JS_TRUE; - } - } - *bp = JS_FALSE; - return JS_TRUE; -} - -static JSBool -GetUint32XMLSetting(JSContext *cx, const char *name, uint32 *uip) -{ - jsval v; - - return GetXMLSetting(cx, name, &v) && js_ValueToECMAUint32(cx, v, uip); -} - -static JSBool -GetXMLSettingFlags(JSContext *cx, uintN *flagsp) -{ - JSBool flag; - - /* Just get the first flag to validate the setting flags cache. */ - if (!GetBooleanXMLSetting(cx, js_ignoreComments_str, &flag)) - return JS_FALSE; - *flagsp = cx->xmlSettingFlags; - return JS_TRUE; -} - -static JSXML * -ParseXMLSource(JSContext *cx, JSString *src) -{ - jsval nsval; - JSXMLNamespace *ns; - size_t urilen, srclen, length, offset, dstlen; - jschar *chars; - const jschar *srcp, *endp; - void *mark; - JSTokenStream *ts; - uintN lineno; - JSStackFrame *fp; - JSOp op; - JSParseNode *pn; - JSXML *xml; - JSXMLArray nsarray; - uintN flags; - - static const char prefix[] = ""; - static const char suffix[] = ""; - -#define constrlen(constr) (sizeof(constr) - 1) - - if (!js_GetDefaultXMLNamespace(cx, &nsval)) - return NULL; - ns = (JSXMLNamespace *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(nsval)); - - urilen = JSSTRING_LENGTH(ns->uri); - srclen = JSSTRING_LENGTH(src); - length = constrlen(prefix) + urilen + constrlen(middle) + srclen + - constrlen(suffix); - - chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar)); - if (!chars) - return NULL; - - dstlen = length; - js_InflateStringToBuffer(cx, prefix, constrlen(prefix), chars, &dstlen); - offset = dstlen; - js_strncpy(chars + offset, JSSTRING_CHARS(ns->uri), urilen); - offset += urilen; - dstlen = length - offset + 1; - js_InflateStringToBuffer(cx, middle, constrlen(middle), chars + offset, &dstlen); - offset += dstlen; - srcp = JSSTRING_CHARS(src); - js_strncpy(chars + offset, srcp, srclen); - offset += srclen; - dstlen = length - offset + 1; - js_InflateStringToBuffer(cx, suffix, constrlen(suffix), chars + offset, &dstlen); - chars [offset + dstlen] = 0; - - mark = JS_ARENA_MARK(&cx->tempPool); - ts = js_NewBufferTokenStream(cx, chars, length); - if (!ts) - return NULL; - for (fp = cx->fp; fp && !fp->pc; fp = fp->down) - continue; - if (fp) { - op = (JSOp) *fp->pc; - if (op == JSOP_TOXML || op == JSOP_TOXMLLIST) { - ts->filename = fp->script->filename; - lineno = js_PCToLineNumber(cx, fp->script, fp->pc); - for (endp = srcp + srclen; srcp < endp; srcp++) - if (*srcp == '\n') - --lineno; - ts->lineno = lineno; - } - } - - JS_KEEP_ATOMS(cx->runtime); - pn = js_ParseXMLTokenStream(cx, cx->fp->scopeChain, ts, JS_FALSE); - xml = NULL; - if (pn && XMLArrayInit(cx, &nsarray, 1)) { - if (GetXMLSettingFlags(cx, &flags)) - xml = ParseNodeToXML(cx, pn, &nsarray, flags); - - XMLArrayFinish(cx, &nsarray); - } - JS_UNKEEP_ATOMS(cx->runtime); - - JS_ARENA_RELEASE(&cx->tempPool, mark); - JS_free(cx, chars); - return xml; - -#undef constrlen -} - -/* - * Errata in 10.3.1, 10.4.1, and 13.4.4.24 (at least). - * - * 10.3.1 Step 6(a) fails to NOTE that implementations that do not enforce - * the constraint: - * - * for all x belonging to XML: - * x.[[InScopeNamespaces]] >= x.[[Parent]].[[InScopeNamespaces]] - * - * must union x.[[InScopeNamespaces]] into x[0].[[InScopeNamespaces]] here - * (in new sub-step 6(a), renumbering the others to (b) and (c)). - * - * Same goes for 10.4.1 Step 7(a). - * - * In order for XML.prototype.namespaceDeclarations() to work correctly, the - * default namespace thereby unioned into x[0].[[InScopeNamespaces]] must be - * flagged as not declared, so that 13.4.4.24 Step 8(a) can exclude all such - * undeclared namespaces associated with x not belonging to ancestorNS. - */ -static JSXML * -OrphanXMLChild(JSContext *cx, JSXML *xml, uint32 i) -{ - JSXMLNamespace *ns; - - ns = XMLARRAY_MEMBER(&xml->xml_namespaces, 0, JSXMLNamespace); - xml = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (!ns || !xml) - return xml; - if (xml->xml_class == JSXML_CLASS_ELEMENT) { - if (!XMLARRAY_APPEND(cx, &xml->xml_namespaces, ns)) - return NULL; - ns->declared = JS_FALSE; - } - xml->parent = NULL; - return xml; -} - -static JSObject * -ToXML(JSContext *cx, jsval v) -{ - JSObject *obj; - JSXML *xml; - JSClass *clasp; - JSString *str; - uint32 length; - - if (JSVAL_IS_PRIMITIVE(v)) { - if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) - goto bad; - } else { - obj = JSVAL_TO_OBJECT(v); - if (OBJECT_IS_XML(cx, obj)) { - xml = (JSXML *) JS_GetPrivate(cx, obj); - if (xml->xml_class == JSXML_CLASS_LIST) { - if (xml->xml_kids.length != 1) - goto bad; - xml = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML); - if (xml) { - JS_ASSERT(xml->xml_class != JSXML_CLASS_LIST); - return js_GetXMLObject(cx, xml); - } - } - return obj; - } - - clasp = OBJ_GET_CLASS(cx, obj); - if (clasp->flags & JSCLASS_DOCUMENT_OBSERVER) { - JS_ASSERT(0); - } - - if (clasp != &js_StringClass && - clasp != &js_NumberClass && - clasp != &js_BooleanClass) { - goto bad; - } - } - - str = js_ValueToString(cx, v); - if (!str) - return NULL; - if (IS_EMPTY(str)) { - length = 0; -#ifdef __GNUC__ /* suppress bogus gcc warnings */ - xml = NULL; -#endif - } else { - xml = ParseXMLSource(cx, str); - if (!xml) - return NULL; - length = JSXML_LENGTH(xml); - } - - if (length == 0) { - obj = js_NewXMLObject(cx, JSXML_CLASS_TEXT); - if (!obj) - return NULL; - } else if (length == 1) { - xml = OrphanXMLChild(cx, xml, 0); - if (!xml) - return NULL; - obj = js_GetXMLObject(cx, xml); - if (!obj) - return NULL; - } else { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_SYNTAX_ERROR); - return NULL; - } - return obj; - -bad: - str = js_DecompileValueGenerator(cx, JSDVG_IGNORE_STACK, v, NULL); - if (str) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_XML_CONVERSION, - JS_GetStringBytes(str)); - } - return NULL; -} - -static JSBool -Append(JSContext *cx, JSXML *list, JSXML *kid); - -static JSObject * -ToXMLList(JSContext *cx, jsval v) -{ - JSObject *obj, *listobj; - JSXML *xml, *list, *kid; - JSClass *clasp; - JSString *str; - uint32 i, length; - - if (JSVAL_IS_PRIMITIVE(v)) { - if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) - goto bad; - } else { - obj = JSVAL_TO_OBJECT(v); - if (OBJECT_IS_XML(cx, obj)) { - xml = (JSXML *) JS_GetPrivate(cx, obj); - if (xml->xml_class != JSXML_CLASS_LIST) { - listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST); - if (!listobj) - return NULL; - list = (JSXML *) JS_GetPrivate(cx, listobj); - if (!Append(cx, list, xml)) - return NULL; - return listobj; - } - return obj; - } - - clasp = OBJ_GET_CLASS(cx, obj); - if (clasp->flags & JSCLASS_DOCUMENT_OBSERVER) { - JS_ASSERT(0); - } - - if (clasp != &js_StringClass && - clasp != &js_NumberClass && - clasp != &js_BooleanClass) { - goto bad; - } - } - - str = js_ValueToString(cx, v); - if (!str) - return NULL; - if (IS_EMPTY(str)) { - xml = NULL; - length = 0; - } else { - if (!JS_EnterLocalRootScope(cx)) - return NULL; - xml = ParseXMLSource(cx, str); - if (!xml) { - JS_LeaveLocalRootScope(cx); - return NULL; - } - length = JSXML_LENGTH(xml); - } - - listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST); - if (listobj) { - list = (JSXML *) JS_GetPrivate(cx, listobj); - for (i = 0; i < length; i++) { - kid = OrphanXMLChild(cx, xml, i); - if (!kid) - return NULL; - if (!Append(cx, list, kid)) { - listobj = NULL; - break; - } - } - } - - if (xml) - JS_LeaveLocalRootScope(cx); - return listobj; - -bad: - str = js_DecompileValueGenerator(cx, JSDVG_IGNORE_STACK, v, NULL); - if (str) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_XMLLIST_CONVERSION, - JS_GetStringBytes(str)); - } - return NULL; -} - -/* - * ECMA-357 10.2.1 Steps 5-7 pulled out as common subroutines of XMLToXMLString - * and their library-public js_* counterparts. The guts of MakeXMLCDataString, - * MakeXMLCommentString, and MakeXMLPIString are further factored into a common - * MakeXMLSpecialString subroutine. - * - * These functions take ownership of sb->base, if sb is non-null, in all cases - * of success or failure. - */ -static JSString * -MakeXMLSpecialString(JSContext *cx, JSStringBuffer *sb, - JSString *str, JSString *str2, - const jschar *prefix, size_t prefixlength, - const jschar *suffix, size_t suffixlength) -{ - JSStringBuffer localSB; - size_t length, length2, newlength; - jschar *bp, *base; - - if (!sb) { - sb = &localSB; - js_InitStringBuffer(sb); - } - - length = JSSTRING_LENGTH(str); - length2 = str2 ? JSSTRING_LENGTH(str2) : 0; - newlength = STRING_BUFFER_OFFSET(sb) + - prefixlength + length + ((length2 != 0) ? 1 + length2 : 0) + - suffixlength; - bp = base = (jschar *) - JS_realloc(cx, sb->base, (newlength + 1) * sizeof(jschar)); - if (!bp) { - js_FinishStringBuffer(sb); - return NULL; - } - - bp += STRING_BUFFER_OFFSET(sb); - js_strncpy(bp, prefix, prefixlength); - bp += prefixlength; - js_strncpy(bp, JSSTRING_CHARS(str), length); - bp += length; - if (length2 != 0) { - *bp++ = (jschar) ' '; - js_strncpy(bp, JSSTRING_CHARS(str2), length2); - bp += length2; - } - js_strncpy(bp, suffix, suffixlength); - bp[suffixlength] = 0; - - str = js_NewString(cx, base, newlength, 0); - if (!str) - free(base); - return str; -} - -static JSString * -MakeXMLCDATAString(JSContext *cx, JSStringBuffer *sb, JSString *str) -{ - static const jschar cdata_prefix_ucNstr[] = {'<', '!', '[', - 'C', 'D', 'A', 'T', 'A', - '['}; - static const jschar cdata_suffix_ucNstr[] = {']', ']', '>'}; - - return MakeXMLSpecialString(cx, sb, str, NULL, - cdata_prefix_ucNstr, 9, - cdata_suffix_ucNstr, 3); -} - -static JSString * -MakeXMLCommentString(JSContext *cx, JSStringBuffer *sb, JSString *str) -{ - static const jschar comment_prefix_ucNstr[] = {'<', '!', '-', '-'}; - static const jschar comment_suffix_ucNstr[] = {'-', '-', '>'}; - - return MakeXMLSpecialString(cx, sb, str, NULL, - comment_prefix_ucNstr, 4, - comment_suffix_ucNstr, 3); -} - -static JSString * -MakeXMLPIString(JSContext *cx, JSStringBuffer *sb, JSString *name, - JSString *value) -{ - static const jschar pi_prefix_ucNstr[] = {'<', '?'}; - static const jschar pi_suffix_ucNstr[] = {'?', '>'}; - - return MakeXMLSpecialString(cx, sb, name, value, - pi_prefix_ucNstr, 2, - pi_suffix_ucNstr, 2); -} - -/* - * ECMA-357 10.2.1 17(d-g) pulled out into a common subroutine that appends - * equals, a double quote, an attribute value, and a closing double quote. - */ -static void -AppendAttributeValue(JSContext *cx, JSStringBuffer *sb, JSString *valstr) -{ - js_AppendCString(sb, "=\""); - valstr = js_EscapeAttributeValue(cx, valstr); - if (!valstr) { - free(sb->base); - sb->base = STRING_BUFFER_ERROR_BASE; - return; - } - js_AppendJSString(sb, valstr); - js_AppendChar(sb, '"'); -} - -/* - * ECMA-357 10.2.1.1 EscapeElementValue helper method. - * - * This function takes ownership of sb->base, if sb is non-null, in all cases - * of success or failure. - */ -static JSString * -EscapeElementValue(JSContext *cx, JSStringBuffer *sb, JSString *str) -{ - size_t length, newlength; - const jschar *cp, *start, *end; - jschar c; - - length = newlength = JSSTRING_LENGTH(str); - for (cp = start = JSSTRING_CHARS(str), end = cp + length; cp < end; cp++) { - c = *cp; - if (c == '<' || c == '>') - newlength += 3; - else if (c == '&') - newlength += 4; - - if (newlength < length) { - JS_ReportOutOfMemory(cx); - return NULL; - } - } - if ((sb && STRING_BUFFER_OFFSET(sb) != 0) || newlength > length) { - JSStringBuffer localSB; - if (!sb) { - sb = &localSB; - js_InitStringBuffer(sb); - } - if (!sb->grow(sb, newlength)) { - JS_ReportOutOfMemory(cx); - return NULL; - } - for (cp = start; cp < end; cp++) { - c = *cp; - if (c == '<') - js_AppendCString(sb, js_lt_entity_str); - else if (c == '>') - js_AppendCString(sb, js_gt_entity_str); - else if (c == '&') - js_AppendCString(sb, js_amp_entity_str); - else - js_AppendChar(sb, c); - } - JS_ASSERT(STRING_BUFFER_OK(sb)); - str = js_NewString(cx, sb->base, STRING_BUFFER_OFFSET(sb), 0); - if (!str) - js_FinishStringBuffer(sb); - } - return str; -} - -/* - * ECMA-357 10.2.1.2 EscapeAttributeValue helper method. - * This function takes ownership of sb->base, if sb is non-null, in all cases. - */ -static JSString * -EscapeAttributeValue(JSContext *cx, JSStringBuffer *sb, JSString *str) -{ - size_t length, newlength; - const jschar *cp, *start, *end; - jschar c; - - length = newlength = JSSTRING_LENGTH(str); - for (cp = start = JSSTRING_CHARS(str), end = cp + length; cp < end; cp++) { - c = *cp; - if (c == '"') - newlength += 5; - else if (c == '<') - newlength += 3; - else if (c == '&' || c == '\n' || c == '\r' || c == '\t') - newlength += 4; - - if (newlength < length) { - JS_ReportOutOfMemory(cx); - return NULL; - } - } - if ((sb && STRING_BUFFER_OFFSET(sb) != 0) || newlength > length) { - JSStringBuffer localSB; - if (!sb) { - sb = &localSB; - js_InitStringBuffer(sb); - } - if (!sb->grow(sb, newlength)) { - JS_ReportOutOfMemory(cx); - return NULL; - } - for (cp = start; cp < end; cp++) { - c = *cp; - if (c == '"') - js_AppendCString(sb, js_quot_entity_str); - else if (c == '<') - js_AppendCString(sb, js_lt_entity_str); - else if (c == '&') - js_AppendCString(sb, js_amp_entity_str); - else if (c == '\n') - js_AppendCString(sb, " "); - else if (c == '\r') - js_AppendCString(sb, " "); - else if (c == '\t') - js_AppendCString(sb, " "); - else - js_AppendChar(sb, c); - } - JS_ASSERT(STRING_BUFFER_OK(sb)); - str = js_NewString(cx, sb->base, STRING_BUFFER_OFFSET(sb), 0); - if (!str) - js_FinishStringBuffer(sb); - } - return str; -} - -/* 13.3.5.4 [[GetNamespace]]([InScopeNamespaces]) */ -static JSXMLNamespace * -GetNamespace(JSContext *cx, JSXMLQName *qn, const JSXMLArray *inScopeNSes) -{ - JSXMLNamespace *match, *ns; - uint32 i, n; - jsval argv[2]; - JSObject *nsobj; - - JS_ASSERT(qn->uri); - if (!qn->uri) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_XML_NAMESPACE, - qn->prefix - ? js_ValueToPrintableString(cx, - STRING_TO_JSVAL(qn->prefix)) - : js_type_str[JSTYPE_VOID]); - return NULL; - } - - /* Look for a matching namespace in inScopeNSes, if provided. */ - match = NULL; - if (inScopeNSes) { - for (i = 0, n = inScopeNSes->length; i < n; i++) { - ns = XMLARRAY_MEMBER(inScopeNSes, i, JSXMLNamespace); - if (!ns) - continue; - - /* - * Erratum, very tricky, and not specified in ECMA-357 13.3.5.4: - * If we preserve prefixes, we must match null qn->prefix against - * an empty ns->prefix, in order to avoid generating redundant - * prefixed and default namespaces for cases such as: - * - * x = - * print(x.toXMLString()); - * - * Per 10.3.2.1, the namespace attribute in t has an empty string - * prefix (*not* a null prefix), per 10.3.2.1 Step 6(h)(i)(1): - * - * 1. If the [local name] property of a is "xmlns" - * a. Map ns.prefix to the empty string - * - * But t's name has a null prefix in this implementation, meaning - * *undefined*, per 10.3.2.1 Step 6(c)'s NOTE (which refers to - * the http://www.w3.org/TR/xml-infoset/ spec, item 2.2.3, without - * saying how "no value" maps to an ECMA-357 value -- but it must - * map to the *undefined* prefix value). - * - * Since "" != undefined (or null, in the current implementation) - * the ECMA-357 spec will fail to match in [[GetNamespace]] called - * on t with argument {} U {(prefix="", uri="http://foo.com")}. - * This spec bug leads to ToXMLString results that duplicate the - * declared namespace. - */ - if (!js_CompareStrings(ns->uri, qn->uri) && - (ns->prefix == qn->prefix || - ((ns->prefix && qn->prefix) - ? !js_CompareStrings(ns->prefix, qn->prefix) - : IS_EMPTY(ns->prefix ? ns->prefix : qn->prefix)))) { - match = ns; - break; - } - } - } - - /* If we didn't match, make a new namespace from qn. */ - if (!match) { - argv[0] = qn->prefix ? STRING_TO_JSVAL(qn->prefix) : JSVAL_VOID; - argv[1] = STRING_TO_JSVAL(qn->uri); - nsobj = js_ConstructObject(cx, &js_NamespaceClass.base, NULL, NULL, - 2, argv); - if (!nsobj) - return NULL; - match = (JSXMLNamespace *) JS_GetPrivate(cx, nsobj); - } - return match; -} - -static JSString * -GeneratePrefix(JSContext *cx, JSString *uri, JSXMLArray *decls) -{ - const jschar *cp, *start, *end; - size_t length, newlength, offset; - uint32 i, n, m, serial; - jschar *bp, *dp; - JSBool done; - JSXMLNamespace *ns; - JSString *prefix; - - JS_ASSERT(!IS_EMPTY(uri)); - - /* - * Try peeling off the last filename suffix or pathname component till - * we have a valid XML name. This heuristic will prefer "xul" given - * ".../there.is.only.xul", "xbl" given ".../xbl", and "xbl2" given any - * likely URI of the form ".../xbl2/2005". - */ - start = JSSTRING_CHARS(uri); - cp = end = start + JSSTRING_LENGTH(uri); - while (--cp > start) { - if (*cp == '.' || *cp == '/' || *cp == ':') { - ++cp; - if (IsXMLName(cp, PTRDIFF(end, cp, jschar))) - break; - end = --cp; - } - } - length = PTRDIFF(end, cp, jschar); - - /* - * Now search through decls looking for a collision. If we collide with - * an existing prefix, start tacking on a hyphen and a serial number. - */ - serial = 0; - bp = NULL; -#ifdef __GNUC__ /* suppress bogus gcc warnings */ - newlength = 0; -#endif - do { - done = JS_TRUE; - for (i = 0, n = decls->length; i < n; i++) { - ns = XMLARRAY_MEMBER(decls, i, JSXMLNamespace); - if (ns && ns->prefix && - JSSTRING_LENGTH(ns->prefix) == length && - !memcmp(JSSTRING_CHARS(ns->prefix), cp, - length * sizeof(jschar))) { - if (!bp) { - newlength = length + 2 + (size_t) log10(n); - bp = (jschar *) - JS_malloc(cx, (newlength + 1) * sizeof(jschar)); - if (!bp) - return NULL; - js_strncpy(bp, cp, length); - } - - ++serial; - JS_ASSERT(serial <= n); - dp = bp + length + 2 + (size_t) log10(serial); - *dp = 0; - for (m = serial; m != 0; m /= 10) - *--dp = (jschar)('0' + m % 10); - *--dp = '-'; - JS_ASSERT(dp == bp + length); - - done = JS_FALSE; - break; - } - } - } while (!done); - - if (!bp) { - offset = PTRDIFF(cp, start, jschar); - prefix = js_NewDependentString(cx, uri, offset, length, 0); - } else { - prefix = js_NewString(cx, bp, newlength, 0); - if (!prefix) - JS_free(cx, bp); - } - return prefix; -} - -static JSBool -namespace_match(const void *a, const void *b) -{ - const JSXMLNamespace *nsa = (const JSXMLNamespace *) a; - const JSXMLNamespace *nsb = (const JSXMLNamespace *) b; - - if (nsb->prefix) - return nsa->prefix && !js_CompareStrings(nsa->prefix, nsb->prefix); - return !js_CompareStrings(nsa->uri, nsb->uri); -} - -/* ECMA-357 10.2.1 and 10.2.2 */ -static JSString * -XMLToXMLString(JSContext *cx, JSXML *xml, const JSXMLArray *ancestorNSes, - uintN indentLevel) -{ - JSBool pretty, indentKids; - JSStringBuffer sb; - JSString *str, *prefix, *kidstr; - JSXMLArrayCursor cursor; - uint32 i, n; - JSXMLArray empty, decls, ancdecls; - JSXMLNamespace *ns, *ns2; - uintN nextIndentLevel; - JSXML *attr, *kid; - - if (!GetBooleanXMLSetting(cx, js_prettyPrinting_str, &pretty)) - return NULL; - - js_InitStringBuffer(&sb); - if (pretty) - js_RepeatChar(&sb, ' ', indentLevel); - str = NULL; - - switch (xml->xml_class) { - case JSXML_CLASS_TEXT: - /* Step 4. */ - if (pretty) { - str = ChompXMLWhitespace(cx, xml->xml_value); - if (!str) - return NULL; - } else { - str = xml->xml_value; - } - return EscapeElementValue(cx, &sb, str); - - case JSXML_CLASS_ATTRIBUTE: - /* Step 5. */ - return EscapeAttributeValue(cx, &sb, xml->xml_value); - - case JSXML_CLASS_COMMENT: - /* Step 6. */ - return MakeXMLCommentString(cx, &sb, xml->xml_value); - - case JSXML_CLASS_PROCESSING_INSTRUCTION: - /* Step 7. */ - return MakeXMLPIString(cx, &sb, xml->name->localName, xml->xml_value); - - case JSXML_CLASS_LIST: - /* ECMA-357 10.2.2. */ - XMLArrayCursorInit(&cursor, &xml->xml_kids); - i = 0; - while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) { - if (pretty && i != 0) - js_AppendChar(&sb, '\n'); - - kidstr = XMLToXMLString(cx, kid, ancestorNSes, indentLevel); - if (!kidstr) - break; - - js_AppendJSString(&sb, kidstr); - ++i; - } - XMLArrayCursorFinish(&cursor); - if (kid) - goto list_out; - - if (!sb.base) { - if (!STRING_BUFFER_OK(&sb)) { - JS_ReportOutOfMemory(cx); - return NULL; - } - return cx->runtime->emptyString; - } - - str = js_NewString(cx, sb.base, STRING_BUFFER_OFFSET(&sb), 0); - list_out: - if (!str) - js_FinishStringBuffer(&sb); - return str; - - default:; - } - - /* After this point, control must flow through label out: to exit. */ - if (!JS_EnterLocalRootScope(cx)) - return NULL; - - /* ECMA-357 10.2.1 step 8 onward: handle ToXMLString on an XML element. */ - if (!ancestorNSes) { - XMLArrayInit(cx, &empty, 0); - ancestorNSes = ∅ - } - XMLArrayInit(cx, &decls, 0); - ancdecls.capacity = 0; - - /* Clone in-scope namespaces not in ancestorNSes into decls. */ - XMLArrayCursorInit(&cursor, &xml->xml_namespaces); - while ((ns = (JSXMLNamespace *) XMLArrayCursorNext(&cursor)) != NULL) { - if (!ns->declared) - continue; - if (!XMLARRAY_HAS_MEMBER(ancestorNSes, ns, namespace_identity)) { - /* NOTE: may want to exclude unused namespaces here. */ - ns2 = js_NewXMLNamespace(cx, ns->prefix, ns->uri, JS_TRUE); - if (!ns2 || !XMLARRAY_APPEND(cx, &decls, ns2)) - break; - } - } - XMLArrayCursorFinish(&cursor); - if (ns) - goto out; - - /* - * Union ancestorNSes and decls into ancdecls. Note that ancdecls does - * not own its member references. In the spec, ancdecls has no name, but - * is always written out as (AncestorNamespaces U namespaceDeclarations). - */ - if (!XMLArrayInit(cx, &ancdecls, ancestorNSes->length + decls.length)) - goto out; - for (i = 0, n = ancestorNSes->length; i < n; i++) { - ns2 = XMLARRAY_MEMBER(ancestorNSes, i, JSXMLNamespace); - if (!ns2) - continue; - JS_ASSERT(!XMLARRAY_HAS_MEMBER(&decls, ns2, namespace_identity)); - if (!XMLARRAY_APPEND(cx, &ancdecls, ns2)) - goto out; - } - for (i = 0, n = decls.length; i < n; i++) { - ns2 = XMLARRAY_MEMBER(&decls, i, JSXMLNamespace); - if (!ns2) - continue; - JS_ASSERT(!XMLARRAY_HAS_MEMBER(&ancdecls, ns2, namespace_identity)); - if (!XMLARRAY_APPEND(cx, &ancdecls, ns2)) - goto out; - } - - /* Step 11, except we don't clone ns unless its prefix is undefined. */ - ns = GetNamespace(cx, xml->name, &ancdecls); - if (!ns) - goto out; - - /* Step 12 (NULL means *undefined* here), plus the deferred ns cloning. */ - if (!ns->prefix) { - /* - * Create a namespace prefix that isn't used by any member of decls. - * Assign the new prefix to a copy of ns. Flag this namespace as if - * it were declared, for assertion-testing's sake later below. - * - * Erratum: if ns->prefix and xml->name are both null (*undefined* in - * ECMA-357), we know that xml was named using the default namespace - * (proof: see GetNamespace and the Namespace constructor called with - * two arguments). So we ought not generate a new prefix here, when - * we can declare ns as the default namespace for xml. - * - * This helps descendants inherit the namespace instead of redundantly - * redeclaring it with generated prefixes in each descendant. - */ - if (!xml->name->prefix) { - prefix = cx->runtime->emptyString; - } else { - prefix = GeneratePrefix(cx, ns->uri, &ancdecls); - if (!prefix) - goto out; - } - ns = js_NewXMLNamespace(cx, prefix, ns->uri, JS_TRUE); - if (!ns) - goto out; - - /* - * If the xml->name was unprefixed, we must remove any declared default - * namespace from decls before appending ns. How can you get a default - * namespace in decls that doesn't match the one from name? Apparently - * by calling x.setNamespace(ns) where ns has no prefix. The other way - * to fix this is to update x's in-scope namespaces when setNamespace - * is called, but that's not specified by ECMA-357. - * - * Likely Erratum here, depending on whether the lack of update to x's - * in-scope namespace in XML.prototype.setNamespace (13.4.4.36) is an - * erratum or not. Note that changing setNamespace to update the list - * of in-scope namespaces will change x.namespaceDeclarations(). - */ - if (IS_EMPTY(prefix)) { - i = XMLArrayFindMember(&decls, ns, namespace_match); - if (i != XML_NOT_FOUND) - XMLArrayDelete(cx, &decls, i, JS_TRUE); - } - - /* - * In the spec, ancdecls has no name, but is always written out as - * (AncestorNamespaces U namespaceDeclarations). Since we compute - * that union in ancdecls, any time we append a namespace strong - * ref to decls, we must also append a weak ref to ancdecls. Order - * matters here: code at label out: releases strong refs in decls. - */ - if (!XMLARRAY_APPEND(cx, &ancdecls, ns) || - !XMLARRAY_APPEND(cx, &decls, ns)) { - goto out; - } - } - - /* Format the element or point-tag into sb. */ - js_AppendChar(&sb, '<'); - - if (ns->prefix && !IS_EMPTY(ns->prefix)) { - js_AppendJSString(&sb, ns->prefix); - js_AppendChar(&sb, ':'); - } - js_AppendJSString(&sb, xml->name->localName); - - /* - * Step 16 makes a union to avoid writing two loops in step 17, to share - * common attribute value appending spec-code. We prefer two loops for - * faster code and less data overhead. - */ - - /* Step 17(c): append XML namespace declarations. */ - XMLArrayCursorInit(&cursor, &decls); - while ((ns2 = (JSXMLNamespace *) XMLArrayCursorNext(&cursor)) != NULL) { - JS_ASSERT(ns2->declared); - - js_AppendCString(&sb, " xmlns"); - - /* 17(c)(ii): NULL means *undefined* here. */ - if (!ns2->prefix) { - prefix = GeneratePrefix(cx, ns2->uri, &ancdecls); - if (!prefix) - break; - ns2->prefix = prefix; - } - - /* 17(c)(iii). */ - if (!IS_EMPTY(ns2->prefix)) { - js_AppendChar(&sb, ':'); - js_AppendJSString(&sb, ns2->prefix); - } - - /* 17(d-g). */ - AppendAttributeValue(cx, &sb, ns2->uri); - } - XMLArrayCursorFinish(&cursor); - if (ns2) - goto out; - - /* Step 17(b): append attributes. */ - XMLArrayCursorInit(&cursor, &xml->xml_attrs); - while ((attr = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) { - js_AppendChar(&sb, ' '); - ns2 = GetNamespace(cx, attr->name, &ancdecls); - if (!ns2) - break; - - /* 17(b)(ii): NULL means *undefined* here. */ - if (!ns2->prefix) { - prefix = GeneratePrefix(cx, ns2->uri, &ancdecls); - if (!prefix) - break; - - /* Again, we avoid copying ns2 until we know it's prefix-less. */ - ns2 = js_NewXMLNamespace(cx, prefix, ns2->uri, JS_TRUE); - if (!ns2) - break; - - /* - * In the spec, ancdecls has no name, but is always written out as - * (AncestorNamespaces U namespaceDeclarations). Since we compute - * that union in ancdecls, any time we append a namespace strong - * ref to decls, we must also append a weak ref to ancdecls. Order - * matters here: code at label out: releases strong refs in decls. - */ - if (!XMLARRAY_APPEND(cx, &ancdecls, ns2) || - !XMLARRAY_APPEND(cx, &decls, ns2)) { - break; - } - } - - /* 17(b)(iii). */ - if (!IS_EMPTY(ns2->prefix)) { - js_AppendJSString(&sb, ns2->prefix); - js_AppendChar(&sb, ':'); - } - - /* 17(b)(iv). */ - js_AppendJSString(&sb, attr->name->localName); - - /* 17(d-g). */ - AppendAttributeValue(cx, &sb, attr->xml_value); - } - XMLArrayCursorFinish(&cursor); - if (attr) - goto out; - - /* Step 18: handle point tags. */ - n = xml->xml_kids.length; - if (n == 0) { - js_AppendCString(&sb, "/>"); - } else { - /* Steps 19 through 25: handle element content, and open the end-tag. */ - js_AppendChar(&sb, '>'); - indentKids = n > 1 || - (n == 1 && - (kid = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML)) && - kid->xml_class != JSXML_CLASS_TEXT); - - if (pretty && indentKids) { - if (!GetUint32XMLSetting(cx, js_prettyIndent_str, &i)) - goto out; - nextIndentLevel = indentLevel + i; - } else { - nextIndentLevel = 0; - } - - XMLArrayCursorInit(&cursor, &xml->xml_kids); - while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) { - if (pretty && indentKids) - js_AppendChar(&sb, '\n'); - - kidstr = XMLToXMLString(cx, kid, &ancdecls, nextIndentLevel); - if (!kidstr) - break; - - js_AppendJSString(&sb, kidstr); - } - XMLArrayCursorFinish(&cursor); - if (kid) - goto out; - - if (pretty && indentKids) { - js_AppendChar(&sb, '\n'); - js_RepeatChar(&sb, ' ', indentLevel); - } - js_AppendCString(&sb, "prefix && !IS_EMPTY(ns->prefix)) { - js_AppendJSString(&sb, ns->prefix); - js_AppendChar(&sb, ':'); - } - - /* Step 27. */ - js_AppendJSString(&sb, xml->name->localName); - js_AppendChar(&sb, '>'); - } - - if (!STRING_BUFFER_OK(&sb)) { - JS_ReportOutOfMemory(cx); - goto out; - } - - str = js_NewString(cx, sb.base, STRING_BUFFER_OFFSET(&sb), 0); -out: - JS_LeaveLocalRootScope(cx); - if (!str && STRING_BUFFER_OK(&sb)) - js_FinishStringBuffer(&sb); - XMLArrayFinish(cx, &decls); - if (ancdecls.capacity != 0) - XMLArrayFinish(cx, &ancdecls); - return str; -} - -/* ECMA-357 10.2 */ -static JSString * -ToXMLString(JSContext *cx, jsval v) -{ - JSObject *obj; - JSString *str; - JSXML *xml; - - if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_XML_CONVERSION, - js_type_str[JSVAL_IS_NULL(v) - ? JSTYPE_NULL - : JSTYPE_VOID]); - return NULL; - } - - if (JSVAL_IS_BOOLEAN(v) || JSVAL_IS_NUMBER(v)) - return js_ValueToString(cx, v); - - if (JSVAL_IS_STRING(v)) - return EscapeElementValue(cx, NULL, JSVAL_TO_STRING(v)); - - obj = JSVAL_TO_OBJECT(v); - if (!OBJECT_IS_XML(cx, obj)) { - if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_STRING, &v)) - return NULL; - str = js_ValueToString(cx, v); - if (!str) - return NULL; - return EscapeElementValue(cx, NULL, str); - } - - /* Handle non-element cases in this switch, returning from each case. */ - xml = (JSXML *) JS_GetPrivate(cx, obj); - return XMLToXMLString(cx, xml, NULL, 0); -} - -static JSXMLQName * -ToAttributeName(JSContext *cx, jsval v) -{ - JSString *name, *uri, *prefix; - JSObject *obj; - JSClass *clasp; - JSXMLQName *qn; - JSTempValueRooter tvr; - - if (JSVAL_IS_STRING(v)) { - name = JSVAL_TO_STRING(v); - uri = prefix = cx->runtime->emptyString; - } else { - if (JSVAL_IS_PRIMITIVE(v)) { - name = js_DecompileValueGenerator(cx, JSDVG_IGNORE_STACK, v, NULL); - if (name) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_XML_ATTR_NAME, - JS_GetStringBytes(name)); - } - return NULL; - } - - obj = JSVAL_TO_OBJECT(v); - clasp = OBJ_GET_CLASS(cx, obj); - if (clasp == &js_AttributeNameClass) - return (JSXMLQName *) JS_GetPrivate(cx, obj); - - if (clasp == &js_QNameClass.base) { - qn = (JSXMLQName *) JS_GetPrivate(cx, obj); - uri = qn->uri; - prefix = qn->prefix; - name = qn->localName; - } else { - if (clasp == &js_AnyNameClass) { - name = ATOM_TO_STRING(cx->runtime->atomState.starAtom); - } else { - name = js_ValueToString(cx, v); - if (!name) - return NULL; - } - uri = prefix = cx->runtime->emptyString; - } - } - - qn = js_NewXMLQName(cx, uri, prefix, name); - if (!qn) - return NULL; - - /* - * Temp and local root scope APIs take GC-thing pointers tagged as jsvals - * and blindly untag. Since qn is a GC-thing pointer, we can treat it as - * an object pointer. - */ - JS_PUSH_SINGLE_TEMP_ROOT(cx, OBJECT_TO_JSVAL(qn), &tvr); - obj = js_GetAttributeNameObject(cx, qn); - JS_POP_TEMP_ROOT(cx, &tvr); - if (!obj) - return NULL; - return qn; -} - -static JSXMLQName * -ToXMLName(JSContext *cx, jsval v, jsid *funidp) -{ - JSString *name; - JSObject *obj; - JSClass *clasp; - uint32 index; - JSXMLQName *qn; - JSAtom *atom; - - if (JSVAL_IS_STRING(v)) { - name = JSVAL_TO_STRING(v); - } else { - if (JSVAL_IS_PRIMITIVE(v)) { - name = js_DecompileValueGenerator(cx, JSDVG_IGNORE_STACK, v, NULL); - if (name) - goto bad; - return NULL; - } - - obj = JSVAL_TO_OBJECT(v); - clasp = OBJ_GET_CLASS(cx, obj); - if (clasp == &js_AttributeNameClass || clasp == &js_QNameClass.base) - goto out; - if (clasp == &js_AnyNameClass) { - name = ATOM_TO_STRING(cx->runtime->atomState.starAtom); - goto construct; - } - name = js_ValueToString(cx, v); - if (!name) - return NULL; - } - - /* - * ECMA-357 10.6.1 step 1 seems to be incorrect. The spec says: - * - * 1. If ToString(ToNumber(P)) == ToString(P), throw a TypeError exception - * - * First, _P_ should be _s_, to refer to the given string. - * - * Second, why does ToXMLName applied to the string type throw TypeError - * only for numeric literals without any leading or trailing whitespace? - * - * If the idea is to reject uint32 property names, then the check needs to - * be stricter, to exclude hexadecimal and floating point literals. - */ - if (js_IdIsIndex(STRING_TO_JSVAL(name), &index)) - goto bad; - - if (*JSSTRING_CHARS(name) == '@') { - name = js_NewDependentString(cx, name, 1, JSSTRING_LENGTH(name) - 1, 0); - if (!name) - return NULL; - *funidp = 0; - return ToAttributeName(cx, STRING_TO_JSVAL(name)); - } - -construct: - v = STRING_TO_JSVAL(name); - obj = js_ConstructObject(cx, &js_QNameClass.base, NULL, NULL, 1, &v); - if (!obj) - return NULL; - -out: - qn = (JSXMLQName *) JS_GetPrivate(cx, obj); - atom = cx->runtime->atomState.lazy.functionNamespaceURIAtom; - if (qn->uri && atom && - (qn->uri == ATOM_TO_STRING(atom) || - !js_CompareStrings(qn->uri, ATOM_TO_STRING(atom)))) { - if (!JS_ValueToId(cx, STRING_TO_JSVAL(qn->localName), funidp)) - return NULL; - } else { - *funidp = 0; - } - return qn; - -bad: - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_XML_NAME, - js_ValueToPrintableString(cx, STRING_TO_JSVAL(name))); - return NULL; -} - -/* ECMA-357 9.1.1.13 XML [[AddInScopeNamespace]]. */ -static JSBool -AddInScopeNamespace(JSContext *cx, JSXML *xml, JSXMLNamespace *ns) -{ - JSXMLNamespace *match, *ns2; - uint32 i, n, m; - - if (xml->xml_class != JSXML_CLASS_ELEMENT) - return JS_TRUE; - - /* NULL means *undefined* here -- see ECMA-357 9.1.1.13 step 2. */ - if (!ns->prefix) { - match = NULL; - for (i = 0, n = xml->xml_namespaces.length; i < n; i++) { - ns2 = XMLARRAY_MEMBER(&xml->xml_namespaces, i, JSXMLNamespace); - if (ns2 && !js_CompareStrings(ns2->uri, ns->uri)) { - match = ns2; - break; - } - } - if (!match && !XMLARRAY_ADD_MEMBER(cx, &xml->xml_namespaces, n, ns)) - return JS_FALSE; - } else { - if (IS_EMPTY(ns->prefix) && IS_EMPTY(xml->name->uri)) - return JS_TRUE; - match = NULL; -#ifdef __GNUC__ /* suppress bogus gcc warnings */ - m = XML_NOT_FOUND; -#endif - for (i = 0, n = xml->xml_namespaces.length; i < n; i++) { - ns2 = XMLARRAY_MEMBER(&xml->xml_namespaces, i, JSXMLNamespace); - if (ns2 && ns2->prefix && - !js_CompareStrings(ns2->prefix, ns->prefix)) { - match = ns2; - m = i; - break; - } - } - if (match && js_CompareStrings(match->uri, ns->uri)) { - ns2 = XMLARRAY_DELETE(cx, &xml->xml_namespaces, m, JS_TRUE, - JSXMLNamespace); - JS_ASSERT(ns2 == match); - match->prefix = NULL; - if (!AddInScopeNamespace(cx, xml, match)) - return JS_FALSE; - } - if (!XMLARRAY_APPEND(cx, &xml->xml_namespaces, ns)) - return JS_FALSE; - } - - /* OPTION: enforce that descendants have superset namespaces. */ - return JS_TRUE; -} - -/* ECMA-357 9.2.1.6 XMLList [[Append]]. */ -static JSBool -Append(JSContext *cx, JSXML *list, JSXML *xml) -{ - uint32 i, j, k, n; - JSXML *kid; - - JS_ASSERT(list->xml_class == JSXML_CLASS_LIST); - i = list->xml_kids.length; - n = 1; - if (xml->xml_class == JSXML_CLASS_LIST) { - list->xml_target = xml->xml_target; - list->xml_targetprop = xml->xml_targetprop; - n = JSXML_LENGTH(xml); - k = i + n; - if (!XMLArraySetCapacity(cx, &list->xml_kids, k)) - return JS_FALSE; - for (j = 0; j < n; j++) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, j, JSXML); - if (kid) - XMLARRAY_SET_MEMBER(&list->xml_kids, i + j, kid); - } - return JS_TRUE; - } - - list->xml_target = xml->parent; - if (xml->xml_class == JSXML_CLASS_PROCESSING_INSTRUCTION) - list->xml_targetprop = NULL; - else - list->xml_targetprop = xml->name; - if (!XMLARRAY_ADD_MEMBER(cx, &list->xml_kids, i, xml)) - return JS_FALSE; - return JS_TRUE; -} - -/* ECMA-357 9.1.1.7 XML [[DeepCopy]] and 9.2.1.7 XMLList [[DeepCopy]]. */ -static JSXML * -DeepCopyInLRS(JSContext *cx, JSXML *xml, uintN flags); - -static JSXML * -DeepCopy(JSContext *cx, JSXML *xml, JSObject *obj, uintN flags) -{ - JSXML *copy; - JSBool ok; - - /* Our caller may not be protecting newborns with a local root scope. */ - if (!JS_EnterLocalRootScope(cx)) - return NULL; - copy = DeepCopyInLRS(cx, xml, flags); - if (copy) { - if (obj) { - /* Caller provided the object for this copy, hook 'em up. */ - ok = JS_SetPrivate(cx, obj, copy); - if (ok) - copy->object = obj; - } else { - ok = js_GetXMLObject(cx, copy) != NULL; - } - if (!ok) - copy = NULL; - } - JS_LeaveLocalRootScope(cx); - return copy; -} - -/* - * (i) We must be in a local root scope (InLRS). - * (ii) parent must have a rooted object. - * (iii) from's owning object must be locked if not thread-local. - */ -static JSBool -DeepCopySetInLRS(JSContext *cx, JSXMLArray *from, JSXMLArray *to, JSXML *parent, - uintN flags) -{ - uint32 j, n; - JSXMLArrayCursor cursor; - JSBool ok; - JSXML *kid, *kid2; - JSString *str; - - JS_ASSERT(cx->localRootStack); - - n = from->length; - if (!XMLArraySetCapacity(cx, to, n)) - return JS_FALSE; - - XMLArrayCursorInit(&cursor, from); - j = 0; - ok = JS_TRUE; - while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) { - if ((flags & XSF_IGNORE_COMMENTS) && - kid->xml_class == JSXML_CLASS_COMMENT) { - continue; - } - if ((flags & XSF_IGNORE_PROCESSING_INSTRUCTIONS) && - kid->xml_class == JSXML_CLASS_PROCESSING_INSTRUCTION) { - continue; - } - if ((flags & XSF_IGNORE_WHITESPACE) && - (kid->xml_flags & XMLF_WHITESPACE_TEXT)) { - continue; - } - kid2 = DeepCopyInLRS(cx, kid, flags); - if (!kid2) { - to->length = j; - ok = JS_FALSE; - break; - } - - if ((flags & XSF_IGNORE_WHITESPACE) && - n > 1 && kid2->xml_class == JSXML_CLASS_TEXT) { - str = ChompXMLWhitespace(cx, kid2->xml_value); - if (!str) { - to->length = j; - ok = JS_FALSE; - break; - } - kid2->xml_value = str; - } - - XMLARRAY_SET_MEMBER(to, j, kid2); - ++j; - if (parent->xml_class != JSXML_CLASS_LIST) - kid2->parent = parent; - } - XMLArrayCursorFinish(&cursor); - if (!ok) - return JS_FALSE; - - if (j < n) - XMLArrayTrim(to); - return JS_TRUE; -} - -static JSXML * -DeepCopyInLRS(JSContext *cx, JSXML *xml, uintN flags) -{ - JSXML *copy; - JSXMLQName *qn; - JSBool ok; - uint32 i, n; - JSXMLNamespace *ns, *ns2; - - /* Our caller must be protecting newborn objects. */ - JS_ASSERT(cx->localRootStack); - - copy = js_NewXML(cx, xml->xml_class); - if (!copy) - return NULL; - qn = xml->name; - if (qn) { - qn = js_NewXMLQName(cx, qn->uri, qn->prefix, qn->localName); - if (!qn) { - ok = JS_FALSE; - goto out; - } - } - copy->name = qn; - copy->xml_flags = xml->xml_flags; - - if (JSXML_HAS_VALUE(xml)) { - copy->xml_value = xml->xml_value; - ok = JS_TRUE; - } else { - ok = DeepCopySetInLRS(cx, &xml->xml_kids, ©->xml_kids, copy, flags); - if (!ok) - goto out; - - if (xml->xml_class == JSXML_CLASS_LIST) { - copy->xml_target = xml->xml_target; - copy->xml_targetprop = xml->xml_targetprop; - } else { - n = xml->xml_namespaces.length; - ok = XMLArraySetCapacity(cx, ©->xml_namespaces, n); - if (!ok) - goto out; - for (i = 0; i < n; i++) { - ns = XMLARRAY_MEMBER(&xml->xml_namespaces, i, JSXMLNamespace); - if (!ns) - continue; - ns2 = js_NewXMLNamespace(cx, ns->prefix, ns->uri, ns->declared); - if (!ns2) { - copy->xml_namespaces.length = i; - ok = JS_FALSE; - goto out; - } - XMLARRAY_SET_MEMBER(©->xml_namespaces, i, ns2); - } - - ok = DeepCopySetInLRS(cx, &xml->xml_attrs, ©->xml_attrs, copy, - 0); - if (!ok) - goto out; - } - } - -out: - if (!ok) - return NULL; - return copy; -} - -static void -ReportBadXMLName(JSContext *cx, jsval id) -{ - JSString *name; - - name = js_DecompileValueGenerator(cx, JSDVG_IGNORE_STACK, id, NULL); - if (name) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_XML_NAME, - JS_GetStringBytes(name)); - } -} - -/* ECMA-357 9.1.1.4 XML [[DeleteByIndex]]. */ -static JSBool -DeleteByIndex(JSContext *cx, JSXML *xml, jsval id, jsval *vp) -{ - uint32 index; - JSXML *kid; - - if (!js_IdIsIndex(id, &index)) { - ReportBadXMLName(cx, id); - return JS_FALSE; - } - - if (JSXML_HAS_KIDS(xml) && index < xml->xml_kids.length) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, index, JSXML); - if (kid) - kid->parent = NULL; - XMLArrayDelete(cx, &xml->xml_kids, index, JS_TRUE); - } - - *vp = JSVAL_TRUE; - return JS_TRUE; -} - -typedef JSBool (*JSXMLNameMatcher)(JSXMLQName *nameqn, JSXML *xml); - -static JSBool -MatchAttrName(JSXMLQName *nameqn, JSXML *attr) -{ - JSXMLQName *attrqn = attr->name; - - return (IS_STAR(nameqn->localName) || - !js_CompareStrings(attrqn->localName, nameqn->localName)) && - (!nameqn->uri || - !js_CompareStrings(attrqn->uri, nameqn->uri)); -} - -static JSBool -MatchElemName(JSXMLQName *nameqn, JSXML *elem) -{ - return (IS_STAR(nameqn->localName) || - (elem->xml_class == JSXML_CLASS_ELEMENT && - !js_CompareStrings(elem->name->localName, nameqn->localName))) && - (!nameqn->uri || - (elem->xml_class == JSXML_CLASS_ELEMENT && - !js_CompareStrings(elem->name->uri, nameqn->uri))); -} - -/* ECMA-357 9.1.1.8 XML [[Descendants]] and 9.2.1.8 XMLList [[Descendants]]. */ -static JSBool -DescendantsHelper(JSContext *cx, JSXML *xml, JSXMLQName *nameqn, JSXML *list) -{ - uint32 i, n; - JSXML *attr, *kid; - - if (xml->xml_class == JSXML_CLASS_ELEMENT && - OBJ_GET_CLASS(cx, nameqn->object) == &js_AttributeNameClass) { - for (i = 0, n = xml->xml_attrs.length; i < n; i++) { - attr = XMLARRAY_MEMBER(&xml->xml_attrs, i, JSXML); - if (attr && MatchAttrName(nameqn, attr)) { - if (!Append(cx, list, attr)) - return JS_FALSE; - } - } - } - - for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (!kid) - continue; - if (OBJ_GET_CLASS(cx, nameqn->object) != &js_AttributeNameClass && - MatchElemName(nameqn, kid)) { - if (!Append(cx, list, kid)) - return JS_FALSE; - } - if (!DescendantsHelper(cx, kid, nameqn, list)) - return JS_FALSE; - } - return JS_TRUE; -} - -static JSXML * -Descendants(JSContext *cx, JSXML *xml, jsval id) -{ - jsid funid; - JSXMLQName *nameqn; - JSObject *listobj; - JSXML *list, *kid; - uint32 i, n; - JSBool ok; - - nameqn = ToXMLName(cx, id, &funid); - if (!nameqn) - return NULL; - - listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST); - if (!listobj) - return NULL; - list = (JSXML *) JS_GetPrivate(cx, listobj); - if (funid) - return list; - - /* - * Protect nameqn's object and strings from GC by linking list to it - * temporarily. The cx->newborn[GCX_OBJECT] GC root protects listobj, - * which protects list. Any other object allocations occuring beneath - * DescendantsHelper use local roots. - */ - list->name = nameqn; - if (!JS_EnterLocalRootScope(cx)) - return NULL; - if (xml->xml_class == JSXML_CLASS_LIST) { - ok = JS_TRUE; - for (i = 0, n = xml->xml_kids.length; i < n; i++) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (kid && kid->xml_class == JSXML_CLASS_ELEMENT) { - ok = DescendantsHelper(cx, kid, nameqn, list); - if (!ok) - break; - } - } - } else { - ok = DescendantsHelper(cx, xml, nameqn, list); - } - JS_LeaveLocalRootScope(cx); - if (!ok) - return NULL; - list->name = NULL; - return list; -} - -static JSBool -xml_equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp); - -/* Recursive (JSXML *) parameterized version of Equals. */ -static JSBool -XMLEquals(JSContext *cx, JSXML *xml, JSXML *vxml, JSBool *bp) -{ - JSXMLQName *qn, *vqn; - uint32 i, j, n; - JSXMLArrayCursor cursor, vcursor; - JSXML *kid, *vkid, *attr, *vattr; - JSBool ok; - JSObject *xobj, *vobj; - -retry: - if (xml->xml_class != vxml->xml_class) { - if (xml->xml_class == JSXML_CLASS_LIST && xml->xml_kids.length == 1) { - xml = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML); - if (xml) - goto retry; - } - if (vxml->xml_class == JSXML_CLASS_LIST && vxml->xml_kids.length == 1) { - vxml = XMLARRAY_MEMBER(&vxml->xml_kids, 0, JSXML); - if (vxml) - goto retry; - } - *bp = JS_FALSE; - return JS_TRUE; - } - - qn = xml->name; - vqn = vxml->name; - if (qn) { - *bp = vqn && - !js_CompareStrings(qn->localName, vqn->localName) && - !js_CompareStrings(qn->uri, vqn->uri); - } else { - *bp = vqn == NULL; - } - if (!*bp) - return JS_TRUE; - - if (JSXML_HAS_VALUE(xml)) { - *bp = !js_CompareStrings(xml->xml_value, vxml->xml_value); - } else if (xml->xml_kids.length != vxml->xml_kids.length) { - *bp = JS_FALSE; - } else { - XMLArrayCursorInit(&cursor, &xml->xml_kids); - XMLArrayCursorInit(&vcursor, &vxml->xml_kids); - for (;;) { - kid = (JSXML *) XMLArrayCursorNext(&cursor); - vkid = (JSXML *) XMLArrayCursorNext(&vcursor); - if (!kid || !vkid) { - *bp = !kid && !vkid; - ok = JS_TRUE; - break; - } - xobj = js_GetXMLObject(cx, kid); - vobj = js_GetXMLObject(cx, vkid); - ok = xobj && vobj && - xml_equality(cx, xobj, OBJECT_TO_JSVAL(vobj), bp); - if (!ok || !*bp) - break; - } - XMLArrayCursorFinish(&vcursor); - XMLArrayCursorFinish(&cursor); - if (!ok) - return JS_FALSE; - - if (*bp && xml->xml_class == JSXML_CLASS_ELEMENT) { - n = xml->xml_attrs.length; - if (n != vxml->xml_attrs.length) - *bp = JS_FALSE; - for (i = 0; *bp && i < n; i++) { - attr = XMLARRAY_MEMBER(&xml->xml_attrs, i, JSXML); - if (!attr) - continue; - j = XMLARRAY_FIND_MEMBER(&vxml->xml_attrs, attr, attr_identity); - if (j == XML_NOT_FOUND) { - *bp = JS_FALSE; - break; - } - vattr = XMLARRAY_MEMBER(&vxml->xml_attrs, j, JSXML); - if (!vattr) - continue; - *bp = !js_CompareStrings(attr->xml_value, vattr->xml_value); - } - } - } - - return JS_TRUE; -} - -/* ECMA-357 9.1.1.9 XML [[Equals]] and 9.2.1.9 XMLList [[Equals]]. */ -static JSBool -Equals(JSContext *cx, JSXML *xml, jsval v, JSBool *bp) -{ - JSObject *vobj; - JSXML *vxml; - - if (JSVAL_IS_PRIMITIVE(v)) { - *bp = JS_FALSE; - if (xml->xml_class == JSXML_CLASS_LIST) { - if (xml->xml_kids.length == 1) { - vxml = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML); - if (!vxml) - return JS_TRUE; - vobj = js_GetXMLObject(cx, vxml); - if (!vobj) - return JS_FALSE; - return js_XMLObjectOps.equality(cx, vobj, v, bp); - } - if (JSVAL_IS_VOID(v) && xml->xml_kids.length == 0) - *bp = JS_TRUE; - } - } else { - vobj = JSVAL_TO_OBJECT(v); - if (!OBJECT_IS_XML(cx, vobj)) { - *bp = JS_FALSE; - } else { - vxml = (JSXML *) JS_GetPrivate(cx, vobj); - if (!XMLEquals(cx, xml, vxml, bp)) - return JS_FALSE; - } - } - return JS_TRUE; -} - -static JSBool -CheckCycle(JSContext *cx, JSXML *xml, JSXML *kid) -{ - JS_ASSERT(kid->xml_class != JSXML_CLASS_LIST); - - do { - if (xml == kid) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_CYCLIC_VALUE, js_XML_str); - return JS_FALSE; - } - } while ((xml = xml->parent) != NULL); - - return JS_TRUE; -} - -/* ECMA-357 9.1.1.11 XML [[Insert]]. */ -static JSBool -Insert(JSContext *cx, JSXML *xml, uint32 i, jsval v) -{ - uint32 j, n; - JSXML *vxml, *kid; - JSObject *vobj; - JSString *str; - - if (!JSXML_HAS_KIDS(xml)) - return JS_TRUE; - - n = 1; - vxml = NULL; - if (!JSVAL_IS_PRIMITIVE(v)) { - vobj = JSVAL_TO_OBJECT(v); - if (OBJECT_IS_XML(cx, vobj)) { - vxml = (JSXML *) JS_GetPrivate(cx, vobj); - if (vxml->xml_class == JSXML_CLASS_LIST) { - n = vxml->xml_kids.length; - if (n == 0) - return JS_TRUE; - for (j = 0; j < n; j++) { - kid = XMLARRAY_MEMBER(&vxml->xml_kids, j, JSXML); - if (!kid) - continue; - if (!CheckCycle(cx, xml, kid)) - return JS_FALSE; - } - } else if (vxml->xml_class == JSXML_CLASS_ELEMENT) { - /* OPTION: enforce that descendants have superset namespaces. */ - if (!CheckCycle(cx, xml, vxml)) - return JS_FALSE; - } - } - } - if (!vxml) { - str = js_ValueToString(cx, v); - if (!str) - return JS_FALSE; - - vxml = js_NewXML(cx, JSXML_CLASS_TEXT); - if (!vxml) - return JS_FALSE; - vxml->xml_value = str; - } - - if (i > xml->xml_kids.length) - i = xml->xml_kids.length; - - if (!XMLArrayInsert(cx, &xml->xml_kids, i, n)) - return JS_FALSE; - - if (vxml->xml_class == JSXML_CLASS_LIST) { - for (j = 0; j < n; j++) { - kid = XMLARRAY_MEMBER(&vxml->xml_kids, j, JSXML); - if (!kid) - continue; - kid->parent = xml; - XMLARRAY_SET_MEMBER(&xml->xml_kids, i + j, kid); - - /* OPTION: enforce that descendants have superset namespaces. */ - } - } else { - vxml->parent = xml; - XMLARRAY_SET_MEMBER(&xml->xml_kids, i, vxml); - } - return JS_TRUE; -} - -static JSBool -IndexToIdVal(JSContext *cx, uint32 index, jsval *idvp) -{ - JSString *str; - - if (index <= JSVAL_INT_MAX) { - *idvp = INT_TO_JSVAL(index); - } else { - str = js_NumberToString(cx, (jsdouble) index); - if (!str) - return JS_FALSE; - *idvp = STRING_TO_JSVAL(str); - } - return JS_TRUE; -} - -/* ECMA-357 9.1.1.12 XML [[Replace]]. */ -static JSBool -Replace(JSContext *cx, JSXML *xml, jsval id, jsval v) -{ - uint32 i, n; - JSXML *vxml, *kid; - JSObject *vobj; - jsval junk; - JSString *str; - - if (!JSXML_HAS_KIDS(xml)) - return JS_TRUE; - - if (!js_IdIsIndex(id, &i)) { - ReportBadXMLName(cx, id); - return JS_FALSE; - } - - /* - * 9.1.1.12 - * [[Replace]] handles _i >= x.[[Length]]_ by incrementing _x.[[Length]_. - * It should therefore constrain callers to pass in _i <= x.[[Length]]_. - */ - n = xml->xml_kids.length; - if (i >= n) { - if (!IndexToIdVal(cx, n, &id)) - return JS_FALSE; - i = n; - } - - vxml = NULL; - if (!JSVAL_IS_PRIMITIVE(v)) { - vobj = JSVAL_TO_OBJECT(v); - if (OBJECT_IS_XML(cx, vobj)) - vxml = (JSXML *) JS_GetPrivate(cx, vobj); - } - - switch (vxml ? vxml->xml_class : JSXML_CLASS_LIMIT) { - case JSXML_CLASS_ELEMENT: - /* OPTION: enforce that descendants have superset namespaces. */ - if (!CheckCycle(cx, xml, vxml)) - return JS_FALSE; - case JSXML_CLASS_COMMENT: - case JSXML_CLASS_PROCESSING_INSTRUCTION: - case JSXML_CLASS_TEXT: - goto do_replace; - - case JSXML_CLASS_LIST: - if (i < n && !DeleteByIndex(cx, xml, id, &junk)) - return JS_FALSE; - if (!Insert(cx, xml, i, v)) - return JS_FALSE; - break; - - default: - str = js_ValueToString(cx, v); - if (!str) - return JS_FALSE; - - vxml = js_NewXML(cx, JSXML_CLASS_TEXT); - if (!vxml) - return JS_FALSE; - vxml->xml_value = str; - - do_replace: - vxml->parent = xml; - if (i < n) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (kid) - kid->parent = NULL; - } - if (!XMLARRAY_ADD_MEMBER(cx, &xml->xml_kids, i, vxml)) - return JS_FALSE; - break; - } - - return JS_TRUE; -} - -/* Forward declared -- its implementation uses other statics that call it. */ -static JSBool -ResolveValue(JSContext *cx, JSXML *list, JSXML **result); - -/* ECMA-357 9.1.1.3 XML [[Delete]], 9.2.1.3 XML [[Delete]]. */ -static JSBool -DeleteProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - JSXML *xml, *kid, *parent; - JSBool isIndex; - JSXMLArray *array; - uint32 length, index, deleteCount; - JSXMLQName *nameqn; - jsid funid; - JSObject *nameobj, *kidobj; - JSXMLNameMatcher matcher; - - xml = (JSXML *) JS_GetPrivate(cx, obj); - isIndex = js_IdIsIndex(id, &index); - if (JSXML_HAS_KIDS(xml)) { - array = &xml->xml_kids; - length = array->length; - } else { - array = NULL; - length = 0; - } - - if (xml->xml_class == JSXML_CLASS_LIST) { - /* ECMA-357 9.2.1.3. */ - if (isIndex && index < length) { - kid = XMLARRAY_MEMBER(array, index, JSXML); - if (!kid) - goto out; - parent = kid->parent; - if (parent) { - JS_ASSERT(parent != xml); - JS_ASSERT(JSXML_HAS_KIDS(parent)); - - if (kid->xml_class == JSXML_CLASS_ATTRIBUTE) { - nameqn = kid->name; - nameobj = js_GetAttributeNameObject(cx, nameqn); - if (!nameobj || !js_GetXMLObject(cx, parent)) - return JS_FALSE; - - id = OBJECT_TO_JSVAL(nameobj); - if (!DeleteProperty(cx, parent->object, id, vp)) - return JS_FALSE; - } else { - index = XMLARRAY_FIND_MEMBER(&parent->xml_kids, kid, NULL); - JS_ASSERT(index != XML_NOT_FOUND); - if (!IndexToIdVal(cx, index, &id)) - return JS_FALSE; - if (!DeleteByIndex(cx, parent, id, vp)) - return JS_FALSE; - } - } - - XMLArrayDelete(cx, array, index, JS_TRUE); - } else { - for (index = 0; index < length; index++) { - kid = XMLARRAY_MEMBER(array, index, JSXML); - if (kid && kid->xml_class == JSXML_CLASS_ELEMENT) { - kidobj = js_GetXMLObject(cx, kid); - if (!kidobj || !DeleteProperty(cx, kidobj, id, vp)) - return JS_FALSE; - } - } - } - } else { - /* ECMA-357 9.1.1.3. */ - if (isIndex) { - /* See NOTE in spec: this variation is reserved for future use. */ - ReportBadXMLName(cx, id); - return JS_FALSE; - } - - nameqn = ToXMLName(cx, id, &funid); - if (!nameqn) - return JS_FALSE; - if (funid) - goto out; - nameobj = nameqn->object; - - if (OBJ_GET_CLASS(cx, nameobj) == &js_AttributeNameClass) { - if (xml->xml_class != JSXML_CLASS_ELEMENT) - goto out; - array = &xml->xml_attrs; - length = array->length; - matcher = MatchAttrName; - } else { - matcher = MatchElemName; - } - if (length != 0) { - deleteCount = 0; - for (index = 0; index < length; index++) { - kid = XMLARRAY_MEMBER(array, index, JSXML); - if (kid && matcher(nameqn, kid)) { - kid->parent = NULL; - XMLArrayDelete(cx, array, index, JS_FALSE); - ++deleteCount; - } else if (deleteCount != 0) { - XMLARRAY_SET_MEMBER(array, - index - deleteCount, - array->vector[index]); - } - } - array->length -= deleteCount; - } - } - -out: - *vp = JSVAL_TRUE; - return JS_TRUE; -} - -/* - * Class compatibility mask flag bits stored in xml_methods[i].extra. If XML - * and XMLList are unified (an incompatible change to ECMA-357), then we don't - * need any of this. - */ -#define XML_MASK 0x1 -#define XMLLIST_MASK 0x2 -#define GENERIC_MASK (XML_MASK | XMLLIST_MASK) -#define CLASS_TO_MASK(c) (1 + ((c) == JSXML_CLASS_LIST)) - -static JSBool -GetFunction(JSContext *cx, JSObject *obj, JSXML *xml, jsid id, jsval *vp) -{ - JSFunction *fun; - - do { - /* XXXbe really want a separate scope for function::*. */ - if (!js_GetProperty(cx, obj, id, vp)) - return JS_FALSE; - if (JSVAL_IS_FUNCTION(cx, *vp)) { - if (xml && OBJECT_IS_XML(cx, obj)) { - fun = (JSFunction *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(*vp)); - if (fun->spare && - (fun->spare & CLASS_TO_MASK(xml->xml_class)) == 0) { - /* XML method called on XMLList or vice versa. */ - *vp = JSVAL_VOID; - } - } - break; - } - } while ((obj = OBJ_GET_PROTO(cx, obj)) != NULL); - return JS_TRUE; -} - -static JSBool -SyncInScopeNamespaces(JSContext *cx, JSXML *xml) -{ - JSXMLArray *nsarray; - uint32 i, n; - JSXMLNamespace *ns; - - nsarray = &xml->xml_namespaces; - while ((xml = xml->parent) != NULL) { - for (i = 0, n = xml->xml_namespaces.length; i < n; i++) { - ns = XMLARRAY_MEMBER(&xml->xml_namespaces, i, JSXMLNamespace); - if (ns && !XMLARRAY_HAS_MEMBER(nsarray, ns, namespace_identity)) { - if (!XMLARRAY_APPEND(cx, nsarray, ns)) - return JS_FALSE; - } - } - } - return JS_TRUE; -} - -/* ECMA-357 9.1.1.1 XML [[Get]] and 9.2.1.1 XMLList [[Get]]. */ -static JSBool -GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - JSXML *xml, *list, *kid; - uint32 index; - JSObject *kidobj, *listobj, *nameobj; - JSXMLQName *nameqn; - jsid funid; - JSBool ok; - JSXMLArrayCursor cursor; - jsval kidval; - JSXMLArray *array; - JSXMLNameMatcher matcher; - - xml = (JSXML *) JS_GetInstancePrivate(cx, obj, &js_XMLClass, NULL); - if (!xml) - return JS_TRUE; - -#ifdef __GNUC__ - list = NULL; /* quell GCC overwarning */ -#endif - -retry: - if (xml->xml_class == JSXML_CLASS_LIST) { - /* ECMA-357 9.2.1.1 starts here. */ - if (js_IdIsIndex(id, &index)) { - /* - * Erratum: 9.2 is not completely clear that indexed properties - * correspond to kids, but that's what it seems to say, and it's - * what any sane user would want. - */ - if (index < xml->xml_kids.length) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, index, JSXML); - if (!kid) { - *vp = JSVAL_VOID; - return JS_TRUE; - } - kidobj = js_GetXMLObject(cx, kid); - if (!kidobj) - return JS_FALSE; - - *vp = OBJECT_TO_JSVAL(kidobj); - } else { - *vp = JSVAL_VOID; - } - return JS_TRUE; - } - - nameqn = ToXMLName(cx, id, &funid); - if (!nameqn) - return JS_FALSE; - if (funid) - return GetFunction(cx, obj, xml, funid, vp); - - /* - * Recursion through GetProperty may allocate more list objects, so - * we make use of local root scopes here. Each new allocation will - * push the newborn onto the local root stack. - */ - ok = JS_EnterLocalRootScope(cx); - if (!ok) - return JS_FALSE; - - /* - * NB: nameqn is already protected from GC by cx->newborn[GCX_OBJECT] - * until listobj is created. After that, a local root keeps listobj - * alive, and listobj's private keeps nameqn alive via targetprop. - */ - listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST); - if (!listobj) { - ok = JS_FALSE; - } else { - list = (JSXML *) JS_GetPrivate(cx, listobj); - list->xml_target = xml; - - XMLArrayCursorInit(&cursor, &xml->xml_kids); - while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) { - if (kid->xml_class == JSXML_CLASS_ELEMENT) { - kidobj = js_GetXMLObject(cx, kid); - if (!kidobj) { - ok = JS_FALSE; - break; - } - ok = GetProperty(cx, kidobj, id, &kidval); - if (!ok) - break; - kidobj = JSVAL_TO_OBJECT(kidval); - kid = (JSXML *) JS_GetPrivate(cx, kidobj); - if (JSXML_LENGTH(kid) > 0) { - ok = Append(cx, list, kid); - if (!ok) - break; - } - } - } - XMLArrayCursorFinish(&cursor); - } - } else { - /* ECMA-357 9.1.1.1 starts here. */ - if (js_IdIsIndex(id, &index)) { - obj = ToXMLList(cx, OBJECT_TO_JSVAL(obj)); - if (!obj) - return JS_FALSE; - xml = (JSXML *) JS_GetPrivate(cx, obj); - goto retry; - } - - nameqn = ToXMLName(cx, id, &funid); - if (!nameqn) - return JS_FALSE; - if (funid) - return GetFunction(cx, obj, xml, funid, vp); - nameobj = nameqn->object; - - /* - * Recursion through GetProperty may allocate more list objects, so - * we make use of local root scopes here. Each new allocation will - * push the newborn onto the local root stack. - */ - ok = JS_EnterLocalRootScope(cx); - if (!ok) - return JS_FALSE; - - listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST); - if (!listobj) { - ok = JS_FALSE; - } else { - list = (JSXML *) JS_GetPrivate(cx, listobj); - list->xml_target = xml; - - if (JSXML_HAS_KIDS(xml)) { - if (OBJ_GET_CLASS(cx, nameobj) == &js_AttributeNameClass) { - array = &xml->xml_attrs; - matcher = MatchAttrName; - } else { - array = &xml->xml_kids; - matcher = MatchElemName; - } - XMLArrayCursorInit(&cursor, array); - while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) { - if (matcher(nameqn, kid)) { - if (array == &xml->xml_kids && - kid->xml_class == JSXML_CLASS_ELEMENT) { - ok = SyncInScopeNamespaces(cx, kid); - if (!ok) - break; - } - ok = Append(cx, list, kid); - if (!ok) - break; - } - } - XMLArrayCursorFinish(&cursor); - } - } - } - - /* Common tail code for list and non-list cases. */ - JS_LeaveLocalRootScope(cx); - if (!ok) - return JS_FALSE; - - /* - * Erratum: ECMA-357 9.1.1.1 misses that [[Append]] sets the given list's - * [[TargetProperty]] to the property that is being appended. This means - * that any use of the internal [[Get]] property returns a list which, - * when used by e.g. [[Insert]] duplicates the last element matched by id. - * See bug 336921. - */ - list->xml_targetprop = nameqn; - *vp = OBJECT_TO_JSVAL(listobj); - return JS_TRUE; -} - -static JSXML * -CopyOnWrite(JSContext *cx, JSXML *xml, JSObject *obj) -{ - JS_ASSERT(xml->object != obj); - - xml = DeepCopy(cx, xml, obj, 0); - if (!xml) - return NULL; - - JS_ASSERT(xml->object == obj); - return xml; -} - -#define CHECK_COPY_ON_WRITE(cx,xml,obj) \ - (xml->object == obj ? xml : CopyOnWrite(cx, xml, obj)) - -static JSString * -KidToString(JSContext *cx, JSXML *xml, uint32 index) -{ - JSXML *kid; - JSObject *kidobj; - - kid = XMLARRAY_MEMBER(&xml->xml_kids, index, JSXML); - if (!kid) - return cx->runtime->emptyString; - kidobj = js_GetXMLObject(cx, kid); - if (!kidobj) - return NULL; - return js_ValueToString(cx, OBJECT_TO_JSVAL(kidobj)); -} - -/* ECMA-357 9.1.1.2 XML [[Put]] and 9.2.1.2 XMLList [[Put]]. */ -static JSBool -PutProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - JSBool ok, primitiveAssign; - enum { OBJ_ROOT, ID_ROOT, VAL_ROOT }; - jsval roots[3]; - JSTempValueRooter tvr; - JSXML *xml, *vxml, *rxml, *kid, *attr, *parent, *copy, *kid2, *match; - JSObject *vobj, *nameobj, *attrobj, *parentobj, *kidobj, *copyobj; - JSXMLQName *targetprop, *nameqn, *attrqn; - uint32 index, i, j, k, n, q; - jsval attrval, nsval, junk; - jsid funid; - JSString *left, *right, *space; - JSXMLNamespace *ns; - - xml = (JSXML *) JS_GetInstancePrivate(cx, obj, &js_XMLClass, NULL); - if (!xml) - return JS_TRUE; - - xml = CHECK_COPY_ON_WRITE(cx, xml, obj); - if (!xml) - return JS_FALSE; - - /* Precompute vxml for 9.2.1.2 2(c)(vii)(2-3) and 2(d) and 9.1.1.2 1. */ - vxml = NULL; - if (!JSVAL_IS_PRIMITIVE(*vp)) { - vobj = JSVAL_TO_OBJECT(*vp); - if (OBJECT_IS_XML(cx, vobj)) - vxml = (JSXML *) JS_GetPrivate(cx, vobj); - } - - /* Control flow after here must exit via label out. */ - ok = JS_EnterLocalRootScope(cx); - if (!ok) - return JS_FALSE; - roots[OBJ_ROOT] = OBJECT_TO_JSVAL(obj); - roots[ID_ROOT] = id; - roots[VAL_ROOT] = *vp; - JS_PUSH_TEMP_ROOT(cx, 3, roots, &tvr); - - if (xml->xml_class == JSXML_CLASS_LIST) { - /* ECMA-357 9.2.1.2. */ - if (js_IdIsIndex(id, &index)) { - /* Step 1 sets i to the property index. */ - i = index; - - /* 2(a-b). */ - if (xml->xml_target) { - ok = ResolveValue(cx, xml->xml_target, &rxml); - if (!ok) - goto out; - if (!rxml) - goto out; - JS_ASSERT(rxml->object); - } else { - rxml = NULL; - } - - /* 2(c). */ - if (index >= xml->xml_kids.length) { - /* 2(c)(i). */ - if (rxml) { - if (rxml->xml_class == JSXML_CLASS_LIST) { - if (rxml->xml_kids.length != 1) - goto out; - rxml = XMLARRAY_MEMBER(&rxml->xml_kids, 0, JSXML); - if (!rxml) - goto out; - ok = js_GetXMLObject(cx, rxml) != NULL; - if (!ok) - goto out; - } - - /* - * Erratum: ECMA-357 9.2.1.2 step 2(c)(ii) sets - * _y.[[Parent]] = r_ where _r_ is the result of - * [[ResolveValue]] called on _x.[[TargetObject]] in - * 2(a)(i). This can result in text parenting text: - * - * var MYXML = new XML(); - * MYXML.appendChild(new XML("Giants")); - * - * (testcase from Werner Sharp ). - * - * To match insertChildAfter, insertChildBefore, - * prependChild, and setChildren, we should silently - * do nothing in this case. - */ - if (!JSXML_HAS_KIDS(rxml)) - goto out; - } - - /* 2(c)(ii) is distributed below as several js_NewXML calls. */ - targetprop = xml->xml_targetprop; - if (!targetprop || IS_STAR(targetprop->localName)) { - /* 2(c)(iv)(1-2), out of order w.r.t. 2(c)(iii). */ - kid = js_NewXML(cx, JSXML_CLASS_TEXT); - if (!kid) - goto bad; - } else { - nameobj = js_GetXMLQNameObject(cx, targetprop); - if (!nameobj) - goto bad; - if (OBJ_GET_CLASS(cx, nameobj) == &js_AttributeNameClass) { - /* - * 2(c)(iii)(1-3). - * Note that rxml can't be null here, because target - * and targetprop are non-null. - */ - ok = GetProperty(cx, rxml->object, id, &attrval); - if (!ok) - goto out; - attrobj = JSVAL_TO_OBJECT(attrval); - attr = (JSXML *) JS_GetPrivate(cx, attrobj); - if (JSXML_LENGTH(attr) != 0) - goto out; - - kid = js_NewXML(cx, JSXML_CLASS_ATTRIBUTE); - } else { - /* 2(c)(v). */ - kid = js_NewXML(cx, JSXML_CLASS_ELEMENT); - } - if (!kid) - goto bad; - - /* An important bit of 2(c)(ii). */ - kid->name = targetprop; - } - - /* Final important bit of 2(c)(ii). */ - kid->parent = rxml; - - /* 2(c)(vi-vii). */ - i = xml->xml_kids.length; - if (kid->xml_class != JSXML_CLASS_ATTRIBUTE) { - /* - * 2(c)(vii)(1) tests whether _y.[[Parent]]_ is not null. - * y.[[Parent]] is here called kid->parent, which we know - * from 2(c)(ii) is _r_, here called rxml. So let's just - * test that! Erratum, the spec should be simpler here. - */ - if (rxml) { - JS_ASSERT(JSXML_HAS_KIDS(rxml)); - n = rxml->xml_kids.length; - j = n - 1; - if (n != 0 && i != 0) { - for (n = j, j = 0; j < n; j++) { - if (rxml->xml_kids.vector[j] == - xml->xml_kids.vector[i-1]) { - break; - } - } - } - - kidobj = js_GetXMLObject(cx, kid); - if (!kidobj) - goto bad; - ok = Insert(cx, rxml, j + 1, OBJECT_TO_JSVAL(kidobj)); - if (!ok) - goto out; - } - - /* - * 2(c)(vii)(2-3). - * Erratum: [[PropertyName]] in 2(c)(vii)(3) must be a - * typo for [[TargetProperty]]. - */ - if (vxml) { - kid->name = (vxml->xml_class == JSXML_CLASS_LIST) - ? vxml->xml_targetprop - : vxml->name; - } - } - - /* 2(c)(viii). */ - ok = Append(cx, xml, kid); - if (!ok) - goto out; - } - - /* 2(d). */ - if (!vxml || - vxml->xml_class == JSXML_CLASS_TEXT || - vxml->xml_class == JSXML_CLASS_ATTRIBUTE) { - ok = JS_ConvertValue(cx, *vp, JSTYPE_STRING, vp); - if (!ok) - goto out; - roots[VAL_ROOT] = *vp; - } - - /* 2(e). */ - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (!kid) - goto out; - parent = kid->parent; - if (kid->xml_class == JSXML_CLASS_ATTRIBUTE) { - nameobj = js_GetAttributeNameObject(cx, kid->name); - if (!nameobj) - goto bad; - id = OBJECT_TO_JSVAL(nameobj); - - if (parent) { - /* 2(e)(i). */ - parentobj = parent->object; - ok = PutProperty(cx, parentobj, id, vp); - if (!ok) - goto out; - - /* 2(e)(ii). */ - ok = GetProperty(cx, parentobj, id, vp); - if (!ok) - goto out; - attr = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(*vp)); - - /* 2(e)(iii). */ - xml->xml_kids.vector[i] = attr->xml_kids.vector[0]; - } - } - - /* 2(f). */ - else if (vxml && vxml->xml_class == JSXML_CLASS_LIST) { - /* 2(f)(i) Create a shallow copy _c_ of _V_. */ - copyobj = js_NewXMLObject(cx, JSXML_CLASS_LIST); - if (!copyobj) - goto bad; - copy = (JSXML *) JS_GetPrivate(cx, copyobj); - n = vxml->xml_kids.length; - ok = XMLArraySetCapacity(cx, ©->xml_kids, n); - if (!ok) - goto out; - for (k = 0; k < n; k++) { - kid2 = XMLARRAY_MEMBER(&vxml->xml_kids, k, JSXML); - XMLARRAY_SET_MEMBER(©->xml_kids, k, kid2); - } - - JS_ASSERT(parent != xml); - if (parent) { - q = XMLARRAY_FIND_MEMBER(&parent->xml_kids, kid, NULL); - JS_ASSERT(q != XML_NOT_FOUND); - - ok = IndexToIdVal(cx, q, &id); - if (!ok) - goto out; - ok = Replace(cx, parent, id, OBJECT_TO_JSVAL(copyobj)); - if (!ok) - goto out; - -#ifdef DEBUG - /* Erratum: this loop in the spec is useless. */ - for (j = 0, n = copy->xml_kids.length; j < n; j++) { - kid2 = XMLARRAY_MEMBER(&parent->xml_kids, q + j, JSXML); - JS_ASSERT(XMLARRAY_MEMBER(©->xml_kids, j, JSXML) - == kid2); - } -#endif - } - - /* - * 2(f)(iv-vi). - * Erratum: notice the unhandled zero-length V basis case and - * the off-by-one errors for the n != 0 cases in the spec. - */ - if (n == 0) { - XMLArrayDelete(cx, &xml->xml_kids, i, JS_TRUE); - } else { - ok = XMLArrayInsert(cx, &xml->xml_kids, i + 1, n - 1); - if (!ok) - goto out; - - for (j = 0; j < n; j++) - xml->xml_kids.vector[i + j] = copy->xml_kids.vector[j]; - } - } - - /* 2(g). */ - else if (vxml || JSXML_HAS_VALUE(kid)) { - if (parent) { - q = XMLARRAY_FIND_MEMBER(&parent->xml_kids, kid, NULL); - JS_ASSERT(q != XML_NOT_FOUND); - - ok = IndexToIdVal(cx, q, &id); - if (!ok) - goto out; - ok = Replace(cx, parent, id, *vp); - if (!ok) - goto out; - - vxml = XMLARRAY_MEMBER(&parent->xml_kids, q, JSXML); - if (!vxml) - goto out; - roots[VAL_ROOT] = *vp = OBJECT_TO_JSVAL(vxml->object); - } - - /* - * 2(g)(iii). - * Erratum: _V_ may not be of type XML, but all index-named - * properties _x[i]_ in an XMLList _x_ must be of type XML, - * according to 9.2.1.1 Overview and other places in the spec. - * - * Thanks to 2(d), we know _V_ (*vp here) is either a string - * or an XML/XMLList object. If *vp is a string, call ToXML - * on it to satisfy the constraint. - */ - if (!vxml) { - JS_ASSERT(JSVAL_IS_STRING(*vp)); - vobj = ToXML(cx, *vp); - if (!vobj) - goto bad; - roots[VAL_ROOT] = *vp = OBJECT_TO_JSVAL(vobj); - vxml = (JSXML *) JS_GetPrivate(cx, vobj); - } - XMLARRAY_SET_MEMBER(&xml->xml_kids, i, vxml); - } - - /* 2(h). */ - else { - kidobj = js_GetXMLObject(cx, kid); - if (!kidobj) - goto bad; - id = ATOM_KEY(cx->runtime->atomState.starAtom); - ok = PutProperty(cx, kidobj, id, vp); - if (!ok) - goto out; - } - } else { - /* - * 3. - * Erratum: if x.[[Length]] > 1 or [[ResolveValue]] returns null - * or an r with r.[[Length]] != 1, throw TypeError. - */ - n = JSXML_LENGTH(xml); - if (n > 1) - goto type_error; - if (n == 0) { - ok = ResolveValue(cx, xml, &rxml); - if (!ok) - goto out; - if (!rxml || JSXML_LENGTH(rxml) != 1) - goto type_error; - ok = Append(cx, xml, rxml); - if (!ok) - goto out; - } - JS_ASSERT(JSXML_LENGTH(xml) == 1); - kid = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML); - if (!kid) - goto out; - kidobj = js_GetXMLObject(cx, kid); - if (!kidobj) - goto bad; - ok = PutProperty(cx, kidobj, id, vp); - if (!ok) - goto out; - } - } else { - /* - * ECMA-357 9.1.1.2. - * Erratum: move steps 3 and 4 to before 1 and 2, to avoid wasted - * effort in ToString or [[DeepCopy]]. - */ - if (js_IdIsIndex(id, &index)) { - /* See NOTE in spec: this variation is reserved for future use. */ - ReportBadXMLName(cx, id); - goto bad; - } - - nameqn = ToXMLName(cx, id, &funid); - if (!nameqn) - goto bad; - if (funid) { - ok = js_SetProperty(cx, obj, funid, vp); - goto out; - } - nameobj = nameqn->object; - - if (JSXML_HAS_VALUE(xml)) - goto out; - - if (!vxml || - vxml->xml_class == JSXML_CLASS_TEXT || - vxml->xml_class == JSXML_CLASS_ATTRIBUTE) { - ok = JS_ConvertValue(cx, *vp, JSTYPE_STRING, vp); - if (!ok) - goto out; - } else { - rxml = DeepCopyInLRS(cx, vxml, 0); - if (!rxml || !js_GetXMLObject(cx, rxml)) - goto bad; - vxml = rxml; - *vp = OBJECT_TO_JSVAL(vxml->object); - } - roots[VAL_ROOT] = *vp; - - /* - * 6. - * Erratum: why is this done here, so early? use is way later.... - */ - ok = js_GetDefaultXMLNamespace(cx, &nsval); - if (!ok) - goto out; - - if (OBJ_GET_CLASS(cx, nameobj) == &js_AttributeNameClass) { - /* 7(a). */ - if (!js_IsXMLName(cx, OBJECT_TO_JSVAL(nameobj))) - goto out; - - /* 7(b-c). */ - if (vxml && vxml->xml_class == JSXML_CLASS_LIST) { - n = vxml->xml_kids.length; - if (n == 0) { - *vp = STRING_TO_JSVAL(cx->runtime->emptyString); - } else { - left = KidToString(cx, vxml, 0); - if (!left) - goto bad; - - space = ATOM_TO_STRING(cx->runtime->atomState.spaceAtom); - for (i = 1; i < n; i++) { - left = js_ConcatStrings(cx, left, space); - if (!left) - goto bad; - right = KidToString(cx, vxml, i); - if (!right) - goto bad; - left = js_ConcatStrings(cx, left, right); - if (!left) - goto bad; - } - - roots[VAL_ROOT] = *vp = STRING_TO_JSVAL(left); - } - } else { - ok = JS_ConvertValue(cx, *vp, JSTYPE_STRING, vp); - if (!ok) - goto out; - roots[VAL_ROOT] = *vp; - } - - /* 7(d-e). */ - match = NULL; - for (i = 0, n = xml->xml_attrs.length; i < n; i++) { - attr = XMLARRAY_MEMBER(&xml->xml_attrs, i, JSXML); - if (!attr) - continue; - attrqn = attr->name; - if (!js_CompareStrings(attrqn->localName, nameqn->localName) && - (!nameqn->uri || - !js_CompareStrings(attrqn->uri, nameqn->uri))) { - if (!match) { - match = attr; - } else { - nameobj = js_GetAttributeNameObject(cx, attrqn); - if (!nameobj) - goto bad; - - id = OBJECT_TO_JSVAL(nameobj); - ok = DeleteProperty(cx, obj, id, &junk); - if (!ok) - goto out; - --i; - } - } - } - - /* 7(f). */ - attr = match; - if (!attr) { - /* 7(f)(i-ii). */ - if (!nameqn->uri) { - left = right = cx->runtime->emptyString; - } else { - left = nameqn->uri; - right = nameqn->prefix; - } - nameqn = js_NewXMLQName(cx, left, right, nameqn->localName); - if (!nameqn) - goto bad; - - /* 7(f)(iii). */ - attr = js_NewXML(cx, JSXML_CLASS_ATTRIBUTE); - if (!attr) - goto bad; - attr->parent = xml; - attr->name = nameqn; - - /* 7(f)(iv). */ - ok = XMLARRAY_ADD_MEMBER(cx, &xml->xml_attrs, n, attr); - if (!ok) - goto out; - - /* 7(f)(v-vi). */ - ns = GetNamespace(cx, nameqn, NULL); - if (!ns) - goto bad; - ok = AddInScopeNamespace(cx, xml, ns); - if (!ok) - goto out; - } - - /* 7(g). */ - attr->xml_value = JSVAL_TO_STRING(*vp); - goto out; - } - - /* 8-9. */ - if (!js_IsXMLName(cx, OBJECT_TO_JSVAL(nameobj)) && - !IS_STAR(nameqn->localName)) { - goto out; - } - - /* 10-11. */ - id = JSVAL_VOID; - primitiveAssign = !vxml && !IS_STAR(nameqn->localName); - - /* 12. */ - k = n = xml->xml_kids.length; - kid2 = NULL; - while (k != 0) { - --k; - kid = XMLARRAY_MEMBER(&xml->xml_kids, k, JSXML); - if (kid && MatchElemName(nameqn, kid)) { - if (!JSVAL_IS_VOID(id)) { - ok = DeleteByIndex(cx, xml, id, &junk); - if (!ok) - goto out; - } - ok = IndexToIdVal(cx, k, &id); - if (!ok) - goto out; - kid2 = kid; - } - } - - /* - * Erratum: ECMA-357 specified child insertion inconsistently: - * insertChildBefore and insertChildAfter insert an arbitrary XML - * instance, and therefore can create cycles, but appendChild as - * specified by the "Overview" of 13.4.4.3 calls [[DeepCopy]] on - * its argument. But the "Semantics" in 13.4.4.3 do not include - * any [[DeepCopy]] call. - * - * Fixing this (https://bugzilla.mozilla.org/show_bug.cgi?id=312692) - * required adding cycle detection, and allowing duplicate kids to - * be created (see comment 6 in the bug). Allowing duplicate kid - * references means the loop above will delete all but the lowest - * indexed reference, and each [[DeleteByIndex]] nulls the kid's - * parent. Thus the need to restore parent here. This is covered - * by https://bugzilla.mozilla.org/show_bug.cgi?id=327564. - */ - if (kid2) { - JS_ASSERT(kid2->parent == xml || !kid2->parent); - if (!kid2->parent) - kid2->parent = xml; - } - - /* 13. */ - if (JSVAL_IS_VOID(id)) { - /* 13(a). */ - ok = IndexToIdVal(cx, n, &id); - if (!ok) - goto out; - - /* 13(b). */ - if (primitiveAssign) { - if (!nameqn->uri) { - ns = (JSXMLNamespace *) - JS_GetPrivate(cx, JSVAL_TO_OBJECT(nsval)); - left = ns->uri; - right = ns->prefix; - } else { - left = nameqn->uri; - right = nameqn->prefix; - } - nameqn = js_NewXMLQName(cx, left, right, nameqn->localName); - if (!nameqn) - goto bad; - - /* 13(b)(iii). */ - vobj = js_NewXMLObject(cx, JSXML_CLASS_ELEMENT); - if (!vobj) - goto bad; - vxml = (JSXML *) JS_GetPrivate(cx, vobj); - vxml->parent = xml; - vxml->name = nameqn; - - /* 13(b)(iv-vi). */ - ns = GetNamespace(cx, nameqn, NULL); - if (!ns) - goto bad; - ok = Replace(cx, xml, id, OBJECT_TO_JSVAL(vobj)); - if (!ok) - goto out; - ok = AddInScopeNamespace(cx, vxml, ns); - if (!ok) - goto out; - } - } - - /* 14. */ - if (primitiveAssign) { - JSXMLArrayCursor cursor; - - js_IdIsIndex(id, &index); - XMLArrayCursorInit(&cursor, &xml->xml_kids); - cursor.index = index; - kid = (JSXML *) XMLArrayCursorItem(&cursor); - if (JSXML_HAS_KIDS(kid)) { - XMLArrayFinish(cx, &kid->xml_kids); - ok = XMLArrayInit(cx, &kid->xml_kids, 1); - } - - /* 14(b-c). */ - /* XXXbe Erratum? redundant w.r.t. 7(b-c) else clause above */ - if (ok) { - ok = JS_ConvertValue(cx, *vp, JSTYPE_STRING, vp); - if (ok && !IS_EMPTY(JSVAL_TO_STRING(*vp))) { - roots[VAL_ROOT] = *vp; - if ((JSXML *) XMLArrayCursorItem(&cursor) == kid) - ok = Replace(cx, kid, JSVAL_ZERO, *vp); - } - } - XMLArrayCursorFinish(&cursor); - } else { - /* 15(a). */ - ok = Replace(cx, xml, id, *vp); - } - } - -out: - JS_POP_TEMP_ROOT(cx, &tvr); - JS_LeaveLocalRootScope(cx); - return ok; - -type_error: - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_XMLLIST_PUT, - js_ValueToPrintableString(cx, id)); -bad: - ok = JS_FALSE; - goto out; -} - -/* ECMA-357 9.1.1.10 XML [[ResolveValue]], 9.2.1.10 XMLList [[ResolveValue]]. */ -static JSBool -ResolveValue(JSContext *cx, JSXML *list, JSXML **result) -{ - JSXML *target, *base; - JSXMLQName *targetprop; - JSObject *targetpropobj; - jsval id, tv; - - /* Our caller must be protecting newborn objects. */ - JS_ASSERT(cx->localRootStack); - - if (list->xml_class != JSXML_CLASS_LIST || list->xml_kids.length != 0) { - if (!js_GetXMLObject(cx, list)) - return JS_FALSE; - *result = list; - return JS_TRUE; - } - - target = list->xml_target; - targetprop = list->xml_targetprop; - if (!target || !targetprop || IS_STAR(targetprop->localName)) { - *result = NULL; - return JS_TRUE; - } - - targetpropobj = js_GetXMLQNameObject(cx, targetprop); - if (!targetpropobj) - return JS_FALSE; - if (OBJ_GET_CLASS(cx, targetpropobj) == &js_AttributeNameClass) { - *result = NULL; - return JS_TRUE; - } - - if (!ResolveValue(cx, target, &base)) - return JS_FALSE; - if (!base) { - *result = NULL; - return JS_TRUE; - } - if (!js_GetXMLObject(cx, base)) - return JS_FALSE; - - id = OBJECT_TO_JSVAL(targetpropobj); - if (!GetProperty(cx, base->object, id, &tv)) - return JS_FALSE; - target = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(tv)); - - if (JSXML_LENGTH(target) == 0) { - if (base->xml_class == JSXML_CLASS_LIST && JSXML_LENGTH(base) > 1) { - *result = NULL; - return JS_TRUE; - } - tv = STRING_TO_JSVAL(cx->runtime->emptyString); - if (!PutProperty(cx, base->object, id, &tv)) - return JS_FALSE; - if (!GetProperty(cx, base->object, id, &tv)) - return JS_FALSE; - target = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(tv)); - } - - *result = target; - return JS_TRUE; -} - -/* - * HasProperty must be able to return a found JSProperty and the object in - * which it was found, if id is of the form function::name. For other ids, - * if they index or name an XML child, we return FOUND_XML_PROPERTY in *propp - * and null in *objp. - * - * DROP_PROPERTY helps HasProperty callers drop function properties without - * trying to drop the magic FOUND_XML_PROPERTY cookie. - */ -#define FOUND_XML_PROPERTY ((JSProperty *) 1) -#define DROP_PROPERTY(cx,pobj,prop) (((prop) != FOUND_XML_PROPERTY) \ - ? OBJ_DROP_PROPERTY(cx, pobj, prop) \ - : (void) 0) - -/* ECMA-357 9.1.1.6 XML [[HasProperty]] and 9.2.1.5 XMLList [[HasProperty]]. */ -static JSBool -HasProperty(JSContext *cx, JSObject *obj, jsval id, JSObject **objp, - JSProperty **propp) -{ - JSXML *xml, *kid; - JSXMLArrayCursor cursor; - JSObject *kidobj; - JSXMLQName *qn; - jsid funid; - JSXMLArray *array; - JSXMLNameMatcher matcher; - uint32 i, n; - - *objp = NULL; - *propp = NULL; - - xml = (JSXML *) JS_GetPrivate(cx, obj); - if (xml->xml_class == JSXML_CLASS_LIST) { - n = JSXML_LENGTH(xml); - if (js_IdIsIndex(id, &i)) { - if (i < n) - *propp = FOUND_XML_PROPERTY; - return JS_TRUE; - } - - XMLArrayCursorInit(&cursor, &xml->xml_kids); - while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) { - if (kid->xml_class == JSXML_CLASS_ELEMENT) { - kidobj = js_GetXMLObject(cx, kid); - if (!kidobj || !HasProperty(cx, kidobj, id, objp, propp)) - break; - if (*propp) - break; - } - } - XMLArrayCursorFinish(&cursor); - if (kid) - return *propp != NULL; - } else { - if (xml->xml_class == JSXML_CLASS_ELEMENT && js_IdIsIndex(id, &i)) { - if (i == 0) - *propp = FOUND_XML_PROPERTY; - return JS_TRUE; - } - - qn = ToXMLName(cx, id, &funid); - if (!qn) - return JS_FALSE; - if (funid) - return js_LookupProperty(cx, obj, funid, objp, propp); - - if (xml->xml_class != JSXML_CLASS_ELEMENT) - return JS_TRUE; - - if (OBJ_GET_CLASS(cx, qn->object) == &js_AttributeNameClass) { - array = &xml->xml_attrs; - matcher = MatchAttrName; - } else { - array = &xml->xml_kids; - matcher = MatchElemName; - } - for (i = 0, n = array->length; i < n; i++) { - kid = XMLARRAY_MEMBER(array, i, JSXML); - if (kid && matcher(qn, kid)) { - *propp = FOUND_XML_PROPERTY; - return JS_TRUE; - } - } - } - - return JS_TRUE; -} - -static void -xml_finalize(JSContext *cx, JSObject *obj) -{ - JSXML *xml; - - xml = (JSXML *) JS_GetPrivate(cx, obj); - if (!xml) - return; - if (xml->object == obj) - xml->object = NULL; - UNMETER(xml_stats.livexmlobj); -} - -static void -xml_mark_vector(JSContext *cx, JSXML **vec, uint32 len, void *arg) -{ - uint32 i; - JSXML *elt; - - for (i = 0; i < len; i++) { - elt = vec[i]; - { -#ifdef GC_MARK_DEBUG - char buf[120]; - - if (elt->xml_class == JSXML_CLASS_LIST) { - strcpy(buf, js_XMLList_str); - } else if (JSXML_HAS_NAME(elt)) { - JSXMLQName *qn = elt->name; - - JS_snprintf(buf, sizeof buf, "%s::%s", - qn->uri ? JS_GetStringBytes(qn->uri) : "*", - JS_GetStringBytes(qn->localName)); - } else { - JSString *str = elt->xml_value; - size_t srclen = JSSTRING_LENGTH(str); - size_t dstlen = sizeof buf; - - if (srclen >= sizeof buf / 6) - srclen = sizeof buf / 6 - 1; - js_DeflateStringToBuffer(cx, JSSTRING_CHARS(str), srclen, - buf, &dstlen); - } -#else - const char *buf = NULL; -#endif - JS_MarkGCThing(cx, elt, buf, arg); - } - } -} - -/* - * js_XMLObjectOps.newObjectMap == js_NewObjectMap, so XML objects appear to - * be native. Therefore, xml_lookupProperty must return a valid JSProperty - * pointer parameter via *propp to signify "property found". Since the only - * call to xml_lookupProperty is via OBJ_LOOKUP_PROPERTY, and then only from - * js_FindXMLProperty (in this file) and js_FindProperty (in jsobj.c, called - * from jsinterp.c), the only time we add a JSScopeProperty here is when an - * unqualified name or XML name is being accessed. - * - * This scope property both speeds up subsequent js_Find*Property calls, and - * keeps the JSOP_NAME code in js_Interpret happy by giving it an sprop with - * (getter, setter) == (GetProperty, PutProperty). We can't use that getter - * and setter as js_XMLClass's getProperty and setProperty, because doing so - * would break the XML methods, which are function-valued properties of the - * XML.prototype object. - * - * NB: xml_deleteProperty must take care to remove any property added here. - */ -static JSBool -xml_lookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, - JSProperty **propp) -{ - JSScopeProperty *sprop; - - if (!HasProperty(cx, obj, ID_TO_VALUE(id), objp, propp)) - return JS_FALSE; - - if (*propp == FOUND_XML_PROPERTY) { - sprop = js_AddNativeProperty(cx, obj, id, GetProperty, PutProperty, - SPROP_INVALID_SLOT, JSPROP_ENUMERATE, - 0, 0); - if (!sprop) - return JS_FALSE; - - JS_LOCK_OBJ(cx, obj); - *objp = obj; - *propp = (JSProperty *) sprop; - } - return JS_TRUE; -} - -static JSBool -xml_defineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value, - JSPropertyOp getter, JSPropertyOp setter, uintN attrs, - JSProperty **propp) -{ - if (JSVAL_IS_FUNCTION(cx, value) || getter || setter || - (attrs & JSPROP_ENUMERATE) == 0 || - (attrs & (JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED))) { - return js_DefineProperty(cx, obj, id, value, getter, setter, attrs, - propp); - } - - if (!PutProperty(cx, obj, ID_TO_VALUE(id), &value)) - return JS_FALSE; - if (propp) - *propp = NULL; - return JS_TRUE; -} - -static JSBool -xml_getProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp) -{ - if (id == JS_DEFAULT_XML_NAMESPACE_ID) { - *vp = JSVAL_VOID; - return JS_TRUE; - } - - return GetProperty(cx, obj, ID_TO_VALUE(id), vp); -} - -static JSBool -xml_setProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp) -{ - return PutProperty(cx, obj, ID_TO_VALUE(id), vp); -} - -static JSBool -FoundProperty(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop, - JSBool *foundp) -{ - JSObject *pobj; - - if (prop) { - *foundp = JS_TRUE; - } else { - if (!HasProperty(cx, obj, ID_TO_VALUE(id), &pobj, &prop)) - return JS_FALSE; - if (prop) - DROP_PROPERTY(cx, pobj, prop); - *foundp = (prop != NULL); - } - return JS_TRUE; -} - -static JSBool -xml_getAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop, - uintN *attrsp) -{ - JSBool found; - - if (!FoundProperty(cx, obj, id, prop, &found)) - return JS_FALSE; - *attrsp = found ? JSPROP_ENUMERATE : 0; - return JS_TRUE; -} - -static JSBool -xml_setAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop, - uintN *attrsp) -{ - JSBool found; - - if (!FoundProperty(cx, obj, id, prop, &found)) - return JS_FALSE; - if (found) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_CANT_SET_XML_ATTRS); - } - return !found; -} - -static JSBool -xml_deleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval) -{ - /* - * If this object has its own (mutable) scope, and if id isn't an index, - * then we may have added a property to the scope in xml_lookupProperty - * for it to return to mean "found" and to provide a handle for access - * operations to call the property's getter or setter. The property also - * helps speed up unqualified accesses via the property cache, avoiding - * what amount to two HasProperty searches. - * - * But now it's time to remove any such property, to purge the property - * cache and remove the scope entry. - */ - if (OBJ_SCOPE(obj)->object == obj && !JSID_IS_INT(id)) { - if (!js_DeleteProperty(cx, obj, id, rval)) - return JS_FALSE; - } - - return DeleteProperty(cx, obj, ID_TO_VALUE(id), rval); -} - -static JSBool -xml_defaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp) -{ - JSXML *xml; - - if (hint == JSTYPE_OBJECT) { - /* Called from for..in code in js_Interpret: return an XMLList. */ - xml = (JSXML *) JS_GetPrivate(cx, obj); - if (xml->xml_class != JSXML_CLASS_LIST) { - obj = ToXMLList(cx, OBJECT_TO_JSVAL(obj)); - if (!obj) - return JS_FALSE; - } - *vp = OBJECT_TO_JSVAL(obj); - return JS_TRUE; - } - - return JS_CallFunctionName(cx, obj, js_toString_str, 0, NULL, vp); -} - -static JSBool -xml_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, - jsval *statep, jsid *idp) -{ - JSXML *xml; - uint32 length, index; - JSXMLArrayCursor *cursor; - - xml = (JSXML *) JS_GetPrivate(cx, obj); - length = JSXML_LENGTH(xml); - - switch (enum_op) { - case JSENUMERATE_INIT: - if (length == 0) { - cursor = NULL; - } else { - cursor = (JSXMLArrayCursor *) JS_malloc(cx, sizeof *cursor); - if (!cursor) - return JS_FALSE; - XMLArrayCursorInit(cursor, &xml->xml_kids); - } - *statep = PRIVATE_TO_JSVAL(cursor); - if (idp) - *idp = INT_TO_JSID(length); - break; - - case JSENUMERATE_NEXT: - cursor = JSVAL_TO_PRIVATE(*statep); - if (cursor && cursor->array && (index = cursor->index) < length) { - *idp = INT_TO_JSID(index); - cursor->index = index + 1; - break; - } - /* FALL THROUGH */ - - case JSENUMERATE_DESTROY: - cursor = JSVAL_TO_PRIVATE(*statep); - if (cursor) { - XMLArrayCursorFinish(cursor); - JS_free(cx, cursor); - } - *statep = JSVAL_NULL; - break; - } - return JS_TRUE; -} - -static JSBool -xml_hasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp) -{ - return JS_TRUE; -} - -static uint32 -xml_mark(JSContext *cx, JSObject *obj, void *arg) -{ - JSXML *xml; - - xml = (JSXML *) JS_GetPrivate(cx, obj); - JS_MarkGCThing(cx, xml, js_private_str, arg); - return js_Mark(cx, obj, arg); -} - -static void -xml_clear(JSContext *cx, JSObject *obj) -{ -} - -static JSBool -HasSimpleContent(JSXML *xml) -{ - JSXML *kid; - JSBool simple; - uint32 i, n; - -again: - switch (xml->xml_class) { - case JSXML_CLASS_COMMENT: - case JSXML_CLASS_PROCESSING_INSTRUCTION: - return JS_FALSE; - case JSXML_CLASS_LIST: - if (xml->xml_kids.length == 0) - return JS_TRUE; - if (xml->xml_kids.length == 1) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML); - if (kid) { - xml = kid; - goto again; - } - } - /* FALL THROUGH */ - default: - simple = JS_TRUE; - for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (kid && kid->xml_class == JSXML_CLASS_ELEMENT) { - simple = JS_FALSE; - break; - } - } - return simple; - } -} - -/* - * 11.2.2.1 Step 3(d) onward. - */ -static JSObject * -xml_getMethod(JSContext *cx, JSObject *obj, jsid id, jsval *vp) -{ - JSXML *xml; - JSTempValueRooter tvr; - jsval roots[2]; - enum { - FUN_ROOT = 0, - OBJ_ROOT = 1 - }; - - JS_ASSERT(JS_InstanceOf(cx, obj, &js_XMLClass, NULL)); - xml = (JSXML *) JS_GetPrivate(cx, obj); - memset(roots, 0, sizeof(roots)); - JS_PUSH_TEMP_ROOT(cx, sizeof roots / sizeof *roots, roots, &tvr); - - /* From this point the control must flow through out: or bad: */ - retry: - if (!GetFunction(cx, obj, xml, id, &roots[FUN_ROOT])) - goto bad; - if (JSVAL_IS_VOID(roots[FUN_ROOT]) && OBJECT_IS_XML(cx, obj)) { - if (xml->xml_class == JSXML_CLASS_LIST) { - if (xml->xml_kids.length == 1) { - xml = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML); - if (xml) { - obj = js_GetXMLObject(cx, xml); - if (!obj) - goto bad; - roots[OBJ_ROOT] = OBJECT_TO_JSVAL(obj); - goto retry; - } - } - } else if (HasSimpleContent(xml)) { - JSString *str; - - str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); - if (!str) - goto bad; - if (!js_ValueToObject(cx, STRING_TO_JSVAL(str), &obj)) - goto bad; - roots[OBJ_ROOT] = OBJECT_TO_JSVAL(obj); - if (!js_GetProperty(cx, obj, id, &roots[FUN_ROOT])) - goto bad; - } - } - out: - *vp = roots[FUN_ROOT]; - if (obj) { - /* - * If we just POP tvr, then it is possible that nothing roots obj, see - * bug 353165. To allow our callers to assume at least weakly rooting - * of the result, we root obj via newborn array. Similarly we root the - * value of roots[FUNCTION] since getMethod callers have a bad habit - * of passing a pointer to unrooted local value as vp. - */ - cx->newborn[GCX_OBJECT] = (JSGCThing *)obj; - cx->lastInternalResult = roots[FUN_ROOT]; - } - JS_POP_TEMP_ROOT(cx, &tvr); - return obj; - bad: - obj = NULL; - goto out; -} - -static JSBool -xml_setMethod(JSContext *cx, JSObject *obj, jsid id, jsval *vp) -{ - return js_SetProperty(cx, obj, id, vp); -} - -static JSBool -xml_enumerateValues(JSContext *cx, JSObject *obj, JSIterateOp enum_op, - jsval *statep, jsid *idp, jsval *vp) -{ - JSXML *xml, *kid; - uint32 length, index; - JSXMLArrayCursor *cursor; - JSObject *kidobj; - - xml = (JSXML *) JS_GetPrivate(cx, obj); - length = JSXML_LENGTH(xml); - JS_ASSERT(INT_FITS_IN_JSVAL(length)); - - switch (enum_op) { - case JSENUMERATE_INIT: - if (length == 0) { - cursor = NULL; - } else { - cursor = (JSXMLArrayCursor *) JS_malloc(cx, sizeof *cursor); - if (!cursor) - return JS_FALSE; - XMLArrayCursorInit(cursor, &xml->xml_kids); - } - *statep = PRIVATE_TO_JSVAL(cursor); - if (idp) - *idp = INT_TO_JSID(length); - if (vp) - *vp = JSVAL_VOID; - break; - - case JSENUMERATE_NEXT: - cursor = JSVAL_TO_PRIVATE(*statep); - if (cursor && cursor->array && (index = cursor->index) < length) { - while (!(kid = XMLARRAY_MEMBER(&xml->xml_kids, index, JSXML))) { - if (++index == length) - goto destroy; - } - kidobj = js_GetXMLObject(cx, kid); - if (!kidobj) - return JS_FALSE; - JS_ASSERT(INT_FITS_IN_JSVAL(index)); - *idp = INT_TO_JSID(index); - *vp = OBJECT_TO_JSVAL(kidobj); - cursor->index = index + 1; - break; - } - /* FALL THROUGH */ - - case JSENUMERATE_DESTROY: - cursor = JSVAL_TO_PRIVATE(*statep); - if (cursor) { - destroy: - XMLArrayCursorFinish(cursor); - JS_free(cx, cursor); - } - *statep = JSVAL_NULL; - break; - } - return JS_TRUE; -} - -static JSBool -xml_equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp) -{ - JSXML *xml, *vxml; - JSObject *vobj; - JSBool ok; - JSString *str, *vstr; - jsdouble d, d2; - - xml = (JSXML *) JS_GetPrivate(cx, obj); - vxml = NULL; - if (!JSVAL_IS_PRIMITIVE(v)) { - vobj = JSVAL_TO_OBJECT(v); - if (OBJECT_IS_XML(cx, vobj)) - vxml = (JSXML *) JS_GetPrivate(cx, vobj); - } - - if (xml->xml_class == JSXML_CLASS_LIST) { - ok = Equals(cx, xml, v, bp); - } else if (vxml) { - if (vxml->xml_class == JSXML_CLASS_LIST) { - ok = Equals(cx, vxml, OBJECT_TO_JSVAL(obj), bp); - } else { - if (((xml->xml_class == JSXML_CLASS_TEXT || - xml->xml_class == JSXML_CLASS_ATTRIBUTE) && - HasSimpleContent(vxml)) || - ((vxml->xml_class == JSXML_CLASS_TEXT || - vxml->xml_class == JSXML_CLASS_ATTRIBUTE) && - HasSimpleContent(xml))) { - ok = JS_EnterLocalRootScope(cx); - if (ok) { - str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); - vstr = js_ValueToString(cx, v); - ok = str && vstr; - if (ok) - *bp = !js_CompareStrings(str, vstr); - JS_LeaveLocalRootScope(cx); - } - } else { - ok = XMLEquals(cx, xml, vxml, bp); - } - } - } else { - ok = JS_EnterLocalRootScope(cx); - if (ok) { - if (HasSimpleContent(xml)) { - str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); - vstr = js_ValueToString(cx, v); - ok = str && vstr; - if (ok) - *bp = !js_CompareStrings(str, vstr); - } else if (JSVAL_IS_STRING(v) || JSVAL_IS_NUMBER(v)) { - str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); - if (!str) { - ok = JS_FALSE; - } else if (JSVAL_IS_STRING(v)) { - *bp = !js_CompareStrings(str, JSVAL_TO_STRING(v)); - } else { - ok = js_ValueToNumber(cx, STRING_TO_JSVAL(str), &d); - if (ok) { - d2 = JSVAL_IS_INT(v) ? JSVAL_TO_INT(v) - : *JSVAL_TO_DOUBLE(v); - *bp = JSDOUBLE_COMPARE(d, ==, d2, JS_FALSE); - } - } - } else { - *bp = JS_FALSE; - } - JS_LeaveLocalRootScope(cx); - } - } - return ok; -} - -static JSBool -xml_concatenate(JSContext *cx, JSObject *obj, jsval v, jsval *vp) -{ - JSBool ok; - JSObject *listobj, *robj; - JSXML *list, *lxml, *rxml; - - ok = JS_EnterLocalRootScope(cx); - if (!ok) - return JS_FALSE; - - listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST); - if (!listobj) { - ok = JS_FALSE; - goto out; - } - - list = (JSXML *) JS_GetPrivate(cx, listobj); - lxml = (JSXML *) JS_GetPrivate(cx, obj); - ok = Append(cx, list, lxml); - if (!ok) - goto out; - - if (VALUE_IS_XML(cx, v)) { - rxml = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v)); - } else { - robj = ToXML(cx, v); - if (!robj) { - ok = JS_FALSE; - goto out; - } - rxml = (JSXML *) JS_GetPrivate(cx, robj); - } - ok = Append(cx, list, rxml); - if (!ok) - goto out; - - *vp = OBJECT_TO_JSVAL(listobj); -out: - JS_LeaveLocalRootScope(cx); - return ok; -} - -/* Use js_NewObjectMap so XML objects satisfy OBJ_IS_NATIVE tests. */ -JS_FRIEND_DATA(JSXMLObjectOps) js_XMLObjectOps = { - { js_NewObjectMap, js_DestroyObjectMap, - xml_lookupProperty, xml_defineProperty, - xml_getProperty, xml_setProperty, - xml_getAttributes, xml_setAttributes, - xml_deleteProperty, xml_defaultValue, - xml_enumerate, js_CheckAccess, - NULL, NULL, - NULL, NULL, - NULL, xml_hasInstance, - js_SetProtoOrParent, js_SetProtoOrParent, - xml_mark, xml_clear, - NULL, NULL }, - xml_getMethod, xml_setMethod, - xml_enumerateValues, xml_equality, - xml_concatenate -}; - -static JSObjectOps * -xml_getObjectOps(JSContext *cx, JSClass *clasp) -{ - return &js_XMLObjectOps.base; -} - -JS_FRIEND_DATA(JSClass) js_XMLClass = { - js_XML_str, JSCLASS_HAS_PRIVATE, - JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, xml_finalize, - xml_getObjectOps, NULL, NULL, NULL, - NULL, NULL, NULL, NULL -}; - -static JSObject * -CallConstructorFunction(JSContext *cx, JSObject *obj, JSClass *clasp, - uintN argc, jsval *argv) -{ - JSObject *tmp; - jsval rval; - - while ((tmp = OBJ_GET_PARENT(cx, obj)) != NULL) - obj = tmp; - if (!JS_CallFunctionName(cx, obj, clasp->name, argc, argv, &rval)) - return NULL; - JS_ASSERT(!JSVAL_IS_PRIMITIVE(rval)); - return JSVAL_TO_OBJECT(rval); -} - -#define XML_METHOD_PROLOG \ - JS_BEGIN_MACRO \ - xml = (JSXML *) JS_GetInstancePrivate(cx, obj, &js_XMLClass, argv); \ - if (!xml) \ - return JS_FALSE; \ - JS_END_MACRO - -static JSBool -xml_addNamespace(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSXML *xml; - JSObject *nsobj; - JSXMLNamespace *ns; - - XML_METHOD_PROLOG; - if (xml->xml_class != JSXML_CLASS_ELEMENT) - return JS_TRUE; - xml = CHECK_COPY_ON_WRITE(cx, xml, obj); - if (!xml) - return JS_FALSE; - - nsobj = CallConstructorFunction(cx, obj, &js_NamespaceClass.base, 1, argv); - if (!nsobj) - return JS_FALSE; - argv[0] = OBJECT_TO_JSVAL(nsobj); - - ns = (JSXMLNamespace *) JS_GetPrivate(cx, nsobj); - if (!AddInScopeNamespace(cx, xml, ns)) - return JS_FALSE; - ns->declared = JS_TRUE; - *rval = OBJECT_TO_JSVAL(obj); - return JS_TRUE; -} - -static JSBool -xml_appendChild(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSXML *xml, *vxml; - jsval name, v; - JSObject *vobj; - - XML_METHOD_PROLOG; - xml = CHECK_COPY_ON_WRITE(cx, xml, obj); - if (!xml) - return JS_FALSE; - - if (!js_GetAnyName(cx, &name)) - return JS_FALSE; - - if (!GetProperty(cx, obj, name, &v)) - return JS_FALSE; - - JS_ASSERT(!JSVAL_IS_PRIMITIVE(v)); - vobj = JSVAL_TO_OBJECT(v); - JS_ASSERT(OBJECT_IS_XML(cx, vobj)); - vxml = (JSXML *) JS_GetPrivate(cx, vobj); - JS_ASSERT(vxml->xml_class == JSXML_CLASS_LIST); - - if (!IndexToIdVal(cx, vxml->xml_kids.length, &name)) - return JS_FALSE; - if (!PutProperty(cx, JSVAL_TO_OBJECT(v), name, &argv[0])) - return JS_FALSE; - - *rval = OBJECT_TO_JSVAL(obj); - return JS_TRUE; -} - -/* XML and XMLList */ -static JSBool -xml_attribute(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSXMLQName *qn; - - qn = ToAttributeName(cx, argv[0]); - if (!qn) - return JS_FALSE; - argv[0] = OBJECT_TO_JSVAL(qn->object); /* local root */ - return GetProperty(cx, obj, argv[0], rval); -} - -/* XML and XMLList */ -static JSBool -xml_attributes(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jsval name; - JSXMLQName *qn; - JSTempValueRooter tvr; - JSBool ok; - - name = ATOM_KEY(cx->runtime->atomState.starAtom); - qn = ToAttributeName(cx, name); - if (!qn) - return JS_FALSE; - name = OBJECT_TO_JSVAL(qn->object); - JS_PUSH_SINGLE_TEMP_ROOT(cx, name, &tvr); - ok = GetProperty(cx, obj, name, rval); - JS_POP_TEMP_ROOT(cx, &tvr); - return ok; -} - -/* XML and XMLList */ -static JSBool -xml_child_helper(JSContext *cx, JSObject *obj, JSXML *xml, jsval name, - jsval *rval) -{ - uint32 index; - JSXML *kid; - JSObject *kidobj; - - /* ECMA-357 13.4.4.6 */ - JS_ASSERT(xml->xml_class != JSXML_CLASS_LIST); - - if (js_IdIsIndex(name, &index)) { - if (index >= JSXML_LENGTH(xml)) { - *rval = JSVAL_VOID; - } else { - kid = XMLARRAY_MEMBER(&xml->xml_kids, index, JSXML); - if (!kid) { - *rval = JSVAL_VOID; - } else { - kidobj = js_GetXMLObject(cx, kid); - if (!kidobj) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(kidobj); - } - } - return JS_TRUE; - } - - return GetProperty(cx, obj, name, rval); -} - -static JSBool -xml_child(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSXML *xml, *list, *kid, *vxml; - JSXMLArrayCursor cursor; - jsval name, v; - JSObject *listobj, *kidobj; - - XML_METHOD_PROLOG; - name = argv[0]; - if (xml->xml_class == JSXML_CLASS_LIST) { - /* ECMA-357 13.5.4.4 */ - listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST); - if (!listobj) - return JS_FALSE; - - *rval = OBJECT_TO_JSVAL(listobj); - list = (JSXML *) JS_GetPrivate(cx, listobj); - list->xml_target = xml; - - XMLArrayCursorInit(&cursor, &xml->xml_kids); - while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) { - kidobj = js_GetXMLObject(cx, kid); - if (!kidobj) - break; - if (!xml_child_helper(cx, kidobj, kid, name, &v)) - break; - if (JSVAL_IS_VOID(v)) { - /* The property didn't exist in this kid. */ - continue; - } - - JS_ASSERT(!JSVAL_IS_PRIMITIVE(v)); - vxml = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v)); - if ((!JSXML_HAS_KIDS(vxml) || vxml->xml_kids.length != 0) && - !Append(cx, list, vxml)) { - break; - } - } - XMLArrayCursorFinish(&cursor); - return !kid; - } - - return xml_child_helper(cx, obj, xml, name, rval); -} - -static JSBool -xml_childIndex(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSXML *xml, *parent; - uint32 i, n; - - XML_METHOD_PROLOG; - parent = xml->parent; - if (!parent || xml->xml_class == JSXML_CLASS_ATTRIBUTE) { - *rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN); - return JS_TRUE; - } - for (i = 0, n = JSXML_LENGTH(parent); i < n; i++) { - if (XMLARRAY_MEMBER(&parent->xml_kids, i, JSXML) == xml) - break; - } - JS_ASSERT(i < n); - return js_NewNumberValue(cx, i, rval); -} - -/* XML and XMLList */ -static JSBool -xml_children(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jsval name; - - name = ATOM_KEY(cx->runtime->atomState.starAtom); - return GetProperty(cx, obj, name, rval); -} - -/* XML and XMLList */ -static JSBool -xml_comments(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSXML *xml, *list, *kid, *vxml; - JSObject *listobj, *kidobj; - JSBool ok; - uint32 i, n; - jsval v; - - XML_METHOD_PROLOG; - listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST); - if (!listobj) - return JS_FALSE; - - *rval = OBJECT_TO_JSVAL(listobj); - list = (JSXML *) JS_GetPrivate(cx, listobj); - list->xml_target = xml; - - ok = JS_TRUE; - - if (xml->xml_class == JSXML_CLASS_LIST) { - /* 13.5.4.6 Step 2. */ - for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (kid && kid->xml_class == JSXML_CLASS_ELEMENT) { - ok = JS_EnterLocalRootScope(cx); - if (!ok) - break; - kidobj = js_GetXMLObject(cx, kid); - ok = kidobj - ? xml_comments(cx, kidobj, argc, argv, &v) - : JS_FALSE; - JS_LeaveLocalRootScope(cx); - if (!ok) - break; - vxml = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v)); - if (JSXML_LENGTH(vxml) != 0) { - ok = Append(cx, list, vxml); - if (!ok) - break; - } - } - } - } else { - /* 13.4.4.9 Step 2. */ - for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (kid && kid->xml_class == JSXML_CLASS_COMMENT) { - ok = Append(cx, list, kid); - if (!ok) - break; - } - } - } - - return ok; -} - -/* XML and XMLList */ -static JSBool -xml_contains(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSXML *xml, *kid; - jsval value; - JSBool eq; - JSXMLArrayCursor cursor; - JSObject *kidobj; - - XML_METHOD_PROLOG; - value = argv[0]; - if (xml->xml_class == JSXML_CLASS_LIST) { - eq = JS_FALSE; - XMLArrayCursorInit(&cursor, &xml->xml_kids); - while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) { - kidobj = js_GetXMLObject(cx, kid); - if (!kidobj || !xml_equality(cx, kidobj, value, &eq)) - break; - if (eq) - break; - } - XMLArrayCursorFinish(&cursor); - if (kid) - return JS_FALSE; - } else { - if (!xml_equality(cx, obj, value, &eq)) - return JS_FALSE; - } - *rval = BOOLEAN_TO_JSVAL(eq); - return JS_TRUE; -} - -/* XML and XMLList */ -static JSBool -xml_copy(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSXML *xml, *copy; - - XML_METHOD_PROLOG; - copy = DeepCopy(cx, xml, NULL, 0); - if (!copy) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(copy->object); - return JS_TRUE; -} - -/* XML and XMLList */ -static JSBool -xml_descendants(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSXML *xml, *list; - jsval name; - - XML_METHOD_PROLOG; - name = (argc == 0) ? ATOM_KEY(cx->runtime->atomState.starAtom) : argv[0]; - list = Descendants(cx, xml, name); - if (!list) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(list->object); - return JS_TRUE; -} - -/* XML and XMLList */ -static JSBool -xml_elements(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSXML *xml, *list, *kid, *vxml; - jsval name, v; - JSXMLQName *nameqn; - jsid funid; - JSObject *listobj, *kidobj; - JSBool ok; - JSXMLArrayCursor cursor; - uint32 i, n; - - XML_METHOD_PROLOG; - name = (argc == 0) ? ATOM_KEY(cx->runtime->atomState.starAtom) : argv[0]; - nameqn = ToXMLName(cx, name, &funid); - if (!nameqn) - return JS_FALSE; - argv[0] = OBJECT_TO_JSVAL(nameqn->object); - - listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST); - if (!listobj) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(listobj); - if (funid) - return JS_TRUE; - - list = (JSXML *) JS_GetPrivate(cx, listobj); - list->xml_target = xml; - list->xml_targetprop = nameqn; - ok = JS_TRUE; - - if (xml->xml_class == JSXML_CLASS_LIST) { - /* 13.5.4.6 */ - XMLArrayCursorInit(&cursor, &xml->xml_kids); - while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) { - if (kid->xml_class == JSXML_CLASS_ELEMENT) { - ok = JS_EnterLocalRootScope(cx); - if (!ok) - break; - kidobj = js_GetXMLObject(cx, kid); - ok = kidobj - ? xml_elements(cx, kidobj, argc, argv, &v) - : JS_FALSE; - JS_LeaveLocalRootScope(cx); - if (!ok) - break; - vxml = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v)); - if (JSXML_LENGTH(vxml) != 0) { - ok = Append(cx, list, vxml); - if (!ok) - break; - } - } - } - XMLArrayCursorFinish(&cursor); - } else { - for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (kid && kid->xml_class == JSXML_CLASS_ELEMENT && - MatchElemName(nameqn, kid)) { - ok = Append(cx, list, kid); - if (!ok) - break; - } - } - } - - return ok; -} - -/* XML and XMLList */ -static JSBool -xml_hasOwnProperty(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jsval name; - JSObject *pobj; - JSProperty *prop; - - if (!JS_InstanceOf(cx, obj, &js_XMLClass, argv)) - return JS_FALSE; - - name = argv[0]; - if (!HasProperty(cx, obj, name, &pobj, &prop)) - return JS_FALSE; - if (!prop) { - return js_HasOwnPropertyHelper(cx, obj, js_LookupProperty, argc, argv, - rval); - } - DROP_PROPERTY(cx, pobj, prop); - *rval = JSVAL_TRUE; - return JS_TRUE; -} - -/* XML and XMLList */ -static JSBool -xml_hasComplexContent(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSXML *xml, *kid; - JSObject *kidobj; - uint32 i, n; - - XML_METHOD_PROLOG; -again: - switch (xml->xml_class) { - case JSXML_CLASS_ATTRIBUTE: - case JSXML_CLASS_COMMENT: - case JSXML_CLASS_PROCESSING_INSTRUCTION: - case JSXML_CLASS_TEXT: - *rval = JSVAL_FALSE; - break; - case JSXML_CLASS_LIST: - if (xml->xml_kids.length == 0) { - *rval = JSVAL_TRUE; - } else if (xml->xml_kids.length == 1) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML); - if (kid) { - kidobj = js_GetXMLObject(cx, kid); - if (!kidobj) - return JS_FALSE; - obj = kidobj; - xml = (JSXML *) JS_GetPrivate(cx, obj); - goto again; - } - } - /* FALL THROUGH */ - default: - *rval = JSVAL_FALSE; - for (i = 0, n = xml->xml_kids.length; i < n; i++) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (kid && kid->xml_class == JSXML_CLASS_ELEMENT) { - *rval = JSVAL_TRUE; - break; - } - } - break; - } - return JS_TRUE; -} - -/* XML and XMLList */ -static JSBool -xml_hasSimpleContent(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSXML *xml; - - XML_METHOD_PROLOG; - *rval = BOOLEAN_TO_JSVAL(HasSimpleContent(xml)); - return JS_TRUE; -} - -typedef struct JSTempRootedNSArray { - JSTempValueRooter tvr; - JSXMLArray array; - jsval value; /* extra root for temporaries */ -} JSTempRootedNSArray; - -JS_STATIC_DLL_CALLBACK(void) -mark_temp_ns_array(JSContext *cx, JSTempValueRooter *tvr) -{ - JSTempRootedNSArray *tmp = (JSTempRootedNSArray *)tvr; - - namespace_mark_vector(cx, - (JSXMLNamespace **)tmp->array.vector, - tmp->array.length, NULL); - XMLArrayCursorMark(cx, tmp->array.cursors); - if (JSVAL_IS_GCTHING(tmp->value)) - GC_MARK(cx, JSVAL_TO_GCTHING(tmp->value), "temp_ns_array_value", NULL); -} - -static void -InitTempNSArray(JSContext *cx, JSTempRootedNSArray *tmp) -{ - XMLArrayInit(cx, &tmp->array, 0); - tmp->value = JSVAL_NULL; - JS_PUSH_TEMP_ROOT_MARKER(cx, mark_temp_ns_array, &tmp->tvr); -} - -static void -FinishTempNSArray(JSContext *cx, JSTempRootedNSArray *tmp) -{ - JS_ASSERT(tmp->tvr.u.marker == mark_temp_ns_array); - JS_POP_TEMP_ROOT(cx, &tmp->tvr); - XMLArrayFinish(cx, &tmp->array); -} - -/* - * Populate a new JS array with elements of JSTempRootedNSArray.array and - * place the result into rval. rval must point to a rooted location. - */ -static JSBool -TempNSArrayToJSArray(JSContext *cx, JSTempRootedNSArray *tmp, jsval *rval) -{ - JSObject *arrayobj; - uint32 i, n; - JSXMLNamespace *ns; - JSObject *nsobj; - - arrayobj = js_NewArrayObject(cx, 0, NULL); - if (!arrayobj) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(arrayobj); - for (i = 0, n = tmp->array.length; i < n; i++) { - ns = XMLARRAY_MEMBER(&tmp->array, i, JSXMLNamespace); - if (!ns) - continue; - nsobj = js_GetXMLNamespaceObject(cx, ns); - if (!nsobj) - return JS_FALSE; - tmp->value = OBJECT_TO_JSVAL(nsobj); - if (!OBJ_SET_PROPERTY(cx, arrayobj, INT_TO_JSID(i), &tmp->value)) - return JS_FALSE; - } - return JS_TRUE; -} - -static JSBool -FindInScopeNamespaces(JSContext *cx, JSXML *xml, JSXMLArray *nsarray) -{ - uint32 length, i, j, n; - JSXMLNamespace *ns, *ns2; - - length = nsarray->length; - do { - if (xml->xml_class != JSXML_CLASS_ELEMENT) - continue; - for (i = 0, n = xml->xml_namespaces.length; i < n; i++) { - ns = XMLARRAY_MEMBER(&xml->xml_namespaces, i, JSXMLNamespace); - if (!ns) - continue; - - for (j = 0; j < length; j++) { - ns2 = XMLARRAY_MEMBER(nsarray, j, JSXMLNamespace); - if (ns2 && - ((ns2->prefix && ns->prefix) - ? !js_CompareStrings(ns2->prefix, ns->prefix) - : !js_CompareStrings(ns2->uri, ns->uri))) { - break; - } - } - - if (j == length) { - if (!XMLARRAY_APPEND(cx, nsarray, ns)) - return JS_FALSE; - ++length; - } - } - } while ((xml = xml->parent) != NULL); - JS_ASSERT(length == nsarray->length); - - return JS_TRUE; -} - -static JSBool -xml_inScopeNamespaces(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSXML *xml; - JSTempRootedNSArray namespaces; - JSBool ok; - - XML_METHOD_PROLOG; - - InitTempNSArray(cx, &namespaces); - ok = FindInScopeNamespaces(cx, xml, &namespaces.array) && - TempNSArrayToJSArray(cx, &namespaces, rval); - FinishTempNSArray(cx, &namespaces); - return ok; -} - -static JSBool -xml_insertChildAfter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSXML *xml, *kid; - jsval arg; - uint32 i; - - XML_METHOD_PROLOG; - if (!JSXML_HAS_KIDS(xml)) - return JS_TRUE; - - arg = argv[0]; - if (JSVAL_IS_NULL(arg)) { - kid = NULL; - i = 0; - } else { - if (!VALUE_IS_XML(cx, arg)) - return JS_TRUE; - kid = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(arg)); - i = XMLARRAY_FIND_MEMBER(&xml->xml_kids, kid, NULL); - if (i == XML_NOT_FOUND) - return JS_TRUE; - ++i; - } - - xml = CHECK_COPY_ON_WRITE(cx, xml, obj); - if (!xml) - return JS_FALSE; - if (!Insert(cx, xml, i, argv[1])) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(obj); - return JS_TRUE; -} - -static JSBool -xml_insertChildBefore(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSXML *xml, *kid; - jsval arg; - uint32 i; - - XML_METHOD_PROLOG; - if (!JSXML_HAS_KIDS(xml)) - return JS_TRUE; - - arg = argv[0]; - if (JSVAL_IS_NULL(arg)) { - kid = NULL; - i = xml->xml_kids.length; - } else { - if (!VALUE_IS_XML(cx, arg)) - return JS_TRUE; - kid = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(arg)); - i = XMLARRAY_FIND_MEMBER(&xml->xml_kids, kid, NULL); - if (i == XML_NOT_FOUND) - return JS_TRUE; - } - - xml = CHECK_COPY_ON_WRITE(cx, xml, obj); - if (!xml) - return JS_FALSE; - if (!Insert(cx, xml, i, argv[1])) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(obj); - return JS_TRUE; -} - -/* XML and XMLList */ -static JSBool -xml_length(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSXML *xml; - - XML_METHOD_PROLOG; - if (xml->xml_class != JSXML_CLASS_LIST) { - *rval = JSVAL_ONE; - } else { - if (!js_NewNumberValue(cx, xml->xml_kids.length, rval)) - return JS_FALSE; - } - return JS_TRUE; -} - -static JSBool -xml_localName(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSXML *xml; - - XML_METHOD_PROLOG; - *rval = xml->name ? STRING_TO_JSVAL(xml->name->localName) : JSVAL_NULL; - return JS_TRUE; -} - -static JSBool -xml_name(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSXML *xml; - JSObject *nameobj; - - XML_METHOD_PROLOG; - if (!xml->name) { - *rval = JSVAL_NULL; - } else { - nameobj = js_GetXMLQNameObject(cx, xml->name); - if (!nameobj) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(nameobj); - } - return JS_TRUE; -} - -static JSBool -xml_namespace(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSXML *xml; - JSString *prefix; - JSTempRootedNSArray inScopeNSes; - JSBool ok; - jsuint i, length; - JSXMLNamespace *ns; - JSObject *nsobj; - - XML_METHOD_PROLOG; - if (argc == 0 && - (xml->xml_class == JSXML_CLASS_TEXT || - xml->xml_class == JSXML_CLASS_COMMENT || - xml->xml_class == JSXML_CLASS_PROCESSING_INSTRUCTION)) { - *rval = JSVAL_NULL; - return JS_TRUE; - } - - if (argc == 0) { - prefix = NULL; - } else { - prefix = js_ValueToString(cx, argv[0]); - if (!prefix) - return JS_FALSE; - argv[0] = STRING_TO_JSVAL(prefix); /* local root */ - } - - /* After this point the control must flow through label out. */ - InitTempNSArray(cx, &inScopeNSes); - ok = FindInScopeNamespaces(cx, xml, &inScopeNSes.array); - if (!ok) - goto out; - - if (!prefix) { - ns = GetNamespace(cx, xml->name, &inScopeNSes.array); - if (!ns) { - ok = JS_FALSE; - goto out; - } - } else { - ns = NULL; - for (i = 0, length = inScopeNSes.array.length; i < length; i++) { - ns = XMLARRAY_MEMBER(&inScopeNSes.array, i, JSXMLNamespace); - if (ns && ns->prefix && !js_CompareStrings(ns->prefix, prefix)) - break; - ns = NULL; - } - } - - if (!ns) { - *rval = JSVAL_VOID; - } else { - nsobj = js_GetXMLNamespaceObject(cx, ns); - if (!nsobj) { - ok = JS_FALSE; - goto out; - } - *rval = OBJECT_TO_JSVAL(nsobj); - } - - out: - FinishTempNSArray(cx, &inScopeNSes); - return JS_TRUE; -} - -static JSBool -xml_namespaceDeclarations(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSXML *xml, *yml; - JSBool ok; - JSTempRootedNSArray ancestors, declared; - uint32 i, n; - JSXMLNamespace *ns; - - XML_METHOD_PROLOG; - if (JSXML_HAS_VALUE(xml) || xml->xml_class == JSXML_CLASS_LIST) - return JS_TRUE; - - /* From here, control flow must goto out to finish these arrays. */ - ok = JS_TRUE; - InitTempNSArray(cx, &ancestors); - InitTempNSArray(cx, &declared); - yml = xml; - - while ((yml = yml->parent) != NULL) { - JS_ASSERT(yml->xml_class == JSXML_CLASS_ELEMENT); - for (i = 0, n = yml->xml_namespaces.length; i < n; i++) { - ns = XMLARRAY_MEMBER(&yml->xml_namespaces, i, JSXMLNamespace); - if (ns && - !XMLARRAY_HAS_MEMBER(&ancestors.array, ns, namespace_match)) { - ok = XMLARRAY_APPEND(cx, &ancestors.array, ns); - if (!ok) - goto out; - } - } - } - - for (i = 0, n = xml->xml_namespaces.length; i < n; i++) { - ns = XMLARRAY_MEMBER(&xml->xml_namespaces, i, JSXMLNamespace); - if (!ns) - continue; - if (!ns->declared) - continue; - if (!XMLARRAY_HAS_MEMBER(&ancestors.array, ns, namespace_match)) { - ok = XMLARRAY_APPEND(cx, &declared.array, ns); - if (!ok) - goto out; - } - } - - ok = TempNSArrayToJSArray(cx, &declared, rval); - -out: - /* Finishing must be in reverse order of initialization to follow LIFO. */ - FinishTempNSArray(cx, &declared); - FinishTempNSArray(cx, &ancestors); - return ok; -} - -static const char js_attribute_str[] = "attribute"; -static const char js_text_str[] = "text"; - -/* Exported to jsgc.c #ifdef GC_MARK_DEBUG. */ -const char *js_xml_class_str[] = { - "list", - "element", - js_attribute_str, - "processing-instruction", - js_text_str, - "comment" -}; - -static JSBool -xml_nodeKind(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSXML *xml; - JSString *str; - - XML_METHOD_PROLOG; - str = JS_InternString(cx, js_xml_class_str[xml->xml_class]); - if (!str) - return JS_FALSE; - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -static JSBool -NormalizingDelete(JSContext *cx, JSObject *obj, JSXML *xml, jsval id) -{ - jsval junk; - - if (xml->xml_class == JSXML_CLASS_LIST) - return DeleteProperty(cx, obj, id, &junk); - return DeleteByIndex(cx, xml, id, &junk); -} - -/* - * Erratum? the testcase js/tests/e4x/XML/13.4.4.26.js wants all-whitespace - * text between tags to be removed by normalize. - */ -static JSBool -IsXMLSpace(JSString *str) -{ - const jschar *cp, *end; - - cp = JSSTRING_CHARS(str); - end = cp + JSSTRING_LENGTH(str); - while (cp < end) { - if (!JS_ISXMLSPACE(*cp)) - return JS_FALSE; - ++cp; - } - return JS_TRUE; -} - -/* XML and XMLList */ -static JSBool -xml_normalize(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSXML *xml, *kid, *kid2; - uint32 i, n; - JSObject *kidobj; - JSString *str; - jsval junk; - - XML_METHOD_PROLOG; - *rval = OBJECT_TO_JSVAL(obj); - if (!JSXML_HAS_KIDS(xml)) - return JS_TRUE; - - xml = CHECK_COPY_ON_WRITE(cx, xml, obj); - if (!xml) - return JS_FALSE; - - for (i = 0, n = xml->xml_kids.length; i < n; i++) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (!kid) - continue; - if (kid->xml_class == JSXML_CLASS_ELEMENT) { - kidobj = js_GetXMLObject(cx, kid); - if (!kidobj || !xml_normalize(cx, kidobj, argc, argv, &junk)) - return JS_FALSE; - } else if (kid->xml_class == JSXML_CLASS_TEXT) { - while (i + 1 < n && - (kid2 = XMLARRAY_MEMBER(&xml->xml_kids, i + 1, JSXML)) && - kid2->xml_class == JSXML_CLASS_TEXT) { - str = js_ConcatStrings(cx, kid->xml_value, kid2->xml_value); - if (!str) - return JS_FALSE; - if (!NormalizingDelete(cx, obj, xml, INT_TO_JSVAL(i + 1))) - return JS_FALSE; - n = xml->xml_kids.length; - kid->xml_value = str; - } - if (IS_EMPTY(kid->xml_value) || IsXMLSpace(kid->xml_value)) { - if (!NormalizingDelete(cx, obj, xml, INT_TO_JSVAL(i))) - return JS_FALSE; - n = xml->xml_kids.length; - --i; - } - } - } - - return JS_TRUE; -} - -/* XML and XMLList */ -static JSBool -xml_parent(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSXML *xml, *parent, *kid; - uint32 i, n; - JSObject *parentobj; - - XML_METHOD_PROLOG; - parent = xml->parent; - if (xml->xml_class == JSXML_CLASS_LIST) { - *rval = JSVAL_VOID; - n = xml->xml_kids.length; - if (n == 0) - return JS_TRUE; - - kid = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML); - if (!kid) - return JS_TRUE; - parent = kid->parent; - for (i = 1; i < n; i++) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (kid && kid->parent != parent) - return JS_TRUE; - } - } - - if (!parent) { - *rval = JSVAL_NULL; - return JS_TRUE; - } - - parentobj = js_GetXMLObject(cx, parent); - if (!parentobj) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(parentobj); - return JS_TRUE; -} - -/* XML and XMLList */ -static JSBool -xml_processingInstructions(JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval) -{ - JSXML *xml, *list, *kid, *vxml; - jsval name, v; - JSXMLQName *nameqn; - jsid funid; - JSObject *listobj, *kidobj; - JSBool ok; - JSXMLArrayCursor cursor; - uint32 i, n; - - XML_METHOD_PROLOG; - name = (argc == 0) ? ATOM_KEY(cx->runtime->atomState.starAtom) : argv[0]; - nameqn = ToXMLName(cx, name, &funid); - if (!nameqn) - return JS_FALSE; - argv[0] = OBJECT_TO_JSVAL(nameqn->object); - - listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST); - if (!listobj) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(listobj); - if (funid) - return JS_TRUE; - - list = (JSXML *) JS_GetPrivate(cx, listobj); - list->xml_target = xml; - list->xml_targetprop = nameqn; - ok = JS_TRUE; - - if (xml->xml_class == JSXML_CLASS_LIST) { - /* 13.5.4.17 Step 4 (misnumbered 9 -- Erratum?). */ - XMLArrayCursorInit(&cursor, &xml->xml_kids); - while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) { - if (kid->xml_class == JSXML_CLASS_ELEMENT) { - ok = JS_EnterLocalRootScope(cx); - if (!ok) - break; - kidobj = js_GetXMLObject(cx, kid); - ok = kidobj - ? xml_processingInstructions(cx, kidobj, argc, argv, &v) - : JS_FALSE; - JS_LeaveLocalRootScope(cx); - if (!ok) - break; - vxml = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v)); - if (JSXML_LENGTH(vxml) != 0) { - ok = Append(cx, list, vxml); - if (!ok) - break; - } - } - } - XMLArrayCursorFinish(&cursor); - } else { - /* 13.4.4.28 Step 4. */ - for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (kid && kid->xml_class == JSXML_CLASS_PROCESSING_INSTRUCTION && - (IS_STAR(nameqn->localName) || - !js_CompareStrings(nameqn->localName, kid->name->localName))) { - ok = Append(cx, list, kid); - if (!ok) - break; - } - } - } - - return ok; -} - -static JSBool -xml_prependChild(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSXML *xml; - - XML_METHOD_PROLOG; - xml = CHECK_COPY_ON_WRITE(cx, xml, obj); - if (!xml) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(obj); - return Insert(cx, xml, 0, argv[0]); -} - -/* XML and XMLList */ -static JSBool -xml_propertyIsEnumerable(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSXML *xml; - jsval name; - uint32 index; - - XML_METHOD_PROLOG; - name = argv[0]; - *rval = JSVAL_FALSE; - if (js_IdIsIndex(name, &index)) { - if (xml->xml_class == JSXML_CLASS_LIST) { - /* 13.5.4.18. */ - *rval = BOOLEAN_TO_JSVAL(index < xml->xml_kids.length); - } else { - /* 13.4.4.30. */ - *rval = BOOLEAN_TO_JSVAL(index == 0); - } - } - return JS_TRUE; -} - -static JSBool -namespace_full_match(const void *a, const void *b) -{ - const JSXMLNamespace *nsa = (const JSXMLNamespace *) a; - const JSXMLNamespace *nsb = (const JSXMLNamespace *) b; - - if (nsa->prefix && nsb->prefix && - js_CompareStrings(nsa->prefix, nsb->prefix)) { - return JS_FALSE; - } - return !js_CompareStrings(nsa->uri, nsb->uri); -} - -static JSBool -xml_removeNamespace_helper(JSContext *cx, JSXML *xml, JSXMLNamespace *ns) -{ - JSXMLNamespace *thisns, *attrns; - uint32 i, n; - JSXML *attr, *kid; - - thisns = GetNamespace(cx, xml->name, &xml->xml_namespaces); - JS_ASSERT(thisns); - if (thisns == ns) - return JS_TRUE; - - for (i = 0, n = xml->xml_attrs.length; i < n; i++) { - attr = XMLARRAY_MEMBER(&xml->xml_attrs, i, JSXML); - if (!attr) - continue; - attrns = GetNamespace(cx, attr->name, &xml->xml_namespaces); - JS_ASSERT(attrns); - if (attrns == ns) - return JS_TRUE; - } - - i = XMLARRAY_FIND_MEMBER(&xml->xml_namespaces, ns, namespace_full_match); - if (i != XML_NOT_FOUND) - XMLArrayDelete(cx, &xml->xml_namespaces, i, JS_TRUE); - - for (i = 0, n = xml->xml_kids.length; i < n; i++) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (kid && kid->xml_class == JSXML_CLASS_ELEMENT) { - if (!xml_removeNamespace_helper(cx, kid, ns)) - return JS_FALSE; - } - } - return JS_TRUE; -} - -static JSBool -xml_removeNamespace(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSXML *xml; - JSObject *nsobj; - JSXMLNamespace *ns; - - XML_METHOD_PROLOG; - *rval = OBJECT_TO_JSVAL(obj); - if (xml->xml_class != JSXML_CLASS_ELEMENT) - return JS_TRUE; - xml = CHECK_COPY_ON_WRITE(cx, xml, obj); - if (!xml) - return JS_FALSE; - - nsobj = CallConstructorFunction(cx, obj, &js_NamespaceClass.base, 1, argv); - if (!nsobj) - return JS_FALSE; - argv[0] = OBJECT_TO_JSVAL(nsobj); - ns = (JSXMLNamespace *) JS_GetPrivate(cx, nsobj); - - /* NOTE: remove ns from each ancestor if not used by that ancestor. */ - return xml_removeNamespace_helper(cx, xml, ns); -} - -static JSBool -xml_replace(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSXML *xml, *vxml, *kid; - jsval name, value, id, junk; - uint32 index; - JSObject *nameobj; - JSXMLQName *nameqn; - - XML_METHOD_PROLOG; - *rval = OBJECT_TO_JSVAL(obj); - if (xml->xml_class != JSXML_CLASS_ELEMENT) - return JS_TRUE; - - value = argv[1]; - vxml = VALUE_IS_XML(cx, value) - ? (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(value)) - : NULL; - if (!vxml) { - if (!JS_ConvertValue(cx, value, JSTYPE_STRING, &argv[1])) - return JS_FALSE; - value = argv[1]; - } else { - vxml = DeepCopy(cx, vxml, NULL, 0); - if (!vxml) - return JS_FALSE; - value = argv[1] = OBJECT_TO_JSVAL(vxml->object); - } - - xml = CHECK_COPY_ON_WRITE(cx, xml, obj); - if (!xml) - return JS_FALSE; - - name = argv[0]; - if (js_IdIsIndex(name, &index)) - return Replace(cx, xml, name, value); - - /* Call function QName per spec, not ToXMLName, to avoid attribute names. */ - nameobj = CallConstructorFunction(cx, obj, &js_QNameClass.base, 1, &name); - if (!nameobj) - return JS_FALSE; - argv[0] = OBJECT_TO_JSVAL(nameobj); - nameqn = (JSXMLQName *) JS_GetPrivate(cx, nameobj); - - id = JSVAL_VOID; - index = xml->xml_kids.length; - while (index != 0) { - --index; - kid = XMLARRAY_MEMBER(&xml->xml_kids, index, JSXML); - if (kid && MatchElemName(nameqn, kid)) { - if (!JSVAL_IS_VOID(id) && !DeleteByIndex(cx, xml, id, &junk)) - return JS_FALSE; - if (!IndexToIdVal(cx, index, &id)) - return JS_FALSE; - } - } - if (JSVAL_IS_VOID(id)) - return JS_TRUE; - return Replace(cx, xml, id, value); -} - -static JSBool -xml_setChildren(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - if (!PutProperty(cx, obj, ATOM_KEY(cx->runtime->atomState.starAtom), - &argv[0])) { - return JS_FALSE; - } - - *rval = OBJECT_TO_JSVAL(obj); - return JS_TRUE; -} - -static JSBool -xml_setLocalName(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSXML *xml; - jsval name; - JSXMLQName *nameqn; - JSString *namestr; - - XML_METHOD_PROLOG; - if (!JSXML_HAS_NAME(xml)) - return JS_TRUE; - - name = argv[0]; - if (!JSVAL_IS_PRIMITIVE(name) && - OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(name)) == &js_QNameClass.base) { - nameqn = (JSXMLQName *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(name)); - namestr = nameqn->localName; - } else { - if (!JS_ConvertValue(cx, name, JSTYPE_STRING, &argv[0])) - return JS_FALSE; - name = argv[0]; - namestr = JSVAL_TO_STRING(name); - } - - xml = CHECK_COPY_ON_WRITE(cx, xml, obj); - if (!xml) - return JS_FALSE; - xml->name->localName = namestr; - return JS_TRUE; -} - -static JSBool -xml_setName(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSXML *xml, *nsowner; - jsval name; - JSXMLQName *nameqn; - JSObject *nameobj; - JSXMLArray *nsarray; - uint32 i, n; - JSXMLNamespace *ns; - - XML_METHOD_PROLOG; - if (!JSXML_HAS_NAME(xml)) - return JS_TRUE; - - name = argv[0]; - if (!JSVAL_IS_PRIMITIVE(name) && - OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(name)) == &js_QNameClass.base && - !(nameqn = (JSXMLQName *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(name))) - ->uri) { - name = argv[0] = STRING_TO_JSVAL(nameqn->localName); - } - - nameobj = js_ConstructObject(cx, &js_QNameClass.base, NULL, NULL, 1, &name); - if (!nameobj) - return JS_FALSE; - nameqn = (JSXMLQName *) JS_GetPrivate(cx, nameobj); - - /* ECMA-357 13.4.4.35 Step 4. */ - if (xml->xml_class == JSXML_CLASS_PROCESSING_INSTRUCTION) - nameqn->uri = cx->runtime->emptyString; - - xml = CHECK_COPY_ON_WRITE(cx, xml, obj); - if (!xml) - return JS_FALSE; - xml->name = nameqn; - - /* - * Erratum: nothing in 13.4.4.35 talks about making the name match the - * in-scope namespaces, either by finding an in-scope namespace with a - * matching uri and setting the new name's prefix to that namespace's - * prefix, or by extending the in-scope namespaces for xml (which are in - * xml->parent if xml is an attribute or a PI). - */ - if (xml->xml_class == JSXML_CLASS_ELEMENT) { - nsowner = xml; - } else { - if (!xml->parent || xml->parent->xml_class != JSXML_CLASS_ELEMENT) - return JS_TRUE; - nsowner = xml->parent; - } - - if (nameqn->prefix) { - /* - * The name being set has a prefix, which originally came from some - * namespace object (which may be the null namespace, where both the - * prefix and uri are the empty string). We must go through a full - * GetNamespace in case that namespace is in-scope in nsowner. - * - * If we find such an in-scope namespace, we return true right away, - * in this block. Otherwise, we fall through to the final return of - * AddInScopeNamespace(cx, nsowner, ns). - */ - ns = GetNamespace(cx, nameqn, &nsowner->xml_namespaces); - if (!ns) - return JS_FALSE; - - /* XXXbe have to test membership to see whether GetNamespace added */ - if (XMLARRAY_HAS_MEMBER(&nsowner->xml_namespaces, ns, NULL)) - return JS_TRUE; - } else { - /* - * At this point, we know nameqn->prefix is null, so nameqn->uri can't - * be the empty string (the null namespace always uses the empty string - * for both prefix and uri). - * - * This means we must inline GetNamespace and specialize it to match - * uri only, never prefix. If we find a namespace with nameqn's uri - * already in nsowner->xml_namespaces, then all that we need do is set - * nameqn->prefix to that namespace's prefix. - * - * If no such namespace exists, we can create one without going through - * the constructor, because we know nameqn->uri is non-empty (so prefix - * does not need to be converted from null to empty by QName). - */ - JS_ASSERT(!IS_EMPTY(nameqn->uri)); - - nsarray = &nsowner->xml_namespaces; - for (i = 0, n = nsarray->length; i < n; i++) { - ns = XMLARRAY_MEMBER(nsarray, i, JSXMLNamespace); - if (ns && !js_CompareStrings(ns->uri, nameqn->uri)) { - nameqn->prefix = ns->prefix; - return JS_TRUE; - } - } - - ns = js_NewXMLNamespace(cx, NULL, nameqn->uri, JS_TRUE); - if (!ns) - return JS_FALSE; - } - - return AddInScopeNamespace(cx, nsowner, ns); -} - -static JSBool -xml_setNamespace(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSXML *xml, *nsowner; - JSObject *nsobj, *qnobj; - JSXMLNamespace *ns; - jsval qnargv[2]; - - XML_METHOD_PROLOG; - if (xml->xml_class != JSXML_CLASS_ELEMENT && - xml->xml_class != JSXML_CLASS_ATTRIBUTE) { - return JS_TRUE; - } - - xml = CHECK_COPY_ON_WRITE(cx, xml, obj); - if (!xml || !js_GetXMLQNameObject(cx, xml->name)) - return JS_FALSE; - - nsobj = js_ConstructObject(cx, &js_NamespaceClass.base, NULL, obj, 1, argv); - if (!nsobj) - return JS_FALSE; - ns = (JSXMLNamespace *) JS_GetPrivate(cx, nsobj); - ns->declared = JS_TRUE; - - qnargv[0] = argv[0] = OBJECT_TO_JSVAL(nsobj); - qnargv[1] = OBJECT_TO_JSVAL(xml->name->object); - qnobj = js_ConstructObject(cx, &js_QNameClass.base, NULL, NULL, 2, qnargv); - if (!qnobj) - return JS_FALSE; - - xml->name = (JSXMLQName *) JS_GetPrivate(cx, qnobj); - - /* - * Erratum: the spec fails to update the governing in-scope namespaces. - * See the erratum noted in xml_setName, above. - */ - if (xml->xml_class == JSXML_CLASS_ELEMENT) { - nsowner = xml; - } else { - if (!xml->parent || xml->parent->xml_class != JSXML_CLASS_ELEMENT) - return JS_TRUE; - nsowner = xml->parent; - } - return AddInScopeNamespace(cx, nsowner, ns); -} - -/* XML and XMLList */ -static JSBool -xml_text(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSXML *xml, *list, *kid, *vxml; - JSObject *listobj, *kidobj; - uint32 i, n; - JSBool ok; - jsval v; - - XML_METHOD_PROLOG; - listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST); - if (!listobj) - return JS_FALSE; - - *rval = OBJECT_TO_JSVAL(listobj); - list = (JSXML *) JS_GetPrivate(cx, listobj); - list->xml_target = xml; - - if (xml->xml_class == JSXML_CLASS_LIST) { - ok = JS_TRUE; - for (i = 0, n = xml->xml_kids.length; i < n; i++) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (kid && kid->xml_class == JSXML_CLASS_ELEMENT) { - ok = JS_EnterLocalRootScope(cx); - if (!ok) - break; - kidobj = js_GetXMLObject(cx, kid); - ok = kidobj - ? xml_text(cx, kidobj, argc, argv, &v) - : JS_FALSE; - JS_LeaveLocalRootScope(cx); - if (!ok) - return JS_FALSE; - vxml = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v)); - if (JSXML_LENGTH(vxml) != 0 && !Append(cx, list, vxml)) - return JS_FALSE; - } - } - } else { - for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (kid && kid->xml_class == JSXML_CLASS_TEXT) { - if (!Append(cx, list, kid)) - return JS_FALSE; - } - } - } - return JS_TRUE; -} - -/* XML and XMLList */ -static JSBool -xml_toXMLString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSString *str; - - str = ToXMLString(cx, OBJECT_TO_JSVAL(obj)); - if (!str) - return JS_FALSE; - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -/* XML and XMLList */ -static JSString * -xml_toString_helper(JSContext *cx, JSXML *xml) -{ - JSString *str, *kidstr; - JSXML *kid; - JSXMLArrayCursor cursor; - - if (xml->xml_class == JSXML_CLASS_ATTRIBUTE || - xml->xml_class == JSXML_CLASS_TEXT) { - return xml->xml_value; - } - - if (!HasSimpleContent(xml)) - return ToXMLString(cx, OBJECT_TO_JSVAL(xml->object)); - - str = cx->runtime->emptyString; - JS_EnterLocalRootScope(cx); - XMLArrayCursorInit(&cursor, &xml->xml_kids); - while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) { - if (kid->xml_class != JSXML_CLASS_COMMENT && - kid->xml_class != JSXML_CLASS_PROCESSING_INSTRUCTION) { - kidstr = xml_toString_helper(cx, kid); - if (!kidstr) { - str = NULL; - break; - } - str = js_ConcatStrings(cx, str, kidstr); - if (!str) - break; - } - } - XMLArrayCursorFinish(&cursor); - JS_LeaveLocalRootScope(cx); - return str; -} - -static JSBool -xml_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSXML *xml; - JSString *str; - - XML_METHOD_PROLOG; - str = xml_toString_helper(cx, xml); - if (!str) - return JS_FALSE; - *rval = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -/* XML and XMLList */ -static JSBool -xml_valueOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - *rval = OBJECT_TO_JSVAL(obj); - return JS_TRUE; -} - -static JSFunctionSpec xml_methods[] = { - {"addNamespace", xml_addNamespace, 1,0,XML_MASK}, - {"appendChild", xml_appendChild, 1,0,XML_MASK}, - {js_attribute_str, xml_attribute, 1,0,GENERIC_MASK}, - {"attributes", xml_attributes, 0,0,GENERIC_MASK}, - {"child", xml_child, 1,0,GENERIC_MASK}, - {"childIndex", xml_childIndex, 0,0,XML_MASK}, - {"children", xml_children, 0,0,GENERIC_MASK}, - {"comments", xml_comments, 0,0,GENERIC_MASK}, - {"contains", xml_contains, 1,0,GENERIC_MASK}, - {"copy", xml_copy, 0,0,GENERIC_MASK}, - {"descendants", xml_descendants, 1,0,GENERIC_MASK}, - {"elements", xml_elements, 1,0,GENERIC_MASK}, - {"hasOwnProperty", xml_hasOwnProperty, 1,0,GENERIC_MASK}, - {"hasComplexContent", xml_hasComplexContent, 1,0,GENERIC_MASK}, - {"hasSimpleContent", xml_hasSimpleContent, 1,0,GENERIC_MASK}, - {"inScopeNamespaces", xml_inScopeNamespaces, 0,0,XML_MASK}, - {"insertChildAfter", xml_insertChildAfter, 2,0,XML_MASK}, - {"insertChildBefore", xml_insertChildBefore, 2,0,XML_MASK}, - {js_length_str, xml_length, 0,0,GENERIC_MASK}, - {js_localName_str, xml_localName, 0,0,XML_MASK}, - {js_name_str, xml_name, 0,0,XML_MASK}, - {js_namespace_str, xml_namespace, 1,0,XML_MASK}, - {"namespaceDeclarations", xml_namespaceDeclarations, 0,0,XML_MASK}, - {"nodeKind", xml_nodeKind, 0,0,XML_MASK}, - {"normalize", xml_normalize, 0,0,GENERIC_MASK}, - {js_xml_parent_str, xml_parent, 0,0,GENERIC_MASK}, - {"processingInstructions",xml_processingInstructions,1,0,GENERIC_MASK}, - {"prependChild", xml_prependChild, 1,0,XML_MASK}, - {"propertyIsEnumerable", xml_propertyIsEnumerable, 1,0,GENERIC_MASK}, - {"removeNamespace", xml_removeNamespace, 1,0,XML_MASK}, - {"replace", xml_replace, 2,0,XML_MASK}, - {"setChildren", xml_setChildren, 1,0,XML_MASK}, - {"setLocalName", xml_setLocalName, 1,0,XML_MASK}, - {"setName", xml_setName, 1,0,XML_MASK}, - {"setNamespace", xml_setNamespace, 1,0,XML_MASK}, - {js_text_str, xml_text, 0,0,GENERIC_MASK}, - {js_toString_str, xml_toString, 0,0,GENERIC_MASK}, - {js_toXMLString_str, xml_toXMLString, 0,0,GENERIC_MASK}, - {js_toSource_str, xml_toXMLString, 0,0,GENERIC_MASK}, - {js_valueOf_str, xml_valueOf, 0,0,GENERIC_MASK}, - {0,0,0,0,0} -}; - -static JSBool -CopyXMLSettings(JSContext *cx, JSObject *from, JSObject *to) -{ - int i; - const char *name; - jsval v; - - for (i = XML_IGNORE_COMMENTS; i < XML_PRETTY_INDENT; i++) { - name = xml_static_props[i].name; - if (!JS_GetProperty(cx, from, name, &v)) - return JS_FALSE; - if (JSVAL_IS_BOOLEAN(v) && !JS_SetProperty(cx, to, name, &v)) - return JS_FALSE; - } - - name = xml_static_props[i].name; - if (!JS_GetProperty(cx, from, name, &v)) - return JS_FALSE; - if (JSVAL_IS_NUMBER(v) && !JS_SetProperty(cx, to, name, &v)) - return JS_FALSE; - return JS_TRUE; -} - -static JSBool -SetDefaultXMLSettings(JSContext *cx, JSObject *obj) -{ - int i; - jsval v; - - for (i = XML_IGNORE_COMMENTS; i < XML_PRETTY_INDENT; i++) { - v = JSVAL_TRUE; - if (!JS_SetProperty(cx, obj, xml_static_props[i].name, &v)) - return JS_FALSE; - } - v = INT_TO_JSVAL(2); - return JS_SetProperty(cx, obj, xml_static_props[i].name, &v); -} - -static JSBool -xml_settings(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSObject *settings; - - settings = JS_NewObject(cx, NULL, NULL, NULL); - if (!settings) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(settings); - return CopyXMLSettings(cx, obj, settings); -} - -static JSBool -xml_setSettings(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - jsval v; - JSBool ok; - JSObject *settings; - - v = argv[0]; - if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) { - cx->xmlSettingFlags = 0; - ok = SetDefaultXMLSettings(cx, obj); - } else { - if (JSVAL_IS_PRIMITIVE(v)) - return JS_TRUE; - settings = JSVAL_TO_OBJECT(v); - cx->xmlSettingFlags = 0; - ok = CopyXMLSettings(cx, settings, obj); - } - if (ok) - cx->xmlSettingFlags |= XSF_CACHE_VALID; - return ok; -} - -static JSBool -xml_defaultSettings(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - JSObject *settings; - - settings = JS_NewObject(cx, NULL, NULL, NULL); - if (!settings) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(settings); - return SetDefaultXMLSettings(cx, settings); -} - -static JSFunctionSpec xml_static_methods[] = { - {"settings", xml_settings, 0,0,0}, - {"setSettings", xml_setSettings, 1,0,0}, - {"defaultSettings", xml_defaultSettings, 0,0,0}, - {0,0,0,0,0} -}; - -static JSBool -XML(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsval v; - JSXML *xml, *copy; - JSObject *xobj, *vobj; - JSClass *clasp; - - v = argv[0]; - if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) - v = STRING_TO_JSVAL(cx->runtime->emptyString); - - xobj = ToXML(cx, v); - if (!xobj) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(xobj); - xml = (JSXML *) JS_GetPrivate(cx, xobj); - - if ((cx->fp->flags & JSFRAME_CONSTRUCTING) && !JSVAL_IS_PRIMITIVE(v)) { - vobj = JSVAL_TO_OBJECT(v); - clasp = OBJ_GET_CLASS(cx, vobj); - if (clasp == &js_XMLClass || - (clasp->flags & JSCLASS_DOCUMENT_OBSERVER)) { - /* No need to lock obj, it's newly constructed and thread local. */ - copy = DeepCopy(cx, xml, obj, 0); - if (!copy) - return JS_FALSE; - JS_ASSERT(copy->object == obj); - *rval = OBJECT_TO_JSVAL(obj); - return JS_TRUE; - } - } - return JS_TRUE; -} - -static JSBool -XMLList(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - jsval v; - JSObject *vobj, *listobj; - JSXML *xml, *list; - - v = argv[0]; - if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) - v = STRING_TO_JSVAL(cx->runtime->emptyString); - - if ((cx->fp->flags & JSFRAME_CONSTRUCTING) && !JSVAL_IS_PRIMITIVE(v)) { - vobj = JSVAL_TO_OBJECT(v); - if (OBJECT_IS_XML(cx, vobj)) { - xml = (JSXML *) JS_GetPrivate(cx, vobj); - if (xml->xml_class == JSXML_CLASS_LIST) { - listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST); - if (!listobj) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(listobj); - - list = (JSXML *) JS_GetPrivate(cx, listobj); - if (!Append(cx, list, xml)) - return JS_FALSE; - return JS_TRUE; - } - } - } - - /* Toggle on XML support since the script has explicitly requested it. */ - listobj = ToXMLList(cx, v); - if (!listobj) - return JS_FALSE; - - *rval = OBJECT_TO_JSVAL(listobj); - return JS_TRUE; -} - -#define JSXML_LIST_SIZE (offsetof(JSXML, u) + sizeof(struct JSXMLListVar)) -#define JSXML_ELEMENT_SIZE (offsetof(JSXML, u) + sizeof(struct JSXMLVar)) -#define JSXML_LEAF_SIZE (offsetof(JSXML, u) + sizeof(JSString *)) - -static size_t sizeof_JSXML[JSXML_CLASS_LIMIT] = { - JSXML_LIST_SIZE, /* JSXML_CLASS_LIST */ - JSXML_ELEMENT_SIZE, /* JSXML_CLASS_ELEMENT */ - JSXML_LEAF_SIZE, /* JSXML_CLASS_ATTRIBUTE */ - JSXML_LEAF_SIZE, /* JSXML_CLASS_PROCESSING_INSTRUCTION */ - JSXML_LEAF_SIZE, /* JSXML_CLASS_TEXT */ - JSXML_LEAF_SIZE /* JSXML_CLASS_COMMENT */ -}; - -#ifdef DEBUG_notme -JSCList xml_leaks = JS_INIT_STATIC_CLIST(&xml_leaks); -uint32 xml_serial; -#endif - -JSXML * -js_NewXML(JSContext *cx, JSXMLClass xml_class) -{ - JSXML *xml; - - xml = (JSXML *) js_NewGCThing(cx, GCX_XML, sizeof_JSXML[xml_class]); - if (!xml) - return NULL; - - xml->object = NULL; - xml->domnode = NULL; - xml->parent = NULL; - xml->name = NULL; - xml->xml_class = xml_class; - xml->xml_flags = 0; - if (JSXML_CLASS_HAS_VALUE(xml_class)) { - xml->xml_value = cx->runtime->emptyString; - } else { - XMLArrayInit(cx, &xml->xml_kids, 0); - if (xml_class == JSXML_CLASS_LIST) { - xml->xml_target = NULL; - xml->xml_targetprop = NULL; - } else { - XMLArrayInit(cx, &xml->xml_namespaces, 0); - XMLArrayInit(cx, &xml->xml_attrs, 0); - } - } - -#ifdef DEBUG_notme - JS_APPEND_LINK(&xml->links, &xml_leaks); - xml->serial = xml_serial++; -#endif - METER(xml_stats.xml); - METER(xml_stats.livexml); - return xml; -} - -static void -xml_mark_tail(JSContext *cx, JSXML *xml, void *arg) -{ - XMLArrayTrim(&xml->xml_kids); - - if (xml->xml_class == JSXML_CLASS_LIST) { - if (xml->xml_target) - JS_MarkGCThing(cx, xml->xml_target, "target", arg); - if (xml->xml_targetprop) - JS_MarkGCThing(cx, xml->xml_targetprop, "targetprop", arg); - } else { - namespace_mark_vector(cx, - (JSXMLNamespace **) xml->xml_namespaces.vector, - xml->xml_namespaces.length, - arg); - XMLArrayCursorMark(cx, xml->xml_namespaces.cursors); - XMLArrayTrim(&xml->xml_namespaces); - - xml_mark_vector(cx, - (JSXML **) xml->xml_attrs.vector, - xml->xml_attrs.length, - arg); - XMLArrayCursorMark(cx, xml->xml_attrs.cursors); - XMLArrayTrim(&xml->xml_attrs); - } -} - -void -js_MarkXML(JSContext *cx, JSXML *xml, void *arg) -{ - JS_MarkGCThing(cx, xml->object, js_object_str, arg); - JS_MarkGCThing(cx, xml->name, js_name_str, arg); - JS_MarkGCThing(cx, xml->parent, js_xml_parent_str, arg); - - if (JSXML_HAS_VALUE(xml)) { - JS_MarkGCThing(cx, xml->xml_value, "value", arg); - } else { - xml_mark_vector(cx, - (JSXML **) xml->xml_kids.vector, - xml->xml_kids.length, - arg); - XMLArrayCursorMark(cx, xml->xml_kids.cursors); - - xml_mark_tail(cx, xml, arg); - } -} - -void -js_FinalizeXML(JSContext *cx, JSXML *xml) -{ - if (JSXML_HAS_KIDS(xml)) { - XMLArrayFinish(cx, &xml->xml_kids); - if (xml->xml_class == JSXML_CLASS_ELEMENT) { - XMLArrayFinish(cx, &xml->xml_namespaces); - XMLArrayFinish(cx, &xml->xml_attrs); - } - } - -#ifdef DEBUG_notme - JS_REMOVE_LINK(&xml->links); -#endif - - UNMETER(xml_stats.livexml); -} - -JSObject * -js_ParseNodeToXMLObject(JSContext *cx, JSParseNode *pn) -{ - jsval nsval; - JSXMLNamespace *ns; - JSXMLArray nsarray; - JSXML *xml; - - if (!js_GetDefaultXMLNamespace(cx, &nsval)) - return NULL; - JS_ASSERT(!JSVAL_IS_PRIMITIVE(nsval)); - ns = (JSXMLNamespace *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(nsval)); - - if (!XMLArrayInit(cx, &nsarray, 1)) - return NULL; - - XMLARRAY_APPEND(cx, &nsarray, ns); - xml = ParseNodeToXML(cx, pn, &nsarray, XSF_PRECOMPILED_ROOT); - XMLArrayFinish(cx, &nsarray); - if (!xml) - return NULL; - - return xml->object; -} - -JSObject * -js_NewXMLObject(JSContext *cx, JSXMLClass xml_class) -{ - JSXML *xml; - JSObject *obj; - JSTempValueRooter tvr; - - xml = js_NewXML(cx, xml_class); - if (!xml) - return NULL; - JS_PUSH_SINGLE_TEMP_ROOT(cx, OBJECT_TO_JSVAL(xml), &tvr); - obj = js_GetXMLObject(cx, xml); - JS_POP_TEMP_ROOT(cx, &tvr); - return obj; -} - -static JSObject * -NewXMLObject(JSContext *cx, JSXML *xml) -{ - JSObject *obj; - - obj = js_NewObject(cx, &js_XMLClass, NULL, NULL); - if (!obj || !JS_SetPrivate(cx, obj, xml)) { - cx->newborn[GCX_OBJECT] = NULL; - return NULL; - } - METER(xml_stats.xmlobj); - METER(xml_stats.livexmlobj); - return obj; -} - -JSObject * -js_GetXMLObject(JSContext *cx, JSXML *xml) -{ - JSObject *obj; - - obj = xml->object; - if (obj) { - JS_ASSERT(JS_GetPrivate(cx, obj) == xml); - return obj; - } - - /* - * A JSXML cannot be shared among threads unless it has an object. - * A JSXML cannot be given an object unless: - * (a) it has no parent; or - * (b) its parent has no object (therefore is thread-private); or - * (c) its parent's object is locked. - * - * Once given an object, a JSXML is immutable. - */ - JS_ASSERT(!xml->parent || - !xml->parent->object || - JS_IS_OBJ_LOCKED(cx, xml->parent->object)); - - obj = NewXMLObject(cx, xml); - if (!obj) - return NULL; - xml->object = obj; - return obj; -} - -JSObject * -js_InitNamespaceClass(JSContext *cx, JSObject *obj) -{ - return JS_InitClass(cx, obj, NULL, &js_NamespaceClass.base, Namespace, 2, - namespace_props, namespace_methods, NULL, NULL); -} - -JSObject * -js_InitQNameClass(JSContext *cx, JSObject *obj) -{ - return JS_InitClass(cx, obj, NULL, &js_QNameClass.base, QName, 2, - qname_props, qname_methods, NULL, NULL); -} - -JSObject * -js_InitAttributeNameClass(JSContext *cx, JSObject *obj) -{ - return JS_InitClass(cx, obj, NULL, &js_AttributeNameClass, AttributeName, 2, - qname_props, qname_methods, NULL, NULL); -} - -JSObject * -js_InitAnyNameClass(JSContext *cx, JSObject *obj) -{ - jsval v; - - if (!js_GetAnyName(cx, &v)) - return NULL; - return JSVAL_TO_OBJECT(v); -} - -JSObject * -js_InitXMLClass(JSContext *cx, JSObject *obj) -{ - JSObject *proto, *pobj, *ctor; - JSFunctionSpec *fs; - JSFunction *fun; - JSXML *xml; - JSProperty *prop; - JSScopeProperty *sprop; - jsval cval, argv[1], junk; - - /* Define the isXMLName function. */ - if (!JS_DefineFunction(cx, obj, js_isXMLName_str, xml_isXMLName, 1, 0)) - return NULL; - - /* Define the XML class constructor and prototype. */ - proto = JS_InitClass(cx, obj, NULL, &js_XMLClass, XML, 1, - NULL, NULL, - xml_static_props, xml_static_methods); - if (!proto) - return NULL; - - /* - * XXX Hack alert: expand JS_DefineFunctions here to copy fs->extra into - * fun->spare, clearing fun->extra. No xml_methods require extra local GC - * roots allocated after actual arguments on the VM stack, but we need a - * way to tell which methods work only on XML objects, which work only on - * XMLList objects, and which work on either. - */ - for (fs = xml_methods; fs->name; fs++) { - fun = JS_DefineFunction(cx, proto, fs->name, fs->call, fs->nargs, - fs->flags); - if (!fun) - return NULL; - fun->extra = 0; - fun->spare = fs->extra; - } - - xml = js_NewXML(cx, JSXML_CLASS_TEXT); - if (!xml || !JS_SetPrivate(cx, proto, xml)) - return NULL; - xml->object = proto; - METER(xml_stats.xmlobj); - METER(xml_stats.livexmlobj); - - /* - * Prepare to set default settings on the XML constructor we just made. - * NB: We can't use JS_GetConstructor, because it calls OBJ_GET_PROPERTY, - * which is xml_getProperty, which creates a new XMLList every time! We - * must instead call js_LookupProperty directly. - */ - if (!js_LookupProperty(cx, proto, - ATOM_TO_JSID(cx->runtime->atomState.constructorAtom), - &pobj, &prop)) { - return NULL; - } - JS_ASSERT(prop); - sprop = (JSScopeProperty *) prop; - JS_ASSERT(SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(pobj))); - cval = OBJ_GET_SLOT(cx, pobj, sprop->slot); - OBJ_DROP_PROPERTY(cx, pobj, prop); - JS_ASSERT(JSVAL_IS_FUNCTION(cx, cval)); - - /* Set default settings. */ - ctor = JSVAL_TO_OBJECT(cval); - argv[0] = JSVAL_VOID; - if (!xml_setSettings(cx, ctor, 1, argv, &junk)) - return NULL; - - /* Define the XMLList function and give it the same prototype as XML. */ - fun = JS_DefineFunction(cx, obj, js_XMLList_str, XMLList, 1, 0); - if (!fun) - return NULL; - if (!js_SetClassPrototype(cx, fun->object, proto, - JSPROP_READONLY | JSPROP_PERMANENT)) { - return NULL; - } - return proto; -} - -JSObject * -js_InitXMLClasses(JSContext *cx, JSObject *obj) -{ - if (!js_InitNamespaceClass(cx, obj)) - return NULL; - if (!js_InitQNameClass(cx, obj)) - return NULL; - if (!js_InitAttributeNameClass(cx, obj)) - return NULL; - if (!js_InitAnyNameClass(cx, obj)) - return NULL; - return js_InitXMLClass(cx, obj); -} - -JSBool -js_GetFunctionNamespace(JSContext *cx, jsval *vp) -{ - JSRuntime *rt; - JSObject *obj; - JSAtom *atom; - JSString *prefix, *uri; - - /* An invalid URI, for internal use only, guaranteed not to collide. */ - static const char anti_uri[] = "@mozilla.org/js/function"; - - rt = cx->runtime; - obj = rt->functionNamespaceObject; - if (!obj) { - atom = js_Atomize(cx, js_function_str, 8, 0); - JS_ASSERT(atom); - prefix = ATOM_TO_STRING(atom); - - atom = js_Atomize(cx, anti_uri, sizeof anti_uri - 1, ATOM_PINNED); - if (!atom) - return JS_FALSE; - rt->atomState.lazy.functionNamespaceURIAtom = atom; - - uri = ATOM_TO_STRING(atom); - obj = js_NewXMLNamespaceObject(cx, prefix, uri, JS_FALSE); - if (!obj) - return JS_FALSE; - - /* - * Avoid entraining any in-scope Object.prototype. The loss of - * Namespace.prototype is not detectable, as there is no way to - * refer to this instance in scripts. When used to qualify method - * names, its prefix and uri references are copied to the QName. - */ - OBJ_SET_PROTO(cx, obj, NULL); - OBJ_SET_PARENT(cx, obj, NULL); - rt->functionNamespaceObject = obj; - } - *vp = OBJECT_TO_JSVAL(obj); - return JS_TRUE; -} - -/* - * Note the asymmetry between js_GetDefaultXMLNamespace and js_SetDefaultXML- - * Namespace. Get searches fp->scopeChain for JS_DEFAULT_XML_NAMESPACE_ID, - * while Set sets JS_DEFAULT_XML_NAMESPACE_ID in fp->varobj (unless fp is a - * lightweight function activation). There's no requirement that fp->varobj - * lie directly on fp->scopeChain, although it should be reachable using the - * prototype chain from a scope object (cf. JSOPTION_VAROBJFIX in jsapi.h). - * - * If Get can't find JS_DEFAULT_XML_NAMESPACE_ID along the scope chain, it - * creates a default namespace via 'new Namespace()'. In contrast, Set uses - * its v argument as the uri of a new Namespace, with "" as the prefix. See - * ECMA-357 12.1 and 12.1.1. Note that if Set is called with a Namespace n, - * the default XML namespace will be set to ("", n.uri). So the uri string - * is really the only usefully stored value of the default namespace. - */ -JSBool -js_GetDefaultXMLNamespace(JSContext *cx, jsval *vp) -{ - JSStackFrame *fp; - JSObject *nsobj, *obj, *tmp; - jsval v; - - fp = cx->fp; - nsobj = fp->xmlNamespace; - if (nsobj) { - *vp = OBJECT_TO_JSVAL(nsobj); - return JS_TRUE; - } - - obj = NULL; - for (tmp = fp->scopeChain; tmp; tmp = OBJ_GET_PARENT(cx, obj)) { - obj = tmp; - if (!OBJ_GET_PROPERTY(cx, obj, JS_DEFAULT_XML_NAMESPACE_ID, &v)) - return JS_FALSE; - if (!JSVAL_IS_PRIMITIVE(v)) { - fp->xmlNamespace = JSVAL_TO_OBJECT(v); - *vp = v; - return JS_TRUE; - } - } - - nsobj = js_ConstructObject(cx, &js_NamespaceClass.base, NULL, obj, 0, NULL); - if (!nsobj) - return JS_FALSE; - v = OBJECT_TO_JSVAL(nsobj); - if (obj && - !OBJ_DEFINE_PROPERTY(cx, obj, JS_DEFAULT_XML_NAMESPACE_ID, v, - JS_PropertyStub, JS_PropertyStub, - JSPROP_PERMANENT, NULL)) { - return JS_FALSE; - } - fp->xmlNamespace = nsobj; - *vp = v; - return JS_TRUE; -} - -JSBool -js_SetDefaultXMLNamespace(JSContext *cx, jsval v) -{ - jsval argv[2]; - JSObject *nsobj, *varobj; - JSStackFrame *fp; - - argv[0] = STRING_TO_JSVAL(cx->runtime->emptyString); - argv[1] = v; - nsobj = js_ConstructObject(cx, &js_NamespaceClass.base, NULL, NULL, - 2, argv); - if (!nsobj) - return JS_FALSE; - v = OBJECT_TO_JSVAL(nsobj); - - fp = cx->fp; - varobj = fp->varobj; - if (varobj) { - if (!OBJ_DEFINE_PROPERTY(cx, varobj, JS_DEFAULT_XML_NAMESPACE_ID, v, - JS_PropertyStub, JS_PropertyStub, - JSPROP_PERMANENT, NULL)) { - return JS_FALSE; - } - } else { - JS_ASSERT(fp->fun && !(fp->fun->flags & JSFUN_HEAVYWEIGHT)); - } - fp->xmlNamespace = JSVAL_TO_OBJECT(v); - return JS_TRUE; -} - -JSBool -js_ToAttributeName(JSContext *cx, jsval *vp) -{ - JSXMLQName *qn; - - qn = ToAttributeName(cx, *vp); - if (!qn) - return JS_FALSE; - *vp = OBJECT_TO_JSVAL(qn->object); - return JS_TRUE; -} - -JSString * -js_EscapeAttributeValue(JSContext *cx, JSString *str) -{ - return EscapeAttributeValue(cx, NULL, str); -} - -JSString * -js_AddAttributePart(JSContext *cx, JSBool isName, JSString *str, JSString *str2) -{ - size_t len, len2, newlen; - jschar *chars; - - if (JSSTRING_IS_DEPENDENT(str) || - !(*js_GetGCThingFlags(str) & GCF_MUTABLE)) { - str = js_NewStringCopyN(cx, JSSTRING_CHARS(str), JSSTRING_LENGTH(str), - 0); - if (!str) - return NULL; - } - - len = str->length; - len2 = JSSTRING_LENGTH(str2); - newlen = (isName) ? len + 1 + len2 : len + 2 + len2 + 1; - chars = (jschar *) JS_realloc(cx, str->chars, (newlen+1) * sizeof(jschar)); - if (!chars) - return NULL; - - /* - * Reallocating str (because we know it has no other references) requires - * purging any deflated string cached for it. - */ - js_PurgeDeflatedStringCache(str); - - str->chars = chars; - str->length = newlen; - chars += len; - if (isName) { - *chars++ = ' '; - js_strncpy(chars, JSSTRING_CHARS(str2), len2); - chars += len2; - } else { - *chars++ = '='; - *chars++ = '"'; - js_strncpy(chars, JSSTRING_CHARS(str2), len2); - chars += len2; - *chars++ = '"'; - } - *chars = 0; - return str; -} - -JSString * -js_EscapeElementValue(JSContext *cx, JSString *str) -{ - return EscapeElementValue(cx, NULL, str); -} - -JSString * -js_ValueToXMLString(JSContext *cx, jsval v) -{ - return ToXMLString(cx, v); -} - -static JSBool -anyname_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - *rval = ATOM_KEY(cx->runtime->atomState.starAtom); - return JS_TRUE; -} - -JSBool -js_GetAnyName(JSContext *cx, jsval *vp) -{ - JSRuntime *rt; - JSObject *obj; - JSXMLQName *qn; - - rt = cx->runtime; - obj = rt->anynameObject; - if (!obj) { - qn = js_NewXMLQName(cx, rt->emptyString, rt->emptyString, - ATOM_TO_STRING(rt->atomState.starAtom)); - if (!qn) - return JS_FALSE; - - obj = js_NewObject(cx, &js_AnyNameClass, NULL, NULL); - if (!obj || !JS_SetPrivate(cx, obj, qn)) { - cx->newborn[GCX_OBJECT] = NULL; - return JS_FALSE; - } - qn->object = obj; - METER(xml_stats.qnameobj); - METER(xml_stats.liveqnameobj); - - /* - * Avoid entraining any in-scope Object.prototype. This loses the - * default toString inheritance, but no big deal: we want a better - * custom one for clearer diagnostics. - */ - if (!JS_DefineFunction(cx, obj, js_toString_str, anyname_toString, - 0, 0)) { - return JS_FALSE; - } - OBJ_SET_PROTO(cx, obj, NULL); - JS_ASSERT(!OBJ_GET_PARENT(cx, obj)); - rt->anynameObject = obj; - } - *vp = OBJECT_TO_JSVAL(obj); - return JS_TRUE; -} - -JSBool -js_FindXMLProperty(JSContext *cx, jsval name, JSObject **objp, jsval *namep) -{ - JSXMLQName *qn; - jsid funid, id; - JSObject *obj, *pobj, *lastobj; - JSProperty *prop; - const char *printable; - - qn = ToXMLName(cx, name, &funid); - if (!qn) - return JS_FALSE; - id = OBJECT_TO_JSID(qn->object); - - obj = cx->fp->scopeChain; - do { - if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &pobj, &prop)) - return JS_FALSE; - if (prop) { - OBJ_DROP_PROPERTY(cx, pobj, prop); - - /* - * Call OBJ_THIS_OBJECT to skip any With object that wraps an XML - * object to carry scope chain linkage in js_FilterXMLList. - */ - pobj = OBJ_THIS_OBJECT(cx, obj); - if (OBJECT_IS_XML(cx, pobj)) { - *objp = pobj; - *namep = ID_TO_VALUE(id); - return JS_TRUE; - } - } - - lastobj = obj; - } while ((obj = OBJ_GET_PARENT(cx, obj)) != NULL); - - printable = js_ValueToPrintableString(cx, name); - if (printable) { - JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, - js_GetErrorMessage, NULL, - JSMSG_UNDEFINED_XML_NAME, printable); - } - return JS_FALSE; -} - -JSBool -js_GetXMLProperty(JSContext *cx, JSObject *obj, jsval name, jsval *vp) -{ - return GetProperty(cx, obj, name, vp); -} - -JSBool -js_SetXMLProperty(JSContext *cx, JSObject *obj, jsval name, jsval *vp) -{ - return PutProperty(cx, obj, name, vp); -} - -static JSXML * -GetPrivate(JSContext *cx, JSObject *obj, const char *method) -{ - JSXML *xml; - - xml = (JSXML *) JS_GetInstancePrivate(cx, obj, &js_XMLClass, NULL); - if (!xml) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_INCOMPATIBLE_METHOD, - js_XML_str, method, OBJ_GET_CLASS(cx, obj)->name); - } - return xml; -} - -JSBool -js_GetXMLDescendants(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - JSXML *xml, *list; - - xml = GetPrivate(cx, obj, "descendants internal method"); - if (!xml) - return JS_FALSE; - - list = Descendants(cx, xml, id); - if (!list) - return JS_FALSE; - *vp = OBJECT_TO_JSVAL(list->object); - return JS_TRUE; -} - -JSBool -js_DeleteXMLListElements(JSContext *cx, JSObject *listobj) -{ - JSXML *list; - uint32 n; - jsval junk; - - list = (JSXML *) JS_GetPrivate(cx, listobj); - for (n = list->xml_kids.length; n != 0; --n) { - if (!DeleteProperty(cx, listobj, INT_TO_JSID(0), &junk)) - return JS_FALSE; - } - return JS_TRUE; -} - -JSBool -js_FilterXMLList(JSContext *cx, JSObject *obj, jsbytecode *pc, jsval *vp) -{ - JSBool ok, match; - JSStackFrame *fp; - JSObject *scobj, *listobj, *resobj, *withobj, *kidobj; - JSXML *xml, *list, *result, *kid; - JSXMLArrayCursor cursor; - - ok = JS_EnterLocalRootScope(cx); - if (!ok) - return JS_FALSE; - - /* All control flow after this point must exit via label out or bad. */ - fp = cx->fp; - scobj = fp->scopeChain; - withobj = NULL; - xml = GetPrivate(cx, obj, "filtering predicate operator"); - if (!xml) - goto bad; - - if (xml->xml_class == JSXML_CLASS_LIST) { - list = xml; - } else { - listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST); - if (!listobj) - goto bad; - list = (JSXML *) JS_GetPrivate(cx, listobj); - ok = Append(cx, list, xml); - if (!ok) - goto out; - } - - resobj = js_NewXMLObject(cx, JSXML_CLASS_LIST); - if (!resobj) - goto bad; - result = (JSXML *) JS_GetPrivate(cx, resobj); - - /* Hoist the scope chain update out of the loop over kids. */ - withobj = js_NewWithObject(cx, NULL, scobj, -1); - if (!withobj) - goto bad; - fp->scopeChain = withobj; - - XMLArrayCursorInit(&cursor, &list->xml_kids); - while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) { - kidobj = js_GetXMLObject(cx, kid); - if (!kidobj) - break; - OBJ_SET_PROTO(cx, withobj, kidobj); - ok = js_Interpret(cx, pc, vp) && js_ValueToBoolean(cx, *vp, &match); - if (ok && match) - ok = Append(cx, result, kid); - if (!ok) - break; - } - XMLArrayCursorFinish(&cursor); - if (!ok) - goto out; - if (kid) - goto bad; - - *vp = OBJECT_TO_JSVAL(resobj); - -out: - if (withobj) { - fp->scopeChain = scobj; - JS_SetPrivate(cx, withobj, NULL); - } - JS_LeaveLocalRootScope(cx); - return ok; -bad: - ok = JS_FALSE; - goto out; -} - -JSObject * -js_ValueToXMLObject(JSContext *cx, jsval v) -{ - return ToXML(cx, v); -} - -JSObject * -js_ValueToXMLListObject(JSContext *cx, jsval v) -{ - return ToXMLList(cx, v); -} - -JSObject * -js_CloneXMLObject(JSContext *cx, JSObject *obj) -{ - uintN flags; - JSXML *xml; - - if (!GetXMLSettingFlags(cx, &flags)) - return NULL; - xml = (JSXML *) JS_GetPrivate(cx, obj); - if (flags & (XSF_IGNORE_COMMENTS | - XSF_IGNORE_PROCESSING_INSTRUCTIONS | - XSF_IGNORE_WHITESPACE)) { - xml = DeepCopy(cx, xml, NULL, flags); - if (!xml) - return NULL; - return xml->object; - } - return NewXMLObject(cx, xml); -} - -JSObject * -js_NewXMLSpecialObject(JSContext *cx, JSXMLClass xml_class, JSString *name, - JSString *value) -{ - uintN flags; - JSObject *obj; - JSXML *xml; - JSXMLQName *qn; - - if (!GetXMLSettingFlags(cx, &flags)) - return NULL; - - if ((xml_class == JSXML_CLASS_COMMENT && - (flags & XSF_IGNORE_COMMENTS)) || - (xml_class == JSXML_CLASS_PROCESSING_INSTRUCTION && - (flags & XSF_IGNORE_PROCESSING_INSTRUCTIONS))) { - return js_NewXMLObject(cx, JSXML_CLASS_TEXT); - } - - obj = js_NewXMLObject(cx, xml_class); - if (!obj) - return NULL; - xml = (JSXML *) JS_GetPrivate(cx, obj); - if (name) { - qn = js_NewXMLQName(cx, cx->runtime->emptyString, NULL, name); - if (!qn) - return NULL; - xml->name = qn; - } - xml->xml_value = value; - return obj; -} - -JSString * -js_MakeXMLCDATAString(JSContext *cx, JSString *str) -{ - return MakeXMLCDATAString(cx, NULL, str); -} - -JSString * -js_MakeXMLCommentString(JSContext *cx, JSString *str) -{ - return MakeXMLCommentString(cx, NULL, str); -} - -JSString * -js_MakeXMLPIString(JSContext *cx, JSString *name, JSString *str) -{ - return MakeXMLPIString(cx, NULL, name, str); -} - -#endif /* JS_HAS_XML_SUPPORT */ diff --git a/lib/javascript/jsxml.h b/lib/javascript/jsxml.h deleted file mode 100644 index 294e66c9..00000000 --- a/lib/javascript/jsxml.h +++ /dev/null @@ -1,329 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is SpiderMonkey E4X code, released August, 2004. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jsxml_h___ -#define jsxml_h___ - -#include "jsstddef.h" -#include "jspubtd.h" - -extern const char js_AnyName_str[]; -extern const char js_AttributeName_str[]; -extern const char js_isXMLName_str[]; -extern const char js_XMLList_str[]; - -extern const char js_amp_entity_str[]; -extern const char js_gt_entity_str[]; -extern const char js_lt_entity_str[]; -extern const char js_quot_entity_str[]; - -struct JSXMLNamespace { - JSObject *object; - JSString *prefix; - JSString *uri; - JSBool declared; /* true if declared in its XML tag */ -}; - -extern JSXMLNamespace * -js_NewXMLNamespace(JSContext *cx, JSString *prefix, JSString *uri, - JSBool declared); - -extern void -js_MarkXMLNamespace(JSContext *cx, JSXMLNamespace *ns, void *arg); - -extern void -js_FinalizeXMLNamespace(JSContext *cx, JSXMLNamespace *ns); - -extern JSObject * -js_NewXMLNamespaceObject(JSContext *cx, JSString *prefix, JSString *uri, - JSBool declared); - -extern JSObject * -js_GetXMLNamespaceObject(JSContext *cx, JSXMLNamespace *ns); - -struct JSXMLQName { - JSObject *object; - JSString *uri; - JSString *prefix; - JSString *localName; -}; - -extern JSXMLQName * -js_NewXMLQName(JSContext *cx, JSString *uri, JSString *prefix, - JSString *localName); - -extern void -js_MarkXMLQName(JSContext *cx, JSXMLQName *qn, void *arg); - -extern void -js_FinalizeXMLQName(JSContext *cx, JSXMLQName *qn); - -extern JSObject * -js_NewXMLQNameObject(JSContext *cx, JSString *uri, JSString *prefix, - JSString *localName); - -extern JSObject * -js_GetXMLQNameObject(JSContext *cx, JSXMLQName *qn); - -extern JSObject * -js_GetAttributeNameObject(JSContext *cx, JSXMLQName *qn); - -extern JSObject * -js_ConstructXMLQNameObject(JSContext *cx, jsval nsval, jsval lnval); - -typedef JSBool -(* JS_DLL_CALLBACK JSIdentityOp)(const void *a, const void *b); - -struct JSXMLArray { - uint32 length; - uint32 capacity; - void **vector; - JSXMLArrayCursor *cursors; -}; - -#define JSXML_PRESET_CAPACITY JS_BIT(31) -#define JSXML_CAPACITY_MASK JS_BITMASK(31) -#define JSXML_CAPACITY(array) ((array)->capacity & JSXML_CAPACITY_MASK) - -struct JSXMLArrayCursor { - JSXMLArray *array; - uint32 index; - JSXMLArrayCursor *next; - JSXMLArrayCursor **prevp; - void *root; -}; - -/* - * NB: don't reorder this enum without changing all array initializers that - * depend on it in jsxml.c. - */ -typedef enum JSXMLClass { - JSXML_CLASS_LIST, - JSXML_CLASS_ELEMENT, - JSXML_CLASS_ATTRIBUTE, - JSXML_CLASS_PROCESSING_INSTRUCTION, - JSXML_CLASS_TEXT, - JSXML_CLASS_COMMENT, - JSXML_CLASS_LIMIT -} JSXMLClass; - -#define JSXML_CLASS_HAS_KIDS(class_) ((class_) < JSXML_CLASS_ATTRIBUTE) -#define JSXML_CLASS_HAS_VALUE(class_) ((class_) >= JSXML_CLASS_ATTRIBUTE) -#define JSXML_CLASS_HAS_NAME(class_) \ - ((uintN)((class_) - JSXML_CLASS_ELEMENT) <= \ - (uintN)(JSXML_CLASS_PROCESSING_INSTRUCTION - JSXML_CLASS_ELEMENT)) - -#ifdef DEBUG_notme -#include "jsclist.h" -#endif - -struct JSXML { -#ifdef DEBUG_notme - JSCList links; - uint32 serial; -#endif - JSObject *object; - void *domnode; /* DOM node if mapped info item */ - JSXML *parent; - JSXMLQName *name; - uint16 xml_class; /* discriminates u, below */ - uint16 xml_flags; /* flags, see below */ - union { - struct JSXMLListVar { - JSXMLArray kids; /* NB: must come first */ - JSXML *target; - JSXMLQName *targetprop; - } list; - struct JSXMLVar { - JSXMLArray kids; /* NB: must come first */ - JSXMLArray namespaces; - JSXMLArray attrs; - } elem; - JSString *value; - } u; - - /* Don't add anything after u -- see js_NewXML for why. */ -}; - -/* union member shorthands */ -#define xml_kids u.list.kids -#define xml_target u.list.target -#define xml_targetprop u.list.targetprop -#define xml_namespaces u.elem.namespaces -#define xml_attrs u.elem.attrs -#define xml_value u.value - -/* xml_flags values */ -#define XMLF_WHITESPACE_TEXT 0x1 - -/* xml_class-testing macros */ -#define JSXML_HAS_KIDS(xml) JSXML_CLASS_HAS_KIDS((xml)->xml_class) -#define JSXML_HAS_VALUE(xml) JSXML_CLASS_HAS_VALUE((xml)->xml_class) -#define JSXML_HAS_NAME(xml) JSXML_CLASS_HAS_NAME((xml)->xml_class) -#define JSXML_LENGTH(xml) (JSXML_CLASS_HAS_KIDS((xml)->xml_class) \ - ? (xml)->xml_kids.length \ - : 0) - -extern JSXML * -js_NewXML(JSContext *cx, JSXMLClass xml_class); - -extern void -js_MarkXML(JSContext *cx, JSXML *xml, void *arg); - -extern void -js_FinalizeXML(JSContext *cx, JSXML *xml); - -extern JSObject * -js_ParseNodeToXMLObject(JSContext *cx, JSParseNode *pn); - -extern JSObject * -js_NewXMLObject(JSContext *cx, JSXMLClass xml_class); - -extern JSObject * -js_GetXMLObject(JSContext *cx, JSXML *xml); - -extern JS_FRIEND_DATA(JSXMLObjectOps) js_XMLObjectOps; -extern JS_FRIEND_DATA(JSClass) js_XMLClass; -extern JS_FRIEND_DATA(JSExtendedClass) js_NamespaceClass; -extern JS_FRIEND_DATA(JSExtendedClass) js_QNameClass; -extern JS_FRIEND_DATA(JSClass) js_AttributeNameClass; -extern JS_FRIEND_DATA(JSClass) js_AnyNameClass; - -/* - * Macros to test whether an object or a value is of type "xml" (per typeof). - * NB: jsapi.h must be included before any call to VALUE_IS_XML. - */ -#define OBJECT_IS_XML(cx,obj) ((obj)->map->ops == &js_XMLObjectOps.base) -#define VALUE_IS_XML(cx,v) (!JSVAL_IS_PRIMITIVE(v) && \ - OBJECT_IS_XML(cx, JSVAL_TO_OBJECT(v))) - -extern JSObject * -js_InitNamespaceClass(JSContext *cx, JSObject *obj); - -extern JSObject * -js_InitQNameClass(JSContext *cx, JSObject *obj); - -extern JSObject * -js_InitAttributeNameClass(JSContext *cx, JSObject *obj); - -extern JSObject * -js_InitAnyNameClass(JSContext *cx, JSObject *obj); - -extern JSObject * -js_InitXMLClass(JSContext *cx, JSObject *obj); - -extern JSObject * -js_InitXMLClasses(JSContext *cx, JSObject *obj); - -extern JSBool -js_GetFunctionNamespace(JSContext *cx, jsval *vp); - -extern JSBool -js_GetDefaultXMLNamespace(JSContext *cx, jsval *vp); - -extern JSBool -js_SetDefaultXMLNamespace(JSContext *cx, jsval v); - -/* - * Return true if v is a XML QName object, or if it converts to a string that - * contains a valid XML qualified name (one containing no :), false otherwise. - * NB: This function is an infallible predicate, it hides exceptions. - */ -extern JSBool -js_IsXMLName(JSContext *cx, jsval v); - -extern JSBool -js_ToAttributeName(JSContext *cx, jsval *vp); - -extern JSString * -js_EscapeAttributeValue(JSContext *cx, JSString *str); - -extern JSString * -js_AddAttributePart(JSContext *cx, JSBool isName, JSString *str, - JSString *str2); - -extern JSString * -js_EscapeElementValue(JSContext *cx, JSString *str); - -extern JSString * -js_ValueToXMLString(JSContext *cx, jsval v); - -extern JSBool -js_GetAnyName(JSContext *cx, jsval *vp); - -extern JSBool -js_FindXMLProperty(JSContext *cx, jsval name, JSObject **objp, jsval *namep); - -extern JSBool -js_GetXMLProperty(JSContext *cx, JSObject *obj, jsval name, jsval *vp); - -extern JSBool -js_SetXMLProperty(JSContext *cx, JSObject *obj, jsval name, jsval *vp); - -extern JSBool -js_GetXMLDescendants(JSContext *cx, JSObject *obj, jsval id, jsval *vp); - -extern JSBool -js_DeleteXMLListElements(JSContext *cx, JSObject *listobj); - -extern JSBool -js_FilterXMLList(JSContext *cx, JSObject *obj, jsbytecode *pc, jsval *vp); - -extern JSObject * -js_ValueToXMLObject(JSContext *cx, jsval v); - -extern JSObject * -js_ValueToXMLListObject(JSContext *cx, jsval v); - -extern JSObject * -js_CloneXMLObject(JSContext *cx, JSObject *obj); - -extern JSObject * -js_NewXMLSpecialObject(JSContext *cx, JSXMLClass xml_class, JSString *name, - JSString *value); - -extern JSString * -js_MakeXMLCDATAString(JSContext *cx, JSString *str); - -extern JSString * -js_MakeXMLCommentString(JSContext *cx, JSString *str); - -extern JSString * -js_MakeXMLPIString(JSContext *cx, JSString *name, JSString *str); - -#endif /* jsxml_h___ */ diff --git a/lib/javascript/liveconnect/.cvsignore b/lib/javascript/liveconnect/.cvsignore deleted file mode 100644 index bb5cc66e..00000000 --- a/lib/javascript/liveconnect/.cvsignore +++ /dev/null @@ -1,7 +0,0 @@ -*.pdb -*.ncb -*.opt -*.plg -Debug -Release -Makefile diff --git a/lib/javascript/liveconnect/LiveConnect.dsp b/lib/javascript/liveconnect/LiveConnect.dsp deleted file mode 100644 index 6e9d21da..00000000 --- a/lib/javascript/liveconnect/LiveConnect.dsp +++ /dev/null @@ -1,157 +0,0 @@ -# Microsoft Developer Studio Project File - Name="LiveConnect" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 5.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 - -CFG=LiveConnect - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "LiveConnect.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "LiveConnect.mak" CFG="LiveConnect - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "LiveConnect - Win32 Release" (based on\ - "Win32 (x86) Dynamic-Link Library") -!MESSAGE "LiveConnect - Win32 Debug" (based on\ - "Win32 (x86) Dynamic-Link Library") -!MESSAGE - -# Begin Project -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -MTL=midl.exe -RSC=rc.exe - -!IF "$(CFG)" == "LiveConnect - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GX /Zi /O2 /I ".." /I "$(JDK)\include" /I "$(JDK)\include\win32" /D "NDEBUG" /D "XP_WIN" /D "JSFILE" /D "WIN32" /D "_WINDOWS" /YX /FD /c -# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ..\Release\js32.lib $(JDK)\lib\javai.lib /nologo /subsystem:windows /dll /debug /machine:I386 - -!ELSEIF "$(CFG)" == "LiveConnect - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I ".." /I "$(JDK)\include" /I "$(JDK)\include\win32" /D "_DEBUG" /D "_CONSOLE" /D "DEBUG" /D "XP_WIN" /D "JSFILE" /D "WIN32" /D "_WINDOWS" /FR /YX /FD /c -# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32 -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ..\Debug\js32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"Debug/LiveConnect_g.dll" /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "LiveConnect - Win32 Release" -# Name "LiveConnect - Win32 Debug" -# Begin Source File - -SOURCE=..\liveconnect\jsj.c -# End Source File -# Begin Source File - -SOURCE=..\liveconnect\jsj_array.c -# End Source File -# Begin Source File - -SOURCE=..\liveconnect\jsj_class.c -# End Source File -# Begin Source File - -SOURCE=..\liveconnect\jsj_convert.c -# End Source File -# Begin Source File - -SOURCE=..\liveconnect\jsj_field.c -# End Source File -# Begin Source File - -SOURCE=.\jsj_hash.c -# End Source File -# Begin Source File - -SOURCE=.\jsj_JavaArray.c -# End Source File -# Begin Source File - -SOURCE=.\jsj_JavaClass.c -# End Source File -# Begin Source File - -SOURCE=.\jsj_JavaMember.c -# End Source File -# Begin Source File - -SOURCE=.\jsj_JavaObject.c -# End Source File -# Begin Source File - -SOURCE=.\jsj_JavaPackage.c -# End Source File -# Begin Source File - -SOURCE=.\jsj_JSObject.c - -!IF "$(CFG)" == "LiveConnect - Win32 Release" - -!ELSEIF "$(CFG)" == "LiveConnect - Win32 Debug" - -# ADD CPP /I ".\_jni" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=..\liveconnect\jsj_method.c -# End Source File -# Begin Source File - -SOURCE=..\liveconnect\jsj_utils.c -# End Source File -# End Target -# End Project diff --git a/lib/javascript/liveconnect/LiveConnectShell.dsp b/lib/javascript/liveconnect/LiveConnectShell.dsp deleted file mode 100644 index 28086f2d..00000000 --- a/lib/javascript/liveconnect/LiveConnectShell.dsp +++ /dev/null @@ -1,120 +0,0 @@ -# Microsoft Developer Studio Project File - Name="LiveConnectShell" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 5.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=LiveConnectShell - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "LiveConnectShell.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "LiveConnectShell.mak" CFG="LiveConnectShell - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "LiveConnectShell - Win32 Release" (based on\ - "Win32 (x86) Console Application") -!MESSAGE "LiveConnectShell - Win32 Debug" (based on\ - "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "LiveConnectShell - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "LiveConnectShell_" -# PROP BASE Intermediate_Dir "LiveConnectShell_" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GX /O2 /I "$(JDK)\include" /I "$(JDK)\include\win32" /I "." /D "_WIN32" /D "WIN32" /D "NDEBUG" /D "XP_WIN" /D "_WINDOWS" /D "JSFILE" /D "LIVECONNECT" /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/lcshell.exe" -# Begin Special Build Tool -SOURCE=$(InputPath) -PostBuild_Desc=Copy DLL(s) to build directory -PostBuild_Cmds=COPY ..\Release\js32.dll .\Release -# End Special Build Tool - -!ELSEIF "$(CFG)" == "LiveConnectShell - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "LiveConnectShell0" -# PROP BASE Intermediate_Dir "LiveConnectShell0" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "$(JDK)\include" /I "$(JDK)\include\win32" /I "." /D "LIVECONNECT" /D "_WIN32" /D "WIN32" /D "_DEBUG" /D "DEBUG" /D "XP_WIN" /D "_WINDOWS" /D "JSFILE" /FR /YX /FD /c -# SUBTRACT CPP /u -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib $(JDK)\lib\javai_g.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/lcshell.exe" /pdbtype:sept -# Begin Special Build Tool -SOURCE=$(InputPath) -PostBuild_Desc=Copy DLL(s) to build directory -PostBuild_Cmds=COPY ..\Debug\js32.dll .\Debug -# End Special Build Tool - -!ENDIF - -# Begin Target - -# Name "LiveConnectShell - Win32 Release" -# Name "LiveConnectShell - Win32 Debug" -# Begin Source File - -SOURCE=..\js.c -# End Source File -# Begin Source File - -SOURCE=..\Debug\js32.lib -# End Source File -# Begin Source File - -SOURCE=.\jsj_simpleapi.c - -!IF "$(CFG)" == "LiveConnectShell - Win32 Release" - -!ELSEIF "$(CFG)" == "LiveConnectShell - Win32 Debug" - -# ADD CPP /I ".." -# SUBTRACT CPP /I "." - -!ENDIF - -# End Source File -# End Target -# End Project diff --git a/lib/javascript/liveconnect/LiveConnectShell.dsw b/lib/javascript/liveconnect/LiveConnectShell.dsw deleted file mode 100644 index 4752be78..00000000 --- a/lib/javascript/liveconnect/LiveConnectShell.dsw +++ /dev/null @@ -1,44 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 5.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "LiveConnect"=.\LiveConnect.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "LiveConnectShell"=.\LiveConnectShell.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name LiveConnect - End Project Dependency -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/lib/javascript/liveconnect/Makefile.in b/lib/javascript/liveconnect/Makefile.in deleted file mode 100644 index 3b0a4981..00000000 --- a/lib/javascript/liveconnect/Makefile.in +++ /dev/null @@ -1,107 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either of the GNU General Public License Version 2 or later (the "GPL"), -# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -DEPTH = ../../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(DEPTH)/config/autoconf.mk - -MODULE = liveconnect -LIBRARY_NAME = jsj -EXPORT_LIBRARY = 1 -ifeq ($(OS_ARCH)$(MOZ_ENABLE_LIBXUL),WINNT) -LIBRARY_NAME = jsj$(MOZ_BITS)$(VERSION_NUMBER) -MAPFILE = $(LIBRARY_NAME).map -endif -JNI_GEN_DIR = _jni -GRE_MODULE = 1 -LIBXUL_LIBRARY = 1 - -PACKAGE_FILE = liveconnect.pkg - -REQUIRES = js \ - xpcom \ - xpconnect \ - java \ - caps \ - necko \ - string \ - $(NULL) - -CSRCS = \ - jsj.c \ - jsj_JSObject.c \ - jsj_JavaArray.c \ - jsj_JavaClass.c \ - jsj_JavaMember.c \ - jsj_JavaObject.c \ - jsj_JavaPackage.c \ - jsj_array.c \ - jsj_class.c \ - jsj_convert.c \ - jsj_field.c \ - jsj_hash.c \ - jsj_method.c \ - jsj_utils.c \ - $(NULL) - -CPPSRCS = \ - nsCLiveconnect.cpp \ - nsCLiveconnectFactory.cpp \ - $(NULL) - -EXPORTS = \ - $(srcdir)/jsjava.h \ - $(srcdir)/$(JNI_GEN_DIR)/netscape_javascript_JSObject.h \ - $(srcdir)/$(JNI_GEN_DIR)/netscape_javascript_JSException.h \ - $(srcdir)/nsILiveconnect.h \ - $(srcdir)/nsISecureLiveconnect.h \ - $(srcdir)/nsISecurityContext.h \ - $(NULL) - -EXTRA_DSO_LDOPTS += \ - $(LIBS_DIR) \ - $(MOZ_JS_LIBS) \ - $(MOZ_COMPONENT_LIBS) \ - $(NULL) - -include $(topsrcdir)/config/rules.mk - - diff --git a/lib/javascript/liveconnect/Makefile.ref b/lib/javascript/liveconnect/Makefile.ref deleted file mode 100644 index e1bb126d..00000000 --- a/lib/javascript/liveconnect/Makefile.ref +++ /dev/null @@ -1,169 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either of the GNU General Public License Version 2 or later (the "GPL"), -# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# JSRef GNUmake makefile. -# - -DEPTH = .. - -# Create JAR file -DIRS += classes - -# -# XCFLAGS may be set in the environment or on the gmake command line -# -CFLAGS += $(OPTIMIZER) $(OS_CFLAGS) $(DEFINES) $(INCLUDES) \ - -DJSFILE $(XCFLAGS) -LDFLAGS += -lm $(XLDFLAGS) - -# For purify -PURE_CFLAGS = -DXP_UNIX $(OPTIMIZER) $(PURE_OS_CFLAGS) $(DEFINES) \ - $(INCLUDES) $(XCFLAGS) - -# -# LC file lists -# -LC_HFILES = \ - jsj_hash.h \ - jsj_private.h \ - jsjava.h \ - netscape_javascript_JSObject.h \ - nsCLiveconnectFactory.h \ - nsILiveconnect.h \ - nsISecureLiveconnect.h \ - nsISecurityContext.h \ - $(NULL) - -OTHER_HFILES = \ - jsj.msg \ - $(NULL) - -HFILES = $(LC_HFILES) $(OTHER_HFILES) - -LC_CFILES = \ - jsj.c \ - jsj_JSObject.c \ - jsj_JavaArray.c \ - jsj_JavaClass.c \ - jsj_JavaMember.c \ - jsj_JavaObject.c \ - jsj_JavaPackage.c \ - jsj_array.c \ - jsj_class.c \ - jsj_convert.c \ - jsj_field.c \ - jsj_hash.c \ - jsj_method.c \ - jsj_utils.c \ - $(NULL) - -LIB_CFILES = $(LC_CFILES) - -PROG_FILE = js - -include $(DEPTH)/config.mk -include config/$(OS_CONFIG).mk - -INCLUDES += -I. -I.. -I../$(OBJDIR) - -ifdef USE_MSVC -OTHER_LIBS += $(DEPTH)/fdlibm/$(OBJDIR)/fdlibm.lib -else -OTHER_LIBS += -L$(DEPTH)/fdlibm/$(OBJDIR) -lfdm -L../$(OBJDIR) -ljs -endif - -# -# Line editing support. -# Define JS_READLINE or JS_EDITLINE to enable line editing in the -# lcshell command-line interpreter. -# -ifdef JS_READLINE -# For those platforms with the readline library installed. -DEFINES += -DEDITLINE -OTHER_LIBS += -lreadline -else -ifdef JS_EDITLINE -# Use the editline library from ../editline. -PREDIRS += ../editline -DEFINES += -DEDITLINE -OTHER_LIBS += -L../editline/$(OBJDIR) -ledit -endif -endif - -NSPR_LIBSUFFIX = 4 - -ifdef JS_THREADSAFE -DEFINES += -DJS_THREADSAFE -INCLUDES += -I../../../dist/$(OBJDIR)/include -ifdef USE_MSVC -OTHER_LIBS += $(DEPTH)/../../dist/$(OBJDIR)/lib/libnspr${NSPR_LIBSUFFIX}.lib -else -OTHER_LIBS += -L$(DEPTH)/../../dist/$(OBJDIR)/lib -lnspr${NSPR_LIBSUFFIX} -endif -endif - -ifdef USE_MSVC -LIBRARY = $(OBJDIR)/jsj.lib -SHARED_LIBRARY = $(OBJDIR)/jsj.dll -PROGRAM = $(OBJDIR)/lcshell.exe -else -LIBRARY = $(OBJDIR)/libjsj.a -SHARED_LIBRARY = $(OBJDIR)/libjsj.$(SO_SUFFIX) -PROGRAM = $(OBJDIR)/lcshell -endif - -include $(DEPTH)/rules.mk - -ifdef USE_MSVC -$(OBJDIR)/$(PROG_FILE)_lc.obj: ../$(PROG_FILE).c - @$(MAKE_OBJDIR) - $(CC) -Fo$@ -c $(CFLAGS) -DLIVECONNECT ../$(PROG_FILE).c - -$(PROGRAM): $(OBJDIR)/$(PROG_FILE)_lc.obj $(OBJDIR)/jsj_simpleapi.obj $(LIBRARY) - link.exe -out:"$@" $(EXE_LINK_FLAGS) ../$(OBJDIR)/js32.lib $(OTHER_LIBS) $? -else -$(OBJDIR)/$(PROG_FILE).o: ../$(PROG_FILE).c - @$(MAKE_OBJDIR) - $(CC) -o $@ -c $(CFLAGS) -DLIVECONNECT ../$(PROG_FILE).c - -$(PROGRAM): $(OBJDIR)/$(PROG_FILE).o $(OBJDIR)/jsj_simpleapi.o - @$(MAKE_OBJDIR) - $(CC) -o $@ $(CFLAGS) $+ $(LIBRARY) ../$(OBJDIR)/libjs.a $(LDFLAGS) $(OTHER_LIBS) -endif diff --git a/lib/javascript/liveconnect/README.html b/lib/javascript/liveconnect/README.html deleted file mode 100644 index 8a5fc02f..00000000 --- a/lib/javascript/liveconnect/README.html +++ /dev/null @@ -1,719 +0,0 @@ - - - - - - - - - README for LiveConnect - - -This is the README file for the JavaScript LiveConnect -Version 3 ("LC3") implementation. -

    -Table of Contents

    - -
    Introduction -
    New features -
    Compatibility -
    Limitations/Bugs/To-Do -
    Build conventions -
    Naming and coding conventions -
    The LiveConnect API -
    Sample LiveConnect shell interactions
    - -

    -Introduction

    - LiveConnect is a library that -permits JavaScript and Java virtual machines to interoperate. Specifically, -it enables JavaScript to access Java fields, invoke Java methods and enables Java -to access JavaScript object properties and evaluate arbitrary JavaScript. -LiveConnect was originally an integrated feature of both the Netscape Navigator -browser and Netscape's server-side JavaScript. Now, it is a standalone library -that can be embedded within other projects, such as the Mozilla browser. More -information on LiveConnect can be found by searching -the index on Netscape's DevEdge site.  This README assumes basic familiarity -with JSRef, -the reference implementation of JavaScript, and with the LiveConnect technology. -

    The JSRef project/makefiles (located in another directory) build a library - or DLL containing the JavaScript runtime (compiler, interpreter, decompiler, - garbage collector, atom manager, standard classes).  The LiveConnect project/makefiles - build a library that links with both JSRef and any Java Virtual Machine (JVM) - that implements the Java Native Interface (JNI), as specified by JavaSoft.  - It then compiles a small "shell" example program and links that with the library - to make an interpreter that can be used interactively and with test scripts.  - See the sample shell interactions. -

    Scott Furman, 10/31/98 -

    -New features

    -The following features were not available in the versions of LiveConnect that -were integrated with Netscape Navigator versions 4.x and earlier.  For information -on LiveConnect version 1, which was used in Navigator versions 3 and 4, and Enterprise -Server 3, see Netscape's -DevEdge site or any number of 3rd-party publications.) -

    LiveConnect version 3 (8/31/99)

    - -
      -
    • In previous versions of LiveConnect, when more than one overloaded Java - method was compatible with the types of arguments in an invocation from JS, - the choice of Java method was made arbitrarily, by using the first one enumerated - by the Java reflection APIs.  Unfortunately, the ordering of methods - when enumerating is not governed by any specification, so differences between - JVM vendors could lead to inconsistencies in LiveConnect behavior.  Now, - a JVM-independent - set of rules is used to choose among a set of overloaded methods.   - Informally, the method with Java parameter types that most  closely match - the JavaScript types is chosen.
      -
      -
    • -
    • The weak correspondence between the JS language typing system and Java's - may result in ambiguity and/or shadowing when resolving among overloaded Java - methods, even when using LC3's improved method overload resolution algorithm - (see above).  For example, JS's number type can map to a Java method - argument that has any floating-point or integral types: byte, char, short, - int, long, float, double.   If necessary, it is now possible to - bypass the method overload resolution process and explicitly specify the method - to be invoked:
    • -
      -
      -   -
        - myPrintMethod = java.io.PrintStream["print(double)"];
        - myPrintMethod(13); -
      -
      -
    • Static methods can now be invoked using either the class name or a reference - to an instance of the class.  (Older versions of LiveConnect allow only - the former.)
      -
      -
    • -
    • It is no longer necessary to convert Java Strings to JS strings before - using them as the receivers of JS string methods, which is typically done - by appending an empty string to the Java string, e.g. -
      -

          s = new java.lang.String("foo") // s contains - a Java string
      -     s = s + "";                     - // s is now a JS string
      -     m = s.match(/o?/)

      -
      -
    • -

      The explicit conversion to a JS string is no longer required because java.lang.String - objects are treated as a special case that "inherit" all the methods of JS - strings, i.e. so that the second statement in the example above is now superfluous.
      -
      -

    • Similarly, JavaArray objects "inherit" the methods of JS's Array.prototype, - so it is possible to apply many, though not all, of the JS array utility methods - such as reverse() and join() to JavaArray objects.
      -
      -
    • -
    • There is now support for the instanceof and in operators.  - These operators are currently proposed for inclusion in the ECMA-2 standard.
      -
      -
    • -
    • LiveConnect has been extended to take advantage of JavaScript exceptions, - a language feature that debuted in JavaScript 1.4.  Now, when JavaScript - calls into Java, any Java exceptions are converted to JS exceptions which - can be caught using JS try-catch statements.  Similarly, JS exceptions - are propagated to Java wrapped in an instance of netscape.javascript.JSException.
      -
      -
    • -
    • JavaScript Array objects can now be passed to Java methods that expect a - Java array as an argument.
      - LiveConnect will create a new Java array of the appropriate type with a length - equal to that of the JS Array object. Each element of the Java array is filled - in by converting the corresponding element of the JS array, including undefined - elements, to an equivalent Java value. Note: Since the contents of the JS - array are copied, side-effects made by the invoked Java method to the Java - array will not be reflected in the JS array argument.
    • -
    - -

    -LiveConnect version 2 (7/31/98)

    - -
    -
  • The Java methods of java.lang.Object are now invokeable methods - of JavaArray objects, matching the behavior - of arrays when accessed from Java.  (Java arrays are a subclass - of java.lang.Object.) For example, Java's getClass() and hashCode() - methods can now be called on JavaArray objects.  (In prior versions - of LiveConnect, the methods of java.lang.Object were only inherited - by non-array Java objects.)
  • - -

    Note that this change has caused the string representation of JavaArray objects - to change.  Previously, the JavaArray toString() method always printed - "[object JavaArray]" for all JavaArray's.  - Now, the Java java.lang.Object.toString() method is called to convert - JavaArray objects to strings, just as with other, non-array Java objects that - are accessible via LiveConnect. java.lang.Object.toString()is defined - in the Java Language Specification to return the value of the following - expression: -

    getClass().getName() + '@' + Integer.toHexString(hashCode())
    -
    -   -

  • A one-character string is now an acceptable match for an argument to a - Java method of type char.  (In earlier versions of LiveConnect, - the only acceptable match for a char had to be a JavaScript value - that was convertible to a number.)  For example, the following is now - possible:
  • - -

    c = new java.lang.Character("F")
    -
    -   -

  • -A JavaClass object is now an acceptable match for an argument to a Java -method of type java.lang.Class.  For example, you can now write:
  • - -

    java.lang.reflect.Array.newInstance(java.lang.String, -3) -

    instead of the more verbose: -

    jls = java.lang.Class.forName("java.lang.String") -
    - java.lang.reflect.Array.newInstance(jls, 3) -


    -   -

    - -

    -Compatibility

    -Unlike this standalone/component release, all previous versions of LiveConnect -appeared only as an integrated feature of Netscape Navigator or the Enterprise -Server.  The variants of LiveConnect that appeared in Navigator versions -3.x and 4.x all behave much the same, modulo bugs.  For brevity we refer -to this classic version of LiveConnect as "LC1" (LiveConnect version 1) and this -most recent release as "LC3".  With a few exceptions LC3 provides a superset -of LC1 features. (There was an intermediate LiveConnect release known as "LC2" -in 7/98, but it was not used in any products.) -
      -
    • As in LC1, JavaScript objects appear to Java as instances of netscape.javascript.JSObject.  - In LC1, two JSObject's could be tested for equality, i.e. to see if - they refer to the same instance, by using the `==' operator.  Instead, - developers must now use the equals()method of netscape.javascript.JSObject - for comparison, a method that overrides java.lang.Object.equals().  - Note that using equals() instead of `==' will work the same in all - versions of LiveConnect, including LC3
    • -

      [It is not possible to replicate the identity behavior of the `==' operator - that LC1 provides without the use of "weak" references, i.e. references that - do not contribute to making a Java object reachable for purposes of garbage - collection, but which nonetheless allow reference to an object as long as - it is reachable by other means.  The use of weak references is not portable, - however.  It is not part of the JNI or JDK 1.1 and it is not provided - on all JVMs.  The JDK1.2 release includes standard support for weak references.]
      -
      -   -

    • It's possible that, in a set of overloaded Java methods, more than one - method is compatible with the types of the actual arguments in a call from - JavaScript to Java via LiveConnect.  LC1 and LC2 resolved these ambiguities - in a simplistic manner, by simply invoking whatever method was enumerated - first by the JVM.  The enumeration order of reflected methods using java.lang.reflect  - is not specified by Sun and may differ among vendor's JVMs, i.e. enumeration - could be in order of classfile appearance, hashtable order, etc.  Hence, - the Java method chosen when there is more than one compatible method may vary - depending on the JVM.  With the Netscape and Sun JVMs, it is possible - to change the behavior of an LC1/LC2 program by changing the order that Java - methods appear in a source file, thus changing the method enumeration order.
    • -

      In LC3, a new method overload resolution algorithm is used.  Informally, - the method with Java parameter types that most  closely match the JavaScript - types is chosen.  You can read all the gorey details in the spec.
      -
      -   -

    • There are several minor changes in error handling to make LiveConnect more - conformant to ECMAScript.  These include, for example, making any attempt - to delete JavaObject, JavaClass or JavaPackage properties fail silently, rather - than causing an error.  Also, some error messages have been changed to - be more informative.  These changes should generally be backward-compatible - with LC1 because few programs that use LiveConnect will depend on the exact - behavior of LiveConnect when handling errors.
    • -
    - -

    Limitations/Bugs/To-Do
    -

    -
      -
    • The efficiency of calling Java methods leaves something to be desired, - due to the convoluted nature of implementing native methods for JS.  - JS_CloneFunctionObject() is called for every Java method invocation and the - inability to store private data in a JSFunction object requires that the method - table be searched twice instead of once for every invocation.
      -
      -
    • -
    • When Java objects are referenced from JS, they are entered into a hash - table, so as to ensure that the same JS Object wrapper is used every time - a particular Java object is reflected into JS.  In this way, the behavior - of the JS '==' and '===' operators are preserved.  Unfortunately, the - hash table may grow quite large (objects are only removed from the hash table - when finalized).  In thread-safe systems, the hash table must be locked - when accessed, leading to slow performance. One alternate solution would be - to make it possible to overload JS's equality-test operators, so that the - hash table would no longer be required.
      -
      -
    • -
    • Initially, JavaClassDescriptor objectswere reference-counted to permit - free'ing of unused descriptors.  However, it's relatively common to develop - cycles in the graph of JavaClassDescriptors, which leads to unused JavaClassDescriptors - that have non-zero reference counts. For that reason, JavaClassDescriptors - are not free'ed until JSJ_Shutdown().  Luckily, the amount of memory - used by JavaClassDescriptors tends to be relatively small.
      -
      -
    • -
    • The LiveConnect API is designed to allow multiple JVMs to be used simultaneously - in the same executable (although each JSContext is limited to interaction - with at most one JVM).  However, the API is not fully implemented.  - For example, many global variables will need to become members of the JSJavaVM - struct so that they are stored on a per-JVM basis.
      -
      -
    • -
    • Java and JavaScript use independent garbage collection systems. A reference - between the two worlds must, therefore, take the form of a GC root. It's possible - to create uncollectable objects when cyclic graphs cross the boundary between - JS and Java, e.g. a JS object that refers to a Java object that refers back - to the original JS object. There is no simple solution to this dual-GC problem. - Luckily, such cyclic object graphs are extremely rare.
    • -
    - -

    -Build conventions

    -

    The following directions are for building the standalone version of LiveConnect. - To build the version that's used in the Mozilla browser, see the Mozilla - build documentation.

    -

    On all platforms, you must update your JVM's CLASSPATH to point to - the js/src/liveconnect/classes subdirectory.  If you do not, LiveConnect - will still operate but with the limitation that JS objects may not be passed - as arguments of Java methods and it will not be possible to call from Java into - JavaScript, i.e. the netscape.javascript.JSObject class will be inaccessible.  - Another downside of operating without these classes is that Java error messages - will not include a Java stack trace, when one is available.  If your CLASSPATH - is set improperly, you will see a message like, "initialization error: Can't - load class netscape/javascript/JSObject" when starting a LiveConnect debug - build.

    -

    By default, all platforms build a version of LiveConnect that is not - threadsafe.  If you require thread-safety, you must also populate the mozilla/dist - directory with NSPR - headers and libraries.  (NSPR implements a portable threading library, - among other things.  The source is downloadable via CVS - from mozilla/nsprpub.)  - Next, you must define JS_THREADSAFE when building LiveConnect, either - on the command-line (gmake/nmake) or in a universal header file.  Note - that JSRef must also be built with JS_THREADSAFE. -

    One important note about building on Windows: There are two independent build - systems (in addition to the Mozilla browser build system). One of them uses - the IDE project files and the other uses gmake and makefiles. The former will - be preferred by most for debugging and the latter is more complete, since it - builds the necessary Java classes in addition to compiling the LiveConnect C - code. -

      Windows -
        -
      • -Build the JS runtime and interpreter, js32.dll, by using the -normal -JSRef build procedure.
      • Set the JDK environment variable to point to the top-level JDK directory, - e.g. D:\jdk1.1.5.  This is used to establish paths for header - file inclusion, linking and execution.  If you are not using Sun's - JVM, the project files may require manual tweaking to set these paths correctly.
      • - -
      • Use MSVC 5 or MSVC 6 with the LiveConnectShell.dsw project file.  - NOTE: makefile.win is an nmake file used only for - building the JS-engine in the Mozilla browser.  Don't attempt to use - it to build the standalone JS-engine.
      • - -
      • -The output files (DLLs and executables) are placed in either the js\src\liveconnect\Debug -or the js\src\liveconnect\Release directory.
      • - -
      • -The LiveConnect-enabled shell is named lcshell.exe and appears -in the output directory.
      • - -
      • -You must have the JVM DLL in your PATH environment -variable in order to run.  If you are using the Sun JDK, the DLL appears -in the JDK's bin directory, e.g. D:\jdk1.1.5\bin\javai_g.dll.
      • - -
      • -Use any Java compiler to compile the java source files in the js\src\liveconnect\classes\netscape\javascript -directory.
      • - -
      • Update your JVM's CLASSPATH to point to the js\src\liveconnect\classes - subdirectory.  (See above)
        -
      • -
      -Mac OS -
        -
      • -Using CodeWarrior Pro 3 is recommended, though the project files will probably -also work with CodeWarrior Pro 4.
      • - -
      • -Install Apple's JVM, MRJ 2.0 (or later), and the MRJ -SDK v2.0.1ea4.  Note: You do not need to install MRJ if you are -running a recent version of MacOS 8, since it is shipped with the OS.
      • - -
      • -Copy the folders CIncludes & Libraries from the SDK's -Interfaces&Libraries directory to js:src:liveconnect:macbuild:JavaSession.
      • - -
      • -Build the LiveConnect test application, LiveConnectShell, with -js:src:liveconnect:macbuild:LiveConnectShell.mcp.
      • - -
      • -Build liveconnect.jar with js:src:liveconnect:macbuild:LiveConnect.mcp.
      • - -
      • -Make an alias to liveconnect.jar and place it in "{SystemFolder}Extensions:MRJ -Libraries:MRJClasses".
        -
      • -
      - Unix (also works on Windows) -
        -
      • Use 'gmake -f Makefile.ref' to build. - To compile optimized code, pass BUILD_OPT=1 on the gmake command - line or preset it in the environment or Makefile.refNOTE: - Do not attempt to use Makefile to build.  This file is used - only for building LiveConnect in the Mozilla browser.
      • -
      • Each platform on which LiveConnect is built must - have a *.mk configuration file in the js/src/liveconnect/config - directory.  The configuration file specifies the JVM headers/libraries - used and allows for customization of command-line options.  To date, - the build system has been tested on Solaris, AIX, HP/UX, OSF, IRIX, x86 - Linux and Windows NT. Most platforms will work with either the vendor compiler - or gcc.
      • -
      • Update your JVM's CLASSPATH to point to - the js/src/liveconnect/classes subdirectory.  (See above)
      • -
      -
    - -

    -Naming and coding conventions:

    - -
      -
    • -Public function names begin with JSJ_ followed by capitalized "intercaps",  -e.g. JSJ_ConnectToJavaVM.
    • - -
    • -Extern but library-private function names use a jsj_ prefix and mixed case, -e.g. jsj_LookupSymbol.
    • - -
    • -Most static function names have unprefixed, underscore-separated names: -get_char.
    • - -
    • -But static native methods of JS objects have intercaps names, e.g., JavaObject_getProperty().
    • - -
    • -And library-private and static data use underscores, not intercaps (but -library-private data do use a js_ prefix).
    • - -
    • -Scalar type names are lowercase and js-prefixed: jsdouble.
    • - -
    • -Aggregate type names are JS-prefixed and mixed-case: JSObject.
    • - -
    • -Macros are generally ALL_CAPS and underscored, to call out potential side -effects, multiple uses of a formal argument, etc.
    • - -
    • -Four spaces of indentation per statement nesting level.  The files -are space-filled, so adjusting of your tab setting should be unnecessary.
    • - -
    • -I don't bow down to the ancient "80 columns per line" gods, since most -of us are not using vt100's to read source code.  My rule of thumb -is to use no more than 95 columns per line, but exceptions are made to -format tables or table-like code.
    • - -
    • -DLL entry points have their return type expanded within a JS_EXPORT_API()  -macro call, to get the right Windows secret type qualifiers in the right -places for both 16- and 32-bit builds.
    • - -
    • -Callback functions that might be called from a DLL are similarly macroized -with JS_STATIC_DLL_CALLBACK (if the function otherwise would be static -to hide its name) or JS_DLL_CALLBACK (this macro takes no type argument; -it should be used after the return type and before the function name).
    • -
    - -

    -The LiveConnect API

    -All public LiveConnect entry points and callbacks are documented in -jsjava.h, -the header file that exports those functions. -
      -

    -File walk-through

    -  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    jsjava.hLiveConnect's only public header file.  Defines all public API -entry points, callbacks and types. 
    jsj_private.hLiveConnect internal header file for intra-module sharing of functions -and types.
    jsj.cPublic LiveConnect API entry points and initialization code. Handling -of multiple threads and multiple JVMs.
    jsj_array.cRead and write elements of a Java array, performing needed conversions -to/from JS types.
    jsj_class.cConstruct and manipulate JavaClassDescriptor structs, which are the -native representation for Java classes.  JavaClassDescriptors are -used to describe the methods and fields of a class, including their type -signatures, and include a reference to the peer java.lang.Class -object.  Since each Java object has a class, there is a JavaClassDescriptor -associated with the JavaScript reflection of each Java Object.
    jsj_convert.cConvert between Java and JavaScript values of all types, which may -require calling routines in other files to wrap JS objects as Java objects -and vice-versa.
    jsj_field.cReflect Java fields as properties of JavaObject objects and implement -getter/setter access to those fields.
    jsj_JavaArray.cImplementation of the JavaScript JavaArray class.  Instances of -JavaArray are used to reflect Java arrays.
    jsj_JavaClass.cImplementation of the JavaScript JavaClass class.   Instances -of JavaClass are used to reflect Java classes.
    jsj_JavaObject.cImplementation of the JavaScript JavaObject class.   Instances -of JavaObject are used to reflect Java objects, except for Java arrays, -although some of the code in this file is used by the JavaArray code.
    jsj_JavaMember.cImplementation of the JavaScript JavaMember class.  JavaMember's -are a strange beast required only to handle the special case of a public -field and a public method that appear in the same Java class and which -have the same name.
    jsj_JavaPackage.cImplementation of the JavaScript JavaPackage class.   Instances -of JavaPackage are used to reflect Java packages.  The JS properties -of a JavaPackage are either nested JavaPackage objects or a JavaClass object.
    jsj_JSObject.cImplementation of the native methods for the  netscape.javascript.JSObject -Java class, which are used for calling into JavaScript from Java.  -It also contains the code that wraps JS objects as instances of  netscape.javascript.JSObject -and -the code that handles propagation of exceptions both into and out of Java.
    jsj_method.cReflect Java methods as properties of JavaObject objects and make it -possible to invoke those methods.  Includes overloaded method resolution -and argument/return-value conversion code.
    jsj_utils.cLow-level utility code for reporting errors, etc.
    - -

    -Sample LiveConnect shell interactions

    - -

    -Java packages, classes and constructors

    -js> java -
    [JavaPackage java] -
    js> awt = java.awt -
    [JavaPackage java.awt] -
    js> Rectangle = awt.Rectangle -
    [JavaClass java.awt.Rectangle] -

    -Java instance fields and methods

    -js> r = new java.awt.Rectangle(34, 23) -
    java.awt.Rectangle[x=0,y=0,width=34,height=23] -
    js> r.width - r.height -
    11 -
    js> r.x = 7; r.y = 4 -
    4 -
    js> r -
    java.awt.Rectangle[x=7,y=4,width=34,height=23] -
    js> r.grow(3) -
    There is no Java method java.awt.Rectangle.grow that matches JavaScript -argument types (number). -
    Candidate methods with the same name are: -
       void grow(int, int) -

    js> r.grow(3, 3) -
    js> r -
    java.awt.Rectangle[x=4,y=1,width=40,height=29] -

    -Java arrays

    -js> s = new java.lang.String("mastiff") -
    mastiff -
    js> c = s.toCharArray() -
    [C@298e9b -
    js> c[0] = "b"; c[4] = "a"; c[5] = "r"; c[6] = "d" -
    d -
    js> s2 = new java.lang.String(c) -
    bastard -

    -Java static fields and methods

    -js> java.lang.reflect.Modifier.ABSTRACT -
    1024 -
    js> java.lang.Math.sin(3) + 2 -
    2.1411200080598674 -

    -Explicit resolution of overloaded Java methods

    -js> x = "23" -
    23 -
    js> java.lang.Math.abs(x) -
    The choice of static Java method java.lang.Math.abs matching JavaScript -argument types (string) is ambiguous. -
    Candidate methods are: -
       long abs(long) -
       float abs(float) -
       double abs(double) -
       int abs(int) -
    js> abs = java.lang.Math["abs(int)"] -

    function abs(int)() { -
        [native code] -
    } -

    js> abs(x) -
    23 -

    -Public Method/field enumeration

    -js> out = java.lang.System.out -
    java.io.PrintStream@2980f5 -
    js> for (m in out) print(m) -
    println -
    print -
    checkError -
    close -
    flush -
    write -
    wait -
    notifyAll -
    notify -
    toString -
    equals -
    hashCode -
    getClass -
    js> for (m in java.lang.String) print(m) -
    copyValueOf -
    valueOf -

    -'instanceof' and 'in' operators

    -js> s = new java.lang.String("foop") -
    foop -
    js> s instanceof java.lang.Class -
    false -
    js> s instanceof java.lang.Object -
    true -
    js> "valueOf" in s -
    true -
    js> "NoSuchThing" in s -
    false -

    -Applying JavaScript string methods to Java strings

    -js> s = new java.lang.String("The rain in Spain falls mainly on my -head.") -
    The rain in Spain falls mainly on my head. -
    js> s.match(/Spain.*my/) -
    Spain falls mainly on my -

    -Applying JavaScript array methods to Java arrays

    -js> s = new java.lang.String("JavaScript") -
    JavaScript -
    js> c = s.toCharArray() -
    [C@298aef -
    js> c.reverse() -
    [C@298aef -
    js> new java.lang.String(c) -
    tpircSavaJ -
      - - diff --git a/lib/javascript/liveconnect/_jni/netscape_javascript_JSException.h b/lib/javascript/liveconnect/_jni/netscape_javascript_JSException.h deleted file mode 100644 index f64412ed..00000000 --- a/lib/javascript/liveconnect/_jni/netscape_javascript_JSException.h +++ /dev/null @@ -1,14 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include "jni.h" - -/* Header for class netscape_javascript_JSException */ - -#ifndef _Included_netscape_javascript_JSException -#define _Included_netscape_javascript_JSException -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif -#endif diff --git a/lib/javascript/liveconnect/_jni/netscape_javascript_JSObject.h b/lib/javascript/liveconnect/_jni/netscape_javascript_JSObject.h deleted file mode 100644 index fcb321b1..00000000 --- a/lib/javascript/liveconnect/_jni/netscape_javascript_JSObject.h +++ /dev/null @@ -1,155 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * This file is part of the Java-vendor-neutral implementation of LiveConnect - * - * Declarations of private (internal) functions/data/types for - * JavaScript <==> Java communication. - * - */ - -#include -/* Header for class netscape_javascript_JSObject */ - -#ifndef _Included_netscape_javascript_JSObject -#define _Included_netscape_javascript_JSObject -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: netscape_javascript_JSObject - * Method: initClass - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_initClass - (JNIEnv *, jclass); - -/* - * Class: netscape_javascript_JSObject - * Method: getMember - * Signature: (Ljava/lang/String;)Ljava/lang/Object; - */ -JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_getMember - (JNIEnv *, jobject, jstring); - -/* - * Class: netscape_javascript_JSObject - * Method: getSlot - * Signature: (I)Ljava/lang/Object; - */ -JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_getSlot - (JNIEnv *, jobject, jint); - -/* - * Class: netscape_javascript_JSObject - * Method: setMember - * Signature: (Ljava/lang/String;Ljava/lang/Object;)V - */ -JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_setMember - (JNIEnv *, jobject, jstring, jobject); - -/* - * Class: netscape_javascript_JSObject - * Method: setSlot - * Signature: (ILjava/lang/Object;)V - */ -JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_setSlot - (JNIEnv *, jobject, jint, jobject); - -/* - * Class: netscape_javascript_JSObject - * Method: removeMember - * Signature: (Ljava/lang/String;)V - */ -JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_removeMember - (JNIEnv *, jobject, jstring); - -/* - * Class: netscape_javascript_JSObject - * Method: call - * Signature: (Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object; - */ -JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_call - (JNIEnv *, jobject, jstring, jobjectArray); - -/* - * Class: netscape_javascript_JSObject - * Method: eval - * Signature: (Ljava/lang/String;)Ljava/lang/Object; - */ -JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_eval - (JNIEnv *, jobject, jstring); - -/* - * Class: netscape_javascript_JSObject - * Method: toString - * Signature: ()Ljava/lang/String; - */ -JNIEXPORT jstring JNICALL Java_netscape_javascript_JSObject_toString - (JNIEnv *, jobject); - -/* - * Class: netscape_javascript_JSObject - * Method: getWindow - * Signature: (Ljava/applet/Applet;)Lnetscape/javascript/JSObject; - */ -JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_getWindow - (JNIEnv *, jclass, jobject); - -/* - * Class: netscape_javascript_JSObject - * Method: finalize - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_finalize - (JNIEnv *, jobject); - -/* - * Class: netscape_javascript_JSObject - * Method: equals - * Signature: (Ljava/lang/Object;)Z - */ -JNIEXPORT jboolean JNICALL Java_netscape_javascript_JSObject_equals - (JNIEnv *, jobject, jobject); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/lib/javascript/liveconnect/classes/.cvsignore b/lib/javascript/liveconnect/classes/.cvsignore deleted file mode 100644 index f3c7a7c5..00000000 --- a/lib/javascript/liveconnect/classes/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -Makefile diff --git a/lib/javascript/liveconnect/classes/Makefile.in b/lib/javascript/liveconnect/classes/Makefile.in deleted file mode 100644 index 0fdadd83..00000000 --- a/lib/javascript/liveconnect/classes/Makefile.in +++ /dev/null @@ -1,89 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either of the GNU General Public License Version 2 or later (the "GPL"), -# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -DEPTH = ../../../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(DEPTH)/config/autoconf.mk - -MODULE = java - -# -# the idea is that the install phase for those modules will -# make their own signed jar files -# there are some exceptions here that we deal with -# stuff in modules and in ns/js/jsj -# -JMODS = netscape/javascript netscape/javascript/adapters - -# -# JDIRS is dependant on JAVA_DESTPATH in config/rules.m[a]k. -# Be sure to touch that directory if you add a new directory to -# JDIRS, or else it will not build. FIXME -# -JDIRS = $(JMODS) - -JAR_JSJ = jsj10.jar -JAR_JSJ_CLASSES = $(JMODS) - -# -# jars to build at install time -# -JARS = $(JAR_JSJ) - -include $(topsrcdir)/config/rules.mk - -JAVA_SOURCEPATH = $(topsrcdir)/js/src/liveconnect/classes - -doc:: - $(JAVADOC) -d $(DIST)/doc netscape.javascript - -natives_list:: FORCE - rm -rf $@ - find . -name "*.class" -print | sed 's@\./\(.*\)\.class$$@\1@' | \ - sed 's@/@.@g' | xargs $(JVH) -natives | sort > $@ - -check_natives:: natives_list - rm -f found_natives - nm -B ../*.o \ - | egrep "Java.*_stub" | awk '{ print $$3; }' | sort > found_natives - diff found_natives natives_list - -FORCE: diff --git a/lib/javascript/liveconnect/classes/Makefile.ref b/lib/javascript/liveconnect/classes/Makefile.ref deleted file mode 100644 index c7cd50f7..00000000 --- a/lib/javascript/liveconnect/classes/Makefile.ref +++ /dev/null @@ -1,57 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either of the GNU General Public License Version 2 or later (the "GPL"), -# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -DEPTH = ../.. - -include $(DEPTH)/config.mk -JAR = $(JDK)/bin/jar -include $(DEPTH)/liveconnect/config/$(OS_CONFIG).mk - -JARS = $(LCJAR) - -JARS := $(addprefix $(CLASSDIR)/$(OBJDIR)/, $(JARS)) - -PREDIRS = netscape -TARGETS += $(JARS) - -include $(DEPTH)/rules.mk - -$(CLASSDIR)/$(OBJDIR)/$(LCJAR): - cd $(CLASSDIR)/$(OBJDIR) ; \ - $(JAR) cvf $(@F) netscape diff --git a/lib/javascript/liveconnect/classes/netscape/Makefile.ref b/lib/javascript/liveconnect/classes/netscape/Makefile.ref deleted file mode 100644 index cb12a40c..00000000 --- a/lib/javascript/liveconnect/classes/netscape/Makefile.ref +++ /dev/null @@ -1,47 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either of the GNU General Public License Version 2 or later (the "GPL"), -# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -DEPTH = ../../.. - -include $(DEPTH)/config.mk -include $(DEPTH)/liveconnect/config/$(OS_CONFIG).mk - -DIRS = javascript - -include $(DEPTH)/rules.mk diff --git a/lib/javascript/liveconnect/classes/netscape/javascript/JSException.java b/lib/javascript/liveconnect/classes/netscape/javascript/JSException.java deleted file mode 100644 index 0f7cfa3c..00000000 --- a/lib/javascript/liveconnect/classes/netscape/javascript/JSException.java +++ /dev/null @@ -1,140 +0,0 @@ -/* -*- Mode: Java; tab-width: 8; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -package netscape.javascript; - -/** - * JSException is an exception which is thrown when JavaScript code - * returns an error. - */ - -public -class JSException extends RuntimeException { - public static final int EXCEPTION_TYPE_EMPTY = -1; - public static final int EXCEPTION_TYPE_VOID = 0; - public static final int EXCEPTION_TYPE_OBJECT = 1; - public static final int EXCEPTION_TYPE_FUNCTION = 2; - public static final int EXCEPTION_TYPE_STRING = 3; - public static final int EXCEPTION_TYPE_NUMBER = 4; - public static final int EXCEPTION_TYPE_BOOLEAN = 5; - public static final int EXCEPTION_TYPE_ERROR = 6; - - String filename; - int lineno; - String source; - int tokenIndex; - private int wrappedExceptionType; - private Object wrappedException; - - /** - * Constructs a JSException without a detail message. - * A detail message is a String that describes this particular exception. - * - * @deprecated Not for public use in future versions. - */ - public JSException() { - super(); - filename = "unknown"; - lineno = 0; - source = ""; - tokenIndex = 0; - wrappedExceptionType = EXCEPTION_TYPE_EMPTY; - } - - /** - * Constructs a JSException with a detail message. - * A detail message is a String that describes this particular exception. - * @param s the detail message - * - * @deprecated Not for public use in future versions. - */ - public JSException(String s) { - super(s); - filename = "unknown"; - lineno = 0; - source = ""; - tokenIndex = 0; - wrappedExceptionType = EXCEPTION_TYPE_EMPTY; - } - - /** - * Constructs a JSException with a wrapped JavaScript exception object. - * This constructor needs to be public so that Java users can throw - * exceptions to JS cleanly. - */ - private JSException(int wrappedExceptionType, Object wrappedException) { - super(); - this.wrappedExceptionType = wrappedExceptionType; - this.wrappedException = wrappedException; - } - - /** - * Constructs a JSException with a detail message and all the - * other info that usually comes with a JavaScript error. - * @param s the detail message - * - * @deprecated Not for public use in future versions. - */ - public JSException(String s, String filename, int lineno, - String source, int tokenIndex) { - super(s); - this.filename = filename; - this.lineno = lineno; - this.source = source; - this.tokenIndex = tokenIndex; - wrappedExceptionType = EXCEPTION_TYPE_EMPTY; - } - - /** - * Instance method getWrappedExceptionType returns the int mapping of the - * type of the wrappedException Object. - */ - public int getWrappedExceptionType() { - return wrappedExceptionType; - } - - /** - * Instance method getWrappedException. - */ - public Object getWrappedException() { - return wrappedException; - } - -} - diff --git a/lib/javascript/liveconnect/classes/netscape/javascript/JSObject.java b/lib/javascript/liveconnect/classes/netscape/javascript/JSObject.java deleted file mode 100644 index 0313a038..00000000 --- a/lib/javascript/liveconnect/classes/netscape/javascript/JSObject.java +++ /dev/null @@ -1,183 +0,0 @@ -/* -*- Mode: Java; tab-width: 8; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* more doc todo: - * threads - * gc - * - * - */ - -package netscape.javascript; - -import java.applet.Applet; - -/** - * JSObject allows Java to manipulate objects that are - * defined in JavaScript. - * Values passed from Java to JavaScript are converted as - * follows:
      - *
    • JSObject is converted to the original JavaScript object - *
    • Any other Java object is converted to a JavaScript wrapper, - * which can be used to access methods and fields of the java object. - * Converting this wrapper to a string will call the toString method - * on the original object, converting to a number will call the - * doubleValue method if possible and fail otherwise. Converting - * to a boolean will try to call the booleanValue method in the - * same way. - *
    • Java arrays are wrapped with a JavaScript object that understands - * array.length and array[index] - *
    • A Java boolean is converted to a JavaScript boolean - *
    • Java byte, char, short, int, long, float, and double are converted - * to JavaScript numbers - *
    - * Values passed from JavaScript to Java are converted as follows:
      - *
    • objects which are wrappers around java objects are unwrapped - *
    • other objects are wrapped with a JSObject - *
    • strings, numbers and booleans are converted to String, Double, - * and Boolean objects respectively - *
    - * This means that all JavaScript values show up as some kind - * of java.lang.Object in Java. In order to make much use of them, - * you will have to cast them to the appropriate subclass of Object, - * e.g. (String) window.getMember("name"); or - * (JSObject) window.getMember("document");. - */ -public final class JSObject { - /* the internal object data */ - private int internal; - private long long_internal; - - /** - * initialize - */ - private static native void initClass(); - static { - // On MRJ, this property won't exist, because the library is preloaded. - String liveConnectLibrary = System.getProperty("netscape.jsj.dll", null); - if (liveConnectLibrary != null) { - System.loadLibrary(liveConnectLibrary); - initClass(); - } - } - - /** - * it is illegal to construct a JSObject manually - */ - private JSObject(int jsobj_addr) { - internal = jsobj_addr; - } - - private JSObject(long jsobj_addr) { - long_internal = jsobj_addr; - } - - /** - * Retrieves a named member of a JavaScript object. - * Equivalent to "this.name" in JavaScript. - */ - public native Object getMember(String name); - - /** - * Retrieves an indexed member of a JavaScript object. - * Equivalent to "this[index]" in JavaScript. - */ -// public Object getMember(int index) { return getSlot(index); } - public native Object getSlot(int index); - - /** - * Sets a named member of a JavaScript object. - * Equivalent to "this.name = value" in JavaScript. - */ - public native void setMember(String name, Object value); - - /** - * Sets an indexed member of a JavaScript object. - * Equivalent to "this[index] = value" in JavaScript. - */ -// public void setMember(int index, Object value) { -// setSlot(index, value); -// } - public native void setSlot(int index, Object value); - - /** - * Removes a named member of a JavaScript object. - */ - public native void removeMember(String name); - - /** - * Calls a JavaScript method. - * Equivalent to "this.methodName(args[0], args[1], ...)" in JavaScript. - */ - public native Object call(String methodName, Object args[]); - - /** - * Evaluates a JavaScript expression. The expression is a string - * of JavaScript source code which will be evaluated in the context - * given by "this". - */ - public native Object eval(String s); - - /** - * Converts a JSObject to a String. - */ - public native String toString(); - - // should use some sort of identifier rather than String - // is "property" the right word? - // native String[] listProperties(); - - - /** - * get a JSObject for the window containing the given applet - */ - public static native JSObject getWindow(Applet applet); - - /** - * Finalization decrements the reference count on the corresponding - * JavaScript object. - */ - protected native void finalize(); - - /** - * Override java.lang.Object.equals() because identity is not preserved - * with instances of JSObject. - */ - public native boolean equals(Object obj); -} diff --git a/lib/javascript/liveconnect/classes/netscape/javascript/JSProxy.java b/lib/javascript/liveconnect/classes/netscape/javascript/JSProxy.java deleted file mode 100644 index e4f1f6ed..00000000 --- a/lib/javascript/liveconnect/classes/netscape/javascript/JSProxy.java +++ /dev/null @@ -1,58 +0,0 @@ -/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/** - * The JSProxy interface allows applets and plugins to - * share javascript contexts. - */ - -package netscape.javascript; -import java.applet.Applet; - -public interface JSProxy { - Object getMember(JSObject jso, String name); - Object getSlot(JSObject jso, int index); - void setMember(JSObject jso, String name, Object value); - void setSlot(JSObject jso, int index, Object value); - void removeMember(JSObject jso, String name); - Object call(JSObject jso, String methodName, Object args[]); - Object eval(JSObject jso, String s); - String toString(JSObject jso); - JSObject getWindow(Applet applet); -} diff --git a/lib/javascript/liveconnect/classes/netscape/javascript/JSRunnable.java b/lib/javascript/liveconnect/classes/netscape/javascript/JSRunnable.java deleted file mode 100644 index 84ecab49..00000000 --- a/lib/javascript/liveconnect/classes/netscape/javascript/JSRunnable.java +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- Mode: Java; tab-width: 8; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -package netscape.javascript; - -/** - * Runs a JavaScript object with a run() method in a separate thread. - */ -public class JSRunnable implements Runnable { - private JSObject runnable; - - public JSRunnable(JSObject runnable) { - this.runnable = runnable; - synchronized(this) { - new Thread(this).start(); - try { - this.wait(); - } catch (InterruptedException ie) { - } - } - } - - public void run() { - try { - runnable.call("run", null); - synchronized(this) { - notifyAll(); - } - } catch (Throwable t) { - System.err.println(t); - t.printStackTrace(System.err); - } - } -} diff --git a/lib/javascript/liveconnect/classes/netscape/javascript/JSUtil.java b/lib/javascript/liveconnect/classes/netscape/javascript/JSUtil.java deleted file mode 100644 index 47bc6e66..00000000 --- a/lib/javascript/liveconnect/classes/netscape/javascript/JSUtil.java +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- Mode: Java; tab-width: 8; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* ** */ - -package netscape.javascript; -import java.io.*; - -public class JSUtil { - - /* Return the stack trace of an exception or error as a String */ - public static String getStackTrace(Throwable t) { - ByteArrayOutputStream captureStream; - PrintWriter p; - - captureStream = new ByteArrayOutputStream(); - p = new PrintWriter(captureStream); - - t.printStackTrace(p); - p.flush(); - - return captureStream.toString(); - } -} diff --git a/lib/javascript/liveconnect/classes/netscape/javascript/Makefile.ref b/lib/javascript/liveconnect/classes/netscape/javascript/Makefile.ref deleted file mode 100644 index d66218fa..00000000 --- a/lib/javascript/liveconnect/classes/netscape/javascript/Makefile.ref +++ /dev/null @@ -1,53 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either of the GNU General Public License Version 2 or later (the "GPL"), -# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -DEPTH = ../../../.. - -include $(DEPTH)/config.mk -include $(DEPTH)/liveconnect/config/$(OS_CONFIG).mk - -JARPATH = netscape/javascript - -JAVA_SRCS = JSException.java \ - JSObject.java \ - JSProxy.java \ - JSRunnable.java \ - JSUtil.java - -include $(DEPTH)/rules.mk diff --git a/lib/javascript/liveconnect/config/AIX4.1.mk b/lib/javascript/liveconnect/config/AIX4.1.mk deleted file mode 100644 index 9c47eccb..00000000 --- a/lib/javascript/liveconnect/config/AIX4.1.mk +++ /dev/null @@ -1,45 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# Change these to the current platform settings!!! - -JDK = /tools/ns - -INCLUDES += -I$(JDK)/include/java -I$(JDK)/include/java/aix - -OTHER_LIBS += -L$(JDK)/lib/aix/native_threads -ljava diff --git a/lib/javascript/liveconnect/config/AIX4.2.mk b/lib/javascript/liveconnect/config/AIX4.2.mk deleted file mode 100644 index 9c47eccb..00000000 --- a/lib/javascript/liveconnect/config/AIX4.2.mk +++ /dev/null @@ -1,45 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# Change these to the current platform settings!!! - -JDK = /tools/ns - -INCLUDES += -I$(JDK)/include/java -I$(JDK)/include/java/aix - -OTHER_LIBS += -L$(JDK)/lib/aix/native_threads -ljava diff --git a/lib/javascript/liveconnect/config/AIX4.3.mk b/lib/javascript/liveconnect/config/AIX4.3.mk deleted file mode 100644 index 19d3d1b4..00000000 --- a/lib/javascript/liveconnect/config/AIX4.3.mk +++ /dev/null @@ -1,50 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# Change these to the current platform settings!!! - -#JDK = /tools/ns -JDK = /share/builds/components/jdk/1.2beta/AIX -JAVAC = $(JDK)/sh/javac -JAR = $(JDK)/sh/jar - -INCLUDES += -I$(JDK)/include - -#OTHER_LIBS += -L$(JDK)/lib/aix/native_threads -ljava -OTHER_LIBS += -L$(JDK)/jre/bin -ljava -L$(JDK)/jre/bin/classic -ljvm - diff --git a/lib/javascript/liveconnect/config/HP-UXB.10.10.mk b/lib/javascript/liveconnect/config/HP-UXB.10.10.mk deleted file mode 100644 index 1ad61570..00000000 --- a/lib/javascript/liveconnect/config/HP-UXB.10.10.mk +++ /dev/null @@ -1,43 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -JDK = /share/builds/components/jdk/1.1.5/HP-UX10 - -INCLUDES += -I$(JDK)/include -I$(JDK)/include/hp-ux - -OTHER_LIBS += -L$(JDK)/lib/PA_RISC/green_threads -ljava diff --git a/lib/javascript/liveconnect/config/HP-UXB.10.20.mk b/lib/javascript/liveconnect/config/HP-UXB.10.20.mk deleted file mode 100644 index 1ad61570..00000000 --- a/lib/javascript/liveconnect/config/HP-UXB.10.20.mk +++ /dev/null @@ -1,43 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -JDK = /share/builds/components/jdk/1.1.5/HP-UX10 - -INCLUDES += -I$(JDK)/include -I$(JDK)/include/hp-ux - -OTHER_LIBS += -L$(JDK)/lib/PA_RISC/green_threads -ljava diff --git a/lib/javascript/liveconnect/config/HP-UXB.11.00.mk b/lib/javascript/liveconnect/config/HP-UXB.11.00.mk deleted file mode 100644 index 0997932c..00000000 --- a/lib/javascript/liveconnect/config/HP-UXB.11.00.mk +++ /dev/null @@ -1,43 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -JDK = /share/builds/components/jdk/1.1.5/HP-UX - -INCLUDES += -I$(JDK)/include -I$(JDK)/include/hp-ux - -OTHER_LIBS += -L$(JDK)/lib/PA_RISC/native_threads -ljava diff --git a/lib/javascript/liveconnect/config/IRIX6.2.mk b/lib/javascript/liveconnect/config/IRIX6.2.mk deleted file mode 100644 index b9306d75..00000000 --- a/lib/javascript/liveconnect/config/IRIX6.2.mk +++ /dev/null @@ -1,43 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -JDK = /share/builds/components/jdk/1.1.6/IRIX - -INCLUDES += -I$(JDK)/include -I$(JDK)/include/irix - -OTHER_LIBS += -L$(JDK)/lib/sgi/native_threads -ljava diff --git a/lib/javascript/liveconnect/config/IRIX6.3.mk b/lib/javascript/liveconnect/config/IRIX6.3.mk deleted file mode 100644 index b9306d75..00000000 --- a/lib/javascript/liveconnect/config/IRIX6.3.mk +++ /dev/null @@ -1,43 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -JDK = /share/builds/components/jdk/1.1.6/IRIX - -INCLUDES += -I$(JDK)/include -I$(JDK)/include/irix - -OTHER_LIBS += -L$(JDK)/lib/sgi/native_threads -ljava diff --git a/lib/javascript/liveconnect/config/IRIX6.5.mk b/lib/javascript/liveconnect/config/IRIX6.5.mk deleted file mode 100644 index e15e6668..00000000 --- a/lib/javascript/liveconnect/config/IRIX6.5.mk +++ /dev/null @@ -1,43 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -JDK = /share/builds/components/jdk/1.1.6/IRIX - -INCLUDES += -I$(JDK)/include -I$(JDK)/include/irix - -OTHER_LIBS += -L$(JDK)/lib32/sgi/native_threads -ljava diff --git a/lib/javascript/liveconnect/config/Linux_All.mk b/lib/javascript/liveconnect/config/Linux_All.mk deleted file mode 100644 index 8de3647a..00000000 --- a/lib/javascript/liveconnect/config/Linux_All.mk +++ /dev/null @@ -1,73 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# JDK_DIR should be the directory you put the JDK in, and should have -# the appropriate lib/ and include/ dirs on it. -# If you're not using the `Blackdown' JDK, try changing the following line: - -# JDK=/share/builds/components/jdk/1.1.7/Linux - -ifndef JDK_VERSION -JDK_VERSION = 1.2.2 -endif - -JDK = /share/builds/components/jdk/$(JDK_VERSION)/Linux - -# INCLUDES += -I$(JDK)/include -I$(JDK)/include/solaris -INCLUDES += -I$(JDK)/include/linux -I$(JDK)/include - -OTHER_LIBS += -L$(JDK)/jre/lib/i386/native_threads -OTHER_LIBS += -L$(JDK)/jre/lib/i386/classic -OTHER_LIBS += -L$(JDK)/jre/lib/i386 -ljava -ljvm -lhpi - -# To run lcshell with the above, built in a Mozilla tree with a local nspr: -# LD_LIBRARY_PATH=../../../dist/lib:/share/builds/components/jdk/1.2.2/Linux/jre/lib/i386:/share/builds/components/jdk/1.2.2/Linux/jre/lib/i386/classic:/share/builds/components/jdk/1.2.2/Linux/jre/lib/i386/native_threads CLASSPATH=./classes/Linux_All_DBG.OBJ/js15lc30.jar lcshell - -# Uncomment below to maybe build against 1.3. - -# export THREADS_FLAG=native - -# JDK = /usr/java/jdk1.3 - -# INCLUDES += -I$(JDK)/include -I$(JDK)/include/md \ -# -I$(JDK)/include/genunix -I$(JDK)/include/linux \ - -# OTHER_LIBS += -L$(JDK)/jre/lib/i386/native_threads -ljava \ -# -L$(JDK)/jre/lib/i386 -lverify -lhpi - -# export THREADS_FLAG=native diff --git a/lib/javascript/liveconnect/config/OSF1V4.0.mk b/lib/javascript/liveconnect/config/OSF1V4.0.mk deleted file mode 100644 index bc0d3b50..00000000 --- a/lib/javascript/liveconnect/config/OSF1V4.0.mk +++ /dev/null @@ -1,65 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# JDK = /share/builds/components/jdk/1.1.6/OSF1 - -# INCLUDES += -I$(JDK)/include/java -I$(JDK)/include/java/alpha - -# OTHER_LIBS += -L$(JDK)/lib/alpha -ljava - -# XLDFLAGS += -taso - -ifndef JDK_VERSION -JDK_VERSION = 1.2.2 -endif - -# jni.h #error's without this. -CFLAGS += -pthread - -JDK = /share/builds/components/jdk/$(JDK_VERSION)/OSF1 - -# INCLUDES += -I$(JDK)/include -I$(JDK)/include/solaris -INCLUDES += -I$(JDK)/include/alpha -I$(JDK)/include - -# XXX is this consistent with -pthread above? -OTHER_LIBS += -L$(JDK)/jre/lib/alpha/native_threads -OTHER_LIBS += -L$(JDK)/jre/lib/alpha/classic -OTHER_LIBS += -L$(JDK)/jre/lib/alpha -ljava -ljvm - -# Taken from the previous revision - no idea what it does. -XLDFLAGS += -taso diff --git a/lib/javascript/liveconnect/config/OSF1V5.0.mk b/lib/javascript/liveconnect/config/OSF1V5.0.mk deleted file mode 100644 index ea415bac..00000000 --- a/lib/javascript/liveconnect/config/OSF1V5.0.mk +++ /dev/null @@ -1,62 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# JDK = /share/builds/components/jdk/1.1.6/OSF1 - -# INCLUDES += -I$(JDK)/include/java -I$(JDK)/include/java/alpha - -# OTHER_LIBS += -L$(JDK)/lib/alpha -ljava - -# XLDFLAGS += -taso - -ifndef JDK_VERSION -JDK_VERSION = 1.2.2 -endif - -# jni.h #error's without this. -CFLAGS += -pthread - -JDK = /share/builds/components/jdk/$(JDK_VERSION)/OSF1 - -# INCLUDES += -I$(JDK)/include -I$(JDK)/include/solaris -INCLUDES += -I$(JDK)/include/alpha -I$(JDK)/include - -# XXX is this consistent with -pthread above? -OTHER_LIBS += -L$(JDK)/jre/lib/alpha/native_threads -OTHER_LIBS += -L$(JDK)/jre/lib/alpha/classic -OTHER_LIBS += -L$(JDK)/jre/lib/alpha -ljava -ljvm diff --git a/lib/javascript/liveconnect/config/SunOS5.5.1.mk b/lib/javascript/liveconnect/config/SunOS5.5.1.mk deleted file mode 100644 index 79d690b1..00000000 --- a/lib/javascript/liveconnect/config/SunOS5.5.1.mk +++ /dev/null @@ -1,55 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# Change these to the current platform settings!!! - -ifndef JDK_VERSION -JDK_VERSION = 1.2.2 -endif - -JDK = /share/builds/components/jdk/$(JDK_VERSION)/SunOS - -# INCLUDES += -I$(JDK)/include -I$(JDK)/include/solaris -INCLUDES += -I$(JDK)/include/solaris -I$(JDK)/include - -OTHER_LIBS += -L$(JDK)/jre/lib/sparc/native_threads -OTHER_LIBS += -L$(JDK)/jre/lib/sparc/classic -OTHER_LIBS += -L$(JDK)/jre/lib/sparc -ljava -ljvm - - diff --git a/lib/javascript/liveconnect/config/SunOS5.6.mk b/lib/javascript/liveconnect/config/SunOS5.6.mk deleted file mode 100644 index 5538fb68..00000000 --- a/lib/javascript/liveconnect/config/SunOS5.6.mk +++ /dev/null @@ -1,39 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -include $(DEPTH)/liveconnect/config/SunOS5.5.1.mk diff --git a/lib/javascript/liveconnect/config/SunOS5.7.mk b/lib/javascript/liveconnect/config/SunOS5.7.mk deleted file mode 100644 index 5538fb68..00000000 --- a/lib/javascript/liveconnect/config/SunOS5.7.mk +++ /dev/null @@ -1,39 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -include $(DEPTH)/liveconnect/config/SunOS5.5.1.mk diff --git a/lib/javascript/liveconnect/config/SunOS5.8.mk b/lib/javascript/liveconnect/config/SunOS5.8.mk deleted file mode 100644 index 5538fb68..00000000 --- a/lib/javascript/liveconnect/config/SunOS5.8.mk +++ /dev/null @@ -1,39 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -include $(DEPTH)/liveconnect/config/SunOS5.5.1.mk diff --git a/lib/javascript/liveconnect/config/WINNT4.0.mk b/lib/javascript/liveconnect/config/WINNT4.0.mk deleted file mode 100644 index 9a255909..00000000 --- a/lib/javascript/liveconnect/config/WINNT4.0.mk +++ /dev/null @@ -1,53 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -ifeq ($(JDKVER),1_2_2) - -JDK = c:/jdk1.2.2 -OTHER_LIBS += $(JDK)/lib/jvm.lib ../$(OBJDIR)/js32.lib - -else - -JDK = c:/jdk1.1.8 -OTHER_LIBS += $(JDK)/lib/javai.lib ../$(OBJDIR)/js32.lib - -endif - -INCLUDES += -I$(JDK)/include -I$(JDK)/include/win32 - -JSDLL_CFLAGS = diff --git a/lib/javascript/liveconnect/jsj.c b/lib/javascript/liveconnect/jsj.c deleted file mode 100644 index 334b3b71..00000000 --- a/lib/javascript/liveconnect/jsj.c +++ /dev/null @@ -1,886 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * This file is part of the Java-vendor-neutral implementation of LiveConnect - * - * It contains the top-level initialization code and the implementation of the - * public API. - * - */ - -#include -#include - -#include "jsj_private.h" /* LiveConnect internals */ -#include "jsjava.h" /* LiveConnect external API */ - -#ifdef JSJ_THREADSAFE -# include "prmon.h" -#endif - -JSBool jsj_JSIsCallingApplet = JS_FALSE; - -/* - * At certain times during initialization, there may be no JavaScript context - * available to direct error reports to, in which case the error messages - * are sent to this function. The caller is responsible for free'ing - * the js_error_msg argument. - */ -static void -report_java_initialization_error(JNIEnv *jEnv, const char *js_error_msg) -{ - const char *error_msg, *java_error_msg; - - java_error_msg = NULL; - - if (jEnv) { - java_error_msg = jsj_GetJavaErrorMessage(jEnv); - (*jEnv)->ExceptionClear(jEnv); - } - - if (java_error_msg) { - error_msg = JS_smprintf("initialization error: %s (%s)\n", - js_error_msg, java_error_msg); - free((void*)java_error_msg); - } else { - error_msg = JS_smprintf("initialization error: %s\n", - js_error_msg); - } - - jsj_LogError(error_msg); - free((void*)error_msg); -} - -/* - * Opaque JVM handles to Java classes and methods required for Java reflection. - * These are computed and cached during initialization. - */ - -jclass jlObject; /* java.lang.Object */ -jclass jlrMethod; /* java.lang.reflect.Method */ -jclass jlrField; /* java.lang.reflect.Field */ -jclass jlrArray; /* java.lang.reflect.Array */ -jclass jlVoid; /* java.lang.Void */ -jclass jlrConstructor; /* java.lang.reflect.Constructor */ -jclass jlThrowable; /* java.lang.Throwable */ -jclass jlSystem; /* java.lang.System */ -jclass jlClass; /* java.lang.Class */ -jclass jlBoolean; /* java.lang.Boolean */ -jclass jlDouble; /* java.lang.Double */ -jclass jlString; /* java.lang.String */ -jclass jaApplet; /* java.applet.Applet */ -jclass njJSObject; /* netscape.javascript.JSObject */ -jclass njJSException; /* netscape.javascript.JSException */ -jclass njJSUtil; /* netscape.javascript.JSUtil */ - -jmethodID jlClass_getMethods; /* java.lang.Class.getMethods() */ -jmethodID jlClass_getConstructors; /* java.lang.Class.getConstructors() */ -jmethodID jlClass_getFields; /* java.lang.Class.getFields() */ -jmethodID jlClass_getName; /* java.lang.Class.getName() */ -jmethodID jlClass_getComponentType; /* java.lang.Class.getComponentType() */ -jmethodID jlClass_getModifiers; /* java.lang.Class.getModifiers() */ -jmethodID jlClass_isArray; /* java.lang.Class.isArray() */ - -jmethodID jlrMethod_getName; /* java.lang.reflect.Method.getName() */ -jmethodID jlrMethod_getParameterTypes; /* java.lang.reflect.Method.getParameterTypes() */ -jmethodID jlrMethod_getReturnType; /* java.lang.reflect.Method.getReturnType() */ -jmethodID jlrMethod_getModifiers; /* java.lang.reflect.Method.getModifiers() */ - -jmethodID jlrConstructor_getParameterTypes; /* java.lang.reflect.Constructor.getParameterTypes() */ -jmethodID jlrConstructor_getModifiers; /* java.lang.reflect.Constructor.getModifiers() */ - -jmethodID jlrField_getName; /* java.lang.reflect.Field.getName() */ -jmethodID jlrField_getType; /* java.lang.reflect.Field.getType() */ -jmethodID jlrField_getModifiers; /* java.lang.reflect.Field.getModifiers() */ - -jmethodID jlrArray_newInstance; /* java.lang.reflect.Array.newInstance() */ - -jmethodID jlBoolean_Boolean; /* java.lang.Boolean constructor */ -jmethodID jlBoolean_booleanValue; /* java.lang.Boolean.booleanValue() */ -jmethodID jlDouble_Double; /* java.lang.Double constructor */ -jmethodID jlDouble_doubleValue; /* java.lang.Double.doubleValue() */ - -jmethodID jlThrowable_toString; /* java.lang.Throwable.toString() */ -jmethodID jlThrowable_getMessage; /* java.lang.Throwable.getMessage() */ - -jmethodID jlSystem_identityHashCode; /* java.lang.System.identityHashCode() */ - -jobject jlVoid_TYPE; /* java.lang.Void.TYPE value */ - -jmethodID njJSException_JSException; /* netscape.javascript.JSException constructor */ -jmethodID njJSException_JSException_wrap;/*netscape.javascript.JSException alternate constructor */ -jmethodID njJSObject_JSObject; /* netscape.javascript.JSObject constructor */ -jmethodID njJSUtil_getStackTrace; /* netscape.javascript.JSUtil.getStackTrace() */ -jfieldID njJSObject_internal; /* netscape.javascript.JSObject.internal */ -jfieldID njJSObject_long_internal; /* netscape.javascript.JSObject.long_internal */ -jfieldID njJSException_lineno; /* netscape.javascript.JSException.lineno */ -jfieldID njJSException_tokenIndex; /* netscape.javascript.JSException.tokenIndex */ -jfieldID njJSException_source; /* netscape.javascript.JSException.source */ -jfieldID njJSException_filename; /* netscape.javascript.JSException.filename */ -jfieldID njJSException_wrappedExceptionType; /* netscape.javascript.JSException.wrappedExceptionType */ -jfieldID njJSException_wrappedException; /* netscape.javascript.JSException.wrappedException */ - -/* Obtain a reference to a Java class */ -#define LOAD_CLASS(qualified_name, class) \ - { \ - jclass _##class = (*jEnv)->FindClass(jEnv, #qualified_name); \ - if (_##class == 0) { \ - (*jEnv)->ExceptionClear(jEnv); \ - report_java_initialization_error(jEnv, \ - "Can't load class " #qualified_name); \ - return JS_FALSE; \ - } \ - class = (*jEnv)->NewGlobalRef(jEnv, _##class); \ - (*jEnv)->DeleteLocalRef(jEnv, _##class); \ - } - -/* Obtain a methodID reference to a Java method or constructor */ -#define _LOAD_METHOD(qualified_class, method, mvar, signature, class, is_static)\ - if (is_static) { \ - class##_##mvar = \ - (*jEnv)->GetStaticMethodID(jEnv, class, #method, signature); \ - } else { \ - class##_##mvar = \ - (*jEnv)->GetMethodID(jEnv, class, #method, signature); \ - } \ - if (class##_##mvar == 0) { \ - (*jEnv)->ExceptionClear(jEnv); \ - report_java_initialization_error(jEnv, \ - "Can't get mid for " #qualified_class "." #method "()"); \ - return JS_FALSE; \ - } - -/* Obtain a methodID reference to a Java instance method */ -#define LOAD_METHOD(qualified_class, method, signature, class) \ - _LOAD_METHOD(qualified_class, method, method, signature, class, JS_FALSE) - -/* Obtain a methodID reference to a Java static method */ -#define LOAD_STATIC_METHOD(qualified_class, method, signature, class) \ - _LOAD_METHOD(qualified_class, method, method, signature, class, JS_TRUE) - -/* Obtain a methodID reference to a Java constructor */ -#define LOAD_CONSTRUCTOR(qualified_class, method, signature, class) \ - _LOAD_METHOD(qualified_class,, method, signature, class, JS_FALSE) - -/* Obtain a fieldID reference to a Java instance or static field */ -#define _LOAD_FIELDID(qualified_class, field, signature, class, is_static) \ - if (is_static) { \ - class##_##field = (*jEnv)->GetStaticFieldID(jEnv, class, #field, signature);\ - } else { \ - class##_##field = (*jEnv)->GetFieldID(jEnv, class, #field, signature);\ - } \ - if (class##_##field == 0) { \ - (*jEnv)->ExceptionClear(jEnv); \ - report_java_initialization_error(jEnv, \ - "Can't get fid for " #qualified_class "." #field); \ - return JS_FALSE; \ - } - -/* Obtain a fieldID reference to a Java instance field */ -#define LOAD_FIELDID(qualified_class, field, signature, class) \ - _LOAD_FIELDID(qualified_class, field, signature, class, JS_FALSE) - -/* Obtain the value of a static field in a Java class */ -#define LOAD_FIELD_VAL(qualified_class, field, signature, class, type) \ - { \ - jfieldID field_id; \ - field_id = (*jEnv)->GetStaticFieldID(jEnv, class, #field, signature);\ - if (field_id == 0) { \ - report_java_initialization_error(jEnv, \ - "Can't get fid for " #qualified_class "." #field); \ - return JS_FALSE; \ - } \ - class##_##field = \ - (*jEnv)->GetStatic##type##Field(jEnv, class, field_id); \ - if (class##_##field == 0) { \ - (*jEnv)->ExceptionClear(jEnv); \ - report_java_initialization_error(jEnv, \ - "Can't read static field " #qualified_class "." #field); \ - return JS_FALSE; \ - } \ - } - -/* Obtain the value of a static field in a Java class, which is known to - contain an object value. */ -#define LOAD_FIELD_OBJ(qualified_class, field, signature, class) \ - LOAD_FIELD_VAL(qualified_class, field, signature, class, Object); \ - class##_##field = (*jEnv)->NewGlobalRef(jEnv, class##_##field); - -/* - * Load the Java classes, and the method and field descriptors required for Java reflection. - * Returns JS_TRUE on success, JS_FALSE on failure. - */ -static JSBool -init_java_VM_reflection(JSJavaVM *jsjava_vm, JNIEnv *jEnv) -{ - /* Load Java system classes and method, including java.lang.reflect classes */ - LOAD_CLASS(java/lang/Object, jlObject); - LOAD_CLASS(java/lang/Class, jlClass); - LOAD_CLASS(java/lang/reflect/Method, jlrMethod); - LOAD_CLASS(java/lang/reflect/Constructor, jlrConstructor); - LOAD_CLASS(java/lang/reflect/Field, jlrField); - LOAD_CLASS(java/lang/reflect/Array, jlrArray); - LOAD_CLASS(java/lang/Throwable, jlThrowable); - LOAD_CLASS(java/lang/System, jlSystem); - LOAD_CLASS(java/lang/Boolean, jlBoolean); - LOAD_CLASS(java/lang/Double, jlDouble); - LOAD_CLASS(java/lang/String, jlString); - LOAD_CLASS(java/lang/Void, jlVoid); - - LOAD_CLASS(java/applet/Applet, jaApplet); - - LOAD_METHOD(java.lang.Class, getMethods, "()[Ljava/lang/reflect/Method;",jlClass); - LOAD_METHOD(java.lang.Class, getConstructors, "()[Ljava/lang/reflect/Constructor;",jlClass); - LOAD_METHOD(java.lang.Class, getFields, "()[Ljava/lang/reflect/Field;", jlClass); - LOAD_METHOD(java.lang.Class, getName, "()Ljava/lang/String;", jlClass); - LOAD_METHOD(java.lang.Class, isArray, "()Z", jlClass); - LOAD_METHOD(java.lang.Class, getComponentType, "()Ljava/lang/Class;", jlClass); - LOAD_METHOD(java.lang.Class, getModifiers, "()I", jlClass); - - LOAD_METHOD(java.lang.reflect.Method, getName, "()Ljava/lang/String;", jlrMethod); - LOAD_METHOD(java.lang.reflect.Method, getParameterTypes, "()[Ljava/lang/Class;", jlrMethod); - LOAD_METHOD(java.lang.reflect.Method, getReturnType, "()Ljava/lang/Class;", jlrMethod); - LOAD_METHOD(java.lang.reflect.Method, getModifiers, "()I", jlrMethod); - - LOAD_METHOD(java.lang.reflect.Constructor, getParameterTypes, "()[Ljava/lang/Class;", jlrConstructor); - LOAD_METHOD(java.lang.reflect.Constructor, getModifiers, "()I", jlrConstructor); - - LOAD_METHOD(java.lang.reflect.Field, getName, "()Ljava/lang/String;", jlrField); - LOAD_METHOD(java.lang.reflect.Field, getType, "()Ljava/lang/Class;", jlrField); - LOAD_METHOD(java.lang.reflect.Field, getModifiers, "()I", jlrField); - - LOAD_STATIC_METHOD(java.lang.reflect.Array, - newInstance, "(Ljava/lang/Class;I)Ljava/lang/Object;",jlrArray); - - LOAD_METHOD(java.lang.Throwable, toString, "()Ljava/lang/String;", jlThrowable); - LOAD_METHOD(java.lang.Throwable, getMessage, "()Ljava/lang/String;", jlThrowable); - - LOAD_METHOD(java.lang.Double, doubleValue, "()D", jlDouble); - - LOAD_METHOD(java.lang.Boolean, booleanValue, "()Z", jlBoolean); - - LOAD_STATIC_METHOD(java.lang.System, identityHashCode, "(Ljava/lang/Object;)I", jlSystem); - - LOAD_CONSTRUCTOR(java.lang.Boolean, Boolean, "(Z)V", jlBoolean); - LOAD_CONSTRUCTOR(java.lang.Double, Double, "(D)V", jlDouble); - - LOAD_FIELD_OBJ(java.lang.Void, TYPE, "Ljava/lang/Class;", jlVoid); - - return JS_TRUE; -} - -#if !defined(OJI) - -/** - * Workaround for the fact that MRJ loads a different instance of the shared library. - */ - -#include "netscape_javascript_JSObject.h" - -/* Manually load the required native methods. */ -static JSBool -JSObject_RegisterNativeMethods(JNIEnv* jEnv) -{ - - static JNINativeMethod nativeMethods[] = { - {"initClass", "()V", (void*)&Java_netscape_javascript_JSObject_initClass}, - -#ifndef OJI - {"getMember", "(Ljava/lang/String;)Ljava/lang/Object;", (void*)&Java_netscape_javascript_JSObject_getMember}, - {"getSlot", "(I)Ljava/lang/Object;", (void*)&Java_netscape_javascript_JSObject_getSlot}, - {"setMember", "(Ljava/lang/String;Ljava/lang/Object;)V", (void*)&Java_netscape_javascript_JSObject_setMember}, - {"setSlot", "(ILjava/lang/Object;)V", (void*)&Java_netscape_javascript_JSObject_setSlot}, - {"removeMember", "(Ljava/lang/String;)V", (void*)&Java_netscape_javascript_JSObject_removeMember}, - {"call", "(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;", (void*)&Java_netscape_javascript_JSObject_call}, - {"eval", "(Ljava/lang/String;)Ljava/lang/Object;", (void*)&Java_netscape_javascript_JSObject_eval}, - - {"toString", "()Ljava/lang/String;", (void*)&Java_netscape_javascript_JSObject_toString}, - {"getWindow", "(Ljava/applet/Applet;)Lnetscape/javascript/JSObject;", (void*)&Java_netscape_javascript_JSObject_getWindow}, - {"finalize", "()V", (void*)&Java_netscape_javascript_JSObject_finalize}, - {"equals", "(Ljava/lang/Object;)Z", (void*)&Java_netscape_javascript_JSObject_equals} -#endif /* !OJI */ - - }; - (*jEnv)->RegisterNatives(jEnv, njJSObject, nativeMethods, sizeof(nativeMethods) / sizeof(JNINativeMethod)); - if ((*jEnv)->ExceptionOccurred(jEnv)) { - report_java_initialization_error(jEnv, "Couldn't initialize JSObject native methods."); - (*jEnv)->ExceptionClear(jEnv); - return JS_FALSE; - } - /* Call the initClass method */ - Java_netscape_javascript_JSObject_initClass(jEnv, njJSObject); - return JS_TRUE; -} - -#endif - -/* Load Netscape-specific Java extension classes, methods, and fields */ -static JSBool -init_netscape_java_classes(JSJavaVM *jsjava_vm, JNIEnv *jEnv) -{ - LOAD_CLASS(netscape/javascript/JSObject, njJSObject); - LOAD_CLASS(netscape/javascript/JSException, njJSException); - LOAD_CLASS(netscape/javascript/JSUtil, njJSUtil); - -#if !defined(OJI) - JSObject_RegisterNativeMethods(jEnv); -#endif - -#ifndef OJI - LOAD_CONSTRUCTOR(netscape.javascript.JSObject, - JSObject, "(I)V", njJSObject); -#endif - LOAD_CONSTRUCTOR(netscape.javascript.JSException, - JSException, "(Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;I)V", - njJSException); - - /* Load second constructor for wrapping JS exception objects inside JSExceptions */ - _LOAD_METHOD(netscape.javascript.JSException,, - JSException_wrap, "(ILjava/lang/Object;)V", - njJSException, JS_FALSE); - -#ifndef OJI - LOAD_FIELDID(netscape.javascript.JSObject, - internal, "I", njJSObject); -#endif - LOAD_FIELDID(netscape.javascript.JSException, - lineno, "I", njJSException); - LOAD_FIELDID(netscape.javascript.JSException, - tokenIndex, "I", njJSException); - LOAD_FIELDID(netscape.javascript.JSException, - source, "Ljava/lang/String;", njJSException); - LOAD_FIELDID(netscape.javascript.JSException, - filename, "Ljava/lang/String;", njJSException); - LOAD_FIELDID(netscape.javascript.JSException, wrappedExceptionType, "I", - njJSException); - LOAD_FIELDID(netscape.javascript.JSException, wrappedException, - "Ljava/lang/Object;", njJSException); - - LOAD_STATIC_METHOD(netscape.javascript.JSUtil, - getStackTrace, "(Ljava/lang/Throwable;)Ljava/lang/String;", - njJSUtil); - - return JS_TRUE; -} - -JSJavaVM *jsjava_vm_list = NULL; - -static JSJavaThreadState *thread_list = NULL; - -#ifdef JSJ_THREADSAFE -static PRMonitor *thread_list_monitor = NULL; -#endif - -/* - * Called once per Java VM, this function initializes the classes, fields, and - * methods required for Java reflection. If java_vm is NULL, a new Java VM is - * created, using the provided classpath in addition to any default classpath. - * The classpath argument is ignored, however, if java_vm_arg is non-NULL. - */ -JSJavaVM * -JSJ_ConnectToJavaVM(SystemJavaVM *java_vm_arg, void* initargs) -{ - SystemJavaVM* java_vm; - JSJavaVM *jsjava_vm; - JNIEnv *jEnv; - - JS_ASSERT(JSJ_callbacks); - JS_ASSERT(JSJ_callbacks->attach_current_thread); - JS_ASSERT(JSJ_callbacks->detach_current_thread); - JS_ASSERT(JSJ_callbacks->get_java_vm); - - jsjava_vm = (JSJavaVM*)malloc(sizeof(JSJavaVM)); - if (!jsjava_vm) - return NULL; - memset(jsjava_vm, 0, sizeof(JSJavaVM)); - - java_vm = java_vm_arg; - - /* If a Java VM was passed in, try to attach to it on the current thread. */ - if (java_vm) { - jEnv = JSJ_callbacks->attach_current_thread(java_vm); - if (jEnv == NULL) { - jsj_LogError("Failed to attach to Java VM thread\n"); - free(jsjava_vm); - return NULL; - } - - jsjava_vm->java_vm = java_vm; - jsjava_vm->main_thread_env = jEnv; - } else { - jsjava_vm->init_args = initargs; - } - -#ifdef JSJ_THREADSAFE - if (jsjava_vm_list == NULL) { - thread_list_monitor = - (struct PRMonitor *) PR_NewMonitor(); - } -#endif /* JSJ_THREADSAFE */ - - /* Put this VM on the list of all created VMs */ - jsjava_vm->next = jsjava_vm_list; - jsjava_vm_list = jsjava_vm; - - return jsjava_vm; -} - -/* Completes a lazy connection to the host Java VM. */ -static JSBool -jsj_ConnectToJavaVM(JSJavaVM *jsjava_vm) -{ - if (!jsjava_vm->java_vm) { - JSBool ok; - JS_ASSERT(JSJ_callbacks->create_java_vm); - JS_ASSERT(JSJ_callbacks->destroy_java_vm); - - ok = JSJ_callbacks->create_java_vm(&jsjava_vm->java_vm, - &jsjava_vm->main_thread_env, - jsjava_vm->init_args); - if (!ok) { - jsj_LogError("Failed to create Java VM\n"); - return JS_FALSE; - } - - /* Remember that we created the VM so that we know to destroy it later */ - jsjava_vm->jsj_created_java_vm = JS_TRUE; - } - - if (!jsjava_vm->jsj_inited_java_vm) { - /* - * JVM initialization for netscape.javascript.JSObject is performed - * independently of the other classes that are initialized in - * init_java_VM_reflection, because we allow it to fail. In the case - * of failure, LiveConnect is still operative, but only when calling - * from JS to Java and not vice-versa. - */ - init_netscape_java_classes(jsjava_vm, jsjava_vm->main_thread_env); - - /* Load the Java classes, and the method and field descriptors required for - Java reflection. */ - if (!init_java_VM_reflection(jsjava_vm, jsjava_vm->main_thread_env) || - !jsj_InitJavaObjReflectionsTable()) { - jsj_LogError("LiveConnect was unable to reflect one or more components of the Java runtime.\nGo to http://bugzilla.mozilla.org/show_bug.cgi?id=5369 for details.\n"); - /* This function crashes when called from here. - Check that all the preconditions for this - call are satisfied before making it. [jd] - JSJ_DisconnectFromJavaVM(jsjava_vm); */ - return JS_FALSE; - } - - jsjava_vm->jsj_inited_java_vm = JS_TRUE; - } - - return JS_TRUE; -} - -JSJCallbacks *JSJ_callbacks = NULL; - -/* Called once to set up callbacks for all instances of LiveConnect */ -void -JSJ_Init(JSJCallbacks *callbacks) -{ - JS_ASSERT(callbacks); - JSJ_callbacks = callbacks; -} - -/* - * Initialize the provided JSContext by setting up the JS classes necessary for - * reflection and by defining JavaPackage objects for the default Java packages - * as properties of global_obj. Additional packages may be pre-defined by - * setting the predefined_packages argument. (Pre-defining a Java package at - * initialization time is not necessary, but it will make package lookup faster - * and, more importantly, will avoid unnecessary network accesses if classes - * are being loaded over the network.) - */ -JSBool -JSJ_InitJSContext(JSContext *cx, JSObject *global_obj, - JavaPackageDef *predefined_packages) -{ - /* Initialize the JavaScript classes used for reflection */ - if (!jsj_init_JavaObject(cx, global_obj)) - return JS_FALSE; - -/* if (!jsj_init_JavaMember(cx, global_obj)) - return JS_FALSE; */ - - if (!jsj_init_JavaPackage(cx, global_obj, predefined_packages)) - return JS_FALSE; - - if (!jsj_init_JavaClass(cx, global_obj)) - return JS_FALSE; - - if (!jsj_init_JavaArray(cx, global_obj)) - return JS_FALSE; - - if (!jsj_init_JavaMember(cx, global_obj)) - return JS_FALSE; - - return JS_TRUE; -} - -/* Eliminate a reference to a Java class */ -#define UNLOAD_CLASS(qualified_name, class) \ - if (class) { \ - (*jEnv)->DeleteGlobalRef(jEnv, class); \ - class = NULL; \ - } - -/* - * This routine severs the connection to a Java VM, freeing all related resources. - * It shouldn't be called until the global scope has been cleared in all related - * JSContexts (so that all LiveConnect objects are finalized) and a JavaScript - * GC is performed. Otherwise, accessed to free'ed memory could result. - */ -void -JSJ_DisconnectFromJavaVM(JSJavaVM *jsjava_vm) -{ - SystemJavaVM *java_vm; - JSJavaVM *j, **jp; - - /* Since JSJ_ConnectToJavaVM is now lazy */ - java_vm = jsjava_vm->java_vm; - if (java_vm) { - JNIEnv *jEnv = jsjava_vm->main_thread_env; - - /* Drop all references to Java objects and classes */ - jsj_DiscardJavaObjReflections(jEnv); - jsj_DiscardJavaClassReflections(jEnv); - - if (jsjava_vm->jsj_created_java_vm) { - (void)JSJ_callbacks->destroy_java_vm(java_vm, jEnv); - } else { - UNLOAD_CLASS(java/lang/Object, jlObject); - UNLOAD_CLASS(java/lang/Class, jlClass); - UNLOAD_CLASS(java/lang/reflect/Method, jlrMethod); - UNLOAD_CLASS(java/lang/reflect/Constructor, jlrConstructor); - UNLOAD_CLASS(java/lang/reflect/Field, jlrField); - UNLOAD_CLASS(java/lang/reflect/Array, jlrArray); - UNLOAD_CLASS(java/lang/Throwable, jlThrowable); - UNLOAD_CLASS(java/lang/System, jlSystem); - UNLOAD_CLASS(java/lang/Boolean, jlBoolean); - UNLOAD_CLASS(java/lang/Double, jlDouble); - UNLOAD_CLASS(java/lang/String, jlString); - UNLOAD_CLASS(java/lang/Void, jlVoid); - UNLOAD_CLASS(java/applet/Applet, jaApplet); - UNLOAD_CLASS(netscape/javascript/JSObject, njJSObject); - UNLOAD_CLASS(netscape/javascript/JSException, njJSException); - UNLOAD_CLASS(netscape/javascript/JSUtil, njJSUtil); - } - } - - /* Remove this VM from the list of all JSJavaVM objects. */ - for (jp = &jsjava_vm_list; (j = *jp) != NULL; jp = &j->next) { - if (j == jsjava_vm) { - *jp = jsjava_vm->next; - break; - } - } - JS_ASSERT(j); /* vm not found in list */ - -#ifdef JSJ_THREADSAFE - if (jsjava_vm_list == NULL) { - PR_DestroyMonitor(thread_list_monitor); - thread_list_monitor = NULL; - } -#endif /* JSJ_THREADSAFE */ - - free(jsjava_vm); -} - -static JSJavaThreadState * -new_jsjava_thread_state(JSJavaVM *jsjava_vm, const char *thread_name, JNIEnv *jEnv) -{ - JSJavaThreadState *jsj_env; - - jsj_env = (JSJavaThreadState *)malloc(sizeof(JSJavaThreadState)); - if (!jsj_env) - return NULL; - memset(jsj_env, 0, sizeof(JSJavaThreadState)); - - jsj_env->jEnv = jEnv; - jsj_env->jsjava_vm = jsjava_vm; - if (thread_name) - jsj_env->name = strdup(thread_name); - -#ifdef JSJ_THREADSAFE - PR_EnterMonitor(thread_list_monitor); -#endif - - jsj_env->next = thread_list; - thread_list = jsj_env; - -#ifdef JSJ_THREADSAFE - PR_ExitMonitor(thread_list_monitor); -#endif - - return jsj_env; -} - -static JSJavaThreadState * -find_jsjava_thread(JNIEnv *jEnv) -{ - JSJavaThreadState *e, **p, *jsj_env; - jsj_env = NULL; - -#ifdef JSJ_THREADSAFE - PR_EnterMonitor(thread_list_monitor); -#endif - - /* Search for the thread state among the list of all created - LiveConnect threads */ - for (p = &thread_list; (e = *p) != NULL; p = &(e->next)) { - if (e->jEnv == jEnv) { - jsj_env = e; - break; - } - } - - /* Move a found thread to head of list for faster search next time. */ - if (jsj_env && p != &thread_list) { - *p = jsj_env->next; - jsj_env->next = thread_list; - thread_list = jsj_env; - } - -#ifdef JSJ_THREADSAFE - PR_ExitMonitor(thread_list_monitor); -#endif - - return jsj_env; -} - -JS_EXPORT_API(JSJavaThreadState *) -JSJ_AttachCurrentThreadToJava(JSJavaVM *jsjava_vm, const char *name, JNIEnv **java_envp) -{ - JNIEnv *jEnv; - SystemJavaVM *java_vm; - JSJavaThreadState *jsj_env; - - /* Make sure we're fully connected to the Java VM */ - if (!jsj_ConnectToJavaVM(jsjava_vm)) - return NULL; - - /* Try to attach a Java thread to the current native thread */ - java_vm = jsjava_vm->java_vm; - if (JSJ_callbacks && JSJ_callbacks->attach_current_thread) - jEnv = JSJ_callbacks->attach_current_thread(java_vm); - else - return NULL; - if (jEnv == NULL) - return NULL; - - /* If we found an existing thread state, just return it. */ - jsj_env = find_jsjava_thread(jEnv); - if (jsj_env) - return jsj_env; - - /* Create a new wrapper around the thread/VM state */ - jsj_env = new_jsjava_thread_state(jsjava_vm, name, jEnv); - - if (java_envp) - *java_envp = jEnv; - return jsj_env; -} - -static JSJavaVM * -map_java_vm_to_jsjava_vm(SystemJavaVM *java_vm) -{ - JSJavaVM *v; - for (v = jsjava_vm_list; v; v = v->next) { - if (!jsj_ConnectToJavaVM(v)) - return NULL; - if (v->java_vm == java_vm) - return v; - } - return NULL; -} - -/* - * Unfortunately, there's no standard means to associate any private data with - * a JNI thread environment, so we need to use the Java environment pointer as - * the key in a lookup table that maps it to a JSJavaThreadState structure, - * where we store all our per-thread private data. If no existing thread state - * is found, a new one is created. - * - * If an error occurs, returns NULL and sets the errp argument to an error - * message, which the caller is responsible for free'ing. - */ -JSJavaThreadState * -jsj_MapJavaThreadToJSJavaThreadState(JNIEnv *jEnv, char **errp) -{ - JSJavaThreadState *jsj_env; - SystemJavaVM *java_vm; - JSJavaVM *jsjava_vm; - - /* If we found an existing thread state, just return it. */ - jsj_env = find_jsjava_thread(jEnv); - if (jsj_env) - return jsj_env; - - /* No one set up a LiveConnect thread state for a given Java thread. - Invoke the callback to create one on-the-fly. */ - - /* First, figure out which Java VM is calling us */ - if (JSJ_callbacks && JSJ_callbacks->get_java_vm) - java_vm = JSJ_callbacks->get_java_vm(jEnv); - else - return NULL; - if (java_vm == NULL) - return NULL; - - /* Get our private JavaVM data */ - jsjava_vm = map_java_vm_to_jsjava_vm(java_vm); - if (!jsjava_vm) { - *errp = JS_smprintf("Total weirdness: No JSJavaVM wrapper ever created " - "for JavaVM 0x%08x", java_vm); - return NULL; - } - - jsj_env = new_jsjava_thread_state(jsjava_vm, NULL, jEnv); - if (!jsj_env) - return NULL; - - return jsj_env; -} - -/* - * This function is used to specify a particular JSContext as *the* JavaScript - * execution environment to be used when LiveConnect is accessed from the given - * Java thread, i.e. by using one of the methods of netscape.javascript.JSObject. - * (There can only be one such JS context for a given Java thread. To - * multiplex JSContexts among a single thread, this function must be called - * before Java is invoked on that thread.) The return value is the previous - * context associated with the given Java thread. - */ -JS_EXPORT_API(JSContext *) -JSJ_SetDefaultJSContextForJavaThread(JSContext *cx, JSJavaThreadState *jsj_env) -{ - JSContext *old_context; - old_context = jsj_env->cx; - jsj_env->cx = cx; - - /* The following line prevents clearing of jsj_env->cx by jsj_ExitJava() */ - jsj_env->recursion_depth++; - return old_context; -} - -JS_EXPORT_API(JSBool) -JSJ_DetachCurrentThreadFromJava(JSJavaThreadState *jsj_env) -{ - SystemJavaVM *java_vm; - JNIEnv* jEnv; - JSJavaThreadState *e, **p; - - /* Disassociate the current native thread from its corresponding Java thread */ - java_vm = jsj_env->jsjava_vm->java_vm; - jEnv = jsj_env->jEnv; - -#ifdef JSJ_THREADSAFE - PR_EnterMonitor(thread_list_monitor); -#endif /* JSJ_THREADSAFE */ - - if (!JSJ_callbacks->detach_current_thread(java_vm, jEnv)) { - -#ifdef JSJ_THREADSAFE - PR_ExitMonitor(thread_list_monitor); -#endif /* JSJ_THREADSAFE */ - - return JS_FALSE; - } - - /* Destroy the LiveConnect execution environment passed in */ - jsj_ClearPendingJSErrors(jsj_env); - - for (p = &thread_list; (e = *p) != NULL; p = &(e->next)) { - if (e == jsj_env) { - *p = jsj_env->next; - break; - } - } - - JS_ASSERT(e); - -#ifdef JSJ_THREADSAFE - PR_ExitMonitor(thread_list_monitor); -#endif /* JSJ_THREADSAFE */ - - free(jsj_env); - return JS_TRUE; -} - -/* Utility routine to wrap a Java object inside a JS object, having a - a result type of either JavaObject or JavaArray. */ -JSBool -JSJ_ConvertJavaObjectToJSValue(JSContext *cx, jobject java_obj, jsval *vp) -{ - JNIEnv *jEnv; - JSBool result; - JSJavaThreadState *jsj_env; - - /* Get the Java per-thread environment pointer for this JSContext */ - jsj_env = jsj_EnterJava(cx, &jEnv); - if (!jEnv) - return JS_FALSE; - - result = jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_obj, vp); - jsj_ExitJava(jsj_env); - return result; -} - - -JS_EXPORT_API(JSBool) -JSJ_ConvertJSValueToJavaObject(JSContext *cx, jsval v, jobject *vp) -{ - if (!JSVAL_IS_PRIMITIVE(v)) { - JSObject *js_obj = JSVAL_TO_OBJECT(v); - JavaObjectWrapper *java_wrapper = JS_GetPrivate(cx, js_obj); - *vp = java_wrapper->java_obj; - return JS_TRUE; - } - return JS_FALSE; -} - - -JS_EXPORT_API(JSBool) -JSJ_IsJSCallApplet() -{ - return jsj_JSIsCallingApplet; -} diff --git a/lib/javascript/liveconnect/jsj.msg b/lib/javascript/liveconnect/jsj.msg deleted file mode 100644 index 4a7a8098..00000000 --- a/lib/javascript/liveconnect/jsj.msg +++ /dev/null @@ -1,98 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* -*- Mode: C; tab-width: 8 -*- - * Copyright (C) 1998-1999 Netscape Communications Corporation, All Rights Reserved. - */ - -/* - Error messages for LiveConnect. See JSJMSG.def for format. - -*/ - -MSG_DEF(JSJMSG_NOT_AN_ERROR, 0, 0, "") -MSG_DEF(JSJMSG_CANT_LOAD_JSOBJECT, 1, 0, "Couldn't convert JavaScript object to an " - "instance of netscape.javascript.JSObject " - "because that class could not be loaded.") -MSG_DEF(JSJMSG_CANT_CONVERT_JS, 2, 2, "Unable to convert JavaScript value {0} to " - "Java value of type {1}") -MSG_DEF(JSJMSG_BAD_OP_JARRAY, 3, 0, "illegal operation on JavaArray prototype object") -MSG_DEF(JSJMSG_CANT_WRITE_JARRAY, 4, 1, "Attempt to write to invalid Java array element \"{0}\"") -MSG_DEF(JSJMSG_BAD_INDEX_EXPR, 5, 0, "invalid Java array index expression") -MSG_DEF(JSJMSG_BAD_JARRAY_INDEX, 6, 1, "Java array index {0} out of range") -MSG_DEF(JSJMSG_JARRAY_PROP_DEFINE, 7, 0, "Cannot define a new property in a JavaArray") -MSG_DEF(JSJMSG_JARRAY_PROP_DELETE, 8, 0, "Properties of JavaArray objects may not be deleted") -MSG_DEF(JSJMSG_JARRAY_PROP_WATCH, 9, 0, "Cannot place watchpoints on JavaArray object properties") -MSG_DEF(JSJMSG_JARRAY_PROP_EXPORT, 10, 0, "Cannot export a JavaArray object's properties") -MSG_DEF(JSJMSG_BAD_JCLASS_EXPR, 11, 0, "invalid JavaClass property expression. " - "(methods and fields of a JavaClass object can only be identified by their name)") -MSG_DEF(JSJMSG_MISSING_NAME, 12, 2, "Java class {0} has no public static field or method named \"{1}\"") -MSG_DEF(JSJMSG_MISSING_STATIC, 13, 2, "No static field named \"{0}\" in Java class {1}") -MSG_DEF(JSJMSG_JCLASS_PROP_DEFINE, 14, 0, "Cannot define a new property in a JavaClass") -MSG_DEF(JSJMSG_JCLASS_PROP_DELETE, 15, 0, "Properties of JavaClass objects may not be deleted") -MSG_DEF(JSJMSG_JCLASS_PROP_WATCH, 16, 0, "Cannot place watchpoints on JavaClass object properties") -MSG_DEF(JSJMSG_JCLASS_PROP_EXPORT, 17, 0, "Cannot export a JavaClass object's properties") -MSG_DEF(JSJMSG_BAD_OP_JCLASS, 18, 0, "illegal operation on JavaClass prototype object") -MSG_DEF(JSJMSG_BAD_OP_PROTO, 19, 0, "illegal operation on prototype object") -MSG_DEF(JSJMSG_NEED_JOBJECT_ARG, 20, 0, "getClass expects a Java object argument") -MSG_DEF(JSJMSG_PROTO_GETCLASS, 21, 0, "getClass called on prototype object") -MSG_DEF(JSJMSG_BAD_OP_JOBJECT, 22, 0, "illegal operation on JavaObject prototype object") -MSG_DEF(JSJMSG_BAD_JOBJECT_EXPR, 23, 0, "invalid JavaObject property expression. " - "(methods and field properties of a JavaObject object can only be strings)") -MSG_DEF(JSJMSG_NO_INSTANCE_NAME, 24, 2, "Java class {0} has no public field or method named \"{1}\"") -MSG_DEF(JSJMSG_NO_NAME_IN_CLASS, 25, 2, "No instance field named \"{0}\" in Java class {1}") -MSG_DEF(JSJMSG_JOBJECT_PROP_DEFINE, 26, 0, "Cannot define a new property in a JavaObject") -MSG_DEF(JSJMSG_JOBJECT_PROP_DELETE, 27, 0, "Properties of JavaObject objects may not be deleted") -MSG_DEF(JSJMSG_JOBJECT_PROP_WATCH, 28, 0, "Cannot place watchpoints on JavaObject object properties") -MSG_DEF(JSJMSG_JOBJECT_PROP_EXPORT, 29, 0, "Cannot export a JavaObject object's properties") -MSG_DEF(JSJMSG_CONVERT_TO_FUNC, 30, 0, "can't convert Java object to function") -MSG_DEF(JSJMSG_BAD_ADD_TO_PACKAGE, 31, 0, "illegal attempt to add property to JavaPackage prototype object") -MSG_DEF(JSJMSG_DONT_ADD_TO_PACKAGE, 32, 0, "You may not add properties to a JavaPackage object") -MSG_DEF(JSJMSG_MISSING_PACKAGE, 33, 1, "No Java system package with name \"{0}\" was identified " - "and no Java class with that name exists either") -MSG_DEF(JSJMSG_DOUBLE_SHIPPING, 34, 1, "Package {0} defined twice ?") -MSG_DEF(JSJMSG_BAD_PACKAGE_PREDEF, 35, 1, "Illegal predefined package definition for {0}") -MSG_DEF(JSJMSG_NULL_MEMBER_NAME, 36, 0, "illegal null member name") -MSG_DEF(JSJMSG_NULL_FUNCTION_NAME, 37, 0, "illegal null JavaScript function name") -MSG_DEF(JSJMSG_NULL_EVAL_ARG, 38, 0, "illegal null string eval argument") -MSG_DEF(JSJMSG_MULTIPLE_JTHREADS, 39, 0, "[Obsolete error message]") -MSG_DEF(JSJMSG_ABSTRACT_JCLASS, 40, 1, "Java class {0} is abstract and therefore may not be instantiated") -MSG_DEF(JSJMSG_IS_INTERFACE, 41, 1, "{0} is a Java interface and therefore may not be instantiated") -MSG_DEF(JSJMSG_NOT_PUBLIC, 42, 1, "Java class {0} is not public and therefore may not be instantiated") -MSG_DEF(JSJMSG_NO_CONSTRUCTORS, 43, 1, "No public constructors defined for Java class {0}") -MSG_DEF(JSJMSG_BAD_PROTO_ASSIGNMENT,44, 0, "Only objects can be assigned as the value of the __proto__ property") -MSG_DEF(JSJMSG_NEED_JCLASS_ARG, 45, 0, "The JavaClass constructor expects an instance of java.lang.Class as an argument") diff --git a/lib/javascript/liveconnect/jsj_JSObject.c b/lib/javascript/liveconnect/jsj_JSObject.c deleted file mode 100644 index a5cba947..00000000 --- a/lib/javascript/liveconnect/jsj_JSObject.c +++ /dev/null @@ -1,1375 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* This file is part of the Java-vendor-neutral implementation of LiveConnect - * - * It contains the implementation of the native methods for the - * netscape.javascript.JSObject Java class, which are used for calling into - * JavaScript from Java. It also contains the code that handles propagation - * of exceptions both into and out of Java. - * - */ - -#include -#include - -#include "jsj_private.h" -#include "jsjava.h" - -#include "jscntxt.h" /* For js_ReportErrorAgain(). - TODO - get rid of private header */ - -#include "netscape_javascript_JSObject.h" /* javah-generated headers */ - - -/* A captured JavaScript error, created when JS_ReportError() is called while - running JavaScript code that is itself called from Java. */ -struct CapturedJSError { - char * message; - JSErrorReport report; /* Line # of error, etc. */ - jthrowable java_exception; /* Java exception, error, or null */ - CapturedJSError * next; /* Next oldest captured JS error */ -}; - - -/*********************** Reflection of JSObjects ****************************/ - -#ifdef PRESERVE_JSOBJECT_IDENTITY -/* - * This is a hash table that maps from JS objects to Java objects. - * It is used to ensure that the same Java object results when a JS - * object is reflected more than once, so that Java object equality - * tests work in the expected manner. - * - * The entry keys are JSObject pointers and the entry values are Java objects - * (of type jobject). When the corresponding Java instance is finalized, - * the entry is removed from the table, and a JavaScript GC root for the JS - * object is removed. - * - * This code is disabled because cycles in GC roots between the two systems - * cause every reflected JS object to become uncollectable. This can only - * be solved by using weak links, a feature not available in JDK1.1. - */ -static JSHashTable *js_obj_reflections = NULL; - -#ifdef JSJ_THREADSAFE -/* - * Used to protect the js_obj_reflections hashtable from simultaneous - * read/write or * write/write access. - */ -static PRMonitor *js_obj_reflections_monitor = NULL; -#endif /* JSJ_THREADSAFE */ -#endif /* PRESERVE_JSOBJECT_IDENTITY */ - -JSBool -jsj_init_js_obj_reflections_table() -{ -#ifdef PRESERVE_JSOBJECT_IDENTITY - if(js_obj_reflections != NULL) - { - return JS_TRUE; - } - js_obj_reflections = JS_NewHashTable(128, NULL, JS_CompareValues, - JS_CompareValues, NULL, NULL); - if (!js_obj_reflections) - return JS_FALSE; - -#ifdef JSJ_THREADSAFE - js_obj_reflections_monitor = PR_NewMonitor(); - if (!js_obj_reflections_monitor) { - JS_HashTableDestroy(js_obj_reflections); - return JS_FALSE; - } -#endif /* JSJ_THREADSAFE */ -#endif /* PRESERVE_JSOBJECT_IDENTITY */ - - return JS_TRUE; -} - -/* - * Return a Java object that "wraps" a given JS object by storing the address - * of the JS object in a private field of the Java object. A hash table is - * used to ensure that the mapping of JS objects to Java objects is done on - * one-to-one basis. - * - * If an error occurs, returns NULL and reports an error. - */ - -#ifdef PRESERVE_JSOBJECT_IDENTITY - -jobject -jsj_WrapJSObject(JSContext *cx, JNIEnv *jEnv, JSObject *js_obj) -{ - jobject java_wrapper_obj; - JSHashEntry *he, **hep; - - java_wrapper_obj = NULL; - -#ifdef JSJ_THREADSAFE - PR_EnterMonitor(js_obj_reflections_monitor); -#endif - - /* First, look in the hash table for an existing reflection of the same - JavaScript object. If one is found, return it. */ - hep = JS_HashTableRawLookup(js_obj_reflections, (JSHashNumber)js_obj, js_obj); - - /* If the same JSObject is reflected into Java more than once then we should - return the same Java object, both for efficiency and so that the '==' - operator works as expected in Java when comparing two JSObjects. - However, it is not possible to hold a reference to a Java object without - inhibiting GC of that object, at least not in a portable way, i.e. - a weak reference. So, for now, JSObject identity is broken. */ - - he = *hep; - if (he) { - java_wrapper_obj = (jobject)he->value; - JS_ASSERT(java_wrapper_obj); - if (java_wrapper_obj) - goto done; - } - - /* No existing reflection found, so create a new Java object that wraps - the JavaScript object by storing its address in a private integer field. */ -#ifndef OJI - java_wrapper_obj = - (*jEnv)->NewObject(jEnv, njJSObject, njJSObject_JSObject, (jint)js_obj); -#else - if (JSJ_callbacks && JSJ_callbacks->get_java_wrapper != NULL) { - java_wrapper_obj = JSJ_callbacks->get_java_wrapper(jEnv, (jint)handle); - } -#endif /*! OJI */ - - if (!java_wrapper_obj) { - jsj_UnexpectedJavaError(cx, jEnv, "Couldn't create new instance of " - "netscape.javascript.JSObject"); - goto done; - } - - /* Add the new reflection to the hash table. */ - he = JS_HashTableRawAdd(js_obj_reflections, hep, (JSHashNumber)js_obj, - js_obj, java_wrapper_obj); - if (he) { - /* Tell the JavaScript GC about this object since the only reference - to it may be in Java-land. */ - JS_AddNamedRoot(cx, (void*)&he->key, "&he->key"); - } else { - JS_ReportOutOfMemory(cx); - /* No need to delete java_wrapper_obj because Java GC will reclaim it */ - java_wrapper_obj = NULL; - } - - /* - * Release local reference to wrapper object, since some JVMs seem reticent - * about collecting it otherwise. - */ - /* FIXME -- beard: this seems to make calls into Java with JSObject's fail. */ - /* We should really be creating a global ref if we are putting it in a hash table. */ - /* (*jEnv)->DeleteLocalRef(jEnv, java_wrapper_obj); */ - -done: -#ifdef JSJ_THREADSAFE - PR_ExitMonitor(js_obj_reflections_monitor); -#endif - - return java_wrapper_obj; -} - -/* - * Remove the mapping of a JS object from the hash table that maps JS objects - * to Java objects. This is called from the finalizer of an instance of - * netscape.javascript.JSObject. - */ -JSBool -jsj_remove_js_obj_reflection_from_hashtable(JSContext *cx, JSObject *js_obj) -{ - JSHashEntry *he, **hep; - JSBool success = JS_FALSE; - -#ifdef JSJ_THREADSAFE - PR_EnterMonitor(js_obj_reflections_monitor); -#endif - - /* Get the hash-table entry for this wrapper object */ - hep = JS_HashTableRawLookup(js_obj_reflections, (JSHashNumber)js_obj, js_obj); - he = *hep; - - JS_ASSERT(he); - if (he) { - /* Tell the JS GC that Java no longer keeps a reference to this - JS object. */ - success = JS_RemoveRoot(cx, (void *)&he->key); - - JS_HashTableRawRemove(js_obj_reflections, hep, he); - } - -#ifdef JSJ_THREADSAFE - PR_ExitMonitor(js_obj_reflections_monitor); -#endif - - return success; -} - -#else /* !PRESERVE_JSOBJECT_IDENTITY */ - - -/* - * The caller must call DeleteLocalRef() on the returned object when no more - * references remain. - */ -jobject -jsj_WrapJSObject(JSContext *cx, JNIEnv *jEnv, JSObject *js_obj) -{ - jobject java_wrapper_obj; - JSObjectHandle *handle; - - /* Create a tiny stub object to act as the GC root that points to the - JSObject from its netscape.javascript.JSObject counterpart. */ - handle = (JSObjectHandle*)JS_malloc(cx, sizeof(JSObjectHandle)); - if (!handle) - return NULL; - handle->js_obj = js_obj; - handle->rt = JS_GetRuntime(cx); - - /* Create a new Java object that wraps the JavaScript object by storing its - address in a private integer field. */ -#ifndef OJI - java_wrapper_obj = - (*jEnv)->NewObject(jEnv, njJSObject, njJSObject_JSObject, (lcjsobject)handle); -#else - if (JSJ_callbacks && JSJ_callbacks->get_java_wrapper != NULL) { - java_wrapper_obj = JSJ_callbacks->get_java_wrapper(jEnv, (lcjsobject)handle); - } else { - java_wrapper_obj = NULL; - } -#endif /*! OJI */ - if (!java_wrapper_obj) { - jsj_UnexpectedJavaError(cx, jEnv, "Couldn't create new instance of " - "netscape.javascript.JSObject"); - goto done; - } - - JS_AddNamedRoot(cx, &handle->js_obj, "&handle->js_obj"); - -done: - - return java_wrapper_obj; -} - -JSObject * -jsj_UnwrapJSObjectWrapper(JNIEnv *jEnv, jobject java_wrapper_obj) -{ - JSObjectHandle *handle; - -#ifndef OJI -#if JS_BYTES_PER_LONG == 8 - handle = (JSObjectHandle*)((*jEnv)->GetLongField(jEnv, java_wrapper_obj, njJSObject_long_internal)); -#else - handle = (JSObjectHandle*)((*jEnv)->GetIntField(jEnv, java_wrapper_obj, njJSObject_internal)); -#endif -#else - /* Unwrapping this wrapper requires knowledge of the structure of the object. This is privileged - information that only the object implementor can know. In this case the object implementor - is the java plugin (such as the Sun plugin class sun.plugin.javascript.navig5.JSObject. - Since the plugin owns this structure, we defer to it to unwrap the object. If the plugin - does not implement this callback, then it should be set to null. In that case we try something - that works with Sun's plugin assuming that it has not yet been implemented yet. This 'else' - case should be removed as soon as the unwrap function is supported by the Sun JPI. */ - - if (JSJ_callbacks && JSJ_callbacks->unwrap_java_wrapper != NULL) { - handle = (JSObjectHandle*)JSJ_callbacks->unwrap_java_wrapper(jEnv, java_wrapper_obj); - } - else { - jclass cid = (*jEnv)->GetObjectClass(jEnv, java_wrapper_obj); -#if JS_BYTES_PER_LONG == 8 - jfieldID fid = (*jEnv)->GetFieldID(jEnv, cid, "nativeJSObject", "J"); - handle = (JSObjectHandle*)((*jEnv)->GetLongField(jEnv, java_wrapper_obj, fid)); -#else - jfieldID fid = (*jEnv)->GetFieldID(jEnv, cid, "nativeJSObject", "I"); - handle = (JSObjectHandle*)((*jEnv)->GetIntField(jEnv, java_wrapper_obj, fid)); -#endif - } -#endif - - /* JNI returns a NULL handle for a Java 'null' */ - if (!handle) - return NULL; - - return handle->js_obj; - -} - -#endif /* !PRESERVE_JSOBJECT_IDENTITY */ - -/*************** Handling of Java exceptions in JavaScript ******************/ - -/* - * Free up a JavaScript error that has been stored by the - * capture_js_error_reports_for_java() function. - */ -static CapturedJSError * -destroy_saved_js_error(JNIEnv *jEnv, CapturedJSError *error) -{ - CapturedJSError *next_error; - if (!error) - return NULL; - next_error = error->next; - - if (error->java_exception) - (*jEnv)->DeleteGlobalRef(jEnv, error->java_exception); - if (error->message) - free((char*)error->message); - if (error->report.filename) - free((char*)error->report.filename); - if (error->report.linebuf) - free((char*)error->report.linebuf); - free(error); - - return next_error; -} - -/* - * Capture a JS error that has been reported using JS_ReportError() by JS code - * that has itself been called from Java. A copy of the JS error data is made - * and hung off the JSJ environment. When JS completes and returns to its Java - * caller, this data is used to synthesize an instance of - * netscape.javascript.JSException. If the resulting JSException is not caught - * within Java, it may be propagated up the stack beyond the Java caller back - * into JavaScript, in which case the error will be re-reported as a JavaScript - * error. - */ -JS_STATIC_DLL_CALLBACK(void) -capture_js_error_reports_for_java(JSContext *cx, const char *message, - JSErrorReport *report) -{ - CapturedJSError *new_error; - JSJavaThreadState *jsj_env; - jthrowable java_exception, tmp_exception; - JNIEnv *jEnv; - - /* Warnings are not propagated as Java exceptions - they are simply - ignored. Ditto for exceptions that are duplicated in the form - of error reports. */ - if (report && (report->flags & (JSREPORT_WARNING | JSREPORT_EXCEPTION))) - return; - - /* Create an empty struct to hold the saved JS error state */ - new_error = malloc(sizeof(CapturedJSError)); - if (!new_error) - goto out_of_memory; - memset(new_error, 0, sizeof(CapturedJSError)); - - /* Copy all the error info out of the original report into a private copy */ - if (message) { - new_error->message = strdup(message); - if (!new_error->message) - goto out_of_memory; - } - if (report) { - new_error->report.lineno = report->lineno; - - if (report->filename) { - new_error->report.filename = strdup(report->filename); - if (!new_error->report.filename) - goto out_of_memory; - } - - if (report->linebuf) { - new_error->report.linebuf = strdup(report->linebuf); - if (!new_error->report.linebuf) - goto out_of_memory; - new_error->report.tokenptr = - new_error->report.linebuf + (report->tokenptr - report->linebuf); - } - } - - /* Get the head of the list of pending JS errors */ - jsj_env = jsj_EnterJava(cx, &jEnv); - if (!jsj_env) - goto abort; - - /* If there's a Java exception associated with this error, save it too. */ - java_exception = (*jEnv)->ExceptionOccurred(jEnv); - if (java_exception) { - (*jEnv)->ExceptionClear(jEnv); - tmp_exception = java_exception; /* Make a copy */ - java_exception = (*jEnv)->NewGlobalRef(jEnv, java_exception); - new_error->java_exception = java_exception; - (*jEnv)->DeleteLocalRef(jEnv, tmp_exception); - } - - /* Push this error onto the list of pending JS errors */ - new_error->next = jsj_env->pending_js_errors; - jsj_env->pending_js_errors = new_error; - jsj_ExitJava(jsj_env); - return; - -abort: -out_of_memory: - /* No recovery action possible */ - JS_ASSERT(0); - destroy_saved_js_error(jEnv, new_error); - return; -} - -void -jsj_ClearPendingJSErrors(JSJavaThreadState *jsj_env) -{ - while (jsj_env->pending_js_errors) - jsj_env->pending_js_errors = destroy_saved_js_error(jsj_env->jEnv, jsj_env->pending_js_errors); -} - -/* - * This is called upon returning from JS back into Java. Any JS errors - * reported during that time will be converted into Java exceptions. It's - * possible that a JS error was actually triggered by Java at some point, in - * which case the original Java exception is thrown. - */ -static void -throw_any_pending_js_error_as_a_java_exception(JSJavaThreadState *jsj_env) -{ - CapturedJSError *error; - JNIEnv *jEnv; - jstring message_jstr, linebuf_jstr, filename_jstr; - jint index, lineno; - JSErrorReport *report; - JSContext *cx; - jsval pending_exception; - jobject java_obj; - int dummy_cost; - JSBool is_local_refp; - JSType primitive_type; - jthrowable java_exception; - - message_jstr = linebuf_jstr = filename_jstr = java_exception = NULL; - - /* Get the Java JNI environment */ - jEnv = jsj_env->jEnv; - - cx = jsj_env->cx; - /* Get the pending JS exception if it exists */ - if (cx&&JS_IsExceptionPending(cx)) { - if (!JS_GetPendingException(cx, &pending_exception)) - goto out_of_memory; - - /* Find out the JSTYPE of this jsval. */ - primitive_type = JS_TypeOfValue(cx, pending_exception); - - /* Convert jsval exception to a java object and then use it to - create an instance of JSException. */ - if (!jsj_ConvertJSValueToJavaObject(cx, jEnv, - pending_exception, - jsj_get_jlObject_descriptor(cx, jEnv), - &dummy_cost, &java_obj, - &is_local_refp)) - goto done; - - java_exception = (*jEnv)->NewObject(jEnv, njJSException, - njJSException_JSException_wrap, - primitive_type, java_obj); - if (is_local_refp) - (*jEnv)->DeleteLocalRef(jEnv, java_obj); - if (!java_exception) - goto out_of_memory; - - /* Throw the newly-created JSException */ - if ((*jEnv)->Throw(jEnv, java_exception) < 0) { - JS_ASSERT(0); - jsj_LogError("Couldn't throw JSException\n"); - goto done; - } - JS_ClearPendingException(cx); - return; - } - if (!jsj_env->pending_js_errors) { -#ifdef DEBUG - /* Any exception should be cleared as soon as it's detected, so there - shouldn't be any pending. */ - if ((*jEnv)->ExceptionOccurred(jEnv)) { - /* A Java exception occurred, but nobody in JS-land noticed. */ - JS_ASSERT(0); - (*jEnv)->ExceptionClear(jEnv); - } -#endif - return; - } - - /* Get the deepest (oldest) saved JS error */ - /* XXX - What's the right thing to do about newer errors ? - For now we just throw them away */ - error = jsj_env->pending_js_errors; - while (error->next) - error = error->next; - - /* - * If the JS error was originally the result of a Java exception, rethrow - * the original exception. - */ - if (error->java_exception) { - (*jEnv)->Throw(jEnv, error->java_exception); - goto done; - } - - /* Propagate any JS errors that did not originate as Java exceptions into - Java as an instance of netscape.javascript.JSException */ - - /* First, marshall the arguments to the JSException constructor */ - message_jstr = NULL; - if (error->message) { - message_jstr = (*jEnv)->NewStringUTF(jEnv, error->message); - if (!message_jstr) - goto out_of_memory; - } - - report = &error->report; - - filename_jstr = NULL; - if (report->filename) { - filename_jstr = (*jEnv)->NewStringUTF(jEnv, report->filename); - if (!filename_jstr) - goto out_of_memory; - } - - linebuf_jstr = NULL; - if (report->linebuf) { - linebuf_jstr = (*jEnv)->NewStringUTF(jEnv, report->linebuf); - if (!linebuf_jstr) - goto out_of_memory; - } - - lineno = report->lineno; - index = report->linebuf ? report->tokenptr - report->linebuf : 0; - - /* Call the JSException constructor */ - java_exception = (*jEnv)->NewObject(jEnv, njJSException, njJSException_JSException, - message_jstr, filename_jstr, lineno, linebuf_jstr, index); - if (!java_exception) - goto out_of_memory; - - /* Throw the newly-created JSException */ - if ((*jEnv)->Throw(jEnv, java_exception) < 0) { - JS_ASSERT(0); - jsj_UnexpectedJavaError(cx, jEnv, "Couldn't throw JSException\n"); - } - goto done; - -out_of_memory: - /* No recovery possible */ - JS_ASSERT(0); - jsj_LogError("Out of memory while attempting to throw JSException\n"); - -done: - jsj_ClearPendingJSErrors(jsj_env); - /* - * Release local references to Java objects, since some JVMs seem reticent - * about collecting them otherwise. - */ - if (message_jstr) - (*jEnv)->DeleteLocalRef(jEnv, message_jstr); - if (filename_jstr) - (*jEnv)->DeleteLocalRef(jEnv, filename_jstr); - if (linebuf_jstr) - (*jEnv)->DeleteLocalRef(jEnv, linebuf_jstr); - if (java_exception) - (*jEnv)->DeleteLocalRef(jEnv, java_exception); -} - -/* - * This function is called up returning from Java back into JS as a result of - * a thrown netscape.javascript.JSException, which itself must have been caused - * by a JS error when Java called into JS. The original JS error is - * reconstituted from the JSException and re-reported as a JS error. - * - * Returns JS_FALSE if an internal error occurs, JS_TRUE otherwise. - */ -JSBool -jsj_ReportUncaughtJSException(JSContext *cx, JNIEnv *jEnv, jthrowable java_exception) -{ - JSBool success; - JSErrorReport report; - const char *linebuf, *filename, *message, *tokenptr; - jint lineno, token_index; - jstring linebuf_jstr, filename_jstr, message_jstr; - - /* Initialize everything to NULL */ - memset(&report, 0, sizeof(JSErrorReport)); - success = JS_FALSE; - filename_jstr = linebuf_jstr = message_jstr = NULL; - filename = message = linebuf = tokenptr = NULL; - - lineno = (*jEnv)->GetIntField(jEnv, java_exception, njJSException_lineno); - report.lineno = lineno; - - filename_jstr = (*jEnv)->GetObjectField(jEnv, java_exception, njJSException_filename); - if ((*jEnv)->ExceptionOccurred(jEnv)) { - jsj_UnexpectedJavaError(cx, jEnv, "Unable to access filename field of a JSException"); - goto done; - } - if (filename_jstr) - filename = (*jEnv)->GetStringUTFChars(jEnv, filename_jstr, 0); - report.filename = filename; - - linebuf_jstr = (*jEnv)->GetObjectField(jEnv, java_exception, njJSException_source); - if ((*jEnv)->ExceptionOccurred(jEnv)) { - jsj_UnexpectedJavaError(cx, jEnv, "Unable to access source field of a JSException"); - goto done; - } - if (linebuf_jstr) - linebuf = (*jEnv)->GetStringUTFChars(jEnv, linebuf_jstr, 0); - report.linebuf = linebuf; - - token_index = (*jEnv)->GetIntField(jEnv, java_exception, njJSException_lineno); - report.tokenptr = linebuf + token_index; - - message_jstr = (*jEnv)->CallObjectMethod(jEnv, java_exception, jlThrowable_getMessage); - if ((*jEnv)->ExceptionOccurred(jEnv)) { - jsj_UnexpectedJavaError(cx, jEnv, "Unable to access message of a JSException"); - goto done; - } - if (message_jstr) - message = (*jEnv)->GetStringUTFChars(jEnv, message_jstr, 0); - - js_ReportErrorAgain(cx, message, &report); - - success = JS_TRUE; - -done: - - if (filename_jstr && filename) - (*jEnv)->ReleaseStringUTFChars(jEnv, filename_jstr, filename); - if (linebuf_jstr && linebuf) - (*jEnv)->ReleaseStringUTFChars(jEnv, linebuf_jstr, linebuf); - if (message_jstr && message) - (*jEnv)->ReleaseStringUTFChars(jEnv, message_jstr, message); - return success; -} - - - -/*************** Utilities for calling JavaScript from Java *****************/ - -/* - * This routine is called just prior to invoking any JS API function from - * Java. It performs a common set of chores, such as obtaining the LiveConnect - * state for the invoking Java thread and determining the JSContext to be - * used for this thread. - * - * Returns NULL on failure. - */ - - -JSJavaThreadState * -jsj_enter_js(JNIEnv *jEnv, void* applet_obj, jobject java_wrapper_obj, - JSContext **cxp, JSObject **js_objp, JSErrorReporter *old_error_reporterp, - void **pNSIPrincipaArray, int numPrincipals, void *pNSISecurityContext) -{ - JSContext *cx; - char *err_msg; - JSObject *js_obj; - JSJavaThreadState *jsj_env; - - cx = NULL; - err_msg = NULL; - - /* Invoke callback, presumably used to implement concurrency constraints */ - if (JSJ_callbacks && JSJ_callbacks->enter_js_from_java) { -#ifdef OJI - if (!JSJ_callbacks->enter_js_from_java(jEnv, &err_msg, pNSIPrincipaArray, numPrincipals, pNSISecurityContext,applet_obj)) -#else - if (!JSJ_callbacks->enter_js_from_java(jEnv, &err_msg)) -#endif - goto entry_failure; - } - - /* Check the JSObject pointer in the wrapper object. */ - if (js_objp) { - -#ifdef PRESERVE_JSOBJECT_IDENTITY -#if JS_BYTES_PER_LONG == 8 - js_obj = (JSObject *)((*jEnv)->GetLongField(jEnv, java_wrapper_obj, njJSObject_long_internal)); -#else - js_obj = (JSObject *)((*jEnv)->GetIntField(jEnv, java_wrapper_obj, njJSObject_internal)); -#endif -#else /* !PRESERVE_JSOBJECT_IDENTITY */ - js_obj = jsj_UnwrapJSObjectWrapper(jEnv, java_wrapper_obj); -#endif /* PRESERVE_JSOBJECT_IDENTITY */ - - JS_ASSERT(js_obj); - if (!js_obj) - goto error; - *js_objp = js_obj; - } - - /* Get the per-thread state corresponding to the current Java thread */ - jsj_env = jsj_MapJavaThreadToJSJavaThreadState(jEnv, &err_msg); - if (!jsj_env) - goto error; - - /* Get the JSContext that we're supposed to use for this Java thread */ - cx = jsj_env->cx; - if (!cx) { - /* We called spontaneously into JS from Java, rather than from JS into - Java and back into JS. Invoke a callback to obtain/create a - JSContext for us to use. */ - if (JSJ_callbacks && JSJ_callbacks->map_jsj_thread_to_js_context) { -#ifdef OJI - cx = JSJ_callbacks->map_jsj_thread_to_js_context(jsj_env, - applet_obj, - jEnv, &err_msg); -#else - cx = JSJ_callbacks->map_jsj_thread_to_js_context(jsj_env, - jEnv, &err_msg); -#endif - if (!cx) - goto error; - } else { - err_msg = JS_smprintf("Unable to find/create JavaScript execution " - "context for JNI thread 0x%08x", jEnv); - goto error; - } - } - *cxp = cx; - - /* - * Capture all JS error reports so that they can be thrown into the Java - * caller as an instance of netscape.javascript.JSException. - */ - *old_error_reporterp = - JS_SetErrorReporter(cx, capture_js_error_reports_for_java); - -#ifdef JSJ_THREADSAFE - JS_BeginRequest(cx); -#endif - - return jsj_env; - -error: - /* Invoke callback, presumably used to implement concurrency constraints */ - if (JSJ_callbacks && JSJ_callbacks->exit_js) - JSJ_callbacks->exit_js(jEnv, cx); - -entry_failure: - if (err_msg) { - if (cx) - JS_ReportError(cx, err_msg); - else - jsj_LogError(err_msg); - free(err_msg); - } - - return NULL; -} - -/* - * This utility function is called just prior to returning into Java from JS. - */ -JSBool -jsj_exit_js(JSContext *cx, JSJavaThreadState *jsj_env, JSErrorReporter original_reporter) -{ - JNIEnv *jEnv; - -#ifdef JSJ_THREADSAFE - JS_EndRequest(cx); -#endif - - /* Restore the JS error reporter */ - JS_SetErrorReporter(cx, original_reporter); - - jEnv = jsj_env->jEnv; - -#ifdef DEBUG - /* Any Java exceptions should have been noticed and reported already */ - if ((*jEnv)->ExceptionOccurred(jEnv)) { - JS_ASSERT(0); - jsj_LogError("Unhandled Java exception detected"); - return JS_FALSE; - } -#endif - - /* - * Convert reported JS errors to JSExceptions, unless the errors were - * themselves the result of Java exceptions, in which case the original - * Java exception is simply propagated. - */ - throw_any_pending_js_error_as_a_java_exception(jsj_env); - - /* Invoke callback, presumably used to implement concurrency constraints */ - if (JSJ_callbacks && JSJ_callbacks->exit_js) - JSJ_callbacks->exit_js(jEnv, cx); - - return JS_TRUE; -} - - -/* Get the JavaClassDescriptor that corresponds to java.lang.Object */ -JavaClassDescriptor * -jsj_get_jlObject_descriptor(JSContext *cx, JNIEnv *jEnv) -{ - /* The JavaClassDescriptor for java.lang.Object */ - static JavaClassDescriptor *jlObject_descriptor = NULL; - - if (!jlObject_descriptor) - jlObject_descriptor = jsj_GetJavaClassDescriptor(cx, jEnv, jlObject); - return jlObject_descriptor; -} - -/****************** Implementation of methods of JSObject *******************/ - -/* - * Class: netscape_javascript_JSObject - * Method: initClass - * Signature: ()V - */ -JNIEXPORT void JNICALL -Java_netscape_javascript_JSObject_initClass(JNIEnv *jEnv, jclass java_class) -{ - jsj_init_js_obj_reflections_table(); -} - -/* - * Class: netscape_javascript_JSObject - * Method: getMember - * Signature: (Ljava/lang/String;)Ljava/lang/Object; - */ -JNIEXPORT jobject JNICALL -Java_netscape_javascript_JSObject_getMember(JNIEnv *jEnv, - jobject java_wrapper_obj, - jstring property_name_jstr) -{ - JSContext *cx = NULL; - JSObject *js_obj; - jsval js_val; - int dummy_cost; - JSBool dummy_bool; - const jchar *property_name_ucs2; - jsize property_name_len; - JSErrorReporter saved_reporter; - jobject member; - jboolean is_copy; - JSJavaThreadState *jsj_env; - - jsj_env = jsj_enter_js(jEnv, NULL, java_wrapper_obj, &cx, &js_obj, &saved_reporter, NULL, 0, NULL); - if (!jsj_env) - return NULL; - - property_name_ucs2 = NULL; - if (!property_name_jstr) { - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_NULL_MEMBER_NAME); - member = NULL; - goto done; - } - - /* Get the Unicode string for the JS property name */ - property_name_ucs2 = (*jEnv)->GetStringChars(jEnv, property_name_jstr, &is_copy); - if (!property_name_ucs2) { - JS_ASSERT(0); - goto done; - } - property_name_len = (*jEnv)->GetStringLength(jEnv, property_name_jstr); - - if (!JS_GetUCProperty(cx, js_obj, property_name_ucs2, property_name_len, &js_val)) - goto done; - - jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, - jsj_get_jlObject_descriptor(cx, jEnv), - &dummy_cost, &member, &dummy_bool); - -done: - if (property_name_ucs2) - (*jEnv)->ReleaseStringChars(jEnv, property_name_jstr, property_name_ucs2); - if (!jsj_exit_js(cx, jsj_env, saved_reporter)) - return NULL; - - return member; -} - -/* - * Class: netscape_javascript_JSObject - * Method: getSlot - * Signature: (I)Ljava/lang/Object; - */ -JNIEXPORT jobject JNICALL -Java_netscape_javascript_JSObject_getSlot(JNIEnv *jEnv, - jobject java_wrapper_obj, - jint slot) -{ - JSContext *cx = NULL; - JSObject *js_obj; - jsval js_val; - int dummy_cost; - JSBool dummy_bool; - JSErrorReporter saved_reporter; - jobject member; - JSJavaThreadState *jsj_env; - - jsj_env = jsj_enter_js(jEnv, NULL, java_wrapper_obj, &cx, &js_obj, &saved_reporter, NULL, 0, NULL); - if (!jsj_env) - return NULL; - - - if (!JS_GetElement(cx, js_obj, slot, &js_val)) - goto done; - if (!jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv), - &dummy_cost, &member, &dummy_bool)) - goto done; - -done: - if (!jsj_exit_js(cx, jsj_env, saved_reporter)) - return NULL; - - return member; -} - -/* - * Class: netscape_javascript_JSObject - * Method: setMember - * Signature: (Ljava/lang/String;Ljava/lang/Object;)V - */ -JNIEXPORT void JNICALL -Java_netscape_javascript_JSObject_setMember(JNIEnv *jEnv, - jobject java_wrapper_obj, - jstring property_name_jstr, - jobject java_obj) -{ - JSContext *cx = NULL; - JSObject *js_obj; - jsval js_val; - const jchar *property_name_ucs2; - jsize property_name_len; - JSErrorReporter saved_reporter; - jboolean is_copy; - JSJavaThreadState *jsj_env; - - jsj_env = jsj_enter_js(jEnv, NULL, java_wrapper_obj, &cx, &js_obj, &saved_reporter, NULL, 0, NULL); - if (!jsj_env) - return; - - property_name_ucs2 = NULL; - if (!property_name_jstr) { - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_NULL_MEMBER_NAME); - goto done; - } - - /* Get the Unicode string for the JS property name */ - property_name_ucs2 = (*jEnv)->GetStringChars(jEnv, property_name_jstr, &is_copy); - if (!property_name_ucs2) { - JS_ASSERT(0); - goto done; - } - property_name_len = (*jEnv)->GetStringLength(jEnv, property_name_jstr); - - if (!jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_obj, &js_val)) - goto done; - - JS_SetUCProperty(cx, js_obj, property_name_ucs2, property_name_len, &js_val); - -done: - if (property_name_ucs2) - (*jEnv)->ReleaseStringChars(jEnv, property_name_jstr, property_name_ucs2); - jsj_exit_js(cx, jsj_env, saved_reporter); -} - -/* - * Class: netscape_javascript_JSObject - * Method: setSlot - * Signature: (ILjava/lang/Object;)V - */ -JNIEXPORT void JNICALL -Java_netscape_javascript_JSObject_setSlot(JNIEnv *jEnv, - jobject java_wrapper_obj, - jint slot, - jobject java_obj) -{ - JSContext *cx = NULL; - JSObject *js_obj; - jsval js_val; - JSErrorReporter saved_reporter; - JSJavaThreadState *jsj_env; - - jsj_env = jsj_enter_js(jEnv, NULL, java_wrapper_obj, &cx, &js_obj, &saved_reporter, NULL, 0, NULL); - if (!jsj_env) - return; - - if (!jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_obj, &js_val)) - goto done; - JS_SetElement(cx, js_obj, slot, &js_val); - -done: - jsj_exit_js(cx, jsj_env, saved_reporter); -} - -/* - * Class: netscape_javascript_JSObject - * Method: removeMember - * Signature: (Ljava/lang/String;)V - */ -JNIEXPORT void JNICALL -Java_netscape_javascript_JSObject_removeMember(JNIEnv *jEnv, - jobject java_wrapper_obj, - jstring property_name_jstr) -{ - JSContext *cx = NULL; - JSObject *js_obj; - jsval js_val; - const jchar *property_name_ucs2; - jsize property_name_len; - JSErrorReporter saved_reporter; - jboolean is_copy; - JSJavaThreadState *jsj_env; - - jsj_env = jsj_enter_js(jEnv, NULL, java_wrapper_obj, &cx, &js_obj, &saved_reporter, NULL, 0, NULL); - if (!jsj_env) - return; - - if (!property_name_jstr) { - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_NULL_MEMBER_NAME); - goto done; - } - /* Get the Unicode string for the JS property name */ - property_name_ucs2 = (*jEnv)->GetStringChars(jEnv, property_name_jstr, &is_copy); - if (!property_name_ucs2) { - JS_ASSERT(0); - goto done; - } - property_name_len = (*jEnv)->GetStringLength(jEnv, property_name_jstr); - - JS_DeleteUCProperty2(cx, js_obj, property_name_ucs2, property_name_len, &js_val); - - (*jEnv)->ReleaseStringChars(jEnv, property_name_jstr, property_name_ucs2); - -done: - jsj_exit_js(cx, jsj_env, saved_reporter); - return; -} - -/* - * Class: netscape_javascript_JSObject - * Method: call - * Signature: (Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object; - */ -JNIEXPORT jobject JNICALL -Java_netscape_javascript_JSObject_call(JNIEnv *jEnv, jobject java_wrapper_obj, - jstring function_name_jstr, jobjectArray java_args) -{ - int i, argc, arg_num; - jsval *argv; - JSContext *cx = NULL; - JSObject *js_obj; - jsval js_val, function_val; - int dummy_cost; - JSBool dummy_bool; - const jchar *function_name_ucs2; - jsize function_name_len; - JSErrorReporter saved_reporter; - jboolean is_copy; - jobject result; - JSJavaThreadState *jsj_env; - - jsj_env = jsj_enter_js(jEnv, NULL, java_wrapper_obj, &cx, &js_obj, &saved_reporter, NULL, 0, NULL); - if (!jsj_env) - return NULL; - - function_name_ucs2 = NULL; - result = NULL; - if (!function_name_jstr) { - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_NULL_FUNCTION_NAME); - goto done; - } - - /* Get the function name to eval as raw Unicode characters */ - function_name_ucs2 = (*jEnv)->GetStringChars(jEnv, function_name_jstr, &is_copy); - if (!function_name_ucs2) { - JS_ASSERT(0); - goto done; - } - function_name_len = (*jEnv)->GetStringLength(jEnv, function_name_jstr); - - /* Allocate space for JS arguments */ - if (java_args) { - argc = (*jEnv)->GetArrayLength(jEnv, java_args); - argv = (jsval*)JS_malloc(cx, argc * sizeof(jsval)); - } else { - argc = 0; - argv = 0; - } - - /* Convert arguments from Java to JS values */ - for (arg_num = 0; arg_num < argc; arg_num++) { - jobject arg = (*jEnv)->GetObjectArrayElement(jEnv, java_args, arg_num); - - if (!jsj_ConvertJavaObjectToJSValue(cx, jEnv, arg, &argv[arg_num])) - goto cleanup_argv; - JS_AddNamedRoot(cx, &argv[arg_num], "&argv[arg_num]"); - } - - if (!JS_GetUCProperty(cx, js_obj, function_name_ucs2, function_name_len, - &function_val)) - goto cleanup_argv; - - if (!JS_CallFunctionValue(cx, js_obj, function_val, argc, argv, &js_val)) - goto cleanup_argv; - - jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv), - &dummy_cost, &result, &dummy_bool); - -cleanup_argv: - if (argv) { - for (i = 0; i < arg_num; i++) - JS_RemoveRoot(cx, &argv[i]); - JS_free(cx, argv); - } - -done: - if (function_name_ucs2) - (*jEnv)->ReleaseStringChars(jEnv, function_name_jstr, function_name_ucs2); - if (!jsj_exit_js(cx, jsj_env, saved_reporter)) - return NULL; - - return result; -} - -/* - * Class: netscape_javascript_JSObject - * Method: eval - * Signature: (Ljava/lang/String;)Ljava/lang/Object; - */ -JNIEXPORT jobject JNICALL -Java_netscape_javascript_JSObject_eval(JNIEnv *jEnv, - jobject java_wrapper_obj, - jstring eval_jstr) -{ - const char *codebase; - JSPrincipals *principals; - JSContext *cx = NULL; - JSBool eval_succeeded; - JSObject *js_obj; - jsval js_val; - int dummy_cost; - JSBool dummy_bool; - const jchar *eval_ucs2; - jsize eval_len; - JSErrorReporter saved_reporter; - jboolean is_copy; - jobject result; - JSJavaThreadState *jsj_env; - - jsj_env = jsj_enter_js(jEnv, NULL, java_wrapper_obj, &cx, &js_obj, &saved_reporter, NULL, 0, NULL); - if (!jsj_env) - return NULL; - - result = NULL; - eval_ucs2 = NULL; - if (!eval_jstr) { - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_NULL_EVAL_ARG); - goto done; - } - - /* Get the string to eval as raw Unicode characters */ - eval_ucs2 = (*jEnv)->GetStringChars(jEnv, eval_jstr, &is_copy); - if (!eval_ucs2) { - JS_ASSERT(0); - goto done; - } - eval_len = (*jEnv)->GetStringLength(jEnv, eval_jstr); - - /* Set up security stuff */ - principals = NULL; - if (JSJ_callbacks && JSJ_callbacks->get_JSPrincipals_from_java_caller) - principals = JSJ_callbacks->get_JSPrincipals_from_java_caller(jEnv, cx, NULL, 0, NULL); - codebase = principals ? principals->codebase : NULL; - - /* Have the JS engine evaluate the unicode string */ - eval_succeeded = JS_EvaluateUCScriptForPrincipals(cx, js_obj, principals, - eval_ucs2, eval_len, - codebase, 0, &js_val); - if (!eval_succeeded) - goto done; - - /* Convert result to a subclass of java.lang.Object */ - jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv), - &dummy_cost, &result, &dummy_bool); - -done: - if (eval_ucs2) - (*jEnv)->ReleaseStringChars(jEnv, eval_jstr, eval_ucs2); - if (!jsj_exit_js(cx, jsj_env, saved_reporter)) - return NULL; - - return result; -} - -/* - * Class: netscape_javascript_JSObject - * Method: toString - * Signature: ()Ljava/lang/String; - */ -JNIEXPORT jstring JNICALL -Java_netscape_javascript_JSObject_toString(JNIEnv *jEnv, - jobject java_wrapper_obj) -{ - jstring result; - JSContext *cx = NULL; - JSObject *js_obj; - JSString *jsstr; - JSErrorReporter saved_reporter; - JSJavaThreadState *jsj_env; - - jsj_env = jsj_enter_js(jEnv, NULL, java_wrapper_obj, &cx, &js_obj, &saved_reporter, NULL, 0, NULL); - if (!jsj_env) - return NULL; - - result = NULL; - jsstr = JS_ValueToString(cx, OBJECT_TO_JSVAL(js_obj)); - if (jsstr) - result = jsj_ConvertJSStringToJavaString(cx, jEnv, jsstr); - if (!result) - result = (*jEnv)->NewStringUTF(jEnv, "*JavaObject*"); - - if (!jsj_exit_js(cx, jsj_env, saved_reporter)) - return NULL; - - return result; -} - -/* - * Class: netscape_javascript_JSObject - * Method: getWindow - * Signature: (Ljava/applet/Applet;)Lnetscape/javascript/JSObject; - */ -JNIEXPORT jobject JNICALL -Java_netscape_javascript_JSObject_getWindow(JNIEnv *jEnv, - jclass js_object_class, - jobject java_applet_obj) -{ - char *err_msg; - JSContext *cx = NULL; - JSObject *js_obj = NULL; - jsval js_val; - int dummy_cost; - JSBool dummy_bool; - JSErrorReporter saved_reporter; - jobject java_obj; - JSJavaThreadState *jsj_env; - - jsj_env = jsj_enter_js(jEnv, java_applet_obj, NULL, &cx, NULL, &saved_reporter, NULL, 0, NULL); - if (!jsj_env) - return NULL; - - err_msg = NULL; - java_obj = NULL; - if (JSJ_callbacks && JSJ_callbacks->map_java_object_to_js_object) - js_obj = JSJ_callbacks->map_java_object_to_js_object(jEnv, java_applet_obj, &err_msg); - if (!js_obj) { - if (err_msg) { - JS_ReportError(cx, err_msg); - free(err_msg); - } - goto done; - } - js_val = OBJECT_TO_JSVAL(js_obj); - jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv), - &dummy_cost, &java_obj, &dummy_bool); -done: - if (!jsj_exit_js(cx, jsj_env, saved_reporter)) - return NULL; - - return java_obj; -} - -/* - * Class: netscape_javascript_JSObject - * Method: finalize - * Signature: ()V - */ -JNIEXPORT void JNICALL -Java_netscape_javascript_JSObject_finalize(JNIEnv *jEnv, jobject java_wrapper_obj) -{ - JSBool success; - JSObjectHandle *handle; - - success = JS_FALSE; - -#if JS_BYTES_PER_LONG == 8 - handle = (JSObjectHandle *)((*jEnv)->GetLongField(jEnv, java_wrapper_obj, njJSObject_long_internal)); -#else - handle = (JSObjectHandle *)((*jEnv)->GetIntField(jEnv, java_wrapper_obj, njJSObject_internal)); -#endif - JS_ASSERT(handle); - if (!handle) - return; - - success = JS_RemoveRootRT(handle->rt, &handle->js_obj); - free(handle); - - JS_ASSERT(success); -} - -/* - * Class: netscape_javascript_JSObject - * Method: equals - * Signature: (Ljava/lang/Object;)Z - */ - -JNIEXPORT jboolean JNICALL -Java_netscape_javascript_JSObject_equals(JNIEnv *jEnv, - jobject java_wrapper_obj, - jobject comparison_obj) -{ -#ifdef PRESERVE_JSOBJECT_IDENTITY -# error "Missing code should be added here" -#else - JSObject *js_obj1, *js_obj2; - - /* Check that we're comparing with another netscape.javascript.JSObject */ - if (!comparison_obj) - return 0; - if (!(*jEnv)->IsInstanceOf(jEnv, comparison_obj, njJSObject)) - return 0; - - js_obj1 = jsj_UnwrapJSObjectWrapper(jEnv, java_wrapper_obj); - js_obj2 = jsj_UnwrapJSObjectWrapper(jEnv, comparison_obj); - - return (js_obj1 == js_obj2); -#endif /* PRESERVE_JSOBJECT_IDENTITY */ -} - diff --git a/lib/javascript/liveconnect/jsj_JavaArray.c b/lib/javascript/liveconnect/jsj_JavaArray.c deleted file mode 100644 index 38e80631..00000000 --- a/lib/javascript/liveconnect/jsj_JavaArray.c +++ /dev/null @@ -1,477 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * This file is part of the Java-vendor-neutral implementation of LiveConnect - * - * It contains the definition of the JavaScript JavaArray class. - * Instances of JavaArray are used to reflect Java arrays. - */ - -#include -#include - -#include "jsj_private.h" /* LiveConnect internals */ - -/* Shorthands for ASCII (7-bit) decimal and hex conversion. */ -#define JS7_ISDEC(c) (((c) >= '0') && ((c) <= '9')) -#define JS7_UNDEC(c) ((c) - '0') - -/* - * Convert any jsval v to an integer jsval if ToString(v) - * contains a base-10 integer that fits into 31 bits. - * Otherwise return v. - */ -static jsval -try_convert_to_jsint(JSContext *cx, jsval idval) -{ - const jschar *cp; - JSString *jsstr; - - jsstr = JS_ValueToString(cx, idval); - if (!jsstr) - return idval; - - cp = JS_GetStringChars(jsstr); - if (JS7_ISDEC(*cp)) { - jsuint index = JS7_UNDEC(*cp++); - jsuint oldIndex = 0; - jsuint c = 0; - if (index != 0) { - while (JS7_ISDEC(*cp)) { - oldIndex = index; - c = JS7_UNDEC(*cp); - index = 10*index + c; - cp++; - } - } - if (*cp == 0 && - (oldIndex < (JSVAL_INT_MAX / 10) || - (oldIndex == (JSVAL_INT_MAX / 10) && c < (JSVAL_INT_MAX % 10)))) { - return INT_TO_JSVAL(index); - } - } - return idval; -} - - -static JSBool -access_java_array_element(JSContext *cx, - JNIEnv *jEnv, - JSObject *obj, - jsid id, - jsval *vp, - JSBool do_assignment) -{ - jsval idval; - jarray java_array; - JavaClassDescriptor *class_descriptor; - JavaObjectWrapper *java_wrapper; - jsize array_length, index; - JavaSignature *array_component_signature; - - /* printf("In JavaArray_getProperty\n"); */ - - java_wrapper = JS_GetPrivate(cx, obj); - if (!java_wrapper) { - const char *property_name; - if (JS_IdToValue(cx, id, &idval) && JSVAL_IS_STRING(idval) && - (property_name = JS_GetStringBytes(JSVAL_TO_STRING(idval))) != NULL) { - if (!strcmp(property_name, "constructor")) { - if (vp) - *vp = JSVAL_VOID; - return JS_TRUE; - } - } - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_BAD_OP_JARRAY); - return JS_FALSE; - } - class_descriptor = java_wrapper->class_descriptor; - java_array = java_wrapper->java_obj; - - JS_ASSERT(class_descriptor->type == JAVA_SIGNATURE_ARRAY); - - JS_IdToValue(cx, id, &idval); - - if (!JSVAL_IS_INT(idval)) - idval = try_convert_to_jsint(cx, idval); - - if (!JSVAL_IS_INT(idval)) { - /* - * Usually, properties of JavaArray objects are indexed by integers, but - * Java arrays also inherit all the methods of java.lang.Object, so a - * string-valued property is also possible. - */ - if (JSVAL_IS_STRING(idval)) { - const char *member_name; - - member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval)); - - if (do_assignment) { - JSVersion version = JS_GetVersion(cx); - - if (!JSVERSION_IS_ECMA(version)) { - - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_CANT_WRITE_JARRAY, member_name); - return JS_FALSE; - } else { - if (vp) - *vp = JSVAL_VOID; - return JS_TRUE; - } - } else { - if (!strcmp(member_name, "length")) { - array_length = jsj_GetJavaArrayLength(cx, jEnv, java_array); - if (array_length < 0) - return JS_FALSE; - if (vp) - *vp = INT_TO_JSVAL(array_length); - return JS_TRUE; - } - - /* Check to see if we're reflecting a Java array method */ - return JavaObject_getPropertyById(cx, obj, id, vp); - } - } - - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_BAD_INDEX_EXPR); - return JS_FALSE; - } - - index = JSVAL_TO_INT(idval); - -#if 0 - array_length = jsj_GetJavaArrayLength(cx, jEnv, java_array); - if (array_length < 0) - return JS_FALSE; - - /* Just let Java throw an exception instead of checking array bounds here */ - if (index < 0 || index >= array_length) { - char numBuf[12]; - sprintf(numBuf, "%d", index); - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_BAD_JARRAY_INDEX, numBuf); - return JS_FALSE; - } -#endif - - array_component_signature = class_descriptor->array_component_signature; - - if (!vp) - return JS_TRUE; - - if (do_assignment) { - return jsj_SetJavaArrayElement(cx, jEnv, java_array, index, - array_component_signature, *vp); - } else { - return jsj_GetJavaArrayElement(cx, jEnv, java_array, index, - array_component_signature, vp); - } -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaArray_getPropertyById(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - JNIEnv *jEnv; - JSJavaThreadState *jsj_env; - JSBool result; - - jsj_env = jsj_EnterJava(cx, &jEnv); - if (!jEnv) - return JS_FALSE; - result = access_java_array_element(cx, jEnv, obj, id, vp, JS_FALSE); - jsj_ExitJava(jsj_env); - return result; -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaArray_setPropertyById(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - JNIEnv *jEnv; - JSJavaThreadState *jsj_env; - JSBool result; - - jsj_env = jsj_EnterJava(cx, &jEnv); - if (!jEnv) - return JS_FALSE; - result = access_java_array_element(cx, jEnv, obj, id, vp, JS_TRUE); - jsj_ExitJava(jsj_env); - return result; -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaArray_lookupProperty(JSContext *cx, JSObject *obj, jsid id, - JSObject **objp, JSProperty **propp) -{ - JNIEnv *jEnv; - JSErrorReporter old_reporter; - JSJavaThreadState *jsj_env; - - jsj_env = jsj_EnterJava(cx, &jEnv); - if (!jEnv) - return JS_FALSE; - - old_reporter = JS_SetErrorReporter(cx, NULL); - if (access_java_array_element(cx, jEnv, obj, id, NULL, JS_FALSE)) { - *objp = obj; - *propp = (JSProperty*)1; - } else { - *objp = NULL; - *propp = NULL; - } - JS_SetErrorReporter(cx, old_reporter); - jsj_ExitJava(jsj_env); - return JS_TRUE; -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaArray_defineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value, - JSPropertyOp getter, JSPropertyOp setter, - uintN attrs, JSProperty **propp) -{ - jsval *vp = &value; - if (propp) - return JS_FALSE; - if (attrs & ~(JSPROP_PERMANENT|JSPROP_ENUMERATE)) - return JS_FALSE; - - return JavaArray_setPropertyById(cx, obj, id, vp); -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaArray_getAttributes(JSContext *cx, JSObject *obj, jsid id, - JSProperty *prop, uintN *attrsp) -{ - /* We don't maintain JS property attributes for Java class members */ - *attrsp = JSPROP_PERMANENT|JSPROP_ENUMERATE; - return JS_FALSE; -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaArray_setAttributes(JSContext *cx, JSObject *obj, jsid id, - JSProperty *prop, uintN *attrsp) -{ - /* We don't maintain JS property attributes for Java class members */ - if (*attrsp != (JSPROP_PERMANENT|JSPROP_ENUMERATE)) { - JS_ASSERT(0); - return JS_FALSE; - } - - /* Silently ignore all setAttribute attempts */ - return JS_TRUE; -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaArray_deleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp) -{ - JSVersion version = JS_GetVersion(cx); - - *vp = JSVAL_FALSE; - - if (!JSVERSION_IS_ECMA(version)) { - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_JARRAY_PROP_DELETE); - return JS_FALSE; - } else { - /* Attempts to delete permanent properties are silently ignored - by ECMAScript. */ - return JS_TRUE; - } -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaArray_defaultValue(JSContext *cx, JSObject *obj, JSType type, jsval *vp) -{ - /* printf("In JavaArray_defaultValue()\n"); */ - return JavaObject_convert(cx, obj, JSTYPE_STRING, vp); -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaArray_newEnumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, - jsval *statep, jsid *idp) -{ - JavaObjectWrapper *java_wrapper; - JSJavaThreadState *jsj_env; - JNIEnv *jEnv; - jsize array_length, index; - JSBool ok = JS_TRUE; - - java_wrapper = JS_GetPrivate(cx, obj); - /* Check for prototype object */ - if (!java_wrapper) { - *statep = JSVAL_NULL; - if (idp) - *idp = INT_TO_JSVAL(0); - return JS_TRUE; - } - - /* Get the Java per-thread environment pointer for this JSContext */ - jsj_env = jsj_EnterJava(cx, &jEnv); - if (!jEnv) - return JS_FALSE; - - array_length = jsj_GetJavaArrayLength(cx, jEnv, java_wrapper->java_obj); - if (array_length < 0) { - jsj_ExitJava(jsj_env); - return JS_FALSE; - } - - switch(enum_op) { - case JSENUMERATE_INIT: - *statep = INT_TO_JSVAL(0); - - if (idp) - *idp = INT_TO_JSVAL(array_length); - break; - - case JSENUMERATE_NEXT: - index = JSVAL_TO_INT(*statep); - if (index < array_length) { - JS_ValueToId(cx, INT_TO_JSVAL(index), idp); - index++; - *statep = INT_TO_JSVAL(index); - break; - } - - /* Fall through ... */ - - case JSENUMERATE_DESTROY: - *statep = JSVAL_NULL; - break; - - default: - JS_ASSERT(0); - ok = JS_FALSE; - break; - } - - jsj_ExitJava(jsj_env); - return ok; -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaArray_checkAccess(JSContext *cx, JSObject *obj, jsid id, - JSAccessMode mode, jsval *vp, uintN *attrsp) -{ - switch (mode) { - case JSACC_WATCH: - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_JARRAY_PROP_WATCH); - return JS_FALSE; - - case JSACC_IMPORT: - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_JARRAY_PROP_EXPORT); - return JS_FALSE; - - default: - return JS_TRUE; - } -} - -JSObjectOps JavaArray_ops = { - /* Mandatory non-null function pointer members. */ - jsj_wrapper_newObjectMap, /* newObjectMap */ - jsj_wrapper_destroyObjectMap, /* destroyObjectMap */ - JavaArray_lookupProperty, - JavaArray_defineProperty, - JavaArray_getPropertyById, /* getProperty */ - JavaArray_setPropertyById, /* setProperty */ - JavaArray_getAttributes, - JavaArray_setAttributes, - JavaArray_deleteProperty, - JavaArray_defaultValue, - JavaArray_newEnumerate, - JavaArray_checkAccess, - - /* Optionally non-null members start here. */ - NULL, /* thisObject */ - NULL, /* dropProperty */ - NULL, /* call */ - NULL, /* construct */ - NULL, /* xdrObject */ - NULL, /* hasInstance */ - NULL, /* setProto */ - NULL, /* setParent */ - NULL, /* mark */ - NULL, /* clear */ - jsj_wrapper_getRequiredSlot, /* getRequiredSlot */ - jsj_wrapper_setRequiredSlot /* setRequiredSlot */ -}; - -JS_STATIC_DLL_CALLBACK(JSObjectOps *) -JavaArray_getObjectOps(JSContext *cx, JSClass *clazz) -{ - return &JavaArray_ops; -} - -JSClass JavaArray_class = { - "JavaArray", JSCLASS_HAS_PRIVATE, - NULL, NULL, NULL, NULL, - NULL, NULL, JavaObject_convert, JavaObject_finalize, - - /* Optionally non-null members start here. */ - JavaArray_getObjectOps, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - 0, -}; - -extern JS_IMPORT_DATA(JSObjectOps) js_ObjectOps; - - -/* Initialize the JS JavaArray class */ -JSBool -jsj_init_JavaArray(JSContext *cx, JSObject *global_obj) -{ - if (!JS_InitClass(cx, global_obj, - 0, &JavaArray_class, 0, 0, - 0, 0, 0, 0)) - return JS_FALSE; - - return JS_TRUE; -} - diff --git a/lib/javascript/liveconnect/jsj_JavaClass.c b/lib/javascript/liveconnect/jsj_JavaClass.c deleted file mode 100644 index ebf7104b..00000000 --- a/lib/javascript/liveconnect/jsj_JavaClass.c +++ /dev/null @@ -1,745 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* This file is part of the Java-vendor-neutral implementation of LiveConnect - * - * It contains the native code implementation of JS's JavaClass class. - * - * A JavaClass is JavaScript's representation of a Java class. - * Its parent JS object is always a JavaPackage object. A JavaClass is not an - * exact reflection of Java's corresponding java.lang.Class object. Rather, - * the properties of a JavaClass are the static methods and properties of the - * corresponding Java class. - * - * Note that there is no runtime equivalent to the JavaClass class in Java. - * (Although there are instances of java.lang.String and there are static - * methods of java.lang.String that can be invoked, there's no such thing as - * a first-class object that can be referenced simply as "java.lang.String".) - */ - -#include -#include - -#include "jsj_private.h" /* LiveConnect internals */ -#include "jscntxt.h" /* for error reporting */ - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaClass_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp) -{ - char *name; - JSString *str; - - JavaClassDescriptor *class_descriptor; - - class_descriptor = JS_GetPrivate(cx, obj); - if (!class_descriptor) - return JS_FALSE; - - switch(type) { - - - case JSTYPE_STRING: - /* Convert '/' to '.' so that it looks like Java language syntax. */ - if (!class_descriptor->name) - break; - name = JS_smprintf("[JavaClass %s]", class_descriptor->name); - if (!name) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - - str = JS_NewString(cx, name, strlen(name)); - if (!str) { - free(name); - /* It's not necessary to call JS_ReportOutOfMemory(), as - JS_NewString() will do so on failure. */ - return JS_FALSE; - } - - *vp = STRING_TO_JSVAL(str); - return JS_TRUE; - - default: - break; - } - return JS_TRUE; -} - -static JSBool -lookup_static_member_by_id(JSContext *cx, JNIEnv *jEnv, JSObject *obj, - JavaClassDescriptor **class_descriptorp, - jsid id, JavaMemberDescriptor **memberp) -{ - jsval idval; - JavaMemberDescriptor *member_descriptor; - const char *member_name; - JavaClassDescriptor *class_descriptor; - - class_descriptor = JS_GetPrivate(cx, obj); - if (!class_descriptor) { - *class_descriptorp = NULL; - *memberp = NULL; - return JS_TRUE; - } - - if (class_descriptorp) - *class_descriptorp = class_descriptor; - - member_descriptor = jsj_LookupJavaStaticMemberDescriptorById(cx, jEnv, class_descriptor, id); - if (!member_descriptor) { - JS_IdToValue(cx, id, &idval); - if (!JSVAL_IS_STRING(idval)) { - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_BAD_JCLASS_EXPR); - return JS_FALSE; - } - - member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval)); - - /* - * See if the property looks like the explicit resolution of an - * overloaded method, e.g. "max(double,double)". - */ - member_descriptor = - jsj_ResolveExplicitMethod(cx, jEnv, class_descriptor, id, JS_TRUE); - if (member_descriptor) - goto done; - - /* Why do we have to do this ? */ - if (!strcmp(member_name, "prototype")) { - *memberp = NULL; - return JS_TRUE; - } - - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_MISSING_NAME, - class_descriptor->name, member_name); - return JS_FALSE; - } - -done: - if (memberp) - *memberp = member_descriptor; - return JS_TRUE; -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaClass_getPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp) -{ - jsval idval; - jclass java_class; - const char *member_name; - JavaClassDescriptor *class_descriptor; - JavaMemberDescriptor *member_descriptor; - JNIEnv *jEnv; - JSJavaThreadState *jsj_env; - JSBool result; - - /* printf("In JavaClass_getProperty\n"); */ - - /* Get the Java per-thread environment pointer for this JSContext */ - jsj_env = jsj_EnterJava(cx, &jEnv); - if (!jEnv) - return JS_FALSE; - - if (!lookup_static_member_by_id(cx, jEnv, obj, &class_descriptor, id, &member_descriptor)) { - jsj_ExitJava(jsj_env); - return JS_FALSE; - } - if (!member_descriptor) { - *vp = JSVAL_VOID; - jsj_ExitJava(jsj_env); - return JS_TRUE; - } - - java_class = class_descriptor->java_class; - - if (member_descriptor->field) { - if (!member_descriptor->methods) { - result = jsj_GetJavaFieldValue(cx, jEnv, member_descriptor->field, java_class, vp); - jsj_ExitJava(jsj_env); - return result; - } else { - JS_ASSERT(0); - } - } else { - JSFunction *function; - - /* TODO - eliminate JSFUN_BOUND_METHOD */ - if (member_descriptor->methods->is_alias) { - /* If this is an explicit resolution of an overloaded method, - use the fully-qualified method name as the name of the - resulting JS function, i.e. "myMethod(int,long)" */ - JS_IdToValue(cx, id, &idval); - member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval)); - } else { - /* Either not explicit resolution of overloaded method or - explicit resolution was unnecessary because method was - not overloaded. */ - member_name = member_descriptor->name; - } - function = JS_NewFunction(cx, jsj_JavaStaticMethodWrapper, 0, - JSFUN_BOUND_METHOD, obj, member_name); - if (!function) { - jsj_ExitJava(jsj_env); - return JS_FALSE; - } - - *vp = OBJECT_TO_JSVAL(JS_GetFunctionObject(function)); - } - - jsj_ExitJava(jsj_env); - return JS_TRUE; -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaClass_setPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp) -{ - jclass java_class; - const char *member_name; - JavaClassDescriptor *class_descriptor; - JavaMemberDescriptor *member_descriptor; - jsval idval; - JNIEnv *jEnv; - JSJavaThreadState *jsj_env; - JSBool result; - - /* printf("In JavaClass_setProperty\n"); */ - - /* Get the Java per-thread environment pointer for this JSContext */ - jsj_env = jsj_EnterJava(cx, &jEnv); - if (!jEnv) - return JS_FALSE; - - if (!lookup_static_member_by_id(cx, jEnv, obj, &class_descriptor, id, &member_descriptor)) { - jsj_ExitJava(jsj_env); - return JS_FALSE; - } - - /* Check for the case where there is a method with the given name, but no field - with that name */ - if (!member_descriptor->field) - goto no_such_field; - - /* Silently fail if field value is final (immutable), as required by ECMA spec */ - if (member_descriptor->field->modifiers & ACC_FINAL) { - jsj_ExitJava(jsj_env); - return JS_TRUE; - } - - java_class = class_descriptor->java_class; - result = jsj_SetJavaFieldValue(cx, jEnv, member_descriptor->field, java_class, *vp); - jsj_ExitJava(jsj_env); - return result; - -no_such_field: - JS_IdToValue(cx, id, &idval); - member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval)); - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_MISSING_STATIC, - member_name, class_descriptor->name); - jsj_ExitJava(jsj_env); - return JS_FALSE; -} - -/* - * Free the private native data associated with the JavaPackage object. - */ -JS_STATIC_DLL_CALLBACK(void) -JavaClass_finalize(JSContext *cx, JSObject *obj) -{ - JNIEnv *jEnv; - JSJavaThreadState *jsj_env; - - JavaClassDescriptor *class_descriptor = JS_GetPrivate(cx, obj); - if (!class_descriptor) - return; - - /* Get the Java per-thread environment pointer for this JSContext */ - jsj_env = jsj_EnterJava(cx, &jEnv); - if (!jEnv) - return; - - /* printf("Finalizing %s\n", class_descriptor->name); */ - jsj_ReleaseJavaClassDescriptor(cx, jEnv, class_descriptor); - jsj_ExitJava(jsj_env); -} - - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaClass_lookupProperty(JSContext *cx, JSObject *obj, jsid id, - JSObject **objp, JSProperty **propp) -{ - JNIEnv *jEnv; - JSErrorReporter old_reporter; - JSJavaThreadState *jsj_env; - - /* printf("In JavaClass_lookupProperty()\n"); */ - - /* Get the Java per-thread environment pointer for this JSContext */ - jsj_env = jsj_EnterJava(cx, &jEnv); - if (!jEnv) - return JS_FALSE; - - old_reporter = JS_SetErrorReporter(cx, NULL); - if (lookup_static_member_by_id(cx, jEnv, obj, NULL, id, NULL)) { - *objp = obj; - *propp = (JSProperty*)1; - } else { - *objp = NULL; - *propp = NULL; - } - - JS_SetErrorReporter(cx, old_reporter); - jsj_ExitJava(jsj_env); - return JS_TRUE; -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaClass_defineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value, - JSPropertyOp getter, JSPropertyOp setter, - uintN attrs, JSProperty **propp) -{ - JavaClassDescriptor *class_descriptor; - - class_descriptor = JS_GetPrivate(cx, obj); - - /* Check for prototype JavaClass object */ - if (!class_descriptor) - return JS_TRUE; - - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_JCLASS_PROP_DEFINE); - return JS_FALSE; -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaClass_getAttributes(JSContext *cx, JSObject *obj, jsid id, - JSProperty *prop, uintN *attrsp) -{ - /* We don't maintain JS property attributes for Java class members */ - *attrsp = JSPROP_PERMANENT|JSPROP_ENUMERATE; - return JS_FALSE; -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaClass_setAttributes(JSContext *cx, JSObject *obj, jsid id, - JSProperty *prop, uintN *attrsp) -{ - /* We don't maintain JS property attributes for Java class members */ - if (*attrsp != (JSPROP_PERMANENT|JSPROP_ENUMERATE)) { - JS_ASSERT(0); - return JS_FALSE; - } - - /* Silently ignore all setAttribute attempts */ - return JS_TRUE; -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaClass_deleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp) -{ - JSVersion version = JS_GetVersion(cx); - - *vp = JSVAL_FALSE; - - if (!JSVERSION_IS_ECMA(version)) { - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_JCLASS_PROP_DELETE); - return JS_FALSE; - } else { - /* Attempts to delete permanent properties are silently ignored - by ECMAScript. */ - return JS_TRUE; - } -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaClass_defaultValue(JSContext *cx, JSObject *obj, JSType type, jsval *vp) -{ - /* printf("In JavaClass_defaultValue()\n"); */ - return JavaClass_convert(cx, obj, JSTYPE_STRING, vp); -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaClass_newEnumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, - jsval *statep, jsid *idp) -{ - JavaMemberDescriptor *member_descriptor; - JavaClassDescriptor *class_descriptor; - JNIEnv *jEnv; - JSJavaThreadState *jsj_env; - - class_descriptor = JS_GetPrivate(cx, obj); - - /* Check for prototype JavaClass object */ - if (!class_descriptor) { - *statep = JSVAL_NULL; - if (idp) - *idp = INT_TO_JSVAL(0); - return JS_TRUE; - } - - switch(enum_op) { - case JSENUMERATE_INIT: - /* Get the Java per-thread environment pointer for this JSContext */ - jsj_env = jsj_EnterJava(cx, &jEnv); - if (!jEnv) - return JS_FALSE; - member_descriptor = jsj_GetClassStaticMembers(cx, jEnv, class_descriptor); - *statep = PRIVATE_TO_JSVAL(member_descriptor); - if (idp) - *idp = INT_TO_JSVAL(class_descriptor->num_instance_members); - jsj_ExitJava(jsj_env); - return JS_TRUE; - - case JSENUMERATE_NEXT: - member_descriptor = JSVAL_TO_PRIVATE(*statep); - if (member_descriptor) { - - /* Don't enumerate explicit-signature methods, i.e. enumerate toValue, - but not toValue(int), toValue(double), etc. */ - while (member_descriptor->methods && member_descriptor->methods->is_alias) { - member_descriptor = member_descriptor->next; - if (!member_descriptor) { - *statep = JSVAL_NULL; - return JS_TRUE; - } - } - - *idp = member_descriptor->id; - *statep = PRIVATE_TO_JSVAL(member_descriptor->next); - return JS_TRUE; - } - /* Fall through ... */ - - case JSENUMERATE_DESTROY: - *statep = JSVAL_NULL; - return JS_TRUE; - - default: - JS_ASSERT(0); - return JS_FALSE; - } -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaClass_checkAccess(JSContext *cx, JSObject *obj, jsid id, - JSAccessMode mode, jsval *vp, uintN *attrsp) -{ - switch (mode) { - case JSACC_WATCH: - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_JCLASS_PROP_WATCH); - return JS_FALSE; - - case JSACC_IMPORT: - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_JCLASS_PROP_EXPORT); - return JS_FALSE; - - default: - return JS_TRUE; - } -} - -/* - * Implement the JavaScript instanceof operator for JavaClass objects by using - * the equivalent Java instanceof operation. - */ -JS_STATIC_DLL_CALLBACK(JSBool) -JavaClass_hasInstance(JSContext *cx, JSObject *obj, jsval candidate_jsval, - JSBool *has_instancep) -{ - JavaClassDescriptor *class_descriptor; - JavaObjectWrapper *java_wrapper; - JSClass *js_class; - JSBool has_instance; - JSObject *candidate_obj; - jclass java_class; - jobject java_obj; - JNIEnv *jEnv; - JSJavaThreadState *jsj_env; - - has_instance = JS_FALSE; - class_descriptor = JS_GetPrivate(cx, obj); - if (!class_descriptor) { - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_BAD_OP_JCLASS); - return JS_FALSE; - } - - /* - * Make sure that the thing to the left of the instanceof operator is a - * Java object. - */ - if (!JSVAL_IS_OBJECT(candidate_jsval)) - goto done; - candidate_obj = JSVAL_TO_OBJECT(candidate_jsval); -#ifdef JS_THREADSAFE - js_class = JS_GetClass(cx, candidate_obj); -#else - js_class = JS_GetClass(candidate_obj); -#endif - if ((js_class != &JavaObject_class) && (js_class != &JavaArray_class)) - goto done; - - java_class = class_descriptor->java_class; - java_wrapper = JS_GetPrivate(cx, candidate_obj); - if (!java_wrapper) { - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_BAD_OP_PROTO); - return JS_FALSE; - } - java_obj = java_wrapper->java_obj; - /* Get JNI pointer */ - jsj_env = jsj_EnterJava(cx, &jEnv); - has_instance = (*jEnv)->IsInstanceOf(jEnv, java_obj, java_class); - jsj_ExitJava(jsj_env); - -done: - *has_instancep = has_instance; - return JS_TRUE; -} - -JSObjectOps JavaClass_ops = { - /* Mandatory non-null function pointer members. */ - jsj_wrapper_newObjectMap, /* newObjectMap */ - jsj_wrapper_destroyObjectMap, /* destroyObjectMap */ - JavaClass_lookupProperty, - JavaClass_defineProperty, - JavaClass_getPropertyById, /* getProperty */ - JavaClass_setPropertyById, /* setProperty */ - JavaClass_getAttributes, - JavaClass_setAttributes, - JavaClass_deleteProperty, - JavaClass_defaultValue, - JavaClass_newEnumerate, - JavaClass_checkAccess, - - /* Optionally non-null members start here. */ - NULL, /* thisObject */ - NULL, /* dropProperty */ - jsj_JavaConstructorWrapper, /* call */ - jsj_JavaConstructorWrapper, /* construct */ - NULL, /* xdrObject */ - JavaClass_hasInstance, /* hasInstance */ - NULL, /* setProto */ - NULL, /* setParent */ - NULL, /* mark */ - NULL, /* clear */ - jsj_wrapper_getRequiredSlot, /* getRequiredSlot */ - jsj_wrapper_setRequiredSlot /* setRequiredSlot */ -}; - -JS_STATIC_DLL_CALLBACK(JSObjectOps *) -JavaClass_getObjectOps(JSContext *cx, JSClass *clazz) -{ - return &JavaClass_ops; -} - -JSClass JavaClass_class = { - "JavaClass", JSCLASS_HAS_PRIVATE, - NULL, NULL, NULL, NULL, - NULL, NULL, JavaClass_convert, JavaClass_finalize, - - /* Optionally non-null members start here. */ - JavaClass_getObjectOps, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - 0, -}; - -static JSObject * -jsj_new_JavaClass(JSContext *cx, JNIEnv *jEnv, JSObject* parent_obj, - JavaClassDescriptor *class_descriptor) -{ - JSObject *JavaClass_obj; - - JavaClass_obj = JS_NewObject(cx, &JavaClass_class, 0, parent_obj); - if (!JavaClass_obj) - return NULL; - - JS_SetPrivate(cx, JavaClass_obj, (void *)class_descriptor); - -#ifdef DEBUG - /* printf("JavaClass \'%s\' created\n", class_descriptor->name); */ -#endif - - return JavaClass_obj; -} - -JSObject * -jsj_define_JavaClass(JSContext *cx, JNIEnv *jEnv, JSObject* parent_obj, - const char *simple_class_name, - jclass java_class) -{ - JavaClassDescriptor *class_descriptor; - JSObject *JavaClass_obj; - - class_descriptor = jsj_GetJavaClassDescriptor(cx, jEnv, java_class); - if (!class_descriptor) - return NULL; - - JavaClass_obj = jsj_new_JavaClass(cx, jEnv, parent_obj, class_descriptor); - if (!JavaClass_obj) - return NULL; - - if (!JS_DefineProperty(cx, parent_obj, simple_class_name, - OBJECT_TO_JSVAL(JavaClass_obj), 0, 0, - JSPROP_PERMANENT|JSPROP_READONLY|JSPROP_ENUMERATE)) - return NULL; - return JavaClass_obj; -} - - -/* - * The getClass() native JS method is defined as a property of the global - * object. Given a JavaObject it returns the corresponding JavaClass. This - * is useful for accessing static methods and fields. - * - * js> getClass(new java.lang.String("foo")) - * [JavaClass java.lang.String] - */ -JS_STATIC_DLL_CALLBACK(JSBool) -getClass(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSObject *obj_arg, *JavaClass_obj; - JavaObjectWrapper *java_wrapper; - JavaClassDescriptor *class_descriptor; - JNIEnv *jEnv; - JSJavaThreadState *jsj_env; - - if (argc != 1 || - !JSVAL_IS_OBJECT(argv[0]) || - !(obj_arg = JSVAL_TO_OBJECT(argv[0])) || - (!JS_InstanceOf(cx, obj_arg, &JavaObject_class, 0) && - !JS_InstanceOf(cx, obj_arg, &JavaArray_class, 0))) { - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_NEED_JOBJECT_ARG); - return JS_FALSE; - } - - java_wrapper = JS_GetPrivate(cx, obj_arg); - if (!java_wrapper) { - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_PROTO_GETCLASS); - return JS_FALSE; - } - - jsj_env = jsj_EnterJava(cx, &jEnv); - if (!jEnv) - return JS_FALSE; - - class_descriptor = java_wrapper->class_descriptor; - - JavaClass_obj = jsj_new_JavaClass(cx, jEnv, NULL, class_descriptor); - if (!JavaClass_obj) { - jsj_ExitJava(jsj_env); - return JS_FALSE; - } - - *rval = OBJECT_TO_JSVAL(JavaClass_obj); - jsj_ExitJava(jsj_env); - return JS_TRUE; -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaClass_construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSObject *obj_arg, *JavaClass_obj; - JavaObjectWrapper *java_wrapper; - JavaClassDescriptor *class_descriptor; - JNIEnv *jEnv; - JSJavaThreadState *jsj_env; - - if (argc != 1 || - !JSVAL_IS_OBJECT(argv[0]) || - !(obj_arg = JSVAL_TO_OBJECT(argv[0])) || - !JS_InstanceOf(cx, obj_arg, &JavaObject_class, 0) || - ((java_wrapper = JS_GetPrivate(cx, obj_arg)) == NULL)) { - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_NEED_JCLASS_ARG); - return JS_FALSE; - } - - jsj_env = jsj_EnterJava(cx, &jEnv); - if (!jEnv) - return JS_FALSE; - - class_descriptor = java_wrapper->class_descriptor; - if (!(*jEnv)->IsSameObject(jEnv, class_descriptor->java_class, jlClass)) { - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_NEED_JCLASS_ARG); - jsj_ExitJava(jsj_env); - return JS_FALSE; - } - - class_descriptor = jsj_GetJavaClassDescriptor(cx, jEnv, java_wrapper->java_obj); - JavaClass_obj = jsj_new_JavaClass(cx, jEnv, NULL, class_descriptor); - if (!JavaClass_obj) { - jsj_ExitJava(jsj_env); - return JS_FALSE; - } - - *rval = OBJECT_TO_JSVAL(JavaClass_obj); - jsj_ExitJava(jsj_env); - return JS_TRUE; -} - -extern JS_IMPORT_DATA(JSObjectOps) js_ObjectOps; - -JSBool -jsj_init_JavaClass(JSContext *cx, JSObject *global_obj) -{ - /* Define JavaClass class */ - if (!JS_InitClass(cx, global_obj, 0, &JavaClass_class, JavaClass_construct, 0, 0, 0, 0, 0)) - return JS_FALSE; - - if (!JS_DefineFunction(cx, global_obj, "getClass", getClass, 0, - JSPROP_READONLY)) - return JS_FALSE; - - return jsj_InitJavaClassReflectionsTable(); -} - diff --git a/lib/javascript/liveconnect/jsj_JavaMember.c b/lib/javascript/liveconnect/jsj_JavaMember.c deleted file mode 100644 index 6937ae1d..00000000 --- a/lib/javascript/liveconnect/jsj_JavaMember.c +++ /dev/null @@ -1,186 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - - /* -*- Mode: C; tab-width: 8 -*- - * Copyright (C) 1998-1999 Netscape Communications Corporation, All Rights Reserved. - */ - -/* - * This file is part of the Java-vendor-neutral implementation of LiveConnect - * - * It contains the native code implementation of JS's JavaMember class. - * JavaMember's are a strange beast required only to handle the special case - * of a public field and a public method that appear in the same class and - * have the same name. When such a field/method is used in Java, the compiler - * can statically determine from context whether the field or the method is - * being referenced, but that is not possible with JavaScript. For example: - * - * ambiguousVal = javaObj.fieldOrMethod; // ambiguousVal is a JavaMember object - * a = ambiguousVal(); // ambiguousVal used as a method value - * b = ambiguousVal + 4; // ambiguousVal used as a field value - * - * A JavaMember instance carries both the captured value of the Java field and - * the method value until the context that the value is to be used in is known, - * at which point conversion forces the use of one or the other. - */ - -#include -#include - -#include "jsj_private.h" /* LiveConnect internals */ - -/* Private, native portion of a JavaMember */ -typedef struct JavaMethodOrFieldValue { - jsval method_val; - jsval field_val; -} JavaMethodOrFieldValue; - -JSObject * -jsj_CreateJavaMember(JSContext *cx, jsval method_val, jsval field_val) -{ - JavaMethodOrFieldValue *member_val; - JSObject *JavaMember_obj; - - member_val = (JavaMethodOrFieldValue *)JS_malloc(cx, sizeof(*member_val)); - if (!member_val) - return NULL; - - JavaMember_obj = JS_NewObject(cx, &JavaMember_class, 0, 0); - if (!JavaMember_obj) { - JS_free(cx, member_val); - return NULL; - } - - JS_SetPrivate(cx, JavaMember_obj, (void *)member_val); - member_val->method_val = method_val; - JS_AddNamedRoot(cx, &member_val->method_val, "&member_val->method_val"); - member_val->field_val = field_val; - if (JSVAL_IS_GCTHING(field_val)) - JS_AddNamedRoot(cx, &member_val->field_val, "&member_val->field_val"); - - return JavaMember_obj; -} - -JS_STATIC_DLL_CALLBACK(void) -JavaMember_finalize(JSContext *cx, JSObject *obj) -{ - JavaMethodOrFieldValue *member_val; - - member_val = JS_GetPrivate(cx, obj); - if (!member_val) - return; - - JS_RemoveRoot(cx, &member_val->method_val); - if (JSVAL_IS_GCTHING(member_val->field_val)) - JS_RemoveRoot(cx, &member_val->field_val); - JS_free(cx, member_val); -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaMember_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp) -{ - JavaMethodOrFieldValue *member_val; - - member_val = JS_GetPrivate(cx, obj); - if (!member_val) { - if (type == JSTYPE_OBJECT) { - *vp = OBJECT_TO_JSVAL(obj); - return JS_TRUE; - } - - JS_ReportError(cx, "illegal operation on JavaObject prototype object"); - return JS_FALSE; - } - - switch (type) { - case JSTYPE_VOID: - case JSTYPE_STRING: - case JSTYPE_NUMBER: - case JSTYPE_BOOLEAN: - case JSTYPE_OBJECT: - *vp = member_val->field_val; - return JS_TRUE; - - case JSTYPE_FUNCTION: - *vp = member_val->method_val; - return JS_TRUE; - - default: - JS_ASSERT(0); - return JS_FALSE; - } -} - -/* - * This function exists only to make JavaMember's Call'able. The way the JS - * engine is written now, it's never actually called because when a JavaMember - * is invoked, it's converted to a JS function via JavaMember_convert(). - */ -JS_STATIC_DLL_CALLBACK(JSBool) -JavaMember_Call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JS_ASSERT(0); - return JS_TRUE; -} - -JSClass JavaMember_class = { - "JavaMember", JSCLASS_HAS_PRIVATE, - JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, - JS_EnumerateStub, JS_ResolveStub, - JavaMember_convert, JavaMember_finalize, - - NULL, /* getObjectOps */ - NULL, /* checkAccess */ - JavaMember_Call, - NULL, /* construct */ - NULL, /* xdrObject */ - NULL, /* hasInstance */ - NULL, /* mark */ - 0, /* spare */ -}; - -JSBool -jsj_init_JavaMember(JSContext *cx, JSObject *global_obj) -{ - if (!JS_InitClass(cx, global_obj, - 0, &JavaMember_class, 0, 0, - 0, 0, - 0, 0)) - return JS_FALSE; - - return JS_TRUE; -} diff --git a/lib/javascript/liveconnect/jsj_JavaObject.c b/lib/javascript/liveconnect/jsj_JavaObject.c deleted file mode 100644 index 91209213..00000000 --- a/lib/javascript/liveconnect/jsj_JavaObject.c +++ /dev/null @@ -1,1096 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * This Original Code has been modified by IBM Corporation. Modifications made - * by IBM described herein are Copyright (c) International Business Machines - * Corporation, 2000. - * Modifications to Mozilla code or documentation identified per MPL Section 3.3 - * - * Date Modified by Description of modification - * 04/20/2000 IBM Corp. OS/2 VisualAge build. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * This file is part of the Java-vendor-neutral implementation of LiveConnect - * - * It contains the native code implementation of JS's JavaObject class. - * - * An instance of JavaObject is the JavaScript reflection of a Java object. - * - */ - -#include -#include - -#include "jsobj.h" -#include "jsj_private.h" /* LiveConnect internals */ -#include "jsj_hash.h" /* Hash table with Java object as key */ - -#ifdef JSJ_THREADSAFE -#include "prmon.h" -#endif - -/* - * This is a hash table that maps from Java objects to JS objects. - * It is used to ensure that the same JS object is obtained when a Java - * object is reflected more than once, so that JS object equality tests - * work in the expected manner, i.e. the "==" and "===" operators. - * - * The table entry keys are Java objects (of type jobject) and the entry values - * are JSObject pointers. Because the jobject type is an opaque handle and - * not necessarily a pointer, the hashing and key comparison functions must - * invoke the appropriate JVM functions. - * - * When the corresponding JS object instance is finalized, the entry is - * removed from the table, and a Java GC root for the Java object is removed. - */ -static JSJHashTable *java_obj_reflections = NULL; - -#ifdef JSJ_THREADSAFE -static PRMonitor *java_obj_reflections_monitor = NULL; -static int java_obj_reflections_mutation_count = 0; -#endif - -static JSBool installed_GC_callback = JS_FALSE; -static JSGCCallback old_GC_callback = NULL; -static JavaObjectWrapper* deferred_wrappers = NULL; - -static JSBool JS_DLL_CALLBACK jsj_GC_callback(JSContext *cx, JSGCStatus status) -{ - if (status == JSGC_END && deferred_wrappers) { - JNIEnv *jEnv; - JSJavaThreadState *jsj_env = jsj_EnterJava(cx, &jEnv); - if (jEnv) { - JavaObjectWrapper* java_wrapper = deferred_wrappers; - while (java_wrapper) { - deferred_wrappers = java_wrapper->u.next; - if (java_wrapper->java_obj) - (*jEnv)->DeleteGlobalRef(jEnv, java_wrapper->java_obj); - jsj_ReleaseJavaClassDescriptor(cx, jEnv, java_wrapper->class_descriptor); - JS_free(cx, java_wrapper); - java_wrapper = deferred_wrappers; - } - jsj_ExitJava(jsj_env); - } - } - /* always chain to old GC callback if non-null. */ - return old_GC_callback ? old_GC_callback(cx, status) : JS_TRUE; -} - -JSBool -jsj_InitJavaObjReflectionsTable(void) -{ - JS_ASSERT(!java_obj_reflections); - - java_obj_reflections = - JSJ_NewHashTable(512, jsj_HashJavaObject, jsj_JavaObjectComparator, - NULL, NULL, NULL); - if (!java_obj_reflections) - return JS_FALSE; - -#ifdef JSJ_THREADSAFE - java_obj_reflections_monitor = (struct PRMonitor *) PR_NewMonitor(); - if (!java_obj_reflections_monitor) { - JSJ_HashTableDestroy(java_obj_reflections); - return JS_FALSE; - } -#endif - - return JS_TRUE; -} - -JSObject * -jsj_WrapJavaObject(JSContext *cx, - JNIEnv *jEnv, - jobject java_obj, - jclass java_class) -{ - JSJHashNumber hash_code; - JSClass *js_class; - JSObject *js_wrapper_obj; - JavaObjectWrapper *java_wrapper; - JavaClassDescriptor *class_descriptor; - JSJHashEntry *he, **hep; - -#ifdef JSJ_THREADSAFE - int mutation_count; -#endif - - js_wrapper_obj = NULL; - - hash_code = jsj_HashJavaObject((void*)java_obj, (void*)jEnv); - -#ifdef JSJ_THREADSAFE - PR_EnterMonitor(java_obj_reflections_monitor); -#endif - - if (!installed_GC_callback) { - /* - * Hook into GC callback mechanism, so we can defer deleting global - * references until it's safe. - */ - old_GC_callback = JS_SetGCCallback(cx, jsj_GC_callback); - installed_GC_callback = JS_TRUE; - } - - hep = JSJ_HashTableRawLookup(java_obj_reflections, - hash_code, java_obj, (void*)jEnv); - he = *hep; - -#ifdef JSJ_THREADSAFE - /* Track mutations to hash table */ - mutation_count = java_obj_reflections_mutation_count; - - /* We must temporarily release this monitor so as to avoid - deadlocks with the JS GC. See Bugsplat #354852 */ - PR_ExitMonitor(java_obj_reflections_monitor); -#endif - - if (he) { - js_wrapper_obj = (JSObject *)he->value; - if (js_wrapper_obj) - return js_wrapper_obj; - } - - /* No existing reflection found. Construct a new one */ - class_descriptor = jsj_GetJavaClassDescriptor(cx, jEnv, java_class); - if (!class_descriptor) - return NULL; - if (class_descriptor->type == JAVA_SIGNATURE_ARRAY) { - js_class = &JavaArray_class; - } else { - JS_ASSERT(IS_OBJECT_TYPE(class_descriptor->type)); - js_class = &JavaObject_class; - } - - /* Create new JS object to reflect Java object */ - js_wrapper_obj = JS_NewObject(cx, js_class, NULL, NULL); - if (!js_wrapper_obj) - return NULL; - - /* Create private, native portion of JavaObject */ - java_wrapper = - (JavaObjectWrapper *)JS_malloc(cx, sizeof(JavaObjectWrapper)); - if (!java_wrapper) { - jsj_ReleaseJavaClassDescriptor(cx, jEnv, class_descriptor); - return NULL; - } - JS_SetPrivate(cx, js_wrapper_obj, java_wrapper); - java_wrapper->class_descriptor = class_descriptor; - java_wrapper->java_obj = NULL; - -#ifdef JSJ_THREADSAFE - PR_EnterMonitor(java_obj_reflections_monitor); - - /* We may need to do the hash table lookup again, since some other - thread may have updated it while the lock wasn't being held. */ - if (mutation_count != java_obj_reflections_mutation_count) { - hep = JSJ_HashTableRawLookup(java_obj_reflections, - hash_code, java_obj, (void*)jEnv); - he = *hep; - if (he) { - js_wrapper_obj = (JSObject *)he->value; - if (js_wrapper_obj) { - PR_ExitMonitor(java_obj_reflections_monitor); - return js_wrapper_obj; - } - } - } - - java_obj_reflections_mutation_count++; - -#endif - - java_obj = (*jEnv)->NewGlobalRef(jEnv, java_obj); - java_wrapper->java_obj = java_obj; - if (!java_obj) - goto out_of_memory; - - /* cache the hash code for all time. */ - java_wrapper->u.hash_code = hash_code; - - /* Add the JavaObject to the hash table */ - he = JSJ_HashTableRawAdd(java_obj_reflections, hep, hash_code, - java_obj, js_wrapper_obj, (void*)jEnv); -#ifdef JSJ_THREADSAFE - PR_ExitMonitor(java_obj_reflections_monitor); -#endif - - if (!he) { - (*jEnv)->DeleteGlobalRef(jEnv, java_obj); - goto out_of_memory; - } - - return js_wrapper_obj; - -out_of_memory: - /* No need to free js_wrapper_obj, as it will be finalized by GC. */ - JS_ReportOutOfMemory(cx); - return NULL; -} - -static void -remove_java_obj_reflection_from_hashtable(jobject java_obj, JSJHashNumber hash_code) -{ - JSJHashEntry *he, **hep; - -#ifdef JSJ_THREADSAFE - PR_EnterMonitor(java_obj_reflections_monitor); -#endif - - hep = JSJ_HashTableRawLookup(java_obj_reflections, hash_code, - java_obj, NULL); - he = *hep; - - JS_ASSERT(he); - if (he) - JSJ_HashTableRawRemove(java_obj_reflections, hep, he, NULL); - -#ifdef JSJ_THREADSAFE - java_obj_reflections_mutation_count++; - - PR_ExitMonitor(java_obj_reflections_monitor); -#endif -} - -JS_EXPORT_API(void) -JavaObject_finalize(JSContext *cx, JSObject *obj) -{ - JavaObjectWrapper *java_wrapper; - jobject java_obj; - JNIEnv *jEnv; - JSJavaThreadState *jsj_env; - - java_wrapper = JS_GetPrivate(cx, obj); - if (!java_wrapper) - return; - java_obj = java_wrapper->java_obj; - - if (java_obj) { - remove_java_obj_reflection_from_hashtable(java_obj, java_wrapper->u.hash_code); - /* defer releasing global refs until it is safe to do so. */ - java_wrapper->u.next = deferred_wrappers; - deferred_wrappers = java_wrapper; - } else { - jsj_env = jsj_EnterJava(cx, &jEnv); - if (jEnv) { - jsj_ReleaseJavaClassDescriptor(cx, jEnv, java_wrapper->class_descriptor); - JS_free(cx, java_wrapper); - jsj_ExitJava(jsj_env); - } else { - java_wrapper->u.next = deferred_wrappers; - deferred_wrappers = java_wrapper; - } - } -} - -/* Trivial helper for jsj_DiscardJavaObjReflections(), below */ -static JSIntn -enumerate_remove_java_obj(JSJHashEntry *he, JSIntn i, void *arg) -{ - JSJavaThreadState *jsj_env = (JSJavaThreadState *)arg; - JNIEnv *jEnv = jsj_env->jEnv; - jobject java_obj; - JavaObjectWrapper *java_wrapper; - JSObject *java_wrapper_obj; - - java_wrapper_obj = (JSObject *)he->value; - - /* Warning: NULL argument may cause assertion in JS engine, but it's actually OK */ - java_wrapper = JS_GetPrivate(jsj_env->cx, java_wrapper_obj); - java_obj = java_wrapper->java_obj; - (*jEnv)->DeleteGlobalRef(jEnv, java_obj); - java_wrapper->java_obj = NULL; - return HT_ENUMERATE_REMOVE; -} - -/* This shutdown routine discards all JNI references to Java objects - that have been reflected into JS, even if there are still references - to them from JS. */ -void -jsj_DiscardJavaObjReflections(JNIEnv *jEnv) -{ - JSJavaThreadState *jsj_env; - char *err_msg; - - /* Get the per-thread state corresponding to the current Java thread */ - jsj_env = jsj_MapJavaThreadToJSJavaThreadState(jEnv, &err_msg); - JS_ASSERT(jsj_env); - if (!jsj_env) - return; - - if (java_obj_reflections) { - JSJ_HashTableEnumerateEntries(java_obj_reflections, - enumerate_remove_java_obj, - (void*)jsj_env); - JSJ_HashTableDestroy(java_obj_reflections); - java_obj_reflections = NULL; - } -} - -JSBool JS_DLL_CALLBACK -JavaObject_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp) -{ - JavaObjectWrapper *java_wrapper; - JavaClassDescriptor *class_descriptor; - jobject java_obj; - JNIEnv *jEnv; - JSJavaThreadState *jsj_env; - JSBool result; - - java_wrapper = JS_GetPrivate(cx, obj); - if (!java_wrapper) { - if (type == JSTYPE_OBJECT) { - *vp = OBJECT_TO_JSVAL(obj); - return JS_TRUE; - } - - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_BAD_OP_JOBJECT); - return JS_FALSE; - } - - java_obj = java_wrapper->java_obj; - class_descriptor = java_wrapper->class_descriptor; - - switch (type) { - case JSTYPE_OBJECT: - *vp = OBJECT_TO_JSVAL(obj); - return JS_TRUE; - - case JSTYPE_FUNCTION: - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_CONVERT_TO_FUNC); - return JS_FALSE; - - case JSTYPE_VOID: - case JSTYPE_STRING: - /* Get the Java per-thread environment pointer for this JSContext */ - jsj_env = jsj_EnterJava(cx, &jEnv); - if (!jEnv) - return JS_FALSE; - - /* Either extract a C-string from the java.lang.String object - or call the Java toString() method */ - result = jsj_ConvertJavaObjectToJSString(cx, jEnv, class_descriptor, java_obj, vp); - jsj_ExitJava(jsj_env); - return result; - - case JSTYPE_NUMBER: - /* Get the Java per-thread environment pointer for this JSContext */ - jsj_env = jsj_EnterJava(cx, &jEnv); - if (!jEnv) - return JS_FALSE; - - /* Call Java doubleValue() method, if applicable */ - result = jsj_ConvertJavaObjectToJSNumber(cx, jEnv, class_descriptor, java_obj, vp); - jsj_ExitJava(jsj_env); - return result; - - case JSTYPE_BOOLEAN: - /* Get the Java per-thread environment pointer for this JSContext */ - jsj_env = jsj_EnterJava(cx, &jEnv); - if (!jEnv) - return JS_FALSE; - - /* Call booleanValue() method, if applicable */ - result = jsj_ConvertJavaObjectToJSBoolean(cx, jEnv, class_descriptor, java_obj, vp); - jsj_ExitJava(jsj_env); - return result; - - default: - JS_ASSERT(0); - return JS_FALSE; - } -} - -/* - * Get a property from the prototype object of a native ECMA object, i.e. - * return .prototype. - * This is used to allow Java objects to inherit methods from Array.prototype - * and String.prototype. - */ -static JSBool -inherit_props_from_JS_natives(JSContext *cx, const char *js_constructor_name, - const char *member_name, jsval *vp) -{ - JSObject *global_obj, *constructor_obj, *prototype_obj; - jsval constructor_val, prototype_val; - - global_obj = JS_GetGlobalObject(cx); - JS_ASSERT(global_obj); - if (!global_obj) - return JS_FALSE; - - JS_GetProperty(cx, global_obj, js_constructor_name, &constructor_val); - JS_ASSERT(JSVAL_IS_OBJECT(constructor_val)); - constructor_obj = JSVAL_TO_OBJECT(constructor_val); - - JS_GetProperty(cx, constructor_obj, "prototype", &prototype_val); - JS_ASSERT(JSVAL_IS_OBJECT(prototype_val)); - prototype_obj = JSVAL_TO_OBJECT(prototype_val); - - return JS_GetProperty(cx, prototype_obj, member_name, vp) && *vp != JSVAL_VOID; -} - -struct JSJPropertyInfo { - JSBool wantProp; /* input param tells whether prop is returned */ - const char* name; /* output param, name of property (XXX ASCII) */ - uintN attributes; /* output param, attributes of property */ - JSProperty *prop; /* output param, if wantProp, held pointer that - must be released via OBJ_DROP_PROPERTY */ -}; -typedef struct JSJPropertyInfo JSJPropertyInfo; - -static JSBool -lookup_member_by_id(JSContext *cx, JNIEnv *jEnv, JSObject *obj, - JavaObjectWrapper **java_wrapperp, jsid id, - JavaMemberDescriptor **member_descriptorp, - jsval *vp, JSObject **proto_chainp, - JSJPropertyInfo *prop_infop) -{ - jsval idval; - JavaObjectWrapper *java_wrapper; - JavaMemberDescriptor *member_descriptor; - const char *member_name; - JavaClassDescriptor *class_descriptor; - JSObject *proto_chain; - JSBool found_in_proto; - - found_in_proto = JS_FALSE; - member_descriptor = NULL; - java_wrapper = JS_GetPrivate(cx, obj); - - /* Handle accesses to prototype object */ - if (!java_wrapper) { - if (JS_IdToValue(cx, id, &idval) && JSVAL_IS_STRING(idval) && - (member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval))) != NULL) { - if (!strcmp(member_name, "constructor")) - goto done; - } - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, JSJMSG_BAD_OP_JOBJECT); - return JS_FALSE; - } - - class_descriptor = java_wrapper->class_descriptor; - JS_ASSERT(IS_REFERENCE_TYPE(class_descriptor->type)); - - member_descriptor = jsj_LookupJavaMemberDescriptorById(cx, jEnv, class_descriptor, id); - if (member_descriptor) - goto done; - - /* Instances can reference static methods and fields */ - member_descriptor = jsj_LookupJavaStaticMemberDescriptorById(cx, jEnv, class_descriptor, id); - if (member_descriptor) - goto done; - - /* Ensure that the property we're searching for is string-valued. */ - JS_IdToValue(cx, id, &idval); - if (!JSVAL_IS_STRING(idval)) { - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, JSJMSG_BAD_JOBJECT_EXPR); - return JS_FALSE; - } - member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval)); - - /* - * A little LC3 feature magic: - * + Instances of java.lang.String "inherit" the standard ECMA string methods - * of String.prototype. All of the ECMA string methods convert the Java - * string to a JS string before performing the string operation. For example, - * s = new java.lang.String("foobar"); - * return s.slice(2); - * + Similarly, instances of Java arrays "inherit" the standard ECMA array - * methods of Array.prototype. (Not all of these methods work properly - * on JavaArray objects, however, since the 'length' property is read-only.) - */ - if (vp) { - if ((class_descriptor->type == JAVA_SIGNATURE_JAVA_LANG_STRING) && - inherit_props_from_JS_natives(cx, "String", member_name, vp)) - goto done; - if ((class_descriptor->type == JAVA_SIGNATURE_ARRAY) && - inherit_props_from_JS_natives(cx, "Array", member_name, vp)) - goto done; - } - - /* Check for access to magic prototype chain property */ - if (!strcmp(member_name, "__proto__")) { - proto_chain = JS_GetPrototype(cx, obj); - if (vp) - *vp = OBJECT_TO_JSVAL(proto_chain); - goto done; - } - - /* - * See if the property looks like the explicit resolution of an - * overloaded method, e.g. "max(double,double)", first as an instance method, - * then as a static method. If we find such a method, it will be cached - * so future accesses won't run this code. - */ - member_descriptor = jsj_ResolveExplicitMethod(cx, jEnv, class_descriptor, id, JS_FALSE); - if (member_descriptor) - goto done; - member_descriptor = jsj_ResolveExplicitMethod(cx, jEnv, class_descriptor, id, JS_TRUE); - if (member_descriptor) - goto done; - - /* Is the property defined in the prototype chain? */ - if (proto_chainp && prop_infop) { - /* If so, follow __proto__ link to search prototype chain */ - proto_chain = JS_GetPrototype(cx, obj); - - /* Use OBJ_LOOKUP_PROPERTY to determine if and where the property - actually exists in the prototype chain. */ - if (proto_chain) { - if (!OBJ_LOOKUP_PROPERTY(cx, proto_chain, id, proto_chainp, - &prop_infop->prop)) { - return JS_FALSE; - } - if (prop_infop->prop) { - if (!OBJ_GET_ATTRIBUTES(cx, *proto_chainp, id, prop_infop->prop, - &prop_infop->attributes)) { - OBJ_DROP_PROPERTY(cx, *proto_chainp, prop_infop->prop); - return JS_FALSE; - } - if (!prop_infop->wantProp) { - OBJ_DROP_PROPERTY(cx, *proto_chainp, prop_infop->prop); - prop_infop->prop = NULL; - } - prop_infop->name = member_name; - found_in_proto = JS_TRUE; - goto done; - } - } - } - - /* Report lack of Java member with the given property name */ - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, JSJMSG_NO_INSTANCE_NAME, - class_descriptor->name, member_name); - return JS_FALSE; - -done: - /* Success. Handle the multiple return values */ - if (java_wrapperp) - *java_wrapperp = java_wrapper; - if (member_descriptorp) - *member_descriptorp = member_descriptor; - if (proto_chainp && !found_in_proto) - *proto_chainp = NULL; - return JS_TRUE; -} - -JS_EXPORT_API(JSBool) -JavaObject_getPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp) -{ - jobject java_obj; - JavaMemberDescriptor *member_descriptor; - JavaObjectWrapper *java_wrapper; - JNIEnv *jEnv; - JSObject *funobj; - jsval field_val, method_val; - JSBool success; - JSJavaThreadState *jsj_env; - JSObject *proto_chain; - JSJPropertyInfo prop_info; - - /* printf("In JavaObject_getProperty\n"); */ - - /* Get the Java per-thread environment pointer for this JSContext */ - jsj_env = jsj_EnterJava(cx, &jEnv); - if (!jEnv) - return JS_FALSE; - - if (vp) - *vp = JSVAL_VOID; - prop_info.wantProp = JS_FALSE; - if (!lookup_member_by_id(cx, jEnv, obj, &java_wrapper, id, &member_descriptor, vp, - &proto_chain, &prop_info)) { - jsj_ExitJava(jsj_env); - return JS_FALSE; - } - - /* Handle access to special, non-Java properties of JavaObjects, e.g. the - "constructor" property of the prototype object */ - if (!member_descriptor) { - jsj_ExitJava(jsj_env); - if (proto_chain) - return JS_GetProperty(cx, proto_chain, prop_info.name, vp); - return JS_TRUE; - } - - java_obj = java_wrapper->java_obj; - field_val = method_val = JSVAL_VOID; - - if (jaApplet && (*jEnv)->IsInstanceOf(jEnv, java_obj, jaApplet)) { - jsj_JSIsCallingApplet = JS_TRUE; - } - - /* If a field member, get the value of the field */ - if (member_descriptor->field) { - success = jsj_GetJavaFieldValue(cx, jEnv, member_descriptor->field, java_obj, &field_val); - if (!success) { - jsj_ExitJava(jsj_env); - return JS_FALSE; - } - } - - /* If a method member, build a wrapper around the Java method */ - if (member_descriptor->methods) { - /* Create a function object with this JavaObject as its parent, so that - JSFUN_BOUND_METHOD binds it as the default 'this' for the function. */ - funobj = JS_CloneFunctionObject(cx, member_descriptor->invoke_func_obj, obj); - if (!funobj) { - jsj_ExitJava(jsj_env); - return JS_FALSE; - } - method_val = OBJECT_TO_JSVAL(funobj); - } - -#if TEST_JAVAMEMBER - /* Always create a JavaMember object, even though it's inefficient */ - obj = jsj_CreateJavaMember(cx, method_val, field_val); - if (!obj) { - jsj_ExitJava(jsj_env); - return JS_FALSE; - } - *vp = OBJECT_TO_JSVAL(obj); -#else /* !TEST_JAVAMEMBER */ - - if (member_descriptor->field) { - if (!member_descriptor->methods) { - /* Return value of Java field */ - *vp = field_val; - } else { - /* Handle special case of access to a property that could refer - to either a Java field or a method that share the same name. - In Java, such ambiguity is not possible because the compiler - can statically determine which is being accessed. */ - obj = jsj_CreateJavaMember(cx, method_val, field_val); - if (!obj) { - jsj_ExitJava(jsj_env); - return JS_FALSE; - } - *vp = OBJECT_TO_JSVAL(obj); - } - - } else { - /* Return wrapper around Java method */ - *vp = method_val; - } - -#endif /* !TEST_JAVAMEMBER */ - - jsj_ExitJava(jsj_env); - return JS_TRUE; -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaObject_setPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp) -{ - jobject java_obj; - const char *member_name; - JavaObjectWrapper *java_wrapper; - JavaClassDescriptor *class_descriptor; - JavaMemberDescriptor *member_descriptor; - jsval idval; - JNIEnv *jEnv; - JSJavaThreadState *jsj_env; - JSObject *proto_chain; - JSJPropertyInfo prop_info; - JSBool result; - - /* printf("In JavaObject_setProperty\n"); */ - - /* Get the Java per-thread environment pointer for this JSContext */ - jsj_env = jsj_EnterJava(cx, &jEnv); - if (!jEnv) - return JS_FALSE; - - prop_info.wantProp = JS_FALSE; - if (!lookup_member_by_id(cx, jEnv, obj, &java_wrapper, id, &member_descriptor, NULL, - &proto_chain, &prop_info)) { - jsj_ExitJava(jsj_env); - return JS_FALSE; - } - - /* Could be assignment to magic JS __proto__ property rather than a Java field */ - if (!member_descriptor) { - if (proto_chain && (prop_info.attributes & JSPROP_SHARED)) { - JS_SetProperty(cx, proto_chain, prop_info.name, vp); - } else { - JS_IdToValue(cx, id, &idval); - if (!JSVAL_IS_STRING(idval)) - goto no_such_field; - member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval)); - if (strcmp(member_name, "__proto__")) - goto no_such_field; - if (!JSVAL_IS_OBJECT(*vp)) { - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_BAD_PROTO_ASSIGNMENT); - jsj_ExitJava(jsj_env); - return JS_FALSE; - } - JS_SetPrototype(cx, obj, JSVAL_TO_OBJECT(*vp)); - } - jsj_ExitJava(jsj_env); - return JS_TRUE; - } - - /* Check for the case where there is a method with the given name, but no field - with that name */ - if (!member_descriptor->field) - goto no_such_field; - - /* Silently fail if field value is final (immutable), as required by ECMA spec */ - if (member_descriptor->field->modifiers & ACC_FINAL) { - jsj_ExitJava(jsj_env); - return JS_TRUE; - } - - java_obj = java_wrapper->java_obj; - - if (jaApplet && (*jEnv)->IsInstanceOf(jEnv, java_obj, jaApplet)) { - jsj_JSIsCallingApplet = JS_TRUE; - } - - result = jsj_SetJavaFieldValue(cx, jEnv, member_descriptor->field, java_obj, *vp); - jsj_ExitJava(jsj_env); - return result; - -no_such_field: - JS_IdToValue(cx, id, &idval); - member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval)); - class_descriptor = java_wrapper->class_descriptor; - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_NO_NAME_IN_CLASS, - member_name, class_descriptor->name); - jsj_ExitJava(jsj_env); - return JS_FALSE; -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaObject_lookupProperty(JSContext *cx, JSObject *obj, jsid id, - JSObject **objp, JSProperty **propp) -{ - JNIEnv *jEnv; - JSErrorReporter old_reporter; - jsval dummy_val; - JSObject *proto_chain; - JSJPropertyInfo prop_info; - JSJavaThreadState *jsj_env; - - /* printf("In JavaObject_lookupProperty()\n"); */ - - /* Get the Java per-thread environment pointer for this JSContext */ - jsj_env = jsj_EnterJava(cx, &jEnv); - if (!jEnv) - return JS_FALSE; - - old_reporter = JS_SetErrorReporter(cx, NULL); - prop_info.wantProp = JS_TRUE; - if (lookup_member_by_id(cx, jEnv, obj, NULL, id, NULL, &dummy_val, - &proto_chain, &prop_info)) { - /* signify that the property is in the prototype chain or the object itself. */ - if (proto_chain) { - *objp = proto_chain; - *propp = prop_info.prop; - } else { - *objp = obj; - *propp = (JSProperty*)1; - } - } else { - *objp = NULL; - *propp = NULL; - } - - JS_SetErrorReporter(cx, old_reporter); - jsj_ExitJava(jsj_env); - return JS_TRUE; -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaObject_defineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value, - JSPropertyOp getter, JSPropertyOp setter, - uintN attrs, JSProperty **propp) -{ - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_JOBJECT_PROP_DEFINE); - return JS_FALSE; -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaObject_getAttributes(JSContext *cx, JSObject *obj, jsid id, - JSProperty *prop, uintN *attrsp) -{ - /* We don't maintain JS property attributes for Java class members */ - *attrsp = JSPROP_PERMANENT|JSPROP_ENUMERATE; - return JS_TRUE; -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaObject_setAttributes(JSContext *cx, JSObject *obj, jsid id, - JSProperty *prop, uintN *attrsp) -{ - /* We don't maintain JS property attributes for Java class members */ - if (*attrsp != (JSPROP_PERMANENT|JSPROP_ENUMERATE)) { - JS_ASSERT(0); - return JS_FALSE; - } - - /* Silently ignore all setAttribute attempts */ - return JS_TRUE; -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaObject_deleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp) -{ - JSVersion version = JS_GetVersion(cx); - - *vp = JSVAL_FALSE; - - if (!JSVERSION_IS_ECMA(version)) { - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_JOBJECT_PROP_DELETE); - return JS_FALSE; - } else { - /* Attempts to delete permanent properties are silently ignored - by ECMAScript. */ - return JS_TRUE; - } -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaObject_defaultValue(JSContext *cx, JSObject *obj, JSType type, jsval *vp) -{ - /* printf("In JavaObject_defaultValue()\n"); */ - return JavaObject_convert(cx, obj, type, vp); -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaObject_newEnumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, - jsval *statep, jsid *idp) -{ - JavaObjectWrapper *java_wrapper; - JavaMemberDescriptor *member_descriptor; - JavaClassDescriptor *class_descriptor; - JNIEnv *jEnv; - JSJavaThreadState *jsj_env; - - java_wrapper = JS_GetPrivate(cx, obj); - /* Check for prototype object */ - if (!java_wrapper) { - *statep = JSVAL_NULL; - if (idp) - *idp = INT_TO_JSVAL(0); - return JS_TRUE; - } - - class_descriptor = java_wrapper->class_descriptor; - - switch(enum_op) { - case JSENUMERATE_INIT: - - /* Get the Java per-thread environment pointer for this JSContext */ - jsj_env = jsj_EnterJava(cx, &jEnv); - if (!jEnv) - return JS_FALSE; - - member_descriptor = jsj_GetClassInstanceMembers(cx, jEnv, class_descriptor); - *statep = PRIVATE_TO_JSVAL(member_descriptor); - if (idp) - *idp = INT_TO_JSVAL(class_descriptor->num_instance_members); - jsj_ExitJava(jsj_env); - return JS_TRUE; - - case JSENUMERATE_NEXT: - member_descriptor = JSVAL_TO_PRIVATE(*statep); - if (member_descriptor) { - - /* Don't enumerate explicit-signature methods, i.e. enumerate toValue, - but not toValue(int), toValue(double), etc. */ - while (member_descriptor->methods && member_descriptor->methods->is_alias) { - member_descriptor = member_descriptor->next; - if (!member_descriptor) { - *statep = JSVAL_NULL; - return JS_TRUE; - } - } - - *idp = member_descriptor->id; - *statep = PRIVATE_TO_JSVAL(member_descriptor->next); - return JS_TRUE; - } - - /* Fall through ... */ - - case JSENUMERATE_DESTROY: - *statep = JSVAL_NULL; - return JS_TRUE; - - default: - JS_ASSERT(0); - return JS_FALSE; - } -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaObject_checkAccess(JSContext *cx, JSObject *obj, jsid id, - JSAccessMode mode, jsval *vp, uintN *attrsp) -{ - switch (mode) { - case JSACC_WATCH: - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_JOBJECT_PROP_WATCH); - return JS_FALSE; - - case JSACC_IMPORT: - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_JOBJECT_PROP_EXPORT); - return JS_FALSE; - - default: - return JS_TRUE; - } -} - -#define JSJ_SLOT_COUNT (JSSLOT_PRIVATE+1) - -JSObjectMap * JS_DLL_CALLBACK -jsj_wrapper_newObjectMap(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops, - JSClass *clasp, JSObject *obj) -{ - JSObjectMap * map; - - map = (JSObjectMap *) JS_malloc(cx, sizeof(JSObjectMap)); - if (map) { - map->nrefs = nrefs; - map->ops = ops; - map->nslots = JSJ_SLOT_COUNT; - map->freeslot = JSJ_SLOT_COUNT; - } - return map; -} - -void JS_DLL_CALLBACK -jsj_wrapper_destroyObjectMap(JSContext *cx, JSObjectMap *map) -{ - JS_free(cx, map); -} - -jsval JS_DLL_CALLBACK -jsj_wrapper_getRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot) -{ - JS_ASSERT(slot < JSJ_SLOT_COUNT); - JS_ASSERT(obj->slots); - JS_ASSERT(obj->map->nslots == JSJ_SLOT_COUNT); - JS_ASSERT(obj->map->freeslot == JSJ_SLOT_COUNT); - return obj->slots[slot]; -} - -JSBool JS_DLL_CALLBACK -jsj_wrapper_setRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot, jsval v) -{ - JS_ASSERT(slot < JSJ_SLOT_COUNT); - JS_ASSERT(obj->slots); - JS_ASSERT(obj->map->nslots == JSJ_SLOT_COUNT); - JS_ASSERT(obj->map->freeslot == JSJ_SLOT_COUNT); - obj->slots[slot] = v; - return JS_TRUE; -} - -JSObjectOps JavaObject_ops = { - /* Mandatory non-null function pointer members. */ - jsj_wrapper_newObjectMap, /* newObjectMap */ - jsj_wrapper_destroyObjectMap, /* destroyObjectMap */ - JavaObject_lookupProperty, - JavaObject_defineProperty, - JavaObject_getPropertyById, /* getProperty */ - JavaObject_setPropertyById, /* setProperty */ - JavaObject_getAttributes, - JavaObject_setAttributes, - JavaObject_deleteProperty, - JavaObject_defaultValue, - JavaObject_newEnumerate, - JavaObject_checkAccess, - - /* Optionally non-null members start here. */ - NULL, /* thisObject */ - NULL, /* dropProperty */ - NULL, /* call */ - NULL, /* construct */ - NULL, /* xdrObject */ - NULL, /* hasInstance */ - NULL, /* setProto */ - NULL, /* setParent */ - NULL, /* mark */ - NULL, /* clear */ - jsj_wrapper_getRequiredSlot, /* getRequiredSlot */ - jsj_wrapper_setRequiredSlot /* setRequiredSlot */ -}; - -JS_STATIC_DLL_CALLBACK(JSObjectOps *) -JavaObject_getObjectOps(JSContext *cx, JSClass *clazz) -{ - return &JavaObject_ops; -} - -JSClass JavaObject_class = { - "JavaObject", JSCLASS_HAS_PRIVATE, - NULL, NULL, NULL, NULL, - NULL, NULL, JavaObject_convert, JavaObject_finalize, - - /* Optionally non-null members start here. */ - JavaObject_getObjectOps, - NULL, /* checkAccess */ - NULL, /* call */ - NULL, /* construct */ - NULL, /* xdrObject */ - NULL, /* hasInstance */ - NULL, /* mark */ - 0, /* spare */ -}; - -extern JS_IMPORT_DATA(JSObjectOps) js_ObjectOps; - -JSBool -jsj_init_JavaObject(JSContext *cx, JSObject *global_obj) -{ - return JS_InitClass(cx, global_obj, - 0, &JavaObject_class, 0, 0, - 0, 0, - 0, 0) != 0; -} diff --git a/lib/javascript/liveconnect/jsj_JavaPackage.c b/lib/javascript/liveconnect/jsj_JavaPackage.c deleted file mode 100644 index 25f30df6..00000000 --- a/lib/javascript/liveconnect/jsj_JavaPackage.c +++ /dev/null @@ -1,548 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* This file is part of the Java-vendor-neutral implementation of LiveConnect - * - * It contains the native code implementation of the JavaPackage class. - * - * A JavaPackage is JavaScript's representation of a Java package. The - * JavaPackage object contains only a string, which is the path to the package, - * e.g. "java/lang". The JS properties of a JavaPackage are either nested packages - * or a JavaClass object, which represents the path to a Java class. - * - * Note that there is no equivalent to a JavaPackage object in Java. Example: - * Although there are instances of java.lang.String and there are static methods - * of java.lang.String that can be invoked, there's no such thing as a java.lang - * object in Java that exists at run time. - * - */ - -#include -#include - -#include "jsj_private.h" /* LiveConnect internals */ -#include "jsjava.h" - - -JSClass JavaPackage_class; /* Forward declaration */ - -/* - * The native part of a JavaPackage object. It gets stored in the object's - * private slot. - */ -typedef struct { - const char * path; /* e.g. "java/lang" or NULL if top level package */ - int flags; /* e.g. PKG_SYSTEM, PKG_CLASS */ -} JavaPackage_Private; - -static JSObject * -define_JavaPackage(JSContext *cx, JSObject *parent_obj, - const char *obj_name, const char *path, int flags, int access) -{ - JSObject *package_obj; - JavaPackage_Private *package; - - package_obj = JS_DefineObject(cx, parent_obj, obj_name, &JavaPackage_class, 0, JSPROP_PERMANENT | access); - - if (!package_obj) - return NULL; - - /* Attach private, native data to the JS object */ - package = (JavaPackage_Private *)JS_malloc(cx, sizeof(JavaPackage_Private)); - JS_SetPrivate(cx, package_obj, (void *)package); - if (path) - package->path = JS_strdup(cx, path); - else - package->path = ""; - - package->flags = flags; - - /* Check for OOM */ - if (!package->path) { - JS_DeleteProperty(cx, parent_obj, obj_name); - JS_free(cx, package); - return NULL; - } - - return package_obj; -} - -/* JavaPackage uses standard JS getProperty */ - -/* - * Don't allow user-defined properties to be set on Java package objects, e.g. - * it is illegal to write "java.lang.myProperty = 4". We probably could relax - * this restriction, but it's potentially confusing and not clearly useful. - */ -JS_STATIC_DLL_CALLBACK(JSBool) -JavaPackage_setProperty(JSContext *cx, JSObject *obj, jsval slot, jsval *vp) -{ - JavaPackage_Private *package = JS_GetPrivate(cx, obj); - if (!package) { - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_BAD_ADD_TO_PACKAGE); - return JS_FALSE; - } - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_DONT_ADD_TO_PACKAGE); - return JS_FALSE; -} - -static JSBool quiet_resolve_failure; - -/* - * Resolve a component name to be either the name of a class or a package. - */ -JS_STATIC_DLL_CALLBACK(JSBool) -JavaPackage_resolve(JSContext *cx, JSObject *obj, jsval id) -{ - JavaPackage_Private *package; - JSBool ok = JS_TRUE; - jclass jclazz; - char *subPath, *newPath; - const char *path; - JNIEnv *jEnv; - JSJavaThreadState *jsj_env; - - /* Painful hack for pre_define_java_packages() */ - if (quiet_resolve_failure) - return JS_FALSE; - - package = (JavaPackage_Private *)JS_GetPrivate(cx, obj); - if (!package) - return JS_TRUE; - - if (!JSVAL_IS_STRING(id)) - return JS_TRUE; - subPath = JS_GetStringBytes(JSVAL_TO_STRING(id)); - - /* - * There will be an attempt to invoke the toString() method when producing - * the string representation of a JavaPackage. When this occurs, avoid - * creating a bogus toString package. (This means that no one can ever - * create a package with the simple name "toString", but we'll live with - * that limitation.) - */ - if (!strcmp(subPath, "toString")) - return JS_FALSE; - - path = package->path; - newPath = JS_smprintf("%s%s%s", path, (path[0] ? "/" : ""), subPath); - if (!newPath) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - - jsj_env = jsj_EnterJava(cx, &jEnv); - if (!jEnv) { - ok = JS_FALSE; - goto out; - } - - /* - Unfortunately, Java provides no way to find out whether a particular - name is a package or not. The only way to tell is to try to load the - name as a class file and, if that fails, assume it's a package. This - makes things work as expected for the most part, but it has three - noticeable problems that keep coming up: - - - You can refer to a package like java.lang.i.buried.paul without - generating a complaint. Of course, you'll never be able to refer to - any classes through it. - - - An annoying consequence of the above is that misspelling a class name - results in a cryptic error about packages. - - - In a browser context, i.e. where applets are involved, figuring out - whether something is a class may require looking for it over the net - using the current classloader. This means that the first time you - refer to java.lang.System in a js context, there will be an attempt - to search for [[DOCBASE]]/java.class on the server. - - A solution is to explicitly tell jsjava the names of all the (local) - packages on the CLASSPATH. (Not implemented yet.) - - */ - jclazz = (*jEnv)->FindClass(jEnv, newPath); - if (jclazz) { - JSObject *newClass; - - newClass = jsj_define_JavaClass(cx, jEnv, obj, subPath, jclazz); - (*jEnv)->DeleteLocalRef(jEnv, jclazz); - if (!newClass) { - ok = JS_FALSE; - goto out; - } - } else { - - /* We assume that any failed attempt to load a class is because it - doesn't exist. If we wanted to do a better job, we would check - the exception type and make sure that it's NoClassDefFoundError */ - (*jEnv)->ExceptionClear(jEnv); - - /* - * If there's no class of the given name, then we must be referring to - * a package. However, don't allow bogus sub-packages of pre-defined - * system packages to be created. - */ - if (JS_InstanceOf(cx, obj, &JavaPackage_class, NULL)) { - JavaPackage_Private *current_package; - - current_package = JS_GetPrivate(cx, obj); - if (current_package->flags & PKG_SYSTEM) { - char *msg, *cp; - msg = JS_strdup(cx, newPath); - - /* Check for OOM */ - if (msg) { - /* Convert package of form "java/lang" to "java.lang" */ - for (cp = msg; *cp != '\0'; cp++) - if (*cp == '/') - *cp = '.'; - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_MISSING_PACKAGE, msg); - free((char*)msg); - } - - ok = JS_FALSE; - goto out; - } - } - - if (!define_JavaPackage(cx, obj, subPath, newPath, 0, JSPROP_READONLY)) { - ok = JS_FALSE; - goto out; - } - -#ifdef DEBUG - /* printf("JavaPackage \'%s\' created\n", newPath); */ -#endif - - } - -out: - free(newPath); - jsj_ExitJava(jsj_env); - return ok; -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaPackage_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp) -{ - JSString *str; - char *name, *cp; - - JavaPackage_Private *package = JS_GetPrivate(cx, obj); - if (!package) { - fprintf(stderr, "JavaPackage_resolve: no private data!\n"); - return JS_FALSE; - } - - switch (type) { - - /* Pretty-printing of JavaPackage */ - case JSTYPE_VOID: /* Default value */ - case JSTYPE_NUMBER: - case JSTYPE_STRING: - /* Convert '/' to '.' so that it looks like Java language syntax. */ - if (!package->path) - break; - name = JS_smprintf("[JavaPackage %s]", package->path); - if (!name) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - for (cp = name; *cp != '\0'; cp++) - if (*cp == '/') - *cp = '.'; - str = JS_NewString(cx, name, strlen(name)); - if (!str) { - free(name); - /* It's not necessary to call JS_ReportOutOfMemory(), as - JS_NewString() will do so on failure. */ - return JS_FALSE; - } - - *vp = STRING_TO_JSVAL(str); - break; - - case JSTYPE_OBJECT: - *vp = OBJECT_TO_JSVAL(obj); - break; - - default: - break; - } - return JS_TRUE; -} - -/* - * Free the private native data associated with the JavaPackage object. - */ -JS_STATIC_DLL_CALLBACK(void) -JavaPackage_finalize(JSContext *cx, JSObject *obj) -{ - JavaPackage_Private *package = JS_GetPrivate(cx, obj); - if (!package) - return; - - if (package->path) - JS_free(cx, (char *)package->path); - JS_free(cx, package); -} - -/* - * The definition of the JavaPackage class - */ -JSClass JavaPackage_class = { - "JavaPackage", JSCLASS_HAS_PRIVATE, - JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JavaPackage_setProperty, - JS_EnumerateStub, JavaPackage_resolve, - JavaPackage_convert, JavaPackage_finalize, - - /* Optionally non-null members start here. */ - NULL, /* getObjectOps */ - NULL, /* checkAccess */ - NULL, /* call */ - NULL, /* construct */ - NULL, /* xdrObject */ - NULL, /* hasInstance */ - NULL, /* mark */ - 0, /* spare */ -}; - -JavaPackageDef -standard_java_packages[] = { - {"java", NULL, PKG_USER, 0}, - {"java.applet", NULL, PKG_USER, JSPROP_READONLY}, - {"java.awt", NULL, PKG_USER, JSPROP_READONLY}, - {"java.awt.datatransfer", - NULL, PKG_SYSTEM, JSPROP_READONLY}, - {"java.awt.event", NULL, PKG_SYSTEM, JSPROP_READONLY}, - {"java.awt.image", NULL, PKG_SYSTEM, JSPROP_READONLY}, - {"java.awt.peer", NULL, PKG_SYSTEM, JSPROP_READONLY}, - {"java.beans", NULL, PKG_USER, JSPROP_READONLY}, - {"java.io", NULL, PKG_SYSTEM, JSPROP_READONLY}, - {"java.lang", NULL, PKG_USER, JSPROP_READONLY}, - {"java.lang.reflect", NULL, PKG_SYSTEM, JSPROP_READONLY}, - {"java.math", NULL, PKG_SYSTEM, JSPROP_READONLY}, - {"java.net", NULL, PKG_USER, JSPROP_READONLY}, - {"java.rmi", NULL, PKG_USER, JSPROP_READONLY}, - {"java.rmi.dgc", NULL, PKG_USER, JSPROP_READONLY}, - {"java.rmi.user", NULL, PKG_USER, JSPROP_READONLY}, - {"java.rmi.registry", NULL, PKG_USER, JSPROP_READONLY}, - {"java.rmi.server", NULL, PKG_USER, JSPROP_READONLY}, - {"java.security", NULL, PKG_USER, JSPROP_READONLY}, - {"java.security.acl", NULL, PKG_SYSTEM, JSPROP_READONLY}, - {"java.security.interfaces", - NULL, PKG_SYSTEM, JSPROP_READONLY}, - {"java.sql", NULL, PKG_USER, JSPROP_READONLY}, - {"java.text", NULL, PKG_USER, JSPROP_READONLY}, - {"java.text.resources", NULL, PKG_SYSTEM, JSPROP_READONLY}, - {"java.util", NULL, PKG_USER, JSPROP_READONLY}, - {"java.util.zip", NULL, PKG_SYSTEM, JSPROP_READONLY}, - - {"netscape", NULL, PKG_USER, 0}, - {"netscape.applet", NULL, PKG_SYSTEM, JSPROP_READONLY}, - {"netscape.application",NULL, PKG_SYSTEM, JSPROP_READONLY}, - {"netscape.debug", NULL, PKG_SYSTEM, JSPROP_READONLY}, - {"netscape.javascript", NULL, PKG_SYSTEM, JSPROP_READONLY}, - {"netscape.ldap", NULL, PKG_SYSTEM, JSPROP_READONLY}, - {"netscape.misc", NULL, PKG_SYSTEM, JSPROP_READONLY}, - {"netscape.net", NULL, PKG_SYSTEM, JSPROP_READONLY}, - {"netscape.plugin", NULL, PKG_SYSTEM, JSPROP_READONLY}, - {"netscape.util", NULL, PKG_SYSTEM, JSPROP_READONLY}, - {"netscape.secfile", NULL, PKG_SYSTEM, JSPROP_READONLY}, - {"netscape.security", NULL, PKG_SYSTEM, JSPROP_READONLY}, - {"netscape.WAI", NULL, PKG_SYSTEM, JSPROP_READONLY}, - - {"sun", NULL, PKG_USER, 0}, - {"Packages", "", PKG_USER, JSPROP_READONLY}, - - {NULL, NULL, 0, 0} -}; - -/* - * On systems which provide strtok_r we'll use that function to avoid - * problems with non-thread-safety. - */ -#if HAVE_STRTOK_R -# define STRTOK_1ST(str, seps, res) strtok_r (str, seps, &res) -# define STRTOK_OTHER(seps, res) strtok_r (res, seps, &res) -#else -# define STRTOK_1ST(str, seps, res) strtok (str, seps) -# define STRTOK_OTHER(seps, res) strtok (NULL, seps) -#endif - -/* - * Pre-define a hierarchy of JavaPackage objects. - * Pre-defining a Java package at initialization time is not necessary, but - * it will make package lookup faster and, more importantly, will avoid - * unnecessary network accesses if classes are being loaded over the network. - */ -static JSBool -pre_define_java_packages(JSContext *cx, JSObject *global_obj, - JavaPackageDef *predefined_packages) -{ - JSBool package_exists; - JSObject *parent_obj; - JavaPackageDef *package_def; - char *simple_name, *cp, *package_name, *path; - int flags; - - if (!predefined_packages) - return JS_TRUE; - - /* Iterate over all pre-defined Java packages */ - for (package_def = predefined_packages; package_def->name; package_def++) { -#if HAVE_STRTOK_R - char *nextstr; -#endif - package_name = path = NULL; - - parent_obj = global_obj; - package_name = strdup(package_def->name); - if (!package_name) - goto out_of_memory; - - /* Walk the chain of JavaPackage objects to get to the parent of the - rightmost sub-package in the fully-qualified package name. */ - for (simple_name = STRTOK_1ST(package_name, ".", nextstr); simple_name /*1*/; simple_name = STRTOK_OTHER(".", nextstr)) { - jsval v; - - if (!simple_name) { - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_DOUBLE_SHIPPING, package_name); - goto error; - } - - /* Check to see if the sub-package already exists */ - quiet_resolve_failure = JS_TRUE; - package_exists = JS_LookupProperty(cx, parent_obj, simple_name, &v) && JSVAL_IS_OBJECT(v); - quiet_resolve_failure = JS_FALSE; - - if (package_exists) { - parent_obj = JSVAL_TO_OBJECT(v); - continue; - } - - /* New package objects should only be created at the terminal - sub-package in a fully-qualified package-name */ - if (STRTOK_OTHER(".", nextstr)) { - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_BAD_PACKAGE_PREDEF, - package_def->name); - goto error; - } - - if (package_def->path) { - path = strdup(package_def->path); - if (!path) - goto out_of_memory; - } else { - /* - * The default path is specified, so create it from the - * fully-qualified package name. - */ - path = strdup(package_def->name); - if (!path) - goto out_of_memory; - /* Transform package name, e.g. "java.lang" ==> "java/lang" */ - for (cp = path; *cp != '\0'; cp++) { - if (*cp == '.') - *cp = '/'; - } - } - flags = package_def->flags; - parent_obj = define_JavaPackage(cx, parent_obj, simple_name, path, flags, - package_def->access); - if (!parent_obj) - goto error; - - free(path); - break; - } - free(package_name); - } - return JS_TRUE; - -out_of_memory: - JS_ReportOutOfMemory(cx); - -error: - JS_FREE_IF(cx, package_name); - JS_FREE_IF(cx, path); - return JS_FALSE; -} - -JS_STATIC_DLL_CALLBACK(JSBool) -JavaPackage_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) -{ - if (!JS_InstanceOf(cx, obj, &JavaPackage_class, argv)) - return JS_FALSE; - return JavaPackage_convert(cx, obj, JSTYPE_STRING, rval); -} - -static JSFunctionSpec JavaPackage_methods[] = { - {"toString", JavaPackage_toString, 0, 0, 0}, - {0, 0, 0, 0, 0}, -}; - -/* - * One-time initialization for the JavaPackage class. (This is not - * run once per thread, rather it's run once for a given JSContext.) - */ -JSBool -jsj_init_JavaPackage(JSContext *cx, JSObject *global_obj, - JavaPackageDef *additional_predefined_packages) { - - /* Define JavaPackage class */ - if (!JS_InitClass(cx, global_obj, 0, &JavaPackage_class, - 0, 0, 0, JavaPackage_methods, 0, 0)) - return JS_FALSE; - - /* Add top-level packages, e.g. : java, netscape, sun */ - if (!pre_define_java_packages(cx, global_obj, standard_java_packages)) - return JS_FALSE; - if (!pre_define_java_packages(cx, global_obj, additional_predefined_packages)) - return JS_FALSE; - - return JS_TRUE; -} diff --git a/lib/javascript/liveconnect/jsj_array.c b/lib/javascript/liveconnect/jsj_array.c deleted file mode 100644 index 17b6a7aa..00000000 --- a/lib/javascript/liveconnect/jsj_array.c +++ /dev/null @@ -1,207 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * This file is part of the Java-vendor-neutral implementation of LiveConnect - * - * It contains the code for reading and writing elements of a Java array. - */ - -#include "jsj_private.h" /* LiveConnect internals */ - -/* - * Read the Java value at a given index into a Java array and convert it - * to a JS value. The array_component_signature describes the type of - * the resulting Java value, which can be a primitive type or an object type. - * More specifically it can be an array type in the case of multidimensional - * arrays. - */ -JSBool -jsj_GetJavaArrayElement(JSContext *cx, JNIEnv *jEnv, jarray java_array, jsize index, - JavaSignature *array_component_signature, - jsval *vp) -{ - jvalue java_value; - JavaSignatureChar component_type; - JSBool success; - -#define GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Type,member) \ - (*jEnv)->Get##Type##ArrayRegion(jEnv, java_array, index, 1, \ - &java_value.member); \ - if ((*jEnv)->ExceptionOccurred(jEnv)) { \ - jsj_ReportJavaError(cx, jEnv, "Error reading element of " \ - "Java primitive array"); \ - return JS_FALSE; \ - } - - component_type = array_component_signature->type; - switch(component_type) { - case JAVA_SIGNATURE_BYTE: - GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Byte,b); - break; - - case JAVA_SIGNATURE_CHAR: - GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Char,c); - break; - - case JAVA_SIGNATURE_SHORT: - GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Short,s); - break; - - case JAVA_SIGNATURE_INT: - GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Int,i); - break; - - case JAVA_SIGNATURE_BOOLEAN: - GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Boolean,z); - break; - - case JAVA_SIGNATURE_LONG: - GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Long,j); - break; - - case JAVA_SIGNATURE_FLOAT: - GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Float,f); - break; - - case JAVA_SIGNATURE_DOUBLE: - GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Double,d); - break; - - /* Non-primitive (reference) type */ - default: - JS_ASSERT(component_type >= JAVA_SIGNATURE_ARRAY); - java_value.l = (*jEnv)->GetObjectArrayElement(jEnv, java_array, index); - if ((*jEnv)->ExceptionOccurred(jEnv)) { - jsj_ReportJavaError(cx, jEnv, "Error reading Java object array"); - return JS_FALSE; - } - success = jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_value.l, vp); - (*jEnv)->DeleteLocalRef(jEnv, java_value.l); - return success; - -#undef GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY - case JAVA_SIGNATURE_UNKNOWN: - case JAVA_SIGNATURE_VOID: - JS_ASSERT(0); /* Unknown java type signature */ - return JS_FALSE; - } - - return jsj_ConvertJavaValueToJSValue(cx, jEnv, array_component_signature, &java_value, vp); -} - -JSBool -jsj_SetJavaArrayElement(JSContext *cx, JNIEnv *jEnv, jarray java_array, jsize index, - JavaSignature *array_component_signature, - jsval js_val) -{ - int dummy_cost; - jvalue java_value; - JavaSignatureChar component_type; - JSBool is_local_ref; - - if (!jsj_ConvertJSValueToJavaValue(cx, jEnv, js_val, array_component_signature, - &dummy_cost, &java_value, &is_local_ref)) - return JS_FALSE; - -#define SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Type,member) \ - (*jEnv)->Set##Type##ArrayRegion(jEnv, java_array, index, 1, \ - &java_value.member); \ - if ((*jEnv)->ExceptionOccurred(jEnv)) { \ - jsj_ReportJavaError(cx, jEnv, "Error assigning to element of " \ - "Java primitive array"); \ - return JS_FALSE; \ - } - - component_type = array_component_signature->type; - switch(component_type) { - case JAVA_SIGNATURE_BYTE: - SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Byte,b); - break; - - case JAVA_SIGNATURE_CHAR: - SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Char,c); - break; - - case JAVA_SIGNATURE_SHORT: - SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Short,s); - break; - - case JAVA_SIGNATURE_INT: - SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Int,i); - break; - - case JAVA_SIGNATURE_BOOLEAN: - SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Boolean,z); - break; - - case JAVA_SIGNATURE_LONG: - SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Long,j); - break; - - case JAVA_SIGNATURE_FLOAT: - SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Float,f); - break; - - case JAVA_SIGNATURE_DOUBLE: - SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Double,d); - break; - - /* Non-primitive (reference) type */ - default: - JS_ASSERT(IS_REFERENCE_TYPE(component_type)); - (*jEnv)->SetObjectArrayElement(jEnv, java_array, index, java_value.l); - if (is_local_ref) \ - (*jEnv)->DeleteLocalRef(jEnv, java_value.l); - if ((*jEnv)->ExceptionOccurred(jEnv)) { - jsj_ReportJavaError(cx, jEnv, "Error assigning to Java object array"); - return JS_FALSE; - } - break; - -#undef SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY - case JAVA_SIGNATURE_UNKNOWN: - case JAVA_SIGNATURE_VOID: - JS_ASSERT(0); /* Unknown java type signature */ - return JS_FALSE; - } - - return JS_TRUE; -} - diff --git a/lib/javascript/liveconnect/jsj_class.c b/lib/javascript/liveconnect/jsj_class.c deleted file mode 100644 index 03992438..00000000 --- a/lib/javascript/liveconnect/jsj_class.c +++ /dev/null @@ -1,765 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * This file is part of the Java-vendor-neutral implementation of LiveConnect - * - * It contains the code that constructs and manipulates JavaClassDescriptor - * structs, which are the native wrappers for Java classes. - * JavaClassDescriptors are used to describe the signatures of methods and - * fields. There is a JavaClassDescriptor associated with the reflection of - * each Java Object. - */ - -#include -#include - -#include "jsj_private.h" /* LiveConnect internals */ -#include "jsj_hash.h" /* Hash tables */ - -#ifdef JSJ_THREADSAFE -# include "prmon.h" -#endif - -/* A one-to-one mapping between all referenced java.lang.Class objects and - their corresponding JavaClassDescriptor objects */ -static JSJHashTable *java_class_reflections; - -#ifdef JSJ_THREADSAFE -static PRMonitor *java_class_reflections_monitor; -#endif - -/* - * Given a JVM handle to a java.lang.Class object, malloc a C-string - * containing the UTF8 encoding of the fully qualified name of the class. - * It's the caller's responsibility to free the returned string. - * - * If an error occurs, NULL is returned and the error reporter called. - */ -const char * -jsj_GetJavaClassName(JSContext *cx, JNIEnv *jEnv, jclass java_class) -{ - jstring java_class_name_jstr; - const char *java_class_name; - - /* Get java.lang.String object containing class name */ - java_class_name_jstr = - (*jEnv)->CallObjectMethod(jEnv, java_class, jlClass_getName); - - if (!java_class_name_jstr) - goto error; - - /* Fix bugzilla #183092 - * It is necessary to check Exception from JPI - * even though java_class_name_jstr != null */ -#ifdef XP_UNIX - if ((*jEnv)->ExceptionOccurred(jEnv)) - goto error; -#endif - - /* Convert to UTF8 encoding and copy */ - java_class_name = jsj_DupJavaStringUTF(cx, jEnv, java_class_name_jstr); - - (*jEnv)->DeleteLocalRef(jEnv, java_class_name_jstr); - return java_class_name; - -error: - jsj_UnexpectedJavaError(cx, jEnv, "Can't get Java class name using" - "java.lang.Class.getName()"); - return NULL; -} - -/* - * Convert in-place a string of the form "java.lang.String" into "java/lang/String". - * Though the former style is conventionally used by Java programmers, the latter is - * what the JNI functions require. - */ -void -jsj_MakeJNIClassname(char * class_name) -{ - char * c; - for (c = class_name; *c; c++) - if (*c == '.') - *c = '/'; -} - -/* - * Classify an instance of java.lang.Class as either one of the primitive - * types, e.g. int, char, etc., as an array type or as a non-array object type - * (subclass of java.lang.Object) by returning the appropriate enum member. - * - */ -static JavaSignatureChar -get_signature_type(JSContext *cx, JavaClassDescriptor *class_descriptor) -{ - JavaSignatureChar type; - const char *java_class_name; - - /* Get UTF8 encoding of class name */ - java_class_name = class_descriptor->name; - JS_ASSERT(java_class_name); - if (!java_class_name) - return JAVA_SIGNATURE_UNKNOWN; - - if (!strcmp(java_class_name, "byte")) - type = JAVA_SIGNATURE_BYTE; - else if (!strcmp(java_class_name, "char")) - type = JAVA_SIGNATURE_CHAR; - else if (!strcmp(java_class_name, "float")) - type = JAVA_SIGNATURE_FLOAT; - else if (!strcmp(java_class_name, "double")) - type = JAVA_SIGNATURE_DOUBLE; - else if (!strcmp(java_class_name, "int")) - type = JAVA_SIGNATURE_INT; - else if (!strcmp(java_class_name, "long")) - type = JAVA_SIGNATURE_LONG; - else if (!strcmp(java_class_name, "short")) - type = JAVA_SIGNATURE_SHORT; - else if (!strcmp(java_class_name, "boolean")) - type = JAVA_SIGNATURE_BOOLEAN; - else if (!strcmp(java_class_name, "void")) - type = JAVA_SIGNATURE_VOID; - else if (!strcmp(java_class_name, "java.lang.Boolean")) - type = JAVA_SIGNATURE_JAVA_LANG_BOOLEAN; - else if (!strcmp(java_class_name, "java.lang.Double")) - type = JAVA_SIGNATURE_JAVA_LANG_DOUBLE; - else if (!strcmp(java_class_name, "java.lang.String")) - type = JAVA_SIGNATURE_JAVA_LANG_STRING; - else if (!strcmp(java_class_name, "java.lang.Object")) - type = JAVA_SIGNATURE_JAVA_LANG_OBJECT; - else if (!strcmp(java_class_name, "java.lang.Class")) - type = JAVA_SIGNATURE_JAVA_LANG_CLASS; - else if (!strcmp(java_class_name, "netscape.javascript.JSObject")) - type = JAVA_SIGNATURE_NETSCAPE_JAVASCRIPT_JSOBJECT; - else - type = JAVA_SIGNATURE_OBJECT; - return type; -} - -static JSBool -is_java_array_class(JNIEnv *jEnv, jclass java_class) -{ - return (*jEnv)->CallBooleanMethod(jEnv, java_class, jlClass_isArray); -} - -/* - * Return the class of a Java array's component type. This is not the same - * as the array's element type. For example, the component type of an array - * of type SomeType[][][] is SomeType[][], but its element type is SomeType. - * - * If an error occurs, NULL is returned and an error reported. - */ -static jclass -get_java_array_component_class(JSContext *cx, JNIEnv *jEnv, jclass java_class) -{ - jclass result; - result = (*jEnv)->CallObjectMethod(jEnv, java_class, jlClass_getComponentType); - if (!result) { - jsj_UnexpectedJavaError(cx, jEnv, - "Can't get Java array component class using " - "java.lang.Class.getComponentType()"); - return NULL; - } - return result; -} - -/* - * Given a Java class, fill in the signature structure that describes the class. - * If an error occurs, JS_FALSE is returned and the error reporter called. - */ -static JSBool -compute_java_class_signature(JSContext *cx, JNIEnv *jEnv, JavaSignature *signature) -{ - jclass java_class = signature->java_class; - - if (is_java_array_class(jEnv, java_class)) { - jclass component_class; - - signature->type = JAVA_SIGNATURE_ARRAY; - - component_class = get_java_array_component_class(cx, jEnv, java_class); - if (!component_class) - return JS_FALSE; - - signature->array_component_signature = - jsj_GetJavaClassDescriptor(cx, jEnv, component_class); - if (!signature->array_component_signature) { - (*jEnv)->DeleteLocalRef(jEnv, component_class); - return JS_FALSE; - } - } else { - signature->type = get_signature_type(cx, signature); - } - return JS_TRUE; -} - -/* - * Convert from JavaSignatureChar enumeration to single-character - * signature used by the JDK and JNI methods. - */ -static char -get_jdk_signature_char(JavaSignatureChar type) -{ - return "XVZCBSIJFD[LLLLLL"[(int)type]; -} - -/* - * Convert a JavaSignature object into a string format as used by - * the JNI functions, e.g. java.lang.Object ==> "Ljava/lang/Object;" - * The caller is responsible for freeing the resulting string. - * - * If an error is encountered, NULL is returned and an error reported. - */ -const char * -jsj_ConvertJavaSignatureToString(JSContext *cx, JavaSignature *signature) -{ - char *sig; - - if (IS_OBJECT_TYPE(signature->type)) { - /* A non-array object class */ - sig = JS_smprintf("L%s;", signature->name); - if (sig) - jsj_MakeJNIClassname(sig); - - } else if (signature->type == JAVA_SIGNATURE_ARRAY) { - /* An array class */ - const char *component_signature_string; - - component_signature_string = - jsj_ConvertJavaSignatureToString(cx, signature->array_component_signature); - if (!component_signature_string) - return NULL; - sig = JS_smprintf("[%s", component_signature_string); - JS_free(cx, (char*)component_signature_string); - - } else { - /* A primitive class */ - sig = JS_smprintf("%c", get_jdk_signature_char(signature->type)); - } - - if (!sig) { - JS_ReportOutOfMemory(cx); - return NULL; - } - return sig; -} - -/* - * Convert a JavaSignature object into a human-readable string format as seen - * in Java source files, e.g. "byte", or "int[][]" or "java.lang.String". - * The caller is responsible for freeing the resulting string. - * - * If an error is encountered, NULL is returned and an error reported. - */ -const char * -jsj_ConvertJavaSignatureToHRString(JSContext *cx, - JavaSignature *signature) -{ - char *sig; - JavaSignature *acs; - - if (signature->type == JAVA_SIGNATURE_ARRAY) { - /* An array class */ - const char *component_signature_string; - acs = signature->array_component_signature; - component_signature_string = - jsj_ConvertJavaSignatureToHRString(cx, acs); - if (!component_signature_string) - return NULL; - sig = JS_smprintf("%s[]", component_signature_string); - JS_free(cx, (char*)component_signature_string); - - } else { - /* A primitive class or a non-array object class */ - sig = JS_strdup(cx, signature->name); - } - - if (!sig) { - JS_ReportOutOfMemory(cx); - return NULL; - } - return sig; -} - -static void -destroy_java_member_descriptor(JSContext *cx, JNIEnv *jEnv, JavaMemberDescriptor *member_descriptor) -{ - JavaMethodSpec *method, *next_method; - if (member_descriptor->field) - jsj_DestroyFieldSpec(cx, jEnv, member_descriptor->field); - - method = member_descriptor->methods; - while (method) { - next_method = method->next; - jsj_DestroyMethodSpec(cx, jEnv, method); - method = next_method; - } - - if (member_descriptor->invoke_func_obj) - JS_RemoveRoot(cx, &member_descriptor->invoke_func_obj); - - JS_FREE_IF(cx, (char *)member_descriptor->name); - JS_free(cx, member_descriptor); -} - -static void -destroy_class_member_descriptors(JSContext *cx, JNIEnv *jEnv, JavaMemberDescriptor *member_descriptor) -{ - JavaMemberDescriptor *next_member; - - while (member_descriptor) { - next_member = member_descriptor->next; - destroy_java_member_descriptor(cx, jEnv, member_descriptor); - member_descriptor = next_member; - } -} - -static void -destroy_class_descriptor(JSContext *cx, JNIEnv *jEnv, JavaClassDescriptor *class_descriptor) -{ - JS_FREE_IF(cx, (char *)class_descriptor->name); - if (class_descriptor->java_class) - (*jEnv)->DeleteGlobalRef(jEnv, class_descriptor->java_class); - - if (class_descriptor->array_component_signature) - jsj_ReleaseJavaClassDescriptor(cx, jEnv, class_descriptor->array_component_signature); - - destroy_class_member_descriptors(cx, jEnv, class_descriptor->instance_members); - destroy_class_member_descriptors(cx, jEnv, class_descriptor->static_members); - destroy_class_member_descriptors(cx, jEnv, class_descriptor->constructors); - JS_free(cx, class_descriptor); -} - -static JavaClassDescriptor * -new_class_descriptor(JSContext *cx, JNIEnv *jEnv, jclass java_class) -{ - JavaClassDescriptor *class_descriptor; - - class_descriptor = (JavaClassDescriptor *)JS_malloc(cx, sizeof(JavaClassDescriptor)); - if (!class_descriptor) - return NULL; - memset(class_descriptor, 0, sizeof(JavaClassDescriptor)); - - class_descriptor->name = jsj_GetJavaClassName(cx, jEnv, java_class); - if (!class_descriptor->name) - goto error; - - java_class = (*jEnv)->NewGlobalRef(jEnv, java_class); - if (!java_class) { - jsj_UnexpectedJavaError(cx, jEnv, "Unable to reference Java class"); - goto error; - } - class_descriptor->java_class = java_class; - - if (!compute_java_class_signature(cx, jEnv, class_descriptor)) - goto error; - - class_descriptor->modifiers = - (*jEnv)->CallIntMethod(jEnv, java_class, jlClass_getModifiers); - class_descriptor->ref_count = 1; - - if (!JSJ_HashTableAdd(java_class_reflections, java_class, class_descriptor, - (void*)jEnv)) - goto error; - - return class_descriptor; - -error: - destroy_class_descriptor(cx, jEnv, class_descriptor); - return NULL; -} - -/* Trivial helper for jsj_DiscardJavaClassReflections(), below */ -JS_STATIC_DLL_CALLBACK(JSIntn) -enumerate_remove_java_class(JSJHashEntry *he, JSIntn i, void *arg) -{ - JSJavaThreadState *jsj_env = (JSJavaThreadState *)arg; - JavaClassDescriptor *class_descriptor; - - class_descriptor = (JavaClassDescriptor*)he->value; - - destroy_class_descriptor(jsj_env->cx, jsj_env->jEnv, class_descriptor); - - return HT_ENUMERATE_REMOVE; -} - -/* This shutdown routine discards all JNI references to Java objects - that have been reflected into JS, even if there are still references - to them from JS. */ -void -jsj_DiscardJavaClassReflections(JNIEnv *jEnv) -{ - JSJavaThreadState *jsj_env; - char *err_msg; - JSContext *cx; - - /* Get the per-thread state corresponding to the current Java thread */ - jsj_env = jsj_MapJavaThreadToJSJavaThreadState(jEnv, &err_msg); - JS_ASSERT(jsj_env); - if (!jsj_env) - return; - - /* Get the JSContext that we're supposed to use for this Java thread */ - cx = jsj_env->cx; - if (!cx) { - /* We called spontaneously into JS from Java, rather than from JS into - Java and back into JS. Invoke a callback to obtain/create a - JSContext for us to use. */ - if (JSJ_callbacks->map_jsj_thread_to_js_context) { -#ifdef OJI - cx = JSJ_callbacks->map_jsj_thread_to_js_context(jsj_env, - NULL, /* FIXME: What should this argument be ? */ - jEnv, &err_msg); -#else - cx = JSJ_callbacks->map_jsj_thread_to_js_context(jsj_env, - jEnv, &err_msg); -#endif - if (!cx) - return; - } else { - err_msg = JS_smprintf("Unable to find/create JavaScript execution " - "context for JNI thread 0x%08x", jEnv); - jsj_LogError(err_msg); - free(err_msg); - return; - } - } - - if (java_class_reflections) { - JSJ_HashTableEnumerateEntries(java_class_reflections, - enumerate_remove_java_class, - (void*)jsj_env); - JSJ_HashTableDestroy(java_class_reflections); - java_class_reflections = NULL; - } -} - -extern JavaClassDescriptor * -jsj_GetJavaClassDescriptor(JSContext *cx, JNIEnv *jEnv, jclass java_class) -{ - JavaClassDescriptor *class_descriptor = NULL; - -#ifdef JSJ_THREADSAFE - PR_EnterMonitor(java_class_reflections_monitor); -#endif - - if (java_class_reflections) { - class_descriptor = JSJ_HashTableLookup(java_class_reflections, - (const void *)java_class, - (void*)jEnv); - } - if (!class_descriptor) { - class_descriptor = new_class_descriptor(cx, jEnv, java_class); - -#ifdef JSJ_THREADSAFE - PR_ExitMonitor(java_class_reflections_monitor); -#endif - return class_descriptor; - } - -#ifdef JSJ_THREADSAFE - PR_ExitMonitor(java_class_reflections_monitor); -#endif - - JS_ASSERT(class_descriptor->ref_count > 0); - class_descriptor->ref_count++; - return class_descriptor; -} - -void -jsj_ReleaseJavaClassDescriptor(JSContext *cx, JNIEnv *jEnv, JavaClassDescriptor *class_descriptor) -{ -#if 0 - /* The ref-counting code doesn't work very well because cycles in the data - structures routinely lead to uncollectible JavaClassDescriptor's. Skip it. */ - JS_ASSERT(class_descriptor->ref_count >= 1); - if (!--class_descriptor->ref_count) { - JSJ_HashTableRemove(java_class_reflections, - class_descriptor->java_class, (void*)jEnv); - destroy_class_descriptor(cx, jEnv, class_descriptor); - } -#endif -} - -#ifdef JSJ_THREADSAFE -static PRMonitor *java_reflect_monitor = NULL; -#endif - -static JSBool -reflect_java_methods_and_fields(JSContext *cx, - JNIEnv *jEnv, - JavaClassDescriptor *class_descriptor, - JSBool reflect_statics_only) -{ - JavaMemberDescriptor *member_descriptor; - JSBool success; - - success = JS_TRUE; /* optimism */ - -#ifdef JSJ_THREADSAFE - PR_EnterMonitor(java_reflect_monitor); -#endif - - /* See if we raced with another thread to reflect members of this class. - If the status is REFLECT_COMPLETE, another thread beat us to it. If - the status is REFLECT_IN_PROGRESS, we've recursively called this - function within a single thread. Either way, we're done. */ - if (reflect_statics_only) { - if (class_descriptor->static_members_reflected != REFLECT_NO) - goto done; - class_descriptor->static_members_reflected = REFLECT_IN_PROGRESS; - } else { - if (class_descriptor->instance_members_reflected != REFLECT_NO) - goto done; - class_descriptor->instance_members_reflected = REFLECT_IN_PROGRESS; - } - - if (!jsj_ReflectJavaMethods(cx, jEnv, class_descriptor, reflect_statics_only)) - goto error; - if (!jsj_ReflectJavaFields(cx, jEnv, class_descriptor, reflect_statics_only)) - goto error; - - if (reflect_statics_only) { - member_descriptor = class_descriptor->static_members; - while (member_descriptor) { - class_descriptor->num_static_members++; - member_descriptor = member_descriptor->next; - } - class_descriptor->static_members_reflected = REFLECT_COMPLETE; - } else { - member_descriptor = class_descriptor->instance_members; - while (member_descriptor) { - class_descriptor->num_instance_members++; - member_descriptor = member_descriptor->next; - } - class_descriptor->instance_members_reflected = REFLECT_COMPLETE; - } - -done: -#ifdef JSJ_THREADSAFE - PR_ExitMonitor(java_reflect_monitor); -#endif - return success; - -error: - success = JS_FALSE; - goto done; -} - -JavaMemberDescriptor * -jsj_GetClassStaticMembers(JSContext *cx, - JNIEnv *jEnv, - JavaClassDescriptor *class_descriptor) -{ - if (class_descriptor->static_members_reflected != REFLECT_COMPLETE) - reflect_java_methods_and_fields(cx, jEnv, class_descriptor, JS_TRUE); - return class_descriptor->static_members; -} - -JavaMemberDescriptor * -jsj_GetClassInstanceMembers(JSContext *cx, - JNIEnv *jEnv, - JavaClassDescriptor *class_descriptor) -{ - if (class_descriptor->instance_members_reflected != REFLECT_COMPLETE) - reflect_java_methods_and_fields(cx, jEnv, class_descriptor, JS_FALSE); - return class_descriptor->instance_members; -} - -JavaMemberDescriptor * -jsj_LookupJavaStaticMemberDescriptorById(JSContext *cx, - JNIEnv *jEnv, - JavaClassDescriptor *class_descriptor, - jsid id) -{ - JavaMemberDescriptor *member_descriptor; - - member_descriptor = jsj_GetClassStaticMembers(cx, jEnv, class_descriptor); - while (member_descriptor) { - if (id == member_descriptor->id) - return member_descriptor; - member_descriptor = member_descriptor->next; - } - return NULL; -} - -JavaMemberDescriptor * -jsj_GetJavaStaticMemberDescriptor(JSContext *cx, - JNIEnv *jEnv, - JavaClassDescriptor *class_descriptor, - jstring member_name_jstr) -{ - JavaMemberDescriptor *member_descriptor; - jsid id; - - if (!JavaStringToId(cx, jEnv, member_name_jstr, &id)) - return NULL; - - member_descriptor = jsj_LookupJavaStaticMemberDescriptorById(cx, jEnv, class_descriptor, id); - if (member_descriptor) - return member_descriptor; - - member_descriptor = JS_malloc(cx, sizeof(JavaMemberDescriptor)); - if (!member_descriptor) - return NULL; - memset(member_descriptor, 0, sizeof(JavaMemberDescriptor)); - - member_descriptor->name = jsj_DupJavaStringUTF(cx, jEnv, member_name_jstr); - if (!member_descriptor->name) { - JS_free(cx, member_descriptor); - return NULL; - } - member_descriptor->id = id; - - member_descriptor->next = class_descriptor->static_members; - class_descriptor->static_members = member_descriptor; - - return member_descriptor; -} - -JavaMemberDescriptor * -jsj_GetJavaClassConstructors(JSContext *cx, - JavaClassDescriptor *class_descriptor) -{ - JavaMemberDescriptor *member_descriptor; - - if (class_descriptor->constructors) - return class_descriptor->constructors; - - member_descriptor = JS_malloc(cx, sizeof(JavaMemberDescriptor)); - if (!member_descriptor) - return NULL; - memset(member_descriptor, 0, sizeof(JavaMemberDescriptor)); - - member_descriptor->name = JS_strdup(cx, ""); - if (!member_descriptor->name) { - JS_free(cx, member_descriptor); - return NULL; - } - - class_descriptor->constructors = member_descriptor; - - return member_descriptor; -} - -JavaMemberDescriptor * -jsj_LookupJavaClassConstructors(JSContext *cx, JNIEnv *jEnv, - JavaClassDescriptor *class_descriptor) -{ - if (class_descriptor->static_members_reflected != REFLECT_COMPLETE) - reflect_java_methods_and_fields(cx, jEnv, class_descriptor, JS_TRUE); - return class_descriptor->constructors; -} - -JavaMemberDescriptor * -jsj_LookupJavaMemberDescriptorById(JSContext *cx, JNIEnv *jEnv, - JavaClassDescriptor *class_descriptor, - jsid id) -{ - JavaMemberDescriptor *member_descriptor; - - member_descriptor = jsj_GetClassInstanceMembers(cx, jEnv, class_descriptor); - while (member_descriptor) { - if (id == member_descriptor->id) - return member_descriptor; - member_descriptor = member_descriptor->next; - } - return NULL; -} - -JavaMemberDescriptor * -jsj_GetJavaMemberDescriptor(JSContext *cx, - JNIEnv *jEnv, - JavaClassDescriptor *class_descriptor, - jstring member_name_jstr) -{ - JavaMemberDescriptor *member_descriptor; - jsid id; - - if (!JavaStringToId(cx, jEnv, member_name_jstr, &id)) - return NULL; - - member_descriptor = jsj_LookupJavaMemberDescriptorById(cx, jEnv, class_descriptor, id); - if (member_descriptor) - return member_descriptor; - - member_descriptor = JS_malloc(cx, sizeof(JavaMemberDescriptor)); - if (!member_descriptor) - return NULL; - memset(member_descriptor, 0, sizeof(JavaMemberDescriptor)); - - member_descriptor->name = jsj_DupJavaStringUTF(cx, jEnv, member_name_jstr); - if (!member_descriptor->name) { - JS_free(cx, member_descriptor); - return NULL; - } - member_descriptor->id = id; - - member_descriptor->next = class_descriptor->instance_members; - class_descriptor->instance_members = member_descriptor; - - return member_descriptor; -} - -JSBool -jsj_InitJavaClassReflectionsTable() -{ - if (!java_class_reflections) { - java_class_reflections = - JSJ_NewHashTable(64, jsj_HashJavaObject, jsj_JavaObjectComparator, - NULL, NULL, NULL); - - if (!java_class_reflections) - return JS_FALSE; - -#ifdef JSJ_THREADSAFE - java_class_reflections_monitor = - (struct PRMonitor *) PR_NewMonitor(); - if (!java_class_reflections_monitor) - return JS_FALSE; - - java_reflect_monitor = - (struct PRMonitor *) PR_NewMonitor(); - if (!java_reflect_monitor) - return JS_FALSE; -#endif - } - - return JS_TRUE; -} diff --git a/lib/javascript/liveconnect/jsj_convert.c b/lib/javascript/liveconnect/jsj_convert.c deleted file mode 100644 index 3d0bfd7d..00000000 --- a/lib/javascript/liveconnect/jsj_convert.c +++ /dev/null @@ -1,882 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* This file is part of the Java-vendor-neutral implementation of LiveConnect - * - * Below is the code that converts between Java and JavaScript values of all - * types. - */ - -#include -#include - -#ifdef OJI -#include "prtypes.h" /* Need platform-dependent definition of HAVE_LONG_LONG - for non-standard jri_md.h file */ -#endif - -#include "jsj_private.h" /* LiveConnect internals */ - -/* Floating-point double utilities, stolen from jsnum.h */ -#ifdef IS_LITTLE_ENDIAN -#define JSDOUBLE_HI32(x) (((uint32 *)&(x))[1]) -#define JSDOUBLE_LO32(x) (((uint32 *)&(x))[0]) -#else -#define JSDOUBLE_HI32(x) (((uint32 *)&(x))[0]) -#define JSDOUBLE_LO32(x) (((uint32 *)&(x))[1]) -#endif -#define JSDOUBLE_HI32_SIGNBIT 0x80000000 -#define JSDOUBLE_HI32_EXPMASK 0x7ff00000 -#define JSDOUBLE_HI32_MANTMASK 0x000fffff - -#define JSDOUBLE_IS_NaN(x) \ - ((JSDOUBLE_HI32(x) & JSDOUBLE_HI32_EXPMASK) == JSDOUBLE_HI32_EXPMASK && \ - (JSDOUBLE_LO32(x) || (JSDOUBLE_HI32(x) & JSDOUBLE_HI32_MANTMASK))) - -#define JSDOUBLE_IS_INFINITE(x) \ - ((JSDOUBLE_HI32(x) & ~JSDOUBLE_HI32_SIGNBIT) == JSDOUBLE_HI32_EXPMASK && \ - !JSDOUBLE_LO32(x)) - -static JSBool -convert_js_obj_to_JSObject_wrapper(JSContext *cx, JNIEnv *jEnv, JSObject *js_obj, - JavaSignature *signature, - int *cost, jobject *java_value) -{ - if (!njJSObject) { - if (java_value) - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_CANT_LOAD_JSOBJECT); - return JS_FALSE; - } - - if (!(*jEnv)->IsAssignableFrom(jEnv, njJSObject, signature->java_class)) - return JS_FALSE; - - if (!java_value) - return JS_TRUE; - - *java_value = jsj_WrapJSObject(cx, jEnv, js_obj); - - return (*java_value != NULL); -} - -/* Copy an array from JS to Java; Create a new Java array and populate its - elements, one by one, with the result of converting each JS array element - to the type of the array component. */ -static JSBool -convert_js_array_to_java_array(JSContext *cx, JNIEnv *jEnv, JSObject *js_array, - JavaSignature *signature, - jobject *java_valuep) -{ - jsuint i; - jsval js_val; - jsuint length; - jclass component_class; - jarray java_array; - JavaSignature *array_component_signature; - - if (!JS_GetArrayLength(cx, js_array, &length)) - return JS_FALSE; - - /* Get the Java class of each element of the array */ - array_component_signature = signature->array_component_signature; - component_class = array_component_signature->java_class; - - /* Create a new empty Java array with the same length as the JS array */ - java_array = (*jEnv)->CallStaticObjectMethod(jEnv, jlrArray, jlrArray_newInstance, - component_class, length); - if (!java_array) { - jsj_ReportJavaError(cx, jEnv, "Error while constructing empty array of %s", - jsj_GetJavaClassName(cx, jEnv, component_class)); - return JS_FALSE; - } - - /* Convert each element of the JS array to an element of the Java array. - If an error occurs, there is no need to worry about releasing the - individual elements of the Java array - they will eventually be GC'ed - by the JVM. */ - for (i = 0; i < length; i++) { - if (!JS_LookupElement(cx, js_array, i, &js_val)) - return JS_FALSE; - - if (!jsj_SetJavaArrayElement(cx, jEnv, java_array, i, array_component_signature, js_val)) - return JS_FALSE; - } - - /* Return the result array */ - *java_valuep = java_array; - return JS_TRUE; -} - -jstring -jsj_ConvertJSStringToJavaString(JSContext *cx, JNIEnv *jEnv, JSString *js_str) -{ - jstring result; - result = (*jEnv)->NewString(jEnv, JS_GetStringChars(js_str), - JS_GetStringLength(js_str)); - if (!result) { - jsj_UnexpectedJavaError(cx, jEnv, "Couldn't construct instance " - "of java.lang.String"); - } - return result; -} - -/* - * Convert a JS value to an instance of java.lang.Object or one of its subclasses, - * performing any necessary type coercion. If non-trivial coercion is required, - * the cost value is incremented. If the java_value pass-by-reference argument - * is non-NULL, the resulting Java value is stored there. - * - * Returns JS_TRUE if the conversion is possible, JS_FALSE otherwise - */ -JSBool -jsj_ConvertJSValueToJavaObject(JSContext *cx, JNIEnv *jEnv, jsval v, JavaSignature *signature, - int *cost, jobject *java_value, JSBool *is_local_refp) -{ - JSString *jsstr; - jclass target_java_class; - - JS_ASSERT(IS_REFERENCE_TYPE(signature->type)); - - /* Initialize to default case, in which no new Java object is - synthesized to perform the conversion and, therefore, no JNI local - references are being held. */ - *is_local_refp = JS_FALSE; - - /* Get the Java type of the target value */ - target_java_class = signature->java_class; - - if (JSVAL_IS_OBJECT(v)) { - JSObject *js_obj = JSVAL_TO_OBJECT(v); - - /* JS null is always assignable to a Java object */ - if (!js_obj) { - if (java_value) - *java_value = NULL; - return JS_TRUE; - } - - if (JS_InstanceOf(cx, js_obj, &JavaObject_class, 0) || - JS_InstanceOf(cx, js_obj, &JavaArray_class, 0)) { - - /* The source value is a Java object wrapped inside a JavaScript - object. Unwrap the JS object and return the original Java - object if it's class makes it assignment-compatible with the - target class using Java's assignability rules. */ - JavaObjectWrapper *java_wrapper = JS_GetPrivate(cx, js_obj); - jobject java_obj = java_wrapper->java_obj; - - if ((*jEnv)->IsInstanceOf(jEnv, java_obj, target_java_class)) { - if (java_value) - *java_value = java_obj; - return JS_TRUE; - } - - /* Fall through, to attempt conversion to a Java string */ - - } else if (JS_InstanceOf(cx, js_obj, &JavaClass_class, 0)) { - /* We're dealing with the reflection of a Java class */ - JavaClassDescriptor *java_class_descriptor = JS_GetPrivate(cx, js_obj); - - /* Check if target type is java.lang.Class class */ - if ((*jEnv)->IsAssignableFrom(jEnv, jlClass, target_java_class)) { - if (java_value) - *java_value = java_class_descriptor->java_class; - return JS_TRUE; - } - - /* Check if target type is netscape.javascript.JSObject wrapper class */ - if (convert_js_obj_to_JSObject_wrapper(cx, jEnv, js_obj, signature, cost, java_value)) { - if (java_value && *java_value) - *is_local_refp = JS_TRUE; - return JS_TRUE; - } - - /* Fall through, to attempt conversion to a Java string */ - - } else if (JS_InstanceOf(cx, js_obj, &JavaMember_class, 0)) { - - if (!JS_ConvertValue(cx, v, JSTYPE_OBJECT, &v)) - return JS_FALSE; - return jsj_ConvertJSValueToJavaObject(cx, jEnv, v, signature, cost, - java_value, is_local_refp); - - /* JS Arrays are converted, element by element, to Java arrays */ - } else if (JS_IsArrayObject(cx, js_obj) && (signature->type == JAVA_SIGNATURE_ARRAY)) { - if (convert_js_array_to_java_array(cx, jEnv, js_obj, signature, java_value)) { - if (java_value && *java_value) - *is_local_refp = JS_TRUE; - return JS_TRUE; - } - return JS_FALSE; - - } else { - /* Otherwise, see if the target type is the netscape.javascript.JSObject - wrapper class or one of its subclasses, in which case a - reference is passed to the original JS object by wrapping it - inside an instance of netscape.javascript.JSObject */ - if (convert_js_obj_to_JSObject_wrapper(cx, jEnv, js_obj, signature, cost, java_value)) { - if (java_value && *java_value) - *is_local_refp = JS_TRUE; - return JS_TRUE; - } - - /* Fall through, to attempt conversion to a Java string */ - } - - } else if (JSVAL_IS_NUMBER(v)) { - /* JS numbers, integral or not, can be converted to instances of java.lang.Double */ - if ((*jEnv)->IsAssignableFrom(jEnv, jlDouble, target_java_class)) { - if (java_value) { - jsdouble d; - if (!JS_ValueToNumber(cx, v, &d)) - goto conversion_error; - *java_value = (*jEnv)->NewObject(jEnv, jlDouble, jlDouble_Double, d); - if (*java_value) { - *is_local_refp = JS_TRUE; - } else { - jsj_UnexpectedJavaError(cx, jEnv, - "Couldn't construct instance of java.lang.Double"); - return JS_FALSE; - } - } - - return JS_TRUE; - } - /* Fall through, to attempt conversion to a java.lang.String ... */ - - } else if (JSVAL_IS_BOOLEAN(v)) { - /* JS boolean values can be converted to instances of java.lang.Boolean */ - if ((*jEnv)->IsAssignableFrom(jEnv, jlBoolean, target_java_class)) { - if (java_value) { - JSBool b; - if (!JS_ValueToBoolean(cx, v, &b)) - goto conversion_error; - *java_value = - (*jEnv)->NewObject(jEnv, jlBoolean, jlBoolean_Boolean, b); - if (*java_value) { - *is_local_refp = JS_TRUE; - } else { - jsj_UnexpectedJavaError(cx, jEnv, "Couldn't construct instance " - "of java.lang.Boolean"); - return JS_FALSE; - } - } - - return JS_TRUE; - } - /* Fall through, to attempt conversion to a java.lang.String ... */ - } - - /* If the source JS type is either a string or undefined, or if no conversion - is possible from a number, boolean or JS object, see if the target type is - java.lang.String */ - if ((*jEnv)->IsAssignableFrom(jEnv, jlString, target_java_class)) { - - /* Convert to JS string, if necessary, and then to a Java Unicode string */ - jsstr = JS_ValueToString(cx, v); - if (jsstr) { - if (java_value) { - *java_value = jsj_ConvertJSStringToJavaString(cx, jEnv, jsstr); - if (*java_value) { - *is_local_refp = JS_TRUE; - } else { - return JS_FALSE; - } - } - - return JS_TRUE; - } - } - -conversion_error: - return JS_FALSE; -} - -/* Valid ranges for Java numeric types */ -#define jbyte_MAX_VALUE 127.0 -#define jbyte_MIN_VALUE -128.0 -#define jchar_MAX_VALUE 65535.0 -#define jchar_MIN_VALUE 0.0 -#define jshort_MAX_VALUE 32767.0 -#define jshort_MIN_VALUE -32768.0 -#define jint_MAX_VALUE 2147483647.0 -#define jint_MIN_VALUE -2147483648.0 -#define jlong_MAX_VALUE 9223372036854775807.0 -#define jlong_MIN_VALUE -9223372036854775808.0 - -/* Utility macro for jsj_ConvertJSValueToJavaValue(), below */ -#define JSVAL_TO_INTEGRAL_JVALUE(type_name, member_name, member_type, jsval, java_value) \ - if (!JSVAL_IS_NUMBER(v)) { \ - if (!JS_ConvertValue(cx, v, JSTYPE_NUMBER, &v)) \ - goto conversion_error; \ - (*cost)++; \ - } \ - { \ - member_type member_name; \ - \ - if (JSVAL_IS_INT(v)) { \ - jsint ival = JSVAL_TO_INT(v); \ - member_name = (member_type) ival; \ - \ - /* Check to see if the jsval's magnitude is too large to be \ - representable in the target java type */ \ - if (member_name != ival) \ - goto numeric_conversion_error; \ - } else { \ - jdouble dval = *JSVAL_TO_DOUBLE(v); \ - \ - /* NaN becomes zero when converted to integral value */ \ - if (JSDOUBLE_IS_NaN(dval)) \ - goto numeric_conversion_error; \ - \ - /* Unrepresentably large numbers, including infinities, */ \ - /* cause an error. */ \ - else if ((dval >= member_type ## _MAX_VALUE + 1) || \ - (dval <= member_type ## _MIN_VALUE - 1)) { \ - goto numeric_conversion_error; \ - } else \ - member_name = (member_type) dval; \ - \ - /* Don't allow a non-integral number to be converted \ - to an integral type */ \ - /* Actually, we have to allow this for LC1 compatibility */ \ - /* if ((jdouble)member_name != dval) \ - (*cost)++; */ \ - } \ - if (java_value) \ - java_value->member_name = member_name; \ - } - -#ifdef XP_OS2 - -/* OS2 utility macro for jsj_ConvertJSValueToJavaValue(), below */ -/* jlong is a structure, see jri_md.h, where the jlong_ macros are defined. */ -#define JSVAL_TO_JLONG_JVALUE(member_name, member_type, jsvalue, java_value) \ - if (!JSVAL_IS_NUMBER(jsvalue)) { \ - if (!JS_ConvertValue(cx, jsvalue, JSTYPE_NUMBER, &jsvalue)) \ - goto conversion_error; \ - (*cost)++; \ - } \ - { \ - member_type member_name; \ - \ - if (JSVAL_IS_INT(jsvalue)) { \ - jsint ival = JSVAL_TO_INT(jsvalue); \ - jlong_I2L(member_name,ival); \ - \ - } else { \ - jdouble dval = *JSVAL_TO_DOUBLE(jsvalue); \ - \ - /* NaN becomes zero when converted to integral value */ \ - if (JSDOUBLE_IS_NaN(dval)) \ - jlong_I2L(member_name,0); \ - \ - /* Unrepresentably large numbers, including infinities, */ \ - /* cause an error. */ \ - else if ((dval > member_type ## _MAX_VALUE) || \ - (dval < member_type ## _MIN_VALUE)) { \ - goto numeric_conversion_error; \ - } else \ - jlong_D2L(member_name,dval); \ - \ - /* Don't allow a non-integral number to be converted \ - to an integral type */ \ - /* Actually, we have to allow this for LC1 compatibility */ \ - /*if (jlong_to_jdouble(member_name) != dval) \ - (*cost)++;*/ \ - } \ - if (java_value) \ - java_value->member_name = member_name; \ - } - -static jdouble jlong_to_jdouble(jlong lvalue) -{ - jdouble d; - jlong_L2D(d,lvalue); - return d; -} - -#else - -#define jlong_to_jdouble(lvalue) ((jdouble) lvalue) - -#endif - -/* - * Convert a JS value to a Java value of the given type signature. The cost - * variable is incremented if coercion is required, e.g. the source value is - * a string, but the target type is a boolean. - * - * Returns JS_FALSE if no conversion is possible, either because the jsval has - * a type that is wholly incompatible with the Java value, or because a scalar - * jsval can't be represented in a variable of the target type without loss of - * precision, e.g. the source value is "4.2" but the destination type is byte. - * If conversion is not possible and java_value is non-NULL, the JS error - * reporter is called with an appropriate message. - */ -JSBool -jsj_ConvertJSValueToJavaValue(JSContext *cx, JNIEnv *jEnv, jsval v_arg, - JavaSignature *signature, - int *cost, jvalue *java_value, JSBool *is_local_refp) -{ - JavaSignatureChar type; - jsval v; - JSBool success = JS_FALSE; - - /* Initialize to default case, in which no new Java object is - synthesized to perform the conversion and, therefore, no JNI local - references are being held. */ - *is_local_refp = JS_FALSE; - - type = signature->type; - v = v_arg; - switch (type) { - case JAVA_SIGNATURE_BOOLEAN: - if (!JSVAL_IS_BOOLEAN(v)) { - if (!JS_ConvertValue(cx, v, JSTYPE_BOOLEAN, &v)) - goto conversion_error; - if (JSVAL_IS_VOID(v)) - goto conversion_error; - (*cost)++; - } - if (java_value) - java_value->z = (jboolean)(JSVAL_TO_BOOLEAN(v) == JS_TRUE); - break; - - case JAVA_SIGNATURE_SHORT: - JSVAL_TO_INTEGRAL_JVALUE(short, s, jshort, v, java_value); - break; - - case JAVA_SIGNATURE_BYTE: - JSVAL_TO_INTEGRAL_JVALUE(byte, b, jbyte, v, java_value); - break; - - case JAVA_SIGNATURE_CHAR: - /* A one-character string can be converted into a character */ - if (JSVAL_IS_STRING(v) && (JS_GetStringLength(JSVAL_TO_STRING(v)) == 1)) { - v = INT_TO_JSVAL(*JS_GetStringChars(JSVAL_TO_STRING(v))); - } - JSVAL_TO_INTEGRAL_JVALUE(char, c, jchar, v, java_value); - break; - - case JAVA_SIGNATURE_INT: - JSVAL_TO_INTEGRAL_JVALUE(int, i, jint, v, java_value); - break; - - case JAVA_SIGNATURE_LONG: -#if (defined(XP_OS2) && !defined(HAVE_LONG_LONG)) - JSVAL_TO_JLONG_JVALUE(j, jlong, v, java_value); -#else - JSVAL_TO_INTEGRAL_JVALUE(long, j, jlong, v, java_value); -#endif - break; - - case JAVA_SIGNATURE_FLOAT: - if (!JSVAL_IS_NUMBER(v)) { - if (!JS_ConvertValue(cx, v, JSTYPE_NUMBER, &v)) - goto conversion_error; - (*cost)++; - } - if (java_value) { - if (JSVAL_IS_INT(v)) - java_value->f = (jfloat) JSVAL_TO_INT(v); - else - java_value->f = (jfloat) *JSVAL_TO_DOUBLE(v); - } - break; - - case JAVA_SIGNATURE_DOUBLE: - if (!JSVAL_IS_NUMBER(v)) { - if (!JS_ConvertValue(cx, v, JSTYPE_NUMBER, &v)) - goto conversion_error; - (*cost)++; - } - if (java_value) { - if (JSVAL_IS_INT(v)) - java_value->d = (jdouble) JSVAL_TO_INT(v); - else - java_value->d = (jdouble) *JSVAL_TO_DOUBLE(v); - } - break; - - /* Non-primitive (reference) type */ - default: - JS_ASSERT(IS_REFERENCE_TYPE(type)); - if (!jsj_ConvertJSValueToJavaObject(cx, jEnv, v, signature, cost, - &java_value->l, is_local_refp)) - goto conversion_error; - break; - - case JAVA_SIGNATURE_UNKNOWN: - case JAVA_SIGNATURE_VOID: - JS_ASSERT(0); - return JS_FALSE; - } - - /* Success */ - return JS_TRUE; - -numeric_conversion_error: - success = JS_TRUE; - /* Fall through ... */ - -conversion_error: - - if (java_value) { - const char *jsval_string; - const char *class_name; - JSString *jsstr; - - jsval_string = NULL; - jsstr = JS_ValueToString(cx, v_arg); - if (jsstr) - jsval_string = JS_GetStringBytes(jsstr); - if (!jsval_string) - jsval_string = ""; - - class_name = jsj_ConvertJavaSignatureToHRString(cx, signature); - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_CANT_CONVERT_JS, jsval_string, - class_name); - - return JS_FALSE; - } - return success; -} - -/* - * A utility routine to create a JavaScript Unicode string from a - * java.lang.String (Unicode) string. - */ -JSString * -jsj_ConvertJavaStringToJSString(JSContext *cx, JNIEnv *jEnv, jstring java_str) -{ - JSString *js_str; - jboolean is_copy; - const jchar *ucs2_str; - jsize ucs2_str_len; - - ucs2_str_len = (*jEnv)->GetStringLength(jEnv, java_str); - ucs2_str = (*jEnv)->GetStringChars(jEnv, java_str, &is_copy); - if (!ucs2_str) { - jsj_UnexpectedJavaError(cx, jEnv, - "Unable to extract native Unicode from Java string"); - return NULL; - } - - /* The string data passed into JS_NewUCString() is - not copied, so make a copy of the Unicode character vector. */ - js_str = JS_NewUCStringCopyN(cx, ucs2_str, ucs2_str_len); - - (*jEnv)->ReleaseStringChars(jEnv, java_str, ucs2_str); - return js_str; -} - -/* - * Attempt to obtain a JS string representation of a Java object. - * The java_obj argument must be of type java.lang.Object or a subclass. - * If java_obj is a Java string, it's value is simply extracted and - * copied into a JS string. Otherwise, the toString() method is called - * on java_obj. - */ -JSBool -jsj_ConvertJavaObjectToJSString(JSContext *cx, - JNIEnv *jEnv, - JavaClassDescriptor *class_descriptor, - jobject java_obj, jsval *vp) -{ - JSString *js_str; - jstring java_str; - jmethodID toString; - jclass java_class; - - /* Create a Java string, unless java_obj is already a java.lang.String */ - if ((*jEnv)->IsInstanceOf(jEnv, java_obj, jlString)) { - - /* Extract Unicode from java.lang.String instance and convert to JS string */ - js_str = jsj_ConvertJavaStringToJSString(cx, jEnv, java_obj); - if (!js_str) - return JS_FALSE; - *vp = STRING_TO_JSVAL(js_str); - return JS_TRUE; - } - - java_class = class_descriptor->java_class; - toString = (*jEnv)->GetMethodID(jEnv, java_class, "toString", - "()Ljava/lang/String;"); - if (!toString) { - /* All Java objects have a toString method */ - jsj_UnexpectedJavaError(cx, jEnv, "No toString() method for class %s!", - class_descriptor->name); - return JS_FALSE; - } - java_str = (*jEnv)->CallObjectMethod(jEnv, java_obj, toString); - if (!java_str) { - jsj_ReportJavaError(cx, jEnv, "toString() method failed"); - return JS_FALSE; - } - - /* Extract Unicode from java.lang.String instance and convert to JS string */ - js_str = jsj_ConvertJavaStringToJSString(cx, jEnv, java_str); - if (!js_str) { - (*jEnv)->DeleteLocalRef(jEnv, java_str); - return JS_FALSE; - } - - *vp = STRING_TO_JSVAL(js_str); - (*jEnv)->DeleteLocalRef(jEnv, java_str); - return JS_TRUE; -} - -/* - * Convert a Java object to a number by attempting to call the - * doubleValue() method on a Java object to get a double result. - * This usually only works on instances of java.lang.Double, but the code - * is generalized to work with any Java object that supports this method. - * - * Returns JS_TRUE if the call was successful. - * Returns JS_FALSE if conversion is not possible or an error occurs. - */ -JSBool -jsj_ConvertJavaObjectToJSNumber(JSContext *cx, JNIEnv *jEnv, - JavaClassDescriptor *class_descriptor, - jobject java_obj, jsval *vp) -{ - jdouble d; - jmethodID doubleValue; - jclass java_class; - - java_class = class_descriptor->java_class; - doubleValue = (*jEnv)->GetMethodID(jEnv, java_class, "doubleValue", "()D"); - if (!doubleValue) { - /* There is no doubleValue() method for the object. Try toString() - instead and the JS engine will attempt to convert the result to - a number. */ - (*jEnv)->ExceptionClear(jEnv); - return jsj_ConvertJavaObjectToJSString(cx, jEnv, class_descriptor, - java_obj, vp); - } - /* - * Sun Java-Plugin team work around bug to be fixed in JRE1.5, where GetMethodID - * called with a non-existent method name returns a non-null result. - * See Mozilla bug 201164. - */ - if ((*jEnv)->ExceptionOccurred(jEnv)) { - jsj_UnexpectedJavaError(cx, jEnv, "No doubleValue() method for class %s!", - class_descriptor->name); - return JS_FALSE; - } - - d = (*jEnv)->CallDoubleMethod(jEnv, java_obj, doubleValue); - if ((*jEnv)->ExceptionOccurred(jEnv)) { - jsj_UnexpectedJavaError(cx, jEnv, "doubleValue() method failed"); - return JS_FALSE; - } - return JS_NewDoubleValue(cx, d, vp); -} - -/* - * Convert a Java object to a boolean by attempting to call the - * booleanValue() method on a Java object to get a boolean result. - * This usually only works on instances of java.lang.Boolean, but the code - * is generalized to work with any Java object that supports this method. - * - * Returns JS_TRUE if the call was successful. - * Returns JS_FALSE if conversion is not possible or an error occurs. - */ -extern JSBool -jsj_ConvertJavaObjectToJSBoolean(JSContext *cx, JNIEnv *jEnv, - JavaClassDescriptor *class_descriptor, - jobject java_obj, jsval *vp) -{ - jboolean b; - jmethodID booleanValue; - jclass java_class; - - /* Null converts to false. */ - if (!java_obj) { - *vp = JSVAL_FALSE; - return JS_TRUE; - } - java_class = class_descriptor->java_class; - booleanValue = (*jEnv)->GetMethodID(jEnv, java_class, "booleanValue", "()Z"); - - /* Non-null Java object does not have a booleanValue() method, so - it converts to true. */ - if (!booleanValue) { - (*jEnv)->ExceptionClear(jEnv); - *vp = JSVAL_TRUE; - return JS_TRUE; - } - - b = (*jEnv)->CallBooleanMethod(jEnv, java_obj, booleanValue); - if ((*jEnv)->ExceptionOccurred(jEnv)) { - jsj_UnexpectedJavaError(cx, jEnv, "booleanValue() method failed"); - return JS_FALSE; - } - *vp = BOOLEAN_TO_JSVAL(b); - return JS_TRUE; -} - -/* - * Reflect a Java object into a JS value. The source object, java_obj, must - * be of type java.lang.Object or a subclass and may, therefore, be an array. - */ -JSBool -jsj_ConvertJavaObjectToJSValue(JSContext *cx, JNIEnv *jEnv, - jobject java_obj, jsval *vp) -{ - jclass java_class; - JSObject *js_obj; - - /* A null in Java-land is also null in JS */ - if (!java_obj) { - *vp = JSVAL_NULL; - return JS_TRUE; - } - - java_class = (*jEnv)->GetObjectClass(jEnv, java_obj); - - /* - * If it's an instance of netscape.javascript.JSObject, i.e. a wrapper - * around a JS object that has been passed into the Java world, unwrap - * it to obtain the original JS object. - */ - if (njJSObject && (*jEnv)->IsInstanceOf(jEnv, java_obj, njJSObject)) { -#ifdef PRESERVE_JSOBJECT_IDENTITY -#if JS_BYTES_PER_LONG == 8 - js_obj = (JSObject *)((*jEnv)->GetLongField(jEnv, java_obj, njJSObject_long_internal)); -#else - js_obj = (JSObject *)((*jEnv)->GetIntField(jEnv, java_obj, njJSObject_internal)); -#endif -#else - js_obj = jsj_UnwrapJSObjectWrapper(jEnv, java_obj); -#endif - /* NULL is actually a valid value. It means 'null'. - - JS_ASSERT(js_obj); - if (!js_obj) - goto error; - */ - - *vp = OBJECT_TO_JSVAL(js_obj); - goto done; - } - - /* otherwise, wrap it inside a JavaObject */ - js_obj = jsj_WrapJavaObject(cx, jEnv, java_obj, java_class); - if (!js_obj) - goto error; - *vp = OBJECT_TO_JSVAL(js_obj); - -done: - (*jEnv)->DeleteLocalRef(jEnv, java_class); - return JS_TRUE; - -error: - (*jEnv)->DeleteLocalRef(jEnv, java_class); - return JS_FALSE; -} - -/* - * Convert a Java value (primitive or object) to a JS value. - * - * This is usually an infallible operation, but JS_FALSE is returned - * on an out-of-memory condition and the error reporter is called. - */ -JSBool -jsj_ConvertJavaValueToJSValue(JSContext *cx, JNIEnv *jEnv, - JavaSignature *signature, - jvalue *java_value, - jsval *vp) -{ - int32 ival32; - - switch (signature->type) { - case JAVA_SIGNATURE_VOID: - *vp = JSVAL_VOID; - return JS_TRUE; - - case JAVA_SIGNATURE_BYTE: - *vp = INT_TO_JSVAL((jsint)java_value->b); - return JS_TRUE; - - case JAVA_SIGNATURE_CHAR: - *vp = INT_TO_JSVAL((jsint)java_value->c); - return JS_TRUE; - - case JAVA_SIGNATURE_SHORT: - *vp = INT_TO_JSVAL((jsint)java_value->s); - return JS_TRUE; - - case JAVA_SIGNATURE_INT: - ival32 = java_value->i; - if (INT_FITS_IN_JSVAL(ival32)) { - *vp = INT_TO_JSVAL((jsint) ival32); - return JS_TRUE; - } else { - return JS_NewDoubleValue(cx, ival32, vp); - } - - case JAVA_SIGNATURE_BOOLEAN: - *vp = BOOLEAN_TO_JSVAL((JSBool) java_value->z); - return JS_TRUE; - - case JAVA_SIGNATURE_LONG: - return JS_NewDoubleValue(cx, jlong_to_jdouble(java_value->j), vp); - - case JAVA_SIGNATURE_FLOAT: - return JS_NewDoubleValue(cx, java_value->f, vp); - - case JAVA_SIGNATURE_DOUBLE: - return JS_NewDoubleValue(cx, java_value->d, vp); - - case JAVA_SIGNATURE_UNKNOWN: - JS_ASSERT(0); - return JS_FALSE; - - /* Non-primitive (reference) type */ - default: - JS_ASSERT(IS_REFERENCE_TYPE(signature->type)); - return jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_value->l, vp); - - } -} - diff --git a/lib/javascript/liveconnect/jsj_field.c b/lib/javascript/liveconnect/jsj_field.c deleted file mode 100644 index 45bebf9b..00000000 --- a/lib/javascript/liveconnect/jsj_field.c +++ /dev/null @@ -1,421 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * This file is part of the Java-vendor-neutral implementation of LiveConnect - * - * It contains the code used to reflect Java fields as properties of - * JavaObject objects and the code to access those fields. - * - */ - -#include - -#include "jsj_private.h" /* LiveConnect internals */ - -/* - * Add a single field, described by java_field, to the JavaMemberDescriptor - * named by field_name within the given JavaClassDescriptor. - * - * Returns JS_TRUE on success. Otherwise, returns JS_FALSE and reports an error. - */ -static JSBool -add_java_field_to_class_descriptor(JSContext *cx, - JNIEnv *jEnv, - JavaClassDescriptor *class_descriptor, - jstring field_name_jstr, - jobject java_field, /* a java.lang.reflect.Field */ - jint modifiers) -{ - jclass fieldType; - jfieldID fieldID; - jclass java_class; - - JSBool is_static_field; - JavaMemberDescriptor *member_descriptor = NULL; - const char *sig_cstr = NULL; - const char *field_name = NULL; - JavaSignature *signature = NULL; - JavaFieldSpec *field_spec = NULL; - - is_static_field = modifiers & ACC_STATIC; - if (is_static_field) { - member_descriptor = jsj_GetJavaStaticMemberDescriptor(cx, jEnv, class_descriptor, field_name_jstr); - } else { - member_descriptor = jsj_GetJavaMemberDescriptor(cx, jEnv, class_descriptor, field_name_jstr); - } - if (!member_descriptor) - goto error; - - field_spec = (JavaFieldSpec*)JS_malloc(cx, sizeof(JavaFieldSpec)); - if (!field_spec) - goto error; - - field_spec->modifiers = modifiers; - - /* Get the Java class corresponding to the type of the field */ - fieldType = (*jEnv)->CallObjectMethod(jEnv, java_field, jlrField_getType); - if (!fieldType) { - jsj_UnexpectedJavaError(cx, jEnv, - "Unable to determine type of field using" - " java.lang.reflect.Field.getType()"); - goto error; - } - - signature = jsj_GetJavaClassDescriptor(cx, jEnv, fieldType); - (*jEnv)->DeleteLocalRef(jEnv, fieldType); - if (!signature) - goto error; - field_spec->signature = signature; - - field_name = jsj_DupJavaStringUTF(cx, jEnv, field_name_jstr); - if (!field_name) - goto error; - field_spec->name = field_name; - - /* Compute the JNI-style (string-based) signature of the field type */ - sig_cstr = jsj_ConvertJavaSignatureToString(cx, signature); - if (!sig_cstr) - goto error; - - /* Compute the JNI fieldID and cache it for quick field access */ - java_class = class_descriptor->java_class; - if (is_static_field) - fieldID = (*jEnv)->GetStaticFieldID(jEnv, java_class, field_name, sig_cstr); - else - fieldID = (*jEnv)->GetFieldID(jEnv, java_class, field_name, sig_cstr); - if (!fieldID) { - jsj_UnexpectedJavaError(cx, jEnv, - "Can't get Java field ID for class %s, field %s (sig=%s)", - class_descriptor->name, field_name, sig_cstr); - goto error; - } - field_spec->fieldID = fieldID; - - JS_free(cx, (char*)sig_cstr); - - member_descriptor->field = field_spec; - - /* Success */ - return JS_TRUE; - -error: - if (field_spec) { - JS_FREE_IF(cx, (char*)field_spec->name); - JS_free(cx, field_spec); - } - JS_FREE_IF(cx, (char*)sig_cstr); - if (signature) - jsj_ReleaseJavaClassDescriptor(cx, jEnv, signature); - return JS_FALSE; -} - -/* - * Free up a JavaFieldSpec and all its resources. - */ -void -jsj_DestroyFieldSpec(JSContext *cx, JNIEnv *jEnv, JavaFieldSpec *field) -{ - JS_FREE_IF(cx, (char*)field->name); - jsj_ReleaseJavaClassDescriptor(cx, jEnv, field->signature); - JS_free(cx, field); -} - -/* - * Add a JavaMemberDescriptor to the collection of members in class_descriptor - * for every public field of the identified Java class. (A separate collection - * is kept in class_descriptor for static and instance members.) - * If reflect_only_static_fields is set, instance fields are not reflected. If - * it isn't set, only instance fields are reflected and static fields are not - * reflected. - * - * Returns JS_TRUE on success. Otherwise, returns JS_FALSE and reports an error. - */ -JSBool -jsj_ReflectJavaFields(JSContext *cx, JNIEnv *jEnv, JavaClassDescriptor *class_descriptor, - JSBool reflect_only_static_fields) -{ - int i; - JSBool ok; - jint modifiers; - jobject java_field; - jstring field_name_jstr; - jarray joFieldArray; - jsize num_fields; - jclass java_class; - - /* Get a java array of java.lang.reflect.Field objects, by calling - java.lang.Class.getFields(). */ - java_class = class_descriptor->java_class; - joFieldArray = (*jEnv)->CallObjectMethod(jEnv, java_class, jlClass_getFields); - if (!joFieldArray) { - jsj_UnexpectedJavaError(cx, jEnv, - "Can't determine Java object's fields " - "using java.lang.Class.getFields()"); - return JS_FALSE; - } - - /* Iterate over the class fields */ - num_fields = (*jEnv)->GetArrayLength(jEnv, joFieldArray); - for (i = 0; i < num_fields; i++) { - - /* Get the i'th reflected field */ - java_field = (*jEnv)->GetObjectArrayElement(jEnv, joFieldArray, i); - if (!java_field) { - jsj_UnexpectedJavaError(cx, jEnv, "Can't access a Field[] array"); - return JS_FALSE; - } - - /* Get the field modifiers, e.g. static, public, private, etc. */ - modifiers = (*jEnv)->CallIntMethod(jEnv, java_field, jlrField_getModifiers); - if ((*jEnv)->ExceptionOccurred(jEnv)) { - jsj_UnexpectedJavaError(cx, jEnv, - "Can't access a Field's modifiers using" - "java.lang.reflect.Field.getModifiers()"); - return JS_FALSE; - } - - /* Don't allow access to private or protected Java fields. */ - if (!(modifiers & ACC_PUBLIC)) - goto no_reflect; - - /* Reflect all instance fields or all static fields, but not both */ - if (reflect_only_static_fields != ((modifiers & ACC_STATIC) != 0)) - goto no_reflect; - - /* Determine the unqualified name of the field */ - field_name_jstr = (*jEnv)->CallObjectMethod(jEnv, java_field, jlrField_getName); - if (!field_name_jstr) { - jsj_UnexpectedJavaError(cx, jEnv, - "Can't obtain a Field's name" - "java.lang.reflect.Field.getName()"); - return JS_FALSE; - } - - /* Add a JavaFieldSpec object to the JavaClassDescriptor */ - ok = add_java_field_to_class_descriptor(cx, jEnv, class_descriptor, field_name_jstr, - java_field, modifiers); - if (!ok) - return JS_FALSE; - - (*jEnv)->DeleteLocalRef(jEnv, field_name_jstr); - field_name_jstr = NULL; - -no_reflect: - (*jEnv)->DeleteLocalRef(jEnv, java_field); - java_field = NULL; - } - - (*jEnv)->DeleteLocalRef(jEnv, joFieldArray); - - /* Success */ - return JS_TRUE; -} - -/* - * Read the value of a Java field and return it as a JavaScript value. - * If the field is static, then java_obj is a Java class, otherwise - * it's a Java instance object. - * - * Returns JS_TRUE on success. Otherwise, returns JS_FALSE and reports an error. - */ -JSBool -jsj_GetJavaFieldValue(JSContext *cx, JNIEnv *jEnv, JavaFieldSpec *field_spec, - jobject java_obj, jsval *vp) -{ - JSBool is_static_field, success; - jvalue java_value; - JavaSignature *signature; - JavaSignatureChar field_type; - jfieldID fieldID = field_spec->fieldID; - - is_static_field = field_spec->modifiers & ACC_STATIC; - -#define GET_JAVA_FIELD(Type,member) \ - JS_BEGIN_MACRO \ - if (is_static_field) \ - java_value.member = \ - (*jEnv)->GetStatic##Type##Field(jEnv, (*jEnv)->GetObjectClass(jEnv, java_obj), fieldID); \ - else \ - java_value.member = \ - (*jEnv)->Get##Type##Field(jEnv, java_obj, fieldID); \ - if ((*jEnv)->ExceptionOccurred(jEnv)) { \ - jsj_UnexpectedJavaError(cx, jEnv, "Error reading Java field"); \ - return JS_FALSE; \ - } \ - JS_END_MACRO - - signature = field_spec->signature; - field_type = signature->type; - switch(field_type) { - case JAVA_SIGNATURE_BYTE: - GET_JAVA_FIELD(Byte,b); - break; - - case JAVA_SIGNATURE_CHAR: - GET_JAVA_FIELD(Char,c); - break; - - case JAVA_SIGNATURE_SHORT: - GET_JAVA_FIELD(Short,s); - break; - - case JAVA_SIGNATURE_INT: - GET_JAVA_FIELD(Int,i); - break; - - case JAVA_SIGNATURE_BOOLEAN: - GET_JAVA_FIELD(Boolean,z); - break; - - case JAVA_SIGNATURE_LONG: - GET_JAVA_FIELD(Long,j); - break; - - case JAVA_SIGNATURE_FLOAT: - GET_JAVA_FIELD(Float,f); - break; - - case JAVA_SIGNATURE_DOUBLE: - GET_JAVA_FIELD(Double,d); - break; - - case JAVA_SIGNATURE_UNKNOWN: - case JAVA_SIGNATURE_VOID: - JS_ASSERT(0); /* Unknown java type signature */ - return JS_FALSE; - - /* Non-primitive (reference) type */ - default: - JS_ASSERT(IS_REFERENCE_TYPE(field_type)); - GET_JAVA_FIELD(Object,l); - success = jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_value.l, vp); - (*jEnv)->DeleteLocalRef(jEnv, java_value.l); - return success; - } - -#undef GET_JAVA_FIELD - - return jsj_ConvertJavaValueToJSValue(cx, jEnv, signature, &java_value, vp); -} - -JSBool -jsj_SetJavaFieldValue(JSContext *cx, JNIEnv *jEnv, JavaFieldSpec *field_spec, - jclass java_obj, jsval js_val) -{ - JSBool is_static_field, is_local_ref; - int dummy_cost; - jvalue java_value; - JavaSignature *signature; - JavaSignatureChar field_type; - jfieldID fieldID = field_spec->fieldID; - - is_static_field = field_spec->modifiers & ACC_STATIC; - -#define SET_JAVA_FIELD(Type,member) \ - JS_BEGIN_MACRO \ - if (is_static_field) { \ - (*jEnv)->SetStatic##Type##Field(jEnv, java_obj, fieldID, \ - java_value.member); \ - } else { \ - (*jEnv)->Set##Type##Field(jEnv, java_obj, fieldID,java_value.member);\ - } \ - if ((*jEnv)->ExceptionOccurred(jEnv)) { \ - jsj_UnexpectedJavaError(cx, jEnv, "Error assigning to Java field"); \ - return JS_FALSE; \ - } \ - JS_END_MACRO - - signature = field_spec->signature; - if (!jsj_ConvertJSValueToJavaValue(cx, jEnv, js_val, signature, &dummy_cost, - &java_value, &is_local_ref)) - return JS_FALSE; - - field_type = signature->type; - switch(field_type) { - case JAVA_SIGNATURE_BYTE: - SET_JAVA_FIELD(Byte,b); - break; - - case JAVA_SIGNATURE_CHAR: - SET_JAVA_FIELD(Char,c); - break; - - case JAVA_SIGNATURE_SHORT: - SET_JAVA_FIELD(Short,s); - break; - - case JAVA_SIGNATURE_INT: - SET_JAVA_FIELD(Int,i); - break; - - case JAVA_SIGNATURE_BOOLEAN: - SET_JAVA_FIELD(Boolean,z); - break; - - case JAVA_SIGNATURE_LONG: - SET_JAVA_FIELD(Long,j); - break; - - case JAVA_SIGNATURE_FLOAT: - SET_JAVA_FIELD(Float,f); - break; - - case JAVA_SIGNATURE_DOUBLE: - SET_JAVA_FIELD(Double,d); - break; - - /* Non-primitive (reference) type */ - default: - JS_ASSERT(IS_REFERENCE_TYPE(field_type)); - SET_JAVA_FIELD(Object,l); - if (is_local_ref) - (*jEnv)->DeleteLocalRef(jEnv, java_value.l); - break; - - case JAVA_SIGNATURE_UNKNOWN: - case JAVA_SIGNATURE_VOID: - JS_ASSERT(0); /* Unknown java type signature */ - return JS_FALSE; - } - -#undef SET_JAVA_FIELD - - return JS_TRUE; -} diff --git a/lib/javascript/liveconnect/jsj_hash.c b/lib/javascript/liveconnect/jsj_hash.c deleted file mode 100644 index ca9d4941..00000000 --- a/lib/javascript/liveconnect/jsj_hash.c +++ /dev/null @@ -1,488 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * This is a copy of the NSPR hash-table library, but it has been slightly - * modified to allow an additional argument to be passed into the hash - * key-comparison function. This is used to maintain thread-safety by - * passing in a JNIEnv pointer to the key-comparison function rather - * than storing it in a global. All types,function names, etc. have - * been renamed from their original NSPR names to protect the innocent. - */ - -#include -#include - -#include "jsj_hash.h" -#include "jstypes.h" -#include "jsutil.h" -#include "jsbit.h" - - -/* Compute the number of buckets in ht */ -#define NBUCKETS(ht) (1 << (JSJ_HASH_BITS - (ht)->shift)) - -/* The smallest table has 16 buckets */ -#define MINBUCKETSLOG2 4 -#define MINBUCKETS (1 << MINBUCKETSLOG2) - -/* Compute the maximum entries given n buckets that we will tolerate, ~90% */ -#define OVERLOADED(n) ((n) - ((n) >> 3)) - -/* Compute the number of entries below which we shrink the table by half */ -#define UNDERLOADED(n) (((n) > MINBUCKETS) ? ((n) >> 2) : 0) - -/* -** Stubs for default hash allocator ops. -*/ -static void * -DefaultAllocTable(void *pool, size_t size) -{ - return malloc(size); -} - -static void -DefaultFreeTable(void *pool, void *item) -{ - free(item); -} - -static JSJHashEntry * -DefaultAllocEntry(void *pool, const void *key) -{ - return malloc(sizeof(JSJHashEntry)); -} - -static void -DefaultFreeEntry(void *pool, JSJHashEntry *he, JSUintn flag) -{ - if (flag == HT_FREE_ENTRY) - free(he); -} - -static JSJHashAllocOps defaultHashAllocOps = { - DefaultAllocTable, DefaultFreeTable, - DefaultAllocEntry, DefaultFreeEntry -}; - -JS_EXPORT_API(JSJHashTable *) -JSJ_NewHashTable(JSUint32 n, JSJHashFunction keyHash, - JSJHashComparator keyCompare, JSJHashComparator valueCompare, - JSJHashAllocOps *allocOps, void *allocPriv) -{ - JSJHashTable *ht; - JSUint32 nb; - - if (n <= MINBUCKETS) { - n = MINBUCKETSLOG2; - } else { - n = JS_CeilingLog2(n); - if ((JSInt32)n < 0) - return 0; - } - - if (!allocOps) allocOps = &defaultHashAllocOps; - - ht = (*allocOps->allocTable)(allocPriv, sizeof *ht); - if (!ht) - return 0; - memset(ht, 0, sizeof *ht); - ht->shift = JSJ_HASH_BITS - n; - n = 1 << n; -#if (defined(XP_WIN) || defined(XP_OS2)) && !defined(_WIN32) - if (n > 16000) { - (*allocOps->freeTable)(allocPriv, ht); - return 0; - } -#endif /* WIN16 */ - nb = n * sizeof(JSJHashEntry *); - ht->buckets = (*allocOps->allocTable)(allocPriv, nb); - if (!ht->buckets) { - (*allocOps->freeTable)(allocPriv, ht); - return 0; - } - memset(ht->buckets, 0, nb); - - ht->keyHash = keyHash; - ht->keyCompare = keyCompare; - ht->valueCompare = valueCompare; - ht->allocOps = allocOps; - ht->allocPriv = allocPriv; - return ht; -} - -JS_EXPORT_API(void) -JSJ_HashTableDestroy(JSJHashTable *ht) -{ - JSUint32 i, n; - JSJHashEntry *he, *next; - JSJHashAllocOps *allocOps = ht->allocOps; - void *allocPriv = ht->allocPriv; - - n = NBUCKETS(ht); - for (i = 0; i < n; i++) { - for (he = ht->buckets[i]; he; he = next) { - next = he->next; - (*allocOps->freeEntry)(allocPriv, he, HT_FREE_ENTRY); - } - } -#ifdef DEBUG - memset(ht->buckets, 0xDB, n * sizeof ht->buckets[0]); -#endif - (*allocOps->freeTable)(allocPriv, ht->buckets); -#ifdef DEBUG - memset(ht, 0xDB, sizeof *ht); -#endif - (*allocOps->freeTable)(allocPriv, ht); -} - -/* -** Multiplicative hash, from Knuth 6.4. -*/ -#define GOLDEN_RATIO 0x9E3779B9U - -JS_EXPORT_API(JSJHashEntry **) -JSJ_HashTableRawLookup(JSJHashTable *ht, JSJHashNumber keyHash, const void *key, void *arg) -{ - JSJHashEntry *he, **hep, **hep0; - JSJHashNumber h; - -#ifdef HASHMETER - ht->nlookups++; -#endif - h = keyHash * GOLDEN_RATIO; - h >>= ht->shift; - hep = hep0 = &ht->buckets[h]; - while ((he = *hep) != 0) { - if (he->keyHash == keyHash && (*ht->keyCompare)(key, he->key, arg)) { - /* Move to front of chain if not already there */ - if (hep != hep0) { - *hep = he->next; - he->next = *hep0; - *hep0 = he; - } - return hep0; - } - hep = &he->next; -#ifdef HASHMETER - ht->nsteps++; -#endif - } - return hep; -} - -JS_EXPORT_API(JSJHashEntry *) -JSJ_HashTableRawAdd(JSJHashTable *ht, JSJHashEntry **hep, - JSJHashNumber keyHash, const void *key, void *value, - void *arg) -{ - JSUint32 i, n; - JSJHashEntry *he, *next, **oldbuckets; - JSUint32 nb; - - /* Grow the table if it is overloaded */ - n = NBUCKETS(ht); - if (ht->nentries >= OVERLOADED(n)) { -#ifdef HASHMETER - ht->ngrows++; -#endif - ht->shift--; - oldbuckets = ht->buckets; -#if (defined(XP_WIN) || defined(XP_OS2)) && !defined(_WIN32) - if (2 * n > 16000) - return 0; -#endif /* WIN16 */ - nb = 2 * n * sizeof(JSJHashEntry *); - ht->buckets = (*ht->allocOps->allocTable)(ht->allocPriv, nb); - if (!ht->buckets) { - ht->buckets = oldbuckets; - return 0; - } - memset(ht->buckets, 0, nb); - - for (i = 0; i < n; i++) { - for (he = oldbuckets[i]; he; he = next) { - next = he->next; - hep = JSJ_HashTableRawLookup(ht, he->keyHash, he->key, arg); - JS_ASSERT(*hep == 0); - he->next = 0; - *hep = he; - } - } -#ifdef DEBUG - memset(oldbuckets, 0xDB, n * sizeof oldbuckets[0]); -#endif - (*ht->allocOps->freeTable)(ht->allocPriv, oldbuckets); - hep = JSJ_HashTableRawLookup(ht, keyHash, key, arg); - } - - /* Make a new key value entry */ - he = (*ht->allocOps->allocEntry)(ht->allocPriv, key); - if (!he) - return 0; - he->keyHash = keyHash; - he->key = key; - he->value = value; - he->next = *hep; - *hep = he; - ht->nentries++; - return he; -} - -JS_EXPORT_API(JSJHashEntry *) -JSJ_HashTableAdd(JSJHashTable *ht, const void *key, void *value, void *arg) -{ - JSJHashNumber keyHash; - JSJHashEntry *he, **hep; - - keyHash = (*ht->keyHash)(key, arg); - hep = JSJ_HashTableRawLookup(ht, keyHash, key, arg); - if ((he = *hep) != 0) { - /* Hit; see if values match */ - if ((*ht->valueCompare)(he->value, value, arg)) { - /* key,value pair is already present in table */ - return he; - } - if (he->value) - (*ht->allocOps->freeEntry)(ht->allocPriv, he, HT_FREE_VALUE); - he->value = value; - return he; - } - return JSJ_HashTableRawAdd(ht, hep, keyHash, key, value, arg); -} - -JS_EXPORT_API(void) -JSJ_HashTableRawRemove(JSJHashTable *ht, JSJHashEntry **hep, JSJHashEntry *he, void *arg) -{ - JSUint32 i, n; - JSJHashEntry *next, **oldbuckets; - JSUint32 nb; - - *hep = he->next; - (*ht->allocOps->freeEntry)(ht->allocPriv, he, HT_FREE_ENTRY); - - /* Shrink table if it's underloaded */ - n = NBUCKETS(ht); - if (--ht->nentries < UNDERLOADED(n)) { -#ifdef HASHMETER - ht->nshrinks++; -#endif - ht->shift++; - oldbuckets = ht->buckets; - nb = n * sizeof(JSJHashEntry*) / 2; - ht->buckets = (*ht->allocOps->allocTable)(ht->allocPriv, nb); - if (!ht->buckets) { - ht->buckets = oldbuckets; - return; - } - memset(ht->buckets, 0, nb); - - for (i = 0; i < n; i++) { - for (he = oldbuckets[i]; he; he = next) { - next = he->next; - hep = JSJ_HashTableRawLookup(ht, he->keyHash, he->key, arg); - JS_ASSERT(*hep == 0); - he->next = 0; - *hep = he; - } - } -#ifdef DEBUG - memset(oldbuckets, 0xDB, n * sizeof oldbuckets[0]); -#endif - (*ht->allocOps->freeTable)(ht->allocPriv, oldbuckets); - } -} - -JS_EXPORT_API(JSBool) -JSJ_HashTableRemove(JSJHashTable *ht, const void *key, void *arg) -{ - JSJHashNumber keyHash; - JSJHashEntry *he, **hep; - - keyHash = (*ht->keyHash)(key, arg); - hep = JSJ_HashTableRawLookup(ht, keyHash, key, arg); - if ((he = *hep) == 0) - return JS_FALSE; - - /* Hit; remove element */ - JSJ_HashTableRawRemove(ht, hep, he, arg); - return JS_TRUE; -} - -JS_EXPORT_API(void *) -JSJ_HashTableLookup(JSJHashTable *ht, const void *key, void *arg) -{ - JSJHashNumber keyHash; - JSJHashEntry *he, **hep; - - keyHash = (*ht->keyHash)(key, arg); - hep = JSJ_HashTableRawLookup(ht, keyHash, key, arg); - if ((he = *hep) != 0) { - return he->value; - } - return 0; -} - -/* -** Iterate over the entries in the hash table calling func for each -** entry found. Stop if "f" says to (return value & JS_ENUMERATE_STOP). -** Return a count of the number of elements scanned. -*/ -JS_EXPORT_API(int) -JSJ_HashTableEnumerateEntries(JSJHashTable *ht, JSJHashEnumerator f, void *arg) -{ - JSJHashEntry *he, **hep; - JSUint32 i, nbuckets; - int rv, n = 0; - JSJHashEntry *todo = 0; - - nbuckets = NBUCKETS(ht); - for (i = 0; i < nbuckets; i++) { - hep = &ht->buckets[i]; - while ((he = *hep) != 0) { - rv = (*f)(he, n, arg); - n++; - if (rv & (HT_ENUMERATE_REMOVE | HT_ENUMERATE_UNHASH)) { - *hep = he->next; - if (rv & HT_ENUMERATE_REMOVE) { - he->next = todo; - todo = he; - } - } else { - hep = &he->next; - } - if (rv & HT_ENUMERATE_STOP) { - goto out; - } - } - } - -out: - hep = &todo; - while ((he = *hep) != 0) { - JSJ_HashTableRawRemove(ht, hep, he, arg); - } - return n; -} - -#ifdef HASHMETER -#include -#include - -JS_EXPORT_API(void) -JSJ_HashTableDumpMeter(JSJHashTable *ht, JSJHashEnumerator dump, FILE *fp) -{ - double mean, variance; - JSUint32 nchains, nbuckets; - JSUint32 i, n, maxChain, maxChainLen; - JSJHashEntry *he; - - variance = 0; - nchains = 0; - maxChainLen = 0; - nbuckets = NBUCKETS(ht); - for (i = 0; i < nbuckets; i++) { - he = ht->buckets[i]; - if (!he) - continue; - nchains++; - for (n = 0; he; he = he->next) - n++; - variance += n * n; - if (n > maxChainLen) { - maxChainLen = n; - maxChain = i; - } - } - mean = (double)ht->nentries / nchains; - variance = fabs(variance / nchains - mean * mean); - - fprintf(fp, "\nHash table statistics:\n"); - fprintf(fp, " number of lookups: %u\n", ht->nlookups); - fprintf(fp, " number of entries: %u\n", ht->nentries); - fprintf(fp, " number of grows: %u\n", ht->ngrows); - fprintf(fp, " number of shrinks: %u\n", ht->nshrinks); - fprintf(fp, " mean steps per hash: %g\n", (double)ht->nsteps - / ht->nlookups); - fprintf(fp, "mean hash chain length: %g\n", mean); - fprintf(fp, " standard deviation: %g\n", sqrt(variance)); - fprintf(fp, " max hash chain length: %u\n", maxChainLen); - fprintf(fp, " max hash chain: [%u]\n", maxChain); - - for (he = ht->buckets[maxChain], i = 0; he; he = he->next, i++) - if ((*dump)(he, i, fp) != HT_ENUMERATE_NEXT) - break; -} -#endif /* HASHMETER */ - -JS_EXPORT_API(int) -JSJ_HashTableDump(JSJHashTable *ht, JSJHashEnumerator dump, FILE *fp) -{ - int count; - - count = JSJ_HashTableEnumerateEntries(ht, dump, fp); -#ifdef HASHMETER - JSJ_HashTableDumpMeter(ht, dump, fp); -#endif - return count; -} - -JS_EXPORT_API(JSJHashNumber) -JSJ_HashString(const void *key) -{ - JSJHashNumber h; - const unsigned char *s; - - h = 0; - for (s = key; *s; s++) - h = (h >> 28) ^ (h << 4) ^ *s; - return h; -} - -JS_EXPORT_API(int) -JSJ_CompareStrings(const void *v1, const void *v2) -{ - return strcmp(v1, v2) == 0; -} - -JS_EXPORT_API(int) -JSJ_CompareValues(const void *v1, const void *v2) -{ - return v1 == v2; -} diff --git a/lib/javascript/liveconnect/jsj_hash.h b/lib/javascript/liveconnect/jsj_hash.h deleted file mode 100644 index 48ee693b..00000000 --- a/lib/javascript/liveconnect/jsj_hash.h +++ /dev/null @@ -1,161 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * This is a copy of the NSPR hash-table library, but it has been slightly - * modified to allow an additional argument to be passed into the hash - * key-comparison function. This is used to maintain thread-safety by - * passing in a JNIEnv pointer to the key-comparison function rather - * than storing it in a global. All types,function names, etc. have - * been renamed from their original NSPR names to protect the innocent. - */ - -#ifndef jsj_hash_h___ -#define jsj_hash_h___ -/* - * API to portable hash table code. - */ -#include -#include -#include "jstypes.h" - -JS_BEGIN_EXTERN_C - -typedef struct JSJHashEntry JSJHashEntry; -typedef struct JSJHashTable JSJHashTable; -typedef JSUint32 JSJHashNumber; -#define JSJ_HASH_BITS 32 -typedef JSJHashNumber (* JS_DLL_CALLBACK JSJHashFunction)(const void *key, void *arg); -typedef JSIntn (* JS_DLL_CALLBACK JSJHashComparator)(const void *v1, const void *v2, void *arg); -typedef JSIntn (* JS_DLL_CALLBACK JSJHashEnumerator)(JSJHashEntry *he, JSIntn i, void *arg); - -/* Flag bits in JSJHashEnumerator's return value */ -#define HT_ENUMERATE_NEXT 0 /* continue enumerating entries */ -#define HT_ENUMERATE_STOP 1 /* stop enumerating entries */ -#define HT_ENUMERATE_REMOVE 2 /* remove and free the current entry */ -#define HT_ENUMERATE_UNHASH 4 /* just unhash the current entry */ - -typedef struct JSJHashAllocOps { - void * (*allocTable)(void *pool, size_t size); - void (*freeTable)(void *pool, void *item); - JSJHashEntry * (*allocEntry)(void *pool, const void *key); - void (*freeEntry)(void *pool, JSJHashEntry *he, JSUintn flag); -} JSJHashAllocOps; - -#define HT_FREE_VALUE 0 /* just free the entry's value */ -#define HT_FREE_ENTRY 1 /* free value and entire entry */ - -struct JSJHashEntry { - JSJHashEntry *next; /* hash chain linkage */ - JSJHashNumber keyHash; /* key hash function result */ - const void *key; /* ptr to opaque key */ - void *value; /* ptr to opaque value */ -}; - -struct JSJHashTable { - JSJHashEntry **buckets; /* vector of hash buckets */ - JSUint32 nentries; /* number of entries in table */ - JSUint32 shift; /* multiplicative hash shift */ - JSJHashFunction keyHash; /* key hash function */ - JSJHashComparator keyCompare; /* key comparison function */ - JSJHashComparator valueCompare; /* value comparison function */ - JSJHashAllocOps *allocOps; /* allocation operations */ - void *allocPriv; /* allocation private data */ -#ifdef HASHMETER - JSUint32 nlookups; /* total number of lookups */ - JSUint32 nsteps; /* number of hash chains traversed */ - JSUint32 ngrows; /* number of table expansions */ - JSUint32 nshrinks; /* number of table contractions */ -#endif -}; - -/* - * Create a new hash table. - * If allocOps is null, use default allocator ops built on top of malloc(). - */ -JS_EXTERN_API(JSJHashTable *) -JSJ_NewHashTable(JSUint32 n, JSJHashFunction keyHash, - JSJHashComparator keyCompare, JSJHashComparator valueCompare, - JSJHashAllocOps *allocOps, void *allocPriv); - -JS_EXTERN_API(void) -JSJ_HashTableDestroy(JSJHashTable *ht); - -/* Low level access methods */ -JS_EXTERN_API(JSJHashEntry **) -JSJ_HashTableRawLookup(JSJHashTable *ht, JSJHashNumber keyHash, const void *key, void *arg); - -JS_EXTERN_API(JSJHashEntry *) -JSJ_HashTableRawAdd(JSJHashTable *ht, JSJHashEntry **hep, JSJHashNumber keyHash, - const void *key, void *value, void *arg); - -JS_EXTERN_API(void) -JSJ_HashTableRawRemove(JSJHashTable *ht, JSJHashEntry **hep, JSJHashEntry *he, void *arg); - -/* Higher level access methods */ -JS_EXTERN_API(JSJHashEntry *) -JSJ_HashTableAdd(JSJHashTable *ht, const void *key, void *value, void *arg); - -JS_EXTERN_API(JSBool) -JSJ_HashTableRemove(JSJHashTable *ht, const void *key, void *arg); - -JS_EXTERN_API(JSIntn) -JSJ_HashTableEnumerateEntries(JSJHashTable *ht, JSJHashEnumerator f, void *arg); - -JS_EXTERN_API(void *) -JSJ_HashTableLookup(JSJHashTable *ht, const void *key, void *arg); - -JS_EXTERN_API(JSIntn) -JSJ_HashTableDump(JSJHashTable *ht, JSJHashEnumerator dump, FILE *fp); - -/* General-purpose C string hash function. */ -JS_EXTERN_API(JSJHashNumber) -JSJ_HashString(const void *key); - -/* Compare strings using strcmp(), return true if equal. */ -JS_EXTERN_API(int) -JSJ_CompareStrings(const void *v1, const void *v2); - -/* Stub function just returns v1 == v2 */ -JS_EXTERN_API(JSIntn) -JSJ_CompareValues(const void *v1, const void *v2); - -JS_END_EXTERN_C - -#endif /* jsj_hash_h___ */ diff --git a/lib/javascript/liveconnect/jsj_method.c b/lib/javascript/liveconnect/jsj_method.c deleted file mode 100644 index 59657b0b..00000000 --- a/lib/javascript/liveconnect/jsj_method.c +++ /dev/null @@ -1,1823 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * This Original Code has been modified by IBM Corporation. Modifications made - * by IBM described herein are Copyright (c) International Business Machines - * Corporation, 2000. - * Modifications to Mozilla code or documentation identified per MPL Section 3.3 - * - * Date Modified by Description of modification - * 04/20/2000 IBM Corp. OS/2 VisualAge build. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * This file is part of the Java-vendor-neutral implementation of LiveConnect - * - * It contains the code used to reflect Java methods as properties of - * JavaObject objects and the code to invoke those methods. - * - */ - -#include -#include - -#include "jsj_private.h" /* LiveConnect internals */ -#include "jsjava.h" /* LiveConnect external API */ -#include "jsclist.h" /* Circular linked lists */ - -/* A list of Java methods */ -typedef JSCList MethodList; - -/* An element in a list of Java methods */ -typedef struct MethodListElement { - JSCList linkage; - JavaMethodSpec *method; -} MethodListElement; - -/* - * This is the return value of functions which compare either two types or two - * method signatures to see if either is "preferred" when converting from - * specified JavaScript value(s). - */ -typedef enum JSJTypePreference { - JSJPREF_FIRST_ARG = 1, /* First argument preferred */ - JSJPREF_SECOND_ARG = 2, /* Second argument preferred */ - JSJPREF_AMBIGUOUS = 3 /* Neither preferred over the other */ -} JSJTypePreference; - -/* - * Classification of JS types with slightly different granularity than JSType. - * This is used to resolve among overloaded Java methods. - */ -typedef enum JSJType { - JSJTYPE_VOID, /* undefined */ - JSJTYPE_BOOLEAN, /* boolean */ - JSJTYPE_NUMBER, /* number */ - JSJTYPE_STRING, /* string */ - JSJTYPE_NULL, /* null */ - JSJTYPE_JAVACLASS, /* JavaClass */ - JSJTYPE_JAVAOBJECT, /* JavaObject */ - JSJTYPE_JAVAARRAY, /* JavaArray */ - JSJTYPE_JSARRAY, /* JS Array */ - JSJTYPE_OBJECT, /* Any other JS Object, including functions */ - JSJTYPE_LIMIT -} JSJType; - -/* - * A helper function for jsj_ConvertJavaMethodSignatureToString(): - * Compute JNI-style (string) signatures for an array of JavaSignature objects - * and concatenate the results into a single string. - * - * If an error is encountered, NULL is returned and the error reporter is called. - */ -static const char * -convert_java_method_arg_signatures_to_string(JSContext *cx, - JavaSignature **arg_signatures, - int num_args) -{ - const char *first_arg_signature, *rest_arg_signatures, *sig; - JavaSignature **rest_args; - - /* Convert the first method argument in the array to a string */ - first_arg_signature = jsj_ConvertJavaSignatureToString(cx, arg_signatures[0]); - if (!first_arg_signature) - return NULL; - - /* If this is the last method argument in the array, we're done. */ - if (num_args == 1) - return first_arg_signature; - - /* Convert the remaining method arguments to a string */ - rest_args = &arg_signatures[1]; - rest_arg_signatures = - convert_java_method_arg_signatures_to_string(cx, rest_args, num_args - 1); - if (!rest_arg_signatures) { - free((void*)first_arg_signature); - return NULL; - } - - /* Concatenate the signature string of this argument with the signature - strings of all the remaining arguments. */ - sig = JS_smprintf("%s%s", first_arg_signature, rest_arg_signatures); - free((void*)first_arg_signature); - free((void*)rest_arg_signatures); - if (!sig) { - JS_ReportOutOfMemory(cx); - return NULL; - } - - return sig; -} - -/* - * A helper function for jsj_ConvertJavaMethodSignatureToHRString(): - * Compute human-readable string signatures for an array of JavaSignatures - * and concatenate the results into a single string. - * - * If an error is encountered, NULL is returned and the error reporter is called. - */ -static const char * -convert_java_method_arg_signatures_to_hr_string(JSContext *cx, - JavaSignature **arg_signatures, - int num_args, - JSBool whitespace) -{ - const char *first_arg_signature, *rest_arg_signatures, *sig, *separator; - JavaSignature **rest_args; - - if (num_args == 0) - return strdup(""); - - /* Convert the first method argument in the array to a string */ - first_arg_signature = jsj_ConvertJavaSignatureToHRString(cx, arg_signatures[0]); - if (!first_arg_signature) - return NULL; - - /* If this is the last method argument in the array, we're done. */ - if (num_args == 1) - return first_arg_signature; - - /* Convert the remaining method arguments to a string */ - rest_args = &arg_signatures[1]; - rest_arg_signatures = - convert_java_method_arg_signatures_to_hr_string(cx, rest_args, num_args - 1, whitespace); - if (!rest_arg_signatures) { - free((void*)first_arg_signature); - return NULL; - } - - /* Concatenate the signature string of this argument with the signature - strings of all the remaining arguments. */ - separator = whitespace ? " " : ""; - sig = JS_smprintf("%s,%s%s", first_arg_signature, separator, rest_arg_signatures); - free((void*)first_arg_signature); - free((void*)rest_arg_signatures); - if (!sig) { - JS_ReportOutOfMemory(cx); - return NULL; - } - - return sig; -} -/* - * Compute a string signature for the given method using the same type names - * that appear in Java source files, e.g. "int[][]", rather than the JNI-style - * type strings that are provided by the functions above. An example return - * value might be "String MyFunc(int, byte, char[][], java.lang.String)". - * - * If an error is encountered, NULL is returned and the error reporter is called. - */ -const char * -jsj_ConvertJavaMethodSignatureToHRString(JSContext *cx, - const char *method_name, - JavaMethodSignature *method_signature) -{ - JavaSignature **arg_signatures, *return_val_signature; - const char *arg_sigs_cstr; - const char *return_val_sig_cstr; - const char *sig_cstr; - - arg_signatures = method_signature->arg_signatures; - return_val_signature = method_signature->return_val_signature; - - /* Convert the method argument signatures to a C-string */ - arg_sigs_cstr = - convert_java_method_arg_signatures_to_hr_string(cx, arg_signatures, - method_signature->num_args, - JS_TRUE); - if (!arg_sigs_cstr) - return NULL; - - /* Convert the method return value signature to a C-string */ - return_val_sig_cstr = jsj_ConvertJavaSignatureToHRString(cx, return_val_signature); - if (!return_val_sig_cstr) { - free((void*)arg_sigs_cstr); - return NULL; - } - - /* Compose method arg signatures string and return val signature string */ - sig_cstr = JS_smprintf("%s %s(%s)", return_val_sig_cstr, method_name, arg_sigs_cstr); - free((void*)arg_sigs_cstr); - free((void*)return_val_sig_cstr); - - if (!sig_cstr) { - JS_ReportOutOfMemory(cx); - return NULL; - } - return sig_cstr; -} -/* - * Destroy the sub-structure of a JavaMethodSignature object without free'ing - * the method signature itself. - */ -void -jsj_PurgeJavaMethodSignature(JSContext *cx, JNIEnv *jEnv, JavaMethodSignature *method_signature) -{ - int i, num_args; - JavaSignature **arg_signatures; - - if (!method_signature) /* Paranoia */ - return; - - /* Free the method argument signatures */ - num_args = method_signature->num_args; - arg_signatures = method_signature->arg_signatures; - for (i = 0; i < num_args; i++) - jsj_ReleaseJavaClassDescriptor(cx, jEnv, arg_signatures[i]); - if (arg_signatures) - JS_free(cx, arg_signatures); - - /* Free the return type signature */ - if (method_signature->return_val_signature) - jsj_ReleaseJavaClassDescriptor(cx, jEnv, method_signature->return_val_signature); -} - -/* - * Fill in the members of a JavaMethodSignature object using the method - * argument, which can be either an instance of either java.lang.reflect.Method - * or java.lang.reflect.Constructor. - * - * With normal completion, return the original method_signature argument. - * If an error occurs, return NULL and call the error reporter. - */ -JavaMethodSignature * -jsj_InitJavaMethodSignature(JSContext *cx, JNIEnv *jEnv, - jobject method, - JavaMethodSignature *method_signature) -{ - int i; - jboolean is_constructor; - jclass return_val_class; - jsize num_args; - JavaSignature *return_val_signature; - jarray arg_classes; - jmethodID getParameterTypes; - - memset(method_signature, 0, sizeof (JavaMethodSignature)); - - is_constructor = (*jEnv)->IsInstanceOf(jEnv, method, jlrConstructor); - - /* Get a Java array that lists the class of each of the method's arguments */ - if (is_constructor) - getParameterTypes = jlrConstructor_getParameterTypes; - else - getParameterTypes = jlrMethod_getParameterTypes; - arg_classes = (*jEnv)->CallObjectMethod(jEnv, method, getParameterTypes); - if (!arg_classes) { - jsj_UnexpectedJavaError(cx, jEnv, - "Can't determine argument signature of method"); - goto error; - } - - /* Compute the number of method arguments */ - num_args = jsj_GetJavaArrayLength(cx, jEnv, arg_classes); - if (num_args < 0) - goto error; - method_signature->num_args = num_args; - - /* Build a JavaSignature array corresponding to the method's arguments */ - if (num_args) { - JavaSignature **arg_signatures; - - /* Allocate an array of JavaSignatures, one for each method argument */ - size_t arg_signatures_size = num_args * sizeof(JavaSignature *); - arg_signatures = (JavaSignature **)JS_malloc(cx, arg_signatures_size); - if (!arg_signatures) - goto error; - memset(arg_signatures, 0, arg_signatures_size); - method_signature->arg_signatures = arg_signatures; - - /* Build an array of JavaSignature objects, each of which corresponds - to the type of an individual method argument. */ - for (i = 0; i < num_args; i++) { - JavaSignature *a; - jclass arg_class = (*jEnv)->GetObjectArrayElement(jEnv, arg_classes, i); - - a = arg_signatures[i] = jsj_GetJavaClassDescriptor(cx, jEnv, arg_class); - (*jEnv)->DeleteLocalRef(jEnv, arg_class); - if (!a) { - jsj_UnexpectedJavaError(cx, jEnv, "Could not determine Java class " - "signature using java.lang.reflect"); - goto error; - } - } - } - - /* Get the Java class of the method's return value */ - if (is_constructor) { - /* Constructors always have a "void" return type */ - return_val_signature = jsj_GetJavaClassDescriptor(cx, jEnv, jlVoid_TYPE); - } else { - return_val_class = - (*jEnv)->CallObjectMethod(jEnv, method, jlrMethod_getReturnType); - if (!return_val_class) { - jsj_UnexpectedJavaError(cx, jEnv, - "Can't determine return type of method " - "using java.lang.reflect.Method.getReturnType()"); - goto error; - } - - /* Build a JavaSignature object corresponding to the method's return value */ - return_val_signature = jsj_GetJavaClassDescriptor(cx, jEnv, return_val_class); - (*jEnv)->DeleteLocalRef(jEnv, return_val_class); - } - - if (!return_val_signature) - goto error; - method_signature->return_val_signature = return_val_signature; - - (*jEnv)->DeleteLocalRef(jEnv, arg_classes); - return method_signature; - -error: - - if (arg_classes) - (*jEnv)->DeleteLocalRef(jEnv, arg_classes); - jsj_PurgeJavaMethodSignature(cx, jEnv, method_signature); - return NULL; -} - -/* - * Compute a JNI-style (string) signature for the given method, e.g. the method - * "String MyFunc(int, byte)" is translated to "(IB)Ljava/lang/String;". - * - * If an error is encountered, NULL is returned and the error reporter is called. - */ -const char * -jsj_ConvertJavaMethodSignatureToString(JSContext *cx, - JavaMethodSignature *method_signature) -{ - JavaSignature **arg_signatures, *return_val_signature; - const char *arg_sigs_cstr; - const char *return_val_sig_cstr; - const char *sig_cstr; - - arg_signatures = method_signature->arg_signatures; - return_val_signature = method_signature->return_val_signature; - - /* Convert the method argument signatures to a C-string */ - arg_sigs_cstr = NULL; - if (arg_signatures) { - arg_sigs_cstr = - convert_java_method_arg_signatures_to_string(cx, arg_signatures, - method_signature->num_args); - if (!arg_sigs_cstr) - return NULL; - } - - /* Convert the method return value signature to a C-string */ - return_val_sig_cstr = jsj_ConvertJavaSignatureToString(cx, return_val_signature); - if (!return_val_sig_cstr) { - free((void*)arg_sigs_cstr); - return NULL; - } - - /* Compose method arg signatures string and return val signature string */ - if (arg_sigs_cstr) { - sig_cstr = JS_smprintf("(%s)%s", arg_sigs_cstr, return_val_sig_cstr); - free((void*)arg_sigs_cstr); - } else { - sig_cstr = JS_smprintf("()%s", return_val_sig_cstr); - } - - free((void*)return_val_sig_cstr); - - if (!sig_cstr) { - JS_ReportOutOfMemory(cx); - return NULL; - } - return sig_cstr; -} - -static JSBool -add_java_method_to_class_descriptor(JSContext *cx, JNIEnv *jEnv, - JavaClassDescriptor *class_descriptor, - jstring method_name_jstr, - jobject java_method, - JSBool is_static_method, - JSBool is_constructor) -{ - jmethodID methodID; - JSFunction *fun; - jclass java_class = class_descriptor->java_class; - - JavaMemberDescriptor *member_descriptor = NULL; - const char *sig_cstr = NULL; - const char *method_name = NULL; - JavaMethodSignature *signature = NULL; - JavaMethodSpec **specp, *method_spec = NULL; - - if (is_constructor) { - member_descriptor = jsj_GetJavaClassConstructors(cx, class_descriptor); - } else { - if (is_static_method) { - member_descriptor = jsj_GetJavaStaticMemberDescriptor(cx, jEnv, class_descriptor, method_name_jstr); - } else { - member_descriptor = jsj_GetJavaMemberDescriptor(cx, jEnv, class_descriptor, method_name_jstr); - } - fun = JS_NewFunction(cx, jsj_JavaInstanceMethodWrapper, 0, - JSFUN_BOUND_METHOD, NULL, member_descriptor->name); - member_descriptor->invoke_func_obj = JS_GetFunctionObject(fun); - JS_AddNamedRoot(cx, &member_descriptor->invoke_func_obj, - "&member_descriptor->invoke_func_obj"); - } - if (!member_descriptor) - return JS_FALSE; - - method_spec = (JavaMethodSpec*)JS_malloc(cx, sizeof(JavaMethodSpec)); - if (!method_spec) - goto error; - memset(method_spec, 0, sizeof(JavaMethodSpec)); - - signature = jsj_InitJavaMethodSignature(cx, jEnv, java_method, &method_spec->signature); - if (!signature) - goto error; - - method_name = JS_strdup(cx, member_descriptor->name); - if (!method_name) - goto error; - method_spec->name = method_name; - - sig_cstr = jsj_ConvertJavaMethodSignatureToString(cx, signature); - if (!sig_cstr) - goto error; - - if (is_static_method) - methodID = (*jEnv)->GetStaticMethodID(jEnv, java_class, method_name, sig_cstr); - else - methodID = (*jEnv)->GetMethodID(jEnv, java_class, method_name, sig_cstr); - method_spec->methodID = methodID; - - if (!methodID) { - jsj_UnexpectedJavaError(cx, jEnv, - "Can't get Java method ID for %s.%s() (sig=%s)", - class_descriptor->name, method_name, sig_cstr); - goto error; - } - - JS_free(cx, (char*)sig_cstr); - - /* Add method to end of list of overloaded methods for this class member */ - specp = &member_descriptor->methods; - while (*specp) { - specp = &(*specp)->next; - } - *specp = method_spec; - - return JS_TRUE; - -error: - if (method_spec) - JS_FREE_IF(cx, (char*)method_spec->name); - JS_FREE_IF(cx, (char*)sig_cstr); - if (signature) - jsj_PurgeJavaMethodSignature(cx, jEnv, signature); - JS_FREE_IF(cx, method_spec); - return JS_FALSE; -} - -JSBool -jsj_ReflectJavaMethods(JSContext *cx, JNIEnv *jEnv, - JavaClassDescriptor *class_descriptor, - JSBool reflect_only_static_methods) -{ - jarray joMethodArray, joConstructorArray; - jsize num_methods, num_constructors; - int i; - jclass java_class; - JSBool ok, reflect_only_instance_methods; - - reflect_only_instance_methods = !reflect_only_static_methods; - - /* Get a java array of java.lang.reflect.Method objects, by calling - java.lang.Class.getMethods(). */ - java_class = class_descriptor->java_class; - joMethodArray = (*jEnv)->CallObjectMethod(jEnv, java_class, jlClass_getMethods); - if (!joMethodArray) { - jsj_UnexpectedJavaError(cx, jEnv, - "Can't determine Java object's methods " - "using java.lang.Class.getMethods()"); - return JS_FALSE; - } - - /* Iterate over the class methods */ - num_methods = (*jEnv)->GetArrayLength(jEnv, joMethodArray); - for (i = 0; i < num_methods; i++) { - jstring method_name_jstr; - - /* Get the i'th reflected method */ - jobject java_method = (*jEnv)->GetObjectArrayElement(jEnv, joMethodArray, i); - - /* Get the method modifiers, eg static, public, private, etc. */ - jint modifiers = (*jEnv)->CallIntMethod(jEnv, java_method, jlrMethod_getModifiers); - - /* Don't allow access to private or protected Java methods. */ - if (!(modifiers & ACC_PUBLIC)) - goto dont_reflect_method; - - /* Abstract methods can't be invoked */ - if (modifiers & ACC_ABSTRACT) - goto dont_reflect_method; - - /* Reflect all instance methods or all static methods, but not both */ - if (reflect_only_static_methods != ((modifiers & ACC_STATIC) != 0)) - goto dont_reflect_method; - - /* Add a JavaMethodSpec object to the JavaClassDescriptor */ - method_name_jstr = (*jEnv)->CallObjectMethod(jEnv, java_method, jlrMethod_getName); - ok = add_java_method_to_class_descriptor(cx, jEnv, class_descriptor, method_name_jstr, java_method, - reflect_only_static_methods, JS_FALSE); - (*jEnv)->DeleteLocalRef(jEnv, method_name_jstr); - if (!ok) { - (*jEnv)->DeleteLocalRef(jEnv, java_method); - (*jEnv)->DeleteLocalRef(jEnv, joMethodArray); - return JS_FALSE; - } - -dont_reflect_method: - (*jEnv)->DeleteLocalRef(jEnv, java_method); - } - - (*jEnv)->DeleteLocalRef(jEnv, joMethodArray); - if (reflect_only_instance_methods) - return JS_TRUE; - - joConstructorArray = (*jEnv)->CallObjectMethod(jEnv, java_class, jlClass_getConstructors); - if (!joConstructorArray) { - jsj_UnexpectedJavaError(cx, jEnv, "internal error: " - "Can't determine Java class's constructors " - "using java.lang.Class.getConstructors()"); - return JS_FALSE; - } - - /* Iterate over the class constructors */ - num_constructors = (*jEnv)->GetArrayLength(jEnv, joConstructorArray); - for (i = 0; i < num_constructors; i++) { - /* Get the i'th reflected constructor */ - jobject java_constructor = - (*jEnv)->GetObjectArrayElement(jEnv, joConstructorArray, i); - - /* Get the method modifiers, eg public, private, etc. */ - jint modifiers = (*jEnv)->CallIntMethod(jEnv, java_constructor, - jlrConstructor_getModifiers); - - /* Don't allow access to private or protected Java methods. */ - if (!(modifiers & ACC_PUBLIC)) - goto dont_reflect_constructor; - - /* Add a JavaMethodSpec object to the JavaClassDescriptor */ - ok = add_java_method_to_class_descriptor(cx, jEnv, class_descriptor, NULL, - java_constructor, - JS_FALSE, JS_TRUE); - if (!ok) { - (*jEnv)->DeleteLocalRef(jEnv, joConstructorArray); - (*jEnv)->DeleteLocalRef(jEnv, java_constructor); - return JS_FALSE; - } - -dont_reflect_constructor: - (*jEnv)->DeleteLocalRef(jEnv, java_constructor); - } - - (*jEnv)->DeleteLocalRef(jEnv, joConstructorArray); - return JS_TRUE; -} - -/* - * Free up a JavaMethodSpec and all its resources. - */ -void -jsj_DestroyMethodSpec(JSContext *cx, JNIEnv *jEnv, JavaMethodSpec *method_spec) -{ - if (!method_spec->is_alias) { - JS_FREE_IF(cx, (char*)method_spec->name); - jsj_PurgeJavaMethodSignature(cx, jEnv, &method_spec->signature); - } - JS_free(cx, method_spec); -} - -static JavaMethodSpec * -copy_java_method_descriptor(JSContext *cx, JavaMethodSpec *method) -{ - JavaMethodSpec *copy; - - copy = (JavaMethodSpec*)JS_malloc(cx, sizeof(JavaMethodSpec)); - if (!copy) - return NULL; - memcpy(copy, method, sizeof(JavaMethodSpec)); - copy->next = NULL; - copy->is_alias = JS_TRUE; - return copy; -} - -/* - * See if a reference to a JavaObject/JavaClass's property looks like the - * explicit resolution of an overloaded method, e.g. - * java.lang.String["max(double,double)"]. If so, add a new member - * (JavaMemberDescriptor) to the object that is an alias for the resolved - * method. - */ -JavaMemberDescriptor * -jsj_ResolveExplicitMethod(JSContext *cx, JNIEnv *jEnv, - JavaClassDescriptor *class_descriptor, - jsid method_name_id, - JSBool is_static) -{ - JavaMethodSpec *method; - JavaMemberDescriptor *member_descriptor; - JavaMethodSignature *ms; - JSString *simple_name_jsstr; - JSFunction *fun; - JSBool is_constructor; - int left_paren; - const char *sig_cstr, *method_name; - char *arg_start; - jsid id; - jsval method_name_jsval; - - /* - * Get the simple name of the explicit method, i.e. get "cos" from - * "cos(double)", and use it to create a new JS string. - */ - JS_IdToValue(cx, method_name_id, &method_name_jsval); - method_name = JS_GetStringBytes(JSVAL_TO_STRING(method_name_jsval)); - arg_start = strchr(method_name, '('); /* Skip until '(' */ - /* If no left-paren, then this is not a case of explicit method resolution */ - if (!arg_start) - return NULL; - /* Left-paren must be first character for constructors */ - is_constructor = (is_static && (arg_start == method_name)); - - left_paren = arg_start - method_name; - simple_name_jsstr = JS_NewStringCopyN(cx, method_name, left_paren); - if (!simple_name_jsstr) - return NULL; - - /* Find all the methods in the same class with the same simple name */ - JS_ValueToId(cx, STRING_TO_JSVAL(simple_name_jsstr), &id); - if (is_constructor) - member_descriptor = jsj_LookupJavaClassConstructors(cx, jEnv, class_descriptor); - else if (is_static) - member_descriptor = jsj_LookupJavaStaticMemberDescriptorById(cx, jEnv, class_descriptor, id); - else - member_descriptor = jsj_LookupJavaMemberDescriptorById(cx, jEnv, class_descriptor, id); - if (!member_descriptor) /* No member with matching simple name ? */ - return NULL; - - /* - * Do a UTF8 comparison of method signatures with all methods of the same name, - * so as to discover a method which exactly matches the specified argument types. - */ - if (!strlen(arg_start + 1)) - return NULL; - arg_start = JS_strdup(cx, arg_start + 1); - if (!arg_start) - return NULL; - arg_start[strlen(arg_start) - 1] = '\0'; /* Get rid of ')' */ - sig_cstr = NULL; /* Quiet gcc warning about uninitialized variable */ - for (method = member_descriptor->methods; method; method = method->next) { - ms = &method->signature; - sig_cstr = convert_java_method_arg_signatures_to_hr_string(cx, ms->arg_signatures, - ms->num_args, JS_FALSE); - if (!sig_cstr) - return NULL; - - if (!strcmp(sig_cstr, arg_start)) - break; - JS_free(cx, (void*)sig_cstr); - } - JS_free(cx, arg_start); - if (!method) - return NULL; - JS_free(cx, (void*)sig_cstr); - - /* Don't bother doing anything if the method isn't overloaded */ - if (!member_descriptor->methods->next) - return member_descriptor; - - /* - * To speed up performance for future accesses, create a new member descriptor - * with a name equal to the explicit method name, i.e. "cos(double)". - */ - member_descriptor = JS_malloc(cx, sizeof(JavaMemberDescriptor)); - if (!member_descriptor) - return NULL; - memset(member_descriptor, 0, sizeof(JavaMemberDescriptor)); - - member_descriptor->id = method_name_id; - member_descriptor->name = - JS_strdup(cx, is_constructor ? "" : JS_GetStringBytes(simple_name_jsstr)); - if (!member_descriptor->name) { - JS_free(cx, member_descriptor); - return NULL; - } - - member_descriptor->methods = copy_java_method_descriptor(cx, method); - if (!member_descriptor->methods) { - JS_free(cx, (void*)member_descriptor->name); - JS_free(cx, member_descriptor); - return NULL; - } - - fun = JS_NewFunction(cx, jsj_JavaInstanceMethodWrapper, 0, - JSFUN_BOUND_METHOD, NULL, method_name); - member_descriptor->invoke_func_obj = JS_GetFunctionObject(fun); - JS_AddNamedRoot(cx, &member_descriptor->invoke_func_obj, - "&member_descriptor->invoke_func_obj"); - - /* THREADSAFETY */ - /* Add the new aliased member to the list of all members for the class */ - if (is_static) { - member_descriptor->next = class_descriptor->static_members; - class_descriptor->static_members = member_descriptor; - } else { - member_descriptor->next = class_descriptor->instance_members; - class_descriptor->instance_members = member_descriptor; - } - - return member_descriptor; -} - -/* - * Return the JavaScript types that a JavaScript method was invoked with - * as a string, e.g. a JS method invoked like foo(3, 'hey', 'you', true) - * would cause a return value of "(number, string, string, boolean)". - * The returned string must be free'ed by the caller. - * Returns NULL and reports an error if out-of-memory. - */ -static const char * -get_js_arg_types_as_string(JSContext *cx, uintN argc, jsval *argv) -{ - uintN i; - const char *arg_type, *arg_string, *tmp; - - if (argc == 0) - return strdup("()"); - - arg_string = strdup("("); - if (!arg_string) - goto out_of_memory; - for (i = 0; i < argc; i++) { - arg_type = JS_GetTypeName(cx, JS_TypeOfValue(cx, argv[i])); - tmp = JS_smprintf("%s%s%s%s", arg_string, i ? ", " : "", arg_type, - (i == argc-1) ? ")" : ""); - free((char*)arg_string); - if (!tmp) - goto out_of_memory; - arg_string = tmp; - } - - return arg_string; - -out_of_memory: - JS_ReportOutOfMemory(cx); - return NULL; -} - -/* - * This is an error reporting routine used when a method of the correct name - * and class exists but either the number of arguments is incorrect or the - * arguments are of the wrong type. - */ -static void -report_method_match_failure(JSContext *cx, - JavaMemberDescriptor *member_descriptor, - JavaClassDescriptor *class_descriptor, - JSBool is_static_method, - uintN argc, jsval *argv) -{ - const char *err, *js_arg_string, *tmp, *method_str, *method_name; - JSBool is_constructor; - JavaMethodSpec *method; - - err = NULL; - is_constructor = (!strcmp(member_descriptor->name, "")); - - js_arg_string = get_js_arg_types_as_string(cx, argc, argv); - if (!js_arg_string) - goto out_of_memory; - - if (is_constructor) { - err = JS_smprintf("There is no Java constructor for class %s that matches " - "JavaScript argument types %s.\n", class_descriptor->name, - js_arg_string); - method_name = class_descriptor->name; - } else { - err = JS_smprintf("There is no %sJava method %s.%s that matches " - "JavaScript argument types %s.\n", - is_static_method ? "static ": "", - class_descriptor->name, member_descriptor->name, js_arg_string); - method_name = member_descriptor->name; - } - if (!err) - goto out_of_memory; - - tmp = JS_smprintf("%sCandidate methods with the same name are:\n", err); - if (!tmp) - goto out_of_memory; - err = tmp; - - method = member_descriptor->methods; - while (method) { - method_str = - jsj_ConvertJavaMethodSignatureToHRString(cx, method_name, &method->signature); - if (!method_str) - goto out_of_memory; - tmp = JS_smprintf("%s %s\n", err, method_str); - free((char*)method_str); - if (!tmp) - goto out_of_memory; - err = tmp; - - method = method->next; - } - - JS_ReportError(cx, err); - return; - -out_of_memory: - if (js_arg_string) - free((char*)js_arg_string); - if (err) - free((char*)err); -} - -/* - * This is an error reporting routine used when a method of the correct name - * and class exists but more than one Java method in a set of overloaded - * methods are compatible with the JavaScript argument types and none of them - * match any better than all the others. - */ -static void -report_ambiguous_method_match(JSContext *cx, - JavaMemberDescriptor *member_descriptor, - JavaClassDescriptor *class_descriptor, - MethodList *ambiguous_methods, - JSBool is_static_method, - uintN argc, jsval *argv) -{ - const char *err, *js_arg_string, *tmp, *method_str, *method_name; - JSBool is_constructor; - JavaMethodSpec *method; - MethodListElement *method_list_element; - - err = NULL; - is_constructor = (!strcmp(member_descriptor->name, "")); - - js_arg_string = get_js_arg_types_as_string(cx, argc, argv); - if (!js_arg_string) - goto out_of_memory; - - if (is_constructor) { - err = JS_smprintf("The choice of Java constructor for class %s with " - "JavaScript argument types %s is ambiguous.\n", - class_descriptor->name, - js_arg_string); - method_name = class_descriptor->name; - } else { - err = JS_smprintf("The choice of %sJava method %s.%s matching " - "JavaScript argument types %s is ambiguous.\n", - is_static_method ? "static ": "", - class_descriptor->name, member_descriptor->name, - js_arg_string); - method_name = member_descriptor->name; - } - if (!err) - goto out_of_memory; - - tmp = JS_smprintf("%sCandidate methods are:\n", err); - if (!tmp) - goto out_of_memory; - err = tmp; - - method_list_element = (MethodListElement*)JS_LIST_HEAD(ambiguous_methods); - while ((MethodList*)method_list_element != ambiguous_methods) { - method = method_list_element->method; - method_str = - jsj_ConvertJavaMethodSignatureToHRString(cx, method_name, &method->signature); - if (!method_str) - goto out_of_memory; - tmp = JS_smprintf("%s %s\n", err, method_str); - free((char*)method_str); - if (!tmp) - goto out_of_memory; - err = tmp; - - method_list_element = (MethodListElement*)method_list_element->linkage.next; - } - - JS_ReportError(cx, err); - return; - -out_of_memory: - if (js_arg_string) - free((char*)js_arg_string); - if (err) - free((char*)err); -} - -/* - * Compute classification of JS types with slightly different granularity - * than JSType. This is used to resolve among overloaded Java methods. - */ -static JSJType -compute_jsj_type(JSContext *cx, jsval v) -{ - JSObject *js_obj; - - if (JSVAL_IS_OBJECT(v)) { - if (JSVAL_IS_NULL(v)) - return JSJTYPE_NULL; - js_obj = JSVAL_TO_OBJECT(v); - if (JS_InstanceOf(cx, js_obj, &JavaObject_class, 0)) - return JSJTYPE_JAVAOBJECT; - if (JS_InstanceOf(cx, js_obj, &JavaArray_class, 0)) - return JSJTYPE_JAVAARRAY; - if (JS_InstanceOf(cx, js_obj, &JavaClass_class, 0)) - return JSJTYPE_JAVACLASS; - if (JS_IsArrayObject(cx, js_obj)) - return JSJTYPE_JSARRAY; - return JSJTYPE_OBJECT; - } else if (JSVAL_IS_NUMBER(v)) { - return JSJTYPE_NUMBER; - } else if (JSVAL_IS_STRING(v)) { - return JSJTYPE_STRING; - } else if (JSVAL_IS_BOOLEAN(v)) { - return JSJTYPE_BOOLEAN; - } else if (JSVAL_IS_VOID(v)) { - return JSJTYPE_VOID; - } - JS_ASSERT(0); /* Unknown JS type ! */ - return JSJTYPE_VOID; -} - -/* - * Ranking table used to establish preferences among Java types when converting - * from JavaScript types. Each row represents a different JavaScript source - * type and each column represents a different target Java type. Lower values - * in the table indicate conversions that are ranked higher. The special - * value 99 indicates a disallowed JS->Java conversion. The special value of - * 0 indicates special handling is required to determine ranking. - */ -static int rank_table[JSJTYPE_LIMIT][JAVA_SIGNATURE_LIMIT] = { -/* boolean long - | char | float java.lang.Boolean - | | byte | | double | java.lang.Class - | | | short | | | array | | java.lang.Double - | | | | int | | | | object | | netscape.javascript.JSObject - | | | | | | | | | | | | | | java.lang.Object - | | | | | | | | | | | | | | | java.lang.String */ - - {99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 1, 1}, /* undefined */ - { 1, 99, 99, 99, 99, 99, 99, 99, 99, 99, 2, 99, 99, 99, 3, 4}, /* boolean */ - {99, 7, 8, 6, 5, 4, 3, 1, 99, 99, 99, 99, 2, 99, 11, 9}, /* number */ - {99, 3, 4, 4, 4, 4, 4, 4, 99, 99, 99, 99, 99, 99, 2, 1}, /* string */ - {99, 99, 99, 99, 99, 99, 99, 99, 1, 1, 1, 1, 1, 1, 1, 1}, /* null */ - {99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 1, 99, 2, 3, 4}, /* JavaClass */ - {99, 7, 8, 6, 5, 4, 3, 2, 0, 0, 0, 0, 0, 0, 0, 1}, /* JavaObject */ - {99, 99, 99, 99, 99, 99, 99, 99, 0, 0, 99, 99, 99, 99, 0, 1}, /* JavaArray */ - {99, 99, 99, 99, 99, 99, 99, 99, 2, 99, 99, 99, 99, 1, 3, 4}, /* JS Array */ - {99, 9, 10, 8, 7, 6, 5, 4, 99, 99, 99, 99, 99, 1, 2, 3} /* other JS object */ -}; - -/* - * Returns JS_TRUE if JavaScript arguments are compatible with the specified - * Java method signature. - */ -static JSBool -method_signature_matches_JS_args(JSContext *cx, JNIEnv *jEnv, uintN argc, jsval *argv, - JavaMethodSignature *method_signature) -{ - uintN i; - JavaClassDescriptor *descriptor; - JavaObjectWrapper *java_wrapper; - jclass java_class; - jobject java_obj; - JSObject *js_obj; - JSJType js_type; - jsval js_val; - int rank; - - if (argc != (uintN)method_signature->num_args) - return JS_FALSE; - - for (i = 0; i < argc; i++) { - js_val = argv[i]; - js_type = compute_jsj_type(cx, js_val); - descriptor = method_signature->arg_signatures[i]; - rank = rank_table[js_type][(int)descriptor->type - 2]; - - /* Check for disallowed JS->Java conversion */ - if (rank == 99) - return JS_FALSE; - - /* Check for special handling required by conversion from JavaObject */ - if (rank == 0) { - java_class = descriptor->java_class; - - js_obj = JSVAL_TO_OBJECT(js_val); - java_wrapper = JS_GetPrivate(cx, js_obj); - java_obj = java_wrapper->java_obj; - - if (!(*jEnv)->IsInstanceOf(jEnv, java_obj, java_class)) - return JS_FALSE; - } - } - - return JS_TRUE; -} - -#ifdef HAS_OLD_STYLE_METHOD_RESOLUTION - -static JavaMethodSpec * -resolve_overloaded_method(JSContext *cx, JNIEnv *jEnv, JavaMemberDescriptor *member_descriptor, - JavaClassDescriptor *class_descriptor, - JSBool is_static_method, - uintN argc, jsval *argv) -{ - int cost, lowest_cost, num_method_matches; - JavaMethodSpec *best_method_match, *method; - - num_method_matches = 0; - lowest_cost = 10000; - best_method_match = NULL; - - for (method = member_descriptor->methods; method; method = method->next) { - cost = 0; - if (!method_signature_matches_JS_args(cx, jEnv, argc, argv, &method->signature, &cost)) - continue; - - if (cost < lowest_cost) { - lowest_cost = cost; - best_method_match = method; - num_method_matches++; - } - } - - if (!best_method_match) - report_method_match_failure(cx, member_descriptor, class_descriptor, - is_static_method, argc, argv); - - if (lowest_cost != 0) - return NULL; - - return best_method_match; -} - -#else /* !OLD_STYLE_METHOD_RESOLUTION */ - -/* - * Determine the more natural (preferred) JavaScript->Java conversion - * given one JavaScript value and two Java types. - * See http://www.mozilla.org/js/liveconnect/lc3_method_overloading.html - * for details. - */ -static JSJTypePreference -preferred_conversion(JSContext *cx, JNIEnv *jEnv, jsval js_val, - JavaClassDescriptor *descriptor1, - JavaClassDescriptor *descriptor2) -{ - JSJType js_type; - int rank1, rank2; - jclass java_class1, java_class2; - JavaObjectWrapper *java_wrapper; - jobject java_obj; - JSObject *js_obj; - - js_type = compute_jsj_type(cx, js_val); - rank1 = rank_table[js_type][(int)descriptor1->type - 2]; - rank2 = rank_table[js_type][(int)descriptor2->type - 2]; - - /* Fast path for conversion from most JS types */ - if (rank1 < rank2) - return JSJPREF_FIRST_ARG; - - /* - * Special logic is required for matching the classes of wrapped - * Java objects. - */ - if (rank2 == 0) { - java_class1 = descriptor1->java_class; - java_class2 = descriptor2->java_class; - - js_obj = JSVAL_TO_OBJECT(js_val); - java_wrapper = JS_GetPrivate(cx, js_obj); - java_obj = java_wrapper->java_obj; - - /* Unwrapped JavaObject must be compatible with Java arg type */ - if (!(*jEnv)->IsInstanceOf(jEnv, java_obj, java_class2)) - return JSJPREF_FIRST_ARG; - - /* - * For JavaObject arguments, any compatible reference type is preferable - * to any primitive Java type or to java.lang.String. - */ - if (rank1 != 0) - return JSJPREF_SECOND_ARG; - - /* - * If argument of type descriptor1 is subclass of type descriptor 2, then - * descriptor1 is preferred and vice-versa. - */ - if ((*jEnv)->IsAssignableFrom(jEnv, java_class1, java_class2)) - return JSJPREF_FIRST_ARG; - - if ((*jEnv)->IsAssignableFrom(jEnv, java_class2, java_class1)) - return JSJPREF_SECOND_ARG; - - /* This can happen in unusual situations involving interface types. */ - return JSJPREF_AMBIGUOUS; - } - - if (rank1 > rank2) - return JSJPREF_SECOND_ARG; - - return JSJPREF_AMBIGUOUS; -} - -static JSJTypePreference -method_preferred(JSContext *cx, JNIEnv *jEnv, jsval *argv, - JavaMethodSignature *method_signature1, - JavaMethodSignature *method_signature2) -{ - int arg_index, argc, preference; - jsval val; - JavaSignature* *arg_signatures1; - JavaSignature* *arg_signatures2; - JavaSignature *arg_type1, *arg_type2; - - arg_signatures1 = method_signature1->arg_signatures; - arg_signatures2 = method_signature2->arg_signatures; - argc = method_signature1->num_args; - JS_ASSERT(argc == method_signature2->num_args); - - preference = 0; - for (arg_index = 0; arg_index < argc; arg_index++) { - val = argv[arg_index]; - arg_type1 = *arg_signatures1++; - arg_type2 = *arg_signatures2++; - - if (arg_type1 == arg_type2) - continue; - - preference |= preferred_conversion(cx, jEnv, val, arg_type1, arg_type2); - - if ((JSJTypePreference)preference == JSJPREF_AMBIGUOUS) - return JSJPREF_AMBIGUOUS; - } - return (JSJTypePreference)preference; -} - -/* - * This routine applies heuristics to guess the intended Java method given the - * runtime JavaScript argument types and the type signatures of the candidate - * methods. Informally, the method with Java parameter types that most closely - * match the JavaScript types is chosen. A more precise specification is - * provided in the lc3_method_resolution.html file. The code uses a very - * brute-force approach. - */ -static JavaMethodSpec * -resolve_overloaded_method(JSContext *cx, JNIEnv *jEnv, - JavaMemberDescriptor *member_descriptor, - JavaClassDescriptor *class_descriptor, - JSBool is_static_method, - uintN argc, jsval *argv) -{ - JSJTypePreference preference; - JavaMethodSpec *method, *best_method_match; - MethodList ambiguous_methods; - MethodListElement *method_list_element, *next_element; - - /* - * Determine the first Java method among the overloaded methods of the same name - * that matches all the JS arguments. - */ - for (method = member_descriptor->methods; method; method = method->next) { - if (method_signature_matches_JS_args(cx, jEnv, argc, argv, &method->signature)) - break; - } - - /* Report an error if no method matched the JS arguments */ - if (!method) { - report_method_match_failure(cx, member_descriptor, class_descriptor, - is_static_method, argc, argv); - return NULL; - } - - /* Shortcut a common case */ - if (!method->next) - return method; - - /* - * Form a list of all methods that are neither more or less preferred than the - * best matching method discovered so far. - */ - JS_INIT_CLIST(&ambiguous_methods); - - best_method_match = method; - - /* See if there are any Java methods that are a better fit for the JS args */ - for (method = method->next; method; method = method->next) { - if (method->signature.num_args != (int)argc) - continue; - preference = method_preferred(cx, jEnv, argv, &best_method_match->signature, - &method->signature); - if (preference == JSJPREF_SECOND_ARG) { - best_method_match = method; - } else if (preference == JSJPREF_AMBIGUOUS) { - /* Add this method to the list of ambiguous methods */ - method_list_element = - (MethodListElement*)JS_malloc(cx, sizeof(MethodListElement)); - if (!method_list_element) - goto error; - method_list_element->method = method; - JS_APPEND_LINK(&method_list_element->linkage, &ambiguous_methods); - } - } - - /* - * Ensure that best_method_match is preferred to all methods on the - * ambiguous_methods list. - */ - - for (method_list_element = (MethodListElement*)JS_LIST_HEAD(&ambiguous_methods); - (MethodList*)method_list_element != &ambiguous_methods; - method_list_element = next_element) { - next_element = (MethodListElement*)method_list_element->linkage.next; - method = method_list_element->method; - preference = method_preferred(cx, jEnv, argv, &best_method_match->signature, - &method->signature); - if (preference != JSJPREF_FIRST_ARG) - continue; - JS_REMOVE_LINK(&method_list_element->linkage); - JS_free(cx, method_list_element); - } - - /* - * The chosen method must be maximally preferred, i.e. there can be no other - * method that is just as preferred. - */ - if (!JS_CLIST_IS_EMPTY(&ambiguous_methods)) { - /* Add the best_method_match to the list of ambiguous methods */ - method_list_element = - (MethodListElement*)JS_malloc(cx, sizeof(MethodListElement)); - if (!method_list_element) - goto error; - method_list_element->method = best_method_match; - JS_APPEND_LINK(&method_list_element->linkage, &ambiguous_methods); - - /* Report the problem */ - report_ambiguous_method_match(cx, member_descriptor, class_descriptor, - &ambiguous_methods, is_static_method, argc, argv); - goto error; - } - - return best_method_match; - -error: - /* Delete the storage for the ambiguous_method list */ - while (!JS_CLIST_IS_EMPTY(&ambiguous_methods)) { - method_list_element = (MethodListElement*)JS_LIST_HEAD(&ambiguous_methods); - JS_REMOVE_LINK(&method_list_element->linkage); - JS_free(cx, method_list_element); - } - - return NULL; -} - -#endif /* !HAS_OLD_STYLE_METHOD_RESOLUTION */ - -static jvalue * -convert_JS_method_args_to_java_argv(JSContext *cx, JNIEnv *jEnv, jsval *argv, - JavaMethodSpec *method, JSBool **localvp) -{ - jvalue *jargv; - JSBool ok, *localv; - uintN i, argc; - JavaSignature **arg_signatures; - JavaMethodSignature *signature; - - - signature = &method->signature; - argc = signature->num_args; - JS_ASSERT(argc != 0); - arg_signatures = signature->arg_signatures; - - jargv = (jvalue *)JS_malloc(cx, sizeof(jvalue) * argc); - - if (!jargv) - return NULL; - - /* - * Allocate an array that contains a flag for each argument, indicating whether - * or not the conversion from a JS value to a Java value resulted in a new - * JNI local reference. - */ - localv = (JSBool *)JS_malloc(cx, sizeof(JSBool) * argc); - *localvp = localv; - if (!localv) { - JS_free(cx, jargv); - return NULL; - } - - for (i = 0; i < argc; i++) { - int dummy_cost; - - ok = jsj_ConvertJSValueToJavaValue(cx, jEnv, argv[i], arg_signatures[i], - &dummy_cost, &jargv[i], &localv[i]); - if (!ok) { - JS_free(cx, jargv); - JS_free(cx, localv); - *localvp = NULL; - return NULL; - } - } - - return jargv; -} - -static JSBool -invoke_java_method(JSContext *cx, JSJavaThreadState *jsj_env, - jobject java_class_or_instance, - JavaClassDescriptor *class_descriptor, - JavaMethodSpec *method, - JSBool is_static_method, - jsval *argv, jsval *vp) -{ - jvalue java_value; - jvalue *jargv; - uintN argc, i; - jobject java_object; - jclass java_class; - jmethodID methodID; - JavaMethodSignature *signature; - JavaSignature *return_val_signature; - JNIEnv *jEnv; - JSBool *localv, error_occurred, success; - - success = error_occurred = JS_FALSE; - return_val_signature = NULL; /* Quiet gcc uninitialized variable warning */ - - methodID = method->methodID; - signature = &method->signature; - argc = signature->num_args; - - jEnv = jsj_env->jEnv; - - if (is_static_method) { - java_object = NULL; - java_class = java_class_or_instance; - } else { - java_object = java_class_or_instance; - java_class = NULL; - } - - jargv = NULL; - localv = NULL; - if (argc) { - jargv = convert_JS_method_args_to_java_argv(cx, jEnv, argv, method, &localv); - if (!jargv) { - error_occurred = JS_TRUE; - goto out; - } - } - - /* Prevent deadlocking if we re-enter JS on another thread as a result of a Java - method call and that new thread wants to perform a GC. */ -#ifdef JSJ_THREADSAFE - JS_EndRequest(cx); -#endif - -#define CALL_JAVA_METHOD(type, member) \ - JS_BEGIN_MACRO \ - if (is_static_method) { \ - java_value.member = (*jEnv)->CallStatic##type##MethodA(jEnv, java_class, methodID, jargv);\ - } else { \ - java_value.member = (*jEnv)->Call##type##MethodA(jEnv, java_object, methodID, jargv);\ - } \ - if ((*jEnv)->ExceptionOccurred(jEnv)) { \ - jsj_ReportJavaError(cx, jEnv, "Error calling method %s.%s()", \ - class_descriptor->name, method->name); \ - error_occurred = JS_TRUE; \ - goto out; \ - } \ - JS_END_MACRO - - return_val_signature = signature->return_val_signature; - switch(return_val_signature->type) { - case JAVA_SIGNATURE_BYTE: - CALL_JAVA_METHOD(Byte, b); - break; - - case JAVA_SIGNATURE_CHAR: - CALL_JAVA_METHOD(Char, c); - break; - - case JAVA_SIGNATURE_FLOAT: - CALL_JAVA_METHOD(Float, f); - break; - - case JAVA_SIGNATURE_DOUBLE: - CALL_JAVA_METHOD(Double, d); - break; - - case JAVA_SIGNATURE_INT: - CALL_JAVA_METHOD(Int, i); - break; - - case JAVA_SIGNATURE_LONG: - CALL_JAVA_METHOD(Long, j); - break; - - case JAVA_SIGNATURE_SHORT: - CALL_JAVA_METHOD(Short, s); - break; - - case JAVA_SIGNATURE_BOOLEAN: - CALL_JAVA_METHOD(Boolean, z); - break; - - case JAVA_SIGNATURE_VOID: - if (is_static_method) - (*jEnv)->CallStaticVoidMethodA(jEnv, java_class, methodID, jargv); - else - (*jEnv)->CallVoidMethodA(jEnv, java_object, methodID, jargv); - if ((*jEnv)->ExceptionOccurred(jEnv)) { - jsj_ReportJavaError(cx, jEnv, "Error calling method %s.%s()", - class_descriptor->name, method->name); - error_occurred = JS_TRUE; - goto out; - } - break; - - case JAVA_SIGNATURE_UNKNOWN: - JS_ASSERT(0); - error_occurred = JS_TRUE; - goto out; - - /* Non-primitive (reference) type */ - default: - JS_ASSERT(IS_REFERENCE_TYPE(return_val_signature->type)); - CALL_JAVA_METHOD(Object, l); - break; - } - -out: - - if (localv) { - for (i = 0; i < argc; i++) { - if (localv[i]) - (*jEnv)->DeleteLocalRef(jEnv, jargv[i].l); - } - JS_free(cx, localv); - } - if (jargv) - JS_free(cx, jargv); - -#ifdef JSJ_THREADSAFE - JS_BeginRequest(cx); -#endif - - if (!error_occurred) { - success = jsj_ConvertJavaValueToJSValue(cx, jEnv, return_val_signature, &java_value, vp); - if (IS_REFERENCE_TYPE(return_val_signature->type)) - (*jEnv)->DeleteLocalRef(jEnv, java_value.l); - } - return success; -} - -static JSBool -invoke_overloaded_java_method(JSContext *cx, JSJavaThreadState *jsj_env, - JavaMemberDescriptor *member, - JSBool is_static_method, - jobject java_class_or_instance, - JavaClassDescriptor *class_descriptor, - uintN argc, jsval *argv, - jsval *vp) -{ - JavaMethodSpec *method; - JNIEnv *jEnv; - - jEnv = jsj_env->jEnv; - - method = resolve_overloaded_method(cx, jEnv, member, class_descriptor, - is_static_method, argc, argv); - if (!method) - return JS_FALSE; - - return invoke_java_method(cx, jsj_env, java_class_or_instance, class_descriptor, - method, is_static_method, argv, vp); -} - -static JSBool -invoke_java_constructor(JSContext *cx, - JSJavaThreadState *jsj_env, - jclass java_class, - JavaMethodSpec *method, - jsval *argv, jsval *vp) -{ - jvalue *jargv; - uintN argc, i; - jobject java_object; - jmethodID methodID; - JavaMethodSignature *signature; - JNIEnv *jEnv; - JSBool *localv; - JSBool success, error_occurred; - java_object = NULL; /* Stifle gcc uninitialized variable warning */ - - success = error_occurred = JS_FALSE; - - methodID = method->methodID; - signature = &method->signature; - argc = signature->num_args; - - jEnv = jsj_env->jEnv; - - jargv = NULL; - localv = NULL; - if (argc) { - jargv = convert_JS_method_args_to_java_argv(cx, jEnv, argv, method, &localv); - if (!jargv) { - error_occurred = JS_TRUE; - goto out; - } - } - - /* Prevent deadlocking if we re-enter JS on another thread as a result of a Java - method call and that new thread wants to perform a GC. */ -#ifdef JSJ_THREADSAFE - JS_EndRequest(cx); -#endif - - /* Call the constructor */ - java_object = (*jEnv)->NewObjectA(jEnv, java_class, methodID, jargv); - -#ifdef JSJ_THREADSAFE - JS_BeginRequest(cx); -#endif - - if (!java_object) { - jsj_ReportJavaError(cx, jEnv, "Error while constructing instance of %s", - jsj_GetJavaClassName(cx, jEnv, java_class)); - error_occurred = JS_TRUE; - goto out; - } - -out: - if (localv) { - for (i = 0; i < argc; i++) { - if (localv[i]) - (*jEnv)->DeleteLocalRef(jEnv, jargv[i].l); - } - JS_free(cx, localv); - } - if (jargv) - JS_free(cx, jargv); - - if (!error_occurred) - success = jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_object, vp); - (*jEnv)->DeleteLocalRef(jEnv, java_object); - return success; -} - -static JSBool -invoke_overloaded_java_constructor(JSContext *cx, - JSJavaThreadState *jsj_env, - JavaMemberDescriptor *member, - JavaClassDescriptor *class_descriptor, - uintN argc, jsval *argv, - jsval *vp) -{ - jclass java_class; - JavaMethodSpec *method; - JNIEnv *jEnv; - - jEnv = jsj_env->jEnv; - - method = resolve_overloaded_method(cx, jEnv, member, class_descriptor, JS_TRUE, - argc, argv); - if (!method) - return JS_FALSE; - - java_class = class_descriptor->java_class; - return invoke_java_constructor(cx, jsj_env, java_class, method, argv, vp); -} - -static JSBool -java_constructor_wrapper(JSContext *cx, JSJavaThreadState *jsj_env, - JavaMemberDescriptor *member_descriptor, - JavaClassDescriptor *class_descriptor, - uintN argc, jsval *argv, jsval *vp) -{ - jint modifiers; - JNIEnv *jEnv; - - jEnv = jsj_env->jEnv; - - /* Get class/interface flags and check them */ - modifiers = class_descriptor->modifiers; - if (modifiers & ACC_ABSTRACT) { - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_ABSTRACT_JCLASS, class_descriptor->name); - return JS_FALSE; - } - if (modifiers & ACC_INTERFACE) { - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_IS_INTERFACE, class_descriptor->name); - return JS_FALSE; - } - if ( !(modifiers & ACC_PUBLIC) ) { - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_NOT_PUBLIC, class_descriptor->name); - return JS_FALSE; - } - - if (!member_descriptor) { - JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, - JSJMSG_NO_CONSTRUCTORS, class_descriptor->name); - return JS_FALSE; - } - - return invoke_overloaded_java_constructor(cx, jsj_env, member_descriptor, - class_descriptor, argc, argv, vp); -} - -JS_EXPORT_API(JSBool) -jsj_JavaConstructorWrapper(JSContext *cx, JSObject *obj, - uintN argc, jsval *argv, jsval *vp) -{ - JavaClassDescriptor *class_descriptor; - JavaMemberDescriptor *member_descriptor; - JSJavaThreadState *jsj_env; - JNIEnv *jEnv; - JSBool result; - - obj = JSVAL_TO_OBJECT(argv[-2]); - class_descriptor = JS_GetPrivate(cx, obj); - JS_ASSERT(class_descriptor); - if (!class_descriptor) - return JS_FALSE; - - /* XXX, workaround for bug 200016, all classes in sun.plugin package should not - be accessible in liveconnect. - Ideally, this checking should be done in JPI side, but it's not going to happen - until Sun JRE 1.5.1 */ - if (strstr(class_descriptor->name, "sun.plugin.") == class_descriptor->name) - return JS_FALSE; - - /* Get the Java per-thread environment pointer for this JSContext */ - jsj_env = jsj_EnterJava(cx, &jEnv); - if (!jEnv) - return JS_FALSE; - member_descriptor = jsj_LookupJavaClassConstructors(cx, jEnv, class_descriptor); - result = java_constructor_wrapper(cx, jsj_env, member_descriptor, - class_descriptor, argc, argv, vp); - jsj_ExitJava(jsj_env); - return result; -} - - -static JSBool -static_method_wrapper(JSContext *cx, JSJavaThreadState *jsj_env, - JavaClassDescriptor *class_descriptor, - jsid id, - uintN argc, jsval *argv, jsval *vp) -{ - JNIEnv *jEnv; - JavaMemberDescriptor *member_descriptor; - - jEnv = jsj_env->jEnv; - member_descriptor = jsj_LookupJavaStaticMemberDescriptorById(cx, jEnv, class_descriptor, id); - - /* Is it a static method that is not a constructor ? */ - if (member_descriptor && strcmp(member_descriptor->name, "")) { - return invoke_overloaded_java_method(cx, jsj_env, member_descriptor, JS_TRUE, - class_descriptor->java_class, - class_descriptor, argc, argv, vp); - } - - JS_ASSERT(member_descriptor); - if (!member_descriptor) - return JS_FALSE; - - /* Must be an explicitly resolved overloaded constructor */ - return java_constructor_wrapper(cx, jsj_env, member_descriptor, - class_descriptor, argc, argv, vp); -} - -JS_EXTERN_API(JSBool) -jsj_JavaStaticMethodWrapper(JSContext *cx, JSObject *obj, - uintN argc, jsval *argv, jsval *vp) -{ - JSFunction *function; - JavaClassDescriptor *class_descriptor; - jsid id; - jsval idval; - JNIEnv *jEnv; - JSJavaThreadState *jsj_env; - JSBool result; - - class_descriptor = JS_GetPrivate(cx, obj); - if (!class_descriptor) - return JS_FALSE; - - /* Get the Java per-thread environment pointer for this JSContext */ - jsj_env = jsj_EnterJava(cx, &jEnv); - if (!jEnv) - return JS_FALSE; - - JS_ASSERT(JS_TypeOfValue(cx, argv[-2]) == JSTYPE_FUNCTION); - function = JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[-2])); - idval = STRING_TO_JSVAL(JS_InternString(cx, JS_GetFunctionName(function))); - JS_ValueToId(cx, idval, &id); - - result = static_method_wrapper(cx, jsj_env, class_descriptor, id, argc, argv, vp); - jsj_ExitJava(jsj_env); - return result; -} - -JS_EXPORT_API(JSBool) -jsj_JavaInstanceMethodWrapper(JSContext *cx, JSObject *obj, - uintN argc, jsval *argv, jsval *vp) -{ - JSFunction *function; - JavaMemberDescriptor *member_descriptor; - JavaObjectWrapper *java_wrapper; - JavaClassDescriptor *class_descriptor; - jsid id; - jsval idval; - JSJavaThreadState *jsj_env; - JNIEnv *jEnv; - jobject java_obj; - JSBool result; - - java_wrapper = JS_GetPrivate(cx, obj); - if (!java_wrapper) - return JS_FALSE; - java_obj = java_wrapper->java_obj; - - JS_ASSERT(JS_TypeOfValue(cx, argv[-2]) == JSTYPE_FUNCTION); - function = JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[-2])); - idval = STRING_TO_JSVAL(JS_InternString(cx, JS_GetFunctionName(function))); - JS_ValueToId(cx, idval, &id); - class_descriptor = java_wrapper->class_descriptor; - - /* Get the Java per-thread environment pointer for this JSContext */ - jsj_env = jsj_EnterJava(cx, &jEnv); - if (!jEnv) - return JS_FALSE; - - if (jaApplet && (*jEnv)->IsInstanceOf(jEnv, java_obj, jaApplet)) { - jsj_JSIsCallingApplet = JS_TRUE; - } - - /* Try to find an instance method with the given name first */ - member_descriptor = jsj_LookupJavaMemberDescriptorById(cx, jEnv, class_descriptor, id); - if (member_descriptor) - result = invoke_overloaded_java_method(cx, jsj_env, member_descriptor, - JS_FALSE, java_obj, - class_descriptor, argc, argv, vp); - - /* If no instance method was found, try for a static method or constructor */ - else - result = static_method_wrapper(cx, jsj_env, class_descriptor, id, argc, argv, vp); - jsj_ExitJava(jsj_env); - return result; -} - diff --git a/lib/javascript/liveconnect/jsj_nodl.c b/lib/javascript/liveconnect/jsj_nodl.c deleted file mode 100644 index 8b137891..00000000 --- a/lib/javascript/liveconnect/jsj_nodl.c +++ /dev/null @@ -1 +0,0 @@ - diff --git a/lib/javascript/liveconnect/jsj_private.h b/lib/javascript/liveconnect/jsj_private.h deleted file mode 100644 index 82f9d28d..00000000 --- a/lib/javascript/liveconnect/jsj_private.h +++ /dev/null @@ -1,684 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * This Original Code has been modified by IBM Corporation. Modifications made - * by IBM described herein are Copyright (c) International Business Machines - * Corporation, 2000. - * Modifications to Mozilla code or documentation identified per MPL Section 3.3 - * - * Date Modified by Description of modification - * 04/20/2000 IBM Corp. OS/2 VisualAge build. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * This file is part of the Java-vendor-neutral implementation of LiveConnect - * - * Declarations of private (internal) functions/data/types for - * JavaScript <==> Java communication. - * - */ - - -#ifndef _JSJAVA_PVT_H -#define _JSJAVA_PVT_H - -#include "jstypes.h" - -# include "jsprf.h" -# include "jsutil.h" -# include "jshash.h" - -#include "jsj_hash.h" /* Hash tables */ -#include "jni.h" /* Java Native Interface */ -#include "jsapi.h" /* JavaScript engine API */ -#include "jsjava.h" /* LiveConnect public API */ - -/* - * OJI provides its own reentrancy-inhibiting monitors in the enter_js() - * and exit_js() callbacks, so it does not need redundant thread-safety code. - */ -#if defined(OJI) && !defined(JSJ_INHIBIT_THREADSAFE) -# define JSJ_INHIBIT_THREADSAFE -#endif - -/* If JS is thread-safe, so is LiveConnect, unless overridden */ -#ifndef JSJ_THREADSAFE -# if defined(JS_THREADSAFE) && !defined(JSJ_INHIBIT_THREADSAFE) -# define JSJ_THREADSAFE -# endif -#endif - -/* - * This file doesn't include prtypes.h, which defines PR_BEGIN_EXTERN_C, - * and I certainly don't want to pull it in to such a high level include - * file, so I'll just do what prtypes.h does. edburns - */ -#ifdef __cplusplus -extern "C" { -#endif - -/*************************** Type Declarations ******************************/ - -/* Forward type declarations */ -typedef struct JavaMemberDescriptor JavaMemberDescriptor; -typedef struct JavaMethodSpec JavaMethodSpec; -typedef struct JavaClassDescriptor JavaClassDescriptor; -typedef struct JavaClassDescriptor JavaSignature; -typedef struct CapturedJSError CapturedJSError; - -/* - * This enum uses a method similar to the JDK to specify - * Java type signatures, but the classification of Java - * object types is more fine-grained. - */ -typedef enum { - JAVA_SIGNATURE_UNKNOWN, - JAVA_SIGNATURE_VOID, - - /* Primitive types */ - JAVA_SIGNATURE_BOOLEAN, - JAVA_SIGNATURE_CHAR, - JAVA_SIGNATURE_BYTE, - JAVA_SIGNATURE_SHORT, - JAVA_SIGNATURE_INT, - JAVA_SIGNATURE_LONG, - JAVA_SIGNATURE_FLOAT, - JAVA_SIGNATURE_DOUBLE, - - /* Reference types */ - JAVA_SIGNATURE_ARRAY, /* Any array class */ - JAVA_SIGNATURE_OBJECT, /* non-array object, but not one of the - more specific types below */ - JAVA_SIGNATURE_JAVA_LANG_BOOLEAN, /* java.lang.Boolean */ - JAVA_SIGNATURE_JAVA_LANG_CLASS, /* java.lang.Class */ - JAVA_SIGNATURE_JAVA_LANG_DOUBLE, /* java.lang.Double */ - JAVA_SIGNATURE_NETSCAPE_JAVASCRIPT_JSOBJECT, /* netscape.javascript.JSObject */ - JAVA_SIGNATURE_JAVA_LANG_OBJECT, /* java.lang.Object */ - JAVA_SIGNATURE_JAVA_LANG_STRING, /* java.lang.String */ - - JAVA_SIGNATURE_LIMIT -} JavaSignatureChar; - -#define IS_REFERENCE_TYPE(sig) ((int)(sig) >= (int)JAVA_SIGNATURE_ARRAY) -#define IS_OBJECT_TYPE(sig) ((int)(sig) >= (int)JAVA_SIGNATURE_OBJECT) -#define IS_PRIMITIVE_TYPE(sig) \ - (((int)(sig) >= (int)JAVA_SIGNATURE_BOOLEAN) && !IS_REFERENCE_TYPE(sig)) \ - -/* This is used for checking whether an exception is wrapped or not. */ -#define JSTYPE_EMPTY -1 - -/* The signature of a Java method consists of the signatures of all its - arguments and its return type signature. */ -typedef struct JavaMethodSignature { - jsize num_args; /* Length of arg_signatures array */ - JavaSignature ** arg_signatures; /* Array of argument signatures */ - JavaSignature * return_val_signature; /* Return type signature */ -} JavaMethodSignature; - -/* A descriptor for the reflection of a single Java field */ -typedef struct JavaFieldSpec { - jfieldID fieldID; /* JVM opaque access handle for field */ - JavaSignature * signature; /* Java type of field */ - int modifiers; /* Bitfield indicating field qualifiers */ - const char * name; /* UTF8; TODO - Should support Unicode field names */ -} JavaFieldSpec; - -/* A descriptor for the reflection of a single Java method. - Each overloaded method has a separate corresponding JavaMethodSpec. */ -struct JavaMethodSpec { - jmethodID methodID; /* JVM opaque access handle for method */ - JavaMethodSignature signature; - const char * name; /* UTF8; TODO - Should support Unicode method names */ - JavaMethodSpec * next; /* next method in chain of overloaded methods */ - JSBool is_alias; /* An aliased name for a Java method ? */ -}; - -/* - * A descriptor for the reflection of a single member of a Java object. - * This can represent one or more Java methods and/or a single field. - * (When there is more than one method attached to a single JavaMemberDescriptor - * they are overloaded methods sharing the same simple name.) This same - * descriptor type is used for both static or instance members. - */ -struct JavaMemberDescriptor { - const char * name; /* simple name of field and/or method */ - jsid id; /* hashed name for quick JS property lookup */ - JavaFieldSpec * field; /* field with the given name, if any */ - JavaMethodSpec * methods; /* Overloaded methods which share the same name, if any */ - JavaMemberDescriptor * next; /* next descriptor in same defining class */ - JSObject * invoke_func_obj; /* If non-null, JSFunction obj to invoke method */ -}; - -/* Status of Class member reflection. See JavaClassDescriptor. */ -typedef enum { - REFLECT_NO, - REFLECT_IN_PROGRESS, - REFLECT_COMPLETE -} ReflectStatus; - -/* This is the native portion of a reflected Java class */ -struct JavaClassDescriptor { - const char * name; /* Name of class, e.g. "java.lang.Byte" */ - JavaSignatureChar type; /* class category: primitive type, object, array */ - jclass java_class; /* Opaque JVM handle to corresponding java.lang.Class */ - int num_instance_members; - int num_static_members; - volatile ReflectStatus instance_members_reflected; - JavaMemberDescriptor * instance_members; - volatile ReflectStatus static_members_reflected; - JavaMemberDescriptor * static_members; - JavaMemberDescriptor * constructors; - int modifiers; /* Class declaration qualifiers, - e.g. abstract, private */ - int ref_count; /* # of references to this struct */ - JavaSignature * array_component_signature; /* Only non-NULL for array classes */ -}; - -typedef struct JavaObjectWrapper JavaObjectWrapper; - -/* This is the native portion of a reflected Java object */ -struct JavaObjectWrapper { - jobject java_obj; /* Opaque JVM ref to Java object */ - JavaClassDescriptor * class_descriptor; /* Java class info */ - union { - JSJHashNumber hash_code; /* Cached hash code */ - JavaObjectWrapper * next; /* Link to next wrapper after finalization */ - } u; -}; - -/* These are definitions of the Java class/method/field modifier bits. - These really shouldn't be hard-coded here. Rather, - they should be read from java.lang.reflect.Modifier */ -#define ACC_PUBLIC 0x0001 /* visible to everyone */ -#define ACC_STATIC 0x0008 /* instance variable is static */ -#define ACC_FINAL 0x0010 /* no further subclassing,overriding */ -#define ACC_INTERFACE 0x0200 /* class is an interface */ -#define ACC_ABSTRACT 0x0400 /* no definition provided */ - -/* A JSJavaVM structure must be created for each Java VM that is accessed - via LiveConnect */ -struct JSJavaVM { -/* TODO - all LiveConnect global variables should be migrated into this - structure in order to allow more than one LiveConnect-enabled - Java VM to exist within the same process. */ - void * init_args; /* args to initialize VM with */ - SystemJavaVM * java_vm; - JNIEnv * main_thread_env; /* Main-thread Java environment */ - JSPackedBool jsj_created_java_vm; - JSPackedBool jsj_inited_java_vm; - int num_attached_threads; - JSJavaVM * next; /* next VM among all created VMs */ -}; - -/* Per-thread state that encapsulates the connection to the Java VM */ -struct JSJavaThreadState { - const char * name; /* Thread name, for debugging */ - JSJavaVM * jsjava_vm; /* All per-JVM state */ - JNIEnv * jEnv; /* Per-thread opaque handle to Java VM */ - CapturedJSError * pending_js_errors; /* JS errors to be thrown as Java exceptions */ - JSContext * cx; /* current JS context for thread */ - int recursion_depth;/* # transitions into Java from JS */ - JSJavaThreadState * next; /* next thread state among all created threads */ -}; - -struct JavaToJSSavedState { - JSErrorReporter error_reporter; - JSJavaThreadState* java_jsj_env; -}; -typedef struct JavaToJSSavedState JavaToJSSavedState; - - -/* This object provides is the "anchor" by which netscape.javscript.JSObject - objects hold a reference to native JSObjects. */ -struct JSObjectHandle { - JSObject *js_obj; - JSRuntime *rt; -}; -typedef struct JSObjectHandle JSObjectHandle; - - -/******************************** Globals ***********************************/ - -extern JSJCallbacks *JSJ_callbacks; - -/* JavaScript classes that reflect Java objects */ -extern JSClass JavaObject_class; -extern JSClass JavaArray_class; -extern JSClass JavaClass_class; -extern JSClass JavaMember_class; - -/* - * Opaque JVM handles to Java classes, methods and objects required for - * Java reflection. These are computed and cached during initialization. - * TODO: These should be moved inside the JSJavaVM struct - */ -extern jclass jlObject; /* java.lang.Object */ -extern jclass jlrConstructor; /* java.lang.reflect.Constructor */ -extern jclass jlrArray; /* java.lang.reflect.Array */ -extern jclass jlThrowable; /* java.lang.Throwable */ -extern jclass jlSystem; /* java.lang.System */ -extern jclass jlClass; /* java.lang.Class */ -extern jclass jlBoolean; /* java.lang.Boolean */ -extern jclass jlDouble; /* java.lang.Double */ -extern jclass jlString; /* java.lang.String */ -extern jclass jaApplet; /* java.applet.Applet */ -extern jclass njJSObject; /* netscape.javascript.JSObject */ -extern jclass njJSException; /* netscape.javascript.JSException */ -extern jclass njJSUtil; /* netscape.javascript.JSUtil */ - -extern jmethodID jlClass_getMethods; /* java.lang.Class.getMethods() */ -extern jmethodID jlClass_getConstructors; /* java.lang.Class.getConstructors() */ -extern jmethodID jlClass_getFields; /* java.lang.Class.getFields() */ -extern jmethodID jlClass_getName; /* java.lang.Class.getName() */ -extern jmethodID jlClass_getComponentType; /* java.lang.Class.getComponentType() */ -extern jmethodID jlClass_getModifiers; /* java.lang.Class.getModifiers() */ -extern jmethodID jlClass_isArray; /* java.lang.Class.isArray() */ - -extern jmethodID jlrMethod_getName; /* java.lang.reflect.Method.getName() */ -extern jmethodID jlrMethod_getParameterTypes; /* java.lang.reflect.Method.getParameterTypes() */ -extern jmethodID jlrMethod_getReturnType; /* java.lang.reflect.Method.getReturnType() */ -extern jmethodID jlrMethod_getModifiers; /* java.lang.reflect.Method.getModifiers() */ - -extern jmethodID jlrConstructor_getParameterTypes; /* java.lang.reflect.Constructor.getParameterTypes() */ -extern jmethodID jlrConstructor_getModifiers; /* java.lang.reflect.Constructor.getModifiers() */ - -extern jmethodID jlrField_getName; /* java.lang.reflect.Field.getName() */ -extern jmethodID jlrField_getType; /* java.lang.reflect.Field.getType() */ -extern jmethodID jlrField_getModifiers; /* java.lang.reflect.Field.getModifiers() */ - -extern jmethodID jlrArray_newInstance; /* java.lang.reflect.Array.newInstance() */ - -extern jmethodID jlThrowable_getMessage; /* java.lang.Throwable.getMessage() */ -extern jmethodID jlThrowable_toString; /* java.lang.Throwable.toString() */ - -extern jmethodID jlBoolean_Boolean; /* java.lang.Boolean constructor */ -extern jmethodID jlBoolean_booleanValue; /* java.lang.Boolean.booleanValue() */ -extern jmethodID jlDouble_Double; /* java.lang.Double constructor */ -extern jmethodID jlDouble_doubleValue; /* java.lang.Double.doubleValue() */ - -extern jmethodID jlSystem_identityHashCode; /* java.lang.System.identityHashCode() */ - -extern jobject jlVoid_TYPE; /* java.lang.Void.TYPE value */ - -extern jmethodID njJSException_JSException; /* netscape.javascipt.JSException constructor */ -extern jmethodID njJSException_JSException_wrap;/*netscape.javascipt.JSException alternate constructor */ -extern jmethodID njJSObject_JSObject; /* netscape.javascript.JSObject constructor */ -extern jmethodID njJSUtil_getStackTrace; /* netscape.javascript.JSUtil.getStackTrace() */ -extern jfieldID njJSObject_internal; /* netscape.javascript.JSObject.internal */ -extern jfieldID njJSObject_long_internal; /* netscape.javascript.JSObject.long_internal */ -extern jfieldID njJSException_lineno; /* netscape.javascript.JSException.lineno */ -extern jfieldID njJSException_tokenIndex; /* netscape.javascript.JSException.tokenIndex */ -extern jfieldID njJSException_source; /* netscape.javascript.JSException.source */ -extern jfieldID njJSException_filename; /* netscape.javascript.JSException.filename */ -extern jfieldID njJSException_wrappedExceptionType; /* netscape.javascript.JSException.wrappedExceptionType */ -extern jfieldID njJSException_wrappedException; /* netscape.javascript.JSException.wrappedException */ - -/* - * XXX, bug 146458, - * whether we are doing a liveconnect call from javascript to java applet - */ -extern JSBool jsj_JSIsCallingApplet; - -/**************** Java <==> JS conversions and Java types *******************/ -extern JSBool -jsj_ComputeJavaClassSignature(JSContext *cx, - JavaSignature *signature, - jclass java_class); - -extern const char * -jsj_ConvertJavaSignatureToString(JSContext *cx, JavaSignature *signature); -extern const char * -jsj_ConvertJavaSignatureToHRString(JSContext *cx, - JavaSignature *signature); -extern JavaMethodSignature * -jsj_InitJavaMethodSignature(JSContext *cx, JNIEnv *jEnv, jobject method, - JavaMethodSignature *method_signature); - -extern const char * -jsj_ConvertJavaMethodSignatureToString(JSContext *cx, - JavaMethodSignature *method_signature); -extern const char * -jsj_ConvertJavaMethodSignatureToHRString(JSContext *cx, - const char *method_name, - JavaMethodSignature *method_signature); -extern void -jsj_PurgeJavaMethodSignature(JSContext *cx, JNIEnv *jEnv, JavaMethodSignature *signature); - -extern JSBool -jsj_ConvertJSValueToJavaValue(JSContext *cx, JNIEnv *jEnv, jsval v, JavaSignature *signature, - int *cost, jvalue *java_value, JSBool *is_local_refp); -extern JSBool -jsj_ConvertJSValueToJavaObject(JSContext *cx, JNIEnv *jEnv, jsval v, JavaSignature *signature, - int *cost, jobject *java_value, JSBool *is_local_refp); -extern jstring -jsj_ConvertJSStringToJavaString(JSContext *cx, JNIEnv *jEnv, JSString *js_str); - -extern JSBool -jsj_ConvertJavaValueToJSValue(JSContext *cx, JNIEnv *jEnv, JavaSignature *signature, - jvalue *java_value, jsval *vp); -extern JSBool -jsj_ConvertJavaObjectToJSValue(JSContext *cx, JNIEnv *jEnv, - jobject java_obj, jsval *vp); - -extern JSString * -jsj_ConvertJavaStringToJSString(JSContext *cx, JNIEnv *jEnv, jstring java_str); - -extern JSBool -jsj_ConvertJavaObjectToJSString(JSContext *cx, JNIEnv *jEnv, - JavaClassDescriptor *class_descriptor, - jobject java_obj, jsval *vp); -extern JSBool -jsj_ConvertJavaObjectToJSNumber(JSContext *cx, JNIEnv *jEnv, - JavaClassDescriptor *class_descriptor, - jobject java_obj, jsval *vp); -extern JSBool -jsj_ConvertJavaObjectToJSBoolean(JSContext *cx, JNIEnv *jEnv, - JavaClassDescriptor *class_descriptor, - jobject java_obj, jsval *vp); -extern JSJavaThreadState * -jsj_enter_js(JNIEnv *jEnv, void* java_applet_obj, jobject java_wrapper_obj, - JSContext **cxp, JSObject **js_objp, JSErrorReporter *old_error_reporterp, - void **pNSIPrincipaArray, int numPrincipals, void *pNSISecurityContext); - -extern JSBool -jsj_exit_js(JSContext *cx, JSJavaThreadState *jsj_env, JSErrorReporter old_error_reporterp); - -extern JavaClassDescriptor * -jsj_get_jlObject_descriptor(JSContext *cx, JNIEnv *jEnv); - -extern JSBool -jsj_remove_js_obj_reflection_from_hashtable(JSContext *cx, JSObject *js_obj); - -extern JSBool -jsj_init_js_obj_reflections_table(void); - -/************************ Java package reflection **************************/ -extern JSBool -jsj_init_JavaPackage(JSContext *, JSObject *, - JavaPackageDef *predefined_packages); - -/************************* Java class reflection ***************************/ -extern JSBool -jsj_init_JavaClass(JSContext *cx, JSObject *global_obj); - -extern void -jsj_DiscardJavaClassReflections(JNIEnv *jEnv); - -extern const char * -jsj_GetJavaClassName(JSContext *cx, JNIEnv *jEnv, jclass java_class); - -extern JavaClassDescriptor * -jsj_GetJavaClassDescriptor(JSContext *cx, JNIEnv *jEnv, jclass java_class); - -extern void -jsj_ReleaseJavaClassDescriptor(JSContext *cx, JNIEnv *jEnv, JavaClassDescriptor *class_descriptor); - -extern JSObject * -jsj_define_JavaClass(JSContext *cx, JNIEnv *jEnv, JSObject *obj, - const char *unqualified_class_name, - jclass jclazz); - -extern JavaMemberDescriptor * -jsj_GetJavaMemberDescriptor(JSContext *cx, - JNIEnv *jEnv, - JavaClassDescriptor *class_descriptor, - jstring member_name); - -extern JavaMemberDescriptor * -jsj_LookupJavaMemberDescriptorById(JSContext *cx, JNIEnv *jEnv, - JavaClassDescriptor *class_descriptor, - jsid id); - -extern JavaMemberDescriptor * -jsj_LookupJavaStaticMemberDescriptorById(JSContext *cx, JNIEnv *jEnv, - JavaClassDescriptor *class_descriptor, - jsid id); - -extern JavaMemberDescriptor * -jsj_GetJavaStaticMemberDescriptor(JSContext *cx, JNIEnv *jEnv, - JavaClassDescriptor *class_descriptor, - jstring member_name); - -extern JavaMemberDescriptor * -jsj_GetJavaClassConstructors(JSContext *cx, - JavaClassDescriptor *class_descriptor); - -extern JavaMemberDescriptor * -jsj_LookupJavaClassConstructors(JSContext *cx, JNIEnv *jEnv, - JavaClassDescriptor *class_descriptor); - -extern JavaMemberDescriptor * -jsj_GetClassInstanceMembers(JSContext *cx, JNIEnv *jEnv, - JavaClassDescriptor *class_descriptor); - -extern JavaMemberDescriptor * -jsj_GetClassStaticMembers(JSContext *cx, JNIEnv *jEnv, - JavaClassDescriptor *class_descriptor); - -extern JSBool -jsj_InitJavaClassReflectionsTable(void); - -/************************* Java field reflection ***************************/ - -extern JSBool -jsj_GetJavaFieldValue(JSContext *cx, JNIEnv *jEnv, JavaFieldSpec *field_spec, - jobject java_obj, jsval *vp); -extern JSBool -jsj_SetJavaFieldValue(JSContext *cx, JNIEnv *jEnv, JavaFieldSpec *field_spec, - jobject java_obj, jsval js_val); -extern JSBool -jsj_ReflectJavaFields(JSContext *cx, JNIEnv *jEnv, - JavaClassDescriptor *class_descriptor, - JSBool reflect_only_static_fields); -extern void -jsj_DestroyFieldSpec(JSContext *cx, JNIEnv *jEnv, JavaFieldSpec *field); - -/************************* Java method reflection ***************************/ -JS_EXTERN_API(JSBool) -jsj_JavaInstanceMethodWrapper(JSContext *cx, JSObject *obj, - uintN argc, jsval *argv, jsval *vp); -JS_EXTERN_API(JSBool) -jsj_JavaStaticMethodWrapper(JSContext *cx, JSObject *obj, - uintN argc, jsval *argv, jsval *vp); -JS_EXTERN_API(JSBool) -jsj_JavaConstructorWrapper(JSContext *cx, JSObject *obj, - uintN argc, jsval *argv, jsval *vp); -extern JSBool -jsj_ReflectJavaMethods(JSContext *cx, JNIEnv *jEnv, - JavaClassDescriptor *class_descriptor, - JSBool reflect_only_static_methods); - -extern JavaMemberDescriptor * -jsj_ResolveExplicitMethod(JSContext *cx, JNIEnv *jEnv, - JavaClassDescriptor *class_descriptor, - jsid method_name_id, - JSBool is_static); -extern void -jsj_DestroyMethodSpec(JSContext *cx, JNIEnv *jEnv, JavaMethodSpec *method_spec); - -/************************* Java member reflection ***************************/ -extern JSBool -jsj_init_JavaMember(JSContext *, JSObject *); - -extern JSBool -jsj_ReflectJavaMethodsAndFields(JSContext *cx, JavaClassDescriptor *class_descriptor, - JSBool reflect_only_statics); - -extern JSObject * -jsj_CreateJavaMember(JSContext *cx, jsval method_val, jsval field_val); - -/************************* Java object reflection **************************/ -extern JSBool -jsj_init_JavaObject(JSContext *, JSObject *); - -extern JSBool -jsj_InitJavaObjReflectionsTable(void); - -extern JSObject * -jsj_WrapJavaObject(JSContext *cx, JNIEnv *jEnv, jobject java_obj, jclass java_class); - -extern void -jsj_DiscardJavaObjReflections(JNIEnv *jEnv); - -extern JSBool JS_DLL_CALLBACK -JavaObject_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp); - -JS_EXTERN_API(void) -JavaObject_finalize(JSContext *cx, JSObject *obj); - -extern JSBool -JavaObject_resolve(JSContext *cx, JSObject *obj, jsval id); - -extern JSBool -JavaObject_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp); - -JS_EXTERN_API(JSBool) -JavaObject_getPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp); - -/************************* Java array reflection ***************************/ -extern JSBool -jsj_init_JavaArray(JSContext *cx, JSObject *global_obj); - -extern JSBool -jsj_GetJavaArrayElement(JSContext *cx, JNIEnv *jEnv, jarray java_array, - jsize index, JavaSignature *array_component_signature, - jsval *vp); - -extern JSBool -jsj_SetJavaArrayElement(JSContext *cx, JNIEnv *jEnv, jarray java_array, - jsize index, JavaSignature *array_component_signature, - jsval js_val); - -/********************* JavaScript object reflection ************************/ -extern jobject -jsj_WrapJSObject(JSContext *cx, JNIEnv *jEnv, JSObject *js_obj); - -extern JSObject * -jsj_UnwrapJSObjectWrapper(JNIEnv *jEnv, jobject java_wrapper_obj); - -extern void -jsj_ClearPendingJSErrors(JSJavaThreadState *jsj_env); - -extern JSBool -jsj_ReportUncaughtJSException(JSContext *cx, JNIEnv *jEnv, jthrowable java_exception); - -/**************************** Utilities ************************************/ -extern void -jsj_ReportJavaError(JSContext *cx, JNIEnv *env, const char *format, ...); - -extern void -jsj_UnexpectedJavaError(JSContext *cx, JNIEnv *env, const char *format, ...); - -extern const char * -jsj_GetJavaErrorMessage(JNIEnv *env); - -extern void -jsj_LogError(const char *error_msg); - -extern const JSErrorFormatString * JS_DLL_CALLBACK -jsj_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber); - -JSJHashNumber JS_DLL_CALLBACK -jsj_HashJavaObject(const void *key, void* env); - -intN JS_DLL_CALLBACK -jsj_JavaObjectComparator(const void *v1, const void *v2, void *arg); - -extern JSJavaThreadState * -jsj_MapJavaThreadToJSJavaThreadState(JNIEnv *jEnv, char **errp); - -extern void -jsj_MakeJNIClassname(char *jClassName); - -extern const char * -jsj_ClassNameOfJavaObject(JSContext *cx, JNIEnv *jEnv, jobject java_object); - -extern jsize -jsj_GetJavaArrayLength(JSContext *cx, JNIEnv *jEnv, jarray java_array); - -extern JSBool -JavaStringToId(JSContext *cx, JNIEnv *jEnv, jstring jstr, jsid *idp); - -extern const char * -jsj_DupJavaStringUTF(JSContext *cx, JNIEnv *jEnv, jstring jstr); - -extern JSJavaThreadState * -jsj_EnterJava(JSContext *cx, JNIEnv **envp); - -extern void -jsj_ExitJava(JSJavaThreadState *jsj_env); - -extern JSObjectMap * JS_DLL_CALLBACK -jsj_wrapper_newObjectMap(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops, - JSClass *clasp, JSObject *obj); - -extern void JS_DLL_CALLBACK -jsj_wrapper_destroyObjectMap(JSContext *cx, JSObjectMap *map); - -extern jsval JS_DLL_CALLBACK -jsj_wrapper_getRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot); - -extern JSBool JS_DLL_CALLBACK -jsj_wrapper_setRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot, jsval v); - -#ifdef DEBUG -#define DEBUG_LOG(args) printf args -#endif - -#define JS_FREE_IF(cx, x) \ - JS_BEGIN_MACRO \ - if (x) \ - JS_free(cx, x); \ - JS_END_MACRO - - -enum JSJErrNum { -#define MSG_DEF(name, number, format, count) \ - name = number, -#include "jsj.msg" -#undef MSG_DEF - JSJ_Err_Limit -#undef MSGDEF -}; - -#ifdef __cplusplus -} -/* end extern "C" */ -#endif - -#endif /* _JSJAVA_PVT_H */ diff --git a/lib/javascript/liveconnect/jsj_simpleapi.c b/lib/javascript/liveconnect/jsj_simpleapi.c deleted file mode 100644 index d735ce95..00000000 --- a/lib/javascript/liveconnect/jsj_simpleapi.c +++ /dev/null @@ -1,219 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* The convenience functions below present a complete, but simplified - LiveConnect API which is designed to handle the special case of a single - Java-VM, single-threaded operation, and use of only one JSContext. */ - -#include "jsjava.h" -#include "jsprf.h" -#include "jsutil.h" - -#include - -/* We can get away with global variables in our single-threaded, - single-JSContext case. */ -static JSJavaVM * the_jsj_vm = NULL; -static JSContext * the_cx = NULL; -static JSJavaThreadState * the_jsj_thread = NULL; -static JSObject * the_global_js_obj = NULL; - -/* Trivial implementation of callback function */ -static JSJavaThreadState * -default_map_js_context_to_jsj_thread(JSContext *cx, char **errp) -{ - return the_jsj_thread; -} - -/* Trivial implementation of callback function */ -static JSContext * -default_map_jsj_thread_to_js_context(JSJavaThreadState *jsj_env, -#ifdef OJI - void *java_applet_obj, -#endif - JNIEnv *jEnv, - char **errp) -{ - return the_cx; -} - -/* Trivial implementation of callback function */ -static JSObject * -default_map_java_object_to_js_object(JNIEnv *jEnv, void *hint, char **errp) -{ - return the_global_js_obj; -} - -static JSBool JS_DLL_CALLBACK -default_create_java_vm(SystemJavaVM* *jvm, JNIEnv* *initialEnv, void* initargs) -{ - jint err; - const char* user_classpath = (const char*)initargs; - char* full_classpath = NULL; - - /* No Java VM supplied, so create our own */ - JDK1_1InitArgs vm_args; - memset(&vm_args, 0, sizeof(vm_args)); - - /* Magic constant indicates JRE version 1.1 */ - vm_args.version = 0x00010001; - JNI_GetDefaultJavaVMInitArgs(&vm_args); - - /* Prepend the classpath argument to the default JVM classpath */ - if (user_classpath) { -#if defined(XP_UNIX) || defined(XP_BEOS) - full_classpath = JS_smprintf("%s:%s", user_classpath, vm_args.classpath); -#else - full_classpath = JS_smprintf("%s;%s", user_classpath, vm_args.classpath); -#endif - if (!full_classpath) { - return JS_FALSE; - } - vm_args.classpath = (char*)full_classpath; - } - - err = JNI_CreateJavaVM((JavaVM**)jvm, initialEnv, &vm_args); - - if (full_classpath) - JS_smprintf_free(full_classpath); - - return err == 0; -} - -static JSBool JS_DLL_CALLBACK -default_destroy_java_vm(SystemJavaVM* jvm, JNIEnv* initialEnv) -{ - JavaVM* java_vm = (JavaVM*)jvm; - jint err = (*java_vm)->DestroyJavaVM(java_vm); - return err == 0; -} - -static JNIEnv* JS_DLL_CALLBACK -default_attach_current_thread(SystemJavaVM* jvm) -{ - JavaVM* java_vm = (JavaVM*)jvm; - JNIEnv* env = NULL; - (*java_vm)->AttachCurrentThread(java_vm, &env, NULL); - return env; -} - -static JSBool JS_DLL_CALLBACK -default_detach_current_thread(SystemJavaVM* jvm, JNIEnv* env) -{ - JavaVM* java_vm = (JavaVM*)jvm; - /* assert that env is the JNIEnv of the current thread */ - jint err = (*java_vm)->DetachCurrentThread(java_vm); - return err == 0; -} - -static SystemJavaVM* JS_DLL_CALLBACK -default_get_java_vm(JNIEnv* env) -{ - JavaVM* java_vm = NULL; - (*env)->GetJavaVM(env, &java_vm); - return (SystemJavaVM*)java_vm; -} - -/* Trivial implementations of callback functions */ -JSJCallbacks jsj_default_callbacks = { - default_map_jsj_thread_to_js_context, - default_map_js_context_to_jsj_thread, - default_map_java_object_to_js_object, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - default_create_java_vm, - default_destroy_java_vm, - default_attach_current_thread, - default_detach_current_thread, - default_get_java_vm -}; - -/* - * Initialize the provided JSContext by setting up the JS classes necessary for - * reflection and by defining JavaPackage objects for the default Java packages - * as properties of global_obj. If java_vm is NULL, a new Java VM is - * created, using the provided classpath in addition to any default classpath. - * The classpath argument is ignored, however, if java_vm is non-NULL. - */ -JSBool -JSJ_SimpleInit(JSContext *cx, JSObject *global_obj, SystemJavaVM *java_vm, const char *classpath) -{ - JNIEnv *jEnv; - - JSJ_Init(&jsj_default_callbacks); - - JS_ASSERT(!the_jsj_vm); - the_jsj_vm = JSJ_ConnectToJavaVM(java_vm, (void*)classpath); - if (!the_jsj_vm) - return JS_FALSE; - - if (!JSJ_InitJSContext(cx, global_obj, NULL)) - goto error; - the_cx = cx; - the_global_js_obj = global_obj; - - the_jsj_thread = JSJ_AttachCurrentThreadToJava(the_jsj_vm, "main thread", &jEnv); - if (!the_jsj_thread) - goto error; - JSJ_SetDefaultJSContextForJavaThread(cx, the_jsj_thread); - return JS_TRUE; - -error: - JSJ_SimpleShutdown(); - return JS_FALSE; -} - -/* - * Free up all LiveConnect resources. Destroy the Java VM if it was - * created by LiveConnect. - */ -JS_EXPORT_API(void) -JSJ_SimpleShutdown() -{ - JS_ASSERT(the_jsj_vm); - JSJ_DisconnectFromJavaVM(the_jsj_vm); - the_jsj_vm = NULL; - the_cx = NULL; - the_global_js_obj = NULL; - the_jsj_thread = NULL; -} diff --git a/lib/javascript/liveconnect/jsj_utils.c b/lib/javascript/liveconnect/jsj_utils.c deleted file mode 100644 index 1b09bc22..00000000 --- a/lib/javascript/liveconnect/jsj_utils.c +++ /dev/null @@ -1,513 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * This Original Code has been modified by IBM Corporation. Modifications made - * by IBM described herein are Copyright (c) International Business Machines - * Corporation, 2000. - * Modifications to Mozilla code or documentation identified per MPL Section 3.3 - * - * Date Modified by Description of modification - * 04/20/2000 IBM Corp. OS/2 VisualAge build. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * This file is part of the Java-vendor-neutral implementation of LiveConnect - * - * It contains low-level utility code. - * - */ - -#include -#include - -#include "jsj_private.h" /* LiveConnect internals */ -#include "jsjava.h" /* External LiveConnect API */ - - -/* - * This is a hash-table utility routine that computes the hash code of a Java - * object by calling java.lang.System.identityHashCode() - */ -JSJHashNumber JS_DLL_CALLBACK -jsj_HashJavaObject(const void *key, void* env) -{ - JSHashNumber hash_code; - jobject java_obj; - JNIEnv *jEnv; - - java_obj = (jobject)key; - jEnv = (JNIEnv*) env; - JS_ASSERT(!(*jEnv)->ExceptionOccurred(jEnv)); - hash_code = (*jEnv)->CallStaticIntMethod(jEnv, jlSystem, - jlSystem_identityHashCode, java_obj); - -#ifdef DEBUG - if ((*jEnv)->ExceptionOccurred(jEnv)) { - (*jEnv)->ExceptionDescribe(jEnv); - JS_ASSERT(0); - } -#endif - - return hash_code; -} - -/* - * This is a hash-table utility routine for comparing two Java objects. - * It's not possible to use the == operator to directly compare two jobject's, - * since they're opaque references and aren't guaranteed to be simple pointers - * or handles (though they may be in some JVM implementations). Instead, - * use the JNI routine for comparing the two objects. - */ -intN JS_DLL_CALLBACK -jsj_JavaObjectComparator(const void *v1, const void *v2, void *arg) -{ - jobject java_obj1, java_obj2; - JNIEnv *jEnv; - - jEnv = (JNIEnv*)arg; - java_obj1 = (jobject)v1; - java_obj2 = (jobject)v2; - - if (java_obj1 == java_obj2) - return 1; - if (jEnv) - return (*jEnv)->IsSameObject(jEnv, java_obj1, java_obj2); - return 0; -} - -/* - * Return a UTF8, null-terminated encoding of a Java string. The string must - * be free'ed by the caller. - * - * If an error occurs, returns NULL and calls the JS error reporter. - */ -const char * -jsj_DupJavaStringUTF(JSContext *cx, JNIEnv *jEnv, jstring jstr) -{ - const char *str, *retval; - - str = (*jEnv)->GetStringUTFChars(jEnv, jstr, 0); - if (!str) { - jsj_UnexpectedJavaError(cx, jEnv, "Can't get UTF8 characters from " - "Java string"); - return NULL; - } - retval = JS_strdup(cx, str); - (*jEnv)->ReleaseStringUTFChars(jEnv, jstr, str); - return retval; -} - -JSBool -JavaStringToId(JSContext *cx, JNIEnv *jEnv, jstring jstr, jsid *idp) -{ - const jschar *ucs2; - JSString *jsstr; - jsize ucs2_len; - jsval val; - - ucs2 = (*jEnv)->GetStringChars(jEnv, jstr, 0); - if (!ucs2) { - jsj_UnexpectedJavaError(cx, jEnv, "Couldn't obtain Unicode characters" - "from Java string"); - return JS_FALSE; - } - - ucs2_len = (*jEnv)->GetStringLength(jEnv, jstr); - jsstr = JS_InternUCStringN(cx, ucs2, ucs2_len); - (*jEnv)->ReleaseStringChars(jEnv, jstr, ucs2); - if (!jsstr) - return JS_FALSE; - - val = STRING_TO_JSVAL(jsstr); - JS_ValueToId(cx, STRING_TO_JSVAL(jsstr), idp); - return JS_TRUE; -} - -/* - * Return, as a C string, the error message associated with a Java exception - * that occurred as a result of a JNI call, preceded by the class name of - * the exception. As a special case, if the class of the exception is - * netscape.javascript.JSException, the exception class name is omitted. - * - * NULL is returned if no Java exception is pending. The caller is - * responsible for free'ing the returned string. On exit, the Java exception - * is *not* cleared. - */ -const char * -jsj_GetJavaErrorMessage(JNIEnv *jEnv) -{ - const char *java_error_msg; - char *error_msg = NULL; - jthrowable exception; - jstring java_exception_jstring; - - exception = (*jEnv)->ExceptionOccurred(jEnv); - if (exception && jlThrowable_toString) { - java_exception_jstring = - (*jEnv)->CallObjectMethod(jEnv, exception, jlThrowable_toString); - if (!java_exception_jstring) - goto done; - java_error_msg = (*jEnv)->GetStringUTFChars(jEnv, java_exception_jstring, NULL); - if (java_error_msg) { - error_msg = strdup((char*)java_error_msg); - (*jEnv)->ReleaseStringUTFChars(jEnv, java_exception_jstring, java_error_msg); - } - (*jEnv)->DeleteLocalRef(jEnv, java_exception_jstring); - -#ifdef DEBUG - /* (*jEnv)->ExceptionDescribe(jEnv); */ -#endif - } -done: - if (exception) - (*jEnv)->DeleteLocalRef(jEnv, exception); - return error_msg; -} - -/* - * Return, as a C string, the JVM stack trace associated with a Java - * exception, as would be printed by java.lang.Throwable.printStackTrace(). - * The caller is responsible for free'ing the returned string. - * - * Returns NULL if an error occurs. - */ -static const char * -get_java_stack_trace(JSContext *cx, JNIEnv *jEnv, jthrowable java_exception) -{ - const char *backtrace; - jstring backtrace_jstr; - - backtrace = NULL; - if (java_exception && njJSUtil_getStackTrace) { - backtrace_jstr = (*jEnv)->CallStaticObjectMethod(jEnv, njJSUtil, - njJSUtil_getStackTrace, - java_exception); - if (!backtrace_jstr) { - jsj_UnexpectedJavaError(cx, jEnv, "Unable to get exception stack trace"); - return NULL; - } - backtrace = jsj_DupJavaStringUTF(cx, jEnv, backtrace_jstr); - (*jEnv)->DeleteLocalRef(jEnv, backtrace_jstr); - } - return backtrace; -} - -/* Full Java backtrace when Java exceptions reported to JavaScript */ -#define REPORT_JAVA_EXCEPTION_STACK_TRACE - -/* - * This is a wrapper around JS_ReportError(), useful when an error condition - * is the result of a JVM failure or exception condition. It appends the - * message associated with the pending Java exception to the passed in - * printf-style format string and arguments. - */ -static void -vreport_java_error(JSContext *cx, JNIEnv *jEnv, const char *format, va_list ap) -{ - jobject java_obj; - jclass java_class; - JavaClassDescriptor *class_descriptor; - jthrowable java_exception; - JSType wrapped_exception_type; - jsval js_exception; - - java_obj = NULL; - class_descriptor = NULL; - - /* Get the exception out of the java environment. */ - java_exception = (*jEnv)->ExceptionOccurred(jEnv); - if (!java_exception) { - JSString *err_jsstr; - char *err = JS_vsmprintf(format, ap); - if (!err) - return; - err_jsstr = JS_NewString(cx, err, strlen(err)); - if (!err_jsstr) - return; - JS_SetPendingException(cx, STRING_TO_JSVAL(err_jsstr)); - return; - } - - - (*jEnv)->ExceptionClear(jEnv); - - /* Check for JSException */ - if (njJSException && - (*jEnv)->IsInstanceOf(jEnv, java_exception, njJSException)) { - - wrapped_exception_type = - (*jEnv)->GetIntField(jEnv, java_exception, - njJSException_wrappedExceptionType); - - /* (int) to suppress warning */ - if ((int)wrapped_exception_type != JSTYPE_EMPTY) { - java_obj = - (*jEnv)->GetObjectField(jEnv, java_exception, - njJSException_wrappedException); - - if ((java_obj == NULL) && - (wrapped_exception_type == JSTYPE_OBJECT)) { - js_exception = JSVAL_NULL; - } else { - java_class = (*jEnv)->GetObjectClass(jEnv, java_obj); - class_descriptor = jsj_GetJavaClassDescriptor(cx, jEnv, java_class); - /* OK to delete ref, since above call adds global ref */ - (*jEnv)->DeleteLocalRef(jEnv, java_class); - - /* Convert native JS values back to native types. */ - switch(wrapped_exception_type) { - case JSTYPE_NUMBER: - if (!jsj_ConvertJavaObjectToJSNumber(cx, jEnv, - class_descriptor, - java_obj, - &js_exception)) - goto error; - break; - case JSTYPE_BOOLEAN: - if (!jsj_ConvertJavaObjectToJSBoolean(cx, jEnv, - class_descriptor, - java_obj, - &js_exception)) - goto error; - break; - case JSTYPE_STRING: - if (!jsj_ConvertJavaObjectToJSString(cx, jEnv, - class_descriptor, - java_obj, - &js_exception)) - goto error; - break; - case JSTYPE_VOID: - js_exception = JSVAL_VOID; - break; - case JSTYPE_OBJECT: - case JSTYPE_FUNCTION: - default: - if ((*jEnv)->IsInstanceOf(jEnv, java_obj, njJSObject)) { - js_exception = OBJECT_TO_JSVAL(jsj_UnwrapJSObjectWrapper(jEnv, java_obj)); - if (!js_exception) - goto error; - } else { - if (!jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_obj, - &js_exception)) - goto error; - } - } - } - } - /* Check for internal exception */ - } else { - if (!JSJ_ConvertJavaObjectToJSValue(cx, java_exception, - &js_exception)) { - goto error; - } - } - - /* Set pending JS exception and clear the java exception. */ - JS_SetPendingException(cx, js_exception); - goto done; - -error: - - JS_ASSERT(0); - jsj_LogError("Out of memory while attempting to throw JSException\n"); - -done: - if (class_descriptor) - jsj_ReleaseJavaClassDescriptor(cx, jEnv, class_descriptor); - if (java_obj) - (*jEnv)->DeleteLocalRef(jEnv, java_obj); - if (java_exception) - (*jEnv)->DeleteLocalRef(jEnv, java_exception); -} - -void -jsj_ReportJavaError(JSContext *cx, JNIEnv *env, const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - vreport_java_error(cx, env, format, ap); - va_end(ap); -} - -/* - * Same as jsj_ReportJavaError, except "internal error: " is prepended - * to message. - */ -void -jsj_UnexpectedJavaError(JSContext *cx, JNIEnv *env, const char *format, ...) -{ - va_list ap; - const char *format2; - - va_start(ap, format); - format2 = JS_smprintf("internal error: %s", format); - if (format2) { - vreport_java_error(cx, env, format2, ap); - free((void*)format2); - } - va_end(ap); -} - -/* - * Most LiveConnect errors are signaled by calling JS_ReportError(), - * but in some circumstances, the target JSContext for such errors - * is not determinable, e.g. during initialization. In such cases - * any error messages are routed to this function. - */ -void -jsj_LogError(const char *error_msg) -{ - if (JSJ_callbacks && JSJ_callbacks->error_print) - JSJ_callbacks->error_print(error_msg); - else - fputs(error_msg, stderr); -} - -/* - Error number handling. - - jsj_ErrorFormatString is an array of format strings mapped - by error number. It is initialized by the contents of jsj.msg - - jsj_GetErrorMessage is invoked by the engine whenever it wants - to convert an error number into an error format string. -*/ -/* - this define needs to go somewhere sensible -*/ -#define JSJ_HAS_DFLT_MSG_STRINGS 1 - -JSErrorFormatString jsj_ErrorFormatString[JSJ_Err_Limit] = { -#if JSJ_HAS_DFLT_MSG_STRINGS -#define MSG_DEF(name, number, count, format) \ - { format, count } , -#else -#define MSG_DEF(name, number, count, format) \ - { NULL, count } , -#endif -#include "jsj.msg" -#undef MSG_DEF -}; - -const JSErrorFormatString * -jsj_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber) -{ - if ((errorNumber > 0) && (errorNumber < JSJ_Err_Limit)) - return &jsj_ErrorFormatString[errorNumber]; - else - return NULL; -} - -jsize -jsj_GetJavaArrayLength(JSContext *cx, JNIEnv *jEnv, jarray java_array) -{ - jsize array_length = (*jEnv)->GetArrayLength(jEnv, java_array); - jthrowable java_exception = (*jEnv)->ExceptionOccurred(jEnv); - if (java_exception) { - jsj_UnexpectedJavaError(cx, jEnv, "Couldn't obtain array length"); - (*jEnv)->DeleteLocalRef(jEnv, java_exception); - return -1; - } - return array_length; -} - -static JSJavaThreadState *the_java_jsj_env = NULL; - -JSJavaThreadState * -jsj_EnterJava(JSContext *cx, JNIEnv **envp) -{ - JSJavaThreadState *jsj_env; - char *err_msg; - - *envp = NULL; - err_msg = NULL; - - jsj_env = the_java_jsj_env; - if (jsj_env == NULL && JSJ_callbacks && JSJ_callbacks->map_js_context_to_jsj_thread) - jsj_env = JSJ_callbacks->map_js_context_to_jsj_thread(cx, &err_msg); - if (!jsj_env) { - if (err_msg) { - JS_ReportError(cx, err_msg); - free(err_msg); - } - return NULL; - } - - /* simultaneous calls from different JSContext are not allowed */ - if ((jsj_env->recursion_depth > 0) && (jsj_env->cx != cx)) - return NULL; - - jsj_env->recursion_depth++; - - /* bug #60018: prevent dangling pointer to JSContext */ - if (!jsj_env->cx) - jsj_env->cx = cx; - - if (envp) - *envp = jsj_env->jEnv; - return jsj_env; -} - -extern void -jsj_ExitJava(JSJavaThreadState *jsj_env) -{ - jsj_JSIsCallingApplet = JS_FALSE; - if (jsj_env) { - JS_ASSERT(jsj_env->recursion_depth > 0); - if (--jsj_env->recursion_depth == 0) - jsj_env->cx = NULL; - } -} - -/** - * Since only one Java thread is allowed to enter JavaScript, this function is - * used to enforce the use of that thread's state. The static global the_java_jsj_env - * overrides using JSJ_callbacks->map_js_context_to_jsj_thread, which maps - * native threads to JSJavaThreadStates. This isn't appropriate when Java calls - * JavaScript, as there can be a many to one mapping from Java threads to native - * threads. - */ -JSJavaThreadState * -jsj_SetJavaJSJEnv(JSJavaThreadState* java_jsj_env) -{ - JSJavaThreadState *old_jsj_env = the_java_jsj_env; - the_java_jsj_env = java_jsj_env; - return old_jsj_env; -} diff --git a/lib/javascript/liveconnect/jsjava.h b/lib/javascript/liveconnect/jsjava.h deleted file mode 100644 index b578781e..00000000 --- a/lib/javascript/liveconnect/jsjava.h +++ /dev/null @@ -1,313 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * This file is part of the Java-vendor-neutral implementation of LiveConnect - * - * Publicly exported functions for JavaScript <==> Java communication. - * - */ - -#ifndef _JSJAVA_H -#define _JSJAVA_H - -#ifndef jstypes_h___ -#include "jstypes.h" -#endif - -JS_BEGIN_EXTERN_C - -#include "jni.h" /* Java Native Interface */ -#include "jsapi.h" /* JavaScript engine API */ - -#if JS_BYTES_PER_LONG == 8 -typedef jlong lcjsobject; -#else -typedef jint lcjsobject; -#endif - -/* - * A JSJavaVM structure is a wrapper around a JavaVM which incorporates - * additional LiveConnect state. - */ -typedef struct JSJavaVM JSJavaVM; - -/* LiveConnect and Java state, one per thread */ -typedef struct JSJavaThreadState JSJavaThreadState; - -/* - * An opaque type that represents the connection to the Java VM. In stand-alone - * Java environments, this may be a JNI JavaVM object; in the browser environment - * it is a reference to a JVM plugin. A set of callbacks in the JSJCallbacks - * struct allow it to be manipulated. - */ -#ifdef OJI -typedef struct SystemJavaVM SystemJavaVM; -#else -typedef JavaVM SystemJavaVM; -#endif - -/* - * This callback table provides hooks to external functions that implement - * functionality specific to the embedding. For example, these callbacks are - * necessary in multi-threaded environments or to implement a security - * policy. - */ -typedef struct JSJCallbacks { - - /* This callback is invoked when there is no JavaScript execution - environment (JSContext) associated with the current Java thread and - a call is made from Java into JavaScript. (A JSContext is associated - with a Java thread by calling the JSJ_SetDefaultJSContextForJavaThread() - function.) This callback is only invoked when Java spontaneously calls - into JavaScript, i.e. it is not called when JS calls into Java which - calls back into JS. - - This callback can be used to create a JSContext lazily, or obtain - one from a pool of available JSContexts. The implementation of this - callback can call JSJ_SetDefaultJSContextForJavaThread() to avoid any - further callbacks of this type for this Java thread. */ - JSContext * (*map_jsj_thread_to_js_context)(JSJavaThreadState *jsj_env, -#ifdef OJI - void *java_applet_obj, -#endif - JNIEnv *jEnv, - char **errp); - - /* This callback is invoked whenever a call is made into Java from - JavaScript. It's responsible for mapping from a JavaScript execution - environment (JSContext) to a Java thread. (A JavaContext can only - be associated with one Java thread at a time.) */ - JSJavaThreadState * (*map_js_context_to_jsj_thread)(JSContext *cx, - char **errp); - - /* This callback implements netscape.javascript.JSObject.getWindow(), - a method named for its behavior in the browser environment, where it - returns the JS "Window" object corresponding to the HTML window that an - applet is embedded within. More generally, it's a way for Java to get - hold of a JS object that has not been explicitly passed to it. */ - JSObject * (*map_java_object_to_js_object)(JNIEnv *jEnv, void *pJavaObject, - char **errp); - - /* An interim callback function until the LiveConnect security story is - straightened out. This function pointer can be set to NULL. */ - JSPrincipals * (*get_JSPrincipals_from_java_caller)(JNIEnv *jEnv, JSContext *pJSContext, void **pNSIPrincipaArray, int numPrincipals, void *pNSISecurityContext); - - /* The following two callbacks sandwich any JS evaluation performed - from Java. They may be used to implement concurrency constraints, e.g. - by suspending the current thread until some condition is met. In the - browser embedding, these are used to maintain the run-to-completion - semantics of JavaScript. It is acceptable for either function pointer - to be NULL. */ -#ifdef OJI - JSBool (*enter_js_from_java)(JNIEnv *jEnv, char **errp, void **pNSIPrincipaArray, int numPrincipals, void *pNSISecurityContext,void* applet_obj); -#else - JSBool (*enter_js_from_java)(JNIEnv *jEnv, char **errp); -#endif - void (*exit_js)(JNIEnv *jEnv, JSContext *cx); - - /* Most LiveConnect errors are signaled by calling JS_ReportError(), but in - some circumstances, the target JSContext for such errors is not - determinable, e.g. during initialization. In such cases any error - messages are routed to this function. If the function pointer is set to - NULL, error messages are sent to stderr. */ - void (*error_print)(const char *error_msg); - - /* This enables liveconnect to ask the VM for a java wrapper so that VM gets a chance to - store a mapping between a jsobject and java wrapper. So the unwrapping can be done on the - VM side before calling nsILiveconnect apis. This saves on a round trip request. */ - jobject (*get_java_wrapper)(JNIEnv *jEnv, lcjsobject jsobj); - - /* This allows liveconnect to unwrap a wrapped JSObject that is passed from java to js. - This happens when Java code is passing back to JS an object that it got from JS. */ - lcjsobject (*unwrap_java_wrapper)(JNIEnv *jEnv, jobject java_wrapper); - - /* The following set of methods abstract over the JavaVM object. */ - JSBool (*create_java_vm)(SystemJavaVM* *jvm, JNIEnv* *initialEnv, void* initargs); - JSBool (*destroy_java_vm)(SystemJavaVM* jvm, JNIEnv* initialEnv); - JNIEnv* (*attach_current_thread)(SystemJavaVM* jvm); - JSBool (*detach_current_thread)(SystemJavaVM* jvm, JNIEnv* env); - SystemJavaVM* (*get_java_vm)(JNIEnv* env); - - /* Reserved for future use */ - void * reserved[10]; -} JSJCallbacks; - -/*===========================================================================*/ - -/* A flag that denotes that a Java package has no sub-packages other than those - explicitly pre-defined at the time of initialization. An access - to a simple name within such a package, therefore, must either correspond to - one of these explicitly pre-defined sub-packages or to a class within this - package. It is reasonable for LiveConnect to signal an error if a simple - name does not comply with these criteria. */ -#define PKG_SYSTEM 1 - -/* A flag that denotes that a Java package which might contain sub-packages - that are not pre-defined at initialization time, because the sub-packages - may not be the same in all installations. Therefore, an access to a simple - name within such a a package which does not correspond to either a - pre-defined sub-package or to a class, must be assummed to refer to an - unknown sub-package. This behavior may cause bogus JavaPackage objects to be - created if a package name is misspelled, e.g. sun.oi.net. */ -#define PKG_USER 2 - -/* A Java package defined at initialization time. */ -typedef struct JavaPackageDef { - const char * name; /* e.g. "java.lang" */ - const char * path; /* e.g. "java/lang", or NULL for default */ - int flags; /* PKG_USER, PKG_SYSTEM, etc. */ - int access; /* JSPROP_READONLY or 0 */ -} JavaPackageDef; - -/*===========================================================================*/ - -/* The following two convenience functions present a complete, but simplified - LiveConnect API which is designed to handle the special case of a single - Java-VM, with single-threaded operation, and the use of only one JSContext. - The full API is in the section below. */ - -/* Initialize the provided JSContext by setting up the JS classes necessary for - reflection and by defining JavaPackage objects for the default Java packages - as properties of global_obj. If java_vm is NULL, a new Java VM is - created, using the provided classpath in addition to any default classpath. - The classpath argument is ignored, however, if java_vm is non-NULL. */ -JS_EXPORT_API(JSBool) -JSJ_SimpleInit(JSContext *cx, JSObject *global_obj, - SystemJavaVM *java_vm, const char *classpath); - -/* Free up all resources. Destroy the Java VM if it was created by LiveConnect */ -JS_EXPORT_API(void) -JSJ_SimpleShutdown(void); - -/*===========================================================================*/ - -/* The "full" LiveConnect API, required when more than one thread, Java VM, or - JSContext is involved. Initialization pseudocode might go roughly like - this: - - JSJ_Init() // Setup callbacks - for each JavaVM { - JSJ_ConnectToJavaVM(...) - } - for each JSContext { - JSJ_InitJSContext(...) - } - for each JS evaluation { - run JavaScript code in the JSContext; - } - */ - -/* Called once for all instances of LiveConnect to set up callbacks */ -JS_EXPORT_API(void) -JSJ_Init(JSJCallbacks *callbacks); - -/* Called once per Java VM, this function initializes the classes, fields, and - methods required for Java reflection. If java_vm is NULL, a new Java VM is - created according to the create_java_vm callback in the JSJCallbacks, - using the provided classpath in addition to any default initargs. - The initargs argument is ignored, however, if java_vm is non-NULL. */ -JS_EXPORT_API(JSJavaVM *) -JSJ_ConnectToJavaVM(SystemJavaVM *java_vm, void* initargs); - -/* Initialize the provided JSContext by setting up the JS classes necessary for - reflection and by defining JavaPackage objects for the default Java packages - as properties of global_obj. Additional packages may be pre-defined by - setting the predefined_packages argument. (Pre-defining a Java package at - initialization time is not necessary, but it will make package lookup faster - and, more importantly, will avoid unnecessary network accesses if classes - are being loaded over the network.) */ -JS_EXPORT_API(JSBool) -JSJ_InitJSContext(JSContext *cx, JSObject *global_obj, - JavaPackageDef *predefined_packages); - -/* This function returns a structure that encapsulates the Java and JavaScript - execution environment for the current native thread. It is intended to - be called from the embedder's implementation of JSJCallback's - map_js_context_to_jsj_thread() function. The thread_name argument is only - used for debugging purposes and can be set to NULL. The Java JNI - environment associated with this thread is returned through the java_envp - argument if java_envp is non-NULL. */ -JS_EXPORT_API(JSJavaThreadState *) -JSJ_AttachCurrentThreadToJava(JSJavaVM *jsjava_vm, const char *thread_name, - JNIEnv **java_envp); - -/* Destructor routine for per-thread JSJavaThreadState structure */ -JS_EXPORT_API(JSBool) -JSJ_DetachCurrentThreadFromJava(JSJavaThreadState *jsj_env); - -/* This function is used to specify a particular JSContext as *the* JavaScript - execution environment to be used when LiveConnect is accessed from the given - Java thread, i.e. when one of the methods of netscape.javascript.JSObject - has been called. There can only be one such JS context for any given Java - thread at a time. (To multiplex JSContexts among a single thread, this - function could be called before Java is invoked on that thread.) The return - value is the previous JSContext associated with the given Java thread. - - If this function has not been called for a thread and a crossing is made - into JavaScript from Java, the map_jsj_thread_to_js_context() callback will - be invoked to determine the JSContext for the thread. The purpose of the - function is to improve performance by avoiding the expense of the callback. -*/ -JS_EXPORT_API(JSContext *) -JSJ_SetDefaultJSContextForJavaThread(JSContext *cx, JSJavaThreadState *jsj_env); - -/* This routine severs the connection to a Java VM, freeing all related resources. - It shouldn't be called until the global scope has been cleared in all related - JSContexts (so that all LiveConnect objects are finalized) and a JavaScript - GC is performed. Otherwise, accessed to free'ed memory could result. */ -JS_EXPORT_API(void) -JSJ_DisconnectFromJavaVM(JSJavaVM *); - -/* - * Reflect a Java object into a JS value. The source object, java_obj, must - * be of type java.lang.Object or a subclass and may, therefore, be an array. - */ -JS_EXPORT_API(JSBool) -JSJ_ConvertJavaObjectToJSValue(JSContext *cx, jobject java_obj, jsval *vp); - -JS_EXPORT_API(JSBool) -JSJ_ConvertJSValueToJavaObject(JSContext *cx, jsval js_val, jobject *vp); - -JS_EXPORT_API(JSBool) -JSJ_IsJSCallApplet(); - -JS_END_EXTERN_C - -#endif /* _JSJAVA_H */ diff --git a/lib/javascript/liveconnect/liveconnect.pkg b/lib/javascript/liveconnect/liveconnect.pkg deleted file mode 100644 index fab35506..00000000 --- a/lib/javascript/liveconnect/liveconnect.pkg +++ /dev/null @@ -1,3 +0,0 @@ -# this is part of the GRE, but *not* part of the embedding packages -[gre] -dist/bin/@SHARED_LIBRARY@ diff --git a/lib/javascript/liveconnect/netscape_javascript_JSObject.h b/lib/javascript/liveconnect/netscape_javascript_JSObject.h deleted file mode 100644 index fcb321b1..00000000 --- a/lib/javascript/liveconnect/netscape_javascript_JSObject.h +++ /dev/null @@ -1,155 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * This file is part of the Java-vendor-neutral implementation of LiveConnect - * - * Declarations of private (internal) functions/data/types for - * JavaScript <==> Java communication. - * - */ - -#include -/* Header for class netscape_javascript_JSObject */ - -#ifndef _Included_netscape_javascript_JSObject -#define _Included_netscape_javascript_JSObject -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: netscape_javascript_JSObject - * Method: initClass - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_initClass - (JNIEnv *, jclass); - -/* - * Class: netscape_javascript_JSObject - * Method: getMember - * Signature: (Ljava/lang/String;)Ljava/lang/Object; - */ -JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_getMember - (JNIEnv *, jobject, jstring); - -/* - * Class: netscape_javascript_JSObject - * Method: getSlot - * Signature: (I)Ljava/lang/Object; - */ -JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_getSlot - (JNIEnv *, jobject, jint); - -/* - * Class: netscape_javascript_JSObject - * Method: setMember - * Signature: (Ljava/lang/String;Ljava/lang/Object;)V - */ -JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_setMember - (JNIEnv *, jobject, jstring, jobject); - -/* - * Class: netscape_javascript_JSObject - * Method: setSlot - * Signature: (ILjava/lang/Object;)V - */ -JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_setSlot - (JNIEnv *, jobject, jint, jobject); - -/* - * Class: netscape_javascript_JSObject - * Method: removeMember - * Signature: (Ljava/lang/String;)V - */ -JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_removeMember - (JNIEnv *, jobject, jstring); - -/* - * Class: netscape_javascript_JSObject - * Method: call - * Signature: (Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object; - */ -JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_call - (JNIEnv *, jobject, jstring, jobjectArray); - -/* - * Class: netscape_javascript_JSObject - * Method: eval - * Signature: (Ljava/lang/String;)Ljava/lang/Object; - */ -JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_eval - (JNIEnv *, jobject, jstring); - -/* - * Class: netscape_javascript_JSObject - * Method: toString - * Signature: ()Ljava/lang/String; - */ -JNIEXPORT jstring JNICALL Java_netscape_javascript_JSObject_toString - (JNIEnv *, jobject); - -/* - * Class: netscape_javascript_JSObject - * Method: getWindow - * Signature: (Ljava/applet/Applet;)Lnetscape/javascript/JSObject; - */ -JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_getWindow - (JNIEnv *, jclass, jobject); - -/* - * Class: netscape_javascript_JSObject - * Method: finalize - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_finalize - (JNIEnv *, jobject); - -/* - * Class: netscape_javascript_JSObject - * Method: equals - * Signature: (Ljava/lang/Object;)Z - */ -JNIEXPORT jboolean JNICALL Java_netscape_javascript_JSObject_equals - (JNIEnv *, jobject, jobject); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/lib/javascript/liveconnect/nsCLiveconnect.cpp b/lib/javascript/liveconnect/nsCLiveconnect.cpp deleted file mode 100644 index 7ff78467..00000000 --- a/lib/javascript/liveconnect/nsCLiveconnect.cpp +++ /dev/null @@ -1,785 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * This file is part of the Java-vendor-neutral implementation of LiveConnect - * - * It contains the implementation providing nsIFactory XP-COM interface. - * - */ - - -#include -#include -#include "prtypes.h" -#include "prprf.h" -#include "prlog.h" - -#include "jsj_private.h" -#include "jsjava.h" - -#include "jscntxt.h" /* For js_ReportErrorAgain().*/ - -#include "netscape_javascript_JSObject.h" /* javah-generated headers */ -#include "nsISecurityContext.h" -#include "nsIServiceManager.h" -#include "nsIJSContextStack.h" - -PR_BEGIN_EXTERN_C - -/* A captured JavaScript error, created when JS_ReportError() is called while - running JavaScript code that is itself called from Java. */ -struct CapturedJSError { - char * message; - JSErrorReport report; /* Line # of error, etc. */ - jthrowable java_exception; /* Java exception, error, or null */ - CapturedJSError * next; /* Next oldest captured JS error */ -}; -PR_END_EXTERN_C - -#include "nsCLiveconnect.h" - -#include "jsinterp.h" // XXX private API so we can auto-push a JSStackFrame -#include "nsIScriptSecurityManager.h" -#include "nsIPrincipal.h" -#include "nsNetUtil.h" -#include "nsISecurityContext.h" -#include "prmem.h" - -/***************************************************************************/ -// A class to put on the stack to manage JS contexts when we are entering JS. -// This pushes and pops the given context -// with the nsThreadJSContextStack service as this object goes into and out -// of scope. It is optimized to not push/pop the cx if it is already on top -// of the stack. We need to push the JSContext when we enter JS because the -// JS security manager looks on the context stack for permissions information. - -class AutoPushJSContext -{ -public: - AutoPushJSContext(nsISupports* aSecuritySupports, - JSContext *cx); - - ~AutoPushJSContext(); - - nsresult ResultOfPush() { return mPushResult; }; - -private: - nsCOMPtr mContextStack; - JSContext* mContext; - JSStackFrame mFrame; - nsresult mPushResult; -}; - -AutoPushJSContext::AutoPushJSContext(nsISupports* aSecuritySupports, - JSContext *cx) - : mContext(cx), mPushResult(NS_OK) -{ - nsCOMPtr contextStack = - do_GetService("@mozilla.org/js/xpc/ContextStack;1"); - - JSContext* currentCX; - if(contextStack && - // Don't push if the current context is already on the stack. - (NS_FAILED(contextStack->Peek(¤tCX)) || - cx != currentCX) ) - { - if (NS_SUCCEEDED(contextStack->Push(cx))) - { - // Leave the reference in mContextStack to - // indicate that we need to pop it in our dtor. - mContextStack.swap(contextStack); - } - } - - nsCOMPtr secMan( - do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &mPushResult)); - - if (NS_FAILED(mPushResult)) - return; - - nsCOMPtr principal; - mPushResult = secMan->GetPrincipalFromContext(cx, getter_AddRefs(principal)); - - if (NS_FAILED(mPushResult)) - { - JS_ReportError(cx, "failed to get a principal"); - return; - } - - // See if JavaScript is enabled for the current window - PRBool jsEnabled = PR_FALSE; - mPushResult = secMan->CanExecuteScripts(cx, principal, &jsEnabled); - if (!jsEnabled) - mPushResult = NS_ERROR_FAILURE; - - memset(&mFrame, 0, sizeof(mFrame)); - - if (NS_SUCCEEDED(mPushResult)) - { - // See if there are any scripts on the stack. - // If not, we need to add a dummy frame with a principal. - - PRBool hasScript = PR_FALSE; - JSStackFrame* tempFP = cx->fp; - while (tempFP) - { - if (tempFP->script) - { - hasScript = PR_TRUE; - break; - } - tempFP = tempFP->down; - }; - - if (!hasScript) - { - JSPrincipals* jsprinc; - principal->GetJSPrincipals(cx, &jsprinc); - - mFrame.script = JS_CompileScriptForPrincipals(cx, JS_GetGlobalObject(cx), - jsprinc, "", 0, "", 1); - JSPRINCIPALS_DROP(cx, jsprinc); - - if (mFrame.script) - { - mFrame.down = cx->fp; - cx->fp = &mFrame; - } - else - mPushResult = NS_ERROR_OUT_OF_MEMORY; - } - } -} - -AutoPushJSContext::~AutoPushJSContext() -{ - if (mContextStack) - mContextStack->Pop(nsnull); - - if (mFrame.script) - mContext->fp = mFrame.down; - -} - - -//////////////////////////////////////////////////////////////////////////// -// from nsISupports and AggregatedQueryInterface: - -// Thes macro expands to the aggregated query interface scheme. - -NS_IMPL_AGGREGATED(nsCLiveconnect) - -NS_METHOD -nsCLiveconnect::AggregatedQueryInterface(const nsIID& aIID, void** aInstancePtr) -{ - NS_ENSURE_ARG_POINTER(aInstancePtr); - - if (aIID.Equals(NS_GET_IID(nsISupports))) { - *aInstancePtr = GetInner(); - } - else if (aIID.Equals(NS_GET_IID(nsILiveconnect))) { - *aInstancePtr = NS_STATIC_CAST(nsILiveconnect*, this); - } - else { - *aInstancePtr = nsnull; - return NS_NOINTERFACE; - } - NS_ADDREF((nsISupports*) *aInstancePtr); - return NS_OK; -} - - - -//////////////////////////////////////////////////////////////////////////// -// from nsILiveconnect: - -/** - * get member of a Native JSObject for a given name. - * - * @param jEnv - JNIEnv on which the call is being made. - * @param obj - A Native JS Object. - * @param name - Name of a member. - * @param pjobj - return parameter as a java object representing - * the member. If it is a basic data type it is converted to - * a corresponding java type. If it is a NJSObject, then it is - * wrapped up as java wrapper netscape.javascript.JSObject. - */ -NS_METHOD -nsCLiveconnect::GetMember(JNIEnv *jEnv, lcjsobject obj, const jchar *name, jsize length, void* principalsArray[], - int numPrincipals, nsISupports *securitySupports, jobject *pjobj) -{ - if(jEnv == NULL || obj == 0) - { - return NS_ERROR_FAILURE; - } - - JSJavaThreadState *jsj_env = NULL; - JSObjectHandle *handle = (JSObjectHandle*)obj; - JSObject *js_obj = handle->js_obj; - JSContext *cx = NULL; - jobject member = NULL; - jsval js_val; - int dummy_cost = 0; - JSBool dummy_bool = PR_FALSE; - JSErrorReporter saved_state = NULL; - - jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports); - if (!jsj_env) - return NS_ERROR_FAILURE; - - AutoPushJSContext autopush(securitySupports, cx); - if (NS_FAILED(autopush.ResultOfPush())) - goto done; - - if (!name) { - JS_ReportError(cx, "illegal null member name"); - member = NULL; - goto done; - } - - if (!JS_GetUCProperty(cx, js_obj, name, length, &js_val)) - goto done; - - jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv), - &dummy_cost, &member, &dummy_bool); - -done: - if (!jsj_exit_js(cx, jsj_env, saved_state)) - return NS_ERROR_FAILURE; - - *pjobj = member; - - return NS_OK; -} - - -/** - * get member of a Native JSObject for a given index. - * - * @param jEnv - JNIEnv on which the call is being made. - * @param obj - A Native JS Object. - * @param index - Index of a member. - * @param pjobj - return parameter as a java object representing - * the member. - */ -NS_METHOD -nsCLiveconnect::GetSlot(JNIEnv *jEnv, lcjsobject obj, jint slot, void* principalsArray[], - int numPrincipals, nsISupports *securitySupports, jobject *pjobj) -{ - if(jEnv == NULL || obj == 0) - { - return NS_ERROR_FAILURE; - } - - JSJavaThreadState *jsj_env = NULL; - JSObjectHandle *handle = (JSObjectHandle*)obj; - JSObject *js_obj = handle->js_obj; - JSContext *cx = NULL; - jobject member = NULL; - jsval js_val; - int dummy_cost = 0; - JSBool dummy_bool = PR_FALSE; - JSErrorReporter saved_state = NULL; - - jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports); - if (!jsj_env) - return NS_ERROR_FAILURE; - - AutoPushJSContext autopush(securitySupports, cx); - if (NS_FAILED(autopush.ResultOfPush())) - goto done; - - // =-= sudu: check to see if slot can be passed in as is. - // Should it be converted to a jsint? - if (!JS_GetElement(cx, js_obj, slot, &js_val)) - goto done; - if (!jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv), - &dummy_cost, &member, &dummy_bool)) - goto done; - -done: - if (!jsj_exit_js(cx, jsj_env, saved_state)) - return NS_ERROR_FAILURE; - - *pjobj = member; - return NS_OK; -} - -/** - * set member of a Native JSObject for a given name. - * - * @param jEnv - JNIEnv on which the call is being made. - * @param obj - A Native JS Object. - * @param name - Name of a member. - * @param jobj - Value to set. If this is a basic data type, it is converted - * using standard JNI calls but if it is a wrapper to a JSObject - * then a internal mapping is consulted to convert to a NJSObject. - */ -NS_METHOD -nsCLiveconnect::SetMember(JNIEnv *jEnv, lcjsobject obj, const jchar *name, jsize length, jobject java_obj, void* principalsArray[], - int numPrincipals, nsISupports *securitySupports) -{ - if(jEnv == NULL || obj == 0) - { - return NS_ERROR_FAILURE; - } - - JSJavaThreadState *jsj_env = NULL; - JSObjectHandle *handle = (JSObjectHandle*)obj; - JSObject *js_obj = handle->js_obj; - JSContext *cx = NULL; - jsval js_val; - JSErrorReporter saved_state = NULL; - - jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports); - if (!jsj_env) - return NS_ERROR_FAILURE; - - AutoPushJSContext autopush(securitySupports, cx); - if (NS_FAILED(autopush.ResultOfPush())) - goto done; - - if (!name) { - JS_ReportError(cx, "illegal null member name"); - goto done; - } - - if (!jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_obj, &js_val)) - goto done; - - JS_SetUCProperty(cx, js_obj, name, length, &js_val); - -done: - jsj_exit_js(cx, jsj_env, saved_state); - return NS_OK; -} - - -/** - * set member of a Native JSObject for a given index. - * - * @param jEnv - JNIEnv on which the call is being made. - * @param obj - A Native JS Object. - * @param index - Index of a member. - * @param jobj - Value to set. If this is a basic data type, it is converted - * using standard JNI calls but if it is a wrapper to a JSObject - * then a internal mapping is consulted to convert to a NJSObject. - */ -NS_METHOD -nsCLiveconnect::SetSlot(JNIEnv *jEnv, lcjsobject obj, jint slot, jobject java_obj, void* principalsArray[], - int numPrincipals, nsISupports *securitySupports) -{ - if(jEnv == NULL || obj == 0) - { - return NS_ERROR_FAILURE; - } - - JSJavaThreadState *jsj_env = NULL; - JSObjectHandle *handle = (JSObjectHandle*)obj; - JSObject *js_obj = handle->js_obj; - JSContext *cx = NULL; - jsval js_val; - JSErrorReporter saved_state = NULL; - - jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports); - if (!jsj_env) - return NS_ERROR_FAILURE; - - AutoPushJSContext autopush(securitySupports, cx); - if (NS_FAILED(autopush.ResultOfPush())) - goto done; - - if (!jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_obj, &js_val)) - goto done; - JS_SetElement(cx, js_obj, slot, &js_val); - -done: - jsj_exit_js(cx, jsj_env, saved_state); - return NS_OK; -} - - -/** - * remove member of a Native JSObject for a given name. - * - * @param jEnv - JNIEnv on which the call is being made. - * @param obj - A Native JS Object. - * @param name - Name of a member. - */ -NS_METHOD -nsCLiveconnect::RemoveMember(JNIEnv *jEnv, lcjsobject obj, const jchar *name, jsize length, void* principalsArray[], - int numPrincipals, nsISupports *securitySupports) -{ - if(jEnv == NULL || obj == 0) - { - return NS_ERROR_FAILURE; - } - - JSJavaThreadState *jsj_env = NULL; - JSObjectHandle *handle = (JSObjectHandle*)obj; - JSObject *js_obj = handle->js_obj; - JSContext *cx = NULL; - jsval js_val; - JSErrorReporter saved_state = NULL; - - jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports); - if (!jsj_env) - return NS_ERROR_FAILURE; - - AutoPushJSContext autopush(securitySupports, cx); - if (NS_FAILED(autopush.ResultOfPush())) - goto done; - - if (!name) { - JS_ReportError(cx, "illegal null member name"); - goto done; - } - - JS_DeleteUCProperty2(cx, js_obj, name, length, &js_val); - -done: - jsj_exit_js(cx, jsj_env, saved_state); - return NS_OK; -} - - -/** - * call a method of Native JSObject. - * - * @param jEnv - JNIEnv on which the call is being made. - * @param obj - A Native JS Object. - * @param name - Name of a method. - * @param jobjArr - Array of jobjects representing parameters of method being caled. - * @param pjobj - return value. - */ -NS_METHOD -nsCLiveconnect::Call(JNIEnv *jEnv, lcjsobject obj, const jchar *name, jsize length, jobjectArray java_args, void* principalsArray[], - int numPrincipals, nsISupports *securitySupports, jobject *pjobj) -{ - if(jEnv == NULL || obj == 0) - { - return NS_ERROR_FAILURE; - } - - int i = 0; - int argc = 0; - int arg_num = 0; - jsval *argv = 0; - JSJavaThreadState *jsj_env = NULL; - JSObjectHandle *handle = (JSObjectHandle*)obj; - JSObject *js_obj = handle->js_obj; - JSContext *cx = NULL; - jsval js_val; - jsval function_val = 0; - int dummy_cost = 0; - JSBool dummy_bool = PR_FALSE; - JSErrorReporter saved_state = NULL; - jobject result = NULL; - - jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports); - if (!jsj_env) - return NS_ERROR_FAILURE; - - result = NULL; - AutoPushJSContext autopush(securitySupports, cx); - if (NS_FAILED(autopush.ResultOfPush())) - goto done; - - if (!name) { - JS_ReportError(cx, "illegal null JavaScript function name"); - goto done; - } - - /* Allocate space for JS arguments */ - argc = java_args ? jEnv->GetArrayLength(java_args) : 0; - if (argc) { - argv = (jsval*)JS_malloc(cx, argc * sizeof(jsval)); - if (!argv) - goto done; - } else { - argv = 0; - } - - /* Convert arguments from Java to JS values */ - for (arg_num = 0; arg_num < argc; arg_num++) { - jobject arg = jEnv->GetObjectArrayElement(java_args, arg_num); - JSBool ret = jsj_ConvertJavaObjectToJSValue(cx, jEnv, arg, &argv[arg_num]); - - jEnv->DeleteLocalRef(arg); - if (!ret) - goto cleanup_argv; - JS_AddRoot(cx, &argv[arg_num]); - } - - if (!JS_GetUCProperty(cx, js_obj, name, length, &function_val)) - goto cleanup_argv; - - if (!JS_CallFunctionValue(cx, js_obj, function_val, argc, argv, &js_val)) - goto cleanup_argv; - - jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv), - &dummy_cost, &result, &dummy_bool); - -cleanup_argv: - if (argv) { - for (i = 0; i < arg_num; i++) - JS_RemoveRoot(cx, &argv[i]); - JS_free(cx, argv); - } - -done: - if (!jsj_exit_js(cx, jsj_env, saved_state)) - return NS_ERROR_FAILURE; - - *pjobj = result; - - return NS_OK; -} - -NS_METHOD -nsCLiveconnect::Eval(JNIEnv *jEnv, lcjsobject obj, const jchar *script, jsize length, void* principalsArray[], - int numPrincipals, nsISupports *securitySupports, jobject *pjobj) -{ - if(jEnv == NULL || obj == 0) - { - return NS_ERROR_FAILURE; - } - - JSJavaThreadState *jsj_env = NULL; - JSObjectHandle *handle = (JSObjectHandle*)obj; - JSObject *js_obj = handle->js_obj; - JSContext *cx = NULL; - jsval js_val; - int dummy_cost = 0; - JSBool dummy_bool = PR_FALSE; - JSErrorReporter saved_state = NULL; - jobject result = NULL; - const char *codebase = NULL; - JSPrincipals *principals = NULL; - JSBool eval_succeeded = PR_FALSE; - - jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports); - if (!jsj_env) - return NS_ERROR_FAILURE; - - result = NULL; - AutoPushJSContext autopush(securitySupports, cx); - if (NS_FAILED(autopush.ResultOfPush())) - goto done; - - if (!script) { - JS_ReportError(cx, "illegal null string eval argument"); - goto done; - } - - /* Set up security stuff */ - if (JSJ_callbacks && JSJ_callbacks->get_JSPrincipals_from_java_caller) - principals = JSJ_callbacks->get_JSPrincipals_from_java_caller(jEnv, cx, principalsArray, numPrincipals, securitySupports); - codebase = principals ? principals->codebase : NULL; - - /* Have the JS engine evaluate the unicode string */ - eval_succeeded = JS_EvaluateUCScriptForPrincipals(cx, js_obj, principals, - script, length, - codebase, 0, &js_val); - - if (!eval_succeeded) - goto done; - - /* Convert result to a subclass of java.lang.Object */ - jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv), - &dummy_cost, &result, &dummy_bool); - -done: - if (principals) - JSPRINCIPALS_DROP(cx, principals); - if (!jsj_exit_js(cx, jsj_env, saved_state)) - return NS_ERROR_FAILURE; - - *pjobj = result; - return NS_OK; -} - - -/** - * Get the window object for a plugin instance. - * - * @param jEnv - JNIEnv on which the call is being made. - * @param pJavaObject - Either a jobject or a pointer to a plugin instance - * representing the java object. - * @param pjobj - return value. This is a native js object - * representing the window object of a frame - * in which a applet/bean resides. - */ -NS_METHOD -nsCLiveconnect::GetWindow(JNIEnv *jEnv, void *pJavaObject, void* principalsArray[], - int numPrincipals, nsISupports *securitySupports, lcjsobject *pobj) -{ - if(jEnv == NULL || JSJ_callbacks == NULL) - { - return NS_ERROR_FAILURE; - } - - // associate this Java client with this LiveConnect connection. - mJavaClient = pJavaObject; - - char *err_msg = NULL; - JSContext *cx = NULL; - JSObject *js_obj = NULL; - JSErrorReporter saved_state = NULL; - JSJavaThreadState *jsj_env = NULL; - JSObjectHandle *handle = NULL; - - jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports); - if (!jsj_env) - return NS_ERROR_FAILURE; - - err_msg = NULL; - AutoPushJSContext autopush(securitySupports, cx); - if (NS_FAILED(autopush.ResultOfPush())) - goto done; - - js_obj = JSJ_callbacks->map_java_object_to_js_object(jEnv, mJavaClient, &err_msg); - if (!js_obj) { - if (err_msg) { - JS_ReportError(cx, err_msg); - free(err_msg); - } - goto done; - } -#ifdef PRESERVE_JSOBJECT_IDENTITY - *pobj = (jint)js_obj; -#else - /* FIXME: to handle PRESERVE_JSOBJECT_IDENTITY case, this needs to - just return a raw JSObject reference. FIXME !!! */ - /* Create a tiny stub object to act as the GC root that points to the - JSObject from its netscape.javascript.JSObject counterpart. */ - handle = (JSObjectHandle*)JS_malloc(cx, sizeof(JSObjectHandle)); - if (handle != NULL) - { - handle->js_obj = js_obj; - handle->rt = JS_GetRuntime(cx); - } - *pobj = (lcjsobject)handle; - /* FIXME: what if the window is explicitly disposed of, how do we - notify Java? */ -#endif -done: - if (!jsj_exit_js(cx, jsj_env, saved_state)) - return NS_ERROR_FAILURE; - - return NS_OK; -} - -/** - * Get the window object for a plugin instance. - * - * @param jEnv - JNIEnv on which the call is being made. - * @param obj - A Native JS Object. - */ -NS_METHOD -nsCLiveconnect::FinalizeJSObject(JNIEnv *jEnv, lcjsobject obj) -{ - if(jEnv == NULL || obj == 0) - { - return NS_ERROR_FAILURE; - } - - JSObjectHandle *handle = (JSObjectHandle *)obj; - - if (!handle) - return NS_ERROR_NULL_POINTER; - JS_RemoveRootRT(handle->rt, &handle->js_obj); - free(handle); - return NS_OK; -} - - -NS_METHOD -nsCLiveconnect::ToString(JNIEnv *jEnv, lcjsobject obj, jstring *pjstring) -{ - if(jEnv == NULL || obj == 0) - { - return NS_ERROR_FAILURE; - } - - JSJavaThreadState *jsj_env = NULL; - JSObjectHandle *handle = (JSObjectHandle*)obj; - JSObject *js_obj = handle->js_obj; - JSContext *cx = NULL; - JSErrorReporter saved_state = NULL; - jstring result = NULL; - JSString *jsstr = NULL; - - jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, NULL, 0, NULL ); - if (!jsj_env) - return NS_ERROR_FAILURE; - - result = NULL; - AutoPushJSContext autopush(nsnull, cx); - if (NS_FAILED(autopush.ResultOfPush())) - return NS_ERROR_FAILURE; - - jsstr = JS_ValueToString(cx, OBJECT_TO_JSVAL(js_obj)); - if (jsstr) - result = jsj_ConvertJSStringToJavaString(cx, jEnv, jsstr); - if (!result) - result = jEnv->NewStringUTF("*JavaObject*"); - - if (!jsj_exit_js(cx, jsj_env, saved_state)) - return NS_ERROR_FAILURE; - *pjstring = result; - return NS_OK; -} - - -//////////////////////////////////////////////////////////////////////////// -// from nsCLiveconnect: - -nsCLiveconnect::nsCLiveconnect(nsISupports *aOuter) - : mJavaClient(NULL) -{ - NS_INIT_AGGREGATED(aOuter); -#ifdef PRESERVE_JSOBJECT_IDENTITY - jsj_init_js_obj_reflections_table(); -#endif -} - -nsCLiveconnect::~nsCLiveconnect() -{ -} diff --git a/lib/javascript/liveconnect/nsCLiveconnect.h b/lib/javascript/liveconnect/nsCLiveconnect.h deleted file mode 100644 index 517c88c7..00000000 --- a/lib/javascript/liveconnect/nsCLiveconnect.h +++ /dev/null @@ -1,197 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * This file is part of the Java-vendor-neutral implementation of LiveConnect - * - * It contains the class definition to implement nsILiveconnect XP-COM interface. - * - */ - - -#ifndef nsCLiveconnect_h___ -#define nsCLiveconnect_h___ - -#include "nsILiveconnect.h" -#include "nsAgg.h" - - -/** - * nsCLiveconnect implements nsILiveconnect interface for navigator. - * This is used by a JVM to implement netscape.javascript.JSObject functionality. - */ -class nsCLiveconnect :public nsILiveconnect { -public: - //////////////////////////////////////////////////////////////////////////// - // from nsISupports and AggregatedQueryInterface: - - NS_DECL_AGGREGATED - - //////////////////////////////////////////////////////////////////////////// - // from nsILiveconnect: - - /** - * get member of a Native JSObject for a given name. - * - * @param obj - A Native JS Object. - * @param name - Name of a member. - * @param pjobj - return parameter as a java object representing - * the member. If it is a basic data type it is converted to - * a corresponding java type. If it is a NJSObject, then it is - * wrapped up as java wrapper netscape.javascript.JSObject. - */ - NS_IMETHOD - GetMember(JNIEnv *jEnv, lcjsobject obj, const jchar *name, jsize length, void* principalsArray[], - int numPrincipals, nsISupports *securitySupports, jobject *pjobj); - - /** - * get member of a Native JSObject for a given index. - * - * @param obj - A Native JS Object. - * @param index - Index of a member. - * @param pjobj - return parameter as a java object representing - * the member. - */ - NS_IMETHOD - GetSlot(JNIEnv *jEnv, lcjsobject obj, jint slot, void* principalsArray[], - int numPrincipals, nsISupports *securitySupports, jobject *pjobj); - - /** - * set member of a Native JSObject for a given name. - * - * @param obj - A Native JS Object. - * @param name - Name of a member. - * @param jobj - Value to set. If this is a basic data type, it is converted - * using standard JNI calls but if it is a wrapper to a JSObject - * then a internal mapping is consulted to convert to a NJSObject. - */ - NS_IMETHOD - SetMember(JNIEnv *jEnv, lcjsobject obj, const jchar *name, jsize length, jobject jobj, void* principalsArray[], - int numPrincipals, nsISupports *securitySupports); - - /** - * set member of a Native JSObject for a given index. - * - * @param obj - A Native JS Object. - * @param index - Index of a member. - * @param jobj - Value to set. If this is a basic data type, it is converted - * using standard JNI calls but if it is a wrapper to a JSObject - * then a internal mapping is consulted to convert to a NJSObject. - */ - NS_IMETHOD - SetSlot(JNIEnv *jEnv, lcjsobject obj, jint slot, jobject jobj, void* principalsArray[], - int numPrincipals, nsISupports *securitySupports); - - /** - * remove member of a Native JSObject for a given name. - * - * @param obj - A Native JS Object. - * @param name - Name of a member. - */ - NS_IMETHOD - RemoveMember(JNIEnv *jEnv, lcjsobject obj, const jchar *name, jsize length, void* principalsArray[], - int numPrincipals, nsISupports *securitySupports); - - /** - * call a method of Native JSObject. - * - * @param obj - A Native JS Object. - * @param name - Name of a method. - * @param jobjArr - Array of jobjects representing parameters of method being caled. - * @param pjobj - return value. - */ - NS_IMETHOD - Call(JNIEnv *jEnv, lcjsobject obj, const jchar *name, jsize length, jobjectArray jobjArr, void* principalsArray[], - int numPrincipals, nsISupports *securitySupports, jobject *pjobj); - - /** - * Evaluate a script with a Native JS Object representing scope. - * - * @param obj - A Native JS Object. - * @param pNSIPrincipaArray - Array of principals to be used to compare privileges. - * @param numPrincipals - Number of principals being passed. - * @param script - Script to be executed. - * @param pjobj - return value. - */ - NS_IMETHOD - Eval(JNIEnv *jEnv, lcjsobject obj, const jchar *script, jsize length, void* principalsArray[], - int numPrincipals, nsISupports *securitySupports, jobject *pjobj); - - /** - * Get the window object for a plugin instance. - * - * @param pJavaObject - Either a jobject or a pointer to a plugin instance - * representing the java object. - * @param pjobj - return value. This is a native js object - * representing the window object of a frame - * in which a applet/bean resides. - */ - NS_IMETHOD - GetWindow(JNIEnv *jEnv, void *pJavaObject, void* principalsArray[], - int numPrincipals, nsISupports *securitySupports, lcjsobject *pobj); - - /** - * Get the window object for a plugin instance. - * - * @param jEnv - JNIEnv on which the call is being made. - * @param obj - A Native JS Object. - */ - NS_IMETHOD - FinalizeJSObject(JNIEnv *jEnv, lcjsobject obj); - - /** - * Get the window object for a plugin instance. - * - * @param jEnv - JNIEnv on which the call is being made. - * @param obj - A Native JS Object. - * @param jstring - Return value as a jstring representing a JS object. - */ - NS_IMETHOD - ToString(JNIEnv *jEnv, lcjsobject obj, jstring *pjstring); - //////////////////////////////////////////////////////////////////////////// - // from nsCLiveconnect: - - nsCLiveconnect(nsISupports *aOuter); - virtual ~nsCLiveconnect(void); - -protected: - void* mJavaClient; -}; - -#endif // nsCLiveconnect_h___ diff --git a/lib/javascript/liveconnect/nsCLiveconnectFactory.cpp b/lib/javascript/liveconnect/nsCLiveconnectFactory.cpp deleted file mode 100644 index 164e8634..00000000 --- a/lib/javascript/liveconnect/nsCLiveconnectFactory.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * This file is part of the Java-vendor-neutral implementation of LiveConnect - * - * It contains the implementation providing nsILiveconnect XP-COM interface. - * - */ -#include "prtypes.h" -#include "nspr.h" -#include "prmem.h" -#include "prmon.h" -#include "prlog.h" - -#include "nsXPCOM.h" -#include "nsCLiveconnect.h" -#include "nsCLiveconnectFactory.h" -#include "nsIComponentManager.h" -#include "nsIComponentRegistrar.h" - -static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); -static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID); -static NS_DEFINE_CID(kCLiveconnectCID, NS_CLIVECONNECT_CID); - -/*+++++++++++++++++++++++++++++++++++++++++++++++++ - * NSGetFactory: - * Provides entry point to liveconnect dll. - +++++++++++++++++++++++++++++++++++++++++++++++++*/ - -extern "C" NS_EXPORT nsresult -NSGetFactory(nsISupports* serviceMgr, - const nsCID &aClass, - const char *aClassName, - const char *aContractID, - nsIFactory **aFactory) -{ - - if (!aClass.Equals(kCLiveconnectCID)) { - return NS_ERROR_FACTORY_NOT_LOADED; // XXX right error? - } - nsCLiveconnectFactory* factory = new nsCLiveconnectFactory(); - if (factory == NULL) - return NS_ERROR_OUT_OF_MEMORY; - factory->AddRef(); - *aFactory = factory; - return NS_OK; -} - -extern "C" NS_EXPORT PRBool -NSCanUnload(nsISupports* serviceMgr) -{ - return PR_FALSE; -} - -extern "C" NS_EXPORT nsresult -JSJ_RegisterLiveConnectFactory() -{ - nsCOMPtr registrar; - nsresult rv = NS_GetComponentRegistrar(getter_AddRefs(registrar)); - if (NS_FAILED(rv)) - return rv; - - nsCOMPtr factory = new nsCLiveconnectFactory; - if (factory) { - return registrar->RegisterFactory(kCLiveconnectCID, "LiveConnect", - "@mozilla.org/liveconnect/liveconnect;1", - factory); - } - return NS_ERROR_OUT_OF_MEMORY; -} - -//////////////////////////////////////////////////////////////////////////// -// from nsISupports - -NS_METHOD -nsCLiveconnectFactory::QueryInterface(const nsIID& aIID, void** aInstancePtr) -{ - PR_ASSERT(NULL != aInstancePtr); - if (NULL == aInstancePtr) { - return NS_ERROR_NULL_POINTER; - } - if (aIID.Equals(kIFactoryIID) || - aIID.Equals(kISupportsIID)) { - *aInstancePtr = (void*) this; - AddRef(); - return NS_OK; - } - return NS_NOINTERFACE; -} - -NS_IMPL_ADDREF(nsCLiveconnectFactory) -NS_IMPL_RELEASE(nsCLiveconnectFactory) - -//////////////////////////////////////////////////////////////////////////// -// from nsIFactory: - -NS_METHOD -nsCLiveconnectFactory::CreateInstance(nsISupports *aOuter, REFNSIID aIID, void **aResult) -{ - if (!aResult) - return NS_ERROR_INVALID_POINTER; - - *aResult = NULL; - - if (aOuter && !aIID.Equals(kISupportsIID)) - return NS_ERROR_INVALID_ARG; - - nsCLiveconnect* liveconnect = new nsCLiveconnect(aOuter); - if (liveconnect == NULL) - return NS_ERROR_OUT_OF_MEMORY; - - nsresult result = liveconnect->AggregatedQueryInterface(aIID, aResult); - if (NS_FAILED(result)) - delete liveconnect; - - return result; -} - -NS_METHOD -nsCLiveconnectFactory::LockFactory(PRBool aLock) -{ - return NS_OK; -} - -//////////////////////////////////////////////////////////////////////////// -// from nsCLiveconnectFactory: - -nsCLiveconnectFactory::nsCLiveconnectFactory(void) -{ -} - -nsCLiveconnectFactory::~nsCLiveconnectFactory() -{ -} diff --git a/lib/javascript/liveconnect/nsCLiveconnectFactory.h b/lib/javascript/liveconnect/nsCLiveconnectFactory.h deleted file mode 100644 index aeda43f6..00000000 --- a/lib/javascript/liveconnect/nsCLiveconnectFactory.h +++ /dev/null @@ -1,76 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * This file is part of the Java-vendor-neutral implementation of LiveConnect - * - * It contains the class definition to implement nsIFactory XP-COM interface. - * - */ - -#ifndef nsCLiveconnectFactory_h___ -#define nsCLiveconnectFactory_h___ - -#include "nsISupports.h" -#include "nsIFactory.h" - -class nsCLiveconnectFactory : public nsIFactory { -public: - //////////////////////////////////////////////////////////////////////////// - // from nsISupports and AggregatedQueryInterface: - - NS_DECL_ISUPPORTS - - //////////////////////////////////////////////////////////////////////////// - // from nsIFactory: - - NS_IMETHOD - CreateInstance(nsISupports *aOuter, REFNSIID aIID, void **aResult); - - NS_IMETHOD - LockFactory(PRBool aLock); - - - //////////////////////////////////////////////////////////////////////////// - // from nsCLiveconnectFactory: - - nsCLiveconnectFactory(void); - virtual ~nsCLiveconnectFactory(void); -}; - -#endif // nsCLiveconnectFactory_h___ diff --git a/lib/javascript/liveconnect/nsILiveconnect.h b/lib/javascript/liveconnect/nsILiveconnect.h deleted file mode 100644 index 059fc22f..00000000 --- a/lib/javascript/liveconnect/nsILiveconnect.h +++ /dev/null @@ -1,195 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * This file is part of the Java-vendor-neutral implementation of LiveConnect - * - * It contains the public XP-COM based interface for java to javascript communication. - * - */ - -#ifndef nsILiveconnect_h___ -#define nsILiveconnect_h___ - -#include "nsISupports.h" -#include "nsIFactory.h" -#include "jni.h" -#include "jsjava.h" // For lcjsobject - -#define NS_ILIVECONNECT_IID \ -{ /* 68190910-3318-11d2-97f0-00805f8a28d0 */ \ - 0x68190910, \ - 0x3318, \ - 0x11d2, \ - {0x97, 0xf0, 0x00, 0x80, 0x5f, 0x8a, 0x28, 0xd0} \ -} - -#define NS_CLIVECONNECT_CID \ -{ /* b8f0cef0-3931-11d2-97f0-00805f8a28d0 */ \ - 0xb8f0cef0, \ - 0x3931, \ - 0x11d2, \ - {0x97, 0xf0, 0x00, 0x80, 0x5f, 0x8a, 0x28, 0xd0} \ -} - -class nsILiveconnect : public nsISupports { -public: - NS_DEFINE_STATIC_IID_ACCESSOR(NS_ILIVECONNECT_IID) - NS_DEFINE_STATIC_CID_ACCESSOR(NS_CLIVECONNECT_CID) - - /** - * get member of a Native JSObject for a given name. - * - * @param obj - A Native JS Object. - * @param name - Name of a member. - * @param pjobj - return parameter as a java object representing - * the member. If it is a basic data type it is converted to - * a corresponding java type. If it is a NJSObject, then it is - * wrapped up as java wrapper netscape.javascript.JSObject. - */ - NS_IMETHOD - GetMember(JNIEnv *jEnv, lcjsobject jsobj, const jchar *name, jsize length, void* principalsArray[], - int numPrincipals, nsISupports *securitySupports, jobject *pjobj) = 0; - - /** - * get member of a Native JSObject for a given index. - * - * @param obj - A Native JS Object. - * @param slot - Index of a member. - * @param pjobj - return parameter as a java object representing - * the member. - */ - NS_IMETHOD - GetSlot(JNIEnv *jEnv, lcjsobject jsobj, jint slot, void* principalsArray[], - int numPrincipals, nsISupports *securitySupports, jobject *pjobj) = 0; - - /** - * set member of a Native JSObject for a given name. - * - * @param obj - A Native JS Object. - * @param name - Name of a member. - * @param jobj - Value to set. If this is a basic data type, it is converted - * using standard JNI calls but if it is a wrapper to a JSObject - * then a internal mapping is consulted to convert to a NJSObject. - */ - NS_IMETHOD - SetMember(JNIEnv *jEnv, lcjsobject jsobj, const jchar* name, jsize length, jobject jobj, void* principalsArray[], - int numPrincipals, nsISupports *securitySupports) = 0; - - /** - * set member of a Native JSObject for a given index. - * - * @param obj - A Native JS Object. - * @param index - Index of a member. - * @param jobj - Value to set. If this is a basic data type, it is converted - * using standard JNI calls but if it is a wrapper to a JSObject - * then a internal mapping is consulted to convert to a NJSObject. - */ - NS_IMETHOD - SetSlot(JNIEnv *jEnv, lcjsobject jsobj, jint slot, jobject jobj, void* principalsArray[], - int numPrincipals, nsISupports *securitySupports) = 0; - - /** - * remove member of a Native JSObject for a given name. - * - * @param obj - A Native JS Object. - * @param name - Name of a member. - */ - NS_IMETHOD - RemoveMember(JNIEnv *jEnv, lcjsobject jsobj, const jchar* name, jsize length, void* principalsArray[], - int numPrincipals, nsISupports *securitySupports) = 0; - - /** - * call a method of Native JSObject. - * - * @param obj - A Native JS Object. - * @param name - Name of a method. - * @param jobjArr - Array of jobjects representing parameters of method being caled. - * @param pjobj - return value. - */ - NS_IMETHOD - Call(JNIEnv *jEnv, lcjsobject jsobj, const jchar* name, jsize length, jobjectArray jobjArr, void* principalsArray[], - int numPrincipals, nsISupports *securitySupports, jobject *pjobj) = 0; - - /** - * Evaluate a script with a Native JS Object representing scope. - * - * @param obj - A Native JS Object. - * @param principalsArray - Array of principals to be used to compare privileges. - * @param numPrincipals - Number of principals being passed. - * @param script - Script to be executed. - * @param pjobj - return value. - */ - NS_IMETHOD - Eval(JNIEnv *jEnv, lcjsobject obj, const jchar *script, jsize length, void* principalsArray[], - int numPrincipals, nsISupports *securitySupports, jobject *pjobj) = 0; - - /** - * Get the window object for a plugin instance. - * - * @param pJavaObject - Either a jobject or a pointer to a plugin instance - * representing the java object. - * @param pjobj - return value. This is a native js object - * representing the window object of a frame - * in which a applet/bean resides. - */ - NS_IMETHOD - GetWindow(JNIEnv *jEnv, void *pJavaObject, void* principalsArray[], - int numPrincipals, nsISupports *securitySupports, lcjsobject *pobj) = 0; - - /** - * Get the window object for a plugin instance. - * - * @param jEnv - JNIEnv on which the call is being made. - * @param obj - A Native JS Object. - */ - NS_IMETHOD - FinalizeJSObject(JNIEnv *jEnv, lcjsobject jsobj) = 0; - - /** - * Get the window object for a plugin instance. - * - * @param jEnv - JNIEnv on which the call is being made. - * @param obj - A Native JS Object. - * @param jstring - Return value as a jstring representing a JS object. - */ - NS_IMETHOD - ToString(JNIEnv *jEnv, lcjsobject obj, jstring *pjstring) = 0; -}; - -#endif // nsILiveconnect_h___ diff --git a/lib/javascript/liveconnect/nsISecureLiveconnect.h b/lib/javascript/liveconnect/nsISecureLiveconnect.h deleted file mode 100644 index 85eb74cb..00000000 --- a/lib/javascript/liveconnect/nsISecureLiveconnect.h +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * This file is part of the Java-vendor-neutral implementation of LiveConnect - * - * It contains the public XP-COM based interface for java to javascript communication. - * This interface allows scripts to be evaluated in a secure fashion. - * - */ - -#ifndef nsISecureLiveconnect_h___ -#define nsISecureLiveconnect_h___ - -#include "nsISupports.h" -#include "nsIFactory.h" -#include "jni.h" - -typedef jint jsobject; - -class nsISecureLiveconnect : public nsISupports { -public: - /** - * Evaluate a script with a Native JS Object representing scope. - * - * @param jEnv - JNIEnv pointer - * @param obj - A Native JS Object. - * @param script - JavaScript to be executed. - * @param pNSIPrincipaArray - Array of principals to be used to compare privileges. - * @param numPrincipals - Number of principals being passed. - * @param context - Security context. - * @param pjobj - return value. - */ - NS_IMETHOD - Eval(JNIEnv *jEnv, jsobject obj, const jchar *script, jsize length, void **pNSIPrincipaArray, - int numPrincipals, void *pNSISecurityContext, jobject *pjobj) = 0; -}; - - -#define NS_ISECURELIVECONNECT_IID \ -{ /* 68190910-3318-11d2-97f0-00805f8a28d0 */ \ - 0x68190910, \ - 0x3318, \ - 0x11d2, \ - {0x97, 0xf0, 0x00, 0x80, 0x5f, 0x8a, 0x28, 0xd0} \ -} - - -#endif // nsILiveconnect_h___ diff --git a/lib/javascript/liveconnect/nsISecurityContext.h b/lib/javascript/liveconnect/nsISecurityContext.h deleted file mode 100644 index 13babdab..00000000 --- a/lib/javascript/liveconnect/nsISecurityContext.h +++ /dev/null @@ -1,135 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* - * This file is part of the Java-vendor-neutral implementation of LiveConnect - * - * It contains the public XP-COM based interface for java to javascript communication. - * This interface allows java and javascript to exchange security contexts to allow - * access to restricted resources on either side. - * - */ - -#ifndef nsISecurityContext_h___ -#define nsISecurityContext_h___ - -#include "nsISupports.h" - -#define NS_ISECURITYCONTEXT_IID \ -{ /* {209B1120-4C41-11d2-A1CB-00805F8F694D} */ \ - 0x209b1120, \ - 0x4c41, \ - 0x11d2, \ - { 0xa1, 0xcb, 0x0, 0x80, 0x5f, 0x8f, 0x69, 0x4d } \ -} - -class nsISecurityContext : public nsISupports { -public: - - NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISECURITYCONTEXT_IID) - - /** - * Get the security context to be used in LiveConnect. - * This is used for JavaScript <--> Java. - * - * @param target -- Possible target. - * @param action -- Possible action on the target. - * @return -- NS_OK if the target and action is permitted on the security context. - * -- NS_FALSE otherwise. - */ - NS_IMETHOD Implies(const char* target, const char* action, PRBool *bAllowedAccess) = 0; - - /** - * Get the origin associated with the context. - * - * @param buf -- Result buffer (managed by the caller.) - * @param len -- Buffer length. - * @return -- NS_OK if the codebase string was obtained. - * -- NS_FALSE otherwise. - */ - NS_IMETHOD GetOrigin(char* buf, int len) = 0; - - /** - * Get the certificate associated with the context. - * - * @param buf -- Result buffer (managed by the caller.) - * @param len -- Buffer length. - * @return -- NS_OK if the codebase string was obtained. - * -- NS_FALSE otherwise. - */ - NS_IMETHOD GetCertificateID(char* buf, int len) = 0; -}; - - -// Supported targets in Netscape Navigator 4.0 (Communicator): - -#define nsSecurityTarget_UniversalThreadAccess "UniversalThreadAccess" // allows manipulation of threads not belonging to the applet -#define nsSecurityTarget_UniversalExecAccess "UniversalExecAccess" // allows executing sub-processes -#define nsSecurityTarget_UniversalExitAccess "UniversalExitAccess" // allows terminating the browser session -#define nsSecurityTarget_UniversalLinkAccess "UniversalLinkAccess" // allows linking to dymanically loaded libraries (DLLs) -#define nsSecurityTarget_UniversalPropertyWrite "UniversalPropertyWrite" // allows reading and writing of all system properties (vs. restrictions on applets) -#define nsSecurityTarget_UniversalPropertyRead "UniversalPropertyRead" // allows reading of all system properties (vs. restrictions on applets) -#define nsSecurityTarget_UniversalFileRead "UniversalFileRead" // allows reading any file in the local filesystem -#define nsSecurityTarget_UniversalFileWrite "UniversalFileWrite" // allows writing any file in the local filesystem -#define nsSecurityTarget_UniversalFileDelete "UniversalFileDelete" // allows deleting of any file in the local filesystem -#define nsSecurityTarget_UniversalFdRead "UniversalFdRead" // allows reading from any arbitrary file descriptor -#define nsSecurityTarget_UniversalFdWrite "UniversalFdWrite" // allows writing to any arbitrary file descriptor -#define nsSecurityTarget_UniversalListen "UniversalListen" // allows establishing the server-side of a network connection -#define nsSecurityTarget_UniversalAccept "UniversalAccept" // allows waiting on a network connection -#define nsSecurityTarget_UniversalConnect "UniversalConnect" // allows establishing the client-side of a network connection -#define nsSecurityTarget_UniversalMulticast "UniversalMulticast" // allows establishing IP multicast a network connection -#define nsSecurityTarget_UniversalTopLevelWindow "UniversalTopLevelWindow" // allows top-level windows to be created by the applet writer. -#define nsSecurityTarget_UniversalPackageAccess "UniversalPackageAccess" // allows access to java packages -#define nsSecurityTarget_UniversalPackageDefinition "UniversalPackageDefinition" // allows access to define packages -#define nsSecurityTarget_UniversalSetFactory "UniversalSetFactory" // allows access to set a networking-related object factory -#define nsSecurityTarget_UniversalMemberAccess "UniversalMemberAccess" // allows access to members of a class -#define nsSecurityTarget_UniversalPrintJobAccess "UniversalPrintJobAccess" // allows access to initiate a print job request -#define nsSecurityTarget_UniversalSystemClipboardAccess "UniversalSystemClipboardAccess" // allows access to System Clipboard -#define nsSecurityTarget_UniversalAwtEventQueueAccess "UniversalAwtEventQueueAccess" // allows access to Awt's EventQueue -#define nsSecurityTarget_UniversalSecurityProvider "UniversalSecurityProvider" // allows access to certain operations to a given provider, for example, only a given provider (e.g. Netscape) is able to retrieve the Netscape provider properties -#define nsSecurityTarget_UniversalBrowserRead "UniversalBrowserRead" // allows access to browser data -#define nsSecurityTarget_UniversalBrowserWrite "UniversalBrowserWrite" // allows modification of browser data -#define nsSecurityTarget_UniversalSendMail "UniversalSendMail" // allows sending mail -#define nsSecurityTarget_SuperUser "SuperUser" // enables all privileges -#define nsSecurityTarget_30Capabilities "30Capabilities" // enables all privileges that are available in Navigator 3.0. -#define nsSecurityTarget_UniversalFileAccess "UniversalFileAccess" // enables read, write and delete of any file in the local filesystem -#define nsSecurityTarget_TerminalEmulator "TerminalEmulator" // enables socket connections, property read and to link dynamic libraries. - - - -#endif // nsISecurityContext_h___ diff --git a/lib/javascript/liveconnect/win32.order b/lib/javascript/liveconnect/win32.order deleted file mode 100644 index 014ecc81..00000000 --- a/lib/javascript/liveconnect/win32.order +++ /dev/null @@ -1,6 +0,0 @@ -?AddRef@nsCLiveconnectFactory@@UAGKXZ ; 2 -?Release@nsCLiveconnectFactory@@UAGKXZ ; 2 -??0nsCLiveconnectFactory@@QAE@XZ ; 1 -_JSJ_RegisterLiveConnectFactory ; 1 -??_EnsCLiveconnectFactory@@UAEPAXI@Z ; 1 -??1nsCLiveconnectFactory@@UAE@XZ ; 1 diff --git a/lib/javascript/lock_SunOS.s b/lib/javascript/lock_SunOS.s deleted file mode 100644 index 7a842d18..00000000 --- a/lib/javascript/lock_SunOS.s +++ /dev/null @@ -1,114 +0,0 @@ -! -! The contents of this file are subject to the Netscape Public -! License Version 1.1 (the "License"); you may not use this file -! except in compliance with the License. You may obtain a copy of -! the License at http://www.mozilla.org/NPL/ -! -! Software distributed under the License is distributed on an "AS -! IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -! implied. See the License for the specific language governing -! rights and limitations under the License. -! -! The Original Code is Mozilla Communicator client code, released -! March 31, 1998. -! -! The Initial Developer of the Original Code is Netscape -! Communications Corporation. Portions created by Netscape are -! Copyright (C) 1998-1999 Netscape Communications Corporation. All -! Rights Reserved. -! -! Contributor(s): -! -! Alternatively, the contents of this file may be used under the -! terms of the GNU Public License (the "GPL"), in which case the -! provisions of the GPL are applicable instead of those above. -! If you wish to allow use of your version of this file only -! under the terms of the GPL and not to allow others to use your -! version of this file under the NPL, indicate your decision by -! deleting the provisions above and replace them with the notice -! and other provisions required by the GPL. If you do not delete -! the provisions above, a recipient may use your version of this -! file under either the NPL or the GPL. -! - -! -! atomic compare-and-swap routines for V8 sparc -! and for V8+ (ultrasparc) -! -! -! standard asm linkage macros; this module must be compiled -! with the -P option (use C preprocessor) - -#include - -! ====================================================================== -! -! Perform the sequence *a = b atomically with respect to previous value -! of a (a0). If *a==a0 then assign *a to b, all in one atomic operation. -! Returns 1 if assignment happened, and 0 otherwise. -! -! usage : old_val = compare_and_swap(address, oldval, newval) -! -! ----------------------- -! Note on REGISTER USAGE: -! as this is a LEAF procedure, a new stack frame is not created; -! we use the caller stack frame so what would normally be %i (input) -! registers are actually %o (output registers). Also, we must not -! overwrite the contents of %l (local) registers as they are not -! assumed to be volatile during calls. -! -! So, the registers used are: -! %o0 [input] - the address of the value to increment -! %o1 [input] - the old value to compare with -! %o2 [input] - the new value to set for [%o0] -! %o3 [local] - work register -! ----------------------- -#ifndef ULTRA_SPARC -! v8 - - ENTRY(compare_and_swap) ! standard assembler/ELF prologue - - stbar - mov -1,%o3 ! busy flag - swap [%o0],%o3 ! get current value -l1: cmp %o3,-1 ! busy? - be,a l1 ! if so, spin - swap [%o0],%o3 ! using branch-delay to swap back value - cmp %o1,%o3 ! compare old with current - be,a l2 ! if equal then swap in new value - swap [%o0],%o2 ! done. - swap [%o0],%o3 ! otherwise, swap back current value - retl - mov 0,%o0 ! return false -l2: retl - mov 1,%o0 ! return true - - SET_SIZE(compare_and_swap) ! standard assembler/ELF epilogue - -! -! end -! -#else /* ULTRA_SPARC */ -! ====================================================================== -! -! v9 - - ENTRY(compare_and_swap) ! standard assembler/ELF prologue - - stbar - cas [%o0],%o1,%o2 ! compare *w with old value and set to new if equal - cmp %o1,%o2 ! did we succeed? - be,a m1 ! yes - mov 1,%o0 ! return true (annulled when no jump) - mov 0,%o0 ! return false -m1: retl - nop - - SET_SIZE(compare_and_swap) ! standard assembler/ELF epilogue - -! -! end -! -! ====================================================================== -! -#endif diff --git a/lib/javascript/perfect.js b/lib/javascript/perfect.js deleted file mode 100644 index aeca1211..00000000 --- a/lib/javascript/perfect.js +++ /dev/null @@ -1,39 +0,0 @@ -// Some simple testing of new, eval and some string stuff. - -// constructor -- expression array initialization -function ExprArray(n,v) -{ - // Initializes n values to v coerced to a string. - for (var i = 0; i < n; i++) { - this[i] = "" + v; - } -} - - -// Print the perfect numbers up to n and the sum expression for n's divisors. -function perfect(n) -{ - print("The perfect numbers up to " + n + " are:"); - - // We build sumOfDivisors[i] to hold a string expression for - // the sum of the divisors of i, excluding i itself. - var sumOfDivisors = new ExprArray(n+1,1); - for (var divisor = 2; divisor <= n; divisor++) { - for (var j = divisor + divisor; j <= n; j += divisor) { - sumOfDivisors[j] += " + " + divisor; - } - // At this point everything up to 'divisor' has its sumOfDivisors - // expression calculated, so we can determine whether it's perfect - // already by evaluating. - if (eval(sumOfDivisors[divisor]) == divisor) { - print("" + divisor + " = " + sumOfDivisors[divisor]); - } - } - print("That's all."); -} - - -print("\nA number is 'perfect' if it is equal to the sum of its") -print("divisors (excluding itself).\n"); -perfect(500); - diff --git a/lib/javascript/perlconnect/.cvsignore b/lib/javascript/perlconnect/.cvsignore deleted file mode 100644 index 8b246c57..00000000 --- a/lib/javascript/perlconnect/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -JS.c diff --git a/lib/javascript/perlconnect/JS.def b/lib/javascript/perlconnect/JS.def deleted file mode 100644 index 8e079e8d..00000000 --- a/lib/javascript/perlconnect/JS.def +++ /dev/null @@ -1,6 +0,0 @@ -LIBRARY "JS" -DESCRIPTION "JS library for Perl <-> JS communications" -CODE LOADONCALL -DATA LOADONCALL NONSHARED MULTIPLE -EXPORTS - boot_JS diff --git a/lib/javascript/perlconnect/JS.dsp b/lib/javascript/perlconnect/JS.dsp deleted file mode 100644 index 1ad34c93..00000000 --- a/lib/javascript/perlconnect/JS.dsp +++ /dev/null @@ -1,107 +0,0 @@ -# Microsoft Developer Studio Project File - Name="JS" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 - -CFG=JS - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "JS.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "JS.mak" CFG="JS - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "JS - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "JS - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -MTL=midl.exe -RSC=rc.exe - -!IF "$(CFG)" == "JS - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c -# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c -# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 - -!ELSEIF "$(CFG)" == "JS - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "d:\opc\ns\js\ref" /I "$(PERL_SRC)" /I "$(PERL_SRC)\win32" /I "$(PERL_SRC)\win32\include" /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "XP_PC" /YX /FD /c -# SUBTRACT CPP /Gy /Fr -# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 /win32 -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept -# ADD LINK32 js32.lib perl.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"z:\livshits\src\perl\lib\auto\JS\JS.dll" /pdbtype:sept /libpath:"..\Debug" /libpath:"$(PERL_SRC)" - -!ENDIF - -# Begin Target - -# Name "JS - Win32 Release" -# Name "JS - Win32 Debug" -# Begin Source File - -SOURCE=.\JS.c -# End Source File -# Begin Source File - -SOURCE=.\JS.def -# End Source File -# Begin Source File - -SOURCE=.\jsperl.c -# End Source File -# Begin Source File - -SOURCE=.\jsperlpvt.h -# End Source File -# End Target -# End Project diff --git a/lib/javascript/perlconnect/JS.pm b/lib/javascript/perlconnect/JS.pm deleted file mode 100644 index f4d95e65..00000000 --- a/lib/javascript/perlconnect/JS.pm +++ /dev/null @@ -1,318 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -############################################################################ -# JS.pm is a Perl interface to JavaScript 3/2/99 5:23PM -# The packages implemented here include -# JS, JS::Runtime, JS::Contents, JS::Object -# See README.html for more information about this module. -############################################################################ - -package JS; -$VERSION='0.03'; -require Exporter; -use DynaLoader; -@ISA = qw(Exporter DynaLoader); -use strict; -use vars qw($VERSION); - -sub boot #7/31/98 5:28PM -{ - # this is to load the JS DLL at run-time - bootstrap JS $VERSION; - push @DynaLoader::dl_library_path, $ENV{'LD_LIBRARY_PATH'}; -} ##boot - -sub new { - my ($class, $maxbytes) = @_; - my $self = new JS::Runtime($maxbytes); - return $self; -} - -############################################################ -# JS::Runtime -############################################################ -package JS::Runtime; -use strict; -use vars qw ($AUTOLOAD $DEBUG %CONTEXTS); - -# we use %CONTEXT hash to remember all created contex. -# reason of this is increase reference to context objects -# and ensure corret order of destructor calls - -sub AUTOLOAD #7/28/98 8:24PM -{ - print "\nJS::Runtime::AUTOLOAD: $AUTOLOAD, not implemented yet\n" if $DEBUG; -} ##AUTOLOAD - - -# Constructor. Calls NewRuntime - -sub new #7/31/98 3:39PM -{ - warn "JS::Runtime::new\n" if $DEBUG; - my($class, $maxbytes) = @_; - my $self = JS::NewRuntime(scalar($maxbytes)); - return $self; -} ##new - -sub createContext { - my ($self, $stacksize) = @_; - #my $cx = $self->NewContext($stacksize); - my $cx = JS::Context->new($self, $stacksize); -# $CONTEXTS{$self} = [] unless exists $CONTEXTS{$self}; -# push @{$CONTEXTS{$self}}, $cx; - return $cx; -} - -# Destructor for Runtimes -sub DESTROY #7/31/98 4:54PM -{ - my $self = shift; - warn "JS::Runtime::DESTROY\n" if $DEBUG; - JS::DestroyRuntime($self); -} ##DESTROY - -############################################################ -# JS::Context -############################################################ -package JS::Context; -use vars qw($AUTOLOAD $DEBUG); - -# sub AUTOLOAD #7/28/98 8:24PM -# { -# print "\nJS::Context::AUTOLOAD: $AUTOLOAD, not implemented yet\n" if $DEBUG; -# } ##AUTOLOAD - -sub new #7/31/98 3:39PM -{ - warn "JS::Context::new\n" if $DEBUG; - my($class, $rt, $stacksize) = @_; - $class = ref $class || $class; - my $cx = JS::Runtime::NewContext($rt, $stacksize); - my $self = { - _handle => $cx, - _name => ("name_" . int (rand 1000)), - }; - $self->{_handle}; - bless $self, $class; - return $self; -} ##new - -use Data::Dumper; - -sub exec { - my ($self, $script) = @_; - $self->exec_($script); -} - -sub DESTROY #7/31/98 4:54PM -{ - my $self = shift; - warn "JS::Context::DESTROY\n" if $DEBUG; - JS::Runtime::DestroyContext($self); -} ##DESTROY - - -############################################################ -# JS::Script -############################################################ -package JS::Script; - -sub new { - my ($class, $cx, $code, $name) = @_; - $class = ref $class || $class; - my $self = {}; - bless $self, $class; - $self->{_script} = $self->compileScript($cx, $code, $name); - $self->{_root} = $self->rootScript($cx, $name); - $self->{_cx} = $cx; #!!! dangerous - $self->{_name} = $name; - return $self; -} - -sub DESTROY { - my $self = shift; - print "---> script destroy\n"; - my $cx = $self->{_cx}; - $self->destroyScript($cx); -} - -############################################################ -# JS::Object -############################################################ -package JS::Object; -use vars qw($AUTOLOAD $DEBUG); - -sub AUTOLOAD #7/28/98 8:24PM -{ - $_ = $AUTOLOAD; - $_ =~ s/.*://; - print "\nJS::Object::AUTOLOAD: $_, not implemented yet\n" if $DEBUG; -} ##AUTOLOAD - - - -############################################################ -# executable part -############################################################ -#$JS::Runtime::DEBUG = 1; -#$JS::Context::DEBUG = 1; -#$JS::Object::DEBUG = 1; - -&JS::boot(); - -1; - -############################################################ -# the end -############################################################ - - - - -__END__ - -package JS; -$VERSION = '0.03'; -require Exporter; -require DynaLoader; -@ISA = qw(Exporter DynaLoader); - -#@ISA = qw(JS); - -############################################################################ -# Duplicates JS::Context::new is a way -############################################################################ -sub new #7/31/98 5:32PM -{ - print "JS::new" if $DEBUG; - my $rt = new JS::Runtime(10_000); - $this = new JS::Context($rt, 1_024); - return $this -} ##new - -############################################################################ -# Uses DynaLoader to load JS support DLL, performs the initialization -############################################################################ -sub boot #7/31/98 5:28PM -{ - # this is to load the JS DLL at run-time - bootstrap JS $VERSION; - push @dl_library_path, $ENV{'LD_LIBRARY_PATH'}; -} ##boot - -############################################################################ -package JS::Runtime; -@EXPORT = qw($this); - -sub AUTOLOAD #7/28/98 8:24PM -{ - print "\nJS::Runtime::AUTOLOAD: $AUTOLOAD, not implemented yet\n" if $DEBUG; -} ##AUTOLOAD - -############################################################################ -# Constructor. Calls NewRuntime and saves the returned value in this -############################################################################ -sub new #7/31/98 3:39PM -{ - print "JS::Runtime::new\n" if $DEBUG; - my($class, $maxbytes) = @_; - $this = JS::NewRuntime(scalar($maxbytes)); - return $this; -} ##new - -############################################################################ -# Destructor for Runtimes -############################################################################ -sub DESTROY #7/31/98 4:54PM -{ - my $self = shift; - print "JS::Runtime::DESTROY\n" if $DEBUG; -warn("JS::Runtime::DESTROY\n"); - JS::DestroyRuntime($self); - undef $this; -} ##DESTROY - -############################################################################ -package JS::Context; -@EXPORT = qw($this); - -sub AUTOLOAD #7/28/98 8:24PM -{ - print "\nJS::Context::AUTOLOAD: $AUTOLOAD, not implemented yet\n" if $DEBUG; -} ##AUTOLOAD - -############################################################################ -# Constructor. Calls NewContext and saves the returned value in this -############################################################################ -sub new #7/31/98 3:39PM -{ - print "JS::Context::new\n" if $DEBUG; -warn("JS::Context::new\n"); - my($class, $rt, $stacksize) = @_; - $this = JS::Runtime::NewContext($rt, $stacksize); - return $this; -} ##new - -############################################################################ -# Destructor for Contexts -############################################################################ -sub DESTROY #7/31/98 4:54PM -{ - my $self = shift; - print "JS::Context::DESTROY\n" if $DEBUG; -warn("JS::Context::DESTROY\n"); - JS::Runtime::DestroyContext($self); - undef $this; -} ##DESTROY - -############################################################################ - -package JS::Object; - -sub AUTOLOAD #7/28/98 8:24PM -{ - $_ = $AUTOLOAD; - $_ =~ s/.*://; - print "\nJS::Object::AUTOLOAD: $_, not implemented yet\n" if $DEBUG; -} ##AUTOLOAD - -&JS::boot(); - -1; diff --git a/lib/javascript/perlconnect/JS.xs b/lib/javascript/perlconnect/JS.xs deleted file mode 100644 index 599e4646..00000000 --- a/lib/javascript/perlconnect/JS.xs +++ /dev/null @@ -1,1050 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * PerlConnect. Provides means for OO Perl <==> JS communications - */ - -/* This is an program written in XSUB. You need to compile it using xsubpp */ -/* usually found in your perl\bin directory. On my machine I do it like this:*/ -/* perl c:\perl\lib\ExtUtils\xsubpp -typemap \ */ -/* c:\perl\lib\extutils\typemap -typemap typemap JS.xs > JS.c */ -/* See perlxs man page for details. */ -/* Don't edit the resulting C file directly. See README.html for more info */ -/* on PerlConnect in general */ - -#ifdef __cplusplus - extern "C"; { -#endif -#include "EXTERN.h" -#include "perl.h" -#include "XSUB.h" -#ifdef __cplusplus - } -#endif - -#include -#include "jsperlpvt.h" -#include - -/* __REMOVE__ */ -/* #include */ - -/************************************************************/ -/* utils */ - -static JSBool -checkError(JSContext *cx) -{ - if(SvTRUE(GvSV(PL_errgv))){ - JS_ReportError(cx, "perl eval failed: %s", - SvPV(GvSV(PL_errgv), PL_na)); - /* clear error status. there should be a way to do this faster */ - perl_eval_sv(newSVpv("undef $@;", 0), G_KEEPERR); - return JS_FALSE; - } - return JS_TRUE; -} - -static void -clearException(JSContext *cx) -{ - if (JS_IsExceptionPending(cx)) { - JS_ClearPendingException(cx); - } -} - -/************************************************************/ -/* calback stub */ - -/* this is internal js structure needed in errorFromPrivate */ -typedef struct JSExnPrivate { - JSErrorReport *errorReport; -} JSExnPrivate; - -static -JSClass global_class = { - "Global", 0, - JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub -}; - -/* __PH__BEGIN */ -/* perl callback structure */ -/* prefix PCB means Perl CallBack */ - -struct PerlCallbackItem{ - char* name; - SV* perl_proc; - int param_num; - struct PerlCallbackItem *next; -}; - -typedef struct PerlCallbackItem PerlCallbackItem; - - -struct PerlObjectItem { - char * name; - SV* pObject; - //JSObject *jsStub; - JSObject *jsObject; - JSClass *jsClass; - struct PerlCallbackItem* vector; - struct PerlObjectItem *next; -}; - -typedef struct PerlObjectItem PerlObjectItem; - -/* error reporter */ -//struct JSContextItem; -//struct JSContextItem; -struct JSContextItem { - JSContext *cx; - SV *errorReporter; - PerlObjectItem *objects; - int dieFromErrors; - struct JSContextItem* next; -}; - -typedef struct JSContextItem JSContextItem; - -static JSContextItem *context_list = NULL; - -static JSContextItem* -PCB_NewContextItem() { - JSContextItem *ret; - ret = (JSContextItem*)calloc(1, sizeof(JSContextItem)); - return ret; -} - -static JSContextItem* -PCB_FindContextItem (JSContext *cx) { - JSContextItem *cxitem = context_list; - while ( cxitem ) { - if (cxitem->cx == cx ) return cxitem; - cxitem = cxitem->next; - } - return NULL; -} - -static SV* -PCB_FindErrorReporter (JSContext *cx) { - JSContextItem *cxitem; - if (cxitem = PCB_FindContextItem(cx)) { - return cxitem->errorReporter; - } else { - return NULL; - } -} - -static void -PCB_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report) -{ - SV *report_proc; - if ( report_proc = PCB_FindErrorReporter(cx) ) { - dSP; - PUSHMARK(SP); - XPUSHs(sv_2mortal(newSVpv((char*)message, 0))); - if ( report ) { - if ( report->filename ) { - XPUSHs(sv_2mortal(newSVpv((char*)report->filename, 0))); - } - XPUSHs(sv_2mortal(newSViv(report->lineno))); - if (report->linebuf) { - XPUSHs(sv_2mortal(newSVpv((char*)report->linebuf, 0))); - XPUSHs(sv_2mortal(newSVpv((char*)report->tokenptr, 0))); - } - } - PUTBACK; - perl_call_sv(report_proc, G_VOID | G_DISCARD); - } else { - warn(message); - } -} - -/* perl object stuff */ - - -/* functions for callback list handling */ -static PerlCallbackItem* -PCB_AddCallback(PerlObjectItem* object, char *name, - SV* perl_proc, int param_num) { - PerlCallbackItem *cbk; - - cbk = (PerlCallbackItem*)calloc(1, sizeof(PerlCallbackItem)); - cbk->name = (char*) malloc(strlen(name) + 1); - strcpy(cbk->name, name); - SvREFCNT_inc(perl_proc); - cbk->perl_proc = perl_proc; - cbk->param_num = param_num; - - cbk->next = object->vector; - object->vector = cbk; - - return cbk; -} - -/* functions for perl object list handling */ - -static PerlObjectItem* -PCB_AddObject(char *name, SV *pobj, JSContext *cx, JSObject *jso, JSClass *class) { - JSContextItem *cxitem; - PerlObjectItem *object; - - /* we should always find the item */ - cxitem = PCB_FindContextItem(cx); - object = (PerlObjectItem*) calloc(1, sizeof(PerlObjectItem)); - object->name = (char*) malloc(strlen(name) + 1); - strcpy(object->name, name); - SvREFCNT_inc(pobj); - object->pObject = pobj; - object->jsObject = jso; - object->jsClass = class; - object->next = cxitem->objects; - cxitem->objects = object; - - return object; -} - -static PerlObjectItem* -PCB_FindObject(JSContext *cx, JSObject *jso) { - JSContextItem *cxitem; - PerlObjectItem *objitem; - - cxitem = PCB_FindContextItem(cx); - objitem = cxitem->objects; - - while ( objitem ) { - if ( objitem->jsObject == jso ) return objitem; - objitem = objitem->next; - } - return NULL; -} - -static PerlCallbackItem* -PCB_FindCallback(PerlObjectItem *obj, const char *name) { - PerlCallbackItem *cbkitem; - - cbkitem = obj->vector; - while ( cbkitem ) { - if ( strcmp(name, cbkitem->name) == 0 ) return cbkitem; - cbkitem = cbkitem->next; - } - return NULL; -} - -/* deletion functions */ - -static void -PCB_FreeCallbackItem(PerlCallbackItem *callback) { - free(callback->name); - /* we have to decrease ref. count to proc */ - SvREFCNT_dec(callback->perl_proc); - free(callback); -} - -static void -PCB_FreeObjectItem(PerlObjectItem *object) { - PerlCallbackItem *cbkitem, *next; - JSClass *class; - - free(object->name); - free(object->jsClass); - - SvREFCNT_dec(object->pObject); - cbkitem = object->vector; - while ( cbkitem ) { - next = cbkitem->next; - PCB_FreeCallbackItem(cbkitem); - cbkitem = next; - } - free(object); -} - -static void -PCB_FreeContextItem(JSContext *cx) { - JSContextItem *cxitem, *aux; - PerlObjectItem *objitem, *next; - - cxitem = PCB_FindContextItem(cx); - objitem = cxitem->objects; - - while ( objitem ) { - next = objitem->next; - PCB_FreeObjectItem(objitem); - objitem = next; - } - - if (cxitem->errorReporter) { - SvREFCNT_dec(cxitem->errorReporter); - } - - if ( context_list == cxitem ) { - context_list = cxitem->next; - } else { - aux = context_list; - while ( aux->next != cxitem ) aux = aux->next; - aux->next = cxitem->next; - } - free(cxitem); -} - -/* later the object list should be bind to JS Context - in this case is needed to update destructor PerlFreeObjectList - */ - -/* property getter and setter - cooperate with AUTOLOAD */ - -static JSBool -PCB_GetProperty(JSContext *cx, JSObject *obj, jsval name, jsval *rval) { - PerlObjectItem *po; - int i, cnt, len; - I32 ax; - SV *proc_sv; - HV *stash; - char prop_name[256]; - char full_name[256]; - char *foo; - GV *gv; - dSP; - - /* property name */ - strcpy(prop_name, JS_GetStringBytes(JSVAL_TO_STRING(name))); - - if (! (po = PCB_FindObject(cx, obj))) - croak("Couldn't find stub for object"); - if ( (PCB_FindCallback(po, prop_name))) - return(JS_TRUE); - - stash = SvSTASH(SvRV(po->pObject)); - /* strcpy(full_name, HvNAME(stash)); - strcat(full_name, "::"); - strcat(full_name, prop_name); - - proc_sv = sv_newmortal(); - sv_setpv(proc_sv, full_name); */ - /* start of perl call stuff */ - - gv = gv_fetchmeth(stash, prop_name, strlen(prop_name), -1); - /* better check and error report should be done here */ - if (!gv) return JS_FALSE; - - ENTER; - SAVETMPS; - PUSHMARK(SP); - XPUSHs(po->pObject); /* self for perl AUTOLOAD */ - PUTBACK; - - /* cnt = perl_call_sv(proc_sv, 0); */ - cnt = perl_call_sv((SV*)GvCV(gv), G_ARRAY); - - SPAGAIN; - /* adjust stack for use of ST macro (see perlcall) */ - SP -= cnt; - ax = (SP - PL_stack_base) + 1; - - /* read value(s) */ - if (cnt == 1) { - SVToJSVAL(cx, obj, ST(0), rval); - } else { - JSObject *jsarr; - jsval val; - int i; - jsarr = JS_NewArrayObject(cx, 0, NULL); - for (i = 0; i < cnt; i++) { - SVToJSVAL(cx, JS_GetGlobalObject(cx), ST(i), &val); - JS_DefineElement(cx, jsarr, i, val, NULL, NULL, 0); - } - *rval = OBJECT_TO_JSVAL(jsarr); - } - PUTBACK; - - FREETMPS; - LEAVE; - - return(JS_TRUE); -} - -static JSBool -PCB_SetProperty(JSContext *cx, JSObject *obj, jsval name, jsval *rval) { - PerlObjectItem *po; - int i, cnt, len; - I32 ax; - SV *proc_sv, *value_sv; - HV *stash; - char prop_name[256]; - char full_name[256]; - char *foo; - dSP; - - /* property name */ - strcpy(prop_name, JS_GetStringBytes(JSVAL_TO_STRING(name))); - - if (! (po = PCB_FindObject(cx, obj))) - croak("Couldn't find stub for object"); - if ( (PCB_FindCallback(po, prop_name))) - return(JS_TRUE); - - stash = SvSTASH(SvRV(po->pObject)); - strcpy(full_name, HvNAME(stash)); - strcat(full_name, "::"); - strcat(full_name, prop_name); - - proc_sv = sv_newmortal(); - sv_setpv(proc_sv, full_name); - JSVALToSV(cx, obj, *rval, &value_sv); - /* start of perl call stuff */ - ENTER; - SAVETMPS; - PUSHMARK(SP); - XPUSHs(po->pObject); /* self for perl AUTOLOAD */ - XPUSHs(value_sv); - PUTBACK; - - cnt = perl_call_sv(proc_sv, G_ARRAY); - - SPAGAIN; - /* adjust stack for use of ST macro (see perlcall) */ - SP -= cnt; - ax = (SP - PL_stack_base) + 1; - - /* read value(s) */ - if (cnt == 1) { - SVToJSVAL(cx, obj, ST(0), rval); - } else { - JSObject *jsarr; - jsval val; - int i; - jsarr = JS_NewArrayObject(cx, 0, NULL); - for (i = 0; i < cnt; i++) { - SVToJSVAL(cx, JS_GetGlobalObject(cx), ST(i), &val); - JS_DefineElement(cx, jsarr, i, val, NULL, NULL, 0); - } - *rval = OBJECT_TO_JSVAL(jsarr); - } - PUTBACK; - - FREETMPS; - LEAVE; - - return(JS_TRUE); -} - -/* helper functions */ -/* JSClass pointer is disposed by - JS engine during context cleanup _PH_ - */ -void -PCB_FinalizeStub(JSContext *cx, JSObject *obj) { -} - -static JSClass* -PCB_NewStdJSClass(char *name) { - JSClass *class; - - class = (JSClass*)calloc(1, sizeof(JSClass)); - class->name = name; - class->flags = JSCLASS_HAS_PRIVATE; - class->addProperty = JS_PropertyStub; - class->delProperty = JS_PropertyStub; - class->getProperty = PCB_GetProperty; - class->setProperty = PCB_SetProperty; - class->enumerate = JS_EnumerateStub; - class->resolve = JS_ResolveStub; - class->convert = JS_ConvertStub; - //class->finalize = JS_FinalizeStub; - class->finalize = PCB_FinalizeStub; - return(class); -} - -static JSBool -PCB_UniversalStub (JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval) { - JSFunction *fun; - PerlObjectItem *po; - PerlCallbackItem *cbk; - int i, cnt; - I32 ax; - SV* sv; - dSP; - - fun = JS_ValueToFunction(cx, argv[-2]); - if (! (po = PCB_FindObject(cx, obj))) - croak("Couldn't find stub for object"); - if (! (cbk = PCB_FindCallback(po, JS_GetFunctionName(fun)))) - croak("Couldn't find perl callback"); - /* start of perl call stuff */ - ENTER; - SAVETMPS; - PUSHMARK(SP); - XPUSHs(po->pObject); /* self for perl object method */ - for (i = 0; i < argc; i++) { - JSVALToSV(cx, obj, argv[i], &sv); - XPUSHs(sv); - } - PUTBACK; - cnt = perl_call_sv(SvRV(cbk->perl_proc), G_ARRAY | G_KEEPERR | G_EVAL); - - SPAGAIN; - /* adjust stack for use of ST macro (see perlcall) */ - SP -= cnt; - ax = (SP - PL_stack_base) + 1; - - /* read value(s) */ - if (cnt == 1) { - SVToJSVAL(cx, obj, ST(0), rval); - } else { - JSObject *jsarr; - jsval val; - int i; - jsarr = JS_NewArrayObject(cx, 0, NULL); - for (i = 0; i < cnt; i++) { - SVToJSVAL(cx, JS_GetGlobalObject(cx), ST(i), &val); - JS_DefineElement(cx, jsarr, i, val, NULL, NULL, 0); - } - *rval = OBJECT_TO_JSVAL(jsarr); - } - - PUTBACK; - FREETMPS; - LEAVE; - - /* this solution is not perfect, but usefull when nested call happens */ - return(checkError(cx) && !JS_IsExceptionPending(cx)); -}; - -/* __PH__END */ - - -/* Helper functions needed for most JS API routines */ -/* -static JSRuntime * -getRuntime() -{ - return (JSRuntime *)SvIV((SV*)SvRV(perl_get_sv("JS::Runtime::rt", FALSE))); -} - -static JSContext * -getContext() -{ - return (JSContext *)SvIV((SV*)SvRV(perl_get_sv("JS::Context::this", FALSE))); -} - */ /* commented as obsolete by __PH__ */ - -/* - The following packages are defined below: - JS -- main container for all JS functionality - JS::Runtime -- wrapper around JSRuntime * - JS::Context -- wrapper around JSContext * - JS::Object -- wrapper around JSObject * - */ - -MODULE = JS PACKAGE = JS PREFIX = JS_ -PROTOTYPES: DISABLE - # package JS - - # Most of the functions below have names coinsiding with those of the - # corresponding JS API functions. Thus, they are not commented. -JSRuntime * -JS_NewRuntime(maxbytes) - int maxbytes - OUTPUT: - RETVAL - -void -JS_DestroyRuntime(rt) - JSRuntime *rt - CODE: - /* - Make sure that the reference count to the runtime is zero. - O.w. this sequence of commands will cause double-deallocation: - $rt = new JS::Runtime(10_000); - $rt1 = $rt; - [exit here] - So both $rt->DESTROY and $rt1->DESTROY will cause runtime destruction. - - _PH_ That's not true, I guess. At least for Perl 5. - */ - /* warn("===> before runtime check\n"); */ - if(SvREFCNT(ST(0)) == 1){ - /* warn("===> really runtime destroing"); */ - /* __PH__ */ - /*__PH__END */ - JS_DestroyRuntime(rt); - } - - - # package JS::Runtime -MODULE = JS PACKAGE = JS::Runtime PREFIX = JS_ - -int -JS_NewContext(rt, stacksize) - JSRuntime *rt - int stacksize - PREINIT: - JSContextItem *cxitem; - CODE: - { - JSObject *obj; - /* jsval v; comment out unused var __PH__*/ - JSContext *cx; - cx = JS_NewContext(rt, stacksize); - cxitem = PCB_NewContextItem(); - cxitem->cx = cx; - cxitem->next = context_list; - context_list = cxitem; - /* __PH__ set the error reporter */ - JS_SetErrorReporter(cx, PCB_ErrorReporter); - obj = JS_NewObject(cx, &global_class, NULL, NULL); - JS_SetGlobalObject(cx, obj); - JS_InitStandardClasses(cx, obj); - RETVAL = (int)cx; - } - OUTPUT: - RETVAL - -void -JS_DestroyContext(cx) - JSContext *cx - CODE: - /* See the comment about ref. count above */ - /* warn("===> before context check\n"); */ - if(SvREFCNT(ST(0)) == 1){ - /* warn("===> really destroing context"); */ - if (JS_IsExceptionPending(cx)) { - JS_ClearPendingException(cx); - } - JS_SetErrorReporter(cx, NULL); - JS_GC(cx); //important - JS_DestroyContext(cx); - PCB_FreeContextItem(cx); - } - - - # package JS::Context -MODULE = JS PACKAGE = JS::Context PREFIX = JS_ - -jsval -JS_eval(cx, bytes, ...) - JSContext *cx - char *bytes - PREINIT: - JSContextItem *cxitem; - char *filename = NULL; - CODE: - { - jsval rval; - if (items > 2) { filename = SvPV(ST(2), PL_na); }; - /* Call on the global object */ - if(!JS_EvaluateScript(cx, JS_GetGlobalObject(cx), - bytes, strlen(bytes), - filename ? filename : "Perl", - 0, &rval)){ - cxitem = PCB_FindContextItem(cx); - if (!cxitem || cxitem->dieFromErrors) - croak("JS script evaluation failed"); - - clearException(cx); - XSRETURN_UNDEF; - } - RETVAL = rval; - } - clearException(cx); - OUTPUT: - RETVAL - - -jsval -JS_exec_(cx, script) - JSContext *cx - SV *script - PREINIT: - JSContextItem *cxitem; - JSScript *handle; - CODE: - { - jsval rval; - handle = (JSScript*)SvIV(*hv_fetch((HV*)SvRV(script), "_script", 7, 0)); - /* Call on the global object */ - if(!JS_ExecuteScript(cx, JS_GetGlobalObject(cx), - handle, &rval)) { - cxitem = PCB_FindContextItem(cx); - if (!cxitem || cxitem->dieFromErrors) - croak("JS script evaluation failed"); - - clearException(cx); - XSRETURN_UNDEF; - } - clearException(cx); - RETVAL = rval; - } - OUTPUT: - RETVAL - -#void -#JS_destroyScript(cx, script) -# JSContext *cx -# JSScript *script -# CODE: -# JS_DestroyScript(cx, script); - -# __PH__ -void -JS_setErrorReporter(cx, reporter) - JSContext *cx - SV* reporter - PREINIT: - JSContextItem *cxitem; - CODE: - cxitem = PCB_FindContextItem(cx); - SvREFCNT_inc(reporter); - if ( cxitem ) cxitem->errorReporter = reporter; - -void -JS_unsetErrorReporter(cx) - JSContext *cx - PREINIT: - JSContextItem *cxitem; - CODE: - cxitem = PCB_FindContextItem(cx); - if ( cxitem ) { - if ( cxitem->errorReporter ) - SvREFCNT_dec(cxitem->errorReporter); - cxitem->errorReporter = NULL; - } - -int -JS_hasException(cx) - JSContext *cx - CODE: - RETVAL = ! JS_IsExceptionPending(cx); - OUTPUT: - RETVAL - -void -JS_reportError(cx, msg) - JSContext *cx - char *msg - CODE: - JS_ReportError(cx, msg); - -void -JS_errorFromPrivate(cx, msg, ex) - JSContext *cx - char *msg - JSObject *ex - PREINIT: - JSErrorReport *rep; - CODE: - rep = (JSErrorReport*) JS_GetPrivate(cx, ex); - if (rep) - PCB_ErrorReporter(cx, msg, ((JSExnPrivate*)rep)->errorReport); - -void -JS_setDieFromErrors(cx, value) - JSContext *cx - int value - PREINIT: - JSContextItem *cxitem; - CODE: - cxitem = PCB_FindContextItem(cx); - if ( cxitem ) cxitem->dieFromErrors = value; - -void -JS_createObject(cx, object, name, methods) - JSContext *cx - SV *object - char *name - SV *methods - PREINIT: - JSObject *jso; - HV *m_hash; - I32 len; - HE *he; - int i; - PerlObjectItem *po; - JSClass *object_class; - PerlCallbackItem *pcbitem; - CODE: - if (SvTYPE(SvRV(methods)) != SVt_PVHV) { - croak("Second parameter has to be HASHREF"); - } - /* create js object in given context */ - object_class = PCB_NewStdJSClass(name); - //jso = JS_NewObject(cx, object_class, NULL, 0); - - jso = JS_DefineObject(cx, JS_GetGlobalObject(cx), name, - object_class, NULL, - JSPROP_ENUMERATE | JSPROP_READONLY | - JSPROP_PERMANENT); - - - if (!jso) croak("Unable create JS object"); - /* create callback info */ - po = PCB_AddObject(name, object, cx, jso, object_class); - m_hash = (HV*)SvRV(methods); - hv_iterinit(m_hash); - while ((he = hv_iternext(m_hash))) { - PCB_AddCallback(po, hv_iterkey(he, &len), hv_iterval(m_hash, he), 0); - } - /* set js object methods */ - /* HERE _PH_ */ - pcbitem = po->vector; - while ( pcbitem ) { - if (! JS_DefineFunction(cx, jso, pcbitem->name, - PCB_UniversalStub, 0, 0)) - croak("Unable create JS function"); - pcbitem = pcbitem->next; - } - -# __PH__END - - - # package JS::Object -MODULE = JS PACKAGE = JS::Object PREFIX = JS_ - - # - # The methods below get used when hash is tied. - # -SV * -JS_TIEHASH(class, obj) - char *class - SV *obj - PREINIT: - JSContext* cx; - CODE: - RETVAL = SvREFCNT_inc(obj); - OUTPUT: - RETVAL - -SV * -JS_TIEARRAY(class, obj) - char *class - SV *obj - PREINIT: - JSContext* cx; - CODE: - RETVAL = SvREFCNT_inc(obj); - OUTPUT: - RETVAL - -jsval -JS_FETCH(obj, key) - JSObject *obj - char *key - PREINIT: - JSContext* cx; - jsval rval; - MAGIC *magic; - CODE: - { - /* printf("+++++++++> FETCH\n"); */ - magic = mg_find(SvRV(ST(0)), '~'); - if (magic) { - cx = (JSContext *)SvIV(magic->mg_obj); - } else { - warn("Tied object has no magic\n"); - } - JS_GetProperty(cx, obj, key, &rval); - RETVAL = rval; - } - OUTPUT: - RETVAL - -int -JS_FETCHSIZE(obj) - JSObject *obj - PREINIT: - JSContext* cx; - MAGIC *magic; - CODE: - { - /* printf("+++++++++> FETCHSIZE: %d\n", ST(0)); */ - magic = mg_find(SvRV(ST(0)), '~'); - if (magic) { - cx = (JSContext *)SvIV(magic->mg_obj); - } else { - warn("Tied object has no magic\n"); - } - JS_IsArrayObject(cx, obj); - JS_GetArrayLength(cx, obj, &RETVAL); - } - OUTPUT: - RETVAL - -void -JS_STORE(obj, key, value) - JSObject *obj - char *key - jsval value - PREINIT: - JSContext* cx; - MAGIC *magic; - { - /* printf("+++++++++> STORE\n"); */ - magic = mg_find(SvRV(ST(0)), '~'); - if (magic) { - cx = (JSContext *)SvIV(magic->mg_obj); - } else { - warn("Tied object has no magic\n"); - } - } - CODE: - { - JS_SetProperty(cx, obj, key, &value); - } - -void -JS_DELETE(obj, key) - JSObject *obj - char *key - PREINIT: - JSContext* cx; - MAGIC *magic; - CODE: - { - /* printf("+++++++++> DELETE\n"); */ - magic = mg_find(SvRV(ST(0)), '~'); - if (magic) { - cx = (JSContext *)SvIV(magic->mg_obj); - } else { - warn("Tied object has no magic\n"); - } - JS_DeleteProperty(cx, obj, key); - } - -void -JS_CLEAR(obj) - JSObject *obj - PREINIT: - JSContext* cx; - MAGIC *magic; - CODE: - { - /* printf("+++++++++> CLEAR\n"); */ - magic = mg_find(SvRV(ST(0)), '~'); - if (magic) { - cx = (JSContext *)SvIV(magic->mg_obj); - } else { - warn("Tied object has no magic\n"); - } - JS_ClearScope(cx, obj); - } - -int -JS_EXISTS(obj, key) - JSObject *obj - char *key - PREINIT: - JSContext* cx; - MAGIC *magic; - CODE: - { - jsval v; - /* printf("+++++++++> EXISTS\n"); */ - magic = mg_find(SvRV(ST(0)), '~'); - if (magic) { - cx = (JSContext *)SvIV(magic->mg_obj); - } else { - warn("Tied object has no magic\n"); - } - JS_LookupProperty(cx, obj, key, &v); - RETVAL = !JSVAL_IS_VOID(v); - } - OUTPUT: - RETVAL - -#script -MODULE = JS PACKAGE = JS::Script PREFIX = JS_ - -int -JS_compileScript(object, cx, bytes, ...) - SV *object - JSContext *cx - char *bytes - PREINIT: - JSContextItem *cxitem; - char *filename = NULL; - CODE: - { - if (items > 2) { filename = SvPV(ST(2), PL_na); }; - /* Call on the global object */ - if(!(RETVAL = (int)JS_CompileScript(cx, JS_GetGlobalObject(cx), - bytes, strlen(bytes), - filename ? filename : "Perl", - 0))) - { - cxitem = PCB_FindContextItem(cx); - if (!cxitem || cxitem->dieFromErrors) - croak("JS script compilation failed"); - XSRETURN_UNDEF; - } - } - OUTPUT: - RETVAL - -int -JS_rootScript(object, cx, name) - SV *object - JSContext *cx - char *name - PREINIT: - JSObject **scrobj; - JSScript *handle; - CODE: - handle = (JSScript*)SvIV(*hv_fetch((HV*)SvRV(object), "_script", 7, 0)); - scrobj = malloc(sizeof(JSObject*)); - *scrobj = JS_NewScriptObject(cx, handle); - JS_AddNamedRoot(cx, scrobj, name); - RETVAL = (int)scrobj; - OUTPUT: - RETVAL - -void -JS_destroyScript(object, cx) - SV *object - JSContext *cx - PREINIT: - JSObject **scrobj; - JSScript *handle; - CODE: - handle = (JSScript*)SvIV(*hv_fetch((HV*)SvRV(object), "_script", 7, 0)); - scrobj = (JSObject**)SvIV(*hv_fetch((HV*)SvRV(object), "_root", 5, 0)); - JS_RemoveRoot(cx, scrobj); - diff --git a/lib/javascript/perlconnect/Makefile.PL b/lib/javascript/perlconnect/Makefile.PL deleted file mode 100644 index 66b32876..00000000 --- a/lib/javascript/perlconnect/Makefile.PL +++ /dev/null @@ -1,67 +0,0 @@ -use ExtUtils::MakeMaker; - -use strict; -use Getopt::Std; - -my (%foo, $jsdir, $inc, $libpath); - -#m - build under mozilla tree -#d - specifies js build directory (with include/ and lib/ directories) -#c - build under charlie tree -getopts('mcd:', \%foo); - -$jsdir = $foo{d}; - -$foo{'m'} = 1 unless $foo{c} || $foo{d}; #mozilla tree is the default - -if ($foo{c}) { - $inc = "-I$ENV{CHARLIE_HOME}/include"; - $libpath = "-L$ENV{CHARLIE_HOME}/lib"; -} - -if ($jsdir) { - $inc = "-I$jsdir/include"; - $libpath = "-L$jsdir/lib -ljs"; -} - -my $tmpmk = <<'eof'; -DEPTH=.. -include ../config.mk - -all: - @echo '$(OBJDIR)' -eof - -if ($foo{'m'}) { - if ($^O eq "MSWin32") { - $inc = "-I.. -I../Debug"; #I'm not sure - $libpath = "-L../Debug"; - } else { #suppose unix, never Mac, gmake - open FOO, ">tempmakefile"; - print FOO $tmpmk; - close FOO; - my $objdir = `gmake -f tempmakefile`; - unlink "tempmakefile"; - $inc = "-I.. -I../$objdir"; - $libpath = "-L../$objdir"; - } -} - -my %extras = (); -my $define; - -if ($^O eq "MSWin32") { - $define = "-DXP_PC"; - $extras{OBJECT} = '$(BASEEXT)$(OBJ_EXT) jsperl.obj'; -} else { - $define = '-DXP_UNIX'; -} - -WriteMakefile(NAME => 'JS', - DEFINE => $define, - INC => $inc, - LIBS => "$libpath -ljs", - VERSION_FROM => 'JS.pm', - %extras,); - -__END__ diff --git a/lib/javascript/perlconnect/Makefile.ref b/lib/javascript/perlconnect/Makefile.ref deleted file mode 100644 index b99681b1..00000000 --- a/lib/javascript/perlconnect/Makefile.ref +++ /dev/null @@ -1,152 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1999 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Makefile for the perlconnect extension to javascript. -# - -# -# Stolen with apologies to liveconnect. -# - -DEPTH = .. - -# -# XCFLAGS may be set in the environment or on the gmake command line -# -CC = cc - -CFLAGS += $(OPTIMIZER) $(OS_CFLAGS) $(DEFINES) $(INCLUDES) \ - -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DX86_LINUX \ - -DDEBUG -DDEBUG_livshits -Dbool=char -DHAS_BOOL -DGCC_OPT_BUG -D_XOPEN_SOURCE - -# -DJSFILE $(XCFLAGS)\ -# -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DX86_LINUX - - -LDFLAGS += -lm $(XLDFLAGS) - -# -# Ask perl what flags it was built with, so we can build js with similar flags -# and link properly. Viva gmake. -# -PERLCFLAGS := $(shell perl -MExtUtils::Embed -e ccopts) -PERLLDFLAGS := $(shell perl -MExtUtils::Embed -e ldopts) - -# perl erroneously reports compiler flag -rdynamic (interpreted by ld -# as -r) when it really meant -export-dynamic. -PERLLDFLAGS := $(subst -rdynamic,-export-dynamic,$(PERLLDFLAGS)) - -CFLAGS += $(PERLCFLAGS) -LDFLAGS += $(PERLLDFLAGS) - - -# For purify -PURE_CFLAGS = -DXP_UNIX $(OPTIMIZER) $(PURE_OS_CFLAGS) $(DEFINES) \ - $(INCLUDES) $(XCFLAGS) - -# -# perlconnect file lists -# -PC_HFILES = \ - jsperl.h \ - $(NULL) - -HFILES = $(PC_HFILES) - -PC_CFILES = \ - jsperl.c \ - JS.c \ - $(NULL) - -#JS.c: JS.xs typemap -# perl jsperlbuild.pl - -LIB_CFILES = $(PC_CFILES) - -PROG_FILE = js - -include $(DEPTH)/config.mk - -# uncomment this if we decide we need a local config dir... -#include config/$(OS_CONFIG).mk - -INCLUDES += -I. -I.. -I../$(OBJDIR) - -ifdef USE_MSVC -OTHER_LIBS += $(DEPTH)/fdlibm/$(OBJDIR)/fdlibm.lib -else -OTHER_LIBS += -L$(DEPTH)/fdlibm/$(OBJDIR) -lfdm -endif - -ifdef JS_THREADSAFE -ifdef USE_MSVC -OTHER_LIBS += $(DEPTH)/../../dist/$(OBJDIR)/lib/nspr3.lib -else -OTHER_LIBS += -L$(DEPTH)/../../dist/$(OBJDIR)/lib -lnspr3 -endif -endif - -ifdef USE_MSVC -LIBRARY = $(OBJDIR)/JS.lib -SHARED_LIBRARY = $(OBJDIR)/JS.dll -PROGRAM = $(OBJDIR)/jsperl.exe -else -LIBRARY = $(OBJDIR)/JS.a -SHARED_LIBRARY = $(OBJDIR)/JS.so -PROGRAM = $(OBJDIR)/jsperl -endif - -include $(DEPTH)/rules.mk - -ifdef USE_MSVC -$(OBJDIR)/$(PROG_FILE)_lc.obj: ../$(PROG_FILE).c - @$(MAKE_OBJDIR) - $(CC) -Fo$@ -c $(CFLAGS) -DPERLCONNECT ../$(PROG_FILE).c - -$(PROGRAM): $(OBJDIR)/$(PROG_FILE)_lc.obj $(LIBRARY) - link.exe -out:"$@" /pdb:"$(OBJDIR)/$(@F:.exe=.pdb)" $(EXE_LINK_FLAGS) ../$(OBJDIR)/js32.lib $? -else -$(OBJDIR)/$(PROG_FILE).o: ../$(PROG_FILE).c - @$(MAKE_OBJDIR) - $(CC) -o $@ -c $(CFLAGS) -DPERLCONNECT ../$(PROG_FILE).c - -$(PROGRAM): $(OBJDIR)/$(PROG_FILE).o - @$(MAKE_OBJDIR) - $(CC) -o $@ $(CFLAGS) $+ $(LIBRARY) ../$(OBJDIR)/libjs.a $(LDFLAGS) $(OTHER_LIBS) -endif diff --git a/lib/javascript/perlconnect/PerlConnect.dsp b/lib/javascript/perlconnect/PerlConnect.dsp deleted file mode 100644 index 8f1c7a70..00000000 --- a/lib/javascript/perlconnect/PerlConnect.dsp +++ /dev/null @@ -1,103 +0,0 @@ -# Microsoft Developer Studio Project File - Name="PerlConnect" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 - -CFG=PerlConnect - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "PerlConnect.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "PerlConnect.mak" CFG="PerlConnect - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "PerlConnect - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "PerlConnect - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -MTL=midl.exe -RSC=rc.exe - -!IF "$(CFG)" == "PerlConnect - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c -# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c -# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 - -!ELSEIF "$(CFG)" == "PerlConnect - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "d:\opc\ns\js\ref" /I "$(PERL_SRC)" /I "$(PERL_SRC)\win32" /I "$(PERL_SRC)\win32\include" /I "." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "PERLCONNECT" /D "JSFILE" /D "XP_PC" /FR /YX /FD /c -# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept -# ADD LINK32 js32.lib perl.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /subsystem:windows /dll /pdb:none /debug /machine:I386 /out:"C:\DLLs\PerlConnect.dll " /implib:"PerlConnect.lib" /libpath:"d:\opc\ns\js\ref\Debug" /libpath:"$(PERL_SRC)" -# SUBTRACT LINK32 /verbose - -!ENDIF - -# Begin Target - -# Name "PerlConnect - Win32 Release" -# Name "PerlConnect - Win32 Debug" -# Begin Source File - -SOURCE=.\jsperl.c -# End Source File -# Begin Source File - -SOURCE=.\jsperl.h -# End Source File -# Begin Source File - -SOURCE=.\jsperlpvt.h -# End Source File -# End Target -# End Project diff --git a/lib/javascript/perlconnect/PerlConnect.dsw b/lib/javascript/perlconnect/PerlConnect.dsw deleted file mode 100644 index 86b2c1f6..00000000 --- a/lib/javascript/perlconnect/PerlConnect.dsw +++ /dev/null @@ -1,59 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "JS"=.\JS.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name PerlConnect - End Project Dependency -}}} - -############################################################################### - -Project: "PerlConnect"=.\PerlConnect.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "PerlConnectShell"=.\PerlConnectShell.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name PerlConnect - End Project Dependency -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/lib/javascript/perlconnect/PerlConnect.pm b/lib/javascript/perlconnect/PerlConnect.pm deleted file mode 100644 index 8e22d99d..00000000 --- a/lib/javascript/perlconnect/PerlConnect.pm +++ /dev/null @@ -1,126 +0,0 @@ -############################################################################ -# PerlConnect support package. 8/3/98 2:50PM -# This packages implements private methods called from jsperl.c -# Please don't try to include in from Perl -# See README.html and JS.xs for information about this module. -############################################################################ - -package JS; -require Exporter; -require DynaLoader; -@ISA = qw(Exporter DynaLoader); -@EXPORT_OK = qw(perl_eval perl_resolve perl_call $js $ver); - -# version string for the interpreter -$ver = "[Perl Interpreter: Version $] compiled under $^O]\n"; -$DEBUG = undef; - -############################################################################ -# TODO: This will be added -############################################################################ -sub AUTOLOAD #7/28/98 8:24PM -{ - print "\nJS::AUTOLOAD: $AUTOLOAD, not implemented yet\n" if $DEBUG; -} ##AUTOLOAD - -############################################################################ -# Evaluates the parameter and returns the return result of eval() as a -# reference -############################################################################ -sub perl_eval #7/15/98 5:13PM -{ - my($stmt) = shift; - package main; - my(@_js) = eval($stmt); - package JS; - my($_js) = (scalar(@_js)==1)?$_js[0]:\@_js; - undef $js; - $js = (ref $_js) ? $_js: \$_js; - print "Failure in perl_call!" unless ref $js; -} ##perl_eval - -############################################################################ -# Calls the procesure passed as the first parameter and passes the rest of -# the arguments to it. The return result is converted to a reference as -# before -############################################################################ -sub perl_call #7/21/98 2:16PM -{ - my($proc) = shift; - my($_js); - - $proc =~ s/main:://g; - #print "Calling $proc\n"; - package main; - my(@_js) = &$proc(@_); - package JS; - #print "here: ", @_js, "\n"; - $_js = (scalar(@_js)==1)?$_js[0]:\@_js; - undef $js; - $js = (ref $_js) ? $_js: \$_js; - #print ref $js; - print "Failure in perl_call!" unless ref $js; -} ##perl_call - -############################################################################ -# Takes the first parameter and tries to retrieve this variable -############################################################################ -sub perl_resolve #7/22/98 10:08AM -{ - my($name) = shift; - my(@parts) = split('::', $name); - my($last_part) = pop(@parts); - - # variable lookup -- variables must start with $, @, or % - if($last_part =~ /^([\$\@\%])(.+)/){ - my($resolved_name) = "$1".join('::', @parts)."::$2"; - package main; - my(@_js) = eval($resolved_name); - package JS; - my($_js) = (scalar(@_js)==1)?$_js[0]:\@_js; - undef $js; - $js = (ref $_js) ? $_js: \$_js; - }else{ - $name =~ s/main:://g; - # if this function exists - # function -- set $js to 1 to indicate this - if(eval "return defined(&main::$name)"){ - print "function $name\n" if $DEBUG; - $js = 1; - # module - }else{ - print "must be a module\n" if $DEBUG; - $js=2; - return; - # defined module -- try to do an eval and check $@ to trap errors - # as a result, the module is automatically pre-use'd if it exists - $name =~ s/main:://g; - if(eval "use $name; return !(defined($@));"){ - $js = 2; - # o.w. this module is undefined - }else{ - $js = 3; - } - } - } -} ##perl_resolve - -############################################################################ -# Validates package name -############################################################################ -sub perl_validate_package #7/22/98 10:15AM -{ - print "perl_validate_package\n" if $DEBUG; - my($name) = shift; - print $name if $DEBUG; - $js = $name?1:undef; -} ##perl_validate_package - -# test procedure -sub c{ - print "da!\n" if wantarray; - print "Called!\n"; - return @_; -} - -1; \ No newline at end of file diff --git a/lib/javascript/perlconnect/PerlConnectShell.dsp b/lib/javascript/perlconnect/PerlConnectShell.dsp deleted file mode 100644 index 4e1add88..00000000 --- a/lib/javascript/perlconnect/PerlConnectShell.dsp +++ /dev/null @@ -1,89 +0,0 @@ -# Microsoft Developer Studio Project File - Name="PerlConnectShell" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=PerlConnectShell - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "PerlConnectShell.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "PerlConnectShell.mak" CFG="PerlConnectShell - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "PerlConnectShell - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "PerlConnectShell - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "PerlConnectShell - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 - -!ELSEIF "$(CFG)" == "PerlConnectShell - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "D:\OPC\ns\js\ref" /I "D:\OPC\ns\js\ref\perlconnect" /I "$(PERL_SRC)" /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "PERLCONNECT" /D "JSFILE" /D "_WIN32" /D "XP_PC" /Fr /YX /FD /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 js32.lib PerlConnect.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"PerlConnectShell.exe" /pdbtype:sept /libpath:"..\Debug" /libpath:"$(PERL_SRC)" - -!ENDIF - -# Begin Target - -# Name "PerlConnectShell - Win32 Release" -# Name "PerlConnectShell - Win32 Debug" -# Begin Source File - -SOURCE=..\js.c -# End Source File -# End Target -# End Project diff --git a/lib/javascript/perlconnect/README.html b/lib/javascript/perlconnect/README.html deleted file mode 100644 index 5f8cc624..00000000 --- a/lib/javascript/perlconnect/README.html +++ /dev/null @@ -1,345 +0,0 @@ - - - - - - - PerlConnect Documentation - - - - -
    -

    -PERLCONNECT  AND  JS.PM

    - -
    USER-LEVEL DOCUMENTATION -
    Vladimir Livshits -
    -
    - -
      -
    1. -Update history
    2. - -
    3. -Overview
    4. - -
    5. -Features
    6. - -
    7. -Design
    8. - -
    9. -Installation
    10. - -
    11. -Current Limitations and Further Work
    12. -
    - -

    -Update History

    - -
      -
    • -3/8/99 -- added some more details, especially pertaining to PerlConnect.pm
    • - -
    • -8/98 -- this document created
    • -
    - -

    -Overview

    -PerlConnect provides glue for the developer between JavaScript and Perl. -It currently consists of two parts, PerlConnect implemented in C and JS.pm, -a Perl module written using XSUBs. PerlConnect and JS.pm allow calling -Perl from JS and JS from Perl, respectively. Whenever possible, it is attempted -to achieve the maximum level of transparency for calling one language -from the other. This is done by converting values between the two languages, -creating wrappers around objects, and emulating the standard language syntax. -

    -PerlConnect Features

    -PerlConnect allows running a Perl interpreter concurrently with your JavaScript -embedding and executing Perl commands from JavaScript. You usually need -to create a Perl interpreter by doing something like this: -
    p = new Perl('Sys::Hostname', 'Test::Harness')
    -In addition to creating an interpreter, this will also include the libraries -you pass to the Perl constructor, which is equivalent to use Sys::Hostname; -use Test::Harness. You can always include libraries explicitly by -using p.eval('use Sys::Hostname; use Test::Harness'). There is -also another way to do this: p.use('Sys::Hostname', 'Test::Harness'). -As you can see, TMTOWTDI. -

    Note: If the statements above fail on you saying something about -libraries not found in the search path, you need to make sure the modules -PerlConnect uses, JS.pm and PerlConnect.pm live in some directory accessible -from the search path. Search path can be set by adjusting the value of PERLLIB -and PERL5LIB environment variables. See  installation -for more details. -

    Note: Despite the illusion p = new Perl(...) syntax might create, -there is actually only one version of the Perl interpreter running. I.e. -if you create two interpreters like this: -

    p = new Perl; q = new Perl; -
    p.eval("$a='ha-'x20");
    -Now you'll see that q["$a"] will give you $a's value -from p. -

    Naturally, you will want to look at the result of your function calls -and eval statements. Suppose, you do something like this: -

    line = p.eval("'-' x 80")
    -Perl's eval returns the last statement evaluated, unless you explicitly -say return. So now line contains 80 dashes. You can do -similar things with non-scalar data types: -
    p.use('Time::gmtime'); -
    t = p.eval('Time::gmtime::gmtime')    // returns -[49,0,4,24,6,98,5,204,0]
    -assigns a Perl array to t. You can print t, use the for/in -syntax to walk through it, compute its length, etc. You can read and assign -to individual elements using the standard syntax. However, PerlValues, -that is, the value we get from Perl, don't support all the standard operations, -for instance, don't expect t.reverse() to work. Hashes can also -be returned from Perl: -
    info=p.eval("{ver=>$], pid=>$$}")
    -Now you can look at individual hash keys like this: -
    info["ver"] or info.pid
    -Suppose you want to use Perl to perform pattern-based string replacement. -Here's how you can do it from JavaScript: -
    p.eval("\ -
        sub perl_replace(){\ -
            my($string, $find, $replace) -= @_;\ -
            eval(\"\\$string =~ -s/$find/$replace/g;\");\ -
            return $string;\ -
        }" -
    );
    -and now -
    p.perl_replace('Quick brown fox jumped over a lazy dog', -'dog', 'rhino')
    -produces what you'd expect. -

    You can use the same syntax to call procedures defined in modules other -than main. The example with gmtime can be rewritten like -this: -

    p.use('Time::gmtime'); -
    t = p.Time.gmtime.gmtime()    // returns [49,0,4,24,6,98,5,204,0]
    - You can reference variables exported by modules other than main -like this: -
    a=p.Foo.$bar or a=p.Foo["$bar"] or -
    a=p.Foo["@bar"]or a=p.Foo["%bar"]
    -Each of the above statements return either an immediate JS value, for -scalar types, or a PerlValue for compound types. a.type contains -the type of the PerlValue in a. This may change because we -may end up separating Perl hashes and arrays into separate classes. -

    -JS.pm Features

    -JS.pm is much less tested then PerlConnect. You should be able to -do similar things from Perl. Just say -
    use JS; -
    $js = new JS();
    -and now you can do something like this: -
    $js->eval(q/ -
    Object o = {}; -
    o.a = 'p'; -
    o.b = 'q'; -
    return o;
    -/);
    -Note: Please see test.js and test.pl, test scripts that test and -demonstrate various features of PerlConnect and JS.pm, respectively. They -will help get you started. -

    -PerlConnect Design

    -PerlConnect is written in C. It uses both JavaScript and Perl APIs and -implements a mapping between the two. The following JavaScript objects -are implemented by PerlConnect: -
      -
    - - - - - - - - - - - - - - - - - - - - - - - -
    ObjectWhat it does
    PerlPerl Interpreter Object. Its prototype type -is PerlModule, it corresponds to main::. Supports eval, -call, -use.
    PerlModuleImplements JS-like syntax for Perl modules. Doesn't -export provide any methods. path property shows the name of the -Perl module the object represents.
    PerlValueRepresents a value returned from eval, -call, -or obtained by using the subscript notation (p.Foo["@bar"]). Its -Perl type is stored in the type property.
    - -

    See comments in the code, jsperl.c and JS.pm for more -info. -
    Note:  PerlConnect heavily relies on PerlConnect.pm, which -does some background magic for it. PerlConnect.pm should not be -used. Use JS.pm instead. -

    -JS.pm Design

    -JSConnect is written using XSUBs, the language in which Perl extensions -are implemented. See the output of man perlxs/perlguts/perlembed/perlxstut  -for more details. The source files are JS.xs and typemap. -After processing them using the XSUBs compiler, xsubpp, the resulting -C file should be compiled into a DLL. See JS.xs for more details -on how to to run the XSUBS compiler. You will need a sufficiently recent -version of Perl to run JS.pm successfully. JS.pm provides bootstrapping -mechanism to load this DLL. -

    The following Perl packages (objects) are implemented: -
      -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PackageWhat it contains
    JSDoesn't do anything in particular at this -point except defining a constructor. So one can say $js = new -JS(), which will create a new runtime, add a context to it and return -that Context. JS also defines a bunch of private functions called from -C by PerlConnect. They are not exposed by default, but pushed onto @EXPORT_OK -array instead.
    JS::RuntimeCorresponds to JSRuntime* struct. Provides -a constructor and destructor. The destructor is invoked automatically, -so you don't have to worry about Runtime deallocation. Constructor syntax -is the following: $rt = new JS::Runtime(10_000), where -the parameter is the same number you pass to JS_NewRuntime. There -are many private functions created in JS.xs that are not exported -by default.
    JS::ContextCorresponds to JSContext* struct. Provides -a constructor and destructor. The destructor is invoked automatically, -so you don't have to worry about Context deallocation. Constructor syntax -is the following: $rt = new JS::Context($rt, 1_000), where -the parameter is the same number you pass to JS_NewContext. There -are many private functions created in JS.xs that are not exported -by default.
    JS::ObjectCorresponds to JSObject* struct. There is not that much here -yet. This object is intended as a wrapper around the JSObject* struct. -Support for tying hashes and possibly arrays with JS::Objects -is coming.
    [JS::Array]I am not quite sure if this is needed. One might probably get away -with just JS::Object defined. If it's implemented, it will be -very much similar to JS::Object above.
    - -

    All the modules above follow the convention of storing the variable -they return in the $this variable of the current class. So $JS::Context::this -will always be the last context created. Currently, this is where JS -API function that require contexts get it. -

    -PerlConnect Installation

    -PerlConnect requires js/src and the Perl libraries and headers. -The only js/src file that must be included in jsapi.h in -the top level directory. You need to compile it together with Perl libraries. -Refer to the perlembed man page for more details. -
    On WINNT: -
    There are MSDEV Workspace and project files in the main PerlConnect -directory. There are three projects included in the PerlConnect workspace: -JS, PerlConnect and PerlConnectShell. You can use the latter to test PerlConnect. -You will probably need to adjust the library and include paths. Set PERL_SRC -environment variable to point to the directory where you unpacked and compiled -Perl sources. It is assumed that the directory structure is more or less -fixed, that is, you have PerlConnect in -js/src/perlconnect. PerlConnect -project produces PerlConnect.dll, you should make sure it and -perl.dll are in your path for PerlConnectShell to work. -

    JS also builds a DLL, JS.dll which is supposed to reside where -Perl's DynaLoader can find it. On my machine I put it under c:\perl\lib\auto\JS\JS.dll. -You can also put it in c:\perl\lib\. You can probably adjust PERLLIB -to achieve the desired result. See Perl's DynaLoader documentation for -more info on how dynamic libraries are found. -

    On UNIX: -
    We are currently working on a UNIX makefile. Please contact -me for more details. -

    -On the MAC:

    -We never really thought of supporting the Mac. If anyone is really interested -in seeing Mac support, drop me a line. -

    -Current Limitations and Further Work

    - -
      -
    1. -Perl variables currently can't be assigned to, that is, p["$a"]=100 -doesn't do anything.
    2. - -
    3. -You can only have one interpreter running at a time. Despite the fact that -you can create multiple Perl objects on JavaScript, they all share the -same namespace. We can probably use Safe.pm to implement independent -namespaces.
    4. - -
    5. -Module name resolution reports an error only when you try to evaluate -the last element of the resolution chain. Here is what I mean: if you reference -p.Foo.Bar.Var and For or Bar don't exist, it -will only complain that p.Foo.Bar.Var is not a valid variable. Perl 5.005 -provides exists Foo::{Bar::} to check if Foo::Bar is a valid package.
    6. - -
    7. -Dynamic loading of the Perl interpreter only if it is required.
    8. - -
    9. -Recursive printing of Perl's arrays and hashes can be added. See Data::Dumper.pm
    10. - -
    11. -Full support for tied hashes and arrays in Perl
    12. - -
    13. -Calling JavaScript functions and accessing variables from Perl. JavaScript -calling syntax support using AUTOLOADing.
    14. - -
    15. -JS can be made a directory with Object.pm, Context.pm, -etc. in it. See how C or Tk are organized on CPAN
    16. - -
    17. -Distribution model for JS.pm. Perl provides something by default. See h2xs -man page, for example.
    18. -
    - - - diff --git a/lib/javascript/perlconnect/bg.jpg b/lib/javascript/perlconnect/bg.jpg deleted file mode 100644 index ba8a02f6..00000000 Binary files a/lib/javascript/perlconnect/bg.jpg and /dev/null differ diff --git a/lib/javascript/perlconnect/jsperl.c b/lib/javascript/perlconnect/jsperl.c deleted file mode 100644 index f41dcad4..00000000 --- a/lib/javascript/perlconnect/jsperl.c +++ /dev/null @@ -1,1100 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * PerlConnect module. - */ - -/* - The first two headers are from the Perl distribution. - Play with "perl -MExtUtils::Embed -e ccopts -e ldopts" - to find out which directories should be included. Refer - to perlembed man page for more info. -*/ -#include "EXTERN.h" -#include "perl.h" -#include "XSUB.h" - -#include -#include - -/*---------------------------------------------------------------------------*/ -/* PerlConnect. Provides means for OO JS <==> Perl communications */ -/* See README.html for more info on PerlConnect. Look for TODO in this file */ -/* for things that are bogus or not completely implemented. Has been tested */ -/* with 5.004 only */ -/*---------------------------------------------------------------------------*/ - -/* Forward declarations */ -static JSBool PerlConstruct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *v); -static void PerlFinalize(JSContext *cx, JSObject *obj); -static JSBool perl_eval(JSContext *cx, JSObject *obj, int argc, jsval *argv, jsval* rval); -static JSBool perl_call(JSContext *cx, JSObject *obj, int argc, jsval *argv, jsval* rval); -static JSBool perl_use(JSContext *cx, JSObject *obj, int argc, jsval *argv, jsval* rval); -static JSBool use(JSContext *cx, JSObject *obj, int argc, jsval *argv, const char* t); -static JSBool PMGetProperty(JSContext *cx, JSObject *obj, jsval name, jsval* rval); -static JSBool PMSetProperty(JSContext *cx, JSObject *obj, jsval name, jsval *rval); -static JSBool PerlToString(JSContext *cx, JSObject *obj, int argc, jsval *argv, jsval* rval); -static JSBool processReturn(JSContext *cx, JSObject *obj, jsval* rval); -static JSBool checkError(JSContext *cx); -static JSBool PMToString(JSContext *cx, JSObject *obj, int argc, jsval *argv, jsval* rval); -static JSBool PVToString(JSContext *cx, JSObject *obj, int argc, jsval *argv, jsval* rval); -static SV* PVGetRef(JSContext *cx, JSObject *obj); -static JSBool PVGetProperty(JSContext *cx, JSObject *obj, jsval name, jsval *rval); -static JSBool PVSetProperty(JSContext *cx, JSObject *obj, jsval name, jsval *rval); -static JSBool PVGetElement(JSContext *cx, JSObject *obj, jsint index, jsval *rval); -static JSBool PVSetElement(JSContext *cx, JSObject *obj, jsint index, jsval v); -static JSBool PVGetKey(JSContext *cx, JSObject *obj, char* name, jsval *rval); -static JSBool PVSetKey(JSContext *cx, JSObject *obj, char* name, jsval v); -static JSBool PVConvert(JSContext *cx, JSObject *obj, JSType type, jsval *v); -static void PVFinalize(JSContext *cx, JSObject *obj); -/* Exported functions */ -JS_EXPORT_API(JSObject*) JS_InitPerlClass(JSContext *cx, JSObject *obj); -JS_EXPORT_API(JSBool) JSVALToSV(JSContext *cx, JSObject *obj, jsval v, SV** sv); -JS_EXPORT_API(JSBool) SVToJSVAL(JSContext *cx, JSObject *obj, SV *ref, jsval *rval); - -/* - The following is required by the Perl dynamic loading mechanism to - link with modules that use C properly. See perlembed man page for details. - This allows things like sockets to be called via PerlConnect. -*/ -#ifdef __cplusplus -# define EXTERN_C extern "C" -#else -# define EXTERN_C extern -#endif - -EXTERN_C void boot_DynaLoader _((CV* cv)); -EXTERN_C void -xs_init() -{ - newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, __FILE__); -} - -/* These properties are not processed by the getter for PerlValue */ -static char* predefined_methods[] = {"toString", "valueOf", "type", "length"}; - -/* Represents a perl interpreter */ -JSClass perlClass = { - "Perl", JSCLASS_HAS_PRIVATE, - JS_PropertyStub, JS_PropertyStub, PMGetProperty, /*PMSetProperty*/JS_PropertyStub, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, PerlFinalize -}; - -static JSFunctionSpec perlMethods[] = { - {"toString", (JSNative)PerlToString, 0,0,0}, - {"eval", (JSNative)perl_eval, 0,0,0}, - {"call", (JSNative)perl_call, 0,0,0}, - {"use", (JSNative)perl_use, 0,0,0}, - {NULL, NULL, 0,0,0} -}; - - -/* Represents a Perl module */ -JSClass perlModuleClass = { - "PerlModule", JSCLASS_HAS_PRIVATE, - JS_PropertyStub, JS_PropertyStub, PMGetProperty, JS_PropertyStub, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub -}; - -JSFunctionSpec perlModuleMethods[] = { - {"toString", (JSNative)PMToString, 0,0,0}, - {NULL, NULL, 0,0,0} -}; - - -/* Represents a value returned from Perl */ -JSClass perlValueClass = { - "PerlValue", JSCLASS_HAS_PRIVATE, - JS_PropertyStub, JS_PropertyStub, PVGetProperty, PVSetProperty, - JS_EnumerateStub, JS_ResolveStub, PVConvert, PVFinalize -}; - -JSFunctionSpec perlValueMethods[] = { - {"toString", (JSNative)PVToString, 0,0,0}, - {NULL, NULL, 0,0,0} -}; - -/* - Initializes Perl class. Should be called by applications that - want to enable PerlConnect. This will probably preload the Perl - DLL even though Perl might not actually be used. We may postpone - this and load the DLL at runtime after the constructor is called. -*/ -static JSObject* -js_InitPerlClass(JSContext *cx, JSObject *obj) -{ - jsval v; - JSObject *module; - JSString *mainString = JS_NewStringCopyZ(cx, "main"); - if (!mainString) - return NULL; - v = STRING_TO_JSVAL(mainString); - module = JS_NewObject(cx, &perlModuleClass, NULL, obj); - if (!module) - return NULL; - - if (!JS_DefineFunctions(cx, module, perlModuleMethods)) - return NULL; - - JS_SetProperty(cx, module, "path", &v); - - return JS_InitClass(cx, obj, module, &perlClass, PerlConstruct, 0, - NULL, NULL, NULL, NULL); -} - -/* Public wrapper for the function above */ -JSObject* -JS_InitPerlClass(JSContext *cx, JSObject *obj) -{ - return js_InitPerlClass(cx, obj); -} - -/* - Perl constructor. Allocates a new interpreter and defines methods on it. - The constructor is sort of bogus in that it doesn't create a new namespace - and all the variables defined in one instance of the Perl object will be - visible in others. In the future, I think it may be a good idea to use - Safe.pm to provide independent contexts for different Perl objects and - prohibit certain operations (like exit(), alarm(), die(), etc.). Or we - may simple disallow calling the constructor more than once. -*/ -static JSBool -PerlConstruct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *v) -{ - PerlInterpreter *perl; - JSObject *perlObject; - JSBool ok; - char *embedding[] = {"", "-e", "0"}; - char *t = "use PerlConnect qw(perl_eval perl_resolve perl_call $js $ver);"; - - /* create a new interpreter */ - perl = perl_alloc(); - - if(perl==NULL){ - JS_ReportError(cx, "Can't allocate a new interpreter"); - return JS_FALSE; - } - - perl_construct(perl); - if(perl_parse(perl, xs_init, 3, embedding, NULL)){ - JS_ReportError(cx, "Parsing failed"); - return JS_FALSE; - } - if(perl_run(perl)){ - JS_ReportError(cx, "Run failed"); - return JS_FALSE; - } - ok = use(cx, obj, argc, argv, t); - - /* make it into an object */ - perlObject = JS_NewObject(cx, &perlClass, NULL, NULL); - if(!perlObject) - return JS_FALSE; - if(!JS_DefineFunctions(cx, perlObject, perlMethods)) - return JS_FALSE; - JS_SetPrivate(cx, perlObject, perl); - *v = OBJECT_TO_JSVAL(perlObject); - return ok; -} - -/* Destructor. Deallocates the interpreter */ -static void -PerlFinalize(JSContext *cx, JSObject *obj) -{ - PerlInterpreter *perl = JS_GetPrivate(cx, obj); - if (perl) { - perl_destruct(perl); - perl_free(perl); - } - /* return JS_TRUE; */ -} - -/* - Returns a string representation of the Perl interpreter. - Can add printing of the Perl version, @ISA, etc., like the - output produced by perl -V. Can also make certain variables - available off the Perl object, like Perl.version, etc. -*/ -static JSBool -PerlToString(JSContext *cx, JSObject *obj, int argc, jsval *argv, jsval* rval){ - JSString *imported; - SV* sv = perl_get_sv("JS::ver", FALSE); - if (!sv) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - imported = JS_NewStringCopyZ(cx, SvPV(sv, PL_na)); - if (!imported) - return JS_FALSE; - *rval = STRING_TO_JSVAL(imported); - return JS_TRUE; -} - -/* - Evaluates the first parameter in Perl and put the eval's - return value into *rval. The return value is of type PerlValue. - This procedure uses JS::perl_eval. Example of use of perl.eval(): - p = new Perl(); - str = p.eval("'-' x 80"); // str contains 80 dashes -*/ -static JSBool -perl_eval(JSContext *cx, JSObject *obj, int argc, jsval *argv, jsval* rval) -{ - char *statement; - char *args[] = {NULL, NULL}; /* two elements */ - - if(argc!=1){ - JS_ReportError(cx, "Perl.eval expects one parameter"); - return JS_FALSE; - } - statement = JS_GetStringBytes(JS_ValueToString(cx, argv[0])); - - args[0] = statement; - perl_call_argv("JS::perl_eval", G_SCALAR|G_KEEPERR|G_EVAL, args); - return processReturn(cx, obj, rval); -} - -/* - Call the perl procedure specified as the first argument and - pass all the other arguments as parameters. The return value - is returned in *rval. Example of use of perl.call(): - p = new Perl('Time::gmtime'); - time = p.call("Time::gmtime::gmtime"); // time is now the following array: - // [40,42,1,22,6,98,3,202,0] - NB: The full function name has to be supplied, i.e. Time::gmtime::gmtime - instead of gmtime unless gmtime is exported into the current package. - - This method is also used when one uses the full package name syntax like - this: - p = new Perl("Sys::Hostname", "JS") - result = p.JS.c(1, 2, 4) - p.hostname() - - This gets called from PMGetProperty, which creates a - function whose native method is perl_call. Also see - JS::perl_call. -*/ -static JSBool -perl_call(JSContext *cx, JSObject *obj, int argc, jsval *argv, jsval* rval) -{ - JSBool ok; - int count, i; - char* fun_name; - SV *sv; - dSP; - - /* Differetiate between direct and method-like call */ - if((JS_TypeOfValue(cx, argv[-2]) == JSTYPE_FUNCTION) && - strcmp("call", JS_GetFunctionName(JS_ValueToFunction(cx, argv[-2])))){ - fun_name = (char*)JS_GetFunctionName(JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[-2]))); - i=0; - }else{ - fun_name = JS_GetStringBytes(JS_ValueToString(cx, argv[0])); - i=1; - } - - PUSHMARK(sp); - XPUSHs(sv_2mortal(newSVpv(fun_name,0))); - - for(;i - -static SV* -PVGetRef(JSContext *cx, JSObject *obj) -{ - SV* ref; - - ref = (SV*)JS_GetInstancePrivate(cx, obj, &perlValueClass, NULL); - - if(!ref || !SvOK(ref) || !SvROK(ref)){ - JS_ReportError(cx, "Can't extract ref"); - return NULL; - } - return ref; -} - -static JSBool -PVCallStub (JSContext *cx, JSObject *obj, uintN argc, - jsval *argv, jsval *rval) { - JSFunction *fun; - int i, cnt; - I32 ax; - SV *sv, *perl_object; - GV *gv; - HV *stash; - char *name; - - dSP; - - fun = JS_ValueToFunction(cx, argv[-2]); - perl_object = PVGetRef(cx, obj); - - fun = JS_ValueToFunction(cx, argv[-2]); - name = (char*) JS_GetFunctionName(fun); - - stash = SvSTASH(SvRV(perl_object)); - gv = gv_fetchmeth(stash, name, strlen(name), 0); - /* cnt = perl_call_pv(method_name, 0); */ - /* start of perl call stuff */ - if (! gv) { - char msg[256]; - sprintf(msg, "Method ``%s'' not defined", name); - JS_ReportError(cx, msg); - return JS_FALSE; - } - - ENTER; - SAVETMPS; - PUSHMARK(SP); - //SvREFCNT_inc(perl_object); - XPUSHs(perl_object); /* self for perl object method */ - for (i = 0; i < argc; i++) { - //sv = sv_newmortal(); - JSVALToSV(cx, obj, argv[i], &sv); - //sv_2mortal(sv); - XPUSHs(sv); - } - PUTBACK; - - cnt = perl_call_sv((SV*)GvCV(gv), G_ARRAY | G_KEEPERR | G_EVAL); - - //SvREFCNT_dec(perl_object); - - SPAGAIN; - /* adjust stack for use of ST macro (see perlcall) */ - SP -= cnt; - ax = (SP - PL_stack_base) + 1; - - /* read value(s) */ - if (cnt == 1) { - SVToJSVAL(cx, obj, ST(0), rval); - } else { - JSObject *jsarr; - jsval val; - int i; - jsarr = JS_NewArrayObject(cx, 0, NULL); - for (i = 0; i < cnt; i++) { - SVToJSVAL(cx, JS_GetGlobalObject(cx), ST(i), &val); - JS_DefineElement(cx, jsarr, i, val, NULL, NULL, 0); - } - *rval = OBJECT_TO_JSVAL(jsarr); - } - PUTBACK; - - FREETMPS; - LEAVE; - - //return(JS_TRUE); - return checkError(cx); -} - -/* - Retrieve property from PerlValue object by its name. Tries - to look at the PerlValue object both as a hash and array. - If the index is numerical, then it looks at the array part - first. *rval contains the result. -*/ -/* __PH__ - ...but. PVGetproperty now firstly looks for method in given - object package. If such method if found, then is returned - universal method stub. Sideeffect of this behavior is, that - method are looked first before properties of the same name. - - Second problem is security. In this way any perl method could - be called. We pay security leak for this. May be we could - support some Perl exporting process (via some package global - array). -*/ -static JSBool -PVGetProperty(JSContext *cx, JSObject *obj, jsval name, jsval *rval) -{ - char* str; - - /* __PH__ array properties should be served first */ - if(JSVAL_IS_INT(name)){ - int32 ip; - - JS_ValueToInt32(cx, name, &ip); - PVGetElement(cx, obj, ip, rval); - if(*rval!=JSVAL_VOID){ - return JS_TRUE; - } - } - - str = JS_GetStringBytes(JS_ValueToString(cx, name)); - - /* __PH__ may, be */ - if(!strcmp(str, "length")){ - SV* sv = SvRV(PVGetRef(cx, obj)); - - if(SvTYPE(sv)==SVt_PVAV){ - *rval = INT_TO_JSVAL(av_len((AV*)sv)+1); - return JS_TRUE; - }else - if(SvTYPE(sv)==SVt_PVHV){ - *rval = INT_TO_JSVAL(av_len((AV*)sv)+1); - return JS_TRUE; - }else{ - *rval = INT_TO_JSVAL(0); - return JS_TRUE; - } - }else{ - int i; - /* __PH__ predefined methods NUST win */ - for(i=0; i < sizeof(predefined_methods)/sizeof(char*); i++){ - if(!strcmp(predefined_methods[i], str)){ - return JS_TRUE; - } - } - - /* __PH__ properties in hash should be served at last (possibly) */ - PVGetKey(cx, obj, str, rval); - if (*rval!=JSVAL_VOID) { - return JS_TRUE; - } else { -#if 0 - char* str = JS_GetStringBytes(JS_ValueToString(cx, name)); - JS_ReportError(cx, "Perl: can't get property '%s'", str); - return JS_FALSE; -#else - /* when Volodya does another job, we may experiment :-) */ - char* str = JS_GetStringBytes(JS_ValueToString(cx, name)); - /* great, but who will dispose it? (GC of JS??) */ - JSFunction *fun = JS_NewFunction(cx, PVCallStub, 0, 0, NULL, str); - *rval = OBJECT_TO_JSVAL(JS_GetFunctionObject(fun)); - return(JS_TRUE); -#endif - } - } - return JS_TRUE; -} - -/* - Set property of PerlValue object. Like GetProperty is looks at - both array and hash components. -*/ -static JSBool -PVSetProperty(JSContext *cx, JSObject *obj, jsval name, jsval *rval) -{ - char* str = JS_GetStringBytes(JS_ValueToString(cx, name)); - - if(JSVAL_IS_INT(name)){ - int32 ip; - - JS_ValueToInt32(cx, name, &ip); - if(PVSetElement(cx, obj, ip, *rval)) return JS_TRUE; - } - return PVSetKey(cx, obj, str, *rval); -} - -/* - Retrieve numerical property of a PerlValue object. - If the object doesn't contain an array, or the - property doesn't exist, NULL is returned. -*/ -static JSBool -PVGetElement(JSContext *cx, JSObject *obj, jsint index, jsval *rval) -{ - SV *ref, **sv; - AV *list; - - *rval = JSVAL_VOID; - - ref = PVGetRef(cx, obj); - - if(SvTYPE(SvRV(ref)) != SVt_PVAV){ - return JS_FALSE; - } - - list = (AV*)SvRV(ref); - - if(!list){ - return JS_FALSE; - } - sv = av_fetch(list, (I32)index, 0); - if(!sv){ - return JS_FALSE; - } - //return SVToJSVAL(cx, obj, newRV_inc(*sv), rval); - return SVToJSVAL(cx, obj, *sv, rval); -} - -/* - Set a numeric property of a PerlValue object. - If the object doesn't contain an array or the - index doesn't exist, JS_FALSE is returned. -*/ -static JSBool -PVSetElement(JSContext *cx, JSObject *obj, jsint index, jsval v) -{ - SV *ref, **sv, *s; - AV *list; - - ref = PVGetRef(cx, obj); - - if(SvTYPE(SvRV(ref)) != SVt_PVAV){ - return JS_FALSE; - } - - list = (AV*)SvRV(ref); - - if(!list) return JS_FALSE; - JSVALToSV(cx, obj, v, &s); - sv = av_store(list, (I32)index, s); - if(!sv) return JS_FALSE; - return JS_TRUE; -} - -/* - Retrieve property. If the object doesn't contain an hash, or the - property doesn't exist, NULL is returned. -*/ -static JSBool -PVGetKey(JSContext *cx, JSObject *obj, char* name, jsval *rval) -{ - SV *ref, **sv; - HV *hash; - - *rval = JSVAL_VOID; - ref = PVGetRef(cx, obj); - - if(SvTYPE(SvRV(ref)) != SVt_PVHV){ - return JS_FALSE; - } - - hash = (HV*)SvRV(ref); - - if(!hash){ - return JS_FALSE; - } - sv = hv_fetch(hash, name, strlen(name), 0); - if(!sv){ - return JS_FALSE; - } - return SVToJSVAL(cx, obj, newRV_inc(*sv), rval); -} - -/* - Get property of a PerlValue object. - If the object doesn't contain a hash or the - property doesn't exist, JS_FALSE is returned. -*/ -static JSBool -PVSetKey(JSContext *cx, JSObject *obj, char* name, jsval v) -{ - SV *ref, **sv, *s; - HV *hash; - - ref = PVGetRef(cx, obj); - - if(SvTYPE(SvRV(ref)) != SVt_PVHV){ - return JS_FALSE; - } - - hash = (HV*)SvRV(ref); - - if(!hash) return JS_FALSE; - JSVALToSV(cx, obj, v, &s); - sv = hv_store(hash, name, strlen(name), s, 0); - if(!sv) return JS_FALSE; - else return JS_TRUE; -} - -/* - toString() method for PerlValue. For arrays uses array's methods. - If this fails, the type of the value gets returned. TODO: It's actually - better to use a Perl module like Data::Dumpvar.pm to print complex - data structures recursively. -*/ -static JSBool -PVToString(JSContext *cx, JSObject *obj, int argc, jsval *argv, jsval* rval) -{ - SV* ref = PVGetRef(cx, obj); - SV* sv = SvRV(ref); - svtype type = SvTYPE(sv); - /*jsval args[]= {STRING_TO_JSVAL(JS_NewStringCopyZ(cx, "JS::Object::toString")), - OBJECT_TO_JSVAL(obj)};*/ - jsval v; - /*return perl_call(cx, obj, 2, args, rval);*/ - - if (type==SVt_PVAV) { - JSObject *arrayObject = JS_NewArrayObject(cx,0,NULL); - JSFunction *fun; - - JS_GetProperty(cx, arrayObject, "toString", &v); - fun = JS_ValueToFunction(cx, v); - return JS_CallFunction(cx, obj, fun, 0, NULL, rval); - } - { - char out[256]; - JSString *newString; - JS_GetProperty(cx, obj, "type", &v); - if(!JSVAL_IS_VOID(v)) - sprintf(out, "[%s]", JS_GetStringBytes(JSVAL_TO_STRING(v))); - else - strcpy(out, "[PerlValue]"); - newString = JS_NewStringCopyZ(cx, out); - if (!newString) - return JS_FALSE; - *rval = STRING_TO_JSVAL(newString); - } - return JS_TRUE; -} - -static JSBool -PVConvert (JSContext *cx, JSObject *obj, JSType type, jsval *rval) -{ - *rval = OBJECT_TO_JSVAL(obj); - return JS_TRUE; -} - -/* - Takes care of GC in Perl: we need to decrement Perl's - reference count when PV goes out of scope. -*/ - -/* #include */ - -static void -PVFinalize (JSContext *cx, JSObject *obj) -{ - /* SV* sv = SvRV(PVGetRef(cx, obj)); */ - SV *sv; - - if ( obj ) { - sv = PVGetRef(cx, obj); - - /* SV *sv = PVGetRef(cx, obj); - if ( SvROK(sv) ) sv = SvRV( sv ); _PH_ test*/ - - /* TODO: GC */ - if(sv && SvREFCNT(sv) > 0){ - /*fprintf(stderr, "Finalization: %d references left", SvREFCNT(sv));*/ - SvREFCNT_dec(sv); - /*fprintf(stderr, "Finalization: %d references left", SvREFCNT(sv));*/ - } - } - /* return JS_TRUE; */ -} - -/* - Convert a jsval to a SV* (scalar value pointer). - Used for parameter passing. This function is also - used by the Perl part of PerlConnect. -*/ - -JSBool -JSVALToSV(JSContext *cx, JSObject *obj, jsval v, SV** sv) -{ - //*sv = &sv_undef; //__PH__?? - if(JSVAL_IS_PRIMITIVE(v)){ - if(JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)){ - *sv = &PL_sv_undef; - //printf("===> JSVALToSV: VOID\n"); - }else - if(JSVAL_IS_INT(v)){ - *sv = sv_newmortal(); - sv_setiv(*sv, JSVAL_TO_INT(v)); - //*sv = newSViv(JSVAL_TO_INT(v)); - //printf("===> JSVALToSV: INT\n"); - }else - if(JSVAL_IS_DOUBLE(v)){ - *sv = sv_newmortal(); - sv_setnv(*sv, *JSVAL_TO_DOUBLE(v)); - //*sv = newSVnv(*JSVAL_TO_DOUBLE(v)); - //printf("===> JSVALToSV: DOUBLE\n"); - }else - if(JSVAL_IS_STRING(v)){ - *sv = sv_newmortal(); - sv_setpv(*sv, JS_GetStringBytes(JSVAL_TO_STRING(v))); - //*sv = newSViv(0); - //sv_setpv(*sv, JS_GetStringBytes(JSVAL_TO_STRING(v))); - //printf("===> JSVALToSV: CHAR\n"); - }else{ - warn("Unknown primitive type"); - } - }else{ - if(JSVAL_IS_OBJECT(v)){ - JSObject *object = JSVAL_TO_OBJECT(v); - if(JS_InstanceOf(cx, object, &perlValueClass, NULL)){ - *sv = PVGetRef(cx, object); - }else{ - if(JS_IsArrayObject(cx, object)){ - *sv = sv_newmortal(); - sv_setref_pv(*sv, "JS::Object", (void*)object); - sv_magic(SvRV(*sv), sv_2mortal(newSViv((IV)cx)), - '~', NULL, 0); - /* printf("===> JSVALToSV: ARRAY\n); */ - }else{ - *sv = sv_newmortal(); - sv_setref_pv(*sv, "JS::Object", (void*)object); - sv_magic(SvRV(*sv), sv_2mortal(newSViv((IV)cx)), - '~', NULL, 0); - //printf("===> JSVALToSV: JS OBJECT\n"); - } - } - }else{ - warn("Type conversion is not supported"); - *sv = &PL_sv_undef; //__PH__?? - return JS_FALSE; - } - } - return JS_TRUE; -} - -/* - Converts a reference Perl value to a jsval. If ref points - to an immediate value, the value itself is returned in rval. - O.w. a PerlValue object is returned. This function is also - used by the Perl part of PerlConnect. -*/ - -#define SV_BIND_TO_OBJECT(sv) (sv_isobject(sv) || (SvROK(sv) && (\ - SvTYPE(SvRV(sv)) == SVt_RV ||\ - SvTYPE(SvRV(sv)) == SVt_PVAV ||\ - SvTYPE(SvRV(sv)) == SVt_PVHV ||\ - SvTYPE(SvRV(sv)) == SVt_PVCV\ - ))) - -JSBool -SVToJSVAL(JSContext *cx, JSObject *obj, SV *ref, jsval *rval) { - SV *sv; - char* name=NULL; - JSBool ok = JS_TRUE; - - /* we'll use the dereferrenced value (excpet for object) */ - if( SvROK(ref) ) { - sv = SvRV(ref); - }else{ - sv = ref; - } - - /* printf("+++> In SVToJSVAL value %s, type=%d\n", SvPV(sv, PL_na), SvTYPE(sv)); */ - - if ( ! SvOK( ref ) ){ - *rval = JSVAL_VOID; - /* printf("---> SVToJSVAL returning VOID\n"); */ - } else - if ( SV_BIND_TO_OBJECT(ref) ) { - JSObject *perlValue, *prototype = NULL; - JSString *nameString; - - /*svtype type = SvTYPE(sv); - switch(type){ - case SVt_RV: name = "Perl Reference"; break; - case SVt_PVAV: name = "Perl Array"; break; - case SVt_PVHV: name = "Perl Hash"; break; - case SVt_PVCV: name = "Perl Code Reference"; break; - case SVt_PVMG: name = "Perl Magic"; break; - default: - warn("Unsupported type in SVToJSVAL: %d", type); - *rval = JSVAL_VOID; - return JS_FALSE; - }*/ - - /* printf("---> SVToJSVAL returning object\n"); */ - name = "Perl Value"; - /* __PH__ */ - SvREFCNT_inc(ref); - - if (SvTYPE(sv) == SVt_PVAV) { - prototype = JS_NewArrayObject(cx, 0, NULL); - if (!prototype) - return JS_FALSE; - } - - perlValue = JS_DefineObject(cx, obj, "PerlValue", - &perlValueClass, prototype, - JSPROP_ENUMERATE); - if (!perlValue) - return JS_FALSE; - JS_SetPrivate(cx, perlValue, ref); - if (!JS_DefineFunctions(cx, perlValue, perlValueMethods)) - return JS_FALSE; - if (name) { - nameString = JS_NewStringCopyZ(cx, name); - if (!nameString) - return JS_FALSE; - } - if (!JS_DefineProperty(cx, perlValue, "type", - name?STRING_TO_JSVAL(nameString):JSVAL_VOID, - NULL, NULL, JSPROP_PERMANENT|JSPROP_READONLY)) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(perlValue); - } else - if(SvIOK(sv)){ - *rval = INT_TO_JSVAL(SvIV(sv)); - /* printf("---> SVToJSVAL returning INTEGER\n"); */ - } else - if(SvNOK(sv)){ - ok = JS_NewDoubleValue(cx, SvNV(sv), rval); - /* printf("---> SVToJSVAL returning DOUBLE\n"); */ - } else - if(SvPOK(sv)){ - *rval = STRING_TO_JSVAL((JS_NewStringCopyZ(cx, SvPV(sv, PL_na)))); - /* printf("---> SVToJSVAL returning CHAR\n\n"); */ - } else { - *rval = JSVAL_VOID; /* shouldn't happen */ - /* printf("---> SVToJSVAL returning VOID (panic)\n"); */ - } - return ok; -} diff --git a/lib/javascript/perlconnect/jsperl.h b/lib/javascript/perlconnect/jsperl.h deleted file mode 100644 index 7c23ef3e..00000000 --- a/lib/javascript/perlconnect/jsperl.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* This is the public header, which means that this is the only thing one */ -/* needs to include to enable the Perl object. See README.html for more */ -/* documentation */ - -#include - -/* - This is the only function that must be called by an - application that wants to use PerlConnect. -*/ -JS_EXTERN_API(JSObject*) -JS_InitPerlClass(JSContext *cx, JSObject *obj); - diff --git a/lib/javascript/perlconnect/jsperlbuild.pl b/lib/javascript/perlconnect/jsperlbuild.pl deleted file mode 100644 index d3e32c66..00000000 --- a/lib/javascript/perlconnect/jsperlbuild.pl +++ /dev/null @@ -1,81 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1999 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Helper perl script to abstract the location of xsubpp -# - -# Thanks to Dave Neuer for the original -# version of this file. Entered as NPL with his permission. - -use File::Find; -use Cwd; - -$notfound = 1; - -foreach(@INC){ - next if /^\.$/; - if(-e $_){ - find(\&find_ExtUtils, $_); - } -} - -if(-e $xsubpp && -e $typemap){ - $res = `perl $xsubpp -typemap $typemap -typemap typemap JS.xs > JS.c`; - if(-e "JS.c"){ - print "Successfuly built JS.c\n"; - exit(0); - } - else{ - die("Couldn't build JS.c: $res"); - } -} -else{ - die("Couldn't locate files neccessary for building JS.c"); -} - -sub find_ExtUtils{ - if($notfound){ - if($File::Find::dir =~ /ExtUtils/){ - my $path = cwd; - $xsubpp = $path . "/xsubpp"; - $typemap = $path . "/typemap"; - undef $notfound; - } - } -} diff --git a/lib/javascript/perlconnect/jsperlpvt.h b/lib/javascript/perlconnect/jsperlpvt.h deleted file mode 100644 index 8edca815..00000000 --- a/lib/javascript/perlconnect/jsperlpvt.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "EXTERN.h" -#include "perl.h" -#include "jsperl.h" -/* Copyright © 1998 Netscape Communications Corporation, All Rights Reserved.*/ -/* This is the private header, which means that it shouldn't be included */ -/* unless you need to use some of the jsval<->SV* conversion functions */ -/* provided by PerlConnect needs to include to enable the Perl object. See */ -/* README.html for more documentation */ - -/* - This and the following function are used to convert - between Perl's "SV*" and JS's "jsval" types. -*/ -JS_EXTERN_API(SV*) -JSVALToSV(JSContext *cx, JSObject *obj, jsval v, SV** sv); - -JS_EXTERN_API(JSBool) -SVToJSVAL(JSContext *cx, JSObject *obj, SV *ref, jsval *rval); diff --git a/lib/javascript/perlconnect/test.js b/lib/javascript/perlconnect/test.js deleted file mode 100644 index 448a9e1e..00000000 --- a/lib/javascript/perlconnect/test.js +++ /dev/null @@ -1,73 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/******************************************************************************* -* PerlConnect test file. Some primitive testing in "silent mode" -- that is, -* you should be able to run -* perlconnectshell test.js -* without any error messages. See README.html for more info. -*******************************************************************************/ - -// Init -assert(p = new Perl('Sys::Hostname', 'Time::gmtime'), "Perl initialization failed"); -// Simple eval -assert(p.eval("'-' x 3") == '---', "Wrong value returned from eval"); - -assert(p.eval("undef()")==undefined, "Wrong value returned from eval"); -// Arrays -assert(a=p.eval("(1, 2, 3);"), "eval failed, 1"); -assert(a[1]==2, "Wrong value"); -assert(a.length==3, "Wrong length"); -// Hashes -assert(h=p.eval("{'one'=>1, 'two'=>2};"), "eval failed, 2"); -assert(h["two"]==2, "Wrong value"); -// Func. call -assert(p.eval("&hostname()") == p.call("hostname"), "Wrong value returned from eval or call"); -// Complex call -assert(b=p.Time.gmtime.gmtime(), "call failed"); -assert(b.length==9, "Wrong length") -// Variables -// Scalars -assert(p.eval("$a = 100; $b = 'abc';"), "eval failed, 3"); -assert(p.$a ==100, "Wrong variable value, 1"); -assert(p["$b"] == 'abc', "Wrong variable value, 2"); - -/* Auxilary function */ -function assert(cond, msg) -{ - cond || print("Error: " + msg+"\n"); -} // assert diff --git a/lib/javascript/perlconnect/test.pl b/lib/javascript/perlconnect/test.pl deleted file mode 100644 index 64a4c936..00000000 --- a/lib/javascript/perlconnect/test.pl +++ /dev/null @@ -1,244 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Test file for JS.pm -# - -############################################################ -# support packages for test script -############################################################ - -############################################################ -# Fotrik -package Father; - -sub old_meth { - return "Father::old_meth"; -} - - -############################################################ -# Synacek -package Son; -use vars qw( @ISA ); -@ISA = qw( Father ); - -sub new { - my $class = shift; - $class = ref $class || $class; - my $self = {}; - bless $self, $class; - return $self; -} - -sub new_meth { - return "Son::new_meth"; -} - -############################################################ -# Proxy -package Proxy; - -sub new { - my $class = shift; - $class = ref $class || $class; - my $self = { property => shift }; - bless $self, $class; - return $self; -} - -sub getObj { - my $ret = new Son(); - return $ret; -} - -sub getValue { - my $self = shift; - return $self->{ property }; -} - -sub getArray { - my $self = shift; - return [34, 35, 36, 37, 38]; -} - -sub getHash { - my $self = shift; - return { testkey1 => 'testvalue1', - testkey2 => 'testvalue2', - testkey3 => 'testvalue3', }; -} - -############################################################ -# main part of the test script -############################################################ - -package main; -use JS; - -BEGIN { - $| = 1; print "1..12\n"; -} - -END - { print "not ok 1\n" unless $loaded; } - -$loaded = 1; -print "ok 1\n"; - -use strict; #no typos, please - -my $rt = new JS(1_204 ** 2); -my $cx = $rt->createContext(8 * 1_024); - -my $jsval; -my $testc = 1; #testcounter -############################################################ -# the simplest test -$testc++; -$jsval = $cx->eval('6;'); -print $jsval == 6 ? "ok $testc\n" : "not ok $testc\n"; #2 - -############################################################ -#second very simple test -$testc++; -$jsval = $cx->eval('"hallo";'); -print $jsval eq "hallo" ? "ok $testc\n" : "not ok $testc\n"; #3 - -############################################################ -# third very simple test -$testc++; -$jsval = $cx->eval("1.23"); -print $jsval == 1.23 ? "ok $testc\n" : "not ok $testc\n"; #4 - -############################################################ -#undef is little bit tricky -$testc++; -$jsval = $cx->eval('undefined'); -print ! defined $jsval ? "ok $testc\n" : "not ok $testc\n"; #5 - -############################################################ -#can ve tie js objects? (generally to hash, Arrays to arrays too) -$testc++; -$jsval = $cx->eval('foo = new Object(); foo.prop = 11; foo;'); -my %hash; -#read js property -tie %hash, 'JS::Object', $jsval; -print $hash{prop} == 11 ? "ok $testc\n" : "not ok $testc\n"; #6 - -############################################################ -#set js propertry -$testc++; -$hash{prop2} = 2; -$jsval = $cx->eval('foo.prop2;'); -print $jsval == 2 ? "ok $testc\n" : "not ok $testc\n"; #7 - -############################################################ -#tie array -$testc++; -my @arr; -$jsval = $cx->eval('arr = new Array(); arr[0] = 0; arr[1] = 1; arr;'); -tie @arr, "JS::Object", $jsval; -print ((($#arr == 1) && ($arr[1] == 1)) ? "ok $testc\n" : "not ok $testc\n");#8 - -############################################################ -# object delegation test -$testc++; -$cx->createObject(new Proxy("init_value"), "perlobj", - { getObj => \&Proxy::getObj, - getValue => \&Proxy::getValue, - getArray => \&Proxy::getArray, - getHash => \&Proxy::getHash, - }); -$jsval = $cx->eval("perlobj.getValue()"); -print $jsval eq "init_value" ? "ok $testc\n" : "not ok $testc\n"; #9 - -############################################################ -# perl object returned to js -$testc++; -$jsval = $cx->eval("po = perlobj.getObj(); po.new_meth()"); -print $jsval eq "Son::new_meth" ? "ok $testc\n" : "not ok $testc\n"; #10 - -############################################################ -# and what about inherited methods? -$testc++; -$jsval = $cx->eval("po.old_meth()"); -print $jsval eq "Father::old_meth" ? "ok $testc\n" : "not ok $testc\n"; #11 - -############################################################ -# pass an array, check the element -$testc++; -$jsval = $cx->eval("parr = perlobj.getArray(); parr[2];"); -print $jsval == 36 ? "ok $testc\n" : "not ok $testc\n"; #12 - -############################################################ -# check the array length -$testc++; -$jsval = $cx->eval("parr.length"); -print $jsval == 5 ? "ok $testc\n" : "not ok $testc\n"; #13 - -############################################################ -# pass a hash, check the element -$testc++; -$jsval = $cx->eval("phash = perlobj.getHash(); phash.testkey1;"); -print $jsval eq 'testvalue1' ? "ok $testc\n" : "not ok $testc\n"; #14 - -############################################################ -# error test -$testc++; -my $line; -my $err; -sub js_ErrorReporter { - my ($msg, $file, $line, $linebuf, $token) = @_; - $err = "line $line $msg"; -} -$cx->setErrorReporter( \&js_ErrorReporter ); -$cx->eval("x = 2 + 4;\nx.method()\n"); -print $err =~ /^line 1/ ? "ok $testc\n" : "not ok $testc\n"; #15 - -############################################################ -# cleanup -# so far we have to undef context value, to make sure, -# it is disposed before runtime -undef $cx; -undef $rt; - -__END__ - - diff --git a/lib/javascript/perlconnect/typemap b/lib/javascript/perlconnect/typemap deleted file mode 100644 index 0a35189b..00000000 --- a/lib/javascript/perlconnect/typemap +++ /dev/null @@ -1,121 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# Typemap for PerlConnect -# - -TYPEMAP -# These types have direct equivalents implemented as Perl packages -JSRuntime * RUNTIME -JSContext * CONTEXT -JSScript * SCRIPT -jsval jsval -# This is an auxilary type. Object serves as a wrapper for it -JSObject * OBJECT - - -OUTPUT -jsval - { - SV *foo = sv_newmortal(); - JSVALToSV(cx, JS_GetGlobalObject(cx), $var, &foo); - sv_setsv($arg, foo); - } - -OBJECT - sv_setref_pv($arg, "JS::Object", (void*)$var); - -#CONTEXT -# sv_setref_pv($arg, "JS::Context", (void*)$var); - -SCRIPT - sv_setref_pv($arg, "JS::Script", (void*)$var); - -RUNTIME - sv_setref_pv($arg, "JS::Runtime", (void*)$var); - -#JS_OBJECT -# sv_setref_pv($arg, "JSObject", (void*)$var); - -INPUT -jsval - { - /* JSContext *cx = getContext(); */ - SVToJSVAL(cx, JS_GetGlobalObject(cx), newRV($arg), &$var); - } - -OBJECT - if(sv_isa($arg, \"JS::Object\")) - $var = ($type)SvIV((SV*)SvRV($arg)); - else{ - warn(\"${Package}::$func_name() -- $var is not a blessed JS::Object reference\"); - XSRETURN_UNDEF; - } - -#CONTEXT -# if(sv_isa($arg, \"JS::Context\")) -# $var = ($type)SvIV((SV*)SvRV($arg)); -# else{ -# warn(\"${Package}::$func_name() -- $var is not a blessed JS::Context reference\"); -# XSRETURN_UNDEF; -# } - -CONTEXT - if(sv_isa($arg, \"JS::Context\")) - $var = ($type)SvIV(*hv_fetch((HV*)SvRV($arg), \"_handle\", 7, 0)); - else{ - warn(\"${Package}::$func_name() -- $var is not a blessed JS::Context reference\"); - XSRETURN_UNDEF; - } - -SCRIPT - if(sv_isa($arg, \"JS::Script\")) - $var = ($type)SvIV((SV*)SvRV($arg)); - else{ - warn(\"${Package}::$func_name() -- $var is not a blessed JS::Script reference\"); - XSRETURN_UNDEF; - } - -RUNTIME - if(sv_isa($arg, \"JS::Runtime\")) - $var = ($type)SvIV((SV*)SvRV($arg)); - else{ - warn(\"${Package}::$func_name() -- $var is not a blessed JS::Runtime reference\"); - XSRETURN_UNDEF; - } diff --git a/lib/javascript/plify_jsdhash.sed b/lib/javascript/plify_jsdhash.sed deleted file mode 100644 index b58e7fde..00000000 --- a/lib/javascript/plify_jsdhash.sed +++ /dev/null @@ -1,32 +0,0 @@ -/ * Double hashing implementation./a\ - * GENERATED BY js/src/plify_jsdhash.sed -- DO NOT EDIT!!! -/ * Double hashing, a la Knuth 6./a\ - * GENERATED BY js/src/plify_jsdhash.sed -- DO NOT EDIT!!! -s/jsdhash_h___/pldhash_h___/ -s/jsdhash\.bigdump/pldhash.bigdump/ -s/jstypes\.h/nscore.h/ -s/jsbit\.h/prbit.h/ -s/jsdhash\.h/pldhash.h/ -s/jsdhash\.c/pldhash.c/ -s/jsdhash:/pldhash:/ -s/jsutil\.h/nsDebug.h/ -s/JS_DHASH/PL_DHASH/g -s/JS_DHash/PL_DHash/g -s/JSDHash/PLDHash/g -s/JSHash/PLHash/g -s/uint32 /PRUint32/g -s/\([^U]\)int32 /\1PRInt32/g -s/uint16 /PRUint16/g -s/\([^U]\)int16 /\1PRInt16/g -s/uint32/PRUint32/g -s/\([^U]\)int32/\1PRInt32/g -s/uint16/PRUint16/g -s/\([^U]\)int16/\1PRInt16/g -s/JSBool/PRBool/g -s/extern JS_PUBLIC_API(\([^()]*\))/NS_COM_GLUE \1/ -s/JS_PUBLIC_API(\([^()]*\))/\1/ -s/JS_DLL_CALLBACK/PR_CALLBACK/ -s/JS_STATIC_DLL_CALLBACK/PR_STATIC_CALLBACK/ -s/JS_NewDHashTable/PL_NewDHashTable/ -s/JS_ASSERT(\(.*\));/NS_ASSERTION(\1, "PLDHash precondition");/ -s/JS_/PR_/g diff --git a/lib/javascript/prmjtime.c b/lib/javascript/prmjtime.c deleted file mode 100644 index 6e08423a..00000000 --- a/lib/javascript/prmjtime.c +++ /dev/null @@ -1,440 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * PR time code. - */ -#include "jsstddef.h" -#ifdef SOLARIS -#define _REENTRANT 1 -#endif -#include -#include -#include "jstypes.h" -#include "jsutil.h" - -#include "jsprf.h" -#include "prmjtime.h" - -#define PRMJ_DO_MILLISECONDS 1 - -#ifdef XP_OS2 -#include -#endif -#ifdef XP_WIN -#include -#include -#endif - -#if defined(XP_UNIX) || defined(XP_BEOS) - -#ifdef _SVID_GETTOD /* Defined only on Solaris, see Solaris */ -extern int gettimeofday(struct timeval *tv); -#endif - -#include - -#endif /* XP_UNIX */ - -#define IS_LEAP(year) \ - (year != 0 && ((((year & 0x3) == 0) && \ - ((year - ((year/100) * 100)) != 0)) || \ - (year - ((year/400) * 400)) == 0)) - -#define PRMJ_HOUR_SECONDS 3600L -#define PRMJ_DAY_SECONDS (24L * PRMJ_HOUR_SECONDS) -#define PRMJ_YEAR_SECONDS (PRMJ_DAY_SECONDS * 365L) -#define PRMJ_MAX_UNIX_TIMET 2145859200L /*time_t value equiv. to 12/31/2037 */ -/* function prototypes */ -static void PRMJ_basetime(JSInt64 tsecs, PRMJTime *prtm); -/* - * get the difference in seconds between this time zone and UTC (GMT) - */ -JSInt32 -PRMJ_LocalGMTDifference() -{ -#if defined(XP_UNIX) || defined(XP_WIN) || defined(XP_OS2) || defined(XP_BEOS) - struct tm ltime; - - /* get the difference between this time zone and GMT */ - memset((char *)<ime,0,sizeof(ltime)); - ltime.tm_mday = 2; - ltime.tm_year = 70; -#ifdef SUNOS4 - ltime.tm_zone = 0; - ltime.tm_gmtoff = 0; - return timelocal(<ime) - (24 * 3600); -#else - return mktime(<ime) - (24L * 3600L); -#endif -#endif -} - -/* Constants for GMT offset from 1970 */ -#define G1970GMTMICROHI 0x00dcdcad /* micro secs to 1970 hi */ -#define G1970GMTMICROLOW 0x8b3fa000 /* micro secs to 1970 low */ - -#define G2037GMTMICROHI 0x00e45fab /* micro secs to 2037 high */ -#define G2037GMTMICROLOW 0x7a238000 /* micro secs to 2037 low */ - -/* Convert from base time to extended time */ -static JSInt64 -PRMJ_ToExtendedTime(JSInt32 base_time) -{ - JSInt64 exttime; - JSInt64 g1970GMTMicroSeconds; - JSInt64 low; - JSInt32 diff; - JSInt64 tmp; - JSInt64 tmp1; - - diff = PRMJ_LocalGMTDifference(); - JSLL_UI2L(tmp, PRMJ_USEC_PER_SEC); - JSLL_I2L(tmp1,diff); - JSLL_MUL(tmp,tmp,tmp1); - - JSLL_UI2L(g1970GMTMicroSeconds,G1970GMTMICROHI); - JSLL_UI2L(low,G1970GMTMICROLOW); -#ifndef JS_HAVE_LONG_LONG - JSLL_SHL(g1970GMTMicroSeconds,g1970GMTMicroSeconds,16); - JSLL_SHL(g1970GMTMicroSeconds,g1970GMTMicroSeconds,16); -#else - JSLL_SHL(g1970GMTMicroSeconds,g1970GMTMicroSeconds,32); -#endif - JSLL_ADD(g1970GMTMicroSeconds,g1970GMTMicroSeconds,low); - - JSLL_I2L(exttime,base_time); - JSLL_ADD(exttime,exttime,g1970GMTMicroSeconds); - JSLL_SUB(exttime,exttime,tmp); - return exttime; -} - -JSInt64 -PRMJ_Now(void) -{ -#ifdef XP_OS2 - JSInt64 s, us, ms2us, s2us; - struct timeb b; -#endif -#ifdef XP_WIN - JSInt64 s, us, - win2un = JSLL_INIT(0x19DB1DE, 0xD53E8000), - ten = JSLL_INIT(0, 10); - FILETIME time, midnight; -#endif -#if defined(XP_UNIX) || defined(XP_BEOS) - struct timeval tv; - JSInt64 s, us, s2us; -#endif /* XP_UNIX */ - -#ifdef XP_OS2 - ftime(&b); - JSLL_UI2L(ms2us, PRMJ_USEC_PER_MSEC); - JSLL_UI2L(s2us, PRMJ_USEC_PER_SEC); - JSLL_UI2L(s, b.time); - JSLL_UI2L(us, b.millitm); - JSLL_MUL(us, us, ms2us); - JSLL_MUL(s, s, s2us); - JSLL_ADD(s, s, us); - return s; -#endif -#ifdef XP_WIN - /* The windows epoch is around 1600. The unix epoch is around 1970. - win2un is the difference (in windows time units which are 10 times - more precise than the JS time unit) */ - GetSystemTimeAsFileTime(&time); - /* Win9x gets confused at midnight - http://support.microsoft.com/default.aspx?scid=KB;en-us;q224423 - So if the low part (precision <8mins) is 0 then we get the time - again. */ - if (!time.dwLowDateTime) { - GetSystemTimeAsFileTime(&midnight); - time.dwHighDateTime = midnight.dwHighDateTime; - } - JSLL_UI2L(s, time.dwHighDateTime); - JSLL_UI2L(us, time.dwLowDateTime); - JSLL_SHL(s, s, 32); - JSLL_ADD(s, s, us); - JSLL_SUB(s, s, win2un); - JSLL_DIV(s, s, ten); - return s; -#endif - -#if defined(XP_UNIX) || defined(XP_BEOS) -#ifdef _SVID_GETTOD /* Defined only on Solaris, see Solaris */ - gettimeofday(&tv); -#else - gettimeofday(&tv, 0); -#endif /* _SVID_GETTOD */ - JSLL_UI2L(s2us, PRMJ_USEC_PER_SEC); - JSLL_UI2L(s, tv.tv_sec); - JSLL_UI2L(us, tv.tv_usec); - JSLL_MUL(s, s, s2us); - JSLL_ADD(s, s, us); - return s; -#endif /* XP_UNIX */ -} - -/* Get the DST timezone offset for the time passed in */ -JSInt64 -PRMJ_DSTOffset(JSInt64 local_time) -{ - JSInt64 us2s; - time_t local; - JSInt32 diff; - JSInt64 maxtimet; - struct tm tm; - PRMJTime prtm; -#ifndef HAVE_LOCALTIME_R - struct tm *ptm; -#endif - - - JSLL_UI2L(us2s, PRMJ_USEC_PER_SEC); - JSLL_DIV(local_time, local_time, us2s); - - /* get the maximum of time_t value */ - JSLL_UI2L(maxtimet,PRMJ_MAX_UNIX_TIMET); - - if(JSLL_CMP(local_time,>,maxtimet)){ - JSLL_UI2L(local_time,PRMJ_MAX_UNIX_TIMET); - } else if(!JSLL_GE_ZERO(local_time)){ - /*go ahead a day to make localtime work (does not work with 0) */ - JSLL_UI2L(local_time,PRMJ_DAY_SECONDS); - } - JSLL_L2UI(local,local_time); - PRMJ_basetime(local_time,&prtm); -#ifndef HAVE_LOCALTIME_R - ptm = localtime(&local); - if(!ptm){ - return JSLL_ZERO; - } - tm = *ptm; -#else - localtime_r(&local,&tm); /* get dst information */ -#endif - - diff = ((tm.tm_hour - prtm.tm_hour) * PRMJ_HOUR_SECONDS) + - ((tm.tm_min - prtm.tm_min) * 60); - - if(diff < 0){ - diff += PRMJ_DAY_SECONDS; - } - - JSLL_UI2L(local_time,diff); - - JSLL_MUL(local_time,local_time,us2s); - - return(local_time); -} - -/* Format a time value into a buffer. Same semantics as strftime() */ -size_t -PRMJ_FormatTime(char *buf, int buflen, char *fmt, PRMJTime *prtm) -{ -#if defined(XP_UNIX) || defined(XP_WIN) || defined(XP_OS2) || defined(XP_BEOS) - struct tm a; - - /* Zero out the tm struct. Linux, SunOS 4 struct tm has extra members int - * tm_gmtoff, char *tm_zone; when tm_zone is garbage, strftime gets - * confused and dumps core. NSPR20 prtime.c attempts to fill these in by - * calling mktime on the partially filled struct, but this doesn't seem to - * work as well; the result string has "can't get timezone" for ECMA-valid - * years. Might still make sense to use this, but find the range of years - * for which valid tz information exists, and map (per ECMA hint) from the - * given year into that range. - - * N.B. This hasn't been tested with anything that actually _uses_ - * tm_gmtoff; zero might be the wrong thing to set it to if you really need - * to format a time. This fix is for jsdate.c, which only uses - * JS_FormatTime to get a string representing the time zone. */ - memset(&a, 0, sizeof(struct tm)); - - a.tm_sec = prtm->tm_sec; - a.tm_min = prtm->tm_min; - a.tm_hour = prtm->tm_hour; - a.tm_mday = prtm->tm_mday; - a.tm_mon = prtm->tm_mon; - a.tm_wday = prtm->tm_wday; - a.tm_year = prtm->tm_year - 1900; - a.tm_yday = prtm->tm_yday; - a.tm_isdst = prtm->tm_isdst; - - /* Even with the above, SunOS 4 seems to detonate if tm_zone and tm_gmtoff - * are null. This doesn't quite work, though - the timezone is off by - * tzoff + dst. (And mktime seems to return -1 for the exact dst - * changeover time.) - - */ - -#if defined(SUNOS4) - if (mktime(&a) == -1) { - /* Seems to fail whenever the requested date is outside of the 32-bit - * UNIX epoch. We could proceed at this point (setting a.tm_zone to - * "") but then strftime returns a string with a 2-digit field of - * garbage for the year. So we return 0 and hope jsdate.c - * will fall back on toString. - */ - return 0; - } -#endif - - return strftime(buf, buflen, fmt, &a); -#endif -} - -/* table for number of days in a month */ -static int mtab[] = { - /* jan, feb,mar,apr,may,jun */ - 31,28,31,30,31,30, - /* july,aug,sep,oct,nov,dec */ - 31,31,30,31,30,31 -}; - -/* - * basic time calculation functionality for localtime and gmtime - * setups up prtm argument with correct values based upon input number - * of seconds. - */ -static void -PRMJ_basetime(JSInt64 tsecs, PRMJTime *prtm) -{ - /* convert tsecs back to year,month,day,hour,secs */ - JSInt32 year = 0; - JSInt32 month = 0; - JSInt32 yday = 0; - JSInt32 mday = 0; - JSInt32 wday = 6; /* start on a Sunday */ - JSInt32 days = 0; - JSInt32 seconds = 0; - JSInt32 minutes = 0; - JSInt32 hours = 0; - JSInt32 isleap = 0; - JSInt64 result; - JSInt64 result1; - JSInt64 result2; - JSInt64 base; - - JSLL_UI2L(result,0); - JSLL_UI2L(result1,0); - JSLL_UI2L(result2,0); - - /* get the base time via UTC */ - base = PRMJ_ToExtendedTime(0); - JSLL_UI2L(result, PRMJ_USEC_PER_SEC); - JSLL_DIV(base,base,result); - JSLL_ADD(tsecs,tsecs,base); - - JSLL_UI2L(result, PRMJ_YEAR_SECONDS); - JSLL_UI2L(result1,PRMJ_DAY_SECONDS); - JSLL_ADD(result2,result,result1); - - /* get the year */ - while ((isleap == 0) ? !JSLL_CMP(tsecs,<,result) : !JSLL_CMP(tsecs,<,result2)) { - /* subtract a year from tsecs */ - JSLL_SUB(tsecs,tsecs,result); - days += 365; - /* is it a leap year ? */ - if(IS_LEAP(year)){ - JSLL_SUB(tsecs,tsecs,result1); - days++; - } - year++; - isleap = IS_LEAP(year); - } - - JSLL_UI2L(result1,PRMJ_DAY_SECONDS); - - JSLL_DIV(result,tsecs,result1); - JSLL_L2I(mday,result); - - /* let's find the month */ - while(((month == 1 && isleap) ? - (mday >= mtab[month] + 1) : - (mday >= mtab[month]))){ - yday += mtab[month]; - days += mtab[month]; - - mday -= mtab[month]; - - /* it's a Feb, check if this is a leap year */ - if(month == 1 && isleap != 0){ - yday++; - days++; - mday--; - } - month++; - } - - /* now adjust tsecs */ - JSLL_MUL(result,result,result1); - JSLL_SUB(tsecs,tsecs,result); - - mday++; /* day of month always start with 1 */ - days += mday; - wday = (days + wday) % 7; - - yday += mday; - - /* get the hours */ - JSLL_UI2L(result1,PRMJ_HOUR_SECONDS); - JSLL_DIV(result,tsecs,result1); - JSLL_L2I(hours,result); - JSLL_MUL(result,result,result1); - JSLL_SUB(tsecs,tsecs,result); - - /* get minutes */ - JSLL_UI2L(result1,60); - JSLL_DIV(result,tsecs,result1); - JSLL_L2I(minutes,result); - JSLL_MUL(result,result,result1); - JSLL_SUB(tsecs,tsecs,result); - - JSLL_L2I(seconds,tsecs); - - prtm->tm_usec = 0L; - prtm->tm_sec = (JSInt8)seconds; - prtm->tm_min = (JSInt8)minutes; - prtm->tm_hour = (JSInt8)hours; - prtm->tm_mday = (JSInt8)mday; - prtm->tm_mon = (JSInt8)month; - prtm->tm_wday = (JSInt8)wday; - prtm->tm_year = (JSInt16)year; - prtm->tm_yday = (JSInt16)yday; -} diff --git a/lib/javascript/prmjtime.h b/lib/javascript/prmjtime.h deleted file mode 100644 index b74fe845..00000000 --- a/lib/javascript/prmjtime.h +++ /dev/null @@ -1,95 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef prmjtime_h___ -#define prmjtime_h___ -/* - * PR date stuff for mocha and java. Placed here temporarily not to break - * Navigator and localize changes to mocha. - */ -#include -#include "jslong.h" -#ifdef MOZILLA_CLIENT -#include "jscompat.h" -#endif - -JS_BEGIN_EXTERN_C - -typedef struct PRMJTime PRMJTime; - -/* - * Broken down form of 64 bit time value. - */ -struct PRMJTime { - JSInt32 tm_usec; /* microseconds of second (0-999999) */ - JSInt8 tm_sec; /* seconds of minute (0-59) */ - JSInt8 tm_min; /* minutes of hour (0-59) */ - JSInt8 tm_hour; /* hour of day (0-23) */ - JSInt8 tm_mday; /* day of month (1-31) */ - JSInt8 tm_mon; /* month of year (0-11) */ - JSInt8 tm_wday; /* 0=sunday, 1=monday, ... */ - JSInt16 tm_year; /* absolute year, AD */ - JSInt16 tm_yday; /* day of year (0 to 365) */ - JSInt8 tm_isdst; /* non-zero if DST in effect */ -}; - -/* Some handy constants */ -#define PRMJ_USEC_PER_SEC 1000000L -#define PRMJ_USEC_PER_MSEC 1000L - -/* Return the current local time in micro-seconds */ -extern JSInt64 -PRMJ_Now(void); - -/* get the difference between this time zone and gmt timezone in seconds */ -extern JSInt32 -PRMJ_LocalGMTDifference(void); - -/* Format a time value into a buffer. Same semantics as strftime() */ -extern size_t -PRMJ_FormatTime(char *buf, int buflen, char *fmt, PRMJTime *tm); - -/* Get the DST offset for the local time passed in */ -extern JSInt64 -PRMJ_DSTOffset(JSInt64 local_time); - -JS_END_EXTERN_C - -#endif /* prmjtime_h___ */ - diff --git a/lib/javascript/resource.h b/lib/javascript/resource.h deleted file mode 100644 index 9301810e..00000000 --- a/lib/javascript/resource.h +++ /dev/null @@ -1,15 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by js3240.rc -// - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1000 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/lib/javascript/rules.mk b/lib/javascript/rules.mk deleted file mode 100644 index d1f5f361..00000000 --- a/lib/javascript/rules.mk +++ /dev/null @@ -1,199 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998-1999 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Michael Ang -# -# Alternatively, the contents of this file may be used under the terms of -# either of the GNU General Public License Version 2 or later (the "GPL"), -# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# JSRef GNUmake makefile rules -# - -ifdef USE_MSVC -LIB_OBJS = $(addprefix $(OBJDIR)/, $(LIB_CFILES:.c=.obj)) -PROG_OBJS = $(addprefix $(OBJDIR)/, $(PROG_CFILES:.c=.obj)) -else -LIB_OBJS = $(addprefix $(OBJDIR)/, $(LIB_CFILES:.c=.o)) -LIB_OBJS += $(addprefix $(OBJDIR)/, $(LIB_ASFILES:.s=.o)) -PROG_OBJS = $(addprefix $(OBJDIR)/, $(PROG_CFILES:.c=.o)) -endif - -CFILES = $(LIB_CFILES) $(PROG_CFILES) -OBJS = $(LIB_OBJS) $(PROG_OBJS) - -ifdef USE_MSVC -# TARGETS = $(LIBRARY) # $(PROGRAM) not supported for MSVC yet -TARGETS += $(SHARED_LIBRARY) $(PROGRAM) # it is now -else -TARGETS += $(LIBRARY) $(SHARED_LIBRARY) $(PROGRAM) -endif - -all: - +$(LOOP_OVER_PREDIRS) -ifneq "$(strip $(TARGETS))" "" - $(MAKE) -f Makefile.ref $(TARGETS) -endif - +$(LOOP_OVER_DIRS) - -$(OBJDIR)/%: %.c - @$(MAKE_OBJDIR) - $(CC) -o $@ $(CFLAGS) $*.c $(LDFLAGS) - -# This rule must come before the rule with no dep on header -$(OBJDIR)/%.o: %.c %.h - @$(MAKE_OBJDIR) - $(CC) -o $@ -c $(CFLAGS) $*.c - - -$(OBJDIR)/%.o: %.c - @$(MAKE_OBJDIR) - $(CC) -o $@ -c $(CFLAGS) $*.c - -$(OBJDIR)/%.o: %.s - @$(MAKE_OBJDIR) - $(AS) -o $@ $(ASFLAGS) $*.s - -# This rule must come before rule with no dep on header -$(OBJDIR)/%.obj: %.c %.h - @$(MAKE_OBJDIR) - $(CC) -Fo$(OBJDIR)/ -c $(CFLAGS) $(JSDLL_CFLAGS) $*.c - -$(OBJDIR)/%.obj: %.c - @$(MAKE_OBJDIR) - $(CC) -Fo$(OBJDIR)/ -c $(CFLAGS) $(JSDLL_CFLAGS) $*.c - -$(OBJDIR)/js.obj: js.c - @$(MAKE_OBJDIR) - $(CC) -Fo$(OBJDIR)/ -c $(CFLAGS) $< - -ifeq ($(OS_ARCH),OS2) -$(LIBRARY): $(LIB_OBJS) - $(AR) $@ $? $(AR_OS2_SUFFIX) - $(RANLIB) $@ -else -ifdef USE_MSVC -$(SHARED_LIBRARY): $(LIB_OBJS) - link.exe $(LIB_LINK_FLAGS) /base:0x61000000 $(OTHER_LIBS) \ - /out:"$@" /pdb:none\ - /implib:"$(OBJDIR)/$(@F:.dll=.lib)" $^ -else -$(LIBRARY): $(LIB_OBJS) - $(AR) rv $@ $? - $(RANLIB) $@ - -$(SHARED_LIBRARY): $(LIB_OBJS) - $(MKSHLIB) -o $@ $(LIB_OBJS) $(LDFLAGS) $(OTHER_LIBS) -endif -endif - -# Java stuff -$(CLASSDIR)/$(OBJDIR)/$(JARPATH)/%.class: %.java - mkdir -p $(@D) - $(JAVAC) $(JAVAC_FLAGS) $< - -define MAKE_OBJDIR -if test ! -d $(@D); then rm -rf $(@D); mkdir -p $(@D); fi -endef - -ifdef DIRS -LOOP_OVER_DIRS = \ - @for d in $(DIRS); do \ - if test -d $$d; then \ - set -e; \ - echo "cd $$d; $(MAKE) -f Makefile.ref $@"; \ - cd $$d; $(MAKE) -f Makefile.ref $@; cd ..; \ - set +e; \ - else \ - echo "Skipping non-directory $$d..."; \ - fi; \ - done -endif - -ifdef PREDIRS -LOOP_OVER_PREDIRS = \ - @for d in $(PREDIRS); do \ - if test -d $$d; then \ - set -e; \ - echo "cd $$d; $(MAKE) -f Makefile.ref $@"; \ - cd $$d; $(MAKE) -f Makefile.ref $@; cd ..; \ - set +e; \ - else \ - echo "Skipping non-directory $$d..."; \ - fi; \ - done -endif - -export: - +$(LOOP_OVER_PREDIRS) - mkdir -p $(DIST)/include $(DIST)/$(LIBDIR) $(DIST)/bin -ifneq "$(strip $(HFILES))" "" - $(CP) $(HFILES) $(DIST)/include -endif -ifneq "$(strip $(LIBRARY))" "" - $(CP) $(LIBRARY) $(DIST)/$(LIBDIR) -endif -ifneq "$(strip $(JARS))" "" - $(CP) $(JARS) $(DIST)/$(LIBDIR) -endif -ifneq "$(strip $(SHARED_LIBRARY))" "" - $(CP) $(SHARED_LIBRARY) $(DIST)/$(LIBDIR) -endif -ifneq "$(strip $(PROGRAM))" "" - $(CP) $(PROGRAM) $(DIST)/bin -endif - +$(LOOP_OVER_DIRS) - -distclean: -clean: - rm -rf $(OBJS) - rm -f obj/*.o - rm -f obj/libjs.a - rm -f fdlibm/obj/libfdm.a - rm -f editline/obj/*.o - rm -f editline/obj/libedit.a - @cd fdlibm; $(MAKE) -f Makefile.ref clean - -clobber: - rm -rf $(OBJS) $(TARGETS) $(DEPENDENCIES) - @cd fdlibm; $(MAKE) -f Makefile.ref clobber - -depend: - gcc -MM $(CFLAGS) $(LIB_CFILES) - -tar: - tar cvf $(TARNAME) $(TARFILES) - gzip $(TARNAME) - diff --git a/lib/javascript/sh/README.html b/lib/javascript/sh/README.html deleted file mode 100644 index e7f30d51..00000000 --- a/lib/javascript/sh/README.html +++ /dev/null @@ -1,229 +0,0 @@ - - - - - - Specification for the JavaScript shell - - - -
    -

    -Object hierarchy for JS Shell:

    -  -
    - - - - - - - -
    - - - - - - - - -
     System 
    -
    Methods
    - -
      -
    • -chdir
    • - -
    • -pipe
    • - -
    • -script
    • - -
    • -exit
    • - -
    • -system
    • - -
    • -gc
    • - -
    • -call (executes an external script)
    • - -
    • -use (make methods of the script you pass available. I.e. if -you say use('Foo','Bar'), you can now call Foo.f() and Bar.f(). -Foo.eval() will evaluate all the code)
    • -
    - -
    Properties
    - -
      -
    • -stdout
    • - -
    • -stdin
    • - -
    • -stderr 
    • - -
    • -platform ('PC', 'UNIX', 'MAC')
    • - -
    • -ARGV (arguments passed to the script)
    • -
    -Notes: pipe works -like backticks in Perl; script works the other way around, -that is, you give it an array and it feeds the array to the executable -you specify (somewhat similar to the script command on UNIX).
    - - - - - - - - -
    Environment
    -
    Properties
    - - -

    All environment variables become properties of -Environment. Assigning to them actually changes the environment.

    - - - - - - - - -
    File
    - - - - - - -
    -
    Properties
    - -
     
    - -
  • -currentDir
  • - -
  • -length 
  • - -
  • -parent 
  • - -
  • -path 
  • - -
  • -name 
  • - -
  • -isDirectory
  • - -
  • -isFile 
  • - -
  • -exists 
  • - -
  • -canRead 
  • - -
  • -canWrite 
  • - -
  • -opened 
  • - -
  • -type 
  • - -
  • -mode 
  • - -
  • -creationTime
  • - -
  • -lastModified
  • - -
  • -size 
  • - -
  • -randomAccess
  • - -
  • -position
  • -
    -
    Methods
    - -
     
    - -
  • -open 
  • - -
  • -close 
  • - -
  • -remove 
  • - -
  • -copyTo 
  • - -
  • -renameTo
  • - -
  • -flush 
  • - -
  • -skip 
  • - -
  • -read 
  • - -
  • -readln 
  • - -
  • -readAll 
  • - -
  • -write 
  • - -
  • -writeln 
  • - -
  • -writeAll
  • - -
  • -list 
  • - -
  • -mkdir 
  • -
    (Henri's stuff)  -
     
    -  -
      - - diff --git a/lib/javascript/sh/jssh.c b/lib/javascript/sh/jssh.c deleted file mode 100644 index a179aec4..00000000 --- a/lib/javascript/sh/jssh.c +++ /dev/null @@ -1,719 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * The contents of this file are subject to the Netscape Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/NPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is Netscape - * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1998 Netscape Communications Corporation. All - * Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU Public License (the "GPL"), in which case the - * provisions of the GPL are applicable instead of those above. - * If you wish to allow use of your version of this file only - * under the terms of the GPL and not to allow others to use your - * version of this file under the NPL, indicate your decision by - * deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete - * the provisions above, a recipient may use your version of this - * file under either the NPL or the GPL. - */ - -/* Copyright © 1998 Netscape Communications Corporation, All Rights Reserved.*/ -/* JavaScript Shell: jssh. Provides capabilities for calling commans, */ -/* loading libraries, etc. in JavaScript. For a full list of features, see -/* README.html */ -#include -#include -#include - -#include "jsapi.h" /* The API itself */ -#include "jsatom.h" -#ifdef HAS_FILE_SUPPORT /* File object */ -# include "jsfile.h" -#endif -#ifdef LIVECONNECT /* link w/LiveConnect DLL */ -# include "jsjava.h" -#endif -#ifdef PERLCONNECT /* link w/PerlConnect DLL */ -# include "jsperl.h" -#endif - -#define STACK_CHUNK_SIZE 8192 -/* Platform-dependent stuff */ -#ifdef XP_PC -# define ENVIRON _environ -# define PUTENV _putenv -# define POPEN _popen -# define PCLOSE _pclose -# define PLATFORM "PC" -#elif XP_UNIX -# define ENVIRON environ -# define PUTENV putenv -# define POPEN popen -# define PCLOSE pclose -# define PLATFORM "UNIX" -#elif XP_BEOS -# define ENVIRON environ -# define PUTENV putenv -# define POPEN popen -# define PCLOSE pclose -# define PLATFORM "BeOS" -#else -# error "Platform not supported." -#endif - - -/* globals */ -JSRuntime *rt; -JSContext *cx; -JSObject *globalObject, *systemObject, *envObject; -/* forward-definitions */ -static JSBool Process(JSContext*, JSObject*, char*, jsval *rval); -static JSBool environment_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp); - -/* global class */ -JSClass globalClass = { - "Global", 0, - JS_PropertyStub, JS_PropertyStub,JS_PropertyStub, JS_PropertyStub, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub -}; - -/* system class */ -JSClass systemClass = { - "System", 0, - JS_PropertyStub, JS_PropertyStub,JS_PropertyStub, JS_PropertyStub, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub -}; - -/* environment class */ -JSClass envClass = { - "Environment", 0, - JS_PropertyStub, environment_setProperty, JS_PropertyStub, JS_PropertyStub, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub -}; - -/* object loaded via use() get a separate namespace of this type */ -JSClass libraryClass = { - "Library", JSCLASS_HAS_PRIVATE, - JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub -}; - -/****************************** global methods ******************************/ -/* load JS files in argv and execute them */ -static JSBool -call(JSContext *cx, JSObject *obj, int argc, jsval *argv, jsval* rval){ - int i; - char *ch; - JSBool result = JS_TRUE; - FILE *file; - static char* processFile(FILE*); - - for(i=0;ilength; i++) { - jschar *prop; - JSString *str; - - JS_IdToValue(cx, ida->vector[i], &v); - str = JS_ValueToString(cx, v); - prop = JS_GetStringChars(str); - JS_GetUCProperty(cx, scriptObject, prop, JS_GetStringLength(str), &v); - /* add v if it's a function */ - if(JS_TypeOfValue(cx, v) == JSTYPE_FUNCTION){ - char const *name = JS_GetFunctionName(JS_ValueToFunction(cx, v)); - JS_DefineProperty(cx, scriptObject, name, v, NULL, NULL, - JSPROP_READONLY|JSPROP_PERMANENT); - } - } - - /* save script as private data for the object */ - if(!JS_SetPrivate(cx, scriptObject, (void*)script)){ - return JS_FALSE; - } - JS_DefineFunction(cx, scriptObject, "eval", evalScript, 0, 0); - } - return JS_TRUE; -} - -/********************** Define system methods **************************/ -/* a replacement for System.out.write */ -static JSBool -system_print(JSContext *cx, JSObject *obj, int argc, jsval *argv, jsval* rval){ - int i; - JSString *str; - - for(i=0;ifilename, report->lineno, message); -} - -/* add properties to Env */ -static void -readEnvironment(JSContext *cx, JSObject *env){ - char **currEnvString; - char currEnvName [256]; - char currEnvValue[1024]; /* this must be big enough */ - JSString *str; - JSBool ok; - - for(currEnvString = ENVIRON; *currEnvString!=NULL; currEnvString++){ - char *equal = strchr(*currEnvString, '='); - strncpy(currEnvName, *currEnvString, equal-*currEnvString); - currEnvName[equal-*currEnvString] = 0; /* append null char at the end */ - equal++; - strncpy(currEnvValue, equal, *currEnvString+strlen(*currEnvString)-equal+1); - str=JS_NewStringCopyZ(cx, equal/*, *currEnvString+strlen(*currEnvString)-equal*/); - if(!str) { - JS_ReportError(cx, "Error in readEnvironment, str==NULL"); - return; - } - /* add a new property to env object */ - ok = JS_DefineProperty(cx, env, currEnvName, - STRING_TO_JSVAL(str), JS_PropertyStub, environment_setProperty, - JSPROP_ENUMERATE|JSPROP_PERMANENT); - if(!ok) { - JS_ReportError(cx, "Error in readEnvironment, can't define a property"); - return; - } - } -} - -/* formatted output of the environment */ -static JSBool -env_toString(JSContext *cx, JSObject *obj, int argc, jsval *argv, jsval* rval){ - char **currEnvString; - char currEnvName [256]; - char currEnvValue[1024]; /* this must be big enough */ - - char *result; - int len=0; - - result = JS_malloc(cx, 1); - strcpy(result, ""); - - for(currEnvString = ENVIRON; *currEnvString!=NULL; currEnvString++){ - char *equal = strchr(*currEnvString, '='), *p; - char line[1024]; - - strncpy(currEnvName, *currEnvString, equal-*currEnvString); - currEnvName[equal-*currEnvString] = 0; /* append null char at the end */ - equal++; - strncpy(currEnvValue, equal, *currEnvString+strlen(*currEnvString)-equal+1); - sprintf(line, "%25s = %s\n", currEnvName, currEnvValue); - len+=strlen(line)+1; - p = (char*)JS_realloc(cx, result, len*sizeof(char)); - if(!p) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - strcpy(p, result); - result=p; - strcat(result, line); - } - - //JS_free(cx, result); - - *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, result)); - return JS_TRUE; -} - -/*************************************************************************/ -/* methods available */ -JSFunctionSpec globalMethods[] = { - {"call", call, 0, 0}, - {"use", use, 0, 0}, - { NULL, NULL, 0, 0} -}; - -JSFunctionSpec systemMethods[] = { - {"print", system_print, 0, 0}, - {"version", system_version, 0, 0}, - {"system", system_system, 0, 0}, - {"gc", system_gc, 0, 0}, - {"pipe", system_pipe, 0, 0}, - {"script", system_script, 0, 0}, - //{"help", system_help, 0, 0}, - {"exit", system_exit, 0, 0}, - { NULL, NULL, 0, 0} -}; - -JSFunctionSpec envMethods[] = { - {"toString", env_toString, 0}, - { NULL, NULL,0 } -}; - -/* - Read a file. Return it as a char pointer that - should be deallocated. Ignore #-comments. -*/ -static char* -processFile(FILE *file){ - char *buf, *bufEnd, *bufUpto, ch; - int bufLen, len; - - /* read the file into memory */ - bufLen = 4096; - buf = malloc(bufLen); /* allocate character buffer */ - bufEnd = buf+bufLen; /* end of the buffer */ - bufUpto = buf; /* current buffer pointer */ - - ch=fgetc(file); /* ignore first line starting with # */ - if(ch=='#') - while((ch=fgetc(file))!=EOF) { if(ch=='\n') break;} - else - ungetc(ch,file); - - while((len=fread(bufUpto, sizeof(char), bufEnd-bufUpto, file))>0){ - bufUpto+=len; - if(bufUpto>=bufEnd) { /* expand the buffer if needed */ - bufLen+=bufLen; - bufEnd=buf+bufLen; - buf=realloc(buf,bufLen); - } - } - *bufUpto = '\0'; - //puts(buf); - return buf; -} - -/* - Read JavaScript source from file or stdin if !filename - Evaluate it. -*/ -static JSBool -Process(JSContext *cx, JSObject *obj, char *filename, jsval *rval){ - FILE *file; - char *ch; - - /* Process the input */ - if(filename){ - file = fopen(filename, "r"); - if(file==NULL){ - JS_ReportError(cx, "Can't open %s\n", filename); - return JS_FALSE; - } - - ch = processFile(file); - JS_EvaluateScript(cx, obj, ch, strlen(ch), "jssh", 0, rval); - free(ch); - fclose(file); - }else{ - /* process input line-by-line */ - char line[256]; - int currLine = 0; - JSString *str; - do{ - printf("js> "); - gets(line); - *rval = JSVAL_VOID; - JS_EvaluateScript(cx, globalObject, line, strlen(line), "jss", ++currLine, rval); - if(!JSVAL_IS_VOID(*rval)){ - str=JS_ValueToString(cx, *rval); - if(!str){ - JS_ReportError(cx, "Can't convert to string"); - } - printf("%s\n", JS_GetStringBytes(str)); - } - }while(1); /* need to type 'exit' to exit */ - } -} - -static int -usage(){ - fprintf(stderr, "%s", JS_GetImplementationVersion()); - fputs("usage: js [ [scriptfile] [scriptarg...] | - ]", stderr); - return 2; -} - -/* - This is taken from JSShell. -*/ -static int -ProcessArgs(JSContext *cx, JSObject *obj, char **argv, int argc){ - int i; - char *filename; - jsval *vector; - jsval *p; - JSObject *argsObj; - jsval rval; - JSBool ok; - - /* prompt */ - if(argc<2 || !strcmp(argv[1], "-")) - filename = NULL; - else if(argc==2) - filename = argv[1]; - else - return usage(); - - vector = JS_malloc(cx, (argc-1)* sizeof(jsval)); - p = vector; - if(!p){ - JS_ReportError(cx, "Error in ProcessArgs, p==NULL!"); - } - - for(i=1;i -# Microsoft Developer Studio Generated Build File, Format Version 5.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=jssh - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "jssh.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "jssh.mak" CFG="jssh - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "jssh - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "jssh - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "jssh - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 - -!ELSEIF "$(CFG)" == "jssh - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "XP_PC" /D "HAS_FILE_SUPPORT" /YX /FD /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 js32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:".." /libpath:"../Debug" /libpath:"../Release" - -!ENDIF - -# Begin Target - -# Name "jssh - Win32 Release" -# Name "jssh - Win32 Debug" -# Begin Source File - -SOURCE=.\jssh.c -# End Source File -# End Target -# End Project diff --git a/lib/javascript/sh/jssh.dsw b/lib/javascript/sh/jssh.dsw deleted file mode 100644 index ee9ab3e5..00000000 --- a/lib/javascript/sh/jssh.dsw +++ /dev/null @@ -1,29 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 5.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "jssh"=.\jssh.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/lib/javascript/win32.order b/lib/javascript/win32.order deleted file mode 100644 index cf4e8c41..00000000 --- a/lib/javascript/win32.order +++ /dev/null @@ -1,391 +0,0 @@ -js_MarkGCThing ; 5893956 -JS_GetPrivate ; 2090130 -JS_HashTableRawLookup ; 1709984 -js_Mark ; 1547496 -js_GetToken ; 1406677 -js_UngetToken ; 1154416 -js_MarkAtom ; 992874 -js_MatchToken ; 980277 -js_CompareStrings ; 662772 -js_Lock ; 628184 -js_Unlock ; 628184 -js_AtomizeString ; 611102 -js_HashString ; 611102 -js_DropScopeProperty ; 546476 -JS_malloc ; 484350 -js_Atomize ; 464433 -js_InflateStringToBuffer ; 460739 -js_HoldScopeProperty ; 442612 -JS_free ; 382991 -js_MarkScript ; 376942 -js_HashId ; 365238 -JS_CompareValues ; 352366 -js_IdToValue ; 337594 -JS_GetClass ; 325296 -js_LookupProperty ; 324680 -js_GetAtom ; 244669 -js_DropProperty ; 223217 -JS_GetParent ; 209680 -js_LiveContext ; 205767 -js_PeekToken ; 200646 -js_GetSlotThreadSafe ; 198839 -JS_GetStringChars ; 190862 -JS_HashTableRawAdd ; 179156 -js_FoldConstants ; 162626 -js_EmitTree ; 145634 -JS_EnumerateStub ; 140640 -js_NewSrcNote ; 136983 -js_GetProperty ; 135639 -js_NewScopeProperty ; 135057 -js_MutateScope ; 135057 -js_GetMutableScope ; 135057 -js_AllocSlot ; 132401 -JS_GetRuntime ; 127316 -JS_FrameIterator ; 121963 -JS_GetFrameFunctionObject ; 120567 -js_AllocGCThing ; 119828 -js_DestroyScopeProperty ; 115989 -js_Emit3 ; 109135 -js_AtomizeChars ; 108038 -JS_HashTableLookup ; 107154 -JS_InstanceOf ; 103905 -js_DefineProperty ; 99514 -js_strncpy ; 88276 -js_PeekTokenSameLine ; 87197 -js_HoldObjectMap ; 79084 -js_DropObjectMap ; 77824 -js_NewObject ; 72421 -js_ValueToString ; 72143 -js_GetClassPrototype ; 66235 -js_UnlockRuntime ; 64699 -js_LockRuntime ; 64699 -js_ContextIterator ; 64586 -JS_ClearWatchPointsForObject ; 64155 -js_FinalizeObject ; 63925 -js_IndexAtom ; 63789 -JS_SetPrivate ; 63702 -JS_GetGlobalObject ; 63546 -js_Emit1 ; 63012 -JS_ContextIterator ; 57847 -JS_GetInstancePrivate ; 57817 -JS_HashTableRawRemove ; 57057 -js_AllocRawStack ; 54181 -js_Invoke ; 53568 -js_FindProperty ; 53150 -JS_GetFrameScript ; 51395 -js_LinkFunctionObject ; 50651 -js_SetSrcNoteOffset ; 47735 -js_InWithStatement ; 47346 -js_NewFunction ; 47074 -js_NewSrcNote2 ; 46165 -JS_HashTableAdd ; 45503 -JS_HashTableRemove ; 45213 -js_InCatchBlock ; 42198 -js_AddRootRT ; 40587 -js_AddRoot ; 40587 -js_SetProperty ; 40558 -JS_AddNamedRoot ; 40462 -js_RemoveRoot ; 40384 -JS_RemoveRootRT ; 38129 -js_NewString ; 37471 -js_DefineFunction ; 36629 -JS_GetContextThread ; 36498 -JS_LookupProperty ; 35137 -JS_ValueToString ; 34072 -JS_realloc ; 33776 -JS_DefineFunction ; 33268 -JS_SetErrorReporter ; 32851 -js_FinalizeString ; 30311 -js_FinalizeStringRT ; 30311 -JS_ArenaAllocate ; 30099 -JS_BeginRequest ; 29323 -JS_EndRequest ; 29323 -JS_GetContextPrivate ; 29189 -JS_CompactArenaPool ; 28874 -js_ValueToStringAtom ; 27934 -JS_ValueToId ; 26517 -js_ValueToBoolean ; 25908 -JS_InternString ; 25467 -js_PopStatement ; 24364 -js_PushStatement ; 24364 -js_NewStringCopyN ; 23911 -js_FlushPropertyCacheByProp ; 23883 -js_GetStringBytes ; 23421 -JS_ArenaRelease ; 23267 -JS_GetStringBytes ; 23106 -js_FreeStack ; 22399 -js_AllocStack ; 22399 -JS_SetProperty ; 21240 -js_InitObjectMap ; 19991 -js_NewScope ; 19991 -js_strlen ; 19070 -JS_GetScriptPrincipals ; 18063 -js_SrcNoteLength ; 17369 -js_DestroyObjectMap ; 17198 -js_DestroyScope ; 17198 -JS_GetStringLength ; 16306 -js_PopStatementCG ; 15418 -JS_GetFrameAnnotation ; 14949 -js_FreeRawStack ; 14032 -js_Interpret ; 14032 -js_TransferScopeLock ; 13899 -JS_ResolveStandardClass ; 13645 -JS_ResumeRequest ; 12837 -JS_SuspendRequest ; 12837 -JS_GetProperty ; 12488 -JS_NewObject ; 11660 -js_AllocTryNotes ; 11418 -js_NewNumberValue ; 10859 -js_InternalInvoke ; 10051 -js_NewDouble ; 9936 -js_SetJumpOffset ; 9886 -js_SkipWhiteSpace ; 9299 -js_NewDoubleValue ; 7474 -JS_GetPendingException ; 7404 -js_NewObjectMap ; 7236 -JS_ClearPendingException ; 7092 -JS_strtod ; 7053 -js_strtod ; 7053 -js_InflateString ; 7004 -JS_GetFunctionName ; 6808 -JS_NewHashTable ; 6794 -JS_NewFunction ; 6575 -js_FreeSlot ; 6476 -js_LockScope ; 6332 -JS_HashTableEnumerateEntries ; 6285 -js_GetLengthProperty ; 6162 -js_LockObj ; 6149 -JS_NewUCStringCopyN ; 5994 -JS_NewNumberValue ; 5904 -js_NewStringCopyZ ; 5809 -JS_NewUCStringCopyZ ; 5809 -js_DeflateString ; 5612 -js_ValueToNumber ; 5456 -JS_SetOptions ; 5322 -js_NewScript ; 4941 -js_InitCodeGenerator ; 4810 -js_FinishTakingSrcNotes ; 4810 -js_NewScriptFromParams ; 4810 -js_InitAtomMap ; 4810 -js_FinishTakingTryNotes ; 4810 -js_NewScriptFromCG ; 4810 -js_FinishCodeGenerator ; 4810 -JS_strdup ; 4534 -JS_HashTableDestroy ; 4119 -js_CheckRedeclaration ; 3965 -JS_DefineFunctions ; 3808 -js_EmitFunctionBody ; 3739 -js_TryMethod ; 3685 -js_DefaultValue ; 3610 -js_CloneFunctionObject ; 3577 -JS_InitClass ; 3546 -js_SetClassPrototype ; 3377 -JS_GetPrototype ; 3268 -JS_DefineProperties ; 3115 -js_FindVariable ; 3093 -js_DestroyScript ; 3041 -JS_ClearScriptTraps ; 3041 -js_FreeAtomMap ; 3041 -JS_NewStringCopyZ ; 2953 -js_AtomizeObject ; 2709 -JS_ValueToBoolean ; 2643 -js_SetLengthProperty ; 2637 -JS_GetOptions ; 2593 -js_ValueToObject ; 2522 -js_ValueToNonNullObject ; 2510 -js_StringToObject ; 2482 -JS_SetElement ; 2448 -js_NumberToString ; 2407 -JS_TypeOfValue ; 2275 -js_NewBufferTokenStream ; 2253 -js_NewTokenStream ; 2253 -js_CloseTokenStream ; 2253 -JS_RemoveRoot ; 2148 -JS_NewDouble ; 2129 -JS_vsnprintf ; 1937 -JS_snprintf ; 1937 -JS_CallFunctionValue ; 1844 -JS_DHashVoidPtrKeyStub ; 1840 -JS_DHashTableOperate ; 1840 -js_SetProtoOrParent ; 1758 -js_DoubleToInteger ; 1729 -JS_SetVersion ; 1531 -js_ValueToFunction ; 1476 -JS_SetPrototype ; 1408 -JS_CeilingLog2 ; 1317 -js_Execute ; 1199 -js_CompileFunctionBody ; 1182 -JS_CompileUCFunctionForPrincipals ; 1182 -js_GetSrcNoteOffset ; 1139 -JS_DHashMatchEntryStub ; 1094 -JS_VersionToString ; 1090 -JS_CompileUCScriptForPrincipals ; 1071 -js_CompileTokenStream ; 1071 -js_CurrentThreadId ; 1058 -JS_IdToValue ; 1046 -js_ConstructObject ; 974 -JS_DestroyScript ; 967 -js_PCToLineNumber ; 967 -JS_DefineProperty ; 930 -JS_GetScriptFilename ; 924 -JS_GetFramePC ; 899 -JS_EvaluateUCScriptForPrincipals ; 892 -JS_PCToLineNumber ; 848 -JS_StringToVersion ; 761 -js_ExecuteRegExp ; 755 -JS_MaybeGC ; 717 -JS_ValueToNumber ; 698 -JS_GetVersion ; 698 -JS_AliasProperty ; 693 -js_AtomizeValue ; 664 -js_BooleanToString ; 664 -js_SetSlotThreadSafe ; 596 -JS_DHashClearEntryStub ; 584 -JS_DHashTableRawRemove ; 584 -JS_DefineObject ; 557 -js_PutCallObject ; 516 -js_GetCallObject ; 516 -js_strchr ; 511 -JS_DefineUCProperty ; 480 -JS_dtostr ; 475 -JS_ValueToInt32 ; 464 -js_ValueToInt32 ; 464 -JS_FinishArenaPool ; 453 -js_NewTryNote ; 441 -js_strtointeger ; 437 -JS_vsmprintf ; 428 -JS_DHashTableInit ; 423 -JS_DHashAllocTable ; 423 -JS_DHashGetStubOps ; 423 -JS_NewDHashTable ; 423 -JS_DHashTableDestroy ; 423 -JS_DHashFreeTable ; 423 -JS_DHashTableFinish ; 423 -js_EmitBreak ; 412 -js_GetAttributes ; 412 -JS_DefineConstDoubles ; 407 -JS_ArenaGrow ; 374 -js_AtomizeInt ; 372 -JS_SetParent ; 345 -JS_CloneFunctionObject ; 343 -JS_IsNativeFrame ; 343 -JS_ReportErrorNumber ; 340 -js_ErrorToException ; 340 -js_ReportErrorNumberVA ; 340 -js_GetErrorMessage ; 340 -js_ExpandErrorArguments ; 340 -js_ReportUncaughtException ; 315 -JS_IsExceptionPending ; 315 -js_ReportErrorAgain ; 315 -js_ErrorFromException ; 315 -JS_LookupUCProperty ; 307 -JS_InitArenaPool ; 293 -PRMJ_Now ; 262 -DllMain@12 ; 235 -JS_ExecuteScript ; 232 -JS_GetFrameFunction ; 226 -PRMJ_LocalGMTDifference ; 175 -JS_GetConstructor ; 175 -JS_SetGlobalObject ; 164 -js_LockGCThing ; 155 -js_NewRegExpObject ; 152 -js_NewRegExp ; 152 -js_InitObjectClass ; 131 -js_InitFunctionClass ; 131 -js_EmitN ; 128 -JS_ArenaFinish ; 124 -js_GC ; 124 -js_SweepAtomState ; 124 -js_MarkAtomState ; 124 -JS_ArenaRealloc ; 124 -js_ForceGC ; 124 -js_FlushPropertyCache ; 122 -js_InitNumberClass ; 114 -JS_smprintf ; 112 -js_DoubleToECMAInt32 ; 112 -js_ValueToECMAInt32 ; 111 -JS_ValueToECMAInt32 ; 111 -JS_SetContextPrivate ; 109 -PRMJ_DSTOffset ; 108 -js_Clear ; 105 -JS_ClearScope ; 105 -JS_NewScriptObject ; 104 -JS_smprintf_free ; 104 -JS_ConvertValue ; 99 -js_GetSrcNote ; 98 -JS_ValueToECMAUint32 ; 93 -js_ValueToECMAUint32 ; 93 -js_printf ; 93 -js_DoubleToECMAUint32 ; 93 -js_DestroyRegExp ; 89 -js_UnlockGCThing ; 89 -js_TryValueOf ; 87 -js_NewSrcNote3 ; 86 -JS_ConvertStub ; 81 -JS_SetPendingException ; 80 -js_InitStringClass ; 79 -JS_GC ; 78 -js_InitArrayClass ; 74 -js_InitDateClass ; 67 -JS_NewContext ; 64 -JS_AddArgumentFormatter ; 64 -js_InitContextForLocking ; 64 -js_NewContext ; 64 -JS_SetBranchCallback ; 64 -JS_ClearRegExpStatics ; 64 -js_InitRegExpStatics ; 64 -js_InitCallClass ; 63 -js_InitRegExpClass ; 61 -js_Enumerate ; 58 -JS_DestroyContext ; 46 -js_DestroyContext ; 46 -js_FreeRegExpStatics ; 46 -js_InitScanner ; 39 -js_NewPrinter ; 36 -js_DestroyPrinter ; 36 -js_GetPrinterOutput ; 36 -JS_FreeArenaPool ; 36 -js_DecompileCode ; 34 -js_EmitContinue ; 33 -js_CheckAccess ; 30 -js_DecompileValueGenerator ; 28 -js_InitMathClass ; 27 -js_InitExceptionClasses ; 25 -js_NewArrayObject ; 24 -js_InitArgumentsClass ; 21 -js_puts ; 20 -js_InitBooleanClass ; 19 -JS_InitStandardClasses ; 19 -js_InitScriptClass ; 19 -js_obj_toString ; 15 -js_GetArgsValue ; 14 -js_GetArgsObject ; 14 -js_AtomizeDouble ; 12 -JS_DestroyIdArray ; 11 -js_NewIdArray ; 11 -JS_GetElement ; 11 -JS_EvaluateScript ; 9 -JS_EvaluateUCScript ; 9 -JS_DecompileFunction ; 8 -js_DecompileFunction ; 8 -JS_NewString ; 8 -js_SetStringBytes ; 8 -JS_GetArrayLength ; 7 -JS_NewArrayObject ; 7 -JS_IsArrayObject ; 7 -JS_ValueToObject ; 7 -JS_DefineElement ; 6 -js_DecompileScript ; 6 -JS_PushArguments ; 4 -JS_PopArguments ; 4 -JS_PushArgumentsVA ; 4 -js_PutArgsObject ; 2 -JS_SetGCCallbackRT ; 2 -JS_Init ; 1 -js_SetupLocks ; 1 -js_InitRuntimeNumberState ; 1 -js_InitRuntimeStringState ; 1 -js_InitLock ; 1 -js_InitGC ; 1 -js_InitAtomState ; 1 -js_InitStringGlobals ; 1