This commit is contained in:
Sean Morris committed 2020-08-22 00:53:41 -04:00
1 parent 3d5f8b8f96
commit d5e9d051a7
16 files changed
+2134 -1293

No files matched your search

+2 -4
View File
@@ -1,8 +1,6 @@
{
"presets": [["es2015"]],
"presets": [["@babel/preset-env"]],
"plugins": [
["babel-plugin-transform-builtin-extend", {
globals: ["EventTarget"]
}]
["@babel/plugin-transform-classes"]
]
}
+1 -2
View File
@@ -1,4 +1,3 @@
/php-src
/php-web.js
/php-web.wasm
/php-web.data
@@ -6,4 +5,4 @@
/php-shell.wasm
/php-shell.data
/Php.js
/node_modules
+3
View File
@@ -0,0 +1,3 @@
[submodule "php-src"]
path = php-src
url = ./php-src
+45 -8
View File
@@ -1,20 +1,57 @@
SHELL=/bin/bash -euo pipefail
SHELL=/bin/bash -euxo pipefail
.PHONY: build hooks build-web-bin build-shell-bin clean
PHP_BRANCH:=PHP-7.4
VRZNO_BRANCH:=master
build: build-js build-web-bin
.PHONY: configure build hooks build-js build-web-bin build-webview-bin build-node-bin build-shell-bin build-worker-bin clean
build: configure build-js build-web-bin build-webview-bin build-node-bin build-shell-bin build-worker-bin
configure: php-src php-src/ext/vrzno
docker-compose run emscripten-builder bash configure.sh
php-src:
git clone https://github.com/php/php-src.git \
--branch ${PHP_BRANCH} \
--single-branch \
--depth 1;
php-src/ext/vrzno:
cd php-src/ext \
&& git clone https://github.com/seanmorris/vrzno.git \
--branch ${VRZNO_BRANCH} \
--single-branch \
--depth 1; \
hooks:
@ git config core.hooksPath githooks
build-js:
@ npx babel source --out-dir . \
@ npm install; npx babel source --out-dir .
build-image:
docker-compose build
pull-image:
docker-compose pull
push-image:
docker-compose push
build-web-bin:
@ docker run --env ENVIRONMENT=web --rm -t -v $$(pwd):/src trzeci/emscripten-ubuntu:latest bash build.sh
docker-compose run -e ENVIRONMENT=web emscripten-builder bash build.sh
# build-shell-bin:
# @ docker run --env ENVIRONMENT=shell --rm -t -v $$(pwd):/src trzeci/emscripten-ubuntu:latest bash build.sh
build-webview-bin:
docker-compose run -e ENVIRONMENT=webview emscripten-builder bash build.sh
build-node-bin:
docker-compose run -e ENVIRONMENT=node emscripten-builder bash build.sh
build-shell-bin:
docker-compose run -e ENVIRONMENT=shell emscripten-builder bash build.sh
build-worker-bin:
docker-compose run -e ENVIRONMENT=worker emscripten-builder bash build.sh
clean:
@ rm -rf php-src php-shell.* php-web.* Php.js
docker-compose run emscripten-builder rm -rf php-src Php.js php-web.* php-webview.* php-node.* php-shell.* php-worker.*
+20 -61
View File
@@ -1,70 +1,29 @@
#!/usr/bin/env bash
set -euo pipefail
set -euxo pipefail;
PHP_BRANCH=PHP-7.4
pushd php-src
if [[ ! -d php-src ]]; then
echo "Get PHP source from branch $PHP_BRANCH"
git clone https://github.com/php/php-src.git --branch $PHP_BRANCH --single-branch --no-tags --depth 1
fi
emmake make -j8
# Install autoconf
if ! hash autoconf 2>/dev/null; then
apt-get update && apt-get install -y autoconf
fi
# Install bison
if ! hash bison 2>/dev/null; then
apt-get update && apt-get install -y bison
fi
# Install re2c
if ! hash re2c 2>/dev/null; then
apt-get update && apt-get install -y re2c
fi
echo "Configure"
cd php-src
./buildconf
emconfigure ./configure \
--disable-all \
--disable-cgi \
--disable-cli \
--disable-rpath \
--disable-phpdbg \
--with-valgrind=no \
--without-pear \
--without-pcre-jit \
--with-layout=GNU \
--enable-embed=static \
--enable-bcmath \
--enable-json \
--enable-ctype \
--enable-mbstring \
--disable-mbregex \
--enable-tokenizer
# echo "Build"
emmake make
mkdir -p out
emcc -O3 -I . -I Zend -I main -I TSRM/ ../source/pib_eval.c -o pib_eval.o
emcc -O3 \
--llvm-lto 2 \
-s ENVIRONMENT=${ENVIRONMENT:-shell} \
-s EXPORTED_FUNCTIONS='["_pib_eval", "_php_embed_init", "_zend_eval_string", "_php_embed_shutdown", "_main"]' \
-s EXTRA_EXPORTED_RUNTIME_METHODS='["ccall"]' \
-s MODULARIZE=1 \
-s EXPORT_NAME="'PHP'" \
-s TOTAL_MEMORY=134217728 \
-s ASSERTIONS=0 \
-s INVOKE_RUN=0 \
-s ERROR_ON_UNDEFINED_SYMBOLS=0 \
--preload-file Zend/bench.php \
libs/libphp7.a pib_eval.o -o out/php-${ENVIRONMENT:-shell}.js
--llvm-lto 2 \
-s ENVIRONMENT=${ENVIRONMENT:-web} \
-s EXPORTED_FUNCTIONS='["_pib_init", "_pib_destroy", "_pib_eval" "_pib_refresh", "_main", "_php_embed_init", "_php_embed_shutdown", "_php_embed_shutdown", "_zend_eval_string"]' \
-s EXTRA_EXPORTED_RUNTIME_METHODS='["ccall", "UTF8ToString", "lengthBytesUTF8"]' \
-s MODULARIZE=1 \
-s EXPORT_NAME="'PHP'" \
-s TOTAL_MEMORY=134217728 \
-s ASSERTIONS=0 \
-s INVOKE_RUN=0 \
-s ERROR_ON_UNDEFINED_SYMBOLS=0 \
libs/libphp7.a pib_eval.o -o out/php-${ENVIRONMENT:-web}.js
cp out/php-${ENVIRONMENT:-shell}.wasm \
out/php-${ENVIRONMENT:-shell}.js \
out/php-${ENVIRONMENT:-shell}.data \
..
popd
echo "Done"
cp ../out/php-${ENVIRONMENT:-web}.wasm \
../out/php-${ENVIRONMENT:-web}.js \
../out/php-${ENVIRONMENT:-web}.data \
../
+25
View File
@@ -0,0 +1,25 @@
#!/usr/bin/env bash
set -euxo pipefail;
pushd php-src
rm configure || true
./buildconf --force
emconfigure ./configure \
--disable-all \
--disable-cgi \
--disable-cli \
--disable-rpath \
--disable-phpdbg \
--with-valgrind=no \
--without-pear \
--without-pcre-jit \
--with-layout=GNU \
--enable-embed=static \
--enable-bcmath \
--enable-json \
--enable-ctype \
--enable-mbstring \
--disable-mbregex \
--enable-tokenizer \
--enable-vrzno
+17
View File
@@ -0,0 +1,17 @@
version: '3'
services:
emscripten-builder:
image: seanmorris/php-emscripten-builder
build:
context: ./
dockerfile: emscripten-builder.dockerfile
args:
PHP_BRANCH: ${PHP_BRANCH:-PHP-7.4}
environment:
EMCC_CORES: 8
ENVIRONMENT: ${ENVIRONMENT:-web}
volumes:
- ./:/src
command: [bash, /src/build.sh]
+109 -80
View File
@@ -1,113 +1,142 @@
'use strict';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
value: true
});
exports.Php = void 0;
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
function _extendableBuiltin(cls) {
function ExtendableBuiltin() {
var instance = Reflect.construct(cls, Array.from(arguments));
Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
return instance;
}
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
ExtendableBuiltin.prototype = Object.create(cls.prototype, {
constructor: {
value: cls,
enumerable: false,
writable: true,
configurable: true
}
});
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
if (Object.setPrototypeOf) {
Object.setPrototypeOf(ExtendableBuiltin, cls);
} else {
ExtendableBuiltin.__proto__ = cls;
}
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
return ExtendableBuiltin;
}
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
var PhpWebBin = require('./php-web');
function _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }
var Php = exports.Php = function (_extendableBuiltin2) {
_inherits(Php, _extendableBuiltin2);
function _construct(Parent, args, Class) { if (_isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }
function Php() {
_classCallCheck(this, Php);
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }
var _this = _possibleConstructorReturn(this, (Php.__proto__ || Object.getPrototypeOf(Php)).call(this));
function _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; }
var FLAGS = {};
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
_this.returnValue = -1;
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
_this.onerror = function () {
console.log('READY!!!');
};
_this.onoutput = function () {};
_this.onready = function () {};
var PhpNode = require('./php-node');
_this.binary = PhpWebBin({
var PhpShell = require('./php-shell');
postRun: function postRun() {
var event = new CustomEvent('ready');
_this.dispatchEvent(event);
_this.onready(event);
},
var PhpWeb = require('./php-web');
print: function print() {
for (var _len = arguments.length, chunks = Array(_len), _key = 0; _key < _len; _key++) {
chunks[_key] = arguments[_key];
}
var PhpWebView = require('./php-webview');
var event = new CustomEvent('output', { detail: chunks });
_this.dispatchEvent(event);
_this.onoutput(event);
},
var PhpWorker = require('./php-worker');
printErr: function printErr() {
for (var _len2 = arguments.length, chunks = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
chunks[_key2] = arguments[_key2];
}
var Php = /*#__PURE__*/function (_EventTarget) {
_inherits(Php, _EventTarget);
var event = new CustomEvent('error', { detail: chunks });
// this.onerror(event);
_this.dispatchEvent(event);
}
var _super = _createSuper(Php);
});
return _this;
}
function Php() {
var _this;
_createClass(Php, [{
key: 'run',
value: function run(phpCode) {
var _this2 = this;
var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'web';
return new Promise(function (accept) {
return _this2.binary.then(function (php) {
_classCallCheck(this, Php);
var retVal = php.ccall('pib_eval', 'number', ["string"], ['?>' + phpCode]);
_this = _super.call(this);
var FLAGS = {};
_this.returnValue = -1;
php.ccall('pib_eval', 'number', ["string"], ['echo "\n"']);
_this.onerror = function () {};
console.log(phpCode, retVal);
_this.onoutput = function () {};
accept(retVal);
});
});
}
}]);
_this.onready = function () {};
return Php;
}(_extendableBuiltin(EventTarget));
var binaryClasses = {
webview: PhpWebView,
worker: PhpWorker,
shell: PhpShell,
node: PhpNode,
web: PhpWeb
};
var binaryClass = binaryClasses[type];
_this.binary = new binaryClass({
postRun: function postRun() {
var event = new CustomEvent('ready');
_this.dispatchEvent(event);
_this.onready(event);
},
print: function print() {
for (var _len = arguments.length, chunks = new Array(_len), _key = 0; _key < _len; _key++) {
chunks[_key] = arguments[_key];
}
var event = new CustomEvent('output', {
detail: chunks
});
_this.dispatchEvent(event);
_this.onoutput(event);
},
printErr: function printErr() {
for (var _len2 = arguments.length, chunks = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
chunks[_key2] = arguments[_key2];
}
var event = new CustomEvent('error', {
detail: chunks
});
_this.onerror(event);
_this.dispatchEvent(event);
}
}).then(function (php) {
var retVal = php.ccall('pib_init', 'number', ["string"], []);
return php;
})["catch"](function (error) {
return console.log(error);
});
return _this;
}
_createClass(Php, [{
key: "run",
value: function run(phpCode) {
return this.binary.then(function (php) {
var retVal = php.ccall('pib_eval', 'number', ["string"], ["?>".concat(phpCode)]);
php.ccall('pib_eval', 'number', ["string"], ["fwrite(fopen('php://stdout', 'w'), PHP_EOL);"]);
return retVal;
});
}
}, {
key: "refresh",
value: function refresh() {
return this.binary.then(function (php) {
return php.ccall('pib_refresh', 'number', [], []);
})["catch"](function (error) {
return console.log(error);
});
}
}]);
return Php;
}( /*#__PURE__*/_wrapNativeSuper(EventTarget));
exports.Php = Php;
+2 -2
View File
@@ -6,10 +6,10 @@ var PHP = (function() {
function(PHP) {
PHP = PHP || {};
var Module=typeof PHP!=="undefined"?PHP:{};if(!Module.expectedDataFileDownloads){Module.expectedDataFileDownloads=0;Module.finishedDataFileDownloads=0}Module.expectedDataFileDownloads++;(function(){var loadPackage=function(metadata){var PACKAGE_PATH;if(typeof window==="object"){PACKAGE_PATH=window["encodeURIComponent"](window.location.pathname.toString().substring(0,window.location.pathname.toString().lastIndexOf("/"))+"/")}else if(typeof location!=="undefined"){PACKAGE_PATH=encodeURIComponent(location.pathname.toString().substring(0,location.pathname.toString().lastIndexOf("/"))+"/")}else{throw"using preloaded data can only be done on a web page or in a web worker"}var PACKAGE_NAME="out/php-web.data";var REMOTE_PACKAGE_BASE="php-web.data";if(typeof Module["locateFilePackage"]==="function"&&!Module["locateFile"]){Module["locateFile"]=Module["locateFilePackage"];err("warning: you defined Module.locateFilePackage, that has been renamed to Module.locateFile (using your locateFilePackage for now)")}var REMOTE_PACKAGE_NAME=Module["locateFile"]?Module["locateFile"](REMOTE_PACKAGE_BASE,""):REMOTE_PACKAGE_BASE;var REMOTE_PACKAGE_SIZE=metadata.remote_package_size;var PACKAGE_UUID=metadata.package_uuid;function fetchRemotePackage(packageName,packageSize,callback,errback){var xhr=new XMLHttpRequest;xhr.open("GET",packageName,true);xhr.responseType="arraybuffer";xhr.onprogress=function(event){var url=packageName;var size=packageSize;if(event.total)size=event.total;if(event.loaded){if(!xhr.addedTotal){xhr.addedTotal=true;if(!Module.dataFileDownloads)Module.dataFileDownloads={};Module.dataFileDownloads[url]={loaded:event.loaded,total:size}}else{Module.dataFileDownloads[url].loaded=event.loaded}var total=0;var loaded=0;var num=0;for(var download in Module.dataFileDownloads){var data=Module.dataFileDownloads[download];total+=data.total;loaded+=data.loaded;num++}total=Math.ceil(total*Module.expectedDataFileDownloads/num);if(Module["setStatus"])Module["setStatus"]("Downloading data... ("+loaded+"/"+total+")")}else if(!Module.dataFileDownloads){if(Module["setStatus"])Module["setStatus"]("Downloading data...")}};xhr.onerror=function(event){throw new Error("NetworkError for: "+packageName)};xhr.onload=function(event){if(xhr.status==200||xhr.status==304||xhr.status==206||xhr.status==0&&xhr.response){var packageData=xhr.response;callback(packageData)}else{throw new Error(xhr.statusText+" : "+xhr.responseURL)}};xhr.send(null)}function handleError(error){console.error("package error:",error)}var fetchedCallback=null;var fetched=Module["getPreloadedPackage"]?Module["getPreloadedPackage"](REMOTE_PACKAGE_NAME,REMOTE_PACKAGE_SIZE):null;if(!fetched)fetchRemotePackage(REMOTE_PACKAGE_NAME,REMOTE_PACKAGE_SIZE,function(data){if(fetchedCallback){fetchedCallback(data);fetchedCallback=null}else{fetched=data}},handleError);function runWithFS(){function assert(check,msg){if(!check)throw msg+(new Error).stack}Module["FS_createPath"]("/","Zend",true,true);function DataRequest(start,end,audio){this.start=start;this.end=end;this.audio=audio}DataRequest.prototype={requests:{},open:function(mode,name){this.name=name;this.requests[name]=this;Module["addRunDependency"]("fp "+this.name)},send:function(){},onload:function(){var byteArray=this.byteArray.subarray(this.start,this.end);this.finish(byteArray)},finish:function(byteArray){var that=this;Module["FS_createDataFile"](this.name,null,byteArray,true,true,true);Module["removeRunDependency"]("fp "+that.name);this.requests[this.name]=null}};var files=metadata.files;for(var i=0;i<files.length;++i){new DataRequest(files[i].start,files[i].end,files[i].audio).open("GET",files[i].filename)}function processPackageData(arrayBuffer){Module.finishedDataFileDownloads++;assert(arrayBuffer,"Loading data file failed.");assert(arrayBuffer instanceof ArrayBuffer,"bad input to processPackageData");var byteArray=new Uint8Array(arrayBuffer);var ptr=Module["getMemory"](byteArray.length);Module["HEAPU8"].set(byteArray,ptr);DataRequest.prototype.byteArray=Module["HEAPU8"].subarray(ptr,ptr+byteArray.length);var files=metadata.files;for(var i=0;i<files.length;++i){DataRequest.prototype.requests[files[i].filename].onload()}Module["removeRunDependency"]("datafile_out/php-web.data")}Module["addRunDependency"]("datafile_out/php-web.data");if(!Module.preloadResults)Module.preloadResults={};Module.preloadResults[PACKAGE_NAME]={fromCache:false};if(fetched){processPackageData(fetched);fetched=null}else{fetchedCallback=processPackageData}}if(Module["calledRun"]){runWithFS()}else{if(!Module["preRun"])Module["preRun"]=[];Module["preRun"].push(runWithFS)}};loadPackage({"files":[{"start":0,"audio":0,"end":7634,"filename":"/Zend/bench.php"}],"remote_package_size":7634,"package_uuid":"5aaa2120-a6ae-49cd-880a-074bfc04569d"})})();var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};vLine truncated
var Module=typeof PHP!=="undefined"?PHP:{};var readyPromiseResolve,readyPromiseReject;Module["ready"]=new Promise(function(resolve,reject){readyPromiseResolve=resolve;readyPromiseReject=reject});var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=true;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptDir){scriptDirectory=_scriptDir}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}setWindowTitle=function(title){document.title=title}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];function dynamicAlloc(size){var ret=HEAP32[DYNAMICTOP_PTR>>2];var end=ret+size+15&-16;HEAP32[DYNAMICTOP_PTR>>2]=end;return ret}function getNativeTypeSize(type){switch(type){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:{if(type[type.length-1]==="*"){return 4}else if(type[0]==="i"){var bits=Number(type.substr(1));assert(bits%8===0,"getNativeTypeSize invalid bits "+bits+", type "+type);return bits/8}else{return 0}}}}var asm2wasmImports={"f64-rem":function(x,y){return x%y},"debugger":function(){}};var functionPointers=new Array(0);var tempRet0=0;var setTempRet0=function(value){tempRet0=value};var getTempRet0=function(){return tempRet0};var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){err("no native wasm support detected")}function setValue(ptr,value,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":HEAP8[ptr>>0]=value;break;case"i8":HEAP8[ptr>>0]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":tempI64=[value>>>0,(tempDouble=value,+Math_abs(tempDouble)>=1?tempDouble>0?(Math_min(+Math_floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[ptr>>2]=tempI64[0],HEAP32[ptr+4>>2]=tempI64[1];break;case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;default:abort("invalid type for setValue: "+type)}}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":5295,"maximum":5295,"element":"anyfunc"});var ABORT=false;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len)}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i<args.length;i++){var converter=toC[argTypes[i]];if(converter){if(stack===0)stack=stackSave();cArgs[i]=converter(args[i])}else{cArgs[i]=args[i]}}}var ret=func.apply(null,cArgs);ret=convertReturnValue(ret);if(stack!==0)stackRestore(stack);return ret}var ALLOC_STACK=1;var ALLOC_NONE=3;function allocate(slab,types,allocator,ptr){var zeroinit,size;if(typeof slab==="numberLine truncated
return PHP
return PHP.ready
}
);
})();
BIN
View File
Binary file not shown.
+25
View File
@@ -0,0 +1,25 @@
FROM trzeci/emscripten:1.39.18-fastcomp
MAINTAINER Sean Morris <sean@seanmorr.is>
SHELL ["/bin/bash", "-c"]
ARG PHP_BRANCH=PHP-7.4
RUN set -euxo pipefail;\
apt-get update; \
apt-get --no-install-recommends -y install \
build-essential \
libsqlite3-dev \
libxml2-dev \
automake \
autoconf \
valgrind \
libtool \
php-dev \
pkgconf \
bison \
flex \
make \
re2c \
gdb \
git
+1796 -1114
View File
File diff suppressed because it is too large. Load diff
+4 -3
View File
@@ -6,9 +6,10 @@
"version": "0.0.1c",
"license": "MIT",
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-preset-es2015": "^6.24.1",
"babel-plugin-transform-builtin-extend": "^1.1.2"
"@babel/cli": "^7.8.4",
"@babel/core": "^7.8.7",
"@babel/plugin-proposal-class-properties": "^7.10.4",
"@babel/preset-env": "^7.0.0"
},
"contributors": [
{
Submodule
+1
Submodule php-src added at 1b21b56074.
+47 -11
View File
@@ -1,8 +1,12 @@
const PhpWebBin = require('./php-web');
const PhpNode = require('./php-node');
const PhpShell = require('./php-shell');
const PhpWeb = require('./php-web');
const PhpWebView = require('./php-webview');
const PhpWorker = require('./php-worker');
export class Php extends EventTarget
{
constructor()
constructor(type = 'web')
{
super();
@@ -10,11 +14,21 @@ export class Php extends EventTarget
this.returnValue = -1;
this.onerror = function () { console.log('READY!!!') };
this.onerror = function () {};
this.onoutput = function () {};
this.onready = function () {};
this.binary = PhpWebBin({
const binaryClasses = {
webview : PhpWebView
, worker: PhpWorker
, shell : PhpShell
, node : PhpNode
, web : PhpWeb
};
const binaryClass = binaryClasses[type];
this.binary = new binaryClass({
postRun: () => {
const event = new CustomEvent('ready');
@@ -30,16 +44,27 @@ export class Php extends EventTarget
printErr: (...chunks) => {
const event = new CustomEvent('error', {detail: chunks});
// this.onerror(event);
this.onerror(event);
this.dispatchEvent(event);
}
});
}).then(php=>{
const retVal = php.ccall(
'pib_init'
, 'number'
, ["string"]
, []
);
return php;
}).catch(error => console.log(error));
}
run(phpCode)
{
return new Promise(accept => this.binary.then(php => {
return this.binary.then(php => {
const retVal = php.ccall(
'pib_eval'
@@ -52,14 +77,25 @@ export class Php extends EventTarget
'pib_eval'
, 'number'
, ["string"]
, [`echo "\n"`]
, [`fwrite(fopen('php://stdout', 'w'), PHP_EOL);`]
);
console.log(phpCode, retVal);
return retVal;
accept(retVal);
});
}
}));
refresh()
{
return this.binary.then(php => {
return php.ccall(
'pib_refresh'
, 'number'
, []
, []
);
}).catch(error => console.log(error));
}
}
+37 -8
View File
@@ -4,12 +4,41 @@
int main() { return 0; }
int EMSCRIPTEN_KEEPALIVE pib_eval(char *code) {
int ret = 0;
putenv("USE_ZEND_ALLOC=0");
PHP_EMBED_START_BLOCK(0, NULL)
ret = zend_eval_string(code, NULL, "PIB");
PHP_EMBED_END_BLOCK()
printf("\n");
return ret;
int EMSCRIPTEN_KEEPALIVE pib_init()
{
putenv("USE_ZEND_ALLOC=0");
return php_embed_init(0, NULL);
}
int EMSCRIPTEN_KEEPALIVE pib_eval(char *code)
{
int retVal = 0;
zend_try
{
retVal = zend_eval_string(code, NULL, "php shell code");
}
zend_catch
{
fflush(stderr);
}
zend_end_try();
fflush(stdout);
return retVal == FAILURE;
}
void EMSCRIPTEN_KEEPALIVE pib_destroy()
{
return php_embed_shutdown();
}
int EMSCRIPTEN_KEEPALIVE pib_refresh()
{
pib_destroy();
return pib_init();
}