js:add lib and .d.ts
This commit is contained in:
22
doric-js/lib/src/runtime/global.d.ts
vendored
Normal file
22
doric-js/lib/src/runtime/global.d.ts
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
export * from 'reflect-metadata';
|
||||
export declare type BridgeContext = {
|
||||
[index: string]: {
|
||||
[index: string]: (args?: any) => Promise<any>;
|
||||
};
|
||||
};
|
||||
declare global {
|
||||
const context: BridgeContext;
|
||||
const Environment: {
|
||||
platform: "Android" | "iOS" | "Qt" | "h5";
|
||||
platformVersion: string;
|
||||
appName: string;
|
||||
appVersion: string;
|
||||
libVersion: string;
|
||||
screenWidth: number;
|
||||
screenHeight: number;
|
||||
};
|
||||
function Entry(constructor: {
|
||||
new (...args: any[]): {};
|
||||
}): any;
|
||||
}
|
||||
export {};
|
0
doric-js/lib/src/runtime/global.js
Normal file
0
doric-js/lib/src/runtime/global.js
Normal file
27
doric-js/lib/src/runtime/sandbox.d.ts
vendored
Normal file
27
doric-js/lib/src/runtime/sandbox.d.ts
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import "reflect-metadata";
|
||||
export declare function jsCallResolve(contextId: string, callbackId: string, args?: any): void;
|
||||
export declare function jsCallReject(contextId: string, callbackId: string, args?: any): void;
|
||||
export declare class Context {
|
||||
entity: any;
|
||||
id: string;
|
||||
callbacks: Map<string, {
|
||||
resolve: Function;
|
||||
reject: Function;
|
||||
}>;
|
||||
hookBeforeNativeCall(): void;
|
||||
hookAfterNativeCall(): void;
|
||||
constructor(id: string);
|
||||
callNative(namespace: string, method: string, args?: any): Promise<any>;
|
||||
register(instance: Object): void;
|
||||
}
|
||||
export declare function jsObtainContext(id: string): Context | undefined;
|
||||
export declare function jsReleaseContext(id: string): void;
|
||||
export declare function __require__(name: string): any;
|
||||
export declare function jsRegisterModule(name: string, moduleObject: any): void;
|
||||
export declare function jsCallEntityMethod(contextId: string, methodName: string, args?: any): any;
|
||||
export declare function jsObtainEntry(contextId: string): <T extends new (...args: any[]) => {}>(constructor: T) => {
|
||||
new (...args: any[]): {
|
||||
context: Context | undefined;
|
||||
};
|
||||
} & T;
|
||||
export declare function jsCallbackTimer(timerId: number): void;
|
302
doric-js/lib/src/runtime/sandbox.js
Normal file
302
doric-js/lib/src/runtime/sandbox.js
Normal file
@@ -0,0 +1,302 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { uniqueId } from "../util/uniqueId";
|
||||
import { loge } from "../util/log";
|
||||
import "reflect-metadata";
|
||||
function hookBeforeNativeCall(context) {
|
||||
if (context) {
|
||||
Reflect.defineMetadata('__doric_context__', context, global);
|
||||
context.hookBeforeNativeCall();
|
||||
}
|
||||
}
|
||||
function hookAfterNativeCall(context) {
|
||||
if (context) {
|
||||
context.hookAfterNativeCall();
|
||||
}
|
||||
}
|
||||
function getContext() {
|
||||
return Reflect.getMetadata('__doric_context__', global);
|
||||
}
|
||||
function setContext(context) {
|
||||
Reflect.defineMetadata('__doric_context__', context, global);
|
||||
}
|
||||
export function jsCallResolve(contextId, callbackId, args) {
|
||||
const context = gContexts.get(contextId);
|
||||
if (context === undefined) {
|
||||
loge(`Cannot find context for context id:${contextId}`);
|
||||
return;
|
||||
}
|
||||
const callback = context.callbacks.get(callbackId);
|
||||
if (callback === undefined) {
|
||||
loge(`Cannot find call for context id:${contextId},callback id:${callbackId}`);
|
||||
return;
|
||||
}
|
||||
const argumentsList = [];
|
||||
for (let i = 2; i < arguments.length; i++) {
|
||||
argumentsList.push(arguments[i]);
|
||||
}
|
||||
hookBeforeNativeCall(context);
|
||||
Reflect.apply(callback.resolve, context, argumentsList);
|
||||
hookAfterNativeCall(context);
|
||||
}
|
||||
export function jsCallReject(contextId, callbackId, args) {
|
||||
const context = gContexts.get(contextId);
|
||||
if (context === undefined) {
|
||||
loge(`Cannot find context for context id:${contextId}`);
|
||||
return;
|
||||
}
|
||||
const callback = context.callbacks.get(callbackId);
|
||||
if (callback === undefined) {
|
||||
loge(`Cannot find call for context id:${contextId},callback id:${callbackId}`);
|
||||
return;
|
||||
}
|
||||
const argumentsList = [];
|
||||
for (let i = 2; i < arguments.length; i++) {
|
||||
argumentsList.push(arguments[i]);
|
||||
}
|
||||
hookBeforeNativeCall(context);
|
||||
Reflect.apply(callback.reject, context.entity, argumentsList);
|
||||
hookAfterNativeCall(context);
|
||||
}
|
||||
export class Context {
|
||||
constructor(id) {
|
||||
this.callbacks = new Map;
|
||||
this.id = id;
|
||||
return new Proxy(this, {
|
||||
get: (target, p) => {
|
||||
if (Reflect.has(target, p)) {
|
||||
return Reflect.get(target, p);
|
||||
}
|
||||
else {
|
||||
const namespace = p;
|
||||
return new Proxy({}, {
|
||||
get: (target, p) => {
|
||||
if (Reflect.has(target, p)) {
|
||||
return Reflect.get(target, p);
|
||||
}
|
||||
else {
|
||||
const context = this;
|
||||
return function () {
|
||||
const args = [];
|
||||
args.push(namespace);
|
||||
args.push(p);
|
||||
for (let arg of arguments) {
|
||||
args.push(arg);
|
||||
}
|
||||
return Reflect.apply(context.callNative, context, args);
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
hookBeforeNativeCall() {
|
||||
if (this.entity && Reflect.has(this.entity, 'hookBeforeNativeCall')) {
|
||||
Reflect.apply(Reflect.get(this.entity, 'hookBeforeNativeCall'), this.entity, []);
|
||||
}
|
||||
}
|
||||
hookAfterNativeCall() {
|
||||
if (this.entity && Reflect.has(this.entity, 'hookAfterNativeCall')) {
|
||||
Reflect.apply(Reflect.get(this.entity, 'hookAfterNativeCall'), this.entity, []);
|
||||
}
|
||||
}
|
||||
callNative(namespace, method, args) {
|
||||
const callbackId = uniqueId('callback');
|
||||
nativeBridge(this.id, namespace, method, callbackId, args);
|
||||
return new Promise((resolve, reject) => {
|
||||
this.callbacks.set(callbackId, {
|
||||
resolve,
|
||||
reject,
|
||||
});
|
||||
});
|
||||
}
|
||||
register(instance) {
|
||||
this.entity = instance;
|
||||
}
|
||||
}
|
||||
const gContexts = new Map;
|
||||
const gModules = new Map;
|
||||
export function jsObtainContext(id) {
|
||||
if (gContexts.has(id)) {
|
||||
const context = gContexts.get(id);
|
||||
setContext(context);
|
||||
return context;
|
||||
}
|
||||
else {
|
||||
const context = new Context(id);
|
||||
gContexts.set(id, context);
|
||||
setContext(context);
|
||||
return context;
|
||||
}
|
||||
}
|
||||
export function jsReleaseContext(id) {
|
||||
const context = gContexts.get(id);
|
||||
const args = arguments;
|
||||
if (context) {
|
||||
timerInfos.forEach((v, k) => {
|
||||
if (v.context === context) {
|
||||
if (global.nativeClearTimer === undefined) {
|
||||
return Reflect.apply(_clearTimeout, undefined, args);
|
||||
}
|
||||
timerInfos.delete(k);
|
||||
nativeClearTimer(k);
|
||||
}
|
||||
});
|
||||
}
|
||||
gContexts.delete(id);
|
||||
}
|
||||
export function __require__(name) {
|
||||
if (gModules.has(name)) {
|
||||
return gModules.get(name);
|
||||
}
|
||||
else {
|
||||
if (nativeRequire(name)) {
|
||||
return gModules.get(name);
|
||||
}
|
||||
else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
export function jsRegisterModule(name, moduleObject) {
|
||||
gModules.set(name, moduleObject);
|
||||
}
|
||||
export function jsCallEntityMethod(contextId, methodName, args) {
|
||||
const context = gContexts.get(contextId);
|
||||
if (context === undefined) {
|
||||
loge(`Cannot find context for context id:${contextId}`);
|
||||
return;
|
||||
}
|
||||
if (context.entity === undefined) {
|
||||
loge(`Cannot find holder for context id:${contextId}`);
|
||||
return;
|
||||
}
|
||||
if (Reflect.has(context.entity, methodName)) {
|
||||
const argumentsList = [];
|
||||
for (let i = 2; i < arguments.length; i++) {
|
||||
argumentsList.push(arguments[i]);
|
||||
}
|
||||
hookBeforeNativeCall(context);
|
||||
const ret = Reflect.apply(Reflect.get(context.entity, methodName), context.entity, argumentsList);
|
||||
hookAfterNativeCall(context);
|
||||
return ret;
|
||||
}
|
||||
else {
|
||||
loge(`Cannot find method for context id:${contextId},method name is:${methodName}`);
|
||||
}
|
||||
}
|
||||
export function jsObtainEntry(contextId) {
|
||||
const context = jsObtainContext(contextId);
|
||||
return (constructor) => {
|
||||
const ret = class extends constructor {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.context = context;
|
||||
}
|
||||
};
|
||||
if (context) {
|
||||
context.register(new ret);
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
const global = Function('return this')();
|
||||
let __timerId__ = 0;
|
||||
const timerInfos = new Map;
|
||||
const _setTimeout = global.setTimeout;
|
||||
const _setInterval = global.setInterval;
|
||||
const _clearTimeout = global.clearTimeout;
|
||||
const _clearInterval = global.clearInterval;
|
||||
const doricSetTimeout = function (handler, timeout, ...args) {
|
||||
if (global.nativeSetTimer === undefined) {
|
||||
return Reflect.apply(_setTimeout, undefined, arguments);
|
||||
}
|
||||
const id = __timerId__++;
|
||||
timerInfos.set(id, {
|
||||
callback: () => {
|
||||
Reflect.apply(handler, undefined, args);
|
||||
timerInfos.delete(id);
|
||||
},
|
||||
context: getContext(),
|
||||
});
|
||||
nativeSetTimer(id, timeout || 0, false);
|
||||
return id;
|
||||
};
|
||||
const doricSetInterval = function (handler, timeout, ...args) {
|
||||
if (global.nativeSetTimer === undefined) {
|
||||
return Reflect.apply(_setInterval, undefined, arguments);
|
||||
}
|
||||
const id = __timerId__++;
|
||||
timerInfos.set(id, {
|
||||
callback: () => {
|
||||
Reflect.apply(handler, undefined, args);
|
||||
},
|
||||
context: getContext(),
|
||||
});
|
||||
nativeSetTimer(id, timeout || 0, true);
|
||||
return id;
|
||||
};
|
||||
const doricClearTimeout = function (timerId) {
|
||||
if (global.nativeClearTimer === undefined) {
|
||||
return Reflect.apply(_clearTimeout, undefined, arguments);
|
||||
}
|
||||
timerInfos.delete(timerId);
|
||||
nativeClearTimer(timerId);
|
||||
};
|
||||
const doricClearInterval = function (timerId) {
|
||||
if (global.nativeClearTimer === undefined) {
|
||||
return Reflect.apply(_clearInterval, undefined, arguments);
|
||||
}
|
||||
timerInfos.delete(timerId);
|
||||
nativeClearTimer(timerId);
|
||||
};
|
||||
if (!global.setTimeout) {
|
||||
global.setTimeout = doricSetTimeout;
|
||||
}
|
||||
else {
|
||||
global.doricSetTimeout = doricSetTimeout;
|
||||
}
|
||||
if (!global.setInterval) {
|
||||
global.setInterval = doricSetInterval;
|
||||
}
|
||||
else {
|
||||
global.doricSetInterval = doricSetInterval;
|
||||
}
|
||||
if (!global.clearTimeout) {
|
||||
global.clearTimeout = doricClearTimeout;
|
||||
}
|
||||
else {
|
||||
global.doricClearTimeout = doricClearTimeout;
|
||||
}
|
||||
if (!global.clearInterval) {
|
||||
global.clearInterval = doricClearInterval;
|
||||
}
|
||||
else {
|
||||
global.doricClearInterval = doricClearInterval;
|
||||
}
|
||||
export function jsCallbackTimer(timerId) {
|
||||
const timerInfo = timerInfos.get(timerId);
|
||||
if (timerInfo === undefined) {
|
||||
return;
|
||||
}
|
||||
if (timerInfo.callback instanceof Function) {
|
||||
hookBeforeNativeCall(timerInfo.context);
|
||||
Reflect.apply(timerInfo.callback, timerInfo.context, []);
|
||||
hookAfterNativeCall(timerInfo.context);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user