5
									
								
								packages/ployfill/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								packages/ployfill/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
/node_modules
 | 
			
		||||
/dist
 | 
			
		||||
/package-lock.json
 | 
			
		||||
/yarn.lock
 | 
			
		||||
/docs
 | 
			
		||||
							
								
								
									
										22
									
								
								packages/ployfill/.npmignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								packages/ployfill/.npmignore
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
src
 | 
			
		||||
test
 | 
			
		||||
typings
 | 
			
		||||
bundled
 | 
			
		||||
build
 | 
			
		||||
coverage
 | 
			
		||||
docs
 | 
			
		||||
wiki
 | 
			
		||||
gulpfile.js
 | 
			
		||||
bower.json
 | 
			
		||||
karma.conf.js
 | 
			
		||||
tsconfig.json
 | 
			
		||||
typings.json
 | 
			
		||||
CONTRIBUTING.md
 | 
			
		||||
ISSUE_TEMPLATE.md
 | 
			
		||||
PULL_REQUEST_TEMPLATE.md
 | 
			
		||||
tslint.json
 | 
			
		||||
wallaby.js
 | 
			
		||||
.travis.yml
 | 
			
		||||
.gitignore
 | 
			
		||||
.vscode
 | 
			
		||||
type_definitions
 | 
			
		||||
							
								
								
									
										27
									
								
								packages/ployfill/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								packages/ployfill/package.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@ms/ployfill",
 | 
			
		||||
    "version": "0.1.0",
 | 
			
		||||
    "description": "MiaoScript ployfill package",
 | 
			
		||||
    "author": "MiaoWoo <admin@yumc.pw>",
 | 
			
		||||
    "homepage": "https://github.com/circlecloud/ms.git",
 | 
			
		||||
    "license": "ISC",
 | 
			
		||||
    "main": "dist/index.js",
 | 
			
		||||
    "types": "dist/index.d.ts",
 | 
			
		||||
    "publishConfig": {
 | 
			
		||||
        "registry": "https://repo.yumc.pw/repository/npm-hosted/"
 | 
			
		||||
    },
 | 
			
		||||
    "scripts": {
 | 
			
		||||
        "clean": "rimraf dist",
 | 
			
		||||
        "watch": "npx tsc --watch",
 | 
			
		||||
        "build": "yarn clean && npx tsc",
 | 
			
		||||
        "test": "echo \"Error: run tests from root\" && exit 1"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@ms/nashorn": "^0.1.0"
 | 
			
		||||
    },
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "reflect-metadata": "^0.1.13",
 | 
			
		||||
        "rimraf": "^3.0.0",
 | 
			
		||||
        "typescript": "^3.6.2"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								packages/ployfill/src/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								packages/ployfill/src/index.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
import { XMLHttpRequest as xhr } from './xml-http-request'
 | 
			
		||||
 | 
			
		||||
var XMLHttpRequest = xhr;
 | 
			
		||||
 | 
			
		||||
export {
 | 
			
		||||
    XMLHttpRequest
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										213
									
								
								packages/ployfill/src/xml-http-request.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										213
									
								
								packages/ployfill/src/xml-http-request.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,213 @@
 | 
			
		||||
import '@ms/nashorn'
 | 
			
		||||
 | 
			
		||||
const URL = Java.type("java.net.URL");
 | 
			
		||||
const Files = Java.type("java.nio.file.Files");
 | 
			
		||||
const StandardCopyOption = Java.type("java.nio.file.StandardCopyOption");
 | 
			
		||||
const JavaString = Java.type("java.lang.String");
 | 
			
		||||
const SecureRandom = Java.type("java.security.SecureRandom");
 | 
			
		||||
const SSLContext = Java.type("javax.net.ssl.SSLContext");
 | 
			
		||||
const HttpsURLConnection = Java.type("javax.net.ssl.HttpsURLConnection");
 | 
			
		||||
const HostnameVerifier = Java.type("javax.net.ssl.HostnameVerifier");
 | 
			
		||||
const X509TrustManager = Java.type("javax.net.ssl.X509TrustManager");
 | 
			
		||||
 | 
			
		||||
const SocketTimeoutException = Java.type('java.net.SocketTimeoutException');
 | 
			
		||||
 | 
			
		||||
const Callable = Java.type('java.util.concurrent.Callable');
 | 
			
		||||
const Executors = Java.type('java.util.concurrent.Executors')
 | 
			
		||||
 | 
			
		||||
const UTF_8 = "UTF-8"
 | 
			
		||||
 | 
			
		||||
const TrustAnyHostnameVerifier = new HostnameVerifier({ verify: () => true });
 | 
			
		||||
 | 
			
		||||
const SSLSocketFactory = function initSSLSocketFactory() {
 | 
			
		||||
    let sslContext = SSLContext.getInstance("TLS");
 | 
			
		||||
    sslContext.init(null, [new X509TrustManager({
 | 
			
		||||
        getAcceptedIssuers: () => null,
 | 
			
		||||
        checkClientTrusted: () => { },
 | 
			
		||||
        checkServerTrusted: () => { }
 | 
			
		||||
    })], new SecureRandom());
 | 
			
		||||
    return sslContext.getSocketFactory();
 | 
			
		||||
}();
 | 
			
		||||
 | 
			
		||||
interface Future<T> {
 | 
			
		||||
    cancel(): boolean;
 | 
			
		||||
    isCancelled(): boolean;
 | 
			
		||||
    isDone(): boolean;
 | 
			
		||||
    get(): T;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum ReadyState {
 | 
			
		||||
    UNSENT,//Client has been created. open() not called yet.
 | 
			
		||||
    OPENED,//open() has been called.
 | 
			
		||||
    HEADERS_RECEIVED,//send() has been called, and headers and status are available.
 | 
			
		||||
    LOADING,//Downloading; responseText holds partial data.
 | 
			
		||||
    DONE,//The operation is complete.
 | 
			
		||||
}
 | 
			
		||||
type RequestMethod = 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'CONNECT' | 'OPTIONS' | 'TRACE' | 'PATCH';
 | 
			
		||||
type ResponseType = '' | 'arraybuffer' | 'blob' | 'document' | 'json' | 'text';
 | 
			
		||||
type EventType = 'load' | 'error' | 'abort' | 'progress' | 'timeout' | 'loadend' | 'loadstart';
 | 
			
		||||
 | 
			
		||||
const executor = Executors.newCachedThreadPool();
 | 
			
		||||
 | 
			
		||||
export class XMLHttpRequest {
 | 
			
		||||
    private _timeout: number;
 | 
			
		||||
    private _responseType: ResponseType;
 | 
			
		||||
    private _withCredentials: boolean;
 | 
			
		||||
 | 
			
		||||
    private _readyState: ReadyState = ReadyState.UNSENT;
 | 
			
		||||
 | 
			
		||||
    private _method: RequestMethod;
 | 
			
		||||
    private _url: string;
 | 
			
		||||
    private _async: boolean;
 | 
			
		||||
    private _mimeType: string;
 | 
			
		||||
 | 
			
		||||
    private _status: number = 0;
 | 
			
		||||
    private _statusText: string = null;
 | 
			
		||||
    private _response: any;
 | 
			
		||||
    private _responseURL: string;
 | 
			
		||||
 | 
			
		||||
    private _connection = null;
 | 
			
		||||
 | 
			
		||||
    get timeout() {
 | 
			
		||||
        return this._timeout;
 | 
			
		||||
    }
 | 
			
		||||
    set timeout(timeout: number) {
 | 
			
		||||
        this._timeout = timeout
 | 
			
		||||
    }
 | 
			
		||||
    get readyState() {
 | 
			
		||||
        return this._readyState;
 | 
			
		||||
    }
 | 
			
		||||
    set responseType(type: ResponseType) {
 | 
			
		||||
        this._responseType = type;
 | 
			
		||||
    }
 | 
			
		||||
    get responseType() {
 | 
			
		||||
        return this._responseType;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get status() {
 | 
			
		||||
        return this._status;
 | 
			
		||||
    }
 | 
			
		||||
    get statusText() {
 | 
			
		||||
        return this._statusText;
 | 
			
		||||
    }
 | 
			
		||||
    get response() {
 | 
			
		||||
        return JSON.parse(this._response);
 | 
			
		||||
    }
 | 
			
		||||
    get responseText() {
 | 
			
		||||
        return this._response;
 | 
			
		||||
    }
 | 
			
		||||
    get responseXML() {
 | 
			
		||||
        return this._response;
 | 
			
		||||
    }
 | 
			
		||||
    get responseURL() {
 | 
			
		||||
        return this._responseURL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    onreadystatechange() {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    onprogress() {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    onabort() {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    onerror(ex: Error) {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    ontimeout(ex: Error) {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setRequestHeader(key: string, val: string) {
 | 
			
		||||
        this._connection.setRequestProperty(key, val);
 | 
			
		||||
    }
 | 
			
		||||
    getResponseHeader(key: string): string {
 | 
			
		||||
        return this._connection.getHeaderField(key);
 | 
			
		||||
    }
 | 
			
		||||
    getAllResponseHeaders(): any {
 | 
			
		||||
        return this._connection.getHeaderFields();
 | 
			
		||||
    }
 | 
			
		||||
    addEventListener(event: EventType, callback: Function) {
 | 
			
		||||
        this[`on${event.toLowerCase()}`] = callback;
 | 
			
		||||
    }
 | 
			
		||||
    overrideMimeType(mimeType: string) {
 | 
			
		||||
        this._mimeType = mimeType;
 | 
			
		||||
    }
 | 
			
		||||
    open(method: RequestMethod, url: string, async: boolean = true, user?: string, password?: string) {
 | 
			
		||||
        this._method = method;
 | 
			
		||||
        this._url = url;
 | 
			
		||||
        this._async = async;
 | 
			
		||||
 | 
			
		||||
        this._connection = new URL(this._url).openConnection()
 | 
			
		||||
        if (this._connection instanceof HttpsURLConnection) {
 | 
			
		||||
            this._connection.setHostnameVerifier(TrustAnyHostnameVerifier);
 | 
			
		||||
            this._connection.setSSLSocketFactory(SSLSocketFactory);
 | 
			
		||||
        }
 | 
			
		||||
        this._connection.setRequestMethod(this._method);
 | 
			
		||||
        this._connection.setDoOutput(true);
 | 
			
		||||
        this._connection.setDoInput(true);
 | 
			
		||||
        this._connection.setConnectTimeout(this._timeout);
 | 
			
		||||
        this._connection.setReadTimeout(this._timeout);
 | 
			
		||||
 | 
			
		||||
        this.setReadyState(ReadyState.OPENED);
 | 
			
		||||
    }
 | 
			
		||||
    send(body?: string | object): Future<string> {
 | 
			
		||||
        if (this._readyState !== ReadyState.OPENED) { throw new Error(`Error Status ${this._readyState}!`) }
 | 
			
		||||
        let future = executor.submit(new Callable({ call: () => this._send(body) }));
 | 
			
		||||
        if (!this._async) { future.get() }
 | 
			
		||||
        return future;
 | 
			
		||||
    }
 | 
			
		||||
    abort() {
 | 
			
		||||
        this._connection.disconnect();
 | 
			
		||||
        this.onabort();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private _send(body?: string | object) {
 | 
			
		||||
        try {
 | 
			
		||||
            this._connection.connect();
 | 
			
		||||
 | 
			
		||||
            if (body) {
 | 
			
		||||
                let bodyType = Object.prototype.toString.call(body);
 | 
			
		||||
                if (bodyType !== '[object String]') { throw new Error(`body(${bodyType}) must be string!`) }
 | 
			
		||||
                var out = this._connection.getOutputStream();
 | 
			
		||||
                out.write(new JavaString(body).getBytes(UTF_8));
 | 
			
		||||
                out.flush();
 | 
			
		||||
                out.close();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.setReadyState(ReadyState.LOADING);
 | 
			
		||||
            this._status = this._connection.getResponseCode();
 | 
			
		||||
            this._statusText = this._connection.getResponseMessage();
 | 
			
		||||
 | 
			
		||||
            if (this._status >= 0 && this._status < 300) {
 | 
			
		||||
                this._response = this.readOutput(this._connection.getInputStream());
 | 
			
		||||
            } else if (this._status >= 300 && this._status < 400) {
 | 
			
		||||
                this._responseURL = this.getResponseHeader('Location');
 | 
			
		||||
            } else {
 | 
			
		||||
                this._response = this.readOutput(this._connection.getErrorStream());
 | 
			
		||||
            }
 | 
			
		||||
            return this._response;
 | 
			
		||||
        } catch (ex) {
 | 
			
		||||
            if (ex instanceof SocketTimeoutException) {
 | 
			
		||||
                this.ontimeout(ex)
 | 
			
		||||
            } else {
 | 
			
		||||
                this.onerror(ex);
 | 
			
		||||
            }
 | 
			
		||||
        } finally {
 | 
			
		||||
            this._connection.disconnect();
 | 
			
		||||
            this.setReadyState(ReadyState.DONE);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private setReadyState(state: ReadyState) {
 | 
			
		||||
        this._readyState = state;
 | 
			
		||||
        this.onreadystatechange();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private readOutput(input: any) {
 | 
			
		||||
        var tempFile = Files.createTempFile('xhr', '.response');
 | 
			
		||||
        Files.copy(input, tempFile, StandardCopyOption['REPLACE_EXISTING']); tempFile.toFile().deleteOnExit();
 | 
			
		||||
        return new JavaString(Files.readAllBytes(tempFile), 'UTF-8');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								packages/ployfill/tsconfig.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								packages/ployfill/tsconfig.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
{
 | 
			
		||||
    "extends": "../../tsconfig.json",
 | 
			
		||||
    "compilerOptions": {
 | 
			
		||||
        "baseUrl": "src",
 | 
			
		||||
        "outDir": "dist"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user