diff --git a/cmake/V8Deps.cmake b/cmake/V8Deps.cmake index 24907a711e..75e4a50dab 100644 --- a/cmake/V8Deps.cmake +++ b/cmake/V8Deps.cmake @@ -1,4 +1,3 @@ - set(NODEDIR "${EXTDIR}/libnode-v6.9.0/") set(V8_INCLUDE_DIRS ${NODEDIR}/src ${NODEDIR}/deps/uv/include ${NODEDIR}/deps/v8/include ${NODEDIR}/deps/cares/include) @@ -23,8 +22,10 @@ if (WIN32) ) elseif (APPLE) set(V8_LIBRARY_DIRS ${NODEDIR}) + set (V8_INCLUDE_DIRS ${V8_INCLUDE_DIRS} ${NODEDIR}/deps/icu-small/source/common/) set(V8_LIBRARIES node) else () + set (V8_INCLUDE_DIRS ${V8_INCLUDE_DIRS} ${NODEDIR}/deps/icu-small/source/common/) set(V8_LIBRARY_DIRS ${NODEDIR}/out/Release/obj.target ${NODEDIR}/out/Release/obj.target/deps/v8_inspector/third_party/v8_inspector/platform/v8_inspector @@ -47,9 +48,9 @@ else () zlib http_parser icustubdata - icui18n - icuucx icudata + icuucx + icui18n ) endif () diff --git a/examples/pxScene2d/external/libnode-v6.9.0/buildNode.sh b/examples/pxScene2d/external/libnode-v6.9.0/buildNode.sh index 4872e4c182..4991935791 100755 --- a/examples/pxScene2d/external/libnode-v6.9.0/buildNode.sh +++ b/examples/pxScene2d/external/libnode-v6.9.0/buildNode.sh @@ -1,4 +1,4 @@ ./configure --shared -make +make -j ln -sf libnode.so.48 out/Release/obj.target/libnode.so ln -sf libnode.48.dylib out/Release/libnode.dylib diff --git a/examples/pxScene2d/external/zlib-1.2.11/Makefile b/examples/pxScene2d/external/zlib-1.2.11/Makefile index 6bba86c73f..6bbf05512c 100644 --- a/examples/pxScene2d/external/zlib-1.2.11/Makefile +++ b/examples/pxScene2d/external/zlib-1.2.11/Makefile @@ -1,5 +1,410 @@ -all: - -@echo "Please use ./configure first. Thank you." +# Makefile for zlib +# Copyright (C) 1995-2017 Jean-loup Gailly, Mark Adler +# For conditions of distribution and use, see copyright notice in zlib.h -distclean: - make -f Makefile.in distclean +# To compile and test, type: +# ./configure; make test +# Normally configure builds both a static and a shared library. +# If you want to build just a static library, use: ./configure --static + +# To use the asm code, type: +# cp contrib/asm?86/match.S ./match.S +# make LOC=-DASMV OBJA=match.o + +# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type: +# make install +# To install in $HOME instead of /usr/local, use: +# make install prefix=$HOME + +CC=gcc + +CFLAGS=-O3 -DHAVE_HIDDEN +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-g -DZLIB_DEBUG +#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ +# -Wstrict-prototypes -Wmissing-prototypes + +SFLAGS=-O3 -fPIC -DHAVE_HIDDEN +LDFLAGS= +TEST_LDFLAGS=-L. libz.a +LDSHARED=gcc -dynamiclib -install_name ${exec_prefix}/lib/libz.1.dylib -compatibility_version 1 -current_version 1.2.11 +CPP=gcc -E + +STATICLIB=libz.a +SHAREDLIB=libz.dylib +SHAREDLIBV=libz.1.2.11.dylib +SHAREDLIBM=libz.1.dylib +LIBS=$(STATICLIB) $(SHAREDLIBV) + +AR=libtool +ARFLAGS=-o +RANLIB=ranlib +LDCONFIG=ldconfig +LDSHAREDLIBC=-lc +TAR=tar +SHELL=/bin/sh +EXE= + +prefix =/usr/local +exec_prefix =${prefix} +libdir =${exec_prefix}/lib +sharedlibdir =${libdir} +includedir =${prefix}/include +mandir =${prefix}/share/man +man3dir = ${mandir}/man3 +pkgconfigdir = ${libdir}/pkgconfig +SRCDIR= +ZINC= +ZINCOUT=-I. + +OBJZ = adler32.o crc32.o deflate.o infback.o inffast.o inflate.o inftrees.o trees.o zutil.o +OBJG = compress.o uncompr.o gzclose.o gzlib.o gzread.o gzwrite.o +OBJC = $(OBJZ) $(OBJG) + +PIC_OBJZ = adler32.lo crc32.lo deflate.lo infback.lo inffast.lo inflate.lo inftrees.lo trees.lo zutil.lo +PIC_OBJG = compress.lo uncompr.lo gzclose.lo gzlib.lo gzread.lo gzwrite.lo +PIC_OBJC = $(PIC_OBJZ) $(PIC_OBJG) + +# to use the asm code: make OBJA=match.o, PIC_OBJA=match.lo +OBJA = +PIC_OBJA = + +OBJS = $(OBJC) $(OBJA) + +PIC_OBJS = $(PIC_OBJC) $(PIC_OBJA) + +all: static shared + +static: example$(EXE) minigzip$(EXE) + +shared: examplesh$(EXE) minigzipsh$(EXE) + +all64: example64$(EXE) minigzip64$(EXE) + +check: test + +test: all teststatic testshared + +teststatic: static + @TMPST=tmpst_$$; \ + if echo hello world | ./minigzip | ./minigzip -d && ./example $$TMPST ; then \ + echo ' *** zlib test OK ***'; \ + else \ + echo ' *** zlib test FAILED ***'; false; \ + fi; \ + rm -f $$TMPST + +testshared: shared + @LD_LIBRARY_PATH=`pwd`:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \ + LD_LIBRARYN32_PATH=`pwd`:$(LD_LIBRARYN32_PATH) ; export LD_LIBRARYN32_PATH; \ + DYLD_LIBRARY_PATH=`pwd`:$(DYLD_LIBRARY_PATH) ; export DYLD_LIBRARY_PATH; \ + SHLIB_PATH=`pwd`:$(SHLIB_PATH) ; export SHLIB_PATH; \ + TMPSH=tmpsh_$$; \ + if echo hello world | ./minigzipsh | ./minigzipsh -d && ./examplesh $$TMPSH; then \ + echo ' *** zlib shared test OK ***'; \ + else \ + echo ' *** zlib shared test FAILED ***'; false; \ + fi; \ + rm -f $$TMPSH + +test64: all64 + @TMP64=tmp64_$$; \ + if echo hello world | ./minigzip64 | ./minigzip64 -d && ./example64 $$TMP64; then \ + echo ' *** zlib 64-bit test OK ***'; \ + else \ + echo ' *** zlib 64-bit test FAILED ***'; false; \ + fi; \ + rm -f $$TMP64 + +infcover.o: $(SRCDIR)test/infcover.c $(SRCDIR)zlib.h zconf.h + $(CC) $(CFLAGS) $(ZINCOUT) -c -o $@ $(SRCDIR)test/infcover.c + +infcover: infcover.o libz.a + $(CC) $(CFLAGS) -o $@ infcover.o libz.a + +cover: infcover + rm -f *.gcda + ./infcover + gcov inf*.c + +libz.a: $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + -@ ($(RANLIB) $@ || true) >/dev/null 2>&1 + +match.o: match.S + $(CPP) match.S > _match.s + $(CC) -c _match.s + mv _match.o match.o + rm -f _match.s + +match.lo: match.S + $(CPP) match.S > _match.s + $(CC) -c -fPIC _match.s + mv _match.o match.lo + rm -f _match.s + +example.o: $(SRCDIR)test/example.c $(SRCDIR)zlib.h zconf.h + $(CC) $(CFLAGS) $(ZINCOUT) -c -o $@ $(SRCDIR)test/example.c + +minigzip.o: $(SRCDIR)test/minigzip.c $(SRCDIR)zlib.h zconf.h + $(CC) $(CFLAGS) $(ZINCOUT) -c -o $@ $(SRCDIR)test/minigzip.c + +example64.o: $(SRCDIR)test/example.c $(SRCDIR)zlib.h zconf.h + $(CC) $(CFLAGS) $(ZINCOUT) -D_FILE_OFFSET_BITS=64 -c -o $@ $(SRCDIR)test/example.c + +minigzip64.o: $(SRCDIR)test/minigzip.c $(SRCDIR)zlib.h zconf.h + $(CC) $(CFLAGS) $(ZINCOUT) -D_FILE_OFFSET_BITS=64 -c -o $@ $(SRCDIR)test/minigzip.c + + +adler32.o: $(SRCDIR)adler32.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)adler32.c + +crc32.o: $(SRCDIR)crc32.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)crc32.c + +deflate.o: $(SRCDIR)deflate.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)deflate.c + +infback.o: $(SRCDIR)infback.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)infback.c + +inffast.o: $(SRCDIR)inffast.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)inffast.c + +inflate.o: $(SRCDIR)inflate.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)inflate.c + +inftrees.o: $(SRCDIR)inftrees.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)inftrees.c + +trees.o: $(SRCDIR)trees.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)trees.c + +zutil.o: $(SRCDIR)zutil.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)zutil.c + +compress.o: $(SRCDIR)compress.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)compress.c + +uncompr.o: $(SRCDIR)uncompr.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)uncompr.c + +gzclose.o: $(SRCDIR)gzclose.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzclose.c + +gzlib.o: $(SRCDIR)gzlib.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzlib.c + +gzread.o: $(SRCDIR)gzread.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzread.c + +gzwrite.o: $(SRCDIR)gzwrite.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzwrite.c + + +adler32.lo: $(SRCDIR)adler32.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/adler32.o $(SRCDIR)adler32.c + -@mv objs/adler32.o $@ + +crc32.lo: $(SRCDIR)crc32.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/crc32.o $(SRCDIR)crc32.c + -@mv objs/crc32.o $@ + +deflate.lo: $(SRCDIR)deflate.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/deflate.o $(SRCDIR)deflate.c + -@mv objs/deflate.o $@ + +infback.lo: $(SRCDIR)infback.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/infback.o $(SRCDIR)infback.c + -@mv objs/infback.o $@ + +inffast.lo: $(SRCDIR)inffast.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/inffast.o $(SRCDIR)inffast.c + -@mv objs/inffast.o $@ + +inflate.lo: $(SRCDIR)inflate.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/inflate.o $(SRCDIR)inflate.c + -@mv objs/inflate.o $@ + +inftrees.lo: $(SRCDIR)inftrees.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/inftrees.o $(SRCDIR)inftrees.c + -@mv objs/inftrees.o $@ + +trees.lo: $(SRCDIR)trees.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/trees.o $(SRCDIR)trees.c + -@mv objs/trees.o $@ + +zutil.lo: $(SRCDIR)zutil.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/zutil.o $(SRCDIR)zutil.c + -@mv objs/zutil.o $@ + +compress.lo: $(SRCDIR)compress.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/compress.o $(SRCDIR)compress.c + -@mv objs/compress.o $@ + +uncompr.lo: $(SRCDIR)uncompr.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/uncompr.o $(SRCDIR)uncompr.c + -@mv objs/uncompr.o $@ + +gzclose.lo: $(SRCDIR)gzclose.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzclose.o $(SRCDIR)gzclose.c + -@mv objs/gzclose.o $@ + +gzlib.lo: $(SRCDIR)gzlib.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzlib.o $(SRCDIR)gzlib.c + -@mv objs/gzlib.o $@ + +gzread.lo: $(SRCDIR)gzread.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzread.o $(SRCDIR)gzread.c + -@mv objs/gzread.o $@ + +gzwrite.lo: $(SRCDIR)gzwrite.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzwrite.o $(SRCDIR)gzwrite.c + -@mv objs/gzwrite.o $@ + + +placebo $(SHAREDLIBV): $(PIC_OBJS) libz.a + $(LDSHARED) $(SFLAGS) -o $@ $(PIC_OBJS) $(LDSHAREDLIBC) $(LDFLAGS) + rm -f $(SHAREDLIB) $(SHAREDLIBM) + ln -s $@ $(SHAREDLIB) + ln -s $@ $(SHAREDLIBM) + -@rmdir objs + +example$(EXE): example.o $(STATICLIB) + $(CC) $(CFLAGS) -o $@ example.o $(TEST_LDFLAGS) + +minigzip$(EXE): minigzip.o $(STATICLIB) + $(CC) $(CFLAGS) -o $@ minigzip.o $(TEST_LDFLAGS) + +examplesh$(EXE): example.o $(SHAREDLIBV) + $(CC) $(CFLAGS) -o $@ example.o -L. $(SHAREDLIBV) + +minigzipsh$(EXE): minigzip.o $(SHAREDLIBV) + $(CC) $(CFLAGS) -o $@ minigzip.o -L. $(SHAREDLIBV) + +example64$(EXE): example64.o $(STATICLIB) + $(CC) $(CFLAGS) -o $@ example64.o $(TEST_LDFLAGS) + +minigzip64$(EXE): minigzip64.o $(STATICLIB) + $(CC) $(CFLAGS) -o $@ minigzip64.o $(TEST_LDFLAGS) + +install-libs: $(LIBS) + -@if [ ! -d $(DESTDIR)$(exec_prefix) ]; then mkdir -p $(DESTDIR)$(exec_prefix); fi + -@if [ ! -d $(DESTDIR)$(libdir) ]; then mkdir -p $(DESTDIR)$(libdir); fi + -@if [ ! -d $(DESTDIR)$(sharedlibdir) ]; then mkdir -p $(DESTDIR)$(sharedlibdir); fi + -@if [ ! -d $(DESTDIR)$(man3dir) ]; then mkdir -p $(DESTDIR)$(man3dir); fi + -@if [ ! -d $(DESTDIR)$(pkgconfigdir) ]; then mkdir -p $(DESTDIR)$(pkgconfigdir); fi + rm -f $(DESTDIR)$(libdir)/$(STATICLIB) + cp $(STATICLIB) $(DESTDIR)$(libdir) + chmod 644 $(DESTDIR)$(libdir)/$(STATICLIB) + -@($(RANLIB) $(DESTDIR)$(libdir)/libz.a || true) >/dev/null 2>&1 + -@if test -n "$(SHAREDLIBV)"; then \ + rm -f $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV); \ + cp $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir); \ + echo "cp $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)"; \ + chmod 755 $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV); \ + echo "chmod 755 $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV)"; \ + rm -f $(DESTDIR)$(sharedlibdir)/$(SHAREDLIB) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBM); \ + ln -s $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIB); \ + ln -s $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBM); \ + ($(LDCONFIG) || true) >/dev/null 2>&1; \ + fi + rm -f $(DESTDIR)$(man3dir)/zlib.3 + cp $(SRCDIR)zlib.3 $(DESTDIR)$(man3dir) + chmod 644 $(DESTDIR)$(man3dir)/zlib.3 + rm -f $(DESTDIR)$(pkgconfigdir)/zlib.pc + cp zlib.pc $(DESTDIR)$(pkgconfigdir) + chmod 644 $(DESTDIR)$(pkgconfigdir)/zlib.pc +# The ranlib in install is needed on NeXTSTEP which checks file times +# ldconfig is for Linux + +install: install-libs + -@if [ ! -d $(DESTDIR)$(includedir) ]; then mkdir -p $(DESTDIR)$(includedir); fi + rm -f $(DESTDIR)$(includedir)/zlib.h $(DESTDIR)$(includedir)/zconf.h + cp $(SRCDIR)zlib.h zconf.h $(DESTDIR)$(includedir) + chmod 644 $(DESTDIR)$(includedir)/zlib.h $(DESTDIR)$(includedir)/zconf.h + +uninstall: + cd $(DESTDIR)$(includedir) && rm -f zlib.h zconf.h + cd $(DESTDIR)$(libdir) && rm -f libz.a; \ + if test -n "$(SHAREDLIBV)" -a -f $(SHAREDLIBV); then \ + rm -f $(SHAREDLIBV) $(SHAREDLIB) $(SHAREDLIBM); \ + fi + cd $(DESTDIR)$(man3dir) && rm -f zlib.3 + cd $(DESTDIR)$(pkgconfigdir) && rm -f zlib.pc + +docs: zlib.3.pdf + +zlib.3.pdf: $(SRCDIR)zlib.3 + groff -mandoc -f H -T ps $(SRCDIR)zlib.3 | ps2pdf - $@ + +zconf.h.cmakein: $(SRCDIR)zconf.h.in + -@ TEMPFILE=zconfh_$$; \ + echo "/#define ZCONF_H/ a\\\\\n#cmakedefine Z_PREFIX\\\\\n#cmakedefine Z_HAVE_UNISTD_H\n" >> $$TEMPFILE &&\ + sed -f $$TEMPFILE $(SRCDIR)zconf.h.in > $@ &&\ + touch -r $(SRCDIR)zconf.h.in $@ &&\ + rm $$TEMPFILE + +zconf: $(SRCDIR)zconf.h.in + cp -p $(SRCDIR)zconf.h.in zconf.h + +mostlyclean: clean +clean: + rm -f *.o *.lo *~ \ + example$(EXE) minigzip$(EXE) examplesh$(EXE) minigzipsh$(EXE) \ + example64$(EXE) minigzip64$(EXE) \ + infcover \ + libz.* foo.gz so_locations \ + _match.s maketree contrib/infback9/*.o + rm -rf objs + rm -f *.gcda *.gcno *.gcov + rm -f contrib/infback9/*.gcda contrib/infback9/*.gcno contrib/infback9/*.gcov + +maintainer-clean: distclean +distclean: clean zconf zconf.h.cmakein docs + rm -f Makefile zlib.pc configure.log + -@rm -f .DS_Store + @if [ -f Makefile.in ]; then \ + printf 'all:\n\t-@echo "Please use ./configure first. Thank you."\n' > Makefile ; \ + printf '\ndistclean:\n\tmake -f Makefile.in distclean\n' >> Makefile ; \ + touch -r $(SRCDIR)Makefile.in Makefile ; fi + @if [ ! -f zconf.h.in ]; then rm -f zconf.h zconf.h.cmakein ; fi + @if [ ! -f zlib.3 ]; then rm -f zlib.3.pdf ; fi + +tags: + etags $(SRCDIR)*.[ch] + +adler32.o zutil.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h +gzclose.o gzlib.o gzread.o gzwrite.o: $(SRCDIR)zlib.h zconf.h $(SRCDIR)gzguts.h +compress.o example.o minigzip.o uncompr.o: $(SRCDIR)zlib.h zconf.h +crc32.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)crc32.h +deflate.o: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h +infback.o inflate.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h $(SRCDIR)inffixed.h +inffast.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h +inftrees.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h +trees.o: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)trees.h + +adler32.lo zutil.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h +gzclose.lo gzlib.lo gzread.lo gzwrite.lo: $(SRCDIR)zlib.h zconf.h $(SRCDIR)gzguts.h +compress.lo example.lo minigzip.lo uncompr.lo: $(SRCDIR)zlib.h zconf.h +crc32.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)crc32.h +deflate.lo: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h +infback.lo inflate.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h $(SRCDIR)inffixed.h +inffast.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h +inftrees.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h +trees.lo: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)trees.h diff --git a/examples/pxScene2d/external/zlib-1.2.11/zconf.h b/examples/pxScene2d/external/zlib-1.2.11/zconf.h index 5e1d68a004..77398c11a1 100644 --- a/examples/pxScene2d/external/zlib-1.2.11/zconf.h +++ b/examples/pxScene2d/external/zlib-1.2.11/zconf.h @@ -431,11 +431,11 @@ typedef uLong FAR uLongf; typedef unsigned long z_crc_t; #endif -#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +#if 1 /* was set to #if 1 by ./configure */ # define Z_HAVE_UNISTD_H #endif -#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +#if 1 /* was set to #if 1 by ./configure */ # define Z_HAVE_STDARG_H #endif diff --git a/examples/pxScene2d/src/init.js b/examples/pxScene2d/src/init.js index 2bde966d76..ddb1c43524 100644 --- a/examples/pxScene2d/src/init.js +++ b/examples/pxScene2d/src/init.js @@ -41,6 +41,15 @@ global.constructPromise = function (obj) { }); } } +else if (isV8) { +console = require('console'); +timers = require('timers'); + +setTimeout = timers.setTimeout; +clearTimeout = timers.clearTimeout; +setInterval = timers.setInterval; +clearInterval = timers.clearInterval; +} var AppSceneContext = require('rcvrcore/AppSceneContext'); var RPCController = require('rcvrcore/rpcController'); diff --git a/examples/pxScene2d/src/mkapp.sh b/examples/pxScene2d/src/mkapp.sh index f626911da0..c225934a38 100755 --- a/examples/pxScene2d/src/mkapp.sh +++ b/examples/pxScene2d/src/mkapp.sh @@ -69,6 +69,7 @@ ${minJS} about.js $bundleRes/about.js ${minJS} browser/editbox.js $bundleRes/browser/editbox.js ${minJS} test_binding.js $bundleRes/test_binding.js ${minJS} test_module_loading.js $bundleRes/test_module_loading.js +${minJS} test_module_binding.js $bundleRes/test_module_binding.js ${minJS} test_promises.js $bundleRes/test_promises.js #./jsMinFolder.sh browser $bundleRes/browser diff --git a/examples/pxScene2d/src/pxScene2d.cpp b/examples/pxScene2d/src/pxScene2d.cpp index cf0ac1070d..e15431dd85 100644 --- a/examples/pxScene2d/src/pxScene2d.cpp +++ b/examples/pxScene2d/src/pxScene2d.cpp @@ -3822,9 +3822,9 @@ void pxScriptView::runScript() mReady = new rtPromise(); #endif -#ifdef PXSCENE_V8_TEST - mCtx->runFile(mUrl); -#else +//#ifdef PXSCENE_V8_TEST + //mCtx->runFile(mUrl); +//#else mCtx->runFile("init.js"); char buffer[MAX_URL_SIZE + 50]; @@ -3852,7 +3852,7 @@ void pxScriptView::runScript() #endif mCtx->runScript(buffer); rtLogInfo("pxScriptView::runScript() ending\n"); -#endif +//#endif } #endif //ENABLE_RT_NODE } diff --git a/examples/pxScene2d/src/rcvrcore/AppSceneContext.js b/examples/pxScene2d/src/rcvrcore/AppSceneContext.js index fbfe386ee9..308696469f 100644 --- a/examples/pxScene2d/src/rcvrcore/AppSceneContext.js +++ b/examples/pxScene2d/src/rcvrcore/AppSceneContext.js @@ -18,7 +18,7 @@ limitations under the License. //"use strict"; -var isDuk=(typeof timers != "undefined")?true:false; +var isDuk=(typeof Duktape != "undefined")?true:false; var url = require('url'); var path = require('path'); @@ -36,15 +36,15 @@ var WrapObj = require('rcvrcore/utils/WrapObj'); var log = new Logger('AppSceneContext'); //overriding original timeout and interval functions -var SetTimeout = isDuk?timers.setTimeout:setTimeout; -var ClearTimeout = isDuk?timers.clearTimeout:clearTimeout; -var SetInterval = isDuk?timers.setInterval:setInterval; -var ClearInterval = isDuk?timers.clearInterval:clearInterval; +var SetTimeout = (isDuk || isV8)?timers.setTimeout:setTimeout; +var ClearTimeout = (isDuk || isV8)?timers.clearTimeout:clearTimeout; +var SetInterval = (isDuk || isV8)?timers.setInterval:setInterval; +var ClearInterval = (isDuk || isV8)?timers.clearInterval:clearInterval; var http_wrap = require('rcvrcore/http_wrap'); var https_wrap = require('rcvrcore/https_wrap'); -var ws_wrap = (isDuk)?"":require('rcvrcore/ws_wrap'); +var ws_wrap = (isDuk || isV8)?"":require('rcvrcore/ws_wrap'); function AppSceneContext(params) { @@ -71,7 +71,7 @@ function AppSceneContext(params) { this.xmoduleMap = {}; this.asyncFileAcquisition = new AsyncFileAcquisition(params.scene); this.accessControl = new AccessControl(params.scene); - this.lastHrTime = isDuk?uv.hrtime():process.hrtime(); + this.lastHrTime = isDuk?uv.hrtime():(isV8?uv_hrtime():process.hrtime()); this.resizeTimer = null; this.topXModule = null; this.jarFileMap = new JarFileMap(); @@ -88,7 +88,7 @@ AppSceneContext.prototype.loadScene = function() { //log.info("loadScene() - begins on ctx: " + getContextID() ); var urlParts = url.parse(this.packageUrl, true); var fullPath = this.packageUrl; - var platform = (isDuk)?uv.platform:process.platform; + var platform = (isDuk)?uv.platform:(isV8?uv_platform():process.platform); if (fullPath.substring(0, 4) !== "http") { if( fullPath.charAt(0) === '.' ) { // local file system @@ -335,7 +335,7 @@ AppSceneContext.prototype.runScriptInNewVMContext = function (packageUri, module var self = this; var newSandbox; try { - if (!isDuk) { + if (!isDuk && !isV8) { var requireMethod = function (pkg) { log.message(3, "old use of require not supported: " + pkg); // TODO: remove @@ -359,7 +359,7 @@ AppSceneContext.prototype.runScriptInNewVMContext = function (packageUri, module } } - if (!isDuk) { + if (!isDuk && !isV8) { var processWrap = WrapObj(process, {"binding":function() { throw new Error("process.binding is not supported"); }}); var globalWrap = WrapObj(global, {"process":processWrap}); @@ -415,7 +415,7 @@ AppSceneContext.prototype.runScriptInNewVMContext = function (packageUri, module urlModule: require("url"), queryStringModule: require("querystring"), theNamedContext: "Sandbox: " + uri, - Buffer: Buffer, + //Buffer: Buffer, importTracking: {} }; // end sandbox } @@ -440,6 +440,14 @@ AppSceneContext.prototype.runScriptInNewVMContext = function (packageUri, module filename: path.normalize(fname), displayErrors: true }, px, xModule, fname, this.basePackageUri); + } else if (isV8) { + var moduleFunc = vm.runInNewContext(sourceCode, newSandbox, { + filename: path.normalize(fname), + displayErrors: true + }, px, xModule, fname, this.basePackageUri); + + moduleFunc(px, xModule, fname, this.basePackageUri); + } else { var moduleFunc = vm.runInNewContext(sourceCode, newSandbox, { filename: path.normalize(fname), @@ -526,7 +534,7 @@ if (false) { AppSceneContext.prototype.getPackageBaseFilePath = function() { var fullPath; var pkgPart; - var platform = (isDuk)?uv.platform:process.platform; + var platform = (isDuk)?uv.platform:(isV8?uv_platform():process.platform); if (this.basePackageUri.substring(0, 4) !== "http") { if (this.basePackageUri.charAt(0) == '.') { pkgPart = this.basePackageUri.substring(1); @@ -767,8 +775,10 @@ AppSceneContext.prototype.processCodeBuffer = function(origFilePath, filePath, c if (isDuk) { vm.runInNewContext(sourceCode, _this.sandbox, { filename: filePath, displayErrors: true }, px, xModule, filePath, filePath); - } - else { + } else if (isV8) { + vm.runInNewContext(sourceCode, _this.sandbox, { filename: filePath, displayErrors: true }, + px, xModule, filePath, filePath); + } else { var moduleFunc = vm.runInContext(sourceCode, _this.sandbox, {filename:filePath, displayErrors:true}); moduleFunc(px, xModule, filePath, filePath); } @@ -804,9 +814,9 @@ AppSceneContext.prototype.processCodeBuffer = function(origFilePath, filePath, c }; AppSceneContext.prototype.onResize = function(resizeEvent) { - var hrTime = isDuk?uv.hrtime():process.hrtime(this.lastHrTime); + var hrTime = isDuk?uv.hrtime():(isV8?uv_hrtime():process.hrtime(this.lastHrTime)); var deltaMillis = (hrTime[0] * 1000 + hrTime[1] / 1000000); - this.lastHrTime = isDuk?uv.hrtime():process.hrtime(); + this.lastHrTime = isDuk?uv.hrtime():(isV8?uv_hrtime():process.hrtime()); if( deltaMillis > 300 ) { if( this.resizeTimer !== null ) { clearTimeout(this.resizeTimer); diff --git a/examples/pxScene2d/src/rcvrcore/SceneModuleLoader.js b/examples/pxScene2d/src/rcvrcore/SceneModuleLoader.js index 9a1796f5b1..ad0998054f 100644 --- a/examples/pxScene2d/src/rcvrcore/SceneModuleLoader.js +++ b/examples/pxScene2d/src/rcvrcore/SceneModuleLoader.js @@ -49,7 +49,7 @@ SceneModuleLoader.prototype.loadScenePackage = function(scene, fileSpec) { } else { - log.message(4, "loadScenePackage: loadArchive succeeded for (",filePath,")."); + log.message(4, "loadScenePackage: loadArchive succeeded for ("+filePath+")."); _this.fileArchive = new FileArchive(filePath, a); log.message(4, "Number of files: " + a.fileNames.length); diff --git a/examples/pxScene2d/src/rcvrcore/scene.1.js b/examples/pxScene2d/src/rcvrcore/scene.1.js index e5cf11f4be..444a8b6ff1 100644 --- a/examples/pxScene2d/src/rcvrcore/scene.1.js +++ b/examples/pxScene2d/src/rcvrcore/scene.1.js @@ -16,7 +16,7 @@ limitations under the License. */ -var isDuk = (typeof timers != "undefined")?true:false; +var isDuk=(typeof Duktape != "undefined")?true:false; var RPCContext = require('rcvrcore/rpcContext'); diff --git a/examples/pxScene2d/src/rcvrcore/utils/FileArchive.js b/examples/pxScene2d/src/rcvrcore/utils/FileArchive.js index 07d137000a..e1b6143b82 100644 --- a/examples/pxScene2d/src/rcvrcore/utils/FileArchive.js +++ b/examples/pxScene2d/src/rcvrcore/utils/FileArchive.js @@ -25,7 +25,7 @@ var url = require('url'); var http = require('http'); // FIXME !!!!!!!!!! duktape merge hack -if (!isDuk) { +if (!isDuk && !isV8) { var JSZip = require("jszip"); } diff --git a/examples/pxScene2d/src/test_module_binding.js b/examples/pxScene2d/src/test_module_binding.js new file mode 100644 index 0000000000..f81338d949 --- /dev/null +++ b/examples/pxScene2d/src/test_module_binding.js @@ -0,0 +1,20 @@ +print(uv_platform()); +var hr = uv_hrtime() +print(hr[0] + " " + hr[1]); +print("0:"+uv_fs_access('C:\\windows\\notepad.exe', 'r')); +print("1:"+uv_fs_access('C:\\windows\\notepad1.exe', 'r')); +print("size:"+uv_fs_size('C:\\windows\\notepad.exe')); +var fd = uv_fs_open('C:\\windows\\notepad.exe', 'r', 420); +var buf = uv_fs_read(fd, 32, 0); +print(buf.byteLength+""); +uv_fs_close(fd); +var tm = uv_timer_new(); +uv_timer_stop(tm); +var tm2 = uv_timer_new(); +uv_timer_start(tm2, 1000, 1000, function () { print("OK2"); }); +var tm1 = uv_timer_new(); +uv_timer_start(tm1, 5000, 0, function () { print("OK1"); uv_timer_stop(tm2); }); + +uv_run_in_context("print(\"in eval context\");"); + +print("isV8 " + isV8); diff --git a/examples/pxScene2d/src/v8_modules/console.js b/examples/pxScene2d/src/v8_modules/console.js new file mode 100644 index 0000000000..9e092903b8 --- /dev/null +++ b/examples/pxScene2d/src/v8_modules/console.js @@ -0,0 +1,47 @@ +/* + +pxCore Copyright 2005-2018 John Robinson + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +"use strict"; + +function trace(msg) { + print("[LOG TRACE] " + msg); +} + +function warn(msg) { + print("[LOG WARN] " + msg); +} + +function error(msg) { + print("[LOG ERROR] " + msg); +} + +function log(msg) { + print("[LOG LOG] " + msg); +} + +function info(msg) { + print("[LOG INFO] " + msg); +} + +module.exports = { + trace: trace, + warn: warn, + error: error, + log: log, + info: info, +} diff --git a/examples/pxScene2d/src/v8_modules/fs.js b/examples/pxScene2d/src/v8_modules/fs.js new file mode 100644 index 0000000000..5a99972c12 --- /dev/null +++ b/examples/pxScene2d/src/v8_modules/fs.js @@ -0,0 +1,36 @@ +/* + +pxCore Copyright 2005-2018 John Robinson + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +"use strict"; + +function readFile(filePath, cb) { + var ares = uv_fs_access(filePath, 'r'); + if (ares < 0) { + cb(ares, ""); + return; + } + var fd = uv_fs_open(filePath, 'r', 420); + var size = uv_fs_size(filePath); + var res = uv_fs_read(fd, size, 0); + uv_fs_close(fd); + cb(0, res); +} + +module.exports = { + 'readFile': readFile, +} diff --git a/examples/pxScene2d/src/v8_modules/http.js b/examples/pxScene2d/src/v8_modules/http.js new file mode 100644 index 0000000000..26fe7db604 --- /dev/null +++ b/examples/pxScene2d/src/v8_modules/http.js @@ -0,0 +1,27 @@ +/* + +pxCore Copyright 2005-2018 John Robinson + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +"use strict"; + +function get(url, cb) { + return httpGet(url, cb); +} + +module.exports = { + 'get': get, +} diff --git a/examples/pxScene2d/src/v8_modules/http_test.js b/examples/pxScene2d/src/v8_modules/http_test.js new file mode 100644 index 0000000000..1c9dcf7e96 --- /dev/null +++ b/examples/pxScene2d/src/v8_modules/http_test.js @@ -0,0 +1,44 @@ +/* + +pxCore Copyright 2005-2018 John Robinson + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + + +px.import({ scene: 'px:scene.1', http: 'http' }).then( function importsAreReady(imports) +{ + var http = imports.http; + + respData = ''; + + http.get('https://bellard.org/pi/pi2700e9', function (resp) { + console.log('http in func cb'); + + resp.on('data', function (chunk) { + console.log('http on data'); + respData += chunk; + }); + + resp.on('end', function () { + console.log('http done. status_code = ' + resp.statusCode + + ' response size = ' + respData.length); + }); + }).on('error', function (e) { + console.log('error fetching data: ' + e.message); + }); + +}).catch( function importFailed(err){ + console.error("Import failed for http_test.js: " + err); +}); diff --git a/examples/pxScene2d/src/v8_modules/https.js b/examples/pxScene2d/src/v8_modules/https.js new file mode 100644 index 0000000000..26fe7db604 --- /dev/null +++ b/examples/pxScene2d/src/v8_modules/https.js @@ -0,0 +1,27 @@ +/* + +pxCore Copyright 2005-2018 John Robinson + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +"use strict"; + +function get(url, cb) { + return httpGet(url, cb); +} + +module.exports = { + 'get': get, +} diff --git a/examples/pxScene2d/src/v8_modules/path.js b/examples/pxScene2d/src/v8_modules/path.js new file mode 100644 index 0000000000..2f92945ca8 --- /dev/null +++ b/examples/pxScene2d/src/v8_modules/path.js @@ -0,0 +1,307 @@ +/* + +pxCore Copyright 2005-2018 John Robinson + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +"use strict"; + +function normalizeStringWin32(path, allowAboveRoot) { + var res = ''; + var lastSlash = -1; + var dots = 0; + var code; + for (var i = 0; i <= path.length; ++i) { + if (i < path.length) + code = path.charCodeAt(i); + else if (code === 47/*/*/ || code === 92/*\*/) + break; + else + code = 47/*/*/; + if (code === 47/*/*/ || code === 92/*\*/) { + if (lastSlash === i - 1 || dots === 1) { + // NOOP + } else if (lastSlash !== i - 1 && dots === 2) { + if (res.length < 2 || + res.charCodeAt(res.length - 1) !== 46/*.*/ || + res.charCodeAt(res.length - 2) !== 46/*.*/) { + if (res.length > 2) { + const start = res.length - 1; + var j = start; + for (; j >= 0; --j) { + if (res.charCodeAt(j) === 92/*\*/) + break; + } + if (j !== start) { + if (j === -1) + res = ''; + else + res = res.slice(0, j); + lastSlash = i; + dots = 0; + continue; + } + } else if (res.length === 2 || res.length === 1) { + res = ''; + lastSlash = i; + dots = 0; + continue; + } + } + if (allowAboveRoot) { + if (res.length > 0) + res += '\\..'; + else + res = '..'; + } + } else { + if (res.length > 0) + res += '\\' + path.slice(lastSlash + 1, i); + else + res = path.slice(lastSlash + 1, i); + } + lastSlash = i; + dots = 0; + } else if (code === 46/*.*/ && dots !== -1) { + ++dots; + } else { + dots = -1; + } + } + return res; +} + +function normalizeStringPosix(path, allowAboveRoot) { + var res = ''; + var lastSlash = -1; + var dots = 0; + var code; + for (var i = 0; i <= path.length; ++i) { + if (i < path.length) + code = path.charCodeAt(i); + else if (code === 47/*/*/) + break; + else + code = 47/*/*/; + if (code === 47/*/*/) { + if (lastSlash === i - 1 || dots === 1) { + // NOOP + } else if (lastSlash !== i - 1 && dots === 2) { + if (res.length < 2 || + res.charCodeAt(res.length - 1) !== 46/*.*/ || + res.charCodeAt(res.length - 2) !== 46/*.*/) { + if (res.length > 2) { + const start = res.length - 1; + var j = start; + for (; j >= 0; --j) { + if (res.charCodeAt(j) === 47/*/*/) + break; + } + if (j !== start) { + if (j === -1) + res = ''; + else + res = res.slice(0, j); + lastSlash = i; + dots = 0; + continue; + } + } else if (res.length === 2 || res.length === 1) { + res = ''; + lastSlash = i; + dots = 0; + continue; + } + } + if (allowAboveRoot) { + if (res.length > 0) + res += '/..'; + else + res = '..'; + } + } else { + if (res.length > 0) + res += '/' + path.slice(lastSlash + 1, i); + else + res = path.slice(lastSlash + 1, i); + } + lastSlash = i; + dots = 0; + } else if (code === 46/*.*/ && dots !== -1) { + ++dots; + } else { + dots = -1; + } + } + return res; +} + + +win32 = { + normalize: function normalize(path) { + const len = path.length; + if (len === 0) + return '.'; + var rootEnd = 0; + var code = path.charCodeAt(0); + var device; + var isAbsolute = false; + + // Try to match a root + if (len > 1) { + if (code === 47/*/*/ || code === 92/*\*/) { + // Possible UNC root + + // If we started with a separator, we know we at least have an absolute + // path of some kind (UNC or otherwise) + isAbsolute = true; + + code = path.charCodeAt(1); + if (code === 47/*/*/ || code === 92/*\*/) { + // Matched double path separator at beginning + var j = 2; + var last = j; + // Match 1 or more non-path separators + for (; j < len; ++j) { + code = path.charCodeAt(j); + if (code === 47/*/*/ || code === 92/*\*/) + break; + } + if (j < len && j !== last) { + const firstPart = path.slice(last, j); + // Matched! + last = j; + // Match 1 or more path separators + for (; j < len; ++j) { + code = path.charCodeAt(j); + if (code !== 47/*/*/ && code !== 92/*\*/) + break; + } + if (j < len && j !== last) { + // Matched! + last = j; + // Match 1 or more non-path separators + for (; j < len; ++j) { + code = path.charCodeAt(j); + if (code === 47/*/*/ || code === 92/*\*/) + break; + } + if (j === len) { + // We matched a UNC root only + // Return the normalized version of the UNC root since there + // is nothing left to process + + return '\\\\' + firstPart + '\\' + path.slice(last) + '\\'; + } else if (j !== last) { + // We matched a UNC root with leftovers + + device = '\\\\' + firstPart + '\\' + path.slice(last, j); + rootEnd = j; + } + } + } + } else { + rootEnd = 1; + } + } else if ((code >= 65/*A*/ && code <= 90/*Z*/) || + (code >= 97/*a*/ && code <= 122/*z*/)) { + // Possible device root + + code = path.charCodeAt(1); + if (path.charCodeAt(1) === 58/*:*/) { + device = path.slice(0, 2); + rootEnd = 2; + if (len > 2) { + code = path.charCodeAt(2); + if (code === 47/*/*/ || code === 92/*\*/) { + // Treat separator following drive name as an absolute path + // indicator + isAbsolute = true; + rootEnd = 3; + } + } + } + } + } else if (code === 47/*/*/ || code === 92/*\*/) { + // `path` contains just a path separator, exit early to avoid unnecessary + // work + return '\\'; + } + + code = path.charCodeAt(len - 1); + var trailingSeparator = (code === 47/*/*/ || code === 92/*\*/); + var tail; + if (rootEnd < len) + tail = normalizeStringWin32(path.slice(rootEnd), !isAbsolute); + else + tail = ''; + if (tail.length === 0 && !isAbsolute) + tail = '.'; + if (tail.length > 0 && trailingSeparator) + tail += '\\'; + if (device === undefined) { + if (isAbsolute) { + if (tail.length > 0) + return '\\' + tail; + else + return '\\'; + } else if (tail.length > 0) { + return tail; + } else { + return ''; + } + } else { + if (isAbsolute) { + if (tail.length > 0) + return device + '\\' + tail; + else + return device + '\\'; + } else if (tail.length > 0) { + return device + tail; + } else { + return device; + } + } + }, +} + +posix = { + sep: '/', + delimiter: ':', + normalize: function normalize(path) { + if (path.length === 0) + return '.'; + + const isAbsolute = path.charCodeAt(0) === 47/*/*/; + const trailingSeparator = path.charCodeAt(path.length - 1) === 47/*/*/; + + // Normalize the path + path = normalizeStringPosix(path, !isAbsolute); + + if (path.length === 0 && !isAbsolute) + path = '.'; + if (path.length > 0 && trailingSeparator) + path += '/'; + + if (isAbsolute) + return '/' + path; + return path; + }, +} + +if (uv_platform() === 'win32') + module.exports = win32; +else + module.exports = posix; diff --git a/examples/pxScene2d/src/v8_modules/punycode.js b/examples/pxScene2d/src/v8_modules/punycode.js new file mode 100644 index 0000000000..59f3538e40 --- /dev/null +++ b/examples/pxScene2d/src/v8_modules/punycode.js @@ -0,0 +1,459 @@ +/* + +pxCore Copyright 2005-2018 John Robinson + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +'use strict'; + +/** Highest positive signed 32-bit float value */ +const maxInt = 2147483647; // aka. 0x7FFFFFFF or 2^31-1 + +/** Bootstring parameters */ +const base = 36; +const tMin = 1; +const tMax = 26; +const skew = 38; +const damp = 700; +const initialBias = 72; +const initialN = 128; // 0x80 +const delimiter = '-'; // '\x2D' + +/** Regular expressions */ +const regexPunycode = /^xn--/; +const regexNonASCII = /[^\x20-\x7E]/; // unprintable ASCII chars + non-ASCII chars +const regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g; // RFC 3490 separators + +/** Error messages */ +const errors = { + 'overflow': 'Overflow: input needs wider integers to process', + 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', + 'invalid-input': 'Invalid input' +}; + +/** Convenience shortcuts */ +const baseMinusTMin = base - tMin; +const floor = Math.floor; +const stringFromCharCode = String.fromCharCode; + +/*--------------------------------------------------------------------------*/ + +/** + * A generic error utility function. + * @private + * @param {String} type The error type. + * @returns {Error} Throws a `RangeError` with the applicable error message. + */ +function error(type) { + throw new RangeError(errors[type]); +} + +/** + * A generic `Array#map` utility function. + * @private + * @param {Array} array The array to iterate over. + * @param {Function} callback The function that gets called for every array + * item. + * @returns {Array} A new array of values returned by the callback function. + */ +function map(array, fn) { + const result = []; + length = array.length; + while (length--) { + result[length] = fn(array[length]); + } + return result; +} + +/** + * A simple `Array#map`-like wrapper to work with domain name strings or email + * addresses. + * @private + * @param {String} domain The domain name or email address. + * @param {Function} callback The function that gets called for every + * character. + * @returns {Array} A new string of characters returned by the callback + * function. + */ +function mapDomain(string, fn) { + const parts = string.split('@'); + result = ''; + if (parts.length > 1) { + // In email addresses, only the domain name should be punycoded. Leave + // the local part (i.e. everything up to `@`) intact. + result = parts[0] + '@'; + string = parts[1]; + } + // Avoid `split(regex)` for IE8 compatibility. See #17. + string = string.replace(regexSeparators, '\x2E'); + const labels = string.split('.'); + const encoded = map(labels, fn).join('.'); + return result + encoded; +} + +/** + * Creates an array containing the numeric code points of each Unicode + * character in the string. While JavaScript uses UCS-2 internally, + * this function will convert a pair of surrogate halves (each of which + * UCS-2 exposes as separate characters) into a single code point, + * matching UTF-16. + * @see `punycode.ucs2.encode` + * @see + * @memberOf punycode.ucs2 + * @name decode + * @param {String} string The Unicode input string (UCS-2). + * @returns {Array} The new array of code points. + */ +function ucs2decode(string) { + const output = []; + counter = 0; + const length = string.length; + while (counter < length) { + const value = string.charCodeAt(counter++); + if (value >= 0xD800 && value <= 0xDBFF && counter < length) { + // It's a high surrogate, and there is a next character. + const extra = string.charCodeAt(counter++); + if ((extra & 0xFC00) == 0xDC00) { // Low surrogate. + output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); + } else { + // It's an unmatched surrogate; only append this code unit, in case the + // next code unit is the high surrogate of a surrogate pair. + output.push(value); + counter--; + } + } else { + output.push(value); + } + } + return output; +} + +/** + * Creates a string based on an array of numeric code points. + * @see `punycode.ucs2.decode` + * @memberOf punycode.ucs2 + * @name encode + * @param {Array} codePoints The array of numeric code points. + * @returns {String} The new Unicode string (UCS-2). + */ +/** + * Converts a basic code point into a digit/integer. + * @see `digitToBasic()` + * @private + * @param {Number} codePoint The basic numeric code point value. + * @returns {Number} The numeric value of a basic code point (for use in + * representing integers) in the range `0` to `base - 1`, or `base` if + * the code point does not represent a value. + */ +const basicToDigit = function(codePoint) { + if (codePoint - 0x30 < 0x0A) { + return codePoint - 0x16; + } + if (codePoint - 0x41 < 0x1A) { + return codePoint - 0x41; + } + if (codePoint - 0x61 < 0x1A) { + return codePoint - 0x61; + } + return base; +}; + +/** + * Converts a digit/integer into a basic code point. + * @see `basicToDigit()` + * @private + * @param {Number} digit The numeric value of a basic code point. + * @returns {Number} The basic code point whose value (when used for + * representing integers) is `digit`, which needs to be in the range + * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is + * used; else, the lowercase form is used. The behavior is undefined + * if `flag` is non-zero and `digit` has no uppercase form. + */ +const digitToBasic = function(digit, flag) { + // 0..25 map to ASCII a..z or A..Z + // 26..35 map to ASCII 0..9 + return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); +}; + +/** + * Bias adaptation function as per section 3.4 of RFC 3492. + * https://tools.ietf.org/html/rfc3492#section-3.4 + * @private + */ +const adapt = function(delta, numPoints, firstTime) { + k = 0; + delta = firstTime ? floor(delta / damp) : delta >> 1; + delta += floor(delta / numPoints); + for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { + delta = floor(delta / baseMinusTMin); + } + return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); +}; + +/** + * Converts a Punycode string of ASCII-only symbols to a string of Unicode + * symbols. + * @memberOf punycode + * @param {String} input The Punycode string of ASCII-only symbols. + * @returns {String} The resulting string of Unicode symbols. + */ +//const decode = function(input) { +// // Don't use UCS-2. +// const output = []; +// const inputLength = input.length; +// var i = 0; +// var n = initialN; +// var bias = initialBias; + +// // Handle the basic code points: let `basic` be the number of input code +// // points before the last delimiter, or `0` if there is none, then copy +// // the first basic code points to the output. + +// var basic = input.lastIndexOf(delimiter); +// if (basic < 0) { +// basic = 0; +// } + +// for (var j = 0; j < basic; ++j) { +// // if it's not a basic code point +// if (input.charCodeAt(j) >= 0x80) { +// error('not-basic'); +// } +// output.push(input.charCodeAt(j)); +// } + +// // Main decoding loop: start just after the last delimiter if any basic code +// // points were copied; start at the beginning otherwise. + +// for (var index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { + +// // `index` is the index of the next character to be consumed. +// // Decode a generalized variable-length integer into `delta`, +// // which gets added to `i`. The overflow checking is easier +// // if we increase `i` as we go, then subtract off its starting +// // value at the end to obtain `delta`. +// var oldi = i; +// for (var w = 1, k = base; /* no condition */; k += base) { + +// if (index >= inputLength) { +// error('invalid-input'); +// } + +// const digit = basicToDigit(input.charCodeAt(index++)); + +// if (digit >= base || digit > floor((maxInt - i) / w)) { +// error('overflow'); +// } + +// i += digit * w; +// const t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + +// if (digit < t) { +// break; +// } + +// const baseMinusT = base - t; +// if (w > floor(maxInt / baseMinusT)) { +// error('overflow'); +// } + +// w *= baseMinusT; + +// } + +// const out = output.length + 1; +// bias = adapt(i - oldi, out, oldi == 0); + +// // `i` was supposed to wrap around from `out` to `0`, +// // incrementing `n` each time, so we'll fix that now: +// if (floor(i / out) > maxInt - n) { +// error('overflow'); +// } + +// n += floor(i / out); +// i %= out; + +// // Insert `n` at position `i` of the output. +// output.splice(i++, 0, n); + +// } + +// return String.fromCodePoint(...output); +//}; + +/** + * Converts a string of Unicode symbols (e.g. a domain name label) to a + * Punycode string of ASCII-only symbols. + * @memberOf punycode + * @param {String} input The string of Unicode symbols. + * @returns {String} The resulting Punycode string of ASCII-only symbols. + */ +const encode = function(input) { + const output = []; + + // Convert the input in UCS-2 to an array of Unicode code points. + input = ucs2decode(input); + + // Cache the length. + var inputLength = input.length; + + // Initialize the state. + var n = initialN; + var delta = 0; + var bias = initialBias; + + // Handle the basic code points. + const length = input.length; + var counter = 0; + while (counter < length) { + const currentValue = input.charCodeAt(counter++); + if (currentValue < 0x80) { + output.push(stringFromCharCode(currentValue)); + } + } + + var basicLength = output.length; + var handledCPCount = basicLength; + + // `handledCPCount` is the number of code points that have been handled; + // `basicLength` is the number of basic code points. + + // Finish the basic string with a delimiter unless it's empty. + if (basicLength) { + output.push(delimiter); + } + + // Main encoding loop: + while (handledCPCount < inputLength) { + + // All non-basic code points < n have been handled already. Find the next + // larger one: + var m = maxInt; + var counter = 0; + while (counter < length) { + const currentValue = input.charCodeAt(counter++); + if (currentValue >= n && currentValue < m) { + m = currentValue; + } + } + + // Increase `delta` enough to advance the decoder's state to , + // but guard against overflow. + const handledCPCountPlusOne = handledCPCount + 1; + if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { + error('overflow'); + } + + delta += (m - n) * handledCPCountPlusOne; + n = m; + + var counter1 = 0; + while (counter1 < length) { + const currentValue = input.charCodeAt(counter1++); + if (currentValue < n && ++delta > maxInt) { + error('overflow'); + } + if (currentValue == n) { + // Represent delta as a generalized variable-length integer. + var q = delta; + for (var k = base; /* no condition */; k += base) { + const t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + if (q < t) { + break; + } + const qMinusT = q - t; + const baseMinusT = base - t; + output.push( + stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) + ); + q = floor(qMinusT / baseMinusT); + } + + output.push(stringFromCharCode(digitToBasic(q, 0))); + bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); + delta = 0; + ++handledCPCount; + } + } + + ++delta; + ++n; + + } + return output.join(''); +}; + +/** + * Converts a Punycode string representing a domain name or an email address + * to Unicode. Only the Punycoded parts of the input will be converted, i.e. + * it doesn't matter if you call it on a string that has already been + * converted to Unicode. + * @memberOf punycode + * @param {String} input The Punycoded domain name or email address to + * convert to Unicode. + * @returns {String} The Unicode representation of the given Punycode + * string. + */ +const toUnicode = function(input) { + return mapDomain(input, function(string) { + return regexPunycode.test(string) + ? decode(string.slice(4).toLowerCase()) + : string; + }); +}; + +/** + * Converts a Unicode string representing a domain name or an email address to + * Punycode. Only the non-ASCII parts of the domain name will be converted, + * i.e. it doesn't matter if you call it with a domain that's already in + * ASCII. + * @memberOf punycode + * @param {String} input The domain name or email address to convert, as a + * Unicode string. + * @returns {String} The Punycode representation of the given domain name or + * email address. + */ +const toASCII = function(input) { + return mapDomain(input, function(string) { + return regexNonASCII.test(string) + ? 'xn--' + encode(string) + : string; + }); +}; + +/*--------------------------------------------------------------------------*/ + +/** Define the public API */ +const punycode = { + /** + * A string representing the current Punycode.js version number. + * @memberOf punycode + * @type String + */ + 'version': '2.0.0', + /** + * An object of methods to convert from JavaScript's internal character + * representation (UCS-2) to Unicode code points, and back. + * @see + * @memberOf punycode + * @type Object + */ + //'decode': decode, + //'encode': encode, + 'toASCII': toASCII, + //'toUnicode': toUnicode +}; + +module.exports = punycode; diff --git a/examples/pxScene2d/src/v8_modules/querystring.js b/examples/pxScene2d/src/v8_modules/querystring.js new file mode 100644 index 0000000000..097f1f8564 --- /dev/null +++ b/examples/pxScene2d/src/v8_modules/querystring.js @@ -0,0 +1,359 @@ +/* + +pxCore Copyright 2005-2018 John Robinson + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +// Query String Utilities + +'use strict'; + +const QueryString = exports; + +// This constructor is used to store parsed query string values. Instantiating +// this is faster than explicitly calling `Object.create(null)` to get a +// "clean" empty object (tested with v8 v4.9). +function ParsedQueryString() {} +ParsedQueryString.prototype = Object.create(null); + +function qsUnescape(s, decodeSpaces) { + print(s); + return decodeURIComponent(s); +} +QueryString.unescape = qsUnescape; + + +var hexTable = new Array(256); +for (var i = 0; i < 256; ++i) + hexTable[i] = '%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase(); +QueryString.escape = function(str) { + // replaces encodeURIComponent + // http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.3.4 + if (typeof str !== 'string') { + if (typeof str === 'object') + str = String(str); + else + str += ''; + } + var out = ''; + var lastPos = 0; + + for (var i = 0; i < str.length; ++i) { + var c = str.charCodeAt(i); + + // These characters do not need escaping (in order): + // ! - . _ ~ + // ' ( ) * + // digits + // alpha (uppercase) + // alpha (lowercase) + if (c === 0x21 || c === 0x2D || c === 0x2E || c === 0x5F || c === 0x7E || + (c >= 0x27 && c <= 0x2A) || + (c >= 0x30 && c <= 0x39) || + (c >= 0x41 && c <= 0x5A) || + (c >= 0x61 && c <= 0x7A)) { + continue; + } + + if (i - lastPos > 0) + out += str.slice(lastPos, i); + + // Other ASCII characters + if (c < 0x80) { + lastPos = i + 1; + out += hexTable[c]; + continue; + } + + // Multi-byte characters ... + if (c < 0x800) { + lastPos = i + 1; + out += hexTable[0xC0 | (c >> 6)] + hexTable[0x80 | (c & 0x3F)]; + continue; + } + if (c < 0xD800 || c >= 0xE000) { + lastPos = i + 1; + out += hexTable[0xE0 | (c >> 12)] + + hexTable[0x80 | ((c >> 6) & 0x3F)] + + hexTable[0x80 | (c & 0x3F)]; + continue; + } + // Surrogate pair + ++i; + var c2; + if (i < str.length) + c2 = str.charCodeAt(i) & 0x3FF; + else + throw new URIError('URI malformed'); + lastPos = i + 1; + c = 0x10000 + (((c & 0x3FF) << 10) | c2); + out += hexTable[0xF0 | (c >> 18)] + + hexTable[0x80 | ((c >> 12) & 0x3F)] + + hexTable[0x80 | ((c >> 6) & 0x3F)] + + hexTable[0x80 | (c & 0x3F)]; + } + if (lastPos === 0) + return str; + if (lastPos < str.length) + return out + str.slice(lastPos); + return out; +}; + +var stringifyPrimitive = function(v) { + if (typeof v === 'string') + return v; + if (typeof v === 'number' && isFinite(v)) + return '' + v; + if (typeof v === 'boolean') + return v ? 'true' : 'false'; + return ''; +}; + + +QueryString.stringify = QueryString.encode = function(obj, sep, eq, options) { + sep = sep || '&'; + eq = eq || '='; + + var encode = QueryString.escape; + if (options && typeof options.encodeURIComponent === 'function') { + encode = options.encodeURIComponent; + } + + if (obj !== null && typeof obj === 'object') { + var keys = Object.keys(obj); + var len = keys.length; + var flast = len - 1; + var fields = ''; + for (var i = 0; i < len; ++i) { + var k = keys[i]; + var v = obj[k]; + var ks = encode(stringifyPrimitive(k)) + eq; + + if (Array.isArray(v)) { + var vlen = v.length; + var vlast = vlen - 1; + for (var j = 0; j < vlen; ++j) { + fields += ks + encode(stringifyPrimitive(v[j])); + if (j < vlast) + fields += sep; + } + if (vlen && i < flast) + fields += sep; + } else { + fields += ks + encode(stringifyPrimitive(v)); + if (i < flast) + fields += sep; + } + } + return fields; + } + return ''; +}; + +// Parse a key/val string. +QueryString.parse = QueryString.decode = function(qs, sep, eq, options) { + sep = sep || '&'; + eq = eq || '='; + + const obj = new ParsedQueryString(); + + if (typeof qs !== 'string' || qs.length === 0) { + return obj; + } + + if (typeof sep !== 'string') + sep += ''; + + const eqLen = eq.length; + const sepLen = sep.length; + + var maxKeys = 1000; + if (options && typeof options.maxKeys === 'number') { + maxKeys = options.maxKeys; + } + + var pairs = Infinity; + if (maxKeys > 0) + pairs = maxKeys; + + var decode = QueryString.unescape; + if (options && typeof options.decodeURIComponent === 'function') { + decode = options.decodeURIComponent; + } + const customDecode = (decode !== qsUnescape); + + + const keys = []; + var lastPos = 0; + var sepIdx = 0; + var eqIdx = 0; + var key = ''; + var value = ''; + var keyEncoded = customDecode; + var valEncoded = customDecode; + var encodeCheck = 0; + for (var i = 0; i < qs.length; ++i) { + const code = qs.charCodeAt(i); + + // Try matching key/value pair separator (e.g. '&') + if (code === sep.charCodeAt(sepIdx)) { + if (++sepIdx === sepLen) { + // Key/value pair separator match! + const end = i - sepIdx + 1; + if (eqIdx < eqLen) { + // If we didn't find the key/value separator, treat the substring as + // part of the key instead of the value + if (lastPos < end) + key += qs.slice(lastPos, end); + } else if (lastPos < end) + value += qs.slice(lastPos, end); + if (keyEncoded) + key = decodeStr(key, decode); + if (valEncoded) + value = decodeStr(value, decode); + // Use a key array lookup instead of using hasOwnProperty(), which is + // slower + if (keys.indexOf(key) === -1) { + obj[key] = value; + keys[keys.length] = key; + } else { + const curValue = obj[key]; + // `instanceof Array` is used instead of Array.isArray() because it + // is ~15-20% faster with v8 4.7 and is safe to use because we are + // using it with values being created within this function + if (curValue instanceof Array) + curValue[curValue.length] = value; + else + obj[key] = [curValue, value]; + } + if (--pairs === 0) + break; + keyEncoded = valEncoded = customDecode; + encodeCheck = 0; + key = value = ''; + lastPos = i + 1; + sepIdx = eqIdx = 0; + } + continue; + } else { + sepIdx = 0; + if (!valEncoded) { + // Try to match an (valid) encoded byte (once) to minimize unnecessary + // calls to string decoding functions + if (code === 37/*%*/) { + encodeCheck = 1; + } else if (encodeCheck > 0 && + ((code >= 48/*0*/ && code <= 57/*9*/) || + (code >= 65/*A*/ && code <= 70/*F*/) || + (code >= 97/*a*/ && code <= 102/*f*/))) { + if (++encodeCheck === 3) + valEncoded = true; + } else { + encodeCheck = 0; + } + } + } + + // Try matching key/value separator (e.g. '=') if we haven't already + if (eqIdx < eqLen) { + if (code === eq.charCodeAt(eqIdx)) { + if (++eqIdx === eqLen) { + // Key/value separator match! + const end = i - eqIdx + 1; + if (lastPos < end) + key += qs.slice(lastPos, end); + encodeCheck = 0; + lastPos = i + 1; + } + continue; + } else { + eqIdx = 0; + if (!keyEncoded) { + // Try to match an (valid) encoded byte once to minimize unnecessary + // calls to string decoding functions + if (code === 37/*%*/) { + encodeCheck = 1; + } else if (encodeCheck > 0 && + ((code >= 48/*0*/ && code <= 57/*9*/) || + (code >= 65/*A*/ && code <= 70/*F*/) || + (code >= 97/*a*/ && code <= 102/*f*/))) { + if (++encodeCheck === 3) + keyEncoded = true; + } else { + encodeCheck = 0; + } + } + } + } + + if (code === 43/*+*/) { + if (eqIdx < eqLen) { + if (i - lastPos > 0) + key += qs.slice(lastPos, i); + key += '%20'; + keyEncoded = true; + } else { + if (i - lastPos > 0) + value += qs.slice(lastPos, i); + value += '%20'; + valEncoded = true; + } + lastPos = i + 1; + } + } + + // Check if we have leftover key or value data + if (pairs > 0 && (lastPos < qs.length || eqIdx > 0)) { + if (lastPos < qs.length) { + if (eqIdx < eqLen) + key += qs.slice(lastPos); + else if (sepIdx < sepLen) + value += qs.slice(lastPos); + } + if (keyEncoded) + key = decodeStr(key, decode); + if (valEncoded) + value = decodeStr(value, decode); + // Use a key array lookup instead of using hasOwnProperty(), which is + // slower + if (keys.indexOf(key) === -1) { + obj[key] = value; + keys[keys.length] = key; + } else { + const curValue = obj[key]; + // `instanceof Array` is used instead of Array.isArray() because it + // is ~15-20% faster with v8 4.7 and is safe to use because we are + // using it with values being created within this function + if (curValue instanceof Array) + curValue[curValue.length] = value; + else + obj[key] = [curValue, value]; + } + } + + return obj; +}; + + +// v8 does not optimize functions with try-catch blocks, so we isolate them here +// to minimize the damage +function decodeStr(s, decoder) { + try { + return decoder(s); + } catch (e) { + return QueryString.unescape(s, true); + } +} + diff --git a/examples/pxScene2d/src/v8_modules/timers.js b/examples/pxScene2d/src/v8_modules/timers.js new file mode 100644 index 0000000000..9f3e5cd9f5 --- /dev/null +++ b/examples/pxScene2d/src/v8_modules/timers.js @@ -0,0 +1,46 @@ +/* + +pxCore Copyright 2005-2018 John Robinson + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +"use strict"; + +function setTimeout(cb, delay, a1, a2, a3) { + var tid = uv_timer_new(); + uv_timer_start(tid, delay, 0, function () { cb(a1, a2, a3); }); + return tid; +} + +function clearTimeout(tid) { + uv_timer_stop(tid); +} + +function setInterval(cb, delay, a1, a2, a3) { + var tid = uv_timer_new(); + uv_timer_start(tid, delay, delay, function () { cb(a1, a2, a3); }); + return tid; +} + +function clearInterval(tid) { + uv_timer_stop(tid); +} + +module.exports = { + setTimeout: setTimeout, + clearTimeout: clearTimeout, + setInterval: setInterval, + clearInterval: clearInterval, +} diff --git a/examples/pxScene2d/src/v8_modules/url.js b/examples/pxScene2d/src/v8_modules/url.js new file mode 100644 index 0000000000..418b270a1e --- /dev/null +++ b/examples/pxScene2d/src/v8_modules/url.js @@ -0,0 +1,1015 @@ +/* + +pxCore Copyright 2005-2018 John Robinson + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +'use strict'; + +toASCII = require('punycode').toASCII; + +exports.parse = urlParse; +exports.resolve = urlResolve; +exports.resolveObject = urlResolveObject; +exports.format = urlFormat; + +exports.Url = Url; + +function Url() { + this.protocol = null; + this.slashes = null; + this.auth = null; + this.host = null; + this.port = null; + this.hostname = null; + this.hash = null; + this.search = null; + this.query = null; + this.pathname = null; + this.path = null; + this.href = null; +} + +// Reference: RFC 3986, RFC 1808, RFC 2396 + +// define these here so at least they only have to be +// compiled once on the first module load. +const protocolPattern = /^([a-z0-9.+-]+:)/i; +const portPattern = /:[0-9]*$/; + +// Special case for a simple path URL +const simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/; + +const hostnameMaxLen = 255; +// protocols that can allow "unsafe" and "unwise" chars. +const unsafeProtocol = { + 'javascript': true, + 'javascript:': true +}; +// protocols that never have a hostname. +const hostlessProtocol = { + 'javascript': true, + 'javascript:': true +}; +// protocols that always contain a // bit. +const slashedProtocol = { + 'http': true, + 'http:': true, + 'https': true, + 'https:': true, + 'ftp': true, + 'ftp:': true, + 'gopher': true, + 'gopher:': true, + 'file': true, + 'file:': true +}; +const querystring = require('querystring.js'); + +// This constructor is used to store parsed query string values. Instantiating +// this is faster than explicitly calling `Object.create(null)` to get a +// "clean" empty object (tested with v8 v4.9). +function ParsedQueryString() {} +ParsedQueryString.prototype = Object.create(null); + +function urlParse(url, parseQueryString, slashesDenoteHost) { + if (url instanceof Url) return url; + + var u = new Url(); + u.parse(url, parseQueryString, slashesDenoteHost); + return u; +} + +Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { + if (typeof url !== 'string') { + throw new TypeError('Parameter "url" must be a string, not ' + typeof url); + } + + // Copy chrome, IE, opera backslash-handling behavior. + // Back slashes before the query string get converted to forward slashes + // See: https://code.google.com/p/chromium/issues/detail?id=25916 + var hasHash = false; + var start = -1; + var end = -1; + var rest = ''; + var lastPos = 0; + var i = 0; + for (var inWs = false, split = false; i < url.length; ++i) { + const code = url.charCodeAt(i); + + // Find first and last non-whitespace characters for trimming + const isWs = code === 32/* */ || + code === 9/*\t*/ || + code === 13/*\r*/ || + code === 10/*\n*/ || + code === 12/*\f*/ || + code === 160/*\u00A0*/ || + code === 65279/*\uFEFF*/; + if (start === -1) { + if (isWs) + continue; + lastPos = start = i; + } else { + if (inWs) { + if (!isWs) { + end = -1; + inWs = false; + } + } else if (isWs) { + end = i; + inWs = true; + } + } + + // Only convert backslashes while we haven't seen a split character + if (!split) { + switch (code) { + case 35: // '#' + hasHash = true; + // Fall through + case 63: // '?' + split = true; + break; + case 92: // '\\' + if (i - lastPos > 0) + rest += url.slice(lastPos, i); + rest += '/'; + lastPos = i + 1; + break; + } + } else if (!hasHash && code === 35/*#*/) { + hasHash = true; + } + } + + // Check if string was non-empty (including strings with only whitespace) + if (start !== -1) { + if (lastPos === start) { + // We didn't convert any backslashes + + if (end === -1) { + if (start === 0) + rest = url; + else + rest = url.slice(start); + } else { + rest = url.slice(start, end); + } + } else if (end === -1 && lastPos < url.length) { + // We converted some backslashes and have only part of the entire string + rest += url.slice(lastPos); + } else if (end !== -1 && lastPos < end) { + // We converted some backslashes and have only part of the entire string + rest += url.slice(lastPos, end); + } + } + + if (!slashesDenoteHost && !hasHash) { + // Try fast path regexp + const simplePath = simplePathPattern.exec(rest); + if (simplePath) { + this.path = rest; + this.href = rest; + this.pathname = simplePath[1]; + if (simplePath[2]) { + this.search = simplePath[2]; + if (parseQueryString) { + this.query = querystring.parse(this.search.slice(1)); + } else { + this.query = this.search.slice(1); + } + } else if (parseQueryString) { + this.search = ''; + this.query = new ParsedQueryString(); + } + return this; + } + } + + var proto = protocolPattern.exec(rest); + if (proto) { + proto = proto[0]; + var lowerProto = proto.toLowerCase(); + this.protocol = lowerProto; + rest = rest.slice(proto.length); + } + + // figure out if it's got a host + // user@server is *always* interpreted as a hostname, and url + // resolution will treat //foo/bar as host=foo,path=bar because that's + // how the browser resolves relative URLs. + if (slashesDenoteHost || proto || /^\/\/[^@\/]+@[^@\/]+/.test(rest)) { + var slashes = rest.charCodeAt(0) === 47/*/*/ && + rest.charCodeAt(1) === 47/*/*/; + if (slashes && !(proto && hostlessProtocol[proto])) { + rest = rest.slice(2); + this.slashes = true; + } + } + + if (!hostlessProtocol[proto] && + (slashes || (proto && !slashedProtocol[proto]))) { + + // there's a hostname. + // the first instance of /, ?, ;, or # ends the host. + // + // If there is an @ in the hostname, then non-host chars *are* allowed + // to the left of the last @ sign, unless some host-ending character + // comes *before* the @-sign. + // URLs are obnoxious. + // + // ex: + // http://a@b@c/ => user:a@b host:c + // http://a@b?@c => user:a host:b path:/?@c + + // v0.12 TODO(isaacs): This is not quite how Chrome does things. + // Review our test case against browsers more comprehensively. + + var hostEnd = -1; + var atSign = -1; + var nonHost = -1; + for (i = 0; i < rest.length; ++i) { + switch (rest.charCodeAt(i)) { + case 9: // '\t' + case 10: // '\n' + case 13: // '\r' + case 32: // ' ' + case 34: // '"' + case 37: // '%' + case 39: // '\'' + case 59: // ';' + case 60: // '<' + case 62: // '>' + case 92: // '\\' + case 94: // '^' + case 96: // '`' + case 123: // '{' + case 124: // '|' + case 125: // '}' + // Characters that are never ever allowed in a hostname from RFC 2396 + if (nonHost === -1) + nonHost = i; + break; + case 35: // '#' + case 47: // '/' + case 63: // '?' + // Find the first instance of any host-ending characters + if (nonHost === -1) + nonHost = i; + hostEnd = i; + break; + case 64: // '@' + // At this point, either we have an explicit point where the + // auth portion cannot go past, or the last @ char is the decider. + atSign = i; + nonHost = -1; + break; + } + if (hostEnd !== -1) + break; + } + start = 0; + if (atSign !== -1) { + this.auth = decodeURIComponent(rest.slice(0, atSign)); + start = atSign + 1; + } + if (nonHost === -1) { + this.host = rest.slice(start); + rest = ''; + } else { + this.host = rest.slice(start, nonHost); + rest = rest.slice(nonHost); + } + + // pull out port. + this.parseHost(); + + // we've indicated that there is a hostname, + // so even if it's empty, it has to be present. + if (typeof this.hostname !== 'string') + this.hostname = ''; + + var hostname = this.hostname; + + // if hostname begins with [ and ends with ] + // assume that it's an IPv6 address. + var ipv6Hostname = hostname.charCodeAt(0) === 91/*[*/ && + hostname.charCodeAt(hostname.length - 1) === 93/*]*/; + + // validate a little. + if (!ipv6Hostname) { + const result = validateHostname(this, rest, hostname); + if (result !== undefined) + rest = result; + } + + if (this.hostname.length > hostnameMaxLen) { + this.hostname = ''; + } else { + // hostnames are always lower case. + this.hostname = this.hostname.toLowerCase(); + } + + if (!ipv6Hostname) { + // IDNA Support: Returns a punycoded representation of "domain". + // It only converts parts of the domain name that + // have non-ASCII characters, i.e. it doesn't matter if + // you call it with a domain that already is ASCII-only. + this.hostname = toASCII(this.hostname); + } + + var p = this.port ? ':' + this.port : ''; + var h = this.hostname || ''; + this.host = h + p; + + // strip [ and ] from the hostname + // the host field still retains them, though + if (ipv6Hostname) { + this.hostname = this.hostname.slice(1, -1); + if (rest[0] !== '/') { + rest = '/' + rest; + } + } + } + + // now rest is set to the post-host stuff. + // chop off any delim chars. + if (!unsafeProtocol[lowerProto]) { + // First, make 100% sure that any "autoEscape" chars get + // escaped, even if encodeURIComponent doesn't think they + // need to be. + const result = autoEscapeStr(rest); + if (result !== undefined) + rest = result; + } + + var questionIdx = -1; + var hashIdx = -1; + for (i = 0; i < rest.length; ++i) { + const code = rest.charCodeAt(i); + if (code === 35/*#*/) { + this.hash = rest.slice(i); + hashIdx = i; + break; + } else if (code === 63/*?*/ && questionIdx === -1) { + questionIdx = i; + } + } + + if (questionIdx !== -1) { + if (hashIdx === -1) { + this.search = rest.slice(questionIdx); + this.query = rest.slice(questionIdx + 1); + } else { + this.search = rest.slice(questionIdx, hashIdx); + this.query = rest.slice(questionIdx + 1, hashIdx); + } + if (parseQueryString) { + this.query = querystring.parse(this.query); + } + } else if (parseQueryString) { + // no query string, but parseQueryString still requested + this.search = ''; + this.query = new ParsedQueryString(); + } + + var firstIdx = (questionIdx !== -1 && + (hashIdx === -1 || questionIdx < hashIdx) + ? questionIdx + : hashIdx); + if (firstIdx === -1) { + if (rest.length > 0) + this.pathname = rest; + } else if (firstIdx > 0) { + this.pathname = rest.slice(0, firstIdx); + } + if (slashedProtocol[lowerProto] && + this.hostname && !this.pathname) { + this.pathname = '/'; + } + + // to support http.request + if (this.pathname || this.search) { + const p = this.pathname || ''; + const s = this.search || ''; + this.path = p + s; + } + + // finally, reconstruct the href based on what has been validated. + this.href = this.format(); + return this; +}; + +function validateHostname(self, rest, hostname) { + for (var i = 0, lastPos; i <= hostname.length; ++i) { + var code; + if (i < hostname.length) + code = hostname.charCodeAt(i); + if (code === 46/*.*/ || i === hostname.length) { + if (i - lastPos > 0) { + if (i - lastPos > 63) { + self.hostname = hostname.slice(0, lastPos + 63); + return '/' + hostname.slice(lastPos + 63) + rest; + } + } + lastPos = i + 1; + continue; + } else if ((code >= 48/*0*/ && code <= 57/*9*/) || + (code >= 97/*a*/ && code <= 122/*z*/) || + code === 45/*-*/ || + (code >= 65/*A*/ && code <= 90/*Z*/) || + code === 43/*+*/ || + code === 95/*_*/ || + code > 127) { + continue; + } + // Invalid host character + self.hostname = hostname.slice(0, i); + if (i < hostname.length) + return '/' + hostname.slice(i) + rest; + break; + } +} + +function autoEscapeStr(rest) { + var newRest = ''; + var lastPos = 0; + for (var i = 0; i < rest.length; ++i) { + // Automatically escape all delimiters and unwise characters from RFC 2396 + // Also escape single quotes in case of an XSS attack + switch (rest.charCodeAt(i)) { + case 9: // '\t' + if (i - lastPos > 0) + newRest += rest.slice(lastPos, i); + newRest += '%09'; + lastPos = i + 1; + break; + case 10: // '\n' + if (i - lastPos > 0) + newRest += rest.slice(lastPos, i); + newRest += '%0A'; + lastPos = i + 1; + break; + case 13: // '\r' + if (i - lastPos > 0) + newRest += rest.slice(lastPos, i); + newRest += '%0D'; + lastPos = i + 1; + break; + case 32: // ' ' + if (i - lastPos > 0) + newRest += rest.slice(lastPos, i); + newRest += '%20'; + lastPos = i + 1; + break; + case 34: // '"' + if (i - lastPos > 0) + newRest += rest.slice(lastPos, i); + newRest += '%22'; + lastPos = i + 1; + break; + case 39: // '\'' + if (i - lastPos > 0) + newRest += rest.slice(lastPos, i); + newRest += '%27'; + lastPos = i + 1; + break; + case 60: // '<' + if (i - lastPos > 0) + newRest += rest.slice(lastPos, i); + newRest += '%3C'; + lastPos = i + 1; + break; + case 62: // '>' + if (i - lastPos > 0) + newRest += rest.slice(lastPos, i); + newRest += '%3E'; + lastPos = i + 1; + break; + case 92: // '\\' + if (i - lastPos > 0) + newRest += rest.slice(lastPos, i); + newRest += '%5C'; + lastPos = i + 1; + break; + case 94: // '^' + if (i - lastPos > 0) + newRest += rest.slice(lastPos, i); + newRest += '%5E'; + lastPos = i + 1; + break; + case 96: // '`' + if (i - lastPos > 0) + newRest += rest.slice(lastPos, i); + newRest += '%60'; + lastPos = i + 1; + break; + case 123: // '{' + if (i - lastPos > 0) + newRest += rest.slice(lastPos, i); + newRest += '%7B'; + lastPos = i + 1; + break; + case 124: // '|' + if (i - lastPos > 0) + newRest += rest.slice(lastPos, i); + newRest += '%7C'; + lastPos = i + 1; + break; + case 125: // '}' + if (i - lastPos > 0) + newRest += rest.slice(lastPos, i); + newRest += '%7D'; + lastPos = i + 1; + break; + } + } + if (lastPos === 0) + return; + if (lastPos < rest.length) + return newRest + rest.slice(lastPos); + else + return newRest; +} + +// format a parsed object into a url string +function urlFormat(obj) { + // ensure it's an object, and not a string url. + // If it's an obj, this is a no-op. + // this way, you can call url_format() on strings + // to clean up potentially wonky urls. + if (typeof obj === 'string') obj = urlParse(obj); + + else if (typeof obj !== 'object' || obj === null) + throw new TypeError('Parameter "urlObj" must be an object, not ' + + obj === null ? 'null' : typeof obj); + + else if (!(obj instanceof Url)) return Url.prototype.format.call(obj); + + return obj.format(); +} + +Url.prototype.format = function() { + var auth = this.auth || ''; + if (auth) { + auth = encodeAuth(auth); + auth += '@'; + } + + var protocol = this.protocol || ''; + var pathname = this.pathname || ''; + var hash = this.hash || ''; + var host = false; + var query = ''; + + if (this.host) { + host = auth + this.host; + } else if (this.hostname) { + host = auth + (this.hostname.indexOf(':') === -1 ? + this.hostname : + '[' + this.hostname + ']'); + if (this.port) { + host += ':' + this.port; + } + } + + if (this.query !== null && typeof this.query === 'object') + query = querystring.stringify(this.query); + + var search = this.search || (query && ('?' + query)) || ''; + + if (protocol && protocol.charCodeAt(protocol.length - 1) !== 58/*:*/) + protocol += ':'; + + var newPathname = ''; + var lastPos = 0; + for (var i = 0; i < pathname.length; ++i) { + switch (pathname.charCodeAt(i)) { + case 35: // '#' + if (i - lastPos > 0) + newPathname += pathname.slice(lastPos, i); + newPathname += '%23'; + lastPos = i + 1; + break; + case 63: // '?' + if (i - lastPos > 0) + newPathname += pathname.slice(lastPos, i); + newPathname += '%3F'; + lastPos = i + 1; + break; + } + } + if (lastPos > 0) { + if (lastPos !== pathname.length) + pathname = newPathname + pathname.slice(lastPos); + else + pathname = newPathname; + } + + // only the slashedProtocols get the //. Not mailto:, xmpp:, etc. + // unless they had them to begin with. + if (this.slashes || + (!protocol || slashedProtocol[protocol]) && host !== false) { + host = '//' + (host || ''); + if (pathname && pathname.charCodeAt(0) !== 47/*/*/) + pathname = '/' + pathname; + } else if (!host) { + host = ''; + } + + search = search.replace(/#/g, '%23'); + + if (hash && hash.charCodeAt(0) !== 35/*#*/) hash = '#' + hash; + if (search && search.charCodeAt(0) !== 63/*?*/) search = '?' + search; + + return protocol + host + pathname + search + hash; +}; + +function urlResolve(source, relative) { + return urlParse(source, false, true).resolve(relative); +} + +Url.prototype.resolve = function(relative) { + return this.resolveObject(urlParse(relative, false, true)).format(); +}; + +function urlResolveObject(source, relative) { + if (!source) return relative; + return urlParse(source, false, true).resolveObject(relative); +} + +Url.prototype.resolveObject = function(relative) { + if (typeof relative === 'string') { + var rel = new Url(); + rel.parse(relative, false, true); + relative = rel; + } + + var result = new Url(); + var tkeys = Object.keys(this); + for (var tk = 0; tk < tkeys.length; tk++) { + var tkey = tkeys[tk]; + result[tkey] = this[tkey]; + } + + // hash is always overridden, no matter what. + // even href="" will remove it. + result.hash = relative.hash; + + // if the relative url is empty, then there's nothing left to do here. + if (relative.href === '') { + result.href = result.format(); + return result; + } + + // hrefs like //foo/bar always cut to the protocol. + if (relative.slashes && !relative.protocol) { + // take everything except the protocol from relative + var rkeys = Object.keys(relative); + for (var rk = 0; rk < rkeys.length; rk++) { + var rkey = rkeys[rk]; + if (rkey !== 'protocol') + result[rkey] = relative[rkey]; + } + + //urlParse appends trailing / to urls like http://www.example.com + if (slashedProtocol[result.protocol] && + result.hostname && !result.pathname) { + result.path = result.pathname = '/'; + } + + result.href = result.format(); + return result; + } + + if (relative.protocol && relative.protocol !== result.protocol) { + // if it's a known url protocol, then changing + // the protocol does weird things + // first, if it's not file:, then we MUST have a host, + // and if there was a path + // to begin with, then we MUST have a path. + // if it is file:, then the host is dropped, + // because that's known to be hostless. + // anything else is assumed to be absolute. + if (!slashedProtocol[relative.protocol]) { + var keys = Object.keys(relative); + for (var v = 0; v < keys.length; v++) { + var k = keys[v]; + result[k] = relative[k]; + } + result.href = result.format(); + return result; + } + + result.protocol = relative.protocol; + if (!relative.host && + !/^file:?$/.test(relative.protocol) && + !hostlessProtocol[relative.protocol]) { + const relPath = (relative.pathname || '').split('/'); + while (relPath.length && !(relative.host = relPath.shift())); + if (!relative.host) relative.host = ''; + if (!relative.hostname) relative.hostname = ''; + if (relPath[0] !== '') relPath.unshift(''); + if (relPath.length < 2) relPath.unshift(''); + result.pathname = relPath.join('/'); + } else { + result.pathname = relative.pathname; + } + result.search = relative.search; + result.query = relative.query; + result.host = relative.host || ''; + result.auth = relative.auth; + result.hostname = relative.hostname || relative.host; + result.port = relative.port; + // to support http.request + if (result.pathname || result.search) { + var p = result.pathname || ''; + var s = result.search || ''; + result.path = p + s; + } + result.slashes = result.slashes || relative.slashes; + result.href = result.format(); + return result; + } + + var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'); + var isRelAbs = ( + relative.host || + relative.pathname && relative.pathname.charAt(0) === '/' + ); + var mustEndAbs = (isRelAbs || isSourceAbs || + (result.host && relative.pathname)); + var removeAllDots = mustEndAbs; + var srcPath = result.pathname && result.pathname.split('/') || []; + var relPath = relative.pathname && relative.pathname.split('/') || []; + var psychotic = result.protocol && !slashedProtocol[result.protocol]; + + // if the url is a non-slashed url, then relative + // links like ../.. should be able + // to crawl up to the hostname, as well. This is strange. + // result.protocol has already been set by now. + // Later on, put the first path part into the host field. + if (psychotic) { + result.hostname = ''; + result.port = null; + if (result.host) { + if (srcPath[0] === '') srcPath[0] = result.host; + else srcPath.unshift(result.host); + } + result.host = ''; + if (relative.protocol) { + relative.hostname = null; + relative.port = null; + result.auth = null; + if (relative.host) { + if (relPath[0] === '') relPath[0] = relative.host; + else relPath.unshift(relative.host); + } + relative.host = null; + } + mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === ''); + } + + if (isRelAbs) { + // it's absolute. + if (relative.host || relative.host === '') { + if (result.host !== relative.host) result.auth = null; + result.host = relative.host; + result.port = relative.port; + } + if (relative.hostname || relative.hostname === '') { + if (result.hostname !== relative.hostname) result.auth = null; + result.hostname = relative.hostname; + } + result.search = relative.search; + result.query = relative.query; + srcPath = relPath; + // fall through to the dot-handling below. + } else if (relPath.length) { + // it's relative + // throw away the existing file, and take the new path instead. + if (!srcPath) srcPath = []; + srcPath.pop(); + srcPath = srcPath.concat(relPath); + result.search = relative.search; + result.query = relative.query; + } else if (relative.search !== null && relative.search !== undefined) { + // just pull out the search. + // like href='?foo'. + // Put this after the other two cases because it simplifies the booleans + if (psychotic) { + result.hostname = result.host = srcPath.shift(); + //occasionally the auth can get stuck only in host + //this especially happens in cases like + //url.resolveObject('mailto:local1@domain1', 'local2@domain2') + const authInHost = result.host && result.host.indexOf('@') > 0 ? + result.host.split('@') : false; + if (authInHost) { + result.auth = authInHost.shift(); + result.host = result.hostname = authInHost.shift(); + } + } + result.search = relative.search; + result.query = relative.query; + //to support http.request + if (result.pathname !== null || result.search !== null) { + result.path = (result.pathname ? result.pathname : '') + + (result.search ? result.search : ''); + } + result.href = result.format(); + return result; + } + + if (!srcPath.length) { + // no path at all. easy. + // we've already handled the other stuff above. + result.pathname = null; + //to support http.request + if (result.search) { + result.path = '/' + result.search; + } else { + result.path = null; + } + result.href = result.format(); + return result; + } + + // if a url ENDs in . or .., then it must get a trailing slash. + // however, if it ends in anything else non-slashy, + // then it must NOT get a trailing slash. + var last = srcPath.slice(-1)[0]; + var hasTrailingSlash = ( + (result.host || relative.host || srcPath.length > 1) && + (last === '.' || last === '..') || last === ''); + + // strip single dots, resolve double dots to parent dir + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = srcPath.length - 1; i >= 0; i--) { + last = srcPath[i]; + if (last === '.') { + spliceOne(srcPath, i); + } else if (last === '..') { + spliceOne(srcPath, i); + up++; + } else if (up) { + spliceOne(srcPath, i); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (!mustEndAbs && !removeAllDots) { + for (; up--; up) { + srcPath.unshift('..'); + } + } + + if (mustEndAbs && srcPath[0] !== '' && + (!srcPath[0] || srcPath[0].charAt(0) !== '/')) { + srcPath.unshift(''); + } + + if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) { + srcPath.push(''); + } + + var isAbsolute = srcPath[0] === '' || + (srcPath[0] && srcPath[0].charAt(0) === '/'); + + // put the host back + if (psychotic) { + result.hostname = result.host = isAbsolute ? '' : + srcPath.length ? srcPath.shift() : ''; + //occasionally the auth can get stuck only in host + //this especially happens in cases like + //url.resolveObject('mailto:local1@domain1', 'local2@domain2') + const authInHost = result.host && result.host.indexOf('@') > 0 ? + result.host.split('@') : false; + if (authInHost) { + result.auth = authInHost.shift(); + result.host = result.hostname = authInHost.shift(); + } + } + + mustEndAbs = mustEndAbs || (result.host && srcPath.length); + + if (mustEndAbs && !isAbsolute) { + srcPath.unshift(''); + } + + if (!srcPath.length) { + result.pathname = null; + result.path = null; + } else { + result.pathname = srcPath.join('/'); + } + + //to support request.http + if (result.pathname !== null || result.search !== null) { + result.path = (result.pathname ? result.pathname : '') + + (result.search ? result.search : ''); + } + result.auth = relative.auth || result.auth; + result.slashes = result.slashes || relative.slashes; + result.href = result.format(); + return result; +}; + +Url.prototype.parseHost = function() { + var host = this.host; + var port = portPattern.exec(host); + if (port) { + port = port[0]; + if (port !== ':') { + this.port = port.slice(1); + } + host = host.slice(0, host.length - port.length); + } + if (host) this.hostname = host; +}; + +// About 1.5x faster than the two-arg version of Array#splice(). +function spliceOne(list, index) { + for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1) + list[i] = list[k]; + list.pop(); +} + +var hexTable = new Array(256); +for (var i = 0; i < 256; ++i) + hexTable[i] = '%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase(); +function encodeAuth(str) { + // faster encodeURIComponent alternative for encoding auth uri components + var out = ''; + var lastPos = 0; + for (var i = 0; i < str.length; ++i) { + var c = str.charCodeAt(i); + + // These characters do not need escaping: + // ! - . _ ~ + // ' ( ) * : + // digits + // alpha (uppercase) + // alpha (lowercase) + if (c === 0x21 || c === 0x2D || c === 0x2E || c === 0x5F || c === 0x7E || + (c >= 0x27 && c <= 0x2A) || + (c >= 0x30 && c <= 0x3A) || + (c >= 0x41 && c <= 0x5A) || + (c >= 0x61 && c <= 0x7A)) { + continue; + } + + if (i - lastPos > 0) + out += str.slice(lastPos, i); + + lastPos = i + 1; + + // Other ASCII characters + if (c < 0x80) { + out += hexTable[c]; + continue; + } + + // Multi-byte characters ... + if (c < 0x800) { + out += hexTable[0xC0 | (c >> 6)] + hexTable[0x80 | (c & 0x3F)]; + continue; + } + if (c < 0xD800 || c >= 0xE000) { + out += hexTable[0xE0 | (c >> 12)] + + hexTable[0x80 | ((c >> 6) & 0x3F)] + + hexTable[0x80 | (c & 0x3F)]; + continue; + } + // Surrogate pair + ++i; + var c2; + if (i < str.length) + c2 = str.charCodeAt(i) & 0x3FF; + else + c2 = 0; + c = 0x10000 + (((c & 0x3FF) << 10) | c2); + out += hexTable[0xF0 | (c >> 18)] + + hexTable[0x80 | ((c >> 12) & 0x3F)] + + hexTable[0x80 | ((c >> 6) & 0x3F)] + + hexTable[0x80 | (c & 0x3F)]; + } + if (lastPos === 0) + return str; + if (lastPos < str.length) + return out + str.slice(lastPos); + return out; +} diff --git a/examples/pxScene2d/src/v8_modules/vm.js b/examples/pxScene2d/src/v8_modules/vm.js new file mode 100644 index 0000000000..25b1551916 --- /dev/null +++ b/examples/pxScene2d/src/v8_modules/vm.js @@ -0,0 +1,28 @@ +/* + +pxCore Copyright 2005-2018 John Robinson + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +"use strict"; + +function runInNewContext(code, sandbox, options, px, xModule, filename, dirname) { + // TODO + return uv_run_in_context(code, sandbox, options, px, xModule, filename, dirname); +} + +module.exports = { + runInNewContext: runInNewContext, +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 86c26006d4..327121f6d9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -222,7 +222,7 @@ if (SUPPORT_V8) message("Adding V8 scripting support") add_definitions(-DRTSCRIPT_SUPPORT_V8) set(PXCORE_FILES ${PXCORE_FILES} rtScriptV8/rtScriptV8.cpp rtScriptV8/jsCallback.cpp rtScriptV8/rtFunctionWrapper.cpp - rtScriptV8/rtObjectWrapper.cpp rtScriptV8/rtWrapperUtils.cpp) + rtScriptV8/rtObjectWrapper.cpp rtScriptV8/rtWrapperUtils.cpp rtScriptV8/rtJsModules.cpp) endif() if (PXCORE_MATRIX_HELPERS) diff --git a/src/rtScriptV8/rtJsModules.cpp b/src/rtScriptV8/rtJsModules.cpp new file mode 100644 index 0000000000..c30bd10d0e --- /dev/null +++ b/src/rtScriptV8/rtJsModules.cpp @@ -0,0 +1,470 @@ +/* + +pxCore Copyright 2005-2018 John Robinson + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +#include "rtWrapperUtils.h" +#include "rtObjectWrapper.h" +#include "rtFunctionWrapper.h" +#include "rtJsModules.h" +#include + +#include +#include +#include + +#if defined(USE_STD_THREADS) +#include +#include +#endif + +#include "v8_headers.h" + +#if !defined(_WIN32) +#include +#endif + +#if defined(_WIN32) +#include +#include +#include +#ifndef S_ISREG +# define S_ISREG(x) (((x) & _S_IFMT) == _S_IFREG) +#endif +#ifndef S_ISDIR +# define S_ISDIR(x) (((x) & _S_IFMT) == _S_IFDIR) +#endif +#ifndef S_ISFIFO +# define S_ISFIFO(x) (((x) & _S_IFMT) == _S_IFIFO) +#endif +#ifndef S_ISCHR +# define S_ISCHR(x) (((x) & _S_IFMT) == _S_IFCHR) +#endif +#ifndef S_ISBLK +# define S_ISBLK(x) 0 +#endif +#ifndef S_ISLINK +# define S_ISLNK(x) 0 +#endif +#ifndef S_ISSOCK +# define S_ISSOCK(x) 0 +#endif +#endif + +using namespace std; + +//----------------------------------- + +namespace rtScriptV8Utils +{ + +static void uvGetPlatform(const v8::FunctionCallbackInfo& args) +{ + Isolate* isolate = args.GetIsolate(); + HandleScope scope(isolate); + const char *platform = "unknown"; +#ifdef _WIN32 + platform = "win32"; +#elif defined(__linux__) + platform = "linux"; +#elif defined(__APPLE__) + platform = "macosx"; +#endif + args.GetReturnValue().Set(String::NewFromUtf8(args.GetIsolate(), platform, NewStringType::kNormal).ToLocalChecked()); +} + +static void uvGetHrTime(const v8::FunctionCallbackInfo& args) +{ + Isolate* isolate = args.GetIsolate(); + HandleScope scope(isolate); + uint64_t hrtime = uv_hrtime(); + int nanoseconds = hrtime % (int)1e9; + int seconds = hrtime / 1e9; + + Local arr = Array::New(isolate, 2); + arr->Set(0, Integer::New(isolate, seconds)); + arr->Set(1, Integer::New(isolate, nanoseconds)); + + args.GetReturnValue().Set(arr); +} + +uv_loop_t *getEventLoopFromArgs(const v8::FunctionCallbackInfo& args) +{ + assert(args.Data()->IsExternal()); + v8::External *val = v8::External::Cast(*args.Data()); + assert(val != NULL); + uv_loop_t *loop = (uv_loop_t *)val->Value(); + return loop; +} + +static void uvFsAccess(const v8::FunctionCallbackInfo& args) +{ + Isolate* isolate = args.GetIsolate(); + HandleScope scope(isolate); + + uv_loop_t *loop = getEventLoopFromArgs(args); + + args.GetReturnValue().Set(-1); + + if (args.Length() != 2) { + return; + } + + assert(args.Length() == 2); + assert(args[0]->IsString()); + assert(args[1]->IsString()); + + rtString filePath = toString(args[0]->ToString()); + rtString fileOpenMode = toString(args[1]->ToString()); + + int mode = 0; + size_t i, l; + for (i = 0, l = fileOpenMode.length(); i < l; ++i) { + switch (fileOpenMode[i]) { + case 'r': case 'R': mode |= R_OK; break; + case 'w': case 'W': mode |= W_OK; break; + case 'x': case 'X': mode |= X_OK; break; + default: + rtLogWarn("Unknown file access mode '%s'", fileOpenMode.cString()); + return; + } + } + + uv_fs_t req; + int ret = uv_fs_access(loop, &req, filePath.cString(), mode, NULL); + + args.GetReturnValue().Set(ret); +} + +static void uvFsGetSize(const v8::FunctionCallbackInfo& args) +{ + Isolate* isolate = args.GetIsolate(); + HandleScope scope(isolate); + + uv_loop_t *loop = getEventLoopFromArgs(args); + + args.GetReturnValue().Set(-1); + + if (args.Length() != 1) { + return; + } + + assert(args.Length() == 1); + assert(args[0]->IsString()); + + rtString filePath = toString(args[0]->ToString()); + + uv_fs_t req; + int ret = uv_fs_stat(loop, &req, filePath.cString(), NULL); + + if (ret < 0) { + return; + } + + args.GetReturnValue().Set((uint32_t)req.statbuf.st_size); +} + +static int stringToFlags(const char* s) +{ + bool read = false; + bool write = false; + int flags = 0; + while (s && s[0]) { + switch (s[0]) { + case 'r': read = true; break; + case 'w': write = true; flags |= O_TRUNC | O_CREAT; break; + case 'a': write = true; flags |= O_APPEND | O_CREAT; break; + case '+': read = true; write = true; break; + case 'x': flags |= O_EXCL; break; + +#ifndef _WIN32 + case 's': flags |= O_SYNC; break; +#endif + + default: + return 0; + } + s++; + } + flags |= read ? (write ? O_RDWR : O_RDONLY) : + (write ? O_WRONLY : 0); + return flags; +} + +static void uvFsOpen(const v8::FunctionCallbackInfo& args) +{ + Isolate* isolate = args.GetIsolate(); + HandleScope scope(isolate); + + uv_loop_t *loop = getEventLoopFromArgs(args); + + args.GetReturnValue().SetNull(); + + if (args.Length() != 3) { + return; + } + + assert(args.Length() == 3); + assert(args[0]->IsString()); + assert(args[1]->IsString()); + + rtString filePath = toString(args[0]->ToString()); + rtString fileOpenMode = toString(args[1]->ToString()); + + int flags = stringToFlags(fileOpenMode.cString()); + int mode = (int)args[2]->ToInteger()->Value(); + + uv_fs_t req; + int ret = uv_fs_open(loop, &req, filePath.cString(), flags, mode, NULL); + + if (ret < 0) { + return; + } + + args.GetReturnValue().Set(v8::External::New(isolate, (void *)req.result)); +} + +static void uvFsRead(const v8::FunctionCallbackInfo& args) +{ + Isolate* isolate = args.GetIsolate(); + HandleScope scope(isolate); + + uv_loop_t *loop = getEventLoopFromArgs(args); + + args.GetReturnValue().SetNull(); + + if (args.Length() != 3 || !args[0]->IsExternal()) { + return; + } + + assert(args.Length() == 3); + assert(args[0]->IsExternal()); + + v8::External *val = v8::External::Cast(*args[0]); + void *fd = (void *)val->Value(); + int size = (int)args[1]->ToInteger()->Value(); + int offset = (int)args[2]->ToInteger()->Value(); + + void *ptr = malloc(size); + uv_buf_t buf = uv_buf_init((char *)ptr, size); + + uv_fs_t req; + uv_fs_read(loop, &req, static_cast(reinterpret_cast(fd)), &buf, 1, offset, NULL); + + if (req.result <= 0) { + free(ptr); + return; + } + + Local arrBuf = ArrayBuffer::New(isolate, ptr, req.result, ArrayBufferCreationMode::kInternalized); + free(ptr); + + args.GetReturnValue().Set(arrBuf); +} + +static void uvFsClose(const v8::FunctionCallbackInfo& args) +{ + Isolate* isolate = args.GetIsolate(); + HandleScope scope(isolate); + + uv_loop_t *loop = getEventLoopFromArgs(args); + + args.GetReturnValue().Set(-1); + + if (args.Length() != 1 || !args[0]->IsExternal()) { + return; + } + + assert(args.Length() == 1); + assert(args[0]->IsExternal()); + + v8::External *val = v8::External::Cast(*args[0]); + void *fd = (void *)val->Value(); + + uv_fs_t req; + int ret = uv_fs_close(loop, &req, static_cast(reinterpret_cast(fd)), NULL); + + if (ret < 0) { + return; + } + + args.GetReturnValue().Set(1); +} + +static void uvTimerNew(const v8::FunctionCallbackInfo& args) +{ + Isolate* isolate = args.GetIsolate(); + HandleScope scope(isolate); + + uv_loop_t *loop = getEventLoopFromArgs(args); + + args.GetReturnValue().SetNull(); + + if (args.Length() != 0) { + return; + } + + uv_timer_t *timer = new uv_timer_t(); + uv_timer_init(loop, timer); + + args.GetReturnValue().Set(v8::External::New(isolate, (void *)timer)); +} + +struct cbData +{ + Isolate *mIsolate; + v8::Persistent mContext; + v8::Persistent mFunc; +}; + +static void v8TimerCallback(uv_timer_t* handle) +{ + cbData *data = (cbData *)handle->data; + + Local ctx = PersistentToLocal(data->mIsolate, data->mContext); + Local func = PersistentToLocal(data->mIsolate, data->mFunc); + Local argv[1] = { func.As() }; + + (void)func->Call(ctx, argv[0], 1, argv); +} + +static void uvTimerStart(const v8::FunctionCallbackInfo& args) +{ + Isolate* isolate = args.GetIsolate(); + HandleScope scope(isolate); + + uv_loop_t *loop = getEventLoopFromArgs(args); + + args.GetReturnValue().Set(-1); + + if (args.Length() != 4 || !args[0]->IsExternal()) { + return; + } + + assert(args.Length() == 4); + assert(args[0]->IsExternal()); + assert(args[3]->IsFunction()); + + v8::External *val = v8::External::Cast(*args[0]); + uv_timer_t *handle = (uv_timer_t *)val->Value(); + int timeout = (int)args[1]->ToInteger()->Value(); + int repeat = (int)args[2]->ToInteger()->Value(); + + v8::Persistent func(isolate, Local::Cast(args[3])); + + cbData *data = new cbData(); + + handle->data = data; + data->mIsolate = isolate; + data->mContext.Reset(isolate, isolate->GetCurrentContext()); + data->mFunc.Reset(isolate, Local::Cast(args[3])); + + uv_timer_start(handle, &v8TimerCallback, timeout, repeat); + + args.GetReturnValue().Set(1); +} + +static void uvTimerStop(const v8::FunctionCallbackInfo& args) +{ + Isolate* isolate = args.GetIsolate(); + HandleScope scope(isolate); + + uv_loop_t *loop = getEventLoopFromArgs(args); + + args.GetReturnValue().Set(-1); + + if (args.Length() != 1 || !args[0]->IsExternal()) { + return; + } + + assert(args.Length() == 1); + assert(args[0]->IsExternal()); + + v8::External *val = v8::External::Cast(*args[0]); + uv_timer_t *handle = (uv_timer_t *)val->Value(); + + uv_timer_stop(handle); + + args.GetReturnValue().Set(1); +} + +static std::string v8ReadFile(const char *file) +{ + std::ifstream src_file(file); + std::stringstream src_script; + + src_script << src_file.rdbuf(); // slurp up file + + std::string s = src_script.str(); + + return s; +} + +static void uvRunInContext(const v8::FunctionCallbackInfo& args) +{ + Isolate* isolate = args.GetIsolate(); + HandleScope scope(isolate); + + uv_loop_t *loop = getEventLoopFromArgs(args); + + args.GetReturnValue().SetNull(); + + /*if (args.Length() != 1) { + return; + }*/ + + assert(args.Length() >= 1); + assert(args[0]->IsString()); + + rtString sourceCode = toString(args[0]->ToString()); + + Locker locker(isolate); + Isolate::Scope isolate_scope(isolate); + HandleScope handle_scope(isolate); + + Local local_context = isolate->GetCurrentContext(); + Context::Scope context_scope(local_context); + + TryCatch tryCatch(isolate); + Local source = String::NewFromUtf8(isolate, sourceCode.cString()); + Local