1 /*
2 * Copyright (c) 2020 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "presets/render_module.h"
17 #include "ace_log.h"
18 #include "component_factory.h"
19 #include "component_utils.h"
20 #include "directive/descriptor_utils.h"
21 #include "js_app_context.h"
22 #include "js_profiler.h"
23 namespace OHOS {
24 namespace ACELite {
25 const char * const RenderModule::FUNC_CREATE_ELEMENT = "_c";
26 const char * const RenderModule::FUNC_INIT_STYLE_SHEET = "initStyleSheet";
27 const char * const RenderModule::FUNC_LOOP_RENDER = "_l";
28 const char * const RenderModule::FUNC_CONDITIONAL_RENDER = "_i";
29 const int RenderModule::ARG_LENGTH_TAG_ONLY = 1;
30 const int RenderModule::ARG_LENGTH_WITHOUT_OPTIONS = 2;
31 const int RenderModule::ARG_LENGTH_WITH_OPTIONS = 3;
32 const int RenderModule::ARG_LENGTH_RENDER = 2;
33
Init()34 void RenderModule::Init()
35 {
36 CreateNamedFunction(FUNC_CREATE_ELEMENT, CreateElement);
37 CreateNamedFunction(FUNC_LOOP_RENDER, LoopRender);
38 CreateNamedFunction(FUNC_CONDITIONAL_RENDER, ConditionalRender);
39 CreateNamedFunction(FUNC_INIT_STYLE_SHEET, InitStyleSheet);
40 }
41
CreateElement(jerry_value_t tagName,jerry_value_t options,jerry_value_t children)42 jerry_value_t RenderModule::CreateElement(jerry_value_t tagName, jerry_value_t options, jerry_value_t children)
43 {
44 uint16_t tagNameLength = 0;
45 char *componentName = MallocStringOf(tagName, &tagNameLength);
46 if (componentName == nullptr) {
47 return UNDEFINED;
48 }
49 if (tagNameLength == 0) {
50 ace_free(componentName);
51 componentName = nullptr;
52 return UNDEFINED;
53 }
54
55 uint16_t componentNameId = KeyParser::ParseKeyId(componentName, tagNameLength);
56 ace_free(componentName);
57 componentName = nullptr;
58
59 // create component by tag name using factory
60 Component *component = ComponentFactory::CreateComponent(componentNameId, options, children);
61 if (component == nullptr) {
62 // Release all children before we return UNDEFINED to avoid the children becoming ownerless in this case.
63 HILOG_ERROR(HILOG_MODULE_ACE, "Fail to create element because the tag is not supported.");
64 DescriptorUtils::ReleaseDescriptorOrElements(children);
65 return UNDEFINED;
66 }
67
68 // component begin to render
69 bool renderResult = component->Render();
70 if (!renderResult) {
71 // render failed, drop this element by release its all children and itself
72 DescriptorUtils::ReleaseDescriptorOrElements(children);
73 component->Release();
74 delete component;
75 component = nullptr;
76 return UNDEFINED;
77 }
78
79 // render successfully
80 return component->GetNativeElement();
81 }
82
CreateElement(const jerry_value_t func,const jerry_value_t context,const jerry_value_t * args,const jerry_length_t argsNum)83 jerry_value_t RenderModule::CreateElement(const jerry_value_t func,
84 const jerry_value_t context,
85 const jerry_value_t *args,
86 const jerry_length_t argsNum)
87 {
88 jerry_value_t tagName;
89 jerry_value_t options;
90 jerry_value_t children;
91 if (argsNum == ARG_LENGTH_WITH_OPTIONS) {
92 tagName = args[0];
93 options = args[1];
94 const int8_t childrenNum = 2;
95 children = args[childrenNum];
96 } else if (argsNum == ARG_LENGTH_WITHOUT_OPTIONS) {
97 tagName = args[0];
98 if (jerry_value_is_array(args[1])) {
99 options = UNDEFINED;
100 children = args[1];
101 } else {
102 options = args[1];
103 children = UNDEFINED;
104 }
105 } else if (argsNum == ARG_LENGTH_TAG_ONLY) {
106 tagName = args[0];
107 options = UNDEFINED;
108 children = UNDEFINED;
109 } else {
110 HILOG_ERROR(HILOG_MODULE_ACE, "Failed to create element cause by invalid arguments.");
111 return UNDEFINED;
112 }
113
114 return CreateElement(tagName, options, children);
115 }
116
InitStyleSheet(const jerry_value_t func,const jerry_value_t context,const jerry_value_t * args,const jerry_length_t argsNum)117 jerry_value_t RenderModule::InitStyleSheet(const jerry_value_t func,
118 const jerry_value_t context,
119 const jerry_value_t *args,
120 const jerry_length_t argsNum)
121 {
122 AppStyleManager *manager = const_cast<AppStyleManager *>(JsAppContext::GetInstance()->GetStyleManager());
123
124 if (argsNum == 0 || manager == nullptr) {
125 HILOG_ERROR(HILOG_MODULE_ACE, "Failed to initialize style sheet cause by invalid arguments or empty manager!");
126 return jerry_create_boolean(false);
127 }
128 START_TRACING(STYLESHEET_INIT);
129 manager->InitStyleSheet(args[0]);
130 STOP_TRACING();
131 return jerry_create_boolean(true);
132 }
133
LoopRender(const jerry_value_t func,const jerry_value_t context,const jerry_value_t * args,const jerry_length_t length)134 jerry_value_t RenderModule::LoopRender(const jerry_value_t func,
135 const jerry_value_t context,
136 const jerry_value_t *args,
137 const jerry_length_t length)
138 {
139 if (length != ARG_LENGTH_RENDER) {
140 HILOG_ERROR(HILOG_MODULE_ACE,
141 "Failed to LoopRender as the length of arguments invalid. Expect 2 but %{public}d", length);
142 return UNDEFINED;
143 }
144
145 return DescriptorUtils::CreateForDescriptor(args[0], args[1]);
146 }
147
ConditionalRender(const jerry_value_t func,const jerry_value_t context,const jerry_value_t * args,const jerry_length_t argsNum)148 jerry_value_t RenderModule::ConditionalRender(const jerry_value_t func,
149 const jerry_value_t context,
150 const jerry_value_t *args,
151 const jerry_length_t argsNum)
152 {
153 if (argsNum != ARG_LENGTH_RENDER) {
154 HILOG_ERROR(HILOG_MODULE_ACE, "Failed to ConditionalRender cause by invlaid paramters. Expect 2 but %{public}d",
155 argsNum);
156 return UNDEFINED;
157 }
158
159 return DescriptorUtils::CreateIfDescriptor(args[0], args[1]);
160 }
161 } // namespace ACELite
162 } // namespace OHOS
163