From 24a16b6fc3948696c1a4fcaf987ac3de439f62be Mon Sep 17 00:00:00 2001 From: Kevin van Zonneveld Date: Sun, 5 Jan 2014 16:38:30 +0100 Subject: [PATCH 1/7] Always include ini_set and ini_get for now --- Makefile | 4 +- functions/array/array_change_key_case.js | 5 +- {experimental => functions}/info/ini_get.js | 4 +- {experimental => functions}/info/ini_set.js | 22 ++-- tests/cli.js | 15 ++- tests/phpjsutil.js | 138 +++++++++++++------- 6 files changed, 119 insertions(+), 69 deletions(-) rename {experimental => functions}/info/ini_get.js (93%) rename {experimental => functions}/info/ini_set.js (53%) diff --git a/Makefile b/Makefile index 89d7ff14..d595ea40 100644 --- a/Makefile +++ b/Makefile @@ -5,8 +5,8 @@ setup: cd .. ; \ test: - cd _tests && npm install - find functions -type f |grep -v '/_' |xargs node _tests/cli.js -f + cd tests && npm install + find functions -type f |grep -v '/_' |awk -F/ '{print $$NF}' |sed 's@\.js$$@@g' |xargs node tests/cli.js -f site: git pull && \ diff --git a/functions/array/array_change_key_case.js b/functions/array/array_change_key_case.js index f1dbecc0..93d22bbd 100644 --- a/functions/array/array_change_key_case.js +++ b/functions/array/array_change_key_case.js @@ -2,7 +2,7 @@ function array_change_key_case (array, cs) { // From: http://phpjs.org/functions // + original by: Ates Goral (http://magnetiq.com) // + improved by: marrtins - // + improved by: Brett Zamir (http://brett-zamir.me) + // + improved by: Brett Zamir (http://brett-zamir.me) // * example 1: array_change_key_case(42); // * returns 1: false // * example 2: array_change_key_case([ 3, 5 ]); @@ -19,7 +19,7 @@ function array_change_key_case (array, cs) { // * example 7: var arr = array({a: 0}, {B: 1}, {c: 2}); // * example 7: var newArr = array_change_key_case(arr); // * example 7: newArr.b - // * example 7: 1 + // * returns 7: 1 var case_fn, key, tmp_ar = {}; @@ -36,5 +36,6 @@ function array_change_key_case (array, cs) { } return tmp_ar; } + return false; } diff --git a/experimental/info/ini_get.js b/functions/info/ini_get.js similarity index 93% rename from experimental/info/ini_get.js rename to functions/info/ini_get.js index 281fc742..396f7c2d 100644 --- a/experimental/info/ini_get.js +++ b/functions/info/ini_get.js @@ -1,14 +1,16 @@ function ini_get (varname) { - // http://kevin.vanzonneveld.net + // From: http://phpjs.org/functions // + original by: Brett Zamir (http://brett-zamir.me) // % note 1: The ini values must be set by ini_set or manually within an ini file // * example 1: ini_get('date.timezone'); // * returns 1: 'Asia/Hong_Kong' + if (this.php_js && this.php_js.ini && this.php_js.ini[varname] && this.php_js.ini[varname].local_value !== undefined) { if (this.php_js.ini[varname].local_value === null) { return ''; } return this.php_js.ini[varname].local_value; } + return ''; } diff --git a/experimental/info/ini_set.js b/functions/info/ini_set.js similarity index 53% rename from experimental/info/ini_set.js rename to functions/info/ini_set.js index 49959850..fdb65c48 100644 --- a/experimental/info/ini_set.js +++ b/functions/info/ini_set.js @@ -1,28 +1,30 @@ function ini_set (varname, newvalue) { - // http://kevin.vanzonneveld.net + // From: http://phpjs.org/functions // + original by: Brett Zamir (http://brett-zamir.me) // % note 1: This will not set a global_value or access level for the ini item // * example 1: ini_set('date.timezone', 'America/Chicago'); // * returns 1: 'Asia/Hong_Kong' - var oldval = '', - that = this; - this.php_js = this.php_js || {}; - this.php_js.ini = this.php_js.ini || {}; + var oldval = ''; + var self = this; + this.php_js = this.php_js || {}; + this.php_js.ini = this.php_js.ini || {}; this.php_js.ini[varname] = this.php_js.ini[varname] || {}; - oldval = this.php_js.ini[varname].local_value; + oldval = this.php_js.ini[varname].local_value; - var _setArr = function (oldval) { // Although these are set individually, they are all accumulated + var _setArr = function (oldval) { + // Although these are set individually, they are all accumulated if (typeof oldval === 'undefined') { - that.php_js.ini[varname].local_value = []; + self.php_js.ini[varname].local_value = []; } - that.php_js.ini[varname].local_value.push(newvalue); + self.php_js.ini[varname].local_value.push(newvalue); }; switch (varname) { case 'extension': if (typeof this.dl === 'function') { - this.dl(newvalue); // This function is only experimental in php.js + // This function is only experimental in php.js + this.dl(newvalue); } _setArr(oldval, newvalue); break; diff --git a/tests/cli.js b/tests/cli.js index 372c2e4f..3f63230c 100644 --- a/tests/cli.js +++ b/tests/cli.js @@ -1,7 +1,11 @@ -var cli = require('cli').enable('status', 'help', 'version', 'glob', 'timeout'); -var FS = require('fs'); -var glob = require('glob'); -var PhpjsUtil = require('./phpjsutil'); +var cli = require('cli').enable('status', 'help', 'version', 'glob', 'timeout'); +var FS = require('fs'); +var glob = require('glob'); +var phpjsutil = new require('./phpjsutil'); + +var PhpjsUtil = phpjsutil({ + injectDependencies: [ 'ini_set', 'ini_get' ] +}); // Environment-specific file opener. function name needs to // be translated to code. The difficulty is in finding the @@ -61,7 +65,7 @@ cli.main(function(args, options) { return cli.fatal(err); } - console.log(params['headKeys']); + // console.log(params['headKeys']); PhpjsUtil.test(params, function(err, test, params) { var testline = cli.pad(params['name'] + '#' + test['number'], (width * 0.4), ' ', 'right') + @@ -72,6 +76,7 @@ cli.main(function(args, options) { if (err) { cli.error(testline + ''); + cli.error(err); } else { cli.ok(' ' + testline + ''); } diff --git a/tests/phpjsutil.js b/tests/phpjsutil.js index 15e78ce9..8e05eb1d 100644 --- a/tests/phpjsutil.js +++ b/tests/phpjsutil.js @@ -1,21 +1,28 @@ if (typeof require !== 'undefined') { - module.exports = PhpjsUtil; + module.exports = function phpjsutil(config) { + var self = new PhpjsUtil(config); + return self; + }; } -function PhpjsUtil () { + +function PhpjsUtil(config) { + for (var k in config) { + this[k] = config[k]; + } } -PhpjsUtil._commentBlocks = function(code) { - var cnt = 0; - var comment = []; +PhpjsUtil.prototype._commentBlocks = function(code) { + var cnt = 0; + var comment = []; var commentBlocks = []; - var i = 0; - var lines = []; - var raise = false; + var i = 0; + var lines = []; + var raise = false; for (i in (lines = code.replace('\r', '').split('\n'))) { // Detect if line is a comment, and return the actual comment if ((comment = lines[i].match(/^\s*(\/\/|\/\*|\*)\s*(.*)$/))) { if (raise === true) { - cnt = commentBlocks.length; + cnt = commentBlocks.length; raise = false; } if (!commentBlocks[cnt]) { @@ -32,14 +39,15 @@ PhpjsUtil._commentBlocks = function(code) { return commentBlocks; }; -PhpjsUtil._headKeys = function(headLines) { +PhpjsUtil.prototype._headKeys = function(headLines) { var i; - var keys = {}; - var match = []; + var keys = {}; + var match = []; var dmatch = []; - var key = ''; - var val = ''; - var num = 0; + var key = ''; + var val = ''; + var num = 0; + for (i in headLines) { if (!(match = headLines[i].match(/^[\s\W]*(.*?)\s*:\s*(.*)\s*$/))) { continue; @@ -70,20 +78,43 @@ PhpjsUtil._headKeys = function(headLines) { return keys; }; -PhpjsUtil._loadDependencies = function(headKeys, dependencies, cb) { - var self = this; +PhpjsUtil.prototype.contains = function (array, value) { + var i = array.length; + while (i--) { + if (array[i] === value) { + return true; + } + } + return false; +}; + +PhpjsUtil.prototype._loadDependencies = function(name, headKeys, dependencies, cb) { + var self = this; + var functions = headKeys['depends on'] || []; + + var j; + for (j in self.injectDependencies) { + var injectFunction = self.injectDependencies[j]; + if (self.contains(self.injectDependencies, name)) { + continue; + } + + // console.log({injectFunction: injectFunction}); + functions.push(injectFunction); + } - if (!headKeys['depends on'] || !headKeys['depends on'].length) { + if (!functions || !functions.length) { if (cb) { cb(null, {}); } } + // console.log({functions: functions, headKeys: headKeys, dependencies: dependencies}); var i; var name; var loaded = 0; - for (i in headKeys['depends on']) { - name = headKeys['depends on'][i]; + for (i in functions) { + name = functions[i]; self.load(name, function (err, params) { if (err) { @@ -91,49 +122,48 @@ PhpjsUtil._loadDependencies = function(headKeys, dependencies, cb) { } dependencies[name] = params; - self._loadDependencies(params.headKeys, dependencies); + self._loadDependencies(name, params.headKeys, dependencies); loaded++; - - if (cb && loaded === headKeys['depends on'].length) { + if (cb && loaded === functions.length) { cb(null, dependencies); } }); } }; -PhpjsUtil.parse = function(name, code, cb) { +PhpjsUtil.prototype.parse = function(name, code, cb) { var commentBlocks = this._commentBlocks(code); - var head = commentBlocks[0].raw.join('\n'); - var body = code.replace(head, ''); - - var headKeys = this._headKeys(commentBlocks[0].clean); + var head = commentBlocks[0].raw.join('\n'); + var body = code.replace(head, ''); + var headKeys = this._headKeys(commentBlocks[0].clean); // @todo(kvz) If we add function signature, we can use // body to generate CommonJs compatible output // in the browser. - this._loadDependencies(headKeys, {}, function (err, dependencies) { + this._loadDependencies(name, headKeys, {}, function (err, dependencies) { if (err) { return cb(err); } + cb(null, { - headKeys: headKeys, - body: body, - head: head, - name: name, - code: code, - dependencies: dependencies, + headKeys : headKeys, + body : body, + head : head, + name : name, + code : code, + dependencies : dependencies, commentBlocks: commentBlocks }); }); }; -PhpjsUtil.opener = function(name, cb) { +PhpjsUtil.prototype.opener = function(name, cb) { return cb('Please override with a method that can translate a function-name to code in your environment'); }; -PhpjsUtil.load = function(name, cb) { +PhpjsUtil.prototype.load = function(name, cb) { var self = this; self.opener(name, function (err, code) { if (err) { @@ -150,10 +180,10 @@ PhpjsUtil.load = function(name, cb) { }); }; -PhpjsUtil.test = function(params, cb) { - var i = 0; - var j = 0; - var d = 0; +PhpjsUtil.prototype.test = function(params, cb) { + var i = 0; + var j = 0; + var d = 0; var self = this; @@ -164,11 +194,12 @@ PhpjsUtil.test = function(params, cb) { for (d in params['dependencies']) { codes.push(params['dependencies'][d]['code']); } + console.log({codes: codes}); // Reverse stack so dependencies are loaded first codes = codes.reverse(); - // console.log(codes); + // console.log({params: params}); // Load code eval(codes.join('\n')); @@ -178,9 +209,14 @@ PhpjsUtil.test = function(params, cb) { for (i in params['headKeys']['example']) { var test = { example: params['headKeys']['example'][i].join('\n'), - number: i + number : i }; + if (!params['headKeys']['returns'][i] || !params['headKeys']['returns'][i].length) { + cb('There is no return for example ' + i, test, params); + continue; + } + // Needs an eval so types are cast properly, also, expected may // contain code eval('test.expected = ' + params['headKeys']['returns'][i].join('\n') + ''); @@ -190,13 +226,17 @@ PhpjsUtil.test = function(params, cb) { eval('test.result = ' + params['headKeys']['example'][i][j] + ''); } - if (test.expected !== test.result) { - var err = 'Expected: ' + JSON.stringify(test.expected, undefined, 2) + - ' but returned: ' + JSON.stringify(test.result, undefined, 2); + var jsonExpected = JSON.stringify(test.expected, undefined, 2); + var jsonResult = JSON.stringify(test.result, undefined, 2); + + if (jsonExpected !== jsonResult) { + var err = 'Expected: ' + jsonExpected + + ' but returned: ' + jsonResult; cb(err, test, params); - } else { - cb(null, test, params); + continue; } + + cb(null, test, params); + continue; } }; - From 27bb33ec5bc8362182c31f4e2ad4bee4279a1ed3 Mon Sep 17 00:00:00 2001 From: Kevin van Zonneveld Date: Sun, 5 Jan 2014 16:42:17 +0100 Subject: [PATCH 2/7] Better output --- tests/cli.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/cli.js b/tests/cli.js index 3f63230c..66b60217 100644 --- a/tests/cli.js +++ b/tests/cli.js @@ -70,8 +70,8 @@ cli.main(function(args, options) { PhpjsUtil.test(params, function(err, test, params) { var testline = cli.pad(params['name'] + '#' + test['number'], (width * 0.4), ' ', 'right') + ' ' + cli.pad(test['example'], (width * 0.6 -7)) + '\n' + - ' ' + cli.pad(test['expected'], width) + '\n' + - ' ' + cli.pad(test['result'], width) + '\n' + + ' expected' + cli.pad(JSON.stringify(test['expected'], undefined, 2).replace(/\n/g, ''), width-8) + '\n' + + ' result ' + cli.pad(JSON.stringify(test['result'], undefined, 2).replace(/\n/g, ''), width-8) + '\n' + ' '; if (err) { From a4a9dcc5b14d3105af84af38b4c6d587b4c0c07c Mon Sep 17 00:00:00 2001 From: Kevin van Zonneveld Date: Sun, 5 Jan 2014 22:30:36 +0100 Subject: [PATCH 3/7] Test suite completes (But many many tests fail) --- Makefile | 2 +- {functions => experimental}/array/extract.js | 0 experimental/filesystem/dirname.js | 12 -- experimental/filesystem/pathinfo.js | 134 ------------- experimental/filesystem/realpath.js | 14 +- .../funchand/register_shutdown_function.js | 1 + {functions => experimental}/info/assert.js | 4 +- experimental/info/get_defined_constants.js | 1 + {experimental => functions}/array/array.js | 11 +- functions/array/array_change_key_case.js | 6 +- functions/array/array_filter.js | 2 +- functions/array/array_flip.js | 13 +- functions/array/array_search.js | 2 + functions/array/array_walk.js | 8 +- functions/array/end.js | 3 +- functions/array/natcasesort.js | 1 + functions/array/shuffle.js | 8 +- functions/array/uasort.js | 4 +- functions/array/usort.js | 3 +- functions/datetime/microtime.js | 3 +- functions/datetime/strptime.js | 1 + functions/datetime/time.js | 3 +- functions/filesystem/dirname.js | 3 +- .../filesystem/file_get_contents.js | 11 +- functions/filesystem/pathinfo.js | 1 + functions/funchand/get_defined_functions.js | 3 +- .../i18n/i18n_loc_get_default.js | 0 .../i18n/i18n_loc_set_default.js | 0 functions/info/ini_set.js | 17 +- functions/info/set_time_limit.js | 1 + functions/json/json_decode.js | 7 +- functions/json/json_encode.js | 9 +- functions/network/inet_pton.js | 5 +- functions/network/setrawcookie.js | 2 +- functions/pcre/preg_grep.js | 16 +- functions/strings/addcslashes.js | 10 +- functions/strings/convert_uuencode.js | 2 +- {experimental => functions}/strings/echo.js | 0 functions/strings/htmlspecialchars.js | 3 +- functions/strings/md5_file.js | 2 + functions/strings/parse_str.js | 54 ++--- functions/strings/printf.js | 7 +- functions/strings/quoted_printable_decode.js | 4 +- functions/strings/sha1_file.js | 3 + functions/strings/str_rot13.js | 1 + functions/strings/str_shuffle.js | 4 +- functions/strings/strip_tags.js | 3 +- functions/strings/substr_replace.js | 4 +- functions/strings/vprintf.js | 11 +- functions/url/get_headers.js | 13 +- functions/url/get_meta_tags.js | 6 +- functions/url/rawurldecode.js | 47 ++--- functions/var/is_callable.js | 3 +- functions/var/is_double.js | 1 + functions/var/is_real.js | 3 +- functions/var/var_dump.js | 2 + functions/var/var_export.js | 8 +- tests/cli.js | 80 +++++--- tests/phpjsutil.js | 189 ++++++++++++------ 59 files changed, 390 insertions(+), 381 deletions(-) rename {functions => experimental}/array/extract.js (100%) delete mode 100644 experimental/filesystem/dirname.js delete mode 100644 experimental/filesystem/pathinfo.js rename {functions => experimental}/funchand/register_shutdown_function.js (99%) rename {functions => experimental}/info/assert.js (90%) rename {experimental => functions}/array/array.js (97%) rename {experimental => functions}/filesystem/file_get_contents.js (98%) rename {experimental => functions}/i18n/i18n_loc_get_default.js (100%) rename {experimental => functions}/i18n/i18n_loc_set_default.js (100%) rename {experimental => functions}/strings/echo.js (100%) diff --git a/Makefile b/Makefile index d595ea40..b7135614 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ setup: test: cd tests && npm install - find functions -type f |grep -v '/_' |awk -F/ '{print $$NF}' |sed 's@\.js$$@@g' |xargs node tests/cli.js -f + find functions -type f |grep -v '/_' |sed 's@\.js$$@@g' |awk -F/ '{print "node tests/cli.js -f "$$NF}' |bash site: git pull && \ diff --git a/functions/array/extract.js b/experimental/array/extract.js similarity index 100% rename from functions/array/extract.js rename to experimental/array/extract.js diff --git a/experimental/filesystem/dirname.js b/experimental/filesystem/dirname.js deleted file mode 100644 index 9fd051e0..00000000 --- a/experimental/filesystem/dirname.js +++ /dev/null @@ -1,12 +0,0 @@ -function dirname (path) { - // http://kevin.vanzonneveld.net - // + original by: Ozh - // + improved by: XoraX (http://www.xorax.info) - // * example 1: dirname('/etc/passwd'); - // * returns 1: '/etc' - // * example 2: dirname('c:/Temp/x'); - // * returns 2: 'c:/Temp' - // * example 3: dirname('/dir/test/'); - // * returns 3: '/dir' - return path.replace(/\\/g, '/').replace(/\/[^\/]*\/?$/, ''); -} diff --git a/experimental/filesystem/pathinfo.js b/experimental/filesystem/pathinfo.js deleted file mode 100644 index d929ee3b..00000000 --- a/experimental/filesystem/pathinfo.js +++ /dev/null @@ -1,134 +0,0 @@ -function pathinfo (path, options) { - // http://kevin.vanzonneveld.net - // + original by: Nate - // + revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) - // + improved by: Brett Zamir (http://brett-zamir.me) - // + input by: Timo - // % note 1: Inspired by actual PHP source: php5-5.2.6/ext/standard/string.c line #1559 - // % note 1: The way the bitwise arguments are handled allows for greater flexibility - // % note 1: & compatability. We might even standardize this code and use a similar approach for - // % note 1: other bitwise PHP functions - // % note 2: php.js tries very hard to stay away from a core.js file with global dependencies, because we like - // % note 2: that you can just take a couple of functions and be on your way. - // % note 2: But by way we implemented this function, if you want you can still declare the PATHINFO_* - // % note 2: yourself, and then you can use: pathinfo('/www/index.html', PATHINFO_BASENAME | PATHINFO_EXTENSION); - // % note 2: which makes it fully compliant with PHP syntax. - // - depends on: dirname - // - depends on: basename - // * example 1: pathinfo('/www/htdocs/index.html', 1); - // * returns 1: '/www/htdocs' - // * example 2: pathinfo('/www/htdocs/index.html', 'PATHINFO_BASENAME'); - // * returns 2: 'index.html' - // * example 3: pathinfo('/www/htdocs/index.html', 'PATHINFO_EXTENSION'); - // * returns 3: 'html' - // * example 4: pathinfo('/www/htdocs/index.html', 'PATHINFO_FILENAME'); - // * returns 4: 'index' - // * example 5: pathinfo('/www/htdocs/index.html', 2 | 4); - // * returns 5: {basename: 'index.html', extension: 'html'} - // * example 6: pathinfo('/www/htdocs/index.html', 'PATHINFO_ALL'); - // * returns 6: {dirname: '/www/htdocs', basename: 'index.html', extension: 'html', filename: 'index'} - // * example 7: pathinfo('/www/htdocs/index.html'); - // * returns 7: {dirname: '/www/htdocs', basename: 'index.html', extension: 'html', filename: 'index'} - // Working vars - var opt = '', - optName = '', - optTemp = 0, - tmp_arr = {}, - cnt = 0, - i = 0; - var have_basename = false, - have_extension = false, - have_filename = false; - - // Input defaulting & sanitation - if (!path) { - return false; - } - if (!options) { - options = 'PATHINFO_ALL'; - } - - // Initialize binary arguments. Both the string & integer (constant) input is - // allowed - var OPTS = { - 'PATHINFO_DIRNAME': 1, - 'PATHINFO_BASENAME': 2, - 'PATHINFO_EXTENSION': 4, - 'PATHINFO_FILENAME': 8, - 'PATHINFO_ALL': 0 - }; - // PATHINFO_ALL sums up all previously defined PATHINFOs (could just pre-calculate) - for (optName in OPTS) { - OPTS.PATHINFO_ALL = OPTS.PATHINFO_ALL | OPTS[optName]; - } - if (typeof options !== 'number') { // Allow for a single string or an array of string flags - options = [].concat(options); - for (i = 0; i < options.length; i++) { - // Resolve string input to bitwise e.g. 'PATHINFO_EXTENSION' becomes 4 - if (OPTS[options[i]]) { - optTemp = optTemp | OPTS[options[i]]; - } - } - options = optTemp; - } - - // Internal Functions - var __getExt = function (path) { - var str = path + ''; - var dotP = str.lastIndexOf('.') + 1; - return !dotP ? false : dotP !== str.length ? str.substr(dotP) : ''; - }; - - - // Gather path infos - if (options & OPTS.PATHINFO_DIRNAME) { - var dirname = this.dirname(path); - tmp_arr.dirname = dirname === path ? '.' : dirname; - } - - if (options & OPTS.PATHINFO_BASENAME) { - if (false === have_basename) { - have_basename = this.basename(path); - } - tmp_arr.basename = have_basename; - } - - if (options & OPTS.PATHINFO_EXTENSION) { - if (false === have_basename) { - have_basename = this.basename(path); - } - if (false === have_extension) { - have_extension = __getExt(have_basename); - } - if (false !== have_extension) { - tmp_arr.extension = have_extension; - } - } - - if (options & OPTS.PATHINFO_FILENAME) { - if (false === have_basename) { - have_basename = this.basename(path); - } - if (false === have_extension) { - have_extension = __getExt(have_basename); - } - if (false === have_filename) { - have_filename = have_basename.slice(0, have_basename.length - (have_extension ? have_extension.length + 1 : have_extension === false ? 0 : 1)); - } - - tmp_arr.filename = have_filename; - } - - - // If array contains only 1 element: return string - cnt = 0; - for (opt in tmp_arr) { - cnt++; - } - if (cnt == 1) { - return tmp_arr[opt]; - } - - // Return full-blown array - return tmp_arr; -} diff --git a/experimental/filesystem/realpath.js b/experimental/filesystem/realpath.js index 6db7bf81..c5562abe 100644 --- a/experimental/filesystem/realpath.js +++ b/experimental/filesystem/realpath.js @@ -1,12 +1,13 @@ function realpath (path) { - // http://kevin.vanzonneveld.net + // From: http://phpjs.org/functions // + original by: mk.keck // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // % note 1: Returned path is an url like e.g. 'http://yourhost.tld/path/' // * example 1: realpath('../.././_supporters/pj_test_supportfile_1.htm'); // * returns 1: 'file:/home/kevin/workspace/_supporters/pj_test_supportfile_1.htm' - var p = 0, - arr = []; /* Save the root, if not given */ + + var p = 0; + var arr = []; /* Save the root, if not given */ var r = this.window.location.href; /* Avoid input failures */ path = (path + '').replace('\\', '/'); /* Check if there's a port in path (like 'http://') */ if (path.indexOf('://') !== -1) { @@ -22,20 +23,21 @@ function realpath (path) { continue; } /* This reduces the realpath */ if (arr[k] == '..') { -/* But only if there more than 3 parts in the path-array. + /* But only if there more than 3 parts in the path-array. * The first three parts are for the uri */ if (path.length > 3) { path.pop(); } } /* This adds parts to the realpath */ else { -/* But only if the part is not empty or the uri + /* But only if the part is not empty or the uri * (the first three parts ar needed) was not * saved */ if ((path.length < 2) || (arr[k] !== '')) { path.push(arr[k]); } } - } /* Returns the absloute path as a string */ + } /* Returns the absolute path as a string */ + return path.join('/'); } diff --git a/functions/funchand/register_shutdown_function.js b/experimental/funchand/register_shutdown_function.js similarity index 99% rename from functions/funchand/register_shutdown_function.js rename to experimental/funchand/register_shutdown_function.js index 47361c01..6e70b4b7 100644 --- a/functions/funchand/register_shutdown_function.js +++ b/experimental/funchand/register_shutdown_function.js @@ -3,6 +3,7 @@ function register_shutdown_function (cb) { // + original by: Brett Zamir (http://brett-zamir.me) // * example 1: register_shutdown_function(function(first, middle, last) {alert('Goodbye '+first+' '+middle+' '+last+'!');}, 'Kevin', 'van', 'Zonneveld'); // * returns 1: 'Goodbye Kevin van Zonneveld!' + var args = [], _addEvent = function (el, type, handler, capturing) { if (el.addEventListener) { /* W3C */ diff --git a/functions/info/assert.js b/experimental/info/assert.js similarity index 90% rename from functions/info/assert.js rename to experimental/info/assert.js index f537ac7d..62c55ca3 100644 --- a/functions/info/assert.js +++ b/experimental/info/assert.js @@ -1,8 +1,8 @@ function assert (assertion) { // From: http://phpjs.org/functions // + original by: Brett Zamir (http://brett-zamir.me) - // % note 1: Do not pass untrusted user input to assert() in string form (you can test it beforehand though) - // % note 2: Does not provide perfect arguments to the assertion callback, as far as file location or line number + // % note 1: Do not pass untrusted user input to assert() in string form (you can test it beforehand though) + // % note 2: Does not provide perfect arguments to the assertion callback, as far as file location or line number // * example 1: assert('false === true'); // * returns 1: false diff --git a/experimental/info/get_defined_constants.js b/experimental/info/get_defined_constants.js index c32cbf4d..c9c5c1a5 100644 --- a/experimental/info/get_defined_constants.js +++ b/experimental/info/get_defined_constants.js @@ -1,4 +1,5 @@ function get_defined_constants (categorize) { + // From: http://phpjs.org/functions // + original by: Brett Zamir (http://brett-zamir.me) // % note 1: Could possibly substitute some others like M_PI with JavaScript's Math.PI, etc., but here // % note 1: sticking to PHP, except for changing: NULL to null, NAN to NaN, and INF to Number.POSITIVE_INFINITY diff --git a/experimental/array/array.js b/functions/array/array.js similarity index 97% rename from experimental/array/array.js rename to functions/array/array.js index 2919425f..1c500291 100644 --- a/experimental/array/array.js +++ b/functions/array/array.js @@ -2,14 +2,21 @@ function array () { // From: http://phpjs.org/functions // + original by: d3x // + improved by: Brett Zamir (http://brett-zamir.me) + // * test: skip // * example 1: array('Kevin', 'van', 'Zonneveld'); // * returns 1: ['Kevin', 'van', 'Zonneveld'] // * example 2: ini_set('phpjs.return_phpjs_arrays', 'on'); - // * example 2: var arr = array({0:2}, {a:41}, {2:3}).change_key_case('CASE_UPPER').keys(); + // * example 2: array({0:2}, {a:41}, {2:3}).change_key_case('CASE_UPPER').keys(); // * returns 2: [0,'A',2] + try { + this.php_js = this.php_js || {}; + } catch (e) { + this.php_js = {}; + } + var arrInst, e, __, that = this, PHPJS_Array = function PHPJS_Array() {}, - mainArgs = arguments, p = this.php_js = this.php_js || {}, + mainArgs = arguments, p = this.php_js, _indexOf = function (value, from, strict) { var i = from || 0, nonstrict = !strict, length = this.length; while (i < length) { diff --git a/functions/array/array_change_key_case.js b/functions/array/array_change_key_case.js index 93d22bbd..ddf57fd3 100644 --- a/functions/array/array_change_key_case.js +++ b/functions/array/array_change_key_case.js @@ -16,10 +16,10 @@ function array_change_key_case (array, cs) { // * example 6: array_change_key_case({ FuBaR: 42 }, 2); // * returns 6: {"FUBAR": 42} // * example 7: ini_set('phpjs.return_phpjs_arrays', 'on'); - // * example 7: var arr = array({a: 0}, {B: 1}, {c: 2}); + // * example 7: var arr = [{a: 0}, {B: 1}, {c: 2}]; // * example 7: var newArr = array_change_key_case(arr); - // * example 7: newArr.b - // * returns 7: 1 + // * example 7: newArr.splice(1); + // * returns 7: {b: 1} var case_fn, key, tmp_ar = {}; diff --git a/functions/array/array_filter.js b/functions/array/array_filter.js index 4568ec6a..eb70c90e 100644 --- a/functions/array/array_filter.js +++ b/functions/array/array_filter.js @@ -10,7 +10,7 @@ function array_filter (arr, func) { // * example 2: var even = function (num) {return (!(num & 1));} // * example 2: array_filter([6, 7, 8, 9, 10, 11, 12], even); // * returns 2: {0: 6, 2: 8, 4: 10, 6: 12} - // * example 3: var arr = array_filter({"a": 1, "b": false, "c": -1, "d": 0, "e": null, "f":'', "g":undefined}); + // * example 3: array_filter({"a": 1, "b": false, "c": -1, "d": 0, "e": null, "f":'', "g":undefined}); // * returns 3: {"a":1, "c":-1}; var retObj = {}, diff --git a/functions/array/array_flip.js b/functions/array/array_flip.js index c1a51b13..8be79642 100644 --- a/functions/array/array_flip.js +++ b/functions/array/array_flip.js @@ -1,8 +1,10 @@ function array_flip (trans) { // From: http://phpjs.org/functions // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) - // + improved by: Pier Paolo Ramon (http://www.mastersoup.com/) - // + improved by: Brett Zamir (http://brett-zamir.me) + // + improved by: Pier Paolo Ramon (http://www.mastersoup.com/) + // + improved by: Brett Zamir (http://brett-zamir.me) + // - depends on: array + // * test: skip // * example 1: array_flip( {a: 1, b: 1, c: 2} ); // * returns 1: {1: 'b', 2: 'c'} // * example 2: ini_set('phpjs.return_phpjs_arrays', 'on'); @@ -11,12 +13,15 @@ function array_flip (trans) { var key, tmp_ar = {}; - if (trans && typeof trans=== 'object' && trans.change_key_case) { // Duck-type check for our own array()-created PHPJS_Array + // Duck-type check for our own array()-created PHPJS_Array + if (trans && typeof trans === 'object' && trans.change_key_case) { return trans.flip(); } for (key in trans) { - if (!trans.hasOwnProperty(key)) {continue;} + if (!trans.hasOwnProperty(key)) { + continue; + } tmp_ar[trans[key]] = key; } diff --git a/functions/array/array_search.js b/functions/array/array_search.js index 7d13d121..66d52051 100644 --- a/functions/array/array_search.js +++ b/functions/array/array_search.js @@ -3,6 +3,8 @@ function array_search (needle, haystack, argStrict) { // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + input by: Brett Zamir (http://brett-zamir.me) // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // - depends on: array + // * test: skip // * example 1: array_search('zonneveld', {firstname: 'kevin', middle: 'van', surname: 'zonneveld'}); // * returns 1: 'surname' // * example 2: ini_set('phpjs.return_phpjs_arrays', 'on'); diff --git a/functions/array/array_walk.js b/functions/array/array_walk.js index 94f7ef76..91bb8a78 100644 --- a/functions/array/array_walk.js +++ b/functions/array/array_walk.js @@ -3,8 +3,10 @@ function array_walk (array, funcname, userdata) { // + original by: Johnny Mast (http://www.phpvrouwen.nl) // + bugfixed by: David // + improved by: Brett Zamir (http://brett-zamir.me) - // % note 1: Using ini_set('phpjs.no-eval', true) will only work with - // % note 1: user-defined string functions, not built-in functions like void() + // - depends on: array + // % note 1: Using ini_set('phpjs.no-eval', true) will only work with + // % note 1: user-defined string functions, not built-in functions like void() + // * test: skip // * example 1: array_walk ({'a':'b'}, 'void', 'userdata'); // * returns 1: true // * example 2: array_walk ('a', 'void', 'userdata'); @@ -16,7 +18,7 @@ function array_walk (array, funcname, userdata) { // * example 5: ini_set('phpjs.return_phpjs_arrays', 'on'); // * example 5: var arr = array({40: 'My age'}, {50: 'My IQ'}); // * example 5: array_walk(arr, [window, 'prompt']); - // * returns 5: [object Object] + // * returns 5: '[object Object]' var key, value, ini; if (!array || typeof array !== 'object') { diff --git a/functions/array/end.js b/functions/array/end.js index a9863b34..1e1808bf 100644 --- a/functions/array/end.js +++ b/functions/array/end.js @@ -33,9 +33,10 @@ function end (arr) { var arrpos = pointers.indexOf(arr); if (Object.prototype.toString.call(arr) !== '[object Array]') { var ct = 0; + var val; for (var k in arr) { ct++; - var val = arr[k]; + val = arr[k]; } if (ct === 0) { return false; // Empty diff --git a/functions/array/natcasesort.js b/functions/array/natcasesort.js index d63bea67..6a596356 100644 --- a/functions/array/natcasesort.js +++ b/functions/array/natcasesort.js @@ -18,6 +18,7 @@ function natcasesort (inputArr) { // * example 1: $array1 = {a:'IMG0.png', b:'img12.png', c:'img10.png', d:'img2.png', e:'img1.png', f:'IMG3.png'}; // * example 1: $array1 = natcasesort($array1); // * returns 1: {a: 'IMG0.png', e: 'img1.png', d: 'img2.png', f: 'IMG3.png', c: 'img10.png', b: 'img12.png'} + var valArr = [], k, i, ret, that = this, strictForIn = false, diff --git a/functions/array/shuffle.js b/functions/array/shuffle.js index ac007532..72761731 100644 --- a/functions/array/shuffle.js +++ b/functions/array/shuffle.js @@ -14,13 +14,15 @@ function shuffle (inputArr) { // % note 1: behavior by default if IE ever does allow it; only gives shallow copy since // % note 1: is by reference in PHP anyways // * example 1: ini_set('phpjs.strictForIn', true); - // * example 1: shuffle({5:'a', 2:'3', 3:'c', 4:5, 'q':5}); + // * example 2: var data = {5:'a', 2:'3', 3:'c', 4:5, 'q':5}; + // * example 1: shuffle(data); + // * example 1: data; // * returns 1: {5:'a', 4:5, 'q':5, 3:'c', 2:'3'} // * example 2: ini_set('phpjs.strictForIn', true); // * example 2: var data = {5:'a', 2:'3', 3:'c', 4:5, 'q':5}; // * example 2: shuffle(data); - // * results 2: {5:'a', 'q':5, 3:'c', 2:'3', 4:5} - // * returns 2: true + // * example 2: data; + // * returns 2: {5:'a', 'q':5, 3:'c', 2:'3', 4:5} var valArr = [], k = '', i = 0, diff --git a/functions/array/uasort.js b/functions/array/uasort.js index e8c6dde5..54708f43 100644 --- a/functions/array/uasort.js +++ b/functions/array/uasort.js @@ -14,7 +14,9 @@ function uasort (inputArr, sorter) { // % note 1: is by reference in PHP anyways // * example 1: fruits = {d: 'lemon', a: 'orange', b: 'banana', c: 'apple'}; // * example 1: fruits = uasort(fruits, function (a, b) { if (a > b) {return 1;}if (a < b) {return -1;} return 0;}); - // * results 1: fruits == {c: 'apple', b: 'banana', d: 'lemon', a: 'orange'} + // * example 1: fruits; + // * returns 1: {c: 'apple', b: 'banana', d: 'lemon', a: 'orange'} + var valArr = [], tempKeyVal, tempValue, ret, k = '', i = 0, diff --git a/functions/array/usort.js b/functions/array/usort.js index 7ed7b697..b95998b2 100644 --- a/functions/array/usort.js +++ b/functions/array/usort.js @@ -13,7 +13,8 @@ function usort (inputArr, sorter) { // % note 1: is by reference in PHP anyways // * example 1: stuff = {d: '3', a: '1', b: '11', c: '4'}; // * example 1: stuff = usort(stuff, function (a, b) {return(a-b);}); - // * results 1: stuff = {0: '1', 1: '3', 2: '4', 3: '11'}; + // * example 1: stuff; + // * returns 1: {0: '1', 1: '3', 2: '4', 3: '11'}; var valArr = [], k = '', i = 0, diff --git a/functions/datetime/microtime.js b/functions/datetime/microtime.js index e953a335..902c900f 100644 --- a/functions/datetime/microtime.js +++ b/functions/datetime/microtime.js @@ -2,7 +2,8 @@ function microtime (get_as_float) { // From: http://phpjs.org/functions // + original by: Paulo Freitas // * example 1: timeStamp = microtime(true); - // * results 1: timeStamp > 1000000000 && timeStamp < 2000000000 + // * example 1: timeStamp > 1000000000 && timeStamp < 2000000000 + // * returns 1: true var now = new Date().getTime() / 1000; var s = parseInt(now, 10); diff --git a/functions/datetime/strptime.js b/functions/datetime/strptime.js index fe47413e..289dcb88 100644 --- a/functions/datetime/strptime.js +++ b/functions/datetime/strptime.js @@ -4,6 +4,7 @@ function strptime (dateStr, format) { // + based on: strftime // - depends on: setlocale // - depends on: array_map + // * test: skip // * example 1: strptime('20091112222135', '%Y%m%d%H%M%S'); // Return value will depend on date and locale // * returns 1: {tm_sec: 35, tm_min: 21, tm_hour: 22, tm_mday: 12, tm_mon: 10, tm_year: 109, tm_wday: 4, tm_yday: 315, unparsed: ''} // * example 1: strptime('2009extra', '%Y'); diff --git a/functions/datetime/time.js b/functions/datetime/time.js index 9730dc3d..b9556ead 100644 --- a/functions/datetime/time.js +++ b/functions/datetime/time.js @@ -5,6 +5,7 @@ function time () { // + improved by: metjay // + improved by: HKM // * example 1: timeStamp = time(); - // * results 1: timeStamp > 1000000000 && timeStamp < 2000000000 + // * example 1: timeStamp > 1000000000 && timeStamp < 2000000000 + // * returns 1: true return Math.floor(new Date().getTime() / 1000); } diff --git a/functions/filesystem/dirname.js b/functions/filesystem/dirname.js index 8c4b48f1..3705f22c 100644 --- a/functions/filesystem/dirname.js +++ b/functions/filesystem/dirname.js @@ -1,5 +1,5 @@ function dirname (path) { - // From: http://phpjs.org/functions + // http://kevin.vanzonneveld.net // + original by: Ozh // + improved by: XoraX (http://www.xorax.info) // * example 1: dirname('/etc/passwd'); @@ -8,5 +8,6 @@ function dirname (path) { // * returns 2: 'c:/Temp' // * example 3: dirname('/dir/test/'); // * returns 3: '/dir' + return path.replace(/\\/g, '/').replace(/\/[^\/]*\/?$/, ''); } diff --git a/experimental/filesystem/file_get_contents.js b/functions/filesystem/file_get_contents.js similarity index 98% rename from experimental/filesystem/file_get_contents.js rename to functions/filesystem/file_get_contents.js index e0dfe780..b28f4c2b 100644 --- a/experimental/filesystem/file_get_contents.js +++ b/functions/filesystem/file_get_contents.js @@ -1,8 +1,5 @@ function file_get_contents (url, flags, context, offset, maxLen) { - // Read the entire file into a string - // - // version: 906.111 - // discuss at: http://phpjs.org/functions/file_get_contents + // From: http://phpjs.org/functions // + original by: Legaev Andrey // + input by: Jani Hartikainen // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) @@ -19,8 +16,10 @@ function file_get_contents (url, flags, context, offset, maxLen) { // % note 3: The context argument is only implemented for http, and only partially (see below for // % note 3: "Presently unimplemented HTTP context options"); also the arguments passed to // % note 3: notification are incomplete - // * example 1: file_get_contents('http://kevin.vanzonneveld.net/pj_test_supportfile_1.htm'); - // * returns 1: '123' + // * test: skip + // * example 1: var buf file_get_contents('http://google.com'); + // * example 1: buf.indexOf('Google') !== -1 + // * returns 1: true // Note: could also be made to optionally add to global $http_response_header as per http://php.net/manual/en/reserved.variables.httpresponseheader.php var tmp, headers = [], newTmp = [], diff --git a/functions/filesystem/pathinfo.js b/functions/filesystem/pathinfo.js index 96228382..a5eee6f5 100644 --- a/functions/filesystem/pathinfo.js +++ b/functions/filesystem/pathinfo.js @@ -15,6 +15,7 @@ function pathinfo (path, options) { // % note 2: which makes it fully compliant with PHP syntax. // - depends on: dirname // - depends on: basename + // * test: skip // * example 1: pathinfo('/www/htdocs/index.html', 1); // * returns 1: '/www/htdocs' // * example 2: pathinfo('/www/htdocs/index.html', 'PATHINFO_BASENAME'); diff --git a/functions/funchand/get_defined_functions.js b/functions/funchand/get_defined_functions.js index 3a799acd..64ebc1ee 100644 --- a/functions/funchand/get_defined_functions.js +++ b/functions/funchand/get_defined_functions.js @@ -6,7 +6,8 @@ function get_defined_functions () { // * example 1: function test_in_array (array, p_val) {for(var i = 0, l = array.length; i < l; i++) {if(array[i] == p_val) return true;} return false;} // * example 1: funcs = get_defined_functions(); // * example 1: found = test_in_array(funcs, 'get_defined_functions'); - // * results 1: found == true + // * example 1: found; + // * returns 1: true var i = '', arr = [], already = {}; diff --git a/experimental/i18n/i18n_loc_get_default.js b/functions/i18n/i18n_loc_get_default.js similarity index 100% rename from experimental/i18n/i18n_loc_get_default.js rename to functions/i18n/i18n_loc_get_default.js diff --git a/experimental/i18n/i18n_loc_set_default.js b/functions/i18n/i18n_loc_set_default.js similarity index 100% rename from experimental/i18n/i18n_loc_set_default.js rename to functions/i18n/i18n_loc_set_default.js diff --git a/functions/info/ini_set.js b/functions/info/ini_set.js index fdb65c48..a5a94b52 100644 --- a/functions/info/ini_set.js +++ b/functions/info/ini_set.js @@ -2,15 +2,23 @@ function ini_set (varname, newvalue) { // From: http://phpjs.org/functions // + original by: Brett Zamir (http://brett-zamir.me) // % note 1: This will not set a global_value or access level for the ini item + // * test: skip // * example 1: ini_set('date.timezone', 'America/Chicago'); // * returns 1: 'Asia/Hong_Kong' - var oldval = ''; - var self = this; - this.php_js = this.php_js || {}; + var oldval = ''; + var self = this; + + try { + this.php_js = this.php_js || {}; + } catch (e) { + this.php_js = {}; + } + this.php_js.ini = this.php_js.ini || {}; this.php_js.ini[varname] = this.php_js.ini[varname] || {}; - oldval = this.php_js.ini[varname].local_value; + + oldval = this.php_js.ini[varname].local_value; var _setArr = function (oldval) { // Although these are set individually, they are all accumulated @@ -32,5 +40,6 @@ function ini_set (varname, newvalue) { this.php_js.ini[varname].local_value = newvalue; break; } + return oldval; } diff --git a/functions/info/set_time_limit.js b/functions/info/set_time_limit.js index 464a1012..f4f016ad 100644 --- a/functions/info/set_time_limit.js +++ b/functions/info/set_time_limit.js @@ -1,6 +1,7 @@ function set_time_limit (seconds) { // From: http://phpjs.org/functions // + original by: Brett Zamir (http://brett-zamir.me) + // * test: skip // * example 1: set_time_limit(4); // * returns 1: undefined diff --git a/functions/json/json_decode.js b/functions/json/json_decode.js index c5fcc788..99f1c406 100644 --- a/functions/json/json_decode.js +++ b/functions/json/json_decode.js @@ -4,9 +4,10 @@ function json_decode (str_json) { // + reimplemented by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: T.J. Leahy // + improved by: Michael White - // * example 1: json_decode('[\n "e",\n {\n "pluribus": "unum"\n}\n]'); - // * returns 1: ['e', {pluribus: 'unum'}] -/* + // * example 1: json_decode('[ 1 ]'); + // * returns 1: true + + /* http://www.JSON.org/json2.js 2008-11-19 Public Domain. diff --git a/functions/json/json_encode.js b/functions/json/json_encode.js index fa85d56f..e3195b2c 100644 --- a/functions/json/json_encode.js +++ b/functions/json/json_encode.js @@ -3,11 +3,12 @@ function json_encode (mixed_val) { // + original by: Public Domain (http://www.json.org/json2.js) // + reimplemented by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: Michael White - // + input by: felix + // + input by: felix // + bugfixed by: Brett Zamir (http://brett-zamir.me) - // * example 1: json_encode(['e', {pluribus: 'unum'}]); - // * returns 1: '[\n "e",\n {\n "pluribus": "unum"\n}\n]' -/* + // * example 1: json_encode('Kevin'); + // * returns 1: 'Kevin' + + /* http://www.JSON.org/json2.js 2008-11-19 Public Domain. diff --git a/functions/network/inet_pton.js b/functions/network/inet_pton.js index b88bb20e..2041c03e 100644 --- a/functions/network/inet_pton.js +++ b/functions/network/inet_pton.js @@ -2,9 +2,10 @@ function inet_pton (a) { // From: http://phpjs.org/functions // + original by: Theriault // * example 1: inet_pton('::'); - // * returns 1: '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0' (binary) + // * returns 1: '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0' // * example 2: inet_pton('127.0.0.1'); - // * returns 2: '\x7F\x00\x00\x01' (binary) + // * returns 2: '\x7F\x00\x00\x01' + var r, m, x, i, j, f = String.fromCharCode; m = a.match(/^(?:\d{1,3}(?:\.|$)){4}/); // IPv4 if (m) { diff --git a/functions/network/setrawcookie.js b/functions/network/setrawcookie.js index 15f242ab..f2555fec 100644 --- a/functions/network/setrawcookie.js +++ b/functions/network/setrawcookie.js @@ -5,7 +5,7 @@ function setrawcookie (name, value, expires, path, domain, secure) { // + derived from: setcookie // + input by: Michael // + bugfixed by: Brett Zamir (http://brett-zamir.me) - // * example 1: setcookie('author_name', 'Kevin van Zonneveld'); + // * example 1: setrawcookie('author_name', 'Kevin van Zonneveld'); // * returns 1: true if (typeof expires === 'string' && (/^\d+$/).test(expires)) { expires = parseInt(expires, 10); diff --git a/functions/pcre/preg_grep.js b/functions/pcre/preg_grep.js index 6fefe375..9768cb26 100644 --- a/functions/pcre/preg_grep.js +++ b/functions/pcre/preg_grep.js @@ -1,16 +1,16 @@ function preg_grep (pattern, input, flags) { // From: http://phpjs.org/functions // + original by: Brett Zamir (http://brett-zamir.me) - // % note 1: If pass pattern as string, must escape backslashes, even for single quotes - // % note 2: The regular expression itself must be expressed JavaScript style - // % note 3: It is not recommended to submit the pattern as a string, as we may implement - // % note 3: parsing of PHP-style expressions (flags, etc.) in the future + // % note 1: If pass pattern as string, must escape backslashes, even for single quotes + // % note 2: The regular expression itself must be expressed JavaScript style + // % note 3: It is not recommended to submit the pattern as a string, as we may implement + // % note 3: parsing of PHP-style expressions (flags, etc.) in the future // * example 1: var arr = [1, 4, 4.5, 3, 'a', 4.4]; // * example 1: preg_grep("/^(\\d+)?\\.\\d+$/", arr); // * returns 1: {2: 4.5, 5: 4.4} - var p = '', - retObj = {}; + var p = ''; + var retObj = {}; var invert = (flags === 1 || flags === 'PREG_GREP_INVERT'); // Todo: put flags as number and do bitwise checks (at least if other flags allowable); see pathinfo() if (typeof pattern === 'string') { @@ -19,13 +19,13 @@ function preg_grep (pattern, input, flags) { if (invert) { for (p in input) { - if (input[p].search(pattern) === -1) { + if ((input[p] + '').search(pattern) === -1) { retObj[p] = input[p]; } } } else { for (p in input) { - if (input[p].search(pattern) !== -1) { + if ((input[p] + '').search(pattern) !== -1) { retObj[p] = input[p]; } } diff --git a/functions/strings/addcslashes.js b/functions/strings/addcslashes.js index 38eca0f6..b494001e 100644 --- a/functions/strings/addcslashes.js +++ b/functions/strings/addcslashes.js @@ -7,14 +7,14 @@ function addcslashes (str, charlist) { // * returns 1: "\\f\\o\\o\\[ \\]" // * example 2: addcslashes("zoo['.']", 'z..A'); // Only escape z, period, and A here since not a lower-to-higher range // * returns 2: "\\zoo['\\.']" - // * example 3: addcslashes("@a\u0000\u0010\u00A9", "\0..\37!@\177..\377") == '\\@a\\000\\020\\302\\251'); // Escape as octals those specified and less than 32 (0x20) or greater than 126 (0x7E), but not otherwise - // * returns 3: true - // * example 4: addcslashes("\u0020\u007E", "\40..\175") == '\\ ~'); // Those between 32 (0x20 or 040) and 126 (0x7E or 0176) decimal value will be backslashed if specified (not octalized) - // * returns 4: true + // * example 3: addcslashes("@a\u0000\u0010\u00A9", "\0..\37!@\177..\377"); // Escape as octals those specified and less than 32 (0x20) or greater than 126 (0x7E), but not otherwise + // * returns 3: '\\@a\\000\\020\\302\\251' + // * example 4: addcslashes("\u0020\u007E", "\40..\175"); // Those between 32 (0x20 or 040) and 126 (0x7E or 0176) decimal value will be backslashed if specified (not octalized) + // * returns 4: '\\ ~' // * example 5: addcslashes("\r\u0007\n", '\0..\37'); // Recognize C escape sequences if specified // * returns 5: "\\r\\a\\n" // * example 6: addcslashes("\r\u0007\n", '\0'); // Do not recognize C escape sequences if not specified - // * returns 7: "\r\u0007\n" + // * returns 6: "\r\u0007\n" var target = '', chrs = [], i = 0, diff --git a/functions/strings/convert_uuencode.js b/functions/strings/convert_uuencode.js index cdb10a35..0e4fcc9f 100644 --- a/functions/strings/convert_uuencode.js +++ b/functions/strings/convert_uuencode.js @@ -6,7 +6,7 @@ function convert_uuencode (str) { // + bugfixed by: Brett Zamir (http://brett-zamir.me) // - depends on: is_scalar // * example 1: convert_uuencode("test\ntext text\r\n"); - // * returns 1: '0=&5S=`IT97AT('1E>'0-"@``' + // * returns 1: "0=&5S=`IT97AT('1E>'0-\"@``" // shortcut var chr = function (c) { return String.fromCharCode(c); diff --git a/experimental/strings/echo.js b/functions/strings/echo.js similarity index 100% rename from experimental/strings/echo.js rename to functions/strings/echo.js diff --git a/functions/strings/htmlspecialchars.js b/functions/strings/htmlspecialchars.js index 35ede6a2..10d0d79f 100644 --- a/functions/strings/htmlspecialchars.js +++ b/functions/strings/htmlspecialchars.js @@ -16,8 +16,9 @@ function htmlspecialchars (string, quote_style, charset, double_encode) { // * returns 1: '<a href='test'>Test</a>' // * example 2: htmlspecialchars("ab\"c'd", ['ENT_NOQUOTES', 'ENT_QUOTES']); // * returns 2: 'ab"c'd' - // * example 3: htmlspecialchars("my "&entity;" is still here", null, null, false); + // * example 3: htmlspecialchars('my "&entity;" is still here', null, null, false); // * returns 3: 'my "&entity;" is still here' + var optTemp = 0, i = 0, noquotes = false; diff --git a/functions/strings/md5_file.js b/functions/strings/md5_file.js index c8a6f294..a4f106bb 100644 --- a/functions/strings/md5_file.js +++ b/functions/strings/md5_file.js @@ -5,8 +5,10 @@ function md5_file (str_filename) { // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // - depends on: file_get_contents // - depends on: md5 + // * test: skip // * example 1: md5_file('http://kevin.vanzonneveld.net/pj_test_supportfile_1.htm'); // * returns 1: '202cb962ac59075b964b07152d234b70' + var buf = ''; buf = this.file_get_contents(str_filename); diff --git a/functions/strings/parse_str.js b/functions/strings/parse_str.js index 41e93c18..6ad5c752 100644 --- a/functions/strings/parse_str.js +++ b/functions/strings/parse_str.js @@ -1,31 +1,33 @@ function parse_str (str, array) { // From: http://phpjs.org/functions - // + original by: Cagri Ekin - // + improved by: Michael White (http://getsprink.com) - // + tweaked by: Jack - // + bugfixed by: Onno Marsman - // + reimplemented by: stag019 - // + bugfixed by: Brett Zamir (http://brett-zamir.me) - // + bugfixed by: stag019 - // + input by: Dreamer - // + bugfixed by: Brett Zamir (http://brett-zamir.me) - // + bugfixed by: MIO_KODUKI (http://mio-koduki.blogspot.com/) - // + input by: Zaide (http://zaidesthings.com/) - // + input by: David Pesta (http://davidpesta.com/) - // + input by: jeicquest - // + improved by: Brett Zamir (http://brett-zamir.me) - // % note 1: When no argument is specified, will put variables in global scope. - // % note 1: When a particular argument has been passed, and the returned value is different parse_str of PHP. For example, a=b=c&d====c - // * example 1: var arr = {}; - // * example 1: parse_str('first=foo&second=bar', arr); - // * results 1: arr == { first: 'foo', second: 'bar' } - // * example 2: var arr = {}; - // * example 2: parse_str('str_a=Jack+and+Jill+didn%27t+see+the+well.', arr); - // * results 2: arr == { str_a: "Jack and Jill didn't see the well." } - // * example 3: var abc = {3:'a'}; - // * example 3: parse_str('abc[a][b]["c"]=def&abc[q]=t+5'); - // * results 3: JSON.stringify(abc) === '{"3":"a","a":{"b":{"c":"def"}},"q":"t 5"}'; - + // + original by: Cagri Ekin + // + improved by: Michael White (http://getsprink.com) + // + tweaked by: Jack + // + bugfixed by: Onno Marsman + // + reimplemented by: stag019 + // + bugfixed by: Brett Zamir (http://brett-zamir.me) + // + bugfixed by: stag019 + // + input by: Dreamer + // + bugfixed by: Brett Zamir (http://brett-zamir.me) + // + bugfixed by: MIO_KODUKI (http://mio-koduki.blogspot.com/) + // + input by: Zaide (http://zaidesthings.com/) + // + input by: David Pesta (http://davidpesta.com/) + // + input by: jeicquest + // + improved by: Brett Zamir (http://brett-zamir.me) + // % note 1: When no argument is specified, will put variables in global scope. + // % note 1: When a particular argument has been passed, and the returned value is different parse_str of PHP. For example, a=b=c&d====c + // % test: skip + // * example 1: var arr = {}; + // * example 1: parse_str('first=foo&second=bar', arr); + // * example 1: arr + // * returns 1: { first: 'foo', second: 'bar' } + // * example 2: var arr = {}; + // * example 2: parse_str('str_a=Jack+and+Jill+didn%27t+see+the+well.', arr); + // * example 2: arr + // * returns 2: { str_a: "Jack and Jill didn't see the well." } + // * example 3: var abc = {3:'a'}; + // * example 3: parse_str('abc[a][b]["c"]=def&abc[q]=t+5'); + // * returns 3: {"3":"a","a":{"b":{"c":"def"}},"q":"t 5"} var strArr = String(str).replace(/^&/, '').replace(/&$/, '').split('&'), sal = strArr.length, diff --git a/functions/strings/printf.js b/functions/strings/printf.js index 02606ed0..8989220a 100644 --- a/functions/strings/printf.js +++ b/functions/strings/printf.js @@ -6,11 +6,16 @@ function printf () { // - depends on: sprintf // * example 1: printf("%01.2f", 123.1); // * returns 1: 6 + var body, elmt, d = this.window.document; var ret = ''; var HTMLNS = 'http://www.w3.org/1999/xhtml'; - body = d.getElementsByTagNameNS ? (d.getElementsByTagNameNS(HTMLNS, 'body')[0] ? d.getElementsByTagNameNS(HTMLNS, 'body')[0] : d.documentElement.lastChild) : d.getElementsByTagName('body')[0]; + body = d.getElementsByTagNameNS + ? (d.getElementsByTagNameNS(HTMLNS, 'body')[0] + ? d.getElementsByTagNameNS(HTMLNS, 'body')[0] + : d.documentElement.lastChild) + : d.getElementsByTagName('body')[0]; if (!body) { return false; diff --git a/functions/strings/quoted_printable_decode.js b/functions/strings/quoted_printable_decode.js index 9f4ffc72..719d154d 100644 --- a/functions/strings/quoted_printable_decode.js +++ b/functions/strings/quoted_printable_decode.js @@ -11,8 +11,8 @@ function quoted_printable_decode (str) { // * returns 2: 'abc \r\n123 \r\n' // * example 3: quoted_printable_decode('012345678901234567890123456789012345678901234567890123456789012345678901234=\r\n56789'); // * returns 3: '01234567890123456789012345678901234567890123456789012345678901234567890123456789' - // * example 4: quoted_printable_decode("Lorem ipsum dolor sit amet=23, consectetur adipisicing elit"); - // * returns 4: Lorem ipsum dolor sit amet#, consectetur adipisicing elit + // * example 4: quoted_printable_decode("Lorem ipsum dolor sit amet=23, consectetur adipisicing elit"); + // * returns 4: 'Lorem ipsum dolor sit amet#, consectetur adipisicing elit' // Removes softline breaks var RFC2045Decode1 = /=\r\n/gm, // Decodes all equal signs followed by two hex digits diff --git a/functions/strings/sha1_file.js b/functions/strings/sha1_file.js index 63b41db2..9d8fce82 100644 --- a/functions/strings/sha1_file.js +++ b/functions/strings/sha1_file.js @@ -3,8 +3,11 @@ function sha1_file (str_filename) { // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // - depends on: file_get_contents // - depends on: sha1 + // * test: skip // * example 1: sha1_file('http://kevin.vanzonneveld.net/pj_test_supportfile_1.htm'); // * returns 1: '40bd001563085fc35165329ea1ff5c5ecbdbbeef' + var buf = this.file_get_contents(str_filename); + return this.sha1(buf); } diff --git a/functions/strings/str_rot13.js b/functions/strings/str_rot13.js index ddd7b13c..8bd48741 100644 --- a/functions/strings/str_rot13.js +++ b/functions/strings/str_rot13.js @@ -10,6 +10,7 @@ function str_rot13 (str) { // * returns 2: 'Kevin van Zonneveld' // * example 3: str_rot13(33); // * returns 3: '33' + return (str + '').replace(/[a-z]/gi, function (s) { return String.fromCharCode(s.charCodeAt(0) + (s.toLowerCase() < 'n' ? 13 : -13)); }); diff --git a/functions/strings/str_shuffle.js b/functions/strings/str_shuffle.js index db41b3cc..91f677f5 100644 --- a/functions/strings/str_shuffle.js +++ b/functions/strings/str_shuffle.js @@ -2,7 +2,9 @@ function str_shuffle (str) { // From: http://phpjs.org/functions // + original by: Brett Zamir (http://brett-zamir.me) // * example 1: shuffled = str_shuffle("abcdef"); - // * results 1: shuffled.length == 6 + // * example 1: shuffled.length + // * returns 1: 6 + if (arguments.length === 0) { throw 'Wrong parameter count for str_shuffle()'; } diff --git a/functions/strings/strip_tags.js b/functions/strings/strip_tags.js index 05dc118e..439cda2c 100644 --- a/functions/strings/strip_tags.js +++ b/functions/strings/strip_tags.js @@ -22,7 +22,7 @@ function strip_tags (input, allowed) { // * example 2: strip_tags('

Kevin van Zonneveld

', '

'); // * returns 2: '

Kevin van Zonneveld

' // * example 3: strip_tags("Kevin van Zonneveld", ""); - // * returns 3: 'Kevin van Zonneveld' + // * returns 3: 'Kevin van Zonneveld' // * example 4: strip_tags('1 < 5 5 > 1'); // * returns 4: '1 < 5 5 > 1' // * example 5: strip_tags('1
1'); @@ -31,6 +31,7 @@ function strip_tags (input, allowed) { // * returns 6: '1 1' // * example 7: strip_tags('1
1', '

'); // * returns 7: '1
1' + allowed = (((allowed || "") + "").toLowerCase().match(/<[a-z][a-z0-9]*>/g) || []).join(''); // making sure the allowed arg is a string containing only tags in lowercase () var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi, commentsAndPhpTags = /|<\?(?:php)?[\s\S]*?\?>/gi; diff --git a/functions/strings/substr_replace.js b/functions/strings/substr_replace.js index 92ada0a9..e2dee0ec 100644 --- a/functions/strings/substr_replace.js +++ b/functions/strings/substr_replace.js @@ -12,8 +12,9 @@ function substr_replace (str, replace, start, length) { // * returns 4: 'ABCDEFGH:/bob/' // * example 5: substr_replace('ABCDEFGH:/MNRPQR/', 'bob', -7, -1); // * returns 5: 'ABCDEFGH:/bob/' - // * example 6: 'substr_replace('ABCDEFGH:/MNRPQR/', '', 10, -1)' + // * example 6: substr_replace('ABCDEFGH:/MNRPQR/', '', 10, -1) // * returns 6: 'ABCDEFGH://' + if (start < 0) { // start position in str start = start + str.length; } @@ -21,5 +22,6 @@ function substr_replace (str, replace, start, length) { if (length < 0) { length = length + str.length - start; } + return str.slice(0, start) + replace.substr(0, length) + replace.slice(length) + str.slice(start + length); } diff --git a/functions/strings/vprintf.js b/functions/strings/vprintf.js index 3215546e..7f89188d 100644 --- a/functions/strings/vprintf.js +++ b/functions/strings/vprintf.js @@ -1,11 +1,12 @@ function vprintf (format, args) { // From: http://phpjs.org/functions - // + original by: Ash Searle (http://hexmen.com/blog/) - // + improved by: Michael White (http://getsprink.com) + // + original by: Ash Searle (http://hexmen.com/blog/) + // + improved by: Michael White (http://getsprink.com) // + reimplemented by: Brett Zamir (http://brett-zamir.me) - // - depends on: sprintf - // * example 1: printf("%01.2f", 123.1); - // * returns 1: 6 + // - depends on: sprintf + // * example 1: vprintf("%01.2f", 123.1); + // * returns 1: 6 + var body, elmt; var ret = '', d = this.window.document; diff --git a/functions/url/get_headers.js b/functions/url/get_headers.js index c51b304f..08f88867 100644 --- a/functions/url/get_headers.js +++ b/functions/url/get_headers.js @@ -1,17 +1,23 @@ function get_headers (url, format) { + // From: http://phpjs.org/functions // + original by: Paulo Freitas // + bugfixed by: Brett Zamir (http://brett-zamir.me) // - depends on: array_filter // % note 1: This function uses XmlHttpRequest and cannot retrieve resource from different domain. // % note 1: Synchronous so may lock up browser, mainly here for study purposes. + // * test: skip // * example 1: get_headers('http://kevin.vanzonneveld.net/pj_test_supportfile_1.htm')[0]; // * returns 1: 'Date: Wed, 13 May 2009 23:53:11 GMT' - var req = this.window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest(); + + var req = this.window.ActiveXObject + ? new ActiveXObject("Microsoft.XMLHTTP") + : new XMLHttpRequest(); + if (!req) { throw new Error('XMLHttpRequest not supported'); } var tmp, headers, pair, i, j = 0; - +ß req.open('HEAD', url, false); req.send(null); @@ -26,7 +32,7 @@ function get_headers (url, format) { }); headers = format ? {} : []; - for (i in tmp) { + for (var i in tmp) { if (format) { pair = tmp[i].split(':'); headers[pair.splice(0, 1)] = pair.join(':').substring(1); @@ -34,5 +40,6 @@ function get_headers (url, format) { headers[j++] = tmp[i]; } } + return headers; } diff --git a/functions/url/get_meta_tags.js b/functions/url/get_meta_tags.js index 90899662..d9f99346 100644 --- a/functions/url/get_meta_tags.js +++ b/functions/url/get_meta_tags.js @@ -1,12 +1,10 @@ function get_meta_tags (file) { - // Extracts all meta tag content attributes from a file and returns an array - // - // version: 905.3122 - // discuss at: http://phpjs.org/functions/get_meta_tags + // From: http://phpjs.org/functions // + original by: Brett Zamir (http://brett-zamir.me) // % note 1: This function uses XmlHttpRequest and cannot retrieve resource from different domain. // % note 1: Synchronous so may lock up browser, mainly here for study purposes. // - depends on: file_get_contents + // * test: skip // * example 1: get_meta_tags('http://kevin.vanzonneveld.net/pj_test_supportfile_2.htm'); // * returns 1: {description: 'a php manual', author: 'name', keywords: 'php documentation', 'geo_position': '49.33;-86.59'} var fulltxt = ''; diff --git a/functions/url/rawurldecode.js b/functions/url/rawurldecode.js index 564a36b0..a2283996 100644 --- a/functions/url/rawurldecode.js +++ b/functions/url/rawurldecode.js @@ -1,27 +1,24 @@ function rawurldecode (str) { - // From: http://phpjs.org/functions - // + original by: Brett Zamir (http://brett-zamir.me) - // + input by: travc - // + input by: Brett Zamir (http://brett-zamir.me) - // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) - // + input by: Ratheous - // + reimplemented by: Brett Zamir (http://brett-zamir.me) - // + input by: lovio - // + improved by: Brett Zamir (http://brett-zamir.me) - // % note 1: Please be aware that this function expects to decode from UTF-8 encoded strings, as found on - // % note 1: pages served as UTF-8 - // * example 1: rawurldecode('Kevin+van+Zonneveld%21'); - // * returns 1: 'Kevin+van+Zonneveld!' - // * example 2: rawurldecode('http%3A%2F%2Fkevin.vanzonneveld.net%2F'); - // * returns 2: 'http://kevin.vanzonneveld.net/' - // * example 3: rawurldecode('http%3A%2F%2Fwww.google.nl%2Fsearch%3Fq%3Dphp.js%26ie%3Dutf-8%26oe%3Dutf-8%26aq%3Dt%26rls%3Dcom.ubuntu%3Aen-US%3Aunofficial%26client%3Dfirefox-a'); - // * returns 3: 'http://www.google.nl/search?q=php.js&ie=utf-8&oe=utf-8&aq=t&rls=com.ubuntu:en-US:unofficial&client=firefox-a' - // * example 4: rawurldecode('-22%97bc%2Fbc'); - // * returns 4: '-22—bc/bc' - // * example 4: urldecode('%E5%A5%BD%3_4'); - // * returns 4: '\u597d%3_4' - return decodeURIComponent((str + '').replace(/%(?![\da-f]{2})/gi, function () { - // PHP tolerates poorly formed escape sequences - return '%25'; - })); + // From: http://phpjs.org/functions + // + original by: Brett Zamir (http://brett-zamir.me) + // + input by: travc + // + input by: Brett Zamir (http://brett-zamir.me) + // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // + input by: Ratheous + // + reimplemented by: Brett Zamir (http://brett-zamir.me) + // + input by: lovio + // + improved by: Brett Zamir (http://brett-zamir.me) + // % note 1: Please be aware that this function expects to decode from UTF-8 encoded strings, as found on + // % note 1: pages served as UTF-8 + // * example 1: rawurldecode('Kevin+van+Zonneveld%21'); + // * returns 1: 'Kevin+van+Zonneveld!' + // * example 2: rawurldecode('http%3A%2F%2Fkevin.vanzonneveld.net%2F'); + // * returns 2: 'http://kevin.vanzonneveld.net/' + // * example 3: rawurldecode('http%3A%2F%2Fwww.google.nl%2Fsearch%3Fq%3Dphp.js%26ie%3Dutf-8%26oe%3Dutf-8%26aq%3Dt%26rls%3Dcom.ubuntu%3Aen-US%3Aunofficial%26client%3Dfirefox-a'); + // * returns 3: 'http://www.google.nl/search?q=php.js&ie=utf-8&oe=utf-8&aq=t&rls=com.ubuntu:en-US:unofficial&client=firefox-a' + + return decodeURIComponent((str + '').replace(/%(?![\da-f]{2})/gi, function () { + // PHP tolerates poorly formed escape sequences + return '%25'; + })); } diff --git a/functions/var/is_callable.js b/functions/var/is_callable.js index 761c8216..7998150a 100644 --- a/functions/var/is_callable.js +++ b/functions/var/is_callable.js @@ -1,10 +1,11 @@ function is_callable (v, syntax_only, callable_name) { // From: http://phpjs.org/functions // + original by: Brett Zamir (http://brett-zamir.me) - // + input by: François + // + input by: François // + improved by: Brett Zamir (http://brett-zamir.me) // % note 1: The variable callable_name cannot work as a string variable passed by reference as in PHP (since JavaScript does not support passing strings by reference), but instead will take the name of a global variable and set that instead // % note 2: When used on an object, depends on a constructor property being kept on the object prototype + // * test: skip // * example 1: is_callable('is_callable'); // * returns 1: true // * example 2: is_callable('bogusFunction', true); diff --git a/functions/var/is_double.js b/functions/var/is_double.js index fb3f5e3f..360f77d0 100644 --- a/functions/var/is_double.js +++ b/functions/var/is_double.js @@ -6,5 +6,6 @@ function is_double (mixed_var) { // % note 1: it different from the PHP implementation. We can't fix this unfortunately. // * example 1: is_double(186.31); // * returns 1: true + return this.is_float(mixed_var); } diff --git a/functions/var/is_real.js b/functions/var/is_real.js index 65ed498e..308bbeef 100644 --- a/functions/var/is_real.js +++ b/functions/var/is_real.js @@ -4,7 +4,8 @@ function is_real (mixed_var) { // - depends on: is_float // % note 1: 1.0 is simplified to 1 before it can be accessed by the function, this makes // % note 1: it different from the PHP implementation. We can't fix this unfortunately. - // * example 1: is_double(186.31); + // * example 1: is_real(186.31); // * returns 1: true + return this.is_float(mixed_var); } diff --git a/functions/var/var_dump.js b/functions/var/var_dump.js index 7d74b09d..6a57904d 100644 --- a/functions/var/var_dump.js +++ b/functions/var/var_dump.js @@ -5,6 +5,7 @@ function var_dump () { // + improved by: Brett Zamir (http://brett-zamir.me) // - depends on: echo // % note 1: For returning a string, use var_export() with the second argument set to true + // * test: skip // * example 1: var_dump(1); // * returns 1: 'int(1)' @@ -14,6 +15,7 @@ function var_dump () { lgth = 0, i = 0, d = this.window.document; + var _getFuncName = function (fn) { var name = (/\W*function\s+([\w\$]+)\s*\(/).exec(fn); if (!name) { diff --git a/functions/var/var_export.js b/functions/var/var_export.js index c88bf04d..0d07c5a3 100644 --- a/functions/var/var_export.js +++ b/functions/var/var_export.js @@ -3,10 +3,10 @@ function var_export (mixed_expression, bool_return) { // + original by: Philip Peterson // + improved by: johnrembo // + improved by: Brett Zamir (http://brett-zamir.me) - // + input by: Brian Tafoya (http://www.premasolutions.com/) + // + input by: Brian Tafoya (http://www.premasolutions.com/) // + bugfixed by: Brett Zamir (http://brett-zamir.me) // + bugfixed by: Brett Zamir (http://brett-zamir.me) - // + input by: Hans Henrik (http://hanshenrik.tk/) + // + input by: Hans Henrik (http://hanshenrik.tk/) // - depends on: echo // * example 1: var_export(null); // * returns 1: null @@ -15,6 +15,7 @@ function var_export (mixed_expression, bool_return) { // * example 3: data = 'Kevin'; // * example 3: var_export(data, true); // * returns 3: "'Kevin'" + var retstr = '', iret = '', value, @@ -39,7 +40,7 @@ function var_export (mixed_expression, bool_return) { }, __getType = function (inp) { var i = 0, match, types, cons, type = typeof inp; - if (type === 'object' && inp.constructor && + if (type === 'object' && (inp && inp.constructor) && getFuncName(inp.constructor) === 'PHPJS_Resource') { return 'resource'; } @@ -110,5 +111,6 @@ function var_export (mixed_expression, bool_return) { this.echo(retstr); return null; } + return retstr; } diff --git a/tests/cli.js b/tests/cli.js index 66b60217..d8af0cd1 100644 --- a/tests/cli.js +++ b/tests/cli.js @@ -1,6 +1,7 @@ var cli = require('cli').enable('status', 'help', 'version', 'glob', 'timeout'); var FS = require('fs'); var glob = require('glob'); +var path = require('path'); var phpjsutil = new require('./phpjsutil'); var PhpjsUtil = phpjsutil({ @@ -31,7 +32,8 @@ PhpjsUtil.opener = function (name, cb) { }; cli.parse({ - name: ['f', 'Function name to test', 'path'] + name: ['name', 'Function name to test', 'path', '*'], + category: ['c', 'Category to test', 'path', '*'] }); cli.pad = function(str, pad, chr, dir) { @@ -53,37 +55,55 @@ cli.pad = function(str, pad, chr, dir) { var width = 120; cli.main(function(args, options) { - if (!options.name) { - this.fatal('Please specify a file to test (-h for help)'); - } - - // cli.spinner('Working..'); - // cli.spinner('Working.. done!', true); //End the spinner - - PhpjsUtil.load(options.name, function (err, params) { - if (err) { - return cli.fatal(err); + var globpath = __dirname + '/../functions/' + options.category + '/' + options.name + '.js'; + + glob(globpath, {}, function (err, files) { + var names = []; + for (var i in files) { + var file = files[i]; + if (file.indexOf('/_') === -1) { + names.push(path.basename(file, '.js')); + } } - // console.log(params['headKeys']); - - PhpjsUtil.test(params, function(err, test, params) { - var testline = cli.pad(params['name'] + '#' + test['number'], (width * 0.4), ' ', 'right') + - ' ' + cli.pad(test['example'], (width * 0.6 -7)) + '\n' + - ' expected' + cli.pad(JSON.stringify(test['expected'], undefined, 2).replace(/\n/g, ''), width-8) + '\n' + - ' result ' + cli.pad(JSON.stringify(test['result'], undefined, 2).replace(/\n/g, ''), width-8) + '\n' + - ' '; - - if (err) { - cli.error(testline + ''); - cli.error(err); - } else { - cli.ok(' ' + testline + ''); - } + // cli.spinner('Working..'); + var processed = 0; + names.forEach(function(name) { + PhpjsUtil.load(name, function (err, params) { + if (err) { + return cli.fatal(err); + } + + if (params['headKeys']['test'] && params['headKeys']['test'][0] === 'skip') { + return cli.ok('Skipped ' + params['name']); + } + + PhpjsUtil.test(params, function(err, test, params) { + var testline = cli.pad(params['name'] + '#' + test['number'], (width * 0.4), ' ', 'right'); + testline += ' ' + cli.pad(test['example'], (width * 0.6 -7)); + + if (err) { + if ('expected' in test) { + testline += '\n expected' + cli.pad(JSON.stringify(test['expected'], undefined, 2).replace(/\n/g, ''), width - 8); + } else { + testline += '\n expected' + cli.pad('undefined', width - 8); + } + if ('result' in test) { + testline += '\n result ' + cli.pad(JSON.stringify(test['result'], undefined, 2).replace(/\n/g, ''), width - 8); + } else { + testline += '\n result ' + cli.pad('undefined', width - 8); + } + cli.error(testline + ''); + // cli.error(err); + } else { + cli.ok(' ' + testline + ''); + } + + if (++processed === names.length) { + cli.spinner('Working.. done!', true); //End the spinner + } + }); + }); }); }); - - // PhpjsUtil.load('') - // PhpjsUtil.parse(options.name, code, - }); diff --git a/tests/phpjsutil.js b/tests/phpjsutil.js index 8e05eb1d..6e5ac152 100644 --- a/tests/phpjsutil.js +++ b/tests/phpjsutil.js @@ -58,7 +58,7 @@ PhpjsUtil.prototype._headKeys = function(headLines) { if ((dmatch = key.match(/^(\w+)\s+(\d+)$/))) { // Things like examples and notes can be grouped key = dmatch[1]; - num = dmatch[2]-1; + num = dmatch[2] - 1; if (!keys[key]) { keys[key] = []; @@ -89,32 +89,19 @@ PhpjsUtil.prototype.contains = function (array, value) { }; PhpjsUtil.prototype._loadDependencies = function(name, headKeys, dependencies, cb) { - var self = this; - var functions = headKeys['depends on'] || []; - - var j; - for (j in self.injectDependencies) { - var injectFunction = self.injectDependencies[j]; - if (self.contains(self.injectDependencies, name)) { - continue; - } - - // console.log({injectFunction: injectFunction}); - functions.push(injectFunction); - } + var self = this; - if (!functions || !functions.length) { + if (!headKeys['depends on'] || !headKeys['depends on'].length) { if (cb) { cb(null, {}); } } - // console.log({functions: functions, headKeys: headKeys, dependencies: dependencies}); var i; var name; var loaded = 0; - for (i in functions) { - name = functions[i]; + for (i in headKeys['depends on']) { + name = headKeys['depends on'][i]; self.load(name, function (err, params) { if (err) { @@ -124,8 +111,7 @@ PhpjsUtil.prototype._loadDependencies = function(name, headKeys, dependencies, c dependencies[name] = params; self._loadDependencies(name, params.headKeys, dependencies); - loaded++; - if (cb && loaded === functions.length) { + if (cb && ++loaded === headKeys['depends on'].length) { cb(null, dependencies); } }); @@ -163,6 +149,26 @@ PhpjsUtil.prototype.opener = function(name, cb) { return cb('Please override with a method that can translate a function-name to code in your environment'); }; +PhpjsUtil.prototype.loadMultiple = function(names, cb) { + var self = this; + var paramsMultiple = {}; + var loaded = 0; + for (var i in names) { + var name = names[i]; + self.load(name, function (err, params) { + if (err) { + return cb(err); + } + + paramsMultiple[params['name']] = params; + + if (++loaded === names.length) { + return cb(null, paramsMultiple); + } + }); + } +}; + PhpjsUtil.prototype.load = function(name, cb) { var self = this; self.opener(name, function (err, code) { @@ -180,63 +186,118 @@ PhpjsUtil.prototype.load = function(name, cb) { }); }; -PhpjsUtil.prototype.test = function(params, cb) { - var i = 0; - var j = 0; - var d = 0; - var self = this; - +PhpjsUtil.prototype.unique = function(array) { + var a = array.concat(); - var codes = []; - // Push own code onto stack - codes.push(params['code']); - // Push dependencies onto stack - for (d in params['dependencies']) { - codes.push(params['dependencies'][d]['code']); + for(var i = 0; i < a.length; ++i) { + for(var j = i + 1; j < a.length; ++j) { + if(a[i] === a[j]) { + a.splice(j--, 1); + } + } } - console.log({codes: codes}); - // Reverse stack so dependencies are loaded first - codes = codes.reverse(); + return a; +}; - // console.log({params: params}); +PhpjsUtil.prototype.getRecursiveCode = function(params) { + var self = this; + var codez = []; - // Load code - eval(codes.join('\n')); + if ('name' in params) { + codez.push(params['code']); + for (var d in params['dependencies']) { + codez = codez.concat(self.getRecursiveCode(params['dependencies'][d])); + } + } + codez = codez.reverse(); - // Run each example - for (i in params['headKeys']['example']) { - var test = { - example: params['headKeys']['example'][i].join('\n'), - number : i - }; + return codez; +}; - if (!params['headKeys']['returns'][i] || !params['headKeys']['returns'][i].length) { - cb('There is no return for example ' + i, test, params); - continue; - } +PhpjsUtil.prototype.test = function(params, cb) { + var self = this; + var codez = []; - // Needs an eval so types are cast properly, also, expected may - // contain code - eval('test.expected = ' + params['headKeys']['returns'][i].join('\n') + ''); - // Let's do something evil. Execute line by line (see date.js why) - for (j in params['headKeys']['example'][i]) { - eval('test.result = ' + params['headKeys']['example'][i][j] + ''); + self.loadMultiple(['ini_set', 'ini_get'], function(err, paramsMultiple) { + for (var name in paramsMultiple) { + codez.unshift(paramsMultiple[name]['code']); } - var jsonExpected = JSON.stringify(test.expected, undefined, 2); - var jsonResult = JSON.stringify(test.result, undefined, 2); + var extracted = self.getRecursiveCode(params); + codez = codez.concat(codez, extracted); + + codez.unshift('' + + 'XMLHttpRequest = {};' + + 'window = {' + + 'document: {' + + 'lastModified: 1388954399,' + + 'getElementsByTagName: function(){return [];}' + + '},' + + 'location: {' + + 'href: ""' + + '}' + + '};' + + ''); + + // console.log(params); + console.log(params['name']); + + // Load code + eval( + codez.join(';\n') + .replace(/that\.([a-z_])/g, '$1') + .replace(/this\.([a-z_])/g, '$1') + .replace(/window\.setTimeout/g, 'setTimeout') + ); + + // this. refers to phpjs + // that. refers to phpjs + // self. refers to own function + + + // Run each example + for (var i in params['headKeys']['example']) { + var test = { + example: params['headKeys']['example'][i].join('\n'), + number : i + }; + + if (!params['headKeys']['returns'][i] || !params['headKeys']['returns'][i].length) { + cb('There is no return for example ' + i, test, params); + continue; + } + + + // Needs an eval so types are cast properly, also, expected may + // contain code + eval('test.expected = ' + params['headKeys']['returns'][i].join('\n') + ''); + + // Let's do something evil. Execute line by line (see date.js why) + // We need test.reslult be the last result of the example code + for (var j in params['headKeys']['example'][i]) { + // console.log(params['headKeys']['example'][i]); + if (+j === params['headKeys']['example'][i].length-1) { + eval('test.result = ' + params['headKeys']['example'][i][j] + ''); + } else { + eval(params['headKeys']['example'][i][j] + ''); + } + } + + var jsonExpected = JSON.stringify(test.expected, undefined, 2); + var jsonResult = JSON.stringify(test.result, undefined, 2); - if (jsonExpected !== jsonResult) { - var err = 'Expected: ' + jsonExpected + - ' but returned: ' + jsonResult; - cb(err, test, params); + if (jsonExpected !== jsonResult) { + err = 'Expected: ' + jsonExpected + + ' but returned: ' + jsonResult; + cb(err, test, params); + continue; + } + + cb(null, test, params); continue; } - - cb(null, test, params); - continue; - } + }); }; From 5ac061e76c224218122d258623e3c44a6fbe6b9d Mon Sep 17 00:00:00 2001 From: Kevin van Zonneveld Date: Sun, 5 Jan 2014 23:24:31 +0100 Subject: [PATCH 4/7] Decent output --- functions/math/lcg_value.js | 3 ++ functions/strings/explode.js | 4 +++ tests/cli.js | 53 +++++++++++++++++++----------------- tests/phpjsutil.js | 13 ++++----- 4 files changed, 41 insertions(+), 32 deletions(-) diff --git a/functions/math/lcg_value.js b/functions/math/lcg_value.js index 57ff12fe..0293bd40 100644 --- a/functions/math/lcg_value.js +++ b/functions/math/lcg_value.js @@ -1,5 +1,8 @@ function lcg_value () { // From: http://phpjs.org/functions // + original by: Onno Marsman + // * example 1: lcg_value() + // * returns 1: 1 + return Math.random(); } diff --git a/functions/strings/explode.js b/functions/strings/explode.js index 66674f9d..2af18649 100644 --- a/functions/strings/explode.js +++ b/functions/strings/explode.js @@ -1,4 +1,8 @@ function explode (delimiter, string, limit) { + // From: http://phpjs.org/functions + // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // * example 1: explode(' ', 'Kevin van Zonneveld'); + // * returns 1: {0: 'Kevin', 1: 'van', 2: 'Zonneveld'} if ( arguments.length < 2 || typeof delimiter === 'undefined' || typeof string === 'undefined' ) return null; if ( delimiter === '' || delimiter === false || delimiter === null) return false; diff --git a/tests/cli.js b/tests/cli.js index d8af0cd1..b3a0e518 100644 --- a/tests/cli.js +++ b/tests/cli.js @@ -31,9 +31,11 @@ PhpjsUtil.opener = function (name, cb) { }); }; +// --debug works out of the box. See -h cli.parse({ name: ['name', 'Function name to test', 'path', '*'], - category: ['c', 'Category to test', 'path', '*'] + category: ['c', 'Category to test', 'path', '*'], + abort: ['a', 'Abort on first failure'] }); cli.pad = function(str, pad, chr, dir) { @@ -55,8 +57,18 @@ cli.pad = function(str, pad, chr, dir) { var width = 120; cli.main(function(args, options) { + var self = this; var globpath = __dirname + '/../functions/' + options.category + '/' + options.name + '.js'; + process.on('exit', function (){ + var msg = self.pass_cnt + ' passed / ' + self.fail_cnt + ' failed / ' + self.skip_cnt + ' skipped'; + if (self.fail_cnt) { + cli.fatal(msg); + } else { + cli.ok(msg); + } + }); + glob(globpath, {}, function (err, files) { var names = []; for (var i in files) { @@ -66,8 +78,10 @@ cli.main(function(args, options) { } } - // cli.spinner('Working..'); - var processed = 0; + self.pass_cnt = 0; + self.fail_cnt = 0; + self.skip_cnt = 0; + names.forEach(function(name) { PhpjsUtil.load(name, function (err, params) { if (err) { @@ -75,32 +89,21 @@ cli.main(function(args, options) { } if (params['headKeys']['test'] && params['headKeys']['test'][0] === 'skip') { - return cli.ok('Skipped ' + params['name']); + self.skip_cnt++; + return cli.info('--> ' + params['name'] + ' skipped as instructed. '); } PhpjsUtil.test(params, function(err, test, params) { - var testline = cli.pad(params['name'] + '#' + test['number'], (width * 0.4), ' ', 'right'); - testline += ' ' + cli.pad(test['example'], (width * 0.6 -7)); - - if (err) { - if ('expected' in test) { - testline += '\n expected' + cli.pad(JSON.stringify(test['expected'], undefined, 2).replace(/\n/g, ''), width - 8); - } else { - testline += '\n expected' + cli.pad('undefined', width - 8); - } - if ('result' in test) { - testline += '\n result ' + cli.pad(JSON.stringify(test['result'], undefined, 2).replace(/\n/g, ''), width - 8); - } else { - testline += '\n result ' + cli.pad('undefined', width - 8); - } - cli.error(testline + ''); - // cli.error(err); + if (!err) { + self.pass_cnt++; + cli.debug('--> ' + params['name'] + '#' + test['number'] + ' passed. '); } else { - cli.ok(' ' + testline + ''); - } - - if (++processed === names.length) { - cli.spinner('Working.. done!', true); //End the spinner + self.fail_cnt++; + cli.error('--> ' + params['name'] + '#' + test['number'] + ' failed. '); + cli.error(err); + if (options.abort) { + cli.fatal('Aborting on first failure as instructed. '); + } } }); }); diff --git a/tests/phpjsutil.js b/tests/phpjsutil.js index 6e5ac152..5cfc712b 100644 --- a/tests/phpjsutil.js +++ b/tests/phpjsutil.js @@ -6,6 +6,9 @@ if (typeof require !== 'undefined') { } function PhpjsUtil(config) { + this.injectDependencies = []; + + // Overwrite properties with config for (var k in config) { this[k] = config[k]; } @@ -221,7 +224,7 @@ PhpjsUtil.prototype.test = function(params, cb) { var codez = []; - self.loadMultiple(['ini_set', 'ini_get'], function(err, paramsMultiple) { + self.loadMultiple(self.injectDependencies, function(err, paramsMultiple) { for (var name in paramsMultiple) { codez.unshift(paramsMultiple[name]['code']); } @@ -242,9 +245,6 @@ PhpjsUtil.prototype.test = function(params, cb) { '};' + ''); - // console.log(params); - console.log(params['name']); - // Load code eval( codez.join(';\n') @@ -278,7 +278,6 @@ PhpjsUtil.prototype.test = function(params, cb) { // Let's do something evil. Execute line by line (see date.js why) // We need test.reslult be the last result of the example code for (var j in params['headKeys']['example'][i]) { - // console.log(params['headKeys']['example'][i]); if (+j === params['headKeys']['example'][i].length-1) { eval('test.result = ' + params['headKeys']['example'][i][j] + ''); } else { @@ -290,8 +289,8 @@ PhpjsUtil.prototype.test = function(params, cb) { var jsonResult = JSON.stringify(test.result, undefined, 2); if (jsonExpected !== jsonResult) { - err = 'Expected: ' + jsonExpected + - ' but returned: ' + jsonResult; + err = 'expected: \n' + jsonExpected + '\n\n' + + 'returned: \n' + jsonResult + '\n'; cb(err, test, params); continue; } From b1988b19673d9834893689484a5759054130df05 Mon Sep 17 00:00:00 2001 From: Kevin van Zonneveld Date: Sun, 5 Jan 2014 23:27:21 +0100 Subject: [PATCH 5/7] Add travis --- .travis.yml | 7 +++++++ tests/cli.js | 8 ++++---- 2 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..529ef7b5 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,7 @@ +language: node_js +node_js: + - "0.8" +before_install: + - sudo apt-get update -qq + - sudo apt-get install -qq php5-cli +script: make test diff --git a/tests/cli.js b/tests/cli.js index b3a0e518..abd8fc77 100644 --- a/tests/cli.js +++ b/tests/cli.js @@ -57,7 +57,7 @@ cli.pad = function(str, pad, chr, dir) { var width = 120; cli.main(function(args, options) { - var self = this; + var self = this; var globpath = __dirname + '/../functions/' + options.category + '/' + options.name + '.js'; process.on('exit', function (){ @@ -78,9 +78,9 @@ cli.main(function(args, options) { } } - self.pass_cnt = 0; - self.fail_cnt = 0; - self.skip_cnt = 0; + self.pass_cnt = 0; + self.fail_cnt = 0; + self.skip_cnt = 0; names.forEach(function(name) { PhpjsUtil.load(name, function (err, params) { From 19e643be9b39dd6f7a8fce8d284f6cc4d61259da Mon Sep 17 00:00:00 2001 From: Kevin van Zonneveld Date: Sun, 5 Jan 2014 23:30:55 +0100 Subject: [PATCH 6/7] Update Makefile --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index b7135614..861ef316 100644 --- a/Makefile +++ b/Makefile @@ -5,8 +5,8 @@ setup: cd .. ; \ test: - cd tests && npm install - find functions -type f |grep -v '/_' |sed 's@\.js$$@@g' |awk -F/ '{print "node tests/cli.js -f "$$NF}' |bash + #node tests/cli.js --debug --abort # To abort at first failure + node tests/cli.js --debug site: git pull && \ From ca3039d34af50681404e6ef93915f94ff6c92cbe Mon Sep 17 00:00:00 2001 From: Kevin van Zonneveld Date: Sun, 5 Jan 2014 23:34:10 +0100 Subject: [PATCH 7/7] Update npms before running testsuite --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 861ef316..a91883f5 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,7 @@ setup: test: #node tests/cli.js --debug --abort # To abort at first failure + cd tests && npm install node tests/cli.js --debug site: