diff --git a/hogvm/__tests__/__snapshots__/ifJump.hoge b/hogvm/__tests__/__snapshots__/ifJump.hoge new file mode 100644 index 00000000000..0e946f4101f --- /dev/null +++ b/hogvm/__tests__/__snapshots__/ifJump.hoge @@ -0,0 +1,3 @@ +["_h", 42, 0, 36, 0, 32, "email", 45, 32, "", 36, 1, 11, 40, 12, 32, "ERROR - Email not found!", 2, "print", 1, 35, 32, +"3", 2, "print", 1, 35, 32, "1", 2, "print", 1, 35, 32, "", 36, 1, 11, 40, 14, 32, "ERROR - Email not found!", 2, +"print", 1, 35, 32, "3", 2, "print", 1, 35, 39, 6, 32, "else", 2, "print", 1, 35, 32, "1", 2, "print", 1, 35, 35, 35] diff --git a/hogvm/__tests__/__snapshots__/ifJump.stdout b/hogvm/__tests__/__snapshots__/ifJump.stdout new file mode 100644 index 00000000000..27f921abd17 --- /dev/null +++ b/hogvm/__tests__/__snapshots__/ifJump.stdout @@ -0,0 +1,3 @@ +1 +else +1 diff --git a/hogvm/__tests__/__snapshots__/stl.hoge b/hogvm/__tests__/__snapshots__/stl.hoge index b3613e96446..df6a1ac4eef 100644 --- a/hogvm/__tests__/__snapshots__/stl.hoge +++ b/hogvm/__tests__/__snapshots__/stl.hoge @@ -1,3 +1,9 @@ ["_h", 32, "-- empty, notEmpty, length, lower, upper, reverse --", 2, "print", 1, 35, 32, "234", 2, "notEmpty", 1, 32, -"", 2, "empty", 1, 3, 2, 40, 11, 32, "123", 2, "length", 1, 2, "print", 1, 35, 32, "tdd4gh", 32, "Tdd4gh", 2, "lower", -1, 11, 40, 11, 32, "test", 2, "upper", 1, 2, "print", 1, 35, 32, "spinner", 2, "reverse", 1, 2, "print", 1, 35] +"", 2, "empty", 1, 3, 2, 40, 9, 32, "123", 2, "length", 1, 2, "print", 1, 35, 32, "tdd4gh", 32, "Tdd4gh", 2, "lower", 1, +11, 40, 9, 32, "test", 2, "upper", 1, 2, "print", 1, 35, 32, "spinner", 2, "reverse", 1, 2, "print", 1, 35, 32, +"http://www.google.com", 2, "encodeURLComponent", 1, 2, "print", 1, 35, 32, "tom & jerry", 2, "encodeURLComponent", 1, +2, "print", 1, 35, 32, "http://www.google.com", 2, "encodeURLComponent", 1, 2, "decodeURLComponent", 1, 2, "print", 1, +35, 32, "tom & jerry", 2, "encodeURLComponent", 1, 2, "decodeURLComponent", 1, 2, "print", 1, 35, 32, +"http://www.google.com", 2, "base64Encode", 1, 2, "print", 1, 35, 32, "tom & jerry", 2, "base64Encode", 1, 2, "print", +1, 35, 32, "http://www.google.com", 2, "base64Encode", 1, 2, "base64Decode", 1, 2, "print", 1, 35, 32, "tom & jerry", 2, +"base64Encode", 1, 2, "base64Decode", 1, 2, "print", 1, 35] diff --git a/hogvm/__tests__/__snapshots__/stl.stdout b/hogvm/__tests__/__snapshots__/stl.stdout index fe9463feee7..762eff9197e 100644 --- a/hogvm/__tests__/__snapshots__/stl.stdout +++ b/hogvm/__tests__/__snapshots__/stl.stdout @@ -2,3 +2,11 @@ 3 TEST rennips +http%3A%2F%2Fwww.google.com +tom%20%26%20jerry +http://www.google.com +tom & jerry +aHR0cDovL3d3dy5nb29nbGUuY29t +dG9tICYgamVycnk= +http://www.google.com +tom & jerry diff --git a/hogvm/__tests__/ifJump.hog b/hogvm/__tests__/ifJump.hog new file mode 100644 index 00000000000..4e4e7084dc7 --- /dev/null +++ b/hogvm/__tests__/ifJump.hog @@ -0,0 +1,20 @@ +let props := { +} +let email := props.email + +if (email == '') { + print('ERROR - Email not found!') + print('3') +} + +print('1') + + +if (email == '') { + print('ERROR - Email not found!') + print('3') +} else { + print('else') +} + +print('1') diff --git a/hogvm/__tests__/stl.hog b/hogvm/__tests__/stl.hog index 111b42e3abf..add53abc003 100644 --- a/hogvm/__tests__/stl.hog +++ b/hogvm/__tests__/stl.hog @@ -2,3 +2,15 @@ print('-- empty, notEmpty, length, lower, upper, reverse --') if (empty('') and notEmpty('234')) print(length('123')) if (lower('Tdd4gh') == 'tdd4gh') print(upper('test')) print(reverse('spinner')) + +print(encodeURLComponent('http://www.google.com')) +print(encodeURLComponent('tom & jerry')) + +print(decodeURLComponent(encodeURLComponent('http://www.google.com'))) +print(decodeURLComponent(encodeURLComponent('tom & jerry'))) + +print(base64Encode('http://www.google.com')) +print(base64Encode('tom & jerry')) + +print(base64Decode(base64Encode('http://www.google.com'))) +print(base64Decode(base64Encode('tom & jerry'))) diff --git a/hogvm/python/stl/__init__.py b/hogvm/python/stl/__init__.py index 134b7335f92..818dc888fa3 100644 --- a/hogvm/python/stl/__init__.py +++ b/hogvm/python/stl/__init__.py @@ -107,6 +107,34 @@ def jsonStringify(name: str, args: list[Any], team: Optional["Team"], stdout: Op return json.dumps(args[0]) +def base64Encode(name: str, args: list[Any], team: Optional["Team"], stdout: Optional[list[str]], timeout: int) -> str: + import base64 + + return base64.b64encode(args[0].encode()).decode() + + +def base64Decode(name: str, args: list[Any], team: Optional["Team"], stdout: Optional[list[str]], timeout: int) -> str: + import base64 + + return base64.b64decode(args[0].encode()).decode() + + +def encodeURLComponent( + name: str, args: list[Any], team: Optional["Team"], stdout: Optional[list[str]], timeout: int +) -> str: + import urllib.parse + + return urllib.parse.quote(args[0], safe="") + + +def decodeURLComponent( + name: str, args: list[Any], team: Optional["Team"], stdout: Optional[list[str]], timeout: int +) -> str: + import urllib.parse + + return urllib.parse.unquote(args[0]) + + STL: dict[str, Callable[[str, list[Any], Optional["Team"], list[str] | None, int], Any]] = { "concat": concat, "match": match, @@ -126,4 +154,8 @@ STL: dict[str, Callable[[str, list[Any], Optional["Team"], list[str] | None, int "run": run, "jsonParse": jsonParse, "jsonStringify": jsonStringify, + "base64Encode": base64Encode, + "base64Decode": base64Decode, + "encodeURLComponent": encodeURLComponent, + "decodeURLComponent": decodeURLComponent, } diff --git a/hogvm/typescript/package.json b/hogvm/typescript/package.json index 3080a86f544..de1a0b9db0b 100644 --- a/hogvm/typescript/package.json +++ b/hogvm/typescript/package.json @@ -1,6 +1,6 @@ { "name": "@posthog/hogvm", - "version": "1.0.11", + "version": "1.0.12", "description": "PostHog Hog Virtual Machine", "types": "dist/index.d.ts", "main": "dist/index.js", diff --git a/hogvm/typescript/src/stl/stl.ts b/hogvm/typescript/src/stl/stl.ts index cb358360ff7..303ef460ed8 100644 --- a/hogvm/typescript/src/stl/stl.ts +++ b/hogvm/typescript/src/stl/stl.ts @@ -86,6 +86,25 @@ export const STL: Record } return JSON.stringify(convert(args[0])) }, + base64Encode: (args) => { + return Buffer.from(args[0]).toString('base64') + }, + base64Decode: (args) => { + return Buffer.from(args[0], 'base64').toString() + }, + tryBase64Decode: (args) => { + try { + return Buffer.from(args[0], 'base64').toString() + } catch (e) { + return '' + } + }, + encodeURLComponent(args) { + return encodeURIComponent(args[0]) + }, + decodeURLComponent(args) { + return decodeURIComponent(args[0]) + }, } export const ASYNC_STL: Record Promise> = { diff --git a/posthog/hogql/bytecode.py b/posthog/hogql/bytecode.py index 7a9ae7165f6..1a5933a88bc 100644 --- a/posthog/hogql/bytecode.py +++ b/posthog/hogql/bytecode.py @@ -248,7 +248,7 @@ class BytecodeBuilder(Visitor): response = [] response.extend(expr) - response.extend([Operation.JUMP_IF_FALSE, len(then) + 2]) # + else's OP_JUMP + count + response.extend([Operation.JUMP_IF_FALSE, len(then) + (2 if else_ else 0)]) response.extend(then) if else_: response.extend([Operation.JUMP, len(else_)])