58fair 动态化界面逻辑JavaScriptCore js对象的创建与释放

本文研究58fair 动态化界面逻辑js JavascriptCore对象的创建与释放

页面js

一个Fair动态化界面的逻辑js文件实例为:

javascript 复制代码
GLOBAL['test1#1'] = (function(__initProps__) {
    const __global__ = this;
    return runCallback(function(__mod__) { //runCallback 在fair_jsbase.js中定义
        with(__mod__.imports) {
            function _Test5NetPluginState() {
                const inner = _Test5NetPluginState.__inner__;
                if (this == __global__) {
                    return new _Test5NetPluginState({
                        __args__: arguments
                    });
                } else {
                    const args = arguments.length > 0 ? arguments[0].__args__ || arguments : [];
                    inner.apply(this, args);
                    _Test5NetPluginState.prototype.ctor.apply(this, args);
                    return this;
                }
            }
            _Test5NetPluginState.__inner__ = function inner() {
                this._page = 0;
            };
            _Test5NetPluginState.prototype = {
                requestData: function requestData() {
                    const __thiz__ = this;
                    with(__thiz__) {
                        _page++;
                        FairNet.requestData({
                            method: 'GET',
                            url: 'https://wos2.58cdn.com.cn/DeFazYxWvDti/frsupload/3be6c61070d3b48c8165af5d18464c0e_hotel_list_data.json',
                            data: convertObjectLiteralToSetOrMap({
                                ['page']: _page,
                                ['pageName']: 'test1#1',
                            }),
                            success: function dummy(resp) {
                                if (resp == null) {
                                    return null;
                                }
                                let data = resp.__op_idx__('data');
                                setState('test1#1', function dummy() {});
                            }
                        });
                    }
                },
            };
            _Test5NetPluginState.prototype.ctor = function() {};;
            return _Test5NetPluginState();
        }
    }, []);
})(convertObjectLiteralToSetOrMap(JSON.parse('{}')));

其中runCallback方法在全局js fair_base.js中定义:

ini 复制代码
function runCallback(func, deps) { //
  const imports = {};
  const __global__ = this;
  deps.map((d) =>
    typeof d == "number"
      ? runModule(d, { exports: imports })
      : runModule(d[0], { exports: imports }, d[1])
  );
  return func.call(__global__, { imports });
}

分析如上jsScript如下:

  1. GLOBAL['test1#1'] = (function(__initProps__) {...})(convertObjectLiteralToSetOrMap(JSON.parse('{}')));:这行代码定义了一个全局函数 test1#1,该函数的实现是一个自执行的函数。这个自执行的函数接受一个参数 __initProps__,但在这个代码段中,它的值被设置为一个空对象。接下来,这个函数内部使用了一个名为 runCallback 的函数,该函数是从 fair_jsbase.js 中导入的。
  2. runCallback 函数的目的是运行给定的函数 func,并且可以传递一些依赖项。它创建了一个名为 imports 的空对象,并且将当前的全局对象 __global__ 存储在 __global__ 变量中。然后,它循环处理依赖项(在这里没有提供详细信息),对于每个依赖项,它可能会运行模块并将其输出存储在 imports 中。
  3. runCallback 函数的最后,它通过调用 func.call(__global__, { imports }) 来运行传入的函数 func,并且传递了一个包含 imports 对象的参数。
  4. 在这个特定的代码片段中,传给 runCallback 的函数是一个大函数,它定义了一个名为 _Test5NetPluginState 的构造函数和一些方法。这个构造函数似乎用于创建一个对象,该对象可以执行一些网络请求和操作。

总结:这段 JavaScript 代码创建了一个全局函数 test1#1,这个函数的实现是一个自执行的函数,它使用 runCallback 函数来处理依赖项并运行给定的函数。在这个特定的示例中,给定的函数定义了一个构造函数 _Test5NetPluginState 和一些方法,用于执行网络请求等操作。

全局基础通用js

json 复制代码
{
  "coreJs": {
    "fair_core": "packages/fair/assets/fair_core/fair_core.js",
    "fair_jsbase": "packages/fair/assets/fair_core/fair_jsbase.js",
    "fair_common_plugin": "packages/fair/assets/fair_core/fair_common_plugin.js"
  }
}

其他可能添加的通用插件js:

json 复制代码
{
  "plugin": {
  }
}


fair_image_picker.js
fair_log_plugin.js
fair_navigator_plugin.js
fair_net_plugin.js
fair_permission.js
fair_toast_plugin.js
fair_url_launcher_plugin.js

全局js文件是在FairApp即FairWidget顶层Widget中,FairApp初始化静态方法runApplication中调用:

scss 复制代码
Runtime().loadCoreJs(package: package, jsPlugins: jsPlugins, baseJsSources: baseJsSources).then((value) => runApp(app));
  • fair_home.json
  • fair_basic_config.json
  • 以及FairApp 的runApplication方法的jsPlugins参数
  • baseJsSources 参数

这4个地方定义JS文件,文件读取为字符串拼装成一个大jsSource内容,所有基础的全局js方法都在这里加载了:

arduino 复制代码
 
map[FairMessage.PATH] = baseJsSource + ' ; ' + pluginJsSource;
map[FairMessage.PAGE_NAME] = 'loadCoreJs';

return _channel!.loadJS(jsonEncode(map), null);
 

调用channel:_methodChannel!.invokeMethod('loadMainJs', args);

对应的native执行为:

ini 复制代码
// 异步注入到JSContext里
[[FairJSBridge sharedInstance] evaluateScriptWithJSScriptAsync:JSScript callback:callback];


JSValue *jsValue = [self.context evaluateScript:jsScript];

FairWidget展示时候:注入页面js

在FairWidget state的didChangeDependencies 中调用:

_mFairApp.runtime.addScript(state2key, resolveJS, widget.data):

ini 复制代码
var map = <dynamic, dynamic>{};
map[FairMessage.PATH] = scriptSource;
map[FairMessage.PAGE_NAME] = pageName;
return _channel!.loadJS(jsonEncode(map), null);

对应跳转到Native执行注入JS:

scss 复制代码
- (JSValue *)evaluateScript:(NSString *)jsScript callback:(FairCallback)callback
{
	JSValue *jsValue = [self.context evaluateScript:jsScript]; //GLOBAL['test1#1']=(函数)(json对象)
	if (callback) {
		callback(jsValue, nil);
	}
	return jsValue;
}

FairWidget页面关闭时候释放 JS:

在 FairState的dispose方法中释放资源:

runtime.release(key);

ini 复制代码
@override
void release(String? pageName) {
	var map = <dynamic, dynamic>{};
	map[FairMessage.FUNC_NAME] = FairMessage.RELEASE_JS;
	var msg = FairMessage(pageName, FairMessage.METHOD, map);
	_channel?.release(jsonEncode(msg.from()), null);
}

对应native实现为:

objectivec 复制代码
- (void)disposePage:(NSString *)pageName
{
	if (FAIR_IS_NOT_EMPTY_STRING(pageName)) {
		self.context[pageName] = nil; //test1#2
	}
}

JS注入与释放

self.context[pageName] = nil // pageName:"test1#1"

[self.context evaluateScript:jsScript] //jsScript:GLOBAL['test1#1'] = (function(__initProps__) {...})(convertObjectLiteralToSetOrMap(JSON.parse('{}')));

通过这样的成对配置,就完成了Javascript GLOBAL对象的创建与释放,避免了内存的泄漏。

相关推荐
m0_7482478015 分钟前
Flutter Intl包使用指南:实现国际化和本地化
前端·javascript·flutter
Code&Ocean26 分钟前
iOS从Matter的设备认证证书中获取VID和PID
ios·matter·chip
/**书香门第*/27 分钟前
Laya ios接入goole广告,开始接入 2
ios
迷雾漫步者1 小时前
Flutter组件————PageView
flutter·跨平台·dart
迷雾漫步者9 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
coder_pig13 小时前
📝小记:Ubuntu 部署 Jenkins 打包 Flutter APK
flutter·ubuntu·jenkins
捡芝麻丢西瓜16 小时前
flutter自学笔记5- dart 编码规范
flutter·dart
恋猫de小郭16 小时前
什么?Flutter 可能会被 SwiftUI/ArkUI 化?全新的 Flutter Roadmap
flutter·ios·swiftui
网安墨雨20 小时前
iOS应用网络安全之HTTPS
web安全·ios·https
福大大架构师每日一题21 小时前
37.1 prometheus管理接口源码讲解
ios·iphone·prometheus