Skip to content

Commit

Permalink
Merge pull request #365 from wuba/f-provider
Browse files Browse the repository at this point in the history
fair provider adapt
  • Loading branch information
wanbing authored Nov 14, 2023
2 parents 093a1f6 + 8fa8a1d commit 4aac629
Show file tree
Hide file tree
Showing 108 changed files with 6,373 additions and 17 deletions.
8 changes: 8 additions & 0 deletions dart2dsl/lib/fairdsl/fair_ast_gen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,11 @@ class CustomAstVisitor extends SimpleAstVisitor<Map> {
return _buildArgumentList(_visitNodeList(node.arguments));
}

@override
Map visitTypeArgumentList(TypeArgumentList node) {
return _buildTypeArgumentList(_visitNodeList(node.arguments));
}

@override
Map? visitLabel(Label node) {
return _visitNode(node.label);
Expand Down Expand Up @@ -543,6 +548,9 @@ class CustomAstVisitor extends SimpleAstVisitor<Map> {
'body': body,
};

Map _buildTypeArgumentList(List<Map> typeArgumentList) =>
{'type': 'TypeArgumentList', 'typeArgumentList': typeArgumentList};

Map _buildArgumentList(List<Map> argumentList) => {'type': 'ArgumentList', 'argumentList': argumentList};

Map _buildStringLiteral(String value) => {'type': 'StringLiteral', 'value': value};
Expand Down
22 changes: 22 additions & 0 deletions dart2dsl/lib/fairdsl/fair_ast_node.dart
Original file line number Diff line number Diff line change
Expand Up @@ -432,8 +432,10 @@ class MethodInvocation extends AstNode {
Expression? callee;
List<Expression?>? argumentList;
SelectAstClass? selectAstClass;
List<Expression?>? typeArgumentList;

MethodInvocation(this.callee, this.argumentList, this.selectAstClass,
this.typeArgumentList,
{Map? ast})
: super(ast: ast);

Expand All @@ -444,6 +446,7 @@ class MethodInvocation extends AstNode {
Expression.fromAst(ast['callee']),
_parseArgumentList(ast['argumentList']),
SelectAstClass.fromAst(ast['selectAstClass']),
_parseTypeArgumentList(ast['typeArguments']),
ast: ast);
}
return null;
Expand Down Expand Up @@ -1097,6 +1100,7 @@ class Expression extends AstNode {
bool? isVariableDeclaration;
bool? isVariableExpression;
bool? isFuncParam;
bool? isTypeName;

@override
Map? toAst() => _ast;
Expand Down Expand Up @@ -1137,6 +1141,7 @@ class Expression extends AstNode {
this.isVariableDeclaration = false,
this.isVariableExpression = false,
this.isFuncParam =false,
this.isTypeName = false,
Map? ast,
}) : super(ast: ast);

Expand Down Expand Up @@ -1237,6 +1242,8 @@ class Expression extends AstNode {
isInterpolationExpression: true, ast: ast);
} else if (astType == astNodeNameValue(AstNodeName.VariableExpression)) {
return Expression(VariableExpression.fromAst(ast), isVariableExpression: true, ast: ast);
} else if (astType == astNodeNameValue(AstNodeName.TypeName)) {
return Expression(TypeName.fromAst(ast), isTypeName: true, ast: ast);
}
return null;
}
Expand Down Expand Up @@ -1311,6 +1318,8 @@ class Expression extends AstNode {
_expression as InterpolationExpression;

VariableExpression get asVariableExpression => _expression as VariableExpression;

TypeName get asTypeNameExpression => _expression as TypeName;
}

class SelectAstClass {
Expand Down Expand Up @@ -1350,6 +1359,19 @@ List<Expression?> _parseArgumentList(Map? ast) {
return arguments;
}

///解析TypeArgumentList 字段
List<Expression?> _parseTypeArgumentList(Map? ast) {
var arguments = <Expression?>[];
if (ast != null) {
var astTypeArgumentList = ast['typeArgumentList'] as List?;
return astTypeArgumentList
?.map((arg) => Expression.fromAst(arg))
.toList() ??
arguments;
}
return arguments;
}

//num _parseNumericValue(Map ast) {
// num n = 0;
// if (ast['type'] == astNodeNameValue(AstNodeName.NumericLiteral)) {
Expand Down
3 changes: 2 additions & 1 deletion dart2dsl/lib/fairdsl/fair_check_node_map.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,6 @@ final checkNode = {
'ImplementsClauseImpl': 'visitImplementsClause',
'WithClauseImpl': 'visitWithClause',
'PropertyAccessImpl': 'visitPropertyAccess',
'PrefixExpressionImpl': 'visitPrefixExpression'
'PrefixExpressionImpl': 'visitPrefixExpression',
'TypeArgumentListImpl':'visitTypeArgumentList'
};
12 changes: 12 additions & 0 deletions dart2dsl/lib/fairdsl/fair_dsl_gen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ dynamic _buildWidgetDsl(
var dslMap = {};
var paMap = [];
var naMap = {};
var taMap =[];

var methodInvocationExpression = widgetExpression?.asMethodInvocation;
//普通类
Expand Down Expand Up @@ -309,6 +310,13 @@ dynamic _buildWidgetDsl(
}
}

//3.ta
if (methodInvocationExpression.typeArgumentList?.isNotEmpty ?? false) {
taMap.addAll(methodInvocationExpression.typeArgumentList
?.map((ta) => ta?.asTypeNameExpression.name) ??
[]);
}

if (paMap.isNotEmpty) {
dslMap.putIfAbsent('pa', () => paMap);
}
Expand All @@ -317,6 +325,10 @@ dynamic _buildWidgetDsl(
dslMap.putIfAbsent('na', () => naMap);
}

if(taMap.isNotEmpty){
dslMap.putIfAbsent('typeArgumentList', () => taMap);
}

return dslMap;
}

Expand Down
47 changes: 47 additions & 0 deletions fair/assets/fair_core/fair_core.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,28 @@ function _invokeMethod(par) {
if (isNull(func)) {
methodResult = '';
} else {
if (Array.isArray(args)) {
for (let key in args) {
if (args.hasOwnProperty(key)) {
const value = args[key];
if (typeof value === 'object') {
invokeMethodArgsInterceptorManager.handle(value)
//入参被压缩为数组时,确保数组内所有元素经拦截器处理
const innerArgs = value;
for (let innerKey in innerArgs) {
if (innerArgs.hasOwnProperty(innerKey)) {
const innerValue = innerArgs[innerKey];
if (typeof innerValue === 'object') {
invokeMethodArgsInterceptorManager.handle(innerValue)
}
}
}
}
}
}
} else {
console.log('_invokeMethod intercept failed, args is not array');
}
methodResult = func.apply(mClass, args);
}
let result = {
Expand Down Expand Up @@ -183,4 +205,29 @@ const invokeFlutterCommonChannel = (invokeData, callback) => {
});
};

class InvokeMethodArgsInterceptorManager {
constructor() {
this.interceptors = [];
}

// 注册拦截器
use(interceptor) {
if (typeof interceptor === 'function') {
this.interceptors.push(interceptor);
}
}

// 处理对象
handle(object) {
for (const interceptor of this.interceptors) {
// 如果有拦截器返回 true,则停止处理并返回结果
if (interceptor(object) === true) {
return object;
}
}
return object;
}
}

// 创建一个拦截器管理器实例
const invokeMethodArgsInterceptorManager = new InvokeMethodArgsInterceptorManager();
5 changes: 5 additions & 0 deletions fair/lib/fair.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ export 'src/experiment/sugar.dart';
export 'src/module/fair_module.dart';
export 'src/public_type.dart';
export 'src/widget.dart';
export 'src/adapter.dart';
export 'src/internal/bind_data.dart';
export 'src/render/builder.dart';
export 'src/render/domain.dart';
export 'src/render/proxy.dart';
export 'src/runtime/plugin/fair_plugin.dart';
export 'src/runtime/plugin/plugin_dispatcher.dart';
export 'src/runtime/plugin/fair_common_plugin.dart';
Expand Down
22 changes: 22 additions & 0 deletions fair/lib/src/adapter.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import 'package:fair/fair.dart';

//adapt third-party library
abstract class IFairLibraryAdapter{
//provide the generated module
GeneratedModule? provideGeneratedModule();

//provide fair plugins
Map<String, IFairPlugin>? provideFairPlugins();

//provide js plugins
Map<String, String>? provideJSPlugins();

//provide dynamic widget builder
DynamicWidgetBuilderFunction? provideDynamicWidgetBuilder();

//provide fair delegate
Map<String, FairDelegateBuilder>? provideFairDelegate();

//provide fair module
Map<String, FairModuleBuilder>? provideFairModule();
}
77 changes: 65 additions & 12 deletions fair/lib/src/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,12 @@
import 'dart:io';

import 'package:fair/fair.dart';
import 'package:fair/src/internal/bind_data.dart';
import 'package:fair/src/render/builder.dart';
import 'package:fair/src/render/proxy.dart';
import 'package:fair/src/internal/global_state.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

import 'internal/flexbuffer/fair_js_decoder_http_decoder.dart';
import 'state.dart';
import 'type.dart';

/// Application which can update the widget tree through bundle file.
///
Expand Down Expand Up @@ -64,8 +60,7 @@ class FairApp extends InheritedWidget with AppState {
final bool debugShowFairBanner;

/// Define a custom DynamicWidgetBuilder to solve special case
final DynamicWidgetBuilder Function(ProxyMirror? proxyMirror, String? page, BindingData? bound,
{String? bundle})? dynamicWidgetBuilder;
List<DynamicWidgetBuilderFunction?>? dynamicWidgetBuilder;

static final WidgetBuilder _defaultHolder = (BuildContext context) {
return Container(
Expand Down Expand Up @@ -119,12 +114,23 @@ class FairApp extends InheritedWidget with AppState {
properties.add(DiagnosticsProperty<Map<String, String>>('bundle', bundleAlias));
}

static void runApplication(Widget app, {
Map<String, IFairPlugin>? plugins,
Map<String, String>? jsPlugins,
String? package,
List<String>? baseJsSources,
static void runApplication(
Widget app, {
Map<String, IFairPlugin>? plugins,
Map<String, String>? jsPlugins,
String? package,
List<String>? baseJsSources,
List<IFairLibraryAdapter>? adapters,
}) {
if (plugins == null) {
plugins = {};
}
if (jsPlugins == null) {
jsPlugins = {};
}
//init 3rd-library adapter
initFairLibraryAdapter(app, plugins: plugins, jsPlugins: jsPlugins, adapters: adapters);

// WidgetsFlutterBinding.ensureInitialized();
FairPluginDispatcher.registerPlugins(plugins);

Expand All @@ -139,4 +145,51 @@ class FairApp extends InheritedWidget with AppState {
Runtime().loadCoreJs(package: package, jsPlugins: jsPlugins, baseJsSources: baseJsSources).then((value) => runApp(app));
}
}

///[app] FairApp
///[plugins] Fair plugin code with Dart
///[jsPlugins] Fair plugin code with JavaScript
///[adapters] 3rd-party libraries which adapted Fair
static void initFairLibraryAdapter(
Widget app, {
Map<String, IFairPlugin>? plugins,
Map<String, String>? jsPlugins,
List<IFairLibraryAdapter>? adapters,
}) {

if (adapters != null && adapters.isNotEmpty) {
adapters.forEach((element) {

if (element.provideFairPlugins()?.isNotEmpty == true) {
plugins?.addAll(element.provideFairPlugins()!);
}

if (element.provideJSPlugins()?.isNotEmpty == true) {
jsPlugins?.addAll(element.provideJSPlugins()!);
}

if (app is FairApp) {
if (element.provideFairModule() != null) {
app.modules.addAll(element.provideFairModule());
}

if (element.provideGeneratedModule() != null && app.proxy is ProxyMirror) {
(app.proxy as ProxyMirror).addGeneratedBinding(element.provideGeneratedModule()!);
}

if (element.provideFairDelegate() != null) {
GlobalState.instance().addExtBuilder(element.provideFairDelegate());
}

if (element.provideDynamicWidgetBuilder() != null) {
if (app.dynamicWidgetBuilder == null) {
app.dynamicWidgetBuilder = [element.provideDynamicWidgetBuilder()];
} else {
app.dynamicWidgetBuilder!.add(element.provideDynamicWidgetBuilder());
}
}
}
});
}
}
}
17 changes: 17 additions & 0 deletions fair/lib/src/internal/global_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,23 @@ class GlobalState {
_builder = builder;
}

void addExtBuilder(Map<String, FairDelegateBuilder>? extBuilder) {
if (extBuilder != null) {
try {
if (_builder != null) {
_builder?.addAll(extBuilder);
} else {
//when _builder is uninitialized
_builder = extBuilder;
}
} catch (e) {
//caught when thrown “_builder is an unmodifiable map”
extBuilder.addAll(_builder!);
_builder = extBuilder;
}
}
}

static String id(String? prefix) {
return '$prefix#${GlobalState._counter++}';
}
Expand Down
2 changes: 2 additions & 0 deletions fair/lib/src/public_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ typedef FairDelegateBuilder = FairDelegate Function(
typedef FairModuleBuilder = FairModule Function();
typedef PropertyValue<T> = T Function();

typedef DynamicWidgetBuilderFunction = DynamicWidgetBuilder Function(ProxyMirror? proxyMirror, String? page, BindingData? bound, {String? bundle});

/// Interface of bundle loader
abstract class BundleLoader {
/// Load resource data into json object; The path can be either assets key or
Expand Down
Loading

0 comments on commit 4aac629

Please sign in to comment.