blob: 0a76f915156e4eff9b8224e8e3344fd987394969 [file] [log] [blame]
/* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 { Router, Message } from '@weex-cli/linker'
import MemoryFile from '../MemoryFile'
import { Config } from '../ConfigResolver'
import { Device } from '../managers/DeviceManager'
import utils from '../utils'
import * as DEBUG from 'debug'
const debug = DEBUG('Handler:Proxy.Native')
const debuggerRouter = Router.get(`debugger-${Config.get('channelId')}`)
let environmentMap = Config.get(`debugger-${Config.get('channelId')}`)
let vmIndex = 0
let jsserviceIndex = 0
let heartbeatTimer
const sendHeartbeat = () => {
heartbeatTimer && clearTimeout(heartbeatTimer)
heartbeatTimer = setTimeout(() => {
debuggerRouter.pushMessage('proxy.native', 'ping')
debug('ping-pong')
sendHeartbeat()
}, Config.get('heartbeatTime') || 30000)
}
debuggerRouter
.registerHandler(async (message: Message) => {
const payload = message.payload
const method = payload.method
const device = Device.getDevice(message.channelId)
if (method === 'WxDebug.initJSRuntime') {
if (!environmentMap[message.channelId]) {
environmentMap[message.channelId] = {}
}
environmentMap[message.channelId]['jsframework'] = new MemoryFile(
'js-framework.js',
payload.params.source,
).getUrl()
if (device && device.logLevel) {
payload.params.env.WXEnvironment.logLevel = device.logLevel
}
environmentMap[message.channelId]['isLayoutAndSandbox'] = payload.params.isLayoutAndSandbox
environmentMap[message.channelId]['environment'] = payload.params.env
environmentMap[message.channelId]['device'] = device
} else if (method === 'WxDebug.callJS' && payload.params.method === 'createInstance') {
const code = payload.params.args[1]
let bundleUrl = payload.params.args[2].bundleUrl
let env = {
environment: environmentMap[message.channelId]['environment'],
device: environmentMap[message.channelId]['device'],
isLayoutAndSandbox: environmentMap[message.channelId]['isLayoutAndSandbox'],
}
if (/^(https?|taobao|qap):\/\/(.*your_current_ip):(\d+)\//i.test(bundleUrl)) {
bundleUrl = bundleUrl.replace(/^(https?|taobao|qap):\/\/(.*your_current_ip):(\d+)\//i, 'file://')
}
env['sourceUrl'] = new MemoryFile(
bundleUrl,
utils.wrapper.bundleWrapper(code, utils.wrapper.transformUrlToLocalUrl(bundleUrl)),
).getUrl()
if (
environmentMap[message.channelId] &&
environmentMap[message.channelId]['polify'] &&
environmentMap[message.channelId]['polify']['jsframework']
) {
env['jsframework'] = environmentMap[message.channelId]['polify']['jsframework']
} else {
env['jsframework'] = environmentMap[message.channelId]['jsframework']
}
environmentMap[message.channelId]['workerjs'] = payload.params.workerjs = new MemoryFile(
`VM_${vmIndex++}`,
utils.wrapper.generateWorkerEntry(env),
).getUrl()
if (environmentMap[message.channelId]['polify'] && environmentMap[message.channelId]['polify']['workerjs']) {
env['workerjs'] = environmentMap[message.channelId]['polify']['workerjs']
} else {
env['workerjs'] = environmentMap[message.channelId]['workerjs']
}
payload.params.workerjs = env['workerjs']
if (
environmentMap[message.channelId]['polify'] &&
Array.isArray(environmentMap[message.channelId]['polify']['jsservice']) &&
environmentMap[message.channelId]['polify']['jsservice'].length > 0
) {
payload.params.jsservice = environmentMap[message.channelId]['polify']['jsservice']
} else {
payload.params.jsservice = environmentMap[message.channelId]['jsservice']
}
if (
environmentMap[message.channelId] &&
environmentMap[message.channelId]['polify'] &&
environmentMap[message.channelId]['polify']['sourcejs']
) {
bundleUrl = payload.params.sourceUrl = environmentMap[message.channelId]['polify']['sourcejs']
} else {
bundleUrl = payload.params.sourceUrl = env['sourceUrl']
}
await debuggerRouter.pushMessageByChannelId('page.debugger', message.channelId, {
method: 'WxDebug.bundleRendered',
params: {
bundleUrl: bundleUrl,
env: {
jsframework: environmentMap[message.channelId]['jsframework'],
jsservice: payload.params.jsservice,
workerjs: payload.params.workerjs,
sourcejs: payload.params.sourceUrl,
},
isSandbox: false,
},
})
} else if (method === 'WxDebug.callJS' && payload.params.method === 'destroyInstance') {
Config.set('ACTIVE_INSTANCEID', '')
} else if (method === 'WxDebug.callJS' && payload.params.method === 'createInstanceContext') {
const options = payload.params.args[1]
const dependenceCode = payload.params.args[3]
let env = {
environment: environmentMap[message.channelId]['environment'],
device: environmentMap[message.channelId]['device'],
isLayoutAndSandbox: environmentMap[message.channelId]['isLayoutAndSandbox'],
}
let bundleUrl = options.bundleUrl
if (/^(https?|taobao|qap):\/\/(.*your_current_ip):(\d+)\//i.test(bundleUrl)) {
bundleUrl = '/source/' + bundleUrl.replace(/^(https?|taobao|qap):\/\/(.*your_current_ip):(\d+)\//i, 'file://')
} else if (/^file:\/\//.test(bundleUrl)) {
bundleUrl = '/source/' + bundleUrl
} else {
bundleUrl = '/source/' + bundleUrl
}
Config.set('ACTIVE_INSTANCEID', payload.params.args[0])
if (dependenceCode) {
environmentMap[message.channelId]['dependencejs'] = new MemoryFile(`dependencejs.js`, dependenceCode).getUrl()
if (
environmentMap[message.channelId]['polify'] &&
environmentMap[message.channelId]['polify']['dependencejs']
) {
payload.params.dependencejs = environmentMap[message.channelId]['polify']['dependencejs']
} else {
payload.params.dependencejs = environmentMap[message.channelId]['dependencejs']
}
}
if (
environmentMap[message.channelId] &&
environmentMap[message.channelId]['polify'] &&
environmentMap[message.channelId]['polify']['jsservice']
) {
payload.params.jsservice = environmentMap[message.channelId]['polify']['jsservice']
} else {
payload.params.jsservice = environmentMap[message.channelId]['jsservice']
}
if (
environmentMap[message.channelId] &&
environmentMap[message.channelId]['polify'] &&
environmentMap[message.channelId]['polify']['jsframework']
) {
env['jsframework'] = environmentMap[message.channelId]['polify']['jsframework']
} else {
env['jsframework'] = environmentMap[message.channelId]['jsframework']
}
env['isLayoutAndSandbox'] = environmentMap[message.channelId]['isLayoutAndSandbox']
environmentMap[message.channelId]['workerjs'] = payload.params.workerjs = new MemoryFile(
`VM_${vmIndex++}`,
utils.wrapper.generateSandboxWorkerEntry(env),
).getUrl()
if (
environmentMap[message.channelId] &&
environmentMap[message.channelId]['polify'] &&
environmentMap[message.channelId]['polify']['workerjs']
) {
payload.params.workerjs = environmentMap[message.channelId]['polify']['workerjs']
} else {
payload.params.workerjs = environmentMap[message.channelId]['workerjs']
}
if (
environmentMap[message.channelId] &&
environmentMap[message.channelId]['polify'] &&
environmentMap[message.channelId]['polify']['sourcejs']
) {
bundleUrl = environmentMap[message.channelId]['polify']['sourcejs']
} else if (environmentMap[message.channelId]['sourcejs']) {
bundleUrl = environmentMap[message.channelId]['sourcejs']
}
await debuggerRouter.pushMessageByChannelId('page.debugger', message.channelId, {
method: 'WxDebug.bundleRendered',
params: {
bundleUrl: bundleUrl,
env: {
jsframework: env['jsframework'],
jsservice: payload.params.jsservice,
workerjs: payload.params.workerjs,
dependencejs: payload.params.dependencejs,
sourcejs: bundleUrl,
},
isSandbox: true,
},
})
} else if (method === 'WxDebug.callJS' && payload.params.method === 'importScript') {
const code = payload.params.args[1]
let bundleUrl = payload.params.args[2] && payload.params.args[2].bundleUrl
bundleUrl = bundleUrl.replace(/\?random=(-)?\d+/i, '')
if (
environmentMap[message.channelId] &&
environmentMap[message.channelId]['polify'] &&
environmentMap[message.channelId]['polify']['sourcejs']
) {
payload.params.sourceUrl = environmentMap[message.channelId]['polify']['sourcejs']
} else {
environmentMap[message.channelId]['sourcejs'] = payload.params.sourceUrl = new MemoryFile(
bundleUrl,
code,
).getUrl()
}
} else if (method === 'WxDebug.importScript') {
const url = new MemoryFile(`jsservice_${jsserviceIndex++}.js`, payload.params.source).getUrl()
if (!environmentMap[message.channelId]['jsservice']) {
environmentMap[message.channelId]['jsservice'] = []
}
if (environmentMap[message.channelId]['jsservice'].indexOf(url) === -1) {
environmentMap[message.channelId]['jsservice'].push(url)
}
} else if (method === 'syncReturn') {
message.payload = {
error: payload.error,
ret: payload.params && payload.params.ret,
}
message.to('sync.native')
return
} else if (method === 'WxDebug.sendTracingData') {
message.to('page.debugger')
return
} else if (method === 'WxDebug.sendSummaryInfo') {
message.to('page.debugger')
return
} else if (method === 'WxDebug.sendPerformanceData') {
message.to('page.debugger')
return
}
message.to('runtime.worker')
})
.at('proxy.native')
.when('payload.method&&payload.method.split(".")[0]==="WxDebug"')
debuggerRouter
.registerHandler(function(message) {
const payload = message.payload
const device = Device.getDevice(message.channelId)
if (payload.method === 'Page.screencastFrame') {
payload.params.sessionId = 1
if (device && device.platform === 'android') {
payload.params.metadata.pageScaleFactor = 0.999
}
} else if (payload.method === 'Console.messageAdded') {
// issue: https://github.com/weexteam/weex-toolkit/issues/408
// TODO: make it can be control by user
if (device && device.remoteDebug) {
message.discard()
} else {
message.payload = {
method: 'Runtime.consoleAPICalled',
params: {
type: payload.params.message.level,
args:
[
{
type: 'string',
value: payload.params.message.text,
},
] || [],
executionContextId: 1,
// "stackTrace": payload.params.message.stackTrace
},
}
}
} else if (payload.result && payload.result.method === 'WxDebug.syncReturn') {
message.payload = {
id: payload.result.params && payload.result.id && payload.result.params.syncId,
error: payload.error,
ret: payload.result.params && payload.result.params.ret,
}
message.to('sync.native')
return
} else if (payload.result && payload.id === undefined) {
message.discard()
}
message.to('proxy.inspector')
})
.at('proxy.native')
.when('!payload.method||(payload.method.split(".")[0]!=="WxDebug")')
debuggerRouter
.registerHandler(async () => {
sendHeartbeat()
})
.at('proxy.native')