Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calling function returned from complex object #68

Open
janober opened this issue Oct 25, 2022 · 3 comments
Open

Calling function returned from complex object #68

janober opened this issue Oct 25, 2022 · 3 comments

Comments

@janober
Copy link

janober commented Oct 25, 2022

Hello,

sadly have one last problem for which I can not figure out what is going on. Would be amazing if you could help me with finding a solution. Thanks a lot for your help!

Here is the code to easily reproduce the issue I am facing:

const { python, builtins } = require('pythonia');

async function main() {
	const proxy = {
		getValue: (parameter1) => {
			return new Proxy(
				{},
				{
					ownKeys(target) {
						return ['first', 'second'];
					},
					getOwnPropertyDescriptor(k) {
						return {
							enumerable: true,
							configurable: true,
						};
					},
					get(target, property, receiver) {
						if (property === 'first') {
							return 'VALUE-first';
						}
						if (property === 'second') {
							return () => {
								return 'VALUE-second';
							};
						}
						return Reflect.get(target, property, receiver);
					},
				},
			);
		},
	};

	await builtins.exec("print(proxy['getValue']('some-key').first)", {
		proxy,
	});
	// Returns as expected:
	//     VALUE-first

	await builtins.exec("print(proxy['getValue']('some-key').second)", {
		proxy,
	});
	// Returns as expected:
	//     [Function (anonymous)]

	await builtins.exec("print(proxy['getValue']('some-key').second())", {
		proxy,
	});
	// Expected:
	//     VALUE-second
	// Actual response:
	//     ERROR
	//     Python Error  Call to 'exec' failed:
	//         await builtins.exec("print(proxy['getValue']('some-key').second())", {
	//      at async main (/data/n8n-python/packages/nodes-base/nodes/PythonFunction/test-node-reference-issue-post.js:44:2)
	// ...     across the bridge ...
}
main().then(() => python.exit());
@janober
Copy link
Author

janober commented Nov 4, 2022

@extremeheat any idea what could be done to make it work?

@extremeheat
Copy link
Owner

Looked into this and it relates to GC. Python freeing memory after __free__ is called on python-side proxy object, causing JS to free it and resulting in an attempt to call an undefined/deallocated function.

[js -> py] { r: 13, key: 'obj', val: 10004 }
[py -> js] { r: 15, action: 'get', ffid: 10004, key: 'second', c: 'jsi' }
[js -> py] { r: 15, key: 'fn', val: 10005 }
[py -> js] { r: 16, action: 'free', args: [ 10004 ], c: 'jsi' }
[py -> js] {
  r: 17,
  c: 'jsi',
  p: 1,
  action: 'call',
  ffid: 10004,
  key: 'second',
  args: []
}

Seems like __del__ is called before __call__ in

self._exe.free(self.ffid)
which is causing this. Will need further investigation.

@janober
Copy link
Author

janober commented Nov 5, 2022

Thanks a lot for looking into this! So seems like it will not be as "easy" as the other issues I had. I will then have to look for some kind of workaround.
Have a great weekend!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants