1e484b35bSopenharmony_ci/* 2e484b35bSopenharmony_ci * Licensed to the Apache Software Foundation (ASF) under one 3e484b35bSopenharmony_ci * or more contributor license agreements. See the NOTICE file 4e484b35bSopenharmony_ci * distributed with this work for additional information 5e484b35bSopenharmony_ci * regarding copyright ownership. The ASF licenses this file 6e484b35bSopenharmony_ci * to you under the Apache License, Version 2.0 (the 7e484b35bSopenharmony_ci * "License"); you may not use this file except in compliance 8e484b35bSopenharmony_ci * with the License. You may obtain a copy of the License at 9e484b35bSopenharmony_ci * 10e484b35bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 11e484b35bSopenharmony_ci * 12e484b35bSopenharmony_ci * Unless required by applicable law or agreed to in writing, 13e484b35bSopenharmony_ci * software distributed under the License is distributed on an 14e484b35bSopenharmony_ci * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15e484b35bSopenharmony_ci * KIND, either express or implied. See the License for the 16e484b35bSopenharmony_ci * specific language governing permissions and limitations 17e484b35bSopenharmony_ci * under the License. 18e484b35bSopenharmony_ci */ 19e484b35bSopenharmony_ci 20e484b35bSopenharmony_ci/** 21e484b35bSopenharmony_ci * @fileOverview 22e484b35bSopenharmony_ci * page controls from native 23e484b35bSopenharmony_ci * 24e484b35bSopenharmony_ci * - init bundle 25e484b35bSopenharmony_ci * 26e484b35bSopenharmony_ci * corresponded with the API of page manager (framework.js) 27e484b35bSopenharmony_ci */ 28e484b35bSopenharmony_ci 29e484b35bSopenharmony_ciimport { 30e484b35bSopenharmony_ci Log 31e484b35bSopenharmony_ci} from '../../../utils/index'; 32e484b35bSopenharmony_ciimport { removePrefix } from '../../util/index'; 33e484b35bSopenharmony_ciimport { 34e484b35bSopenharmony_ci defineFn, 35e484b35bSopenharmony_ci bootstrap 36e484b35bSopenharmony_ci} from './bundle'; 37e484b35bSopenharmony_ciimport { updateActions } from '../api/misc'; 38e484b35bSopenharmony_ciimport { getPageGlobal } from '../../app/helper'; 39e484b35bSopenharmony_ciimport { Image } from '../Image'; 40e484b35bSopenharmony_ciimport { OffscreenCanvas } from '../OffscreenCanvas'; 41e484b35bSopenharmony_ciimport Page from '../index'; 42e484b35bSopenharmony_ciimport { Services } from '../../app/index'; 43e484b35bSopenharmony_ciimport { requireModule } from '../register'; 44e484b35bSopenharmony_ciimport { App } from '../../app/App'; 45e484b35bSopenharmony_ci 46e484b35bSopenharmony_ciinterface ParseOptions { 47e484b35bSopenharmony_ci $app_define$(...args: any[]): void; // eslint-disable-line camelcase 48e484b35bSopenharmony_ci $app_bootstrap$(name: string): void; // eslint-disable-line camelcase 49e484b35bSopenharmony_ci $app_require$(name: string): void; // eslint-disable-line camelcase 50e484b35bSopenharmony_ci Image(): void; 51e484b35bSopenharmony_ci OffscreenCanvas(width, height): void; 52e484b35bSopenharmony_ci} 53e484b35bSopenharmony_ci 54e484b35bSopenharmony_ci/** 55e484b35bSopenharmony_ci * Init a page by run code with data. 56e484b35bSopenharmony_ci * @param {Page} page 57e484b35bSopenharmony_ci * @param {string} code 58e484b35bSopenharmony_ci * @param {Object} data 59e484b35bSopenharmony_ci * @param {Services} services 60e484b35bSopenharmony_ci * @return {*} 61e484b35bSopenharmony_ci */ 62e484b35bSopenharmony_ciexport function init(page: Page, code: string | Function, data: object, services: Services): any { 63e484b35bSopenharmony_ci Log.debug('Intialize a page with:\n', data); 64e484b35bSopenharmony_ci let result; 65e484b35bSopenharmony_ci 66e484b35bSopenharmony_ci // Methods to parse code. 67e484b35bSopenharmony_ci const pageDefine = (...args) => defineFn(page, ...args); 68e484b35bSopenharmony_ci const pageBoot = (name) => { 69e484b35bSopenharmony_ci result = bootstrap(page, name, data); 70e484b35bSopenharmony_ci updateActions(page); 71e484b35bSopenharmony_ci page.doc.taskCenter.send('dom', { action: 'createFinish' }, []); 72e484b35bSopenharmony_ci Log.debug(`After initialized a page(${page.id}).`); 73e484b35bSopenharmony_ci }; 74e484b35bSopenharmony_ci 75e484b35bSopenharmony_ci const packageName = page.packageName; 76e484b35bSopenharmony_ci const appFunction = () => { 77e484b35bSopenharmony_ci if (page && page.doc) { 78e484b35bSopenharmony_ci return page; 79e484b35bSopenharmony_ci } 80e484b35bSopenharmony_ci // card not has packageName 81e484b35bSopenharmony_ci if (packageName === 'notset') { 82e484b35bSopenharmony_ci return page; 83e484b35bSopenharmony_ci } 84e484b35bSopenharmony_ci const instance = App.pageMap.getTop(packageName); 85e484b35bSopenharmony_ci return instance || page; 86e484b35bSopenharmony_ci }; 87e484b35bSopenharmony_ci 88e484b35bSopenharmony_ci const pageRequireModule = name => requireModule(appFunction, removePrefix(name)); 89e484b35bSopenharmony_ci 90e484b35bSopenharmony_ci const imageObj: () => Image = function() { 91e484b35bSopenharmony_ci return new Image(page); 92e484b35bSopenharmony_ci }; 93e484b35bSopenharmony_ci const offscreenCanvasObj: (width, height) => OffscreenCanvas = function(width, height) { 94e484b35bSopenharmony_ci return new OffscreenCanvas(page, width, height); 95e484b35bSopenharmony_ci }; 96e484b35bSopenharmony_ci const options: ParseOptions = { 97e484b35bSopenharmony_ci $app_define$: pageDefine, 98e484b35bSopenharmony_ci $app_bootstrap$: pageBoot, 99e484b35bSopenharmony_ci $app_require$: pageRequireModule, 100e484b35bSopenharmony_ci Image: imageObj, 101e484b35bSopenharmony_ci OffscreenCanvas: offscreenCanvasObj 102e484b35bSopenharmony_ci }; 103e484b35bSopenharmony_ci 104e484b35bSopenharmony_ci // Support page global and init language. 105e484b35bSopenharmony_ci global.__appProto__ = getPageGlobal(page.packageName); 106e484b35bSopenharmony_ci global.language = page.options.language; 107e484b35bSopenharmony_ci global.$app_define$ = pageDefine; 108e484b35bSopenharmony_ci global.$app_require$ = pageRequireModule; 109e484b35bSopenharmony_ci global.Image = imageObj; 110e484b35bSopenharmony_ci global.OffscreenCanvas = offscreenCanvasObj; 111e484b35bSopenharmony_ci 112e484b35bSopenharmony_ci let functionCode: string; 113e484b35bSopenharmony_ci if (typeof code !== 'function') { 114e484b35bSopenharmony_ci functionCode = `(function(global){\n\n"use strict";\n\n ${code} \n\n})(this.__appProto__)`; 115e484b35bSopenharmony_ci } 116e484b35bSopenharmony_ci 117e484b35bSopenharmony_ci // Compile js bundle code and get result. 118e484b35bSopenharmony_ci if (typeof code === 'function') { 119e484b35bSopenharmony_ci code.call(global, options); 120e484b35bSopenharmony_ci } else { 121e484b35bSopenharmony_ci compileBundle(functionCode, page.doc.url, options, services); 122e484b35bSopenharmony_ci } 123e484b35bSopenharmony_ci return result; 124e484b35bSopenharmony_ci} 125e484b35bSopenharmony_ci 126e484b35bSopenharmony_ci/** 127e484b35bSopenharmony_ci * Run bundle code by a new function. 128e484b35bSopenharmony_ci * @param {string} functionCode - Js bundle code. 129e484b35bSopenharmony_ci * @param {Object[]} args - Global methods for compile js bundle code. 130e484b35bSopenharmony_ci * @return {*} 131e484b35bSopenharmony_ci */ 132e484b35bSopenharmony_ciexport function compileBundle(functionCode: string, file: string, ...args: object[]): any { 133e484b35bSopenharmony_ci const funcKeys: string[] = []; 134e484b35bSopenharmony_ci const funcValues: Function[] = []; 135e484b35bSopenharmony_ci args.forEach((module) => { 136e484b35bSopenharmony_ci for (const key in module) { 137e484b35bSopenharmony_ci funcKeys.push(key); 138e484b35bSopenharmony_ci funcValues.push(module[key]); 139e484b35bSopenharmony_ci } 140e484b35bSopenharmony_ci }); 141e484b35bSopenharmony_ci 142e484b35bSopenharmony_ci // If failed to run code on native, then run code on framework. 143e484b35bSopenharmony_ci if (!compileBundleNative(funcKeys, funcValues, functionCode, file)) { 144e484b35bSopenharmony_ci Log.error(`Compile js bundle failed, typeof code is not 'function'`) 145e484b35bSopenharmony_ci return; 146e484b35bSopenharmony_ci } 147e484b35bSopenharmony_ci} 148e484b35bSopenharmony_ci 149e484b35bSopenharmony_ci/** 150e484b35bSopenharmony_ci * Call a new function generated on the V8 native side. 151e484b35bSopenharmony_ci * @param {string[]} funcKeys 152e484b35bSopenharmony_ci * @param {Function[]} funcValues 153e484b35bSopenharmony_ci * @param {string} functionCode 154e484b35bSopenharmony_ci * @return {boolean} Return true if no error occurred. 155e484b35bSopenharmony_ci */ 156e484b35bSopenharmony_cifunction compileBundleNative(funcKeys: string[], funcValues: Function[], functionCode: string, file: string): boolean { 157e484b35bSopenharmony_ci if (typeof compileAndRunBundle !== 'function') { 158e484b35bSopenharmony_ci return false; 159e484b35bSopenharmony_ci } 160e484b35bSopenharmony_ci 161e484b35bSopenharmony_ci let isSuccess: boolean = false; 162e484b35bSopenharmony_ci const bundle: string = `(function (${funcKeys.toString()}) {${functionCode}})`; 163e484b35bSopenharmony_ci try { 164e484b35bSopenharmony_ci const compileFunction: Function = compileAndRunBundle(bundle, file); 165e484b35bSopenharmony_ci if (compileFunction && typeof compileFunction === 'function') { 166e484b35bSopenharmony_ci compileFunction(...funcValues); 167e484b35bSopenharmony_ci isSuccess = true; 168e484b35bSopenharmony_ci } 169e484b35bSopenharmony_ci } catch (e) { 170e484b35bSopenharmony_ci Log.error(e); 171e484b35bSopenharmony_ci } 172e484b35bSopenharmony_ci return isSuccess; 173e484b35bSopenharmony_ci} 174