Skip to content

Commit adeb422

Browse files
committed
feat: add code generator.
1 parent 6dab9e7 commit adeb422

17 files changed

+234
-112
lines changed

bridge/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ xcschememanagement.plist
22

33
cmake-build-*
44
build
5+
out

bridge/CMakeLists.txt

+10-6
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,10 @@ execute_process(
3434
) # g
3535

3636
execute_process(
37-
COMMAND bash "-c" "node bin/code_generator -s ../../bindings/qjs/dom/elements -d ../../bindings/qjs/dom/elements/.gen"
37+
COMMAND bash "-c" "node bin/code_generator -s ../../core -d ../../out"
3838
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/scripts/code_generator
3939
) # generate elements code
4040

41-
execute_process(
42-
COMMAND bash "-c" "node bin/code_generator -s ../../bindings/qjs/dom/events -d ../../bindings/qjs/dom/events/.gen"
43-
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/scripts/code_generator
44-
) # generate events code
45-
4641
execute_process(
4742
COMMAND bash "-c" "read dart_sdk < <(type -p dart) && echo $\{dart_sdk%/*\}/cache/dart-sdk/include | xargs"
4843
OUTPUT_VARIABLE DART_SDK
@@ -142,6 +137,7 @@ list(APPEND GUMBO_PARSER
142137

143138
list(APPEND BRIDGE_INCLUDE
144139
${CMAKE_CURRENT_LIST_DIR}/foundation
140+
${CMAKE_CURRENT_LIST_DIR}/out
145141
${CMAKE_CURRENT_LIST_DIR}
146142
${CMAKE_CURRENT_LIST_DIR}/include
147143
${CMAKE_CURRENT_LIST_DIR}/polyfill/dist
@@ -221,6 +217,8 @@ if ($ENV{KRAKEN_JS_ENGINE} MATCHES "quickjs")
221217
core/executing_context_data.cc
222218
core/executing_context_data.h
223219
core/dart_methods.h
220+
core/frame/console.cc
221+
core/frame/console.h
224222
core/frame/dom_timer.cc
225223
core/frame/dom_timer.h
226224
core/frame/dom_timer_coordinator.cc
@@ -255,6 +253,12 @@ if ($ENV{KRAKEN_JS_ENGINE} MATCHES "quickjs")
255253
# core/dom/events/event_target.h
256254
)
257255

256+
# Gen sources.
257+
list(APPEND BRIDGE_SOURCE
258+
out/qjs_console.cc
259+
out/qjs_console.h
260+
)
261+
258262
# Quickjs use __builtin_frame_address() to get stack pointer, we should add follow options to get it work with -O2
259263
# https://stackoverflow.com/questions/14735010/how-do-you-get-gccs-builtin-frame-address-to-work-with-o2
260264
add_compile_options(-fno-optimize-sibling-calls -fno-omit-frame-pointer)

bridge/bindings/qjs/binding_initializer.cc

+2-35
Original file line numberDiff line numberDiff line change
@@ -7,47 +7,14 @@
77

88
#include "qjs_window.h"
99
#include "qjs_module_manager.h"
10-
11-
//#include "bindings/qjs/bom/blob.h"
12-
//#include "bindings/qjs/bom/console.h"
13-
//#include "bindings/qjs/bom/location.h"
14-
//#include "bindings/qjs/bom/performance.h"
15-
//#include "bindings/qjs/bom/screen.h"
16-
//#include "bindings/qjs/bom/timer.h"
17-
//#include "bindings/qjs/bom/window.h"
18-
//#include "bindings/qjs/dom/comment_node.h"
19-
//#include "bindings/qjs/dom/custom_event.h"
20-
//#include "bindings/qjs/dom/document.h"
21-
//#include "bindings/qjs/dom/document_fragment.h"
22-
//#include "bindings/qjs/dom/element.h"
23-
//#include "bindings/qjs/dom/elements/.gen/anchor_element.h"
24-
//#include "bindings/qjs/dom/elements/.gen/canvas_element.h"
25-
//#include "bindings/qjs/dom/elements/.gen/input_element.h"
26-
//#include "bindings/qjs/dom/elements/.gen/object_element.h"
27-
//#include "bindings/qjs/dom/elements/.gen/script_element.h"
28-
//#include "bindings/qjs/dom/elements/image_element.h"
29-
//#include "bindings/qjs/dom/elements/template_element.h"
30-
//#include "bindings/qjs/dom/event.h"
31-
//#include "bindings/qjs/dom/event_target.h"
32-
//#include "bindings/qjs/dom/events/.gen/close_event.h"
33-
//#include "bindings/qjs/dom/events/.gen/gesture_event.h"
34-
//#include "bindings/qjs/dom/events/.gen/input_event.h"
35-
//#include "bindings/qjs/dom/events/.gen/intersection_change.h"
36-
//#include "bindings/qjs/dom/events/.gen/media_error_event.h"
37-
//#include "bindings/qjs/dom/events/.gen/message_event.h"
38-
//#include "bindings/qjs/dom/events/.gen/mouse_event.h"
39-
//#include "bindings/qjs/dom/events/.gen/popstate_event.h"
40-
//#include "bindings/qjs/dom/events/touch_event.h"
41-
//#include "bindings/qjs/dom/style_declaration.h"
42-
//#include "bindings/qjs/dom/text_node.h"
43-
//#include "bindings/qjs/module_manager.h"
10+
#include "qjs_console.h"
4411

4512
namespace kraken {
4613

4714
void installBindings(JSContext* ctx) {
4815
QJSWindow::installGlobalFunctions(ctx);
4916
QJSModuleManager::installGlobalFunctions(ctx);
50-
17+
QJSConsole::install(ctx);
5118
}
5219

5320
} // namespace kraken

bridge/bindings/qjs/script_value.cc

+8
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ bool ScriptValue::isEmpty() {
3838
return JS_IsNull(m_value);
3939
}
4040

41+
bool ScriptValue::isString() {
42+
return JS_IsString(m_value);
43+
}
44+
4145
JSValue ScriptValue::toQuickJS() {
4246
return m_value;
4347
}
@@ -60,6 +64,10 @@ std::unique_ptr<NativeString> ScriptValue::toNativeString() {
6064
return jsValueToNativeString(m_ctx, m_value);
6165
}
6266

67+
std::string ScriptValue::toCString() {
68+
return jsValueToStdString(m_ctx, m_value);
69+
}
70+
6371
bool ScriptValue::isException() {
6472
return JS_IsException(m_value);
6573
}

bridge/bindings/qjs/script_value.h

+2
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,12 @@ class ScriptValue final {
4343
JS_FreeValue(m_ctx, m_value);
4444
}
4545
bool isEmpty();
46+
bool isString();
4647
JSValue toQuickJS();
4748
// Create a new ScriptValue from call JSON.stringify to current value.
4849
ScriptValue toJSONStringify(ExceptionState* exception);
4950
std::unique_ptr<NativeString> toNativeString();
51+
std::string toCString();
5052

5153
bool isException();
5254

bridge/core/frame/console.cc

+7-22
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,19 @@
44
*/
55

66
#include "console.h"
7+
#include <sstream>
8+
#include "foundation/logging.h"
79

810
namespace kraken {
911

10-
JSValue print(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv) {
12+
void Console::__kraken_print__(ExecutionContext* context, ScriptValue& logValue, ScriptValue& levelValue, ExceptionState* exception) {
1113
std::stringstream stream;
12-
JSValue log = argv[0];
13-
if (JS_IsString(log)) {
14-
const char* buffer = JS_ToCString(ctx, log);
15-
stream << buffer;
16-
JS_FreeCString(ctx, buffer);
17-
} else {
18-
return JS_ThrowTypeError(ctx, "Failed to execute 'print': log must be string.");
19-
}
2014

21-
auto* context = static_cast<ExecutionContext*>(JS_GetContextOpaque(ctx));
22-
const char* logLevel = "info";
23-
JSValue level = argv[1];
24-
if (JS_IsString(level)) {
25-
logLevel = JS_ToCString(ctx, level);
26-
JS_FreeCString(ctx, logLevel);
27-
}
15+
std::string buffer = logValue.toCString();
16+
stream << buffer;
2817

29-
foundation::printLog(context->getContextId(), stream, logLevel, nullptr);
30-
return JS_UNDEFINED;
31-
}
32-
33-
void bindConsole(ExecutionContext* context) {
34-
QJS_GLOBAL_BINDING_FUNCTION(context, print, "__kraken_print__", 2);
18+
std::string logLevel = levelValue.isEmpty() ? "info" : levelValue.toCString();
19+
printLog(context->getContextId(), stream, logLevel, nullptr);
3520
}
3621

3722
} // namespace kraken

bridge/core/frame/console.d.ts

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
declare const __kraken_print__: (log: string, level?: string) => void;
2+
3+
// @ts-ignore
4+
class EventTarget {
5+
6+
}
7+
8+
// @ts-ignore
9+
class Node extends EventTarget {
10+
11+
}

bridge/core/frame/console.h

+9-5
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,19 @@
33
* Author: Kraken Team.
44
*/
55

6-
#ifndef KRAKENBRIDGE_CONSOLE_H
7-
#define KRAKENBRIDGE_CONSOLE_H
6+
#ifndef KRAKE_CONSOLE_H
7+
#define KRAKE_CONSOLE_H
88

9-
#include "bindings/qjs/executing_context.h"
9+
#include "bindings/qjs/script_value.h"
10+
#include "core/executing_context.h"
1011

1112
namespace kraken {
1213

13-
void bindConsole(ExecutionContext* context);
14+
class Console final {
15+
public:
16+
static void __kraken_print__(ExecutionContext* context, ScriptValue& log, ScriptValue& level, ExceptionState* exception);
17+
};
1418

1519
}
1620

17-
#endif // KRAKENBRIDGE_CONSOLE_H
21+
#endif // KRAKE_CONSOLE_H

bridge/scripts/code_generator/bin/code_generator.js

+9-6
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,22 @@ let files = glob.sync("**/*.d.ts", {
3030
});
3131

3232
let blobs = files.map(file => {
33-
let filename = file.replace('.d.ts', '');
34-
return new Blob(path.join(source, file), dist, filename);
35-
});
33+
let filename = 'qjs_' + file.split('/').slice(-1)[0].replace('.d.ts', '');
34+
let implement = file.replace(path.join(__dirname, '../../')).replace('.d.ts', '');
35+
return new Blob(path.join(source, file), dist, filename, implement);
36+
}).filter(blob => blob.filename === 'qjs_console');
3637

3738
for (let i = 0; i < blobs.length; i ++) {
3839
let b = blobs[i];
3940
let result = analyzer(b);
4041

4142
if (!fs.existsSync(b.dist)) {
42-
fs.mkdirSync(b.dist);
43+
fs.mkdirSync(b.dist, {recursive: true});
4344
}
4445

45-
fs.writeFileSync(path.join(b.dist, b.filename) + '.h', result.header);
46-
fs.writeFileSync(path.join(b.dist, b.filename) + '.cc', result.source);
46+
let genFilePath = path.join(b.dist, b.filename);
47+
48+
fs.writeFileSync(genFilePath + '.h', result.header);
49+
fs.writeFileSync(genFilePath + '.cc', result.source);
4750
}
4851

bridge/scripts/code_generator/src/analyzer.ts

+32-3
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
1-
import ts, {HeritageClause, ScriptTarget} from 'typescript';
1+
import ts, {HeritageClause, ScriptTarget, VariableStatement} from 'typescript';
22
import {Blob} from './blob';
33
import {
44
ClassObject,
55
FunctionArguments,
66
FunctionArgumentType,
77
FunctionDeclaration,
8+
FunctionObject,
89
PropsDeclaration,
9-
PropsDeclarationKind
10+
PropsDeclarationKind,
11+
ReturnType
1012
} from './declaration';
1113
import {generatorSource} from './generator';
1214

1315
export function analyzer(blob: Blob) {
1416
let code = blob.raw;
1517
const sourceFile = ts.createSourceFile(blob.source, blob.raw, ScriptTarget.ES2020);
16-
blob.objects = sourceFile.statements.map(statement => walkProgram(statement)).filter(o => o instanceof ClassObject) as ClassObject[];
18+
blob.objects = sourceFile.statements.map(statement => walkProgram(statement)).filter(o => {
19+
return o instanceof ClassObject || o instanceof FunctionObject;
20+
}) as (FunctionObject | ClassObject)[];
1721
return generatorSource(blob);
1822
}
1923

@@ -48,6 +52,14 @@ function getPropKind(type: ts.TypeNode): PropsDeclarationKind {
4852
return PropsDeclarationKind.object;
4953
}
5054

55+
function getFunctionReturnType(keyword: ts.TypeNode): ReturnType {
56+
switch (keyword.kind) {
57+
case ts.SyntaxKind.VoidKeyword:
58+
return ReturnType.void;
59+
}
60+
return ReturnType.null;
61+
}
62+
5163
function getPropName(propName: ts.PropertyName) {
5264
if (propName.kind == ts.SyntaxKind.Identifier) {
5365
return propName.escapedText.toString();
@@ -149,6 +161,23 @@ function walkProgram(statement: ts.Statement) {
149161

150162
return obj;
151163
}
164+
case ts.SyntaxKind.VariableStatement: {
165+
let declaration = (statement as VariableStatement).declarationList.declarations[0];
166+
let methodName = (declaration.name as ts.Identifier).text;
167+
let type = declaration.type;
168+
let functionObject = new FunctionObject();
169+
170+
functionObject.declare = new FunctionDeclaration();
171+
if (type?.kind == ts.SyntaxKind.FunctionType) {
172+
functionObject.declare.args = (type as ts.FunctionTypeNode).parameters.map(param => paramsNodeToArguments(param));
173+
functionObject.declare.returnType = getFunctionReturnType((type as ts.FunctionTypeNode).type);
174+
functionObject.declare.name = methodName.toString();
175+
}
176+
177+
console.log(functionObject);
178+
179+
return functionObject;
180+
}
152181
}
153182

154183
return null;
+5-3
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
import fs from 'fs';
2-
import {ClassObject} from "./declaration";
2+
import {ClassObject, FunctionObject} from "./declaration";
33

44
export class Blob {
55
raw: string;
66
dist: string;
77
source: string;
88
filename: string;
9-
objects: ClassObject[];
9+
implement: string;
10+
objects: (ClassObject | FunctionObject)[];
1011

11-
constructor(source: string, dist: string, filename: string) {
12+
constructor(source: string, dist: string, filename: string, implement: string) {
1213
this.source = source;
1314
this.raw = fs.readFileSync(source, {encoding: 'utf-8'});
1415
this.dist = dist;
1516
this.filename = filename;
17+
this.implement = implement;
1618
}
1719
}

bridge/scripts/code_generator/src/declaration.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,14 @@ export class PropsDeclaration {
2727
readonly: boolean;
2828
}
2929

30+
export enum ReturnType {
31+
void,
32+
null
33+
}
34+
3035
export class FunctionDeclaration extends PropsDeclaration {
31-
args: FunctionArguments[]
36+
args: FunctionArguments[];
37+
returnType: ReturnType;
3238
}
3339

3440
export class ClassObject {
@@ -37,3 +43,7 @@ export class ClassObject {
3743
props: PropsDeclaration[] = [];
3844
methods: FunctionDeclaration[] = [];
3945
}
46+
47+
export class FunctionObject {
48+
declare: FunctionDeclaration
49+
}

0 commit comments

Comments
 (0)