add lisp packages

This commit is contained in:
2020-12-05 21:29:49 +01:00
parent 85e20365ae
commit a6e2395755
7272 changed files with 1363243 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
## Tests
```
npm run serve
```
Open : http://localhost:8080/tests/index.html
Replace params in `config.json`.
```
npm test
```
To clear IE cache: `RunDll32.exe InetCpl.cpl,ClearMyTracksByProcess 255`

View File

@@ -0,0 +1,35 @@
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
class Async {
static $delay(timeout) {
return new Promise((resolve) => {
setTimeout(resolve, timeout);
});
}
static $yield() {
return new Promise((resolve) => {
// process.nextTick(resolve);
// setTimeout(resolve, 0);
setImmediate(resolve);
});
}
static async $await(callback, timeout = 0) {
const startTime = Date.now();
while (!callback()) {
await this.$yield();
if ((timeout > 0) && (Date.now() - startTime > timeout))
throw new Error('Timeout reached');
}
}
}
exports.Async = Async;
});

View File

@@ -0,0 +1,141 @@
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports", "selenium-webdriver"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const $webdriver = require("selenium-webdriver");
class Driver {
static get CHROME() {
return 'chrome';
}
;
static get FIREFOX() {
return 'firefox';
}
;
static get OPERA() {
return 'opera';
}
;
static get IE() {
return 'ie';
}
;
static get EDGE() {
return 'edge';
}
;
static create(browserName, remoteUrl) {
let capabilities = null;
switch (browserName) {
case this.CHROME:
capabilities = $webdriver.Capabilities.chrome();
break;
case this.IE:
capabilities = $webdriver.Capabilities.ie();
break;
case this.FIREFOX:
capabilities = $webdriver.Capabilities.firefox();
break;
case this.OPERA:
capabilities = $webdriver.Capabilities.opera();
break;
case this.EDGE:
capabilities = $webdriver.Capabilities.edge();
break;
default:
throw new Error(`Can't find browswer name ${browserName}`);
}
let builder = new $webdriver.Builder();
if (remoteUrl !== void 0) {
builder = builder.usingServer(remoteUrl);
}
return new Driver(builder
.withCapabilities(capabilities)
.build());
}
constructor(driver) {
this.driver = driver;
}
/**
* Executes an async script in the browser. Provides 2 function:
* - resolve
* - reject
* @param {string} script
* @return {Promise<void>}
*/
executeAsyncScript(script) {
// return this.driver.executeAsyncScript('arguments[arguments.length - 1]()');
return this.driver.executeAsyncScript(`
var __done = arguments[arguments.length - 1];
var resolve = function(data) {
if(__done) __done({ success : true, data: data });
__done = null;
};
var reject = function(error) {
if(error instanceof Error) {
var type = error.constructor.name || (/^\\s*function\\s+([^\\(\\s]*)\\s*/).exec(error.constructor.toString())[1]
error = { type: type, name: error.name || '', message: error.message || '', stack: error.stack || '' };
}
if(__done) __done({ success : false, _error: error });
__done = null;
};
try {
${script}
} catch(error) {
reject(error);
}
`).then((data) => {
if (data.success) {
return data.data;
}
else {
let error = data._error;
if (typeof error === 'object') {
const type = (error.type in global) ? global[error.type] : Error;
const _error = new type(error.message || '');
if (error.name && (error.name !== _error.name))
_error.name = error.name;
// if(error.stack) _error.stack = error.stack;
_error.stack = error.stack || `${error.name}: ${error.message}\n\tempty stack`;
error = _error;
}
throw error;
}
});
}
/**
* Executes a script in the browser.
* Can return a value with 'return'
* @param {string} script
* @return {Promise<void>}
*/
executeScript(script) {
return this.executeAsyncScript(`resolve(
(function() {
${script}
})()
);`);
}
navigate(url) {
return this.driver.navigate().to(url);
}
ngNavigate(path) {
return this.driver.executeScript(`return window.router.navigate(${JSON.stringify(path)});`);
}
quit() {
return this.driver.quit();
}
}
exports.Driver = Driver;
});

View File

@@ -0,0 +1,56 @@
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports", "./Driver"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Driver_1 = require("./Driver");
class Tester {
constructor(remoteUrl) {
this.remoteUrl = remoteUrl;
}
runForMany(browsers, callback) {
return Promise.all(browsers.map((browser) => this.runFor(browser, callback))).then(() => {
});
}
runFor(browser, callback) {
const driver = Driver_1.Driver.create(browser, this.remoteUrl);
return new Promise((resolve) => {
resolve(callback(driver));
})
.then(() => {
return driver.quit();
}, (error) => {
return Promise.race([
driver.quit(),
new Promise((resolve) => setTimeout(resolve, 2000))
]).then(() => Promise.reject(error));
});
}
test(testName, callback) {
return new Promise((resolve, reject) => {
this.log(`Starting test '${testName}'`, 33);
resolve(callback());
})
.then(() => {
this.log(`test '${testName}' succeed`, 32);
}, (error) => {
this.log(`test '${testName}' failed`, 31);
console.log(error);
throw error;
});
}
log(content, color) {
console.log(this.colorString(content, color));
}
colorString(content, color = 0) {
return `\x1b[${color}m${content}\x1b[0m`;
}
}
exports.Tester = Tester;
});

View File

@@ -0,0 +1,4 @@
{
"testServer": "http://192.168.0.128:4444/wd/hub",
"testHost": "http://192.168.0.130:9876/tests/"
}

View File

@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Tests</title>
<script type="text/javascript">
['url-polyfill'].forEach(function(fileName) {
var script = document.createElement('script');
script.src = '../' + fileName + '.js?timeout=' + Math.random().toString();
document.head.appendChild(script);
});
</script>
</head>
<body>
Test executing...
</body>
</html>

View File

@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Tests</title>
<!--<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.3/require.min.js"></script>-->
<script type="text/javascript">
var script = document.createElement('script');
exports = {};
script.src = 'url-class-test.js?timeout=' + Math.random().toString();
document.head.appendChild(script);
</script>
</head>
<body>
Test executing...
</body>
</html>

View File

@@ -0,0 +1,35 @@
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports", "../do-not-use/url"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const originalURL = window.URL;
const url_1 = require("../do-not-use/url");
const test = () => {
let a = new originalURL('?fr=yset_ie_syc_oracle&type=orcl_hpset#page0', 'https://username:password@www.yahoo.com:80/path');
let b = new url_1.URL('?fr=yset_ie_syc_oracle&type=orcl_hpset#page0', 'https://username:password@www.yahoo.com:80/path');
// let b = new URL('https://username:password@www.yahoo.com:80/path?fr=yset_ie_syc_oracle&type=orcl_hpset#page0', '');
window.a = a;
window.b = b;
// 'a+"*ç%&/()=?±“#Ç[]|{}≠b'
for (let key in a) {
let value = a[key];
switch (typeof value) {
case 'boolean':
case 'number':
case 'string':
if (value !== b[key]) {
throw new Error('Values mismatch for key "' + key + '" : \n' + value + '\n' + b[key]);
}
break;
}
}
};
test();
});

View File

@@ -0,0 +1,157 @@
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports", "./classes/Driver", "./classes/Async", "./classes/Tester"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Driver_1 = require("./classes/Driver");
const Async_1 = require("./classes/Async");
const Tester_1 = require("./classes/Tester");
(function example() {
const config = require('./config.json');
const tester = new Tester_1.Tester(config.testServer);
return tester.runForMany([
Driver_1.Driver.EDGE,
Driver_1.Driver.CHROME,
// Driver.FIREFOX,
// Driver.OPERA,
Driver_1.Driver.IE
], async (driver) => {
await driver.driver.manage().setTimeouts({
pageLoad: 300000,
script: 300000,
});
await driver.navigate(config.testHost);
await Async_1.Async.$delay(500);
await tester.test('Test URL', () => {
return driver.executeScript(`
var url = new URL('https://www.yahoo.com:80/?fr=yset_ie_syc_oracle&type=orcl_hpset#page0');
if(url.hash !== '#page0') throw new Error('Invalid hash : ' + url.hash);
if(url.host !== 'www.yahoo.com:80') throw new Error('Invalid host : ' + url.host);
if(url.hostname !== 'www.yahoo.com') throw new Error('Invalid hostname : ' + url.hostname);
if(url.href !== 'https://www.yahoo.com:80/?fr=yset_ie_syc_oracle&type=orcl_hpset#page0') throw new Error('Invalid href : ' + url.href);
if(url.origin !== 'https://www.yahoo.com:80') throw new Error('Invalid origin : ' + url.origin);
if(url.pathname !== '/') throw new Error('Invalid pathname : ' + url.pathname);
if(url.port !== '80') throw new Error('Invalid port : ' + url.port);
if(url.protocol !== 'https:') throw new Error('Invalid protocol : ' + url.protocol);
if(url.search !== '?fr=yset_ie_syc_oracle&type=orcl_hpset') throw new Error('Invalid search : ' + url.search);
url.searchParams.append('page', 1);
if(url.search !== '?fr=yset_ie_syc_oracle&type=orcl_hpset&page=1') throw new Error('Invalid search (append page 1) : ' + url.search);
url.searchParams.delete('type');
if(url.search !== '?fr=yset_ie_syc_oracle&page=1') throw new Error('Invalid search (delete type) : ' + url.search);
return url;
`);
});
await tester.test('Test URLSearchParams', () => {
return driver.executeScript(`
var url = new URL('http://localhost/?a=b');
if(url.searchParams !== url.searchParams) throw new Error('Expects url.searchParams === url.searchParams');
url.search = 'c=b';
if(url.searchParams.toString() !== 'c=b') throw new Error('Expects url.searchParams.toString() === c=b');
url.searchParams.append('d', 'e');
if(url.search !== '?c=b&d=e') throw new Error('Expects url.search === ?c=b&d=e');
return url;
`);
});
await tester.test('Test URLSearchParams special char encoding/decoding', () => {
return driver.executeScript(`
if(new URLSearchParams('a=2018-12-19T09:14:35%2B09:00').get('a') !== '2018-12-19T09:14:35+09:00') {
throw new Error('a=2018-12-19T09:14:35%2B09:00 failed');
}
if(new URLSearchParams('a=one+two').get('a') !== 'one two') {
throw new Error('a=one+two failed');
}
`);
});
await tester.test('Test URLSearchParams constructor', () => {
return driver.executeScript(`
var a = new URLSearchParams('b=1&a=2&c=3');
if(a.toString() !== 'b=1&a=2&c=3') throw new Error('Invalid constructor with new URLSearchParams(\\'b=1&a=2&c=3\\')');
var b = new URLSearchParams(a);
if(b.toString() !== 'b=1&a=2&c=3') throw new Error('Invalid constructor with new URLSearchParams(new URLSearchParams(\\'b=1&a=2&c=3\\'))');
var c = new URLSearchParams([['b', 1], ['a', 2], ['c', 3]]);
if(c.toString() !== 'b=1&a=2&c=3') throw new Error('Invalid constructor with new URLSearchParams([[\\'b\\', 1], [\\'a\\', 2], [\\'c\\', 3]])');
var d = new URLSearchParams({ 'b': 1, 'a': 2, 'c': 3 });
if(d.toString() !== 'b=1&a=2&c=3') throw new Error('Invalid constructor with new URLSearchParams({ \\'b\\': 1, \\'a\\': 2, \\'c\\': 3 })');
`);
});
await tester.test('Test URLSearchParams.sort', () => {
return driver.executeScript(`
var a = new URLSearchParams('b=1&a=2&c=3');
a.sort();
if(a.toString() !== 'a=2&b=1&c=3') throw new Error('Expects searchParams.sort().toString() === a=2&b=1&c=3');
`);
});
await tester.test('Test URL with base', () => {
return driver.executeScript(`
var url = new URL('test', 'http://www.example.com/base');
if(url.host !== 'www.example.com') throw new Error('Invalid host : ' + url.host);
if(url.hostname !== 'www.example.com') throw new Error('Invalid hostname : ' + url.hostname);
if(url.href !== 'http://www.example.com/test') throw new Error('Invalid href : ' + url.href);
if(url.pathname !== '/test') throw new Error('Invalid pathname : ' + url.pathname);
if(url.protocol !== 'http:') throw new Error('Invalid protocol : ' + url.protocol);
if(url.search !== '') throw new Error('Invalid search : ' + url.search);
return url;
`);
});
await tester.test('Test pathname variations', () => {
return driver.executeScript(`
var url = new URL('test/long/path.html', 'http://www.example.com');
if(url.pathname !== '/test/long/path.html') throw new Error('Invalid pathname : ' + url.pathname);
url.pathname = 'a/b 1'
if(url.pathname !== '/a/b%201') throw new Error('Invalid pathname : ' + url.pathname);
return url;
`);
});
await tester.test('Ensure url.href does\'nt finish with ? if url.search is empty', () => {
return driver.executeScript(`
var url = new URL('https://www.example.com/');
url.searchParams.delete('foo');
if(url.toString() !== 'https://www.example.com/') throw new Error('Invalid url : ' + url.toString());
`);
});
await tester.test('URL SearchParams should have spaces encoded as "+"', () => {
return driver.executeScript(`
var url = new URL('https://www.example.com/');
url.searchParams.set('foo', 'value with spaces');
if(url.toString() !== 'https://www.example.com/?foo=value+with+spaces') throw new Error('Invalid url : ' + url.toString());
var url = new URL('https://www.example.com/?foo=another+value+with+spaces');
var fooParam = url.searchParams.get('foo');
if(fooParam !== 'another value with spaces') throw new Error('Invalid "foo" param value : ' + fooParam);
`);
});
await tester.test('Url Protocol should control the visibility of port in origin', () => {
return driver.executeScript(`
var url = new URL('https://www.example.com:443'); // No port for https on 443
var url2 = new URL('http://www.example.com:8080'); // Port for http on 8080
var url3 = new URL('https://www.example.com:80'); // port for https on 80
if (url.origin !== 'https://www.example.com') throw new Error('Origin value is not correct ' + url.origin);
if (url2.origin !== 'http://www.example.com:8080') throw new Error('Origin value is not correct ' + url2.origin);
if (url3.origin !== 'https://www.example.com:80') throw new Error('Origin value is not correct ' + url3.origin);
`);
});
});
})().catch(_ => console.log('ERROR: ', _));
});

View File

@@ -0,0 +1,618 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
(function(scope) {
'use strict';
// feature detect for URL constructor
var hasWorkingUrl = false;
if (!scope.forceJURL) {
try {
var u = new URL('b', 'http://a');
u.pathname = 'c%20d';
hasWorkingUrl = u.href === 'http://a/c%20d';
} catch(e) {}
}
if (hasWorkingUrl)
return;
var relative = Object.create(null);
relative['ftp'] = 21;
relative['file'] = 0;
relative['gopher'] = 70;
relative['http'] = 80;
relative['https'] = 443;
relative['ws'] = 80;
relative['wss'] = 443;
var relativePathDotMapping = Object.create(null);
relativePathDotMapping['%2e'] = '.';
relativePathDotMapping['.%2e'] = '..';
relativePathDotMapping['%2e.'] = '..';
relativePathDotMapping['%2e%2e'] = '..';
function isRelativeScheme(scheme) {
return relative[scheme] !== undefined;
}
function invalid() {
clear.call(this);
this._isInvalid = true;
}
function IDNAToASCII(h) {
if ('' == h) {
invalid.call(this)
}
// XXX
return h.toLowerCase()
}
function percentEscape(c) {
var unicode = c.charCodeAt(0);
if (unicode > 0x20 &&
unicode < 0x7F &&
// " # < > ? `
[0x22, 0x23, 0x3C, 0x3E, 0x3F, 0x60].indexOf(unicode) == -1
) {
return c;
}
return encodeURIComponent(c);
}
function percentEscapeQuery(c) {
// XXX This actually needs to encode c using encoding and then
// convert the bytes one-by-one.
var unicode = c.charCodeAt(0);
if (unicode > 0x20 &&
unicode < 0x7F &&
// " # < > ` (do not escape '?')
[0x22, 0x23, 0x3C, 0x3E, 0x60].indexOf(unicode) == -1
) {
return c;
}
return encodeURIComponent(c);
}
var EOF = undefined,
ALPHA = /[a-zA-Z]/,
ALPHANUMERIC = /[a-zA-Z0-9\+\-\.]/;
function parse(input, stateOverride, base) {
function err(message) {
errors.push(message)
}
var state = stateOverride || 'scheme start',
cursor = 0,
buffer = '',
seenAt = false,
seenBracket = false,
errors = [];
loop: while ((input[cursor - 1] != EOF || cursor == 0) && !this._isInvalid) {
var c = input[cursor];
switch (state) {
case 'scheme start':
if (c && ALPHA.test(c)) {
buffer += c.toLowerCase(); // ASCII-safe
state = 'scheme';
} else if (!stateOverride) {
buffer = '';
state = 'no scheme';
continue;
} else {
err('Invalid scheme.');
break loop;
}
break;
case 'scheme':
if (c && ALPHANUMERIC.test(c)) {
buffer += c.toLowerCase(); // ASCII-safe
} else if (':' == c) {
this._scheme = buffer;
buffer = '';
if (stateOverride) {
break loop;
}
if (isRelativeScheme(this._scheme)) {
this._isRelative = true;
}
if ('file' == this._scheme) {
state = 'relative';
} else if (this._isRelative && base && base._scheme == this._scheme) {
state = 'relative or authority';
} else if (this._isRelative) {
state = 'authority first slash';
} else {
state = 'scheme data';
}
} else if (!stateOverride) {
buffer = '';
cursor = 0;
state = 'no scheme';
continue;
} else if (EOF == c) {
break loop;
} else {
err('Code point not allowed in scheme: ' + c)
break loop;
}
break;
case 'scheme data':
if ('?' == c) {
query = '?';
state = 'query';
} else if ('#' == c) {
this._fragment = '#';
state = 'fragment';
} else {
// XXX error handling
if (EOF != c && '\t' != c && '\n' != c && '\r' != c) {
this._schemeData += percentEscape(c);
}
}
break;
case 'no scheme':
if (!base || !(isRelativeScheme(base._scheme))) {
err('Missing scheme.');
invalid.call(this);
} else {
state = 'relative';
continue;
}
break;
case 'relative or authority':
if ('/' == c && '/' == input[cursor+1]) {
state = 'authority ignore slashes';
} else {
err('Expected /, got: ' + c);
state = 'relative';
continue
}
break;
case 'relative':
this._isRelative = true;
if ('file' != this._scheme)
this._scheme = base._scheme;
if (EOF == c) {
this._host = base._host;
this._port = base._port;
this._path = base._path.slice();
this._query = base._query;
this._username = base._username;
this._password = base._password;
break loop;
} else if ('/' == c || '\\' == c) {
if ('\\' == c)
err('\\ is an invalid code point.');
state = 'relative slash';
} else if ('?' == c) {
this._host = base._host;
this._port = base._port;
this._path = base._path.slice();
this._query = '?';
this._username = base._username;
this._password = base._password;
state = 'query';
} else if ('#' == c) {
this._host = base._host;
this._port = base._port;
this._path = base._path.slice();
this._query = base._query;
this._fragment = '#';
this._username = base._username;
this._password = base._password;
state = 'fragment';
} else {
var nextC = input[cursor+1]
var nextNextC = input[cursor+2]
if (
'file' != this._scheme || !ALPHA.test(c) ||
(nextC != ':' && nextC != '|') ||
(EOF != nextNextC && '/' != nextNextC && '\\' != nextNextC && '?' != nextNextC && '#' != nextNextC)) {
this._host = base._host;
this._port = base._port;
this._username = base._username;
this._password = base._password;
this._path = base._path.slice();
this._path.pop();
}
state = 'relative path';
continue;
}
break;
case 'relative slash':
if ('/' == c || '\\' == c) {
if ('\\' == c) {
err('\\ is an invalid code point.');
}
if ('file' == this._scheme) {
state = 'file host';
} else {
state = 'authority ignore slashes';
}
} else {
if ('file' != this._scheme) {
this._host = base._host;
this._port = base._port;
this._username = base._username;
this._password = base._password;
}
state = 'relative path';
continue;
}
break;
case 'authority first slash':
if ('/' == c) {
state = 'authority second slash';
} else {
err("Expected '/', got: " + c);
state = 'authority ignore slashes';
continue;
}
break;
case 'authority second slash':
state = 'authority ignore slashes';
if ('/' != c) {
err("Expected '/', got: " + c);
continue;
}
break;
case 'authority ignore slashes':
if ('/' != c && '\\' != c) {
state = 'authority';
continue;
} else {
err('Expected authority, got: ' + c);
}
break;
case 'authority':
if ('@' == c) {
if (seenAt) {
err('@ already seen.');
buffer += '%40';
}
seenAt = true;
for (var i = 0; i < buffer.length; i++) {
var cp = buffer[i];
if ('\t' == cp || '\n' == cp || '\r' == cp) {
err('Invalid whitespace in authority.');
continue;
}
// XXX check URL code points
if (':' == cp && null === this._password) {
this._password = '';
continue;
}
var tempC = percentEscape(cp);
(null !== this._password) ? this._password += tempC : this._username += tempC;
}
buffer = '';
} else if (EOF == c || '/' == c || '\\' == c || '?' == c || '#' == c) {
cursor -= buffer.length;
buffer = '';
state = 'host';
continue;
} else {
buffer += c;
}
break;
case 'file host':
if (EOF == c || '/' == c || '\\' == c || '?' == c || '#' == c) {
if (buffer.length == 2 && ALPHA.test(buffer[0]) && (buffer[1] == ':' || buffer[1] == '|')) {
state = 'relative path';
} else if (buffer.length == 0) {
state = 'relative path start';
} else {
this._host = IDNAToASCII.call(this, buffer);
buffer = '';
state = 'relative path start';
}
continue;
} else if ('\t' == c || '\n' == c || '\r' == c) {
err('Invalid whitespace in file host.');
} else {
buffer += c;
}
break;
case 'host':
case 'hostname':
if (':' == c && !seenBracket) {
// XXX host parsing
this._host = IDNAToASCII.call(this, buffer);
buffer = '';
state = 'port';
if ('hostname' == stateOverride) {
break loop;
}
} else if (EOF == c || '/' == c || '\\' == c || '?' == c || '#' == c) {
this._host = IDNAToASCII.call(this, buffer);
buffer = '';
state = 'relative path start';
if (stateOverride) {
break loop;
}
continue;
} else if ('\t' != c && '\n' != c && '\r' != c) {
if ('[' == c) {
seenBracket = true;
} else if (']' == c) {
seenBracket = false;
}
buffer += c;
} else {
err('Invalid code point in host/hostname: ' + c);
}
break;
case 'port':
if (/[0-9]/.test(c)) {
buffer += c;
} else if (EOF == c || '/' == c || '\\' == c || '?' == c || '#' == c || stateOverride) {
if ('' != buffer) {
var temp = parseInt(buffer, 10);
if (temp != relative[this._scheme]) {
this._port = temp + '';
}
buffer = '';
}
if (stateOverride) {
break loop;
}
state = 'relative path start';
continue;
} else if ('\t' == c || '\n' == c || '\r' == c) {
err('Invalid code point in port: ' + c);
} else {
invalid.call(this);
}
break;
case 'relative path start':
if ('\\' == c)
err("'\\' not allowed in path.");
state = 'relative path';
if ('/' != c && '\\' != c) {
continue;
}
break;
case 'relative path':
if (EOF == c || '/' == c || '\\' == c || (!stateOverride && ('?' == c || '#' == c))) {
if ('\\' == c) {
err('\\ not allowed in relative path.');
}
var tmp;
if (tmp = relativePathDotMapping[buffer.toLowerCase()]) {
buffer = tmp;
}
if ('..' == buffer) {
this._path.pop();
if ('/' != c && '\\' != c) {
this._path.push('');
}
} else if ('.' == buffer && '/' != c && '\\' != c) {
this._path.push('');
} else if ('.' != buffer) {
if ('file' == this._scheme && this._path.length == 0 && buffer.length == 2 && ALPHA.test(buffer[0]) && buffer[1] == '|') {
buffer = buffer[0] + ':';
}
this._path.push(buffer);
}
buffer = '';
if ('?' == c) {
this._query = '?';
state = 'query';
} else if ('#' == c) {
this._fragment = '#';
state = 'fragment';
}
} else if ('\t' != c && '\n' != c && '\r' != c) {
buffer += percentEscape(c);
}
break;
case 'query':
if (!stateOverride && '#' == c) {
this._fragment = '#';
state = 'fragment';
} else if (EOF != c && '\t' != c && '\n' != c && '\r' != c) {
this._query += percentEscapeQuery(c);
}
break;
case 'fragment':
if (EOF != c && '\t' != c && '\n' != c && '\r' != c) {
this._fragment += c;
}
break;
}
cursor++;
}
}
function clear() {
this._scheme = '';
this._schemeData = '';
this._username = '';
this._password = null;
this._host = '';
this._port = '';
this._path = [];
this._query = '';
this._fragment = '';
this._isInvalid = false;
this._isRelative = false;
}
// Does not process domain names or IP addresses.
// Does not handle encoding for the query parameter.
function jURL(url, base /* , encoding */) {
if (base !== undefined && !(base instanceof jURL))
base = new jURL(String(base));
url = String(url)
this._url = url
clear.call(this);
var input = url.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g, '');
// encoding = encoding || 'utf-8'
parse.call(this, input, null, base);
}
jURL.prototype = {
toString: function() {
return this.href;
},
get href() {
if (this._isInvalid)
return this._url;
var authority = '';
if ('' != this._username || null != this._password) {
authority = this._username +
(null != this._password ? ':' + this._password : '') + '@';
}
return this.protocol +
(this._isRelative ? '//' + authority + this.host : '') +
this.pathname + this._query + this._fragment;
},
set href(href) {
clear.call(this);
parse.call(this, href);
},
get protocol() {
return this._scheme + ':';
},
set protocol(protocol) {
if (this._isInvalid)
return;
parse.call(this, protocol + ':', 'scheme start');
},
get host() {
return this._isInvalid ? '' : this._port ?
this._host + ':' + this._port : this._host;
},
set host(host) {
if (this._isInvalid || !this._isRelative)
return;
parse.call(this, host, 'host');
},
get hostname() {
return this._host;
},
set hostname(hostname) {
if (this._isInvalid || !this._isRelative)
return;
parse.call(this, hostname, 'hostname');
},
get port() {
return this._port;
},
set port(port) {
if (this._isInvalid || !this._isRelative)
return;
parse.call(this, port, 'port');
},
get pathname() {
return this._isInvalid ? '' : this._isRelative ?
'/' + this._path.join('/') : this._schemeData;
},
set pathname(pathname) {
if (this._isInvalid || !this._isRelative)
return;
this._path = [];
parse.call(this, pathname, 'relative path start');
},
get search() {
return this._isInvalid || !this._query || '?' == this._query ?
'' : this._query;
},
set search(search) {
if (this._isInvalid || !this._isRelative)
return;
this._query = '?';
if ('?' == search[0])
search = search.slice(1);
parse.call(this, search, 'query');
},
get hash() {
return this._isInvalid || !this._fragment || '#' == this._fragment ?
'' : this._fragment;
},
set hash(hash) {
if (this._isInvalid)
return;
this._fragment = '#';
if ('#' == hash[0])
hash = hash.slice(1);
parse.call(this, hash, 'fragment');
},
get origin() {
var host;
if (this._isInvalid || !this._scheme) {
return '';
}
// javascript: Gecko returns String(""), WebKit/Blink String("null")
// Gecko throws error for "data://"
// data: Gecko returns "", Blink returns "data://", WebKit returns "null"
// Gecko returns String("") for file: mailto:
// WebKit/Blink returns String("SCHEME://") for file: mailto:
switch (this._scheme) {
case 'data':
case 'file':
case 'javascript':
case 'mailto':
return 'null';
}
host = this.host;
if (!host) {
return '';
}
return this._scheme + '://' + host;
}
};
// Copy over the static methods
var OriginalURL = scope.URL;
if (OriginalURL) {
jURL.createObjectURL = function(blob) {
// IE extension allows a second optional options argument.
// http://msdn.microsoft.com/en-us/library/ie/hh772302(v=vs.85).aspx
return OriginalURL.createObjectURL.apply(OriginalURL, arguments);
};
jURL.revokeObjectURL = function(url) {
OriginalURL.revokeObjectURL(url);
};
}
scope.URL = jURL;
})(this);