├── .gitattributes ├── .github └── workflows │ └── swift.yml ├── .gitignore ├── LICENSE ├── Package.swift ├── README.md ├── Sources ├── QuickJS │ ├── JSContext.swift │ ├── JSContextWrapper.swift │ ├── JSFunction.swift │ ├── JSModule.swift │ ├── JSRunloop.swift │ ├── JSRuntime.swift │ └── JSValue.swift └── QuickJSC │ ├── .gitignore │ ├── cutils.c │ ├── include │ ├── cutils.h │ ├── libregexp-opcode.h │ ├── libregexp.h │ ├── libunicode-table.h │ ├── libunicode.h │ ├── list.h │ ├── module.modulemap │ ├── quickjs-atom.h │ ├── quickjs-libc.h │ ├── quickjs-opcode.h │ └── quickjs.h │ ├── libregexp.c │ ├── libunicode.c │ ├── quickjs-libc.c │ └── quickjs.c └── Tests ├── LinuxMain.swift └── QuickJSTests ├── QuickJSTests.swift ├── RunloopTests.swift └── XCTestManifests.swift /.gitattributes: -------------------------------------------------------------------------------- 1 | Sources/QuickJSC/* linguist-vendored 2 | -------------------------------------------------------------------------------- /.github/workflows/swift.yml: -------------------------------------------------------------------------------- 1 | name: Swift 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: macos-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: Build 17 | run: swift build -v 18 | - name: Run tests 19 | run: swift test -v 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /.swiftpm 5 | /*.xcodeproj 6 | xcuserdata/ 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 zqqf16 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.3 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "QuickJS", 8 | products: [ 9 | // Products define the executables and libraries a package produces, and make them visible to other packages. 10 | .library( 11 | name: "QuickJS", 12 | targets: ["QuickJS"]), 13 | ], 14 | dependencies: [ 15 | // Dependencies declare other packages that this package depends on. 16 | // .package(url: /* package url */, from: "1.0.0"), 17 | ], 18 | targets: [ 19 | // Targets are the basic building blocks of a package. A target can define a module or a test suite. 20 | // Targets can depend on other targets in this package, and on products in packages this package depends on. 21 | .target( 22 | name: "QuickJSC", 23 | dependencies: [], 24 | path: "Sources/QuickJSC"), 25 | .target( 26 | name: "QuickJS", 27 | dependencies: ["QuickJSC"]), 28 | .testTarget( 29 | name: "QuickJSTests", 30 | dependencies: ["QuickJS"]), 31 | ] 32 | ) 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QuickJS-Swift 2 | 3 | ![CI Status](https://github.com/zqqf16/QuickJS-Swift/actions/workflows/swift.yml/badge.svg) 4 | 5 | Swift bindings to QuickJS. Using **NSRunloop** to implement asynchronization. 6 | 7 | ### Usage 8 | 9 | #### Execute javascript code 10 | 11 | ```swift 12 | import QuickJS 13 | 14 | let runtime = JSRuntime()! 15 | let context = runtime.createContext()! 16 | 17 | let jsCode = "var i = 10; i;" 18 | let result = context.eval(jsCode).int 19 | print("Result is \(result!)") //10 20 | ``` 21 | 22 | #### Create a native module 23 | 24 | ```swift 25 | import QuickJS 26 | 27 | let runtime = JSRuntime()! 28 | let context = runtime.createContext()! 29 | 30 | // Create a module named "Magic" with two functions "getMagic" and "getMagic2" 31 | context.module("Magic") { 32 | JSModuleFunction("getMagic", argc: 0) { context, this, argc, argv in 33 | return 10 34 | } 35 | JSModuleFunction("getMagic2", argc: 0) { context, this, argc, argv in 36 | return 20 37 | } 38 | } 39 | 40 | let getMagic = """ 41 | "use strict"; 42 | import { getMagic, getMagic2 } from 'Magic' 43 | globalThis.magic = getMagic(); 44 | globalThis.magic2 = getMagic2(); 45 | """ 46 | 47 | context.eval(getMagic, type: .module) 48 | 49 | let magic = context.eval("magic;").int 50 | print("Magic is \(magic!)") //10 51 | 52 | let magic2 = context.eval("magic2;").int 53 | print("Magic2 is \(magic2!)") //20 54 | ``` 55 | 56 | #### Runloop 57 | 58 | ```swift 59 | let runtime = JSRuntime()! 60 | let context = runtime.createContext()! 61 | context.enableRunloop() 62 | 63 | let jsCode = """ 64 | "use strict"; 65 | import * as rl from "Runloop"; 66 | rl.setTimeout(function(){ console.log("Hello Runloop"); }, 3000); 67 | """ 68 | 69 | let _ = context.eval(jsCode, type: .module) 70 | 71 | // waiting for 3 seconds 72 | // Hello Runloop 73 | ``` 74 | 75 | ### Swift Package Manager 76 | 77 | Add this dependency to your `Package.swift` file: 78 | 79 | ```swift 80 | .package(url: "https://github.com/zqqf16/QuickJS-Swift.git", .branch("master")), 81 | ``` 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /Sources/QuickJS/JSContext.swift: -------------------------------------------------------------------------------- 1 | // QuickJS Swift 2 | // 3 | // Copyright (c) 2021 zqqf16 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | import Foundation 24 | import QuickJSC 25 | 26 | public class JSContext { 27 | let core: JSContextWrapper 28 | let runtime: JSRuntime 29 | 30 | required init?(_ runtime: JSRuntime, context: OpaquePointer) { 31 | self.runtime = runtime 32 | self.core = JSContextWrapper(context) 33 | self.core.opaque = self 34 | } 35 | 36 | public enum EvalType: Int32 { 37 | case global = 0 38 | case module = 1 39 | } 40 | 41 | @discardableResult 42 | public func eval(_ jsCode: String, type: EvalType = .global) -> JSValue { 43 | let value = JS_Eval(core.context, jsCode, jsCode.lengthOfBytes(using: .utf8), "", type.rawValue) 44 | return JSValue(core, value: value) 45 | } 46 | 47 | @discardableResult 48 | public func call(function: JSValue, argc: Int, argv: JSCValuePointer?) -> JSValue { 49 | let result = JS_Call(core.context, function.cValue, .undefined, Int32(argc), argv) 50 | let obj = JSValue(core, value: result) 51 | if (obj.isException) { 52 | if let exception = self.getException() { 53 | print(exception) 54 | } 55 | } 56 | 57 | return obj 58 | } 59 | 60 | // MARK: Property 61 | public func setGlobalProperty(name: String, value: String) { 62 | let globalObj = JS_GetGlobalObject(core.context) 63 | let jsValue = JS_NewString(core.context, value.cString(using: .utf8)) 64 | JS_SetPropertyStr(core.context, globalObj, name.cString(using: .utf8), jsValue) 65 | 66 | JS_FreeValue(core.context, globalObj) 67 | } 68 | 69 | public func hasGlobalProperty(name: String) -> Bool { 70 | let globalObj = JS_GetGlobalObject(core.context) 71 | 72 | let jsValue = JS_GetPropertyStr(core.context, globalObj, name.cString(using: .ascii)) 73 | 74 | defer { 75 | JS_FreeValue(core.context, jsValue) 76 | JS_FreeValue(core.context, globalObj) 77 | } 78 | 79 | if JS_IsException(jsValue) != 0 || JS_IsUndefined(jsValue) != 0 { 80 | return false 81 | } 82 | 83 | return true 84 | } 85 | 86 | // MARK: Module 87 | private var modules: [OpaquePointer: JSModule] = [:] 88 | private func loadModule(_ cModule: OpaquePointer) { 89 | guard let module = self.modules[cModule] else { 90 | return 91 | } 92 | module.load() 93 | } 94 | 95 | static let JS_ModuleInit: JSModuleInitFunction = { (ctx, m) in 96 | guard let ctx = ctx, 97 | let m = m, 98 | let context = ctx.opaqueContext else { 99 | return -1 100 | } 101 | 102 | context.loadModule(m) 103 | return 0; 104 | } 105 | 106 | @discardableResult 107 | public func module(_ name: String, @ModuleBuilder _ propertyBuilder: () -> JSModuleProperty) -> T? { 108 | guard let cModule = JS_NewCModule(core.context, name, JSContext.JS_ModuleInit) else { 109 | return nil 110 | } 111 | 112 | let module = T(self.core, module: cModule, name: name, propertyBuilder) 113 | self.modules[cModule] = module 114 | return module 115 | } 116 | 117 | func flushPendingJobs() { 118 | var ctx: OpaquePointer? 119 | while true { 120 | if JS_ExecutePendingJob(self.runtime.jsInstance, &ctx) <= 0 { 121 | break 122 | } 123 | } 124 | } 125 | 126 | // Exception 127 | public func getException() -> String? { 128 | let exception = JS_GetException(core.context) 129 | defer { 130 | JS_FreeValue(core.context, exception) 131 | } 132 | 133 | let description = String(self.core, value: exception) 134 | if JS_IsError(core.context, exception) == 0 { 135 | return description 136 | } 137 | 138 | let stack = JS_GetPropertyStr(core.context, exception, "stack") 139 | defer { 140 | JS_FreeValue(core.context, stack) 141 | } 142 | 143 | let stackStr = String(self.core, value: stack) 144 | if description == nil { 145 | return stackStr 146 | } 147 | 148 | if stackStr == nil { 149 | return description 150 | } 151 | 152 | return "\(description!)\n\(stackStr!)" 153 | } 154 | 155 | // Runloop 156 | public func enableRunloop() { 157 | let _: JSRunloop? = self.module("Runloop", {}) 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /Sources/QuickJS/JSContextWrapper.swift: -------------------------------------------------------------------------------- 1 | // QuickJS Swift 2 | // 3 | // Copyright (c) 2021 zqqf16 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | import Foundation 24 | import QuickJSC 25 | 26 | extension OpaquePointer { 27 | var opaqueContext: JSContext? { 28 | get { 29 | guard let ptr = JS_GetContextOpaque(self) else { 30 | return nil 31 | } 32 | return Unmanaged.fromOpaque(ptr).takeUnretainedValue() 33 | } 34 | set { 35 | if let jsContext = newValue { 36 | let ptr = Unmanaged.passUnretained(jsContext).toOpaque() 37 | JS_SetContextOpaque(self, ptr) 38 | } else { 39 | JS_SetContextOpaque(self, nil) 40 | } 41 | } 42 | } 43 | } 44 | 45 | public class JSContextWrapper { 46 | var context: OpaquePointer 47 | 48 | init(_ context: OpaquePointer) { 49 | self.context = context 50 | } 51 | 52 | deinit { 53 | JS_FreeContext(context) 54 | } 55 | 56 | var opaque: JSContext? { 57 | get { 58 | return context.opaqueContext 59 | } 60 | set { 61 | context.opaqueContext = newValue 62 | } 63 | } 64 | } 65 | 66 | // Alloc & Free 67 | extension JSContextWrapper { 68 | func free(_ value: JSCValue) { 69 | JS_FreeValue(context, value) 70 | } 71 | 72 | func dup(_ value: JSCValue) -> JSCValue { 73 | return JS_DupValue(context, value) 74 | } 75 | 76 | func object() -> JSValue { 77 | let obj = JS_NewObject(context) 78 | return JSValue(self, value: obj) 79 | } 80 | } 81 | 82 | // MARK: Function 83 | extension JSContextWrapper { 84 | func function(_ function: @escaping JSCFunctionData, argc: Int32, magic: Int32, length: Int32, data: JSCValuePointer?) -> JSCValue { 85 | return JS_NewCFunctionData(context, function, argc, magic, length, data) 86 | } 87 | } 88 | 89 | // MARK: Module 90 | extension JSContextWrapper { 91 | func addExport(module: OpaquePointer, name: String) { 92 | JS_AddModuleExport(context, module, name) 93 | } 94 | 95 | func setExport(module: OpaquePointer, name: String, value: JSCValue) { 96 | JS_SetModuleExport(context, module, name, value) 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Sources/QuickJS/JSFunction.swift: -------------------------------------------------------------------------------- 1 | // QuickJS Swift 2 | // 3 | // Copyright (c) 2021 zqqf16 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | import Foundation 24 | import QuickJSC 25 | 26 | public typealias JSModuleInitFunction = @convention(c) (OpaquePointer?, OpaquePointer?) -> CInt 27 | 28 | public typealias JSCFunction = @convention(c) (_ ctx: OpaquePointer?, _ this: JSCValue, _ argc: Int32, _ argv: JSCValuePointer?) -> JSCValue 29 | 30 | public typealias JSCFunctionData = @convention(c) (_ ctx: OpaquePointer?, _ this: JSCValue, _ argc: Int32, _ argv: JSCValuePointer?, _ magic: Int32, _ data: JSCValuePointer?) -> JSCValue 31 | 32 | public class JSFunction : JSValue { 33 | public typealias Block = (_ context: JSContext, _ this: JSValue, _ argc: Int, _ argv: JSCValuePointer?) -> ConvertibleWithJavascript? 34 | 35 | public var name: String 36 | public var argc: Int32 37 | 38 | private var block: Block 39 | private var functionData: JSValue? 40 | 41 | override var context: JSContextWrapper? { 42 | didSet { 43 | if context != nil { 44 | self.buildFunction() 45 | } 46 | } 47 | } 48 | 49 | init(_ context: JSContextWrapper?, name: String, argc: Int32, block: @escaping Block) { 50 | self.name = name 51 | self.argc = argc 52 | self.block = block 53 | super.init(context, value: .undefined, autoFree: false) 54 | 55 | if context != nil { 56 | self.buildFunction() 57 | } 58 | } 59 | 60 | required init(_ context: JSContextWrapper?, value: JSCValue, dup: Bool = false, autoFree: Bool = true) { 61 | fatalError("init(_:value:dup:autoFree) has not been implemented") 62 | } 63 | 64 | func buildFunction() { 65 | guard let context = self.context else { 66 | return 67 | } 68 | 69 | self.functionData = context.object() 70 | 71 | let dataFunction: JSCFunctionData = { (ctx, this, argc, argv, magic, data) -> JSCValue in 72 | guard let _ = ctx?.opaqueContext, 73 | let funcData = data, 74 | let mySelfPtr = JS_GetOpaque(funcData[0], 1) 75 | else { 76 | return .undefined 77 | } 78 | 79 | let mySelf = Unmanaged.fromOpaque(mySelfPtr).takeUnretainedValue() 80 | return mySelf.callRealFunction(ctx, this, argc, argv, magic, data) 81 | } 82 | 83 | self.functionData!.setOpaque(self) 84 | self.cValue = context.function(dataFunction, argc: argc, magic: 0, length: 1, data: &(self.functionData!.cValue)) 85 | } 86 | 87 | func callRealFunction(_ ctx: OpaquePointer?, _ this: JSCValue, _ argc: Int32, _ argv: JSCValuePointer?, _ magic: Int32, _ data: JSCValuePointer?) -> JSCValue { 88 | guard let context = ctx?.opaqueContext else { 89 | return .undefined 90 | } 91 | 92 | let thisObj = JSValue(context.core, value: this, dup: true) 93 | if let result = self.block(context, thisObj, Int(argc), argv) { 94 | return result.jsValue(context.core).cValue 95 | } 96 | return .undefined 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Sources/QuickJS/JSModule.swift: -------------------------------------------------------------------------------- 1 | // QuickJS Swift 2 | // 3 | // Copyright (c) 2021 zqqf16 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | import Foundation 24 | import QuickJSC 25 | 26 | 27 | public protocol JSModuleProperty { 28 | var name: String { get } 29 | var jsValue: JSCValue { get } 30 | 31 | func add(toContext context: JSContextWrapper) 32 | } 33 | 34 | public class JSModuleFunction : JSFunction, JSModuleProperty { 35 | required public init(_ name: String, argc: Int32, block: @escaping Block) { 36 | super.init(nil, name: name, argc: argc, block: block) 37 | } 38 | 39 | required init(_ context: JSContextWrapper?, value: JSCValue, dup: Bool = false, autoFree: Bool = true) { 40 | fatalError("init(_:value:dup:autoFree) has not been implemented") 41 | } 42 | 43 | public var jsValue: JSCValue { 44 | return self.cValue 45 | } 46 | 47 | public func add(toContext context: JSContextWrapper) { 48 | self.context = context 49 | } 50 | } 51 | 52 | fileprivate struct JSModuleCombineProperty : JSModuleProperty { 53 | var jsValue: JSCValue = .undefined 54 | var name: String 55 | var children: [JSModuleProperty] 56 | 57 | init(_ children: [JSModuleProperty]) { 58 | self.name = "" 59 | self.children = children 60 | } 61 | 62 | func add(toContext context: JSContextWrapper) { 63 | self.children.forEach { obj in 64 | obj.add(toContext: context) 65 | } 66 | } 67 | } 68 | 69 | @resultBuilder 70 | public struct ModuleBuilder { 71 | public static func buildBlock(_ components: JSModuleProperty...) -> JSModuleProperty { 72 | return JSModuleCombineProperty(components) 73 | } 74 | } 75 | 76 | public class JSModule { 77 | public var name: String 78 | var properties: [String: JSModuleProperty] = [:] 79 | 80 | var context: JSContextWrapper? 81 | var jsInstance: OpaquePointer 82 | 83 | required init(_ context: JSContextWrapper, module: OpaquePointer, name: String, @ModuleBuilder _ propertyBuilder: () -> JSModuleProperty) { 84 | self.jsInstance = module 85 | self.context = context 86 | self.name = name 87 | 88 | let property = propertyBuilder() 89 | if property is JSModuleCombineProperty { 90 | let children = (property as! JSModuleCombineProperty).children 91 | children.forEach { obj in 92 | self.properties[obj.name] = obj 93 | } 94 | } else { 95 | self.properties[property.name] = property 96 | } 97 | 98 | self.properties.forEach { (key, value) in 99 | value.add(toContext: self.context!) 100 | self.addExport(key) 101 | } 102 | } 103 | 104 | public func function(_ name: String, argc: Int32, block: @escaping JSFunction.Block) { 105 | let function = JSModuleFunction(name, argc: argc, block: block) 106 | function.add(toContext: self.context!) 107 | self.properties[name] = function 108 | self.addExport(name) 109 | } 110 | 111 | func addExport(_ name: String) { 112 | context?.addExport(module: jsInstance, name: name) 113 | } 114 | 115 | func load() { 116 | self.properties.forEach { (key, value) in 117 | context?.setExport(module: jsInstance, name: key, value: value.jsValue) 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /Sources/QuickJS/JSRunloop.swift: -------------------------------------------------------------------------------- 1 | // QuickJS Swift 2 | // 3 | // Copyright (c) 2021 zqqf16 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | import Foundation 24 | import QuickJSC 25 | 26 | struct JSRunloopTimer { 27 | var context: OpaquePointer 28 | var argc: Int32 29 | var argv: UnsafeMutablePointer 30 | } 31 | 32 | final class JSRunloop : JSModule { 33 | var runloop: RunLoop 34 | 35 | required init(_ context: JSContextWrapper, module: OpaquePointer, name: String, @ModuleBuilder _ propertyBuilder: () -> JSModuleProperty) { 36 | runloop = RunLoop.current 37 | super.init(context, module: module, name: "Runloop", propertyBuilder) 38 | self.addObserver() 39 | self.registerFunctions() 40 | } 41 | 42 | func registerFunctions() { 43 | self.function("setTimeout", argc: 2) { [weak self] context, this, argc, argv in 44 | guard let self = self else { return nil } 45 | self.scheduleTimer(argc, argv) 46 | return nil 47 | } 48 | } 49 | 50 | func addObserver() { 51 | let observer = CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault, CFRunLoopActivity.allActivities.rawValue, true, 0) { [weak self] ob, ac in 52 | guard let self = self else { 53 | return 54 | } 55 | if ac == .beforeTimers { 56 | self.context?.opaque?.flushPendingJobs() 57 | } 58 | } 59 | let cfRunloop = self.runloop.getCFRunLoop() 60 | CFRunLoopAddObserver(cfRunloop, observer, .defaultMode) 61 | } 62 | 63 | func scheduleTimer(_ argc: Int, _ argv: JSCValuePointer?) { 64 | guard let context = self.context, 65 | let arguments = argv, 66 | argc >= 2 67 | else { 68 | return 69 | } 70 | 71 | let function = JSValue(context, value: arguments[0], dup: true) 72 | if !function.isFunction { 73 | return 74 | } 75 | 76 | let interval = JSValue(context, value: arguments[1], dup: true).double ?? 0 77 | 78 | if #available(macOS 10.12, *) { 79 | let timer = Timer(timeInterval: interval/1000, repeats: false) { timer in 80 | context.opaque?.call(function: function, argc: argc-2, argv: arguments+2) 81 | } 82 | self.runloop.add(timer, forMode: .default) 83 | } else { 84 | assert(false, "Upgrade your mac version") 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /Sources/QuickJS/JSRuntime.swift: -------------------------------------------------------------------------------- 1 | // QuickJS Swift 2 | // 3 | // Copyright (c) 2021 zqqf16 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | import Foundation 24 | import QuickJSC 25 | 26 | public class JSRuntime { 27 | public var jsInstance: OpaquePointer 28 | 29 | static let contextBuilder: @convention(c) (OpaquePointer?) -> OpaquePointer? = { rt in 30 | guard let ctx = JS_NewContext(rt) else { 31 | return nil 32 | } 33 | 34 | let _ = js_init_module_std(ctx, "std") 35 | let _ = js_init_module_std(ctx, "os") 36 | js_std_add_helpers(ctx, -1, nil) 37 | 38 | return ctx 39 | } 40 | 41 | public init?() { 42 | guard let runtime = JS_NewRuntime() else { 43 | return nil 44 | } 45 | self.jsInstance = runtime 46 | js_std_set_worker_new_context_func(JSRuntime.contextBuilder); 47 | js_std_init_handlers(runtime); 48 | JS_SetModuleLoaderFunc(runtime, nil, js_module_loader, nil); 49 | } 50 | 51 | deinit { 52 | JS_FreeRuntime(self.jsInstance) 53 | } 54 | 55 | public func createContext() -> JSContext? { 56 | if let context = JSRuntime.contextBuilder(self.jsInstance) { 57 | return JSContext(self, context: context) 58 | } 59 | return nil 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Sources/QuickJS/JSValue.swift: -------------------------------------------------------------------------------- 1 | // QuickJS Swift 2 | // 3 | // Copyright (c) 2021 zqqf16 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | import Foundation 24 | import QuickJSC 25 | 26 | public typealias JSCValue = QuickJSC.JSValue 27 | public typealias JSCValuePointer = UnsafeMutablePointer 28 | 29 | // MARK: - JSValue 30 | 31 | extension JSCValue { 32 | static var null: JSCValue { 33 | return JSCValue(u: JSValueUnion(int32: 0), tag: Int64(JS_TAG_NULL)) 34 | } 35 | 36 | static var undefined: JSCValue { 37 | return JSCValue(u: JSValueUnion(int32: 0), tag: Int64(JS_TAG_UNDEFINED)) 38 | } 39 | } 40 | 41 | public class JSValue { 42 | var cValue: JSCValue 43 | var context: JSContextWrapper? 44 | var autoFree: Bool = true 45 | 46 | required init(_ context: JSContextWrapper?, value: JSCValue, dup: Bool = false, autoFree: Bool = true) { 47 | self.context = context 48 | if dup { 49 | self.cValue = self.context!.dup(value) 50 | } 51 | self.cValue = value 52 | self.autoFree = autoFree 53 | } 54 | 55 | func setOpaque(_ obj: T) { 56 | let ptr = Unmanaged.passUnretained(obj).toOpaque() 57 | JS_SetOpaque(cValue, ptr) 58 | } 59 | 60 | func getOpaque() -> T? { 61 | if let ptr = JS_GetOpaque(cValue, 1) { 62 | return Unmanaged.fromOpaque(ptr).takeUnretainedValue() 63 | } 64 | return nil 65 | } 66 | 67 | deinit { 68 | if autoFree { 69 | context?.free(cValue) 70 | } 71 | } 72 | } 73 | 74 | extension JSValue { 75 | static var undefined: JSValue { 76 | return JSValue(nil, value: .undefined) 77 | } 78 | static var null: JSValue { 79 | return JSValue(nil, value: .null) 80 | } 81 | } 82 | 83 | extension JSValue { 84 | var isFunction: Bool { 85 | guard let context = context?.context else { return false } 86 | return JS_IsFunction(context, cValue) != 0 87 | } 88 | 89 | var isException: Bool { 90 | return JS_IsException(cValue) != 0 91 | } 92 | 93 | func getValue() -> T? { 94 | return context != nil ? T(context!, value: cValue) : nil 95 | } 96 | 97 | var double: Double? { 98 | guard self.context != nil else { return nil } 99 | return self.getValue() 100 | } 101 | 102 | var int: Int? { 103 | guard self.context != nil else { return nil } 104 | return self.getValue() 105 | } 106 | 107 | var string: String? { 108 | guard self.context != nil else { return nil } 109 | return self.getValue() 110 | } 111 | 112 | var error: JSError? { 113 | guard self.context != nil else { return nil } 114 | return self.getValue() 115 | } 116 | } 117 | 118 | // MARK: Swift Types 119 | 120 | public protocol ConvertibleWithJavascript { 121 | init?(_ context: JSContextWrapper, value: JSCValue) 122 | func jsValue(_ context: JSContextWrapper) -> JSValue 123 | } 124 | 125 | extension ConvertibleWithJavascript { 126 | public func jsValue(_ context: JSContextWrapper) -> JSValue { 127 | return .undefined 128 | } 129 | } 130 | 131 | extension String: ConvertibleWithJavascript { 132 | public init?(_ context: JSContextWrapper, value: JSCValue) { 133 | if let cString = JS_ToCString(context.context, value) { 134 | self.init(cString: cString) 135 | JS_FreeCString(context.context, cString) 136 | } else { 137 | return nil 138 | } 139 | } 140 | 141 | public func jsValue(_ context: JSContextWrapper) -> JSValue { 142 | let value = JS_NewString(context.context, self) 143 | return JSValue(context, value: value) 144 | } 145 | } 146 | 147 | extension Int32: ConvertibleWithJavascript { 148 | public init?(_ context: JSContextWrapper, value: JSCValue) { 149 | if JS_IsNumber(value) == 0 { 150 | return nil 151 | } 152 | 153 | var pres: Int32 = 0 154 | if JS_ToInt32(context.context, &pres, value) < 0 { 155 | return nil 156 | } 157 | self = pres 158 | } 159 | 160 | public func jsValue(_ context: JSContextWrapper) -> JSValue { 161 | let value = JS_NewInt32(context.context, self) 162 | return JSValue(context, value: value) 163 | } 164 | } 165 | 166 | extension UInt32: ConvertibleWithJavascript { 167 | public init?(_ context: JSContextWrapper, value: JSCValue) { 168 | if JS_IsNumber(value) == 0 { 169 | return nil 170 | } 171 | 172 | var pres: UInt32 = 0 173 | if JS_ToUint32(context.context, &pres, value) < 0 { 174 | return nil 175 | } 176 | self = pres 177 | } 178 | 179 | public func jsValue(_ context: JSContextWrapper) -> JSValue { 180 | let value = JS_NewUint32(context.context, self) 181 | return JSValue(context, value: value) 182 | } 183 | } 184 | 185 | extension Int64: ConvertibleWithJavascript { 186 | public init?(_ context: JSContextWrapper, value: JSCValue) { 187 | if JS_IsNumber(value) == 0 { 188 | return nil 189 | } 190 | 191 | var pres: Int64 = 0 192 | if JS_ToInt64(context.context, &pres, value) < 0 { 193 | return nil 194 | } 195 | self = pres 196 | } 197 | 198 | public func jsValue(_ context: JSContextWrapper) -> JSValue { 199 | let value = JS_NewInt64(context.context, self) 200 | return JSValue(context, value: value) 201 | } 202 | } 203 | 204 | extension Int: ConvertibleWithJavascript { 205 | public init?(_ context: JSContextWrapper, value: JSCValue) { 206 | guard let valueIn64 = Int64(context, value: value) else { 207 | return nil 208 | } 209 | self = .init(valueIn64) 210 | } 211 | 212 | public func jsValue(_ context: JSContextWrapper) -> JSValue { 213 | return Int64(self).jsValue(context) 214 | } 215 | } 216 | 217 | extension UInt: ConvertibleWithJavascript { 218 | public init?(_ context: JSContextWrapper, value: JSCValue) { 219 | guard let valueIn32 = UInt32(context, value: value) else { 220 | return nil 221 | } 222 | self = .init(valueIn32) 223 | } 224 | 225 | public func jsValue(_ context: JSContextWrapper) -> JSValue { 226 | return UInt32(self).jsValue(context) 227 | } 228 | } 229 | 230 | extension Double: ConvertibleWithJavascript { 231 | public init?(_ context: JSContextWrapper, value: JSCValue) { 232 | if JS_IsNumber(value) == 0 { 233 | return nil 234 | } 235 | 236 | var pres: Double = 0 237 | if JS_ToFloat64(context.context, &pres, value) < 0 { 238 | return nil 239 | } 240 | self = pres 241 | } 242 | 243 | public func jsValue(_ context: JSContextWrapper) -> JSValue { 244 | let value = JS_NewFloat64(context.context, self) 245 | return JSValue(context, value: value) 246 | } 247 | } 248 | 249 | extension Array: ConvertibleWithJavascript where Element: ConvertibleWithJavascript { 250 | public init?(_ context: JSContextWrapper, value: JSCValue) { 251 | guard JS_IsObject(value) != 0 else { 252 | return nil 253 | } 254 | 255 | let length = JS_GetPropertyStr(context.context, value, "length") 256 | defer { 257 | context.free(length) 258 | } 259 | var size: UInt64 = 0 260 | if JS_ToIndex(context.context, &size, value) < 0 { 261 | return nil 262 | } 263 | 264 | self = [] 265 | for index in 0.. JSValue { 276 | fatalError("TODO") 277 | } 278 | } 279 | 280 | public enum JSError: Error, ConvertibleWithJavascript { 281 | case exception 282 | 283 | public init?(_ context: JSContextWrapper, value: JSCValue) { 284 | guard JS_IsException(value) != 0 else { 285 | return nil 286 | } 287 | self = .exception 288 | } 289 | } 290 | -------------------------------------------------------------------------------- /Sources/QuickJSC/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | -------------------------------------------------------------------------------- /Sources/QuickJSC/cutils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * C utilities 3 | * 4 | * Copyright (c) 2017 Fabrice Bellard 5 | * Copyright (c) 2018 Charlie Gordon 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "cutils.h" 31 | 32 | void pstrcpy(char *buf, int buf_size, const char *str) 33 | { 34 | int c; 35 | char *q = buf; 36 | 37 | if (buf_size <= 0) 38 | return; 39 | 40 | for(;;) { 41 | c = *str++; 42 | if (c == 0 || q >= buf + buf_size - 1) 43 | break; 44 | *q++ = c; 45 | } 46 | *q = '\0'; 47 | } 48 | 49 | /* strcat and truncate. */ 50 | char *pstrcat(char *buf, int buf_size, const char *s) 51 | { 52 | int len; 53 | len = strlen(buf); 54 | if (len < buf_size) 55 | pstrcpy(buf + len, buf_size - len, s); 56 | return buf; 57 | } 58 | 59 | int strstart(const char *str, const char *val, const char **ptr) 60 | { 61 | const char *p, *q; 62 | p = str; 63 | q = val; 64 | while (*q != '\0') { 65 | if (*p != *q) 66 | return 0; 67 | p++; 68 | q++; 69 | } 70 | if (ptr) 71 | *ptr = p; 72 | return 1; 73 | } 74 | 75 | int has_suffix(const char *str, const char *suffix) 76 | { 77 | size_t len = strlen(str); 78 | size_t slen = strlen(suffix); 79 | return (len >= slen && !memcmp(str + len - slen, suffix, slen)); 80 | } 81 | 82 | /* Dynamic buffer package */ 83 | 84 | static void *dbuf_default_realloc(void *opaque, void *ptr, size_t size) 85 | { 86 | return realloc(ptr, size); 87 | } 88 | 89 | void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func) 90 | { 91 | memset(s, 0, sizeof(*s)); 92 | if (!realloc_func) 93 | realloc_func = dbuf_default_realloc; 94 | s->opaque = opaque; 95 | s->realloc_func = realloc_func; 96 | } 97 | 98 | void dbuf_init(DynBuf *s) 99 | { 100 | dbuf_init2(s, NULL, NULL); 101 | } 102 | 103 | /* return < 0 if error */ 104 | int dbuf_realloc(DynBuf *s, size_t new_size) 105 | { 106 | size_t size; 107 | uint8_t *new_buf; 108 | if (new_size > s->allocated_size) { 109 | if (s->error) 110 | return -1; 111 | size = s->allocated_size * 3 / 2; 112 | if (size > new_size) 113 | new_size = size; 114 | new_buf = s->realloc_func(s->opaque, s->buf, new_size); 115 | if (!new_buf) { 116 | s->error = TRUE; 117 | return -1; 118 | } 119 | s->buf = new_buf; 120 | s->allocated_size = new_size; 121 | } 122 | return 0; 123 | } 124 | 125 | int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len) 126 | { 127 | size_t end; 128 | end = offset + len; 129 | if (dbuf_realloc(s, end)) 130 | return -1; 131 | memcpy(s->buf + offset, data, len); 132 | if (end > s->size) 133 | s->size = end; 134 | return 0; 135 | } 136 | 137 | int dbuf_put(DynBuf *s, const uint8_t *data, size_t len) 138 | { 139 | if (unlikely((s->size + len) > s->allocated_size)) { 140 | if (dbuf_realloc(s, s->size + len)) 141 | return -1; 142 | } 143 | memcpy(s->buf + s->size, data, len); 144 | s->size += len; 145 | return 0; 146 | } 147 | 148 | int dbuf_put_self(DynBuf *s, size_t offset, size_t len) 149 | { 150 | if (unlikely((s->size + len) > s->allocated_size)) { 151 | if (dbuf_realloc(s, s->size + len)) 152 | return -1; 153 | } 154 | memcpy(s->buf + s->size, s->buf + offset, len); 155 | s->size += len; 156 | return 0; 157 | } 158 | 159 | int dbuf_putc(DynBuf *s, uint8_t c) 160 | { 161 | return dbuf_put(s, &c, 1); 162 | } 163 | 164 | int dbuf_putstr(DynBuf *s, const char *str) 165 | { 166 | return dbuf_put(s, (const uint8_t *)str, strlen(str)); 167 | } 168 | 169 | int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s, 170 | const char *fmt, ...) 171 | { 172 | va_list ap; 173 | char buf[128]; 174 | int len; 175 | 176 | va_start(ap, fmt); 177 | len = vsnprintf(buf, sizeof(buf), fmt, ap); 178 | va_end(ap); 179 | if (len < sizeof(buf)) { 180 | /* fast case */ 181 | return dbuf_put(s, (uint8_t *)buf, len); 182 | } else { 183 | if (dbuf_realloc(s, s->size + len + 1)) 184 | return -1; 185 | va_start(ap, fmt); 186 | vsnprintf((char *)(s->buf + s->size), s->allocated_size - s->size, 187 | fmt, ap); 188 | va_end(ap); 189 | s->size += len; 190 | } 191 | return 0; 192 | } 193 | 194 | void dbuf_free(DynBuf *s) 195 | { 196 | /* we test s->buf as a fail safe to avoid crashing if dbuf_free() 197 | is called twice */ 198 | if (s->buf) { 199 | s->realloc_func(s->opaque, s->buf, 0); 200 | } 201 | memset(s, 0, sizeof(*s)); 202 | } 203 | 204 | /* Note: at most 31 bits are encoded. At most UTF8_CHAR_LEN_MAX bytes 205 | are output. */ 206 | int unicode_to_utf8(uint8_t *buf, unsigned int c) 207 | { 208 | uint8_t *q = buf; 209 | 210 | if (c < 0x80) { 211 | *q++ = c; 212 | } else { 213 | if (c < 0x800) { 214 | *q++ = (c >> 6) | 0xc0; 215 | } else { 216 | if (c < 0x10000) { 217 | *q++ = (c >> 12) | 0xe0; 218 | } else { 219 | if (c < 0x00200000) { 220 | *q++ = (c >> 18) | 0xf0; 221 | } else { 222 | if (c < 0x04000000) { 223 | *q++ = (c >> 24) | 0xf8; 224 | } else if (c < 0x80000000) { 225 | *q++ = (c >> 30) | 0xfc; 226 | *q++ = ((c >> 24) & 0x3f) | 0x80; 227 | } else { 228 | return 0; 229 | } 230 | *q++ = ((c >> 18) & 0x3f) | 0x80; 231 | } 232 | *q++ = ((c >> 12) & 0x3f) | 0x80; 233 | } 234 | *q++ = ((c >> 6) & 0x3f) | 0x80; 235 | } 236 | *q++ = (c & 0x3f) | 0x80; 237 | } 238 | return q - buf; 239 | } 240 | 241 | static const unsigned int utf8_min_code[5] = { 242 | 0x80, 0x800, 0x10000, 0x00200000, 0x04000000, 243 | }; 244 | 245 | static const unsigned char utf8_first_code_mask[5] = { 246 | 0x1f, 0xf, 0x7, 0x3, 0x1, 247 | }; 248 | 249 | /* return -1 if error. *pp is not updated in this case. max_len must 250 | be >= 1. The maximum length for a UTF8 byte sequence is 6 bytes. */ 251 | int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp) 252 | { 253 | int l, c, b, i; 254 | 255 | c = *p++; 256 | if (c < 0x80) { 257 | *pp = p; 258 | return c; 259 | } 260 | switch(c) { 261 | case 0xc0: case 0xc1: case 0xc2: case 0xc3: 262 | case 0xc4: case 0xc5: case 0xc6: case 0xc7: 263 | case 0xc8: case 0xc9: case 0xca: case 0xcb: 264 | case 0xcc: case 0xcd: case 0xce: case 0xcf: 265 | case 0xd0: case 0xd1: case 0xd2: case 0xd3: 266 | case 0xd4: case 0xd5: case 0xd6: case 0xd7: 267 | case 0xd8: case 0xd9: case 0xda: case 0xdb: 268 | case 0xdc: case 0xdd: case 0xde: case 0xdf: 269 | l = 1; 270 | break; 271 | case 0xe0: case 0xe1: case 0xe2: case 0xe3: 272 | case 0xe4: case 0xe5: case 0xe6: case 0xe7: 273 | case 0xe8: case 0xe9: case 0xea: case 0xeb: 274 | case 0xec: case 0xed: case 0xee: case 0xef: 275 | l = 2; 276 | break; 277 | case 0xf0: case 0xf1: case 0xf2: case 0xf3: 278 | case 0xf4: case 0xf5: case 0xf6: case 0xf7: 279 | l = 3; 280 | break; 281 | case 0xf8: case 0xf9: case 0xfa: case 0xfb: 282 | l = 4; 283 | break; 284 | case 0xfc: case 0xfd: 285 | l = 5; 286 | break; 287 | default: 288 | return -1; 289 | } 290 | /* check that we have enough characters */ 291 | if (l > (max_len - 1)) 292 | return -1; 293 | c &= utf8_first_code_mask[l - 1]; 294 | for(i = 0; i < l; i++) { 295 | b = *p++; 296 | if (b < 0x80 || b >= 0xc0) 297 | return -1; 298 | c = (c << 6) | (b & 0x3f); 299 | } 300 | if (c < utf8_min_code[l - 1]) 301 | return -1; 302 | *pp = p; 303 | return c; 304 | } 305 | 306 | #if 0 307 | 308 | #if defined(EMSCRIPTEN) || defined(__ANDROID__) 309 | 310 | static void *rqsort_arg; 311 | static int (*rqsort_cmp)(const void *, const void *, void *); 312 | 313 | static int rqsort_cmp2(const void *p1, const void *p2) 314 | { 315 | return rqsort_cmp(p1, p2, rqsort_arg); 316 | } 317 | 318 | /* not reentrant, but not needed with emscripten */ 319 | void rqsort(void *base, size_t nmemb, size_t size, 320 | int (*cmp)(const void *, const void *, void *), 321 | void *arg) 322 | { 323 | rqsort_arg = arg; 324 | rqsort_cmp = cmp; 325 | qsort(base, nmemb, size, rqsort_cmp2); 326 | } 327 | 328 | #endif 329 | 330 | #else 331 | 332 | typedef void (*exchange_f)(void *a, void *b, size_t size); 333 | typedef int (*cmp_f)(const void *, const void *, void *opaque); 334 | 335 | static void exchange_bytes(void *a, void *b, size_t size) { 336 | uint8_t *ap = (uint8_t *)a; 337 | uint8_t *bp = (uint8_t *)b; 338 | 339 | while (size-- != 0) { 340 | uint8_t t = *ap; 341 | *ap++ = *bp; 342 | *bp++ = t; 343 | } 344 | } 345 | 346 | static void exchange_one_byte(void *a, void *b, size_t size) { 347 | uint8_t *ap = (uint8_t *)a; 348 | uint8_t *bp = (uint8_t *)b; 349 | uint8_t t = *ap; 350 | *ap = *bp; 351 | *bp = t; 352 | } 353 | 354 | static void exchange_int16s(void *a, void *b, size_t size) { 355 | uint16_t *ap = (uint16_t *)a; 356 | uint16_t *bp = (uint16_t *)b; 357 | 358 | for (size /= sizeof(uint16_t); size-- != 0;) { 359 | uint16_t t = *ap; 360 | *ap++ = *bp; 361 | *bp++ = t; 362 | } 363 | } 364 | 365 | static void exchange_one_int16(void *a, void *b, size_t size) { 366 | uint16_t *ap = (uint16_t *)a; 367 | uint16_t *bp = (uint16_t *)b; 368 | uint16_t t = *ap; 369 | *ap = *bp; 370 | *bp = t; 371 | } 372 | 373 | static void exchange_int32s(void *a, void *b, size_t size) { 374 | uint32_t *ap = (uint32_t *)a; 375 | uint32_t *bp = (uint32_t *)b; 376 | 377 | for (size /= sizeof(uint32_t); size-- != 0;) { 378 | uint32_t t = *ap; 379 | *ap++ = *bp; 380 | *bp++ = t; 381 | } 382 | } 383 | 384 | static void exchange_one_int32(void *a, void *b, size_t size) { 385 | uint32_t *ap = (uint32_t *)a; 386 | uint32_t *bp = (uint32_t *)b; 387 | uint32_t t = *ap; 388 | *ap = *bp; 389 | *bp = t; 390 | } 391 | 392 | static void exchange_int64s(void *a, void *b, size_t size) { 393 | uint64_t *ap = (uint64_t *)a; 394 | uint64_t *bp = (uint64_t *)b; 395 | 396 | for (size /= sizeof(uint64_t); size-- != 0;) { 397 | uint64_t t = *ap; 398 | *ap++ = *bp; 399 | *bp++ = t; 400 | } 401 | } 402 | 403 | static void exchange_one_int64(void *a, void *b, size_t size) { 404 | uint64_t *ap = (uint64_t *)a; 405 | uint64_t *bp = (uint64_t *)b; 406 | uint64_t t = *ap; 407 | *ap = *bp; 408 | *bp = t; 409 | } 410 | 411 | static void exchange_int128s(void *a, void *b, size_t size) { 412 | uint64_t *ap = (uint64_t *)a; 413 | uint64_t *bp = (uint64_t *)b; 414 | 415 | for (size /= sizeof(uint64_t) * 2; size-- != 0; ap += 2, bp += 2) { 416 | uint64_t t = ap[0]; 417 | uint64_t u = ap[1]; 418 | ap[0] = bp[0]; 419 | ap[1] = bp[1]; 420 | bp[0] = t; 421 | bp[1] = u; 422 | } 423 | } 424 | 425 | static void exchange_one_int128(void *a, void *b, size_t size) { 426 | uint64_t *ap = (uint64_t *)a; 427 | uint64_t *bp = (uint64_t *)b; 428 | uint64_t t = ap[0]; 429 | uint64_t u = ap[1]; 430 | ap[0] = bp[0]; 431 | ap[1] = bp[1]; 432 | bp[0] = t; 433 | bp[1] = u; 434 | } 435 | 436 | static inline exchange_f exchange_func(const void *base, size_t size) { 437 | switch (((uintptr_t)base | (uintptr_t)size) & 15) { 438 | case 0: 439 | if (size == sizeof(uint64_t) * 2) 440 | return exchange_one_int128; 441 | else 442 | return exchange_int128s; 443 | case 8: 444 | if (size == sizeof(uint64_t)) 445 | return exchange_one_int64; 446 | else 447 | return exchange_int64s; 448 | case 4: 449 | case 12: 450 | if (size == sizeof(uint32_t)) 451 | return exchange_one_int32; 452 | else 453 | return exchange_int32s; 454 | case 2: 455 | case 6: 456 | case 10: 457 | case 14: 458 | if (size == sizeof(uint16_t)) 459 | return exchange_one_int16; 460 | else 461 | return exchange_int16s; 462 | default: 463 | if (size == 1) 464 | return exchange_one_byte; 465 | else 466 | return exchange_bytes; 467 | } 468 | } 469 | 470 | static void heapsortx(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque) 471 | { 472 | uint8_t *basep = (uint8_t *)base; 473 | size_t i, n, c, r; 474 | exchange_f swap = exchange_func(base, size); 475 | 476 | if (nmemb > 1) { 477 | i = (nmemb / 2) * size; 478 | n = nmemb * size; 479 | 480 | while (i > 0) { 481 | i -= size; 482 | for (r = i; (c = r * 2 + size) < n; r = c) { 483 | if (c < n - size && cmp(basep + c, basep + c + size, opaque) <= 0) 484 | c += size; 485 | if (cmp(basep + r, basep + c, opaque) > 0) 486 | break; 487 | swap(basep + r, basep + c, size); 488 | } 489 | } 490 | for (i = n - size; i > 0; i -= size) { 491 | swap(basep, basep + i, size); 492 | 493 | for (r = 0; (c = r * 2 + size) < i; r = c) { 494 | if (c < i - size && cmp(basep + c, basep + c + size, opaque) <= 0) 495 | c += size; 496 | if (cmp(basep + r, basep + c, opaque) > 0) 497 | break; 498 | swap(basep + r, basep + c, size); 499 | } 500 | } 501 | } 502 | } 503 | 504 | static inline void *med3(void *a, void *b, void *c, cmp_f cmp, void *opaque) 505 | { 506 | return cmp(a, b, opaque) < 0 ? 507 | (cmp(b, c, opaque) < 0 ? b : (cmp(a, c, opaque) < 0 ? c : a )) : 508 | (cmp(b, c, opaque) > 0 ? b : (cmp(a, c, opaque) < 0 ? a : c )); 509 | } 510 | 511 | /* pointer based version with local stack and insertion sort threshhold */ 512 | void rqsort(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque) 513 | { 514 | struct { uint8_t *base; size_t count; int depth; } stack[50], *sp = stack; 515 | uint8_t *ptr, *pi, *pj, *plt, *pgt, *top, *m; 516 | size_t m4, i, lt, gt, span, span2; 517 | int c, depth; 518 | exchange_f swap = exchange_func(base, size); 519 | exchange_f swap_block = exchange_func(base, size | 128); 520 | 521 | if (nmemb < 2 || size <= 0) 522 | return; 523 | 524 | sp->base = (uint8_t *)base; 525 | sp->count = nmemb; 526 | sp->depth = 0; 527 | sp++; 528 | 529 | while (sp > stack) { 530 | sp--; 531 | ptr = sp->base; 532 | nmemb = sp->count; 533 | depth = sp->depth; 534 | 535 | while (nmemb > 6) { 536 | if (++depth > 50) { 537 | /* depth check to ensure worst case logarithmic time */ 538 | heapsortx(ptr, nmemb, size, cmp, opaque); 539 | nmemb = 0; 540 | break; 541 | } 542 | /* select median of 3 from 1/4, 1/2, 3/4 positions */ 543 | /* should use median of 5 or 9? */ 544 | m4 = (nmemb >> 2) * size; 545 | m = med3(ptr + m4, ptr + 2 * m4, ptr + 3 * m4, cmp, opaque); 546 | swap(ptr, m, size); /* move the pivot to the start or the array */ 547 | i = lt = 1; 548 | pi = plt = ptr + size; 549 | gt = nmemb; 550 | pj = pgt = top = ptr + nmemb * size; 551 | for (;;) { 552 | while (pi < pj && (c = cmp(ptr, pi, opaque)) >= 0) { 553 | if (c == 0) { 554 | swap(plt, pi, size); 555 | lt++; 556 | plt += size; 557 | } 558 | i++; 559 | pi += size; 560 | } 561 | while (pi < (pj -= size) && (c = cmp(ptr, pj, opaque)) <= 0) { 562 | if (c == 0) { 563 | gt--; 564 | pgt -= size; 565 | swap(pgt, pj, size); 566 | } 567 | } 568 | if (pi >= pj) 569 | break; 570 | swap(pi, pj, size); 571 | i++; 572 | pi += size; 573 | } 574 | /* array has 4 parts: 575 | * from 0 to lt excluded: elements identical to pivot 576 | * from lt to pi excluded: elements smaller than pivot 577 | * from pi to gt excluded: elements greater than pivot 578 | * from gt to n excluded: elements identical to pivot 579 | */ 580 | /* move elements identical to pivot in the middle of the array: */ 581 | /* swap values in ranges [0..lt[ and [i-lt..i[ 582 | swapping the smallest span between lt and i-lt is sufficient 583 | */ 584 | span = plt - ptr; 585 | span2 = pi - plt; 586 | lt = i - lt; 587 | if (span > span2) 588 | span = span2; 589 | swap_block(ptr, pi - span, span); 590 | /* swap values in ranges [gt..top[ and [i..top-(top-gt)[ 591 | swapping the smallest span between top-gt and gt-i is sufficient 592 | */ 593 | span = top - pgt; 594 | span2 = pgt - pi; 595 | pgt = top - span2; 596 | gt = nmemb - (gt - i); 597 | if (span > span2) 598 | span = span2; 599 | swap_block(pi, top - span, span); 600 | 601 | /* now array has 3 parts: 602 | * from 0 to lt excluded: elements smaller than pivot 603 | * from lt to gt excluded: elements identical to pivot 604 | * from gt to n excluded: elements greater than pivot 605 | */ 606 | /* stack the larger segment and keep processing the smaller one 607 | to minimize stack use for pathological distributions */ 608 | if (lt > nmemb - gt) { 609 | sp->base = ptr; 610 | sp->count = lt; 611 | sp->depth = depth; 612 | sp++; 613 | ptr = pgt; 614 | nmemb -= gt; 615 | } else { 616 | sp->base = pgt; 617 | sp->count = nmemb - gt; 618 | sp->depth = depth; 619 | sp++; 620 | nmemb = lt; 621 | } 622 | } 623 | /* Use insertion sort for small fragments */ 624 | for (pi = ptr + size, top = ptr + nmemb * size; pi < top; pi += size) { 625 | for (pj = pi; pj > ptr && cmp(pj - size, pj, opaque) > 0; pj -= size) 626 | swap(pj, pj - size, size); 627 | } 628 | } 629 | } 630 | 631 | #endif 632 | -------------------------------------------------------------------------------- /Sources/QuickJSC/include/cutils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * C utilities 3 | * 4 | * Copyright (c) 2017 Fabrice Bellard 5 | * Copyright (c) 2018 Charlie Gordon 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | #ifndef CUTILS_H 26 | #define CUTILS_H 27 | 28 | #include 29 | #include 30 | 31 | /* set if CPU is big endian */ 32 | #undef WORDS_BIGENDIAN 33 | 34 | #define likely(x) __builtin_expect(!!(x), 1) 35 | #define unlikely(x) __builtin_expect(!!(x), 0) 36 | #define force_inline inline __attribute__((always_inline)) 37 | #define no_inline __attribute__((noinline)) 38 | #define __maybe_unused __attribute__((unused)) 39 | 40 | #define xglue(x, y) x ## y 41 | #define glue(x, y) xglue(x, y) 42 | #define stringify(s) tostring(s) 43 | #define tostring(s) #s 44 | 45 | #ifndef offsetof 46 | #define offsetof(type, field) ((size_t) &((type *)0)->field) 47 | #endif 48 | #ifndef countof 49 | #define countof(x) (sizeof(x) / sizeof((x)[0])) 50 | #endif 51 | 52 | typedef int BOOL; 53 | 54 | #ifndef FALSE 55 | enum { 56 | FALSE = 0, 57 | TRUE = 1, 58 | }; 59 | #endif 60 | 61 | void pstrcpy(char *buf, int buf_size, const char *str); 62 | char *pstrcat(char *buf, int buf_size, const char *s); 63 | int strstart(const char *str, const char *val, const char **ptr); 64 | int has_suffix(const char *str, const char *suffix); 65 | 66 | static inline int max_int(int a, int b) 67 | { 68 | if (a > b) 69 | return a; 70 | else 71 | return b; 72 | } 73 | 74 | static inline int min_int(int a, int b) 75 | { 76 | if (a < b) 77 | return a; 78 | else 79 | return b; 80 | } 81 | 82 | static inline uint32_t max_uint32(uint32_t a, uint32_t b) 83 | { 84 | if (a > b) 85 | return a; 86 | else 87 | return b; 88 | } 89 | 90 | static inline uint32_t min_uint32(uint32_t a, uint32_t b) 91 | { 92 | if (a < b) 93 | return a; 94 | else 95 | return b; 96 | } 97 | 98 | static inline int64_t max_int64(int64_t a, int64_t b) 99 | { 100 | if (a > b) 101 | return a; 102 | else 103 | return b; 104 | } 105 | 106 | static inline int64_t min_int64(int64_t a, int64_t b) 107 | { 108 | if (a < b) 109 | return a; 110 | else 111 | return b; 112 | } 113 | 114 | /* WARNING: undefined if a = 0 */ 115 | static inline int clz32(unsigned int a) 116 | { 117 | return __builtin_clz(a); 118 | } 119 | 120 | /* WARNING: undefined if a = 0 */ 121 | static inline int clz64(uint64_t a) 122 | { 123 | return __builtin_clzll(a); 124 | } 125 | 126 | /* WARNING: undefined if a = 0 */ 127 | static inline int ctz32(unsigned int a) 128 | { 129 | return __builtin_ctz(a); 130 | } 131 | 132 | /* WARNING: undefined if a = 0 */ 133 | static inline int ctz64(uint64_t a) 134 | { 135 | return __builtin_ctzll(a); 136 | } 137 | 138 | struct __attribute__((packed)) packed_u64 { 139 | uint64_t v; 140 | }; 141 | 142 | struct __attribute__((packed)) packed_u32 { 143 | uint32_t v; 144 | }; 145 | 146 | struct __attribute__((packed)) packed_u16 { 147 | uint16_t v; 148 | }; 149 | 150 | static inline uint64_t get_u64(const uint8_t *tab) 151 | { 152 | return ((const struct packed_u64 *)tab)->v; 153 | } 154 | 155 | static inline int64_t get_i64(const uint8_t *tab) 156 | { 157 | return (int64_t)((const struct packed_u64 *)tab)->v; 158 | } 159 | 160 | static inline void put_u64(uint8_t *tab, uint64_t val) 161 | { 162 | ((struct packed_u64 *)tab)->v = val; 163 | } 164 | 165 | static inline uint32_t get_u32(const uint8_t *tab) 166 | { 167 | return ((const struct packed_u32 *)tab)->v; 168 | } 169 | 170 | static inline int32_t get_i32(const uint8_t *tab) 171 | { 172 | return (int32_t)((const struct packed_u32 *)tab)->v; 173 | } 174 | 175 | static inline void put_u32(uint8_t *tab, uint32_t val) 176 | { 177 | ((struct packed_u32 *)tab)->v = val; 178 | } 179 | 180 | static inline uint32_t get_u16(const uint8_t *tab) 181 | { 182 | return ((const struct packed_u16 *)tab)->v; 183 | } 184 | 185 | static inline int32_t get_i16(const uint8_t *tab) 186 | { 187 | return (int16_t)((const struct packed_u16 *)tab)->v; 188 | } 189 | 190 | static inline void put_u16(uint8_t *tab, uint16_t val) 191 | { 192 | ((struct packed_u16 *)tab)->v = val; 193 | } 194 | 195 | static inline uint32_t get_u8(const uint8_t *tab) 196 | { 197 | return *tab; 198 | } 199 | 200 | static inline int32_t get_i8(const uint8_t *tab) 201 | { 202 | return (int8_t)*tab; 203 | } 204 | 205 | static inline void put_u8(uint8_t *tab, uint8_t val) 206 | { 207 | *tab = val; 208 | } 209 | 210 | static inline uint16_t bswap16(uint16_t x) 211 | { 212 | return (x >> 8) | (x << 8); 213 | } 214 | 215 | static inline uint32_t bswap32(uint32_t v) 216 | { 217 | return ((v & 0xff000000) >> 24) | ((v & 0x00ff0000) >> 8) | 218 | ((v & 0x0000ff00) << 8) | ((v & 0x000000ff) << 24); 219 | } 220 | 221 | static inline uint64_t bswap64(uint64_t v) 222 | { 223 | return ((v & ((uint64_t)0xff << (7 * 8))) >> (7 * 8)) | 224 | ((v & ((uint64_t)0xff << (6 * 8))) >> (5 * 8)) | 225 | ((v & ((uint64_t)0xff << (5 * 8))) >> (3 * 8)) | 226 | ((v & ((uint64_t)0xff << (4 * 8))) >> (1 * 8)) | 227 | ((v & ((uint64_t)0xff << (3 * 8))) << (1 * 8)) | 228 | ((v & ((uint64_t)0xff << (2 * 8))) << (3 * 8)) | 229 | ((v & ((uint64_t)0xff << (1 * 8))) << (5 * 8)) | 230 | ((v & ((uint64_t)0xff << (0 * 8))) << (7 * 8)); 231 | } 232 | 233 | /* XXX: should take an extra argument to pass slack information to the caller */ 234 | typedef void *DynBufReallocFunc(void *opaque, void *ptr, size_t size); 235 | 236 | typedef struct DynBuf { 237 | uint8_t *buf; 238 | size_t size; 239 | size_t allocated_size; 240 | BOOL error; /* true if a memory allocation error occurred */ 241 | DynBufReallocFunc *realloc_func; 242 | void *opaque; /* for realloc_func */ 243 | } DynBuf; 244 | 245 | void dbuf_init(DynBuf *s); 246 | void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func); 247 | int dbuf_realloc(DynBuf *s, size_t new_size); 248 | int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len); 249 | int dbuf_put(DynBuf *s, const uint8_t *data, size_t len); 250 | int dbuf_put_self(DynBuf *s, size_t offset, size_t len); 251 | int dbuf_putc(DynBuf *s, uint8_t c); 252 | int dbuf_putstr(DynBuf *s, const char *str); 253 | static inline int dbuf_put_u16(DynBuf *s, uint16_t val) 254 | { 255 | return dbuf_put(s, (uint8_t *)&val, 2); 256 | } 257 | static inline int dbuf_put_u32(DynBuf *s, uint32_t val) 258 | { 259 | return dbuf_put(s, (uint8_t *)&val, 4); 260 | } 261 | static inline int dbuf_put_u64(DynBuf *s, uint64_t val) 262 | { 263 | return dbuf_put(s, (uint8_t *)&val, 8); 264 | } 265 | int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s, 266 | const char *fmt, ...); 267 | void dbuf_free(DynBuf *s); 268 | static inline BOOL dbuf_error(DynBuf *s) { 269 | return s->error; 270 | } 271 | static inline void dbuf_set_error(DynBuf *s) 272 | { 273 | s->error = TRUE; 274 | } 275 | 276 | #define UTF8_CHAR_LEN_MAX 6 277 | 278 | int unicode_to_utf8(uint8_t *buf, unsigned int c); 279 | int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp); 280 | 281 | static inline int from_hex(int c) 282 | { 283 | if (c >= '0' && c <= '9') 284 | return c - '0'; 285 | else if (c >= 'A' && c <= 'F') 286 | return c - 'A' + 10; 287 | else if (c >= 'a' && c <= 'f') 288 | return c - 'a' + 10; 289 | else 290 | return -1; 291 | } 292 | 293 | void rqsort(void *base, size_t nmemb, size_t size, 294 | int (*cmp)(const void *, const void *, void *), 295 | void *arg); 296 | 297 | #endif /* CUTILS_H */ 298 | -------------------------------------------------------------------------------- /Sources/QuickJSC/include/libregexp-opcode.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Regular Expression Engine 3 | * 4 | * Copyright (c) 2017-2018 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifdef DEF 26 | 27 | DEF(invalid, 1) /* never used */ 28 | DEF(char, 3) 29 | DEF(char32, 5) 30 | DEF(dot, 1) 31 | DEF(any, 1) /* same as dot but match any character including line terminator */ 32 | DEF(line_start, 1) 33 | DEF(line_end, 1) 34 | DEF(goto, 5) 35 | DEF(split_goto_first, 5) 36 | DEF(split_next_first, 5) 37 | DEF(match, 1) 38 | DEF(save_start, 2) /* save start position */ 39 | DEF(save_end, 2) /* save end position, must come after saved_start */ 40 | DEF(save_reset, 3) /* reset save positions */ 41 | DEF(loop, 5) /* decrement the top the stack and goto if != 0 */ 42 | DEF(push_i32, 5) /* push integer on the stack */ 43 | DEF(drop, 1) 44 | DEF(word_boundary, 1) 45 | DEF(not_word_boundary, 1) 46 | DEF(back_reference, 2) 47 | DEF(backward_back_reference, 2) /* must come after back_reference */ 48 | DEF(range, 3) /* variable length */ 49 | DEF(range32, 3) /* variable length */ 50 | DEF(lookahead, 5) 51 | DEF(negative_lookahead, 5) 52 | DEF(push_char_pos, 1) /* push the character position on the stack */ 53 | DEF(bne_char_pos, 5) /* pop one stack element and jump if equal to the character 54 | position */ 55 | DEF(prev, 1) /* go to the previous char */ 56 | DEF(simple_greedy_quant, 17) 57 | 58 | #endif /* DEF */ 59 | -------------------------------------------------------------------------------- /Sources/QuickJSC/include/libregexp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Regular Expression Engine 3 | * 4 | * Copyright (c) 2017-2018 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef LIBREGEXP_H 25 | #define LIBREGEXP_H 26 | 27 | #include 28 | 29 | #include "libunicode.h" 30 | 31 | #define LRE_BOOL int /* for documentation purposes */ 32 | 33 | #define LRE_FLAG_GLOBAL (1 << 0) 34 | #define LRE_FLAG_IGNORECASE (1 << 1) 35 | #define LRE_FLAG_MULTILINE (1 << 2) 36 | #define LRE_FLAG_DOTALL (1 << 3) 37 | #define LRE_FLAG_UTF16 (1 << 4) 38 | #define LRE_FLAG_STICKY (1 << 5) 39 | 40 | #define LRE_FLAG_NAMED_GROUPS (1 << 7) /* named groups are present in the regexp */ 41 | 42 | uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size, 43 | const char *buf, size_t buf_len, int re_flags, 44 | void *opaque); 45 | int lre_get_capture_count(const uint8_t *bc_buf); 46 | int lre_get_flags(const uint8_t *bc_buf); 47 | const char *lre_get_groupnames(const uint8_t *bc_buf); 48 | int lre_exec(uint8_t **capture, 49 | const uint8_t *bc_buf, const uint8_t *cbuf, int cindex, int clen, 50 | int cbuf_type, void *opaque); 51 | 52 | int lre_parse_escape(const uint8_t **pp, int allow_utf16); 53 | LRE_BOOL lre_is_space(int c); 54 | 55 | /* must be provided by the user */ 56 | LRE_BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size); 57 | void *lre_realloc(void *opaque, void *ptr, size_t size); 58 | 59 | /* JS identifier test */ 60 | extern uint32_t const lre_id_start_table_ascii[4]; 61 | extern uint32_t const lre_id_continue_table_ascii[4]; 62 | 63 | static inline int lre_js_is_ident_first(int c) 64 | { 65 | if ((uint32_t)c < 128) { 66 | return (lre_id_start_table_ascii[c >> 5] >> (c & 31)) & 1; 67 | } else { 68 | #ifdef CONFIG_ALL_UNICODE 69 | return lre_is_id_start(c); 70 | #else 71 | return !lre_is_space(c); 72 | #endif 73 | } 74 | } 75 | 76 | static inline int lre_js_is_ident_next(int c) 77 | { 78 | if ((uint32_t)c < 128) { 79 | return (lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1; 80 | } else { 81 | /* ZWNJ and ZWJ are accepted in identifiers */ 82 | #ifdef CONFIG_ALL_UNICODE 83 | return lre_is_id_continue(c) || c == 0x200C || c == 0x200D; 84 | #else 85 | return !lre_is_space(c) || c == 0x200C || c == 0x200D; 86 | #endif 87 | } 88 | } 89 | 90 | #undef LRE_BOOL 91 | 92 | #endif /* LIBREGEXP_H */ 93 | -------------------------------------------------------------------------------- /Sources/QuickJSC/include/libunicode.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Unicode utilities 3 | * 4 | * Copyright (c) 2017-2018 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef LIBUNICODE_H 25 | #define LIBUNICODE_H 26 | 27 | #include 28 | 29 | #define LRE_BOOL int /* for documentation purposes */ 30 | 31 | /* define it to include all the unicode tables (40KB larger) */ 32 | #define CONFIG_ALL_UNICODE 33 | 34 | #define LRE_CC_RES_LEN_MAX 3 35 | 36 | typedef enum { 37 | UNICODE_NFC, 38 | UNICODE_NFD, 39 | UNICODE_NFKC, 40 | UNICODE_NFKD, 41 | } UnicodeNormalizationEnum; 42 | 43 | int lre_case_conv(uint32_t *res, uint32_t c, int conv_type); 44 | LRE_BOOL lre_is_cased(uint32_t c); 45 | LRE_BOOL lre_is_case_ignorable(uint32_t c); 46 | 47 | /* char ranges */ 48 | 49 | typedef struct { 50 | int len; /* in points, always even */ 51 | int size; 52 | uint32_t *points; /* points sorted by increasing value */ 53 | void *mem_opaque; 54 | void *(*realloc_func)(void *opaque, void *ptr, size_t size); 55 | } CharRange; 56 | 57 | typedef enum { 58 | CR_OP_UNION, 59 | CR_OP_INTER, 60 | CR_OP_XOR, 61 | } CharRangeOpEnum; 62 | 63 | void cr_init(CharRange *cr, void *mem_opaque, void *(*realloc_func)(void *opaque, void *ptr, size_t size)); 64 | void cr_free(CharRange *cr); 65 | int cr_realloc(CharRange *cr, int size); 66 | int cr_copy(CharRange *cr, const CharRange *cr1); 67 | 68 | static inline int cr_add_point(CharRange *cr, uint32_t v) 69 | { 70 | if (cr->len >= cr->size) { 71 | if (cr_realloc(cr, cr->len + 1)) 72 | return -1; 73 | } 74 | cr->points[cr->len++] = v; 75 | return 0; 76 | } 77 | 78 | static inline int cr_add_interval(CharRange *cr, uint32_t c1, uint32_t c2) 79 | { 80 | if ((cr->len + 2) > cr->size) { 81 | if (cr_realloc(cr, cr->len + 2)) 82 | return -1; 83 | } 84 | cr->points[cr->len++] = c1; 85 | cr->points[cr->len++] = c2; 86 | return 0; 87 | } 88 | 89 | int cr_union1(CharRange *cr, const uint32_t *b_pt, int b_len); 90 | 91 | static inline int cr_union_interval(CharRange *cr, uint32_t c1, uint32_t c2) 92 | { 93 | uint32_t b_pt[2]; 94 | b_pt[0] = c1; 95 | b_pt[1] = c2 + 1; 96 | return cr_union1(cr, b_pt, 2); 97 | } 98 | 99 | int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len, 100 | const uint32_t *b_pt, int b_len, int op); 101 | 102 | int cr_invert(CharRange *cr); 103 | 104 | #ifdef CONFIG_ALL_UNICODE 105 | 106 | LRE_BOOL lre_is_id_start(uint32_t c); 107 | LRE_BOOL lre_is_id_continue(uint32_t c); 108 | 109 | int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len, 110 | UnicodeNormalizationEnum n_type, 111 | void *opaque, void *(*realloc_func)(void *opaque, void *ptr, size_t size)); 112 | 113 | /* Unicode character range functions */ 114 | 115 | int unicode_script(CharRange *cr, 116 | const char *script_name, LRE_BOOL is_ext); 117 | int unicode_general_category(CharRange *cr, const char *gc_name); 118 | int unicode_prop(CharRange *cr, const char *prop_name); 119 | 120 | #endif /* CONFIG_ALL_UNICODE */ 121 | 122 | #undef LRE_BOOL 123 | 124 | #endif /* LIBUNICODE_H */ 125 | -------------------------------------------------------------------------------- /Sources/QuickJSC/include/list.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Linux klist like system 3 | * 4 | * Copyright (c) 2016-2017 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef LIST_H 25 | #define LIST_H 26 | 27 | #ifndef NULL 28 | #include 29 | #endif 30 | 31 | struct list_head { 32 | struct list_head *prev; 33 | struct list_head *next; 34 | }; 35 | 36 | #define LIST_HEAD_INIT(el) { &(el), &(el) } 37 | 38 | /* return the pointer of type 'type *' containing 'el' as field 'member' */ 39 | #define list_entry(el, type, member) \ 40 | ((type *)((uint8_t *)(el) - offsetof(type, member))) 41 | 42 | static inline void init_list_head(struct list_head *head) 43 | { 44 | head->prev = head; 45 | head->next = head; 46 | } 47 | 48 | /* insert 'el' between 'prev' and 'next' */ 49 | static inline void __list_add(struct list_head *el, 50 | struct list_head *prev, struct list_head *next) 51 | { 52 | prev->next = el; 53 | el->prev = prev; 54 | el->next = next; 55 | next->prev = el; 56 | } 57 | 58 | /* add 'el' at the head of the list 'head' (= after element head) */ 59 | static inline void list_add(struct list_head *el, struct list_head *head) 60 | { 61 | __list_add(el, head, head->next); 62 | } 63 | 64 | /* add 'el' at the end of the list 'head' (= before element head) */ 65 | static inline void list_add_tail(struct list_head *el, struct list_head *head) 66 | { 67 | __list_add(el, head->prev, head); 68 | } 69 | 70 | static inline void list_del(struct list_head *el) 71 | { 72 | struct list_head *prev, *next; 73 | prev = el->prev; 74 | next = el->next; 75 | prev->next = next; 76 | next->prev = prev; 77 | el->prev = NULL; /* fail safe */ 78 | el->next = NULL; /* fail safe */ 79 | } 80 | 81 | static inline int list_empty(struct list_head *el) 82 | { 83 | return el->next == el; 84 | } 85 | 86 | #define list_for_each(el, head) \ 87 | for(el = (head)->next; el != (head); el = el->next) 88 | 89 | #define list_for_each_safe(el, el1, head) \ 90 | for(el = (head)->next, el1 = el->next; el != (head); \ 91 | el = el1, el1 = el->next) 92 | 93 | #define list_for_each_prev(el, head) \ 94 | for(el = (head)->prev; el != (head); el = el->prev) 95 | 96 | #define list_for_each_prev_safe(el, el1, head) \ 97 | for(el = (head)->prev, el1 = el->prev; el != (head); \ 98 | el = el1, el1 = el->prev) 99 | 100 | #endif /* LIST_H */ 101 | -------------------------------------------------------------------------------- /Sources/QuickJSC/include/module.modulemap: -------------------------------------------------------------------------------- 1 | module QuickJSC { 2 | header "quickjs.h" 3 | header "quickjs-libc.h" 4 | export * 5 | } 6 | -------------------------------------------------------------------------------- /Sources/QuickJSC/include/quickjs-atom.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS atom definitions 3 | * 4 | * Copyright (c) 2017-2018 Fabrice Bellard 5 | * Copyright (c) 2017-2018 Charlie Gordon 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #ifdef DEF 27 | 28 | /* Note: first atoms are considered as keywords in the parser */ 29 | DEF(null, "null") /* must be first */ 30 | DEF(false, "false") 31 | DEF(true, "true") 32 | DEF(if, "if") 33 | DEF(else, "else") 34 | DEF(return, "return") 35 | DEF(var, "var") 36 | DEF(this, "this") 37 | DEF(delete, "delete") 38 | DEF(void, "void") 39 | DEF(typeof, "typeof") 40 | DEF(new, "new") 41 | DEF(in, "in") 42 | DEF(instanceof, "instanceof") 43 | DEF(do, "do") 44 | DEF(while, "while") 45 | DEF(for, "for") 46 | DEF(break, "break") 47 | DEF(continue, "continue") 48 | DEF(switch, "switch") 49 | DEF(case, "case") 50 | DEF(default, "default") 51 | DEF(throw, "throw") 52 | DEF(try, "try") 53 | DEF(catch, "catch") 54 | DEF(finally, "finally") 55 | DEF(function, "function") 56 | DEF(debugger, "debugger") 57 | DEF(with, "with") 58 | /* FutureReservedWord */ 59 | DEF(class, "class") 60 | DEF(const, "const") 61 | DEF(enum, "enum") 62 | DEF(export, "export") 63 | DEF(extends, "extends") 64 | DEF(import, "import") 65 | DEF(super, "super") 66 | /* FutureReservedWords when parsing strict mode code */ 67 | DEF(implements, "implements") 68 | DEF(interface, "interface") 69 | DEF(let, "let") 70 | DEF(package, "package") 71 | DEF(private, "private") 72 | DEF(protected, "protected") 73 | DEF(public, "public") 74 | DEF(static, "static") 75 | DEF(yield, "yield") 76 | DEF(await, "await") 77 | 78 | /* empty string */ 79 | DEF(empty_string, "") 80 | /* identifiers */ 81 | DEF(length, "length") 82 | DEF(fileName, "fileName") 83 | DEF(lineNumber, "lineNumber") 84 | DEF(message, "message") 85 | DEF(errors, "errors") 86 | DEF(stack, "stack") 87 | DEF(name, "name") 88 | DEF(toString, "toString") 89 | DEF(toLocaleString, "toLocaleString") 90 | DEF(valueOf, "valueOf") 91 | DEF(eval, "eval") 92 | DEF(prototype, "prototype") 93 | DEF(constructor, "constructor") 94 | DEF(configurable, "configurable") 95 | DEF(writable, "writable") 96 | DEF(enumerable, "enumerable") 97 | DEF(value, "value") 98 | DEF(get, "get") 99 | DEF(set, "set") 100 | DEF(of, "of") 101 | DEF(__proto__, "__proto__") 102 | DEF(undefined, "undefined") 103 | DEF(number, "number") 104 | DEF(boolean, "boolean") 105 | DEF(string, "string") 106 | DEF(object, "object") 107 | DEF(symbol, "symbol") 108 | DEF(integer, "integer") 109 | DEF(unknown, "unknown") 110 | DEF(arguments, "arguments") 111 | DEF(callee, "callee") 112 | DEF(caller, "caller") 113 | DEF(_eval_, "") 114 | DEF(_ret_, "") 115 | DEF(_var_, "") 116 | DEF(_arg_var_, "") 117 | DEF(_with_, "") 118 | DEF(lastIndex, "lastIndex") 119 | DEF(target, "target") 120 | DEF(index, "index") 121 | DEF(input, "input") 122 | DEF(defineProperties, "defineProperties") 123 | DEF(apply, "apply") 124 | DEF(join, "join") 125 | DEF(concat, "concat") 126 | DEF(split, "split") 127 | DEF(construct, "construct") 128 | DEF(getPrototypeOf, "getPrototypeOf") 129 | DEF(setPrototypeOf, "setPrototypeOf") 130 | DEF(isExtensible, "isExtensible") 131 | DEF(preventExtensions, "preventExtensions") 132 | DEF(has, "has") 133 | DEF(deleteProperty, "deleteProperty") 134 | DEF(defineProperty, "defineProperty") 135 | DEF(getOwnPropertyDescriptor, "getOwnPropertyDescriptor") 136 | DEF(ownKeys, "ownKeys") 137 | DEF(add, "add") 138 | DEF(done, "done") 139 | DEF(next, "next") 140 | DEF(values, "values") 141 | DEF(source, "source") 142 | DEF(flags, "flags") 143 | DEF(global, "global") 144 | DEF(unicode, "unicode") 145 | DEF(raw, "raw") 146 | DEF(new_target, "new.target") 147 | DEF(this_active_func, "this.active_func") 148 | DEF(home_object, "") 149 | DEF(computed_field, "") 150 | DEF(static_computed_field, "") /* must come after computed_fields */ 151 | DEF(class_fields_init, "") 152 | DEF(brand, "") 153 | DEF(hash_constructor, "#constructor") 154 | DEF(as, "as") 155 | DEF(from, "from") 156 | DEF(meta, "meta") 157 | DEF(_default_, "*default*") 158 | DEF(_star_, "*") 159 | DEF(Module, "Module") 160 | DEF(then, "then") 161 | DEF(resolve, "resolve") 162 | DEF(reject, "reject") 163 | DEF(promise, "promise") 164 | DEF(proxy, "proxy") 165 | DEF(revoke, "revoke") 166 | DEF(async, "async") 167 | DEF(exec, "exec") 168 | DEF(groups, "groups") 169 | DEF(status, "status") 170 | DEF(reason, "reason") 171 | DEF(globalThis, "globalThis") 172 | #ifdef CONFIG_BIGNUM 173 | DEF(bigint, "bigint") 174 | DEF(bigfloat, "bigfloat") 175 | DEF(bigdecimal, "bigdecimal") 176 | DEF(roundingMode, "roundingMode") 177 | DEF(maximumSignificantDigits, "maximumSignificantDigits") 178 | DEF(maximumFractionDigits, "maximumFractionDigits") 179 | #endif 180 | #ifdef CONFIG_ATOMICS 181 | DEF(not_equal, "not-equal") 182 | DEF(timed_out, "timed-out") 183 | DEF(ok, "ok") 184 | #endif 185 | DEF(toJSON, "toJSON") 186 | /* class names */ 187 | DEF(Object, "Object") 188 | DEF(Array, "Array") 189 | DEF(Error, "Error") 190 | DEF(Number, "Number") 191 | DEF(String, "String") 192 | DEF(Boolean, "Boolean") 193 | DEF(Symbol, "Symbol") 194 | DEF(Arguments, "Arguments") 195 | DEF(Math, "Math") 196 | DEF(JSON, "JSON") 197 | DEF(Date, "Date") 198 | DEF(Function, "Function") 199 | DEF(GeneratorFunction, "GeneratorFunction") 200 | DEF(ForInIterator, "ForInIterator") 201 | DEF(RegExp, "RegExp") 202 | DEF(ArrayBuffer, "ArrayBuffer") 203 | DEF(SharedArrayBuffer, "SharedArrayBuffer") 204 | /* must keep same order as class IDs for typed arrays */ 205 | DEF(Uint8ClampedArray, "Uint8ClampedArray") 206 | DEF(Int8Array, "Int8Array") 207 | DEF(Uint8Array, "Uint8Array") 208 | DEF(Int16Array, "Int16Array") 209 | DEF(Uint16Array, "Uint16Array") 210 | DEF(Int32Array, "Int32Array") 211 | DEF(Uint32Array, "Uint32Array") 212 | #ifdef CONFIG_BIGNUM 213 | DEF(BigInt64Array, "BigInt64Array") 214 | DEF(BigUint64Array, "BigUint64Array") 215 | #endif 216 | DEF(Float32Array, "Float32Array") 217 | DEF(Float64Array, "Float64Array") 218 | DEF(DataView, "DataView") 219 | #ifdef CONFIG_BIGNUM 220 | DEF(BigInt, "BigInt") 221 | DEF(BigFloat, "BigFloat") 222 | DEF(BigFloatEnv, "BigFloatEnv") 223 | DEF(BigDecimal, "BigDecimal") 224 | DEF(OperatorSet, "OperatorSet") 225 | DEF(Operators, "Operators") 226 | #endif 227 | DEF(Map, "Map") 228 | DEF(Set, "Set") /* Map + 1 */ 229 | DEF(WeakMap, "WeakMap") /* Map + 2 */ 230 | DEF(WeakSet, "WeakSet") /* Map + 3 */ 231 | DEF(Map_Iterator, "Map Iterator") 232 | DEF(Set_Iterator, "Set Iterator") 233 | DEF(Array_Iterator, "Array Iterator") 234 | DEF(String_Iterator, "String Iterator") 235 | DEF(RegExp_String_Iterator, "RegExp String Iterator") 236 | DEF(Generator, "Generator") 237 | DEF(Proxy, "Proxy") 238 | DEF(Promise, "Promise") 239 | DEF(PromiseResolveFunction, "PromiseResolveFunction") 240 | DEF(PromiseRejectFunction, "PromiseRejectFunction") 241 | DEF(AsyncFunction, "AsyncFunction") 242 | DEF(AsyncFunctionResolve, "AsyncFunctionResolve") 243 | DEF(AsyncFunctionReject, "AsyncFunctionReject") 244 | DEF(AsyncGeneratorFunction, "AsyncGeneratorFunction") 245 | DEF(AsyncGenerator, "AsyncGenerator") 246 | DEF(EvalError, "EvalError") 247 | DEF(RangeError, "RangeError") 248 | DEF(ReferenceError, "ReferenceError") 249 | DEF(SyntaxError, "SyntaxError") 250 | DEF(TypeError, "TypeError") 251 | DEF(URIError, "URIError") 252 | DEF(InternalError, "InternalError") 253 | /* private symbols */ 254 | DEF(Private_brand, "") 255 | /* symbols */ 256 | DEF(Symbol_toPrimitive, "Symbol.toPrimitive") 257 | DEF(Symbol_iterator, "Symbol.iterator") 258 | DEF(Symbol_match, "Symbol.match") 259 | DEF(Symbol_matchAll, "Symbol.matchAll") 260 | DEF(Symbol_replace, "Symbol.replace") 261 | DEF(Symbol_search, "Symbol.search") 262 | DEF(Symbol_split, "Symbol.split") 263 | DEF(Symbol_toStringTag, "Symbol.toStringTag") 264 | DEF(Symbol_isConcatSpreadable, "Symbol.isConcatSpreadable") 265 | DEF(Symbol_hasInstance, "Symbol.hasInstance") 266 | DEF(Symbol_species, "Symbol.species") 267 | DEF(Symbol_unscopables, "Symbol.unscopables") 268 | DEF(Symbol_asyncIterator, "Symbol.asyncIterator") 269 | #ifdef CONFIG_BIGNUM 270 | DEF(Symbol_operatorSet, "Symbol.operatorSet") 271 | #endif 272 | 273 | #endif /* DEF */ 274 | -------------------------------------------------------------------------------- /Sources/QuickJSC/include/quickjs-libc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS C library 3 | * 4 | * Copyright (c) 2017-2018 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef QUICKJS_LIBC_H 25 | #define QUICKJS_LIBC_H 26 | 27 | #include 28 | #include 29 | 30 | #include "quickjs.h" 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif 35 | 36 | JSModuleDef *js_init_module_std(JSContext *ctx, const char *module_name); 37 | JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name); 38 | void js_std_add_helpers(JSContext *ctx, int argc, char **argv); 39 | void js_std_loop(JSContext *ctx); 40 | void js_std_init_handlers(JSRuntime *rt); 41 | void js_std_free_handlers(JSRuntime *rt); 42 | void js_std_dump_error(JSContext *ctx); 43 | uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename); 44 | int js_module_set_import_meta(JSContext *ctx, JSCValueonst func_val, 45 | JS_BOOL use_realpath, JS_BOOL is_main); 46 | JSModuleDef *js_module_loader(JSContext *ctx, 47 | const char *module_name, void *opaque); 48 | void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len, 49 | int flags); 50 | void js_std_promise_rejection_tracker(JSContext *ctx, JSCValueonst promise, 51 | JSCValueonst reason, 52 | JS_BOOL is_handled, void *opaque); 53 | void js_std_set_worker_new_context_func(JSContext *(*func)(JSRuntime *rt)); 54 | 55 | #ifdef __cplusplus 56 | } /* extern "C" { */ 57 | #endif 58 | 59 | #endif /* QUICKJS_LIBC_H */ 60 | -------------------------------------------------------------------------------- /Sources/QuickJSC/include/quickjs-opcode.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS opcode definitions 3 | * 4 | * Copyright (c) 2017-2018 Fabrice Bellard 5 | * Copyright (c) 2017-2018 Charlie Gordon 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #ifdef FMT 27 | FMT(none) 28 | FMT(none_int) 29 | FMT(none_loc) 30 | FMT(none_arg) 31 | FMT(none_var_ref) 32 | FMT(u8) 33 | FMT(i8) 34 | FMT(loc8) 35 | FMT(const8) 36 | FMT(label8) 37 | FMT(u16) 38 | FMT(i16) 39 | FMT(label16) 40 | FMT(npop) 41 | FMT(npopx) 42 | FMT(npop_u16) 43 | FMT(loc) 44 | FMT(arg) 45 | FMT(var_ref) 46 | FMT(u32) 47 | FMT(i32) 48 | FMT(const) 49 | FMT(label) 50 | FMT(atom) 51 | FMT(atom_u8) 52 | FMT(atom_u16) 53 | FMT(atom_label_u8) 54 | FMT(atom_label_u16) 55 | FMT(label_u16) 56 | #undef FMT 57 | #endif /* FMT */ 58 | 59 | #ifdef DEF 60 | 61 | #ifndef def 62 | #define def(id, size, n_pop, n_push, f) DEF(id, size, n_pop, n_push, f) 63 | #endif 64 | 65 | DEF(invalid, 1, 0, 0, none) /* never emitted */ 66 | 67 | /* push values */ 68 | DEF( push_i32, 5, 0, 1, i32) 69 | DEF( push_const, 5, 0, 1, const) 70 | DEF( fclosure, 5, 0, 1, const) /* must follow push_const */ 71 | DEF(push_atom_value, 5, 0, 1, atom) 72 | DEF( private_symbol, 5, 0, 1, atom) 73 | DEF( undefined, 1, 0, 1, none) 74 | DEF( null, 1, 0, 1, none) 75 | DEF( push_this, 1, 0, 1, none) /* only used at the start of a function */ 76 | DEF( push_false, 1, 0, 1, none) 77 | DEF( push_true, 1, 0, 1, none) 78 | DEF( object, 1, 0, 1, none) 79 | DEF( special_object, 2, 0, 1, u8) /* only used at the start of a function */ 80 | DEF( rest, 3, 0, 1, u16) /* only used at the start of a function */ 81 | 82 | DEF( drop, 1, 1, 0, none) /* a -> */ 83 | DEF( nip, 1, 2, 1, none) /* a b -> b */ 84 | DEF( nip1, 1, 3, 2, none) /* a b c -> b c */ 85 | DEF( dup, 1, 1, 2, none) /* a -> a a */ 86 | DEF( dup1, 1, 2, 3, none) /* a b -> a a b */ 87 | DEF( dup2, 1, 2, 4, none) /* a b -> a b a b */ 88 | DEF( dup3, 1, 3, 6, none) /* a b c -> a b c a b c */ 89 | DEF( insert2, 1, 2, 3, none) /* obj a -> a obj a (dup_x1) */ 90 | DEF( insert3, 1, 3, 4, none) /* obj prop a -> a obj prop a (dup_x2) */ 91 | DEF( insert4, 1, 4, 5, none) /* this obj prop a -> a this obj prop a */ 92 | DEF( perm3, 1, 3, 3, none) /* obj a b -> a obj b */ 93 | DEF( perm4, 1, 4, 4, none) /* obj prop a b -> a obj prop b */ 94 | DEF( perm5, 1, 5, 5, none) /* this obj prop a b -> a this obj prop b */ 95 | DEF( swap, 1, 2, 2, none) /* a b -> b a */ 96 | DEF( swap2, 1, 4, 4, none) /* a b c d -> c d a b */ 97 | DEF( rot3l, 1, 3, 3, none) /* x a b -> a b x */ 98 | DEF( rot3r, 1, 3, 3, none) /* a b x -> x a b */ 99 | DEF( rot4l, 1, 4, 4, none) /* x a b c -> a b c x */ 100 | DEF( rot5l, 1, 5, 5, none) /* x a b c d -> a b c d x */ 101 | 102 | DEF(call_constructor, 3, 2, 1, npop) /* func new.target args -> ret. arguments are not counted in n_pop */ 103 | DEF( call, 3, 1, 1, npop) /* arguments are not counted in n_pop */ 104 | DEF( tail_call, 3, 1, 0, npop) /* arguments are not counted in n_pop */ 105 | DEF( call_method, 3, 2, 1, npop) /* arguments are not counted in n_pop */ 106 | DEF(tail_call_method, 3, 2, 0, npop) /* arguments are not counted in n_pop */ 107 | DEF( array_from, 3, 0, 1, npop) /* arguments are not counted in n_pop */ 108 | DEF( apply, 3, 3, 1, u16) 109 | DEF( return, 1, 1, 0, none) 110 | DEF( return_undef, 1, 0, 0, none) 111 | DEF(check_ctor_return, 1, 1, 2, none) 112 | DEF( check_ctor, 1, 0, 0, none) 113 | DEF( check_brand, 1, 2, 2, none) /* this_obj func -> this_obj func */ 114 | DEF( add_brand, 1, 2, 0, none) /* this_obj home_obj -> */ 115 | DEF( return_async, 1, 1, 0, none) 116 | DEF( throw, 1, 1, 0, none) 117 | DEF( throw_error, 6, 0, 0, atom_u8) 118 | DEF( eval, 5, 1, 1, npop_u16) /* func args... -> ret_val */ 119 | DEF( apply_eval, 3, 2, 1, u16) /* func array -> ret_eval */ 120 | DEF( regexp, 1, 2, 1, none) /* create a RegExp object from the pattern and a 121 | bytecode string */ 122 | DEF( get_super, 1, 1, 1, none) 123 | DEF( import, 1, 1, 1, none) /* dynamic module import */ 124 | 125 | DEF( check_var, 5, 0, 1, atom) /* check if a variable exists */ 126 | DEF( get_var_undef, 5, 0, 1, atom) /* push undefined if the variable does not exist */ 127 | DEF( get_var, 5, 0, 1, atom) /* throw an exception if the variable does not exist */ 128 | DEF( put_var, 5, 1, 0, atom) /* must come after get_var */ 129 | DEF( put_var_init, 5, 1, 0, atom) /* must come after put_var. Used to initialize a global lexical variable */ 130 | DEF( put_var_strict, 5, 2, 0, atom) /* for strict mode variable write */ 131 | 132 | DEF( get_ref_value, 1, 2, 3, none) 133 | DEF( put_ref_value, 1, 3, 0, none) 134 | 135 | DEF( define_var, 6, 0, 0, atom_u8) 136 | DEF(check_define_var, 6, 0, 0, atom_u8) 137 | DEF( define_func, 6, 1, 0, atom_u8) 138 | DEF( get_field, 5, 1, 1, atom) 139 | DEF( get_field2, 5, 1, 2, atom) 140 | DEF( put_field, 5, 2, 0, atom) 141 | DEF( get_private_field, 1, 2, 1, none) /* obj prop -> value */ 142 | DEF( put_private_field, 1, 3, 0, none) /* obj value prop -> */ 143 | DEF(define_private_field, 1, 3, 1, none) /* obj prop value -> obj */ 144 | DEF( get_array_el, 1, 2, 1, none) 145 | DEF( get_array_el2, 1, 2, 2, none) /* obj prop -> obj value */ 146 | DEF( put_array_el, 1, 3, 0, none) 147 | DEF(get_super_value, 1, 3, 1, none) /* this obj prop -> value */ 148 | DEF(put_super_value, 1, 4, 0, none) /* this obj prop value -> */ 149 | DEF( define_field, 5, 2, 1, atom) 150 | DEF( set_name, 5, 1, 1, atom) 151 | DEF(set_name_computed, 1, 2, 2, none) 152 | DEF( set_proto, 1, 2, 1, none) 153 | DEF(set_home_object, 1, 2, 2, none) 154 | DEF(define_array_el, 1, 3, 2, none) 155 | DEF( append, 1, 3, 2, none) /* append enumerated object, update length */ 156 | DEF(copy_data_properties, 2, 3, 3, u8) 157 | DEF( define_method, 6, 2, 1, atom_u8) 158 | DEF(define_method_computed, 2, 3, 1, u8) /* must come after define_method */ 159 | DEF( define_class, 6, 2, 2, atom_u8) /* parent ctor -> ctor proto */ 160 | DEF( define_class_computed, 6, 3, 3, atom_u8) /* field_name parent ctor -> field_name ctor proto (class with computed name) */ 161 | 162 | DEF( get_loc, 3, 0, 1, loc) 163 | DEF( put_loc, 3, 1, 0, loc) /* must come after get_loc */ 164 | DEF( set_loc, 3, 1, 1, loc) /* must come after put_loc */ 165 | DEF( get_arg, 3, 0, 1, arg) 166 | DEF( put_arg, 3, 1, 0, arg) /* must come after get_arg */ 167 | DEF( set_arg, 3, 1, 1, arg) /* must come after put_arg */ 168 | DEF( get_var_ref, 3, 0, 1, var_ref) 169 | DEF( put_var_ref, 3, 1, 0, var_ref) /* must come after get_var_ref */ 170 | DEF( set_var_ref, 3, 1, 1, var_ref) /* must come after put_var_ref */ 171 | DEF(set_loc_uninitialized, 3, 0, 0, loc) 172 | DEF( get_loc_check, 3, 0, 1, loc) 173 | DEF( put_loc_check, 3, 1, 0, loc) /* must come after get_loc_check */ 174 | DEF( put_loc_check_init, 3, 1, 0, loc) 175 | DEF(get_var_ref_check, 3, 0, 1, var_ref) 176 | DEF(put_var_ref_check, 3, 1, 0, var_ref) /* must come after get_var_ref_check */ 177 | DEF(put_var_ref_check_init, 3, 1, 0, var_ref) 178 | DEF( close_loc, 3, 0, 0, loc) 179 | DEF( if_false, 5, 1, 0, label) 180 | DEF( if_true, 5, 1, 0, label) /* must come after if_false */ 181 | DEF( goto, 5, 0, 0, label) /* must come after if_true */ 182 | DEF( catch, 5, 0, 1, label) 183 | DEF( gosub, 5, 0, 0, label) /* used to execute the finally block */ 184 | DEF( ret, 1, 1, 0, none) /* used to return from the finally block */ 185 | 186 | DEF( to_object, 1, 1, 1, none) 187 | //DEF( to_string, 1, 1, 1, none) 188 | DEF( to_propkey, 1, 1, 1, none) 189 | DEF( to_propkey2, 1, 2, 2, none) 190 | 191 | DEF( with_get_var, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */ 192 | DEF( with_put_var, 10, 2, 1, atom_label_u8) /* must be in the same order as scope_xxx */ 193 | DEF(with_delete_var, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */ 194 | DEF( with_make_ref, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */ 195 | DEF( with_get_ref, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */ 196 | DEF(with_get_ref_undef, 10, 1, 0, atom_label_u8) 197 | 198 | DEF( make_loc_ref, 7, 0, 2, atom_u16) 199 | DEF( make_arg_ref, 7, 0, 2, atom_u16) 200 | DEF(make_var_ref_ref, 7, 0, 2, atom_u16) 201 | DEF( make_var_ref, 5, 0, 2, atom) 202 | 203 | DEF( for_in_start, 1, 1, 1, none) 204 | DEF( for_of_start, 1, 1, 3, none) 205 | DEF(for_await_of_start, 1, 1, 3, none) 206 | DEF( for_in_next, 1, 1, 3, none) 207 | DEF( for_of_next, 2, 3, 5, u8) 208 | DEF(iterator_check_object, 1, 1, 1, none) 209 | DEF(iterator_get_value_done, 1, 1, 2, none) 210 | DEF( iterator_close, 1, 3, 0, none) 211 | DEF(iterator_close_return, 1, 4, 4, none) 212 | DEF( iterator_next, 1, 4, 4, none) 213 | DEF( iterator_call, 2, 4, 5, u8) 214 | DEF( initial_yield, 1, 0, 0, none) 215 | DEF( yield, 1, 1, 2, none) 216 | DEF( yield_star, 1, 1, 2, none) 217 | DEF(async_yield_star, 1, 1, 2, none) 218 | DEF( await, 1, 1, 1, none) 219 | 220 | /* arithmetic/logic operations */ 221 | DEF( neg, 1, 1, 1, none) 222 | DEF( plus, 1, 1, 1, none) 223 | DEF( dec, 1, 1, 1, none) 224 | DEF( inc, 1, 1, 1, none) 225 | DEF( post_dec, 1, 1, 2, none) 226 | DEF( post_inc, 1, 1, 2, none) 227 | DEF( dec_loc, 2, 0, 0, loc8) 228 | DEF( inc_loc, 2, 0, 0, loc8) 229 | DEF( add_loc, 2, 1, 0, loc8) 230 | DEF( not, 1, 1, 1, none) 231 | DEF( lnot, 1, 1, 1, none) 232 | DEF( typeof, 1, 1, 1, none) 233 | DEF( delete, 1, 2, 1, none) 234 | DEF( delete_var, 5, 0, 1, atom) 235 | 236 | DEF( mul, 1, 2, 1, none) 237 | DEF( div, 1, 2, 1, none) 238 | DEF( mod, 1, 2, 1, none) 239 | DEF( add, 1, 2, 1, none) 240 | DEF( sub, 1, 2, 1, none) 241 | DEF( pow, 1, 2, 1, none) 242 | DEF( shl, 1, 2, 1, none) 243 | DEF( sar, 1, 2, 1, none) 244 | DEF( shr, 1, 2, 1, none) 245 | DEF( lt, 1, 2, 1, none) 246 | DEF( lte, 1, 2, 1, none) 247 | DEF( gt, 1, 2, 1, none) 248 | DEF( gte, 1, 2, 1, none) 249 | DEF( instanceof, 1, 2, 1, none) 250 | DEF( in, 1, 2, 1, none) 251 | DEF( eq, 1, 2, 1, none) 252 | DEF( neq, 1, 2, 1, none) 253 | DEF( strict_eq, 1, 2, 1, none) 254 | DEF( strict_neq, 1, 2, 1, none) 255 | DEF( and, 1, 2, 1, none) 256 | DEF( xor, 1, 2, 1, none) 257 | DEF( or, 1, 2, 1, none) 258 | DEF(is_undefined_or_null, 1, 1, 1, none) 259 | #ifdef CONFIG_BIGNUM 260 | DEF( mul_pow10, 1, 2, 1, none) 261 | DEF( math_mod, 1, 2, 1, none) 262 | #endif 263 | /* must be the last non short and non temporary opcode */ 264 | DEF( nop, 1, 0, 0, none) 265 | 266 | /* temporary opcodes: never emitted in the final bytecode */ 267 | 268 | def( enter_scope, 3, 0, 0, u16) /* emitted in phase 1, removed in phase 2 */ 269 | def( leave_scope, 3, 0, 0, u16) /* emitted in phase 1, removed in phase 2 */ 270 | 271 | def( label, 5, 0, 0, label) /* emitted in phase 1, removed in phase 3 */ 272 | 273 | def(scope_get_var_undef, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */ 274 | def( scope_get_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */ 275 | def( scope_put_var, 7, 1, 0, atom_u16) /* emitted in phase 1, removed in phase 2 */ 276 | def(scope_delete_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */ 277 | def( scope_make_ref, 11, 0, 2, atom_label_u16) /* emitted in phase 1, removed in phase 2 */ 278 | def( scope_get_ref, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */ 279 | def(scope_put_var_init, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */ 280 | def(scope_get_private_field, 7, 1, 1, atom_u16) /* obj -> value, emitted in phase 1, removed in phase 2 */ 281 | def(scope_get_private_field2, 7, 1, 2, atom_u16) /* obj -> obj value, emitted in phase 1, removed in phase 2 */ 282 | def(scope_put_private_field, 7, 1, 1, atom_u16) /* obj value ->, emitted in phase 1, removed in phase 2 */ 283 | 284 | def( set_class_name, 5, 1, 1, u32) /* emitted in phase 1, removed in phase 2 */ 285 | 286 | def( line_num, 5, 0, 0, u32) /* emitted in phase 1, removed in phase 3 */ 287 | 288 | #if SHORT_OPCODES 289 | DEF( push_minus1, 1, 0, 1, none_int) 290 | DEF( push_0, 1, 0, 1, none_int) 291 | DEF( push_1, 1, 0, 1, none_int) 292 | DEF( push_2, 1, 0, 1, none_int) 293 | DEF( push_3, 1, 0, 1, none_int) 294 | DEF( push_4, 1, 0, 1, none_int) 295 | DEF( push_5, 1, 0, 1, none_int) 296 | DEF( push_6, 1, 0, 1, none_int) 297 | DEF( push_7, 1, 0, 1, none_int) 298 | DEF( push_i8, 2, 0, 1, i8) 299 | DEF( push_i16, 3, 0, 1, i16) 300 | DEF( push_const8, 2, 0, 1, const8) 301 | DEF( fclosure8, 2, 0, 1, const8) /* must follow push_const8 */ 302 | DEF(push_empty_string, 1, 0, 1, none) 303 | 304 | DEF( get_loc8, 2, 0, 1, loc8) 305 | DEF( put_loc8, 2, 1, 0, loc8) 306 | DEF( set_loc8, 2, 1, 1, loc8) 307 | 308 | DEF( get_loc0, 1, 0, 1, none_loc) 309 | DEF( get_loc1, 1, 0, 1, none_loc) 310 | DEF( get_loc2, 1, 0, 1, none_loc) 311 | DEF( get_loc3, 1, 0, 1, none_loc) 312 | DEF( put_loc0, 1, 1, 0, none_loc) 313 | DEF( put_loc1, 1, 1, 0, none_loc) 314 | DEF( put_loc2, 1, 1, 0, none_loc) 315 | DEF( put_loc3, 1, 1, 0, none_loc) 316 | DEF( set_loc0, 1, 1, 1, none_loc) 317 | DEF( set_loc1, 1, 1, 1, none_loc) 318 | DEF( set_loc2, 1, 1, 1, none_loc) 319 | DEF( set_loc3, 1, 1, 1, none_loc) 320 | DEF( get_arg0, 1, 0, 1, none_arg) 321 | DEF( get_arg1, 1, 0, 1, none_arg) 322 | DEF( get_arg2, 1, 0, 1, none_arg) 323 | DEF( get_arg3, 1, 0, 1, none_arg) 324 | DEF( put_arg0, 1, 1, 0, none_arg) 325 | DEF( put_arg1, 1, 1, 0, none_arg) 326 | DEF( put_arg2, 1, 1, 0, none_arg) 327 | DEF( put_arg3, 1, 1, 0, none_arg) 328 | DEF( set_arg0, 1, 1, 1, none_arg) 329 | DEF( set_arg1, 1, 1, 1, none_arg) 330 | DEF( set_arg2, 1, 1, 1, none_arg) 331 | DEF( set_arg3, 1, 1, 1, none_arg) 332 | DEF( get_var_ref0, 1, 0, 1, none_var_ref) 333 | DEF( get_var_ref1, 1, 0, 1, none_var_ref) 334 | DEF( get_var_ref2, 1, 0, 1, none_var_ref) 335 | DEF( get_var_ref3, 1, 0, 1, none_var_ref) 336 | DEF( put_var_ref0, 1, 1, 0, none_var_ref) 337 | DEF( put_var_ref1, 1, 1, 0, none_var_ref) 338 | DEF( put_var_ref2, 1, 1, 0, none_var_ref) 339 | DEF( put_var_ref3, 1, 1, 0, none_var_ref) 340 | DEF( set_var_ref0, 1, 1, 1, none_var_ref) 341 | DEF( set_var_ref1, 1, 1, 1, none_var_ref) 342 | DEF( set_var_ref2, 1, 1, 1, none_var_ref) 343 | DEF( set_var_ref3, 1, 1, 1, none_var_ref) 344 | 345 | DEF( get_length, 1, 1, 1, none) 346 | 347 | DEF( if_false8, 2, 1, 0, label8) 348 | DEF( if_true8, 2, 1, 0, label8) /* must come after if_false8 */ 349 | DEF( goto8, 2, 0, 0, label8) /* must come after if_true8 */ 350 | DEF( goto16, 3, 0, 0, label16) 351 | 352 | DEF( call0, 1, 1, 1, npopx) 353 | DEF( call1, 1, 1, 1, npopx) 354 | DEF( call2, 1, 1, 1, npopx) 355 | DEF( call3, 1, 1, 1, npopx) 356 | 357 | DEF( is_undefined, 1, 1, 1, none) 358 | DEF( is_null, 1, 1, 1, none) 359 | DEF(typeof_is_undefined, 1, 1, 1, none) 360 | DEF( typeof_is_function, 1, 1, 1, none) 361 | #endif 362 | 363 | #undef DEF 364 | #undef def 365 | #endif /* DEF */ 366 | -------------------------------------------------------------------------------- /Sources/QuickJSC/include/quickjs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2020 Fabrice Bellard 5 | * Copyright (c) 2017-2020 Charlie Gordon 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | #ifndef QUICKJS_H 26 | #define QUICKJS_H 27 | 28 | #include 29 | #include 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | #define CONFIG_VERSION "2020-02-22" 36 | 37 | #if defined(__GNUC__) || defined(__clang__) 38 | #define js_likely(x) __builtin_expect(!!(x), 1) 39 | #define js_unlikely(x) __builtin_expect(!!(x), 0) 40 | #define js_force_inline inline __attribute__((always_inline)) 41 | #define __js_printf_like(f, a) __attribute__((format(printf, f, a))) 42 | #else 43 | #define js_likely(x) (x) 44 | #define js_unlikely(x) (x) 45 | #define js_force_inline inline 46 | #define __js_printf_like(a, b) 47 | #endif 48 | 49 | #define JS_BOOL int 50 | 51 | typedef struct JSRuntime JSRuntime; 52 | typedef struct JSContext JSContext; 53 | typedef struct JSObject JSObject; 54 | typedef struct JSClass JSClass; 55 | typedef uint32_t JSClassID; 56 | typedef uint32_t JSAtom; 57 | 58 | #if INTPTR_MAX >= INT64_MAX 59 | #define JS_PTR64 60 | #define JS_PTR64_DEF(a) a 61 | #else 62 | #define JS_PTR64_DEF(a) 63 | #endif 64 | 65 | #ifndef JS_PTR64 66 | #define JS_NAN_BOXING 67 | #endif 68 | 69 | enum { 70 | /* all tags with a reference count are negative */ 71 | JS_TAG_FIRST = -11, /* first negative tag */ 72 | JS_TAG_BIG_DECIMAL = -11, 73 | JS_TAG_BIG_INT = -10, 74 | JS_TAG_BIG_FLOAT = -9, 75 | JS_TAG_SYMBOL = -8, 76 | JS_TAG_STRING = -7, 77 | JS_TAG_MODULE = -3, /* used internally */ 78 | JS_TAG_FUNCTION_BYTECODE = -2, /* used internally */ 79 | JS_TAG_OBJECT = -1, 80 | 81 | JS_TAG_INT = 0, 82 | JS_TAG_BOOL = 1, 83 | JS_TAG_NULL = 2, 84 | JS_TAG_UNDEFINED = 3, 85 | JS_TAG_UNINITIALIZED = 4, 86 | JS_TAG_CATCH_OFFSET = 5, 87 | JS_TAG_EXCEPTION = 6, 88 | JS_TAG_FLOAT64 = 7, 89 | /* any larger tag is FLOAT64 if JS_NAN_BOXING */ 90 | }; 91 | 92 | typedef struct JSRefCountHeader { 93 | int ref_count; 94 | } JSRefCountHeader; 95 | 96 | #define JS_FLOAT64_NAN NAN 97 | 98 | #ifdef CONFIG_CHECK_JSVALUE 99 | /* JSValue consistency : it is not possible to run the code in this 100 | mode, but it is useful to detect simple reference counting 101 | errors. It would be interesting to modify a static C analyzer to 102 | handle specific annotations (clang has such annotations but only 103 | for objective C) */ 104 | typedef struct __JSValue *JSValue; 105 | typedef const struct __JSValue *JSCValueonst; 106 | 107 | #define JS_VALUE_GET_TAG(v) (int)((uintptr_t)(v) & 0xf) 108 | /* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */ 109 | #define JS_VALUE_GET_NORM_TAG(v) JS_VALUE_GET_TAG(v) 110 | #define JS_VALUE_GET_INT(v) (int)((intptr_t)(v) >> 4) 111 | #define JS_VALUE_GET_BOOL(v) JS_VALUE_GET_INT(v) 112 | #define JS_VALUE_GET_FLOAT64(v) (double)JS_VALUE_GET_INT(v) 113 | #define JS_VALUE_GET_PTR(v) (void *)((intptr_t)(v) & ~0xf) 114 | 115 | #define JS_MKVAL(tag, val) (JSValue)(intptr_t)(((val) << 4) | (tag)) 116 | #define JS_MKPTR(tag, p) (JSValue)((intptr_t)(p) | (tag)) 117 | 118 | #define JS_TAG_IS_FLOAT64(tag) ((unsigned)(tag) == JS_TAG_FLOAT64) 119 | 120 | #define JS_NAN JS_MKVAL(JS_TAG_FLOAT64, 1) 121 | 122 | static inline JSValue __JS_NewFloat64(JSContext *ctx, double d) 123 | { 124 | return JS_MKVAL(JS_TAG_FLOAT64, (int)d); 125 | } 126 | 127 | static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v) 128 | { 129 | return 0; 130 | } 131 | 132 | #elif defined(JS_NAN_BOXING) 133 | 134 | typedef uint64_t JSValue; 135 | 136 | #define JSCValueonst JSValue 137 | 138 | #define JS_VALUE_GET_TAG(v) (int)((v) >> 32) 139 | #define JS_VALUE_GET_INT(v) (int)(v) 140 | #define JS_VALUE_GET_BOOL(v) (int)(v) 141 | #define JS_VALUE_GET_PTR(v) (void *)(intptr_t)(v) 142 | 143 | #define JS_MKVAL(tag, val) (((uint64_t)(tag) << 32) | (uint32_t)(val)) 144 | #define JS_MKPTR(tag, ptr) (((uint64_t)(tag) << 32) | (uintptr_t)(ptr)) 145 | 146 | #define JS_FLOAT64_TAG_ADDEND (0x7ff80000 - JS_TAG_FIRST + 1) /* quiet NaN encoding */ 147 | 148 | static inline double JS_VALUE_GET_FLOAT64(JSValue v) 149 | { 150 | union { 151 | JSValue v; 152 | double d; 153 | } u; 154 | u.v = v; 155 | u.v += (uint64_t)JS_FLOAT64_TAG_ADDEND << 32; 156 | return u.d; 157 | } 158 | 159 | #define JS_NAN (0x7ff8000000000000 - ((uint64_t)JS_FLOAT64_TAG_ADDEND << 32)) 160 | 161 | static inline JSValue __JS_NewFloat64(JSContext *ctx, double d) 162 | { 163 | union { 164 | double d; 165 | uint64_t u64; 166 | } u; 167 | JSValue v; 168 | u.d = d; 169 | /* normalize NaN */ 170 | if (js_unlikely((u.u64 & 0x7fffffffffffffff) > 0x7ff0000000000000)) 171 | v = JS_NAN; 172 | else 173 | v = u.u64 - ((uint64_t)JS_FLOAT64_TAG_ADDEND << 32); 174 | return v; 175 | } 176 | 177 | #define JS_TAG_IS_FLOAT64(tag) ((unsigned)((tag) - JS_TAG_FIRST) >= (JS_TAG_FLOAT64 - JS_TAG_FIRST)) 178 | 179 | /* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */ 180 | static inline int JS_VALUE_GET_NORM_TAG(JSValue v) 181 | { 182 | uint32_t tag; 183 | tag = JS_VALUE_GET_TAG(v); 184 | if (JS_TAG_IS_FLOAT64(tag)) 185 | return JS_TAG_FLOAT64; 186 | else 187 | return tag; 188 | } 189 | 190 | static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v) 191 | { 192 | uint32_t tag; 193 | tag = JS_VALUE_GET_TAG(v); 194 | return tag == (JS_NAN >> 32); 195 | } 196 | 197 | #else /* !JS_NAN_BOXING */ 198 | 199 | typedef union JSValueUnion { 200 | int32_t int32; 201 | double float64; 202 | void *ptr; 203 | } JSValueUnion; 204 | 205 | typedef struct JSValue { 206 | JSValueUnion u; 207 | int64_t tag; 208 | } JSValue; 209 | 210 | #define JSCValueonst JSValue 211 | 212 | #define JS_VALUE_GET_TAG(v) ((int32_t)(v).tag) 213 | /* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */ 214 | #define JS_VALUE_GET_NORM_TAG(v) JS_VALUE_GET_TAG(v) 215 | #define JS_VALUE_GET_INT(v) ((v).u.int32) 216 | #define JS_VALUE_GET_BOOL(v) ((v).u.int32) 217 | #define JS_VALUE_GET_FLOAT64(v) ((v).u.float64) 218 | #define JS_VALUE_GET_PTR(v) ((v).u.ptr) 219 | 220 | #define JS_MKVAL(tag, val) (JSValue){ (JSValueUnion){ .int32 = val }, tag } 221 | #define JS_MKPTR(tag, p) (JSValue){ (JSValueUnion){ .ptr = p }, tag } 222 | 223 | #define JS_TAG_IS_FLOAT64(tag) ((unsigned)(tag) == JS_TAG_FLOAT64) 224 | 225 | #define JS_NAN (JSValue){ .u.float64 = JS_FLOAT64_NAN, JS_TAG_FLOAT64 } 226 | 227 | static inline JSValue __JS_NewFloat64(JSContext *ctx, double d) 228 | { 229 | JSValue v; 230 | v.tag = JS_TAG_FLOAT64; 231 | v.u.float64 = d; 232 | return v; 233 | } 234 | 235 | static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v) 236 | { 237 | union { 238 | double d; 239 | uint64_t u64; 240 | } u; 241 | if (v.tag != JS_TAG_FLOAT64) 242 | return 0; 243 | u.d = v.u.float64; 244 | return (u.u64 & 0x7fffffffffffffff) > 0x7ff0000000000000; 245 | } 246 | 247 | #endif /* !JS_NAN_BOXING */ 248 | 249 | #define JS_VALUE_IS_BOTH_INT(v1, v2) ((JS_VALUE_GET_TAG(v1) | JS_VALUE_GET_TAG(v2)) == 0) 250 | #define JS_VALUE_IS_BOTH_FLOAT(v1, v2) (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v1)) && JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v2))) 251 | 252 | #define JS_VALUE_GET_OBJ(v) ((JSObject *)JS_VALUE_GET_PTR(v)) 253 | #define JS_VALUE_GET_STRING(v) ((JSString *)JS_VALUE_GET_PTR(v)) 254 | #define JS_VALUE_HAS_REF_COUNT(v) ((unsigned)JS_VALUE_GET_TAG(v) >= (unsigned)JS_TAG_FIRST) 255 | 256 | /* special values */ 257 | #define JS_NULL JS_MKVAL(JS_TAG_NULL, 0) 258 | #define JS_UNDEFINED JS_MKVAL(JS_TAG_UNDEFINED, 0) 259 | #define JS_FALSE JS_MKVAL(JS_TAG_BOOL, 0) 260 | #define JS_TRUE JS_MKVAL(JS_TAG_BOOL, 1) 261 | #define JS_EXCEPTION JS_MKVAL(JS_TAG_EXCEPTION, 0) 262 | #define JS_UNINITIALIZED JS_MKVAL(JS_TAG_UNINITIALIZED, 0) 263 | 264 | /* flags for object properties */ 265 | #define JS_PROP_CONFIGURABLE (1 << 0) 266 | #define JS_PROP_WRITABLE (1 << 1) 267 | #define JS_PROP_ENUMERABLE (1 << 2) 268 | #define JS_PROP_C_W_E (JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE | JS_PROP_ENUMERABLE) 269 | #define JS_PROP_LENGTH (1 << 3) /* used internally in Arrays */ 270 | #define JS_PROP_TMASK (3 << 4) /* mask for NORMAL, GETSET, VARREF, AUTOINIT */ 271 | #define JS_PROP_NORMAL (0 << 4) 272 | #define JS_PROP_GETSET (1 << 4) 273 | #define JS_PROP_VARREF (2 << 4) /* used internally */ 274 | #define JS_PROP_AUTOINIT (3 << 4) /* used internally */ 275 | 276 | /* flags for JS_DefineProperty */ 277 | #define JS_PROP_HAS_SHIFT 8 278 | #define JS_PROP_HAS_CONFIGURABLE (1 << 8) 279 | #define JS_PROP_HAS_WRITABLE (1 << 9) 280 | #define JS_PROP_HAS_ENUMERABLE (1 << 10) 281 | #define JS_PROP_HAS_GET (1 << 11) 282 | #define JS_PROP_HAS_SET (1 << 12) 283 | #define JS_PROP_HAS_VALUE (1 << 13) 284 | 285 | /* throw an exception if false would be returned 286 | (JS_DefineProperty/JS_SetProperty) */ 287 | #define JS_PROP_THROW (1 << 14) 288 | /* throw an exception if false would be returned in strict mode 289 | (JS_SetProperty) */ 290 | #define JS_PROP_THROW_STRICT (1 << 15) 291 | 292 | #define JS_PROP_NO_ADD (1 << 16) /* internal use */ 293 | #define JS_PROP_NO_EXOTIC (1 << 17) /* internal use */ 294 | 295 | #define JS_DEFAULT_STACK_SIZE (256 * 1024) 296 | 297 | /* JS_Eval() flags */ 298 | #define JS_EVAL_TYPE_GLOBAL (0 << 0) /* global code (default) */ 299 | #define JS_EVAL_TYPE_MODULE (1 << 0) /* module code */ 300 | #define JS_EVAL_TYPE_DIRECT (2 << 0) /* direct call (internal use) */ 301 | #define JS_EVAL_TYPE_INDIRECT (3 << 0) /* indirect call (internal use) */ 302 | #define JS_EVAL_TYPE_MASK (3 << 0) 303 | 304 | #define JS_EVAL_FLAG_STRICT (1 << 3) /* force 'strict' mode */ 305 | #define JS_EVAL_FLAG_STRIP (1 << 4) /* force 'strip' mode */ 306 | /* compile but do not run. The result is an object with a 307 | JS_TAG_FUNCTION_BYTECODE or JS_TAG_MODULE tag. It can be executed 308 | with JS_EvalFunction(). */ 309 | #define JS_EVAL_FLAG_COMPILE_ONLY (1 << 5) 310 | /* don't include the stack frames before this eval in the Error() backtraces */ 311 | #define JS_EVAL_FLAG_BACKTRACE_BARRIER (1 << 6) 312 | 313 | typedef JSValue JSCFunction(JSContext *ctx, JSCValueonst this_val, int argc, JSCValueonst *argv); 314 | typedef JSValue JSCFunctionMagic(JSContext *ctx, JSCValueonst this_val, int argc, JSCValueonst *argv, int magic); 315 | typedef JSValue JSCFunctionData(JSContext *ctx, JSCValueonst this_val, int argc, JSCValueonst *argv, int magic, JSValue *func_data); 316 | 317 | typedef struct JSMallocState { 318 | size_t malloc_count; 319 | size_t malloc_size; 320 | size_t malloc_limit; 321 | void *opaque; /* user opaque */ 322 | } JSMallocState; 323 | 324 | typedef struct JSMallocFunctions { 325 | void *(*js_malloc)(JSMallocState *s, size_t size); 326 | void (*js_free)(JSMallocState *s, void *ptr); 327 | void *(*js_realloc)(JSMallocState *s, void *ptr, size_t size); 328 | size_t (*js_malloc_usable_size)(const void *ptr); 329 | } JSMallocFunctions; 330 | 331 | typedef struct JSGCObjectHeader JSGCObjectHeader; 332 | 333 | JSRuntime *JS_NewRuntime(void); 334 | /* info lifetime must exceed that of rt */ 335 | void JS_SetRuntimeInfo(JSRuntime *rt, const char *info); 336 | void JS_SetMemoryLimit(JSRuntime *rt, size_t limit); 337 | void JS_SetGCThreshold(JSRuntime *rt, size_t gc_threshold); 338 | void JS_SetMaxStackSize(JSRuntime *rt, size_t stack_size); 339 | JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque); 340 | void JS_FreeRuntime(JSRuntime *rt); 341 | void *JS_GetRuntimeOpaque(JSRuntime *rt); 342 | void JS_SetRuntimeOpaque(JSRuntime *rt, void *opaque); 343 | typedef void JS_MarkFunc(JSRuntime *rt, JSGCObjectHeader *gp); 344 | void JS_MarkValue(JSRuntime *rt, JSCValueonst val, JS_MarkFunc *mark_func); 345 | void JS_RunGC(JSRuntime *rt); 346 | JS_BOOL JS_IsLiveObject(JSRuntime *rt, JSCValueonst obj); 347 | 348 | JSContext *JS_NewContext(JSRuntime *rt); 349 | void JS_FreeContext(JSContext *s); 350 | JSContext *JS_DupContext(JSContext *ctx); 351 | void *JS_GetContextOpaque(JSContext *ctx); 352 | void JS_SetContextOpaque(JSContext *ctx, void *opaque); 353 | JSRuntime *JS_GetRuntime(JSContext *ctx); 354 | void JS_SetClassProto(JSContext *ctx, JSClassID class_id, JSValue obj); 355 | JSValue JS_GetClassProto(JSContext *ctx, JSClassID class_id); 356 | 357 | /* the following functions are used to select the intrinsic object to 358 | save memory */ 359 | JSContext *JS_NewContextRaw(JSRuntime *rt); 360 | void JS_AddIntrinsicBaseObjects(JSContext *ctx); 361 | void JS_AddIntrinsicDate(JSContext *ctx); 362 | void JS_AddIntrinsicEval(JSContext *ctx); 363 | void JS_AddIntrinsicStringNormalize(JSContext *ctx); 364 | void JS_AddIntrinsicRegExpCompiler(JSContext *ctx); 365 | void JS_AddIntrinsicRegExp(JSContext *ctx); 366 | void JS_AddIntrinsicJSON(JSContext *ctx); 367 | void JS_AddIntrinsicProxy(JSContext *ctx); 368 | void JS_AddIntrinsicMapSet(JSContext *ctx); 369 | void JS_AddIntrinsicTypedArrays(JSContext *ctx); 370 | void JS_AddIntrinsicPromise(JSContext *ctx); 371 | void JS_AddIntrinsicBigInt(JSContext *ctx); 372 | void JS_AddIntrinsicBigFloat(JSContext *ctx); 373 | void JS_AddIntrinsicBigDecimal(JSContext *ctx); 374 | /* enable operator overloading */ 375 | void JS_AddIntrinsicOperators(JSContext *ctx); 376 | /* enable "use math" */ 377 | void JS_EnableBignumExt(JSContext *ctx, JS_BOOL enable); 378 | 379 | JSValue js_string_codePointRange(JSContext *ctx, JSCValueonst this_val, 380 | int argc, JSCValueonst *argv); 381 | 382 | void *js_malloc_rt(JSRuntime *rt, size_t size); 383 | void js_free_rt(JSRuntime *rt, void *ptr); 384 | void *js_realloc_rt(JSRuntime *rt, void *ptr, size_t size); 385 | size_t js_malloc_usable_size_rt(JSRuntime *rt, const void *ptr); 386 | void *js_mallocz_rt(JSRuntime *rt, size_t size); 387 | 388 | void *js_malloc(JSContext *ctx, size_t size); 389 | void js_free(JSContext *ctx, void *ptr); 390 | void *js_realloc(JSContext *ctx, void *ptr, size_t size); 391 | size_t js_malloc_usable_size(JSContext *ctx, const void *ptr); 392 | void *js_realloc2(JSContext *ctx, void *ptr, size_t size, size_t *pslack); 393 | void *js_mallocz(JSContext *ctx, size_t size); 394 | char *js_strdup(JSContext *ctx, const char *str); 395 | char *js_strndup(JSContext *ctx, const char *s, size_t n); 396 | 397 | typedef struct JSMemoryUsage { 398 | int64_t malloc_size, malloc_limit, memory_used_size; 399 | int64_t malloc_count; 400 | int64_t memory_used_count; 401 | int64_t atom_count, atom_size; 402 | int64_t str_count, str_size; 403 | int64_t obj_count, obj_size; 404 | int64_t prop_count, prop_size; 405 | int64_t shape_count, shape_size; 406 | int64_t js_func_count, js_func_size, js_func_code_size; 407 | int64_t js_func_pc2line_count, js_func_pc2line_size; 408 | int64_t c_func_count, array_count; 409 | int64_t fast_array_count, fast_array_elements; 410 | int64_t binary_object_count, binary_object_size; 411 | } JSMemoryUsage; 412 | 413 | void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s); 414 | void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt); 415 | 416 | /* atom support */ 417 | #define JS_ATOM_NULL 0 418 | 419 | JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len); 420 | JSAtom JS_NewAtom(JSContext *ctx, const char *str); 421 | JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n); 422 | JSAtom JS_DupAtom(JSContext *ctx, JSAtom v); 423 | void JS_FreeAtom(JSContext *ctx, JSAtom v); 424 | void JS_FreeAtomRT(JSRuntime *rt, JSAtom v); 425 | JSValue JS_AtomToValue(JSContext *ctx, JSAtom atom); 426 | JSValue JS_AtomToString(JSContext *ctx, JSAtom atom); 427 | const char *JS_AtomToCString(JSContext *ctx, JSAtom atom); 428 | JSAtom JS_ValueToAtom(JSContext *ctx, JSCValueonst val); 429 | 430 | /* object class support */ 431 | 432 | typedef struct JSPropertyEnum { 433 | JS_BOOL is_enumerable; 434 | JSAtom atom; 435 | } JSPropertyEnum; 436 | 437 | typedef struct JSPropertyDescriptor { 438 | int flags; 439 | JSValue value; 440 | JSValue getter; 441 | JSValue setter; 442 | } JSPropertyDescriptor; 443 | 444 | typedef struct JSClassExoticMethods { 445 | /* Return -1 if exception (can only happen in case of Proxy object), 446 | FALSE if the property does not exists, TRUE if it exists. If 1 is 447 | returned, the property descriptor 'desc' is filled if != NULL. */ 448 | int (*get_own_property)(JSContext *ctx, JSPropertyDescriptor *desc, 449 | JSCValueonst obj, JSAtom prop); 450 | /* '*ptab' should hold the '*plen' property keys. Return 0 if OK, 451 | -1 if exception. The 'is_enumerable' field is ignored. 452 | */ 453 | int (*get_own_property_names)(JSContext *ctx, JSPropertyEnum **ptab, 454 | uint32_t *plen, 455 | JSCValueonst obj); 456 | /* return < 0 if exception, or TRUE/FALSE */ 457 | int (*delete_property)(JSContext *ctx, JSCValueonst obj, JSAtom prop); 458 | /* return < 0 if exception or TRUE/FALSE */ 459 | int (*define_own_property)(JSContext *ctx, JSCValueonst this_obj, 460 | JSAtom prop, JSCValueonst val, 461 | JSCValueonst getter, JSCValueonst setter, 462 | int flags); 463 | /* The following methods can be emulated with the previous ones, 464 | so they are usually not needed */ 465 | /* return < 0 if exception or TRUE/FALSE */ 466 | int (*has_property)(JSContext *ctx, JSCValueonst obj, JSAtom atom); 467 | JSValue (*get_property)(JSContext *ctx, JSCValueonst obj, JSAtom atom, 468 | JSCValueonst receiver); 469 | /* return < 0 if exception or TRUE/FALSE */ 470 | int (*set_property)(JSContext *ctx, JSCValueonst obj, JSAtom atom, 471 | JSCValueonst value, JSCValueonst receiver, int flags); 472 | } JSClassExoticMethods; 473 | 474 | typedef void JSClassFinalizer(JSRuntime *rt, JSValue val); 475 | typedef void JSClassGCMark(JSRuntime *rt, JSCValueonst val, 476 | JS_MarkFunc *mark_func); 477 | #define JS_CALL_FLAG_CONSTRUCTOR (1 << 0) 478 | typedef JSValue JSClassCall(JSContext *ctx, JSCValueonst func_obj, 479 | JSCValueonst this_val, int argc, JSCValueonst *argv, 480 | int flags); 481 | 482 | typedef struct JSClassDef { 483 | const char *class_name; 484 | JSClassFinalizer *finalizer; 485 | JSClassGCMark *gc_mark; 486 | /* if call != NULL, the object is a function. If (flags & 487 | JS_CALL_FLAG_CONSTRUCTOR) != 0, the function is called as a 488 | constructor. In this case, 'this_val' is new.target. A 489 | constructor call only happens if the object constructor bit is 490 | set (see JS_SetConstructorBit()). */ 491 | JSClassCall *call; 492 | /* XXX: suppress this indirection ? It is here only to save memory 493 | because only a few classes need these methods */ 494 | JSClassExoticMethods *exotic; 495 | } JSClassDef; 496 | 497 | JSClassID JS_NewClassID(JSClassID *pclass_id); 498 | int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def); 499 | int JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id); 500 | 501 | /* value handling */ 502 | 503 | static js_force_inline JSValue JS_NewBool(JSContext *ctx, JS_BOOL val) 504 | { 505 | return JS_MKVAL(JS_TAG_BOOL, (val != 0)); 506 | } 507 | 508 | static js_force_inline JSValue JS_NewInt32(JSContext *ctx, int32_t val) 509 | { 510 | return JS_MKVAL(JS_TAG_INT, val); 511 | } 512 | 513 | static js_force_inline JSValue JS_NewCatchOffset(JSContext *ctx, int32_t val) 514 | { 515 | return JS_MKVAL(JS_TAG_CATCH_OFFSET, val); 516 | } 517 | 518 | static js_force_inline JSValue JS_NewInt64(JSContext *ctx, int64_t val) 519 | { 520 | JSValue v; 521 | if (val == (int32_t)val) { 522 | v = JS_NewInt32(ctx, val); 523 | } else { 524 | v = __JS_NewFloat64(ctx, val); 525 | } 526 | return v; 527 | } 528 | 529 | static js_force_inline JSValue JS_NewUint32(JSContext *ctx, uint32_t val) 530 | { 531 | JSValue v; 532 | if (val <= 0x7fffffff) { 533 | v = JS_NewInt32(ctx, val); 534 | } else { 535 | v = __JS_NewFloat64(ctx, val); 536 | } 537 | return v; 538 | } 539 | 540 | JSValue JS_NewBigInt64(JSContext *ctx, int64_t v); 541 | JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v); 542 | 543 | static js_force_inline JSValue JS_NewFloat64(JSContext *ctx, double d) 544 | { 545 | JSValue v; 546 | int32_t val; 547 | union { 548 | double d; 549 | uint64_t u; 550 | } u, t; 551 | u.d = d; 552 | val = (int32_t)d; 553 | t.d = val; 554 | /* -0 cannot be represented as integer, so we compare the bit 555 | representation */ 556 | if (u.u == t.u) { 557 | v = JS_MKVAL(JS_TAG_INT, val); 558 | } else { 559 | v = __JS_NewFloat64(ctx, d); 560 | } 561 | return v; 562 | } 563 | 564 | static inline JS_BOOL JS_IsNumber(JSCValueonst v) 565 | { 566 | int tag = JS_VALUE_GET_TAG(v); 567 | return tag == JS_TAG_INT || JS_TAG_IS_FLOAT64(tag); 568 | } 569 | 570 | static inline JS_BOOL JS_IsBigInt(JSContext *ctx, JSCValueonst v) 571 | { 572 | int tag = JS_VALUE_GET_TAG(v); 573 | return tag == JS_TAG_BIG_INT; 574 | } 575 | 576 | static inline JS_BOOL JS_IsBigFloat(JSCValueonst v) 577 | { 578 | int tag = JS_VALUE_GET_TAG(v); 579 | return tag == JS_TAG_BIG_FLOAT; 580 | } 581 | 582 | static inline JS_BOOL JS_IsBigDecimal(JSCValueonst v) 583 | { 584 | int tag = JS_VALUE_GET_TAG(v); 585 | return tag == JS_TAG_BIG_DECIMAL; 586 | } 587 | 588 | static inline JS_BOOL JS_IsBool(JSCValueonst v) 589 | { 590 | return JS_VALUE_GET_TAG(v) == JS_TAG_BOOL; 591 | } 592 | 593 | static inline JS_BOOL JS_IsNull(JSCValueonst v) 594 | { 595 | return JS_VALUE_GET_TAG(v) == JS_TAG_NULL; 596 | } 597 | 598 | static inline JS_BOOL JS_IsUndefined(JSCValueonst v) 599 | { 600 | return JS_VALUE_GET_TAG(v) == JS_TAG_UNDEFINED; 601 | } 602 | 603 | static inline JS_BOOL JS_IsException(JSCValueonst v) 604 | { 605 | return js_unlikely(JS_VALUE_GET_TAG(v) == JS_TAG_EXCEPTION); 606 | } 607 | 608 | static inline JS_BOOL JS_IsUninitialized(JSCValueonst v) 609 | { 610 | return js_unlikely(JS_VALUE_GET_TAG(v) == JS_TAG_UNINITIALIZED); 611 | } 612 | 613 | static inline JS_BOOL JS_IsString(JSCValueonst v) 614 | { 615 | return JS_VALUE_GET_TAG(v) == JS_TAG_STRING; 616 | } 617 | 618 | static inline JS_BOOL JS_IsSymbol(JSCValueonst v) 619 | { 620 | return JS_VALUE_GET_TAG(v) == JS_TAG_SYMBOL; 621 | } 622 | 623 | static inline JS_BOOL JS_IsObject(JSCValueonst v) 624 | { 625 | return JS_VALUE_GET_TAG(v) == JS_TAG_OBJECT; 626 | } 627 | 628 | JSValue JS_Throw(JSContext *ctx, JSValue obj); 629 | JSValue JS_GetException(JSContext *ctx); 630 | JS_BOOL JS_IsError(JSContext *ctx, JSCValueonst val); 631 | void JS_ResetUncatchableError(JSContext *ctx); 632 | JSValue JS_NewError(JSContext *ctx); 633 | JSValue __js_printf_like(2, 3) JS_ThrowSyntaxError(JSContext *ctx, const char *fmt, ...); 634 | JSValue __js_printf_like(2, 3) JS_ThrowTypeError(JSContext *ctx, const char *fmt, ...); 635 | JSValue __js_printf_like(2, 3) JS_ThrowReferenceError(JSContext *ctx, const char *fmt, ...); 636 | JSValue __js_printf_like(2, 3) JS_ThrowRangeError(JSContext *ctx, const char *fmt, ...); 637 | JSValue __js_printf_like(2, 3) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...); 638 | JSValue JS_ThrowOutOfMemory(JSContext *ctx); 639 | 640 | void __JS_FreeValue(JSContext *ctx, JSValue v); 641 | static inline void JS_FreeValue(JSContext *ctx, JSValue v) 642 | { 643 | if (JS_VALUE_HAS_REF_COUNT(v)) { 644 | JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); 645 | if (--p->ref_count <= 0) { 646 | __JS_FreeValue(ctx, v); 647 | } 648 | } 649 | } 650 | void __JS_FreeValueRT(JSRuntime *rt, JSValue v); 651 | static inline void JS_FreeValueRT(JSRuntime *rt, JSValue v) 652 | { 653 | if (JS_VALUE_HAS_REF_COUNT(v)) { 654 | JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); 655 | if (--p->ref_count <= 0) { 656 | __JS_FreeValueRT(rt, v); 657 | } 658 | } 659 | } 660 | 661 | static inline JSValue JS_DupValue(JSContext *ctx, JSCValueonst v) 662 | { 663 | if (JS_VALUE_HAS_REF_COUNT(v)) { 664 | JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); 665 | p->ref_count++; 666 | } 667 | return (JSValue)v; 668 | } 669 | 670 | static inline JSValue JS_DupValueRT(JSRuntime *rt, JSCValueonst v) 671 | { 672 | if (JS_VALUE_HAS_REF_COUNT(v)) { 673 | JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); 674 | p->ref_count++; 675 | } 676 | return (JSValue)v; 677 | } 678 | 679 | int JS_ToBool(JSContext *ctx, JSCValueonst val); /* return -1 for JS_EXCEPTION */ 680 | int JS_ToInt32(JSContext *ctx, int32_t *pres, JSCValueonst val); 681 | static inline int JS_ToUint32(JSContext *ctx, uint32_t *pres, JSCValueonst val) 682 | { 683 | return JS_ToInt32(ctx, (int32_t*)pres, val); 684 | } 685 | int JS_ToInt64(JSContext *ctx, int64_t *pres, JSCValueonst val); 686 | int JS_ToIndex(JSContext *ctx, uint64_t *plen, JSCValueonst val); 687 | int JS_ToFloat64(JSContext *ctx, double *pres, JSCValueonst val); 688 | /* return an exception if 'val' is a Number */ 689 | int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSCValueonst val); 690 | /* same as JS_ToInt64() but allow BigInt */ 691 | int JS_ToInt64Ext(JSContext *ctx, int64_t *pres, JSCValueonst val); 692 | 693 | JSValue JS_NewStringLen(JSContext *ctx, const char *str1, size_t len1); 694 | JSValue JS_NewString(JSContext *ctx, const char *str); 695 | JSValue JS_NewAtomString(JSContext *ctx, const char *str); 696 | JSValue JS_ToString(JSContext *ctx, JSCValueonst val); 697 | JSValue JS_ToPropertyKey(JSContext *ctx, JSCValueonst val); 698 | const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSCValueonst val1, JS_BOOL cesu8); 699 | static inline const char *JS_ToCStringLen(JSContext *ctx, size_t *plen, JSCValueonst val1) 700 | { 701 | return JS_ToCStringLen2(ctx, plen, val1, 0); 702 | } 703 | static inline const char *JS_ToCString(JSContext *ctx, JSCValueonst val1) 704 | { 705 | return JS_ToCStringLen2(ctx, NULL, val1, 0); 706 | } 707 | void JS_FreeCString(JSContext *ctx, const char *ptr); 708 | 709 | JSValue JS_NewObjectProtoClass(JSContext *ctx, JSCValueonst proto, JSClassID class_id); 710 | JSValue JS_NewObjectClass(JSContext *ctx, int class_id); 711 | JSValue JS_NewObjectProto(JSContext *ctx, JSCValueonst proto); 712 | JSValue JS_NewObject(JSContext *ctx); 713 | 714 | JS_BOOL JS_IsFunction(JSContext* ctx, JSCValueonst val); 715 | JS_BOOL JS_IsConstructor(JSContext* ctx, JSCValueonst val); 716 | JS_BOOL JS_SetConstructorBit(JSContext *ctx, JSCValueonst func_obj, JS_BOOL val); 717 | 718 | JSValue JS_NewArray(JSContext *ctx); 719 | int JS_IsArray(JSContext *ctx, JSCValueonst val); 720 | 721 | JSValue JS_GetPropertyInternal(JSContext *ctx, JSCValueonst obj, 722 | JSAtom prop, JSCValueonst receiver, 723 | JS_BOOL throw_ref_error); 724 | static js_force_inline JSValue JS_GetProperty(JSContext *ctx, JSCValueonst this_obj, 725 | JSAtom prop) 726 | { 727 | return JS_GetPropertyInternal(ctx, this_obj, prop, this_obj, 0); 728 | } 729 | JSValue JS_GetPropertyStr(JSContext *ctx, JSCValueonst this_obj, 730 | const char *prop); 731 | JSValue JS_GetPropertyUint32(JSContext *ctx, JSCValueonst this_obj, 732 | uint32_t idx); 733 | 734 | int JS_SetPropertyInternal(JSContext *ctx, JSCValueonst this_obj, 735 | JSAtom prop, JSValue val, 736 | int flags); 737 | static inline int JS_SetProperty(JSContext *ctx, JSCValueonst this_obj, 738 | JSAtom prop, JSValue val) 739 | { 740 | return JS_SetPropertyInternal(ctx, this_obj, prop, val, JS_PROP_THROW); 741 | } 742 | int JS_SetPropertyUint32(JSContext *ctx, JSCValueonst this_obj, 743 | uint32_t idx, JSValue val); 744 | int JS_SetPropertyInt64(JSContext *ctx, JSCValueonst this_obj, 745 | int64_t idx, JSValue val); 746 | int JS_SetPropertyStr(JSContext *ctx, JSCValueonst this_obj, 747 | const char *prop, JSValue val); 748 | int JS_HasProperty(JSContext *ctx, JSCValueonst this_obj, JSAtom prop); 749 | int JS_IsExtensible(JSContext *ctx, JSCValueonst obj); 750 | int JS_PreventExtensions(JSContext *ctx, JSCValueonst obj); 751 | int JS_DeleteProperty(JSContext *ctx, JSCValueonst obj, JSAtom prop, int flags); 752 | int JS_SetPrototype(JSContext *ctx, JSCValueonst obj, JSCValueonst proto_val); 753 | JSValue JS_GetPrototype(JSContext *ctx, JSCValueonst val); 754 | 755 | #define JS_GPN_STRING_MASK (1 << 0) 756 | #define JS_GPN_SYMBOL_MASK (1 << 1) 757 | #define JS_GPN_PRIVATE_MASK (1 << 2) 758 | /* only include the enumerable properties */ 759 | #define JS_GPN_ENUM_ONLY (1 << 4) 760 | /* set theJSPropertyEnum.is_enumerable field */ 761 | #define JS_GPN_SET_ENUM (1 << 5) 762 | 763 | int JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **ptab, 764 | uint32_t *plen, JSCValueonst obj, int flags); 765 | int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc, 766 | JSCValueonst obj, JSAtom prop); 767 | 768 | JSValue JS_Call(JSContext *ctx, JSCValueonst func_obj, JSCValueonst this_obj, 769 | int argc, JSCValueonst *argv); 770 | JSValue JS_Invoke(JSContext *ctx, JSCValueonst this_val, JSAtom atom, 771 | int argc, JSCValueonst *argv); 772 | JSValue JS_CallConstructor(JSContext *ctx, JSCValueonst func_obj, 773 | int argc, JSCValueonst *argv); 774 | JSValue JS_CallConstructor2(JSContext *ctx, JSCValueonst func_obj, 775 | JSCValueonst new_target, 776 | int argc, JSCValueonst *argv); 777 | JS_BOOL JS_DetectModule(const char *input, size_t input_len); 778 | /* 'input' must be zero terminated i.e. input[input_len] = '\0'. */ 779 | JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len, 780 | const char *filename, int eval_flags); 781 | /* same as JS_Eval() but with an explicit 'this_obj' parameter */ 782 | JSValue JS_EvalThis(JSContext *ctx, JSCValueonst this_obj, 783 | const char *input, size_t input_len, 784 | const char *filename, int eval_flags); 785 | JSValue JS_GetGlobalObject(JSContext *ctx); 786 | int JS_IsInstanceOf(JSContext *ctx, JSCValueonst val, JSCValueonst obj); 787 | int JS_DefineProperty(JSContext *ctx, JSCValueonst this_obj, 788 | JSAtom prop, JSCValueonst val, 789 | JSCValueonst getter, JSCValueonst setter, int flags); 790 | int JS_DefinePropertyValue(JSContext *ctx, JSCValueonst this_obj, 791 | JSAtom prop, JSValue val, int flags); 792 | int JS_DefinePropertyValueUint32(JSContext *ctx, JSCValueonst this_obj, 793 | uint32_t idx, JSValue val, int flags); 794 | int JS_DefinePropertyValueStr(JSContext *ctx, JSCValueonst this_obj, 795 | const char *prop, JSValue val, int flags); 796 | int JS_DefinePropertyGetSet(JSContext *ctx, JSCValueonst this_obj, 797 | JSAtom prop, JSValue getter, JSValue setter, 798 | int flags); 799 | void JS_SetOpaque(JSValue obj, void *opaque); 800 | void *JS_GetOpaque(JSCValueonst obj, JSClassID class_id); 801 | void *JS_GetOpaque2(JSContext *ctx, JSCValueonst obj, JSClassID class_id); 802 | 803 | /* 'buf' must be zero terminated i.e. buf[buf_len] = '\0'. */ 804 | JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len, 805 | const char *filename); 806 | #define JS_PARSE_JSON_EXT (1 << 0) /* allow extended JSON */ 807 | JSValue JS_ParseJSON2(JSContext *ctx, const char *buf, size_t buf_len, 808 | const char *filename, int flags); 809 | JSValue JS_JSONStringify(JSContext *ctx, JSCValueonst obj, 810 | JSCValueonst replacer, JSCValueonst space0); 811 | 812 | typedef void JSFreeArrayBufferDataFunc(JSRuntime *rt, void *opaque, void *ptr); 813 | JSValue JS_NewArrayBuffer(JSContext *ctx, uint8_t *buf, size_t len, 814 | JSFreeArrayBufferDataFunc *free_func, void *opaque, 815 | JS_BOOL is_shared); 816 | JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len); 817 | void JS_DetachArrayBuffer(JSContext *ctx, JSCValueonst obj); 818 | uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSCValueonst obj); 819 | JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSCValueonst obj, 820 | size_t *pbyte_offset, 821 | size_t *pbyte_length, 822 | size_t *pbytes_per_element); 823 | typedef struct { 824 | void *(*sab_alloc)(void *opaque, size_t size); 825 | void (*sab_free)(void *opaque, void *ptr); 826 | void (*sab_dup)(void *opaque, void *ptr); 827 | void *sab_opaque; 828 | } JSSharedArrayBufferFunctions; 829 | void JS_SetSharedArrayBufferFunctions(JSRuntime *rt, 830 | const JSSharedArrayBufferFunctions *sf); 831 | 832 | JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs); 833 | 834 | /* is_handled = TRUE means that the rejection is handled */ 835 | typedef void JSHostPromiseRejectionTracker(JSContext *ctx, JSCValueonst promise, 836 | JSCValueonst reason, 837 | JS_BOOL is_handled, void *opaque); 838 | void JS_SetHostPromiseRejectionTracker(JSRuntime *rt, JSHostPromiseRejectionTracker *cb, void *opaque); 839 | 840 | /* return != 0 if the JS code needs to be interrupted */ 841 | typedef int JSInterruptHandler(JSRuntime *rt, void *opaque); 842 | void JS_SetInterruptHandler(JSRuntime *rt, JSInterruptHandler *cb, void *opaque); 843 | /* if can_block is TRUE, Atomics.wait() can be used */ 844 | void JS_SetCanBlock(JSRuntime *rt, JS_BOOL can_block); 845 | /* set the [IsHTMLDDA] internal slot */ 846 | void JS_SetIsHTMLDDA(JSContext *ctx, JSCValueonst obj); 847 | 848 | typedef struct JSModuleDef JSModuleDef; 849 | 850 | /* return the module specifier (allocated with js_malloc()) or NULL if 851 | exception */ 852 | typedef char *JSModuleNormalizeFunc(JSContext *ctx, 853 | const char *module_base_name, 854 | const char *module_name, void *opaque); 855 | typedef JSModuleDef *JSModuleLoaderFunc(JSContext *ctx, 856 | const char *module_name, void *opaque); 857 | 858 | /* module_normalize = NULL is allowed and invokes the default module 859 | filename normalizer */ 860 | void JS_SetModuleLoaderFunc(JSRuntime *rt, 861 | JSModuleNormalizeFunc *module_normalize, 862 | JSModuleLoaderFunc *module_loader, void *opaque); 863 | /* return the import.meta object of a module */ 864 | JSValue JS_GetImportMeta(JSContext *ctx, JSModuleDef *m); 865 | JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m); 866 | 867 | /* JS Job support */ 868 | 869 | typedef JSValue JSJobFunc(JSContext *ctx, int argc, JSCValueonst *argv); 870 | int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func, int argc, JSCValueonst *argv); 871 | 872 | JS_BOOL JS_IsJobPending(JSRuntime *rt); 873 | int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx); 874 | 875 | /* Object Writer/Reader (currently only used to handle precompiled code) */ 876 | #define JS_WRITE_OBJ_BYTECODE (1 << 0) /* allow function/module */ 877 | #define JS_WRITE_OBJ_BSWAP (1 << 1) /* byte swapped output */ 878 | #define JS_WRITE_OBJ_SAB (1 << 2) /* allow SharedArrayBuffer */ 879 | #define JS_WRITE_OBJ_REFERENCE (1 << 3) /* allow object references to 880 | encode arbitrary object 881 | graph */ 882 | uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSCValueonst obj, 883 | int flags); 884 | uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSCValueonst obj, 885 | int flags, uint8_t ***psab_tab, size_t *psab_tab_len); 886 | 887 | #define JS_READ_OBJ_BYTECODE (1 << 0) /* allow function/module */ 888 | #define JS_READ_OBJ_ROM_DATA (1 << 1) /* avoid duplicating 'buf' data */ 889 | #define JS_READ_OBJ_SAB (1 << 2) /* allow SharedArrayBuffer */ 890 | #define JS_READ_OBJ_REFERENCE (1 << 3) /* allow object references */ 891 | JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len, 892 | int flags); 893 | /* instantiate and evaluate a bytecode function. Only used when 894 | reading a script or module with JS_ReadObject() */ 895 | JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj); 896 | /* load the dependencies of the module 'obj'. Useful when JS_ReadObject() 897 | returns a module. */ 898 | int JS_ResolveModule(JSContext *ctx, JSCValueonst obj); 899 | 900 | /* only exported for os.Worker() */ 901 | JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels); 902 | /* only exported for os.Worker() */ 903 | JSModuleDef *JS_RunModule(JSContext *ctx, const char *basename, 904 | const char *filename); 905 | 906 | /* C function definition */ 907 | typedef enum JSCFunctionEnum { /* XXX: should rename for namespace isolation */ 908 | JS_CFUNC_generic, 909 | JS_CFUNC_generic_magic, 910 | JS_CFUNC_constructor, 911 | JS_CFUNC_constructor_magic, 912 | JS_CFUNC_constructor_or_func, 913 | JS_CFUNC_constructor_or_func_magic, 914 | JS_CFUNC_f_f, 915 | JS_CFUNC_f_f_f, 916 | JS_CFUNC_getter, 917 | JS_CFUNC_setter, 918 | JS_CFUNC_getter_magic, 919 | JS_CFUNC_setter_magic, 920 | JS_CFUNC_iterator_next, 921 | } JSCFunctionEnum; 922 | 923 | typedef union JSCFunctionType { 924 | JSCFunction *generic; 925 | JSValue (*generic_magic)(JSContext *ctx, JSCValueonst this_val, int argc, JSCValueonst *argv, int magic); 926 | JSCFunction *constructor; 927 | JSValue (*constructor_magic)(JSContext *ctx, JSCValueonst new_target, int argc, JSCValueonst *argv, int magic); 928 | JSCFunction *constructor_or_func; 929 | double (*f_f)(double); 930 | double (*f_f_f)(double, double); 931 | JSValue (*getter)(JSContext *ctx, JSCValueonst this_val); 932 | JSValue (*setter)(JSContext *ctx, JSCValueonst this_val, JSCValueonst val); 933 | JSValue (*getter_magic)(JSContext *ctx, JSCValueonst this_val, int magic); 934 | JSValue (*setter_magic)(JSContext *ctx, JSCValueonst this_val, JSCValueonst val, int magic); 935 | JSValue (*iterator_next)(JSContext *ctx, JSCValueonst this_val, 936 | int argc, JSCValueonst *argv, int *pdone, int magic); 937 | } JSCFunctionType; 938 | 939 | JSValue JS_NewCFunction2(JSContext *ctx, JSCFunction *func, 940 | const char *name, 941 | int length, JSCFunctionEnum cproto, int magic); 942 | JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func, 943 | int length, int magic, int data_len, 944 | JSCValueonst *data); 945 | 946 | static inline JSValue JS_NewCFunction(JSContext *ctx, JSCFunction *func, const char *name, 947 | int length) 948 | { 949 | return JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_generic, 0); 950 | } 951 | 952 | static inline JSValue JS_NewCFunctionMagic(JSContext *ctx, JSCFunctionMagic *func, 953 | const char *name, 954 | int length, JSCFunctionEnum cproto, int magic) 955 | { 956 | return JS_NewCFunction2(ctx, (JSCFunction *)func, name, length, cproto, magic); 957 | } 958 | void JS_SetConstructor(JSContext *ctx, JSCValueonst func_obj, 959 | JSCValueonst proto); 960 | 961 | /* C property definition */ 962 | 963 | typedef struct JSCFunctionListEntry { 964 | const char *name; 965 | uint8_t prop_flags; 966 | uint8_t def_type; 967 | int16_t magic; 968 | union { 969 | struct { 970 | uint8_t length; /* XXX: should move outside union */ 971 | uint8_t cproto; /* XXX: should move outside union */ 972 | JSCFunctionType cfunc; 973 | } func; 974 | struct { 975 | JSCFunctionType get; 976 | JSCFunctionType set; 977 | } getset; 978 | struct { 979 | const char *name; 980 | int base; 981 | } alias; 982 | struct { 983 | const struct JSCFunctionListEntry *tab; 984 | int len; 985 | } prop_list; 986 | const char *str; 987 | int32_t i32; 988 | int64_t i64; 989 | double f64; 990 | } u; 991 | } JSCFunctionListEntry; 992 | 993 | #define JS_DEF_CFUNC 0 994 | #define JS_DEF_CGETSET 1 995 | #define JS_DEF_CGETSET_MAGIC 2 996 | #define JS_DEF_PROP_STRING 3 997 | #define JS_DEF_PROP_INT32 4 998 | #define JS_DEF_PROP_INT64 5 999 | #define JS_DEF_PROP_DOUBLE 6 1000 | #define JS_DEF_PROP_UNDEFINED 7 1001 | #define JS_DEF_OBJECT 8 1002 | #define JS_DEF_ALIAS 9 1003 | 1004 | /* Note: c++ does not like nested designators */ 1005 | #define JS_CFUNC_DEF(name, length, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, 0, .u = { .func = { length, JS_CFUNC_generic, { .generic = func1 } } } } 1006 | #define JS_CFUNC_MAGIC_DEF(name, length, func1, magic) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, magic, .u = { .func = { length, JS_CFUNC_generic_magic, { .generic_magic = func1 } } } } 1007 | #define JS_CFUNC_SPECIAL_DEF(name, length, cproto, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, 0, .u = { .func = { length, JS_CFUNC_ ## cproto, { .cproto = func1 } } } } 1008 | #define JS_ITERATOR_NEXT_DEF(name, length, func1, magic) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, magic, .u = { .func = { length, JS_CFUNC_iterator_next, { .iterator_next = func1 } } } } 1009 | #define JS_CGETSET_DEF(name, fgetter, fsetter) { name, JS_PROP_CONFIGURABLE, JS_DEF_CGETSET, 0, .u = { .getset = { .get = { .getter = fgetter }, .set = { .setter = fsetter } } } } 1010 | #define JS_CGETSET_MAGIC_DEF(name, fgetter, fsetter, magic) { name, JS_PROP_CONFIGURABLE, JS_DEF_CGETSET_MAGIC, magic, .u = { .getset = { .get = { .getter_magic = fgetter }, .set = { .setter_magic = fsetter } } } } 1011 | #define JS_PROP_STRING_DEF(name, cstr, prop_flags) { name, prop_flags, JS_DEF_PROP_STRING, 0, .u = { .str = cstr } } 1012 | #define JS_PROP_INT32_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT32, 0, .u = { .i32 = val } } 1013 | #define JS_PROP_INT64_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT64, 0, .u = { .i64 = val } } 1014 | #define JS_PROP_DOUBLE_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_DOUBLE, 0, .u = { .f64 = val } } 1015 | #define JS_PROP_UNDEFINED_DEF(name, prop_flags) { name, prop_flags, JS_DEF_PROP_UNDEFINED, 0, .u = { .i32 = 0 } } 1016 | #define JS_OBJECT_DEF(name, tab, len, prop_flags) { name, prop_flags, JS_DEF_OBJECT, 0, .u = { .prop_list = { tab, len } } } 1017 | #define JS_ALIAS_DEF(name, from) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, .u = { .alias = { from, -1 } } } 1018 | #define JS_ALIAS_BASE_DEF(name, from, base) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, .u = { .alias = { from, base } } } 1019 | 1020 | void JS_SetPropertyFunctionList(JSContext *ctx, JSCValueonst obj, 1021 | const JSCFunctionListEntry *tab, 1022 | int len); 1023 | 1024 | /* C module definition */ 1025 | 1026 | typedef int JSModuleInitFunc(JSContext *ctx, JSModuleDef *m); 1027 | 1028 | JSModuleDef *JS_NewCModule(JSContext *ctx, const char *name_str, 1029 | JSModuleInitFunc *func); 1030 | /* can only be called before the module is instantiated */ 1031 | int JS_AddModuleExport(JSContext *ctx, JSModuleDef *m, const char *name_str); 1032 | int JS_AddModuleExportList(JSContext *ctx, JSModuleDef *m, 1033 | const JSCFunctionListEntry *tab, int len); 1034 | /* can only be called after the module is instantiated */ 1035 | int JS_SetModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name, 1036 | JSValue val); 1037 | int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m, 1038 | const JSCFunctionListEntry *tab, int len); 1039 | 1040 | #undef js_unlikely 1041 | #undef js_force_inline 1042 | 1043 | #ifdef __cplusplus 1044 | } /* extern "C" { */ 1045 | #endif 1046 | 1047 | #endif /* QUICKJS_H */ 1048 | -------------------------------------------------------------------------------- /Sources/QuickJSC/libunicode.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Unicode utilities 3 | * 4 | * Copyright (c) 2017-2018 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "cutils.h" 31 | #include "libunicode.h" 32 | #include "libunicode-table.h" 33 | 34 | enum { 35 | RUN_TYPE_U, 36 | RUN_TYPE_L, 37 | RUN_TYPE_UF, 38 | RUN_TYPE_LF, 39 | RUN_TYPE_UL, 40 | RUN_TYPE_LSU, 41 | RUN_TYPE_U2L_399_EXT2, 42 | RUN_TYPE_UF_D20, 43 | RUN_TYPE_UF_D1_EXT, 44 | RUN_TYPE_U_EXT, 45 | RUN_TYPE_LF_EXT, 46 | RUN_TYPE_U_EXT2, 47 | RUN_TYPE_L_EXT2, 48 | RUN_TYPE_U_EXT3, 49 | }; 50 | 51 | /* conv_type: 52 | 0 = to upper 53 | 1 = to lower 54 | 2 = case folding (= to lower with modifications) 55 | */ 56 | int lre_case_conv(uint32_t *res, uint32_t c, int conv_type) 57 | { 58 | if (c < 128) { 59 | if (conv_type) { 60 | if (c >= 'A' && c <= 'Z') { 61 | c = c - 'A' + 'a'; 62 | } 63 | } else { 64 | if (c >= 'a' && c <= 'z') { 65 | c = c - 'a' + 'A'; 66 | } 67 | } 68 | } else { 69 | uint32_t v, code, data, type, len, a, is_lower; 70 | int idx, idx_min, idx_max; 71 | 72 | is_lower = (conv_type != 0); 73 | idx_min = 0; 74 | idx_max = countof(case_conv_table1) - 1; 75 | while (idx_min <= idx_max) { 76 | idx = (unsigned)(idx_max + idx_min) / 2; 77 | v = case_conv_table1[idx]; 78 | code = v >> (32 - 17); 79 | len = (v >> (32 - 17 - 7)) & 0x7f; 80 | if (c < code) { 81 | idx_max = idx - 1; 82 | } else if (c >= code + len) { 83 | idx_min = idx + 1; 84 | } else { 85 | type = (v >> (32 - 17 - 7 - 4)) & 0xf; 86 | data = ((v & 0xf) << 8) | case_conv_table2[idx]; 87 | switch(type) { 88 | case RUN_TYPE_U: 89 | case RUN_TYPE_L: 90 | case RUN_TYPE_UF: 91 | case RUN_TYPE_LF: 92 | if (conv_type == (type & 1) || 93 | (type >= RUN_TYPE_UF && conv_type == 2)) { 94 | c = c - code + (case_conv_table1[data] >> (32 - 17)); 95 | } 96 | break; 97 | case RUN_TYPE_UL: 98 | a = c - code; 99 | if ((a & 1) != (1 - is_lower)) 100 | break; 101 | c = (a ^ 1) + code; 102 | break; 103 | case RUN_TYPE_LSU: 104 | a = c - code; 105 | if (a == 1) { 106 | c += 2 * is_lower - 1; 107 | } else if (a == (1 - is_lower) * 2) { 108 | c += (2 * is_lower - 1) * 2; 109 | } 110 | break; 111 | case RUN_TYPE_U2L_399_EXT2: 112 | if (!is_lower) { 113 | res[0] = c - code + case_conv_ext[data >> 6]; 114 | res[1] = 0x399; 115 | return 2; 116 | } else { 117 | c = c - code + case_conv_ext[data & 0x3f]; 118 | } 119 | break; 120 | case RUN_TYPE_UF_D20: 121 | if (conv_type == 1) 122 | break; 123 | c = data + (conv_type == 2) * 0x20; 124 | break; 125 | case RUN_TYPE_UF_D1_EXT: 126 | if (conv_type == 1) 127 | break; 128 | c = case_conv_ext[data] + (conv_type == 2); 129 | break; 130 | case RUN_TYPE_U_EXT: 131 | case RUN_TYPE_LF_EXT: 132 | if (is_lower != (type - RUN_TYPE_U_EXT)) 133 | break; 134 | c = case_conv_ext[data]; 135 | break; 136 | case RUN_TYPE_U_EXT2: 137 | case RUN_TYPE_L_EXT2: 138 | if (conv_type != (type - RUN_TYPE_U_EXT2)) 139 | break; 140 | res[0] = c - code + case_conv_ext[data >> 6]; 141 | res[1] = case_conv_ext[data & 0x3f]; 142 | return 2; 143 | default: 144 | case RUN_TYPE_U_EXT3: 145 | if (conv_type != 0) 146 | break; 147 | res[0] = case_conv_ext[data >> 8]; 148 | res[1] = case_conv_ext[(data >> 4) & 0xf]; 149 | res[2] = case_conv_ext[data & 0xf]; 150 | return 3; 151 | } 152 | break; 153 | } 154 | } 155 | } 156 | res[0] = c; 157 | return 1; 158 | } 159 | 160 | static uint32_t get_le24(const uint8_t *ptr) 161 | { 162 | #if defined(__x86__) || defined(__x86_64__) 163 | return *(uint16_t *)ptr | (ptr[2] << 16); 164 | #else 165 | return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16); 166 | #endif 167 | } 168 | 169 | #define UNICODE_INDEX_BLOCK_LEN 32 170 | 171 | /* return -1 if not in table, otherwise the offset in the block */ 172 | static int get_index_pos(uint32_t *pcode, uint32_t c, 173 | const uint8_t *index_table, int index_table_len) 174 | { 175 | uint32_t code, v; 176 | int idx_min, idx_max, idx; 177 | 178 | idx_min = 0; 179 | v = get_le24(index_table); 180 | code = v & ((1 << 21) - 1); 181 | if (c < code) { 182 | *pcode = 0; 183 | return 0; 184 | } 185 | idx_max = index_table_len - 1; 186 | code = get_le24(index_table + idx_max * 3); 187 | if (c >= code) 188 | return -1; 189 | /* invariant: tab[idx_min] <= c < tab2[idx_max] */ 190 | while ((idx_max - idx_min) > 1) { 191 | idx = (idx_max + idx_min) / 2; 192 | v = get_le24(index_table + idx * 3); 193 | code = v & ((1 << 21) - 1); 194 | if (c < code) { 195 | idx_max = idx; 196 | } else { 197 | idx_min = idx; 198 | } 199 | } 200 | v = get_le24(index_table + idx_min * 3); 201 | *pcode = v & ((1 << 21) - 1); 202 | return (idx_min + 1) * UNICODE_INDEX_BLOCK_LEN + (v >> 21); 203 | } 204 | 205 | static BOOL lre_is_in_table(uint32_t c, const uint8_t *table, 206 | const uint8_t *index_table, int index_table_len) 207 | { 208 | uint32_t code, b, bit; 209 | int pos; 210 | const uint8_t *p; 211 | 212 | pos = get_index_pos(&code, c, index_table, index_table_len); 213 | if (pos < 0) 214 | return FALSE; /* outside the table */ 215 | p = table + pos; 216 | bit = 0; 217 | for(;;) { 218 | b = *p++; 219 | if (b < 64) { 220 | code += (b >> 3) + 1; 221 | if (c < code) 222 | return bit; 223 | bit ^= 1; 224 | code += (b & 7) + 1; 225 | } else if (b >= 0x80) { 226 | code += b - 0x80 + 1; 227 | } else if (b < 0x60) { 228 | code += (((b - 0x40) << 8) | p[0]) + 1; 229 | p++; 230 | } else { 231 | code += (((b - 0x60) << 16) | (p[0] << 8) | p[1]) + 1; 232 | p += 2; 233 | } 234 | if (c < code) 235 | return bit; 236 | bit ^= 1; 237 | } 238 | } 239 | 240 | BOOL lre_is_cased(uint32_t c) 241 | { 242 | uint32_t v, code, len; 243 | int idx, idx_min, idx_max; 244 | 245 | idx_min = 0; 246 | idx_max = countof(case_conv_table1) - 1; 247 | while (idx_min <= idx_max) { 248 | idx = (unsigned)(idx_max + idx_min) / 2; 249 | v = case_conv_table1[idx]; 250 | code = v >> (32 - 17); 251 | len = (v >> (32 - 17 - 7)) & 0x7f; 252 | if (c < code) { 253 | idx_max = idx - 1; 254 | } else if (c >= code + len) { 255 | idx_min = idx + 1; 256 | } else { 257 | return TRUE; 258 | } 259 | } 260 | return lre_is_in_table(c, unicode_prop_Cased1_table, 261 | unicode_prop_Cased1_index, 262 | sizeof(unicode_prop_Cased1_index) / 3); 263 | } 264 | 265 | BOOL lre_is_case_ignorable(uint32_t c) 266 | { 267 | return lre_is_in_table(c, unicode_prop_Case_Ignorable_table, 268 | unicode_prop_Case_Ignorable_index, 269 | sizeof(unicode_prop_Case_Ignorable_index) / 3); 270 | } 271 | 272 | /* character range */ 273 | 274 | static __maybe_unused void cr_dump(CharRange *cr) 275 | { 276 | int i; 277 | for(i = 0; i < cr->len; i++) 278 | printf("%d: 0x%04x\n", i, cr->points[i]); 279 | } 280 | 281 | static void *cr_default_realloc(void *opaque, void *ptr, size_t size) 282 | { 283 | return realloc(ptr, size); 284 | } 285 | 286 | void cr_init(CharRange *cr, void *mem_opaque, DynBufReallocFunc *realloc_func) 287 | { 288 | cr->len = cr->size = 0; 289 | cr->points = NULL; 290 | cr->mem_opaque = mem_opaque; 291 | cr->realloc_func = realloc_func ? realloc_func : cr_default_realloc; 292 | } 293 | 294 | void cr_free(CharRange *cr) 295 | { 296 | cr->realloc_func(cr->mem_opaque, cr->points, 0); 297 | } 298 | 299 | int cr_realloc(CharRange *cr, int size) 300 | { 301 | int new_size; 302 | uint32_t *new_buf; 303 | 304 | if (size > cr->size) { 305 | new_size = max_int(size, cr->size * 3 / 2); 306 | new_buf = cr->realloc_func(cr->mem_opaque, cr->points, 307 | new_size * sizeof(cr->points[0])); 308 | if (!new_buf) 309 | return -1; 310 | cr->points = new_buf; 311 | cr->size = new_size; 312 | } 313 | return 0; 314 | } 315 | 316 | int cr_copy(CharRange *cr, const CharRange *cr1) 317 | { 318 | if (cr_realloc(cr, cr1->len)) 319 | return -1; 320 | memcpy(cr->points, cr1->points, sizeof(cr->points[0]) * cr1->len); 321 | cr->len = cr1->len; 322 | return 0; 323 | } 324 | 325 | /* merge consecutive intervals and remove empty intervals */ 326 | static void cr_compress(CharRange *cr) 327 | { 328 | int i, j, k, len; 329 | uint32_t *pt; 330 | 331 | pt = cr->points; 332 | len = cr->len; 333 | i = 0; 334 | j = 0; 335 | k = 0; 336 | while ((i + 1) < len) { 337 | if (pt[i] == pt[i + 1]) { 338 | /* empty interval */ 339 | i += 2; 340 | } else { 341 | j = i; 342 | while ((j + 3) < len && pt[j + 1] == pt[j + 2]) 343 | j += 2; 344 | /* just copy */ 345 | pt[k] = pt[i]; 346 | pt[k + 1] = pt[j + 1]; 347 | k += 2; 348 | i = j + 2; 349 | } 350 | } 351 | cr->len = k; 352 | } 353 | 354 | /* union or intersection */ 355 | int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len, 356 | const uint32_t *b_pt, int b_len, int op) 357 | { 358 | int a_idx, b_idx, is_in; 359 | uint32_t v; 360 | 361 | a_idx = 0; 362 | b_idx = 0; 363 | for(;;) { 364 | /* get one more point from a or b in increasing order */ 365 | if (a_idx < a_len && b_idx < b_len) { 366 | if (a_pt[a_idx] < b_pt[b_idx]) { 367 | goto a_add; 368 | } else if (a_pt[a_idx] == b_pt[b_idx]) { 369 | v = a_pt[a_idx]; 370 | a_idx++; 371 | b_idx++; 372 | } else { 373 | goto b_add; 374 | } 375 | } else if (a_idx < a_len) { 376 | a_add: 377 | v = a_pt[a_idx++]; 378 | } else if (b_idx < b_len) { 379 | b_add: 380 | v = b_pt[b_idx++]; 381 | } else { 382 | break; 383 | } 384 | /* add the point if the in/out status changes */ 385 | switch(op) { 386 | case CR_OP_UNION: 387 | is_in = (a_idx & 1) | (b_idx & 1); 388 | break; 389 | case CR_OP_INTER: 390 | is_in = (a_idx & 1) & (b_idx & 1); 391 | break; 392 | case CR_OP_XOR: 393 | is_in = (a_idx & 1) ^ (b_idx & 1); 394 | break; 395 | default: 396 | abort(); 397 | } 398 | if (is_in != (cr->len & 1)) { 399 | if (cr_add_point(cr, v)) 400 | return -1; 401 | } 402 | } 403 | cr_compress(cr); 404 | return 0; 405 | } 406 | 407 | int cr_union1(CharRange *cr, const uint32_t *b_pt, int b_len) 408 | { 409 | CharRange a = *cr; 410 | int ret; 411 | cr->len = 0; 412 | cr->size = 0; 413 | cr->points = NULL; 414 | ret = cr_op(cr, a.points, a.len, b_pt, b_len, CR_OP_UNION); 415 | cr_free(&a); 416 | return ret; 417 | } 418 | 419 | int cr_invert(CharRange *cr) 420 | { 421 | int len; 422 | len = cr->len; 423 | if (cr_realloc(cr, len + 2)) 424 | return -1; 425 | memmove(cr->points + 1, cr->points, len * sizeof(cr->points[0])); 426 | cr->points[0] = 0; 427 | cr->points[len + 1] = UINT32_MAX; 428 | cr->len = len + 2; 429 | cr_compress(cr); 430 | return 0; 431 | } 432 | 433 | #ifdef CONFIG_ALL_UNICODE 434 | 435 | BOOL lre_is_id_start(uint32_t c) 436 | { 437 | return lre_is_in_table(c, unicode_prop_ID_Start_table, 438 | unicode_prop_ID_Start_index, 439 | sizeof(unicode_prop_ID_Start_index) / 3); 440 | } 441 | 442 | BOOL lre_is_id_continue(uint32_t c) 443 | { 444 | return lre_is_id_start(c) || 445 | lre_is_in_table(c, unicode_prop_ID_Continue1_table, 446 | unicode_prop_ID_Continue1_index, 447 | sizeof(unicode_prop_ID_Continue1_index) / 3); 448 | } 449 | 450 | #define UNICODE_DECOMP_LEN_MAX 18 451 | 452 | typedef enum { 453 | DECOMP_TYPE_C1, /* 16 bit char */ 454 | DECOMP_TYPE_L1, /* 16 bit char table */ 455 | DECOMP_TYPE_L2, 456 | DECOMP_TYPE_L3, 457 | DECOMP_TYPE_L4, 458 | DECOMP_TYPE_L5, /* XXX: not used */ 459 | DECOMP_TYPE_L6, /* XXX: could remove */ 460 | DECOMP_TYPE_L7, /* XXX: could remove */ 461 | DECOMP_TYPE_LL1, /* 18 bit char table */ 462 | DECOMP_TYPE_LL2, 463 | DECOMP_TYPE_S1, /* 8 bit char table */ 464 | DECOMP_TYPE_S2, 465 | DECOMP_TYPE_S3, 466 | DECOMP_TYPE_S4, 467 | DECOMP_TYPE_S5, 468 | DECOMP_TYPE_I1, /* increment 16 bit char value */ 469 | DECOMP_TYPE_I2_0, 470 | DECOMP_TYPE_I2_1, 471 | DECOMP_TYPE_I3_1, 472 | DECOMP_TYPE_I3_2, 473 | DECOMP_TYPE_I4_1, 474 | DECOMP_TYPE_I4_2, 475 | DECOMP_TYPE_B1, /* 16 bit base + 8 bit offset */ 476 | DECOMP_TYPE_B2, 477 | DECOMP_TYPE_B3, 478 | DECOMP_TYPE_B4, 479 | DECOMP_TYPE_B5, 480 | DECOMP_TYPE_B6, 481 | DECOMP_TYPE_B7, 482 | DECOMP_TYPE_B8, 483 | DECOMP_TYPE_B18, 484 | DECOMP_TYPE_LS2, 485 | DECOMP_TYPE_PAT3, 486 | DECOMP_TYPE_S2_UL, 487 | DECOMP_TYPE_LS2_UL, 488 | } DecompTypeEnum; 489 | 490 | static uint32_t unicode_get_short_code(uint32_t c) 491 | { 492 | static const uint16_t unicode_short_table[2] = { 0x2044, 0x2215 }; 493 | 494 | if (c < 0x80) 495 | return c; 496 | else if (c < 0x80 + 0x50) 497 | return c - 0x80 + 0x300; 498 | else 499 | return unicode_short_table[c - 0x80 - 0x50]; 500 | } 501 | 502 | static uint32_t unicode_get_lower_simple(uint32_t c) 503 | { 504 | if (c < 0x100 || (c >= 0x410 && c <= 0x42f)) 505 | c += 0x20; 506 | else 507 | c++; 508 | return c; 509 | } 510 | 511 | static uint16_t unicode_get16(const uint8_t *p) 512 | { 513 | return p[0] | (p[1] << 8); 514 | } 515 | 516 | static int unicode_decomp_entry(uint32_t *res, uint32_t c, 517 | int idx, uint32_t code, uint32_t len, 518 | uint32_t type) 519 | { 520 | uint32_t c1; 521 | int l, i, p; 522 | const uint8_t *d; 523 | 524 | if (type == DECOMP_TYPE_C1) { 525 | res[0] = unicode_decomp_table2[idx]; 526 | return 1; 527 | } else { 528 | d = unicode_decomp_data + unicode_decomp_table2[idx]; 529 | switch(type) { 530 | case DECOMP_TYPE_L1: 531 | case DECOMP_TYPE_L2: 532 | case DECOMP_TYPE_L3: 533 | case DECOMP_TYPE_L4: 534 | case DECOMP_TYPE_L5: 535 | case DECOMP_TYPE_L6: 536 | case DECOMP_TYPE_L7: 537 | l = type - DECOMP_TYPE_L1 + 1; 538 | d += (c - code) * l * 2; 539 | for(i = 0; i < l; i++) { 540 | if ((res[i] = unicode_get16(d + 2 * i)) == 0) 541 | return 0; 542 | } 543 | return l; 544 | case DECOMP_TYPE_LL1: 545 | case DECOMP_TYPE_LL2: 546 | { 547 | uint32_t k, p; 548 | l = type - DECOMP_TYPE_LL1 + 1; 549 | k = (c - code) * l; 550 | p = len * l * 2; 551 | for(i = 0; i < l; i++) { 552 | c1 = unicode_get16(d + 2 * k) | 553 | (((d[p + (k / 4)] >> ((k % 4) * 2)) & 3) << 16); 554 | if (!c1) 555 | return 0; 556 | res[i] = c1; 557 | k++; 558 | } 559 | } 560 | return l; 561 | case DECOMP_TYPE_S1: 562 | case DECOMP_TYPE_S2: 563 | case DECOMP_TYPE_S3: 564 | case DECOMP_TYPE_S4: 565 | case DECOMP_TYPE_S5: 566 | l = type - DECOMP_TYPE_S1 + 1; 567 | d += (c - code) * l; 568 | for(i = 0; i < l; i++) { 569 | if ((res[i] = unicode_get_short_code(d[i])) == 0) 570 | return 0; 571 | } 572 | return l; 573 | case DECOMP_TYPE_I1: 574 | l = 1; 575 | p = 0; 576 | goto decomp_type_i; 577 | case DECOMP_TYPE_I2_0: 578 | case DECOMP_TYPE_I2_1: 579 | case DECOMP_TYPE_I3_1: 580 | case DECOMP_TYPE_I3_2: 581 | case DECOMP_TYPE_I4_1: 582 | case DECOMP_TYPE_I4_2: 583 | l = 2 + ((type - DECOMP_TYPE_I2_0) >> 1); 584 | p = ((type - DECOMP_TYPE_I2_0) & 1) + (l > 2); 585 | decomp_type_i: 586 | for(i = 0; i < l; i++) { 587 | c1 = unicode_get16(d + 2 * i); 588 | if (i == p) 589 | c1 += c - code; 590 | res[i] = c1; 591 | } 592 | return l; 593 | case DECOMP_TYPE_B18: 594 | l = 18; 595 | goto decomp_type_b; 596 | case DECOMP_TYPE_B1: 597 | case DECOMP_TYPE_B2: 598 | case DECOMP_TYPE_B3: 599 | case DECOMP_TYPE_B4: 600 | case DECOMP_TYPE_B5: 601 | case DECOMP_TYPE_B6: 602 | case DECOMP_TYPE_B7: 603 | case DECOMP_TYPE_B8: 604 | l = type - DECOMP_TYPE_B1 + 1; 605 | decomp_type_b: 606 | { 607 | uint32_t c_min; 608 | c_min = unicode_get16(d); 609 | d += 2 + (c - code) * l; 610 | for(i = 0; i < l; i++) { 611 | c1 = d[i]; 612 | if (c1 == 0xff) 613 | c1 = 0x20; 614 | else 615 | c1 += c_min; 616 | res[i] = c1; 617 | } 618 | } 619 | return l; 620 | case DECOMP_TYPE_LS2: 621 | d += (c - code) * 3; 622 | if (!(res[0] = unicode_get16(d))) 623 | return 0; 624 | res[1] = unicode_get_short_code(d[2]); 625 | return 2; 626 | case DECOMP_TYPE_PAT3: 627 | res[0] = unicode_get16(d); 628 | res[2] = unicode_get16(d + 2); 629 | d += 4 + (c - code) * 2; 630 | res[1] = unicode_get16(d); 631 | return 3; 632 | case DECOMP_TYPE_S2_UL: 633 | case DECOMP_TYPE_LS2_UL: 634 | c1 = c - code; 635 | if (type == DECOMP_TYPE_S2_UL) { 636 | d += c1 & ~1; 637 | c = unicode_get_short_code(*d); 638 | d++; 639 | } else { 640 | d += (c1 >> 1) * 3; 641 | c = unicode_get16(d); 642 | d += 2; 643 | } 644 | if (c1 & 1) 645 | c = unicode_get_lower_simple(c); 646 | res[0] = c; 647 | res[1] = unicode_get_short_code(*d); 648 | return 2; 649 | } 650 | } 651 | return 0; 652 | } 653 | 654 | 655 | /* return the length of the decomposition (length <= 656 | UNICODE_DECOMP_LEN_MAX) or 0 if no decomposition */ 657 | static int unicode_decomp_char(uint32_t *res, uint32_t c, BOOL is_compat1) 658 | { 659 | uint32_t v, type, is_compat, code, len; 660 | int idx_min, idx_max, idx; 661 | 662 | idx_min = 0; 663 | idx_max = countof(unicode_decomp_table1) - 1; 664 | while (idx_min <= idx_max) { 665 | idx = (idx_max + idx_min) / 2; 666 | v = unicode_decomp_table1[idx]; 667 | code = v >> (32 - 18); 668 | len = (v >> (32 - 18 - 7)) & 0x7f; 669 | // printf("idx=%d code=%05x len=%d\n", idx, code, len); 670 | if (c < code) { 671 | idx_max = idx - 1; 672 | } else if (c >= code + len) { 673 | idx_min = idx + 1; 674 | } else { 675 | is_compat = v & 1; 676 | if (is_compat1 < is_compat) 677 | break; 678 | type = (v >> (32 - 18 - 7 - 6)) & 0x3f; 679 | return unicode_decomp_entry(res, c, idx, code, len, type); 680 | } 681 | } 682 | return 0; 683 | } 684 | 685 | /* return 0 if no pair found */ 686 | static int unicode_compose_pair(uint32_t c0, uint32_t c1) 687 | { 688 | uint32_t code, len, type, v, idx1, d_idx, d_offset, ch; 689 | int idx_min, idx_max, idx, d; 690 | uint32_t pair[2]; 691 | 692 | idx_min = 0; 693 | idx_max = countof(unicode_comp_table) - 1; 694 | while (idx_min <= idx_max) { 695 | idx = (idx_max + idx_min) / 2; 696 | idx1 = unicode_comp_table[idx]; 697 | 698 | /* idx1 represent an entry of the decomposition table */ 699 | d_idx = idx1 >> 6; 700 | d_offset = idx1 & 0x3f; 701 | v = unicode_decomp_table1[d_idx]; 702 | code = v >> (32 - 18); 703 | len = (v >> (32 - 18 - 7)) & 0x7f; 704 | type = (v >> (32 - 18 - 7 - 6)) & 0x3f; 705 | ch = code + d_offset; 706 | unicode_decomp_entry(pair, ch, d_idx, code, len, type); 707 | d = c0 - pair[0]; 708 | if (d == 0) 709 | d = c1 - pair[1]; 710 | if (d < 0) { 711 | idx_max = idx - 1; 712 | } else if (d > 0) { 713 | idx_min = idx + 1; 714 | } else { 715 | return ch; 716 | } 717 | } 718 | return 0; 719 | } 720 | 721 | /* return the combining class of character c (between 0 and 255) */ 722 | static int unicode_get_cc(uint32_t c) 723 | { 724 | uint32_t code, n, type, cc, c1, b; 725 | int pos; 726 | const uint8_t *p; 727 | 728 | pos = get_index_pos(&code, c, 729 | unicode_cc_index, sizeof(unicode_cc_index) / 3); 730 | if (pos < 0) 731 | return 0; 732 | p = unicode_cc_table + pos; 733 | for(;;) { 734 | b = *p++; 735 | type = b >> 6; 736 | n = b & 0x3f; 737 | if (n < 48) { 738 | } else if (n < 56) { 739 | n = (n - 48) << 8; 740 | n |= *p++; 741 | n += 48; 742 | } else { 743 | n = (n - 56) << 8; 744 | n |= *p++ << 8; 745 | n |= *p++; 746 | n += 48 + (1 << 11); 747 | } 748 | if (type <= 1) 749 | p++; 750 | c1 = code + n + 1; 751 | if (c < c1) { 752 | switch(type) { 753 | case 0: 754 | cc = p[-1]; 755 | break; 756 | case 1: 757 | cc = p[-1] + c - code; 758 | break; 759 | case 2: 760 | cc = 0; 761 | break; 762 | default: 763 | case 3: 764 | cc = 230; 765 | break; 766 | } 767 | return cc; 768 | } 769 | code = c1; 770 | } 771 | } 772 | 773 | static void sort_cc(int *buf, int len) 774 | { 775 | int i, j, k, cc, cc1, start, ch1; 776 | 777 | for(i = 0; i < len; i++) { 778 | cc = unicode_get_cc(buf[i]); 779 | if (cc != 0) { 780 | start = i; 781 | j = i + 1; 782 | while (j < len) { 783 | ch1 = buf[j]; 784 | cc1 = unicode_get_cc(ch1); 785 | if (cc1 == 0) 786 | break; 787 | k = j - 1; 788 | while (k >= start) { 789 | if (unicode_get_cc(buf[k]) <= cc1) 790 | break; 791 | buf[k + 1] = buf[k]; 792 | k--; 793 | } 794 | buf[k + 1] = ch1; 795 | j++; 796 | } 797 | #if 0 798 | printf("cc:"); 799 | for(k = start; k < j; k++) { 800 | printf(" %3d", unicode_get_cc(buf[k])); 801 | } 802 | printf("\n"); 803 | #endif 804 | i = j; 805 | } 806 | } 807 | } 808 | 809 | static void to_nfd_rec(DynBuf *dbuf, 810 | const int *src, int src_len, int is_compat) 811 | { 812 | uint32_t c, v; 813 | int i, l; 814 | uint32_t res[UNICODE_DECOMP_LEN_MAX]; 815 | 816 | for(i = 0; i < src_len; i++) { 817 | c = src[i]; 818 | if (c >= 0xac00 && c < 0xd7a4) { 819 | /* Hangul decomposition */ 820 | c -= 0xac00; 821 | dbuf_put_u32(dbuf, 0x1100 + c / 588); 822 | dbuf_put_u32(dbuf, 0x1161 + (c % 588) / 28); 823 | v = c % 28; 824 | if (v != 0) 825 | dbuf_put_u32(dbuf, 0x11a7 + v); 826 | } else { 827 | l = unicode_decomp_char(res, c, is_compat); 828 | if (l) { 829 | to_nfd_rec(dbuf, (int *)res, l, is_compat); 830 | } else { 831 | dbuf_put_u32(dbuf, c); 832 | } 833 | } 834 | } 835 | } 836 | 837 | /* return 0 if not found */ 838 | static int compose_pair(uint32_t c0, uint32_t c1) 839 | { 840 | /* Hangul composition */ 841 | if (c0 >= 0x1100 && c0 < 0x1100 + 19 && 842 | c1 >= 0x1161 && c1 < 0x1161 + 21) { 843 | return 0xac00 + (c0 - 0x1100) * 588 + (c1 - 0x1161) * 28; 844 | } else if (c0 >= 0xac00 && c0 < 0xac00 + 11172 && 845 | (c0 - 0xac00) % 28 == 0 && 846 | c1 >= 0x11a7 && c1 < 0x11a7 + 28) { 847 | return c0 + c1 - 0x11a7; 848 | } else { 849 | return unicode_compose_pair(c0, c1); 850 | } 851 | } 852 | 853 | int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len, 854 | UnicodeNormalizationEnum n_type, 855 | void *opaque, DynBufReallocFunc *realloc_func) 856 | { 857 | int *buf, buf_len, i, p, starter_pos, cc, last_cc, out_len; 858 | BOOL is_compat; 859 | DynBuf dbuf_s, *dbuf = &dbuf_s; 860 | 861 | is_compat = n_type >> 1; 862 | 863 | dbuf_init2(dbuf, opaque, realloc_func); 864 | if (dbuf_realloc(dbuf, sizeof(int) * src_len)) 865 | goto fail; 866 | 867 | /* common case: latin1 is unaffected by NFC */ 868 | if (n_type == UNICODE_NFC) { 869 | for(i = 0; i < src_len; i++) { 870 | if (src[i] >= 0x100) 871 | goto not_latin1; 872 | } 873 | buf = (int *)dbuf->buf; 874 | memcpy(buf, src, src_len * sizeof(int)); 875 | *pdst = (uint32_t *)buf; 876 | return src_len; 877 | not_latin1: ; 878 | } 879 | 880 | to_nfd_rec(dbuf, (const int *)src, src_len, is_compat); 881 | if (dbuf_error(dbuf)) { 882 | fail: 883 | *pdst = NULL; 884 | return -1; 885 | } 886 | buf = (int *)dbuf->buf; 887 | buf_len = dbuf->size / sizeof(int); 888 | 889 | sort_cc(buf, buf_len); 890 | 891 | if (buf_len <= 1 || (n_type & 1) != 0) { 892 | /* NFD / NFKD */ 893 | *pdst = (uint32_t *)buf; 894 | return buf_len; 895 | } 896 | 897 | i = 1; 898 | out_len = 1; 899 | while (i < buf_len) { 900 | /* find the starter character and test if it is blocked from 901 | the character at 'i' */ 902 | last_cc = unicode_get_cc(buf[i]); 903 | starter_pos = out_len - 1; 904 | while (starter_pos >= 0) { 905 | cc = unicode_get_cc(buf[starter_pos]); 906 | if (cc == 0) 907 | break; 908 | if (cc >= last_cc) 909 | goto next; 910 | last_cc = 256; 911 | starter_pos--; 912 | } 913 | if (starter_pos >= 0 && 914 | (p = compose_pair(buf[starter_pos], buf[i])) != 0) { 915 | buf[starter_pos] = p; 916 | i++; 917 | } else { 918 | next: 919 | buf[out_len++] = buf[i++]; 920 | } 921 | } 922 | *pdst = (uint32_t *)buf; 923 | return out_len; 924 | } 925 | 926 | /* char ranges for various unicode properties */ 927 | 928 | static int unicode_find_name(const char *name_table, const char *name) 929 | { 930 | const char *p, *r; 931 | int pos; 932 | size_t name_len, len; 933 | 934 | p = name_table; 935 | pos = 0; 936 | name_len = strlen(name); 937 | while (*p) { 938 | for(;;) { 939 | r = strchr(p, ','); 940 | if (!r) 941 | len = strlen(p); 942 | else 943 | len = r - p; 944 | if (len == name_len && !memcmp(p, name, name_len)) 945 | return pos; 946 | p += len + 1; 947 | if (!r) 948 | break; 949 | } 950 | pos++; 951 | } 952 | return -1; 953 | } 954 | 955 | /* 'cr' must be initialized and empty. Return 0 if OK, -1 if error, -2 956 | if not found */ 957 | int unicode_script(CharRange *cr, 958 | const char *script_name, BOOL is_ext) 959 | { 960 | int script_idx; 961 | const uint8_t *p, *p_end; 962 | uint32_t c, c1, b, n, v, v_len, i, type; 963 | CharRange cr1_s, *cr1; 964 | CharRange cr2_s, *cr2 = &cr2_s; 965 | BOOL is_common; 966 | 967 | script_idx = unicode_find_name(unicode_script_name_table, script_name); 968 | if (script_idx < 0) 969 | return -2; 970 | /* Note: we remove the "Unknown" Script */ 971 | script_idx += UNICODE_SCRIPT_Unknown + 1; 972 | 973 | is_common = (script_idx == UNICODE_SCRIPT_Common || 974 | script_idx == UNICODE_SCRIPT_Inherited); 975 | if (is_ext) { 976 | cr1 = &cr1_s; 977 | cr_init(cr1, cr->mem_opaque, cr->realloc_func); 978 | cr_init(cr2, cr->mem_opaque, cr->realloc_func); 979 | } else { 980 | cr1 = cr; 981 | } 982 | 983 | p = unicode_script_table; 984 | p_end = unicode_script_table + countof(unicode_script_table); 985 | c = 0; 986 | while (p < p_end) { 987 | b = *p++; 988 | type = b >> 7; 989 | n = b & 0x7f; 990 | if (n < 96) { 991 | } else if (n < 112) { 992 | n = (n - 96) << 8; 993 | n |= *p++; 994 | n += 96; 995 | } else { 996 | n = (n - 112) << 16; 997 | n |= *p++ << 8; 998 | n |= *p++; 999 | n += 96 + (1 << 12); 1000 | } 1001 | if (type == 0) 1002 | v = 0; 1003 | else 1004 | v = *p++; 1005 | c1 = c + n + 1; 1006 | if (v == script_idx) { 1007 | if (cr_add_interval(cr1, c, c1)) 1008 | goto fail; 1009 | } 1010 | c = c1; 1011 | } 1012 | 1013 | if (is_ext) { 1014 | /* add the script extensions */ 1015 | p = unicode_script_ext_table; 1016 | p_end = unicode_script_ext_table + countof(unicode_script_ext_table); 1017 | c = 0; 1018 | while (p < p_end) { 1019 | b = *p++; 1020 | if (b < 128) { 1021 | n = b; 1022 | } else if (b < 128 + 64) { 1023 | n = (b - 128) << 8; 1024 | n |= *p++; 1025 | n += 128; 1026 | } else { 1027 | n = (b - 128 - 64) << 16; 1028 | n |= *p++ << 8; 1029 | n |= *p++; 1030 | n += 128 + (1 << 14); 1031 | } 1032 | c1 = c + n + 1; 1033 | v_len = *p++; 1034 | if (is_common) { 1035 | if (v_len != 0) { 1036 | if (cr_add_interval(cr2, c, c1)) 1037 | goto fail; 1038 | } 1039 | } else { 1040 | for(i = 0; i < v_len; i++) { 1041 | if (p[i] == script_idx) { 1042 | if (cr_add_interval(cr2, c, c1)) 1043 | goto fail; 1044 | break; 1045 | } 1046 | } 1047 | } 1048 | p += v_len; 1049 | c = c1; 1050 | } 1051 | if (is_common) { 1052 | /* remove all the characters with script extensions */ 1053 | if (cr_invert(cr2)) 1054 | goto fail; 1055 | if (cr_op(cr, cr1->points, cr1->len, cr2->points, cr2->len, 1056 | CR_OP_INTER)) 1057 | goto fail; 1058 | } else { 1059 | if (cr_op(cr, cr1->points, cr1->len, cr2->points, cr2->len, 1060 | CR_OP_UNION)) 1061 | goto fail; 1062 | } 1063 | cr_free(cr1); 1064 | cr_free(cr2); 1065 | } 1066 | return 0; 1067 | fail: 1068 | if (is_ext) { 1069 | cr_free(cr1); 1070 | cr_free(cr2); 1071 | } 1072 | goto fail; 1073 | } 1074 | 1075 | #define M(id) (1U << UNICODE_GC_ ## id) 1076 | 1077 | static int unicode_general_category1(CharRange *cr, uint32_t gc_mask) 1078 | { 1079 | const uint8_t *p, *p_end; 1080 | uint32_t c, c0, b, n, v; 1081 | 1082 | p = unicode_gc_table; 1083 | p_end = unicode_gc_table + countof(unicode_gc_table); 1084 | c = 0; 1085 | while (p < p_end) { 1086 | b = *p++; 1087 | n = b >> 5; 1088 | v = b & 0x1f; 1089 | if (n == 7) { 1090 | n = *p++; 1091 | if (n < 128) { 1092 | n += 7; 1093 | } else if (n < 128 + 64) { 1094 | n = (n - 128) << 8; 1095 | n |= *p++; 1096 | n += 7 + 128; 1097 | } else { 1098 | n = (n - 128 - 64) << 16; 1099 | n |= *p++ << 8; 1100 | n |= *p++; 1101 | n += 7 + 128 + (1 << 14); 1102 | } 1103 | } 1104 | c0 = c; 1105 | c += n + 1; 1106 | if (v == 31) { 1107 | /* run of Lu / Ll */ 1108 | b = gc_mask & (M(Lu) | M(Ll)); 1109 | if (b != 0) { 1110 | if (b == (M(Lu) | M(Ll))) { 1111 | goto add_range; 1112 | } else { 1113 | c0 += ((gc_mask & M(Ll)) != 0); 1114 | for(; c0 < c; c0 += 2) { 1115 | if (cr_add_interval(cr, c0, c0 + 1)) 1116 | return -1; 1117 | } 1118 | } 1119 | } 1120 | } else if ((gc_mask >> v) & 1) { 1121 | add_range: 1122 | if (cr_add_interval(cr, c0, c)) 1123 | return -1; 1124 | } 1125 | } 1126 | return 0; 1127 | } 1128 | 1129 | static int unicode_prop1(CharRange *cr, int prop_idx) 1130 | { 1131 | const uint8_t *p, *p_end; 1132 | uint32_t c, c0, b, bit; 1133 | 1134 | p = unicode_prop_table[prop_idx]; 1135 | p_end = p + unicode_prop_len_table[prop_idx]; 1136 | c = 0; 1137 | bit = 0; 1138 | while (p < p_end) { 1139 | c0 = c; 1140 | b = *p++; 1141 | if (b < 64) { 1142 | c += (b >> 3) + 1; 1143 | if (bit) { 1144 | if (cr_add_interval(cr, c0, c)) 1145 | return -1; 1146 | } 1147 | bit ^= 1; 1148 | c0 = c; 1149 | c += (b & 7) + 1; 1150 | } else if (b >= 0x80) { 1151 | c += b - 0x80 + 1; 1152 | } else if (b < 0x60) { 1153 | c += (((b - 0x40) << 8) | p[0]) + 1; 1154 | p++; 1155 | } else { 1156 | c += (((b - 0x60) << 16) | (p[0] << 8) | p[1]) + 1; 1157 | p += 2; 1158 | } 1159 | if (bit) { 1160 | if (cr_add_interval(cr, c0, c)) 1161 | return -1; 1162 | } 1163 | bit ^= 1; 1164 | } 1165 | return 0; 1166 | } 1167 | 1168 | #define CASE_U (1 << 0) 1169 | #define CASE_L (1 << 1) 1170 | #define CASE_F (1 << 2) 1171 | 1172 | /* use the case conversion table to generate range of characters. 1173 | CASE_U: set char if modified by uppercasing, 1174 | CASE_L: set char if modified by lowercasing, 1175 | CASE_F: set char if modified by case folding, 1176 | */ 1177 | static int unicode_case1(CharRange *cr, int case_mask) 1178 | { 1179 | #define MR(x) (1 << RUN_TYPE_ ## x) 1180 | const uint32_t tab_run_mask[3] = { 1181 | MR(U) | MR(UF) | MR(UL) | MR(LSU) | MR(U2L_399_EXT2) | MR(UF_D20) | 1182 | MR(UF_D1_EXT) | MR(U_EXT) | MR(U_EXT2) | MR(U_EXT3), 1183 | 1184 | MR(L) | MR(LF) | MR(UL) | MR(LSU) | MR(U2L_399_EXT2) | MR(LF_EXT) | MR(L_EXT2), 1185 | 1186 | MR(UF) | MR(LF) | MR(UL) | MR(LSU) | MR(U2L_399_EXT2) | MR(LF_EXT) | MR(UF_D20) | MR(UF_D1_EXT) | MR(LF_EXT), 1187 | }; 1188 | #undef MR 1189 | uint32_t mask, v, code, type, len, i, idx; 1190 | 1191 | if (case_mask == 0) 1192 | return 0; 1193 | mask = 0; 1194 | for(i = 0; i < 3; i++) { 1195 | if ((case_mask >> i) & 1) 1196 | mask |= tab_run_mask[i]; 1197 | } 1198 | for(idx = 0; idx < countof(case_conv_table1); idx++) { 1199 | v = case_conv_table1[idx]; 1200 | type = (v >> (32 - 17 - 7 - 4)) & 0xf; 1201 | code = v >> (32 - 17); 1202 | len = (v >> (32 - 17 - 7)) & 0x7f; 1203 | if ((mask >> type) & 1) { 1204 | // printf("%d: type=%d %04x %04x\n", idx, type, code, code + len - 1); 1205 | switch(type) { 1206 | case RUN_TYPE_UL: 1207 | if ((case_mask & CASE_U) && (case_mask & (CASE_L | CASE_F))) 1208 | goto def_case; 1209 | code += ((case_mask & CASE_U) != 0); 1210 | for(i = 0; i < len; i += 2) { 1211 | if (cr_add_interval(cr, code + i, code + i + 1)) 1212 | return -1; 1213 | } 1214 | break; 1215 | case RUN_TYPE_LSU: 1216 | if ((case_mask & CASE_U) && (case_mask & (CASE_L | CASE_F))) 1217 | goto def_case; 1218 | if (!(case_mask & CASE_U)) { 1219 | if (cr_add_interval(cr, code, code + 1)) 1220 | return -1; 1221 | } 1222 | if (cr_add_interval(cr, code + 1, code + 2)) 1223 | return -1; 1224 | if (case_mask & CASE_U) { 1225 | if (cr_add_interval(cr, code + 2, code + 3)) 1226 | return -1; 1227 | } 1228 | break; 1229 | default: 1230 | def_case: 1231 | if (cr_add_interval(cr, code, code + len)) 1232 | return -1; 1233 | break; 1234 | } 1235 | } 1236 | } 1237 | return 0; 1238 | } 1239 | 1240 | typedef enum { 1241 | POP_GC, 1242 | POP_PROP, 1243 | POP_CASE, 1244 | POP_UNION, 1245 | POP_INTER, 1246 | POP_XOR, 1247 | POP_INVERT, 1248 | POP_END, 1249 | } PropOPEnum; 1250 | 1251 | #define POP_STACK_LEN_MAX 4 1252 | 1253 | static int unicode_prop_ops(CharRange *cr, ...) 1254 | { 1255 | va_list ap; 1256 | CharRange stack[POP_STACK_LEN_MAX]; 1257 | int stack_len, op, ret, i; 1258 | uint32_t a; 1259 | 1260 | va_start(ap, cr); 1261 | stack_len = 0; 1262 | for(;;) { 1263 | op = va_arg(ap, int); 1264 | switch(op) { 1265 | case POP_GC: 1266 | assert(stack_len < POP_STACK_LEN_MAX); 1267 | a = va_arg(ap, int); 1268 | cr_init(&stack[stack_len++], cr->mem_opaque, cr->realloc_func); 1269 | if (unicode_general_category1(&stack[stack_len - 1], a)) 1270 | goto fail; 1271 | break; 1272 | case POP_PROP: 1273 | assert(stack_len < POP_STACK_LEN_MAX); 1274 | a = va_arg(ap, int); 1275 | cr_init(&stack[stack_len++], cr->mem_opaque, cr->realloc_func); 1276 | if (unicode_prop1(&stack[stack_len - 1], a)) 1277 | goto fail; 1278 | break; 1279 | case POP_CASE: 1280 | assert(stack_len < POP_STACK_LEN_MAX); 1281 | a = va_arg(ap, int); 1282 | cr_init(&stack[stack_len++], cr->mem_opaque, cr->realloc_func); 1283 | if (unicode_case1(&stack[stack_len - 1], a)) 1284 | goto fail; 1285 | break; 1286 | case POP_UNION: 1287 | case POP_INTER: 1288 | case POP_XOR: 1289 | { 1290 | CharRange *cr1, *cr2, *cr3; 1291 | assert(stack_len >= 2); 1292 | assert(stack_len < POP_STACK_LEN_MAX); 1293 | cr1 = &stack[stack_len - 2]; 1294 | cr2 = &stack[stack_len - 1]; 1295 | cr3 = &stack[stack_len++]; 1296 | cr_init(cr3, cr->mem_opaque, cr->realloc_func); 1297 | if (cr_op(cr3, cr1->points, cr1->len, 1298 | cr2->points, cr2->len, op - POP_UNION + CR_OP_UNION)) 1299 | goto fail; 1300 | cr_free(cr1); 1301 | cr_free(cr2); 1302 | *cr1 = *cr3; 1303 | stack_len -= 2; 1304 | } 1305 | break; 1306 | case POP_INVERT: 1307 | assert(stack_len >= 1); 1308 | if (cr_invert(&stack[stack_len - 1])) 1309 | goto fail; 1310 | break; 1311 | case POP_END: 1312 | goto done; 1313 | default: 1314 | abort(); 1315 | } 1316 | } 1317 | done: 1318 | assert(stack_len == 1); 1319 | ret = cr_copy(cr, &stack[0]); 1320 | cr_free(&stack[0]); 1321 | return ret; 1322 | fail: 1323 | for(i = 0; i < stack_len; i++) 1324 | cr_free(&stack[i]); 1325 | return -1; 1326 | } 1327 | 1328 | static const uint32_t unicode_gc_mask_table[] = { 1329 | M(Lu) | M(Ll) | M(Lt), /* LC */ 1330 | M(Lu) | M(Ll) | M(Lt) | M(Lm) | M(Lo), /* L */ 1331 | M(Mn) | M(Mc) | M(Me), /* M */ 1332 | M(Nd) | M(Nl) | M(No), /* N */ 1333 | M(Sm) | M(Sc) | M(Sk) | M(So), /* S */ 1334 | M(Pc) | M(Pd) | M(Ps) | M(Pe) | M(Pi) | M(Pf) | M(Po), /* P */ 1335 | M(Zs) | M(Zl) | M(Zp), /* Z */ 1336 | M(Cc) | M(Cf) | M(Cs) | M(Co) | M(Cn), /* C */ 1337 | }; 1338 | 1339 | /* 'cr' must be initialized and empty. Return 0 if OK, -1 if error, -2 1340 | if not found */ 1341 | int unicode_general_category(CharRange *cr, const char *gc_name) 1342 | { 1343 | int gc_idx; 1344 | uint32_t gc_mask; 1345 | 1346 | gc_idx = unicode_find_name(unicode_gc_name_table, gc_name); 1347 | if (gc_idx < 0) 1348 | return -2; 1349 | if (gc_idx <= UNICODE_GC_Co) { 1350 | gc_mask = (uint64_t)1 << gc_idx; 1351 | } else { 1352 | gc_mask = unicode_gc_mask_table[gc_idx - UNICODE_GC_LC]; 1353 | } 1354 | return unicode_general_category1(cr, gc_mask); 1355 | } 1356 | 1357 | 1358 | /* 'cr' must be initialized and empty. Return 0 if OK, -1 if error, -2 1359 | if not found */ 1360 | int unicode_prop(CharRange *cr, const char *prop_name) 1361 | { 1362 | int prop_idx, ret; 1363 | 1364 | prop_idx = unicode_find_name(unicode_prop_name_table, prop_name); 1365 | if (prop_idx < 0) 1366 | return -2; 1367 | prop_idx += UNICODE_PROP_ASCII_Hex_Digit; 1368 | 1369 | ret = 0; 1370 | switch(prop_idx) { 1371 | case UNICODE_PROP_ASCII: 1372 | if (cr_add_interval(cr, 0x00, 0x7f + 1)) 1373 | return -1; 1374 | break; 1375 | case UNICODE_PROP_Any: 1376 | if (cr_add_interval(cr, 0x00000, 0x10ffff + 1)) 1377 | return -1; 1378 | break; 1379 | case UNICODE_PROP_Assigned: 1380 | ret = unicode_prop_ops(cr, 1381 | POP_GC, M(Cn), 1382 | POP_INVERT, 1383 | POP_END); 1384 | break; 1385 | case UNICODE_PROP_Math: 1386 | ret = unicode_prop_ops(cr, 1387 | POP_GC, M(Sm), 1388 | POP_PROP, UNICODE_PROP_Other_Math, 1389 | POP_UNION, 1390 | POP_END); 1391 | break; 1392 | case UNICODE_PROP_Lowercase: 1393 | ret = unicode_prop_ops(cr, 1394 | POP_GC, M(Ll), 1395 | POP_PROP, UNICODE_PROP_Other_Lowercase, 1396 | POP_UNION, 1397 | POP_END); 1398 | break; 1399 | case UNICODE_PROP_Uppercase: 1400 | ret = unicode_prop_ops(cr, 1401 | POP_GC, M(Lu), 1402 | POP_PROP, UNICODE_PROP_Other_Uppercase, 1403 | POP_UNION, 1404 | POP_END); 1405 | break; 1406 | case UNICODE_PROP_Cased: 1407 | ret = unicode_prop_ops(cr, 1408 | POP_GC, M(Lu) | M(Ll) | M(Lt), 1409 | POP_PROP, UNICODE_PROP_Other_Uppercase, 1410 | POP_UNION, 1411 | POP_PROP, UNICODE_PROP_Other_Lowercase, 1412 | POP_UNION, 1413 | POP_END); 1414 | break; 1415 | case UNICODE_PROP_Alphabetic: 1416 | ret = unicode_prop_ops(cr, 1417 | POP_GC, M(Lu) | M(Ll) | M(Lt) | M(Lm) | M(Lo) | M(Nl), 1418 | POP_PROP, UNICODE_PROP_Other_Uppercase, 1419 | POP_UNION, 1420 | POP_PROP, UNICODE_PROP_Other_Lowercase, 1421 | POP_UNION, 1422 | POP_PROP, UNICODE_PROP_Other_Alphabetic, 1423 | POP_UNION, 1424 | POP_END); 1425 | break; 1426 | case UNICODE_PROP_Grapheme_Base: 1427 | ret = unicode_prop_ops(cr, 1428 | POP_GC, M(Cc) | M(Cf) | M(Cs) | M(Co) | M(Cn) | M(Zl) | M(Zp) | M(Me) | M(Mn), 1429 | POP_PROP, UNICODE_PROP_Other_Grapheme_Extend, 1430 | POP_UNION, 1431 | POP_INVERT, 1432 | POP_END); 1433 | break; 1434 | case UNICODE_PROP_Grapheme_Extend: 1435 | ret = unicode_prop_ops(cr, 1436 | POP_GC, M(Me) | M(Mn), 1437 | POP_PROP, UNICODE_PROP_Other_Grapheme_Extend, 1438 | POP_UNION, 1439 | POP_END); 1440 | break; 1441 | case UNICODE_PROP_XID_Start: 1442 | ret = unicode_prop_ops(cr, 1443 | POP_GC, M(Lu) | M(Ll) | M(Lt) | M(Lm) | M(Lo) | M(Nl), 1444 | POP_PROP, UNICODE_PROP_Other_ID_Start, 1445 | POP_UNION, 1446 | POP_PROP, UNICODE_PROP_Pattern_Syntax, 1447 | POP_PROP, UNICODE_PROP_Pattern_White_Space, 1448 | POP_UNION, 1449 | POP_PROP, UNICODE_PROP_XID_Start1, 1450 | POP_UNION, 1451 | POP_INVERT, 1452 | POP_INTER, 1453 | POP_END); 1454 | break; 1455 | case UNICODE_PROP_XID_Continue: 1456 | ret = unicode_prop_ops(cr, 1457 | POP_GC, M(Lu) | M(Ll) | M(Lt) | M(Lm) | M(Lo) | M(Nl) | 1458 | M(Mn) | M(Mc) | M(Nd) | M(Pc), 1459 | POP_PROP, UNICODE_PROP_Other_ID_Start, 1460 | POP_UNION, 1461 | POP_PROP, UNICODE_PROP_Other_ID_Continue, 1462 | POP_UNION, 1463 | POP_PROP, UNICODE_PROP_Pattern_Syntax, 1464 | POP_PROP, UNICODE_PROP_Pattern_White_Space, 1465 | POP_UNION, 1466 | POP_PROP, UNICODE_PROP_XID_Continue1, 1467 | POP_UNION, 1468 | POP_INVERT, 1469 | POP_INTER, 1470 | POP_END); 1471 | break; 1472 | case UNICODE_PROP_Changes_When_Uppercased: 1473 | ret = unicode_case1(cr, CASE_U); 1474 | break; 1475 | case UNICODE_PROP_Changes_When_Lowercased: 1476 | ret = unicode_case1(cr, CASE_L); 1477 | break; 1478 | case UNICODE_PROP_Changes_When_Casemapped: 1479 | ret = unicode_case1(cr, CASE_U | CASE_L | CASE_F); 1480 | break; 1481 | case UNICODE_PROP_Changes_When_Titlecased: 1482 | ret = unicode_prop_ops(cr, 1483 | POP_CASE, CASE_U, 1484 | POP_PROP, UNICODE_PROP_Changes_When_Titlecased1, 1485 | POP_XOR, 1486 | POP_END); 1487 | break; 1488 | case UNICODE_PROP_Changes_When_Casefolded: 1489 | ret = unicode_prop_ops(cr, 1490 | POP_CASE, CASE_F, 1491 | POP_PROP, UNICODE_PROP_Changes_When_Casefolded1, 1492 | POP_XOR, 1493 | POP_END); 1494 | break; 1495 | case UNICODE_PROP_Changes_When_NFKC_Casefolded: 1496 | ret = unicode_prop_ops(cr, 1497 | POP_CASE, CASE_F, 1498 | POP_PROP, UNICODE_PROP_Changes_When_NFKC_Casefolded1, 1499 | POP_XOR, 1500 | POP_END); 1501 | break; 1502 | #if 0 1503 | case UNICODE_PROP_ID_Start: 1504 | ret = unicode_prop_ops(cr, 1505 | POP_GC, M(Lu) | M(Ll) | M(Lt) | M(Lm) | M(Lo) | M(Nl), 1506 | POP_PROP, UNICODE_PROP_Other_ID_Start, 1507 | POP_UNION, 1508 | POP_PROP, UNICODE_PROP_Pattern_Syntax, 1509 | POP_PROP, UNICODE_PROP_Pattern_White_Space, 1510 | POP_UNION, 1511 | POP_INVERT, 1512 | POP_INTER, 1513 | POP_END); 1514 | break; 1515 | case UNICODE_PROP_ID_Continue: 1516 | ret = unicode_prop_ops(cr, 1517 | POP_GC, M(Lu) | M(Ll) | M(Lt) | M(Lm) | M(Lo) | M(Nl) | 1518 | M(Mn) | M(Mc) | M(Nd) | M(Pc), 1519 | POP_PROP, UNICODE_PROP_Other_ID_Start, 1520 | POP_UNION, 1521 | POP_PROP, UNICODE_PROP_Other_ID_Continue, 1522 | POP_UNION, 1523 | POP_PROP, UNICODE_PROP_Pattern_Syntax, 1524 | POP_PROP, UNICODE_PROP_Pattern_White_Space, 1525 | POP_UNION, 1526 | POP_INVERT, 1527 | POP_INTER, 1528 | POP_END); 1529 | break; 1530 | case UNICODE_PROP_Case_Ignorable: 1531 | ret = unicode_prop_ops(cr, 1532 | POP_GC, M(Mn) | M(Cf) | M(Lm) | M(Sk), 1533 | POP_PROP, UNICODE_PROP_Case_Ignorable1, 1534 | POP_XOR, 1535 | POP_END); 1536 | break; 1537 | #else 1538 | /* we use the existing tables */ 1539 | case UNICODE_PROP_ID_Continue: 1540 | ret = unicode_prop_ops(cr, 1541 | POP_PROP, UNICODE_PROP_ID_Start, 1542 | POP_PROP, UNICODE_PROP_ID_Continue1, 1543 | POP_XOR, 1544 | POP_END); 1545 | break; 1546 | #endif 1547 | default: 1548 | if (prop_idx >= countof(unicode_prop_table)) 1549 | return -2; 1550 | ret = unicode_prop1(cr, prop_idx); 1551 | break; 1552 | } 1553 | return ret; 1554 | } 1555 | 1556 | #endif /* CONFIG_ALL_UNICODE */ 1557 | -------------------------------------------------------------------------------- /Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | import QuickJSSwiftTests 4 | 5 | var tests = [XCTestCaseEntry]() 6 | tests += QuickJSSwiftTests.allTests() 7 | XCTMain(tests) 8 | -------------------------------------------------------------------------------- /Tests/QuickJSTests/QuickJSTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | @testable import QuickJS 4 | 5 | final class QuickJSSwiftTests: XCTestCase { 6 | func testExample() { 7 | // This is an example of a functional test case. 8 | // Use XCTAssert and related functions to verify your tests produce the correct 9 | // results. 10 | 11 | let runtime = JSRuntime() 12 | XCTAssertNotNil(runtime) 13 | 14 | let context = runtime!.createContext() 15 | XCTAssertNotNil(context) 16 | 17 | context!.eval("console.log('Hello QuickJS');") 18 | 19 | let js = "var i = 10; i;" 20 | let result = context!.eval(js).int 21 | XCTAssertEqual(result, 10) 22 | 23 | let property = "$SwiftTest" 24 | XCTAssertFalse(context!.hasGlobalProperty(name: property)) 25 | context!.setGlobalProperty(name: property, value: "Hello world") 26 | XCTAssertTrue(context!.hasGlobalProperty(name: property)) 27 | 28 | context!.module("swift") { 29 | JSModuleFunction("getMagic", argc: 0) { context, this, argc, argv in 30 | return 10 31 | } 32 | JSModuleFunction("getMagic2", argc: 0) { context, this, argc, argv in 33 | return 20 34 | } 35 | } 36 | 37 | let getMagic = """ 38 | "use strict"; 39 | import { getMagic, getMagic2 } from 'swift' 40 | globalThis.magic = getMagic(); 41 | globalThis.magic2 = getMagic2(); 42 | """ 43 | 44 | let error = context!.eval(getMagic, type: .module).error 45 | XCTAssertNil(error) 46 | 47 | let magic = context!.eval("magic;").int 48 | XCTAssertEqual(magic, 10) 49 | 50 | let magic2 = context!.eval("magic2;").int 51 | XCTAssertEqual(magic2, 20) 52 | } 53 | 54 | static var allTests = [ 55 | ("testExample", testExample), 56 | ] 57 | } 58 | -------------------------------------------------------------------------------- /Tests/QuickJSTests/RunloopTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | @testable import QuickJSC 4 | @testable import QuickJS 5 | 6 | class RunloopTests: XCTestCase { 7 | 8 | override func setUpWithError() throws { 9 | // Put setup code here. This method is called before the invocation of each test method in the class. 10 | } 11 | 12 | override func tearDownWithError() throws { 13 | // Put teardown code here. This method is called after the invocation of each test method in the class. 14 | } 15 | 16 | func testExample() throws { 17 | let runtime = JSRuntime() 18 | XCTAssertNotNil(runtime) 19 | 20 | let context = runtime!.createContext() 21 | XCTAssertNotNil(context) 22 | 23 | context?.enableRunloop() 24 | 25 | let expectation = XCTestExpectation(description: "Waiting for runloop") 26 | 27 | context?.module("Waiter") { 28 | JSModuleFunction("timeIsUp", argc: 0) { context, this, argc, argv in 29 | expectation.fulfill() 30 | return nil 31 | } 32 | } 33 | 34 | let jsCode = """ 35 | "use strict"; 36 | import * as runloop from "Runloop"; 37 | import { timeIsUp } from "Waiter"; 38 | runloop.setTimeout(function(){ timeIsUp(); console.log("Hello Runloop"); }, 3000); 39 | """ 40 | 41 | let result = context?.eval(jsCode, type: .module).error 42 | XCTAssertNil(result) 43 | 44 | self.wait(for: [expectation], timeout: 5) 45 | } 46 | 47 | func testPerformanceExample() throws { 48 | // This is an example of a performance test case. 49 | self.measure { 50 | // Put the code you want to measure the time of here. 51 | } 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /Tests/QuickJSTests/XCTestManifests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | #if !canImport(ObjectiveC) 4 | public func allTests() -> [XCTestCaseEntry] { 5 | return [ 6 | testCase(QuickJSTests.allTests), 7 | ] 8 | } 9 | #endif 10 | --------------------------------------------------------------------------------