config Entry

This commit is contained in:
pengfei.zhou 2019-07-22 13:41:38 +08:00
parent 410ee99414
commit bdb5a12735
7 changed files with 119 additions and 72 deletions

View File

@ -19,3 +19,13 @@
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
-keep class com.github.penfeizhou.doric.extension.bridge.DoricPlugin
-keep class com.github.penfeizhou.doric.extension.bridge.DoricMethod
-keep @com.github.penfeizhou.doric.extension.bridge.DoricPlugin class * {*;}
-keepclasseswithmembers @com.github.penfeizhou.doric.extension.bridge.DoricPlugin class * {*;}
-keep class * {
@com.github.penfeizhou.doric.extension.bridge.DoricMethod <fields>;
}

View File

@ -166,7 +166,7 @@ public class DoricJSEngine implements Handler.Callback, DoricTimerExtension.Time
}
private String packageContextScript(String contextId, String content) {
return String.format(DoricConstant.TEMPLATE_CONTEXT_CREATE, content, contextId, contextId);
return String.format(DoricConstant.TEMPLATE_CONTEXT_CREATE, content, contextId, contextId, contextId);
}
private String packageModuleScript(String moduleName, String content) {

View File

@ -18,11 +18,12 @@ public class DoricConstant {
public static final String INJECT_BRIDGE = "nativeBridge";
public static final String TEMPLATE_CONTEXT_CREATE = "Reflect.apply(" +
"function(doric,context,require,exports){" + "\n" +
"function(doric,context,Entry,require,exports){" + "\n" +
"%s" + "\n" +
"},doric.jsObtainContext(\"%s\"),[" +
"undefined," +
"doric.jsObtainContext(\"%s\")," +
"doric.jsObtainEntry(\"%s\")," +
"doric.__require__" +
",{}" +
"])";

View File

@ -1,44 +1,18 @@
import { Text, Alignment, Color, VLayout, Link, Panel, log, logw, loge } from "./index"
import { Text, Alignment, Color, VLayout, Panel, log, logw, loge } from "./index"
import { NativeCall } from "./src/ui/panel";
const v = new Text
v.width = 20
v.height = 30
v.left = 5
v.top = 5
v.bgColor = Color.parse('#00ff00')
v.config = {
alignment: Alignment.start
}
// console.log(v.toModel())
const layout = new VLayout
layout.space = 10
console.log(layout.viewId)
console.log(layout.toModel())
// log('console', Object.getOwnPropertyNames(console))
// setTimeout(() => {
// log('exec setTimeout')
// // context.callNative("modal", "toast", "Hello,Doric!")
// }, 1000)
// const timerId = setInterval(() => {
// log('exec setInterval')
// }, 1000)
// setTimeout(() => {
// log('exec cancelTimer')
// clearInterval(timerId)
// }, 5000)
@Link(context)
@Entry
export class MyPage extends Panel {
build() {
return layout
return new Text
}
@NativeCall
log() {
// log("Hello.HEGO")
// logw("Hello.HEGO")
// loge("Hello.HEGO")
log("Hello.HEGO")
logw("Hello.HEGO")
loge("Hello.HEGO")
context.bridge.demo_testPromise(true).then((r) => {
log('resolve', r)
}, (e) => {
@ -49,5 +23,8 @@ export class MyPage extends Panel {
}, (e) => {
log('reject', e)
})
setTimeout(function () {
log('settimeout')
}, 1000)
}
}

View File

@ -1,6 +1,7 @@
import { Context } from "./sandbox";
declare global {
const context: Context
const context: Context;
function Entry(constructor: { new(...args: any[]): {} }): any
}
export { }

View File

@ -1,16 +1,18 @@
import { uniqueId } from "../util/uniqueId";
import { loge } from "../util/log";
import "reflect-metadata"
/**
* ``` TypeScript
* // load script in global scope
* Reflect.apply(
* function(hego,context,require){
* function(hego,context,Entry,require){
* //Script content
* REG()
* },hego.jsObtainContext(id),[
* undefined,
* hego.jsObtainContext(id),
* hego.jsObtainEntry(id),
* hego.__require__,
* ])
* // load module in global scope
@ -31,6 +33,31 @@ declare function nativeRequire(moduleName: string): boolean
declare function nativeBridge(contextId: string, namespace: string, method: string, callbackId?: string, args?: any): boolean
declare function nativeSetTimer(timerId: number, interval: number, repeat: boolean): void
declare function nativeClearTimer(timerId: number): void
function hookBeforeNativeCall(context?: Context) {
if (context) {
Reflect.defineMetadata('__doric_context__', context, global)
context.hookBeforeNativeCall()
}
}
function hookAfterNativeCall(context?: Context) {
if (context) {
context.hookAfterNativeCall()
}
}
function getContext(): Context | undefined {
return Reflect.getMetadata('__doric_context__', global)
}
function setContext(context?: Context) {
Reflect.defineMetadata('__doric_context__', context, global)
}
export function jsCallResolve(contextId: string, callbackId: string, args?: any) {
const context = gContexts.get(contextId)
if (context === undefined) {
@ -46,7 +73,9 @@ export function jsCallResolve(contextId: string, callbackId: string, args?: any)
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: string, callbackId: string, args?: any) {
@ -64,7 +93,9 @@ export function jsCallReject(contextId: string, callbackId: string, args?: any)
for (let i = 2; i < arguments.length; i++) {
argumentsList.push(arguments[i])
}
Reflect.apply(callback.reject, context, argumentsList)
hookBeforeNativeCall(context)
Reflect.apply(callback.reject, context.entity, argumentsList)
hookAfterNativeCall(context)
}
export class Context {
@ -73,6 +104,18 @@ export class Context {
callbacks: Map<string, { resolve: Function, reject: Function }> = new Map
bridge: { [index: string]: (args?: any) => Promise<any> }
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, [])
}
}
constructor(id: string) {
this.id = id
this.bridge = new Proxy({}, {
@ -110,10 +153,13 @@ const gModules: Map<string, any> = new Map
export function jsObtainContext(id: string) {
if (gContexts.has(id)) {
return gContexts.get(id)
const context = gContexts.get(id)
setContext(context)
return context
} else {
const context: Context = new Context(id)
gContexts.set(id, context)
setContext(context)
return context
}
}
@ -153,50 +199,77 @@ export function jsCallEntityMethod(contextId: string, methodName: string, args?:
for (let i = 2; i < arguments.length; i++) {
argumentsList.push(arguments[i])
}
return Reflect.apply(Reflect.get(context.entity, methodName), context.entity, argumentsList)
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: string) {
const context = jsObtainContext(contextId)
return <T extends { new(...args: any[]): {} }>(constructor: T) => {
const ret = class extends constructor {
context = context
}
if (context) {
context.register(new ret)
}
return ret
}
}
const global = Function('return this')()
let __timerId__ = 0
const timerCallbacks: Map<number, () => void> = new Map
declare function nativeSetTimer(timerId: number, interval: number, repeat: boolean): void
declare function nativeClearTimer(timerId: number): void
const timerInfos: Map<number, { callback: () => void, context?: Context }> = new Map
global.setTimeout = (handler: Function, timeout?: number | undefined, ...args: any[]) => {
const id = __timerId__++
timerCallbacks.set(id, () => {
Reflect.apply(handler, undefined, args)
timerCallbacks.delete(id)
timerInfos.set(id, {
callback: () => {
Reflect.apply(handler, undefined, args)
timerInfos.delete(id)
},
context: getContext(),
})
nativeSetTimer(id, timeout || 0, false)
return id
}
global.setInterval = (handler: Function, timeout?: number | undefined, ...args: any[]) => {
const id = __timerId__++
timerCallbacks.set(id, () => {
Reflect.apply(handler, undefined, args)
timerInfos.set(id, {
callback: () => {
Reflect.apply(handler, undefined, args)
},
context: getContext(),
})
nativeSetTimer(id, timeout || 0, true)
return id
}
global.clearTimeout = (timerId: number) => {
timerCallbacks.delete(timerId)
timerInfos.delete(timerId)
nativeClearTimer(timerId)
}
global.clearInterval = (timerId: number) => {
timerCallbacks.delete(timerId)
timerInfos.delete(timerId)
nativeClearTimer(timerId)
}
export function jsCallbackTimer(timerId: number) {
const timerCallback = timerCallbacks.get(timerId)
if (timerCallback instanceof Function) {
Reflect.apply(timerCallback, undefined, [])
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)
}
}

View File

@ -2,26 +2,11 @@ import { } from './../runtime/global';
import { View, Stack, Group } from "./view";
import { loge, log } from '../util/log';
export function Link(context: any) {
return <T extends { new(...args: any[]): {} }>(constructor: T) => {
const ret = class extends constructor {
context = context
}
context.register(new ret)
return ret
}
}
export function NativeCall(target: Panel, propertyKey: string, descriptor: PropertyDescriptor) {
const originVal = descriptor.value
descriptor.value = function () {
const args = []
for (let index in arguments) {
args.push(arguments[index]);
}
Reflect.apply(Reflect.get(target, '__hookBeforeNativeCall__'), this, [])
const ret = Reflect.apply(originVal, this, args)
Reflect.apply(Reflect.get(target, '__hookAfterNativeCall__'), this, [])
const ret = Reflect.apply(originVal, this, arguments)
return ret
}
return descriptor
@ -103,11 +88,11 @@ export abstract class Panel {
}, this.__rootView__)
}
private __hookBeforeNativeCall__() {
private hookBeforeNativeCall() {
log('__hookBeforeNativeCall__')
}
private __hookAfterNativeCall__() {
private hookAfterNativeCall() {
log('__hookAfterNativeCall__')
if (this.__rootView__.isDirty()) {
const model = this.__rootView__.toModel()